mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add SIDEEFFECT warning on mishandled side effect cases (#487 partial)
This commit is contained in:
parent
684aba0e90
commit
c14eae6d56
1
Changes
1
Changes
@ -13,6 +13,7 @@ Verilator 5.017 devel
|
|||||||
|
|
||||||
**Minor:**
|
**Minor:**
|
||||||
|
|
||||||
|
* Add SIDEEFFECT warning on mishandled side effect cases.
|
||||||
* Add trace() API even when Verilated without --trace (#4462). [phelter]
|
* Add trace() API even when Verilated without --trace (#4462). [phelter]
|
||||||
* Add warning on interface instantiation without parens (#4094). [Gökçe Aydos]
|
* Add warning on interface instantiation without parens (#4094). [Gökçe Aydos]
|
||||||
* Support randc (#4349).
|
* Support randc (#4349).
|
||||||
|
@ -1514,6 +1514,39 @@ List Of Warnings
|
|||||||
modeled values, or DPI calls.
|
modeled values, or DPI calls.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: SIDEEFFECT
|
||||||
|
|
||||||
|
Warns that an expression has a side effect that might not properly be
|
||||||
|
executed by Verilator.
|
||||||
|
|
||||||
|
This often represents a bug in Verilator, as opposed to a bad code
|
||||||
|
construct, however the Verilog code can typically be changed to avoid
|
||||||
|
the warning.
|
||||||
|
|
||||||
|
Faulty example:
|
||||||
|
|
||||||
|
.. code-block:: sv
|
||||||
|
:linenos:
|
||||||
|
:emphasize-lines: 1
|
||||||
|
|
||||||
|
x = y[a++];
|
||||||
|
|
||||||
|
This example warns because Verilator does not currently handle side
|
||||||
|
effects inside array subscripts; the a++ may be executed multiple times.
|
||||||
|
|
||||||
|
Rewrite the code to avoid expression side effects, typically by using a
|
||||||
|
temporary:
|
||||||
|
|
||||||
|
.. code-block:: sv
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
temp = a++;
|
||||||
|
x = y[temp];
|
||||||
|
|
||||||
|
Ignoring this warning may make Verilator simulations differ from other
|
||||||
|
simulators.
|
||||||
|
|
||||||
|
|
||||||
.. option:: SPLITVAR
|
.. option:: SPLITVAR
|
||||||
|
|
||||||
Warns that a variable with a :option:`/*verilator&32;split_var*/`
|
Warns that a variable with a :option:`/*verilator&32;split_var*/`
|
||||||
|
@ -801,26 +801,33 @@ void AstNode::swapWith(AstNode* bp) {
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Clone
|
// Clone
|
||||||
|
|
||||||
AstNode* AstNode::cloneTreeIter() {
|
AstNode* AstNode::cloneTreeIter(bool needPure) {
|
||||||
// private: Clone single node and children
|
// private: Clone single node and children
|
||||||
|
if (VL_UNLIKELY(needPure && !isPure())) {
|
||||||
|
this->v3warn(SIDEEFFECT,
|
||||||
|
"Expression side effect may be mishandled\n"
|
||||||
|
<< this->warnMore()
|
||||||
|
<< "... Suggest use a temporary variable in place of this expression");
|
||||||
|
// this->v3fatalSrc("cloneTreePure debug backtrace"); // Comment in to debug where caused it
|
||||||
|
}
|
||||||
AstNode* const newp = this->clone();
|
AstNode* const newp = this->clone();
|
||||||
if (this->m_op1p) newp->op1p(this->m_op1p->cloneTreeIterList());
|
if (this->m_op1p) newp->op1p(this->m_op1p->cloneTreeIterList(needPure));
|
||||||
if (this->m_op2p) newp->op2p(this->m_op2p->cloneTreeIterList());
|
if (this->m_op2p) newp->op2p(this->m_op2p->cloneTreeIterList(needPure));
|
||||||
if (this->m_op3p) newp->op3p(this->m_op3p->cloneTreeIterList());
|
if (this->m_op3p) newp->op3p(this->m_op3p->cloneTreeIterList(needPure));
|
||||||
if (this->m_op4p) newp->op4p(this->m_op4p->cloneTreeIterList());
|
if (this->m_op4p) newp->op4p(this->m_op4p->cloneTreeIterList(needPure));
|
||||||
newp->m_iterpp = nullptr;
|
newp->m_iterpp = nullptr;
|
||||||
newp->clonep(this); // Save pointers to/from both to simplify relinking.
|
newp->clonep(this); // Save pointers to/from both to simplify relinking.
|
||||||
this->clonep(newp); // Save pointers to/from both to simplify relinking.
|
this->clonep(newp); // Save pointers to/from both to simplify relinking.
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::cloneTreeIterList() {
|
AstNode* AstNode::cloneTreeIterList(bool needPure) {
|
||||||
// private: Clone list of nodes, set m_headtailp
|
// private: Clone list of nodes, set m_headtailp
|
||||||
AstNode* newheadp = nullptr;
|
AstNode* newheadp = nullptr;
|
||||||
AstNode* newtailp = nullptr;
|
AstNode* newtailp = nullptr;
|
||||||
// Audited to make sure this is never nullptr
|
// Audited to make sure this is never nullptr
|
||||||
for (AstNode* oldp = this; oldp; oldp = oldp->m_nextp) {
|
for (AstNode* oldp = this; oldp; oldp = oldp->m_nextp) {
|
||||||
AstNode* const newp = oldp->cloneTreeIter();
|
AstNode* const newp = oldp->cloneTreeIter(needPure);
|
||||||
newp->m_headtailp = nullptr;
|
newp->m_headtailp = nullptr;
|
||||||
newp->m_backp = newtailp;
|
newp->m_backp = newtailp;
|
||||||
if (newtailp) newtailp->m_nextp = newp;
|
if (newtailp) newtailp->m_nextp = newp;
|
||||||
@ -832,14 +839,14 @@ AstNode* AstNode::cloneTreeIterList() {
|
|||||||
return newheadp;
|
return newheadp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::cloneTree(bool cloneNextLink) {
|
AstNode* AstNode::cloneTree(bool cloneNextLink, bool needPure) {
|
||||||
debugTreeChange(this, "-cloneThs: ", __LINE__, cloneNextLink);
|
debugTreeChange(this, "-cloneThs: ", __LINE__, cloneNextLink);
|
||||||
cloneClearTree();
|
cloneClearTree();
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
if (cloneNextLink && this->m_nextp) {
|
if (cloneNextLink && this->m_nextp) {
|
||||||
newp = cloneTreeIterList();
|
newp = cloneTreeIterList(needPure);
|
||||||
} else {
|
} else {
|
||||||
newp = cloneTreeIter();
|
newp = cloneTreeIter(needPure);
|
||||||
newp->m_nextp = nullptr;
|
newp->m_nextp = nullptr;
|
||||||
newp->m_headtailp = newp;
|
newp->m_headtailp = newp;
|
||||||
}
|
}
|
||||||
|
@ -1713,8 +1713,8 @@ class AstNode VL_NOT_FINAL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AstNode* cloneTreeIter();
|
AstNode* cloneTreeIter(bool needPure);
|
||||||
AstNode* cloneTreeIterList();
|
AstNode* cloneTreeIterList(bool needPure);
|
||||||
void checkTreeIter(const AstNode* prevBackp) const VL_MT_STABLE;
|
void checkTreeIter(const AstNode* prevBackp) const VL_MT_STABLE;
|
||||||
bool gateTreeIter() const;
|
bool gateTreeIter() const;
|
||||||
static bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext,
|
static bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext,
|
||||||
@ -2074,8 +2074,8 @@ public:
|
|||||||
AstNode* belowp); // When calling, "this" is second argument
|
AstNode* belowp); // When calling, "this" is second argument
|
||||||
|
|
||||||
// METHODS - Iterate on a tree
|
// METHODS - Iterate on a tree
|
||||||
AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep //
|
AstNode* cloneTree(bool cloneNextLink, bool needPure = false); // Not const, as sets clonep() on original nodep
|
||||||
AstNode* cloneTreePure(bool cloneNextLink) { return cloneTree(cloneNextLink); }
|
AstNode* cloneTreePure(bool cloneNextLink) { return cloneTree(cloneNextLink, true); }
|
||||||
bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable?
|
bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable?
|
||||||
inline bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p?
|
inline bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p?
|
||||||
// Does tree of this == node2p?, not allowing non-isGateOptimizable
|
// Does tree of this == node2p?, not allowing non-isGateOptimizable
|
||||||
|
@ -136,6 +136,7 @@ public:
|
|||||||
RISEFALLDLY, // Unsupported: rise/fall/turn-off delays
|
RISEFALLDLY, // Unsupported: rise/fall/turn-off delays
|
||||||
SELRANGE, // Selection index out of range
|
SELRANGE, // Selection index out of range
|
||||||
SHORTREAL, // Shortreal not supported
|
SHORTREAL, // Shortreal not supported
|
||||||
|
SIDEEFFECT, // Sideeffect ignored
|
||||||
SPLITVAR, // Cannot split the variable
|
SPLITVAR, // Cannot split the variable
|
||||||
STATICVAR, // Static variable declared in a loop with a declaration assignment
|
STATICVAR, // Static variable declared in a loop with a declaration assignment
|
||||||
STMTDLY, // Delayed statement
|
STMTDLY, // Delayed statement
|
||||||
@ -203,7 +204,8 @@ public:
|
|||||||
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOLATCH", "NULLPORT", "PINCONNECTEMPTY",
|
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOLATCH", "NULLPORT", "PINCONNECTEMPTY",
|
||||||
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PROCASSWIRE",
|
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PROCASSWIRE",
|
||||||
"PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY",
|
"PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY",
|
||||||
"SELRANGE", "SHORTREAL", "SPLITVAR", "STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
"SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPLITVAR",
|
||||||
|
"STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||||
"TICKCOUNT", "TIMESCALEMOD",
|
"TICKCOUNT", "TIMESCALEMOD",
|
||||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
||||||
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDPARAM", "UNUSEDSIGNAL",
|
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDPARAM", "UNUSEDSIGNAL",
|
||||||
@ -231,7 +233,8 @@ public:
|
|||||||
}
|
}
|
||||||
// Warnings to mention manual
|
// Warnings to mention manual
|
||||||
bool mentionManual() const VL_MT_SAFE {
|
bool mentionManual() const VL_MT_SAFE {
|
||||||
return (m_e == EC_FATALSRC || m_e == SYMRSVDWORD || m_e == ZERODLY || pretendError());
|
return (m_e == EC_FATALSRC || m_e == SIDEEFFECT || m_e == SYMRSVDWORD || m_e == ZERODLY
|
||||||
|
|| pretendError());
|
||||||
}
|
}
|
||||||
// Warnings that are lint only
|
// Warnings that are lint only
|
||||||
bool lintError() const VL_MT_SAFE {
|
bool lintError() const VL_MT_SAFE {
|
||||||
|
@ -220,16 +220,6 @@ private:
|
|||||||
}
|
}
|
||||||
void prepost_stmt_visit(AstNodeTriop* nodep) {
|
void prepost_stmt_visit(AstNodeTriop* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
||||||
// Currently we can't reference the target, so we just copy the AST both for read and
|
|
||||||
// write, but doing so would double any side-effects, so as a safety measure all
|
|
||||||
// statements which could have side-effects are banned at the moment.
|
|
||||||
if (!nodep->rhsp()->isPure()) {
|
|
||||||
nodep->rhsp()->v3warn(E_UNSUPPORTED,
|
|
||||||
"Unsupported: Inc/Dec of expression with side-effects");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstConst* const constp = VN_AS(nodep->lhsp(), Const);
|
AstConst* const constp = VN_AS(nodep->lhsp(), Const);
|
||||||
UASSERT_OBJ(nodep, constp, "Expecting CONST");
|
UASSERT_OBJ(nodep, constp, "Expecting CONST");
|
||||||
AstConst* const newconstp = constp->cloneTree(true);
|
AstConst* const newconstp = constp->cloneTree(true);
|
||||||
@ -250,16 +240,6 @@ private:
|
|||||||
}
|
}
|
||||||
void prepost_expr_visit(AstNodeTriop* nodep) {
|
void prepost_expr_visit(AstNodeTriop* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
||||||
// Currently we can't reference the target, so we just copy the AST both for read and
|
|
||||||
// write, but doing so would double any side-effects, so as a safety measure all
|
|
||||||
// statements which could have side-effects are banned at the moment.
|
|
||||||
if (!nodep->rhsp()->isPure()) {
|
|
||||||
nodep->rhsp()->v3warn(E_UNSUPPORTED,
|
|
||||||
"Unsupported: Inc/Dec of expression with side-effects");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_unsupportedHere) {
|
if (m_unsupportedHere) {
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Incrementation in this context.");
|
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Incrementation in this context.");
|
||||||
return;
|
return;
|
||||||
|
@ -2557,12 +2557,14 @@ module lpm_clshift (
|
|||||||
// ALWAYS CONSTRUCT BLOCK
|
// ALWAYS CONSTRUCT BLOCK
|
||||||
always @(data or i_direction or distance)
|
always @(data or i_direction or distance)
|
||||||
begin
|
begin
|
||||||
|
// verilator lint_off SIDEEFFECT
|
||||||
if ((lpm_shifttype == "LOGICAL") || (lpm_shifttype == "UNUSED"))
|
if ((lpm_shifttype == "LOGICAL") || (lpm_shifttype == "UNUSED"))
|
||||||
{tmp_overflow, tmp_underflow, tmp_result} = LogicShift(data, distance, i_direction);
|
{tmp_overflow, tmp_underflow, tmp_result} = LogicShift(data, distance, i_direction);
|
||||||
else if (lpm_shifttype == "ARITHMETIC")
|
else if (lpm_shifttype == "ARITHMETIC")
|
||||||
{tmp_overflow, tmp_underflow, tmp_result} = ArithShift(data, distance, i_direction);
|
{tmp_overflow, tmp_underflow, tmp_result} = ArithShift(data, distance, i_direction);
|
||||||
else if (lpm_shifttype == "ROTATE")
|
else if (lpm_shifttype == "ROTATE")
|
||||||
{tmp_overflow, tmp_underflow, tmp_result} = RotateShift(data, distance, i_direction);
|
{tmp_overflow, tmp_underflow, tmp_result} = RotateShift(data, distance, i_direction);
|
||||||
|
// verilator lint_on SIDEEFFECT
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge i_clock or posedge i_aclr)
|
always @(posedge i_clock or posedge i_aclr)
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
%Error-UNSUPPORTED: t/t_expr_incr_unsup.v:17:34: Unsupported: Inc/Dec of expression with side-effects
|
%Warning-SIDEEFFECT: t/t_expr_incr_unsup.v:17:34: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
17 | $display("Value: %d", arr[postincrement_i()]++);
|
17 | $display("Value: %d", arr[postincrement_i()]++);
|
||||||
| ^
|
| ^
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
... For warning description see https://verilator.org/warn/SIDEEFFECT?v=latest
|
||||||
|
... Use "/* verilator lint_off SIDEEFFECT */" and lint_on around source to disable this message.
|
||||||
|
%Warning-SIDEEFFECT: t/t_expr_incr_unsup.v:17:35: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
17 | $display("Value: %d", arr[postincrement_i()]++);
|
||||||
|
| ^~~~~~~~~~~~~~~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
24
test_regress/t/t_lint_sideeffect_bad.out
Normal file
24
test_regress/t/t_lint_sideeffect_bad.out
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
%Warning-SIDEEFFECT: t/t_lint_sideeffect_bad.v:19:31: Expression side effect may be mishandled
|
||||||
|
: ... note: In instance 't'
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
19 | $display("0x%8x", array[$c(0) +: 32]);
|
||||||
|
| ^~
|
||||||
|
... For warning description see https://verilator.org/warn/SIDEEFFECT?v=latest
|
||||||
|
... Use "/* verilator lint_off SIDEEFFECT */" and lint_on around source to disable this message.
|
||||||
|
%Warning-SIDEEFFECT: t/t_lint_sideeffect_bad.v:12:13: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
12 | case ($c("1"))
|
||||||
|
| ^~
|
||||||
|
%Warning-SIDEEFFECT: t/t_lint_sideeffect_bad.v:13:10: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
13 | 1: $stop;
|
||||||
|
| ^
|
||||||
|
%Warning-SIDEEFFECT: t/t_lint_sideeffect_bad.v:14:10: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
14 | 2: $stop;
|
||||||
|
| ^
|
||||||
|
%Warning-SIDEEFFECT: t/t_lint_sideeffect_bad.v:15:10: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
15 | 3: $stop;
|
||||||
|
| ^
|
||||||
|
%Error: Exiting due to
|
19
test_regress/t/t_lint_sideeffect_bad.pl
Executable file
19
test_regress/t/t_lint_sideeffect_bad.pl
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2008 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(linter => 1);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
22
test_regress/t/t_lint_sideeffect_bad.v
Normal file
22
test_regress/t/t_lint_sideeffect_bad.v
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2023 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
logic [63:0] array = 64'hfeedf00d12345678;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
case ($c("1"))
|
||||||
|
1: $stop;
|
||||||
|
2: $stop;
|
||||||
|
3: $stop;
|
||||||
|
default: $stop;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
$display("0x%8x", array[$c(0) +: 32]);
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -1,5 +1,11 @@
|
|||||||
%Error-UNSUPPORTED: t/t_stmt_incr_unsup.v:17:12: Unsupported: Inc/Dec of expression with side-effects
|
%Warning-SIDEEFFECT: t/t_stmt_incr_unsup.v:17:12: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
17 | arr[postincrement_i()]++;
|
17 | arr[postincrement_i()]++;
|
||||||
| ^
|
| ^
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
... For warning description see https://verilator.org/warn/SIDEEFFECT?v=latest
|
||||||
|
... Use "/* verilator lint_off SIDEEFFECT */" and lint_on around source to disable this message.
|
||||||
|
%Warning-SIDEEFFECT: t/t_stmt_incr_unsup.v:17:13: Expression side effect may be mishandled
|
||||||
|
: ... Suggest use a temporary variable in place of this expression
|
||||||
|
17 | arr[postincrement_i()]++;
|
||||||
|
| ^~~~~~~~~~~~~~~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
@ -112,10 +112,12 @@ module ports
|
|||||||
// - Setup read multiplexer -
|
// - Setup read multiplexer -
|
||||||
for ( j = PORTID_A; j <= PORTID_D; j++ )
|
for ( j = PORTID_A; j <= PORTID_D; j++ )
|
||||||
begin
|
begin
|
||||||
|
// verilator lint_off SIDEEFFECT
|
||||||
if ( padsif.IsPort( j ) )
|
if ( padsif.IsPort( j ) )
|
||||||
data[j] = '{ port[j].dir, port[j].out, 8'h00, 8'h00 };
|
data[j] = '{ port[j].dir, port[j].out, 8'h00, 8'h00 };
|
||||||
else
|
else
|
||||||
data[j] = '{ 8'h00, 8'h00, 8'h00, 8'h00 };
|
data[j] = '{ 8'h00, 8'h00, 8'h00, 8'h00 };
|
||||||
|
// verilator lint_on SIDEEFFECT
|
||||||
end
|
end
|
||||||
|
|
||||||
// - Connect "genbusif" -
|
// - Connect "genbusif" -
|
||||||
|
Loading…
Reference in New Issue
Block a user