Skip to content

Commit

Permalink
Support assignments of packed values to stream expressions on queues (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
RRozak authored Aug 25, 2023
1 parent e8e7912 commit 2daa32b
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 58 deletions.
8 changes: 8 additions & 0 deletions include/verilated_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,14 @@ static inline WDataOutP VL_STREAML_WWI(int lbits, WDataOutP owp, WDataInP const
return owp;
}

template <typename T>
static inline void VL_ASSIGN_DYN_Q(VlQueue<T>& q, int elem_size, int lbits, QData from) {
const int size = (lbits + elem_size - 1) / elem_size;
q.renew(size);
const QData mask = VL_MASK_Q(elem_size);
for (int i = 0; i < size; ++i) q.at(i) = (T)((from >> (i * elem_size)) & mask);
}

// Because concats are common and wide, it's valuable to always have a clean output.
// Thus we specify inputs must be clean, so we don't need to clean the output.
// Note the bit shifts are always constants, so the adds in these constify out.
Expand Down
14 changes: 14 additions & 0 deletions src/V3AstNodeExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,20 @@ class AstConst final : public AstNodeExpr {
// May return nullptr on parse failure.
static AstConst* parseParamLiteral(FileLine* fl, const string& literal);
};
class AstCvtPackedToDynArray final : public AstNodeExpr {
// Cast from packed array to dynamic queue data type
// @astgen op1 := fromp : AstNodeExpr
public:
AstCvtPackedToDynArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtPackedToDynArray(fl) {
this->fromp(fromp);
dtypeFrom(dtp);
}
ASTGEN_MEMBERS_AstCvtPackedToDynArray;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
};
class AstDot final : public AstNodeExpr {
// A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
// These are eliminated in the link stage
Expand Down
30 changes: 15 additions & 15 deletions src/V3Const.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2158,12 +2158,11 @@ class ConstVisitor final : public VNVisitor {
return true;
} else if (m_doV && VN_IS(nodep->lhsp(), StreamL)) {
// Push the stream operator to the rhs of the assignment statement
const int dWidth = VN_AS(nodep->lhsp(), StreamL)->lhsp()->width();
const int sWidth = nodep->rhsp()->width();
// Unlink the stuff
AstNodeExpr* const dstp = VN_AS(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack();
AstNodeExpr* streamp = VN_AS(nodep->lhsp(), StreamL)->unlinkFrBack();
AstNodeExpr* streamp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
const int sWidth = srcp->width();
const int dWidth = dstp->width();
// Connect the rhs to the stream operator and update its width
VN_AS(streamp, StreamL)->lhsp(srcp);
if (VN_IS(srcp->dtypep(), DynArrayDType) || VN_IS(srcp->dtypep(), QueueDType)
Expand All @@ -2172,26 +2171,27 @@ class ConstVisitor final : public VNVisitor {
} else {
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
}
// Shrink the RHS if necessary
if (sWidth > dWidth) {
if (dWidth == 0) {
streamp = new AstCvtPackedToDynArray{nodep->fileline(), streamp, dstp->dtypep()};
} else if (sWidth > dWidth) {
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};
}
// Link the nodes back in
nodep->lhsp(dstp);
nodep->rhsp(streamp);
return true;
} else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) {
// The right stream operator on lhs of assignment statement does
// not reorder bits. However, if the rhs is wider than the lhs,
// then we select bits from the left-most, not the right-most.
const int dWidth = VN_AS(nodep->lhsp(), StreamR)->lhsp()->width();
const int sWidth = nodep->rhsp()->width();
// Unlink the stuff
AstNodeExpr* const dstp = VN_AS(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack();
AstNode* const sizep = VN_AS(nodep->lhsp(), StreamR)->rhsp()->unlinkFrBack();
AstNodeExpr* const streamp = VN_AS(nodep->lhsp(), StreamR)->unlinkFrBack();
AstNodeExpr* const streamp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const dstp = VN_AS(streamp, StreamR)->lhsp()->unlinkFrBack();
AstNode* const sizep = VN_AS(streamp, StreamR)->rhsp()->unlinkFrBack();
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
if (sWidth > dWidth) {
const int sWidth = srcp->width();
const int dWidth = dstp->width();
if (dWidth == 0) {
srcp = new AstCvtPackedToDynArray{nodep->fileline(), srcp, dstp->dtypep()};
} else if (sWidth > dWidth) {
srcp = new AstSel{streamp->fileline(), srcp, sWidth - dWidth, dWidth};
}
nodep->lhsp(dstp);
Expand Down
13 changes: 13 additions & 0 deletions src/V3EmitCFunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,19 @@ class EmitCFunc VL_NOT_FINAL : public EmitCConstInit {
puts(cvtToStr(nodep->widthMin()) + ",");
iterateAndNextConstNull(nodep->lhsp());
puts(", ");
} else if (const AstCvtPackedToDynArray* const castp
= VN_CAST(nodep->rhsp(), CvtPackedToDynArray)) {
puts("VL_ASSIGN_DYN_Q<");
putbs(castp->dtypep()->subDTypep()->cType("", false, false));
puts(">(");
iterateAndNextConstNull(nodep->lhsp());
puts(", ");
puts(cvtToStr(castp->dtypep()->subDTypep()->widthMin()));
puts(", ");
puts(cvtToStr(castp->fromp()->widthMin()));
puts(", ");
rhs = false;
iterateAndNextConstNull(castp->fromp());
} else if (nodep->isWide() && VN_IS(nodep->lhsp(), VarRef) //
&& !VN_IS(nodep->rhsp(), CExpr) //
&& !VN_IS(nodep->rhsp(), CMethodHard) //
Expand Down
10 changes: 7 additions & 3 deletions src/V3Width.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,9 +840,13 @@ class WidthVisitor final : public VNVisitor {
} else {
nodep->v3error("Slice size isn't a constant or basic data type.");
}
if (VN_IS(nodep->lhsp()->dtypep(), DynArrayDType)
|| VN_IS(nodep->lhsp()->dtypep(), QueueDType)
|| VN_IS(nodep->lhsp()->dtypep(), UnpackArrayDType)) {
const AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep();
if (VN_IS(lhsDtypep, DynArrayDType) || VN_IS(lhsDtypep, QueueDType)) {
nodep->dtypeSetStream();
} else if (VN_IS(lhsDtypep, UnpackArrayDType) || lhsDtypep->isCompound()) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Stream operation on a variable of a type "
<< lhsDtypep->prettyDTypeNameQ());
nodep->dtypeSetStream();
} else {
nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), nodep->lhsp()->widthMin(),
Expand Down
5 changes: 5 additions & 0 deletions test_regress/t/t_stream_bad.out
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^~
%Error-UNSUPPORTED: t/t_stream_bad.v:12:30: Unsupported: Stream operation on a variable of a type 'byte$[0:3]'
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to
21 changes: 21 additions & 0 deletions test_regress/t/t_stream_dynamic.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 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(simulator => 1);

compile(
);

execute(
check_finished => 1,
);

ok(1);
1;
40 changes: 40 additions & 0 deletions test_regress/t/t_stream_dynamic.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0

`define stop $stop
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);

module t (/*AUTOARG*/);
initial begin
bit arr[];
bit [1:0] arr2[$];
bit [4:0] arr5[];
bit [5:0] arr6[$];
string v;
bit [5:0] bit6 = 6'b111000;

{ >> bit {arr}} = bit6;
v = $sformatf("%p", arr); `checks(v, "'{'h0, 'h0, 'h0, 'h1, 'h1, 'h1} ");

{ << bit {arr}} = bit6;
v = $sformatf("%p", arr); `checks(v, "'{'h1, 'h1, 'h1, 'h0, 'h0, 'h0} ");

{ >> bit[1:0] {arr2}} = bit6;
v = $sformatf("%p", arr2); `checks(v, "'{'h0, 'h2, 'h3} ");

{ << bit[1:0] {arr2}} = bit6;
v = $sformatf("%p", arr2); `checks(v, "'{'h3, 'h2, 'h0} ");

{ >> bit [5:0] {arr6} } = bit6;
v = $sformatf("%p", arr6); `checks(v, "'{'h38} ");

{ << bit [5:0] {arr6} } = bit6;
v = $sformatf("%p", arr6); `checks(v, "'{'h38} ");

$write("*-* All Finished *-*\n");
$finish;
end
endmodule
40 changes: 0 additions & 40 deletions test_regress/t/t_stream_integer_type.out

This file was deleted.

Loading

0 comments on commit 2daa32b

Please sign in to comment.