Skip to content

Commit 27ec13a

Browse files
authored
Finish Verilog backend unification (#137)
1 parent fa982e2 commit 27ec13a

File tree

14 files changed

+552
-404
lines changed

14 files changed

+552
-404
lines changed

src/bin/emit-verilog.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn main() -> std::io::Result<()> {
7777
expr
7878
};
7979

80-
let module = SVModule::from_expr(expr, mod_name.clone(), args.output_names.clone())
80+
let module = SVModule::from_luts(expr, mod_name.clone(), args.output_names.clone())
8181
.map_err(|s| std::io::Error::new(std::io::ErrorKind::Other, s))?;
8282
print!("{}", module);
8383
break;

src/bin/epak.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ fn main() -> std::io::Result<()> {
241241

242242
eprintln!("INFO: Writing output to Verilog...");
243243
let output_names: Vec<String> = f.get_outputs().iter().map(|x| x.to_string()).collect();
244-
let mut module = SVModule::from_expr(
244+
let mut module = SVModule::from_luts(
245245
result.get_expr().to_owned(),
246246
f.get_name().to_string(),
247247
output_names,

src/driver.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,16 +357,16 @@ enum ExtractStrat {
357357
}
358358

359359
/// The list of gates that must be reachable by the disassembling rewrite rule system.
360-
pub const GATE_WHITELIST_STR: &str = "MUX,AND2,OR2,XOR2,NOT,INV,REG,NAND2,NOR2";
360+
pub const GATE_WHITELIST_STR: &str = "MUX,AND,OR,XOR,NOT,INV,REG,NAND,NOR";
361361

362362
/// The list of gates that must be reachable by the disassembling rewrite rule system.
363363
pub const GATE_WHITELIST: [&str; 9] = [
364-
"MUX", "AND2", "OR2", "XOR2", "NOT", "INV", "REG", "NAND2", "NOR2",
364+
"MUX", "AND", "OR", "XOR", "NOT", "INV", "REG", "NAND", "NOR",
365365
];
366366

367367
impl ExtractStrat {
368368
/// Create an extraction strategy from a comma-separated list of gates.
369-
/// For example, `list` can be `"MUX,AND2,NOT"`.
369+
/// For example, `list` can be `"MUX,AND,NOT"`.
370370
pub fn from_gate_set(list: &str) -> Result<Self, String> {
371371
if list.is_empty() || list == "all" {
372372
return Self::from_gate_set(GATE_WHITELIST_STR);

src/lib.rs

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ mod tests {
2929
use driver::Canonical;
3030
use egg::{Analysis, Language, RecExpr};
3131
use lut::{LutExprInfo, LutLang};
32-
use verilog::{SVModule, sv_parse_wrapper};
32+
use verilog::{PrimitiveType, SVModule, sv_parse_wrapper};
3333

3434
use super::*;
3535

@@ -290,7 +290,7 @@ endmodule\n"
290290
#[test]
291291
fn test_assignment_emission() {
292292
let expr: RecExpr<LutLang> = "d".parse().unwrap();
293-
let module = SVModule::from_expr(expr, "passthru".to_string(), vec!["y".to_string()]);
293+
let module = SVModule::from_luts(expr, "passthru".to_string(), vec!["y".to_string()]);
294294
assert!(module.is_ok());
295295
let module = module.unwrap();
296296
assert_eq!(module.to_string(), get_assignment_verilog());
@@ -299,7 +299,7 @@ endmodule\n"
299299
#[test]
300300
fn test_duplicate_assignment() {
301301
let expr: RecExpr<LutLang> = "(BUS d d)".parse().unwrap();
302-
let module = SVModule::from_expr(expr, "passthru".to_string(), vec![]);
302+
let module = SVModule::from_luts(expr, "passthru".to_string(), vec![]);
303303
assert!(module.is_ok());
304304
let module = module.unwrap();
305305
let correct = "module passthru (
@@ -444,7 +444,7 @@ endmodule\n"
444444
wire b;
445445
output y;
446446
wire y;
447-
AND2 _0_ (
447+
AND _0_ (
448448
.A(a),
449449
.B(b),
450450
.Y(y)
@@ -471,19 +471,19 @@ endmodule\n"
471471
wire tmp1;
472472
wire tmp2;
473473
474-
AND2 _0_ (
474+
AND _0_ (
475475
.A(1'd1),
476476
.B(1'h01),
477477
.Y(tmp1)
478478
);
479479
480-
AND2 _1_ (
480+
AND _1_ (
481481
.A(1'b00),
482482
.B(1'd0),
483483
.Y(tmp2)
484484
);
485485
486-
AND2 _2_ (
486+
AND _2_ (
487487
.A(tmp1),
488488
.B(tmp2),
489489
.Y(y)
@@ -501,12 +501,47 @@ endmodule\n"
501501
);
502502
}
503503

504+
#[test]
505+
fn test_double_inverter() {
506+
let module = "module dinv (
507+
d,
508+
y
509+
);
510+
input d;
511+
wire d;
512+
output y;
513+
wire y;
514+
wire __0__;
515+
516+
NOT _1_ (
517+
.A(d),
518+
.Y(__0__)
519+
);
520+
521+
INV _2_ (
522+
.A (__0__),
523+
.ZN(y)
524+
);
525+
526+
endmodule
527+
"
528+
.to_string();
529+
let ast = sv_parse_wrapper(&module, None).unwrap();
530+
let module = SVModule::from_ast(&ast);
531+
assert!(module.is_ok());
532+
let module = module.unwrap();
533+
assert_eq!(
534+
module.to_single_expr().unwrap().to_string(),
535+
"(NOT (NOT d))".to_string()
536+
);
537+
}
538+
504539
#[test]
505540
fn test_verilog_emitter() {
506541
let mux: RecExpr<LutLang> = "(LUT 202 s1 (LUT 202 s0 a b) (LUT 202 s0 c d))"
507542
.parse()
508543
.unwrap();
509-
let module = SVModule::from_expr(mux, "mux_4_1".to_string(), Vec::new());
544+
let module = SVModule::from_luts(mux, "mux_4_1".to_string(), Vec::new());
510545
assert!(module.is_ok());
511546
let module = module.unwrap();
512547
let golden = "module mux_4_1 (
@@ -566,7 +601,7 @@ endmodule\n"
566601
#[test]
567602
fn test_emit_reg() {
568603
let reg: RecExpr<LutLang> = "(REG a)".parse().unwrap();
569-
let module = SVModule::from_expr(reg, "my_reg".to_string(), Vec::new());
604+
let module = SVModule::from_luts(reg, "my_reg".to_string(), Vec::new());
570605
assert!(module.is_ok());
571606
let module = module.unwrap();
572607
let golden = "module my_reg (
@@ -599,7 +634,7 @@ endmodule\n"
599634
let expr: RecExpr<LutLang> = "(AND a (XOR b (NOR c (NOT (MUX s t false)))))"
600635
.parse()
601636
.unwrap();
602-
let module = SVModule::from_expr(expr, "gate_list".to_string(), Vec::new());
637+
let module = SVModule::from_luts(expr, "gate_list".to_string(), Vec::new());
603638
assert!(module.is_ok());
604639
let module = module.unwrap();
605640
let golden = "module gate_list (
@@ -640,19 +675,19 @@ endmodule\n"
640675
.A(__1__),
641676
.Y(__2__)
642677
);
643-
NOR2 #(
678+
NOR #(
644679
) __8__ (
645680
.A(c),
646681
.B(__2__),
647682
.Y(__3__)
648683
);
649-
XOR2 #(
684+
XOR #(
650685
) __9__ (
651686
.A(b),
652687
.B(__3__),
653688
.Y(__4__)
654689
);
655-
AND2 #(
690+
AND #(
656691
) __10__ (
657692
.A(a),
658693
.B(__4__),
@@ -856,6 +891,22 @@ endmodule\n"
856891
assert!(matches!(expr.as_ref().last().unwrap(), CellLang::And(_)));
857892
}
858893

894+
#[test]
895+
fn test_input_lists() {
896+
assert_eq!(
897+
PrimitiveType::AND4.get_input_list(),
898+
vec!["A1", "A2", "A3", "A4"]
899+
);
900+
assert_eq!(
901+
PrimitiveType::AOI22.get_input_list(),
902+
vec!["A1", "A2", "B1", "B2"]
903+
);
904+
assert_eq!(
905+
PrimitiveType::LUT6.get_input_list(),
906+
vec!["I0", "I1", "I2", "I3", "I4", "I5"]
907+
);
908+
}
909+
859910
#[test]
860911
fn test_emit_celllang() {
861912
let expr: RecExpr<CellLang> = "(NOR2_X1 b (NAND2_X1 a false))".parse().unwrap();

src/lut.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,10 +483,10 @@ impl LutLang {
483483
/// Returns the Verilog primitive name for a node type
484484
pub fn get_prim_name(&self) -> Option<String> {
485485
match self {
486-
LutLang::Nor(_) => Some("NOR2".to_string()),
486+
LutLang::Nor(_) => Some("NOR".to_string()),
487487
LutLang::Mux(_) => Some("MUX".to_string()),
488-
LutLang::And(_) => Some("AND2".to_string()),
489-
LutLang::Xor(_) => Some("XOR2".to_string()),
488+
LutLang::And(_) => Some("AND".to_string()),
489+
LutLang::Xor(_) => Some("XOR".to_string()),
490490
LutLang::Not(_) => Some("NOT".to_string()),
491491
LutLang::Lut(l) => Some(format!("LUT{}", l.len() - 1)),
492492
_ => None,

0 commit comments

Comments
 (0)