Cleanup and test EmitV for internal coverage
This commit is contained in:
parent
c1d35c8622
commit
993115d30a
|
|
@ -31,6 +31,7 @@
|
||||||
class EmitVBaseVisitor : public EmitCBaseVisitor {
|
class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
bool m_suppressSemi = false;
|
bool m_suppressSemi = false;
|
||||||
|
bool m_suppressUnknown = false;
|
||||||
AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE
|
AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -51,12 +52,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); }
|
virtual void visit(AstNetlist* nodep) override { iterateAndNextNull(nodep->modulesp()); }
|
||||||
virtual void visit(AstNodeModule* nodep) override {
|
virtual void visit(AstNodeModule* nodep) override {
|
||||||
putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n");
|
putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n");
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
putqs(nodep, "end" + nodep->verilogKwd() + "\n");
|
putqs(nodep, "end" + nodep->verilogKwd() + "\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstPort* nodep) override {}
|
||||||
virtual void visit(AstNodeFTask* nodep) override {
|
virtual void visit(AstNodeFTask* nodep) override {
|
||||||
putfs(nodep, nodep->isFunction() ? "function" : "task");
|
putfs(nodep, nodep->isFunction() ? "function" : "task");
|
||||||
puts(" ");
|
puts(" ");
|
||||||
|
|
@ -654,13 +656,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
puts(string("\n???? // ") + nodep->prettyTypeName() + "\n");
|
puts(string("\n???? // ") + nodep->prettyTypeName() + "\n");
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Not v3fatalSrc so we keep processing
|
// Not v3fatalSrc so we keep processing
|
||||||
nodep->v3error("Internal: Unknown node type reached emitter: " << nodep->prettyTypeName());
|
if (!m_suppressUnknown) {
|
||||||
|
nodep->v3error(
|
||||||
|
"Internal: Unknown node type reached emitter: " << nodep->prettyTypeName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars
|
bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars
|
||||||
explicit EmitVBaseVisitor(AstSenTree* domainp = nullptr)
|
explicit EmitVBaseVisitor(bool suppressUnknown, AstSenTree* domainp)
|
||||||
: m_sensesp{domainp} {}
|
: m_suppressUnknown{suppressUnknown}
|
||||||
|
, m_sensesp{domainp} {}
|
||||||
virtual ~EmitVBaseVisitor() override {}
|
virtual ~EmitVBaseVisitor() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -679,8 +685,9 @@ class EmitVFileVisitor : public EmitVBaseVisitor {
|
||||||
virtual void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); }
|
virtual void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText = false,
|
EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText, bool suppressVarSemi,
|
||||||
bool suppressVarSemi = false) {
|
bool suppressUnknown)
|
||||||
|
: EmitVBaseVisitor{suppressUnknown, nullptr} {
|
||||||
m_ofp = ofp;
|
m_ofp = ofp;
|
||||||
m_trackText = trackText;
|
m_trackText = trackText;
|
||||||
m_suppressVarSemi = suppressVarSemi;
|
m_suppressVarSemi = suppressVarSemi;
|
||||||
|
|
@ -704,7 +711,8 @@ class EmitVStreamVisitor : public EmitVBaseVisitor {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EmitVStreamVisitor(AstNode* nodep, std::ostream& os)
|
EmitVStreamVisitor(AstNode* nodep, std::ostream& os)
|
||||||
: m_os(os) { // Need () or GCC 4.8 false warning
|
: EmitVBaseVisitor{false, nullptr}
|
||||||
|
, m_os(os) { // Need () or GCC 4.8 false warning
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
}
|
}
|
||||||
virtual ~EmitVStreamVisitor() override {}
|
virtual ~EmitVStreamVisitor() override {}
|
||||||
|
|
@ -747,9 +755,8 @@ public:
|
||||||
, m_prefix{prefix}
|
, m_prefix{prefix}
|
||||||
, m_flWidth{flWidth} {
|
, m_flWidth{flWidth} {
|
||||||
m_column = 0;
|
m_column = 0;
|
||||||
m_prefixFl
|
m_prefixFl = v3Global.rootp()->fileline(); // NETLIST's fileline instead of nullptr to
|
||||||
= v3Global.rootp()
|
// avoid nullptr checks
|
||||||
->fileline(); // NETLIST's fileline instead of nullptr to avoid nullptr checks
|
|
||||||
}
|
}
|
||||||
virtual ~EmitVPrefixedFormatter() override {
|
virtual ~EmitVPrefixedFormatter() override {
|
||||||
if (m_column) puts("\n");
|
if (m_column) puts("\n");
|
||||||
|
|
@ -780,7 +787,7 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor {
|
||||||
public:
|
public:
|
||||||
EmitVPrefixedVisitor(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth,
|
EmitVPrefixedVisitor(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth,
|
||||||
AstSenTree* domainp, bool user3mark)
|
AstSenTree* domainp, bool user3mark)
|
||||||
: EmitVBaseVisitor{domainp}
|
: EmitVBaseVisitor{false, domainp}
|
||||||
, m_formatter{os, prefix, flWidth} {
|
, m_formatter{os, prefix, flWidth} {
|
||||||
if (user3mark) { AstUser3InUse::check(); }
|
if (user3mark) { AstUser3InUse::check(); }
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
|
|
@ -807,7 +814,14 @@ void V3EmitV::emitvFiles() {
|
||||||
V3OutVFile of(vfilep->name());
|
V3OutVFile of(vfilep->name());
|
||||||
of.puts("// DESCR"
|
of.puts("// DESCR"
|
||||||
"IPTION: Verilator generated Verilog\n");
|
"IPTION: Verilator generated Verilog\n");
|
||||||
EmitVFileVisitor visitor(vfilep->tblockp(), &of, true, true);
|
EmitVFileVisitor visitor(vfilep->tblockp(), &of, true, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3EmitV::debugEmitV(const string& stage) {
|
||||||
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
|
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__" + stage + ".v";
|
||||||
|
V3OutVFile of(filename);
|
||||||
|
EmitVFileVisitor visitor(v3Global.rootp(), &of, true, false, true);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ public:
|
||||||
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix,
|
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix,
|
||||||
int flWidth, AstSenTree* domainp, bool user3mark);
|
int flWidth, AstSenTree* domainp, bool user3mark);
|
||||||
static void emitvFiles();
|
static void emitvFiles();
|
||||||
|
static void debugEmitV(const string& stage);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -1013,6 +1013,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||||
m_debugCheck = flag;
|
m_debugCheck = flag;
|
||||||
} else if (onoff(sw, "-debug-collision", flag /*ref*/)) { // Undocumented
|
} else if (onoff(sw, "-debug-collision", flag /*ref*/)) { // Undocumented
|
||||||
m_debugCollision = flag;
|
m_debugCollision = flag;
|
||||||
|
} else if (onoff(sw, "-debug-emitv", flag /*ref*/)) { // Undocumented
|
||||||
|
m_debugEmitV = flag;
|
||||||
} else if (onoff(sw, "-debug-exit-parse", flag /*ref*/)) { // Undocumented
|
} else if (onoff(sw, "-debug-exit-parse", flag /*ref*/)) { // Undocumented
|
||||||
m_debugExitParse = flag;
|
m_debugExitParse = flag;
|
||||||
} else if (onoff(sw, "-debug-exit-uvm", flag /*ref*/)) { // Undocumented
|
} else if (onoff(sw, "-debug-exit-uvm", flag /*ref*/)) { // Undocumented
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,7 @@ private:
|
||||||
bool m_coverageUser = false; // main switch: --coverage-func
|
bool m_coverageUser = false; // main switch: --coverage-func
|
||||||
bool m_debugCheck = false; // main switch: --debug-check
|
bool m_debugCheck = false; // main switch: --debug-check
|
||||||
bool m_debugCollision = false; // main switch: --debug-collision
|
bool m_debugCollision = false; // main switch: --debug-collision
|
||||||
|
bool m_debugEmitV = false; // main switch: --debug-emitv
|
||||||
bool m_debugExitParse = false; // main switch: --debug-exit-parse
|
bool m_debugExitParse = false; // main switch: --debug-exit-parse
|
||||||
bool m_debugExitUvm = false; // main switch: --debug-exit-uvm
|
bool m_debugExitUvm = false; // main switch: --debug-exit-uvm
|
||||||
bool m_debugLeak = true; // main switch: --debug-leak
|
bool m_debugLeak = true; // main switch: --debug-leak
|
||||||
|
|
@ -469,6 +470,7 @@ public:
|
||||||
bool coverageUser() const { return m_coverageUser; }
|
bool coverageUser() const { return m_coverageUser; }
|
||||||
bool debugCheck() const { return m_debugCheck; }
|
bool debugCheck() const { return m_debugCheck; }
|
||||||
bool debugCollision() const { return m_debugCollision; }
|
bool debugCollision() const { return m_debugCollision; }
|
||||||
|
bool debugEmitV() const { return m_debugEmitV; }
|
||||||
bool debugExitParse() const { return m_debugExitParse; }
|
bool debugExitParse() const { return m_debugExitParse; }
|
||||||
bool debugExitUvm() const { return m_debugExitUvm; }
|
bool debugExitUvm() const { return m_debugExitUvm; }
|
||||||
bool debugLeak() const { return m_debugLeak; }
|
bool debugLeak() const { return m_debugLeak; }
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ static void reportStatsIfEnabled() {
|
||||||
V3Stats::statsFinalAll(v3Global.rootp());
|
V3Stats::statsFinalAll(v3Global.rootp());
|
||||||
V3Stats::statsReport();
|
V3Stats::statsReport();
|
||||||
}
|
}
|
||||||
|
if (v3Global.opt.debugEmitV()) V3EmitV::debugEmitV("final");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process() {
|
static void process() {
|
||||||
|
|
@ -363,6 +364,7 @@ static void process() {
|
||||||
V3ActiveTop::activeTopAll(v3Global.rootp());
|
V3ActiveTop::activeTopAll(v3Global.rootp());
|
||||||
|
|
||||||
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "PreOrder");
|
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "PreOrder");
|
||||||
|
if (v3Global.opt.debugEmitV()) V3EmitV::debugEmitV("preorder");
|
||||||
|
|
||||||
// Order the code; form SBLOCKs and BLOCKCALLs
|
// Order the code; form SBLOCKs and BLOCKCALLs
|
||||||
V3Order::orderAll(v3Global.rootp());
|
V3Order::orderAll(v3Global.rootp());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
module Vt_debug_emitv;
|
||||||
|
input logic clk;
|
||||||
|
input logic in;
|
||||||
|
signed int [31:0] [0:2] t.array;
|
||||||
|
logic logic [15:0] t.pubflat;
|
||||||
|
logic logic [15:0] t.pubflat_r;
|
||||||
|
int signed int [31:0] t.fd;
|
||||||
|
int signed int [31:0] t.cyc;
|
||||||
|
int signed int [31:0] t.fo;
|
||||||
|
int signed int [31:0] t.sum;
|
||||||
|
string string t.str;
|
||||||
|
int signed int [31:0] t._Vpast_0_0;
|
||||||
|
int signed int [31:0] t._Vpast_1_0;
|
||||||
|
int signed int [31:0] t.unnamedblk3.i;
|
||||||
|
@(*)@([settle])@([initial])@(posedge clk)@(negedge
|
||||||
|
clk)always @(
|
||||||
|
*)@(
|
||||||
|
[settle])@(
|
||||||
|
[initial])@(
|
||||||
|
posedge
|
||||||
|
clk)@(
|
||||||
|
negedge
|
||||||
|
clk) begin
|
||||||
|
$display("stmt");
|
||||||
|
end
|
||||||
|
always @([settle])@([initial])@(posedge clk)@(negedge
|
||||||
|
clk) begin
|
||||||
|
$display("stmt");
|
||||||
|
end
|
||||||
|
initial begin
|
||||||
|
// Function: f
|
||||||
|
$write("stmt\nstmt 0 99\n");
|
||||||
|
// Function: t
|
||||||
|
$display("stmt");
|
||||||
|
// Function: f
|
||||||
|
$write("stmt\nstmt 1 -1\n");
|
||||||
|
// Function: t
|
||||||
|
$display("stmt");
|
||||||
|
// Function: f
|
||||||
|
$display("stmt");
|
||||||
|
$display("stmt 2 -2");
|
||||||
|
// Function: t
|
||||||
|
$display("stmt");
|
||||||
|
$display("stmt");
|
||||||
|
end
|
||||||
|
|
||||||
|
???? // CFUNC '_final_TOP'
|
||||||
|
$_CSTMT(Vt_debug_emitv* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||||
|
);
|
||||||
|
// FINAL
|
||||||
|
$display("stmt");
|
||||||
|
always @(posedge clk)@(negedge clk) begin
|
||||||
|
$display("posedge clk");
|
||||||
|
end
|
||||||
|
always @(posedge clk)@(negedge clk) begin
|
||||||
|
__Vdly__t.pubflat_r <= t.pubflat;
|
||||||
|
end
|
||||||
|
always @(posedge clk)@(negedge clk) begin
|
||||||
|
__Vdly__t.cyc <= (32'sh1 + t.cyc);
|
||||||
|
t.fo = t.cyc;
|
||||||
|
// Function: inc
|
||||||
|
__Vtask_t.sub.inc__2__i = t.fo;
|
||||||
|
__Vtask_t.sub.inc__2__o = (32'h1 + __Vtask_t.sub.inc__2__i[31:1]);
|
||||||
|
t.sum = __Vtask_t.sub.inc__2__o;
|
||||||
|
// Function: f
|
||||||
|
__Vfunc_t.sub.f__3__v = t.sum;
|
||||||
|
begin : label0
|
||||||
|
begin : label0
|
||||||
|
if ((32'sh0 == __Vfunc_t.sub.f__3__v)) begin
|
||||||
|
__Vfunc_t.sub.f__3__Vfuncout = 32'sh21;
|
||||||
|
disable label0;
|
||||||
|
end
|
||||||
|
__Vfunc_t.sub.f__3__Vfuncout = (32'h1
|
||||||
|
+ __Vfunc_t.sub.f__3__v[2]);
|
||||||
|
disable label0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
t.sum = __Vfunc_t.sub.f__3__Vfuncout;
|
||||||
|
$display("sum = %~", t.sum);
|
||||||
|
$c(;);
|
||||||
|
$display("%d", $c(0));
|
||||||
|
$fopen(72'h2f6465762f6e756c6c);
|
||||||
|
$fclose(t.fd);
|
||||||
|
$fopen(72'h2f6465762f6e756c6c, 8'h72);
|
||||||
|
$fgetc(t.fd);
|
||||||
|
$fflush(t.fd);
|
||||||
|
$fscanf(t.fd, "%d", t.sum);
|
||||||
|
;
|
||||||
|
$fdisplay(32'h69203d20, "%d", t.sum);
|
||||||
|
$fwrite(t.fd, "hello");
|
||||||
|
$readmemh(t.fd, t.array);
|
||||||
|
$readmemh(t.fd, t.array, 32'sh0);
|
||||||
|
$readmemh(t.fd, t.array, 32'sh0, 32'sh0);
|
||||||
|
t.sum = 32'sh0;
|
||||||
|
t.unnamedblk3.i = 32'sh0;
|
||||||
|
begin : label0
|
||||||
|
while ((t.unnamedblk3.i < t.cyc)) begin
|
||||||
|
t.sum = (t.sum + t.unnamedblk3.i);
|
||||||
|
if ((32'sha < t.sum)) begin
|
||||||
|
disable label0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
t.sum = (32'sh1 + t.sum);
|
||||||
|
end
|
||||||
|
t.unnamedblk3.i = (32'h1 + t.unnamedblk3.i);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ((32'sh63 == t.cyc)) begin
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
if ((32'sh64 == t.cyc)) begin
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("default");
|
||||||
|
end
|
||||||
|
if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("default");
|
||||||
|
end
|
||||||
|
if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("default");
|
||||||
|
end
|
||||||
|
if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("default");
|
||||||
|
end
|
||||||
|
if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("0");
|
||||||
|
end
|
||||||
|
priority if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("0");
|
||||||
|
end
|
||||||
|
unique if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("0");
|
||||||
|
end
|
||||||
|
unique0 if (in) begin
|
||||||
|
$display("1");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("0");
|
||||||
|
end
|
||||||
|
$display("%d%d", t._Vpast_0_0t._Vpast_1_0,
|
||||||
|
t._Vpast_1_0);
|
||||||
|
t.str = $sformatf("cyc=%~", t.cyc);
|
||||||
|
;
|
||||||
|
$display("str = %@", t.str);
|
||||||
|
$display("[%t] [%^]", $time$realtime, $realtime);
|
||||||
|
end
|
||||||
|
/*verilator public_flat_rw @(posedge clk)@(negedge
|
||||||
|
clk) t.pubflat*/
|
||||||
|
always @(posedge clk)@(negedge clk) begin
|
||||||
|
__Vdly__t._Vpast_0_0 <= t.cyc;
|
||||||
|
end
|
||||||
|
always @(posedge clk)@(negedge clk) begin
|
||||||
|
__Vdly__t._Vpast_1_0 <= t.cyc;
|
||||||
|
end
|
||||||
|
__Vdly__t._Vpast_1_0 = t._Vpast_1_0;
|
||||||
|
t._Vpast_1_0 = __Vdly__t._Vpast_1_0;
|
||||||
|
__Vdly__t._Vpast_0_0 = t._Vpast_0_0;
|
||||||
|
t._Vpast_0_0 = __Vdly__t._Vpast_0_0;
|
||||||
|
__Vdly__t.cyc = t.cyc;
|
||||||
|
t.cyc = __Vdly__t.cyc;
|
||||||
|
__Vdly__t.pubflat_r = t.pubflat_r;
|
||||||
|
t.pubflat_r = __Vdly__t.pubflat_r;
|
||||||
|
always @(negedge clk) begin
|
||||||
|
$display("negedge clk, pfr = %x", t.pubflat_r);
|
||||||
|
end
|
||||||
|
int signed int [31:0] __Vtask_t.sub.inc__2__i;
|
||||||
|
int signed int [31:0] __Vtask_t.sub.inc__2__o;
|
||||||
|
int signed int [31:0] __Vfunc_t.sub.f__3__Vfuncout;
|
||||||
|
int signed int [31:0] __Vfunc_t.sub.f__3__v;
|
||||||
|
logic logic [15:0] __Vdly__t.pubflat_r;
|
||||||
|
int signed int [31:0] __Vdly__t.cyc;
|
||||||
|
int signed int [31:0] __Vdly__t._Vpast_0_0;
|
||||||
|
int signed int [31:0] __Vdly__t._Vpast_1_0;
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
# We also have dump-tree turned on, so hit a lot of AstNode*::dump() functions
|
||||||
|
# Likewise XML
|
||||||
|
v_flags => ["--lint-only --dump-treei 9 --debug-emitv"],
|
||||||
|
);
|
||||||
|
|
||||||
|
files_identical("$Self->{obj_dir}/$Self->{VM_PREFIX}__preorder.v", $Self->{golden_filename});
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
// DESCRIPTION: Verilator: Dotted reference that uses another dotted reference
|
||||||
|
// as the select expression
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk, in
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
input in;
|
||||||
|
|
||||||
|
// verilator lint_off UNPACKED
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZERO,
|
||||||
|
ONE = 1
|
||||||
|
} e_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
e_t a;
|
||||||
|
} ps_t;
|
||||||
|
typedef struct {
|
||||||
|
logic signed [2:0] a;
|
||||||
|
} us_t;
|
||||||
|
|
||||||
|
const ps_t ps[3];
|
||||||
|
us_t us;
|
||||||
|
|
||||||
|
int array[3];
|
||||||
|
initial array = '{1,2,3};
|
||||||
|
|
||||||
|
reg [15:0] pubflat /*verilator public_flat_rw @(posedge clk) */;
|
||||||
|
|
||||||
|
reg [15:0] pubflat_r;
|
||||||
|
wire [15:0] pubflat_w = pubflat;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
task t;
|
||||||
|
$display("stmt");
|
||||||
|
endtask
|
||||||
|
function int f(input int v);
|
||||||
|
$display("stmt");
|
||||||
|
return v == 0 ? 99 : ~v + 1;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
sub sub();
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int other;
|
||||||
|
begin //unnamed
|
||||||
|
for (int i = 0; i < 3; ++i) begin
|
||||||
|
other = f(i);
|
||||||
|
$display("stmt %d %d", i, other);
|
||||||
|
t();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
begin : named
|
||||||
|
$display("stmt");
|
||||||
|
end : named
|
||||||
|
end
|
||||||
|
final begin
|
||||||
|
$display("stmt");
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (in) begin
|
||||||
|
$display("stmt");
|
||||||
|
end
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
$display("posedge clk");
|
||||||
|
pubflat_r <= pubflat_w;
|
||||||
|
end
|
||||||
|
always @ (negedge clk) begin
|
||||||
|
$display("negedge clk, pfr = %x", pubflat_r);
|
||||||
|
end
|
||||||
|
|
||||||
|
int cyc;
|
||||||
|
int fo;
|
||||||
|
int sum;
|
||||||
|
string str;
|
||||||
|
always_ff @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
fo = cyc;
|
||||||
|
sub.inc(fo, sum);
|
||||||
|
sum = sub.f(sum);
|
||||||
|
$display("sum = %d", sum);
|
||||||
|
|
||||||
|
$c(";");
|
||||||
|
$display("%d", $c("0"));
|
||||||
|
fd = $fopen("/dev/null");
|
||||||
|
$fclose(fd);
|
||||||
|
fd = $fopen("/dev/null", "r");
|
||||||
|
$fgetc(fd); // stmt
|
||||||
|
$fflush(fd);
|
||||||
|
$fscanf(fd, "%d", sum);
|
||||||
|
$fdisplay("i = ", sum);
|
||||||
|
$fwrite(fd, "hello");
|
||||||
|
$readmemh(fd, array);
|
||||||
|
$readmemh(fd, array, 0);
|
||||||
|
$readmemh(fd, array, 0, 0);
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
for (int i = 0; i < cyc; ++i) begin
|
||||||
|
sum += i;
|
||||||
|
if (sum > 10) break;
|
||||||
|
else sum += 1;
|
||||||
|
end
|
||||||
|
if (cyc == 99) $finish;
|
||||||
|
if (cyc == 100) $stop;
|
||||||
|
|
||||||
|
case (in) // synopsys full_case parallel_case
|
||||||
|
1: $display("1");
|
||||||
|
default: $display("default");
|
||||||
|
endcase
|
||||||
|
priority case (in)
|
||||||
|
1: $display("1");
|
||||||
|
default: $display("default");
|
||||||
|
endcase
|
||||||
|
unique case (in)
|
||||||
|
1: $display("1");
|
||||||
|
default: $display("default");
|
||||||
|
endcase
|
||||||
|
unique0 case (in)
|
||||||
|
1: $display("1");
|
||||||
|
default: $display("default");
|
||||||
|
endcase
|
||||||
|
if (in) $display("1"); else $display("0");
|
||||||
|
priority if (in) $display("1"); else $display("0");
|
||||||
|
unique if (in) $display("1"); else $display("0");
|
||||||
|
unique0 if (in) $display("1"); else $display("0");
|
||||||
|
|
||||||
|
$display($past(cyc), $past(cyc, 1));
|
||||||
|
|
||||||
|
str = $sformatf("cyc=%d", cyc);
|
||||||
|
$display("str = %s", str);
|
||||||
|
$display("[%t] [%t]", $time, $realtime);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub();
|
||||||
|
task inc(input int i, output int o);
|
||||||
|
o = {1'b0, i[31:1]} + 32'd1;
|
||||||
|
endtask
|
||||||
|
function int f(input int v);
|
||||||
|
if (v == 0) return 33;
|
||||||
|
return {31'd0, v[2]} + 32'd1;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue