From f23ab17926d72d9a82d66ce38e341d15f85feb09 Mon Sep 17 00:00:00 2001 From: Alexander Nutz Date: Tue, 26 Aug 2025 20:47:30 +0200 Subject: [PATCH] c --- README.md | 19 +++++---- src/ast.rs | 18 +++++++-- src/lib.rs | 16 ++++++++ src/tests.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 148 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index db667f9..02a3737 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ low-memory-usage BLIF (berkeley logic interchange format) parser. +## Comparison with other parsers | | this | SIS | yosys | abc | [pip blifparser] | [lorina] | [crates.io blif-parser] | [quaigh] | [libblifparse] | [spydrnet] | | ------------------------------------------- | ---- | --- | ----- | --- | ---------------- | -------- | ----------------------- | -------- | -------------- | ---------- | | top module, latches, LUTs | x | x | x | x | x | x | x | x | x | x | @@ -15,7 +16,7 @@ low-memory-usage BLIF (berkeley logic interchange format) parser. | sub-file references | x | x | ? | - | x | - | - | - | - | - | | finite state machines (`.start_kiss`) | x | x | - | - | x | - | - | - | - | - | | clock constraints (mostly for simulation) | soon | x | - | - | - | - | - | - | - | - | -| delay constraints | soon | x | - | x | - | - | - | - | - | - | +| delay constraints | soon | x | - | ~ | - | - | - | - | - | - | | full BLIF specification [^1] | soon | x | - | - | - | - | - | - | - | - | | extension: "Black- & White-boxes" [^2] | soon | - | - | - | - | - | - | - | - | - | | extension: `.blackbox` | soon | - | x | x | - | - | - | - | x | x | @@ -23,7 +24,7 @@ low-memory-usage BLIF (berkeley logic interchange format) parser. | extension: `.attr` and `.param` (EBLIF[^3]) | x | - | x | - | - | - | - | - | x | x | | extension: `.conn` (EBLIF[^3]) | x | - | x | - | - | - | - | - | x | x | | extension: `.barbuff` (identical: `.conn`) | x | - | x | - | - | - | - | - | - | - | - +| extension: `.and_gate_delay` | soon | - | - | x | - | - | - | - | - | - | [^1]: https://people.eecs.berkeley.edu/~alanmi/publications/other/blif.pdf @@ -37,11 +38,13 @@ low-memory-usage BLIF (berkeley logic interchange format) parser. [libblifparse]: https://github.com/verilog-to-routing/libblifparse [spydrnet]: https://github.com/byuccl/spydrnet -- the latest BLIF specification (dated July 28, 1992) -- all yosys BLIF extensions - (supports reading of BLIF files generated with `write_blif -iname -iattr -param -cname -blackbox -attr -conn`) -- KISS state machines (which yosys doesn't even support) -- clock and delay constraints (yosys just ignores those) -If you found a program that generates non-standard BLIF attributes or keywords, please open a GitHub issue. +## Tested with BLIF generators +- yosys `write_blif`, including all supported extensions: `write_blif -iname -iattr -param -cname -blackbox -attr -conn` +- abc write blif + +## Goals +- parse every BLIF file in existence + +If you found a program that generates or consists of non-standard BLIF attributes or keywords, please open a GitHub issue. We want to support all non-standard extensions. diff --git a/src/ast.rs b/src/ast.rs index a31f33b..f9ffa07 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -127,10 +127,17 @@ impl From for ModelCmd { } } -#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Default)] +pub struct ModelAttr { + /// from blif `.area` attribute + pub area: Option, +} + +#[derive(Debug, Clone, PartialEq, PartialOrd)] pub struct Model { pub meta: ModelMeta, pub commands: Vec, + pub attr: ModelAttr, } impl CommandConsumer for Model { @@ -214,6 +221,10 @@ impl CommandConsumer for Model { .into(), ) } + + fn set_area(&mut self, area: f64) { + self.attr.area = Some(area); + } } #[derive(Debug)] @@ -225,12 +236,12 @@ pub enum FullBlifErr { SearchPathsNotSupported, } -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, PartialEq)] pub enum BlifEntry { Model(Model), } -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, PartialEq)] pub struct Blif { pub entries: Vec, to_search: Vec, @@ -243,6 +254,7 @@ impl ModelConsumer for Blif { Model { meta, commands: vec![], + attr: Default::default(), } } diff --git a/src/lib.rs b/src/lib.rs index 58067fb..e209cf5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,6 +106,8 @@ pub trait CommandConsumer { /// non-standard fn connect(&mut self, from: &str, to: &str); + + fn set_area(&mut self, area: f64); } #[derive(Debug, Clone, Hash, PartialEq, PartialOrd)] @@ -844,6 +846,20 @@ fn parse_mod( consumer.connect(from, to); } + ".area" => { + let val = args + .next() + .ok_or(BlifParserError::MissingArgs)? + .parse() + .map_err(|_| BlifParserError::Invalid)?; + + if args.next().is_some() { + Err(BlifParserError::TooManyArgs)? + } + + consumer.set_area(val); + } + // TODO: clock & delay cst // TODO: .blackblox _ => Err(BlifParserError::UnknownKw(cmd.to_string()))?, diff --git a/src/tests.rs b/src/tests.rs index b78381d..28d47b8 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,3 +1,8 @@ +#![allow(non_snake_case)] +#![allow(unused)] + +use std::default; + use super::ast::*; use super::*; @@ -38,6 +43,7 @@ fn simple_named() { }) .into() ], + attr: Default::default(), })], ); } @@ -77,6 +83,7 @@ fn simple_unnamed() { }) .into() ], + attr: Default::default(), })], ); } @@ -115,6 +122,7 @@ c }) .into() ], + attr: Default::default(), })], ); } @@ -154,6 +162,7 @@ c }) .into() ], + attr: Default::default(), })], ); } @@ -224,6 +233,7 @@ fn lut() { }) .into() ], + attr: Default::default(), })], ); } @@ -281,7 +291,8 @@ fn submod() { lut: LUT(vec![([Tristate::True].into_iter().collect(), true)]) }) .into() - ] + ], + attr: Default::default(), }), BlifEntry::Model(Model { meta: ModelMeta { @@ -303,7 +314,8 @@ fn submod() { )]) }) .into() - ] + ], + attr: Default::default(), }) ] ); @@ -507,3 +519,95 @@ fn yosys_attrs() { // TODO: assert_eq } + +#[test] +fn delay_cst__area() { + let ast = parse_str_blif_to_ast( + "top.blif", + r#" +.model top +.names $true +1 +# .area is not a model attribute, but a command +.area 100.31 +"#, + ) + .unwrap(); + + assert_eq!( + ast.entries, + vec![BlifEntry::Model(Model { + meta: ModelMeta { + name: "top".into(), + inputs: None, + outputs: None, + clocks: vec![], + }, + commands: vec![ModelCmd { + kind: ModelCmdKind::Gate(Gate { + meta: GateMeta { + inputs: vec![], + output: "$true".into(), + external_dc: false, + }, + lut: LUT(vec![([].into_iter().collect(), true)]) + }), + attrs: vec![], + }], + attr: ModelAttr { + area: Some(100.31), + ..Default::default() + } + })] + ); +} + +/// generated by abc: https://github.com/berkeley-abc/abc/blob/master/src/base/io/ioWriteBlif.c +#[test] +fn abc__and_gate_delay() { + let ast = parse_str_blif_to_ast( + "top.blif", + r#" +.model top +.names $true +1 +# not a model attribute, but a command +.and_gate_delay 12.31 +"#, + ) + .unwrap(); + + // TODO: assert +} + +#[test] +fn delay_cst__default_spec() { + let ast = parse_str_blif_to_ast( + "top.blif", + r#" +.model top +.names $true +1 +# not a model attribute, but a command + +.default_input_arrival 3.0 3.2 +.default_output_required 2.1 2.5 + +.default_max_input_load 200 +.default_output_load 300 +"#, + ) + .unwrap(); + + // TODO: assert +} + +// TODO: +//.delay +//.wire_load_slope +//.wire +//.input_arrival [ ] +//.output_required [ ] +//.max_input_load +//.input_drive +//.output_load