Skip to content

Commit 3b0ac8a

Browse files
authored
Verilog emission refactor (#133)
1 parent 9d890e9 commit 3b0ac8a

File tree

6 files changed

+610
-128
lines changed

6 files changed

+610
-128
lines changed

src/asic.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ define_language! {
2121
Const(bool),
2222
Var(Symbol),
2323
"AND" = And([Id; 2]),
24-
"OR" = Xor([Id; 2]),
24+
"OR" = Or([Id; 2]),
2525
"INV" = Inv([Id; 1]),
2626
Cell(Symbol, Vec<Id>), // or Box<[Id]>?
2727
}
@@ -46,6 +46,17 @@ impl CellLang {
4646
_ => Ok(()),
4747
}
4848
}
49+
50+
/// Get the drive strength of a cell
51+
pub fn get_drive_strength(&self) -> Option<usize> {
52+
match self {
53+
CellLang::Cell(s, _) => match s.as_str().split_once("_X") {
54+
Some((_, strength)) => strength.parse::<usize>().ok(),
55+
None => None,
56+
},
57+
_ => None,
58+
}
59+
}
4960
}
5061

5162
/// A cost function that extracts a circuit with the least depth
@@ -285,8 +296,8 @@ pub fn asic_rewrites() -> Vec<egg::Rewrite<CellLang, CellAnalysis>> {
285296
rules
286297
.push(rewrite!("xor2_x1"; "(OR (AND ?b (INV ?a)) (AND ?a (INV ?b)))" => "(XOR2_X1 ?a ?b)"));
287298
rules.push(rewrite!("inv_x1"; "(INV ?a)" => "(INV_X1 ?a)"));
288-
rules.push(rewrite!("aoi_x1"; "(INV (OR (AND ?a ?b) ?c))" => "(AOI_X1 ?a ?b ?c)"));
289-
rules.push(rewrite!("oai_x1"; "(INV (AND (OR ?a ?b) ?c))" => "(OAI_X1 ?a ?b ?c)"));
299+
rules.push(rewrite!("aoi_x1"; "(INV (OR (AND ?a ?b) ?c))" => "(AOI21_X1 ?a ?b ?c)"));
300+
rules.push(rewrite!("oai_x1"; "(INV (AND (OR ?a ?b) ?c))" => "(OAI21_X1 ?a ?b ?c)"));
290301

291302
rules
292303
}

src/bin/cellmap.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use egg::{FromOpError, RecExpr, RecExprParseError};
33
use lut_synth::{
44
asic::{CellAnalysis, CellLang, CellRpt, asic_rewrites},
55
driver::{SynthRequest, process_string_expression, simple_reader},
6+
verilog::SVModule,
67
};
78
use std::path::PathBuf;
89

@@ -78,6 +79,10 @@ struct Args {
7879
#[arg(short = 'v', long, default_value_t = false)]
7980
verbose: bool,
8081

82+
/// Output Verilog
83+
#[arg(long, default_value_t = false)]
84+
verilog: bool,
85+
8186
/// Extract for minimum circuit depth
8287
#[arg(long, default_value_t = false)]
8388
min_depth: bool,
@@ -170,7 +175,18 @@ fn main() -> std::io::Result<()> {
170175
args.verbose,
171176
)?;
172177
if !result.is_empty() {
173-
println!("{}", result);
178+
if args.verilog {
179+
let module = SVModule::from_cells(
180+
result.get_expr().to_owned(),
181+
"top".to_string(),
182+
Vec::new(),
183+
);
184+
let module =
185+
module.map_err(|s| std::io::Error::new(std::io::ErrorKind::Other, s))?;
186+
println!("{}", module);
187+
} else {
188+
println!("{}", result);
189+
}
174190
}
175191
}
176192
Ok(())

src/driver.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use egg::{
1414
};
1515
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
1616
use std::collections::{BTreeMap, HashSet};
17-
use std::rc::Rc;
1817
use std::sync::Arc;
1918
use std::sync::atomic::{AtomicBool, Ordering};
2019
use std::time::{Duration, Instant};
@@ -212,7 +211,7 @@ where
212211
})
213212
}
214213

215-
fn get_rule_uses_rec(map: &mut BTreeMap<String, usize>, expl: &[Rc<TreeTerm<L>>]) {
214+
fn get_rule_uses_rec(map: &mut BTreeMap<String, usize>, expl: &[std::rc::Rc<TreeTerm<L>>]) {
216215
for t in expl {
217216
if let Some(r) = t.backward_rule {
218217
let name = r.to_string();

src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,4 +855,41 @@ endmodule\n"
855855
assert!(CellLang::verify_expr(&expr).is_ok());
856856
assert!(matches!(expr.as_ref().last().unwrap(), CellLang::And(_)));
857857
}
858+
859+
#[test]
860+
fn test_emit_celllang() {
861+
let expr: RecExpr<CellLang> = "(NOR2_X1 b (NAND2_X1 a false))".parse().unwrap();
862+
let module = SVModule::from_cells(expr, "gate_list".to_string(), Vec::new());
863+
assert!(module.is_ok());
864+
let module = module.unwrap();
865+
let golden = "module gate_list (
866+
b,
867+
a,
868+
y
869+
);
870+
input b;
871+
wire b;
872+
input a;
873+
wire a;
874+
output y;
875+
wire y;
876+
wire __0__;
877+
wire __1__;
878+
assign __0__ = 1'b0;
879+
NAND2_X1 #(
880+
) __3__ (
881+
.A1(a),
882+
.A2(__0__),
883+
.ZN(__1__)
884+
);
885+
NOR2_X1 #(
886+
) __4__ (
887+
.A1(b),
888+
.A2(__1__),
889+
.ZN(y)
890+
);
891+
endmodule\n"
892+
.to_string();
893+
assert_eq!(module.to_string(), golden);
894+
}
858895
}

0 commit comments

Comments
 (0)