mirror of
https://github.com/YosysHQ/sby.git
synced 2025-11-01 21:37:52 +00:00
150 lines
4.3 KiB
Rust
150 lines
4.3 KiB
Rust
#![allow(clippy::needless_range_loop)]
|
|
|
|
use std::{fs, mem::replace, path::PathBuf};
|
|
|
|
use clap::{Parser, ValueEnum};
|
|
use color_eyre::eyre::bail;
|
|
|
|
use flussab_aiger::binary;
|
|
|
|
pub mod aig_eval;
|
|
pub mod care_graph;
|
|
pub mod util;
|
|
|
|
/// AIG counter example minimization
|
|
#[derive(clap::Parser)]
|
|
#[command(author, version, about, long_about = None, help_template="\
|
|
{before-help}{name} {version}
|
|
{author-with-newline}{about-with-newline}
|
|
{usage-heading} {usage}
|
|
|
|
{all-args}{after-help}
|
|
")]
|
|
pub struct Options {
|
|
/// Input AIGER file
|
|
aig: PathBuf,
|
|
/// Input AIGER witness file
|
|
witness: PathBuf,
|
|
/// Output AIGER witness file
|
|
output: PathBuf,
|
|
|
|
/// Verify the minimized counter example
|
|
#[clap(long, default_value = "cex")]
|
|
verify: VerificationOption,
|
|
|
|
/// Minimize latch initialization values
|
|
///
|
|
/// Without this option the latch initialization values of the witness file are assumed to be
|
|
/// fixed and will remain as-is in the minimized witness file.
|
|
///
|
|
/// Note that some tools (including the current Yosys/SBY flow) do not use AIGER native latch
|
|
/// initialization but instead perform initialization using inputs in the first frame.
|
|
#[clap(long)]
|
|
latches: bool,
|
|
|
|
/// Require assumptions to stay satisfied during minimization
|
|
#[clap(long)]
|
|
satisfy_assumptions: bool
|
|
}
|
|
|
|
#[derive(Copy, Clone, ValueEnum)]
|
|
enum VerificationOption {
|
|
/// Skip verification
|
|
Off,
|
|
/// Verify the counter example
|
|
Cex,
|
|
/// Verify the counter example and that it is minimal (expensive)
|
|
Full,
|
|
}
|
|
|
|
fn main() -> color_eyre::Result<()> {
|
|
let options = Options::parse();
|
|
|
|
color_eyre::install()?;
|
|
|
|
let file_input = fs::File::open(options.aig)?;
|
|
let file_witness = fs::File::open(options.witness)?;
|
|
let file_output = fs::File::create(options.output)?;
|
|
|
|
let mut writer_output = flussab::DeferredWriter::from_write(file_output);
|
|
|
|
let mut read_witness_owned = flussab::DeferredReader::from_read(file_witness);
|
|
let read_witness = &mut read_witness_owned;
|
|
|
|
let aig_reader = binary::Parser::<u32>::from_read(file_input, binary::Config::default())?;
|
|
|
|
let aig = aig_reader.parse()?;
|
|
|
|
let mut offset = 0;
|
|
offset = flussab::text::next_newline(read_witness, offset);
|
|
|
|
if offset == 2 {
|
|
read_witness.advance(replace(&mut offset, 0));
|
|
offset = flussab::text::next_newline(read_witness, offset);
|
|
read_witness.advance(replace(&mut offset, 0));
|
|
|
|
offset = flussab::text::next_newline(read_witness, offset);
|
|
}
|
|
|
|
if offset != aig.latches.len() + 1 {
|
|
bail!(
|
|
"unexpected number of initial latch states, found {} expected {}",
|
|
offset.saturating_sub(1),
|
|
aig.latches.len()
|
|
);
|
|
}
|
|
|
|
let latch_init = read_witness.buf()[..aig.latches.len()]
|
|
.iter()
|
|
.copied()
|
|
.map(util::parse_input_bit)
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
read_witness.advance(replace(&mut offset, 0));
|
|
|
|
let mut frame_inputs = vec![];
|
|
|
|
loop {
|
|
offset = flussab::text::next_newline(read_witness, offset);
|
|
|
|
if matches!(read_witness.buf().first(), None | Some(b'.') | Some(b'#')) {
|
|
read_witness.check_io_error()?;
|
|
break;
|
|
}
|
|
|
|
if offset != aig.input_count + 1 {
|
|
bail!(
|
|
"unexpected number of input bits, found {} expected {}",
|
|
offset.saturating_sub(1),
|
|
aig.input_count
|
|
);
|
|
}
|
|
|
|
frame_inputs.push(
|
|
read_witness.buf()[..aig.input_count]
|
|
.iter()
|
|
.copied()
|
|
.map(util::parse_input_bit)
|
|
.collect::<Result<Vec<_>, _>>()?,
|
|
);
|
|
read_witness.advance(replace(&mut offset, 0));
|
|
}
|
|
|
|
care_graph::minimize(
|
|
&aig,
|
|
&latch_init,
|
|
&frame_inputs,
|
|
&mut writer_output,
|
|
&care_graph::MinimizationOptions {
|
|
fixed_init: !options.latches,
|
|
satisfy_assumptions: options.satisfy_assumptions,
|
|
verify: match options.verify {
|
|
VerificationOption::Off => None,
|
|
VerificationOption::Cex => Some(care_graph::Verification::Cex),
|
|
VerificationOption::Full => Some(care_graph::Verification::Full),
|
|
},
|
|
},
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|