mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Support for wired nets, wor
/trior
/wand
/triand
. (#5496)
This commit is contained in:
parent
041f6603c3
commit
1710b6bab4
18
src/V3Ast.h
18
src/V3Ast.h
@ -899,6 +899,8 @@ public:
|
|||||||
SUPPLY1,
|
SUPPLY1,
|
||||||
WIRE,
|
WIRE,
|
||||||
WREAL,
|
WREAL,
|
||||||
|
TRIAND,
|
||||||
|
TRIOR,
|
||||||
TRIWIRE,
|
TRIWIRE,
|
||||||
TRI0,
|
TRI0,
|
||||||
TRI1,
|
TRI1,
|
||||||
@ -919,20 +921,24 @@ public:
|
|||||||
constexpr operator en() const { return m_e; }
|
constexpr operator en() const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* const names[]
|
static const char* const names[]
|
||||||
= {"?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1",
|
= {"?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1",
|
||||||
"WIRE", "WREAL", "TRIWIRE", "TRI0", "TRI1", "PORT", "BLOCKTEMP",
|
"WIRE", "WREAL", "TRIAND", "TRIOR", "TRIWIRE", "TRI0", "TRI1",
|
||||||
"MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
|
"PORT", "BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
}
|
}
|
||||||
bool isParam() const { return m_e == GPARAM || m_e == LPARAM; }
|
bool isParam() const { return m_e == GPARAM || m_e == LPARAM; }
|
||||||
bool isSignal() const {
|
bool isSignal() const {
|
||||||
return (m_e == WIRE || m_e == WREAL || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1
|
return (m_e == WIRE || m_e == WREAL || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1
|
||||||
|| m_e == PORT || m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == VAR);
|
|| m_e == PORT || m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == VAR || m_e == TRIOR
|
||||||
|
|| m_e == TRIAND);
|
||||||
}
|
}
|
||||||
bool isNet() const {
|
bool isNet() const {
|
||||||
return (m_e == WIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1 || m_e == SUPPLY0
|
return (m_e == WIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1 || m_e == SUPPLY0
|
||||||
|| m_e == SUPPLY1);
|
|| m_e == SUPPLY1 || m_e == TRIOR || m_e == TRIAND);
|
||||||
}
|
}
|
||||||
|
bool isWor() const { return (m_e == TRIOR); }
|
||||||
|
bool isWand() const { return (m_e == TRIAND); }
|
||||||
|
bool isWiredNet() const { return (m_e == TRIOR || m_e == TRIAND); }
|
||||||
bool isContAssignable() const { // In Verilog, always ok in SystemVerilog
|
bool isContAssignable() const { // In Verilog, always ok in SystemVerilog
|
||||||
return (m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == WIRE || m_e == WREAL || m_e == TRIWIRE
|
return (m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == WIRE || m_e == WREAL || m_e == TRIWIRE
|
||||||
|| m_e == TRI0 || m_e == TRI1 || m_e == PORT || m_e == BLOCKTEMP
|
|| m_e == TRI0 || m_e == TRI1 || m_e == PORT || m_e == BLOCKTEMP
|
||||||
@ -963,6 +969,8 @@ public:
|
|||||||
/* SUPPLY1: */ "SUPPLY1",
|
/* SUPPLY1: */ "SUPPLY1",
|
||||||
/* WIRE: */ "WIRE",
|
/* WIRE: */ "WIRE",
|
||||||
/* WREAL: */ "WIRE",
|
/* WREAL: */ "WIRE",
|
||||||
|
/* TRIAND: */ "TRIAND",
|
||||||
|
/* TRIOR: */ "TRIOR",
|
||||||
/* TRIWIRE: */ "TRI",
|
/* TRIWIRE: */ "TRI",
|
||||||
/* TRI0: */ "TRI0",
|
/* TRI0: */ "TRI0",
|
||||||
/* TRI1: */ "TRI1",
|
/* TRI1: */ "TRI1",
|
||||||
|
@ -2073,6 +2073,9 @@ public:
|
|||||||
bool isInternal() const { return m_isInternal; }
|
bool isInternal() const { return m_isInternal; }
|
||||||
bool isSignal() const { return varType().isSignal(); }
|
bool isSignal() const { return varType().isSignal(); }
|
||||||
bool isNet() const { return varType().isNet(); }
|
bool isNet() const { return varType().isNet(); }
|
||||||
|
bool isWor() const { return varType().isWor(); }
|
||||||
|
bool isWand() const { return varType().isWand(); }
|
||||||
|
bool isWiredNet() const { return varType().isWiredNet(); }
|
||||||
bool isTemp() const { return varType().isTemp(); }
|
bool isTemp() const { return varType().isTemp(); }
|
||||||
bool isToggleCoverable() const {
|
bool isToggleCoverable() const {
|
||||||
return ((isIO() || isSignal())
|
return ((isIO() || isSignal())
|
||||||
|
@ -914,6 +914,51 @@ class TristateVisitor final : public TristateBaseVisitor {
|
|||||||
|| (strength1 <= strength && assignmentOfValueOnAllBits(assignp, 1));
|
|| (strength1 <= strength && assignmentOfValueOnAllBits(assignp, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeExpr* newMergeExpr(AstNodeExpr* const lhsp, AstNodeExpr* const rhsp, FileLine* const fl,
|
||||||
|
bool isWor) {
|
||||||
|
AstNodeExpr* expr = nullptr;
|
||||||
|
if (isWor)
|
||||||
|
expr = new AstOr{fl, lhsp, rhsp};
|
||||||
|
else
|
||||||
|
expr = new AstAnd{fl, lhsp, rhsp};
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mergeWiredNetsAssignments() {
|
||||||
|
// Support for WOR/TRIOR/WAND/TRIAND, by merging the Assignments for the
|
||||||
|
// same Net (merge by or for WOR/TIOR and merge by and for WAND/TRIAND).
|
||||||
|
for (auto& varpAssigns : m_assigns) {
|
||||||
|
Assigns& assigns = varpAssigns.second;
|
||||||
|
if (assigns.size() > 1) {
|
||||||
|
AstVar* varp = varpAssigns.first;
|
||||||
|
if (varp->isWiredNet()) {
|
||||||
|
auto it = assigns.begin();
|
||||||
|
AstAssignW* const assignWp0 = *it;
|
||||||
|
FileLine* const fl = assignWp0->fileline();
|
||||||
|
AstNodeExpr* wExp = nullptr;
|
||||||
|
while (++it != assigns.end()) {
|
||||||
|
AstAssignW* assignWpi = *it;
|
||||||
|
if (!wExp) {
|
||||||
|
wExp = newMergeExpr(assignWp0->rhsp()->cloneTreePure(false),
|
||||||
|
assignWpi->rhsp()->cloneTreePure(false), fl,
|
||||||
|
varp->isWor());
|
||||||
|
} else {
|
||||||
|
wExp = newMergeExpr(wExp, assignWpi->rhsp()->cloneTreePure(false), fl,
|
||||||
|
varp->isWor());
|
||||||
|
}
|
||||||
|
VL_DO_DANGLING((assignWpi->unlinkFrBack()->deleteTree()), assignWpi);
|
||||||
|
}
|
||||||
|
AstVarRef* const wVarRef = new AstVarRef{fl, varp, VAccess::WRITE};
|
||||||
|
AstAssignW* const wAssignp = new AstAssignW{fl, wVarRef, wExp};
|
||||||
|
assignWp0->replaceWith(wAssignp);
|
||||||
|
VL_DO_DANGLING(pushDeletep(assignWp0), assignWp0);
|
||||||
|
assigns.clear();
|
||||||
|
assigns.push_back(wAssignp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void removeNotStrongerAssignments(Assigns& assigns, AstAssignW* strongestp,
|
void removeNotStrongerAssignments(Assigns& assigns, AstAssignW* strongestp,
|
||||||
uint8_t greatestKnownStrength) {
|
uint8_t greatestKnownStrength) {
|
||||||
// Weaker assignments are these assignments that can't change the final value of the net.
|
// Weaker assignments are these assignments that can't change the final value of the net.
|
||||||
@ -1776,6 +1821,8 @@ class TristateVisitor final : public TristateBaseVisitor {
|
|||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_graphing = false;
|
m_graphing = false;
|
||||||
}
|
}
|
||||||
|
// Merge the assignments for very Wired net LHS : wor, trior, wand and triand
|
||||||
|
mergeWiredNetsAssignments();
|
||||||
// Remove all assignments not stronger than the strongest uniform constant
|
// Remove all assignments not stronger than the strongest uniform constant
|
||||||
removeAssignmentsNotStrongerThanUniformConstant();
|
removeAssignmentsNotStrongerThanUniformConstant();
|
||||||
// Use graph to find tristate signals
|
// Use graph to find tristate signals
|
||||||
|
@ -1994,12 +1994,12 @@ net_type: // ==IEEE: net_type
|
|||||||
| yTRI { VARDECL(TRIWIRE); }
|
| yTRI { VARDECL(TRIWIRE); }
|
||||||
| yTRI0 { VARDECL(TRI0); }
|
| yTRI0 { VARDECL(TRI0); }
|
||||||
| yTRI1 { VARDECL(TRI1); }
|
| yTRI1 { VARDECL(TRI1); }
|
||||||
| yTRIAND { VARDECL(WIRE); BBUNSUP($1, "Unsupported: triand"); }
|
| yTRIAND { VARDECL(TRIAND); }
|
||||||
| yTRIOR { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trior"); }
|
| yTRIOR { VARDECL(TRIOR); }
|
||||||
| yTRIREG { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trireg"); }
|
| yTRIREG { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trireg"); }
|
||||||
| yWAND { VARDECL(WIRE); BBUNSUP($1, "Unsupported: wand"); }
|
| yWAND { VARDECL(TRIAND); }
|
||||||
| yWIRE { VARDECL(WIRE); }
|
| yWIRE { VARDECL(WIRE); }
|
||||||
| yWOR { VARDECL(WIRE); BBUNSUP($1, "Unsupported: wor"); }
|
| yWOR { VARDECL(TRIOR); }
|
||||||
// // VAMS - somewhat hackish
|
// // VAMS - somewhat hackish
|
||||||
| yWREAL { VARDECL(WREAL); }
|
| yWREAL { VARDECL(WREAL); }
|
||||||
;
|
;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
%Error-UNSUPPORTED: t/t_wire_triand.v:11:4: Unsupported: triand
|
|
||||||
11 | triand ta;
|
|
||||||
| ^~~~~~
|
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
|
||||||
%Error-UNSUPPORTED: t/t_wire_triand.v:12:4: Unsupported: trior
|
|
||||||
12 | trior to;
|
|
||||||
| ^~~~~
|
|
||||||
%Error: Exiting due to
|
|
@ -1,14 +0,0 @@
|
|||||||
// DESCRIPTION: Verilator: Verilog Test module for SystemVerilog 'alias'
|
|
||||||
//
|
|
||||||
// Simple bi-directional alias test.
|
|
||||||
//
|
|
||||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
|
||||||
// any use, without warranty, 2024 by Wilson Snyder.
|
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
|
||||||
|
|
||||||
triand ta;
|
|
||||||
trior to;
|
|
||||||
|
|
||||||
endmodule
|
|
@ -9,8 +9,10 @@
|
|||||||
|
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('linter')
|
test.scenarios('simulator')
|
||||||
|
|
||||||
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
71
test_regress/t/t_wired_net_test.v
Executable file
71
test_regress/t/t_wired_net_test.v
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2022 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`define stop $stop
|
||||||
|
`define checkb(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='b%x exp='b%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||||
|
|
||||||
|
module t(
|
||||||
|
clk
|
||||||
|
/*AUTOARG*/);
|
||||||
|
input clk;
|
||||||
|
wor [3:0] ptrior1;
|
||||||
|
trior [3:0] ptrior2;
|
||||||
|
wand [3:0] ptriand1;
|
||||||
|
triand [3:0] ptriand2;
|
||||||
|
wire [3:0] z1;
|
||||||
|
wire [3:0] z2;
|
||||||
|
wire [3:0] tri_z1;
|
||||||
|
wire [3:0] tri_z2;
|
||||||
|
logic [3:0] x;
|
||||||
|
logic [3:0] y;
|
||||||
|
logic [3:0] tri_x;
|
||||||
|
logic [3:0] tri_y;
|
||||||
|
logic [3:0] tri_x_dat;
|
||||||
|
logic [3:0] tri_y_dat;
|
||||||
|
logic [3:0] tri_x_en;
|
||||||
|
logic [3:0] tri_y_en;
|
||||||
|
assign ptrior1 = x & y;
|
||||||
|
assign ptrior1 = x + y;
|
||||||
|
assign ptrior2 = tri_x & tri_y;
|
||||||
|
assign ptrior2 = tri_x + tri_y;
|
||||||
|
assign ptriand1 = x & y;
|
||||||
|
assign ptriand1 = x + y;
|
||||||
|
assign ptriand2 = tri_x & tri_y;
|
||||||
|
assign ptriand2 = tri_x + tri_y;
|
||||||
|
assign z1 = (x & y) | (x + y);
|
||||||
|
assign z2 = (x & y) & (x + y);
|
||||||
|
assign tri_z1 = (tri_x & tri_y) | (tri_x + tri_y);
|
||||||
|
assign tri_z2 = (tri_x & tri_y) & (tri_x + tri_y);
|
||||||
|
integer cyc = 0;
|
||||||
|
integer xz_index = 0;
|
||||||
|
integer xz_num = 0;
|
||||||
|
integer i;
|
||||||
|
assign tri_x[0] = tri_x_en[0] ? tri_x_dat[0] : 1'bz;
|
||||||
|
assign tri_x[1] = tri_x_en[1] ? tri_x_dat[1] : 1'bz;
|
||||||
|
assign tri_x[2] = tri_x_en[2] ? tri_x_dat[2] : 1'bz;
|
||||||
|
assign tri_x[3] = tri_x_en[3] ? tri_x_dat[3] : 1'bz;
|
||||||
|
assign tri_y[0] = tri_y_en[0] ? tri_y_dat[0] : 1'bz;
|
||||||
|
assign tri_y[1] = tri_y_en[1] ? tri_y_dat[1] : 1'bz;
|
||||||
|
assign tri_y[2] = tri_y_en[2] ? tri_y_dat[2] : 1'bz;
|
||||||
|
assign tri_y[3] = tri_y_en[3] ? tri_y_dat[3] : 1'bz;
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
x = {$random}[3:0];
|
||||||
|
y = {$random}[3:0];
|
||||||
|
tri_x_dat = {$random}[3:0];
|
||||||
|
tri_y_dat = {$random}[3:0];
|
||||||
|
tri_x_en = {$random}[3:0];
|
||||||
|
tri_y_en = {$random}[3:0];
|
||||||
|
`checkb(ptrior1, z1);
|
||||||
|
`checkb(ptrior2, tri_z1);
|
||||||
|
`checkb(ptriand1, z2);
|
||||||
|
`checkb(ptriand2, tri_z2);
|
||||||
|
if (cyc == 20) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
Loading…
Reference in New Issue
Block a user