Fixes #7663.
This commit is contained in:
parent
f316ec0d66
commit
38895f8f29
|
|
@ -110,6 +110,8 @@ Ilya Barkov
|
|||
Iru Cai
|
||||
Ivan Vnučec
|
||||
Iztok Jeras
|
||||
JAEUK LEE
|
||||
Jaeuk Lee (이재욱)
|
||||
Jake Merdich
|
||||
Jakub Michalski
|
||||
Jakub Wasilewski
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ module t;
|
|||
//this will not compile without -fno-life
|
||||
initial begin
|
||||
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
|
||||
got_pkt = {>>{byte_pkt}};
|
||||
if (8'hd == got_pkt) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish();
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue