Fix queue assignment with different limits, negative indicies

This commit is contained in:
Wilson Snyder 2020-10-24 22:08:11 -04:00
parent 835905bdae
commit 046c0a7aa1
2 changed files with 53 additions and 10 deletions

View File

@ -272,7 +272,15 @@ public:
// m_defaultValue isn't defaulted. Caller's constructor must do it.
}
~VlQueue() {}
// Standard copy constructor works. Verilog: assoca = assocb
// Also must allow conversion from a different T_MaxSize queue
template <size_t U_MaxSize = 0> VlQueue operator=(const VlQueue<T_Value, U_MaxSize>& rhs) {
m_deque = rhs.privateDeque();
if (VL_UNLIKELY(T_MaxSize && T_MaxSize < m_deque.size())) m_deque.resize(T_MaxSize - 1);
return *this;
}
static VlQueue cons(const T_Value& lhs) {
VlQueue out;
out.push_back(lhs);
@ -302,13 +310,15 @@ public:
// METHODS
T_Value& atDefault() { return m_defaultValue; }
const Deque& privateDeque() const { return m_deque; }
// Size. Verilog: function int size(), or int num()
int size() const { return m_deque.size(); }
// Clear array. Verilog: function void delete([input index])
void clear() { m_deque.clear(); }
void erase(size_t index) {
if (VL_LIKELY(index < m_deque.size())) m_deque.erase(m_deque.begin() + index);
void erase(vlsint32_t index) {
if (VL_LIKELY(index >= 0 && index < m_deque.size()))
m_deque.erase(m_deque.begin() + index);
}
// Dynamic array new[] becomes a renew()
@ -353,10 +363,10 @@ public:
// Setting. Verilog: assoc[index] = v
// Can't just overload operator[] or provide a "at" reference to set,
// because we need to be able to insert only when the value is set
T_Value& at(size_t index) {
T_Value& at(vlsint32_t index) {
static T_Value s_throwAway;
// Needs to work for dynamic arrays, so does not use T_MaxSize
if (VL_UNLIKELY(index >= m_deque.size())) {
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
s_throwAway = atDefault();
return s_throwAway;
} else {
@ -364,27 +374,28 @@ public:
}
}
// Accessing. Verilog: v = assoc[index]
const T_Value& at(size_t index) const {
const T_Value& at(vlsint32_t index) const {
static T_Value s_throwAway;
// Needs to work for dynamic arrays, so does not use T_MaxSize
if (VL_UNLIKELY(index >= m_deque.size())) {
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
return atDefault();
} else {
return m_deque[index];
}
}
// function void q.insert(index, value);
void insert(size_t index, const T_Value& value) {
if (VL_UNLIKELY(index >= m_deque.size())) return;
void insert(vlsint32_t index, const T_Value& value) {
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) return;
m_deque.insert(m_deque.begin() + index, value);
}
// Return slice q[lsb:msb]
VlQueue slice(size_t lsb, size_t msb) const {
VlQueue slice(vlsint32_t lsb, vlsint32_t msb) const {
VlQueue out;
if (VL_UNLIKELY(lsb < 0)) lsb = 0;
if (VL_UNLIKELY(lsb >= m_deque.size())) lsb = m_deque.size() - 1;
if (VL_UNLIKELY(msb >= m_deque.size())) msb = m_deque.size() - 1;
for (size_t i = lsb; i <= msb; ++i) out.push_back(m_deque[i]);
for (vlsint32_t i = lsb; i <= msb; ++i) out.push_back(m_deque[i]);
return out;
}

View File

@ -13,6 +13,8 @@ module t (/*AUTOARG*/);
string q[$];
string v;
int i;
int qi[$:5];
int ri[$];
q.push_front("non-empty");
i = q.size(); `checkh(i, 1);
@ -43,6 +45,9 @@ module t (/*AUTOARG*/);
// Slicing
q = '{"q", "b", "c", "d", "e", "f"};
q = q[-1:0];
v = $sformatf("%p", q); `checks(v, "'{\"q\"} ");
q = '{"q", "b", "c", "d", "e", "f"};
q = q[2:3];
v = $sformatf("%p", q); `checks(v, "'{\"c\", \"d\"} ");
q = '{"q", "b", "c", "d", "e", "f"};
@ -80,7 +85,34 @@ module t (/*AUTOARG*/);
v = q.pop_front(); `checks(v, "CC");
end
begin
qi.push_back(0);
qi.push_back(1);
qi.push_back(2);
qi.push_back(3);
qi.push_back(4);
qi.push_back(5);
// Assignment to unsized queue from sized queue
ri = qi[ 2 : 4 ];
`checkh(ri.size, 3);
ri = qi[ 4 : 2 ];
`checkh(ri.size, 0);
ri = qi[ 2 : 2 ];
`checkh(ri.size, 1);
ri = qi[ -2 : 2 ]; // 2 - 0 + 1 = 3
`checkh(ri.size, 3);
ri = qi[ 2 : 10 ]; // 5 - 2 + 1 = 4
`checkh(ri.size, 4);
// Assignment from unsized to sized
ri = '{1,2,3,4,5,6,7,8,9};
qi = ri;
`checkh(qi.size, 5);
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule