15856 lines
540 KiB
Rust
15856 lines
540 KiB
Rust
#![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 we’ll lock a1 and then we’ll enable all
|
||
// the assertions and then unlock a1 as we want future assertion
|
||
// control tasks to affect a1.
|
||
#10 $assertcontrol(LOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, a1);
|
||
$assertcontrol(ON); // enable all the assertions except a1
|
||
$assertcontrol(UNLOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, a1);
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"wire a1, a2, a3, a4, a5, a6, a7;
|
||
logic b1, b2, b3;
|
||
wire [1:7] awire;
|
||
logic [1:3] breg;
|
||
|
||
initial begin
|
||
$async$and$array(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3});
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module async_array(a1,a2,a3,a4,a5,a6,a7,b1,b2,b3);
|
||
input a1, a2, a3, a4, a5, a6, a7 ;
|
||
output b1, b2, b3;
|
||
logic [1:7] mem[1:3]; // memory declaration for array personality
|
||
logic b1, b2, b3;
|
||
initial begin
|
||
// set up the personality from the file array.dat
|
||
$readmemb("array.dat", mem);
|
||
// set up an asynchronous logic array with the input
|
||
// and output terms expressed as concatenations
|
||
$async$and$array(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3});
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module sync_array(a1,a2,a3,a4,a5,a6,a7,b1,b2,b3,clk);
|
||
input a1, a2, a3, a4, a5, a6, a7, clk;
|
||
output b1, b2, b3;
|
||
logic [1:7] mem[1:3]; // memory declaration
|
||
logic b1, b2, b3;
|
||
initial begin
|
||
// set up the personality
|
||
$readmemb("array.dat", mem);
|
||
// set up a synchronous logic array to be evaluated
|
||
// when a positive edge on the clock occurs
|
||
forever @(posedge clk)
|
||
$async$and$array(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3});
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module pla;
|
||
logic [1:cols] a, mem[1:rows];
|
||
logic [1:rows] b;
|
||
initial begin
|
||
// PLA system call
|
||
$async$and$plane(mem,a[1:3],b[1:4]);
|
||
mem[1] = 3'b10?;
|
||
mem[2] = 3'b??1;
|
||
mem[3] = 3'b0?0;
|
||
mem[4] = 3'b???;
|
||
// stimulus and display
|
||
#10 a = 3'b111;
|
||
#10 $displayb(a, " -> ", b);
|
||
#10 a = 3'b000;
|
||
#10 $displayb(a, " -> ", b);
|
||
#10 a = 3'bxxx;
|
||
#10 $displayb(a, " -> ", b);
|
||
#10 a = 3'b101;
|
||
#10 $displayb(a, " -> ", b);
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module top;
|
||
initial $system("mv design.v adder.v");
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn clause21() {
|
||
test!(
|
||
many1(module_item),
|
||
r##"module disp;
|
||
initial begin
|
||
$display("\\\t\\\n\"\123");
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module disp;
|
||
logic [31:0] rval;
|
||
pulldown (pd);
|
||
initial begin
|
||
rval = 101;
|
||
$display("rval = %h hex %d decimal",rval,rval);
|
||
$display("rval = %o octal\nrval = %b bin",rval,rval);
|
||
$display("rval has %c ascii character value",rval);
|
||
$display("pd strength value is %v",pd);
|
||
$display("current scope is %m");
|
||
$display("%s is ascii value for 101",101);
|
||
$display("simulation time is %t", $time);
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module printval;
|
||
logic [11:0] r1;
|
||
initial begin
|
||
r1 = 10;
|
||
$display( "Printing with maximum size - :%d: :%h:", r1,r1 );
|
||
$display( "Printing with minimum size - :%0d: :%0h:", r1,r1 );
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"always
|
||
#15 $display($time,,"group=%b signals=%v %v %v",{s1,s2,s3},s1,s2,s3);"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module top;
|
||
typedef enum {ON, OFF} switch_e;
|
||
typedef struct {switch_e sw; string s;} pair_t;
|
||
pair_t va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}};
|
||
|
||
initial begin
|
||
$display("va[int] = %p;",va);
|
||
$display("va[int] = %0p;",va);
|
||
$display("va[10].s = %p;", va[10].s);
|
||
end
|
||
endmodule : top"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
forever @(negedge clock)
|
||
$strobe ("At time %d, data is %h",$time,data);
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"integer
|
||
messages, broadcast,
|
||
cpu_chann, alu_chann, mem_chann;
|
||
initial begin
|
||
cpu_chann = $fopen("cpu.dat");
|
||
if (cpu_chann == 0) $finish;
|
||
alu_chann = $fopen("alu.dat");
|
||
if (alu_chann == 0) $finish;
|
||
mem_chann = $fopen("mem.dat");
|
||
if (mem_chann == 0) $finish;
|
||
messages = cpu_chann | alu_chann | mem_chann;
|
||
// broadcast includes standard output
|
||
broadcast = 1 | messages;
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer c;
|
||
c = $fgetc ( fd );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer code;
|
||
code = $ungetc ( c, fd );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer code;
|
||
code = $fgets ( str, fd );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer code ;
|
||
code = $fscanf ( fd, format, args );
|
||
code = $sscanf ( str, format, args );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer code ;
|
||
code = $fread( integral_var, fd);
|
||
code = $fread( mem, fd);
|
||
code = $fread( mem, fd, start);
|
||
code = $fread( mem, fd, start, count);
|
||
code = $fread( mem, fd, , count);
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer pos ;
|
||
pos = $ftell ( fd );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer code ;
|
||
code = $fseek ( fd, offset, operation );
|
||
code = $rewind ( fd );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
$fflush ( mcd );
|
||
$fflush ( fd );
|
||
$fflush ( );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer errno ;
|
||
errno = $ferror ( fd, str );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
integer code;
|
||
code = $feof ( fd );
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial $readmemh("mem.data", mem);
|
||
initial $readmemh("mem.data", mem, 16);
|
||
initial $readmemh("mem.data", mem, 128, 1);"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
if ($test$plusargs("HELLO")) $display("Hello argument found.");
|
||
if ($test$plusargs("HE")) $display("The HE subset string is detected.");
|
||
if ($test$plusargs("H")) $display("Argument starting with H found.");
|
||
if ($test$plusargs("HELLO_HERE")) $display("Long argument.");
|
||
if ($test$plusargs("HI")) $display("Simple greeting.");
|
||
if ($test$plusargs("LO")) $display("Does not match.");
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module goodtasks;
|
||
STRING str;
|
||
integer i1;
|
||
logic [31:0] vect;
|
||
real realvar;
|
||
|
||
initial
|
||
begin
|
||
if ($value$plusargs("TEST=%d", i1))
|
||
$display("value was %d", i1);
|
||
else
|
||
$display("+TEST= not found");
|
||
#100 $finish;
|
||
end
|
||
endmodule
|
||
|
||
module ieee1364_example;
|
||
real frequency;
|
||
logic [8*32:1] testname;
|
||
logic [64*8:1] pstring;
|
||
logic clk;
|
||
|
||
initial
|
||
begin
|
||
if ($value$plusargs("TESTNAME=%s",testname))
|
||
begin
|
||
$display(" TESTNAME= %s.",testname);
|
||
$finish;
|
||
end
|
||
|
||
if (!($value$plusargs("FREQ+%0F",frequency)))
|
||
frequency = 8.33333; // 166 MHz
|
||
$display("frequency = %f",frequency);
|
||
|
||
pstring = "TEST%d";
|
||
if ($value$plusargs(pstring, testname))
|
||
$display("Running test number %0d.",testname);
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial $dumpfile ("module1.dump") ;"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
$dumpvars (1, top);
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
$dumpvars (0, top.mod1, top.mod2.net1);
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
#10 $dumpvars();
|
||
|
||
#200 $dumpoff;
|
||
|
||
#800 $dumpon;
|
||
|
||
#900 $dumpoff;
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"initial begin
|
||
$dumpvars ;
|
||
$dumpflush ;
|
||
//$(applications program) ;
|
||
end"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module dump;
|
||
event do_dump;
|
||
initial $dumpfile("verilog.dump");
|
||
initial @do_dump
|
||
$dumpvars; //dump variables in the design
|
||
|
||
always @do_dump //to begin the dump at event do_dump
|
||
begin
|
||
$dumpon; //no effect the first time through
|
||
repeat (500) @(posedge clock); //dump for 500 cycles
|
||
$dumpoff; //stop the dump
|
||
end
|
||
|
||
initial @(do_dump)
|
||
forever #10000 $dumpall; // checkpoint all variables
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
many1(module_item),
|
||
r##"module test_device(count_out, carry, data, reset);
|
||
output count_out, carry ;
|
||
input [0:3] data;
|
||
input reset;
|
||
initial
|
||
begin
|
||
$dumpports(testbench.DUT, "testoutput.vcd");
|
||
end
|
||
endmodule"##,
|
||
Ok((_, _))
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn clause22() {
|
||
test!(
|
||
source_text,
|
||
r##"`define D(x,y) initial $display("start", x , y, "end");"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
source_text,
|
||
r##"`define MACRO1(a=5,b="B",c) $display(a,,b,,c);
|
||
`define MACRO2(a=5, b, c="C") $display(a,,b,,c);
|
||
`define MACRO3(a=5, b=0, c="C") $display(a,,b,,c);"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
source_text,
|
||
r##"`define wordsize 8
|
||
`define var_nand(dly) nand #dly"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
source_text,
|
||
r##"`define max(a,b)((a) > (b) ? (a) : (b))"##,
|
||
Ok((_, _))
|
||
);
|
||
test!(source_text, r##"`define TOP(a,b) a + b"##, Ok((_, _)));
|
||
test!(
|
||
source_text,
|
||
r##"`define msg(x,y) `"x: `\`"y`\`"`""##,
|
||
Ok((_, _))
|
||
);
|
||
test!(source_text, r##"`define append(f) f``_master"##, Ok((_, _)));
|
||
test!(
|
||
source_text,
|
||
r##"`define home(filename) `"/home/mydir/filename`""##,
|
||
Ok((_, _))
|
||
);
|
||
test!(
|
||
source_text,
|
||
r##"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();
|
||
}
|