diff --git a/Changes b/Changes index 55c7ae2c6..9945d0d94 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.825*** +*** Add sc_bv attribute to force bit vectors, bug402. [by Stefan Wallentowitz] + * Verilator 3.824 2011/10/25 diff --git a/bin/verilator b/bin/verilator index b4b2ebae6..62c7a6250 100755 --- a/bin/verilator +++ b/bin/verilator @@ -722,7 +722,8 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64. Specifies SystemC inputs/outputs of greater than or equal to I bits wide should use sc_bv's instead of uint32/vluint64_t's. The default is "--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv -33". The more sc_bv is used, the worse for performance. +33". The more sc_bv is used, the worse for performance. Use the +"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv. =item --pins-uint8 @@ -2030,6 +2031,15 @@ should be declared in SystemC as a sc_clock instead of a bool. This was needed in SystemC 1.1 and 1.2 only; versions 2.0 and later do not require clock pins to be sc_clocks and this is no longer needed. +=item /*verilator sc_bv*/ + +Used after a port declaration. It sets the port to be of sc_bv> +type, instead of bool, vluint32_t or vluint64_t. This may be useful if +the port width is parametrized and different of such modules interface +a templated module (such as a transactor) or for other reasons. In general +you should avoid using this attribute when not necessary as with increasing +usage of sc_bv the performance increases significantly. + =item /*verilator sformat*/ Attached to the final input of a function or task "input string" to diff --git a/src/V3Ast.h b/src/V3Ast.h index d07fe7835..f3dda1661 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -215,6 +215,7 @@ public: VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign + VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat }; enum en m_e; @@ -223,7 +224,7 @@ public: "%E-AT", "EXPR_BITS", "VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW", - "VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT" + "VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT" }; return names[m_e]; }; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index db6a4865f..6f7ddd87a 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -70,7 +70,7 @@ bool AstVar::isScQuad() const { } bool AstVar::isScBv() const { - return (isSc() && width() >= v3Global.opt.pinsBv()); + return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv); } void AstVar::combineType(AstVarType type) { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 74366204d..969d5c1e3 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -587,6 +587,7 @@ private: bool m_funcLocal:1; // Local variable for a function bool m_funcReturn:1; // Return variable for a function bool m_attrClockEn:1;// User clock enable attribute + bool m_attrScBv:1; // User force bit vector attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute bool m_attrSFormat:1;// User sformat attribute bool m_fileDescr:1; // File descriptor @@ -601,7 +602,7 @@ private: m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false; m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false; m_funcLocal=false; m_funcReturn=false; - m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false; + m_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false; m_fileDescr=false; m_isConst=false; m_isStatic=false; m_trace=false; } @@ -664,6 +665,7 @@ public: void attrClockEn(bool flag) { m_attrClockEn = flag; } void attrFileDescr(bool flag) { m_fileDescr = flag; } void attrScClocked(bool flag) { m_scClocked = flag; } + void attrScBv(bool flag) { m_attrScBv = flag; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } void attrSFormat(bool flag) { m_attrSFormat = flag; } void usedClock(bool flag) { m_usedClock = flag; } @@ -724,6 +726,7 @@ public: bool isFuncLocal() const { return m_funcLocal; } bool isFuncReturn() const { return m_funcReturn; } bool attrClockEn() const { return m_attrClockEn; } + bool attrScBv() const { return m_attrScBv; } bool attrFileDescr() const { return m_fileDescr; } bool attrScClocked() const { return m_scClocked; } bool attrSFormat() const { return m_attrSFormat; } diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 67dec96cd..35698056a 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -326,6 +326,11 @@ private: m_varp->attrSFormat(true); nodep->unlinkFrBack()->deleteTree(); nodep=NULL; } + else if (nodep->attrType() == AstAttrType::VAR_SC_BV) { + if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); + m_varp->attrScBv(true); + nodep->unlinkFrBack()->deleteTree(); nodep=NULL; + } } virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { diff --git a/src/verilog.l b/src/verilog.l index 3d6136b52..0f9b8da04 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -649,6 +649,7 @@ word [a-zA-Z0-9_]+ "/*verilator public_flat_rw*/" { FL; return yVL_PUBLIC_FLAT_RW; } // The @(edge) is converted by the preproc "/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; } "/*verilator sc_clock*/" { FL; return yVL_CLOCK; } + "/*verilator sc_bv*/" { FL; return yVL_SC_BV; } "/*verilator sformat*/" { FL; return yVL_SFORMAT; } "/*verilator systemc_clock*/" { FL; return yVL_CLOCK; } "/*verilator tracing_off*/" {PARSEP->fileline()->tracingOn(false); } diff --git a/src/verilog.y b/src/verilog.y index 32967ac33..196241e6c 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -447,6 +447,7 @@ class AstSenTree; %token yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" %token yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/" %token yVL_NO_INLINE_TASK "/*verilator no_inline_task*/" +%token yVL_SC_BV "/*verilator sc_bv*/" %token yVL_SFORMAT "/*verilator sformat*/" %token yVL_PARALLEL_CASE "/*verilator parallel_case*/" %token yVL_PUBLIC "/*verilator public*/" @@ -1596,6 +1597,7 @@ sigAttr: | yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); $$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); } | yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); } + | yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); } | yVL_SFORMAT { $$ = new AstAttrOf($1,AstAttrType::VAR_SFORMAT); } ; diff --git a/test_regress/t/t_var_pins_sc1.pl b/test_regress/t/t_var_pins_sc1.pl index aaad9f3fd..871ad5e36 100755 --- a/test_regress/t/t_var_pins_sc1.pl +++ b/test_regress/t/t_var_pins_sc1.pl @@ -23,6 +23,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv16;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o1;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o8;/x); @@ -30,6 +32,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv16;/x); } execute(); diff --git a/test_regress/t/t_var_pins_sc2.pl b/test_regress/t/t_var_pins_sc2.pl index 847019505..eb03cbc9c 100755 --- a/test_regress/t/t_var_pins_sc2.pl +++ b/test_regress/t/t_var_pins_sc2.pl @@ -23,6 +23,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv16;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o1;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o8;/x); @@ -30,6 +32,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv16;/x); } execute(); diff --git a/test_regress/t/t_var_pins_sc32.pl b/test_regress/t/t_var_pins_sc32.pl index 35df4c6c0..329ff9405 100755 --- a/test_regress/t/t_var_pins_sc32.pl +++ b/test_regress/t/t_var_pins_sc32.pl @@ -23,6 +23,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in \s+ i32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv16;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o1;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o8;/x); @@ -30,6 +32,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv16;/x); } execute(); diff --git a/test_regress/t/t_var_pins_sc64.pl b/test_regress/t/t_var_pins_sc64.pl index 3e9e1af1d..896b74026 100755 --- a/test_regress/t/t_var_pins_sc64.pl +++ b/test_regress/t/t_var_pins_sc64.pl @@ -23,6 +23,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in \s+ i32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in \s+ i64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv16;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o1;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o8;/x); @@ -30,6 +32,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv16;/x); } execute(); diff --git a/test_regress/t/t_var_pins_scui.pl b/test_regress/t/t_var_pins_scui.pl index 1c168edd3..5c2fddf7f 100755 --- a/test_regress/t/t_var_pins_scui.pl +++ b/test_regress/t/t_var_pins_scui.pl @@ -23,6 +23,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in \s+ i32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in \s+ i64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ i65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in\s> \s+ ibv16;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o1;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o8;/x); @@ -30,6 +32,8 @@ if ($Self->{vlt}) { file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o32;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out \s+ o64;/x); file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ o65;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv1;/x); + file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out\s> \s+ obv16;/x); } execute(); diff --git a/test_regress/t/t_var_pinsizes.v b/test_regress/t/t_var_pinsizes.v index a00d5b660..bca013395 100644 --- a/test_regress/t/t_var_pinsizes.v +++ b/test_regress/t/t_var_pinsizes.v @@ -8,9 +8,9 @@ module t (/*AUTOARG*/ // Outputs - o1, o8, o16, o32, o64, o65, + o1, o8, o16, o32, o64, o65, obv1, obv16, // Inputs - clk, i1, i8, i16, i32, i64, i65 + clk, i1, i8, i16, i32, i64, i65, ibv1, ibv16 ); input clk; @@ -29,6 +29,12 @@ module t (/*AUTOARG*/ output [63:0] o64; output [64:0] o65; + input [0:0] ibv1 /*verilator sc_bv*/; + input [15:0] ibv16 /*verilator sc_bv*/; + + output [0:0] obv1 /*verilator sc_bv*/; + output [15:0] obv16 /*verilator sc_bv*/; + always @ (posedge clk) begin o1 <= i1; o8 <= i8; @@ -36,6 +42,8 @@ module t (/*AUTOARG*/ o32 <= i32; o64 <= i64; o65 <= i65; + obv1 <= ibv1; + obv16 <= ibv16; end endmodule