#![cfg(test)] use crate::*; macro_rules! test { ( $x:expr, $y:expr, $z:pat ) => { nom_packrat::init!(); let info = SpanInfo::default(); #[cfg(feature = "trace")] let info = info.set_tracable_info( info.get_tracable_info() //.fold("white_space") .fold("number") .fold("binary_operator") .fold("unary_operator"), ); let ret = all_consuming($x)(Span::new_extra($y, info)); if let $z = ret { } else { assert!(false, "{:?}", ret) } }; } mod unit { use super::*; #[test] fn test_pulldown_strength() { test!(pulldown_strength, "(supply0, strong1)", Ok((_, _))); test!(pulldown_strength, "(pull1, weak0)", Ok((_, _))); test!(pulldown_strength, "(pull0)", Ok((_, _))); test!(pulldown_strength, "(pull0)", Ok((_, _))); test!(pulldown_strength, "(pull0)", Ok((_, _))); } #[test] fn test_pullup_strength() { test!(pullup_strength, "(supply0, strong1)", Ok((_, _))); test!(pullup_strength, "(pull1, weak0)", Ok((_, _))); test!(pullup_strength, "(supply1)", Ok((_, _))); } #[test] fn test_cmos_switchtype() { test!(cmos_switchtype, "cmos ", Ok((_, _))); test!(cmos_switchtype, "rcmos ", Ok((_, _))); } #[test] fn test_enable_gatetype() { test!(enable_gatetype, "bufif0 ", Ok((_, _))); test!(enable_gatetype, "bufif1 ", Ok((_, _))); test!(enable_gatetype, "notif0 ", Ok((_, _))); test!(enable_gatetype, "notif1 ", Ok((_, _))); } #[test] fn test_mos_switchtype() { test!(mos_switchtype, "nmos ", Ok((_, _))); test!(mos_switchtype, "pmos ", Ok((_, _))); test!(mos_switchtype, "rnmos ", Ok((_, _))); test!(mos_switchtype, "rpmos ", Ok((_, _))); } #[test] fn test_n_input_gatetype() { test!(n_input_gatetype, "and ", Ok((_, _))); test!(n_input_gatetype, "nand ", Ok((_, _))); test!(n_input_gatetype, "or ", Ok((_, _))); test!(n_input_gatetype, "nor ", Ok((_, _))); test!(n_input_gatetype, "xor ", Ok((_, _))); test!(n_input_gatetype, "xnor ", Ok((_, _))); } #[test] fn test_n_output_gatetype() { test!(n_output_gatetype, "buf ", Ok((_, _))); test!(n_output_gatetype, "not ", Ok((_, _))); } #[test] fn test_pass_en_switchtype() { test!(pass_en_switchtype, "tranif0 ", Ok((_, _))); test!(pass_en_switchtype, "tranif1 ", Ok((_, _))); test!(pass_en_switchtype, "rtranif0 ", Ok((_, _))); test!(pass_en_switchtype, "rtranif1 ", Ok((_, _))); } #[test] fn test_pass_switchtype() { test!(pass_switchtype, "tran ", Ok((_, _))); test!(pass_switchtype, "rtran ", Ok((_, _))); } #[test] fn test_library_text() { test!( library_text, "library rtlLib \"*.v\" -incdir \"aaa\";\ninclude \"bbb\";;", Ok((_, _)) ); } #[test] fn test_timeunits_declaration() { test!(timeunits_declaration, "timeunit 1.0ps;", Ok((_, _))); test!(timeunits_declaration, "timeunit 1.0ps / 20ms;", Ok((_, _))); test!(timeunits_declaration, "timeprecision 10.0fs;", Ok((_, _))); test!( timeunits_declaration, "timeunit 10.0fs; timeprecision 20s;", Ok((_, _)) ); test!( timeunits_declaration, "timeprecision 10.0fs; timeunit 20s \n;", Ok((_, _)) ); } #[test] fn test_inout_declaration() { test!(inout_declaration, "inout a", Ok((_, _))); test!(inout_declaration, "inout [7:0] a", Ok((_, _))); test!(inout_declaration, "inout signed [7:0] a", Ok((_, _))); } #[test] fn test_drive_strength() { test!(drive_strength, "(supply0, strong1)", Ok((_, _))); test!(drive_strength, "(pull1, weak0)", Ok((_, _))); test!(drive_strength, "(pull0, highz1)", Ok((_, _))); test!(drive_strength, "(weak1, highz0)", Ok((_, _))); test!(drive_strength, "(highz0, supply1)", Ok((_, _))); test!(drive_strength, "(highz1, strong0)", Ok((_, _))); } #[test] fn test_charge_strength() { test!(charge_strength, "( small)", Ok((_, _))); test!(charge_strength, "( medium )", Ok((_, _))); test!(charge_strength, "(large)", Ok((_, _))); } #[test] fn test_primary() { test!(primary, "'0", Ok((_, Primary::PrimaryLiteral(_)))); test!(primary, "10", Ok((_, Primary::PrimaryLiteral(_)))); test!(primary, "\"aaa\"", Ok((_, Primary::PrimaryLiteral(_)))); test!(primary, "this ", Ok((_, Primary::This(_)))); test!(primary, "$ ", Ok((_, Primary::Dollar(_)))); test!(primary, "null ", Ok((_, Primary::Null(_)))); } #[test] fn test_cast() { test!(cast, "int'(2.0 * 3.0)", Ok((_, _))); test!(cast, "shortint'({8'hFA,8'hCE}) ", Ok((_, _))); test!(cast, "signed'(x)", Ok((_, _))); test!(cast, "const'(x)", Ok((_, _))); test!(cast, "type_t'(x)", Ok((_, _))); } #[test] fn test_unbased_unsized_literal() { test!(unbased_unsized_literal, "'0", Ok((_, _))); test!(unbased_unsized_literal, "'1", Ok((_, _))); test!(unbased_unsized_literal, "'x", Ok((_, _))); test!(unbased_unsized_literal, "'z", Ok((_, _))); } #[test] fn test_net_lvalue() { test!(net_lvalue, "A", Ok((_, _))); test!(net_lvalue, "{A[7:0],A[15:8],A[23:16]}", Ok((_, _))); test!(net_lvalue, "'{A[7:0],A[15:8]}", Ok((_, _))); } #[test] fn test_variable_lvalue() { test!(variable_lvalue, "A", Ok((_, _))); test!(variable_lvalue, "{A[7:0],A[15:8],A[23:16]}", Ok((_, _))); test!(variable_lvalue, "'{A[7:0],A[15:8]}", Ok((_, _))); } #[test] fn test_nonrange_variable_lvalue() { test!(nonrange_variable_lvalue, "A", Ok((_, _))); test!(nonrange_variable_lvalue, "A[1][2][3]", Ok((_, _))); //TODO //test!(nonrange_variable_lvalue, "A[][2][3]", Ok((_, _))); //test!(nonrange_variable_lvalue, "A[][]", Ok((_, _))); } #[test] fn test_unary_operator() { test!(unary_operator, "+", Ok((_, _))); test!(unary_operator, "-", Ok((_, _))); test!(unary_operator, "!", Ok((_, _))); test!(unary_operator, "&", Ok((_, _))); test!(unary_operator, "|", Ok((_, _))); test!(unary_operator, "~&", Ok((_, _))); test!(unary_operator, "~|", Ok((_, _))); test!(unary_operator, "~^", Ok((_, _))); test!(unary_operator, "^~", Ok((_, _))); test!(unary_operator, "^", Ok((_, _))); test!(unary_operator, "~", Ok((_, _))); } #[test] fn test_binary_operator() { test!(binary_operator, "+", Ok((_, _))); test!(binary_operator, "-", Ok((_, _))); test!(binary_operator, "**", Ok((_, _))); test!(binary_operator, "*", Ok((_, _))); test!(binary_operator, "/", Ok((_, _))); test!(binary_operator, "%", Ok((_, _))); test!(binary_operator, "===", Ok((_, _))); test!(binary_operator, "==?", Ok((_, _))); test!(binary_operator, "==", Ok((_, _))); test!(binary_operator, "!==", Ok((_, _))); test!(binary_operator, "!=?", Ok((_, _))); test!(binary_operator, "!=", Ok((_, _))); test!(binary_operator, "&&", Ok((_, _))); test!(binary_operator, "||", Ok((_, _))); test!(binary_operator, "&", Ok((_, _))); test!(binary_operator, "|", Ok((_, _))); test!(binary_operator, "^~", Ok((_, _))); test!(binary_operator, "^", Ok((_, _))); test!(binary_operator, "~^", Ok((_, _))); test!(binary_operator, ">>>", Ok((_, _))); test!(binary_operator, ">>", Ok((_, _))); test!(binary_operator, "<<<", Ok((_, _))); test!(binary_operator, "<<", Ok((_, _))); test!(binary_operator, "->", Ok((_, _))); test!(binary_operator, "<->", Ok((_, _))); test!(binary_operator, "<=", Ok((_, _))); test!(binary_operator, "<", Ok((_, _))); test!(binary_operator, ">=", Ok((_, _))); test!(binary_operator, ">", Ok((_, _))); } #[test] fn test_inc_or_dec_operator() { test!(inc_or_dec_operator, "++", Ok((_, _))); test!(inc_or_dec_operator, "--", Ok((_, _))); } #[test] fn test_unary_module_path_operator() { test!(unary_module_path_operator, "!", Ok((_, _))); test!(unary_module_path_operator, "&", Ok((_, _))); test!(unary_module_path_operator, "|", Ok((_, _))); test!(unary_module_path_operator, "~&", Ok((_, _))); test!(unary_module_path_operator, "~|", Ok((_, _))); test!(unary_module_path_operator, "~^", Ok((_, _))); test!(unary_module_path_operator, "^~", Ok((_, _))); test!(unary_module_path_operator, "^", Ok((_, _))); test!(unary_module_path_operator, "~", Ok((_, _))); } #[test] fn test_binary_module_path_operator() { test!(binary_module_path_operator, "==", Ok((_, _))); test!(binary_module_path_operator, "!=", Ok((_, _))); test!(binary_module_path_operator, "&&", Ok((_, _))); test!(binary_module_path_operator, "||", Ok((_, _))); test!(binary_module_path_operator, "&", Ok((_, _))); test!(binary_module_path_operator, "|", Ok((_, _))); test!(binary_module_path_operator, "^~", Ok((_, _))); test!(binary_module_path_operator, "^", Ok((_, _))); test!(binary_module_path_operator, "~^", Ok((_, _))); } #[test] fn test_string_literal() { test!(string_literal, "\"aaa aaaa\"", Ok((_, _))); test!(string_literal, r#""aaa\" aaaa""#, Ok((_, _))); test!(string_literal, r#""aaa\"""#, Ok((_, _))); } #[test] fn test_comment() { test!(comment, "// comment", Ok((_, _))); test!(comment, "//", Ok((_, _))); test!(comment, "/* comment\n\n */", Ok((_, _))); } #[test] fn test_expression() { test!(expression, "(!a ? 0 : !b : 1 : c ? 0 : 1)", Ok((_, _))); } #[test] fn test_text_macro_definition() { test!(text_macro_definition, r##"`define a b c"##, Ok((_, _))); test!( text_macro_definition, r##"`define a b \ c"##, Ok((_, _)) ); test!(text_macro_definition, r##"`define a"##, Ok((_, _))); } } mod spec { use super::*; #[test] fn clause3() { test!( module_declaration, r##"module mux2to1 (input wire a, b, sel, // combined port and type declaration output logic y); always_comb begin // procedural block if (sel) y = a; // procedural statement else y = b; end endmodule: mux2to1"##, Ok((_, _)) ); test!( program_declaration, r##"program test (input clk, input [16:1] addr, inout [7:0] data); initial begin end endprogram"##, Ok((_, _)) ); test!( module_declaration, r##"module memMod(simple_bus a); // simple_bus interface port logic avail; // When memMod is instantiated in module top, a.req is the req // signal in the sb_intf instance of the 'simple_bus' interface always @(posedge a.clk) a.gnt <= a.req & avail; endmodule"##, Ok((_, _)) ); test!( module_declaration, r##"module cpuMod(simple_bus b); // simple_bus interface port endmodule"##, Ok((_, _)) ); test!( module_declaration, r##"module top; logic clk = 0; simple_bus sb_intf(.clk(clk)); // Instantiate the interface memMod mem(.a(sb_intf)); // Connect interface to module instance cpuMod cpu(.b(sb_intf)); // Connect interface to module instance endmodule"##, Ok((_, _)) ); test!( package_declaration, r##"package ComplexPkg; typedef struct { shortreal i, r; } Complex; function Complex add(Complex a, b); add.r = a.r + b.r; add.i = a.i + b.i; endfunction function Complex mul(Complex a, b); mul.r = (a.r * b.r) - (a.i * b.i); mul.i = (a.r * b.i) + (a.i * b.r); endfunction endpackage : ComplexPkg"##, Ok((_, _)) ); test!( module_declaration, r##"module top; // module with no ports logic in1, in2, select; // variable declarations wire out1; // net declaration mux2to1 m1 (.a(in1), .b(in2), .sel(select), .y(out1)); // module instance endmodule: top"##, Ok((_, _)) ); test!( module_declaration, r##"module mux2to1 (input wire a, b, sel, // combined port and type declaration output logic y); // netlist using built-in primitive instances not g1 (sel_n, sel); and g2 (a_s, a, sel_n); and g3 (b_s, b, sel); or g4 (y, a_s, b_s); endmodule: mux2to1"##, Ok((_, _)) ); test!( task_declaration, r##"task t; int b; b = 5 + $unit::b; // $unit::b is the one outside endtask"##, Ok((_, _)) ); test!( module_declaration, r##"module D; timeunit 100ps; timeprecision 10fs; endmodule"##, Ok((_, _)) ); test!( module_declaration, r##"module E; timeunit 100ps / 10fs; // timeunit with optional second argument endmodule"##, Ok((_, _)) ); } #[test] fn clause4() { test!( module_declaration, r##"module test; logic a; initial begin a <= 0; a <= 1; end endmodule"##, Ok((_, _)) ); test!( module_declaration, r##"module test; assign p = q; initial begin q = 1; #1 q = 0; $display(p); end endmodule"##, Ok((_, _)) ); } #[test] fn clause5() { test!(identifier, "shiftreg_a", Ok((_, _))); test!(identifier, "busa_index", Ok((_, _))); test!(identifier, "error_condition", Ok((_, _))); test!(identifier, "merge_ab", Ok((_, _))); test!(identifier, "_bus3", Ok((_, _))); test!(identifier, "n$657", Ok((_, _))); test!(identifier, "\\busa+index", Ok((_, _))); test!(identifier, "\\-clock", Ok((_, _))); test!(identifier, "\\***error-condition***", Ok((_, _))); test!(identifier, "\\net1/\\net2", Ok((_, _))); test!(identifier, "\\{a,b}", Ok((_, _))); test!(identifier, "\\a*(b+c)", Ok((_, _))); test!( subroutine_call_statement, "$display (\"display a message\");", Ok((_, _)) ); test!(subroutine_call_statement, "$finish;", Ok((_, _))); test!(primary, "'0", Ok((_, _))); test!(primary, "'1", Ok((_, _))); test!(primary, "'X", Ok((_, _))); test!(primary, "'x", Ok((_, _))); test!(primary, "'Z", Ok((_, _))); test!(primary, "'z", Ok((_, _))); test!(number, "659", Ok((_, Number::IntegralNumber(_)))); test!(number, "'h 837FF", Ok((_, Number::IntegralNumber(_)))); test!(number, "'h 837FF", Ok((_, Number::IntegralNumber(_)))); test!(number, "'o7460", Ok((_, Number::IntegralNumber(_)))); test!(number, "'4af", Err(_)); test!(number, "4'b1001", Ok((_, Number::IntegralNumber(_)))); test!(number, "5 'D 3", Ok((_, Number::IntegralNumber(_)))); test!(number, "3'b01x", Ok((_, Number::IntegralNumber(_)))); test!(number, "12'hx", Ok((_, Number::IntegralNumber(_)))); test!(number, "16'hz", Ok((_, Number::IntegralNumber(_)))); test!(number, "8 'd -6", Err(_)); test!(number, "4 'shf", Ok((_, Number::IntegralNumber(_)))); test!(number, "16'sd?", Ok((_, Number::IntegralNumber(_)))); test!(number, "27_195_000", Ok((_, Number::IntegralNumber(_)))); test!( number, "16'b0011_0101_0001_1111", Ok((_, Number::IntegralNumber(_))) ); test!( number, "32 'h 12ab_f001", Ok((_, Number::IntegralNumber(_))) ); test!(number, "1.2", Ok((_, Number::RealNumber(_)))); test!(number, "0.1", Ok((_, Number::RealNumber(_)))); test!(number, "2394.26331", Ok((_, Number::RealNumber(_)))); test!(number, "1.2E12", Ok((_, Number::RealNumber(_)))); test!(number, "1.30e-2", Ok((_, Number::RealNumber(_)))); test!(number, "0.1e-0", Ok((_, Number::RealNumber(_)))); test!(number, "23E10", Ok((_, Number::RealNumber(_)))); test!(number, "29E-2", Ok((_, Number::RealNumber(_)))); test!(number, "236.123_763_e-12", Ok((_, Number::RealNumber(_)))); test!(number, ".12", Err(_)); test!(number, "9.", Err(_)); test!(number, "4.E3", Err(_)); test!(number, ".2e-7", Err(_)); test!(primary, "2.1ns ", Ok((_, Primary::PrimaryLiteral(_)))); test!(primary, "40 ps ", Ok((_, Primary::PrimaryLiteral(_)))); test!( subroutine_call_statement, r##"$display("Humpty Dumpty sat on a wall. \ Humpty Dumpty had a great fall.");"##, Ok((_, _)) ); test!( subroutine_call_statement, r##"$display("Humpty Dumpty sat on a wall.\n\ Humpty Dumpty had a great fall.");"##, Ok((_, _)) ); test!(module_item, r##"byte c1 = "A" ;"##, Ok((_, _))); test!(module_item, r##"bit [7:0] d = "\n" ;"##, Ok((_, _))); test!( module_item, r##"bit [8*12:1] stringvar = "Hello world\n";"##, Ok((_, _)) ); test!( module_item, r##"bit [0:11] [7:0] stringvar = "Hello world\n" ;"##, Ok((_, _)) ); test!( module_item, r##"byte c3 [0:12] = "hello world\n" ;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct {int a; shortreal b;} ab; ab c; c = '{0, 0.0}; // structure literal type determined from // the left-hand context (c)"##, Ok((_, _)) ); test!( module_item, r##"ab abarr[1:0] = '{'{1, 1.0}, '{2, 2.0}};"##, Ok((_, _)) ); test!( many1(module_item), r##"c = '{a:0, b:0.0}; // member name and value for that member c = '{default:0}; // all elements of structure c are set to 0 d = ab'{int:1, shortreal:1.0}; // data type and default value for all // members of that type"##, Ok((_, _)) ); test!( module_item, r##"ab abarr[1:0] = '{'{1, 1.0}, '{2, 2.0}};"##, Ok((_, _)) ); test!( many1(module_item), r##"struct {int X,Y,Z;} XYZ = '{3{1}}; typedef struct {int a,b[4];} ab_t; int a,b,c; ab_t v1[1:0] [2:0]; v1 = '{2{'{3{'{a,'{2{b,c}}}}}}};"##, Ok((_, _)) ); test!( module_item, r##"int n[1:2][1:3] = '{'{0,1,2},'{3{4}}};"##, Ok((_, _)) ); test!( module_item, r##"int n[1:2][1:6] = '{2{'{3{4, 5}}}}; // same as '{'{4,5,4,5,4,5},'{4,5,4,5,4,5}}"##, Ok((_, _)) ); test!(module_item, r##"typedef int triple [1:3];"##, Ok((_, _))); test!( module_item, r##"triple b = '{1:1, default:0}; // indices 2 and 3 assigned 0"##, Ok((_, _)) ); test!( attribute_instance, r##"(* full_case, parallel_case *)"##, Ok((_, _)) ); test!(attribute_instance, r##"(* full_case=1 *)"##, Ok((_, _))); test!( attribute_instance, r##"(* full_case, // no value assigned parallel_case=1 *)"##, Ok((_, _)) ); test!(attribute_instance, r##"(* full_case *)"##, Ok((_, _))); test!( attribute_instance, r##"(* full_case=1, parallel_case = 0 *)"##, Ok((_, _)) ); test!( many1(module_item), r##"(* fsm_state *) logic [7:0] state1; (* fsm_state=1 *) logic [3:0] state2, state3; logic [3:0] reg1; // reg1 does NOT have fsm_state set (* fsm_state=0 *) logic [3:0] reg2; // nor does reg2"##, Ok((_, _)) ); test!( module_item, r##"a = b + (* mode = "cla" *) c; // sets the value for the attribute mode // to be the string cla."##, Ok((_, _)) ); test!( module_item, r##"a = add (* mode = "cla" *) (b, c);"##, Ok((_, _)) ); test!( module_item, r##"a = b ? (* no_glitch *) c : d;"##, Ok((_, _)) ); } #[test] fn clause6() { test!( many1(module_item), r##"trireg a; // trireg net of charge strength medium trireg (large) #(0,0,50) cap1; // trireg net of charge strength large // with charge decay time 50 time units trireg (small) signed [3:0] cap2; // signed 4-bit trireg vector of // charge strength small"##, Ok((_, _)) ); test!( many1(module_item), r##"struct { bit [7:0] A; bit [7:0] B; byte C; } abc;"##, Ok((_, _)) ); test!( many1(module_item), r##"assign abc.C = sel ? 8'hBE : 8'hEF; not (abc.A[0],abc.B[0]), (abc.A[1],abc.B[1]), (abc.A[2],abc.B[2]), (abc.A[3],abc.B[3]); always @(posedge clk) abc.B <= abc.B + 1;"##, Ok((_, _)) ); test!( many1(module_item), r##"assign abc.C = sel ? 8'hDE : 8'hED; // Mixing continuous and procedural assignments to abc.A[3] always @(posedge clk) abc.A[7:3] <= !abc.B[7:3];"##, Ok((_, _)) ); test!( many1(module_item), r##"wire w = vara & varb; // net with a continuous assignment logic v = consta & constb; // variable with initialization logic vw; // no initial assignment assign vw = vara & varb; // continuous assignment to a variable real circ; assign circ = 2.0 * PI * R; // continuous assignment to a variable"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct { real field1; bit field2; } T; // user-defined resolution function Tsum function automatic T Tsum (input T driver[]); Tsum.field1 = 0.0; foreach (driver[i]) Tsum.field1 += driver[i].field1; endfunction nettype T wT; // an unresolved nettype wT whose data type is T // a nettype wTsum whose data type is T and // resolution function is Tsum nettype T wTsum with Tsum; // user-defined data type TR typedef real TR[5]; // an unresolved nettype wTR whose data type // is an array of real nettype TR wTR; // declare another name nettypeid2 for nettype wTsum nettype wTsum nettypeid2;"##, Ok((_, _)) ); test!( many1(module_item), r##"class Base #(parameter p = 1); typedef struct { real r; bit[p-1:0] data; } T; static function T Tsum (input T driver[]); Tsum.r = 0.0; Tsum.data = 0; foreach (driver[i]) Tsum.data += driver[i].data; Tsum.r = $itor(Tsum.data); endfunction endclass typedef Base#(32) MyBaseT; nettype MyBaseT::T narrowTsum with MyBaseT::Tsum; typedef Base#(64) MyBaseType; nettype MyBaseType::T wideTsum with MyBaseType::Tsum; narrowTsum net1; // data is 32 bits wide wideTsum net2; // data is 64 bits wide"##, Ok((_, _)) ); test!( source_text, r##"package NetsPkg; nettype real realNet; endpackage : NetsPkg module top(); interconnect [0:1] iBus; lDriver l1(iBus[0]); rDriver r1(iBus[1]); rlMod m1(iBus); endmodule : top module lDriver(output wire logic out); endmodule : lDriver module rDriver import NetsPkg::*; (output realNet out); endmodule : rDriver module rlMod(input interconnect [0:1] iBus); lMod l1(iBus[0]); rMod r1(iBus[1]); endmodule : rlMod"##, Ok((_, _)) ); test!( library_text, r##"library realLib *.svr; library logicLib *.sv; config cfgReal; design logicLib.top; default liblist realLib logicLib; endconfig config cfgLogic; design logicLib.top; default liblist logicLib realLib; endconfig"##, Ok((_, _)) ); test!( source_text, r##"module top(); interconnect [0:3] [0:1] aBus; logic [0:3] dBus; driver driverArray[0:3](aBus); cmp cmpArray[0:3](aBus,rst,dBus); endmodule : top"##, Ok((_, _)) ); test!( source_text, r##"package NetsPkg; nettype real realNet; endpackage : NetsPkg"##, Ok((_, _)) ); test!( source_text, r##"module driver import NetsPkg::*; #(parameter int delay = 30, int iterations = 256) (output realNet [0:1] out); timeunit 1ns / 1ps; real outR[1:0]; assign out = outR; initial begin outR[0] = 0.0; outR[1] = 3.3; for (int i = 0; i < iterations; i++) begin #delay outR[0] += 0.2; outR[1] -= 0.2; end end endmodule : driver"##, Ok((_, _)) ); test!( source_text, r##"module driver #(parameter int delay = 30, int iterations = 256) (output wire logic [0:1] out); timeunit 1ns / 1ps; logic [0:1] outvar; assign out = outvar; initial begin outvar = '0; for (int i = 0; i < iterations; i++) #delay outvar++; end endmodule : driver"##, Ok((_, _)) ); test!( source_text, r##"module cmp import NetsPkg::*; #(parameter real hyst = 0.65) (input realNet [0:1] inA, input logic rst, output logic out); timeunit 1ns / 1ps; real updatePeriod = 100.0; initial out = 1'b0; always #updatePeriod begin if (rst) out <= 1'b0; else if (inA[0] > inA[1]) out <= 1'b1; else if (inA[0] < inA[1] - hyst) out <= 1'b0; end endmodule : cmp"##, Ok((_, _)) ); test!( source_text, r##"module cmp #(parameter real hyst = 0.65) (input wire logic [0:1] inA, input logic rst, output logic out); initial out = 1'b0; always @(inA, rst) begin if (rst) out <= 1'b0; else if (inA[0] & ~inA[1]) out <= 1'b1; else out <= 1'b0; end endmodule : cmp"##, Ok((_, _)) ); test!( many1(module_item), r##"trireg (large) logic #(0,0,0) cap1; typedef logic [31:0] addressT; wire addressT w1; wire struct packed { logic ecc; logic [7:0] data; } memsig;"##, Ok((_, _)) ); test!( many1(module_item), r##"wire w; // equivalent to "wire logic w;" wire [15:0] ww; // equivalent to "wire logic [15:0] ww;""##, Ok((_, _)) ); test!( many1(module_item), r##"tri reg r; inout wire reg p;"##, Ok((_, _)) ); test!( many1(module_item), r##"interconnect w1; // legal interconnect [3:0] w2; // legal interconnect [3:0] w3 [1:0]; // legal"##, Ok((_, _)) ); test!( many1(module_item), r##"nettype T wT; // a nettype wTsum whose data type is T and // resolution function is Tsum // Refer to example in 6.6.7 for the declaration of Tsum nettype T wTsum with Tsum; // a net of unresolved nettype wT wT w1; // an array of nets, each net element is of unresolved nettype wT wT w2[8]; // a net of resolved nettype wTsum and resolution function Tsum wTsum w3; // an array of nets, each net is of resolved nettype wTsum wTsum w4[8]; // user-defined data type TR which is an array of reals typedef real TR[5]; // an unresolved nettype wTR with data type TR nettype TR wTR; // a net with unresolved nettype wTR and data type TR wTR w5; // an array of nets, each net has an unresolved nettype wTR // and data type TR wTR w6[8];"##, Ok((_, _)) ); test!(many1(module_item), r##"shortint s1, s2[0:9];"##, Ok((_, _))); test!( many1(module_item), r##"var byte my_byte; // equivalent to "byte my_byte;" var v; // equivalent to "var logic v;" var [15:0] vw; // equivalent to "var logic [15:0] vw;" var enum bit { clear, error } status; input var logic data_in; var reg r;"##, Ok((_, _)) ); test!(many1(module_item), r##"int i = 0;"##, Ok((_, _))); test!( many1(module_item), r##"wand w; // a scalar "wand" net tri [15:0] busa; // a 16-bit bus trireg (small) storeit; // a charge storage node of strength small logic a; // a scalar variable logic[3:0] v; // a 4-bit vector made up of (from most to // least significant)v[3], v[2], v[1], and v[0] logic signed [3:0] signed_reg; // a 4-bit vector in range -8 to 7 logic [-1:4] b; // a 6-bit vector wire w1, w2; // declares two nets logic [4:0] x, y, z; // declares three 5-bit variables"##, Ok((_, _)) ); test!( many1(module_item), r##"tri1 scalared [63:0] bus64; //a bus that will be expanded tri vectored [31:0] data; //a bus that may or may not be expanded"##, Ok((_, _)) ); test!( many1(module_item), r##"int unsigned ui; int signed si;"##, Ok((_, _)) ); test!( many1(module_item), r##"chandle variable_name ;"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter string default_name = "John Smith"; string myName = default_name;"##, Ok((_, _)) ); test!( many1(module_item), r##"byte c = "A"; // assigns to c "A" bit [10:0] b = "\x41"; // assigns to b 'b000_0100_0001 bit [1:4][7:0] h = "hello" ; // assigns to h "ello""##, Ok((_, _)) ); test!( many1(module_item), r##"string s0 = "String literal assign";// sets s0 to "String literal assign" string s1 = "hello\0world"; // sets s1 to "helloworld" bit [11:0] b = 12'ha41; string s2 = string'(b); // sets s2 to 16'h0a41"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef logic [15:0] r_t; r_t r; integer i = 1; string b = ""; string a = {"Hi", b}; r = r_t'(a); // OK b = string'(r); // OK b = "Hi"; // OK b = {5{"Hi"}}; // OK a = {i{"Hi"}}; // OK (non-constant replication) r = {i{"Hi"}}; // invalid (non-constant replication) a = {i{b}}; // OK a = {a,b}; // OK a = {"Hi",b}; // OK r = {"H",""}; // yields "H\0". "" is converted to 8'b0 b = {"H",""}; // yields "H". "" is the empty string a[0] = "h"; // OK, same as a[0] = "cough" a[0] = b; // invalid, requires a cast a[1] = "\0"; // ignored, a is unchanged"##, Ok((_, _)) ); test!( many1(module_item), r##"str = "123"; int i = str.atoi(); // assigns 123 to i."##, Ok((_, _)) ); test!( many1(module_item), r##"event done; // declare a new event called done event done_too = done; // declare done_too as alias to done event empty = null; // event variable with no synchronization object"##, Ok((_, _)) ); test!(many1(module_item), r##"typedef int intP;"##, Ok((_, _))); test!(many1(module_item), r##"intP a, b;"##, Ok((_, _))); test!( source_text, r##"interface intf_i; typedef int data_t; endinterface module sub(intf_i p); typedef p.data_t my_data_t; my_data_t data; // type of 'data' will be int when connected to interface above endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum type_identifier; typedef struct type_identifier; typedef union type_identifier; typedef class type_identifier; typedef interface class type_identifier; typedef type_identifier;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef C; C::T x; // illegal; C is an incomplete forward type typedef C::T c_t; // legal; reference to C::T is made by a typedef c_t y; class C; typedef int T; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"enum {red, yellow, green} light1, light2; // anonymous int type"##, Ok((_, _)) ); test!( many1(module_item), r##"enum bit [1:0] {IDLE, XX='x, S1=2'b01, S2=2'b10} state, next;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum integer {IDLE, XX='x, S1, S2} state, next;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum {bronze=3, silver, gold} medal; // silver=4, gold=5"##, Ok((_, _)) ); test!( many1(module_item), r##"enum {a=3, b=7, c} alphabet;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum {a=0, b=7, c, d=8} alphabet;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum {a, b=7, c} alphabet;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum bit [3:0] {bronze='h3, silver, gold='h5} medal2; // Correct declaration - bronze and gold sizes are redundant enum bit [3:0] {bronze=4'h3, silver, gold=4'h5} medal3; // Error in the bronze and gold member declarations enum bit [3:0] {bronze=5'h13, silver, gold=3'h5} medal4; // Error in c declaration, requires at least 2 bits enum bit [0:0] {a,b,c} alphabet;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum {NO, YES} boolean; boolean myvar; // named type"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum { add=10, sub[5], jmp[6:8] } E1;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum { register[2] = 1, register[2:4] = 10 } vr;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum { red, green, blue, yellow, white, black } Colors;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum { red, green, blue, yellow, white, black } Colors; Colors col; integer a, b; a = blue * 3; col = yellow; b = col + green;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum {Red, Green, Blue} Colors; typedef enum {Mo,Tu,We,Th,Fr,Sa,Su} Week; Colors C; Week W; int I; C = Colors'(C+1); // C is converted to an integer, then added to // one, then converted back to a Colors type C = Colors'(Su); // Legal; puts an out of range value into C I = C + W; // Legal; C and W are automatically cast to int"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef enum { red, green, blue, yellow } Colors; Colors c = c.first; forever begin $display( "%s : %d\n", c.name, c ); if( c == c.last ) break; c = c.next; end end"##, Ok((_, _)) ); test!( many1(module_item), r##"localparam byte colon1 = ":" ; specparam delay = 10 ; // specparams are used for specify blocks parameter logic flag = 1 ;"##, Ok((_, _)) ); test!( source_text, r##"class vector #(size = 1); // size is a parameter in a parameter port list logic [size-1:0] v; endclass interface simple_bus #(AWIDTH = 64, type T = word) // parameter port list (input logic clk) ; // port list endinterface"##, Ok((_, _)) ); test!( source_text, r##"module mc #(int N = 5, M = N*16, type T = int, T x = 0) (); endmodule"##, Ok((_, _)) ); test!( source_text, r##"class Mem #(type T, int size); T words[size]; endclass typedef Mem#(byte, 1024) Kbyte;"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter msb = 7; // defines msb as a constant value 7 parameter e = 25, f = 9; // defines two constant numbers parameter r = 5.7; // declares r as a real parameter parameter byte_size = 8, byte_mask = byte_size - 1; parameter average_delay = (r + f) / 2; parameter signed [3:0] mux_selector = 0; parameter real r1 = 3.5e17; parameter p1 = 13'h7e; parameter [31:0] dec_const = 1'b1; // value converted to 32 bits parameter newconst = 3'h4; // implied range of [2:0] parameter newconst = 4; // implied range of at least [31:0]"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter logic [31:0] P1 [3:0] = '{ 1, 2, 3, 4 } ; // unpacked array // parameter declaration"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter r2 = $; property inq1(r1,r2); @(posedge clk) a ##[r1:r2] b ##1 c |=> d; endproperty assert property (inq1(3, r2));"##, Ok((_, _)) ); test!( many1(module_item), r##"interface quiet_time_checker #(parameter min_quiet = 0, parameter max_quiet = 0) (input logic clk, reset_n, logic [1:0]en); generate if ( max_quiet == 0) begin property quiet_time; @(posedge clk) reset_n |-> ($countones(en) == 1); endproperty a1: assert property (quiet_time); end else begin property quiet_time; @(posedge clk) (reset_n && ($past(en) != 0) && en == 0) |->(en == 0)[*min_quiet:max_quiet] ##1 ($countones(en) == 1); endproperty a1: assert property (quiet_time); end if ((min_quiet == 0) && ($isunbounded(max_quiet))) $warning(warning_msg); endgenerate endinterface quiet_time_checker #(0, 0) quiet_never (clk,1,enables); quiet_time_checker #(2, 4) quiet_in_window (clk,1,enables); quiet_time_checker #(0, $) quiet_any (clk,1,enables);"##, Ok((_, _)) ); test!( many1(module_item), r##"interface width_checker #(parameter min_cks = 1, parameter max_cks = 1) (input logic clk, reset_n, expr); generate if ($isunbounded(max_cks)) begin property width; @(posedge clk) (reset_n && $rose(expr)) |-> (expr [* min_cks]); endproperty a2: assert property (width); end else begin property assert_width_p; @(posedge clk) (reset_n && $rose(expr)) |-> (expr[* min_cks:max_cks]) ##1 (!expr); endproperty a2: assert property (width); end endgenerate endinterface width_checker #(3, $) max_width_unspecified (clk,1,enables); width_checker #(2, 4) width_specified (clk,1,enables);"##, Ok((_, _)) ); test!( source_text, r##"module ma #( parameter p1 = 1, parameter type p2 = shortint ) (input logic [p1:0] i, output logic [p1:0] o); p2 j = 0; // type of j is set by a parameter, (shortint unless redefined) always @(i) begin o = i; j++; end endmodule module mb; logic [3:0] i,o; ma #(.p1(3), .p2(int)) u1(i,o); //redefines p2 to a type of int endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"specify specparam tRise_clk_q = 150, tFall_clk_q = 200; specparam tRise_control = 40, tFall_control = 50; endspecify"##, Ok((_, _)) ); test!( source_text, r##"module RAM16GEN ( output [7:0] DOUT, input [7:0] DIN, input [5:0] ADR, input WE, CE); specparam dhold = 1.0; specparam ddly = 1.0; parameter width = 1; parameter regsize = dhold + 1.0; // Illegal - cannot assign // specparams to parameters endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"const logic option = a.b.c ;"##, Ok((_, _)) ); test!( many1(module_item), r##"const class_name object = new(5,3);"##, Ok((_, _)) ); test!( source_text, r##"module msl; int st0; // static initial begin int st1; // static static int st2; // static automatic int auto1; // automatic end task automatic t1(); int auto2; // automatic static int st3; // static automatic int auto3; // automatic endtask endmodule"##, Ok((_, _)) ); test!( source_text, r##"module top_legal; int svar1 = 1; // static keyword optional initial begin for (int i=0; i<3; i++) begin automatic int loop3 = 0; // executes every loop for (int j=0; j<3; j++) begin loop3++; $display(loop3); end end // prints 1 2 3 1 2 3 1 2 3 for (int i=0; i<3; i++) begin static int loop2 = 0; // executes once at time zero for (int j=0; j<3; j++) begin loop2++; $display(loop2); end end // prints 1 2 3 4 5 6 7 8 9 end endmodule : top_legal module top_illegal; // should not compile initial begin int svar2 = 2; // static/automatic needed to show intent for (int i=0; i<3; i++) begin int loop3 = 0; // illegal statement for (int i=0; i<3; i++) begin loop3++; $display(loop3); end end end endmodule : top_illegal"##, Ok((_, _)) ); test!( source_text, r##"program automatic test ; int i; // not within a procedural block - static task t ( int a ); // arguments and variables in t are automatic endtask endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef bit node; // 'bit' and 'node' are matching types typedef type1 type2; // 'type1' and 'type2' are matching types"##, Ok((_, _)) ); test!( many1(module_item), r##"struct packed {int A; int B;} AB1, AB2; // AB1, AB2 have matching types struct packed {int A; int B;} AB3; // the type of AB3 does not match // the type of AB1"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct packed {int A; int B;} AB_t; AB_t AB1; AB_t AB2; // AB1 and AB2 have matching types typedef struct packed {int A; int B;} otherAB_t; otherAB_t AB3; // the type of AB3 does not match the type of AB1 or AB2"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef bit signed [7:0] BYTE; // matches the byte type typedef bit signed [0:7] ETYB; // does not match the byte type"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef byte MEM_BYTES [256]; typedef bit signed [7:0] MY_MEM_BYTES [256]; // MY_MEM_BYTES matches // MEM_BYTES typedef logic [1:0] [3:0] NIBBLES; typedef logic [7:0] MY_BYTE; // MY_BYTE and NIBBLES are not matching types typedef logic MD_ARY [][2:0]; typedef logic MD_ARY_TOO [][0:2]; // Does not match MD_ARY"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef byte signed MY_CHAR; // MY_CHAR matches the byte type"##, Ok((_, _)) ); test!( many1(module_item), r##"struct {int A; int B;} AB1, AB2; // AB1, AB2 have equivalent types struct {int A; int B;} AB3; // AB3 is not type equivalent to AB1"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef bit signed [7:0] BYTE; // equivalent to the byte type typedef struct packed signed {bit[3:0] a, b;} uint8; // equivalent to the byte type"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [9:0] A [0:5]; bit [1:10] B [6]; typedef bit [10:1] uint10; uint10 C [6:1]; // A, B and C have equivalent types typedef int anint [0:0]; // anint is not type equivalent to int"##, Ok((_, _)) ); test!( source_text, r##"package p1; typedef struct {int A;} t_1; endpackage typedef struct {int A;} t_2; module sub(); import p1::t_1; parameter type t_3 = int; parameter type t_4 = int; typedef struct {int A;} t_5; t_1 v1; t_2 v2; t_3 v3; t_4 v4; t_5 v5; endmodule module top(); typedef struct {int A;} t_6; sub #(.t_3(t_6)) s1 (); sub #(.t_3(t_6)) s2 (); initial begin s1.v1 = s2.v1; // legal - both types from package p1 (rule 8) s1.v2 = s2.v2; // legal - both types from $unit (rule 4) s1.v3 = s2.v3; // legal - both types from top (rule 2) s1.v4 = s2.v4; // legal - both types are int (rule 1) s1.v5 = s2.v5; // illegal - types from s1 and s2 (rule 4) end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"nettype nettypeid1 nettypeid2;"##, Ok((_, _)) ); test!( many1(module_item), r##"var type(a+b) c, d; c = type(i+3)'(v[15:0]);"##, Ok((_, _)) ); test!( many1(module_item), r##"localparam type T = type(bit[12:0]);"##, Ok((_, _)) ); // TODO // What is addfixed_int/add_float? UDP? //test!( // many1(module_item), // r##"bit [12:0] A_bus, B_bus; // parameter type bus_t = type(A_bus); // generate // case (type(bus_t)) // type(bit[12:0]): addfixed_int #(bus_t) (A_bus,B_bus); // type(real): add_float #(type(A_bus)) (A_bus,B_bus); // endcase // endgenerate"##, // Ok((_, _)) //); test!( many1(module_item), r##"A = cast_t1'(expr_1) + cast_t2'(expr_2);"##, Ok((_, _)) ); test!( many1(module_item), r##"cast_t1 temp1; cast_t2 temp2; temp1 = expr_1; temp2 = expr_2; A = temp1 + temp2;"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [7:0] regA; logic signed [7:0] regS; regA = unsigned'(-4); // regA = 8'b11111100 regS = signed'(4'b1100); // regS = -4"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct { bit isfloat; union { int i; shortreal f; } n; // anonymous type } tagged_st; // named structure typedef bit [$bits(tagged_st) - 1 : 0] tagbits; // tagged_st defined above tagged_st a [7:0]; // unpacked array of structures tagbits t = tagbits'(a[3]); // convert structure to array of bits a[4] = tagged_st'(t); // convert array of bits back to structure"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef enum { red, green, blue, yellow, white, black } Colors; Colors col; $cast( col, 2 + 3 ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin if ( ! $cast( col, 2 + 8 ) ) // 10: invalid cast $display( "Error in cast" ); end"##, Ok((_, _)) ); test!(many1(module_item), r##"col = Colors'(2 + 3);"##, Ok((_, _))); test!(many1(module_item), r##"B = dest_t'(A);"##, Ok((_, _))); test!( many1(module_item), r##"struct {bit[7:0] a; shortint b;} a; int b = int'(a); // Illegal conversion from 20-bit struct to int (32 bits) - run time error struct {bit a[$]; shortint b;} a = {{1,2,3,4}, 67}; int b = int'(a); // Illegal conversion from int (32 bits) to struct dest_t (25 or 33 bits), // compile time error typedef struct {byte a[$]; bit b;} dest_t; int a; dest_t b = dest_t'(a);"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct { shortint address; logic [3:0] code; byte command [2]; } Control; typedef bit Bits [36:1]; Control p; Bits stream[$]; initial begin stream.push_back(Bits'(p)); // append packet to unpacked queue of Bits end initial begin Bits b; Control q; b = stream.pop_front(); // get packet (as Bits) from stream q = Control'(b); // convert packet bits back to a Control packet end"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct { byte length; shortint address; byte payload[]; byte chksum; } Packet;"##, Ok((_, _)) ); // TODO // randomize can't take hierarchical identifier //test!( // many1(module_item), // r##"function Packet genPkt(); // Packet p; // void'( randomize( p.address, p.length, p.payload ) // with { p.length > 1 && p.payload.size == p.length; } ); // p.chksum = p.payload.xor(); // return p; // endfunction"##, // Ok((_, _)) //); test!( many1(module_item), r##"typedef byte channel_type[$]; channel_type channel; channel = {channel, channel_type'(genPkt())};"##, Ok((_, _)) ); // TODO // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), // r##"initial begin // Packet p; // int size; // size = channel[0] + 4; // p = Packet'( channel[0 : size - 1] ); // convert stream to Packet // channel = channel[ size : $ ]; // update the stream so it now // // lacks that packet // end"##, // Ok((_, _)) //); test!( source_text, r##"virtual class C#(parameter type T = logic, parameter SIZE = 1); typedef logic [SIZE-1:0] t_vector; typedef T t_array [SIZE-1:0]; typedef struct { t_vector m0 [2*SIZE-1:0]; t_array m1; } t_struct; endclass"##, Ok((_, _)) ); test!( source_text, r##"module top (); typedef logic [7:0] t_t0; C#(t_t0,3)::t_vector v0; C#(t_t0,3)::t_array a0; C#(bit,4)::t_struct s0; endmodule"##, Ok((_, _)) ); } #[test] fn clause7() { test!( many1(module_item), r##"struct { bit [7:0] opcode; bit [23:0] addr; }IR; // anonymous structure // defines variable IR initial begin IR.opcode = 1; // set field in IR. end typedef struct { bit [7:0] opcode; bit [23:0] addr; } instruction; // named structure type instruction IR; // define variable"##, Ok((_, _)) ); test!( many1(module_item), r##"struct packed signed { int a; shortint b; byte c; bit [7:0] d; } pack1; // signed, 2-state struct packed unsigned { time a; integer b; logic [31:0] c; } pack2; // unsigned, 4-state"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct packed { // default unsigned bit [3:0] GFC; bit [7:0] VPI; bit [11:0] VCI; bit CLP; bit [3:0] PT ; bit [7:0] HEC; bit [47:0] [7:0] Payload; bit [2:0] filler; } s_atmcell;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct { int addr = 1 + constant; int crc; byte data [4] = '{4{1}}; } packet1;"##, Ok((_, _)) ); test!( many1(module_item), r##"packet1 p1; // initialization defined by the typedef. // p1.crc will use the default value for an int"##, Ok((_, _)) ); test!( many1(module_item), r##"packet1 pi = '{1,2,'{2,3,4,5}}; //suppresses the typedef initialization"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef union { int i; shortreal f; } num; // named union type num n; initial begin n.f = 0.0; // set n in floating point format end typedef struct { bit isfloat; union { int i; shortreal f; } n; // anonymous union type } tagged_st; // named structure"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef union packed { // default unsigned s_atmcell acell; bit [423:0] bit_slice; bit [52:0][7:0] byte_slice; } u_atmcell; u_atmcell u1; byte b; bit [3:0] nib; b = u1.bit_slice[415:408]; // same as b = u1.byte_slice[51]; nib = u1.bit_slice [423:420]; // same as nib = u1.acell.GFC;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef union tagged { void Invalid; int Valid; } VInt;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef union tagged { struct { bit [4:0] reg1, reg2, regd; } Add; union tagged { bit [9:0] JmpU; struct { bit [1:0] cc; bit [9:0] addr; } JmpC; } Jmp; } Instr;"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [7:0] c1; // packed array of scalar bit types real u [7:0]; // unpacked array of real types"##, Ok((_, _)) ); test!( many1(module_item), r##"byte c2; // same as bit signed [7:0] c2; integer i1; // same as logic signed [31:0] i1;"##, Ok((_, _)) ); test!( many1(module_item), r##"int Array[0:7][0:31]; // array declaration using ranges int Array[8][32]; // array declaration using sizes"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [7:0] mema [0:255]; // declares a memory array of 256 8-bit // elements. The array indices are 0 to 255 mema[5] = 0; // Write to word at address 5 data = mema[addr]; // Read word at address indexed by addr"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [3:0] [7:0] joe [1:10]; // 10 elements of 4 8-bit bytes // (each element packed into 32 bits)"##, Ok((_, _)) ); test!( many1(module_item), r##"joe[9] = joe[8] + 1; // 4 byte add joe[7][3:2] = joe[6][1:0]; // 2 byte copy"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [1:10] v1 [1:5]; // 1 to 10 varies most rapidly; compatible with memory arrays bit v2 [1:5] [1:10]; // 1 to 10 varies most rapidly, compatible with C bit [1:5] [1:10] v3 ; // 1 to 10 varies most rapidly bit [1:5] [1:6] v4 [1:7] [1:8]; // 1 to 6 varies most rapidly, followed by // 1 to 5, then 1 to 8 and then 1 to 7"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef bit [1:5] bsix; bsix [1:10] v5; // 1 to 5 varies most rapidly"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef bsix mem_type [0:3]; // array of four 'bsix' elements mem_type ba [0:7]; // array of eight 'mem_type' elements"##, Ok((_, _)) ); test!( many1(module_item), r##"int A[2][3][4], B[2][3][4], C[5][4]; A[0][2] = B[1][1]; // assign a subarray composed of four ints A[1] = B[0]; // assign a subarray composed of three arrays of // four ints each A = B; // assign an entire array A[0][1] = C[4]; // assign compatible subarray of four ints"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [7:0] [31:0] v7 [1:5] [1:10], v8 [0:255]; // two arrays declared"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [63:0] data; logic [7:0] byte2; byte2 = data[23:16]; // an 8-bit part-select from data"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [3:0] [7:0] j; // j is a packed array byte k; k = j[2]; // select a single 8-bit element from j"##, Ok((_, _)) ); test!( many1(module_item), r##"bit signed [31:0] busA [7:0] ; // unpacked array of 8 32-bit vectors int busB [1:0]; // unpacked array of 2 integers busB = busA[7:6]; // select a 2-vector slice from busA"##, Ok((_, _)) ); test!( many1(module_item), r##"int i = bitvec[j +: k]; // k must be constant. int a[x:y], b[y:z], e; a = {b[c -: d], e}; // d must be constant"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [3:0] nibble[]; // Dynamic array of 4-bit vectors integer mem[2][]; // Fixed-size unpacked array composed // of 2 dynamic subarrays of integers"##, Ok((_, _)) ); test!( many1(module_item), r##"int arr1 [][2][3] = new [4]; // arr1 sized to length 4; elements are // fixed-size arrays and so do not require // initializing int arr2 [][] = new [4]; // arr2 sized to length 4; dynamic subarrays // remain unsized and uninitialized"##, Ok((_, _)) ); test!( many1(module_item), r##"int arr[2][][]; initial begin arr[0] = new [4]; // dynamic subarray arr[0] sized to length 4 arr[0][0] = new [2]; // legal, arr[0][n] created above for n = 0..3 arr[1][0] = new [2]; // illegal, arr[1] not initialized so arr[1][0] does // not exist arr[0][1][1] = new[2]; // illegal, arr[0][1][1] is an int, not a dynamic // array end"##, Ok((_, _)) ); test!( many1(module_item), r##"int idest[], isrc[3] = '{5, 6, 7}; initial begin idest = new [3] (isrc); // set size and array element data values (5, 6, 7) end"##, Ok((_, _)) ); test!( many1(module_item), r##"int src[3], dest1[], dest2[]; initial begin src = '{2, 3, 4}; dest1 = new[2] (src); // dest1's elements are {2, 3}. dest2 = new[4] (src); // dest2's elements are {2, 3, 4, 0}. end"##, Ok((_, _)) ); test!( many1(module_item), r##"integer addr[]; // Declare the dynamic array. initial begin addr = new[100]; // Create a 100-element array. // Double the array size, preserving previous values. // Preexisting references to elements of addr are outdated. addr = new[200](addr); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int j = addr.size; addr = new[ addr.size() * 4 ] (addr); // quadruple addr array end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int ab [] = new[ N ]; // create a temporary array of size N // use ab ab.delete; // delete the array contents $display( "%d", ab.size ); // prints 0 end"##, Ok((_, _)) ); test!( many1(module_item), r##"int A[10:1]; // fixed-size array of 10 elements int B[0:9]; // fixed-size array of 10 elements int C[24:1]; // fixed-size array of 24 elements A = B; // ok. Compatible type and same size A = C; // type check error: different sizes"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [7:0] V1[10:1]; logic [7:0] V2[10]; wire [7:0] W[9:0]; // data type is logic [7:0] W[9:0] assign W = V1; initial #10 V2 = W;"##, Ok((_, _)) ); test!( many1(module_item), r##"int A[2][100:1]; int B[] = new[100]; // dynamic array of 100 elements int C[] = new[8]; // dynamic array of 8 elements int D [3][][]; // multidimensional array with dynamic subarrays initial begin D[2] = new [2]; // initialize one of D's dynamic subarrays D[2][0] = new [100]; A[1] = B; // OK. Both are arrays of 100 ints A[1] = C; // type check error: different sizes (100 vs. 8 ints) A = D[2]; // A[0:1][100:1] and subarray D[2][0:1][0:99] both // comprise 2 subarrays of 100 ints end"##, Ok((_, _)) ); test!( many1(module_item), r##"int A[100:1]; // fixed-size array of 100 elements int B[]; // empty dynamic array int C[] = new[8]; // dynamic array of size 8 initial begin B = A; // ok. B has 100 elements B = C; // ok. B has 8 elements end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin B = new[ C.size ] (C); end"##, Ok((_, _)) ); test!( many1(module_item), r##"string d[1:5] = '{ "a", "b", "c", "d", "e" }; string p[]; p = { d[1:3], "hello", d[4:5] };"##, Ok((_, _)) ); test!( many1(module_item), r##"int b[3:1][3:1]; // OK: same type, dimension, and size int b[1:3][0:2]; // OK: same type, dimension, & size (different ranges) logic b[3:1][3:1]; // error: incompatible element type event b[3:1][3:1]; // error: incompatible type int b[3:1]; // error: incompatible number of dimensions int b[3:1][4:1]; // error: incompatible size (3 vs. 4)"##, Ok((_, _)) ); test!( many1(module_item), r##"string b[4:1]; // OK: same type and size string b[5:2]; // OK: same type and size (different range) string b[] = new[4]; // OK: same type, number of dimensions, and // dimension size; requires run-time check"##, Ok((_, _)) ); test!( many1(module_item), r##"integer i_array[*]; // associative array of integer (unspecified // index) bit [20:0] array_b[string]; // associative array of 21-bit vector, // indexed by string event ev_array[myClass]; // associative array of event indexed by class // myClass"##, Ok((_, _)) ); test!(many1(module_item), r##"int array_name [*];"##, Ok((_, _))); test!( many1(module_item), r##"int array_name [ string ];"##, Ok((_, _)) ); test!( many1(module_item), r##"int array_name [ some_Class ];"##, Ok((_, _)) ); test!( many1(module_item), r##"int array_name1 [ integer ]; typedef bit signed [4:1] SNibble; int array_name2 [ SNibble ]; typedef bit [4:1] UNibble; int array_name3 [ UNibble ];"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef struct {byte B; int I[*];} Unpkt; int array_name [ Unpkt ];"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int a[int] = '{default:1}; typedef struct { int x=1,y=2; } xy_t; xy_t b[int]; begin a[1]++; b[2].x = 5; end end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int imem[int]; imem[ 3 ] = 1; imem[ 16'hffff ] = 2; imem[ 4'b1000 ] = 3; $display( "%0d entries\n", imem.num ); // prints "3 entries" end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int map[ string ]; map[ "hello" ] = 1; map[ "sad" ] = 2; map[ "world" ] = 3; map.delete( "sad" ); // remove entry whose index is "sad" from "map" map.delete; // remove all entries from the associative array "map" end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin if ( map.exists( "hello" )) map[ "hello" ] += 1; else map[ "hello" ] = 0; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string s; if ( map.first( s ) ) $display( "First entry is : map[ %s ] = %0d\n", s, map[s] ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string s; if ( map.last( s ) ) $display( "Last entry is : map[ %s ] = %0d\n", s, map[s] ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string s; if ( map.first( s ) ) do $display( "%s : %d\n", s, map[ s ] ); while ( map.next( s ) ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string s; if ( map.last( s ) ) do $display( "%s : %d\n", s, map[ s ] ); while ( map.prev( s ) ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string aa[int]; byte ix; int status; aa[ 1000 ] = "a"; status = aa.first( ix ); // status is –1 // ix is 232 (least significant 8 bits of 1000) end"##, Ok((_, _)) ); test!( many1(module_item), r##"string words [int] = '{default: "hello"}; // an associative array of 4-state integers indexed by strings, default is –1 integer tab [string] = '{"Peter":20, "Paul":22, "Mary":23, default:-1 };"##, Ok((_, _)) ); test!( many1(module_item), r##"byte q1[$]; // A queue of bytes string names[$] = { "Bob" }; // A queue of strings with one element integer Q[$] = { 3, 2, 7 }; // An initialized queue of integers bit q2[$:255]; // A queue whose maximum size is 256 bits"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef mytype element_t; // mytype is any legal type for a queue typedef element_t queue_t[$]; element_t e; queue_t Q; int i;"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin for ( int j = 0; j < Q.size; j++ ) $display( Q[j] ); end"##, Ok((_, _)) ); // TODO // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), // r##"initial begin // int q[$] = { 2, 4, 8 }; // int e, pos; // // assignment // method call yielding the // // // same value in variable q // // ----------------------------- // ------------------------- // q = { q, 6 }; // q.push_back(6) // q = { e, q }; // q.push_front(e) // q = q[1:$]; // void'(q.pop_front()) or q.delete(0) // q = q[0:$-1]; // void'(q.pop_back()) or // // q.delete(q.size-1) // q = { q[0:pos-1], e, q[pos:$] }; // q.insert(pos, e) // q = { q[0:pos], e, q[pos+1:$] }; // q.insert(pos+1, e) // q = {}; // q.delete() // end"##, // Ok((_, _)) //); // TODO // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), // r##"initial begin // q = q[2:$]; // a new queue lacking the first two items // q = q[1:$-1]; // a new queue lacking the first and last items // end"##, // Ok((_, _)) //); test!( many1(module_item), r##"initial begin string SA[10], qs[$]; int IA[int], qi[$]; // Find all items greater than 5 qi = IA.find( x ) with ( x > 5 ); qi = IA.find( x ); // shall be an error // Find indices of all items equal to 3 qi = IA.find_index with ( item == 3 ); // Find first item equal to Bob qs = SA.find_first with ( item == "Bob" ); // Find last item equal to Henry qs = SA.find_last( y ) with ( y == "Henry" ); // Find index of last item greater than Z qi = SA.find_last_index( s ) with ( s > "Z" ); // Find smallest item qi = IA.min; // Find string with largest numerical value qs = SA.max with ( item.atoi ); // Find all unique string elements qs = SA.unique; // Find all unique strings in lowercase qs = SA.unique( s ) with ( s.tolower ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string s[] = { "hello", "sad", "world" }; s.reverse; // s becomes { "world", "sad", "hello" }; end initial begin int q[$] = { 4, 5, 3, 1 }; q.sort; // q becomes { 1, 3, 4, 5 } end initial begin struct { byte red, green, blue; } c [512]; c.sort with ( item.red ); // sort c using the red field only c.sort( x ) with ( {x.blue, x.green} ); // sort by blue then green end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin byte b[] = { 1, 2, 3, 4 }; int y; y = b.sum ; // y becomes 10 => 1 + 2 + 3 + 4 y = b.product ; // y becomes 24 => 1 * 2 * 3 * 4 y = b.xor with ( item + 4 ); // y becomes 12 => 5 ^ 6 ^ 7 ^ 8 end initial begin logic [7:0] m [2][2] = '{ '{5, 10}, '{15, 20} }; int y; y = m.sum with (item.sum with (item)); // y becomes 50 => 5+10+15+20 end initial begin logic bit_arr [1024]; int y; y = bit_arr.sum with ( int'(item) ); // forces result to be 32-bit end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int arr[]; int q[$]; // find all items equal to their position (index) q = arr.find with ( item == item.index ); end"##, Ok((_, _)) ); } #[test] fn clause8() { test!( many1(module_item), r##"class Packet ; //data or class properties bit [3:0] command; bit [40:0] address; bit [4:0] master_id; integer time_requested; integer time_issued; integer status; typedef enum { ERR_OVERFLOW = 10, ERR_UNDERFLOW = 1123} PCKT_TYPE; const integer buffer_size = 100; const integer header_size; // initialization function new(); command = 4'd0; address = 41'b0; master_id = 5'bx; header_size = 10; endfunction // methods // public access entry points task clean(); command = 0; address = 0; master_id = 5'bx; endtask task issue_request( int delay ); // send request to bus endtask function integer current_status(); current_status = status; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"Packet p; // declare a variable of class Packet p = new; // initialize variable to a new allocated object // of the class Packet"##, Ok((_, _)) ); test!( many1(module_item), r##"class obj_example; endclass task task1(integer a, obj_example myexample); if (myexample == null) myexample = new; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin Packet p = new; int var1; p.command = INIT; p.address = $random; packet_time = p.time_requested; var1 = p.buffer_size; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial $display (p.ERR_OVERFLOW);"##, Ok((_, _)) ); test!( many1(module_item), r##"class vector #(parameter width = 7, type T = int); endclass vector #(3) v = new; initial $display (vector #(3)::T'(3.45)); // Typecasting initial $display ((v.T)'(3.45)); //ILLEGAL initial $display (v.width);"##, Ok((_, _)) ); test!( many1(module_item), r##"Packet p = new; status = p.current_status();"##, Ok((_, _)) ); test!( many1(module_item), r##"status = current_status(p);"##, Ok((_, _)) ); test!(many1(module_item), r##"Packet p = new;"##, Ok((_, _))); test!( many1(module_item), r##"class Packet; integer command; function new(); command = IDLE; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class C; int c1 = 1; int c2 = 1; int c3 = 1; function new(int a); c2 = 2; c3 = a; endfunction endclass class D extends C; int d1 = 4; int d2 = c2; int d3 = 6; function new; super.new(d3); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"Packet p = new(STARTUP, $random, $time);"##, Ok((_, _)) ); test!( many1(module_item), r##"class c; function new(int cmd = IDLE, bit[12:0] adrs = 0, int cmd_time ); command = cmd; address = adrs; time_requested = cmd_time; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class C; endclass class D extends C; endclass C c = D::new; // variable c of superclass type C now references // a newly constructed object of type D"##, Ok((_, _)) ); test!( many1(module_item), r##"D d = new; C c = d;"##, Ok((_, _)) ); test!( many1(module_item), r##"class E #(type T = int) extends C; T x; function new(T x_init); super.new(); x = x_init; endfunction endclass initial begin c = E #(.T(byte))::new(.x_init(5)); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet ; static integer fileID = $fopen( "data", "r" ); endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"Packet p; c = $fgetc( p.fileID );"##, Ok((_, _)) ); test!( many1(module_item), r##"class id; static int current = 0; static function int next_id(); next_id = ++current; // OK to access static class property endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class TwoTasks; static task t1(); endtask // static class method with // automatic variable lifetime task static t2(); endtask // ILLEGAL: non-static class method with // static variable lifetime endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Demo ; integer x; function new (integer x); this.x = x; endfunction endclass"##, Ok((_, _)) ); test!(many1(module_item), r##"Packet p1;"##, Ok((_, _))); test!(many1(module_item), r##"p1 = new;"##, Ok((_, _))); test!( many1(module_item), r##"Packet p2; p2 = p1;"##, Ok((_, _)) ); test!( many1(module_item), r##"Packet p1; Packet p2; p1 = new; p2 = new p1;"##, Ok((_, _)) ); test!( many1(module_item), r##"class baseA ; integer j = 5; endclass class B ; integer i = 1; baseA a = new; endclass class xtndA extends baseA; rand int x; constraint cst1 { x < 10; } endclass function integer test; xtndA xtnd1; baseA base2, base3; B b1 = new; // Create an object of class B B b2 = new b1; // Create an object that is a copy of b1 b2.i = 10; // i is changed in b2, but not in b1 b2.a.j = 50; // change a.j, shared by both b1 and b2 test = b1.i; // test is set to 1 (b1.i has not changed) test = b1.a.j; // test is set to 50 (a.j has changed) xtnd1 = new; // create a new instance of class xtndA xtnd1.x = 3; base2 = xtnd1; // base2 refers to the same object as xtnd1 base3 = new base2; // Creates a shallow copy of xtnd1 endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin Packet p1 = new; Packet p2 = new; p2.copy(p1); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class LinkedPacket; Packet packet_c; LinkedPacket next; function LinkedPacket get_next(); get_next = next; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class LinkedPacket extends Packet; LinkedPacket next; function LinkedPacket get_next(); get_next = next; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"LinkedPacket lp = new; Packet p = lp;"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet; integer i = 1; function integer get(); get = i; endfunction endclass class LinkedPacket extends Packet; integer i = 2; function integer get(); get = -i; endfunction endclass initial begin LinkedPacket lp = new; Packet p = lp; j = p.i; // j = 1, not 2 j = p.get(); // j = 1, not -1 or –2 end"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet; // base class integer value; function integer delay(); delay = value * value; endfunction endclass class LinkedPacket extends Packet; // derived class integer value; function integer delay(); delay = super.delay()+ value * super.value; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class c; function new(); super.new(5); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet; local integer i; function integer compare (Packet other); compare = (this.i == other.i); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Jumbo_Packet; const int max_size = 9 * 1024; // global constant byte payload []; function new( int size ); payload = new[ size > max_size ? max_size : size ]; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Big_Packet; const int size; // instance constant byte payload []; function new(); size = $urandom % 4096; //one assignment in new -> ok payload = new[ size ]; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class BasePacket; int A = 1; int B = 2; function void printA; $display("BasePacket::A is %d", A); endfunction : printA virtual function void printB; $display("BasePacket::B is %d", B); endfunction : printB endclass : BasePacket class My_Packet extends BasePacket; int A = 3; int B = 4; function void printA; $display("My_Packet::A is %d", A); endfunction: printA virtual function void printB; $display("My_Packet::B is %d", B); endfunction : printB endclass : My_Packet BasePacket P1 = new; My_Packet P2 = new; initial begin P1.printA; // displays 'BasePacket::A is 1' P1.printB; // displays 'BasePacket::B is 2' P1 = P2; // P1 has a handle to a My_packet object P1.printA; // displays 'BasePacket::A is 1' P1.printB; // displays 'My_Packet::B is 4' – latest derived method P2.printA; // displays 'My_Packet::A is 3' P2.printB; // displays 'My_Packet::B is 4' end"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef int T; // T and int are matching data types. class C; virtual function C some_method(int a); endfunction endclass class D extends C; virtual function D some_method(T a); endfunction endclass class E #(type Y = logic) extends C; virtual function D some_method(Y a); endfunction endclass E #() v1; // Illegal: type parameter Y resolves to logic, which is not // a matching type for argument a E #(int) v2; // Legal: type parameter Y resolves to int"##, Ok((_, _)) ); test!( many1(module_item), r##"virtual class BasePacket; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"virtual class BasePacket; pure virtual function integer send(bit[31:0] data); // No implementation endclass class EtherPacket extends BasePacket; virtual function integer send(bit[31:0] data); // body of the function endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class c; virtual function integer send(bit[31:0] data); // Will return 'x endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"BasePacket packets[100];"##, Ok((_, _)) ); test!( many1(module_item), r##"EtherPacket ep = new; // extends BasePacket TokenPacket tp = new; // extends BasePacket GPSPacket gp = new; // extends EtherPacket packets[0] = ep; packets[1] = tp; packets[2] = gp;"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin packets[1].send(); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class Base; typedef enum {bin,oct,dec,hex} radix; static task print( radix r, integer n ); endtask endclass initial begin Base b = new; int bin = 123; b.print( Base::bin, bin ); // Base::bin and bin are different Base::print( Base::hex, 66 ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class StringList; class Node; // Nested class for a node in a linked list. string name; Node link; endclass endclass class StringTree; class Node; // Nested class for a node in a binary tree. string name; Node left, right; endclass endclass // StringList::Node is different from StringTree::Node"##, Ok((_, _)) ); test!( many1(module_item), r##"class Outer; int outerProp; local int outerLocalProp; static int outerStaticProp; static local int outerLocalStaticProp; class Inner; function void innerMethod(Outer h); outerStaticProp = 0; // Legal, same as Outer::outerStaticProp outerLocalStaticProp = 0; // Legal, nested classes may access local's in outer class outerProp = 0; // Illegal, unqualified access to non-static outer h.outerProp = 0; // Legal, qualified access. h.outerLocalProp = 0; // Legal, qualified access and locals to outer class allowed. endfunction endclass endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet; Packet next; function Packet get_next();// single line get_next = next; endfunction // out-of-body (extern) declaration extern protected virtual function int send(int value); endclass function int Packet::send(int value); // dropped protected virtual, added Packet:: // body of method endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef real T; class C; typedef int T; extern function T f(); extern function real f2(); endclass function C::T C::f(); // the return must use the class scope resolution // operator, since the type is defined within the // class return 1; endfunction function real C::f2(); return 1.0; endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef int T; class C; extern function void f(T x); typedef real T; endclass function void C::f(T x); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"class vector #(int size = 1); bit [size-1:0] a; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"vector #(10) vten; // object with vector of size 10 vector #(.size(2)) vtwo; // object with vector of size 2 typedef vector#(4) Vfour; // Class with vector of size 4"##, Ok((_, _)) ); test!( many1(module_item), r##"class stack #(type T = int); local T items[]; task push( T a ); endtask task pop( ref T a ); endtask endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"stack is; // default: a stack of ints stack#(bit[1:10]) bs; // a stack of 10-bit vectors stack#(real) rs; // a stack of real numbers"##, Ok((_, _)) ); test!( many1(module_item), r##"class vector #(int size = 1); bit [size-1:0] a; static int count = 0; function void disp_count(); $display( "count: %d of size %d", count, size ); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef vector my_vector; // use default size of 1 vector#(6) vx; // use size 6"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef vector#(4) Vfour; typedef stack#(Vfour) Stack4; Stack4 s1, s2; // declare objects of type Stack4"##, Ok((_, _)) ); test!( many1(module_item), r##"class C #(type T = bit); endclass // base class class D1 #(type P = real) extends C; endclass // T is bit (the default) class D2 #(type P = real) extends C #(integer); endclass // T is integer class D3 #(type P = real) extends C #(P); endclass // T is P class D4 #(type P = C#(real)) extends P; endclass // for default, T is real"##, Ok((_, _)) ); test!( many1(module_item), r##"class C #(int p = 1); endclass class D #(int p); endclass C obj; // legal; equivalent to "C#() obj"; D obj; // illegal; D has no default specialization"##, Ok((_, _)) ); test!( many1(module_item), r##"class C #(int p = 1); parameter int q = 5; // local parameter static task t; int p; int x = C::p; // C::p disambiguates p // C::p is not p in the default specialization endtask endclass int x = C::p; // illegal; C:: is not permitted in this context int y = C#()::p; // legal; refers to parameter p in the default // specialization of C typedef C T; // T is a default specialization, not an alias to // the name "C" int z = T::p; // legal; T::p refers to p in the default specialization int v = C#(3)::p; // legal; parameter p in the specialization of C#(3) int w = C#()::q; // legal; refers to the local parameter T obj = new(); int u = obj.q; // legal; refers to the local parameter bit arr[obj.q]; // illegal: local parameter is not a constant expression"##, Ok((_, _)) ); // TODO // class static method is denied because ps_or_hierarchical_tf_identifier doesn't have class_scope. //test!( // many1(module_item), // r##"class C #(int p = 1, type T = int); // extern static function T f(); // endclass // function C::T C::f(); // return p + C::p; // endfunction // initial $display("%0d %0d", C#()::f(),C#(5)::f()); // output is "2 10""##, // Ok((_, _)) //); test!( many1(module_item), r##"interface class A; endclass class B implements A; endclass class C extends B; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class PutImp#(type PUT_T = logic); pure virtual function void put(PUT_T a); endclass interface class GetImp#(type GET_T = logic); pure virtual function GET_T get(); endclass class Fifo#(type T = logic, int DEPTH=1) implements PutImp#(T), GetImp#(T); T myFifo [$:DEPTH-1]; virtual function void put(T a); myFifo.push_back(a); endfunction virtual function T get(); get = myFifo.pop_front(); endfunction endclass class Stack#(type T = logic, int DEPTH=1) implements PutImp#(T), GetImp#(T); T myFifo [$:DEPTH-1]; virtual function void put(T a); myFifo.push_front(a); endfunction virtual function T get(); get = myFifo.pop_front(); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class PutImp#(type PUT_T = logic); pure virtual function void put(PUT_T a); endclass interface class GetImp#(type GET_T = logic); pure virtual function GET_T get(); endclass class MyQueue #(type T = logic, int DEPTH = 1); T PipeQueue[$:DEPTH-1]; virtual function void deleteQ(); PipeQueue.delete(); endfunction endclass class Fifo #(type T = logic, int DEPTH = 1) extends MyQueue#(T, DEPTH) implements PutImp#(T), GetImp#(T); virtual function void put(T a); PipeQueue.push_back(a); endfunction virtual function T get(); get = PipeQueue.pop_front(); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"virtual class XFifo#(type T_in = logic, type T_out = logic, int DEPTH = 1) extends MyQueue#(T_out) implements PutImp#(T_in), GetImp#(T_out); pure virtual function T_out translate(T_in a); virtual function void put(T_in a); PipeQueue.push_back(translate(a)); endfunction virtual function T_out get(); get = PipeQueue.pop_front(); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfClass; pure virtual function bit funcBase(); pure virtual function bit funcExt(); endclass class BaseClass; virtual function bit funcBase(); return (1); endfunction endclass class ExtClass extends BaseClass implements IntfClass; virtual function bit funcExt(); return (0); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfClass; pure virtual function void f(); endclass class BaseClass; function void f(); $display("Called BaseClass::f()"); endfunction endclass class ExtClass extends BaseClass implements IntfClass; virtual function void f(); $display("Called ExtClass::f()"); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfA #(type T1 = logic); typedef T1[1:0] T2; pure virtual function T2 funcA(); endclass : IntfA interface class IntfB #(type T = bit) extends IntfA #(T); pure virtual function T2 funcB(); // legal, type T2 is inherited endclass : IntfB"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfC; typedef enum {ONE, TWO, THREE} t1_t; pure virtual function t1_t funcC(); endclass : IntfC class ClassA implements IntfC; t1_t t1_i; // error, t1_t is not inherited from IntfC virtual function IntfC::t1_t funcC(); // correct return (IntfC::ONE); // correct endfunction : funcC endclass : ClassA"##, Ok((_, _)) ); test!( many1(module_item), r##"class Fifo #(type T = PutImp) implements T; endclass virtual class Fifo #(type T = PutImp) implements T; endclass interface class Fifo #(type T = PutImp) extends T; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef interface class IntfD; class ClassB implements IntfD #(bit); // illegal virtual function bit[1:0] funcD(); endfunction endclass : ClassB // This interface class declaration must be declared before ClassB interface class IntfD #(type T1 = logic); typedef T1[1:0] T2; pure virtual function T2 funcD(); endclass : IntfD"##, Ok((_, _)) ); test!( many1(module_item), r##"class Fifo #(type T = int) implements PutImp#(T), GetImp#(T); endclass Fifo#(int) fifo_obj = new; PutImp#(int) put_ref = fifo_obj;"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin GetImp#(int) get_ref; Fifo#(int) fifo_obj = new; PutImp#(int) put_ref = fifo_obj; $cast(get_ref, put_ref); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin $cast(fifo_obj, put_ref); // legal $cast(put_ref, fifo_obj); // legal, but casting is not required end"##, Ok((_, _)) ); test!( many1(module_item), r##"put_ref = new(); // illegal"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfBase1; pure virtual function bit funcBase(); endclass interface class IntfBase2; pure virtual function bit funcBase(); endclass virtual class ClassBase; pure virtual function bit funcBase(); endclass class ClassExt extends ClassBase implements IntfBase1, IntfBase2; virtual function bit funcBase(); return (0); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfBaseA; pure virtual function bit funcBase(); endclass interface class IntfBaseB; pure virtual function string funcBase(); endclass class ClassA implements IntfBaseA, IntfBaseB; virtual function bit funcBase(); return (0); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class PutImp#(type T = logic); pure virtual function void put(T a); endclass interface class GetImp#(type T = logic); pure virtual function T get(); endclass interface class PutGetIntf#(type TYPE = logic) extends PutImp#(TYPE), GetImp#(TYPE); typedef TYPE T; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfBase; parameter SIZE = 64; endclass interface class IntfExt1 extends IntfBase; pure virtual function bit funcExt1(); endclass interface class IntfExt2 extends IntfBase; pure virtual function bit funcExt2(); endclass interface class IntfExt3 extends IntfExt1, IntfExt2; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfBase #(type T = int); pure virtual function bit funcBase(); endclass interface class IntfExt1 extends IntfBase#(bit); pure virtual function bit funcExt1(); endclass interface class IntfExt2 extends IntfBase#(logic); pure virtual function bit funcExt2(); endclass interface class IntfFinal extends IntfExt1, IntfExt2; typedef bit T; // Override the conflicting identifier name pure virtual function bit funcBase(); endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"interface class IntfClass; pure virtual function bit funcA(); pure virtual function bit funcB(); endclass // Partial implementation of IntfClass virtual class ClassA implements IntfClass; virtual function bit funcA(); return (1); endfunction pure virtual function bit funcB(); endclass // Complete implementation of IntfClass class ClassB extends ClassA; virtual function bit funcB(); return (1); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef class C2; // C2 is declared to be of type class class C1; C2 c; endclass class C2; C1 c; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef class C ; module top ; C#(1, real) v2 ; // positional parameter override C#(.p(2), .T(real)) v3 ; // named parameter override endmodule class C #(parameter p = 2, type T = int); endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin myClass obj = new; fork task1( obj ); task2( obj ); join_none end"##, Ok((_, _)) ); } #[test] fn clause9() { test!( many1(module_item), r##"initial begin a = 0; // initialize a for (int index = 0; index < size; index++) memory[index] = 0; // initialize memory word end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin inputs = 'b000000; // initialize at time zero #10 inputs = 'b011001; // first pattern #10 inputs = 'b011011; // second pattern #10 inputs = 'b011000; // third pattern #10 inputs = 'b001000; // last pattern end"##, Ok((_, _)) ); test!(many1(module_item), r##"always areg = ~areg;"##, Ok((_, _))); test!( many1(module_item), r##"always #half_period areg = ~areg;"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb a = b & c; always_comb d <= #1ns b & c;"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb begin a = b & c; A1:assert (a != e) else if (!disable_error) $error("failed"); end"##, Ok((_, _)) ); test!( many1(module_item), r##"always_latch if(ck) q <= d;"##, Ok((_, _)) ); test!( many1(module_item), r##"always_ff @(posedge clock iff reset == 0 or posedge reset) begin r1 <= reset ? 0 : r2 + 1; end"##, Ok((_, _)) ); test!( many1(module_item), r##"final begin $display("Number of cycles executed %d",$time/period); $display("Final PC = %h",PC); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin areg = breg; creg = areg; // creg stores the value of breg end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin areg = breg; @(posedge clock) creg = areg; // assignment delayed until end // posedge on clock"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter d = 50; // d declared as a parameter and logic [7:0] r; // r declared as an 8-bit variable initial begin // a waveform controlled by sequential delays #d r = 'h35; #d r = 'hE2; #d r = 'h00; #d r = 'hF7; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork #50 r = 'h35; #100 r = 'hE2; #150 r = 'h00; #200 r = 'hF7; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork begin statement1; // one process with 2 statements statement2; end join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork begin $display( "First Block\n" ); # 20ns; end begin $display( "Second Block\n" ); @eventA; end join end"##, Ok((_, _)) ); test!( many1(module_item), r##"task wait_20; fork # 20; return ; // Illegal: cannot return; task lives in another process join_none endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"initial for( int j = 1; j <= 3; ++j ) fork automatic int k = j; // local copy, k, for each value of j #k $write( "%0d", k ); begin automatic int m = j; // the value of m is undetermined end join_none"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork #200 r = 'hF7; #150 r = 'h00; #100 r = 'hE2; #50 r = 'h35; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork @Aevent; @Bevent; join areg = breg; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork @enable_a begin #ta wa = 0; #ta wa = 1; #ta wa = 0; end @enable_b begin #tb wb = 1; #tb wb = 0; #tb wb = 1; end join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin: blockB // block name after the begin or fork end: blockB"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin labelB: fork // label before the begin or fork join_none : labelB end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin #10 rega = regb; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin #d rega = regb; // d is defined as a parameter #((d+e)/2) rega = regb; // delay is average of d and e #regr regr = regr + 1; // delay is the value in regr end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @r rega = regb; // controlled by any value change in the reg r @(posedge clock) rega = regb; // controlled by posedge on clock forever @(negedge clock) rega = regb; // controlled by negedge on clock forever @(edge clock) rega = regb; // controlled by edge on clock end"##, Ok((_, _)) ); test!( many1(module_item), r##"real AOR[]; // dynamic array of reals byte stream[$]; // queue of bytes initial wait(AOR.size() > 0); // waits for array to be allocated initial wait($bits(stream) > 60); // waits for total number of bits // in stream greater than 60 Packet p = new; // Packet 1 -- Packet is defined in 8.2 Packet q = new; // Packet 2 initial fork @(p.status); // Wait for status in Packet 1 to change @p; // Wait for a change to handle p # 10 p = q; // triggers @p. // @(p.status) now waits for status in Packet 2 to change, // if not already different from Packet 1 join"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(trig or enable) rega = regb; // controlled by trig or enable @(posedge clk_a or posedge clk_b or trig) rega = regb; end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(a, b, c, d, e); always @(posedge clk, negedge rstn); always @(a or b, c, d or e);"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(*) // equivalent to @(a or b or c or d or f) y = (a & b) | (c & d) | myfunction(f);"##, Ok((_, _)) ); test!( many1(module_item), r##"always @* begin // equivalent to @(a or b or c or d or tmp1 or tmp2) tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @* begin // equivalent to @(b) @(i) kid = b; // i is not added to @* end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @* begin // equivalent to @(a or b or c or d) x = a ^ b; @* // equivalent to @(c or d) x = c ^ d; end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @* begin // same as @(a or en) y = 8'hff; y[a] = !en; end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @* begin // same as @(state or go or ws) next = 4'b0; case (1'b1) state[IDLE]: if (go) next[READ] = 1'b1; else next[IDLE] = 1'b1; state[READ]: next[DLY ] = 1'b1; state[DLY ]: if (!ws) next[DONE] = 1'b1; else next[READ] = 1'b1; state[DONE]: next[IDLE] = 1'b1; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"module latch (output logic [31:0] y, input [31:0] a, input enable); always @(a iff enable == 1) y <= a; //latch is in transparent mode endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence abc; @(posedge clk) a ##1 b ##1 c; endsequence program test; initial begin @ abc $display( "Saw a-b-c" ); end endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin wait (!enable) #10 a = b; #10 c = d; end"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence abc; @(posedge clk) a ##1 b ##1 c; endsequence sequence de; @(negedge clk) d ##[2:5] e; endsequence program check; initial begin wait( abc.triggered || de.triggered ); if( abc.triggered ) $display( "abc succeeded" ); if( de.triggered ) $display( "de succeeded" ); end endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin repeat (3) @ (event_expression); // will execute event_expression three times repeat (-3) @ (event_expression); // will not execute event_expression. repeat (a) @ (event_expression); // if a is assigned -3, it will execute the event_expression if a is // declared as an unsigned variable, but not if a is signed end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork #5 a = b; #5 b = a; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork // data swap a = #5 b; b = #5 a; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork // data shift a = @(posedge clk) b; b = @(posedge clk) c; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a <= repeat(5) @(posedge clk) data; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a = repeat(num) @(clk) data; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a <= repeat(a+b) @(posedge phi1 or negedge phi2) data; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a <= repeat(a+b) @(edge phi1) data; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin : test fork child1(); child2(); join_none do_test(); end : test task do_test(); fork child3(); child4(); fork : child5 // nested fork-join_none is a child process descendant1(); descendant2(); join_none join_none do_sequence(); wait fork; // block until child1 ... child7 complete endtask function void do_sequence(); fork child6(); child7(); join_none endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin : block_name rega = regb; disable block_name; regc = rega; // this assignment will never execute end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin : block_name if (a == 0) disable block_name; end // end of named block // continue with code following named block"##, Ok((_, _)) ); test!( many1(module_item), r##"module m (); always begin : always1 t1: task1( ); // task call end always begin disable m.always1; // exit always1, which will exit task1, // if it was currently executing end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"task proc_a; begin if (a == 0) disable proc_a; // return if true end endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin : outer_block for (i = 0; i < n; i = i+1) begin : inner_block @clk if (a == 0) // "continue" loop disable inner_block ; @clk if (a == b) // "break" from loop disable outer_block; end end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork begin : event_expr @ev1; repeat (3) @trig; #d action (areg, breg); end @reset disable event_expr; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"always begin : monostable #250 q = 0; end always @retrig begin disable monostable; q = 1; end"##, Ok((_, _)) ); test!( many1(module_item), r##"task get_first( output int adr ); fork wait_device( 1, adr ); wait_device( 7, adr ); wait_device( 13, adr ); join_any disable fork; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"task automatic do_n_way( int N ); process job[] = new [N]; foreach (job[j]) fork automatic int k = j; begin job[k] = process::self(); end join_none foreach (job[j]) // wait for all processes to start wait( job[j] != null ); job[1].await(); // wait for first process to finish foreach (job[j]) begin if ( job[j].status != process::FINISHED ) job[j].kill(); end endtask"##, Ok((_, _)) ); } #[test] fn clause10() { test!( many1(module_item), r##"initial begin #1ns r = a; r = #1ns a; r <= #1ns a; end assign #2.5ns sum = a + b;"##, Ok((_, _)) ); test!( many1(module_item), r##"wire (strong1, pull0) mynet = enable;"##, Ok((_, _)) ); test!( many1(module_item), r##"wire mynet ; assign (strong1, pull0) mynet = enable;"##, Ok((_, _)) ); test!( many1(module_item), r##"module adder (sum_out, carry_out, carry_in, ina, inb); output [3:0] sum_out; output carry_out; input [3:0] ina, inb; input carry_in; wire carry_out, carry_in; wire [3:0] sum_out, ina, inb; assign {carry_out, sum_out} = ina + inb + carry_in; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module select_bus(busout, bus0, bus1, bus2, bus3, enable, s); parameter n = 16; parameter Zee = 16'bz; output [1:n] busout; input [1:n] bus0, bus1, bus2, bus3; input enable; input [1:2] s; tri [1:n] data; // net declaration // net declaration with continuous assignment tri [1:n] busout = enable ? data : Zee; // assignment statement with four continuous assignments assign data = (s == 0) ? bus0 : Zee, data = (s == 1) ? bus1 : Zee, data = (s == 2) ? bus2 : Zee, data = (s == 3) ? bus3 : Zee; endmodule"##, Ok((_, _)) ); test!(many1(module_item), r##"wire #10 wireA;"##, Ok((_, _))); test!( many1(module_item), r##"initial begin rega = 0; rega[3] = 1; // a bit-select rega[3:5] = 7; // a part-select mema[address] = 8'hff; // assignment to a mem element {carry, acc} = rega + regb; // a concatenation end"##, Ok((_, _)) ); test!( many1(module_item), r##"module evaluates (out); output out; logic a, b, c; initial begin a = 0; b = 1; c = 0; end always c = #5 ~c; always @(posedge c) begin a <= b; // evaluates, schedules, b <= a; // and executes in two steps end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module nonblock1; logic a, b, c, d, e, f; // blocking assignments initial begin a = #10 1; // a will be assigned 1 at time 10 b = #2 0; // b will be assigned 0 at time 12 c = #4 1; // c will be assigned 1 at time 16 end // nonblocking assignments initial begin d <= #10 1; // d will be assigned 1 at time 10 e <= #2 0; // e will be assigned 0 at time 2 f <= #4 1; // f will be assigned 1 at time 4 end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module nonblock2; logic a, b; initial begin a = 0; b = 1; a <= b; // evaluates, schedules, b <= a; // and executes in two steps end initial begin $monitor ($time, ,"a = %b b = %b", a, b); #100 $finish; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module multiple; logic a; initial a = 1; // The assigned value of the variable is determinate initial begin a <= #4 0; // schedules a = 0 at time 4 a <= #4 1; // schedules a = 1 at time 4 end // At time 4, a = 1 endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module multiple2; logic a; initial a = 1; initial a <= #4 0; // schedules 0 at time 4 initial a <= #4 1; // schedules 1 at time 4 // At time 4, a = ?? // The assigned value of the variable is indeterminate endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module multiple3; logic a; initial #8 a <= #8 1; // executed at time 8; // schedules an update of 1 at time 16 initial #12 a <= #4 0; // executed at time 12; // schedules an update of 0 at time 16 // Because it is determinate that the update of a to the value 1 // is scheduled before the update of a to the value 0, // then it is determinate that a will have the value 0 // at the end of time slot 16. endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module multiple4; logic r1; logic [2:0] i; initial begin // makes assignments to r1 without cancelling previous assignments for (i = 0; i <= 5; i++) r1 <= # (i*10) i[0]; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"wire w = vara & varb; // net with a continuous assignment logic v = consta & constb; // variable with initialization"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin force a = b + f(c) ; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module dff (q, d, clear, preset, clock); output q; input d, clear, preset, clock; logic q; always @(clear or preset) if (!clear) assign q = 0; else if (!preset) assign q = 1; else deassign q; always @(posedge clock) q = d; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module test; logic a, b, c, d; wire e; and and1 (e, a, b, c); initial begin $monitor("%d d=%b,e=%b", $stime, d, e); assign d = a & b & c; a = 1; b = 0; c = 1; #10; force d = (a | b | c); force e = (a | b | c); #10; release d; release e; #10 $finish; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [5:0] a; logic signed [4:0] b; initial begin a = 8'hff; // After the assignment, a = 6'h3f b = 8'hff; // After the assignment, b = 5'h1f end"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [0:5] a; logic signed [0:4] b, c; initial begin a = 8'sh8f; // After the assignment, a = 6'h0f b = 8'sh8f; // After the assignment, b = 5'h0f c = -113; // After the assignment, c = 15 // 1000_1111 = (-'h71 = -113) truncates to ('h0F = 15) end"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [7:0] a; logic signed [7:0] b; logic signed [5:0] c, d; initial begin a = 8'hff; c = a; // After the assignment, c = 6'h3f b = -113; d = b; // After the assignment, d = 6'h0f end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin var int A[N] = '{default:1}; var integer i = '{31:1, 23:1, 15:1, 8:1, default:0}; typedef struct {real r, th;} C; var C x = '{th:PI/2.0, r:1.0}; var real y [0:1] = '{0.0, 1.1}, z [0:9] = '{default: 3.1416}; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin var int B[4] = '{a, b, c, d}; var C y = '{1.0, PI/2.0}; '{a, b, c, d} = B; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef logic [1:0] [3:0] T; a = shortint'({T'{1,2}, T'{3,4}}); // yields 16'sh1234 end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef byte U[3]; var U A = '{1, 2, 3}; var byte a, b, c; U'{a, b, c} = A; U'{c, a, b} = '{a+1, b+1, c+1}; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin bit unpackedbits [1:0] = '{1,1}; // no size warning required as // bit can be set to 1 int unpackedints [1:0] = '{1'b1, 1'b1}; // no size warning required as // int can be set to 1'b1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin unpackedbits = '{2 {y}} ; // same as '{y, y} int n[1:2][1:3] = '{2{'{3{y}}}}; // same as '{'{y,y,y},'{y,y,y}} end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial unpackedints = '{default:2}; // sets elements to 2"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin struct {int a; time b;} abkey[1:0]; abkey = '{'{a:1, b:2ns}, '{int:5, time:$time}}; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module mod1; typedef struct { int x; int y; } st; st s1; int k = 1; initial begin #1 s1 = '{1, 2+k}; // by position #1 $display( s1.x, s1.y); #1 s1 = '{x:2, y:3+k}; // by name #1 $display( s1.x, s1.y); #1 $finish; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"initial s1 = '{default:2}; // sets x and y to 2"##, Ok((_, _)) ); test!( many1(module_item), r##"ab abkey[1:0] = '{'{a:1, b:1.0}, '{int:2, shortreal:2.0}};"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin struct { int A; struct { int B, C; } BC1, BC2; } ABC, DEF; ABC = '{A:1, BC1:'{B:2, C:3}, BC2:'{B:4,C:5}}; DEF = '{default:10}; end"##, Ok((_, _)) ); // TODO // string is not included in assignment_pattern_key //test!( // many1(module_item), // r##"typedef struct { // logic [7:0] a; // bit b; // bit signed [31:0] c; // string s; // } sa; // sa s2; // initial s2 = '{int:1, default:0, string:""}; // set all to 0 except the // // array of bits to 1 and // // string to """##, // Ok((_, _)) //); test!( many1(module_item), r##"initial #10 s2 = '{default:'1, s : ""}; // set all to 1 except s to """##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int A3[1:3]; A3 = {1, 2, 3}; // unpacked array concatenation: A3[1]=1, A3[2]=2, A3[3]=3 A3 = '{1, 2, 3}; // array assignment pattern: A3[1]=1, A3[2]=2, A3[3]=3 end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef int AI3[1:3]; AI3 A3; int A9[1:9]; A3 = '{1, 2, 3}; A9 = '{3{A3}}; // illegal, A3 is wrong element type A9 = '{A3, 4, 5, 6, 7, 8, 9}; // illegal, A3 is wrong element type A9 = {A3, 4, 5, A3, 6}; // legal, gives A9='{1,2,3,4,5,1,2,3,6} A9 = '{9{1}}; // legal, gives A9='{1,1,1,1,1,1,1,1,1} A9 = {9{1}}; // illegal, no replication in unpacked // array concatenation A9 = {A3, {4,5,6,7,8,9} }; // illegal, {...} is not self-determined here A9 = {A3, '{4,5,6,7,8,9} }; // illegal, '{...} is not self-determined A9 = {A3, 4, AI3'{5, 6, 7}, 8, 9}; // legal, A9='{1,2,3,4,5,6,7,8,9} end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string S, hello; string SA[2]; byte B; byte BA[2]; hello = "hello"; S = {hello, " world"}; // string concatenation: "hello world" SA = {hello, " world"}; // array concatenation: // SA[0]="hello", SA[1]=" world" B = {4'h6, 4'hf}; // vector concatenation: B=8'h6f BA = {4'h6, 4'hf}; // array concatenation: BA[0]=8'h06, BA[1]=8'h0f end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string S1, S2; typedef string T_SQ[$]; T_SQ SQ; S1 = "S1"; S2 = "S2"; SQ = '{"element 0", "element 1"}; // assignment pattern, two strings SQ = {S1, SQ, {"element 3 is ", S2} }; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin SQ = {S1, SQ, T_SQ'{"element 3 is ", S2} }; // result: '{"S1", "element 0", "element 1", "element 3 is ", "S2"} end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef int T_QI[$]; T_QI jagged_array[$] = '{ {1}, T_QI'{2,3,4}, {5,6} }; // jagged_array[0][0] = 1 -- jagged_array[0] is a queue of 1 int // jagged_array[1][0] = 2 -- jagged_array[1] is a queue of 3 ints // jagged_array[1][1] = 3 // jagged_array[1][2] = 4 // jagged_array[2][0] = 5 -- jagged_array[2] is a queue of 2 ints // jagged_array[2][1] = 6 end"##, Ok((_, _)) ); test!( many1(module_item), r##"module byte_swap (inout wire [31:0] A, inout wire [31:0] B); alias {A[7:0],A[15:8],A[23:16],A[31:24]} = B; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module byte_rip (inout wire [31:0] W, inout wire [7:0] LSB, MSB); alias W[7:0] = LSB; alias W[31:24] = MSB; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12); alias bus16[11:0] = low12; alias bus16[15:4] = high12; endmodule module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12); alias bus16 = {high12, low12[3:0]}; alias high12[7:0] = low12[11:4]; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"alias bus16 = {high12[11:8], low12}; alias bus16 = {high12, low12[3:0]};"##, Ok((_, _)) ); test!( many1(module_item), r##"alias bus16 = {high12, bus16[3:0]} = {bus16[15:12], low12};"##, Ok((_, _)) ); test!( many1(module_item), r##"module lib1_dff(Reset, Clk, Data, Q, Q_Bar); endmodule module lib2_dff(reset, clock, data, q, qbar); endmodule module lib3_dff(RST, CLK, D, Q, Q_); endmodule module my_dff(rst, clk, d, q, q_bar); // wrapper cell input rst, clk, d; output q, q_bar; alias rst = Reset = reset = RST; alias clk = Clk = clock = CLK; alias d = Data = data = D; alias q = Q; alias Q_ = q_bar = Q_Bar = qbar; LIB_DFF my_dff (.*); // LIB_DFF is any of lib1_dff, lib2_dff or lib3_dff endmodule"##, Ok((_, _)) ); } #[test] fn clause11() { test!( many1(module_item), r##"initial begin int IntA; IntA = -12 / 3; // The result is -4 IntA = -'d 12 / 3; // The result is 1431655761 IntA = -'sd 12 / 3; // The result is -4 IntA = -4'sd 12 / 3; // -4'sd12 is the negative of the 4-bit // quantity 1100, which is -4. -(-4) = 4 // The result is 1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int n = 8, zero = 0; int res = 'b01xz | n; // res gets 'b11xz coerced to int, or 'b1100 int sum = n + n; // sum gets 16 coerced to int, or 16 int sumx = 'x + n; // sumx gets 'x coerced to int, or 0 int div2 = n/zero + n; // div2 gets 'x coerced to int, or 0 integer div4 = n/zero + n; // div4 gets 'x end"##, Ok((_, _)) ); test!( many1(module_item), r##"logic regA, regB, regC, result ; function logic myFunc(logic x); endfunction initial begin result = regA & (regB | myFunc(regC)) ; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin if ((a=b)) b = (a+=1); a = (b = (c = 5)); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a[i]+=2; // same as a[i] = a[i] +2; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin i = 10; j = i++ + (i = i - 1); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer intS; var logic [15:0] U; var logic signed [15:0] S; intS = -4'd12; U = intS / 3; // expression result is -4, // intS is an integer data type, U is 65532 U = -4'd12; // U is 65524 intS = U / 3; // expression result is 21841, // U is a logic data type intS = -4'd12 / 3; // expression result is 1431655761. // -4'd12 is effectively a 32-bit logic data type U = -12 / 3; // expression result is -4, -12 is effectively // an integer data type. U is 65532 S = -12 / 3; // expression result is -4. S is a signed logic S = -4'sd12 / 3; // expression result is 1. -4'sd12 is actually 4. // The rules for integer division yield 4/3==1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin regA = alpha && beta; // regA is set to 0 regB = alpha || beta; // regB is set to 1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"module shift; logic [3:0] start, result; initial begin start = 1; result = (start << 2); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module ashift; logic signed [3:0] start, result; initial begin start = 4'b1000; result = (start >>> 2); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"wire [15:0] busa = drive_busa ? data : 16'bz;"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic log1, log2, log3; {log1, log2, log3} = 3'b111; {log1, log2, log3} = {1'b1, 1'b1, 1'b1}; // same effect as 3'b111 end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin byte a, b ; bit [1:0] c ; c = {a + b}[1:0]; // 2 lsb's of sum of a and b end"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter P = 32; // The following is legal for all P from 1 to 32 assign b[31:0] = { {32-P{1'b1}}, a[P-1:0] } ; // The following is illegal for P=32 because the zero // replication appears alone within a concatenation assign c[31:0] = { {{32-P{1'b1}}}, a[P-1:0] }; // The following is illegal for P=32 initial $displayb({32-P{1'b1}}, a[P-1:0]);"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin result = {4{func(w)}} ; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin y = func(w) ; result = {y, y, y, y} ; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string hello = "hello"; string s; s = { hello, " ", "world" }; $display( "%s\n", s ); // displays 'hello world' s = { s, " and goodbye" }; $display( "%s\n", s ); // displays 'hello world and goodbye' end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int n = 3; string s = {n { "boo " }}; $display( "%s\n", s ); // displays 'boo boo boo ' end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int a, b, c; int array [$] = '{3,4,5}; if ( a inside {b, c} ); if ( ex inside {1, 2, array} ); // same as { 1, 2, 3, 4, 5} end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic [2:0] val; while ( val inside {3'b1?1} ) ; // matches 3'b101, 3'b111, 3'b1x1, 3'b1z1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"wire r; assign r=3'bz11 inside {3'b1?1, 3'b011}; // r = 1'bx"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin bit ba = a inside { [16:23], [32:47] }; string I; if (I inside {["a rock":"hard place"]}); // I between "a rock" and a "hard place" end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int a, b, c; logic [10:0] up [3:0]; logic [11:1] p1, p2, p3, p4; bit [96:1] y = {>>{ a, b, c }}; // OK: pack a, b, c int j = {>>{ a, b, c }}; // error: j is 32 bits < 96 bits bit [99:0] d = {>>{ a, b, c }}; // OK: d is padded with 4 bits {>>{ a, b, c }} = 23'b1; // error: too few bits in stream {>>{ a, b, c }} = 96'b1; // OK: unpack a = 0, b = 0, c = 1 {>>{ a, b, c }} = 100'b11111; // OK: unpack a = 0, b = 0, c = 1 // 96 MSBs unpacked, 4 LSBs truncated { >> {p1, p2, p3, p4}} = up; // OK: unpack p1 = up[3], p2 = up[2], // p3 = up[1], p4 = up[0] end"##, Ok((_, _)) ); // TODO // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), // r##"byte stream[$]; // byte stream // class Packet; // rand int header; // rand int len; // rand byte payload[]; // int crc; // constraint G { len > 1; payload.size == len ; } // function void post_randomize; crc = payload.sum; endfunction // endclass // initial begin // send: begin // Create random packet and transmit // byte q[$]; // Packet p = new; // void'(p.randomize()); // q = {<< byte{p.header, p.len, p.payload, p.crc}}; // pack // stream = {stream, q}; // append to stream // end // receive: begin // Receive packet, unpack, and remove // byte q[$]; // Packet p = new; // {<< byte{ p.header, p.len, p.payload with [0 +: p.len], p.crc }} = stream; // stream = stream[ $bits(p) / 8 : $ ]; // remove packet // end // end"##, // Ok((_, _)) //); test!( many1(module_item), r##"initial begin q = {<> 1; // will not work properly end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin answer = (a + b + 0) >> 1; // will work correctly end"##, Ok((_, _)) ); test!( many1(module_item), r##"module bitlength(); logic [3:0] a, b, c; logic [4:0] d; initial begin a = 9; b = 8; c = 1; $display("answer = %b", c ? (a&b) : d); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [3:0] a; logic [5:0] b; logic [15:0] c; initial begin a = 4'hF; b = 6'hA; $display("a*b=%h", a*b); // expression size is self-determined c = {a**b}; // expression a**b is self-determined // due to concatenation operator {} $display("a**b=%h", c); c = a**b; // expression size is determined by c $display("c=%h", c); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic [7:0] regA, regB; logic signed [7:0] regS; regA = $unsigned(-4); // regA = 8'b11111100 regB = $unsigned(-4'sd4); // regB = 8'b00001100 regS = $signed (4'b1100); // regS = -4 regA = unsigned'(-4); // regA = 8'b11111100 regS = signed'(4'b1100); // regS = -4 regS = regA + regB; // will do unsigned addition regS = byte'(regA) + byte'(regB); // will do signed addition regS = signed'(regA) + signed'(regB); // will do signed addition regS = $signed(regA) + $signed(regB); // will do signed addition end"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [15:0] a; logic signed [7:0] b; initial a = b[7:0]; // b[7:0] is unsigned and therefore zero-extended"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef union tagged { void Invalid; int Valid; } VInt; VInt vi1, vi2; vi1 = tagged Valid (23+34); // Create Valid int vi2 = tagged Invalid; // Create an Invalid value end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef union tagged { struct { bit [4:0] reg1, reg2, regd; } Add; union tagged { bit [9:0] JmpU; struct { bit [1:0] cc; bit [9:0] addr; } JmpC; } Jmp; } Instr; Instr i1, i2; // Create an Add instruction with its 3 register fields i1 = ( e ? tagged Add '{ e1, 4, ed } // struct members by position : tagged Add '{ reg2:e2, regd:3, reg1:19 }); // by name (order irrelevant) // Create a Jump instruction, with "unconditional" sub-opcode i1 = tagged Jmp (tagged JmpU 239); // Create a Jump instruction, with "conditional" sub-opcode i2 = tagged Jmp (tagged JmpC '{ 2, 83 }); // inner struct by position i2 = tagged Jmp (tagged JmpC '{ cc:2, addr:83 }); // by name end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin x = i1.Add.reg1; i1.Add = '{19, 4, 3}; i1.Add.reg2 = 4; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module string_test; bit [8*14:1] stringvar; initial begin stringvar = "Hello world"; $display("%s is stored as %h", stringvar, stringvar); stringvar = {stringvar,"!!!"}; $display("%s is stored as %h", stringvar, stringvar); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [8*10:1] s1, s2; initial begin s1 = "Hello"; s2 = " world!"; if ({s1,s2} == "Hello world!") $display("strings are equal"); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a = (a:b:c) + (d:e:f); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a = val - (32'd 50: 32'd 75: 32'd 100); end"##, Ok((_, _)) ); test!( source_text, r##"package pex_gen9_common_expressions; let valid_arb(request, valid, override) = |(request & valid) || override; endpackage module my_checker; import pex_gen9_common_expressions::*; logic a, b; wire [1:0] req; wire [1:0] vld; logic ovr; initial begin if (valid_arb(.request(req), .valid(vld), .override(ovr))) begin end end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"let mult(x, y) = ($bits(x) + $bits(y))'(x * y);"##, Ok((_, _)) ); test!( many1(module_item), r##"let at_least_two(sig, rst = 1'b0) = rst || ($countones(sig) >= 2); logic [15:0] sig1; logic [3:0] sig2; always_comb begin q1: assert (at_least_two(sig1)); q2: assert (at_least_two(~sig2)); end"##, Ok((_, _)) ); test!( many1(module_item), r##"task write_value; input logic [31:0] addr; input logic [31:0] value; endtask let addr = top.block1.unit1.base + top.block1.unit2.displ; initial begin write_value(addr, 0); end"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; logic clk, a, b; logic p, q, r; // let with formal arguments and default value on y let eq(x, y = b) = x == y; // without parameters, binds to a, b above let tmp = a && b; a1: assert property (@(posedge clk) eq(p,q)); always_comb begin a2: assert (eq(r)); // use default for y a3: assert (tmp); end endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; bit clk, a, b; logic p, q, r; // let eq(x, y = b) = x == y; // let tmp = a && b; a1: assert property (@(posedge clk) (m.p == m.q)); always_comb begin a2: assert ((m.r == m.b)); // use default for y a3: assert ((m.a && m.b)); end endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic x = 1'b1; logic a, b; let y = x; always_comb begin // y binds to preceding definition of x // in the declarative context of let bit x = 1'b0; b = a | y; end endmodule : top"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; bit x = 1'b1; bit a; // let y = x; always_comb begin // y binds to preceding definition of x // in the declarative context of let bit x = 1'b0; b = a | (top.x); end endmodule : top"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic a, b; let x = a || b; sequence s; x ##1 b; endsequence : s endmodule : top"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic a, b; // let x = a || b; sequence s; (top.a || top.b) ##1 b; endsequence : s endmodule : top"##, Ok((_, _)) ); // TODO // assign can't have block_identifier like assert //test!( // many1(module_item), // r##"module m(); // wire a, b; // wire [2:0] c; // wire [2:0] d; // wire e; // for (genvar i = 0; i < 3; i++) begin : L0 // if (i !=1) begin : L1 // let my_let(x) = !x || b && c[i]; // s1: assign d[2 - i] = my_let(a); // OK // end : L1 // end : L0 // s2: assign e = L0[0].L1.my_let(a); // Illegal // endmodule : m"##, // Ok((_, _)) //); test!( many1(module_item), r##"assign d[2] = (!m.a || m.b && m.c[0]);"##, Ok((_, _)) ); test!( many1(module_item), r##"assign d[0] = (!m.a || m.b && m.c[2]);"##, Ok((_, _)) ); test!( many1(module_item), r##"module m(input clock); logic [15:0] a, b; logic c, d; typedef bit [15:0] bits; let ones_match(bits x, y) = x == y; let same(logic x, y) = x === y; always_comb a1: assert(ones_match(a, b)); property toggles(bit x, y); same(x, y) |=> !same(x, y); endproperty a2: assert property (@(posedge clock) toggles(c, d)); endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"module m(input clock); logic [15:0] a, b; logic c, d; typedef bit [15:0] bits; // let ones_match(bits x, y) = x == y; // let same(logic x, y) = x === y; always_comb a1:assert((bits'(a) == bits'(b))); property toggles(bit x, y); (logic'(x) === logic'(y)) |=> ! (logic'(x) === logic'(y)); endproperty a2: assert property (@(posedge clock) toggles(c, d)); endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"module m(input clock); logic a; let p1(x) = $past(x); let p2(x) = $past(x,,,@(posedge clock)); let s(x) = $sampled(x); always_comb begin a1: assert(p1(a)); a2: assert(p2(a)); a3: assert(s(a)); end a4: assert property(@(posedge clock) p1(a)); endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"module m(input clock); logic a; let p1(x) = $past(x); let p2(x) = $past(x,,,@(posedge clock)); let s(x) = $sampled(x); always_comb begin a1: assert(($past(a))); // Illegal: no clock can be inferred a2: assert(($past(a,,,@(posedge clock)))); a3: assert(($sampled (a))); end a4: assert property(@(posedge clock)($past(a))); // @(posedge clock) // is inferred endmodule : m"##, Ok((_, _)) ); } #[test] fn clause12() { test!( many1(module_item), r##"initial begin if (index > 0) if (rega > regb) result = rega; else // else applies to preceding if result = regb; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin if (index > 0) begin if (rega > regb) result = rega; end else result = regb; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin // declare variables and parameters logic [31:0] instruction, segment_area[255:0]; logic [7:0] index; logic [5:0] modify_seg1, modify_seg2, modify_seg3; parameter segment1 = 0, inc_seg1 = 1, segment2 = 20, inc_seg2 = 2, segment3 = 64, inc_seg3 = 4, data = 128; // test the index variable if (index < segment2) begin instruction = segment_area [index + modify_seg1]; index = index + inc_seg1; end else if (index < segment3) begin instruction = segment_area [index + modify_seg2]; index = index + inc_seg2; end else if (index < data) begin instruction = segment_area [index + modify_seg3]; index = index + inc_seg3; end else instruction = segment_area [index]; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin unique if ((a==0) || (a==1)) $display("0 or 1"); else if (a == 2) $display("2"); else if (a == 4) $display("4"); // values 3,5,6,7 cause a violation report priority if (a[2:1]==0) $display("0 or 1"); else if (a[2] == 0) $display("2 or 3"); else $display("4 to 7"); // covers all other possible values, // so no violation report end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin unique0 if ((a==0) || (a==1)) $display("0 or 1"); else if (a == 2) $display("2"); else if (a == 4) $display("4"); // values 3,5,6,7 // cause no violation report end"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb begin not_a = !a; end always_comb begin : a1 u1: unique if (a) z = a | b; else if (not_a) z = a | c; end"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb begin for (int j = 0; j < 3; j++) not_a[j] = !a[j]; end always_comb begin : a1 for (int j = 0; j < 3; j++) unique if (a[j]) z[j] = a[j] | b[j]; else if (not_a[j]) z[j] = a[j] | c[j]; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module fsm(); function bit f1(bit a, bit not_a); a1: unique if (a); else if (not_a); endfunction always_comb begin : b1 some_stuff = f1(c, d); end always_comb begin : b2 other_stuff = f1(e, f); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic [15:0] data; logic [9:0] result; case (data) 16'd0: result = 10'b0111111111; 16'd1: result = 10'b1011111111; 16'd2: result = 10'b1101111111; 16'd3: result = 10'b1110111111; 16'd4: result = 10'b1111011111; 16'd5: result = 10'b1111101111; 16'd6: result = 10'b1111110111; 16'd7: result = 10'b1111111011; 16'd8: result = 10'b1111111101; 16'd9: result = 10'b1111111110; default result = 'x; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin case (select[1:2]) 2'b00: result = 0; 2'b01: result = flaga; 2'b0x, 2'b0z: result = flaga ? 'x : 0; 2'b10: result = flagb; 2'bx0, 2'bz0: result = flagb ? 'x : 0; default result = 'x; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin case (sig) 1'bz: $display("signal is floating"); 1'bx: $display("signal is unknown"); default: $display("signal is %b", sig); endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic [7:0] ir; casez (ir) 8'b1???????: instruction1(ir); 8'b01??????: instruction2(ir); 8'b00010???: instruction3(ir); 8'b000001??: instruction4(ir); endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic [7:0] r, mask; mask = 8'bx0x0x0x0; casex (r ^ mask) 8'b001100xx: stat1; 8'b1100xx00: stat2; 8'b00xx0011: stat3; 8'bxx010100: stat4; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin logic [2:0] encode ; case (1) encode[2] : $display("Select Line 2") ; encode[1] : $display("Select Line 1") ; encode[0] : $display("Select Line 0") ; default $display("Error: One of the bits expected ON"); endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin bit [2:0] a; unique case(a) // values 3,5,6,7 cause a violation report 0,1: $display("0 or 1"); 2: $display("2"); 4: $display("4"); endcase priority casez(a) // values 4,5,6,7 cause a violation report 3'b00?: $display("0 or 1"); 3'b0??: $display("2 or 3"); endcase unique0 case(a) // values 3,5,6,7 do not cause a violation report 0,1: $display("0 or 1"); 2: $display("2"); 4: $display("4"); endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb begin not_a = !a; end always_comb begin : a1 unique case (1'b1) a : z = b; not_a : z = c; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [2:0] status; always @(posedge clock) priority case (status) inside 1, 3 : task1; // matches 'b001 and 'b011 3'b0?0, [4:7]: task2; // matches 'b000 'b010 'b0x0 'b0z0 // 'b100 'b101 'b110 'b111 endcase // priority case fails all other values including // 'b00x 'b01x 'bxxx"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef union tagged { void Invalid; int Valid; } VInt; VInt v; case (v) matches tagged Invalid : $display ("v is Invalid"); tagged Valid .n : $display ("v is Valid with value %d", n); endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef union tagged { struct { bit [4:0] reg1, reg2, regd; } Add; union tagged { bit [9:0] JmpU; struct { bit [1:0] cc; bit [9:0] addr; } JmpC; } Jmp; } Instr; Instr instr; case (instr) matches tagged Add '{.r1, .r2, .rd} &&& (rd != 0) : rf[rd] = rf[r1] + rf[r2]; tagged Jmp .j : case (j) matches tagged JmpU .a : pc = pc + a; tagged JmpC '{.c, .a}: if (rf[c]) pc = a; endcase endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin case (instr) matches tagged Add '{.*, .*, 0} : ; // no op tagged Add '{.r1, .r2, .rd} : rf[rd] = rf[r1] + rf[r2]; tagged Jmp .j : case (j) matches tagged JmpU .a : pc = pc + a; tagged JmpC '{.c, .a} : if (rf[c]) pc = a; endcase endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin case (instr) matches tagged Add s: case (s) matches '{.*, .*, 0} : ; // no op '{.r1, .r2, .rd} : rf[rd] = rf[r1] + rf[r2]; endcase tagged Jmp .j: case (j) matches tagged JmpU .a : pc = pc + a; tagged JmpC '{.c, .a} : if (rf[c]) pc = a; endcase endcase end"##, Ok((_, _)) ); // TODO // tagged can't have paren. //test!( // many1(module_item), // r##"initial begin // case (instr) matches // tagged Add '{.r1, .r2, .rd} &&& (rd != 0) : rf[rd] = rf[r1] + rf[r2]; // tagged Jmp (tagged JmpU .a) : pc = pc + a; // tagged Jmp (tagged JmpC '{.c, .a}) : if (rf[c]) pc = a; // endcase // end"##, // Ok((_, _)) //); // TODO // tagged can't have paren. //test!( // many1(module_item), // r##"initial begin // case (instr) matches // tagged Add '{reg2:.r2,regd:.rd,reg1:.r1} &&& (rd != 0): // rf[rd] = rf[r1] + rf[r2]; // tagged Jmp (tagged JmpU .a) : pc = pc + a; // tagged Jmp (tagged JmpC '{addr:.a,cc:.c}) : if (rf[c]) pc = a; // endcase // end"##, // Ok((_, _)) //); // TODO // tagged can't have paren. //test!( // many1(module_item), // r##"initial begin // if (e matches (tagged Jmp (tagged JmpC '{cc:.c,addr:.a}))) // ; // c and a can be used here // else // ; // end"##, // Ok((_, _)) //); // TODO // tagged can't have paren. //test!( // many1(module_item), // r##"initial begin // if (e matches (tagged Jmp .j) &&& // j matches (tagged JmpC '{cc:.c,addr:.a})) // ; // c and a can be used here // else // ; // end"##, // Ok((_, _)) //); // TODO // tagged can't have paren. //test!( // many1(module_item), // r##"initial begin // if (e matches (tagged Jmp (tagged JmpC '{cc:.c,addr:.a})) // &&& (rf[c] != 0)) // ; // c and a can be used here // else // ; // end"##, // Ok((_, _)) //); test!( many1(module_item), r##"module m; initial begin for (int i = 0; i <= 255; i++); end initial begin loop2: for (int i = 15; i >= 0; i--); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; initial begin begin automatic int i; for (i = 0; i <= 255; i++); end end initial begin begin : loop2 automatic int i; for (i = 15; i >= 0; i--); end end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin for ( int count = 0; count < 3; count++ ) value = value +((a[count]) * (count+1)); for ( int count = 0, done = 0, j = 0; j * count < 125; j++, count++) $display("Value j = %d\n", j ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin parameter size = 8, longsize = 16; logic [size:1] opa, opb; logic [longsize:1] result; begin : mult logic [longsize:1] shift_opa, shift_opb; shift_opa = opa; shift_opb = opb; result = 0; repeat (size) begin if (shift_opb[1]) result = result + shift_opa; shift_opa = shift_opa << 1; shift_opb = shift_opb >> 1; end end end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string words [2] = '{ "hello", "world" }; int prod [1:8] [1:3]; foreach( words [ j ] ) $display( j , words[j] ); // print each index and value foreach( prod[ k, m ] ) prod[k][m] = k * m; // initialize end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin begin : count1s logic [7:0] tempreg; count = 0; tempreg = data; while (tempreg) begin if (tempreg[0]) count++; tempreg >>= 1; end end end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin string s; if ( map.first( s ) ) do $display( "%s : %d\n", s, map[ s ] ); while ( map.next( s ) ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin clock1 <= 0; clock2 <= 0; fork forever #10 clock1 = ~clock1; #5 forever #10 clock2 = ~clock2; join end"##, Ok((_, _)) ); } #[test] fn clause13() { test!( many1(module_item), r##"initial begin switch_bytes (old_word, new_word); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin new_word = switch_bytes (old_word); end"##, Ok((_, _)) ); test!( many1(module_item), r##"task mytask1 (output int x, input logic y); endtask task mytask2; output x; input y; int x; logic y; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"task mytask3(a, b, output logic [15:0] u, v); endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"task mytask4(input [3:0][7:0] a, b[3:0], output [3:0][7:0] y[1:0]); endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"task my_task; input a, b; inout c; output d, e; c = a; // the assignments that initialize result outputs d = b; e = c; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"task my_task (input a, b, inout c, output d, e); c = a; // the assignments that initialize result variables d = b; e = c; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"initial my_task (v, w, x, y, z);"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a = v; b = w; c = x; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin x = c; y = d; z = e; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module traffic_lights; logic clock, red, amber, green; parameter on = 1, off = 0, red_tics = 350, amber_tics = 30, green_tics = 200; // initialize colors initial red = off; initial amber = off; initial green = off; always begin // sequence to control the lights red = on; // turn red light on light(red, red_tics); // and wait. green = on; // turn green light on light(green, green_tics); // and wait. amber = on; // turn amber light on light(amber, amber_tics); // and wait. end // task to wait for 'tics' positive edge clocks // before turning 'color' light off task light (output color, input [31:0] tics); repeat (tics) @ (posedge clock); color = off; // turn light off. endtask: light always begin // waveform for the clock #100 clock = 0; #100 clock = 1; end endmodule: traffic_lights"##, Ok((_, _)) ); test!( many1(module_item), r##"function logic [15:0] myfunc1(int x, int y); endfunction function logic [15:0] myfunc2; input int x; input int y; endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"function logic [15:0] myfunc3(int a, int b, output logic [15:0] u, v); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"function [3:0][7:0] myfunc4(input [3:0][7:0] a, b[3:0]); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"function [15:0] myfunc1 (input [7:0] x,y); myfunc1 = x * y - 1; // return value assigned to function name endfunction function [15:0] myfunc2 (input [7:0] x,y); return x * y - 1; //return value is specified using return statement endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin a = b + myfunc1(c, d); // call myfunc1 (defined above) as an expression myprint(a); // call myprint (defined below) as a statement end function void myprint (int a); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin void'(some_function()); end"##, Ok((_, _)) ); test!( many1(module_item), r##"module tryfact; // define the function function automatic integer factorial (input [31:0] operand); if (operand >= 2) factorial = factorial (operand - 1) * operand; else factorial = 1; endfunction: factorial // test the function integer result; initial begin for (int n = 0; n <= 7; n++) begin result = factorial(n); $display("%0d factorial=%0d", n, result); end end endmodule: tryfact"##, Ok((_, _)) ); test!( many1(module_item), r##"module ram_model (address, write, chip_select, data); parameter data_width = 8; parameter ram_depth = 256; localparam addr_width = clogb2(ram_depth); input [addr_width - 1:0] address; input write, chip_select; inout [data_width - 1:0] data; //define the clogb2 function function integer clogb2 (input [31:0] value); value = value - 1; for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) value = value >> 1; endfunction logic [data_width - 1:0] data_store[0:ram_depth - 1]; //the rest of the ram model endmodule: ram_model"##, Ok((_, _)) ); test!( many1(module_item), r##"ram_model #(32,421) ram_a0(a_addr,a_wr,a_cs,a_data);"##, Ok((_, _)) ); test!( many1(module_item), r##"class IntClass; int a; endclass IntClass address=new(), stack=new(); function automatic bit watch_for_zero( IntClass p ); fork forever @p.a begin if ( p.a == 0 ) $display ("Unexpected zero"); end join_none return ( p.a == 0 ); endfunction function bit start_check(); return ( watch_for_zero( address ) | watch_for_zero( stack ) ); endfunction bit y = watch_for_zero( stack ); // illegal initial if ( start_check() ) $display ( "OK"); // legal initial fork if (start_check() ) $display( "OK too"); // legal join_none"##, Ok((_, _)) ); test!( many1(module_item), r##"function automatic int crc( byte packet [1000:1] ); for( int j= 1; j <= 1000; j++ ) begin crc ^= packet[j]; end endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"function automatic int crc( ref byte packet [1000:1] ); for( int j= 1; j <= 1000; j++ ) begin crc ^= packet[j]; end endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin byte packet1[1000:1]; int k = crc( packet1 ); // pass by value or by reference: call is the same end"##, Ok((_, _)) ); test!( many1(module_item), r##"task automatic show ( const ref byte data [] ); for ( int j = 0; j < data.size ; j++ ) $display( data[j] ); // data can be read but not written endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"task read(int j = 0, int k, int data = 1 ); endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin read( , 5 ); // is equivalent to read( 0, 5, 1 ); read( 2, 5 ); // is equivalent to read( 2, 5, 1 ); read( , 5, ); // is equivalent to read( 0, 5, 1 ); read( , 5, 7 ); // is equivalent to read( 0, 5, 7 ); read( 1, 5, 2 ); // is equivalent to read( 1, 5, 2 ); read( ); // error; k has no default value read( 1, , 7 ); // error; k has no default value end"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; logic a, w; task t1 (output o = a) ; // default binds to m.a endtask :t1 task t2 (output o = b) ; // illegal, b cannot be resolved endtask :t2 task t3 (inout io = w) ; // default binds to m.w endtask :t1 endmodule :m module n; logic a; initial begin m.t1(); // same as m.t1(m.a), not m.t1(n.a); // at end of task, value of t1.o is copied to m.a m.t3(); // same as m.t3(m.w) // value of m.w is copied to t3.io at start of task and // value of t3.io is copied to m.w at end of task end endmodule :n"##, Ok((_, _)) ); test!( many1(module_item), r##"function int fun( int j = 1, string s = "no" ); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fun( .j(2), .s("yes") ); // fun( 2, "yes" ); fun( .s("yes") ); // fun( 1, "yes" ); fun( , "yes" ); // fun( 1, "yes" ); fun( .j(2) ); // fun( 2, "no" ); fun( .s("yes"), .j(2) ); // fun( 2, "yes" ); fun( .s(), .j() ); // fun( 1, "no" ); fun( 2 ); // fun( 2, "no" ); fun( ); // fun( 1, "no" ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin //fun( .s("yes"), 2 ); // illegal fun( 2, .s("yes") ); // OK end"##, Ok((_, _)) ); test!( many1(module_item), r##"virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W)); static function logic [ENCODE_W-1:0] ENCODER_f (input logic [DECODE_W-1:0] DecodeIn); ENCODER_f = '0; for (int i=0; i (posedge clk1) end endmodule endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"clocking cb @(negedge clk); input v; endclocking always @(cb) $display(cb.v); always @(negedge clk) $display(cb.v);"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic clk1, clk2; global clocking sys @(clk1 or clk2); endclocking endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; subsystem1 sub1(); subsystem2 sub2(); endmodule module subsystem1; logic subclk1; global clocking sub_sys1 @(subclk1); endclocking common_sub common(); endmodule module subsystem2; logic subclk2; global clocking sub_sys2 @(subclk2); endclocking common_sub common(); endmodule module common_sub; always @($global_clock) begin end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; subsystem1 sub1(); subsystem2 sub2(); endmodule module subsystem1; logic subclk1, req, ack; global clocking sub_sys1 @(subclk1); endclocking common_checks checks(req, ack); endmodule module subsystem2; logic subclk2, req, ack; global clocking sub_sys2 @(subclk2); endclocking common_checks checks(req, ack); endmodule module another_module; logic another_clk; global clocking another_clocking @(another_clk); endclocking property p(req, ack); @($global_clock) req |=> ack; endproperty endmodule checker common_checks(logic req, logic ack); assert property (another_module.p(req, ack)); endchecker"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; subsystem1 sub1(); subsystem2 sub2(); endmodule module subsystem1; logic subclk1, req, ack; global clocking sub_sys1 @(subclk1); endclocking always another_module.t(req, ack); endmodule module subsystem2; logic subclk2, req, ack; global clocking sub_sys2 @(subclk2); endclocking always another_module.t(req, ack); endmodule module another_module; logic another_clk; global clocking another_clocking @(another_clk); endclocking task t(input req, input ack); @($global_clock); endtask endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic a, b, c, clk; global clocking top_clocking @(clk); endclocking property p1(req, ack); @($global_clock) req |=> ack; endproperty property p2(req, ack, interrupt); @($global_clock) accept_on(interrupt) p1(req, ack); endproperty my_checker check( p2(a, b, c), @($global_clock) a[*1:$] ##1 b); endmodule checker my_checker(property p, sequence s); logic checker_clk; global clocking checker_clocking @(checker_clk); endclocking assert property (p); cover property (s); endchecker"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(ram_bus.ack_l); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(ram_bus); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(posedge ram_bus.enable); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(negedge dom.sign[a]); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(posedge dom.sig1 or dom.sig2); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(negedge dom.sig1 or posedge dom.sig2); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(edge dom.sig1); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @(negedge dom.sig1 or posedge dom.sig1); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin bus.data[3:0] <= 4'h5; // drive data in Re-NBA region of the current cycle ##1 bus.data <= 8'hz; // wait 1 default clocking cycle, then drive data ##2; bus.data <= 2; // wait 2 default clocking cycles, then drive data bus.data <= ##2 r; // remember the value of r and then drive // data 2 (bus) cycles later bus.data <= #4 r; // error: regular intra-assignment delay not allowed // in synchronous drives end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking cb @(posedge clk); // Assume clk has a period of #10 units output v; endclocking initial begin #3 cb.v <= expr1; // Matures in cycle 1; equivalent to ##1 cb.v <= expr1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"clocking cb @(posedge clk); inout a; output b; endclocking initial begin cb.a <= c; // The value of a will change in the Re-NBA region cb.b <= cb.a; // b is assigned the value of a before the change end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking pe @(posedge clk); output nibble; // four bit output endclocking initial begin ##2; pe.nibble <= 4'b0101; pe.nibble <= 4'b0011; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; bit a = 1'b1; default clocking cb @(posedge clk); output a; endclocking initial begin ## 1; cb.a <= 1'b0; @(x); // x is triggered by reactive stimulus running in same time step cb.a <= 1'b1; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"bit v; default clocking cb @(posedge clk); output v; endclocking initial begin ##1; // Wait until cycle 1 cb.v <= expr1; // Matures in cycle 1, v is assigned expr1 cb.v <= ##2 expr2; // Matures in cycle 3 #1 cb.v <= ##2 expr3; // Matures in cycle 3 ##1 cb.v <= ##1 expr4; // Matures in cycle 3, v is assigned expr4 end"##, Ok((_, _)) ); test!( many1(module_item), r##"reg j; clocking pe @(posedge clk); output j; endclocking clocking ne @(negedge clk); output j; endclocking"##, Ok((_, _)) ); test!( many1(module_item), r##"reg j; clocking e @(edge clk); output j; endclocking"##, Ok((_, _)) ); } #[test] fn clause15() { test!( many1(module_item), r##"initial begin semaphore smTx; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin mailbox mbxRcv; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin typedef mailbox #(string) s_mbox; s_mbox sm = new; string s; sm.put( "hello" ); sm.get( s ); // s <- "hello" end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin @ hierarchical_event_identifier; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin wait ( hierarchical_event_identifier.triggered ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"event done, blast; // declare two new events event done_too = done; // declare done_too as alias to done task trigger( event ev ); -> ev; endtask initial begin fork @ done_too; // wait for done through done_too #1 trigger( done ); // trigger done through task trigger join fork -> blast; wait ( blast.triggered ); join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin wait_order( a, b, c); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin wait_order( a, b, c ) else $display( "Error: events out of order" ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin bit success; wait_order( a, b, c ) success = 1; else success = 0; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin event a, b, c; a = b; -> c; -> a; // also triggers b -> b; // also triggers a a = c; b = a; -> a; // also triggers b and c -> b; // also triggers a and c -> c; // also triggers a and b end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork T1: forever @ E2; T2: forever @ E1; T3: begin E2 = E1; forever -> E2; end join end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin event E1 = null; @ E1; // undefined: might block forever or not at all wait( E1.triggered ); // undefined -> E1; // no effect end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin event E1, E2; if ( E1 ) // same as if ( E1 != null ) E1 = E2; if ( E1 == E2 ) $display( "E1 and E2 are the same event" ); end"##, Ok((_, _)) ); } #[test] fn clause16() { test!( many1(module_item), r##"initial begin assert_f: assert(f) $info("passed"); else $error("failed"); assume_inputs: assume (in_a || in_b) $info("assumption holds"); else $error("assumption does not hold"); cover_a_and_b: cover (in_a && in_b) $info("in_a && in_b == 1 covered"); end"##, Ok((_, _)) ); test!( many1(module_item), r##"time t; always @(posedge clk) if (state == REQ) assert (req1 || req2) else begin t = $time; #5 $error("assert failed at time %0t",t); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin assert (myfunc(a,b)) count1 = count + 1; else ->event1; assert (y == 0) else flag = 1; end"##, Ok((_, _)) ); test!( many1(module_item), r##"assign not_a = !a; always_comb begin : b1 a1: assert (not_a != a); a2: assert #0 (not_a != a); // Should pass once values have settled end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(a or b) begin : b1 a3: assert #0 (a == b) rptobj.success(0); else rptobj.error(0, a, b); #1; a4: assert #0 (a == b) rptobj.success(1); else rptobj.error(1, a, b); end"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb begin : b1 c1: cover (b != a); c2: cover #0 (b != a); end"##, Ok((_, _)) ); test!( many1(module_item), r##"function f(bit v); p: assert #0 (v); endfunction always_comb begin: myblk a = b || f(c); end"##, Ok((_, _)) ); test!( many1(module_item), r##"function int error_type (int opcode); func_assert: assert (opcode < 64) else $display("Opcode error."); if (opcode < 32) return (0); else return (1); endfunction always_comb begin : b1 a1: assert #0 (my_cond) else $error("Error on operation of type %d\n", error_type(opcode)); a2: assert #0 (my_cond) else error_type(opcode); end"##, Ok((_, _)) ); test!( many1(module_item), r##"module dut(input logic clk, input logic a, input logic b); logic c; always_ff @(posedge clk) c <= b; a1: assert #0 (!(a & c)) $display("Pass"); else $display("Fail"); a2: assert final (!(a & c)) $display("Pass"); else $display("Fail"); endmodule program tb(input logic clk, output logic a, output logic b); default clocking m @(posedge clk); default input #0; default output #0; output a; output b; endclocking initial begin a = 1; b = 0; ##10; b = 1; ##1; a = 0; end endprogram module sva_svtb; bit clk; logic a, b; dut dut (.*); tb tb (.*); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m (input a, b); a1: assert #0 (a == b); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m (input a, b); always_comb begin a1: assert #0 (a == b); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(bad_val or bad_val_ok) begin : b1 a1: assert #0 (bad_val) else $fatal(1, "Sorry"); if (bad_val_ok) begin disable a1; end end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(a or b or c) begin : b2 if (c == 8'hff) begin a2: assert #0 (a && b); end else begin a3: assert #0 (a || b); end end always @(clear_b2) begin : b3 disable b2; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module fsm(); function bit f (int a, int b); a1: assert #0 (a == b); endfunction always_comb begin : b1 some_stuff = f(x,y); end always_comb begin : b2 other_stuff = f(z,w); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"global clocking @clk; endclocking assert property(@($global_clock) a);"##, Ok((_, _)) ); test!( many1(module_item), r##"assert property(@clk a);"##, Ok((_, _)) ); test!( many1(module_item), r##"base_rule1: assert property (cont_prop(rst,in1,in2)) $display("%m, passing"); else $display("%m, failed");"##, Ok((_, _)) ); test!( many1(module_item), r##"bit a; integer b; byte q[$]; property p1; $rose(a) |-> q[0]; endproperty property p2; integer l_b; ($rose(a), l_b = b) |-> ##[3:10] q[l_b]; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [2:0] count; realtime t; initial count = 0; always @(posedge clk) begin if (count == 0) t = $realtime; //capture t in a procedural context count++; end property p1; @(posedge clk) count == 7 |-> $realtime - t < 50.5; endproperty property p2; realtime l_t; @(posedge clk) (count == 0, l_t = $realtime) ##1 (count == 7)[->1] |-> $realtime - l_t < 50.5; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence delay_example(x, y, min, max, delay1); x ##delay1 y[*min:max]; endsequence // Legal a1: assert property (@(posedge clk) delay_example(x, y, 3, $, 2)); int z, d; // Illegal: z and d are not elaboration-time constants a2_illegal: assert property (@(posedge clk) delay_example(x, y, z, $, d));"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s1; @(posedge clk) a ##1 b ##1 c; endsequence sequence s2; @(posedge clk) d ##1 e ##1 f; endsequence sequence s3; @(negedge clk) g ##1 h ##1 i; endsequence sequence s4; @(edge clk) j ##1 k ##1 l; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s20_1(data,en); (!frame && (data==data_bus)) ##1 (c_be[0:3] == en); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s; a ##1 b ##1 c; endsequence sequence rule; @(posedge sysclk) trans ##1 start_trans ##1 s ##1 end_trans; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence rule; @(posedge sysclk) trans ##1 start_trans ##1 (a ##1 b ##1 c) ##1 end_trans ; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s1; @(posedge sysclk) (x ##1 s2); endsequence sequence s2; @(posedge sysclk) (y ##1 s1); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s1(w, x, y); w ##1 x ##[2:10] y; endsequence sequence s2(w, y, bit x); w ##1 x ##[2:10] y; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence delay_arg_example (max, shortint delay1, delay2, min); x ##delay1 y[*min:max] ##delay2 z; endsequence parameter my_delay=2; cover property (delay_arg_example($, my_delay, my_delay-1, 3));"##, Ok((_, _)) ); test!( many1(module_item), r##"cover property (x ##2 y[*3:$] ##1 z);"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence event_arg_example (event ev); @(ev) x ##1 y; endsequence cover property (event_arg_example(posedge clk));"##, Ok((_, _)) ); test!( many1(module_item), r##"cover property (@(posedge clk) x ##1 y);"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence event_arg_example2 (reg sig); @(posedge sig) x ##1 y; endsequence cover property (event_arg_example2(clk));"##, Ok((_, _)) ); test!( many1(module_item), r##"cover property (@(posedge clk) x ##1 y);"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s(bit a, bit b); bit loc_a; (1'b1, loc_a = a) ##0 (t == loc_a) [*0:$] ##1 b; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"logic b_d, d_d; sequence legal_loc_var_formal ( local inout logic a, local logic b = b_d, // input inferred, default actual argument b_d c, // local input logic inferred, no default // actual argument d = d_d, // local input logic inferred, default actual // argument d_d logic e, f // e and f are not local variable formal arguments ); logic g = c, h = g || d; g ##1 h; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence sub_seq2(local inout int lv); (a ##1 !a, lv += data_in) ##1 !b[*0:$] ##1 b && (data_out == lv); endsequence sequence seq2; int v1; (c, v1 = data) ##1 sub_seq2(v1) // lv is initialized by assigning it the value of v1; // when the instance sub_seq2(v1) matches, v1 is // assigned the value of lv ##1 (do1 == v1); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence seq2_inlined; int v1, lv; (c, v1 = data) ##1 ( (1, lv = v1) ##0 (a ##1 !a, lv += data_in) ##1 (!b[*0:$] ##1 b && (data_out == lv), v1 = lv) ) ##1 (do1 == v1); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"logic a, b, clk; // ... a1_bad: assert property (@clk a == b) else $error("Different values: a = %b, b = %b", a, b); a2_ok: assert property (@clk a == b) else $error("Different values: a = %b, b = %b", $sampled(a), $sampled(b));"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) reg1 <= a & $rose(b);"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin $past(in1, , enable); end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) reg1 <= a & $past(b);"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) for (int i = 0; i < 4; i ++) if (cond[i]) reg1[i] <= $past(b[i]);"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) if (enable) q <= d; always @(posedge clk) assert property (done |=> (out == $past(q, 2,enable)) );"##, Ok((_, _)) ); test!( many1(module_item), r##"bit clk, fclk, req, gnt, en; a1: assert property (@(posedge clk) en && $rose(req) |=> gnt); a2: assert property (@(posedge clk) en && $rose(req, @(posedge fclk)) |=> gnt);"##, Ok((_, _)) ); test!( many1(module_item), r##"always_ff @(posedge clk1) reg1 <= $rose(b, @(posedge clk2));"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) begin @(negedge clk2); x = $past(y, 5); // illegal if not within default clocking end"##, Ok((_, _)) ); test!( many1(module_item), r##"a1: assert property (@clk $future_gclk(a || $rising_gclk(b))); sequence s; bit v; (a, v = a) ##1 (b == v)[->1]; endsequence : s // Illegal: a global clocking future sampled value function shall not // be used in an assertion containing sequence match items a2: assert property (@clk s |=> $future_gclk(c));"##, Ok((_, _)) ); test!( many1(module_item), r##"a1: assert property (@($global_clock) $changing_gclk(sig) |-> $falling_gclk(clk)) else $error("sig is not stable");"##, Ok((_, _)) ); test!( many1(module_item), r##"a2: assume property(@($global_clock) $falling_gclk(clk) ##1 (!$falling_gclk(clk)[*1:$]) |-> $steady_gclk(sig));"##, Ok((_, _)) ); test!( many1(module_item), r##"a3: assert property (@($global_clock) disable iff (rst) $changing_gclk(sig) |-> $falling_gclk(clk)) else $error("sig is not stable");"##, Ok((_, _)) ); test!( many1(module_item), r##"a4: assert property (##1 $stable_gclk(sig)); // In a5, there is no issue at cycle 0 a5: assert property ($steady_gclk(sig));"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence t1; te1 ## [2:5] te2; endsequence sequence ts1; first_match(te1 ## [2:5] te2); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence t2; (a ##[2:3] b) or (c ##[1:2] d); endsequence sequence ts2; first_match(t2); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence burst_rule1; @(posedge mclk) $fell(burst_mode) ##0 ((!burst_mode) throughout (##2 ((trdy==0)&&(irdy==0)) [*7])); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s; a ##1 b ##1 c; endsequence sequence rule; @(posedge sysclk) trans ##1 start_trans ##1 s ##1 end_trans; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence e1; @(posedge sysclk) $rose(ready) ##1 proc1 ##1 proc2 ; endsequence sequence rule; @(posedge sysclk) reset ##1 inst ##1 e1.triggered ##1 branch_back; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence e2(a,b,c); @(posedge sysclk) $rose(a) ##1 b ##1 c; endsequence sequence rule2; @(posedge sysclk) reset ##1 inst ##1 e2(ready,proc1,proc2).triggered ##1 branch_back; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence e2_instantiated; e2(ready,proc1,proc2); endsequence sequence rule2a; @(posedge sysclk) reset ##1 inst ##1 e2_instantiated.triggered ##1 branch_back; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence e3(sequence a, untyped b); @(posedge sysclk) a.triggered ##1 b; endsequence sequence rule3; @(posedge sysclk) reset ##1 e3(ready ##1 proc1, proc2) ##1 branch_back; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence zero_or_one_req; (req==1'b1)[*0:1]; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s; logic u, v = a, w = v || b; u; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"property e; int x; (valid_in, x = pipe_in) |-> ##5 (pipe_out1 == (x+1)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence data_check; int x; a ##1 (!a, x = data_in) ##1 !b[*0:$] ##1 b && (data_out == x); endsequence property data_check_p; int x; a ##1 (!a, x = data_in) |=> !b[*0:$] ##1 b && (data_out == x); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence rep_v; int x = 0; (a[->1], x += data)[*4] ##1 b ##1 c && (data_out == x); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence count_a_cycles; int x; ($rose(a), x = 1) ##1 (a, x++)[*0:$] ##1 !a && (x <= MAX); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence sub_seq1; int v1; (a ##1 !a, v1 = data_in) ##1 !b[*0:$] ##1 b && (data_out == v1); endsequence sequence seq1; c ##1 sub_seq1 ##1 (do1 == v1); // error because v1 is not visible endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence sub_seq2(lv); (a ##1 !a, lv = data_in) ##1 !b[*0:$] ##1 b && (data_out == lv); endsequence sequence seq2; int v1; c ##1 sub_seq2(v1) // v1 is bound to lv ##1 (do1 == v1); // v1 holds the value that was assigned to lv endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence seq2a; int v1; c ##1 sub_seq2(v1).triggered ##1 (do1 == v1); // v1 is now bound to lv endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence seq2b; int v1; c ##1 !sub_seq2(v1).triggered ##1 (do1 == v1); // v1 unassigned endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence sub_seq3(lv); int lv; // illegal because lv is a formal argument (a ##1 !a, lv = data_in) ##1 !b[*0:$] ##1 b && (data_out == lv); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s4; int x; (a ##1 (b, x = data) ##1 c) or (d ##1 (e==x)); // illegal endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s5; int x,y; ((a ##1 (b, x = data, y = data1) ##1 c) or (d ##1 (true, x = data) ##0 (e==x))) ##1 (y==data2); // illegal because y is not in the intersection endsequence sequence s6; int x,y; ((a ##1 (b, x = data, y = data1) ##1 c) or (d ##1 (true, x = data) ##0 (e==x))) ##1 (x==data2); // legal because x is in the intersection endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s7; int x,y; ((a ##1 (b, x = data, y = data1) ##1 c) and (d ##1 (true, x = data) ##0 (e==x))) ##1 (x==data2); // illegal because x is common to both threads endsequence sequence s8; int x,y; ((a ##1 (b, x = data, y = data1) ##1 c) and (d ##1 (true, x = data) ##0 (e==x))) ##1 (y==data2); // legal because y is in the difference endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s1; logic v, w; (a, v = e) ##1 (b[->1], w = f, $display("b after a with v = %h, w = %h\n", v, w)); endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"property p3; b ##1 c; endproperty c1: cover property (@(posedge clk) a #-# p3); a1: assert property (@(posedge clk) a |-> p3);"##, Ok((_, _)) ); test!( many1(module_item), r##"a1: assert property (@clk not a ##1 b);"##, Ok((_, _)) ); test!( many1(module_item), r##"a2: assert property (@clk not strong(a ##1 b));"##, Ok((_, _)) ); test!( many1(module_item), r##"let ready_exp = (irdy == 0) && ($fell(trdy) || $fell(stop)); property data_end; @(posedge mclk) $rose(data_phase) |-> ##[1:5] ready_exp; endproperty a1: assert property(data_end);"##, Ok((_, _)) ); test!( many1(module_item), r##"let data_end_exp = data_phase && ready_exp; property data_end_rule1; @(posedge mclk) data_end_exp |-> ##[1:2] $rose(frame) ##1 $rose(irdy); endproperty a2: assert property(data_end_rule1);"##, Ok((_, _)) ); test!( many1(module_item), r##"property data_end_rule2; @(posedge mclk) ##[1:2] $rose(frame) ##1 $rose(irdy); endproperty a3: assert property(data_end_rule2);"##, Ok((_, _)) ); test!( many1(module_item), r##"property write_to_addr; (write_en & data_valid) ##0 (write_en && (retire_address[0:4]==addr)) [*2] |-> ##[3:8] write_en && !data_valid &&(write_address[0:4]==addr); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property write_to_addr_nested; (write_en & data_valid) |-> (write_en && (retire_address[0:4]==addr)) [*2] |-> ##[3:8] write_en && !data_valid && (write_address[0:4]==addr); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p1; ##[0:5] done #-# always !rst; endproperty property p2; ##[0:5] done #=# always !rst; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p1; nexttime a; endproperty // the clock shall tick once more and a shall be true at the next clock tick. property p2; s_nexttime a; endproperty // as long as the clock ticks, a shall be true at each future clock tick // starting from the next clock tick property p3; nexttime always a; endproperty // the clock shall tick at least once more and as long as it ticks, a shall // be true at every clock tick starting from the next one property p4; s_nexttime always a; endproperty // if the clock ticks at least once more, it shall tick enough times for a to // be true at some point in the future starting from the next clock tick property p5; nexttime s_eventually a; endproperty // a shall be true sometime in the strict future property p6; s_nexttime s_eventually a; endproperty // if there are at least two more clock ticks, a shall be true at the second // future clock tick property p7; nexttime[2] a; endproperty // there shall be at least two more clock ticks, and a shall be true at the // second future clock tick property p8; s_nexttime[2] a; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"implicit_always: assert property(p);"##, Ok((_, _)) ); test!( many1(module_item), r##"initial explicit_always: assert property(always p);"##, Ok((_, _)) ); test!( many1(module_item), r##"initial a1: assume property( @(posedge clk) reset[*5] #=# always !reset); property p1; a ##1 b |=> always c; endproperty property p2; always [2:5] a; endproperty property p3; s_always [2:5] a; endproperty property p4; always [2:$] a; endproperty property p5; s_always [2:$] a; // Illegal endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p1; a until b; endproperty property p2; a s_until b; endproperty property p3; a until_with b; endproperty property p4; a s_until_with b; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p1; s_eventually a; endproperty property p2; s_eventually always a; endproperty property p3; always s_eventually a; endproperty property p4; eventually [2:5] a; endproperty property p5; s_eventually [2:5] a; endproperty //property p6; // eventually [2:$] a; // Illegal //endproperty property p7; s_eventually [2:$] a; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"assert property (@(clk) go ##1 get[*2] |-> reject_on(stop) put[->2]);"##, Ok((_, _)) ); test!( many1(module_item), r##"assert property (@(clk) go ##1 get[*2] |-> sync_reject_on(stop) put[->2]);"##, Ok((_, _)) ); test!( many1(module_item), r##"assert property (@(clk) go ##1 get[*2] |-> !stop throughout put[->2]);"##, Ok((_, _)) ); test!( many1(module_item), r##"property p; (accept_on(a) p1) and (reject_on(b) p2); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p; (accept_on(a) p1) or (reject_on(b) p2); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p; not (accept_on(a) p1); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p; accept_on(a) reject_on(b) p1; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p_delay(logic [1:0] delay); case (delay) 2'd0 : a && b; 2'd1 : a ##2 b; 2'd2 : a ##4 b; 2'd3 : a ##8 b; default: 0; // cause a failure if delay has x or z values endcase endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property prop_always(p); p and (1'b1 |=> prop_always(p)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p1(s,p); s |=> prop_always(p); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property prop_weak_until(p,q); q or (p and (1'b1 |=> prop_weak_until(p,q))); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p2(s,p,q); s |=> prop_weak_until(p,q); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property check_phase1; s1 |-> (phase1_prop and (1'b1 |=> check_phase2)); endproperty property check_phase2; s2 |-> (phase2_prop and (1'b1 |=> check_phase1)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property illegal_recursion_1(p); not prop_always(not p); endproperty property illegal_recursion_2(p); p and (1'b1 |=> not illegal_recursion_2(p)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property illegal_recursion_3(p); disable iff (b) p and (1'b1 |=> illegal_recursion_3(p)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property legal_3(p); disable iff (b) prop_always(p); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property illegal_recursion_4(p); p and (1'b1 |-> illegal_recursion_4(p)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property fibonacci1 (local input int a, b, n, int fib_sig); (n > 0) |-> ( (fib_sig == a) and (1'b1 |=> fibonacci1(b, a + b, n - 1, fib_sig)) ); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property fibonacci2 (int a, b, n, fib_sig); (n > 0) |-> ( (fib_sig == a) and (1'b1 |=> fibonacci2(b, a + b, n - 1, fib_sig)) ); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property p3(p, bit b, abort); (p and (1'b1 |=> p4(p, b, abort))); endproperty property p4(p, bit b, abort); accept_on(b) reject_on(abort) p3(p, b, abort); endproperty"##, Ok((_, _)) ); // TODO // stack overflow (pass with RUST_MIN_STACK=33554432) //test!( // many1(module_item), // r##"property check_write; // logic [0:127] expected_data; // local variable to sample model data // logic [3:0] tag; // local variable to sample tag // disable iff (reset) // ( // write_request && write_request_ack, // expected_data = model_data, // tag = write_request_ack_tag // ) // |=> // check_write_data_beat(expected_data, tag, 4'h0); // endproperty // property check_write_data_beat // ( // local input logic [0:127] expected_data, // local input logic [3:0] tag, i // ); // ( // (data_valid && (data_valid_tag == tag)) // || // (retry && (retry_tag == tag)) // )[->1] // |-> // ( // ( // (data_valid && (data_valid_tag == tag)) // |-> // (data == expected_data[i*8+:8]) // ) // and // ( // if (retry && (retry_tag == tag)) // ( // 1'b1 |=> check_write_data_beat(expected_data, tag, 4'h0) // ) // else if (!last_data_valid) // ( // 1'b1 |=> check_write_data_beat(expected_data, tag, i+4'h1) // ) // else // ( // ##1 (retry && (retry_tag == tag)) // |=> // check_write_data_beat(expected_data, tag, 4'h0) // ) // ) // ); // endproperty"##, // Ok((_, _)) //); test!( many1(module_item), r##"property rule1; @(posedge clk) a |-> b ##1 c ##1 d; endproperty property rule2; @(clkev) disable iff (e) a |-> not(b ##1 c ##1 d); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property rule3; @(posedge clk) a[*2] |-> ((##[1:3] c) or (d |=> e)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property rule4; @(posedge clk) a[*2] |-> ((##[1:3] c) and (d |=> e)); endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property rule5; @(posedge clk) a ##1 (b || c)[->1] |-> if (b) (##1 d |-> e) else // c f ; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property rule6(x,y); ##1 x |-> y; endproperty property rule5a; @(posedge clk) a ##1 (b || c)[->1] |-> if (b) rule6(d,e) else // c f ; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s1; a ##1 b; // unclocked sequence endsequence sequence s2; c ##1 d; // unclocked sequence endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence mult_s; @(posedge clk) a ##1 @(posedge clk1) s1 ##1 @(posedge clk2) s2; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"property mult_p1; @(posedge clk) a ##1 @(posedge clk1) s1 ##1 @(posedge clk2) s2; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property mult_p2; mult_s; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property mult_p3; @(posedge clk) a ##1 @(posedge clk1) s1 |=> @(posedge clk2) s2; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property mult_p6; mult_s |=> mult_s; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property mult_p7; @(posedge clk) a ##1 b |-> c ##1 @(posedge clk1) d; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property mult_p8; @(posedge clk) a ##1 b |-> if (c) (1 |=> @(posedge clk1) d) else e ##1 @(posedge clk2) f ; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence e1(a,b,c); @(posedge clk) $rose(a) ##1 b ##1 c ; endsequence sequence e2; @(posedge sysclk) reset ##1 inst ##1 e1(ready,proc1,proc2).matched [->1] ##1 branch_back; endsequence"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence e1; @(posedge sysclk) $rose(a) ##1 b ##1 c; endsequence sequence e2; @(posedge sysclk) reset ##1 inst ##1 e1.triggered ##1 branch_back; endsequence sequence e3; @(posedge clk) reset1 ##1 e1.matched ##1 branch_back1; endsequence sequence e2_with_arg(sequence subseq); @(posedge sysclk) reset ##1 inst ##1 subseq.triggered ##1 branch_back; endsequence sequence e4; e2_with_arg(@(posedge sysclk) $rose(a) ##1 b ##1 c); endsequence program check; initial begin wait (e1.triggered || e2.triggered); if (e1.triggered) $display("e1 passed"); if (e2.triggered) $display("e2 passed"); end endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"module mod_sva_checks; logic a, b, c, d; logic clk_a, clk_d, clk_e1, clk_e2; logic clk_c, clk_p; clocking cb_prog @(posedge clk_p); endclocking clocking cb_checker @(posedge clk_c); endclocking default clocking cb @(posedge clk_d); endclocking sequence e4; $rose(b) ##1 c; endsequence // e4 infers posedge clk_a as per clock flow rules a1: assert property (@(posedge clk_a) a |=> e4.triggered); sequence e5; // e4 will infer posedge clk_e1 as per clock flow rules // wherever e5 is instantiated (with/without a method) @(posedge clk_e1) a ##[1:3] e4.triggered ##1 c; endsequence // e4, used in e5, infers posedge clk_e1 from e5 a2: assert property (@(posedge clk_a) a |=> e5.matched); sequence e6(f); @(posedge clk_e2) f; endsequence // e4 infers posedge clk_e2 as per clock flow rules a3: assert property (@(posedge clk_a) a |=> e6(e4.triggered)); sequence e7; e4 ##1 e6(d); endsequence // Leading clock of e7 is posedge clk_a as per clock flow rules a4: assert property (@(posedge clk_a) a |=> e7.triggered); // Illegal use in a disable condition, e4 is not explicitly clocked a5_illegal: assert property ( @(posedge clk_a) disable iff (e4.triggered) a |=> b); always @(posedge clk_a) begin // e4 infers default clocking cb and not posedge clk_a as there is // more than one event control in this procedure (16.14.6) @(e4); d = a; end program prog_e4; default clocking cb_prog; initial begin // e4 infers default clocking cb_prog wait (e4.triggered); $display("e4 passed"); end endprogram : prog_e4 checker check(input in1, input sequence s_f); default clocking cb_checker; always @(s_f) $display("sequence triggered"); a4: assert property (a |=> in1); endchecker : check // e4 infers checker's default clocking cb_checker check c1(e4.triggered, e4); // e4 connected to port of a module instance infers default clocking cb mod_adder ai1(e4.triggered); endmodule : mod_sva_checks"##, Ok((_, _)) ); test!( many1(module_item), r##"property p; logic v = e; (@(posedge clk1) (a == v)[*1:$] |-> b) and (@(posedge clk2) c[*1:$] |-> d == v) ; endproperty a1: assert property (@(posedge clk) f |=> p);"##, Ok((_, _)) ); test!( many1(module_item), r##"property p; logic v; (@(posedge clk1) (1, v = e) ##0 (a == v)[*1:$] |-> b) and (@(posedge clk2) (1, v = e) ##0 c[*1:$] |-> d == v) ; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property abc(a, b, c); disable iff (a==2) @(posedge clk) not (b ##1 c); endproperty env_prop: assert property (abc(rst, in1, in2)) $display("env_prop passed."); else $display("env_prop failed.");"##, Ok((_, _)) ); test!( many1(module_item), r##"property abc(a, b, c); disable iff (c) @(posedge clk) a |=> b; endproperty env_prop: assume property (abc(req, gnt, rst)) else $error("Assumption failed.");"##, Ok((_, _)) ); test!( many1(module_item), r##"a1:assume property ( @(posedge clk) req dist {0:=40, 1:=60} ) ; property proto ; @(posedge clk) req |-> req[*1:$] ##0 ack; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"a1_assertion:assert property ( @(posedge clk) req inside {0, 1} ) ; property proto_assertion ; @(posedge clk) req |-> req[*1:$] ##0 ack; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property pr1; @(posedge clk) !reset_n |-> !req; // when reset_n is asserted (0), // keep req 0 endproperty property pr2; @(posedge clk) ack |=> !req; // one cycle after ack, req // must be deasserted endproperty property pr3; @(posedge clk) req |-> req[*1:$] ##0 ack; // hold req asserted until // and including ack asserted endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"property pa1; @(posedge clk) !reset_n || !req |-> !ack; endproperty property pa2; @(posedge clk) ack |=> !ack; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"a1:assume property (@(posedge clk) req dist {0:=40, 1:=60} ); assume_req1:assume property (pr1); assume_req2:assume property (pr2); assume_req3:assume property (pr3); assert_ack1:assert property (pa1) else $error("ack asserted while req is still deasserted"); assert_ack2:assert property (pa2) else $error("ack is extended over more than one cycle");"##, Ok((_, _)) ); test!( many1(module_item), r##"restrict property (@(posedge clk) ctr == '0);"##, Ok((_, _)) ); test!( many1(module_item), r##"module top(input logic clk); logic a,b,c; property rule3; @(posedge clk) a |-> b ##1 c; endproperty a1: assert property (rule3); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module top(input logic clk); logic a,b,c; sequence seq3; @(posedge clk) b ##1 c; endsequence c1: cover property (seq3); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"property rule; a ##1 b ##1 c; endproperty always @(posedge clk) begin assert property (rule); end"##, Ok((_, _)) ); test!( many1(module_item), r##"property r1; q != d; endproperty always @(posedge mclk) begin q <= d1; r1_p1: assert property (r1); r1_p2: assert property (@(posedge scanclk)r1); end"##, Ok((_, _)) ); test!( many1(module_item), r##"property r2; q != d; endproperty always_ff @(posedge clock iff reset == 0 or posedge reset) begin cnt <= reset ? 0 : cnt + 1; q <= $past(d1); r2_p: assert property (r2); end"##, Ok((_, _)) ); test!( many1(module_item), r##"property r3; q != d; endproperty always_ff @(clock iff reset == 0 or posedge reset) begin cnt <= reset ? 0 : cnt + 1; q <= $past(d1); // no inferred clock r3_p: assert property (r3); // no inferred clock end"##, Ok((_, _)) ); test!( many1(module_item), r##"property r4; q != d; endproperty always @(posedge mclk) begin #10 q <= d1; // delay prevents clock inference @(negedge mclk) // event control prevents clock inference #10 q1 <= !d1; r4_p: assert property (r4); // no inferred clock end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) begin int i = 10; for (i=0; i<10; i++) begin a1: assert property (foo[i] && bar[i]); a2: assert property (foo[const'(i)] && bar[i]); a3: assert property (foo[const'(i)] && bar[const'(i)]); end end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking @(posedge clk); endclocking generate for (genvar i=0; i<10; i++) begin a1: assert property (foo[10] && bar[10]); a2: assert property (foo[i] && bar[10]); a3: assert property (foo[i] && bar[i]); end endgenerate"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) begin // variable declared in for statement is automatic (see 12.7.1) for (int i=0; i<10; i++) begin a4: assert property (foo[i] && bar[i]); a5: assert property (foo[const'(i)] && bar[i]); a6: assert property (foo[const'(i)] && bar[const'(i)]); end end"##, Ok((_, _)) ); test!( many1(module_item), r##"wire w; always @(posedge clk) begin : procedural_block_1 if (my_activation_condition == 1) begin for (int i=0; i<2; i++) begin a7: assume property (foo[i] |=> bar[i] ##1 (w==1'b1)); end end end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) begin int i = 10; for (i=0; i<10; i++) begin a8: assert property (foo[const'(i)] && bar[i]) else $error("a8 failed for const i=%d and i=%d", const'(i), $sampled(i)); end end"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) begin if (en) begin a9: assert property (p1(a,b,c)); end if ($sampled(en)) begin a10: assert property (p1(a,b,c)); end end"##, Ok((_, _)) ); test!( many1(module_item), r##"assign not_a = !a; default clocking @(posedge clk); endclocking always_comb begin : b1 // Probably better to not use consts in this example // ...but using them to illustrate effects of flushing method a1: assert property (const'(not_a) != const'(a)); end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking @(posedge clk); endclocking always @(a or b) begin : b1 a2: assert property (a == b) r.success(0); else r.error(0, a, b); #1; a3: assert property (a == b) r.success(1); else r.error(1, a, b); end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking @(posedge clk); endclocking always_comb begin : b1 c1: cover property (const'(b) != const'(a)); end"##, Ok((_, _)) ); test!( many1(module_item), r##"always_comb begin : procedural_block_1 if (en) foo = bar; end always_comb begin : procedural_block_2 p1: assert property ( @(posedge clk) (const'(foo) == const'(bar)) ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking @(posedge clk); endclocking always @(bad_val or bad_val_ok) begin : b1 a1: assert property (bad_val) else $fatal(1, "Sorry"); if (bad_val_ok) begin disable a1; end end"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking @(posedge clk); endclocking always @(a or b or c) begin : b2 if (c == 8'hff) begin a2: assert property (a && b); end else begin a3: assert property (a || b); end end always @(clear_b2) begin : b3 disable b2; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module m(logic a, b, c, d, rst1, clk1, clk2); logic rst; default clocking @(negedge clk1); endclocking default disable iff rst1; property p_triggers(start_event, end_event, form, clk = $inferred_clock, rst = $inferred_disable); @clk disable iff (rst) (start_event ##0 end_event[->1]) |=> form; endproperty property p_multiclock(clkw, clkx = $inferred_clock, clky, w, x, y, z); @clkw w ##1 @clkx x |=> @clky y ##1 z; endproperty a1: assert property (p_triggers(a, b, c)); a2: assert property (p_triggers(a, b, c, posedge clk1, 1'b0) ); always @(posedge clk2 or posedge rst) begin end a4: assert property(p_multiclock(negedge clk2, , posedge clk1, a, b, c, d) ); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m(logic a, b, c, d, rst1, clk1, clk2); logic rst; a1: assert property (@(negedge clk1) disable iff (rst1) a ##0 b[->1] |=> c); a2: assert property (@(posedge clk1) disable iff (1'b0) a ##0 b[->1] |=> c); always @(posedge clk2 or posedge rst) begin end a3: assert property ( @(posedge clk2) disable iff (rst1) (a ##0 b[->1]) |=> c ); a4: assert property (@(negedge clk2) a ##1 @(negedge clk1) b |=> @(posedge clk1) c ##1 d); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m1; bit clk, rst1; default disable iff rst1; a1: assert property (@(posedge clk) p1); // property p1 is // defined elsewhere module m2; bit rst2; a2: assert property (@(posedge clk) p2); // property p2 is // defined elsewhere endmodule endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m1; bit clk, rst1; default disable iff rst1; a1: assert property (@(posedge clk) p1); // property p1 is // defined elsewhere module m2; bit rst2; default disable iff rst2; a2: assert property (@(posedge clk) p2); // property p2 is // defined elsewhere endmodule endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module examples_with_default (input logic a, b, clk, rst, rst1); default disable iff rst; property p1; disable iff (rst1) a |=> b; endproperty // Disable condition is rst1 - explicitly specified within a1 a1 : assert property (@(posedge clk) disable iff (rst1) a |=> b); // Disable condition is rst1 - explicitly specified within p1 a2 : assert property (@(posedge clk) p1); // Disable condition is rst - no explicit specification, inferred from // default disable iff declaration a3 : assert property (@(posedge clk) a |=> b); // Disable condition is 1'b0. This is the only way to // cancel the effect of default disable. a4 : assert property (@(posedge clk) disable iff (1'b0) a |=> b); endmodule module examples_without_default (input logic a, b, clk, rst); property p2; disable iff (rst) a |=> b; endproperty // Disable condition is rst - explicitly specified within a5 a5 : assert property (@(posedge clk) disable iff (rst) a |=> b); // Disable condition is rst - explicitly specified within p2 a6 : assert property (@ (posedge clk) p2); // No disable condition a7 : assert property (@ (posedge clk) a |=> b); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"sequence s2; @(posedge clk) a ##2 b; endsequence property p2; not s2; endproperty assert property (p2);"##, Ok((_, _)) ); test!( many1(module_item), r##"property p3; @(posedge clk) not (a ##2 b); endproperty assert property (p3);"##, Ok((_, _)) ); test!( many1(module_item), r##"always @(posedge clk) assert property (not (a ##2 b));"##, Ok((_, _)) ); test!( many1(module_item), r##"clocking master_clk @(posedge clk); property p3; not (a ##2 b); endproperty endclocking assert property (master_clk.p3);"##, Ok((_, _)) ); test!( many1(module_item), r##"default clocking master_clk ; // master clock as defined above property p4; (a ##2 b); endproperty assert property (p4);"##, Ok((_, _)) ); test!( many1(module_item), r##"module examples_with_default (input logic a, b, c, clk); property q1; $rose(a) |-> ##[1:5] b; endproperty property q2; @(posedge clk) q1; endproperty default clocking posedge_clk @(posedge clk); property q3; $fell(c) |=> q1; // legal: q1 has no clocking event endproperty property q4; $fell(c) |=> q2; // legal: q2 has clocking event identical to that of // the clocking block endproperty sequence s1; @(posedge clk) b[*3]; // illegal: explicit clocking event in clocking block endsequence endclocking property q5; @(negedge clk) b[*3] |=> !b; endproperty always @(negedge clk) begin a1: assert property ($fell(c) |=> q1); // legal: contextually inferred leading clocking event, // @(negedge clk) a2: assert property (posedge_clk.q4); // legal: will be queued (pending) on negedge clk, then // (if matured) checked at next posedge clk (see 16.14.6) a3: assert property ($fell(c) |=> q2); // illegal: multiclocked property with contextually // inferred leading clocking event a4: assert property (q5); // legal: contextually inferred leading clocking event, // @(negedge clk) end property q6; q1 and q5; endproperty a5: assert property (q6); // illegal: default leading clocking event, @(posedge clk), // but semantic leading clock is not unique a6: assert property ($fell(c) |=> q6); // legal: default leading clocking event, @(posedge clk), // is the unique semantic leading clock sequence s2; $rose(a) ##[1:5] b; endsequence c1: cover property (s2); // legal: default leading clocking event, @(posedge clk) c2: cover property (@(negedge clk) s2); // legal: explicit leading clocking event, @(negedge clk) endmodule module examples_without_default (input logic a, b, c, clk); property q1; $rose(a) |-> ##[1:5] b; endproperty property q5; @(negedge clk) b[*3] |=> !b; endproperty property q6; q1 and q5; endproperty a5: assert property (q6); // illegal: no leading clocking event a6: assert property ($fell(c) |=> q6); // illegal: no leading clocking event sequence s2; $rose(a) ##[1:5] b; endsequence c1: cover property (s2); // illegal: no leading clocking event c2: cover property (@(negedge clk) s2); // legal: explicit leading clocking event, @(negedge clk) sequence s3; @(negedge clk) s2; endsequence c3: cover property (s3); // legal: leading clocking event, @(negedge clk), // determined from declaration of s3 c4: cover property (s3 ##1 b); // illegal: no default, inferred, or explicit leading // clocking event and maximal property is not an instance endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"wire clk1, clk2; logic a, b; assign clk2 = clk1; a1: assert property (@(clk1) a and @(clk2) b); // Illegal a2: assert property (@(clk1) a and @(clk1) b); // OK always @(posedge clk1) begin a3: assert property(a and @(posedge clk2) b); //Illegal a4: assert property(a and @(posedge clk1) b); // OK end"##, Ok((_, _)) ); test!( many1(module_item), r##"program tst; initial begin # 200ms; expect( @(posedge clk) a ##1 b ##1 c ) else $error( "expect failed" ); end endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"integer data; task automatic wait_for( integer value, output bit success ); expect( @(posedge clk) ##[1:10] data == value ) success = 1; else success = 0; endtask initial begin bit ok; wait_for( 23, ok ); // wait for the value 23 end"##, Ok((_, _)) ); test!( many1(module_item), r##"module A; logic a, clk; clocking cb_with_input @(posedge clk); input a; property p1; a; endproperty endclocking clocking cb_without_input @(posedge clk); property p1; a; endproperty endclocking property p1; @(posedge clk) a; endproperty property p2; @(posedge clk) cb_with_input.a; endproperty a1: assert property (p1); a2: assert property (cb_with_input.p1); a3: assert property (p2); a4: assert property (cb_without_input.p1); endmodule"##, Ok((_, _)) ); } #[test] fn clause17() { test!( many1(module_item), r##"checker my_check1 (logic test_sig, event clock); default clocking @clock; endclocking property p(logic sig); a; endproperty a1: assert property (p (test_sig)); c1: cover property (!test_sig ##1 test_sig); endchecker : my_check1"##, Ok((_, _)) ); test!( many1(module_item), r##"checker my_check2 (logic a, b); a1: assert #0 ($onehot0({a, b})); c1: cover #0 (a == 0 && b == 0); c2: cover #0 (a == 1); c3: cover #0 (b == 1); endchecker : my_check2"##, Ok((_, _)) ); test!( many1(module_item), r##"checker my_check3 (logic a, b, event clock, output bit failure, undef); default clocking @clock; endclocking a1: assert property ($onehot0({a, b})) failure = 1'b0; else failure = 1'b1; a2: assert property ($isunknown({a, b})) undef = 1'b0; else undef = 1'b1; endchecker : my_check3"##, Ok((_, _)) ); test!( many1(module_item), r##"checker my_check4 (input logic in, en = 1'b1, // default value event clock, output int ctr = 0); // initial value default clocking @clock; endclocking always_ff @clock if (en && in) ctr <= ctr + 1; a1: assert property (ctr < 5); endchecker : my_check4"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; default clocking @clk1; endclocking default disable iff rst1; checker c1; // Inherits @clk1 and rst1 endchecker : c1 checker c2; // Explicitly redefines its default values default clocking @clk2; endclocking default disable iff rst2; endchecker : c2 endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"checker mutex (logic [31:0] sig, event clock, output bit failure); assert property (@clock $onehot0(sig)) failure = 1'b0; else failure = 1'b1; endchecker : mutex module m(wire [31:0] bus, logic clk); logic res, scan; // ... mutex check_bus(bus, posedge clk, res); always @(posedge clk) scan <= res; endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"checker c1(event clk, logic[7:0] a, b); logic [7:0] sum; always_ff @(clk) begin sum <= a + 1'b1; p0: assert property (sum < MAX_SUM); end p1: assert property (@clk sum < MAX_SUM); p2: assert property (@clk a != b); p3: assert #0 ($onehot(a)); endchecker module m(input logic rst, clk, logic en, logic[7:0] in1, in2, in_array [20:0]); c1 check_outside(posedge clk, in1, in2); always @(posedge clk) begin automatic logic [7:0] v1=0; if (en) begin // v1 is automatic, so current procedural value is used c1 check_inside(posedge clk, in1, v1); end for (int i = 0; i < 4; i++) begin v1 = v1+5; if (i != 2) begin // v1 is automatic, so current procedural value is used c1 check_loop(posedge clk, in1, in_array[v1]); end end end endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"checker check_in_context (logic test_sig, event clock = $inferred_clock, logic reset = $inferred_disable); property p(logic sig); a; endproperty a1: assert property (@clock disable iff (reset) p(test_sig)); c1: cover property (@clock !reset throughout !test_sig ##1 test_sig); endchecker : check_in_context module m(logic rst); wire clk; logic a, en; wire b = a && en; // No context inference check_in_context my_check1(.test_sig(b), .clock(clk), .reset(rst)); always @(posedge clk) begin if (en) begin // inferred from context: // .clock(posedge clk) // .reset(1'b0) check_in_context my_check2(a); end end endmodule : m"##, Ok((_, _)) ); test!( many1(module_item), r##"checker check(logic a, b, c, clk, rst); logic x, y, z, v, t; assign x = a; // current value of a always_ff @(posedge clk or negedge rst) // current values of clk and rst begin a1: assert (b); // sampled value of b if (rst) // current value of rst z <= b; // sampled value of b else z <= !c; // sampled value of c end always_comb begin a2: assert (b); // current value of b if (a) // current value of a v = b; // current value of b else v = !b; // current value of b end always_latch begin a3: assert (b); // current value of b if (clk) // current value of clk t <= b; // current value of b end // ... endchecker : check"##, Ok((_, _)) ); test!( many1(module_item), r##"checker clocking_example (logic sig1, sig2, default_clk, rst, event e1, e2, e3 ); bit local_sig; default clocking @(posedge default_clk); endclocking always_ff @(e1) begin: p1_block p1a: assert property (sig1 == sig2); p1b: assert property (@(e1) (sig1 == sig2)); end always_ff @(e2 or e3) begin: p2_block local_sig <= rst; p2a: assert property (sig1 == sig2); p2b: assert property (@(e2) (sig1 == sig2)); end always_ff @(rst or e3) begin: p3_block local_sig <= rst; p3a: assert property (sig1 == sig2); p3b: assert property (@(e3) (sig1 == sig2)); end endchecker clocking_example c1 (s1, s2, default_clk, rst, posedge clk1 or posedge clk2, posedge clk1, negedge rst);"##, Ok((_, _)) ); test!( many1(module_item), r##"checker my_check(logic clk, active); bit active_d1 = 1'b0; always_ff @(posedge clk) begin active_d1 <= active; end covergroup cg_active @(posedge clk); cp_active : coverpoint active { bins idle = { 1'b0 }; bins active = { 1'b1 }; } cp_active_d1 : coverpoint active_d1 { bins idle = { 1'b0 }; bins active = { 1'b1 }; } option.per_instance = 1; endgroup cg_active cg_active_1 = new(); endchecker : my_check"##, Ok((_, _)) ); test!( many1(module_item), r##"checker op_test (logic clk, vld_1, vld_2, logic [3:0] opcode); bit [3:0] opcode_d1; always_ff @(posedge clk) opcode_d1 <= opcode; covergroup cg_op; cp_op : coverpoint opcode_d1; endgroup: cg_op cg_op cg_op_1 = new(); sequence op_accept; @(posedge clk) vld_1 ##1 (vld_2, cg_op_1.sample()); endsequence cover property (op_accept); endchecker"##, Ok((_, _)) ); test!( many1(module_item), r##"checker op_test (logic clk, vld_1, vld_2, logic [3:0] opcode); bit [3:0] opcode_d1; always_ff @(posedge clk) opcode_d1 <= opcode; covergroup cg_op with function sample(bit [3:0] opcode_d1); cp_op : coverpoint opcode_d1; endgroup: cg_op cg_op cg_op_1 = new(); sequence op_accept; @(posedge clk) vld_1 ##1 (vld_2, cg_op_1.sample(opcode_d1)); endsequence cover property (op_accept); endchecker"##, Ok((_, _)) ); test!( many1(module_item), r##"checker counter_model(logic flag); bit [2:0] counter = '0; always_ff @($global_clock) counter <= counter + 1'b1; assert property (@($global_clock) counter == 0 |-> flag); endchecker : counter_model"##, Ok((_, _)) ); test!( many1(module_item), r##"checker observer_model(bit valid, reset); default clocking @($global_clock); endclocking rand bit flag; m1: assume property (reset |=> !flag); m2: assume property (!reset && flag |=> flag); m3: assume property ($rising_gclk(flag) |-> valid); endchecker : observer_model"##, Ok((_, _)) ); test!( many1(module_item), r##"checker reason_about_one_bit(bit [63:0] data1, bit [63:0] data2, event clock); rand const bit [5:0] idx; a1: assert property (@clock data1[idx] == data2[idx]); endchecker : reason_about_one_bit"##, Ok((_, _)) ); test!( many1(module_item), r##"checker reason_about_all_bit(bit [63:0] data1, bit [63:0] data2, event clock); a1: assert property (@clock data1 == data2); endchecker : reason_about_all_bit"##, Ok((_, _)) ); test!( many1(module_item), r##"checker data_legal(start_ev, end_ev, in_data, out_data); rand const bit [$bits(in_data)-1:0] mem_data; sequence transaction; start_ev && (in_data == mem_data) ##1 end_ev[->1]; endsequence a1: assert property (@clock transaction |-> out_data == mem_data); endchecker : data_legal"##, Ok((_, _)) ); test!( many1(module_item), r##"checker data_legal_with_loc(start_ev, end_ev, in_data, out_data); sequence transaction (loc_var); (start_ev, loc_var = in_data) ##1 end_ev[->1]; endsequence property data_legal; bit [$bits(in_data)-1:0] mem_data; transaction(mem_data) |-> out_data == mem_data; endproperty a1: assert property (@clock data_legal); endchecker : data_legal_with_loc"##, Ok((_, _)) ); test!( many1(module_item), r##"checker check; bit a; endchecker module m; check my_check; wire x = my_check.a; // Illegal bit y; always @(posedge clk) begin my_check.a = y; // Illegal end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"checker check1(bit a, b, event clk); rand bit x, y, z, v; assign x = a & b; // Illegal always_comb y = a & b; // Illegal always_ff @clk z <= a & b; // OK endchecker : check1"##, Ok((_, _)) ); test!( many1(module_item), r##"module my_mod(); bit mclk, v1, v2; checker c1(bit fclk, bit a, bit b); default clocking @ (posedge fclk); endclocking checker c2(bit bclk, bit x, bit y); default clocking @ (posedge bclk); endclocking rand bit m, n; u1: assume property (f1(x,m)); u2: assume property (f2(y,n)); endchecker rand bit q, r; c2 B1(fclk, q+r, r); always_ff @ (posedge fclk) r <= a || q; // assignment makes r inactive u3: assume property (f3(a, q)); u4: assume property (f4(b, r)); endchecker c1 F1(mclk, v1, const'(v2)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"checker my_check; sequence s; a; endsequence always_ff @clk a <= s.triggered; endchecker"##, Ok((_, _)) ); test!( many1(module_item), r##"checker check(bit clk1); // clk1 assigned in the Active region rand bit v, w; assign clk2 = clk1; m1: assume property (@clk1 !(v && w)); m2: assume property (@clk2 v || w); a1: assert property (@clk1 v != w); // ... endchecker : check"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum { cover_none, cover_all } coverage_level; checker assert_window1 ( logic test_expr, // Expression to be true in the window untyped start_event, // Window opens at the completion of the start_event untyped end_event, // Window closes at the completion of the end_event event clock = $inferred_clock, logic reset = $inferred_disable, string error_msg = "violation", coverage_level clevel = cover_all // This argument should be bound to an // elaboration time constant expression ); default clocking @clock; endclocking default disable iff reset; bit window = 1'b0, next_window = 1'b1; // Compute next value of window always_comb begin if (reset || window && end_event) next_window = 1'b0; else if (!window && start_event) next_window = 1'b1; else next_window = window; end always_ff @clock window <= next_window; property p_window; start_event && !window |=> test_expr[+] ##0 end_event; endproperty a_window: assert property (p_window) else $error(error_msg); generate if (clevel != cover_none) begin : cover_b cover_window_open: cover property (start_event && !window) $display("window_open covered"); cover_window: cover property ( start_event && !window ##1 (!end_event && window) [*] ##1 end_event && window ) $display("window covered"); end : cover_b endgenerate endchecker : assert_window1"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum { cover_none, cover_all } coverage_level; checker assert_window2 ( logic test_expr, // Expression to be true in the window sequence start_event, // Window opens at the completion of the start_event sequence end_event, // Window closes at the completion of the end_event event clock = $inferred_clock, logic reset = $inferred_disable, string error_msg = "violation", coverage_level clevel = cover_all // This argument should be bound to an // elaboration time constant expression ); default clocking @clock; endclocking default disable iff reset; bit window = 0; let start_flag = start_event.triggered; let end_flag = end_event.triggered; // Compute next value of window function bit next_window (bit win); if (reset || win && end_flag) return 1'b0; if (!win && start_flag) return 1'b1; return win; endfunction always_ff @clock window <= next_window(window); property p_window; start_flag && !window |=> test_expr[+] ##0 end_flag; endproperty a_window: assert property (p_window) else $error(error_msg); generate if (clevel != cover_none) begin : cover_b cover_window_open: cover property (start_flag && !window) $display("window_open covered"); cover_window: cover property ( start_flag && !window ##1 (!end_flag && window) [*] ##1 end_flag && window ) $display("window covered"); end : cover_b endgenerate endchecker : assert_window2"##, Ok((_, _)) ); } #[test] fn clause18() { test!( many1(module_item), r##"class Bus; rand bit[15:0] addr; rand bit[31:0] data; constraint word_align {addr[1:0] == 2'b0;} endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin Bus bus = new; repeat (50) begin if ( bus.randomize() == 1 ) $display ("addr = %16h data = %h\n", bus.addr, bus.data); else $display ("Randomization failed.\n"); end end"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum {low, mid, high} AddrType; class MyBus extends Bus; rand AddrType atype; constraint addr_range { (atype == low ) -> addr inside { [0 : 15] }; (atype == mid ) -> addr inside { [16 : 127]}; (atype == high) -> addr inside {[128 : 255]}; } endclass"##, Ok((_, _)) ); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"task exercise_bus (MyBus bus); // int res; // // EXAMPLE 1: restrict to low addresses // res = bus.randomize() with {atype == low;}; // // EXAMPLE 2: restrict to address between 10 and 20 // res = bus.randomize() with {10 <= addr && addr <= 20;}; // // EXAMPLE 3: restrict data values to powers-of-two // res = bus.randomize() with {(data & (data - 1)) == 0;}; // endtask"##, // Ok((_, _)) //); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"task exercise_illegal(MyBus bus, int cycles); // int res; // // Disable word alignment constraint. // bus.word_align.constraint_mode(0); // repeat (cycles) begin // // CASE 1: restrict to small addresses. // res = bus.randomize() with {addr[0] || addr[1];}; // end // // Reenable word alignment constraint // bus.word_align.constraint_mode(1); // endtask"##, // Ok((_, _)) //); test!( many1(module_item), r##"class XYPair; rand integer x, y; endclass class MyXYPair extends XYPair; function void pre_randomize(); super.pre_randomize(); $display("Before randomize x=%0d, y=%0d", x, y); endfunction function void post_randomize(); super.post_randomize(); $display("After randomize x=%0d, y=%0d", x, y); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class packet; typedef struct { randc int addr = 1 + constant; int crc; rand byte data [] = {1,2,3,4}; } header; rand header h1; endclass packet p1=new;"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef enum bit [1:0] { A=2'b00, B=2'b11 } ab_e; typedef struct packed { ab_e ValidAB; } VStructEnum; typedef union packed { ab_e ValidAB; } VUnionEnum;"##, Ok((_, _)) ); test!( many1(module_item), r##"class C; rand int x; constraint proto1; // implicit form extern constraint proto2; // explicit form endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"virtual class D; pure constraint Test; endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class c; rand integer x, y, z; constraint c1 {x inside {3, 5, [9:15], [24:32], [y:2*y], z};} rand integer a, b, c; constraint c2 {a inside {b, c};} integer fives[4] = '{ 5, 10, 15, 20 }; rand integer v; constraint c3 { v inside {fives}; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class c; rand byte a[5]; rand byte b; rand byte excluded; constraint u { unique {b, a[2:3], excluded}; } constraint exclusion { excluded == 5; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class c; rand bit [3:0] a, b; constraint c { (a == 0) -> (b == 1); } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class C; rand byte A[] ; constraint C1 { foreach ( A [ i ] ) A[i] inside {2,4,8,16}; } constraint C2 { foreach ( A [ j ] ) A[j] > 2 * j; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class C; rand int A[] ; constraint c1 { A.size inside {[1:10]}; } constraint c2 { foreach ( A[ k ] ) (k < A.size - 1) -> A[k + 1] > A[k]; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class C; rand bit [7:0] A[] ; constraint c1 { A.size == 5; } constraint c2 { A.sum() with (int'(item)) < 1000; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class A; // leaf node rand bit [7:0] v; endclass class B extends A; // heap node rand A left; rand A right; constraint heapcond {left.v <= v; right.v > v;} endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class B; rand bit s; rand bit [31:0] d; constraint c { s -> d == 0; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class B; rand bit s; rand bit [31:0] d; constraint c { s -> d == 0; } constraint order { solve s before d; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"function int count_ones ( bit [9:0] w ); for( count_ones = 0; w != 0; w = w >> 1 ) count_ones += w & 1'b1; endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"class B; rand int x, y; constraint C { x <= F(y); } constraint D { y inside { 2, 4, 8 } ; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class SList; rand int n; rand Slist next; constraint sort { n < next.n; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class D; int x; endclass class C; rand int x, y; D a, b; constraint c1 { (x < y || a.x > b.x || a.x == 5 ) -> x+y == 10; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class D; int x; endclass class C; rand int x, y; D a, b; constraint c1 { (x < y && a.x > b.x && a.x == 5 ) -> x+y == 10; } endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class D; int x; endclass class C; rand int x, y; D a, b; constraint c1 { (x < y && (a.x > b.x || a.x ==5)) -> x+y == 10; } endclass"##, Ok((_, _)) ); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"class Packet; // rand bit mode; // rand int length; // constraint deflt { // soft length inside {32,1024}; // soft mode -> length == 1024; // // Note: soft mode -> {length == 1024;} is not legal syntax, // // as soft must be followed by an expression // } // endclass // initial begin // Packet p = new(); // p.randomize() with { length == 1512;} // mode will randomize to 0 // p.randomize() with { length == 1512; mode == 1;} // mode will randomize to 1 // end"##, // Ok((_, _)) //); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"class B1; // rand int x; // constraint a { soft x > 10 ; soft x < 100 ; } // endclass /* a1 */ /* a2 */ // class D1 extends B1; // constraint b { soft x inside {[5:9]} ; } // endclass /* b1 */ // class B2; // rand int y; // constraint c { soft y > 10 ; } // endclass /* c1 */ // class D2 extends B2; // constraint d { soft y inside {[5:9]} ; } // constraint e ; /* d1 */ // rand D1 p1; // rand B1 p2; // rand D1 p3; // constraint f { soft p1.x < p2.x ; } // endclass /* f1 */ // constraint D2::e { soft y > 100 ; } // /* e1 */ // D2 d = new(); // initial begin // d.randomize() with { soft y inside {10,20,30} ; soft y < p1.x ; }; // end /* i1 */ /* i2 */"##, // Ok((_, _)) //); test!( many1(module_item), r##"class A; rand int x; constraint A1 { soft x == 3; } constraint A2 { disable soft x; } // discard soft constraints constraint A3 { soft x inside { 1, 2 }; } endclass initial begin A a = new(); a.randomize(); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class B; rand int x; constraint B1 { soft x == 5; } constraint B2 { disable soft x; soft x dist {5, 8};} endclass initial begin B b = new(); b.randomize(); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class B; rand int x; constraint B1 { soft x == 5; } constraint B3 { soft x dist {5, 8}; } endclass initial begin B b = new(); b.randomize(); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class SimpleSum; rand bit [7:0] x, y, z; constraint c {z == x + y;} endclass"##, Ok((_, _)) ); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"class SimpleSum; // rand bit [7:0] x, y, z; // constraint c {z == x + y;} // endclass // task InlineConstraintDemo(SimpleSum p); // int success; // success = p.randomize() with {x < y;}; // endtask"##, // Ok((_, _)) //); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"class C1; // rand integer x; // endclass // class C2; // integer x; // integer y; // task doit(C1 f, integer x, integer z); // int result; // result = f.randomize() with {x < y + z;}; // endtask // endclass"##, // Ok((_, _)) //); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"class C; // rand integer x; // endclass // function int F(C obj, integer y); // F = obj.randomize() with (x) { x < y; }; // endfunction"##, // Ok((_, _)) //); // TODO // randomize is not keyword //test!( // many1(module_item), // r##"class C; // rand integer x; // endclass // function int F(C obj, integer x); // F = obj.randomize() with { x < local::x; }; // endfunction"##, // Ok((_, _)) //); test!( many1(module_item), r##"class Packet; rand integer source_value, dest_value; endclass initial begin int ret; Packet packet_a = new; // Turn off all variables in object packet_a.rand_mode(0); // ... other code // Enable source_value packet_a.source_value.rand_mode(1); ret = packet_a.dest_value.rand_mode(); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet; rand integer source_value; constraint filter1 { source_value > 2 * m; } endclass function integer toggle_rand( Packet p ); if ( p.filter1.constraint_mode() ) p.filter1.constraint_mode(0); else p.filter1.constraint_mode(1); toggle_rand = p.randomize(); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"class CA; rand byte x, y; byte v, w; constraint c1 { x < v && y > w; }; endclass initial begin CA a = new; a.randomize(); // random variables: x, y state variables: v, w a.randomize( x ); // random variables: x state variables: y, v, w a.randomize( v, w ); // random variables: v, w state variables: x, y a.randomize( w, x ); // random variables: w, x state variables: y, v end"##, Ok((_, _)) ); test!( many1(module_item), r##"module stim; bit [15:0] addr; bit [31:0] data; function bit gen_stim(); bit success, rd_wr; success = randomize( addr, data, rd_wr ); // call std::randomize return rd_wr ; endfunction endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"class stimc; rand bit [15:0] addr; rand bit [31:0] data; rand bit rd_wr; endclass function bit gen_stim( stimc p ); bit [15:0] addr; bit [31:0] data; bit success; success = p.randomize(); addr = p.addr; data = p.data; return p.rd_wr; endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"task stimulus( int length ); int a, b, c, success; success = std::randomize( a, b, c ) with { a < b ; a + b < length ; }; success = std::randomize( a, b ) with { b - a > length ; }; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin bit [64:1] addr; bit [ 3:0] number; addr[32:1] = $urandom( 254 ); // Initialize the generator, // get 32-bit random number addr = {$urandom, $urandom }; // 64-bit random number number = $urandom & 15; // 4-bit random number end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer x, y, z; fork //set a seed at the start of a thread begin process::self.srandom(100); x = $urandom; end //set a seed during a thread begin y = $urandom; process::self.srandom(200); end // draw 2 values from the thread RNG begin z = $urandom + $urandom ; end join end"##, Ok((_, _)) ); test!( many1(module_item), r##"class C1; rand integer x; endclass class C2; rand integer y; endclass initial begin C1 c1 = new(); C2 c2 = new(); integer z; void'(c1.randomize()); // z = $random; void'(c2.randomize()); end"##, Ok((_, _)) ); test!( many1(module_item), r##"class C3; function new (integer seed); //set a new seed for this instance this.srandom(seed); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Packet; rand bit[15:0] header; function new (int seed); this.srandom(seed); endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randcase 3 : x = 1; 1 : x = 2; 4 : x = 3; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin byte a, b; randcase a + b : x = 1; a - b : x = 2; a ^ ~b : x = 3; 12'h800 : x = 4; endcase end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence( main ) main : first second done ; first : add | dec ; second : pop | push ; done : { $display("done"); } ; add : { $display("add"); } ; dec : { $display("dec"); } ; pop : { $display("pop"); } ; push : { $display("push"); } ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence() PP_OP : if ( depth < 2 ) PUSH else POP ; PUSH : { ++depth; do_push(); }; POP : { --depth; do_pop(); }; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence() SELECT : case ( device & 7 ) 0 : NETWORK ; 1, 2 : DISK ; default : MEMORY ; endcase ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence() PUSH_OPER : repeat( $urandom_range( 2, 6 ) ) PUSH ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence( TOP ) TOP : rand join S1 S2 ; S1 : A B ; S2 : C D ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence() WRITE : SETUP DATA ; SETUP : { if( fifo_length >= max_length ) break; } COMMAND ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence() TOP : P1 P2 ; P1 : A B C ; P2 : A { if( flag == 1 ) return; } B C ; A : { $display( "A" ); } ; B : { if( flag == 2 ) return; $display( "B" ); } ; C : { $display( "C" ); } ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence( main ) main : first second gen ; first : add | dec ; second : pop | push ; add : gen("add") ; dec : gen("dec") ; pop : gen("pop") ; push : gen("push") ; gen( string s = "done" ) : { $display( s ); } ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin randsequence( bin_op ) void bin_op : value operator value // void type is optional { $display("%s %b %b", operator, value[1], value[2]); } ; bit [7:0] value : { return $urandom; } ; string operator : add := 5 { return "+" ; } | dec := 2 { return "-" ; } | mult := 1 { return "*" ; } ; endsequence end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int cnt; randsequence( A ) void A : A1 A2; void A1 : { cnt = 1; } B repeat(5) C B { $display("c=%d, b1=%d, b2=%d", C, B[1], B[2]); } ; void A2 : if (cond) D(5) else D(20) { $display("d1=%d, d2=%d", D[1], D[2]); } ; int B : C { return C;} | C C { return C[2]; } | C C C { return C[3]; } ; int C : { cnt = cnt + 1; return cnt; }; int D (int prm) : { return prm; }; endsequence end"##, Ok((_, _)) ); // TODO // function can't return queue //test!( // many1(module_item), // r##"function int[$] GenQueue(int low, int high); // int[$] q; // randsequence() // TOP : BOUND(low) LIST BOUND(high) ; // LIST : LIST ITEM := 8 { q = { q, ITEM }; } // | ITEM := 2 { q = { q, ITEM }; } // ; // int ITEM : { return $urandom_range( low, high ); } ; // BOUND(int b) : { q = { q, b }; } ; // endsequence // GenQueue = q; // endfunction"##, // Ok((_, _)) //); test!( many1(module_item), r##"class DSL; endclass // class that creates valid DSL packets initial begin randsequence (STREAM) STREAM : GAP DATA := 80 | DATA := 20 ; DATA : PACKET(0) := 94 { transmit( PACKET ); } | PACKET(1) := 6 { transmit( PACKET ); } ; DSL PACKET (bit bad) : { DSL d = new; if( bad ) d.crc ^= 23; // mangle crc return d; }; GAP: { ## ($urandom_range( 1, 20 )); }; endsequence end"##, Ok((_, _)) ); } #[test] fn clause19() { test!( many1(module_item), r##"covergroup cg; endgroup cg cg_inst = new;"##, Ok((_, _)) ); test!( many1(module_item), r##"enum { red, green, blue } color; covergroup g1 @(posedge clk); c: coverpoint color; endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"enum { red, green, blue } color; bit [3:0] pixel_adr, pixel_offset, pixel_hue; covergroup g2 @(posedge clk); Hue: coverpoint pixel_hue; Offset: coverpoint pixel_offset; AxC: cross color, pixel_adr; // cross 2 variables (implicitly declared // coverpoints) all: cross color, Hue, Offset; // cross 1 variable and 2 coverpoints endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"class xyz; bit [3:0] m_x; int m_y; bit m_z; covergroup cov1 @m_z; // embedded covergroup coverpoint m_x; coverpoint m_y; endgroup function new(); cov1 = new; endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class MC; logic [3:0] m_x; local logic m_z; bit m_e; covergroup cv1 @(posedge clk); coverpoint m_x; endgroup covergroup cv2 @m_e ; coverpoint m_z; endgroup endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class Helper; int m_ev; endclass class MyClass; Helper m_obj; int m_a; covergroup Cov @(m_obj.m_ev); coverpoint m_a; endgroup function new(); m_obj = new; Cov = new; // Create embedded covergroup after creating m_obj endfunction endclass"##, Ok((_, _)) ); test!( many1(module_item), r##"class C1; bit [7:0] x; covergroup cv (int arg) @(posedge clk); option.at_least = arg; coverpoint x; endgroup function new(int p1); cv = new(p1); endfunction endclass initial begin C1 obj = new(4); end"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup cg ( ref int x , ref int y, input int c); coverpoint x; // creates coverpoint "x" covering the formal "x" x: coverpoint y; // INVALID: coverpoint label "x" already exists b: coverpoint y; // creates coverpoint "b" covering the formal "y" cx: coverpoint x; // creates coverpoint "cx" covering the formal "x" option.weight = c; // set weight of "cg" to value of formal "c" bit [7:0] d: coverpoint y[31:24]; // creates coverpoint "d" covering the // high order 8 bits of the formal "y" e: coverpoint x { option.weight = 2; // set the weight of coverpoint "e" } //e.option.weight = 2; // INVALID use of "e", also syntax error cross x, y { // Creates implicit coverpoint "y" covering // the formal "y". Then creates a cross of // coverpoints "x", "y" option.weight = c; // set weight of cross to value of formal "c" } b: cross y, x; // INVALID: coverpoint label "b" already exists endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup g4; coverpoint s0 iff(!reset); endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [9:0] v_a; covergroup cg @(posedge clk); coverpoint v_a { bins a = { [0:63],65 }; bins b[] = { [127:150],[148:191] }; // note overlapping values bins c[] = { 200,201,202 }; bins d = { [1000:$] }; bins others[] = default; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup cg (ref int ra, input int low, int high ) @(posedge clk); coverpoint ra // sample variable passed by reference { bins good = { [low : high] }; bins bad[] = default; } endgroup int va, vb; cg c1 = new( va, 0, 50 ); // cover variable va in the range 0 to 50 cg c2 = new( vb, 120, 600 ); // cover variable vb in the range 120 to 600"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [4:1] v_a; covergroup cg @(posedge clk); coverpoint v_a { bins sa = (4 => 5 => 6), ([7:9],10=>11,12); bins sb[] = (4=> 5 => 6), ([7:9],10=>11,12); bins sc = (12 => 3 [-> 1]); bins allother = default sequence ; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup sg @(posedge clk); coverpoint v { bins b2 = ( 2 [-> 3:5] ); // 3 to 5 nonconsecutive 2's bins b3 = ( 3 [-> 3:5] ); // 3 to 5 nonconsecutive 3's bins b5 = ( 5 [* 3] ); // 3 consecutive 5's bins b6 = ( 1 => 3 [-> 4:6] => 1); // 1 followed by // 4 to 6 goto nonconsecutive 3's // followed immediately by a 1 bins b7 = ( 1 => 2 [= 3:6] => 5); // 1 followed by // 3 to 6 non consecutive 2's // followed sometime later by a 5 } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup cg23; coverpoint a { ignore_bins ignore_vals = {7,8}; ignore_bins ignore_trans = (1=>3=>5); } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup cg3; coverpoint b { illegal_bins bad_vals = {1,2,3}; illegal_bins bad_trans = (4=>5=>6); } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [2:0] p1; // type expresses values in the range 0 to 7 bit signed [2:0] p2; // type expresses values in the range –4 to 3 covergroup g1 @(posedge clk); coverpoint p1 { bins b1 = { 1, [2:5], [6:10] }; bins b2 = { -1, [1:10], 15 }; } coverpoint p2 { bins b3 = {1, [2:5], [6:10] }; bins b4 = { -1, [1:10], 15 }; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [3:0] a, b; covergroup cov @(posedge clk); aXb : cross a, b; endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [3:0] a, b, c; covergroup cov2 @(posedge clk); BC: coverpoint b+c; aXb : cross a, BC; endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [31:0] a_var; bit [3:0] b_var; covergroup cov3 @(posedge clk); A: coverpoint a_var { bins yy[] = { [0:9] }; } CC: cross b_var, A; endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"int i,j; covergroup ct; coverpoint i { bins i[] = { [0:1] }; } coverpoint j { bins j[] = { [0:1] }; } x1: cross i,j; x2: cross i,j { bins i_zero = binsof(i) intersect { 0 }; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [7:0] v_a, v_b; covergroup cg @(posedge clk); a: coverpoint v_a { bins a1 = { [0:63] }; bins a2 = { [64:127] }; bins a3 = { [128:191] }; bins a4 = { [192:255] }; } b: coverpoint v_b { bins b1 = {0}; bins b2 = { [1:84] }; bins b3 = { [85:169] }; bins b4 = { [170:255] }; } c : cross a, b { bins c1 = ! binsof(a) intersect {[100:200]};// 4 cross products bins c2 = binsof(a.a2) || binsof(b.b2);// 7 cross products bins c3 = binsof(a.a1) && binsof(b.b4);// 1 cross product } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [0:7] a, b; parameter [0:7] mask; covergroup cg; coverpoint a { bins low[] = {[0:127]}; bins high = {[128:255]}; } coverpoint b { bins two[] = b with (item % 2 == 0); bins three[] = b with (item % 3 == 0); } X: cross a,b { bins apple = X with (a+b < 257) matches 127; bins cherry = ( binsof(b) intersect {[0:50]} && binsof(a.low) intersect {[0:50]} with (a==b) ); bins plum = binsof(b.two) with (b > 12) || binsof(a.low) with (a & b & mask); } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"int a; logic [7:0] b; covergroup cg; coverpoint a { bins x[] = {[0:10]}; } coverpoint b { bins y[] = {[0:20]}; } aXb : cross a, b { bins one = '{ '{1,2}, '{3,4}, '{5,6} }; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"module mod_m; logic [31:0] a, b; covergroup cg(int cg_lim); coverpoint a; coverpoint b; aXb : cross a, b { function CrossQueueType myFunc1(int f_lim); for (int i = 0; i < f_lim; ++i) myFunc1.push_back('{i,i}); endfunction bins one = myFunc1(cg_lim); bins two = myFunc2(cg_lim); function CrossQueueType myFunc2(logic [31:0] f_lim); for (logic [31:0] i = 0; i < f_lim; ++i) myFunc2.push_back('{2*i,2*i}); endfunction } endgroup cg cg_inst = new(3); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup yy; cross a, b { ignore_bins ignore = binsof(a) intersect { 5, [1:3] }; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup zz(int bad); cross x, y { illegal_bins illegal = binsof(y) intersect {bad}; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup g1 (int w, string instComment) @(posedge clk) ; // track coverage information for each instance of g1 in addition // to the cumulative coverage information for covergroup type g1 option.per_instance = 1; // comment for each instance of this covergroup option.comment = instComment; a : coverpoint a_var { // Create 128 automatic bins for coverpoint “a” of each instance of g1 option.auto_bin_max = 128; } b : coverpoint b_var { // This coverpoint contributes w times as much to the coverage of an // instance of g1 as coverpoints "a" and "c1" option.weight = w; } c1 : cross a_var, b_var ; endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup gc (int maxA, int maxB) @(posedge clk) ; a : coverpoint a_var; b : coverpoint b_var; endgroup initial begin gc g1 = new (10,20); g1.option.comment = "Here is a comment set for the instance g1"; g1.a.option.weight = 3; // Set weight for coverpoint "a" of instance g1 end"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup g1 (int w, string instComment) @(posedge clk) ; // track coverage information for each instance of g1 in addition // to the cumulative coverage information for covergroup type g1 option.per_instance = 1; type_option.comment = "Coverage model for features x and y"; type_option.strobe = 1; // sample at the end of the time slot // compute type coverage as the merge of all instances type_option.merge_instances = 1; // comment for each instance of this covergroup option.comment = instComment; a : coverpoint a_var { // Use weight 2 to compute the coverage of each instance option.weight = 2; // Use weight 3 to compute the cumulative (type) coverage for g1 type_option.weight = 3; // NOTE: type_option.weight = w would cause syntax error. } b : coverpoint b_var { // Use weight w to compute the coverage of each instance option.weight = w; // Use weight 5 to compute the cumulative (type) coverage of g1 type_option.weight = 5; } endgroup"##, Ok((_, _)) ); //test!( // many1(module_item), // r##"covergroup gc @(posedge clk) ; // a : coverpoint a_var; // b : coverpoint b_var; // endgroup // initial begin // // Set the comment for all covergroups of type "gc" // gc::type_option.comment = "Here is a comment for covergroup g1"; // // Set the weight for coverpoint "a" of all covergroups of type gc // gc::a::type_option.weight = 3; // gc g1 = new; // end"##, // Ok((_, _)) //); //test!( // many1(module_item), // r##"covergroup cg (int xb, yb, ref int x, y) ; // coverpoint x {bins xbins[] = { [0:xb] }; } // coverpoint y {bins ybins[] = { [0:yb] }; } // endgroup // cg cv1 = new (1,2,a,b); // cv1.x has 2 bins, cv1.y has 3 bins // cg cv2 = new (3,6,c,d); // cv2.x has 4 bins, cv2.y has 7 bins // initial begin // cv1.x.get_inst_coverage(covered,total); // total = 2 // cv1.get_inst_coverage(covered,total); // total = 5 // cg::x::get_coverage(covered,total); // total = 6 // cg::get_coverage(covered,total); // total = 16 // end"##, // Ok((_, _)) //); test!( many1(module_item), r##"covergroup p_cg with function sample(bit a, int x); coverpoint x; cross x, a; endgroup : p_cg p_cg cg1 = new; property p1; int x; @(posedge clk)(a, x = b) ##1 (c, cg1.sample(a, x)); endproperty : p1 c1: cover property (p1); function automatic void F(int j); bit d; cg1.sample( d, j ); endfunction"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup C1 (int v) with function sample (int v, bit b); // error (v) coverpoint v; option.per_instance = b;// error: b may only designate a coverpoint option.weight = v; // error: v is ambiguous endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"struct // covergroup option declaration { string name ; int weight ; int goal ; string comment ; int at_least ; int auto_bin_max ; int cross_num_print_missing ; bit detect_overlap ; bit per_instance ; bit get_inst_coverage ; } option; struct // coverpoint option declaration { int weight ; int goal ; string comment ; int at_least ; int auto_bin_max ; bit detect_overlap ; } option; struct // cross option declaration { int weight ; int goal ; string comment ; int at_least ; int cross_num_print_missing ; } option; struct // covergroup type_option declaration { int weight ; int goal ; string comment ; bit strobe ; bit merge_instances ; bit distribute_first ; } type_option; struct // coverpoint and cross type_option declaration { int weight ; int goal ; string comment ; } type_option;"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [2:0] a, b; covergroup ct; coverpoint b { option.auto_bin_max = 4; ignore_bins ig = { [0:1], [5:6] }; } endgroup"##, Ok((_, _)) ); test!( many1(module_item), r##"covergroup gt ( int l, h); coverpoint a { bins b[] = { [l:h] }; } endgroup gt gv1 = new (0,1); gt gv2 = new (1,2);"##, Ok((_, _)) ); test!( many1(module_item), r##"bit [7:0] a; covergroup ga ( int abm); option.auto_bin_max = abm; coverpoint a { ignore_bins i = {3}; } endgroup ga gv1 = new (64); ga gv2 = new (32);"##, Ok((_, _)) ); } #[test] fn clause20() { test!( source_text, r##"`timescale 10 ns / 1 ns module test; logic set; parameter p = 1.55; initial begin $monitor($time,,"set=", set); #p set = 0; #p set = 1; end endmodule"##, Ok((_, _)) ); test!( source_text, r##"`timescale 10 ns / 1 ns module test; logic set; parameter p = 1.55; initial begin $monitor($realtime,,"set=", set); #p set = 0; #p set = 1; end endmodule"##, Ok((_, _)) ); test!( source_text, r##"`timescale 1 ms / 1 us module a_dat; initial $printtimescale(b_dat.c1); endmodule `timescale 10 fs / 1 fs module b_dat; c_dat c1 (); endmodule `timescale 1 ns / 1 ns module c_dat; endmodule"##, Ok((_, _)) ); test!( source_text, r##"`timescale 1 ms / 1 ns module cntrl; initial $timeformat(-9, 5, " ns", 10); endmodule `timescale 1 fs / 1 fs module a1_dat; logic in1; integer file; buf #10000000 (o1,in1); initial begin file = $fopen("a1.dat"); #00000000 $fmonitor(file,"%m: %t in1=%d o1=%h", $realtime,in1,o1); #10000000 in1 = 0; #10000000 in1 = 1; end endmodule `timescale 1 ps / 1 ps module a2_dat; logic in2; integer file2; buf #10000 (o2,in2); initial begin file2=$fopen("a2.dat"); #00000 $fmonitor(file2,"%m: %t in2=%d o2=%h",$realtime,in2,o2); #10000 in2 = 0; #10000 in2 = 1; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module driver (net_r); output [64:1] net_r; real r; wire [64:1] net_r = $realtobits(r); endmodule module receiver (net_r); input [64:1] net_r; wire [64:1] net_r; real r; initial assign r = $bitstoreal(net_r); endmodule"##, Ok((_, _)) ); test!( source_text, r##"typedef bit node; // "bit" node [2:0] X; // "bit [2:0]" int signed Y; // "int" package A; enum {A,B,C=99} X; // "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::e$1" typedef bit [9:1'b1] word; // "A::bit[9:1]" endpackage : A import A::*; module top; typedef struct {node A,B;} AB_t; AB_t AB[10]; // "struct{bit A;bit B;}top.AB_t$[0:9]" endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"typedef bit[$bits(MyType):1] MyBits; //same as typedef bit [9:1] MyBits; MyBits b;"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [3:0][2:1] n [1:5][2:8]; typedef logic [3:0][2:1] packed_reg; packed_reg n[1:5][2:8]; // same dimensions as in the lines above"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin int a[3][][5]; // array dimension 2 has variable size $display( $unpacked_dimensions(a) ); // displays 3 a[2] = new[4]; a[2][2][0] = 220; // OK, a[2][2] is a 5-element array $display( $size(a, 1) ); // OK, displays 3 $display( $size(a, 2) ); // ERROR, dimension 2 is dynamic $display( $size(a[2], 1) ); // OK, displays 4 (a[2] is // a 4-element dynamic array) $display( $size(a[1], 1) ); // OK, displays 0 (a[1] is // an empty dynamic array) $display( $size(a, 3) ); // OK, displays 5 (fixed-size dimension) end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer result; result = $clog2(n); end"##, Ok((_, _)) ); test!( many1(module_item), r##"logic [1:0] bad_bits; logic [31:0] myvec; logic design_initialization_done; always_comb begin if (!design_initialization_done) begin bad_bits[0] = 'x; bad_bits[1] = 'x; // Repeated control_bit same as single occurrence end else begin bad_bits[0] = 'x; bad_bits[1] = 'z; end // Z allowed during initialization, but no Z or X allowed afterwards a1: assert ($countbits(myvec,bad_bits[0],bad_bits[1]) == 0); end"##, Ok((_, _)) ); test!( many1(module_item), r##"module test #(N = 1) (input [N-1:0] in, output [N-1:0] out); if ((N < 1) || (N > 8)) // conditional generate construct $error("Parameter N has an invalid value of %0d", N); assign out = in; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"generate if ($bits(vect) == 1) begin : err $error("Only a 1-bit vector"); end for (genvar i = 0; i < $bits(vect); i++) begin : Loop if (i==0) begin : Cond sequence t; vect[0]; endsequence $info("i=0 branch generated"); end : Cond else begin : Cond sequence t; vect[i] ##1 Loop[i-1].Cond.t; endsequence $info("i = %0d branch generated", i); end : Cond end : Loop endgenerate // instantiate the last generated sequence in a property property p; @(posedge clk) trig |-> Loop[$bits(vect)-1].Cond.t; endproperty"##, Ok((_, _)) ); test!( many1(module_item), r##"module test; logic clk; logic a, b; logic c, d; // Define lets to make the code more readable. let LOCK = 1; let UNLOCK = 2; let ON = 3; let OFF = 4; let KILL = 5; let CONCURRENT = 1; let S_IMMEDIATE = 2; // simple immediate let D_IMMEDIATE = 12; // Final and Observed deferred immediate let EXPECT = 16; let UNIQUE = 32; // unique if and case violation let UNIQUE0 = 64; // unique0 if and case violation let PRIORITY = 128; // priority if and case violation let ASSERT = 1; let COVER = 2; let ASSUME = 4; let ALL_DIRECTIVES = (ASSERT|COVER|ASSUME); let ALL_ASSERTS = (CONCURRENT|S_IMMEDIATE|D_IMMEDIATE|EXPECT); let VACUOUSOFF = 11; a1: assert property (@(posedge clk) a |=> b) $info("assert passed"); else $error("assert failed"); c1: cover property (@(posedge clk) a ##1 b); always @(posedge clk) begin ia1: assert (a); end always_comb begin if (c) df1: assert #0 (d); unique if ((a==0) || (a==1)) $display("0 or 1"); else if (a == 2) $display("2"); else if (a == 4) $display("4"); // values 3,5,6,7 cause a violation // report end initial begin // The following systasks affect the whole design so no modules // are specified // Disable vacuous pass action for all the concurrent asserts, // covers and assumes in the design. Also disable vacuous pass // action for expect statements. $assertcontrol(VACUOUSOFF, CONCURRENT | EXPECT); // Disable concurrent and immediate asserts and covers. // This will also disable violation reporting. // The following systask does not affect expect // statements as control type is Off. $assertcontrol(OFF); // using default values of all the // arguments after first argument // After 20 time units, enable assertions, // This will not enable violation reporting. // explicitly specifying second, third and fourth arguments // in the following task call #20 $assertcontrol(ON, CONCURRENT|S_IMMEDIATE|D_IMMEDIATE, ASSERT|COVER|ASSUME, 0); // Enable violation reporting after 20 time units. #20 $assertcontrol(ON, UNIQUE|UNIQUE0|PRIORITY); // Kill currently executing concurrent assertions after // 100 time units but do not kill concurrent covers/assumes // and immediate/deferred asserts/covers/assumes // using appropriate values of second and third arguments. #100 $assertcontrol(KILL, CONCURRENT, ASSERT, 0); // The following assertion control task does not have any effect as // directive_type is assert but it has selected cover directive c1. #10 $assertcontrol(ON, CONCURRENT|S_IMMEDIATE|D_IMMEDIATE, ASSERT, 0, c1); // Now, after 10 time units, enable all the assertions except a1. // To accomplish this, first we’ll lock a1 and then we’ll enable all // the assertions and then unlock a1 as we want future assertion // control tasks to affect a1. #10 $assertcontrol(LOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, a1); $assertcontrol(ON); // enable all the assertions except a1 $assertcontrol(UNLOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, a1); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"wire a1, a2, a3, a4, a5, a6, a7; logic b1, b2, b3; wire [1:7] awire; logic [1:3] breg; initial begin $async$and$array(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3}); end"##, Ok((_, _)) ); test!( many1(module_item), r##"module async_array(a1,a2,a3,a4,a5,a6,a7,b1,b2,b3); input a1, a2, a3, a4, a5, a6, a7 ; output b1, b2, b3; logic [1:7] mem[1:3]; // memory declaration for array personality logic b1, b2, b3; initial begin // set up the personality from the file array.dat $readmemb("array.dat", mem); // set up an asynchronous logic array with the input // and output terms expressed as concatenations $async$and$array(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3}); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module sync_array(a1,a2,a3,a4,a5,a6,a7,b1,b2,b3,clk); input a1, a2, a3, a4, a5, a6, a7, clk; output b1, b2, b3; logic [1:7] mem[1:3]; // memory declaration logic b1, b2, b3; initial begin // set up the personality $readmemb("array.dat", mem); // set up a synchronous logic array to be evaluated // when a positive edge on the clock occurs forever @(posedge clk) $async$and$array(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3}); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module pla; logic [1:cols] a, mem[1:rows]; logic [1:rows] b; initial begin // PLA system call $async$and$plane(mem,a[1:3],b[1:4]); mem[1] = 3'b10?; mem[2] = 3'b??1; mem[3] = 3'b0?0; mem[4] = 3'b???; // stimulus and display #10 a = 3'b111; #10 $displayb(a, " -> ", b); #10 a = 3'b000; #10 $displayb(a, " -> ", b); #10 a = 3'bxxx; #10 $displayb(a, " -> ", b); #10 a = 3'b101; #10 $displayb(a, " -> ", b); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; initial $system("mv design.v adder.v"); endmodule"##, Ok((_, _)) ); } #[test] fn clause21() { test!( many1(module_item), r##"module disp; initial begin $display("\\\t\\\n\"\123"); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module disp; logic [31:0] rval; pulldown (pd); initial begin rval = 101; $display("rval = %h hex %d decimal",rval,rval); $display("rval = %o octal\nrval = %b bin",rval,rval); $display("rval has %c ascii character value",rval); $display("pd strength value is %v",pd); $display("current scope is %m"); $display("%s is ascii value for 101",101); $display("simulation time is %t", $time); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module printval; logic [11:0] r1; initial begin r1 = 10; $display( "Printing with maximum size - :%d: :%h:", r1,r1 ); $display( "Printing with minimum size - :%0d: :%0h:", r1,r1 ); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"always #15 $display($time,,"group=%b signals=%v %v %v",{s1,s2,s3},s1,s2,s3);"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; typedef enum {ON, OFF} switch_e; typedef struct {switch_e sw; string s;} pair_t; pair_t va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}}; initial begin $display("va[int] = %p;",va); $display("va[int] = %0p;",va); $display("va[10].s = %p;", va[10].s); end endmodule : top"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin forever @(negedge clock) $strobe ("At time %d, data is %h",$time,data); end"##, Ok((_, _)) ); test!( many1(module_item), r##"integer messages, broadcast, cpu_chann, alu_chann, mem_chann; initial begin cpu_chann = $fopen("cpu.dat"); if (cpu_chann == 0) $finish; alu_chann = $fopen("alu.dat"); if (alu_chann == 0) $finish; mem_chann = $fopen("mem.dat"); if (mem_chann == 0) $finish; messages = cpu_chann | alu_chann | mem_chann; // broadcast includes standard output broadcast = 1 | messages; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer c; c = $fgetc ( fd ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer code; code = $ungetc ( c, fd ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer code; code = $fgets ( str, fd ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer code ; code = $fscanf ( fd, format, args ); code = $sscanf ( str, format, args ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer code ; code = $fread( integral_var, fd); code = $fread( mem, fd); code = $fread( mem, fd, start); code = $fread( mem, fd, start, count); code = $fread( mem, fd, , count); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer pos ; pos = $ftell ( fd ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer code ; code = $fseek ( fd, offset, operation ); code = $rewind ( fd ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin $fflush ( mcd ); $fflush ( fd ); $fflush ( ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer errno ; errno = $ferror ( fd, str ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin integer code; code = $feof ( fd ); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial $readmemh("mem.data", mem); initial $readmemh("mem.data", mem, 16); initial $readmemh("mem.data", mem, 128, 1);"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin if ($test$plusargs("HELLO")) $display("Hello argument found."); if ($test$plusargs("HE")) $display("The HE subset string is detected."); if ($test$plusargs("H")) $display("Argument starting with H found."); if ($test$plusargs("HELLO_HERE")) $display("Long argument."); if ($test$plusargs("HI")) $display("Simple greeting."); if ($test$plusargs("LO")) $display("Does not match."); end"##, Ok((_, _)) ); test!( many1(module_item), r##"module goodtasks; STRING str; integer i1; logic [31:0] vect; real realvar; initial begin if ($value$plusargs("TEST=%d", i1)) $display("value was %d", i1); else $display("+TEST= not found"); #100 $finish; end endmodule module ieee1364_example; real frequency; logic [8*32:1] testname; logic [64*8:1] pstring; logic clk; initial begin if ($value$plusargs("TESTNAME=%s",testname)) begin $display(" TESTNAME= %s.",testname); $finish; end if (!($value$plusargs("FREQ+%0F",frequency))) frequency = 8.33333; // 166 MHz $display("frequency = %f",frequency); pstring = "TEST%d"; if ($value$plusargs(pstring, testname)) $display("Running test number %0d.",testname); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"initial $dumpfile ("module1.dump") ;"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin $dumpvars (1, top); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin $dumpvars (0, top.mod1, top.mod2.net1); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin #10 $dumpvars(); #200 $dumpoff; #800 $dumpon; #900 $dumpoff; end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin $dumpvars ; $dumpflush ; //$(applications program) ; end"##, Ok((_, _)) ); test!( many1(module_item), r##"module dump; event do_dump; initial $dumpfile("verilog.dump"); initial @do_dump $dumpvars; //dump variables in the design always @do_dump //to begin the dump at event do_dump begin $dumpon; //no effect the first time through repeat (500) @(posedge clock); //dump for 500 cycles $dumpoff; //stop the dump end initial @(do_dump) forever #10000 $dumpall; // checkpoint all variables endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module test_device(count_out, carry, data, reset); output count_out, carry ; input [0:3] data; input reset; initial begin $dumpports(testbench.DUT, "testoutput.vcd"); end endmodule"##, Ok((_, _)) ); } #[test] fn clause22() { test!( source_text, r##"`define D(x,y) initial $display("start", x , y, "end");"##, Ok((_, _)) ); test!( source_text, r##"`define MACRO1(a=5,b="B",c) $display(a,,b,,c); `define MACRO2(a=5, b, c="C") $display(a,,b,,c); `define MACRO3(a=5, b=0, c="C") $display(a,,b,,c);"##, Ok((_, _)) ); test!( source_text, r##"`define wordsize 8 `define var_nand(dly) nand #dly"##, Ok((_, _)) ); test!( source_text, r##"`define max(a,b)((a) > (b) ? (a) : (b))"##, Ok((_, _)) ); test!(source_text, r##"`define TOP(a,b) a + b"##, Ok((_, _))); test!( source_text, r##"`define msg(x,y) `"x: `\`"y`\`"`""##, Ok((_, _)) ); test!(source_text, r##"`define append(f) f``_master"##, Ok((_, _))); test!( source_text, r##"`define home(filename) `"/home/mydir/filename`""##, Ok((_, _)) ); test!(source_text, r##"`timescale 1 ns / 1 ps"##, Ok((_, _))); test!(source_text, r##"`timescale 10 us / 100 ns"##, Ok((_, _))); test!( source_text, r##"`timescale 10 ns / 1 ns module test; logic set; parameter d = 1.55; initial begin #d set = 0; #d set = 1; end endmodule"##, Ok((_, _)) ); test!( source_text, r##"`line 3 "orig.v" 2 // This line is line 3 of orig.v after exiting include file"##, Ok((_, _)) ); test!( source_text, r##"`begin_keywords "1364-2001" // use IEEE Std 1364-2001 Verilog keywords module m2; reg [63:0] logic; // OK: "logic" is not a keyword in 1364-2001 endmodule `end_keywords"##, Ok((_, _)) ); test!( source_text, r##"`begin_keywords "1800-2005" // use IEEE Std 1800-2005 SystemVerilog keywords module m2; reg [63:0] logic; // ERROR: "logic" is a keyword in 1800-2005 endmodule `end_keywords"##, Err(_) ); test!( source_text, r##"`begin_keywords "1800-2005" // use IEEE Std 1800-2005 SystemVerilog keywords interface if1; endinterface `end_keywords"##, Ok((_, _)) ); } #[test] fn clause23() { test!( many1(module_item), r##"typedef struct { bit isfloat; union { int i; shortreal f; } n; } tagged_st; // named structure module mh1 (input var int in1, input var shortreal in2, output tagged_st out); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module test(a,b,c,d,e,f,g,h); input [7:0] a; // no explicit net declaration - net is unsigned input [7:0] b; input signed [7:0] c; input signed [7:0] d; // no explicit net declaration - net is signed output [7:0] e; // no explicit net declaration - net is unsigned output [7:0] f; output signed [7:0] g; output signed [7:0] h; // no explicit net declaration - net is signed wire signed [7:0] b; // port b inherits signed attribute from net decl. wire [7:0] c; // net c inherits signed attribute from port logic signed [7:0] f;// port f inherits signed attribute from logic decl. logic [7:0] g; // logic g inherits signed attribute from port endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module complex_ports ( {c,d}, .e(f) ); // Nets {c,d} receive the first port bits. // Name 'f' is declared inside the module. // Name 'e' is defined outside the module. // Cannot use named port connections of first port endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module split_ports (a[7:4], a[3:0]); // First port is upper 4 bits of 'a'. // Second port is lower 4 bits of 'a'. // Cannot use named port connections because // of part-select port 'a'. endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module same_port (.a(i), .b(i)); // Name 'i' is declared inside the module as an inout port. // Names 'a' and 'b' are defined for port connections. endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module renamed_concat (.a({b,c}), f, .g(h[1])); // Names 'b', 'c', 'f', 'h' are defined inside the module. // Names 'a', 'f', 'g' are defined for port connections. // Can use named port connections. endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module same_input (a,a); input a; // This is legal. The inputs are tied together. endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module mixed_direction (.p({a, e})); input a; // p contains both input and output directions. output e; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module test ( input [7:0] a, input signed [7:0] b, c, d, // Multiple ports that share all // attributes can be declared together. output [7:0] e, // Every attribute of the declaration // must be in the one declaration. output var signed [7:0] f, g, output signed [7:0] h) ; // It is illegal to redeclare any ports of // the module in the body of the module. endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module cpuMod(interface d, interface j); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module mymod ( output .P1(r[3:0]), output .P2(r[7:4]), ref .Y(x), input R ); logic [7:0] r; int x; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module mh_nonansi(x, y); input wire x; output tri0 y; endmodule module mh0 (wire x); endmodule // inout wire logic x module mh1 (integer x); endmodule // inout wire integer x module mh2 (inout integer x); endmodule // inout wire integer x module mh3 ([5:0] x); endmodule // inout wire logic [5:0] x module mh4 (var x); endmodule // ERROR: direction defaults to inout, // which cannot be var module mh5 (input x); endmodule // input wire logic x module mh6 (input var x); endmodule // input var logic x module mh7 (input var integer x); endmodule // input var integer x module mh8 (output x); endmodule // output wire logic x module mh9 (output var x); endmodule // output var logic x module mh10(output signed [5:0] x); endmodule// output wire logic signed [5:0] x module mh11(output integer x); endmodule // output var integer x module mh12(ref [5:0] x); endmodule // ref var logic [5:0] x module mh13(ref x [5:0]); endmodule // ref var logic x [5:0]"##, Ok((_, _)) ); test!( many1(module_item), r##"module mh14(wire x, y[7:0]); endmodule // inout wire logic x // inout wire logic y[7:0] module mh15(integer x, signed [5:0] y); endmodule // inout wire integer x // inout wire logic signed [5:0] y module mh16([5:0] x, wire y); endmodule // inout wire logic [5:0] x // inout wire logic y module mh17(input var integer x, wire y); endmodule // input var integer x // input wire logic y module mh18(output var x, input y); endmodule // output var logic x // input wire logic y module mh19(output signed [5:0] x, integer y); endmodule // output wire logic signed [5:0] x // output var integer y module mh20(ref [5:0] x, y); endmodule // ref var logic [5:0] x // ref var logic [5:0] y module mh21(ref x [5:0], y); endmodule // ref var logic x [5:0] // ref var logic y"##, Ok((_, _)) ); test!( many1(module_item), r##"module mh22 (input wire integer p_a, .p_b(s_b), p_c); logic [5:0] s_b; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter logic [7:0] My_DataIn = 8'hFF; module bus_conn ( output logic [7:0] dataout, input [7:0] datain = My_DataIn); assign dataout = datain; endmodule module bus_connect1 ( output logic [31:0] dataout, input [ 7:0] datain); parameter logic [7:0] My_DataIn = 8'h00; bus_conn bconn0 (dataout[31:24], 8'h0F); // Constant literal overrides default in bus_conn definition bus_conn bconn1 (dataout[23:16]); // Omitted port for datain, default parameter value 8'hFF in // bus_conn used bus_conn bconn2 (dataout[15:8], My_DataIn); // The parameter value 8'h00 from the instantiating scope is used bus_conn bconn3 (dataout[7:0]); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module generic_fifo (clk, read, write, reset, out, full, empty ); parameter MSB=3, LSB=0, DEPTH=4; // these parameters can be redefined input [MSB:LSB] in; input clk, read, write, reset; output [MSB:LSB] out; output full, empty; wire [MSB:LSB] in; wire clk, read, write, reset; logic [MSB:LSB] out; logic full, empty; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module generic_fifo #(parameter MSB=3, LSB=0, DEPTH=4) // these parameters can be redefined (input wire [MSB:LSB] in, input wire clk, read, write, reset, output logic [MSB:LSB] out, output logic full, empty ); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module generic_decoder #(num_code_bits = 3, localparam num_out_bits = 1 << num_code_bits) (input [num_code_bits-1:0] A, output reg [num_out_bits-1:0] Y); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter logic [7:0] My_DataIn = 8'hFF; module alu ( output reg [7:0] alu_out, output reg zero, input [7:0] ain, bin, input [2:0] opcode); // RTL code for the alu module endmodule module accum ( output reg [7:0] dataout, input [7:0] datain = My_DataIn, input clk, rst_n = 1'b1); // RTL code for the accumulator module endmodule module xtend ( output reg [7:0] dout, input din, input clk, rst = 1'b0 ); // RTL code for the sign-extension module endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module alu_accum1 ( output [15:0] dataout, input [7:0] ain, bin, input [2:0] opcode, input clk, rst_n, rst); wire [7:0] alu_out; alu alu (alu_out, , ain, bin, opcode); // zero output is unconnected accum accum (dataout[7:0], alu_out, clk, rst_n); xtend xtend (dataout[15:8], alu_out[7], clk); // rst gets default // value 1'b0 endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module alu_accum2 ( output [15:0] dataout, input [7:0] ain, bin, input [2:0] opcode, input clk, rst_n, rst); wire [7:0] alu_out; alu alu (.alu_out(alu_out), .zero(), .ain(ain), .bin(bin), .opcode(opcode)); // zero output is unconnected accum accum (.dataout(dataout[7:0]), .datain(alu_out), .clk(clk)); // rst_n is not in the port list and so gets default value 1'b1 xtend xtend (.dout(dataout[15:8]), .din(alu_out[7]), .clk(clk), .rst() ); // rst has a default value, but has an empty port connection, // therefore it is left unconnected endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module test; A ia ( .i (a), .i (b), // illegal connection of input port twice .o (c), .o (d), // illegal connection of output port twice .e (e), .e (f)); // illegal connection of inout port twice endmodule module A (input i, output o, inout e); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module alu_accum3 ( output [15:0] dataout, input [7:0] ain, bin, input [2:0] opcode, input clk, rst_n); wire [7:0] alu_out; alu alu (.alu_out, .zero(), .ain, .bin, .opcode); accum accum (.dataout(dataout[7:0]), .datain(alu_out), .clk, .rst_n()); xtend xtend (.dout(dataout[15:8]), .din(alu_out[7]), .clk, .rst); // Error: rst does not exist in the instantiation module endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module alu_accum4 ( output [15:0] dataout, input [7:0] ain, bin, input [2:0] opcode, input clk); wire [7:0] alu_out; alu alu (.*, .zero()); accum accum (.*, .dataout(dataout[7:0]), .datain(alu_out)); xtend xtend (.*, .dout(dataout[15:8]), .din(alu_out[7])); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module alu_accum5 ( output [15:0] dataout, input [7:0] ain, bin, input [2:0] opcode, input clk, rst_n); wire [7:0] alu_out; // mixture of named port connections and // implicit .name port connections alu alu (.ain(ain), .bin(bin), .alu_out, .zero(), .opcode); // positional port connections accum accum (dataout[7:0], alu_out, clk, rst_n); // mixture of named port connections and implicit .* port connections xtend xtend (.dout(dataout[15:8]), .*, .din(alu_out[7])); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module child(output o, input i[5]); //... endmodule : child module parent(output o[8][4], input i[8][4][5] ); child c[8][4](o,i); //... endmodule : parent"##, Ok((_, _)) ); test!( many1(module_item), r##"module MxN_pipeline #(M=3,N=4) (input [M-1:0] in, output [M-1:0] out, input clk); typedef logic T [M-1:0][1:N]; T Ins, Outs; DFF dff[M-1:0][1:N](Outs, Ins, clk); for (genvar I = M-1; I >= 0; I--) begin for (genvar J = 1; J <= N; J++) begin case (J) 1: begin assign out[I] = Outs[I][1]; assign Ins[I][J] = Outs[I][2]; end default: assign Ins[I][J] = Outs[I][J+1]; N: assign Ins[I][N] = in[I]; endcase end end endmodule : MxN_pipeline"##, Ok((_, _)) ); test!( many1(module_item), r##"module netlist; interconnect iwire; dut1 child1(iwire); dut2 child2(iwire); endmodule module dut1(inout wire w); assign w = 1; endmodule module dut2(inout wand w); assign w = 0; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module dff_flat(input d, ck, pr, clr, output q, nq); wire q1, nq1, q2, nq2; nand g1b (nq1, d, clr, q1); nand g1a (q1, ck, nq2, nq1); nand g2b (nq2, ck, clr, q2); nand g2a (q2, nq1, pr, nq2); nand g3a (q, nq2, clr, nq); nand g3b (nq, q1, pr, q); endmodule // This example shows how the flip-flop can be structured into 3 RS latches. module dff_nested(input d, ck, pr, clr, output q, nq); wire q1, nq1, nq2; module ff1; nand g1b (nq1, d, clr, q1); nand g1a (q1, ck, nq2, nq1); endmodule ff1 i1(); module ff2; wire q2; // This wire can be encapsulated in ff2 nand g2b (nq2, ck, clr, q2); nand g2a (q2, nq1, pr, nq2); endmodule ff2 i2(); module ff3; nand g3a (q, nq2, clr, nq); nand g3b (nq, q1, pr, q); endmodule ff3 i3(); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module part1(); module and2(input a, b, output z); endmodule module or2(input a, b, output z); endmodule and2 u1(), u2(), u3(); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"extern module m (a,b,c,d); extern module a #(parameter size= 8, parameter type TP = logic [7:0]) (input [size:0] a, output TP b); module top (); wire [8:0] a; logic [7:0] b; wire c, d; m mm (.*); a aa (.*); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module top (); wire [8:0] a; logic [7:0] b; wire c, d; m mm (a,b,c,d); a aa (a,b); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"extern module m (a,b,c,d); extern module a #(parameter size = 8, parameter type TP = logic [7:0]) (input [size:0] a, output TP b); module m (.*); input a,b,c; output d; endmodule module a (.*); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m (a,b,c,d); input a,b,c; output d; endmodule module a #(parameter size = 8, parameter type TP = logic [7:0]) (input [size:0] a, output TP b); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module cct (stim1, stim2); input stim1, stim2; // instantiate mod mod amod(stim1), bmod(stim2); endmodule module mod (in); input in; always @(posedge in) begin : keep logic hold; hold = in; end endmodule module wave; logic stim1, stim2; cct a(stim1, stim2); // instantiate cct initial begin :wave1 #100 fork :innerwave reg hold; join #150 begin stim1 = 0; end end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin fork : mod_1 reg x; mod_2.x = 1; join fork : mod_2 reg x; mod_1.x = 0; join end"##, Ok((_, _)) ); test!( many1(module_item), r##"module top(); logic clk, x, y, z; m m_i(clk, x, y, z); endmodule module m(input logic clk, a, b, c); assert #0 (a^b); // no label, assertion cannot be referred to A1: assert #0 (a^b); // assertion can be accessed in control tasks initial begin : B1 assert (a); // cannot be accessed in control tasks A1: assert (a) // can be accessed, e.g., top.m_i.B1.A1 begin // unnamed block, d cannot be accessed bit d; d = a ^ b; end else begin : B2 // name required to access items in action block bit d; // d can be accessed using, e.g., top.m_i.B1.A1.B2.d d = a ^ b; end end logic e; always_ff @(posedge clk) begin // unnamed block, no scope created e <= a && c; C1: cover property(e) // C1 and A2 can be referred to begin // hierarchical name top.m_i.C1.A2 A2: assert (m_i.B1.A1.B2.d); end end always_ff @(posedge clk) begin // unnamed block, scope created // declaration of f causes begin-end to create scope static logic f; f <= a && c; C2: cover property(f) // C2 and A3 cannot be referred to begin A3: assert (m_i.B1.A1.B2.d); end end always_ff @(posedge clk) begin : B2 // named block and scope created static logic f; f <= a && c; C3: cover property(f) // C3 and A4 can be referred to begin // hierarchical name top.m_i.B2.C3.A4 A4: assert (m_i.B1.A1.B2.d); end end assert property(@(posedge clk) a |-> b) else // unnamed assertion begin: B3 static bit d; // d can be referred to, e.g., top.m_i.B3.d A5: assert(d); // hierarchical name top.m_i.B3.A5 end // Any other labelled object with name B3 at the module // level shall be an error endmodule"##, Ok((_, _)) ); test!( source_text, r##"package p; struct { int x; } s1; struct { int x; } s2; function void f(); int x; endfunction endpackage module m; import p::*; if (1) begin : s1 initial begin s1.x = 1; // dotted name 1 s2.x = 1; // dotted name 2 f.x = 1; // dotted name 3 f2.x = 1; // dotted name 4 end int x; some_module s2(); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module a; integer i; b a_b1(); endmodule module b; integer i; c b_c1(), b_c2(); initial // downward path references two copies of i: #10 b_c1.i = 2; // a.a_b1.b_c1.i, d.d_b1.b_c1.i endmodule module c; integer i; initial begin // local name references four copies of i: i = 1; // a.a_b1.b_c1.i, a.a_b1.b_c2.i, // d.d_b1.b_c1.i, d.d_b1.b_c2.i b.i = 1; // upward path references two copies of i: // a.a_b1.i, d.d_b1.i end endmodule module d; integer i; b d_b1(); initial begin // full path name references each copy of i a.i = 1; d.i = 5; a.a_b1.i = 2; d.d_b1.i = 6; a.a_b1.b_c1.i = 3; d.d_b1.b_c1.i = 7; a.a_b1.b_c2.i = 4; d.d_b1.b_c2.i = 8; end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"task t; int x; x = f(1); // valid reference to function f in $unit scope endtask function int f(int y); return y+1; endfunction"##, Ok((_, _)) ); test!( source_text, r##"package p; function void f(); $display("p::f"); endfunction endpackage module top; import p::*; if (1) begin : b // generate block initial f(); // reference to “f” function void f(); $display("top.b.f"); endfunction end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"task t; logic s; begin : b logic r; t.b.r = 0;// These three lines access the same variable r b.r = 0; r = 0; t.s = 0;// These two lines access the same variable s s = 0; end endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"module generic_fifo #(MSB=3, LSB=0) // parameter port list parameters (input wire [MSB:LSB] in, input wire clk, read, write, reset, output logic [MSB:LSB] out, output logic full, empty ); parameter DEPTH=4; // module item parameter localparam FIFO_MSB = DEPTH*MSB; localparam FIFO_LSB = LSB; // These constants are local, and cannot be overridden. // They can be affected by altering the value parameters above logic [FIFO_MSB:FIFO_LSB] fifo; logic [LOG2(DEPTH):0] depth; always @(posedge clk or posedge reset) begin //casez ({read,write,reset}) // // implementation of fifo //endcase end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m1 (a,b); real r1,r2; parameter [2:0] A = 3'h2; parameter B = 3'h2; initial begin r1 = A; r2 = B; $display("r1 is %f r2 is %f",r1,r2); end endmodule: m1 module m2; wire a,b; defparam f1.A = 3.1415; defparam f1.B = 3.1415; m1 f1(a,b); endmodule: m2"##, Ok((_, _)) ); test!( many1(module_item), r##"genvar i; generate for (i = 0; i < 8; i = i + 1) begin : somename flop my_flop(in[i], in1[i], out1[i]); defparam somename[i+1].my_flop.xyz = i ; end endgenerate"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic clk; logic [0:4] in1; logic [0:9] in2; wire [0:4] o1; wire [0:9] o2; vdff m1 (o1, in1, clk); vdff m2 (o2, in2, clk); endmodule module vdff (out, in, clk); parameter size = 1, delay = 1; input [0:size-1] in; input clk; output [0:size-1] out; logic [0:size-1] out; always @(posedge clk) # delay out = in; endmodule module annotate; defparam top.m1.size = 5, top.m1.delay = 10, top.m2.size = 10, top.m2.delay = 20; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module tb1; wire [9:0] out_a, out_d; wire [4:0] out_b, out_c; logic [9:0] in_a, in_d; logic [4:0] in_b, in_c; logic clk; // testbench clock & stimulus generation code ... // Four instances of vdff with parameter value assignment by ordered list // mod_a has new parameter values size=10 and delay=15 // mod_b has default parameters (size=5, delay=1) // mod_c has one default size=5 and one new delay=12 // In order to change the value of delay, // it is necessary to specify the (default) value of size as well. // mod_d has a new parameter value size=10. // delay retains its default value vdff #(10,15) mod_a (.out(out_a), .in(in_a), .clk(clk)); vdff mod_b (.out(out_b), .in(in_b), .clk(clk)); vdff #( 5,12) mod_c (.out(out_c), .in(in_c), .clk(clk)); vdff #(10) mod_d (.out(out_d), .in(in_d), .clk(clk)); endmodule module vdff (out, in, clk); parameter size=5, delay=1; output [size-1:0] out; input [size-1:0] in; input clk; logic [size-1:0] out; always @(posedge clk) #delay out = in; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module my_mem (addr, data); parameter addr_width = 16; localparam mem_size = 1 << addr_width; parameter data_width = 8; endmodule module top; my_mem #(12, 16) m(addr,data); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module tb2; wire [9:0] out_a, out_d; wire [4:0] out_b, out_c; logic [9:0] in_a, in_d; logic [4:0] in_b, in_c; logic clk; // testbench clock & stimulus generation code ... // Four instances of vdff with parameter value assignment by name // mod_a has new parameter values size=10 and delay=15 // mod_b has default parameters (size=5, delay=1) // mod_c has one default size=5 and one new delay=12 // mod_d has a new parameter value size=10. // delay retains its default value vdff #(.size(10),.delay(15)) mod_a (.out(out_a),.in(in_a),.clk(clk)); vdff mod_b (.out(out_b),.in(in_b),.clk(clk)); vdff #(.delay(12)) mod_c (.out(out_c),.in(in_c),.clk(clk)); vdff #(.delay( ),.size(10) ) mod_d (.out(out_d),.in(in_d),.clk(clk)); endmodule module vdff (out, in, clk); parameter size=5, delay=1; output [size-1:0] out; input [size-1:0] in; input clk; logic [size-1:0] out; always @(posedge clk) #delay out = in; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module tb3; // declarations & code // legal mixture of instance with positional parameters and // another instance with named parameters vdff #(10, 15) mod_a (.out(out_a), .in(in_a), .clk(clk)); vdff mod_b (.out(out_b), .in(in_b), .clk(clk)); vdff #(.delay(12)) mod_c (.out(out_c), .in(in_c), .clk(clk)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter word_size = 32, memory_size = word_size * 4096;"##, Ok((_, _)) ); test!( many1(module_item), r##"parameter p = 1; parameter [p:0] p2 = 4; parameter type T = int; parameter T p3 = 7;"##, Ok((_, _)) ); test!( many1(module_item), r##"class C ; endclass module M #( type T = C, T p = 4, type T2, T2 p2 = 4 ) () ; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; m1 n(); endmodule module m1; parameter p = 2; defparam m.n.p = 1; initial $display(m.n.p); generate if (p == 1) begin : m m2 n(); end endgenerate endmodule module m2; parameter p = 3; endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"bind cpu fpu_props fpu_rules_1(a,b,c);"##, Ok((_, _)) ); test!( many1(module_item), r##"bind cpu: cpu1 fpu_props fpu_rules_1(a, b, c);"##, Ok((_, _)) ); test!( many1(module_item), r##"bind cpu: cpu1, cpu2, cpu3 fpu_props fpu_rules_1(a, b, c);"##, Ok((_, _)) ); test!( many1(module_item), r##"interface range (input clk, enable, input var int minval, expr); property crange_en; @(posedge clk) enable |-> (minval <= expr); endproperty range_chk: assert property (crange_en); endinterface bind cr_unit range r1(c_clk,c_en,v_low,(in1&&in2));"##, Ok((_, _)) ); test!( many1(module_item), r##"bind targetmod mycheck #(.param1(const4), .param2(8'h44)) i_mycheck(.*, .p1(f1({v1, 1'b0, b1.c}, v2 & v3)), .p2(top.v4));"##, Ok((_, _)) ); } #[test] fn clause24() { test!( many1(module_item), r##"program test (input clk, input [16:1] addr, inout [7:0] data); endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"program test ( interface device_ifc ); endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"module test; int shared; // variable shared by programs p1 and p1 program p1; endprogram program p2; endprogram // p1 and p2 are implicitly instantiated once in module test endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; logic r; wire dw1, dw2; initial begin r = 0; #10 r = 1; end assign dw1 = r; p p_i(dw2, dw1); always @(dw2) $display("dw2 is %b", dw2); endmodule program p(output pw2, input pw1); assign pw2 = pw1; endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; task T; S1: a = b; // executes in reactive region set if called from a program #5; S2: b <= 1'b1; // executes in reactive region set if called from a program endtask endmodule"##, Ok((_, _)) ); } #[test] fn clause25() { test!( many1(module_item), r##"myinterface #(100) scalar1(), vector[9:0]();"##, Ok((_, _)) ); test!( many1(module_item), r##"module memMod( input logic req, logic clk, logic start, logic [1:0] mode, logic [7:0] addr, inout wire [7:0] data, output bit gnt, bit rdy ); logic avail; endmodule module cpuMod( input logic clk, logic gnt, logic rdy, inout wire [7:0] data, output logic req, logic start, logic [7:0] addr, logic [1:0] mode ); endmodule module top; logic req, gnt, start, rdy; logic clk = 0; logic [1:0] mode; logic [7:0] addr; wire [7:0] data; memMod mem(req, clk, start, mode, addr, data, gnt, rdy); cpuMod cpu(clk, gnt, rdy, data, req, start, addr, mode); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus; // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; endinterface: simple_bus module memMod(simple_bus a, // Access the simple_bus interface input logic clk); logic avail; // When memMod is instantiated in module top, a.req is the req // signal in the sb_intf instance of the 'simple_bus' interface always @(posedge clk) a.gnt <= a.req & avail; endmodule module cpuMod(simple_bus b, input logic clk); endmodule module top; logic clk = 0; simple_bus sb_intf(); // Instantiate the interface memMod mem(sb_intf, clk); // Connect the interface to the module instance cpuMod cpu(.b(sb_intf), .clk(clk)); // Either by position or by name endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module memMod (simple_bus sb_intf, input logic clk); endmodule module cpuMod (simple_bus sb_intf, input logic clk); endmodule module top; logic clk = 0; simple_bus sb_intf(); memMod mem (.*); // implicit port connections cpuMod cpu (.*); // implicit port connections endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module memMod (interface a, input logic clk); endmodule module cpuMod(interface b, input logic clk); endmodule interface simple_bus; // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; endinterface: simple_bus module top; logic clk = 0; simple_bus sb_intf(); // Instantiate the interface // Reference the sb_intf instance of the simple_bus // interface from the generic interfaces of the // memMod and cpuMod modules memMod mem (.a(sb_intf), .clk(clk)); cpuMod cpu (.b(sb_intf), .clk(clk)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module memMod (interface a, input logic clk); endmodule module cpuMod (interface b, input logic clk); endmodule module top; logic clk = 0; simple_bus sb_intf(); memMod mem (.*, .a(sb_intf)); // partial implicit port connections cpuMod cpu (.*, .b(sb_intf)); // partial implicit port connections endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface i1 (input a, output b, inout c); wire d; endinterface"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; endinterface: simple_bus module memMod(simple_bus a); // Uses just the interface logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; // a.req is in the 'simple_bus' interface endmodule module cpuMod(simple_bus b); endmodule module top; logic clk = 0; simple_bus sb_intf1(clk); // Instantiate the interface simple_bus sb_intf2(clk); // Instantiate the interface memMod mem1(.a(sb_intf1)); // Reference simple_bus 1 to memory 1 cpuMod cpu1(.b(sb_intf1)); memMod mem2(.a(sb_intf2)); // Reference simple_bus 2 to memory 2 cpuMod cpu2(.b(sb_intf2)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface i2; wire a, b, c, d; modport master (input a, b, output c, d); modport slave (output a, b, input c, d); endinterface"##, Ok((_, _)) ); test!( many1(module_item), r##"module m (i2.master i); endmodule module s (i2.slave i); endmodule module top; i2 i(); m u1(.i(i)); s u2(.i(i)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module m (i2 i); endmodule module s (i2 i); endmodule module top; i2 i(); m u1(.i(i.master)); s u2(.i(i.slave)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface i; wire x, y; interface illegal_i; wire a, b, c, d; // x, y not declared by this interface modport master(input a, b, x, output c, d, y); modport slave(output a, b, x, input c, d, y); endinterface : illegal_i endinterface : i interface illegal_i; // a, b, c, d not declared by this interface modport master(input a, b, output c, d); modport slave(output a, b, input c, d); endinterface : illegal_i"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; modport slave (input req, addr, mode, start, clk, output gnt, rdy, ref data); modport master(input gnt, rdy, clk, output req, addr, mode, start, ref data); endinterface: simple_bus module memMod (simple_bus.slave a); // interface name and modport name logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; // the gnt and req signal in the interface endmodule module cpuMod (simple_bus.master b); endmodule module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface initial repeat(10) #10 clk++; memMod mem(.a(sb_intf)); // Connect the interface to the module instance cpuMod cpu(.b(sb_intf)); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; modport slave (input req, addr, mode, start, clk, output gnt, rdy, ref data); modport master(input gnt, rdy, clk, output req, addr, mode, start, ref data); endinterface: simple_bus module memMod(simple_bus a); // Uses just the interface name logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; // the gnt and req signal in the interface endmodule module cpuMod(simple_bus b); endmodule module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface initial repeat(10) #10 clk++; memMod mem(sb_intf.slave); // Connect the modport to the module instance cpuMod cpu(sb_intf.master); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; modport slave (input req, addr, mode, start, clk, output gnt, rdy, ref data); modport master(input gnt, rdy, clk, output req, addr, mode, start, ref data); endinterface: simple_bus module memMod(interface a); // Uses just the interface logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; // the gnt and req signal in the interface endmodule module cpuMod(interface b); endmodule module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface memMod mem(sb_intf.slave); // Connect the modport to the module instance cpuMod cpu(sb_intf.master); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface I; logic [7:0] r; const int x=1; bit R; modport A (output .P(r[3:0]), input .Q(x), R); modport B (output .P(r[7:4]), input .Q(2), R); endinterface module M ( interface i); initial i.P = i.Q; endmodule module top; I i1 (); M u1 (i1.A); M u2 (i1.B); initial #1 $display("%b", i1.r); // displays 00100001 endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface A_Bus( input logic clk ); wire req, gnt; wire [7:0] addr, data; clocking sb @(posedge clk); input gnt; output req, addr; inout data; property p1; req ##[1:3] gnt; endproperty endclocking modport DUT ( input clk, req, addr, // Device under test modport output gnt, inout data ); modport STB ( clocking sb ); // synchronous testbench modport modport TB ( input gnt, // asynchronous testbench modport output req, addr, inout data ); endinterface"##, Ok((_, _)) ); test!( many1(module_item), r##"module dev1(A_Bus.DUT b); // Some device: Part of the design endmodule module dev2(A_Bus.DUT b); // Some device: Part of the design endmodule module top; logic clk; A_Bus b1( clk ); A_Bus b2( clk ); dev1 d1( b1 ); dev2 d2( b2 ); T tb( b1, b2 ); endmodule program T (A_Bus.STB b1, A_Bus.STB b2 ); // testbench: 2 synchronous ports assert property (b1.sb.p1); // assert property from within program initial begin b1.sb.req <= 1; wait( b1.sb.gnt == 1 ); b1.sb.req <= 0; b2.sb.req <= 1; wait( b2.sb.gnt == 1 ); b2.sb.req <= 0; end endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"interface itf; logic c,q,d; modport flop (input c,d, output q); endinterface module dtype (itf.flop ch); always_ff @(posedge ch.c) ch.q <= ch.d; specify ( posedge ch.c => (ch.q+:ch.d)) = (5,6); $setup( ch.d, posedge ch.c, 1 ); endspecify endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; task masterRead(input logic [7:0] raddr); // masterRead method // ... endtask: masterRead task slaveRead; // slaveRead method // ... endtask: slaveRead endinterface: simple_bus module memMod(interface a); // Uses any interface logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; // the gnt and req signals in the interface always @(a.start) a.slaveRead; endmodule module cpuMod(interface b); enum {read, write} instr; logic [7:0] raddr; always @(posedge b.clk) if (instr == read) b.masterRead(raddr); // call the Interface method endmodule module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface memMod mem(sb_intf); cpuMod cpu(sb_intf); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; modport slave (input req, addr, mode, start, clk, output gnt, rdy, ref data, import slaveRead, slaveWrite); // import into module that uses the modport modport master(input gnt, rdy, clk, output req, addr, mode, start, ref data, import masterRead, masterWrite); // import into module that uses the modport task masterRead(input logic [7:0] raddr); // masterRead method // ... endtask task slaveRead; // slaveRead method // ... endtask task masterWrite(input logic [7:0] waddr); //... endtask task slaveWrite; //... endtask endinterface: simple_bus module memMod(interface a); // Uses just the interface logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; // the gnt and req signals in the interface always @(a.start) if (a.mode[0] == 1'b0) a.slaveRead; else a.slaveWrite; endmodule module cpuMod(interface b); enum {read, write} instr; logic [7:0] raddr = $random(); always @(posedge b.clk) if (instr == read) b.masterRead(raddr); // call the Interface method else b.masterWrite(raddr); endmodule module omniMod( interface b); //... endmodule: omniMod module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface memMod mem(sb_intf.slave); // only has access to the slave tasks cpuMod cpu(sb_intf.master); // only has access to the master tasks omniMod omni(sb_intf); // has access to all master and slave tasks endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; modport slave( input req, addr, mode, start, clk, output gnt, rdy, ref data, export Read, Write); // export from module that uses the modport modport master(input gnt, rdy, clk, output req, addr, mode, start, ref data, import task Read(input logic [7:0] raddr), task Write(input logic [7:0] waddr)); // import requires the full task prototype endinterface: simple_bus module memMod(interface a); // Uses just the interface keyword logic avail; task a.Read; // Read method avail = 0; avail = 1; endtask task a.Write; avail = 0; avail = 1; endtask endmodule module cpuMod(interface b); enum {read, write} instr; logic [7:0] raddr; always @(posedge b.clk) if (instr == read) b.Read(raddr); // call the slave method via the interface else b.Write(raddr); endmodule module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface memMod mem(sb_intf.slave); // exports the Read and Write tasks cpuMod cpu(sb_intf.master); // imports the Read and Write tasks endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus (input logic clk); // Define the interface logic req, gnt; logic [7:0] addr, data; logic [1:0] mode; logic start, rdy; int slaves = 0; // tasks executed concurrently as a fork-join block extern forkjoin task countSlaves(); extern forkjoin task Read (input logic [7:0] raddr); extern forkjoin task Write (input logic [7:0] waddr); modport slave (input req,addr, mode, start, clk, output gnt, rdy, ref data, slaves, export Read, Write, countSlaves); // export from module that uses the modport modport master ( input gnt, rdy, clk, output req, addr, mode, start, ref data, import task Read(input logic [7:0] raddr), task Write(input logic [7:0] waddr)); // import requires the full task prototype initial begin slaves = 0; countSlaves; $display ("number of slaves = %d", slaves); end endinterface: simple_bus module memMod #(parameter int minaddr=0, maxaddr=0) (interface a); logic avail = 1; logic [7:0] mem[255:0]; task a.countSlaves(); a.slaves++; endtask task a.Read(input logic [7:0] raddr); // Read method if (raddr >= minaddr && raddr <= maxaddr) begin avail = 0; #10 a.data = mem[raddr]; avail = 1; end endtask task a.Write(input logic [7:0] waddr); // Write method if (waddr >= minaddr && waddr <= maxaddr) begin avail = 0; #10 mem[waddr] = a.data; avail = 1; end endtask endmodule module cpuMod(interface b); typedef enum {read, write} instr; instr inst; logic [7:0] raddr; integer seed; always @(posedge b.clk) begin inst = instr'($dist_uniform(seed, 0, 1)); raddr = $dist_uniform(seed, 0, 3); if (inst == read) begin $display("%t begin read %h @ %h", $time, b.data, raddr); callr:b.Read(raddr); $display("%t end read %h @ %h", $time, b.data, raddr); end else begin $display("%t begin write %h @ %h", $time, b.data, raddr); b.data = raddr; callw:b.Write(raddr); $display("%t end write %h @ %h", $time, b.data, raddr); end end endmodule module top; logic clk = 0; function void interrupt(); disable mem1.a.Read; // task via module instance disable sb_intf.Write; // task via interface instance if (mem1.avail == 0) $display ("mem1 was interrupted"); if (mem2.avail == 0) $display ("mem2 was interrupted"); endfunction always #5 clk++; initial begin #28 interrupt(); #10 interrupt(); #100 $finish; end simple_bus sb_intf(clk); memMod #(0, 127) mem1(sb_intf.slave); memMod #(128, 255) mem2(sb_intf.slave); cpuMod cpu(sb_intf.master); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface simple_bus #(AWIDTH = 8, DWIDTH = 8) (input logic clk); // Define the interface logic req, gnt; logic [AWIDTH-1:0] addr; logic [DWIDTH-1:0] data; logic [1:0] mode; logic start, rdy; modport slave( input req, addr, mode, start, clk, output gnt, rdy, ref data, import task slaveRead, task slaveWrite); // import into module that uses the modport modport master(input gnt, rdy, clk, output req, addr, mode, start, ref data, import task masterRead(input logic [AWIDTH-1:0] raddr), task masterWrite(input logic [AWIDTH-1:0] waddr)); // import requires the full task prototype task masterRead(input logic [AWIDTH-1:0] raddr); // masterRead method endtask task slaveRead; // slaveRead method endtask task masterWrite(input logic [AWIDTH-1:0] waddr); endtask task slaveWrite; endtask endinterface: simple_bus module memMod(interface a); // Uses just the interface keyword logic avail; always @(posedge a.clk) // the clk signal from the interface a.gnt <= a.req & avail; //the gnt and req signals in the interface always @(a.start) if (a.mode[0] == 1'b0) a.slaveRead; else a.slaveWrite; endmodule module cpuMod(interface b); enum {read, write} instr; logic [7:0] raddr; always @(posedge b.clk) if (instr == read) b.masterRead(raddr); // call the Interface method else b.masterWrite(raddr); endmodule module top; logic clk = 0; simple_bus sb_intf(clk); // Instantiate default interface simple_bus #(.DWIDTH(16)) wide_intf(clk); // Interface with 16-bit data initial repeat(10) #10 clk++; memMod mem(sb_intf.slave); // only has access to the slaveRead task cpuMod cpu(sb_intf.master); // only has access to the masterRead task memMod memW(wide_intf.slave); // 16-bit wide memory cpuMod cpuW(wide_intf.master); // 16-bit wide cpu endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface SBus; // A Simple bus interface logic req, grant; logic [7:0] addr, data; endinterface class SBusTransactor; // SBus transactor class virtual SBus bus; // virtual interface of type SBus function new( virtual SBus s ); bus = s; // initialize the virtual interface endfunction task request(); // request the bus bus.req <= 1'b1; endtask task wait_for_bus(); // wait for the bus to be granted @(posedge bus.grant); endtask endclass module devA( SBus s ); endmodule // devices that use SBus module devB( SBus s ); endmodule module top; SBus s[1:4] (); // instantiate 4 interfaces devA a1( s[1] ); // instantiate 4 devices devB b1( s[2] ); devA a2( s[3] ); devB b2( s[4] ); initial begin SBusTransactor t[1:4]; // create 4 bus-transactors and bind t[1] = new( s[1] ); t[2] = new( s[2] ); t[3] = new( s[3] ); t[4] = new( s[4] ); // test t[1:4] end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface PBus #(parameter WIDTH=8); // A parameterized bus interface logic req, grant; logic [WIDTH-1:0] addr, data; modport phy(input addr, ref data); endinterface module top; PBus #(16) p16(); PBus #(32) p32(); virtual PBus v8; // legal declaration, but no legal assignments virtual PBus #(35) v35; // legal declaration, but no legal assignments virtual PBus #(16) v16; virtual PBus #(16).phy v16_phy; virtual PBus #(32) v32; virtual PBus #(32).phy v32_phy; initial begin v16 = p16; // legal – parameter values match v32 = p32; // legal – parameter values match v16 = p32; // illegal – parameter values don't match v16 = v32; // illegal – parameter values don't match v16_phy = v16; // legal assignment from no selected modport to // selected modport v16 = v16_phy; // illegal assignment from selected modport to // no selected modport v32_phy = p32; // legal assignment from no selected modport to // selected modport v32 = p32.phy; // illegal assignment from selected modport to // no selected modport end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface SyncBus( input logic clk ); wire a, b, c; clocking sb @(posedge clk); input a; output b; inout c; endclocking endinterface typedef virtual SyncBus VI; // A virtual interface type task do_it( VI v ); // handles any SyncBus via clocking sb if( v.sb.a == 1 ) v.sb.b <= 0; else v.sb.c <= ##1 1; endtask"##, Ok((_, _)) ); test!( many1(module_item), r##"module top; logic clk; SyncBus b1( clk ); SyncBus b2( clk ); initial begin VI v[2] = '{ b1, b2 }; repeat( 20 ) do_it( v[ $urandom_range( 0, 1 ) ] ); end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"interface A_Bus( input logic clk ); wire req, gnt; wire [7:0] addr, data; clocking sb @(posedge clk); input gnt; output req, addr; inout data; property p1; req ##[1:3] gnt; endproperty endclocking modport DUT ( input clk, req, addr, // Device under test modport output gnt, inout data ); modport STB ( clocking sb ); // synchronous testbench modport modport TB ( input gnt, // asynchronous testbench modport output req, addr, inout data ); endinterface"##, Ok((_, _)) ); test!( many1(module_item), r##"module dev1(A_Bus.DUT b); // Some device: Part of the design endmodule module dev2(A_Bus.DUT b); // Some device: Part of the design endmodule program T (A_Bus.STB b1, A_Bus.STB b2 ); // Testbench: 2 synchronous ports endprogram module top; logic clk; A_Bus b1( clk ); A_Bus b2( clk ); dev1 d1( b1 ); dev2 d2( b2 ); T tb( b1, b2 ); endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"program T (A_Bus.STB b1, A_Bus.STB b2 ); // Testbench: 2 synchronous ports typedef virtual A_Bus.STB SYNCTB; task request( SYNCTB s ); s.sb.req <= 1; endtask task wait_grant( SYNCTB s ); wait( s.sb.gnt == 1 ); endtask task drive(SYNCTB s, logic [7:0] adr, data ); if( s.sb.gnt == 0 ) begin request(s); // acquire bus if needed wait_grant(s); end s.sb.addr = adr; s.sb.data = data; repeat(2) @s.sb; s.sb.req = 0; //release bus endtask assert property (b1.sb.p1); // assert property from within program initial begin drive( b1, $random, $random ); drive( b2, $random, $random ); end endprogram"##, Ok((_, _)) ); test!( many1(module_item), r##"interface ebus_i; integer I; // reference to I not allowed through modport mp typedef enum {Y,N} choice; choice Q; localparam True = 1; modport mp(input Q); endinterface module Top; ebus_i ebus (); sub s1 (ebus.mp); endmodule module sub(interface.mp i); typedef i.choice yes_no; // import type from interface yes_no P; assign P = i.Q; // refer to Q with a port reference initial Top.ebus.Q = i.True; // refer to Q with a hierarchical reference initial Top.ebus.I = 0; // referring to i.I would not be legal because // is not in modport mp endmodule"##, Ok((_, _)) ); } #[test] fn clause26() { test!( source_text, r##"package ComplexPkg; typedef struct { shortreal i, r; } Complex; function Complex add(Complex a, b); add.r = a.r + b.r; add.i = a.i + b.i; endfunction function Complex mul(Complex a, b); mul.r = (a.r * b.r) - (a.i * b.i); mul.i = (a.r * b.i) + (a.i * b.r); endfunction endpackage : ComplexPkg"##, Ok((_, _)) ); test!( many1(module_item), r##"import ComplexPkg::Complex; import ComplexPkg::add;"##, Ok((_, _)) ); test!( source_text, r##"package p; typedef enum { FALSE, TRUE } bool_t; endpackage package q; typedef enum { ORIGINAL, FALSE } teeth_t; endpackage module top1 ; import p::*; import q::teeth_t; teeth_t myteeth; initial begin myteeth = q:: FALSE; // OK: myteeth = FALSE; // ERROR: Direct reference to FALSE refers to the end // FALSE enumeration literal imported from p endmodule module top2 ; import p::*; import q::teeth_t, q::ORIGINAL, q::FALSE; teeth_t myteeth; initial begin myteeth = FALSE; // OK: Direct reference to FALSE refers to the end // FALSE enumeration literal imported from q endmodule"##, Ok((_, _)) ); test!(many1(module_item), r##"import ComplexPkg::*;"##, Ok((_, _))); test!( source_text, r##"package p; int x; endpackage module top; import p::*; // line 1 if (1) begin : b initial x = 1; // line 2 int x; // line 3 initial x = 1; // line 4 end int x; // line 5 endmodule"##, Ok((_, _)) ); test!( source_text, r##"package p; int x; endpackage package p2; int x; endpackage module top; import p::*; // line 1 if (1) begin : b initial x = 1; // line 2 import p2::*; // line 3 end endmodule"##, Ok((_, _)) ); test!( source_text, r##"package p; function int f(); return 1; endfunction endpackage module top; int x; if (1) begin : b initial x = f(); // line 2 import p::*; // line 3 end function int f(); return 1; endfunction endmodule"##, Ok((_, _)) ); test!( source_text, r##"package p; function int f(); return 1; endfunction endpackage package p2; function int f(); return 1; endfunction endpackage module top; import p::*; int x; if (1) begin : b initial x = f(); // line 1 end import p2::*; endmodule"##, Ok((_, _)) ); test!( source_text, r##"package A; typedef struct { bit [ 7:0] opcode; bit [23:0] addr; } instruction_t; endpackage: A package B; typedef enum bit {FALSE, TRUE} boolean_t; endpackage: B module M import A::instruction_t, B::*; #(WIDTH = 32) (input [WIDTH-1:0] data, input instruction_t a, output [WIDTH-1:0] result, output boolean_t OK ); endmodule: M"##, Ok((_, _)) ); test!( source_text, r##"package p; typedef enum { FALSE, TRUE } BOOL; const BOOL c = FALSE; endpackage package q; const int c = 0; endpackage"##, Ok((_, _)) ); test!( many1(module_item), r##"module m; import q::*; wire a = c; // This statement forces the import of q::c; import p::c; // The conflict with q::c and p::c creates an error. endmodule"##, Ok((_, _)) ); test!( source_text, r##"package p1; int x, y; endpackage package p2; import p1::x; export p1::*; // exports p1::x as the name "x"; // p1::x and p2::x are the same declaration endpackage package p3; import p1::*; import p2::*; export p2::*; int q = x; // p1::x and q are made available from p3. Although p1::y // is a candidate for import, it is not actually imported // since it is not referenced. Since p1::y is not imported, // it is not made available by the export. endpackage package p4; import p1::*; export p1::*; int y = x; // y is available as a direct declaration; // p1::x is made available by the export endpackage package p5; import p4::*; import p1::*; export p1::x; export p4::x; // p4::x refers to the same declaration // as p1::x so this is legal. endpackage package p6; import p1::*; export p1::x; int x; // Error. export p1::x is considered to // be a reference to "x" so a subsequent // declaration of x is illegal. endpackage package p7; int y; endpackage package p8; export *::*; // Exports both p7::y and p1::x. import p7::y; import p1::x; endpackage module top; import p2::*; import p4::*; int y = x; // x is p1::x endmodule"##, Ok((_, _)) ); // TODO // Syntax 26-5 (not in Annex A) //test!( // many1(module_item), // r##"initial begin // std::sys_task(); // end"##, // Ok((_, _)) //); } #[test] fn clause27() { test!( many1(module_item), r##"module mod_a; genvar i; // "generate", "endgenerate" keywords are not required for (i=0; i<5; i=i+1) begin:a for (i=0; i<5; i=i+1) begin:b end end endmodule module mod_b; genvar i; logic a; for (i=1; i<0; i=i+1) begin: a end endmodule module mod_c; genvar i; for (i=1; i<5; i=i+1) begin: a end for (i=10; i<15; i=i+1) begin: a end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module gray2bin1 (bin, gray); parameter SIZE = 8; // this module is parameterizable output [SIZE-1:0] bin; input [SIZE-1:0] gray; genvar i; generate for (i=0; i0) begin:B4 // scope B1[i].B4 for (m=0; m q) = (tRise_clk_q, tFall_clk_q); $setup(d, posedge clk, tSetup); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"module XORgate (a, b, out); input a, b; output out; xor x1 (out, a, b); specify specparam noninvrise = 1, noninvfall = 2; specparam invertrise = 3, invertfall = 4; if (a) (b => out) = (invertrise, invertfall); if (b) (a => out) = (invertrise, invertfall); if (~a)(b => out) = (noninvrise, noninvfall); if (~b)(a => out) = (noninvrise, noninvfall); endspecify endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"module ALU (o1, i1, i2, opcode); input [7:0] i1, i2; input [2:1] opcode; output [7:0] o1; //functional description omitted specify // add operation if (opcode == 2'b00) (i1,i2 *> o1) = (25.0, 25.0); // pass-through i1 operation if (opcode == 2'b01) (i1 => o1) = (5.6, 8.0); // pass-through i2 operation if (opcode == 2'b10) (i2 => o1) = (5.6, 8.0); // delays on opcode changes (opcode *> o1) = (6.1, 6.5); endspecify endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"specify ( posedge clk => ( q[0] : data ) ) = (10, 5); ( negedge clk => ( q[0] : data ) ) = (20, 12); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify if (reset) (posedge clk => ( q[0] : data ) ) = (15, 8); if (!reset && cntrl) (posedge clk => ( q[0] : data ) ) = (6, 2); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify if (reset) (posedge clk => (q[3:0]:data)) = (10,5); if (!reset) (posedge clk => (q[0]:data)) = (15,8); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"module mux8 (in1, in2, s, q) ; output [7:0] q; input [7:0] in1, in2; input s; // Functional description omitted ... specify (in1 => q) = (3, 4) ; (in2 => q) = (2, 3) ; (s *> q) = 1; endspecify endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"specify // Specify Parameters specparam tRise_clk_q = 45:150:270, tFall_clk_q=60:200:350; specparam tRise_Control = 35:40:45, tFall_control=40:50:65; // Module Path Assignments (clk => q) = (tRise_clk_q, tFall_clk_q); (clr, pre *> q) = (tRise_control, tFall_control); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify // one expression specifies all transitions (C => Q) = 20; (C => Q) = 10:14:20; // two expressions specify rise and fall delays specparam tPLH1 = 12, tPHL1 = 25; specparam tPLH2 = 12:16:22, tPHL2 = 16:22:25; (C => Q) = ( tPLH1, tPHL1 ) ; (C => Q) = ( tPLH2, tPHL2 ) ; // three expressions specify rise, fall, and z transition delays specparam tPLH1 = 12, tPHL1 = 22, tPz1 = 34; specparam tPLH2 = 12:14:30, tPHL2 = 16:22:40, tPz2 = 22:30:34; (C => Q) = (tPLH1, tPHL1, tPz1); (C => Q) = (tPLH2, tPHL2, tPz2); // six expressions specify transitions to/from 0, 1, and z specparam t01 = 12, t10 = 16, t0z = 13, tz1 = 10, t1z = 14, tz0 = 34 ; (C => Q) = ( t01, t10, t0z, tz1, t1z, tz0) ; specparam T01 = 12:14:24, T10 = 16:18:20, T0z = 13:16:30 ; specparam Tz1 = 10:12:16, T1z = 14:23:36, Tz0 = 15:19:34 ; (C => Q) = ( T01, T10, T0z, Tz1, T1z, Tz0) ; // twelve expressions specify all transition delays explicitly specparam t01=10, t10=12, t0z=14, tz1=15, t1z=29, tz0=36, t0x=14, tx1=15, t1x=15, tx0=14, txz=20, tzx=30 ; (C => Q) = (t01, t10, t0z, tz1, t1z, tz0, t0x, tx1, t1x, tx0, txz, tzx) ; endspecify"##, Ok((_, _)) ); // TODO // specify_input_terminal_descriptor can have $ //test!( // many1(module_item), // r##"specify // (clk => q) = 12; // (data => q) = 10; // (clr, pre *> q) = 4; // specparam // PATHPULSE$clk$q = (2,9), // PATHPULSE$clr$q = (0,4), // PATHPULSE$ = 3; // endspecify"##, // Ok((_, _)) //); test!( many1(module_item), r##"specify (a=>out)=(2,3); (b =>out)=(3,4); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify (a=>out)=(2,3); showcancelled out; (b =>out)=(3,4); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify showcancelled out; pulsestyle_ondetect out; (a => out) = (2,3); (b => out) = (4,5); showcancelled out_b; pulsestyle_ondetect out_b; (a => out_b) = (3,4); (b => out_b) = (5,6); endspecify specify showcancelled out,out_b; pulsestyle_ondetect out,out_b; (a => out) = (2,3); (b => out) = (4,5); (a => out_b) = (3,4); (b => out_b) = (5,6); endspecify"##, Ok((_, _)) ); } #[test] fn clause31() { test!( many1(module_item), r##"specify $setuphold( posedge clk, data, tSU, tHLD ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup( data, posedge clk, tSU ); $hold( posedge clk, data, tHLD ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $recrem( posedge clear, posedge clk, tREC, tREM ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $removal( posedge clear, posedge clk, tREM ); $recovery( posedge clear, posedge clk, tREC ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $timeskew (posedge CP &&& MODE, negedge CPN, 50, , event_based_flag, remain_active_flag); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $fullskew (posedge CP &&& MODE, negedge CPN, 50, 70,, event_based_flag, remain_active_flag); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $width (posedge clk, 6, 0, ntfr_reg); endspecify"##, Ok((_, _)) ); // TODO // $width must have threshold //test!( // many1(module_item), // r##"specify // // Legal Calls // $width ( negedge clr, lim ); // $width ( negedge clr, lim, thresh, notif ); // $width ( negedge clr, lim, 0, notif ); // // Illegal Calls // //$width ( negedge clr, lim, , notif ); // //$width ( negedge clr, lim, notif ); // endspecify"##, // Ok((_, _)) //); test!( many1(module_item), r##"specify $nochange( posedge clk, data, 0, 0) ; endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup( data, posedge clk, 10, notifier ) ; $width( posedge clk, 16, 0, notifier ) ; endspecify"##, Ok((_, _)) ); test!( source_text, r##"primitive posdff_udp(q, clock, data, preset, clear, notifier); output q; reg q; input clock, data, preset, clear, notifier; table //clock data p c notifier state q //------------------------------------- r 0 1 1 ? : ? : 0 ; r 1 1 1 ? : ? : 1 ; p 1 ? 1 ? : 1 : 1 ; p 0 1 ? ? : 0 : 0 ; n ? ? ? ? : ? : - ; ? * ? ? ? : ? : - ; ? ? 0 1 ? : ? : 1 ; ? ? * 1 ? : 1 : 1 ; ? ? 1 0 ? : ? : 0 ; ? ? 1 * ? : 0 : 0 ; ? ? ? ? * : ? : x ;// At any notifier event // output x endtable endprimitive module dff(q, qbar, clock, data, preset, clear); output q, qbar; input clock, data, preset, clear; reg notifier; and (enable, preset, clear); not (qbar, ffout); buf (q, ffout); posdff_udp (ffout, clock, data, preset, clear, notifier); specify // Define timing check specparam values specparam tSU = 10, tHD = 1, tPW = 25, tWPC = 10, tREC = 5; // Define module path delay rise and fall min:typ:max values specparam tPLHc = 4:6:9 , tPHLc = 5:8:11; specparam tPLHpc = 3:5:6 , tPHLpc = 4:7:9; // Specify module path delays (clock *> q,qbar) = (tPLHc, tPHLc); (preset,clear *> q,qbar) = (tPLHpc, tPHLpc); // Setup time : data to clock, only when preset and clear are 1 $setup(data, posedge clock &&& enable, tSU, notifier); // Hold time: clock to data, only when preset and clear are 1 $hold(posedge clock, data &&& enable, tHD, notifier); // Clock period check $period(posedge clock, tPW, notifier); // Pulse width : preset, clear $width(negedge preset, tWPC, 0, notifier); $width(negedge clear, tWPC, 0, notifier); // Recovery time: clear or preset to clock $recovery(posedge preset, posedge clock, tREC, notifier); $recovery(posedge clear, posedge clock, tREC, notifier); endspecify endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup( data, posedge clk, 10 ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup( data, posedge clk &&& clr, 10 ) ; endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup( data, posedge clk &&& (~clr), 10 ) ; $setup( data, posedge clk &&& (clr===0), 10 ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup( data, posedge clk &&& clr_and_set, 10 ); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"module DFF (Q, CLK, DAT); input CLK; input [7:0] DAT; output [7:0] Q; always @(posedge clk) Q = DAT; specify $setup (DAT, posedge CLK, 10); endspecify endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setuphold(posedge CLK, DATA, -10, 20); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setuphold(posedge CLK, DATA1, -10, 20); $setuphold(posedge CLK, DATA2, -15, 18); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setuphold(posedge CLK, DATA1, -10, 20,,,, del_CLK, del_DATA1); $setuphold(posedge CLK, DATA2, -15, 18); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify (CLK => Q) = 6; $setuphold (posedge CLK, posedge D, -3, 8, , , , dCLK, dD); $setuphold (posedge CLK, negedge D, -7, 13, , , , dCLK, dD); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setup (data, clk &&& cond1, tsetup, ntfr); $hold (clk, data &&& cond1, thold, ntfr); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"specify $setuphold( clk, data, tsetup, thold, ntfr, , cond1); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"assign TE_cond_D = (dTE !== 1'b1); assign TE_cond_TI = (dTE !== 1'b0); assign DXTI_cond = (dTI !== dD); specify $setuphold(posedge CP, D, -10, 20, notifier, ,TE_cond_D, dCP, dD); $setuphold(posedge CP, TI, 20, -10, notifier, ,TE_cond_TI, dCP, dTI); $setuphold(posedge CP, TE, -4, 8, notifier, ,DXTI_cond, dCP, dTE); endspecify"##, Ok((_, _)) ); } #[test] fn clause32() { test!( many1(module_item), r##"specify $setuphold (posedge clk &&& mode, data, 1, 1, ntfr); $setuphold (negedge clk &&& !mode, data, 1, 1, ntfr); $setuphold (edge clk, data, 1, 1, ntfr); endspecify"##, Ok((_, _)) ); test!( many1(module_item), r##"module clock(clk); output clk; reg clk; specparam dhigh=0, dlow=0; initial clk = 0; always begin #dhigh clk = 1; // Clock remains low for time dlow // before transitioning to 1 #dlow clk = 0; // Clock remains high for time dhigh // before transitioning to 0 end endmodule"##, Ok((_, _)) ); test!( many1(module_item), r##"specparam cap = 0; specify (A => Z) = 1.4 * cap + 0.7; endspecify"##, Ok((_, _)) ); } #[test] fn clause33() { test!( source_text, r##"config cfg1; // specify rtl adder for top.a1, gate-level adder for top.a2 design rtlLib.top; default liblist rtlLib; instance top.a2 liblist gateLib; endconfig"##, Ok((_, _)) ); test!( library_text, r##"library rtlLib *.v; // matches all files in the current directory with // a .v suffix library gateLib ./*.vg; // matches all files in the current directory with // a .vg suffix"##, Ok((_, _)) ); test!( source_text, r##"config bot; design lib1.bot; default liblist lib1 lib2; instance bot.a1 liblist lib3; endconfig config top; design lib1.top; default liblist lib2 lib1; instance top.bot use lib1.bot:config; instance top.bot.a1 liblist lib4; // ERROR - cannot set liblist for top.bot.a1 from this config endconfig"##, Ok((_, _)) ); // TODO // use don't have #() //test!( // source_text, // r##"config cfgl; // design rtlLib.top; // instance top use #(.WIDTH(32)); // instance top.a1 use #(.W(top.WIDTH)); // endconfig"##, // Ok((_, _)) //); // TODO // use don't have #() //test!( // source_text, // r##"module top4 (); // parameter S = 16; // adder a1 #(.ID("a1"))(); // adder a2 #(.ID("a2"))(); // adder a3 #(.ID("a3"))(); // adder a4 #(.ID("a4"))(); // endmodule // config cfg2; // localparam S = 24; // design rtlLib.top4; // instance top4.a1 use #(.W(top4.S)); // instance top4.a2 use #(.W(S)); // endconfig"##, // Ok((_, _)) //); // TODO // use don't have #() //test!( // source_text, // r##"config cfg3; // design rtlLib.top5; // instance top5.a1 use #(.W()); // set only parameter W back to its default // endconfig"##, // Ok((_, _)) //); // TODO // use don't have #() //test!( // source_text, // r##"config cfg4; // design rtlLib.top; // instance top.a1 use #(); // set all parameters in instance a1 // // back to their defaults // endconfig"##, // Ok((_, _)) //); // TODO // use don't have #() //test!( // source_text, // r##"module test; // top8 t(); // defparam t.WIDTH = 64; // defparam t.a1.W = 16; // endmodule // module top8 (); // parameter WIDTH = 32; // adder a1 #(.ID("a1")) (); // adder a2 #(.ID("a2"),.W(WIDTH))(); // endmodule // module adder #(parameter ID = "id", // W = 8, // D = 512) // (); // $display("ID = %s, W = %d, D = %d", ID, W, D); // endmodule // config cfg6; // design rtlLib.test; // instance test.t use #(.WIDTH(48)); // endconfig"##, // Ok((_, _)) //); test!( source_text, r##"config cfg1; design rtlLib.top ; default liblist aLib rtlLib; endconfig"##, Ok((_, _)) ); test!( source_text, r##"config cfg2; design rtlLib.top ; default liblist gateLib aLib rtlLib; endconfig"##, Ok((_, _)) ); test!( source_text, r##"config cfg3; design rtlLib.top ; default liblist aLib rtlLib; cell m use gateLib.m ; endconfig"##, Ok((_, _)) ); test!( source_text, r##"config cfg4; design rtlLib.top ; default liblist gateLib rtlLib; instance top.a2 liblist aLib; endconfig"##, Ok((_, _)) ); test!( source_text, r##"config cfg5; design aLib.adder; default liblist gateLib aLib; instance adder.f1 liblist rtlLib; endconfig"##, Ok((_, _)) ); test!( source_text, r##"config cfg6; design rtlLib.top; default liblist aLib rtlLib; instance top.a2 use work.cfg5:config ; endconfig"##, Ok((_, _)) ); test!( library_text, r##"library lib1 "/proj/lib/foo*.v"; library lib2 "/proj/lib/foo.v"; library lib3 "../lib/"; library lib4 "/proj/lib/*ver.v";"##, Ok((_, _)) ); } #[test] fn clause34() { test!( source_text, r##"module secret (a, b); input a; output b; `pragma protect encoding=(enctype="raw") `pragma protect data_method="x-caesar", data_keyname="rot13", begin `pragma protect runtime_license=(library="lic.so",feature="runSecret",entry="chk", match=42) logic b; initial begin b = 0; end always begin #5 b = a; end `pragma protect end endmodule // secret"##, Ok((_, _)) ); test!( source_text, r##"module secret (a, b); input a; output b; `pragma protect encoding=(enctype="raw") `pragma protect data_method="x-caesar", data_keyname="rot13", begin_protected `pragma protect encoding=(enctype="raw", bytes=190), data_block //`centzn cebgrpg ehagvzr_yvprafr=(yvoenel="yvp.fb",srngher="ehaFrperg", //ragel="pux",zngpu=42) // ert o; // vavgvny // ortva // o = 0; // raq // nyjnlf // ortva // #5 o = n; // raq `pragma protect end_protected `pragma reset protect endmodule // secret"##, Ok((_, _)) ); } #[test] fn clause35() { // TODO // c_identifier can't accept \begin. //test!( // source_text, // r##"export "DPI-C" f_plus = function \f+ ; // "f+" exported as "f_plus" // export "DPI-C" function f; // "f" exported under its own name // import "DPI-C" init_1 = function void \init[1] (); // "init_1" is a linkage name // import "DPI-C" \begin = function void \init[2] (); // "begin" is a linkage name"##, // Ok((_, _)) //); test!( source_text, r##"import "DPI-C" function void myInit(); // from standard math library import "DPI-C" pure function real sin(real); // from standard C library: memory management import "DPI-C" function chandle malloc(int size); // standard C function import "DPI-C" function void free(chandle ptr); // standard C function // abstract data structure: queue import "DPI-C" function chandle newQueue(input string name_of_queue); // Note the following import uses the same foreign function for // implementation as the prior import, but has different SystemVerilog name // and provides a default value for the argument. import "DPI-C" newQueue=function chandle newAnonQueue(input string s=null); import "DPI-C" function chandle newElem(bit [15:0]); import "DPI-C" function void enqueue(chandle queue, chandle elem); import "DPI-C" function chandle dequeue(chandle queue); // miscellanea import "DPI-C" function bit [15:0] getStimulus(); import "DPI-C" context function void processTransaction(chandle elem, output logic [64:1] arr [0:63]); import "DPI-C" task checkResults(input string s, bit [511:0] packet);"##, Ok((_, _)) ); test!( source_text, r##"import "DPI-C" function void f1(input logic [127:0]); import "DPI-C" function void f2(logic [127:0] i []); //open array of 128-bit"##, Ok((_, _)) ); test!( source_text, r##"import "DPI-C" function void f3(input MyType i [][]); /* 2-dimensional unsized unpacked array of MyType */"##, Ok((_, _)) ); } #[test] fn clause36() { test!( many1(module_item), r##"initial begin $get_vector("test_vector.pat", input_bus); end"##, Ok((_, _)) ); test!( many1(module_item), r##"initial begin for (i = 1; i <= 1024; i = i + 1) @(posedge clk) $get_vector("test_vector.pat", input_bus); end"##, Ok((_, _)) ); } } #[test] fn debug() { nom_tracable::cumulative_histogram(); }