Fix various round-trip Verilog output, including packed arrays

This commit is contained in:
Wilson Snyder 2025-01-24 21:00:45 -05:00
parent 432d5f851d
commit 929e15fa4c
4 changed files with 233 additions and 172 deletions

View File

@ -28,13 +28,17 @@ VL_DEFINE_DEBUG_FUNCTIONS;
// Emit statements and expressions // Emit statements and expressions
class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst { class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
// MEMBERS // STATE - across all visitors
bool m_suppressSemi = false;
const bool m_suppressUnknown = false; const bool m_suppressUnknown = false;
// STATE - for current visit position (use VL_RESTORER)
AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE
bool m_suppressSemi = false; // Non-statement, don't print ;
bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars
bool m_arrayPost = false; // Print array information that goes after identifier (vs after)
std::deque<AstNodeArrayDType*> m_packedps; // Packed arrays to print with BasicDType
// METHODS // METHODS
virtual void puts(const string& str) = 0; virtual void puts(const string& str) = 0;
virtual void putbs(const string& str) = 0; virtual void putbs(const string& str) = 0;
virtual void putfs(AstNode* nodep, const string& str) = 0; // Fileline and node %% mark virtual void putfs(AstNode* nodep, const string& str) = 0; // Fileline and node %% mark
@ -49,6 +53,20 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
putsNoTracking("\""); putsNoTracking("\"");
} }
void iterateAndCommaConstNull(AstNode* nodep) {
for (; nodep; nodep = nodep->nextp()) {
iterateConst(nodep);
if (nodep->nextp()) puts(", ");
}
}
void emitPacked() {
for (AstNodeArrayDType* packedp : m_packedps) {
puts(" ");
iterateConstNull(packedp->rangep());
}
m_packedps.clear();
}
// VISITORS // VISITORS
void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); } void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); }
void visit(AstNodeModule* nodep) override { void visit(AstNodeModule* nodep) override {
@ -58,13 +76,14 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
void visit(AstPort* nodep) override {} void visit(AstPort* nodep) override {}
void visit(AstNodeFTask* nodep) override { void visit(AstNodeFTask* nodep) override {
putfs(nodep, nodep->isFunction() ? "function" : "task"); const bool func = nodep->isFunction() || nodep->name() == "new";
putfs(nodep, func ? "function" : "task");
puts(" "); puts(" ");
puts(nodep->prettyName()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
// Only putfs the first time for each visitor; later for same node is putqs // Only putfs the first time for each visitor; later for same node is putqs
iterateAndNextConstNull(nodep->stmtsp()); iterateAndNextConstNull(nodep->stmtsp());
putfs(nodep, nodep->isFunction() ? "endfunction\n" : "endtask\n"); putfs(nodep, func ? "endfunction\n" : "endtask\n");
} }
void visit(AstBegin* nodep) override { void visit(AstBegin* nodep) override {
@ -169,7 +188,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
void visit(AstSenItem* nodep) override { void visit(AstSenItem* nodep) override {
putfs(nodep, ""); putfs(nodep, "");
puts(nodep->edgeType().verilogKwd()); if (nodep->edgeType() != VEdgeType::ET_CHANGED) puts(nodep->edgeType().verilogKwd());
if (nodep->sensp()) puts(" "); if (nodep->sensp()) puts(" ");
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
} }
@ -221,13 +240,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
if (fileOrStrgp) { if (fileOrStrgp) {
iterateAndNextConstNull(fileOrStrgp); iterateConstNull(fileOrStrgp);
putbs(", "); putbs(", ");
} }
putsQuoted(text); putsQuoted(text);
for (AstNode* expp = exprsp; expp; expp = expp->nextp()) { for (AstNode* expp = exprsp; expp; expp = expp->nextp()) {
puts(", "); puts(", ");
iterateAndNextConstNull(expp); iterateConstNull(expp);
} }
puts(");\n"); puts(");\n");
} }
@ -393,7 +412,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
void visit(AstTextBlock* nodep) override { void visit(AstTextBlock* nodep) override {
visit(static_cast<AstNodeSimpleText*>(nodep)); visit(static_cast<AstNodeSimpleText*>(nodep));
VL_RESTORER(m_suppressSemi); VL_RESTORER(m_suppressVarSemi);
m_suppressVarSemi = nodep->commas(); m_suppressVarSemi = nodep->commas();
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) { for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
iterateConst(childp); iterateConst(childp);
@ -403,17 +422,17 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
void visit(AstScopeName* nodep) override {} void visit(AstScopeName* nodep) override {}
void visit(AstCStmt* nodep) override { void visit(AstCStmt* nodep) override {
putfs(nodep, "$_CSTMT("); putfs(nodep, "$_CSTMT(");
iterateAndNextConstNull(nodep->exprsp()); iterateAndCommaConstNull(nodep->exprsp());
puts(");\n"); puts(");\n");
} }
void visit(AstCExpr* nodep) override { void visit(AstCExpr* nodep) override {
putfs(nodep, "$_CEXPR("); putfs(nodep, "$_CEXPR(");
iterateAndNextConstNull(nodep->exprsp()); iterateAndCommaConstNull(nodep->exprsp());
puts(")"); puts(")");
} }
void visit(AstUCStmt* nodep) override { void visit(AstUCStmt* nodep) override {
putfs(nodep, "$c("); putfs(nodep, "$c(");
iterateAndNextConstNull(nodep->exprsp()); iterateAndCommaConstNull(nodep->exprsp());
puts(");\n"); puts(");\n");
} }
void visit(AstUCFunc* nodep) override { void visit(AstUCFunc* nodep) override {
@ -431,19 +450,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
void visit(AstCMethodHard* nodep) override { void visit(AstCMethodHard* nodep) override {
iterateConst(nodep->fromp()); iterateConst(nodep->fromp());
puts("." + nodep->name() + "("); puts("." + nodep->name() + "(");
for (AstNode* pinp = nodep->pinsp(); pinp; pinp = pinp->nextp()) { iterateAndCommaConstNull(nodep->pinsp());
if (pinp != nodep->pinsp()) puts(", ");
iterateConst(pinp);
}
puts(")"); puts(")");
} }
void visit(AstCMethodCall* nodep) override { void visit(AstCMethodCall* nodep) override {
iterateConst(nodep->fromp()); iterateConst(nodep->fromp());
puts("." + nodep->name() + "("); puts("." + nodep->name() + "(");
for (AstNode* pinp = nodep->argsp(); pinp; pinp = pinp->nextp()) { iterateAndCommaConstNull(nodep->argsp());
if (pinp != nodep->argsp()) puts(", ");
iterateConst(pinp);
}
puts(")"); puts(")");
} }
@ -565,13 +578,15 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
puts(cvtToStr(nodep->leftConst())); puts(cvtToStr(nodep->leftConst()));
puts(":"); puts(":");
puts(cvtToStr(nodep->rightConst())); puts(cvtToStr(nodep->rightConst()));
puts("]");
} else { } else {
iterateAndNextConstNull(nodep->leftp()); iterateAndNextConstNull(nodep->leftp());
puts(":"); puts(":");
iterateAndNextConstNull(nodep->rightp()); iterateAndNextConstNull(nodep->rightp());
puts("]");
} }
puts("]");
}
void visit(AstRand* nodep) override {
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->seedp());
} }
void visit(AstSel* nodep) override { void visit(AstSel* nodep) override {
iterateAndNextConstNull(nodep->fromp()); iterateAndNextConstNull(nodep->fromp());
@ -603,17 +618,31 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
void visit(AstTypedef* nodep) override { void visit(AstTypedef* nodep) override {
putfs(nodep, "typedef "); putfs(nodep, "typedef ");
iterateAndNextConstNull(nodep->subDTypep()); iterateConstNull(nodep->subDTypep());
puts(" "); puts(" ");
puts(nodep->prettyName()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
} }
void visit(AstAssocArrayDType* nodep) override {
if (!m_arrayPost) {
iterateConst(nodep->subDTypep());
} else {
VL_RESTORER(m_arrayPost);
m_arrayPost = false;
puts("[");
iterateConst(nodep->keyDTypep());
puts("]");
m_arrayPost = true;
iterateConst(nodep->subDTypep()); // For post's key
}
}
void visit(AstBasicDType* nodep) override { void visit(AstBasicDType* nodep) override {
if (m_arrayPost) return;
putfs(nodep, nodep->prettyName()); putfs(nodep, nodep->prettyName());
if (nodep->isSigned()) putfs(nodep, " signed"); if (nodep->isSigned() && !nodep->keyword().isDouble()) putfs(nodep, " signed");
// Do not emit ranges for integer atoms. // Do not emit ranges for integer atoms.
if (nodep->keyword().isIntNumeric() && !nodep->keyword().isBitLogic()) return; if (nodep->keyword().isIntNumeric() && !nodep->keyword().isBitLogic()) return;
emitPacked();
if (nodep->rangep()) { if (nodep->rangep()) {
puts(" "); puts(" ");
iterateAndNextConstNull(nodep->rangep()); iterateAndNextConstNull(nodep->rangep());
@ -627,12 +656,50 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
} }
void visit(AstConstDType* nodep) override { void visit(AstConstDType* nodep) override {
if (m_arrayPost) return;
putfs(nodep, "const "); putfs(nodep, "const ");
iterateConst(nodep->subDTypep()); iterateConst(nodep->subDTypep());
} }
void visit(AstNodeArrayDType* nodep) override { void visit(AstDynArrayDType* nodep) override {
if (!m_arrayPost) {
iterateConst(nodep->subDTypep());
} else {
puts("[]");
iterateConst(nodep->subDTypep()); // For post's key
}
}
void visit(AstEnumDType* nodep) override {
if (m_arrayPost) return;
putfs(nodep, "enum ");
iterateConst(nodep->subDTypep()); iterateConst(nodep->subDTypep());
iterateAndNextConstNull(nodep->rangep()); puts("{\n");
iterateAndNextConstNull(nodep->itemsp());
puts("}");
}
void visit(AstEnumItem* nodep) override {
putfs(nodep, nodep->name());
iterateConstNull(nodep->rangep());
puts(" = ");
iterateConstNull(nodep->valuep());
if (nodep->nextp()) puts(",");
puts("\n");
}
void visit(AstNodeArrayDType* nodep) override {
if (!m_arrayPost) {
if (VN_IS(nodep, PackArrayDType)) {
// Unpacked ranges handled in BasicDType, as they print "backwards"
m_packedps.push_back(nodep);
}
iterateConst(nodep->subDTypep());
} else {
if (VN_IS(nodep, UnpackArrayDType)) {
VL_RESTORER(m_arrayPost);
m_arrayPost = false;
iterateAndNextConstNull(nodep->rangep());
m_arrayPost = true;
}
iterateConst(nodep->subDTypep()); // For post's key
}
} }
void visit(AstRefDType* nodep) override { void visit(AstRefDType* nodep) override {
if (nodep->subDTypep()) { if (nodep->subDTypep()) {
@ -642,21 +709,43 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
} }
void visit(AstNodeUOrStructDType* nodep) override { void visit(AstNodeUOrStructDType* nodep) override {
if (m_arrayPost) return;
puts(nodep->verilogKwd() + " "); puts(nodep->verilogKwd() + " ");
if (nodep->packed()) puts("packed "); if (nodep->packed()) puts("packed ");
puts("\n"); {
puts("{"); puts("{\n");
for (AstMemberDType* itemp = nodep->membersp(); itemp; VL_RESTORER(m_packedps);
itemp = VN_AS(itemp->nextp(), MemberDType)) { m_packedps.clear();
iterateConst(itemp); for (AstMemberDType* itemp = nodep->membersp(); itemp;
puts(";"); itemp = VN_AS(itemp->nextp(), MemberDType)) {
iterateConst(itemp);
}
puts("}");
} }
puts("}"); emitPacked();
} }
void visit(AstMemberDType* nodep) override { void visit(AstMemberDType* nodep) override {
if (m_arrayPost) return;
iterateConst(nodep->subDTypep()); iterateConst(nodep->subDTypep());
puts(" "); puts(" ");
puts(nodep->name()); puts(nodep->name());
puts(";\n");
}
void visit(AstQueueDType* nodep) override {
if (!m_arrayPost) {
iterateConst(nodep->subDTypep());
} else {
VL_RESTORER(m_arrayPost);
m_arrayPost = false;
puts("[$");
if (nodep->boundp()) {
puts(":");
iterateConst(nodep->boundp());
}
puts("]");
m_arrayPost = true;
iterateConst(nodep->subDTypep()); // For post's key
}
} }
void visit(AstNodeFTaskRef* nodep) override { void visit(AstNodeFTaskRef* nodep) override {
if (nodep->dotted() != "") { if (nodep->dotted() != "") {
@ -719,37 +808,23 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
puts(" "); puts(" ");
} }
std::vector<const AstUnpackArrayDType*> unpackps; VL_RESTORER(m_arrayPost);
for (AstNodeDType* dtypep = nodep->dtypep(); dtypep;) { m_arrayPost = false;
dtypep = dtypep->skipRefp(); iterateConstNull(nodep->dtypep()); // Dtype part before identifier
if (const AstUnpackArrayDType* const unpackp = VN_CAST(dtypep, UnpackArrayDType)) { puts(" ");
unpackps.push_back(unpackp); puts(nodep->prettyName());
dtypep = unpackp->subDTypep(); m_arrayPost = true;
} else { iterateConstNull(nodep->dtypep()); // Dtype part after identifier
iterateConst(dtypep);
puts(" ");
puts(nodep->prettyName());
dtypep = nullptr;
}
}
// If nodep is an unpacked array, append unpacked dimensions
for (const auto& unpackp : unpackps) {
puts("[");
puts(cvtToStr(unpackp->rangep()->leftConst()));
puts(":");
puts(cvtToStr(unpackp->rangep()->rightConst()));
puts("]");
}
puts(m_suppressVarSemi ? "\n" : ";\n"); puts(m_suppressVarSemi ? "\n" : ";\n");
} }
void visit(AstActive* nodep) override { void visit(AstActive* nodep) override {
VL_RESTORER(m_sensesp);
m_sensesp = nodep->sensesp(); m_sensesp = nodep->sensesp();
iterateAndNextConstNull(nodep->stmtsp()); iterateAndNextConstNull(nodep->stmtsp());
m_sensesp = nullptr;
} }
void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); } void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); }
void visit(AstVarScope*) override {}
void visit(AstNodeText*) override {} void visit(AstNodeText*) override {}
void visit(AstVarScope*) override {}
void visit(AstTraceDecl*) override {} void visit(AstTraceDecl*) override {}
void visit(AstTraceInc*) override {} void visit(AstTraceInc*) override {}
// NOPs // NOPs
@ -767,7 +842,6 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
} }
public: public:
bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars
explicit EmitVBaseVisitorConst(bool suppressUnknown, AstSenTree* domainp) explicit EmitVBaseVisitorConst(bool suppressUnknown, AstSenTree* domainp)
: m_suppressUnknown{suppressUnknown} : m_suppressUnknown{suppressUnknown}
, m_sensesp{domainp} {} , m_sensesp{domainp} {}

View File

@ -1,94 +1,65 @@
module Vt_debug_emitv_t; module Vt_debug_emitv_t;
input logic clk; input logic clk;
input logic in; input logic in;
typedef typedef enum logic [2:0] {
???? // ENUMDTYPE 't.e_t' ZERO = 3'h0,
ONE = 3'h1
???? // ENUMITEM 'ZERO' } e_t;
32'h0 typedef struct packed {
???? // ENUMITEM 'ONE' logic [2:0] a;
32'h1int signedstruct packed } ps_t;
{int signed a;}logic signed [2:0] struct typedef struct {
{logic signed [2:0] a;}logicunion logic signed [2:0] a;
{logic a;}struct packed } us_t;
{int signed a;}bit [31:0] const struct packed typedef union {
{int signed a;}const struct packed logic a;
{int signed a;}[0:2]struct } union_t;
{logic signed [2:0] a;}union const struct packed {
{logic a;}int signedint signed[0:2]logic [15:0] logic [15:0] logic [15:0] int signedint signedint signed logic [2:0] a;
???? // QUEUEDTYPE } ps[0:2];
int signedstring struct {
???? // ASSOCARRAYDTYPE logic signed [2:0] a;
int signed } us;
???? // DYNARRAYDTYPE union {
int signedint signedint signedint signedint signedint signedint signedreal signedstringIDatalogic signed [31:0] int signed e_t; logic a;
typedef struct packed } unu;
{int signed a;}logic signed [2:0] struct
{logic signed [2:0] a;}logicunion
{logic a;}struct packed
{int signed a;}bit [31:0] const struct packed
{int signed a;}const struct packed
{int signed a;}[0:2]struct
{logic signed [2:0] a;}union
{logic a;}int signedint signed[0:2]logic [15:0] logic [15:0] logic [15:0] int signedint signedint signed
???? // QUEUEDTYPE
int signedstring
???? // ASSOCARRAYDTYPE
int signed
???? // DYNARRAYDTYPE
int signedint signedint signedint signedint signedint signedint signedreal signedstringIDatalogic signed [31:0] int signed ps_t;
typedef struct
{logic signed [2:0] a;}logicunion
{logic a;}struct packed
{int signed a;}bit [31:0] const struct packed
{int signed a;}const struct packed
{int signed a;}[0:2]struct
{logic signed [2:0] a;}union
{logic a;}int signedint signed[0:2]logic [15:0] logic [15:0] logic [15:0] int signedint signedint signed
???? // QUEUEDTYPE
int signedstring
???? // ASSOCARRAYDTYPE
int signed
???? // DYNARRAYDTYPE
int signedint signedint signedint signedint signedint signedint signedreal signedstringIDatalogic signed [31:0] int signed us_t;
typedef union
{logic a;}struct packed
{int signed a;}bit [31:0] const struct packed
{int signed a;}const struct packed
{int signed a;}[0:2]struct
{logic signed [2:0] a;}union
{logic a;}int signedint signed[0:2]logic [15:0] logic [15:0] logic [15:0] int signedint signedint signed
???? // QUEUEDTYPE
int signedstring
???? // ASSOCARRAYDTYPE
int signed
???? // DYNARRAYDTYPE
int signedint signedint signedint signedint signedint signedint signedreal signedstringIDatalogic signed [31:0] int signed union_t;
struct packed
{int signed a;} ps[0:2];
struct
{logic signed [2:0] a;} us;
union
{logic a;} unu;
int signed array[0:2]; int signed array[0:2];
initial begin initial begin
array = '{0:32'sh1, 1:32'sh2, 2:32'sh3}; array = '{0:32'sh1, 1:32'sh2, 2:32'sh3};
end end
bit [6:5] [4:3] [2:1] arraymanyd[10:11][12:13][14:15];
logic [15:0] pubflat; logic [15:0] pubflat;
logic [15:0] pubflat_r; logic [15:0] pubflat_r;
logic [15:0] pubflat_w; logic [15:0] pubflat_w;
assign pubflat_w = pubflat; assign pubflat_w = pubflat;
int signed fd; int signed fd;
int signed i; int signed i;
int signed q[$];
???? // QUEUEDTYPE int signed qb[$:'sh3];
q; int signed assoc[string];
int signed assocassoc[string][real];
???? // ASSOCARRAYDTYPE int signed dyn[];
assoc; typedef struct packed {
logic nn1;
???? // DYNARRAYDTYPE } nested_named_t;
dyn; typedef struct packed {
struct packed {
logic nn2;
} nested_anonymous;
struct packed {
logic nn1;
} nested_named;
logic [11:10] nn3;
} nibble_t;
struct packed {
struct packed {
logic nn2;
} nested_anonymous;
struct packed {
logic nn1;
} nested_named;
logic [11:10] nn3;
} [5:4] nibblearray[3:2];
task t; task t;
$display("stmt"); $display("stmt");
endtask endtask
@ -111,7 +82,7 @@ module Vt_debug_emitv_t;
begin begin
other = f(i); other = f(i);
$display("stmt %~ %~", $display("stmt %~ %~",
iother, other); i, other);
t(); t();
end end
i = (i + 'h1); i = (i + 'h1);
@ -128,7 +99,7 @@ module Vt_debug_emitv_t;
$display("stmt"); $display("stmt");
end end
end end
always @([changed] in) begin always @( in) begin
begin begin
$display("stmt"); $display("stmt");
end end
@ -147,7 +118,7 @@ module Vt_debug_emitv_t;
int signed cyc; int signed cyc;
int signed fo; int signed fo;
int signed sum; int signed sum;
real signed r; real r;
string str; string str;
always @(posedge clk) begin always @(posedge clk) begin
begin begin
@ -156,7 +127,7 @@ module Vt_debug_emitv_t;
fo = cyc; fo = cyc;
sub.inc(fosum); sub.inc(fosum);
sum = sub.f(sum); sum = sub.f(sum);
$display("[%0t] sum = %~", $timesum, sum); $display("[%0t] sum = %~", $time, sum);
$display("a?= %d", ($c('sh1) ? $c('sh14) $display("a?= %d", ($c('sh1) ? $c('sh14)
: $c('sh1e))); : $c('sh1e)));
$c(;); $c(;);
@ -248,32 +219,23 @@ module Vt_debug_emitv_t;
else begin else begin
$display("0"); $display("0");
end end
$display("%~%~", $past(cyc)$past(cyc, 'sh1), $display("%~%~", $past(cyc), $past(cyc,
$past(cyc, 'sh1)); 'sh1));
str = $sformatf("cyc=%~", cyc); str = $sformatf("cyc=%~", cyc);
; ;
$display("str = %@", str); $display("str = %@", str);
$display("%% [%t] [%^] to=%o td=%d", $time $display("%% [%t] [%^] to=%o td=%d", $time,
$realtime$time$time, $realtime $realtime, $time, $time);
$time$time, $time$time, $time);
$sscanf(40'h666f6f3d35, "foo=%d", i); $sscanf(40'h666f6f3d35, "foo=%d", i);
; ;
$printtimescale; $printtimescale;
if ((i != 'sh5)) begin if ((i != 'sh5)) begin
$stop; $stop;
end end
sum = sum = $random();
???? // RAND sum = $random('sha);
; sum = $urandom();
sum = sum = $urandom('sha);
???? // RAND
'sha;
sum =
???? // RAND
;
sum =
???? // RAND
'sha;
if ((PKG_PARAM != 'sh1)) begin if ((PKG_PARAM != 'sh1)) begin
$stop; $stop;
end end
@ -318,8 +280,8 @@ package Vt_debug_emitv___024unit;
member = 'sh1; member = 'sh1;
task method; task method;
endtask endtask
task new; function new;
endtask endfunction
endclass endclass
endpackage endpackage
module Vt_debug_emitv_sub; module Vt_debug_emitv_sub;
@ -339,7 +301,7 @@ module Vt_debug_emitv_sub;
disable label0; disable label0;
end end
endfunction endfunction
real signed r; real r;
endmodule endmodule
package Vt_debug_emitv_p; package Vt_debug_emitv_p;
logic pkgvar; logic pkgvar;

View File

@ -16,7 +16,16 @@ test.lint(
# Likewise XML # Likewise XML
v_flags=["--lint-only --dumpi-tree 9 --dumpi-V3EmitV 9 --debug-emitv"]) v_flags=["--lint-only --dumpi-tree 9 --dumpi-V3EmitV 9 --debug-emitv"])
test.files_identical(test.glob_one(test.obj_dir + "/" + test.vm_prefix + "_*_width.tree.v"), output_v = test.glob_one(test.obj_dir + "/" + test.vm_prefix + "_*_width.tree.v")
test.golden_filename)
test.files_identical(output_v, test.golden_filename)
if test.verbose:
# Print if that the output Verilog is clean
# TODO not yet round-trip clean
test.run(cmd=[os.environ["VERILATOR_ROOT"] + "/bin/verilator", "--lint-only", output_v],
logfile=test.obj_dir + "/sim_roundtrip.log",
fails=True,
verilator_run=True)
test.passes() test.passes()

View File

@ -33,7 +33,7 @@ module t (/*AUTOARG*/
// verilator lint_off UNPACKED // verilator lint_off UNPACKED
typedef enum { typedef enum [2:0] {
ZERO, ZERO,
ONE = 1 ONE = 1
} e_t; } e_t;
@ -52,19 +52,35 @@ module t (/*AUTOARG*/
us_t us; us_t us;
union_t unu; union_t unu;
int array[3]; int array[3];
initial array = '{1,2,3}; initial array = '{1,2,3};
reg [15:0] pubflat /*verilator public_flat_rw @(posedge clk) */; bit [6:5][4:3][2:1] arraymanyd[10:11][12:13][14:15];
reg [15:0] pubflat_r; reg [15:0] pubflat /*verilator public_flat_rw @(posedge clk) */;
wire [15:0] pubflat_w = pubflat;
int fd;
int i;
int q[$]; reg [15:0] pubflat_r;
int assoc[string]; wire [15:0] pubflat_w = pubflat;
int dyn[]; int fd;
int i;
int q[$];
int qb[$ : 3];
int assoc[string];
int assocassoc[string][real];
int dyn[];
typedef struct packed {
logic nn1;
} nested_named_t;
typedef struct packed {
struct packed {
logic nn2;
} nested_anonymous;
nested_named_t nested_named;
logic [11:10] nn3;
} nibble_t;
nibble_t [5:4] nibblearray[3:2];
task t; task t;
$display("stmt"); $display("stmt");