2019-11-06 15:11:59 +09:00

15856 lines
540 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#![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!(comment, "/* comment\n//aaa\n */", Ok((_, _)));
test!(comment, "/*! comment\n * aaa\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((_, _)));
test!(
source_text,
r##"module test(out);
`define nest_two
`ifdef wow
initial $display("wow is defined");
`else
initial $display("wow is not defined");
`endif
endmodule"##,
Ok((_, _))
);
}
#[test]
fn test_regression() {
test!(
source_text,
r##"package pkg; localparam [5:0] RES = RES5[0]; endpackage"##,
Ok((_, _))
);
test!(
source_text,
r##"interface intf (); localparam TYPE DEFAULT = TYPE'(0); endinterface"##,
Ok((_, _))
);
test!(source_text, r##"`macro(A, B, logic, C)"##, Ok((_, _)));
test!(source_text, r##"`macro(A, B, logic, a())"##, Ok((_, _)));
test!(
source_text,
r##"module ibex_cs_registers;
localparam logic [31:0] MISA_VALUE = 32'(RV32E);
endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"module ibex_cs_registers;
localparam logic [31:0] MISA_VALUE = (32'(RV32E));
endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"module a; always_comb if ( a ? b : c ) begin end endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"module SimDTM; assign #0.1 debug_req_valid = __debug_req_valid; endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"`define LONG_MACRO(
a,
b, c) text goes here"##,
Ok((_, _))
);
test!(
source_text,
r##"class A; static uvm_pool#(string,uvm_resource#(T)) m_rsc[uvm_component]; endclass"##,
Ok((_, _))
);
test!(
source_text,
r##"module a; initial begin elements.push_back(urme_container.elements[i].clone()); end endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"class a; function a b(); return this.a.b(); endfunction endclass"##,
Ok((_, _))
);
test!(
source_text,
r##"class a; const local a b = new("a"); endclass"##,
Ok((_, _))
);
test!(
source_text,
r##"module a; initial begin #a.b; end endmodule"##,
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((_, _))
);
// BNF-WA
// reported at https://accellera.mantishub.io/view.php?id=1642
// 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 = {<<byte{p.header, p.len, p.payload with [0 +: p.len], p.crc}};
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
q = {<<byte{p.header, p.len, p.payload with [0 : p.len-1], p.crc}};
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
q = {<<byte{p}};
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
logic [31: 0] a_vect;
logic [0 :31] b_vect;
logic [63: 0] dword;
integer sel;
a = a_vect[ 0 +: 8]; // == a_vect[ 7 : 0]
a = a_vect[15 -: 8]; // == a_vect[15 : 8]
a = b_vect[ 0 +: 8]; // == b_vect[0 : 7]
a = b_vect[15 -: 8]; // == b_vect[8 :15]
a = dword[8*sel +: 8]; // variable part-select with fixed width
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"logic [15:0] acc;
logic [2:17] acc;"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
logic [7:0] vect;
vect = 4; // fills vect with the pattern 00000100
// msb is bit 7, lsb is bit 0
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"logic [7:0] mem_name[0:1023];"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"logic [7:0] twod_array[0:255][0:255];
wire threed_array[0:255][0:255][0:7];"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
localparam p = 7;
reg [7:0] m [5:1][5:1];
integer i;
a = m[1][i]; // longest static prefix is m[1]
a = m[p][1]; // longest static prefix is m[p][1]
a = m[i][1]; // longest static prefix is m
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
logic [15:0] a, b; // 16-bit variables
logic [15:0] sumA; // 16-bit variable
logic [16:0] sumB; // 17-bit variable
sumA = a + b; // expression evaluates using 16 bits
sumB = a + b; // expression evaluates using 17 bits
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
logic [15:0] a, b, answer; // 16-bit variables
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
answer = (a + b) >> 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<DECODE_W; i++) begin
if(DecodeIn[i]) begin
ENCODER_f = i[ENCODE_W-1:0];
break;
end
end
endfunction
static function logic [DECODE_W-1:0] DECODER_f
(input logic [ENCODE_W-1:0] EncodeIn);
DECODER_f = '0;
DECODER_f[EncodeIn] = 1'b1;
endfunction
endclass"##,
Ok((_, _))
);
// BNF-WA
// reported at https://accellera.mantishub.io/view.php?id=1642
// class static method is denied because ps_or_hierarchical_tf_identifier doesn't have class_scope.
test!(
many1(module_item),
r##"module top ();
logic [7:0] encoder_in;
logic [2:0] encoder_out;
logic [1:0] decoder_in;
logic [3:0] decoder_out;
// Encoder and Decoder Input Assignments
assign encoder_in = 8'b0100_0000;
assign decoder_in = 2'b11;
// Encoder and Decoder Function calls
assign encoder_out = C#(8)::ENCODER_f(encoder_in);
assign decoder_out = C#(4)::DECODER_f(decoder_in);
initial begin
#50;
$display("Encoder input = %b Encoder output = %b\n",
encoder_in, encoder_out );
$display("Decoder input = %b Decoder output = %b\n",
decoder_in, decoder_out );
end
endmodule"##,
Ok((_, _))
);
}
#[test]
fn clause14() {
test!(
many1(module_item),
r##"clocking ck1 @(posedge clk);
default input #1step output negedge; // legal
// outputs driven on the negedge clk
endclocking
clocking ck2 @(clk); // no edge specified!
default input #1step output negedge; // legal
endclocking"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"clocking bus @(posedge clock1);
default input #10ns output #2ns;
input data, ready, enable = top.mem1.enable;
output negedge ack;
input #1step addr;
endclocking"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"clocking dram @(clk);
input #1ps address;
input #5 output #6 data;
endclocking"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"clocking cd1 @(posedge phi1);
input #1step state = top.cpu1.state;
endclocking"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"clocking mem @(clock);
input instruction = { opcode, regA, regB[3:1] };
endclocking"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"program test( input phi1, input [15:0] data, output logic write,
input phi2, inout [8:1] cmd, input enable
);
reg [8:1] cmd_reg;
clocking cd1 @(posedge phi1);
input data;
output write;
input state = top.cpu1.state;
endclocking
clocking cd2 @(posedge phi2);
input #2 output #4ps cmd;
input enable;
endclocking
initial begin
// program begins here
// user can access cd1.data , cd2.cmd , etc…
end
assign cmd = enable ? cmd_reg: 'x;
endprogram"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module top;
logic phi1, phi2;
wire [8:1] cmd; // cannot be logic (two bidirectional drivers)
logic [15:0] data;
test main (phi1, data, write, phi2, cmd, enable);
cpu cpu1 (phi1, data, write);
mem mem1 (phi2, cmd, enable);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"interface bus_A (input clk);
logic [15:0] data;
logic write;
modport test (input data, output write);
modport dut (output data, input write);
endinterface
interface bus_B (input clk);
logic [8:1] cmd;
logic enable;
modport test (input enable);
modport dut (output enable);
endinterface
program test( bus_A.test a, bus_B.test b );
clocking cd1 @(posedge a.clk);
input data = a.data;
output write = a.write;
inout state = top.cpu1.state;
endclocking
clocking cd2 @(posedge b.clk);
input #2 output #4ps cmd = b.cmd;
input en = b.enable;
endclocking
initial begin
// program begins here
// user can access cd1.data, cd1.write, cd1.state,
// cd2.cmd, and cd2.en
end
endprogram"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module top;
logic phi1, phi2;
bus_A a (phi1);
bus_B b (phi2);
test main (a, b);
cpu cpu1 (a);
mem mem1 (b);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"clocking dram @(posedge phi1);
inout data;
output negedge #1 address;
endclocking"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
@(dram);
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"initial begin
##5; // wait 5 cycles (clocking events) using the default clocking
##(j + 1); // wait j+1 cycles (clocking events) using the default clocking
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"program test(input logic clk, input logic [15:0] data);
default clocking bus @(posedge clk);
inout data;
endclocking
initial begin
## 5;
if (bus.data == 10)
## 1;
end
endprogram"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module processor();
clocking busA @(posedge clk1); endclocking
clocking busB @(negedge clk2); endclocking
module cpu( interface y );
default clocking busA ;
initial begin
## 5; // use busA => (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((_, _))
);
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((_, _))
);
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((_, _))
);
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((_, _))
);
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((_, _))
);
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((_, _))
);
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((_, _))
);
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((_, _))
);
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 well lock a1 and then well 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##"module and_op (a, b, c);
output a;
input b, c;
`ifdef behavioral
wire a = b & c;
`else
and a1 (a,b,c);
`endif
endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"module test(out);
output out;
`define wow
`define nest_one
`define second_nest
`define nest_two
`ifdef wow
initial $display("wow is defined");
`ifdef nest_one
initial $display("nest_one is defined");
`ifdef nest_two
initial $display("nest_two is defined");
`else
initial $display("nest_two is not defined");
`endif
`else
initial $display("nest_one is not defined");
`endif
`else
initial $display("wow is not defined");
`ifdef second_nest
initial $display("second_nest is defined");
`else
initial $display("second_nest is not defined");
`endif
`endif
endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"module test;
`ifdef first_block
`ifndef second_nest
initial $display("first_block is defined");
`else
initial $display("first_block and second_nest defined");
`endif
`elsif second_block
initial $display("second_block defined, first_block is not");
`else
`ifndef last_result
initial $display("first_block, second_block,",
" last_result not defined.");
`elsif real_last
initial $display("first_block, second_block not defined,",
" last_result and real_last defined.");
`else
initial $display("Only last_result defined!");
`endif
`endif
endmodule"##,
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; i<SIZE; i=i+1) begin:bitnum
assign bin[i] = ^gray[SIZE-1:i];
// i refers to the implicitly defined localparam whose
// value in each instance of the generate block is
// the value of the genvar when it was elaborated.
end
endgenerate
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module addergen1 (co, sum, a, b, ci);
parameter SIZE = 4;
output [SIZE-1:0] sum;
output co;
input [SIZE-1:0] a, b;
input ci;
wire [SIZE :0] c;
wire [SIZE-1:0] t [1:3];
genvar i;
assign c[0] = ci;
// Hierarchical gate instance names are:
// xor gates: bitnum[0].g1 bitnum[1].g1 bitnum[2].g1 bitnum[3].g1
// bitnum[0].g2 bitnum[1].g2 bitnum[2].g2 bitnum[3].g2
// and gates: bitnum[0].g3 bitnum[1].g3 bitnum[2].g3 bitnum[3].g3
// bitnum[0].g4 bitnum[1].g4 bitnum[2].g4 bitnum[3].g4
// or gates: bitnum[0].g5 bitnum[1].g5 bitnum[2].g5 bitnum[3].g5
// Generated instances are connected with
// multidimensional nets t[1][3:0] t[2][3:0] t[3][3:0]
// (12 nets total)
for(i=0; i<SIZE; i=i+1) begin:bitnum
xor g1 ( t[1][i], a[i], b[i]);
xor g2 ( sum[i], t[1][i], c[i]);
and g3 ( t[2][i], a[i], b[i]);
and g4 ( t[3][i], t[1][i], c[i]);
or g5 ( c[i+1], t[2][i], t[3][i]);
end
assign co = c[SIZE];
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module addergen1 (co, sum, a, b, ci);
parameter SIZE = 4;
output [SIZE-1:0] sum;
output co;
input [SIZE-1:0] a, b;
input ci;
wire [SIZE :0] c;
genvar i;
assign c[0] = ci;
// Hierarchical gate instance names are:
// xor gates: bitnum[0].g1 bitnum[1].g1 bitnum[2].g1 bitnum[3].g1
// bitnum[0].g2 bitnum[1].g2 bitnum[2].g2 bitnum[3].g2
// and gates: bitnum[0].g3 bitnum[1].g3 bitnum[2].g3 bitnum[3].g3
// bitnum[0].g4 bitnum[1].g4 bitnum[2].g4 bitnum[3].g4
// or gates: bitnum[0].g5 bitnum[1].g5 bitnum[2].g5 bitnum[3].g5
// Gate instances are connected with nets named:
// bitnum[0].t1 bitnum[1].t1 bitnum[2].t1 bitnum[3].t1
// bitnum[0].t2 bitnum[1].t2 bitnum[2].t2 bitnum[3].t2
// bitnum[0].t3 bitnum[1].t3 bitnum[2].t3 bitnum[3].t3
for(i=0; i<SIZE; i=i+1) begin:bitnum
wire t1, t2, t3;
xor g1 ( t1, a[i], b[i]);
xor g2 ( sum[i], t1, c[i]);
and g3 ( t2, a[i], b[i]);
and g4 ( t3, t1, c[i]);
or g5 ( c[i+1], t2, t3);
end
assign co = c[SIZE];
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"parameter SIZE = 2;
genvar i, j, k, m;
generate
for (i=0; i<SIZE; i=i+1) begin:B1 // scope B1[i]
M1 N1(); // instantiates B1[i].N1
for (j=0; j<SIZE; j=j+1) begin:B2 // scope B1[i].B2[j]
M2 N2(); // instantiates B1[i].B2[j].N2
for (k=0; k<SIZE; k=k+1) begin:B3 // scope B1[i].B2[j].B3[k]
M3 N3(); // instantiates
end // B1[i].B2[j].B3[k].N3
end
if (i>0) begin:B4 // scope B1[i].B4
for (m=0; m<SIZE; m=m+1) begin:B5 // scope B1[i].B4.B5[m]
M4 N4(); // instantiates
end // B1[i].B4.B5[m].N4
end
end
endgenerate"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module test;
parameter p = 0, q = 0;
wire a, b, c;
//---------------------------------------------------------
// Code to either generate a u1.g1 instance or no instance.
// The u1.g1 instance of one of the following gates:
// (and, or, xor, xnor) is generated if
// {p,q} == {1,0}, {1,2}, {2,0}, {2,1}, {2,2}, {2, default}
//---------------------------------------------------------
if (p == 1)
if (q == 0)
begin : u1 // If p==1 and q==0, then instantiate
and g1(a, b, c); // AND with hierarchical name test.u1.g1
end
else if (q == 2)
begin : u1 // If p==1 and q==2, then instantiate
or g1(a, b, c); // OR with hierarchical name test.u1.g1
end
// "else" added to end "if (q == 2)" statement
else ; // If p==1 and q!=0 or 2, then no instantiation
else if (p == 2)
case (q)
0, 1, 2:
begin : u1 // If p==2 and q==0,1, or 2, then instantiate
xor g1(a, b, c); // XOR with hierarchical name test.u1.g1
end
default:
begin : u1 // If p==2 and q!=0,1, or 2, then instantiate
xnor g1(a, b, c); // XNOR with hierarchical name test.u1.g1
end
endcase
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module multiplier(a,b,product);
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;
// cannot be modified directly with the defparam
// statement or the module instance statement #
input [a_width-1:0] a;
input [b_width-1:0] b;
output [product_width-1:0] product;
generate
if((a_width < 8) || (b_width < 8)) begin: mult
CLA_multiplier #(a_width,b_width) u1(a, b, product);
// instantiate a CLA multiplier
end
else begin: mult
WALLACE_multiplier #(a_width,b_width) u1(a, b, product);
// instantiate a Wallace-tree multiplier
end
endgenerate
// The hierarchical instance name is mult.u1
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"generate
case (WIDTH)
1: begin: adder // 1-bit adder implementation
adder_1bit x1(co, sum, a, b, ci);
end
2: begin: adder // 2-bit adder implementation
adder_2bit x1(co, sum, a, b, ci);
end
default:
begin: adder // others - carry look-ahead adder
adder_cla #(WIDTH) x1(co, sum, a, b, ci);
end
endcase
// The hierarchical instance name is adder.x1
endgenerate"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module dimm(addr, ba, rasx, casx, csx, wex, cke, clk, dqm, data, dev_id);
parameter [31:0] MEM_WIDTH = 16, MEM_SIZE = 8; // in mbytes
input [10:0] addr;
input ba, rasx, casx, csx, wex, cke, clk;
input [ 7:0] dqm;
inout [63:0] data;
input [ 4:0] dev_id;
genvar i;
case ({MEM_SIZE, MEM_WIDTH})
{32'd8, 32'd16}: // 8Meg x 16 bits wide
begin: memory
for (i=0; i<4; i=i+1) begin:word16
sms_08b216t0 p(.clk(clk), .csb(csx), .cke(cke),.ba(ba),
.addr(addr), .rasb(rasx), .casb(casx),
.web(wex), .udqm(dqm[2*i+1]), .ldqm(dqm[2*i]),
.dqi(data[15+16*i:16*i]), .dev_id(dev_id));
// The hierarchical instance names are:
// memory.word16[3].p, memory.word16[2].p,
// memory.word16[1].p, memory.word16[0].p,
// and the task memory.read_mem
end
task read_mem;
input [31:0] address;
output [63:0] data;
begin // call read_mem in sms module
word16[3].p.read_mem(address, data[63:48]);
word16[2].p.read_mem(address, data[47:32]);
word16[1].p.read_mem(address, data[31:16]);
word16[0].p.read_mem(address, data[15: 0]);
end
endtask
end
{32'd16, 32'd8}: // 16Meg x 8 bits wide
begin: memory
for (i=0; i<8; i=i+1) begin:word8
sms_16b208t0 p(.clk(clk), .csb(csx), .cke(cke),.ba(ba),
.addr(addr), .rasb(rasx), .casb(casx),
.web(wex), .dqm(dqm[i]),
.dqi(data[7+8*i:8*i]), .dev_id(dev_id));
// The hierarchical instance names are
// memory.word8[7].p, memory.word8[6].p,
// ...
// memory.word8[1].p, memory.word8[0].p,
// and the task memory.read_mem
end
task read_mem;
input [31:0] address;
output [63:0] data;
begin // call read_mem in sms module
word8[7].p.read_mem(address, data[63:56]);
word8[6].p.read_mem(address, data[55:48]);
word8[5].p.read_mem(address, data[47:40]);
word8[4].p.read_mem(address, data[39:32]);
word8[3].p.read_mem(address, data[31:24]);
word8[2].p.read_mem(address, data[23:16]);
word8[1].p.read_mem(address, data[15: 8]);
word8[0].p.read_mem(address, data[ 7: 0]);
end
endtask
end
// Other memory cases ...
endcase
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module top;
parameter genblk2 = 0;
genvar i;
// The following generate block is implicitly named genblk1
if (genblk2) logic a; // top.genblk1.a
else logic b; // top.genblk1.b
// The following generate block is implicitly named genblk02
// as genblk2 is already a declared identifier
if (genblk2) logic a; // top.genblk02.a
else logic b; // top.genblk02.b
// The following generate block would have been named genblk3
// but is explicitly named g1
for (i = 0; i < 1; i = i + 1) begin : g1 // block name
// The following generate block is implicitly named genblk1
// as the first nested scope inside g1
if (1) logic a; // top.g1[0].genblk1.a
end
// The following generate block is implicitly named genblk4 since
// it belongs to the fourth generate construct in scope "top".
// The previous generate block would have been
// named genblk3 if it had not been explicitly named g1
for (i = 0; i < 1; i = i + 1)
// The following generate block is implicitly named genblk1
// as the first nested generate block in genblk4
if (1) logic a; // top.genblk4[0].genblk1.a
// The following generate block is implicitly named genblk5
if (1) logic a; // top.genblk5.a
endmodule"##,
Ok((_, _))
);
}
#[test]
fn clause28() {
test!(
many1(module_item),
r##"module driver (in, out, en);
input [3:0] in;
output [3:0] out;
input en;
bufif0 ar[3:0] (out, in, en); // array of three-state buffers
endmodule
module driver_equiv (in, out, en);
input [3:0] in;
output [3:0] out;
input en;
bufif0 ar3 (out[3], in[3], en); // each buffer declared separately
bufif0 ar2 (out[2], in[2], en);
bufif0 ar1 (out[1], in[1], en);
bufif0 ar0 (out[0], in[0], en);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module busdriver (busin, bushigh, buslow, enh, enl);
input [15:0] busin;
output [ 7:0] bushigh, buslow;
input enh, enl;
driver busar3 (busin[15:12], bushigh[7:4], enh);
driver busar2 (busin[11:8], bushigh[3:0], enh);
driver busar1 (busin[7:4], buslow[7:4], enl);
driver busar0 (busin[3:0], buslow[3:0], enl);
endmodule
module busdriver_equiv (busin, bushigh, buslow, enh, enl);
input [15:0] busin;
output [ 7:0] bushigh, buslow;
input enh, enl;
driver busar[3:0] (.out({bushigh, buslow}), .in(busin),
.en({enh, enh, enl, enl}));
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module dffn (q, d, clk);
parameter bits = 1;
input [bits-1:0] d;
output [bits-1:0] q;
input clk ;
DFF dff[bits-1:0] (q, d, clk); // create a row of D flip-flops
endmodule
module MxN_pipeline (in, out, clk);
parameter M = 3, N = 4; // M=width,N=depth
input [M-1:0] in;
output [M-1:0] out;
input clk;
wire [M*(N-1):1] t;
// #(M) redefines the bits parameter for dffn
// create p[1:N] columns of dffn rows (pipeline)
dffn #(M) p[1:N] ({out, t}, {t, in}, clk);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"and a1 (out, in1, in2);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"buf b1 (out1, out2, in);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"bufif1 bf1 (outw, inw, controlw);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"pmos p1 (out, data, control);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"tranif1 t1 (inout1,inout2,control);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"cmos (w, datain, ncontrol, pcontrol);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"nmos (w, datain, ncontrol);
pmos (w, datain, pcontrol);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"pullup (strong1) p1 (neta), p2 (netb);"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"and #(10) a1 (out, in1, in2); // only one delay
and #(10,12) a2 (out, in1, in2); // rise and fall delays
bufif0 #(10,12,11) b3 (out, in, ctrl); // rise, fall, and turn-off delays"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module tri_latch (qout, nqout, clock, data, enable);
output qout, nqout;
input clock, data, enable;
tri qout, nqout;
not #5 n1 (ndata, data);
nand #(3,5) n2 (wa, data, clock),
n3 (wb, ndata, clock);
nand #(12,15) n4 (q, nq, wa),
n5 (nq, q, wb);
bufif1 #(3,7,13) q_drive (qout, q, enable),
nq_drive (nqout, nq, enable);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module iobuf (io1, io2, dir);
bufif0 #(5:7:9, 8:10:12, 15:18:21) b1 (io1, io2, dir);
bufif1 #(6:8:10, 5:7:9, 13:17:19) b2 (io2, io1, dir);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"parameter min_hi = 97, typ_hi = 100, max_hi = 107;
logic clk;
always begin
#(95:100:105) clk = 1;
#(min_hi:typ_hi:max_hi) clk = 0;
end"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"trireg (large) #(0,0,50) cap1;"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module capacitor;
logic data, gate;
// trireg declaration with a charge decay time of 50 time units
trireg (large) #(0,0,50) cap1;
nmos nmos1 (cap1, data, gate); // nmos that drives the trireg
initial begin
$monitor("%0d data=%v gate=%v cap1=%v", $time, data, gate, cap1);
data = 1;
// Toggle the driver of the control input to the nmos switch
gate = 1;
#10 gate = 0;
#30 gate = 1;
#10 gate = 0;
#100 $finish;
end
endmodule"##,
Ok((_, _))
);
}
#[test]
fn clause29() {
test!(
source_text,
r##"primitive multiplexer (mux, control, dataA, dataB);
output mux;
input control, dataA, dataB;
table
// control dataA dataB mux
0 1 0 : 1 ;
0 1 1 : 1 ;
0 1 x : 1 ;
0 0 0 : 0 ;
0 0 1 : 0 ;
0 0 x : 0 ;
1 0 1 : 1 ;
1 1 1 : 1 ;
1 x 1 : 1 ;
1 0 0 : 0 ;
1 1 0 : 0 ;
1 x 0 : 0 ;
x 0 0 : 0 ;
x 1 1 : 1 ;
endtable
endprimitive"##,
Ok((_, _))
);
test!(
source_text,
r##"primitive multiplexer (mux, control, dataA, dataB);
output mux;
input control, dataA, dataB;
table
// control dataA dataB mux
0 1 ? : 1 ; // ? = 0 1 x
0 0 ? : 0 ;
1 ? 1 : 1 ;
1 ? 0 : 0 ;
x 0 0 : 0 ;
x 1 1 : 1 ;
endtable
endprimitive"##,
Ok((_, _))
);
test!(
source_text,
r##"primitive latch (q, ena_, data);
output q; reg q;
input ena_, data;
table
// ena_ data : q : q+
0 1 : ? : 1 ;
0 0 : ? : 0 ;
1 ? : ? : - ; // - = no change
endtable
endprimitive"##,
Ok((_, _))
);
test!(
source_text,
r##"primitive d_edge_ff (q, clock, data);
output q; reg q;
input clock, data;
table
// clock data q q+
// obtain output on rising edge of clock
(01) 0 : ? : 0 ;
(01) 1 : ? : 1 ;
(0?) 1 : 1 : 1 ;
(0?) 0 : 0 : 0 ;
// ignore negative edge of clock
(?0) ? : ? : - ;
// ignore data changes on steady clock
? (??) : ? : - ;
endtable
endprimitive"##,
Ok((_, _))
);
test!(
source_text,
r##"primitive srff (q, s, r);
output q; reg q;
input s, r;
initial q = 1'b1;
table
// s r q q+
1 0 : ? : 1 ;
f 0 : 1 : - ;
0 r : ? : 0 ;
0 f : 0 : - ;
1 1 : ? : 0 ;
endtable
endprimitive"##,
Ok((_, _))
);
test!(
source_text,
r##"primitive dff1 (q, clk, d);
input clk, d;
output q; reg q;
initial q = 1'b1;
table
// clk d q q+
r 0 : ? : 0 ;
r 1 : ? : 1 ;
f ? : ? : - ;
? * : ? : - ;
endtable
endprimitive
module dff (q, qb, clk, d);
input clk, d;
output q, qb;
dff1 g1 (qi, clk, d);
buf #3 g2 (q, qi);
not #5 g3 (qb, qi);
endmodule"##,
Ok((_, _))
);
test!(
many1(module_item),
r##"module flip;
reg clock, data;
parameter p1 = 10;
parameter p2 = 33;
parameter p3 = 12;
d_edge_ff #p3 d_inst (q, clock, data);
initial begin
data = 1;
clock = 1;
#(20 * p1) $finish;
end
always #p1 clock = ~clock;
always #p2 data = ~data;
endmodule"##,
Ok((_, _))
);
test!(
source_text,
r##"primitive jk_edge_ff (q, clock, j, k, preset, clear);
output q; reg q;
input clock, j, k, preset, clear;
table
// clock jk pc state output/next state
? ?? 01 : ? : 1 ; // preset logic
? ?? *1 : 1 : 1 ;
? ?? 10 : ? : 0 ; // clear logic
? ?? 1* : 0 : 0 ;
r 00 00 : 0 : 1 ; // normal clocking cases
r 00 11 : ? : - ;
r 01 11 : ? : 0 ;
r 10 11 : ? : 1 ;
r 11 11 : 0 : 1 ;
r 11 11 : 1 : 0 ;
f ?? ?? : ? : - ;
b *? ?? : ? : - ; // j and k transition cases
b ?* ?? : ? : - ;
endtable
endprimitive"##,
Ok((_, _))
);
}
#[test]
fn clause30() {
test!(
many1(module_item),
r##"specify
specparam tRise_clk_q = 150, tFall_clk_q = 200;
specparam tSetup = 70;
(clk => 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() {
test!(
source_text,
r##"module a; initial begin #a.b; end endmodule"##,
Ok((_, _))
);
nom_tracable::cumulative_histogram();
}