Support for wired nets, wor/trior/wand/triand. (#5496)

This commit is contained in:
Zhou Shen 2024-10-10 05:53:46 +08:00 committed by GitHub
parent 041f6603c3
commit 1710b6bab4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 142 additions and 33 deletions

View File

@ -899,6 +899,8 @@ public:
SUPPLY1,
WIRE,
WREAL,
TRIAND,
TRIOR,
TRIWIRE,
TRI0,
TRI1,
@ -919,20 +921,24 @@ public:
constexpr operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[]
= {"?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1",
"WIRE", "WREAL", "TRIWIRE", "TRI0", "TRI1", "PORT", "BLOCKTEMP",
"MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
= {"?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1",
"WIRE", "WREAL", "TRIAND", "TRIOR", "TRIWIRE", "TRI0", "TRI1",
"PORT", "BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
return names[m_e];
}
bool isParam() const { return m_e == GPARAM || m_e == LPARAM; }
bool isSignal() const {
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 {
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
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
@ -963,6 +969,8 @@ public:
/* SUPPLY1: */ "SUPPLY1",
/* WIRE: */ "WIRE",
/* WREAL: */ "WIRE",
/* TRIAND: */ "TRIAND",
/* TRIOR: */ "TRIOR",
/* TRIWIRE: */ "TRI",
/* TRI0: */ "TRI0",
/* TRI1: */ "TRI1",

View File

@ -2073,6 +2073,9 @@ public:
bool isInternal() const { return m_isInternal; }
bool isSignal() const { return varType().isSignal(); }
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 isToggleCoverable() const {
return ((isIO() || isSignal())

View File

@ -914,6 +914,51 @@ class TristateVisitor final : public TristateBaseVisitor {
|| (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,
uint8_t greatestKnownStrength) {
// 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);
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
removeAssignmentsNotStrongerThanUniformConstant();
// Use graph to find tristate signals

View File

@ -1994,12 +1994,12 @@ net_type: // ==IEEE: net_type
| yTRI { VARDECL(TRIWIRE); }
| yTRI0 { VARDECL(TRI0); }
| yTRI1 { VARDECL(TRI1); }
| yTRIAND { VARDECL(WIRE); BBUNSUP($1, "Unsupported: triand"); }
| yTRIOR { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trior"); }
| yTRIAND { VARDECL(TRIAND); }
| yTRIOR { VARDECL(TRIOR); }
| yTRIREG { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trireg"); }
| yWAND { VARDECL(WIRE); BBUNSUP($1, "Unsupported: wand"); }
| yWAND { VARDECL(TRIAND); }
| yWIRE { VARDECL(WIRE); }
| yWOR { VARDECL(WIRE); BBUNSUP($1, "Unsupported: wor"); }
| yWOR { VARDECL(TRIOR); }
// // VAMS - somewhat hackish
| yWREAL { VARDECL(WREAL); }
;

View File

@ -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

View File

@ -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

View File

@ -9,8 +9,10 @@
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()

View 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