Support bounded queues.
This commit is contained in:
parent
2a1c57ada6
commit
2408de16a0
2
Changes
2
Changes
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue