Support some stream operations on queues (#4292)

This commit is contained in:
Ryszard Rozak 2023-06-14 04:46:42 +02:00 committed by GitHub
parent 9dbc669199
commit b517fb5ee3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 128 additions and 156 deletions

View File

@ -1896,6 +1896,12 @@ std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_PURE {
return std::string{destout, len};
}
std::string VL_CVT_PACK_STR_ND(const VlQueue<std::string>& q) VL_PURE {
std::string output;
for (const std::string& s : q) output += s;
return output;
}
std::string VL_PUTC_N(const std::string& lhs, IData rhs, CData ths) VL_PURE {
std::string lstring = lhs;
const int32_t rhs_s = rhs; // To signed value

View File

@ -2196,6 +2196,7 @@ extern IData VL_DIST_UNIFORM(IData& seedr, IData ustart, IData uend) VL_MT_SAFE;
// Conversion functions
extern std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_PURE;
extern std::string VL_CVT_PACK_STR_ND(const VlQueue<std::string>& q) VL_PURE;
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
VlWide<VL_WQ_WORDS_E> lw;
VL_SET_WQ(lw, lhs);

View File

@ -1406,6 +1406,9 @@ AstNodeDType* AstNode::findQueueIndexDType() const {
AstNodeDType* AstNode::findVoidDType() const {
return v3Global.rootp()->typeTablep()->findVoidDType(fileline());
}
AstNodeDType* AstNode::findStreamDType() const {
return v3Global.rootp()->typeTablep()->findStreamDType(fileline());
}
//######################################################################
// VNDeleter

View File

@ -1867,6 +1867,7 @@ public:
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
void dtypeSetEmptyQueue() { dtypep(findEmptyQueueDType()); }
void dtypeSetVoid() { dtypep(findVoidDType()); }
void dtypeSetStream() { dtypep(findStreamDType()); }
// Data type locators
AstNodeDType* findBitDType() const { return findBasicDType(VBasicDTypeKwd::LOGIC); }
@ -1878,6 +1879,7 @@ public:
AstNodeDType* findCHandleDType() const { return findBasicDType(VBasicDTypeKwd::CHANDLE); }
AstNodeDType* findEmptyQueueDType() const;
AstNodeDType* findVoidDType() const;
AstNodeDType* findStreamDType() const;
AstNodeDType* findQueueIndexDType() const;
AstNodeDType* findBitDType(int width, int widthMin, VSigning numeric) const;
AstNodeDType* findLogicDType(int width, int widthMin, VSigning numeric) const;

View File

@ -1188,6 +1188,34 @@ public:
int widthTotalBytes() const override { return sizeof(std::map<std::string, std::string>); }
bool isCompound() const override { return true; }
};
class AstStreamDType final : public AstNodeDType {
// Stream data type, used only as data type of stream operations
// Should behave like AstPackArrayDType, but it doesn't have a size
public:
explicit AstStreamDType(FileLine* fl)
: ASTGEN_SUPER_StreamDType(fl) {
dtypep(this);
}
ASTGEN_MEMBERS_AstStreamDType;
void dumpSmall(std::ostream& str) const override;
bool hasDType() const override { return true; }
bool maybePointedTo() const override { return true; }
bool undead() const override { return true; }
AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }
bool isCompound() const override { return false; }
};
class AstUnsizedArrayDType final : public AstNodeDType {
// Unsized/open-range Array data type, ie "some_dtype var_name []"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width

View File

@ -4671,7 +4671,7 @@ public:
ASTGEN_MEMBERS_AstCvtPackString;
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
string emitVerilog() override { return "%f$_CAST(%l)"; }
string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
bool cleanLhs() const override { return true; }
bool sizeMattersLhs() const override { return false; }

View File

@ -1513,6 +1513,7 @@ class AstTypeTable final : public AstNode {
AstEmptyQueueDType* m_emptyQueuep = nullptr;
AstQueueDType* m_queueIndexp = nullptr;
AstVoidDType* m_voidp = nullptr;
AstStreamDType* m_streamp = nullptr;
AstBasicDType* m_basicps[VBasicDTypeKwd::_ENUM_MAX]{};
//
using DetailedMap = std::map<VBasicTypeKey, AstBasicDType*>;
@ -1538,6 +1539,7 @@ public:
AstEmptyQueueDType* findEmptyQueueDType(FileLine* fl);
AstQueueDType* findQueueIndexDType(FileLine* fl);
AstVoidDType* findVoidDType(FileLine* fl);
AstStreamDType* findStreamDType(FileLine* fl);
void clearCache();
void repairCache();
void dump(std::ostream& str = std::cout) const override;

View File

@ -1071,6 +1071,15 @@ AstVoidDType* AstTypeTable::findVoidDType(FileLine* fl) {
return m_voidp;
}
AstStreamDType* AstTypeTable::findStreamDType(FileLine* fl) {
if (VL_UNLIKELY(!m_streamp)) {
AstStreamDType* const newp = new AstStreamDType{fl};
addTypesp(newp);
m_streamp = newp;
}
return m_streamp;
}
AstQueueDType* AstTypeTable::findQueueIndexDType(FileLine* fl) {
if (VL_UNLIKELY(!m_queueIndexp)) {
AstQueueDType* const newp = new AstQueueDType{fl, AstNode::findUInt32DType(), nullptr};
@ -2055,6 +2064,10 @@ void AstVoidDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "void";
}
void AstStreamDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "stream";
}
void AstVarScope::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isTrace()) str << " [T]";

View File

@ -95,6 +95,7 @@ private:
|| VN_IS(nodep->dtypep()->skipRefp(), DynArrayDType)
|| VN_IS(nodep->dtypep()->skipRefp(), ClassRefDType)
|| VN_IS(nodep->dtypep()->skipRefp(), QueueDType)
|| VN_IS(nodep->dtypep()->skipRefp(), StreamDType)
|| VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)
|| VN_IS(nodep->dtypep()->skipRefp(), VoidDType)) {
} else {

View File

@ -2166,7 +2166,12 @@ private:
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
// Connect the rhs to the stream operator and update its width
VN_AS(streamp, StreamL)->lhsp(srcp);
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
if (VN_IS(srcp->dtypep(), DynArrayDType) || VN_IS(srcp->dtypep(), QueueDType)
|| VN_IS(srcp->dtypep(), UnpackArrayDType)) {
streamp->dtypeSetStream();
} else {
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
}
// Shrink the RHS if necessary
if (sWidth > dWidth) {
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};

View File

@ -452,6 +452,10 @@ void EmitCFunc::emitCvtPackStr(AstNode* nodep) {
putbs("std::string{");
putsQuoted(constp->num().toString());
puts("}");
} else if (VN_IS(nodep->dtypep(), StreamDType)) {
putbs("VL_CVT_PACK_STR_ND(");
iterateAndNextConstNull(nodep);
puts(")");
} else {
putbs("VL_CVT_PACK_STR_N");
emitIQW(nodep);

View File

@ -1026,6 +1026,7 @@ public:
UASSERT_OBJ(!emitSimpleOk(nodep), nodep, "Triop cannot be described in a simple way");
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nodep->thsp());
}
void visit(AstCvtPackString* nodep) override { emitCvtPackStr(nodep->lhsp()); }
void visit(AstRedXor* nodep) override {
if (nodep->lhsp()->isWide()) {
visit(static_cast<AstNodeUniop*>(nodep));

View File

@ -848,8 +848,14 @@ private:
} else {
nodep->v3error("Slice size isn't a constant or basic data type.");
}
nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), nodep->lhsp()->widthMin(),
VSigning::UNSIGNED);
if (VN_IS(nodep->lhsp()->dtypep(), DynArrayDType)
|| VN_IS(nodep->lhsp()->dtypep(), QueueDType)
|| VN_IS(nodep->lhsp()->dtypep(), UnpackArrayDType)) {
nodep->dtypeSetStream();
} else {
nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), nodep->lhsp()->widthMin(),
VSigning::UNSIGNED);
}
}
if (m_vup->final()) {
if (!nodep->dtypep()->widthSized()) {

View File

@ -6,10 +6,4 @@
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^~
%Warning-WIDTHEXPAND: t/t_stream_bad.v:12:27: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^
... For warning description see https://verilator.org/warn/WIDTHEXPAND?v=latest
... Use "/* verilator lint_off WIDTHEXPAND */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -1,149 +1,3 @@
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:118:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
118 | packed_data_32 = {<<8{byte_in}};
| ^
... For warning description see https://verilator.org/warn/WIDTHEXPAND?v=latest
... Use "/* verilator lint_off WIDTHEXPAND */" and lint_on around source to disable this message.
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:119:28: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's STREAML generates 16 bits.
: ... In instance t
119 | packed_data_64 = {<<16{shortint_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:120:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
120 | packed_data_128 = {<<32{int_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:121:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
121 | packed_data_128_i = {<<32{integer_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:122:28: Operator ASSIGN expects 256 bits on the Assign RHS, but Assign RHS's STREAML generates 64 bits.
: ... In instance t
122 | packed_data_256 = {<<64{longint_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:123:28: Operator ASSIGN expects 256 bits on the Assign RHS, but Assign RHS's STREAML generates 64 bits.
: ... In instance t
123 | packed_time_256 = {<<64{time_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:124:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
124 | v_packed_data_32 = {<<8{bit_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:125:28: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's STREAML generates 16 bits.
: ... In instance t
125 | v_packed_data_64 = {<<16{logic_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:126:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
126 | v_packed_data_128 = {<<32{reg_in}};
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:128:31: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_32' generates 32 bits.
: ... In instance t
128 | {<<8{byte_out}} = packed_data_32;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:129:31: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_64' generates 64 bits.
: ... In instance t
129 | {<<16{shortint_out}} = packed_data_64;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:130:31: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_128' generates 128 bits.
: ... In instance t
130 | {<<32{int_out}} = packed_data_128;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:131:31: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_128_i' generates 128 bits.
: ... In instance t
131 | {<<32{integer_out}} = packed_data_128_i;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:132:31: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_256' generates 256 bits.
: ... In instance t
132 | {<<64{longint_out}} = packed_data_256;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:133:31: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's VARREF 'packed_time_256' generates 256 bits.
: ... In instance t
133 | {<<64{time_out}} = packed_time_256;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:134:31: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_32' generates 32 bits.
: ... In instance t
134 | {<<8{bit_out}} = v_packed_data_32;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:135:31: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_64' generates 64 bits.
: ... In instance t
135 | {<<16{logic_out}} = v_packed_data_64;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:136:31: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_128' generates 128 bits.
: ... In instance t
136 | {<<32{reg_out}} = v_packed_data_128;
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:150:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
150 | packed_data_32 = {<<byte{byte_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:151:28: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's STREAML generates 16 bits.
: ... In instance t
151 | packed_data_64 = {<<shortint{shortint_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:152:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
152 | packed_data_128 = {<<int{int_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:153:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
153 | packed_data_128_i = {<<integer{integer_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:154:28: Operator ASSIGN expects 256 bits on the Assign RHS, but Assign RHS's STREAML generates 64 bits.
: ... In instance t
154 | packed_data_256 = {<<longint{longint_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:155:28: Operator ASSIGN expects 256 bits on the Assign RHS, but Assign RHS's STREAML generates 64 bits.
: ... In instance t
155 | packed_time_256 = {<<time{time_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:156:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
156 | v_packed_data_32 = {<<test_byte{bit_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:157:28: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's STREAML generates 16 bits.
: ... In instance t
157 | v_packed_data_64 = {<<test_short{logic_in}};
| ^
%Warning-WIDTHEXPAND: t/t_stream_integer_type.v:158:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
158 | v_packed_data_128 = {<<test_word{reg_in}};
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:160:37: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_32' generates 32 bits.
: ... In instance t
160 | {<<byte{byte_out}} = packed_data_32;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:161:37: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_64' generates 64 bits.
: ... In instance t
161 | {<<shortint{shortint_out}} = packed_data_64;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:162:37: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_128' generates 128 bits.
: ... In instance t
162 | {<<int{int_out}} = packed_data_128;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:163:37: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_128_i' generates 128 bits.
: ... In instance t
163 | {<<integer{integer_out}} = packed_data_128_i;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:164:37: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_256' generates 256 bits.
: ... In instance t
164 | {<<longint{longint_out}} = packed_data_256;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:165:37: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's VARREF 'packed_time_256' generates 256 bits.
: ... In instance t
165 | {<<time{time_out}} = packed_time_256;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:166:37: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_32' generates 32 bits.
: ... In instance t
166 | {<<test_byte{bit_out}} = v_packed_data_32;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:167:37: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_64' generates 64 bits.
: ... In instance t
167 | {<<test_short{logic_out}} = v_packed_data_64;
| ^
%Warning-WIDTHTRUNC: t/t_stream_integer_type.v:168:37: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_128' generates 128 bits.
: ... In instance t
168 | {<<test_word{reg_out}} = v_packed_data_128;
| ^
%Error: t/t_stream_integer_type.v:128:11: SEL is not an unpacked array, but is in an unpacked array context
128 | {<<8{byte_out}} = packed_data_32;
| ^~

View File

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

View File

@ -0,0 +1,31 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t;
string qs[$];
string as[];
string s;
initial begin
s = {>>{qs}};
if (s != "") $stop;
s = {>>{as}};
if (s != "") $stop;
qs = '{"ab", "c", ""};
s = {>>{qs}};
if (s != "abc") $stop;
as = new[3];
as[0] = "abcd";
as[2] = "ef";
s = {>>{as}};
if (s != "abcdef") $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule