parent
37d68d39c8
commit
f6c0108c86
1
Changes
1
Changes
|
|
@ -36,6 +36,7 @@ Verilator 4.202 2021-04-24
|
||||||
* Add PINNOTFOUND warning in place of error (#2868). [Udi Finkelstein]
|
* Add PINNOTFOUND warning in place of error (#2868). [Udi Finkelstein]
|
||||||
* Support overlaps in priority case statements (#2864). [Rupert Swarbrick]
|
* Support overlaps in priority case statements (#2864). [Rupert Swarbrick]
|
||||||
* Support for null ports (#2875). [Udi Finkelstein]
|
* Support for null ports (#2875). [Udi Finkelstein]
|
||||||
|
* Optimize large lookup tables to static data (#2925). [Geza Lore]
|
||||||
* Fix class unpacked-array compile error (#2774). [Iru Cai]
|
* Fix class unpacked-array compile error (#2774). [Iru Cai]
|
||||||
* Fix scope types in FST and VCD traces (#2805). [Alex Torregrosa]
|
* Fix scope types in FST and VCD traces (#2805). [Alex Torregrosa]
|
||||||
* Fix exceeding command-line ar limit (#2834). [Yinan Xu]
|
* Fix exceeding command-line ar limit (#2834). [Yinan Xu]
|
||||||
|
|
|
||||||
|
|
@ -1814,13 +1814,18 @@ class EmitCImp final : EmitCStmts {
|
||||||
splitSizeInc(1);
|
splitSizeInc(1);
|
||||||
if (dtypep->isWide()) { // Handle unpacked; not basicp->isWide
|
if (dtypep->isWide()) { // Handle unpacked; not basicp->isWide
|
||||||
string out;
|
string out;
|
||||||
if (zeroit) {
|
if (varp->valuep()) {
|
||||||
out += "VL_ZERO_RESET_W(";
|
AstConst* const constp = VN_CAST(varp->valuep(), Const);
|
||||||
|
if (!constp) varp->v3fatalSrc("non-const initializer for variable");
|
||||||
|
for (int w = 0; w < varp->widthWords(); ++w) {
|
||||||
|
out += varp->nameProtect() + suffix + "[" + cvtToStr(w) + "] = ";
|
||||||
|
out += cvtToStr(constp->num().edataWord(w)) + "U;\n";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out += "VL_RAND_RESET_W(";
|
out += zeroit ? "VL_ZERO_RESET_W(" : "VL_RAND_RESET_W(";
|
||||||
|
out += cvtToStr(dtypep->widthMin());
|
||||||
|
out += ", " + varp->nameProtect() + suffix + ");\n";
|
||||||
}
|
}
|
||||||
out += cvtToStr(dtypep->widthMin());
|
|
||||||
out += ", " + varp->nameProtect() + suffix + ");\n";
|
|
||||||
return out;
|
return out;
|
||||||
} else {
|
} else {
|
||||||
string out = varp->nameProtect() + suffix;
|
string out = varp->nameProtect() + suffix;
|
||||||
|
|
|
||||||
|
|
@ -1526,11 +1526,8 @@ bool V3Number::isCaseEq(const V3Number& rhs) const {
|
||||||
if (isString()) return toString() == rhs.toString();
|
if (isString()) return toString() == rhs.toString();
|
||||||
if (isDouble()) return toDouble() == rhs.toDouble();
|
if (isDouble()) return toDouble() == rhs.toDouble();
|
||||||
if (this->width() != rhs.width()) return false;
|
if (this->width() != rhs.width()) return false;
|
||||||
|
if (m_value != rhs.m_value) return false;
|
||||||
for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) {
|
return m_valueX == rhs.m_valueX;
|
||||||
if (this->bitIs(bit) != rhs.bitIs(bit)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
V3Number& V3Number::opCaseEq(const V3Number& lhs, const V3Number& rhs) {
|
V3Number& V3Number::opCaseEq(const V3Number& lhs, const V3Number& rhs) {
|
||||||
|
|
|
||||||
|
|
@ -30,17 +30,21 @@
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Premit.h"
|
#include "V3Premit.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
#include "V3Hashed.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
constexpr int STATIC_CONST_MIN_WIDTH = 256; // Minimum size to extract to static constant
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Structure for global state
|
// Structure for global state
|
||||||
|
|
||||||
class PremitAssignVisitor final : public AstNVisitor {
|
class PremitAssignVisitor final : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// AstVar::user4() // bool; occurs on LHS of current assignment
|
// AstVar::user3() // bool; occurs on LHS of current assignment
|
||||||
AstUser4InUse m_inuser4;
|
AstUser3InUse m_inuser3;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_noopt = false; // Disable optimization of variables in this block
|
bool m_noopt = false; // Disable optimization of variables in this block
|
||||||
|
|
@ -50,7 +54,7 @@ private:
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeAssign* nodep) override {
|
virtual void visit(AstNodeAssign* nodep) override {
|
||||||
// AstNode::user4ClearTree(); // Implied by AstUser4InUse
|
// AstNode::user3ClearTree(); // Implied by AstUser3InUse
|
||||||
// LHS first as fewer varrefs
|
// LHS first as fewer varrefs
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
// Now find vars marked as lhs
|
// Now find vars marked as lhs
|
||||||
|
|
@ -59,9 +63,9 @@ private:
|
||||||
virtual void visit(AstVarRef* nodep) override {
|
virtual void visit(AstVarRef* nodep) override {
|
||||||
// it's LHS var is used so need a deep temporary
|
// it's LHS var is used so need a deep temporary
|
||||||
if (nodep->access().isWriteOrRW()) {
|
if (nodep->access().isWriteOrRW()) {
|
||||||
nodep->varp()->user4(true);
|
nodep->varp()->user3(true);
|
||||||
} else {
|
} else {
|
||||||
if (nodep->varp()->user4()) {
|
if (nodep->varp()->user3()) {
|
||||||
if (!m_noopt) UINFO(4, "Block has LHS+RHS var: " << nodep << endl);
|
if (!m_noopt) UINFO(4, "Block has LHS+RHS var: " << nodep << endl);
|
||||||
m_noopt = true;
|
m_noopt = true;
|
||||||
}
|
}
|
||||||
|
|
@ -88,9 +92,11 @@ private:
|
||||||
// AstNodeMath::user() -> bool. True if iterated already
|
// AstNodeMath::user() -> bool. True if iterated already
|
||||||
// AstShiftL::user2() -> bool. True if converted to conditional
|
// AstShiftL::user2() -> bool. True if converted to conditional
|
||||||
// AstShiftR::user2() -> bool. True if converted to conditional
|
// AstShiftR::user2() -> bool. True if converted to conditional
|
||||||
|
// AstConst::user2p() -> Replacement static variable pointer
|
||||||
// *::user4() -> See PremitAssignVisitor
|
// *::user4() -> See PremitAssignVisitor
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
|
// AstUser4InUse part of V3Hashed
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp = nullptr; // Current module
|
AstNodeModule* m_modp = nullptr; // Current module
|
||||||
|
|
@ -100,6 +106,11 @@ private:
|
||||||
AstTraceInc* m_inTracep = nullptr; // Inside while loop, special statement additions
|
AstTraceInc* m_inTracep = nullptr; // Inside while loop, special statement additions
|
||||||
bool m_assignLhs = false; // Inside assignment lhs, don't breakup extracts
|
bool m_assignLhs = false; // Inside assignment lhs, don't breakup extracts
|
||||||
|
|
||||||
|
V3Hashed m_hashed; // Hash set for static constants that can be reused
|
||||||
|
|
||||||
|
VDouble0 m_staticConstantsExtracted; // Statistic tracking
|
||||||
|
VDouble0 m_staticConstantsReused; // Statistic tracking
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
||||||
|
|
@ -139,14 +150,6 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstVar* getBlockTemp(AstNode* nodep) {
|
|
||||||
string newvarname = (string("__Vtemp") + cvtToStr(m_modp->varNumGetInc()));
|
|
||||||
AstVar* varp
|
|
||||||
= new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname, nodep->dtypep());
|
|
||||||
m_cfuncp->addInitsp(varp);
|
|
||||||
return varp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void insertBeforeStmt(AstNode* newp) {
|
void insertBeforeStmt(AstNode* newp) {
|
||||||
// Insert newp before m_stmtp
|
// Insert newp before m_stmtp
|
||||||
if (m_inWhilep) {
|
if (m_inWhilep) {
|
||||||
|
|
@ -173,28 +176,66 @@ private:
|
||||||
AstNRelinker linker;
|
AstNRelinker linker;
|
||||||
nodep->unlinkFrBack(&linker);
|
nodep->unlinkFrBack(&linker);
|
||||||
|
|
||||||
AstVar* varp = getBlockTemp(nodep);
|
AstVar* varp = nullptr;
|
||||||
|
|
||||||
|
AstConst* const constp = VN_CAST(nodep, Const);
|
||||||
|
|
||||||
|
const bool useStatic = constp && (constp->width() >= STATIC_CONST_MIN_WIDTH)
|
||||||
|
&& !constp->num().isFourState();
|
||||||
|
if (useStatic) {
|
||||||
|
// Extract as static constant
|
||||||
|
m_hashed.hash(constp);
|
||||||
|
const auto& it = m_hashed.findDuplicate(constp);
|
||||||
|
if (it == m_hashed.end()) {
|
||||||
|
const string newvarname = string("__Vconst") + cvtToStr(m_modp->varNumGetInc());
|
||||||
|
varp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, newvarname,
|
||||||
|
nodep->dtypep());
|
||||||
|
varp->isConst(true);
|
||||||
|
varp->isStatic(true);
|
||||||
|
varp->valuep(constp);
|
||||||
|
m_modp->addStmtp(varp);
|
||||||
|
m_hashed.hashAndInsert(constp);
|
||||||
|
nodep->user2p(varp);
|
||||||
|
++m_staticConstantsExtracted;
|
||||||
|
} else {
|
||||||
|
varp = VN_CAST(it->second->user2p(), Var);
|
||||||
|
++m_staticConstantsReused;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Keep as local temporary
|
||||||
|
const string newvarname = string("__Vtemp") + cvtToStr(m_modp->varNumGetInc());
|
||||||
|
varp
|
||||||
|
= new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname, nodep->dtypep());
|
||||||
|
m_cfuncp->addInitsp(varp);
|
||||||
|
}
|
||||||
|
|
||||||
if (noSubst) varp->noSubst(true); // Do not remove varrefs to this in V3Const
|
if (noSubst) varp->noSubst(true); // Do not remove varrefs to this in V3Const
|
||||||
|
|
||||||
// Replace node tree with reference to var
|
// Replace node tree with reference to var
|
||||||
AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, VAccess::READ);
|
AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, VAccess::READ);
|
||||||
linker.relink(newp);
|
linker.relink(newp);
|
||||||
// Put assignment before the referencing statement
|
|
||||||
AstAssign* assp = new AstAssign(
|
if (!useStatic) {
|
||||||
nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), nodep);
|
// Put assignment before the referencing statement
|
||||||
insertBeforeStmt(assp);
|
AstAssign* assp = new AstAssign(
|
||||||
if (debug() > 8) assp->dumpTree(cout, "deepou:");
|
nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), nodep);
|
||||||
|
insertBeforeStmt(assp);
|
||||||
|
if (debug() > 8) assp->dumpTree(cout, "deepou:");
|
||||||
|
}
|
||||||
|
|
||||||
nodep->user1(true); // Don't add another assignment
|
nodep->user1(true); // Don't add another assignment
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep) override {
|
virtual void visit(AstNodeModule* nodep) override {
|
||||||
UINFO(4, " MOD " << nodep << endl);
|
UINFO(4, " MOD " << nodep << endl);
|
||||||
VL_RESTORER(m_modp);
|
UASSERT_OBJ(m_modp == nullptr, nodep, "Nested modules ?");
|
||||||
{
|
UASSERT_OBJ(m_hashed.mmap().empty(), nodep, "Statements outside module ?");
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_cfuncp = nullptr;
|
m_cfuncp = nullptr;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
m_modp = nullptr;
|
||||||
|
m_hashed.clear();
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep) override {
|
virtual void visit(AstCFunc* nodep) override {
|
||||||
VL_RESTORER(m_cfuncp);
|
VL_RESTORER(m_cfuncp);
|
||||||
|
|
@ -401,7 +442,11 @@ private:
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit PremitVisitor(AstNetlist* nodep) { iterate(nodep); }
|
explicit PremitVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||||
virtual ~PremitVisitor() override = default;
|
virtual ~PremitVisitor() {
|
||||||
|
V3Stats::addStat("Optimizations, Prelim static constants extracted",
|
||||||
|
m_staticConstantsExtracted);
|
||||||
|
V3Stats::addStat("Optimizations, Prelim static constants reused", m_staticConstantsReused);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
0x88888888
|
||||||
|
0x77777777
|
||||||
|
0x66666666
|
||||||
|
0x55555555
|
||||||
|
0x44444444
|
||||||
|
0x33333333
|
||||||
|
0x22222222
|
||||||
|
0x11111111
|
||||||
|
*-* All Finished *-*
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/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_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--stats"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($Self->{vlt}) {
|
||||||
|
# Note, with vltmt this might be split differently, so only checking vlt
|
||||||
|
file_grep($Self->{stats}, qr/Optimizations, Prelim static constants extracted\s+(\d+)/i,
|
||||||
|
1);
|
||||||
|
file_grep($Self->{stats}, qr/Optimizations, Prelim static constants reused\s+(\d+)/i,
|
||||||
|
7);
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Geza Lore.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
wire [255:0] C = {32'h1111_1111,
|
||||||
|
32'h2222_2222,
|
||||||
|
32'h3333_3333,
|
||||||
|
32'h4444_4444,
|
||||||
|
32'h5555_5555,
|
||||||
|
32'h6666_6666,
|
||||||
|
32'h7777_7777,
|
||||||
|
32'h8888_8888};
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Note: Base index via $c to prevent optimizatoin by Verilator
|
||||||
|
$display("0x%32x", C[$c(0*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(1*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(2*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(3*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(4*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(5*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(6*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(7*32)+:32]);
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
0x88888888
|
||||||
|
0x66666666
|
||||||
|
0x44444444
|
||||||
|
0x22222222
|
||||||
|
0x1111111122222222333333334444444455555555666666667777777788888888
|
||||||
|
0x77777777
|
||||||
|
0x55555555
|
||||||
|
0x33333333
|
||||||
|
0x11111111
|
||||||
|
0x1111111122222222333333334444444455555555666666667777777788888888
|
||||||
|
*-* All Finished *-*
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/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_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--stats"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($Self->{vlt}) {
|
||||||
|
# Note, with vltmt this might be split differently, so only checking vlt
|
||||||
|
file_grep($Self->{stats}, qr/Optimizations, Prelim static constants extracted\s+(\d+)/i,
|
||||||
|
2);
|
||||||
|
file_grep($Self->{stats}, qr/Optimizations, Prelim static constants reused\s+(\d+)/i,
|
||||||
|
6);
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Geza Lore.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constants should not be shared by different non-inlined modules
|
||||||
|
//
|
||||||
|
|
||||||
|
module a(
|
||||||
|
input wire clk,
|
||||||
|
input wire trig_i,
|
||||||
|
output reg trig_o
|
||||||
|
);
|
||||||
|
/* verilator no_inline_module */
|
||||||
|
|
||||||
|
// Same constant as in module b
|
||||||
|
wire [255:0] C = {32'h1111_1111,
|
||||||
|
32'h2222_2222,
|
||||||
|
32'h3333_3333,
|
||||||
|
32'h4444_4444,
|
||||||
|
32'h5555_5555,
|
||||||
|
32'h6666_6666,
|
||||||
|
32'h7777_7777,
|
||||||
|
32'h8888_8888};
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
trig_o <= 1'd0;
|
||||||
|
if (trig_i) begin
|
||||||
|
// Note: Base index via $c to prevent optimizatoin by Verilator
|
||||||
|
$display("0x%32x", C[$c(0*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(2*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(4*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(6*32)+:32]);
|
||||||
|
$display("0x%256x", C);
|
||||||
|
trig_o <= 1'd1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module b(
|
||||||
|
input wire clk,
|
||||||
|
input wire trig_i,
|
||||||
|
output reg trig_o
|
||||||
|
);
|
||||||
|
/* verilator no_inline_module */
|
||||||
|
|
||||||
|
// Same constant as in module a
|
||||||
|
wire [255:0] C = {32'h1111_1111,
|
||||||
|
32'h2222_2222,
|
||||||
|
32'h3333_3333,
|
||||||
|
32'h4444_4444,
|
||||||
|
32'h5555_5555,
|
||||||
|
32'h6666_6666,
|
||||||
|
32'h7777_7777,
|
||||||
|
32'h8888_8888};
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
trig_o <= 1'd0;
|
||||||
|
if (trig_i) begin
|
||||||
|
// Note: Base index via $c to prevent optimizatoin by Verilator
|
||||||
|
$display("0x%32x", C[$c(1*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(3*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(5*32)+:32]);
|
||||||
|
$display("0x%32x", C[$c(7*32)+:32]);
|
||||||
|
$display("0x%256x", C);
|
||||||
|
trig_o <= 1'd1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc = 0;
|
||||||
|
|
||||||
|
reg trig_i;
|
||||||
|
wire trig_ab;
|
||||||
|
wire trig_o;
|
||||||
|
|
||||||
|
a a_inst(.clk(clk), .trig_i(trig_i), .trig_o(trig_ab));
|
||||||
|
b b_inst(.clk(clk), .trig_i(trig_ab), .trig_o(trig_o));
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
trig_i <= cyc == 1;
|
||||||
|
|
||||||
|
if (trig_o) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
cyc++;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue