Support bounded queues.

This commit is contained in:
Wilson Snyder 2019-12-14 21:39:47 -05:00
parent 2a1c57ada6
commit 2408de16a0
11 changed files with 46 additions and 51 deletions

View File

@ -4,7 +4,7 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.025 devel
*** Add BOUNDED warning and promote bounded queues to unbounded.
*** Support bounded queues.
*** Support string compare, icompare, ato* methods, bug1606. [Yutetsu TAKATSUKASA]

View File

@ -185,7 +185,8 @@ std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
// There are no multithreaded locks on this; the base variable must
// be protected by other means
//
template <class T_Value> class VlQueue {
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
template <class T_Value, size_t T_MaxSize = 0> class VlQueue {
private:
// TYPES
typedef std::deque<T_Value> Deque;
@ -215,9 +216,14 @@ public:
void erase(size_t index) { if (VL_LIKELY(index < m_deque.size())) m_deque.erase(index); }
// function void q.push_front(value)
void push_front(const T_Value& value) { m_deque.push_front(value); }
void push_front(const T_Value& value) {
m_deque.push_front(value);
if (VL_UNLIKELY(T_MaxSize != 0 && m_deque.size() > T_MaxSize)) m_deque.pop_back();
}
// function void q.push_back(value)
void push_back(const T_Value& value) { m_deque.push_back(value); }
void push_back(const T_Value& value) {
if (VL_LIKELY(T_MaxSize == 0 || m_deque.size() < T_MaxSize)) m_deque.push_back(value);
}
// function value_t q.pop_front();
T_Value pop_front() {
if (m_deque.empty()) return m_defaultValue;

View File

@ -285,6 +285,8 @@ AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDT
if (!sub.m_osuffix.empty() || !sub.m_oref.empty()) {
out += " " + sub.m_osuffix + sub.m_oref;
}
// + 1 below as VlQueue uses 0 to mean unlimited, 1 to mean size() max is 1
if (adtypep->boundp()) out += ", " + cvtToStr(adtypep->boundConst() + 1);
out += "> ";
info.m_oprefix = out;
return info;

View File

@ -743,8 +743,9 @@ class AstQueueDType : public AstNodeDType {
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
public:
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp)
: AstNodeDType(fl) {
setNOp2p(boundp);
childDTypep(dtp); // Only for parser
refDTypep(NULL);
dtypep(NULL); // V3Width will resolve
@ -770,6 +771,9 @@ public:
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNode* boundp() const { return op2p(); } // op2 = Bound, NULL = none
void boundp(AstNode* nodep) { setNOp2p(nodep); }
int boundConst() const { AstConst* constp = VN_CAST(boundp(), Const); return (constp?constp->toSInt() : 0); }
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
// METHODS

View File

@ -105,7 +105,6 @@ public:
SYMRSVDWORD, // Symbol is Reserved Word
SYNCASYNCNET, // Mixed sync + async reset
TICKCOUNT, // Too large tick count
UNBOUNDED, // Unbounded queue
UNDRIVEN, // No drivers
UNOPT, // Unoptimizable block
UNOPTFLAT, // Unoptimizable block after flattening
@ -155,7 +154,7 @@ public:
"REALCVT", "REDEFMACRO",
"SELRANGE", "SHORTREAL", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT",
"UNBOUNDED", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSIGNED", "UNUSED",
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",

View File

@ -118,14 +118,11 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep,
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else if (VN_IS(nrangep, QueueRange)) {
arrayp = new AstQueueDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
(nrangep->fileline(), VFlagChildDType(), arrayp, NULL);
} else if (rangep && (VN_IS(rangep->leftp(), Unbounded)
|| VN_IS(rangep->rightp(), Unbounded))) {
if (!VN_IS(rangep->rightp(), Unbounded)) {
rangep->v3warn(UNBOUNDED,
"Unsupported: Bounded queues. Converting to unbounded.");
}
arrayp = new AstQueueDType(nrangep->fileline(), VFlagChildDType(), arrayp);
arrayp = new AstQueueDType(nrangep->fileline(), VFlagChildDType(), arrayp,
rangep->rightp()->cloneTree(true));
} else if (rangep) {
arrayp = new AstUnpackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);

View File

@ -1124,6 +1124,9 @@ private:
// Iterate into subDTypep() to resolve that type and update pointer.
nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep()));
nodep->dtypep(nodep); // The array itself, not subDtype
if (VN_IS(nodep->boundp(), Unbounded)) {
nodep->boundp()->unlinkFrBack()->deleteTree(); // NULL will represent unbounded
}
UINFO(4,"dtWidthed "<<nodep<<endl);
}
virtual void visit(AstUnsizedArrayDType* nodep) {

View File

@ -5,17 +5,32 @@
module t (/*AUTOARG*/);
// verilator lint_off UNBOUNDED
int q[$ : 3];
int q[$ : 2]; // Shall not go higher than [2], i.e. size 3
initial begin
q.push_front(1);
q.push_front(1);
q.push_front(3);
if (q.size() != 1) $stop;
q.push_front(2);
if (q.size() != 2) $stop;
q.push_front(1);
if (q.size() != 3) $stop;
q.push_front(1);
// TODO correct answer when supported:
//if (q.size() != 3) $stop;
q.push_front(0);
if (q.size() != 3) $stop;
if (q[0] != 0) $stop;
if (q[1] != 1) $stop;
if (q[2] != 2) $stop;
q.delete();
q.push_back(0);
q.push_back(1);
q.push_back(2);
if (q.size() != 3) $stop;
q.push_back(3);
if (q.size() != 3) $stop;
if (q[0] != 0) $stop;
if (q[1] != 1) $stop;
if (q[2] != 2) $stop;
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -1,5 +0,0 @@
%Warning-UNBOUNDED: t/t_queue_bounded_unsup_bad.v:7: Unsupported: Bounded queues. Converting to unbounded.
int q[$ : 3];
^
... Use "/* verilator lint_off UNBOUNDED */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -1,18 +0,0 @@
#!/usr/bin/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.
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -1,8 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t (/*AUTOARG*/);
int q[$ : 3];
endmodule