use vast::util::file::read_to_string; use vast::v05::ast::*; macro_rules! check { ($res:expr, $exp:expr) => { assert!( $res == $exp, "\n\nresult:\n{}\nexpected:\n{}\n\n", $res, $exp ); }; } #[test] fn test_expr_str() { let expr = Expr::new_str("multiply"); let exp = r#""multiply""#.to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_ulit_bin() { let expr = Expr::new_ulit_bin(4, "1000"); let exp = "4'b1000".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_x() { let expr = Expr::X; let exp = "'x".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_ulit_hex() { let expr = Expr::new_ulit_hex(8, "ff"); let exp = "8'hff".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_ulit_dec() { let expr = Expr::new_ulit_dec(16, "78"); let exp = "16'd78".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_ref() { let expr = Expr::new_ref("a"); let exp = "a".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_signed() { let expr = Expr::new_signed_ref("a"); let exp = "$signed(a)".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_concat() { let mut concat = ExprConcat::default(); concat.add_expr(Expr::new_ref("a")); concat.add_expr(Expr::new_ulit_bin(1, "0")); let expr = Expr::from(concat); let exp = "{1'b0, a}".to_string(); let res = expr.to_string(); check!(res, exp); } #[test] fn test_expr_mux() { let cond = Expr::new_eq(Expr::new_ref("a"), Expr::new_ref("b")); let tru = Expr::new_ref("a"); let fal = Expr::new_ref("b"); let mux = Expr::new_mux(cond, tru, fal); let res = mux.to_string(); let exp = "a == b ? a : b".to_string(); check!(res, exp); } #[test] fn test_expr_slice() { let hi = Expr::new_int(7); let lo = Expr::new_int(0); let slice = Expr::new_slice("a", hi, lo); let res = slice.to_string(); let exp = "a[7:0]".to_string(); check!(res, exp); } #[test] fn test_expr_index_slice() { let lo = Expr::new_int(0); let slice = Expr::new_index_slice("a", lo, 8); let res = slice.to_string(); let exp = "a[0 +: 8]".to_string(); check!(res, exp); } #[test] fn test_attr_val() { let mut attr = Attribute::default(); attr.add_val("full_case"); let exp = "(*full_case*)".to_string(); let res = attr.to_string(); check!(res, exp); } #[test] fn test_attr_stmt() { let mut attr = Attribute::default(); attr.add_stmt("x", "3"); let exp = "(*x = \"3\"*)".to_string(); let res = attr.to_string(); check!(res, exp); } #[test] fn test_decl_wire_width_32() { let wire = Decl::new_wire("foo", 32); let exp = "wire [31:0] foo".to_string(); let res = wire.to_string(); check!(res, exp); } #[test] fn test_decl_wire_width_1() { let wire = Decl::new_wire("foo", 1); let exp = "wire foo".to_string(); let res = wire.to_string(); check!(res, exp); } #[test] fn test_decl_reg_width_32() { let reg = Decl::new_reg("foo", 32); let exp = "reg [31:0] foo".to_string(); let res = reg.to_string(); check!(res, exp); } #[test] fn test_decl_reg_width_1() { let reg = Decl::new_reg("foo", 1); let exp = "reg foo".to_string(); let res = reg.to_string(); check!(res, exp); } #[test] fn test_decl_param_uint() { let param = Decl::new_param_uint("width", 3); let exp = "parameter width = 32'd3".to_string(); let res = param.to_string(); check!(res, exp); } #[test] fn test_decl_array() { let decl = Decl::new_array("ram", 32, 32).to_string(); let exp = "reg [31:0] ram [31:0]".to_string(); check!(decl, exp); } #[test] fn test_event_ty_posedge() { let event = EventTy::Posedge; let exp = "posedge".to_string(); let res = event.to_string(); check!(res, exp); } #[test] fn test_event_ty_negedge() { let event = EventTy::Negedge; let exp = "negedge".to_string(); let res = event.to_string(); check!(res, exp); } #[test] fn test_sequential_event_posedge_clock() { let seq = Sequential::Event(EventTy::Posedge, Expr::Ref("clock".to_string())); let exp = "posedge clock".to_string(); let res = seq.to_string(); check!(res, exp); } #[test] fn test_sequential_if() { let cond = Expr::new_ref("reset"); let y = Expr::new_ref("y"); let a = Expr::new_ref("a"); let seq = Sequential::new_nonblk_assign(y, a); let mut ifelse = SequentialIfElse::new(cond); ifelse.add_seq(seq); let exp = r#"if(reset) begin y <= a; end"#; let res = ifelse.to_string(); check!(res, exp); } #[test] fn test_sequential_if_else() { let c0 = Expr::new_ref("reset"); let y = Expr::new_ref("y"); let a = Expr::new_ref("a"); let val = Expr::new_int(0); let s0 = Sequential::new_nonblk_assign(y.clone(), val); let s1 = Sequential::new_nonblk_assign(y, a); let mut i0 = SequentialIfElse::new(c0); let mut i1 = SequentialIfElse::default(); i0.add_seq(s0); i1.add_seq(s1); i0.set_else(i1); let exp = r#"if(reset) begin y <= 0; end else begin y <= a; end"#; let res = i0.to_string(); check!(res, exp); } #[test] fn test_sequential_if_else_if() { let c0 = Expr::new_ref("reset"); let c1 = Expr::new_ref("en"); let y = Expr::new_ref("y"); let a = Expr::new_ref("a"); let val = Expr::new_int(0); let s0 = Sequential::new_nonblk_assign(y.clone(), val); let s1 = Sequential::new_nonblk_assign(y, a); let mut i0 = SequentialIfElse::new(c0); let mut i1 = SequentialIfElse::new(c1); i0.add_seq(s0); i1.add_seq(s1); i0.set_else(i1); let exp = r#"if(reset) begin y <= 0; end else if(en) begin y <= a; end"#; let res = i0.to_string(); check!(res, exp); } #[test] fn test_parallel_assign() { let val = Expr::new_ulit_dec(32, "3"); let var = Expr::new_ref("a"); let par = Parallel::Assign(var, val); let exp = "assign a = 32'd3;".to_string(); let res = par.to_string(); check!(res, exp); } #[test] fn test_parallel_always() { let event = Sequential::new_posedge("clock"); let y = Expr::new_ref("y"); let a = Expr::new_ref("a"); let seq = Sequential::new_nonblk_assign(y, a); let mut always = ParallelProcess::new_always(); always.set_event(event); always.add_seq(seq); let exp = r#"always @(posedge clock) begin y <= a; end"#; let res = always.to_string(); check!(res, exp); } #[test] fn test_attribute_decl() { let mut attr = Attribute::default(); attr.add_stmt("ram_style", "block"); let decl = Decl::new_attribute_decl(attr, Decl::new_reg("ram", 32)).to_string(); let gold = r#"(*ram_style = "block"*) reg [31:0] ram"#; check!(decl, gold); } #[test] fn test_module_simple() { let mut module = Module::new("foo"); module.add_input("a", 32); let res = module.to_string(); let exp = r#"module foo ( input wire [31:0] a ); endmodule "#; check!(res, exp); } #[test] fn test_module_empty() { let exp = read_to_string("regression/v05/module_empty.v"); let res = Module::new("empty").to_string(); check!(res, exp); } #[test] fn test_module_attribute() { let exp = read_to_string("regression/v05/module_attribute.v"); let mut attr = Attribute::default(); attr.add_stmt("use", "yes"); let mut module = Module::new("attribute"); module.set_attr(attr); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_one_input() { let exp = read_to_string("regression/v05/module_one_input.v"); let mut module = Module::new("one_input"); module.add_input("a", 5); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_three_inputs() { let exp = read_to_string("regression/v05/module_three_inputs.v"); let mut module = Module::new("three_inputs"); module.add_input("a", 5); module.add_input("b", 61); module.add_input("c", 1); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_one_wire() { let exp = read_to_string("regression/v05/module_one_wire.v"); let mut module = Module::new("one_wire"); let wire = Decl::new_wire("one_wire", 8); module.add_stmt(Stmt::from(wire)); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_one_param() { let exp = read_to_string("regression/v05/module_one_param.v"); let mut module = Module::new("one_param"); module.add_param_uint("width", 32); module.add_input("data", 4); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_two_params() { let exp = read_to_string("regression/v05/module_two_params.v"); let mut module = Module::new("two_params"); module.add_param_uint("width", 4); module.add_param_uint("length", 8); module.add_input("data", 4); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_mix_params() { let exp = read_to_string("regression/v05/module_mix_params.v"); let mut module = Module::new("mix_params"); module.add_param_uint("width", 4); module.add_param_uint("length", 8); module.add_param_str("name", "foo"); module.add_input("data", 4); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_with_instances() { let exp = read_to_string("regression/v05/module_with_instances.v"); let mut i0 = Instance::new("i0", "prim"); let mut i1 = Instance::new("i1", "prim"); let mut i2 = Instance::new("i2", "prim"); let e0 = Expr::new_ulit_hex(4, "0"); let e1 = Expr::new_ulit_hex(4, "8"); let e2 = Expr::new_ulit_hex(4, "f"); i1.add_param_str("name", "multiply"); i2.add_param_uint("WIDTH", 3); i0.connect("port_a", e0); i1.connect("port_a", e1); i2.connect("port_a", e2); let mut module = Module::new("module_with_instances"); module.add_instance(i0); module.add_instance(i1); module.add_instance(i2); let res = module.to_string(); check!(res, exp); } #[test] fn test_module_with_instance_attribute() { let exp = read_to_string("regression/v05/module_with_instance_attribute.v"); let mut attr = Attribute::default(); attr.add_stmt("TYPE", "LUT6"); attr.add_stmt("LOC", "X0Y0"); let mut i0 = Instance::new("i0", "prim"); let e0 = Expr::new_ulit_hex(4, "0"); i0.connect("port_a", e0); i0.set_attr(attr); let mut module = Module::new("module_with_instance_attribute"); module.add_instance(i0); let res = module.to_string(); check!(res, exp); }