Fix $display accepting streaming concat arguments (#7663) (#7890)

Fixes #7663.
This commit is contained in:
Jaeuk Lee 2026-07-09 21:41:40 +09:00 committed by GitHub
parent f316ec0d66
commit 38895f8f29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 221 additions and 72 deletions

View File

@ -110,6 +110,8 @@ Ilya Barkov
Iru Cai
Ivan Vnučec
Iztok Jeras
JAEUK LEE
Jaeuk Lee (이재욱)
Jake Merdich
Jakub Michalski
Jakub Wasilewski

View File

@ -109,6 +109,12 @@ std::ostream& operator<<(std::ostream& str, const Determ& rhs) {
return str << s_det[rhs];
}
enum StreamUse : uint8_t {
STREAM_USE_NONE, // Stream concatenation is not allowed in this context
STREAM_USE_ASSIGN, // Assignment-like context permits stream concatenation
STREAM_USE_CAST, // Explicit cast context permits stream concatenation
};
#define v3widthWarn(lhs, rhs, msg) \
v3warnCode(((lhs) < (rhs) ? V3ErrorCode::WIDTHTRUNC \
: (lhs) > (rhs) ? V3ErrorCode::WIDTHEXPAND \
@ -122,21 +128,26 @@ class WidthVP final {
// Parameters to pass down hierarchy with visit functions.
AstNodeDType* const m_dtypep; // Parent's data type to resolve to
const Stage m_stage; // If true, report errors
const StreamUse m_streamUse; // Current expression may be a stream concat
public:
WidthVP(AstNodeDType* dtypep, Stage stage)
WidthVP(AstNodeDType* dtypep, Stage stage, StreamUse streamUse = STREAM_USE_NONE)
: m_dtypep{dtypep}
, m_stage{stage} {
, m_stage{stage}
, m_streamUse{streamUse} {
// Prelim doesn't look at assignments, so shouldn't need a dtype,
// however AstPattern uses them
}
WidthVP(Determ determ, Stage stage)
WidthVP(Determ determ, Stage stage, StreamUse streamUse = STREAM_USE_NONE)
: m_dtypep{nullptr}
, m_stage{stage} {
, m_stage{stage}
, m_streamUse{streamUse} {
if (determ != SELF && stage != PRELIM)
v3fatalSrc("Context-determined width request only allowed as prelim step");
}
WidthVP* p() { return this; }
bool selfDtm() const { return m_dtypep == nullptr; }
StreamUse streamUse() const { return m_streamUse; }
AstNodeDType* dtypep() const {
// Detect where overrideDType is probably the intended call
UASSERT(m_dtypep, "Width dtype request on self-determined or preliminary VUP");
@ -255,6 +266,12 @@ class WidthVisitor final : public VNVisitor {
EXTEND_OFF // No extension
};
static StreamUse streamUseForDeterm(Determ determ) {
return determ == ASSIGN ? STREAM_USE_ASSIGN : STREAM_USE_NONE;
}
StreamUse currentStreamUse() const { return m_vup ? m_vup->streamUse() : STREAM_USE_NONE; }
static void packIfUnpacked(AstNodeExpr* const nodep) {
if (AstUnpackArrayDType* const unpackDTypep = VN_CAST(nodep->dtypep(), UnpackArrayDType)) {
const int elementsNum = unpackDTypep->arrayUnpackedElements();
@ -969,6 +986,15 @@ class WidthVisitor final : public VNVisitor {
nodep->dtypeSetInteger();
}
}
bool streamImplicitUseAllowed(const AstNodeStream* nodep) const {
if (m_streamConcat) return true;
if (m_vup && m_vup->streamUse() != STREAM_USE_NONE) return true;
const AstNode* const backp = nodep->backp();
if (!backp) return true; // Error elsewhere
return VN_IS(backp, NodeAssign);
}
void visit(AstNodeStream* nodep) override {
VL_RESTORER(m_streamConcat);
// UINFOTREE(1, nodep, "stream-in vup" << m_vup, "stream-in ");
@ -1002,6 +1028,12 @@ class WidthVisitor final : public VNVisitor {
}
}
if (m_vup->final()) {
if (!streamImplicitUseAllowed(nodep)) {
nodep->v3error(
"Streaming concatenation cannot be used in an implicitly cast context "
"(IEEE 1800-2023 11.4.17)\n"
<< nodep->warnMore() << "... Suggest use a cast");
}
if (!nodep->dtypep()->widthSized()) {
// See also error in V3Number
nodeForUnsizedWarning(nodep)->v3warn(
@ -2071,25 +2103,25 @@ class WidthVisitor final : public VNVisitor {
void visit(AstCvtPackString* nodep) override {
if (nodep->didWidthAndSet()) return;
// Opaque returns, so arbitrary
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, BOTH}.p());
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, BOTH, currentStreamUse()}.p());
// Type set in constructor
}
void visit(AstCvtPackedToArray* nodep) override {
if (nodep->didWidthAndSet()) return;
// Opaque returns, so arbitrary
userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH}.p());
userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH, currentStreamUse()}.p());
// Type set in constructor
}
void visit(AstCvtArrayToArray* nodep) override {
if (nodep->didWidthAndSet()) return;
// Opaque returns, so arbitrary
userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH}.p());
userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH, currentStreamUse()}.p());
// Type set in constructor
}
void visit(AstCvtArrayToPacked* nodep) override {
if (nodep->didWidthAndSet()) return;
// Opaque returns, so arbitrary
userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH}.p());
userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH, currentStreamUse()}.p());
// Type set in constructor
}
void visit(AstCvtUnpackedToQueue* nodep) override {
@ -2712,7 +2744,7 @@ class WidthVisitor final : public VNVisitor {
VL_DO_DANGLING(fromp->deleteTree(), fromp);
}
}
userIterateAndNext(nodep->fromp(), WidthVP{SELF, PRELIM}.p());
userIterateAndNext(nodep->fromp(), WidthVP{SELF, PRELIM, STREAM_USE_CAST}.p());
UINFOTREE(9, nodep, "", "CastDit");
AstNodeDType* const toDtp = nodep->dtypep()->skipRefToEnump();
AstNodeDType* const fromDtp = nodep->fromp()->dtypep()->skipRefToEnump();
@ -2815,7 +2847,7 @@ class WidthVisitor final : public VNVisitor {
if (m_vup->final()) {
UINFOTREE(9, nodep, "", "CastFPit");
iterateCheck(nodep, "value", nodep->fromp(), SELF, FINAL, nodep->fromp()->dtypep(),
EXTEND_EXP, false);
EXTEND_EXP, false, STREAM_USE_CAST);
UINFOTREE(9, nodep, "", "CastFin");
AstNodeExpr* const underp = nodep->fromp()->unlinkFrBack();
underp->dtypeFrom(nodep);
@ -2838,7 +2870,7 @@ class WidthVisitor final : public VNVisitor {
nodep->v3error("Size-changing cast to zero or negative size: " << width);
width = 1;
}
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM, STREAM_USE_CAST}.p());
castSized(nodep, nodep->lhsp(), width); // lhsp may change
}
if (m_vup->final()) {
@ -2851,7 +2883,7 @@ class WidthVisitor final : public VNVisitor {
}
void visit(AstCastWrap* nodep) override {
// Inserted by V3Width only so we know has been resolved
userIterateAndNext(nodep->lhsp(), WidthVP{nodep->dtypep(), BOTH}.p());
userIterateAndNext(nodep->lhsp(), WidthVP{nodep->dtypep(), BOTH, STREAM_USE_CAST}.p());
}
void castSized(AstNode* nodep, AstNode* underp, int width) {
const AstBasicDType* underDtp = VN_CAST(underp->dtypep(), BasicDType);
@ -2872,7 +2904,7 @@ class WidthVisitor final : public VNVisitor {
nodep->dtypep(calcDtp);
// We ignore warnings as that is sort of the point of a cast
iterateCheck(nodep, "Cast expr", underp, CONTEXT_DET, FINAL, calcDtp, EXTEND_EXP,
false);
false, STREAM_USE_CAST);
VL_DANGLING(underp);
underp = nodep->op1p(); // Above asserts that op1 was underp pre-relink
}
@ -7534,7 +7566,7 @@ class WidthVisitor final : public VNVisitor {
// Output args: at return caller = callee, reverse direction.
checkClassAssign(nodep, "Function Argument", pinp, portDTypep,
portp->direction() == VDirection::OUTPUT);
userIterate(pinp, WidthVP{portDTypep, FINAL}.p());
userIterate(pinp, WidthVP{portDTypep, FINAL, STREAM_USE_ASSIGN}.p());
} else {
iterateCheckAssign(nodep, "Function Argument", pinp, FINAL, portDTypep);
}
@ -9203,7 +9235,7 @@ class WidthVisitor final : public VNVisitor {
AstNode* iterateCheck(AstNode* parentp, const char* side, AstNode* underp, Determ determ,
Stage stage, AstNodeDType* expDTypep, ExtendRule extendRule,
bool warnOn = true) {
bool warnOn = true, StreamUse streamUse = STREAM_USE_NONE) {
// Perform data type check on underp, which is underneath parentp used for error reporting
// Returns the new underp
// Conversion to/from doubles and integers are before iterating.
@ -9211,30 +9243,37 @@ class WidthVisitor final : public VNVisitor {
UASSERT_OBJ(underp, parentp, "Node has no child");
UASSERT_OBJ(underp->dtypep(), underp,
"Node has no type"); // Perhaps forgot to do a prelim visit on it?
const StreamUse childStreamUse
= streamUse != STREAM_USE_NONE ? streamUse : streamUseForDeterm(determ);
if (VN_IS(underp, NodeDType)) { // Note the node itself, not node's data type
// Must be near top of these checks as underp->dtypep() will look normal
underp->v3error(ucfirst(parentp->prettyOperatorName())
<< " expected non-datatype " << side << " but "
<< underp->prettyNameQ() << " is a datatype.");
} else if (expDTypep == underp->dtypep()) { // Perfect
underp = userIterateSubtreeReturnEdits(underp, WidthVP{expDTypep, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{expDTypep, FINAL, childStreamUse}.p());
} else if (expDTypep->isDouble() && underp->isDouble()) { // Also good
underp = userIterateSubtreeReturnEdits(underp, WidthVP{expDTypep, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{expDTypep, FINAL, childStreamUse}.p());
} else if (expDTypep->isDouble() && !underp->isDouble()) {
AstNode* const oldp
= underp; // Need FINAL on children; otherwise splice would block it
spliceCvtD(VN_AS(underp, NodeExpr));
underp = userIterateSubtreeReturnEdits(oldp, WidthVP{SELF, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
oldp, WidthVP{SELF, FINAL, childStreamUse}.p());
} else if (!expDTypep->isDouble() && underp->isDouble()) {
AstNode* const oldp
= underp; // Need FINAL on children; otherwise splice would block it
spliceCvtS(VN_AS(underp, NodeExpr), true, expDTypep->width()); // Round RHS
underp = userIterateSubtreeReturnEdits(oldp, WidthVP{SELF, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
oldp, WidthVP{SELF, FINAL, childStreamUse}.p());
} else if (expDTypep->isString() && !underp->dtypep()->isString()) {
AstNode* const oldp
= underp; // Need FINAL on children; otherwise splice would block it
spliceCvtString(VN_AS(underp, NodeExpr));
underp = userIterateSubtreeReturnEdits(oldp, WidthVP{SELF, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
oldp, WidthVP{SELF, FINAL, childStreamUse}.p());
} else {
const AstBasicDType* const expBasicp = expDTypep->basicp();
const AstBasicDType* const underBasicp = underp->dtypep()->basicp();
@ -9262,7 +9301,8 @@ class WidthVisitor final : public VNVisitor {
// is e.g. an ADD, the ADD will auto-adjust to the proper data type
// or if another operation e.g. ATOI will not.
if (determ == SELF) {
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{SELF, FINAL, childStreamUse}.p());
} else if (determ == ASSIGN) {
// IEEE: Signedness is solely determined by the RHS
// (underp), not by the LHS (expDTypep)
@ -9274,9 +9314,11 @@ class WidthVisitor final : public VNVisitor {
VSigning::fromBool(underp->isSigned()));
UINFO(9, "Assignment of opposite-signed RHS to LHS: " << parentp);
}
underp = userIterateSubtreeReturnEdits(underp, WidthVP{subDTypep, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{subDTypep, FINAL, childStreamUse}.p());
} else {
underp = userIterateSubtreeReturnEdits(underp, WidthVP{subDTypep, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{subDTypep, FINAL, childStreamUse}.p());
}
// Note the check uses the expected size, not the child's subDTypep as we want the
// child node's width to end up correct for the assignment (etc)
@ -9315,11 +9357,13 @@ class WidthVisitor final : public VNVisitor {
<< " interface modport on " << side << " but got "
<< underIfaceRefp->modportp()->prettyNameQ() << " modport.");
} else {
underp = userIterateSubtreeReturnEdits(underp, WidthVP{expDTypep, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{expDTypep, FINAL, childStreamUse}.p());
}
} else {
// Hope it just works out (perhaps a cast will deal with it)
underp = userIterateSubtreeReturnEdits(underp, WidthVP{expDTypep, FINAL}.p());
underp = userIterateSubtreeReturnEdits(
underp, WidthVP{expDTypep, FINAL, childStreamUse}.p());
}
}
return underp;

View File

@ -0,0 +1,47 @@
%Error: t/t_display_stream_bad.v:19:15: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
19 | result = {<<{value}} + 1;
| ^~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_display_stream_bad.v:20:23: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
20 | result = value + {<<{value}};
| ^~
%Error: t/t_display_stream_bad.v:21:26: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
21 | result = value[0] ? {<<{value}} : other;
| ^~
%Error: t/t_display_stream_bad.v:22:16: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
22 | result = {{<<{value}}};
| ^~
%Error: t/t_display_stream_bad.v:23:14: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
23 | flag = ({<<{value}} == other);
| ^~
%Error: t/t_display_stream_bad.v:24:15: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
24 | $display({<<{value}});
| ^~
%Error: t/t_display_stream_bad.v:25:22: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
25 | $display("%0d", {<<{value}});
| ^~
%Error: t/t_display_stream_bad.v:26:29: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
26 | void'($sformatf("%0d", {<<{value}}));
| ^~
%Error: t/t_display_stream_bad.v:27:27: Streaming concatenation cannot be used in an implicitly cast context (IEEE 1800-2023 11.4.17)
: ... note: In instance 't'
: ... Suggest use a cast
27 | result = passthrough({<<{value}} + 1);
| ^~
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('linter')
test.lint(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,31 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
module t;
int value = 1;
int other = 2;
int result;
bit flag;
function automatic int passthrough(input int arg);
return arg;
endfunction
initial begin
result = passthrough({<<{value}});
result = {<<{value}} + 1;
result = value + {<<{value}};
result = value[0] ? {<<{value}} : other;
result = {{<<{value}}};
flag = ({<<{value}} == other);
$display({<<{value}});
$display("%0d", {<<{value}});
void'($sformatf("%0d", {<<{value}}));
result = passthrough({<<{value}} + 1);
result = int'({<<{value}});
result = int'({<<{value}}) + 1;
end
endmodule

View File

@ -6,6 +6,13 @@
`define stop $stop
`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%h' exp='%h'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
`define checks_w(width,gotv,expv) do begin \
logic [(width)-1:0] got_check; \
logic [(width)-1:0] exp_check; \
got_check = (gotv); \
exp_check = (expv); \
`checks(got_check, exp_check) \
end while(0);
module t;
logic [7:0] i_char;
@ -69,8 +76,8 @@ module t;
byte_pkt = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = byte_pkt;
`checks({>>{byte_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({i_header,i_len,i_crc,i_data},{<<8{byte_pkt}});
`checks_w(128, {>>{byte_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{<<8{byte_pkt}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
// //----------- SData QUEUE --------
@ -95,7 +102,7 @@ module t;
sdata_pkt = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = sdata_pkt;
`checks({>>{sdata_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{sdata_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- IData QUEUE --------
@ -111,7 +118,7 @@ module t;
int_pkt = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = int_pkt;
`checks({>>{int_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{int_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- QData QUEUE --------
@ -130,7 +137,7 @@ module t;
qdata_pkt = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = qdata_pkt;
`checks({>>{qdata_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{qdata_pkt}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
// ----------- VLWide QUEUE --------
@ -143,7 +150,7 @@ module t;
/* verilator lint_off WIDTHEXPAND */
wide129 = {<<8{i_header,i_len,i_crc,i_data}};
`checks({>>{vlwide_pkt_129}},wide129);
`checks_w(129, {>>{vlwide_pkt_129}},wide129);
/* verilator lint_on WIDTHEXPAND */
//------------------------------- REVERSE ENDIAN ------------------------------
@ -167,8 +174,8 @@ module t;
byte_pkt_rev = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = byte_pkt_rev;
`checks({>>{byte_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({i_header,i_len,i_crc,i_data},{<<8{byte_pkt_rev}});
`checks_w(128, {>>{byte_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{<<8{byte_pkt_rev}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- SData QUEUE --------
@ -188,7 +195,7 @@ module t;
sdata_pkt_rev = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = sdata_pkt_rev;
`checks({>>{sdata_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{sdata_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- IData QUEUE --------
@ -204,7 +211,7 @@ module t;
int_pkt_rev = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = int_pkt_rev;
`checks({>>{int_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{int_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- QData QUEUE --------
@ -218,7 +225,7 @@ module t;
qdata_pkt_rev = {<<8{i_header,i_len,i_crc,i_data}};
{<<8{o_header,o_len,o_crc,o_data}} = qdata_pkt_rev;
`checks({>>{qdata_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{qdata_pkt_rev}},{<<8{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
// ----------- VLWide QUEUE --------
@ -227,7 +234,7 @@ module t;
/* verilator lint_off WIDTHEXPAND */
wide129 = {<<8{i_header,i_len,i_crc,i_data}};
/* verilator lint_on WIDTHEXPAND */
`checks({>>{vlwide_pkt_129_rev}},wide129);
`checks_w(129, {>>{vlwide_pkt_129_rev}},wide129);
// // -------------------- STREAMR ------------------------------------
// //----------- CData QUEUE --------
@ -237,21 +244,21 @@ module t;
byte_pkt = {>>{i_header,i_len}};
{>>{o_header,o_len}} = byte_pkt;
`checks({>>{i_header,i_len}},{>>{o_header,o_len}});
`checks_w(64, {>>{i_header,i_len}},{>>{o_header,o_len}});
`checks({i_header,i_len},{o_header,o_len});
byte_pkt = {>>{i_header,i_len,i_crc,i_data}};
{>>{o_header,o_len,o_crc,o_data}} = byte_pkt;
`checks({>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- IData QUEUE --------
int_pkt = {>>{i_header}};
o_header = {>>{int_pkt}};
`checks(o_header,i_header);
`checks(o_header,{>>{int_pkt}});
`checks({>>{o_header}},{>>{int_pkt}});
`checks_w(32, o_header,{>>{int_pkt}});
`checks_w(32, {>>{o_header}},{>>{int_pkt}});
//test with QData
int_pkt = {>>{i_header,i_len}};
@ -261,7 +268,7 @@ module t;
int_pkt = {>>{i_header,i_len,i_crc,i_data}};
{>>{o_header,o_len,o_crc,o_data}} = int_pkt;
`checks({>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//----------- QData QUEUE --------
@ -274,7 +281,7 @@ module t;
qdata_pkt = {>>{i_header,i_len,i_crc,i_data}};
{>>{o_header,o_len,o_crc,o_data}} = qdata_pkt;
`checks({>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
// ----------- VLWide QUEUE --------
@ -288,84 +295,84 @@ module t;
vlwide_pkt_129 = {>>{i_header,i_len,i_crc,i_data}};
{>>{o_header,o_len,o_crc,o_data}} = vlwide_pkt_129;
`checks({>>{vlwide_pkt_129}},{>>{1'b0,i_header,i_len,i_crc,i_data}});
`checks_w(129, {>>{vlwide_pkt_129}},{>>{1'b0,i_header,i_len,i_crc,i_data}});
`checks({o_header,o_len,o_crc,o_data} ,{i_header,i_len,i_crc,i_data});
//---------- into other queues ------
int_pkt = {>>{i_header,i_len,i_crc,i_data}};
byte_pkt = {>>{int_pkt}};
`checks({>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
byte_pkt = {>>{i_header,i_len,i_crc,i_data}};
int_pkt = {>>{byte_pkt}};
`checks({>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
byte_pkt = {>>{i_header,i_len,i_crc,i_data}};
int_pkt = {>>{byte_pkt}};
`checks({>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
sdata_pkt = {>>{i_header,i_len,i_crc,i_data}};
byte_pkt = {>>{sdata_pkt}};
`checks({>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
byte_pkt = {>>{i_header,i_len,i_crc,i_data}};
sdata_pkt = {>>{byte_pkt}};
`checks({>>{sdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{sdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
byte_pkt = {>>{i_header,i_len,i_crc,i_data}};
qdata_pkt = {>>{byte_pkt}};
`checks({>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
qdata_pkt = {>>{i_header,i_len,i_crc,i_data}};
byte_pkt = {>>{qdata_pkt}};
`checks({>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
qdata_pkt = {>>{i_header,i_len,i_crc,i_data}};
int_pkt = {>>{qdata_pkt}};
`checks({>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
int_pkt = {>>{i_header,i_len,i_crc,i_data}};
qdata_pkt = {>>{int_pkt}};
`checks({>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
byte_pkt = {>>{i_header,i_len,i_crc,i_data}};
vlwide_pkt_128 = {>>{byte_pkt}};
`checks({>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data}});
vlwide_pkt_128 = {>>{i_header,i_len,i_crc,i_data}};
byte_pkt = {>>{vlwide_pkt_128}};
`checks({i_header,i_len,i_crc,i_data},{>>{byte_pkt}});
`checks({>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{>>{byte_pkt}});
`checks_w(128, {>>{byte_pkt}},{>>{i_header,i_len,i_crc,i_data}});
int_pkt = {>>{i_header,i_len,i_crc,i_data}};
vlwide_pkt_128 = {>>{int_pkt}};
`checks({i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks({>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks_w(128, {>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data}});
vlwide_pkt_128 = {>>{i_header,i_len,i_crc,i_data}};
int_pkt = {>>{vlwide_pkt_128}};
`checks({i_header,i_len,i_crc,i_data},{>>{int_pkt}});
`checks({>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{>>{int_pkt}});
`checks_w(128, {>>{int_pkt}},{>>{i_header,i_len,i_crc,i_data}});
qdata_pkt = {>>{i_header,i_len,i_crc,i_data}};
vlwide_pkt_128 = {>>{qdata_pkt}};
`checks({i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks({>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks_w(128, {>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data}});
qdata_pkt = {>>{i_header,i_len,i_crc,i_data,i_header,i_len,i_crc,i_data}};
vlwide_pkt_128 = {>>{qdata_pkt}};
`checks({i_header,i_len,i_crc,i_data,i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks({>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data,i_header,i_len,i_crc,i_data}});
`checks_w(256, {i_header,i_len,i_crc,i_data,i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks_w(256, {>>{vlwide_pkt_128}},{>>{i_header,i_len,i_crc,i_data,i_header,i_len,i_crc,i_data}});
qdata_pkt = {>>{i_header,i_len,i_crc,i_data,i_header,i_len,i_crc}};
vlwide_pkt_128 = {>>{qdata_pkt}};
`checks({32'h0,i_header,i_len,i_crc,i_data,i_header,i_len,i_crc},{>>{vlwide_pkt_128}});
`checks({>>{vlwide_pkt_128}},{>>{32'h0,i_header,i_len,i_crc,i_data,i_header,i_len,i_crc}});
`checks_w(256, {32'h0,i_header,i_len,i_crc,i_data,i_header,i_len,i_crc},{>>{vlwide_pkt_128}});
`checks_w(256, {>>{vlwide_pkt_128}},{>>{32'h0,i_header,i_len,i_crc,i_data,i_header,i_len,i_crc}});
vlwide_pkt_128 = {>>{i_header,i_len,i_crc,i_data}};
qdata_pkt = {>>{vlwide_pkt_128}};
`checks({i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks({>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
`checks_w(128, {i_header,i_len,i_crc,i_data},{>>{vlwide_pkt_128}});
`checks_w(128, {>>{qdata_pkt}},{>>{i_header,i_len,i_crc,i_data}});
$write("*-* All Finished *-*\n");
$finish;

View File

@ -21,15 +21,17 @@ module t;
pkt_if pkt_if_init (clk);
//this will not compile without -fno-life
initial begin
byte byte_pkt[$];
byte byte_pkt[$];
byte got_pkt;
//---------------------- STREAM WITH INTERFACE -------------------
//using this forces verilator to a AstSel Node into a Stream Node
#0 //make sure we dont optimize it all away in v3life
pkt_if_init.s.extra = 8'hd;
byte_pkt = {>>{pkt_if_init.s.extra}};
if(8'hd == {>>{byte_pkt}}) begin
$write("*-* All Finished *-*\n");
$finish();
got_pkt = {>>{byte_pkt}};
if (8'hd == got_pkt) begin
$write("*-* All Finished *-*\n");
$finish();
end
end