mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-05-13 03:00:26 -04:00
Merge pull request #376 from powdr-org/move-csv-export
Move CSV export to pil command
This commit is contained in:
@@ -5,6 +5,7 @@ use std::fs;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
use ast::analyzed::Analyzed;
|
||||
@@ -35,9 +36,9 @@ pub fn compile_pil_or_asm<T: FieldElement>(
|
||||
output_dir: &Path,
|
||||
force_overwrite: bool,
|
||||
prove_with: Option<Backend>,
|
||||
) {
|
||||
) -> PathBuf {
|
||||
if file_name.ends_with(".asm") {
|
||||
compile_asm(file_name, inputs, output_dir, force_overwrite, prove_with);
|
||||
compile_asm(file_name, inputs, output_dir, force_overwrite, prove_with)
|
||||
} else {
|
||||
compile_pil(
|
||||
Path::new(file_name),
|
||||
@@ -45,6 +46,7 @@ pub fn compile_pil_or_asm<T: FieldElement>(
|
||||
Some(inputs_to_query_callback(inputs)),
|
||||
prove_with,
|
||||
);
|
||||
PathBuf::from(file_name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +105,7 @@ pub fn compile_asm<T: FieldElement>(
|
||||
output_dir: &Path,
|
||||
force_overwrite: bool,
|
||||
prove_with: Option<Backend>,
|
||||
) {
|
||||
) -> PathBuf {
|
||||
let contents = fs::read_to_string(file_name).unwrap();
|
||||
compile_asm_string(
|
||||
file_name,
|
||||
@@ -112,7 +114,7 @@ pub fn compile_asm<T: FieldElement>(
|
||||
output_dir,
|
||||
force_overwrite,
|
||||
prove_with,
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
/// Compiles the contents of a .asm file, outputs the PIL on stdout and tries to generate
|
||||
@@ -126,7 +128,7 @@ pub fn compile_asm_string<T: FieldElement>(
|
||||
output_dir: &Path,
|
||||
force_overwrite: bool,
|
||||
prove_with: Option<Backend>,
|
||||
) -> String {
|
||||
) -> PathBuf {
|
||||
let parsed = parser::parse_asm(Some(file_name), contents).unwrap_or_else(|err| {
|
||||
eprintln!("Error parsing .asm file:");
|
||||
err.output_to_stderr();
|
||||
@@ -139,13 +141,13 @@ pub fn compile_asm_string<T: FieldElement>(
|
||||
Path::new(file_name).file_stem().unwrap().to_str().unwrap()
|
||||
);
|
||||
|
||||
let pil_file_path = output_dir.join(&pil_file_name);
|
||||
let pil_file_path = output_dir.join(pil_file_name);
|
||||
if pil_file_path.exists() && !force_overwrite {
|
||||
eprint!(
|
||||
"Target file {} already exists. Not overwriting.",
|
||||
pil_file_path.to_str().unwrap()
|
||||
);
|
||||
return pil_file_name;
|
||||
return pil_file_path;
|
||||
}
|
||||
fs::write(pil_file_path.clone(), format!("{pil}")).unwrap();
|
||||
|
||||
@@ -157,7 +159,7 @@ pub fn compile_asm_string<T: FieldElement>(
|
||||
prove_with,
|
||||
);
|
||||
|
||||
pil_file_name
|
||||
pil_file_path
|
||||
}
|
||||
|
||||
fn compile<T: FieldElement, QueryCallback>(
|
||||
|
||||
@@ -5,7 +5,8 @@ use crate::compile_asm_string;
|
||||
|
||||
pub fn verify_asm_string<T: FieldElement>(file_name: &str, contents: &str, inputs: Vec<T>) {
|
||||
let temp_dir = mktemp::Temp::new_dir().unwrap();
|
||||
let pil_file_name = compile_asm_string(file_name, contents, inputs, &temp_dir, true, None);
|
||||
let pil_file_path = compile_asm_string(file_name, contents, inputs, &temp_dir, true, None);
|
||||
let pil_file_name = pil_file_path.file_name().unwrap().to_string_lossy();
|
||||
verify(&pil_file_name, &temp_dir);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use env_logger::{Builder, Target};
|
||||
use log::LevelFilter;
|
||||
use number::{Bn254Field, FieldElement, GoldilocksField};
|
||||
use riscv::{compile_riscv_asm, compile_rust};
|
||||
use std::{borrow::Cow, fs, io::Write, path::Path};
|
||||
use std::{borrow::Cow, collections::HashSet, fs, io::Write, path::Path};
|
||||
use strum::{Display, EnumString, EnumVariantNames};
|
||||
|
||||
use std::io::{BufWriter, Cursor};
|
||||
@@ -74,6 +74,17 @@ enum Commands {
|
||||
#[arg(short, long)]
|
||||
#[arg(value_parser = clap_enum_variants!(Backend))]
|
||||
prove_with: Option<Backend>,
|
||||
|
||||
/// Generate a CSV file containing the fixed and witness column values. Useful for debugging purposes.
|
||||
#[arg(long)]
|
||||
#[arg(default_value_t = false)]
|
||||
export_csv: bool,
|
||||
|
||||
/// How to render field elements in the csv file
|
||||
#[arg(long)]
|
||||
#[arg(default_value_t = CsvRenderMode::Hex)]
|
||||
#[arg(value_parser = clap_enum_variants!(CsvRenderMode))]
|
||||
csv_mode: CsvRenderMode,
|
||||
},
|
||||
/// Compiles (no-std) rust code to riscv assembly, then to powdr assembly
|
||||
/// and finally to PIL and generates fixed and witness columns.
|
||||
@@ -164,11 +175,11 @@ enum Commands {
|
||||
backend: Backend,
|
||||
|
||||
/// File containing previously generated proof for aggregation.
|
||||
#[arg(short, long)]
|
||||
#[arg(long)]
|
||||
proof: Option<String>,
|
||||
|
||||
/// File containing previously generated setup parameters.
|
||||
#[arg(short, long)]
|
||||
#[arg(long)]
|
||||
params: Option<String>,
|
||||
},
|
||||
|
||||
@@ -210,29 +221,6 @@ enum Commands {
|
||||
#[arg(value_parser = clap_enum_variants!(FieldArgument))]
|
||||
field: FieldArgument,
|
||||
},
|
||||
|
||||
/// Exports witness and fixed columns to a csv file.
|
||||
ExportCsv {
|
||||
/// Input PIL file
|
||||
file: String,
|
||||
|
||||
/// Directory to find the committed and fixed values
|
||||
#[arg(short, long)]
|
||||
#[arg(default_value_t = String::from("."))]
|
||||
dir: String,
|
||||
|
||||
/// The field to use
|
||||
#[arg(long)]
|
||||
#[arg(default_value_t = FieldArgument::Gl)]
|
||||
#[arg(value_parser = clap_enum_variants!(FieldArgument))]
|
||||
field: FieldArgument,
|
||||
|
||||
/// How to render field elements in the csv file
|
||||
#[arg(long)]
|
||||
#[arg(default_value_t = CsvRenderMode::Hex)]
|
||||
#[arg(value_parser = clap_enum_variants!(CsvRenderMode))]
|
||||
render_mode: CsvRenderMode,
|
||||
},
|
||||
}
|
||||
|
||||
fn split_inputs<T: FieldElement>(inputs: &str) -> Vec<T> {
|
||||
@@ -310,13 +298,26 @@ fn main() {
|
||||
inputs,
|
||||
force,
|
||||
prove_with,
|
||||
} => call_with_field!(compile_pil_or_asm::<field>(
|
||||
&file,
|
||||
split_inputs(&inputs),
|
||||
Path::new(&output_directory),
|
||||
force,
|
||||
prove_with
|
||||
)),
|
||||
export_csv,
|
||||
csv_mode,
|
||||
} => {
|
||||
let pil_filename = call_with_field!(compile_pil_or_asm::<field>(
|
||||
&file,
|
||||
split_inputs(&inputs),
|
||||
Path::new(&output_directory),
|
||||
force,
|
||||
prove_with
|
||||
));
|
||||
|
||||
if export_csv {
|
||||
let pil = Path::new(&pil_filename);
|
||||
let dir = Path::new(&output_directory);
|
||||
let csv_path = dir.join("columns.csv");
|
||||
call_with_field!(export_columns_to_csv::<field>(
|
||||
pil, dir, &csv_path, csv_mode
|
||||
));
|
||||
}
|
||||
}
|
||||
Commands::Prove {
|
||||
file,
|
||||
dir,
|
||||
@@ -344,24 +345,6 @@ fn main() {
|
||||
log::info!("Wrote {proof_filename}.");
|
||||
}
|
||||
}
|
||||
|
||||
Commands::ExportCsv {
|
||||
file,
|
||||
dir,
|
||||
field,
|
||||
render_mode,
|
||||
} => {
|
||||
let pil = Path::new(&file);
|
||||
let dir = Path::new(&dir);
|
||||
let csv_path = dir.join("columns.csv");
|
||||
|
||||
call_with_field!(export_columns_to_csv::<field>(
|
||||
pil,
|
||||
dir,
|
||||
&csv_path,
|
||||
render_mode
|
||||
));
|
||||
}
|
||||
Commands::Setup {
|
||||
size,
|
||||
dir,
|
||||
@@ -413,11 +396,26 @@ fn export_columns_to_csv<T: FieldElement>(
|
||||
let mut csv_file = fs::File::create(csv_path).unwrap();
|
||||
let mut csv_writer = BufWriter::new(&mut csv_file);
|
||||
|
||||
// Write the column headers
|
||||
// Remove prefixes (e.g. "Assembly.") if column names are still unique after
|
||||
let headers = columns
|
||||
.iter()
|
||||
.map(|(header, _)| header.clone())
|
||||
.map(|(header, _)| header.to_owned())
|
||||
.collect::<Vec<_>>();
|
||||
let headers_without_prefix = headers
|
||||
.iter()
|
||||
.map(|header| {
|
||||
let suffix_start = header.rfind('.').map(|i| i + 1).unwrap_or(0);
|
||||
header[suffix_start..].to_owned()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let unique_elements = headers_without_prefix.iter().collect::<HashSet<_>>();
|
||||
let headers = if unique_elements.len() == headers.len() {
|
||||
headers_without_prefix
|
||||
} else {
|
||||
headers
|
||||
};
|
||||
|
||||
writeln!(csv_writer, "Row,{}", headers.join(",")).unwrap();
|
||||
|
||||
// Write the column values
|
||||
|
||||
Reference in New Issue
Block a user