Merge pull request #640 from larsclausen/darray-packed-array
Support dynamic arrays and queues of packed arrays
This commit is contained in:
commit
d7e4d209b8
|
|
@ -111,7 +111,6 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
|||
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
|
||||
net_design.o netclass.o netdarray.o \
|
||||
netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \
|
||||
make_ivl_type.o \
|
||||
net_event.o net_expr.o net_func.o \
|
||||
net_func_eval.o net_link.o net_modulo.o \
|
||||
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
|
||||
|
|
|
|||
7
PWire.h
7
PWire.h
|
|
@ -130,6 +130,13 @@ class PWire : public PNamedItem {
|
|||
private: // not implemented
|
||||
PWire(const PWire&);
|
||||
PWire& operator= (const PWire&);
|
||||
|
||||
ivl_type_t elaborate_type(Design*des, NetScope*scope,
|
||||
const std::vector<netrange_t>&packed_dimensions) const;
|
||||
ivl_type_t elaborate_darray_type(Design*des, NetScope*scope,
|
||||
const char *darray_type,
|
||||
const std::vector<netrange_t>&packed_dimensions)
|
||||
const;
|
||||
};
|
||||
|
||||
#endif /* IVL_PWire_H */
|
||||
|
|
|
|||
187
elab_sig.cc
187
elab_sig.cc
|
|
@ -934,6 +934,64 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
|
|||
return true;
|
||||
}
|
||||
|
||||
ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
|
||||
const std::vector<netrange_t>&packed_dimensions) const
|
||||
{
|
||||
if (dynamic_cast<struct_type_t*>(set_data_type_) ||
|
||||
dynamic_cast<enum_type_t*>(set_data_type_) ||
|
||||
dynamic_cast<string_type_t*>(set_data_type_) ||
|
||||
dynamic_cast<class_type_t*>(set_data_type_) ||
|
||||
dynamic_cast<parray_type_t*>(set_data_type_)) {
|
||||
ivl_type_t use_type = set_data_type_->elaborate_type(des, scope);
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
return use_type;
|
||||
}
|
||||
|
||||
// Fallback method. Create vector type.
|
||||
|
||||
ivl_variable_type_t use_data_type = data_type_;
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_data_type == IVL_VT_LOGIC ||
|
||||
use_data_type == IVL_VT_BOOL ||
|
||||
use_data_type == IVL_VT_REAL);
|
||||
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
|
||||
vec->set_signed(get_signed());
|
||||
vec->set_isint(get_isint());
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
ivl_type_t PWire::elaborate_darray_type(Design*des, NetScope*scope,
|
||||
const char *darray_type,
|
||||
const std::vector<netrange_t>&packed_dimensions)
|
||||
const
|
||||
{
|
||||
ivl_type_t type = elaborate_type(des, scope, packed_dimensions);
|
||||
|
||||
if (dynamic_cast<const netvector_t*>(type) ||
|
||||
dynamic_cast<const netparray_t*>(type) ||
|
||||
dynamic_cast<const netreal_t*>(type) ||
|
||||
dynamic_cast<const netstring_t*>(type))
|
||||
return type;
|
||||
|
||||
cerr << get_fileline() << ": Sorry: "
|
||||
<< darray_type << " of type `" << *type
|
||||
<< "` is not yet supported." << endl;
|
||||
des->errors++;
|
||||
|
||||
// Return something to recover
|
||||
return new netvector_t(IVL_VT_LOGIC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||
|
|
@ -1100,19 +1158,21 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// dimensions, then turn this into a dynamic array and
|
||||
// put all the packed dimensions there.
|
||||
if (use_lidx==0 && use_ridx==0) {
|
||||
ivl_type_t vec = make_ivl_type(data_type_, packed_dimensions,
|
||||
get_signed());
|
||||
ivl_type_t base_type = elaborate_darray_type(des, scope,
|
||||
"Dynamic array",
|
||||
packed_dimensions);
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
netdarray = new netdarray_t(base_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: Detect the mark for a QUEUE
|
||||
// declaration, which is the dimensions [null:max_idx].
|
||||
if (dynamic_cast<PENull*>(use_lidx)) {
|
||||
ivl_type_t vec = make_ivl_type(data_type_, packed_dimensions,
|
||||
get_signed());
|
||||
ivl_type_t base_type = elaborate_darray_type(des, scope,
|
||||
"Queue",
|
||||
packed_dimensions);
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
long max_idx;
|
||||
|
|
@ -1144,7 +1204,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
} else max_idx = -1;
|
||||
netdarray = new netqueue_t(vec, max_idx);
|
||||
netdarray = new netqueue_t(base_type, max_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1213,52 +1273,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
NetNet*sig = 0;
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*>(set_data_type_)) {
|
||||
// If this is a class variable, then the class type
|
||||
// should already have been elaborated. All we need to
|
||||
// do right now is locate the netclass_t object for the
|
||||
// class, and use that to build the net.
|
||||
|
||||
ivl_assert(*this, class_type->save_elaborated_type);
|
||||
netclass_t*use_type = class_type->save_elaborated_type;
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
|
||||
// If this is a struct type, then build the net with the
|
||||
// struct type.
|
||||
ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope);
|
||||
netstruct_t*use_type = dynamic_cast<netstruct_t*>(tmp_type);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
if (use_type->packed())
|
||||
cerr << " " << use_type->packed_width() << " bit packed struct ";
|
||||
else
|
||||
cerr << " struct <> ";
|
||||
cerr << name_;
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Create signal " << wtype
|
||||
<< " enumeration "
|
||||
<< name_ << " in scope " << scope_path(scope)
|
||||
<< " with packed_dimensions=" << packed_dimensions
|
||||
<< " and packed_width=" << use_enum->packed_width() << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
|
||||
|
||||
|
||||
} else if (netdarray) {
|
||||
if (netdarray) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
|
|
@ -1272,76 +1287,18 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, unpacked_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, netdarray);
|
||||
|
||||
} else if (dynamic_cast<string_type_t*>(set_data_type_)) {
|
||||
|
||||
// Signal declared as: string foo;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Create signal " << wtype
|
||||
<< " string "
|
||||
<< name_ << " in scope " << scope_path(scope)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions,
|
||||
&netstring_t::type_string);
|
||||
|
||||
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
|
||||
// The pform gives us a parray_type_t for packed arrays
|
||||
// that show up in type definitions. This can be handled
|
||||
// a lot like packed dimensions from other means.
|
||||
|
||||
// The trick here is that the parray type has an
|
||||
// arbitrary sub-type, and not just a scalar bit...
|
||||
ivl_type_t tmp_type = parray_type->elaborate_type(des, scope);
|
||||
const netparray_t*use_type = dynamic_cast<const netparray_t*>(tmp_type);
|
||||
// Should not be getting packed dimensions other than
|
||||
// through the parray type declaration.
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
} else {
|
||||
ivl_type_t use_type = elaborate_type(des, scope,
|
||||
packed_dimensions);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " parray=" << use_type->static_dimensions()
|
||||
cerr << get_fileline() << ": debug: Create signal "
|
||||
<< wtype << " " << *set_data_type_
|
||||
<< " " << name_ << unpacked_dimensions
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
|
||||
} else {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Create vector signal " << wtype
|
||||
<< " data_type=" << data_type_;
|
||||
if (!packed_dimensions.empty()) {
|
||||
cerr << " " << packed_dimensions;
|
||||
}
|
||||
cerr << " " << name_ << unpacked_dimensions;
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
ivl_variable_type_t use_data_type = data_type_;
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_data_type == IVL_VT_LOGIC ||
|
||||
use_data_type == IVL_VT_BOOL ||
|
||||
use_data_type == IVL_VT_REAL);
|
||||
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
|
||||
vec->set_signed(get_signed());
|
||||
vec->set_isint(get_isint());
|
||||
packed_dimensions.clear();
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec);
|
||||
|
||||
}
|
||||
|
||||
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
./ivltests/sv_queue_parray.v:35: Warning: skipping delete(0) on empty queue.
|
||||
./ivltests/sv_queue_parray.v:39: Warning: pop_front() on empty queue<vector[40]>.
|
||||
./ivltests/sv_queue_parray.v:45: Warning: pop_back() on empty queue<vector[40]>.
|
||||
./ivltests/sv_queue_parray.v:56: Warning: skipping out of range delete(3) on queue of size 3.
|
||||
./ivltests/sv_queue_parray.v:57: Warning: skipping queue delete() with negative index.
|
||||
./ivltests/sv_queue_parray.v:58: Warning: skipping queue delete() with undefined index.
|
||||
./ivltests/sv_queue_parray.v:132: Warning: cannot assign to a negative queue<vector[40]> index (-1). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:133: Warning: cannot assign to an undefined queue<vector[40]> index. 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:134: Warning: assigning to queue<vector>[4] is outside of size (3). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:137: Warning: cannot assign to a negative queue<vector[40]> index (-1). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:139: Warning: cannot assign to an undefined queue<vector[40]> index. 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:141: Warning: assigning to queue<vector>[4] is outside of size (3). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:153: Warning: cannot insert at a negative queue<vector[40]> index (-1). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:154: Warning: cannot insert at an undefined queue<vector[40]> index. 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray.v:155: Warning: inserting to queue<vector[40]>[5] is outside of size (4). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
PASSED
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
./ivltests/sv_queue_parray_bounded.v:61: Warning: Array pattern assignment has more elements (4) than bounded queue 'q_tst' supports (3).
|
||||
Only using first 3 elements.
|
||||
./ivltests/sv_queue_parray_bounded.v:38: Warning: push_back(40'b0000000000000000000000000000000001100100) skipped for already full bounded queue<vector[40]> [3].
|
||||
./ivltests/sv_queue_parray_bounded.v:45: Warning: push_front(40'b0000000000000000000000000000000000000101) removed 40'b0000000000000000000000000000000000000011 from already full bounded queue<vector[40]> [3].
|
||||
./ivltests/sv_queue_parray_bounded.v:46: Warning: assigning to queue<vector>[3] is outside bound (3). 40'b0000000000000000000000000000000000000011 was not added.
|
||||
./ivltests/sv_queue_parray_bounded.v:53: Warning: inserting to queue<vector[40]>[3] is outside bound (3). 40'b0000000000000000000000000000000000001010 was not added.
|
||||
./ivltests/sv_queue_parray_bounded.v:54: Warning: insert(1, 40'b0000000000000000000000000000000000000010) removed 40'b0000000000000000000000000000000000000010 from already full bounded queue<vector[40]> [3].
|
||||
./ivltests/sv_queue_parray_bounded.v:69: Warning: queue<vector> is bounded to have at most 3 elements, source has 4 elements.
|
||||
PASSED
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
./ivltests/sv_queue_parray_fail.v:7: error: queue 'q_vec1' bound must be positive (-1)!
|
||||
./ivltests/sv_queue_parray_fail.v:8: error: queue 'q_vec2' bound is undefined!
|
||||
./ivltests/sv_queue_parray_fail.v:9: error: A reference to a wire or reg (`bound') is not allowed in a constant expression.
|
||||
./ivltests/sv_queue_parray_fail.v:9: error: queue 'q_vec3' bound must be a constant!
|
||||
./ivltests/sv_queue_parray_fail.v:12: error: size() method takes no arguments
|
||||
./ivltests/sv_queue_parray_fail.v:13: error: pop_front() method takes no arguments
|
||||
./ivltests/sv_queue_parray_fail.v:14: error: pop_back() method takes no arguments
|
||||
./ivltests/sv_queue_parray_fail.v:15: error: push_front() method requires a single argument.
|
||||
./ivltests/sv_queue_parray_fail.v:16: error: push_back() method requires a single argument.
|
||||
9 error(s) during elaboration.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// Check that dynamic arrays of packed array types are supported
|
||||
|
||||
module main;
|
||||
|
||||
typedef reg [3:0] T1;
|
||||
typedef T1 [7:0] T2;
|
||||
|
||||
T2 foo[];
|
||||
int idx;
|
||||
|
||||
initial begin
|
||||
if (foo.size() != 0) begin
|
||||
$display("FAILED -- foo.size()=%0d, s.b. 0", foo.size());
|
||||
$finish;
|
||||
end
|
||||
|
||||
foo = new[10];
|
||||
if (foo.size() != 10) begin
|
||||
$display("FAILED -- foo.size()=%0d, s.b. 10", foo.size());
|
||||
$finish;
|
||||
end
|
||||
|
||||
for (idx = 0 ; idx < foo.size() ; idx += 1) begin
|
||||
foo[idx] = idx;
|
||||
end
|
||||
|
||||
$display("foo[7] = %d", foo[7]);
|
||||
if (foo[7] != 7) begin
|
||||
$display("FAILED -- foo[7] = %0d (s.b. 7)", foo[7]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("foo[9] = %d", foo[9]);
|
||||
if (foo[9] != 9) begin
|
||||
$display("FAILED -- foo[9] = %0d (s.b. 9)", foo[9]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
for (idx = 0 ; idx < 2*foo.size() ; idx += 1) begin
|
||||
if (foo[idx%10] != (idx%10)) begin
|
||||
$display("FAILED -- foo[%0d%%10] = %0d", idx, foo[idx%10]);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
foo.delete();
|
||||
if (foo.size() != 0) begin
|
||||
$display("FAILED -- foo.size()=%0d (after delete: s.b. 0)", foo.size());
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule // main
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
module top;
|
||||
typedef reg [4:0] T1;
|
||||
typedef T1 [7:0] T2;
|
||||
|
||||
T2 q_tst [$];
|
||||
T2 q_tmp [$];
|
||||
T2 elem;
|
||||
integer idx;
|
||||
bit passed;
|
||||
|
||||
task automatic check_size(integer size,
|
||||
string fname,
|
||||
integer lineno);
|
||||
if (q_tst.size !== size) begin
|
||||
$display("%s:%0d: Failed: queue size != %0d (%0d)",
|
||||
fname, lineno, size, q_tst.size);
|
||||
passed = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic check_idx_value(integer idx,
|
||||
T2 expected,
|
||||
string fname,
|
||||
integer lineno);
|
||||
if (q_tst[idx] != expected) begin
|
||||
$display("%s:%0d: Failed: element [%0d] != %0d (%0d)",
|
||||
fname, lineno, idx, expected, q_tst[idx]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
passed = 1'b1;
|
||||
|
||||
q_tst.delete(0); // Warning: skip delete on an empty queue
|
||||
check_size(0, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 0, `__FILE__, `__LINE__);
|
||||
|
||||
elem = q_tst.pop_front(); // Warning: cannot pop_front() an empty queue
|
||||
if (elem !== 'X) begin
|
||||
$display("Failed: pop_front() != 'X (%0d)", elem);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
elem = q_tst.pop_back(); // Warning: cannot pop_back() an empty queue
|
||||
if (elem !== 'X) begin
|
||||
$display("Failed: pop_back() != 'X (%0d)", elem);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
q_tst.push_back(2);
|
||||
q_tst.push_front(1);
|
||||
q_tst.push_back(3);
|
||||
q_tst.push_back(100);
|
||||
q_tst.delete(3); // Should $ work here?
|
||||
q_tst.delete(3); // Warning: skip an out of range delete()
|
||||
q_tst.delete(-1); // Warning: skip delete with negative index
|
||||
q_tst.delete('X); // Warning: skip delete with undefined index
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
|
||||
if (q_tst[0] !== 1) begin
|
||||
$display("Failed: element [0] != 1 (%0d)", q_tst[0]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
if (q_tst[1] !== 2) begin
|
||||
$display("Failed: element [1] != 2 (%0d)", q_tst[1]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
if (q_tst[2] !== 3) begin
|
||||
$display("Failed: element [2] != 3 (%0d)", q_tst[2]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
if (q_tst[3] !== 'X) begin
|
||||
$display("Failed: element [3] != 'X (%0d)", q_tst[3]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
if (q_tst[-1] !== 'X) begin
|
||||
$display("Failed: element [-1] != 'X (%0d)", q_tst[-1]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
if (q_tst['X] !== 'X) begin
|
||||
$display("Failed: element ['X] != 'X (%0d)", q_tst['X]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
check_idx_value(-1, 0.0, `__FILE__, `__LINE__);
|
||||
check_idx_value('X, 0.0, `__FILE__, `__LINE__);
|
||||
|
||||
elem = q_tst.pop_front();
|
||||
if (elem !== 1) begin
|
||||
$display("Failed: element pop_front() != 1 (%0d)", elem);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
elem = q_tst.pop_back();
|
||||
if (elem !== 3) begin
|
||||
$display("Failed: element pop_back() != 3 (%0d)", elem);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
check_size(1, `__FILE__, `__LINE__);
|
||||
|
||||
if ((q_tst[0] !== q_tst[$]) || (q_tst[0] !== 2)) begin
|
||||
$display("Failed: q_tst[0](%0d) != q_tst[$](%0d) != 2",
|
||||
q_tst[0], q_tst[$]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
|
||||
q_tst.delete();
|
||||
|
||||
check_size(0, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst.push_front(5);
|
||||
q_tst.push_front(100);
|
||||
q_tst.push_back(100);
|
||||
elem = q_tst.pop_back;
|
||||
elem = q_tst.pop_front;
|
||||
|
||||
check_size(1, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 5, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst[0] = 1;
|
||||
q_tst[1] = 3;
|
||||
q_tst[1] = 2;
|
||||
q_tst[2] = 3;
|
||||
q_tst[-1] = 10; // Warning: will not be added (negative index)
|
||||
q_tst['X] = 10; // Warning: will not be added (undefined index)
|
||||
q_tst[4] = 10; // Warning: will not be added (out of range index)
|
||||
|
||||
idx = -1;
|
||||
q_tst[idx] = 10; // Warning: will not be added (negative index)
|
||||
idx = 3'b0x1;
|
||||
q_tst[idx] = 10; // Warning: will not be added (undefined index)
|
||||
idx = 4;
|
||||
q_tst[idx] = 10; // Warning: will not be added (out of range index)
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 1, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 3, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst.delete();
|
||||
q_tst[0] = 2;
|
||||
q_tst.insert(1, 4);
|
||||
q_tst.insert(0, 1);
|
||||
q_tst.insert(2, 3);
|
||||
q_tst.insert(-1, 10); // Warning: will not be added (negative index)
|
||||
q_tst.insert('X, 10); // Warning: will not be added (undefined index)
|
||||
q_tst.insert(5, 10); // Warning: will not be added (out of range index)
|
||||
|
||||
check_size(4, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 1, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 3, `__FILE__, `__LINE__);
|
||||
check_idx_value(3, 4, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst = '{3, 2, 1};
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 3, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 1, `__FILE__, `__LINE__);
|
||||
|
||||
q_tmp = '{1, 2};
|
||||
q_tst = q_tmp;
|
||||
q_tmp[0] = 3;
|
||||
q_tmp[2] = 1;
|
||||
|
||||
check_size(2, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 1.0, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2.0, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst[2] = 3;
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 3, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst = {1, 2};
|
||||
check_size(2, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 1, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst = '{};
|
||||
|
||||
check_size(0, `__FILE__, `__LINE__);
|
||||
|
||||
if (passed) $display("PASSED");
|
||||
|
||||
end
|
||||
endmodule : top
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
module top;
|
||||
typedef reg [4:0] T1;
|
||||
typedef T1 [7:0] T2;
|
||||
|
||||
T2 q_tst [$:2];
|
||||
T2 q_tmp [$];
|
||||
bit passed;
|
||||
|
||||
task automatic check_size(integer size,
|
||||
string fname,
|
||||
integer lineno);
|
||||
if (q_tst.size !== size) begin
|
||||
$display("%s:%0d: Failed: queue size != %0d (%0d)",
|
||||
fname, lineno, size, q_tst.size);
|
||||
passed = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic check_idx_value(integer idx,
|
||||
T2 expected,
|
||||
string fname,
|
||||
integer lineno);
|
||||
if (q_tst[idx] != expected) begin
|
||||
$display("%s:%0d: Failed: element [%0d] != %0d (%0d)",
|
||||
fname, lineno, idx, expected, q_tst[idx]);
|
||||
passed = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
passed = 1'b1;
|
||||
|
||||
check_size(0, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst.push_back(2);
|
||||
q_tst.push_front(1);
|
||||
q_tst.push_back(3);
|
||||
q_tst.push_back(100); // Warning: item not added.
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 1, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 3, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst.push_front(5); // Warning: back item removed.
|
||||
q_tst[3] = 3; // Warning: item not added.
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 5, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 1, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 2, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst.insert(3, 10); // Warning: item not added.
|
||||
q_tst.insert(1, 2); // Warning: back item removed.
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 5, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 1, `__FILE__, `__LINE__);
|
||||
|
||||
q_tst = '{1, 2, 3, 4}; // Warning: items not added.
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 1, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 2, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 3, `__FILE__, `__LINE__);
|
||||
|
||||
q_tmp = '{4, 3, 2, 1};
|
||||
q_tst = q_tmp; // Warning not all items copied
|
||||
q_tmp[0] = 5;
|
||||
|
||||
check_size(3, `__FILE__, `__LINE__);
|
||||
check_idx_value(0, 4, `__FILE__, `__LINE__);
|
||||
check_idx_value(1, 3, `__FILE__, `__LINE__);
|
||||
check_idx_value(2, 2, `__FILE__, `__LINE__);
|
||||
|
||||
if (passed) $display("PASSED");
|
||||
|
||||
end
|
||||
endmodule : top
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
module top;
|
||||
typedef reg [4:0] T1;
|
||||
typedef T1 [7:0] T2;
|
||||
|
||||
int bound = 2;
|
||||
T2 q_vec [$];
|
||||
T2 q_vec1 [$:-1];
|
||||
T2 q_vec2 [$:'X];
|
||||
T2 q_vec3 [$:bound];
|
||||
|
||||
initial begin
|
||||
$display(q_vec.size(1));
|
||||
$display(q_vec.pop_front(1));
|
||||
$display(q_vec.pop_back(1));
|
||||
q_vec.push_front(1, 2);
|
||||
q_vec.push_back(1, 2);
|
||||
$display("FAILED");
|
||||
end
|
||||
endmodule : top
|
||||
|
|
@ -43,7 +43,8 @@ module unp_array_typedef();
|
|||
real_unparray real_unparr;
|
||||
int_darray int_darr;
|
||||
int_unparray int_unparr;
|
||||
word_darray word_darr;
|
||||
// TODO at the moment dynamic arrays of struct are not supported
|
||||
// word_darray word_darr;
|
||||
word_unparray word_unparr;
|
||||
|
||||
initial begin
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ sv_darray4 normal,-g2009 ivltests
|
|||
sv_darray5 normal,-g2009 ivltests
|
||||
sv_darray5b normal,-g2009 ivltests
|
||||
sv_darray6 normal,-g2009 ivltests
|
||||
sv_darray7 normal,-g2009 ivltests
|
||||
sv_darray_args1 normal,-g2009 ivltests
|
||||
sv_darray_args2 normal,-g2009 ivltests
|
||||
sv_darray_args2b normal,-g2009 ivltests
|
||||
|
|
@ -514,6 +515,9 @@ sv_port_default14 CE,-g2009 ivltests
|
|||
sv_queue1 normal,-g2009 ivltests
|
||||
sv_queue2 normal,-g2009 ivltests
|
||||
sv_queue3 normal,-g2009 ivltests
|
||||
sv_queue_parray normal,-g2009,-pfileline=1 ivltests gold=sv_queue_parray.gold
|
||||
sv_queue_parray_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_parray_bounded.gold
|
||||
sv_queue_parray_fail CE,-g2009 ivltests gold=sv_queue_parray_fail.gold
|
||||
sv_queue_real normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real.gold
|
||||
sv_queue_real_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real_bounded.gold
|
||||
sv_queue_real_fail CE,-g2009 ivltests gold=sv_queue_real_fail.gold
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ sv_darray4 CE,-g2009,-pallowsigned=1 ivltests
|
|||
sv_darray5 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_darray5b CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_darray6 CE,-g2009,-pallowsigned=1 ivltests # Also string
|
||||
sv_darray7 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_darray_args1 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_darray_args2 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_darray_args2b CE,-g2009,-pallowsigned=1 ivltests
|
||||
|
|
@ -588,6 +589,9 @@ sv_queue_string_fail CE,-g2009 ivltests
|
|||
sv_queue_vec CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_queue_vec_bounded CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_queue_vec_fail CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_queue_parray CE,-g2009, ivltests
|
||||
sv_queue_parray_bounded CE,-g2009, ivltests
|
||||
sv_queue_parray_fail CE,-g2009, ivltests
|
||||
test_forgen CE,-g2009,ivltests/forgen.vhd ivltests
|
||||
test_gxor CE,-g2009,-pallowsigned=1,ivltests/gxor.vhd ivltests
|
||||
test_varray1 CE,-g2009,-pallowsigned=1,ivltests/varray1.vhd ivltests
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "nettypes.h"
|
||||
# include "netscalar.h"
|
||||
# include "netvector.h"
|
||||
|
||||
ivl_type_t make_ivl_type(ivl_variable_type_t vt,
|
||||
const std::vector<netrange_t>&packed_dimensions,
|
||||
bool signed_flag, bool isint_flag)
|
||||
{
|
||||
netvector_t*vec;
|
||||
|
||||
if (packed_dimensions.size() > 0) {
|
||||
vec = new netvector_t(packed_dimensions, vt);
|
||||
vec->set_signed(signed_flag);
|
||||
return vec;
|
||||
}
|
||||
|
||||
switch (vt) {
|
||||
case IVL_VT_REAL:
|
||||
return &netreal_t::type_real;
|
||||
case IVL_VT_STRING:
|
||||
return &netstring_t::type_string;
|
||||
default:
|
||||
vec = new netvector_t(packed_dimensions, vt);
|
||||
vec->set_signed(signed_flag);
|
||||
vec->set_isint(isint_flag);
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,18 +28,7 @@ void darray_new(ivl_type_t element_type, unsigned size_reg)
|
|||
ivl_variable_type_t type = ivl_type_base(element_type);
|
||||
|
||||
if ((type == IVL_VT_BOOL) || (type == IVL_VT_LOGIC)) {
|
||||
// bool objects are vectorable, but for now only support
|
||||
// a single dimensions.
|
||||
assert(ivl_type_packed_dimensions(element_type) <= 1);
|
||||
if (ivl_type_packed_dimensions(element_type) == 1) {
|
||||
int msb, lsb;
|
||||
msb = ivl_type_packed_msb(element_type, 0);
|
||||
lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
wid = msb>=lsb ? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
} else {
|
||||
wid = 1;
|
||||
}
|
||||
wid = width_of_packed_type(element_type);
|
||||
signed_char = ivl_type_signed(element_type) ? "s" : "";
|
||||
} else {
|
||||
// REAL or STRING objects are not packable.
|
||||
|
|
|
|||
Loading…
Reference in New Issue