Support empty queue assignment to delete queue

This commit is contained in:
Wilson Snyder 2021-08-28 17:23:35 -04:00
parent 27d53691bd
commit 43aa3229fb
10 changed files with 140 additions and 8 deletions

View File

@ -1264,12 +1264,15 @@ AstNodeDType* AstNode::findBitRangeDType(const VNumRange& range, int widthMin,
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
return v3Global.rootp()->typeTablep()->findInsertSameDType(nodep);
}
AstNodeDType* AstNode::findVoidDType() const {
return v3Global.rootp()->typeTablep()->findVoidDType(fileline());
AstNodeDType* AstNode::findEmptyQueueDType() const {
return v3Global.rootp()->typeTablep()->findEmptyQueueDType(fileline());
}
AstNodeDType* AstNode::findQueueIndexDType() const {
return v3Global.rootp()->typeTablep()->findQueueIndexDType(fileline());
}
AstNodeDType* AstNode::findVoidDType() const {
return v3Global.rootp()->typeTablep()->findVoidDType(fileline());
}
//######################################################################
// AstNVisitor

View File

@ -1698,6 +1698,7 @@ public:
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
void dtypeSetEmptyQueue() { dtypep(findEmptyQueueDType()); }
void dtypeSetVoid() { dtypep(findVoidDType()); }
// Data type locators
@ -1708,6 +1709,7 @@ public:
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); }
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); }
AstNodeDType* findCHandleDType() { return findBasicDType(AstBasicDTypeKwd::CHANDLE); }
AstNodeDType* findEmptyQueueDType() const;
AstNodeDType* findVoidDType() const;
AstNodeDType* findQueueIndexDType() const;
AstNodeDType* findBitDType(int width, int widthMin, VSigning numeric) const;

View File

@ -932,9 +932,18 @@ void AstTypeTable::repairCache() {
}
}
AstEmptyQueueDType* AstTypeTable::findEmptyQueueDType(FileLine* fl) {
if (VL_UNLIKELY(!m_emptyQueuep)) {
AstEmptyQueueDType* newp = new AstEmptyQueueDType{fl};
addTypesp(newp);
m_emptyQueuep = newp;
}
return m_emptyQueuep;
}
AstVoidDType* AstTypeTable::findVoidDType(FileLine* fl) {
if (VL_UNLIKELY(!m_voidp)) {
AstVoidDType* newp = new AstVoidDType(fl);
AstVoidDType* newp = new AstVoidDType{fl};
addTypesp(newp);
m_voidp = newp;
}
@ -1642,6 +1651,10 @@ void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "[]";
}
void AstEmptyQueueDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "emptyq";
}
void AstVoidDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "void";

View File

@ -183,6 +183,17 @@ public:
static AstConst* parseParamLiteral(FileLine* fl, const string& literal);
};
class AstEmptyQueue final : public AstNodeMath {
public:
AstEmptyQueue(FileLine* fl)
: ASTGEN_SUPER_EmptyQueue(fl) {}
ASTNODE_NODE_FUNCS(EmptyQueue)
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual string emitVerilog() { return "{}"; }
virtual bool same(const AstNode* samep) const override { return true; }
virtual bool cleanOut() const { return true; }
};
class AstRange final : public AstNodeRange {
// Range specification, for use under variables and cells
public:
@ -1354,6 +1365,33 @@ public:
}
};
class AstEmptyQueueDType final : public AstNodeDType {
// For EmptyQueue
public:
explicit AstEmptyQueueDType(FileLine* fl)
: ASTGEN_SUPER_EmptyQueueDType(fl) {
dtypep(this);
}
ASTNODE_NODE_FUNCS(EmptyQueueDType)
virtual void dumpSmall(std::ostream& str) const override;
virtual bool hasDType() const override { return true; }
virtual bool maybePointedTo() const override { return true; }
virtual AstNodeDType* subDTypep() const override { return nullptr; }
virtual AstNodeDType* virtRefDTypep() const override { return nullptr; }
virtual void virtRefDTypep(AstNodeDType* nodep) override {}
virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
virtual AstBasicDType* basicp() const override { return nullptr; }
// cppcheck-suppress csyleCast
virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const override { return 1; }
virtual int widthTotalBytes() const override { return 1; }
virtual bool isCompound() const override { return false; }
};
class AstVoidDType final : public AstNodeDType {
// For e.g. a function returning void
public:
@ -9088,8 +9126,9 @@ public:
class AstTypeTable final : public AstNode {
// Container for hash of standard data types
// Children: NODEDTYPEs
AstVoidDType* m_voidp = nullptr;
AstEmptyQueueDType* m_emptyQueuep = nullptr;
AstQueueDType* m_queueIndexp = nullptr;
AstVoidDType* m_voidp = nullptr;
AstBasicDType* m_basicps[AstBasicDTypeKwd::_ENUM_MAX];
//
using DetailedMap = std::map<VBasicTypeKey, AstBasicDType*>;
@ -9100,14 +9139,15 @@ public:
ASTNODE_NODE_FUNCS(TypeTable)
AstNodeDType* typesp() const { return VN_CAST(op1p(), NodeDType); } // op1 = List of dtypes
void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); }
AstVoidDType* findVoidDType(FileLine* fl);
AstQueueDType* findQueueIndexDType(FileLine* fl);
AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd);
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, int width, int widthMin,
VSigning numeric);
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, const VNumRange& range,
int widthMin, VSigning numeric);
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
AstEmptyQueueDType* findEmptyQueueDType(FileLine* fl);
AstQueueDType* findQueueIndexDType(FileLine* fl);
AstVoidDType* findVoidDType(FileLine* fl);
void clearCache();
void repairCache();
virtual void dump(std::ostream& str = std::cout) const override;

View File

@ -1078,6 +1078,12 @@ private:
// We don't size the constant until we commit the widths, as need parameters
// to remain unsized, and numbers to remain unsized to avoid backp() warnings
}
virtual void visit(AstEmptyQueue* nodep) override {
nodep->dtypeSetEmptyQueue();
if (!VN_IS(nodep->backp(), Assign))
nodep->v3warn(E_UNSUPPORTED,
"Unsupported/Illegal: empty queue ('{}') in this context");
}
virtual void visit(AstFell* nodep) override {
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
@ -1173,6 +1179,7 @@ private:
return;
}
}
nodep->backp()->dumpTree(cout, "-FIXME-tr ");
nodep->v3warn(E_UNSUPPORTED, "Unsupported/illegal unbounded ('$') in this context.");
}
virtual void visit(AstIsUnbounded* nodep) override {
@ -3761,6 +3768,23 @@ private:
nodep->v3warn(E_UNSUPPORTED, "Unsupported: assignment of event data type");
}
}
if (VN_IS(nodep->rhsp(), EmptyQueue)) {
UINFO(9, "= {} -> .delete(): " << nodep);
if (!VN_IS(nodep->lhsp()->dtypep()->skipRefp(), QueueDType)) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported/Illegal: empty queue ('{}') in this assign context");
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
}
AstMethodCall* const newp = new AstMethodCall{
nodep->fileline(), nodep->lhsp()->unlinkFrBack(), "delete", nullptr};
newp->makeStatement();
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
// Need to now convert it
visit(newp);
return;
}
if (AstNewDynamic* dynp = VN_CAST(nodep->rhsp(), NewDynamic)) {
UINFO(9, "= new[] -> .resize(): " << nodep);
AstCMethodHard* newp;
@ -3777,6 +3801,7 @@ private:
newp->makeStatement();
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
// return;
}
}

View File

@ -4268,8 +4268,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// // IEEE: "... hierarchical_identifier select" see below
//
// // IEEE: empty_queue (IEEE 1800-2017 empty_unpacked_array_concatenation)
| '{' '}' { $$ = new AstConst($1, AstConst::BitFalse());
BBUNSUP($<fl>1, "Unsupported: empty queues (\"{ }\")"); }
| '{' '}' { $$ = new AstEmptyQueue($1); }
//
// // IEEE: concatenation/constant_concatenation
// // Part of exprOkLvalue below

View File

@ -0,0 +1,10 @@
%Error-UNSUPPORTED: t/t_queue_empty_bad.v:11:11: Unsupported/Illegal: empty queue ('{}') in this context
: ... In instance t
11 | i = {} + 1;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_queue_empty_bad.v:13:9: Unsupported/Illegal: empty queue ('{}') in this assign context
: ... In instance t
13 | i = {};
| ^
%Error: Exiting due to

View 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 2003 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(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,18 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
initial begin
int i;
i = {} + 1;
i = {};
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -26,6 +26,9 @@ module t (/*AUTOARG*/);
q = '{"q"};
v = $sformatf("%p", q); `checks(v, "'{\"q\"} ");
q = {};
i = q.size(); `checkh(i, 0);
q = '{"q", "b", "c", "d", "e", "f"};
if (q[0] !== "q") $stop;
v = $sformatf("%p", q); `checks(v, "'{\"q\", \"b\", \"c\", \"d\", \"e\", \"f\"} ");