Merge pull request #953 from larsclausen/assign-pattern-uarray
Add initial support for array assignment patterns
This commit is contained in:
commit
df8ac73bba
9
PExpr.h
9
PExpr.h
|
|
@ -222,8 +222,13 @@ class PEAssignPattern : public PExpr {
|
||||||
NetExpr* elaborate_expr_struct_(Design *des, NetScope *scope,
|
NetExpr* elaborate_expr_struct_(Design *des, NetScope *scope,
|
||||||
const netstruct_t *struct_type,
|
const netstruct_t *struct_type,
|
||||||
bool need_const) const;
|
bool need_const) const;
|
||||||
NetExpr* elaborate_expr_darray_(Design *des, NetScope *scope,
|
NetExpr* elaborate_expr_array_(Design *des, NetScope *scope,
|
||||||
const netdarray_t *array_type,
|
const netarray_t *array_type,
|
||||||
|
bool need_const, bool up) const;
|
||||||
|
NetExpr* elaborate_expr_uarray_(Design *des, NetScope *scope,
|
||||||
|
const netuarray_t *uarray_type,
|
||||||
|
const std::vector<netrange_t> &dims,
|
||||||
|
unsigned int cur_dim,
|
||||||
bool need_const) const;
|
bool need_const) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
97
elab_expr.cc
97
elab_expr.cc
|
|
@ -142,6 +142,11 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the target is an unpacked array we want full type checking,
|
||||||
|
// regardless of the base type of the array.
|
||||||
|
if (dynamic_cast<const netuarray_t *>(lv_net_type))
|
||||||
|
typed_elab = true;
|
||||||
|
|
||||||
// Special case, PEAssignPattern is context dependend on the type and
|
// Special case, PEAssignPattern is context dependend on the type and
|
||||||
// always uses the typed elaboration
|
// always uses the typed elaboration
|
||||||
if (dynamic_cast<PEAssignPattern*>(expr))
|
if (dynamic_cast<PEAssignPattern*>(expr))
|
||||||
|
|
@ -236,7 +241,13 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
|
||||||
bool need_const = NEED_CONST & flags;
|
bool need_const = NEED_CONST & flags;
|
||||||
|
|
||||||
if (auto darray_type = dynamic_cast<const netdarray_t*>(ntype))
|
if (auto darray_type = dynamic_cast<const netdarray_t*>(ntype))
|
||||||
return elaborate_expr_darray_(des, scope, darray_type, need_const);
|
return elaborate_expr_array_(des, scope, darray_type, need_const, true);
|
||||||
|
|
||||||
|
if (auto uarray_type = dynamic_cast<const netuarray_t*>(ntype)) {
|
||||||
|
return elaborate_expr_uarray_(des, scope, uarray_type,
|
||||||
|
uarray_type->static_dimensions(), 0,
|
||||||
|
need_const);
|
||||||
|
}
|
||||||
|
|
||||||
if (auto parray_type = dynamic_cast<const netparray_t*>(ntype)) {
|
if (auto parray_type = dynamic_cast<const netparray_t*>(ntype)) {
|
||||||
return elaborate_expr_packed_(des, scope, parray_type->base_type(),
|
return elaborate_expr_packed_(des, scope, parray_type->base_type(),
|
||||||
|
|
@ -265,9 +276,9 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PEAssignPattern::elaborate_expr_darray_(Design *des, NetScope *scope,
|
NetExpr* PEAssignPattern::elaborate_expr_array_(Design *des, NetScope *scope,
|
||||||
const netdarray_t *array_type,
|
const netarray_t *array_type,
|
||||||
bool need_const) const
|
bool need_const, bool up) const
|
||||||
{
|
{
|
||||||
// Special case: If this is an empty pattern (i.e. '{}) then convert
|
// Special case: If this is an empty pattern (i.e. '{}) then convert
|
||||||
// this to a null handle. Internally, Icarus Verilog uses this to
|
// this to a null handle. Internally, Icarus Verilog uses this to
|
||||||
|
|
@ -283,10 +294,14 @@ NetExpr* PEAssignPattern::elaborate_expr_darray_(Design *des, NetScope *scope,
|
||||||
// element_type expressions.
|
// element_type expressions.
|
||||||
ivl_type_t elem_type = array_type->element_type();
|
ivl_type_t elem_type = array_type->element_type();
|
||||||
vector<NetExpr*> elem_exprs (parms_.size());
|
vector<NetExpr*> elem_exprs (parms_.size());
|
||||||
|
size_t elem_idx = up ? 0 : parms_.size() - 1;
|
||||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||||
NetExpr*tmp = elaborate_rval_expr(des, scope, elem_type,
|
elem_exprs[elem_idx] = elaborate_rval_expr(des, scope, elem_type,
|
||||||
parms_[idx], need_const);
|
parms_[idx], need_const);
|
||||||
elem_exprs[idx] = tmp;
|
if (up)
|
||||||
|
elem_idx++;
|
||||||
|
else
|
||||||
|
elem_idx--;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs);
|
NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs);
|
||||||
|
|
@ -294,6 +309,74 @@ NetExpr* PEAssignPattern::elaborate_expr_darray_(Design *des, NetScope *scope,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetExpr* PEAssignPattern::elaborate_expr_uarray_(Design *des, NetScope *scope,
|
||||||
|
const netuarray_t *uarray_type,
|
||||||
|
const std::vector<netrange_t> &dims,
|
||||||
|
unsigned int cur_dim,
|
||||||
|
bool need_const) const
|
||||||
|
{
|
||||||
|
if (dims.size() <= cur_dim)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (dims[cur_dim].width() != parms_.size()) {
|
||||||
|
cerr << get_fileline() << ": error: Unpacked array assignment pattern expects "
|
||||||
|
<< dims[cur_dim].width() << " element(s) in this context.\n"
|
||||||
|
<< get_fileline() << ": : Found "
|
||||||
|
<< parms_.size() << " element(s)." << endl;
|
||||||
|
des->errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool up = dims[cur_dim].get_msb() < dims[cur_dim].get_lsb();
|
||||||
|
if (cur_dim == dims.size() - 1) {
|
||||||
|
return elaborate_expr_array_(des, scope, uarray_type, need_const, up);
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_dim++;
|
||||||
|
vector<NetExpr*> elem_exprs(parms_.size());
|
||||||
|
size_t elem_idx = up ? 0 : parms_.size() - 1;
|
||||||
|
for (size_t idx = 0; idx < parms_.size(); idx++) {
|
||||||
|
NetExpr *expr = nullptr;
|
||||||
|
// Handle nested assignment patterns as a special case. We do not
|
||||||
|
// have a good way of passing the inner dimensions through the
|
||||||
|
// generic elaborate_expr() API and assigment patterns is the only
|
||||||
|
// place where we need it.
|
||||||
|
if (auto ap = dynamic_cast<PEAssignPattern*>(parms_[idx])) {
|
||||||
|
expr = ap->elaborate_expr_uarray_(des, scope, uarray_type,
|
||||||
|
dims, cur_dim, need_const);
|
||||||
|
} else if (dynamic_cast<PEConcat*>(parms_[idx])) {
|
||||||
|
cerr << get_fileline() << ": sorry: "
|
||||||
|
<< "Array concatenation is not yet supported."
|
||||||
|
<< endl;
|
||||||
|
des->errors++;
|
||||||
|
} else if (dynamic_cast<PEIdent*>(parms_[idx])) {
|
||||||
|
// The only other thing that's allow in this
|
||||||
|
// context is an array slice or identifier.
|
||||||
|
cerr << get_fileline() << ": sorry: "
|
||||||
|
<< "Procedural assignment of array or array slice"
|
||||||
|
<< " is not yet supported." << endl;
|
||||||
|
des->errors++;
|
||||||
|
} else if (parms_[idx]) {
|
||||||
|
cerr << get_fileline() << ": error: Expression "
|
||||||
|
<< *parms_[idx]
|
||||||
|
<< " is not compatible with this context."
|
||||||
|
<< " Expected array or array-like expression."
|
||||||
|
<< endl;
|
||||||
|
des->errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
elem_exprs[elem_idx] = expr;
|
||||||
|
|
||||||
|
if (up)
|
||||||
|
elem_idx++;
|
||||||
|
else
|
||||||
|
elem_idx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetEArrayPattern *res = new NetEArrayPattern(uarray_type, elem_exprs);
|
||||||
|
res->set_line(*this);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
NetExpr* PEAssignPattern::elaborate_expr_packed_(Design *des, NetScope *scope,
|
NetExpr* PEAssignPattern::elaborate_expr_packed_(Design *des, NetScope *scope,
|
||||||
ivl_variable_type_t base_type,
|
ivl_variable_type_t base_type,
|
||||||
unsigned int width,
|
unsigned int width,
|
||||||
|
|
|
||||||
|
|
@ -242,8 +242,12 @@ NetAssign_*PEIdent::elaborate_lval_var_(Design *des, NetScope *scope,
|
||||||
// is less than the array dimensions (unpacked).
|
// is less than the array dimensions (unpacked).
|
||||||
if (reg->unpacked_dimensions() > name_tail.index.size()) {
|
if (reg->unpacked_dimensions() > name_tail.index.size()) {
|
||||||
if (gn_system_verilog()) {
|
if (gn_system_verilog()) {
|
||||||
cerr << get_fileline() << ": sorry: Assignment to an entire"
|
if (name_tail.index.empty()) {
|
||||||
" array or to an array slice is not yet supported."
|
NetAssign_*lv = new NetAssign_(reg);
|
||||||
|
return lv;
|
||||||
|
}
|
||||||
|
cerr << get_fileline() << ": sorry: Assignment to an "
|
||||||
|
" array slice is not yet supported."
|
||||||
<< endl;
|
<< endl;
|
||||||
} else {
|
} else {
|
||||||
cerr << get_fileline() << ": error: Assignment to an entire"
|
cerr << get_fileline() << ": error: Assignment to an entire"
|
||||||
|
|
|
||||||
19
elaborate.cc
19
elaborate.cc
|
|
@ -251,25 +251,29 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||||
NetNet *elaborate_unpacked_array(Design *des, NetScope *scope, const LineInfo &loc,
|
NetNet *elaborate_unpacked_array(Design *des, NetScope *scope, const LineInfo &loc,
|
||||||
const NetNet *lval, PExpr *expr)
|
const NetNet *lval, PExpr *expr)
|
||||||
{
|
{
|
||||||
|
NetNet *expr_net;
|
||||||
PEIdent* ident = dynamic_cast<PEIdent*> (expr);
|
PEIdent* ident = dynamic_cast<PEIdent*> (expr);
|
||||||
if (!ident) {
|
if (!ident) {
|
||||||
des->errors++;
|
|
||||||
if (dynamic_cast<PEConcat*> (expr)) {
|
if (dynamic_cast<PEConcat*> (expr)) {
|
||||||
cout << loc.get_fileline() << ": sorry: Continuous assignment"
|
cout << loc.get_fileline() << ": sorry: Continuous assignment"
|
||||||
<< " of array concatenation is not yet supported."
|
<< " of array concatenation is not yet supported."
|
||||||
<< endl;
|
<< endl;
|
||||||
|
des->errors++;
|
||||||
|
return nullptr;
|
||||||
} else if (dynamic_cast<PEAssignPattern*> (expr)) {
|
} else if (dynamic_cast<PEAssignPattern*> (expr)) {
|
||||||
cout << loc.get_fileline() << ": sorry: Continuous assignment"
|
auto net_expr = elaborate_rval_expr(des, scope, lval->array_type(), expr);
|
||||||
<< " of assignment pattern is not yet supported." << endl;
|
expr_net = net_expr->synthesize(des, scope, net_expr);
|
||||||
} else {
|
} else {
|
||||||
cout << loc.get_fileline() << ": error: Can not assign"
|
cout << loc.get_fileline() << ": error: Can not assign"
|
||||||
<< " non-array expression `" << *expr << "` to array."
|
<< " non-array expression `" << *expr << "` to array."
|
||||||
<< endl;
|
<< endl;
|
||||||
|
des->errors++;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return nullptr;
|
} else {
|
||||||
|
expr_net = ident->elaborate_unpacked_net(des, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetNet *expr_net = ident->elaborate_unpacked_net(des, scope);
|
|
||||||
if (!expr_net)
|
if (!expr_net)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
@ -2642,8 +2646,9 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||||
<< "lv->word() = <nil>" << endl;
|
<< "lv->word() = <nil>" << endl;
|
||||||
}
|
}
|
||||||
ivl_assert(*this, lv->word());
|
ivl_type_t use_lv_type = lv_net_type;
|
||||||
ivl_type_t use_lv_type = utype->element_type();
|
if (lv->word())
|
||||||
|
use_lv_type = utype->element_type();
|
||||||
|
|
||||||
ivl_assert(*this, use_lv_type);
|
ivl_assert(*this, use_lv_type);
|
||||||
rv = elaborate_rval_(des, scope, use_lv_type);
|
rv = elaborate_rval_(des, scope, use_lv_type);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "netvector.h"
|
# include "netvector.h"
|
||||||
|
# include "netparray.h"
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
|
@ -813,6 +814,58 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
return osig;
|
return osig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetNet *NetEArrayPattern::synthesize(Design *des, NetScope *scope, NetExpr *root)
|
||||||
|
{
|
||||||
|
const netsarray_t *array_type = dynamic_cast<const netsarray_t *>(net_type());
|
||||||
|
ivl_assert(*this, array_type);
|
||||||
|
|
||||||
|
if (items_.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
bool failed = false;
|
||||||
|
|
||||||
|
std::unique_ptr<NetNet*[]> nets(new NetNet*[items_.size()]);
|
||||||
|
for (unsigned int idx = 0; idx < items_.size(); idx++) {
|
||||||
|
if (!items_[idx]) {
|
||||||
|
failed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nets[idx] = items_[idx]->synthesize(des, scope, root);
|
||||||
|
if (!nets[idx])
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Infer which dimension we are in for nested assignment patterns based on
|
||||||
|
// the dimensions of the element.
|
||||||
|
size_t dim = nets[0]->unpacked_dims().size() + 1;
|
||||||
|
const auto &type_dims = array_type->static_dimensions();
|
||||||
|
|
||||||
|
if (dim > type_dims.size())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::list<netrange_t> dims(type_dims.end() - dim, type_dims.end());
|
||||||
|
|
||||||
|
if (dims.front().width() != items_.size())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
perm_string path = scope->local_symbol();
|
||||||
|
NetNet *osig = new NetNet(scope, path, NetNet::IMPLICIT, dims,
|
||||||
|
array_type->element_type());
|
||||||
|
osig->set_line(*this);
|
||||||
|
osig->local_flag(true);
|
||||||
|
|
||||||
|
unsigned int opin = 0;
|
||||||
|
for (unsigned int idx = 0; idx < items_.size(); idx++) {
|
||||||
|
for (unsigned int net_pin = 0; net_pin < nets[idx]->pin_count(); net_pin++)
|
||||||
|
connect(osig->pin(opin++), nets[idx]->pin(net_pin));
|
||||||
|
}
|
||||||
|
|
||||||
|
return osig;
|
||||||
|
}
|
||||||
|
|
||||||
NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*)
|
NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*)
|
||||||
{
|
{
|
||||||
perm_string path = scope->local_symbol();
|
perm_string path = scope->local_symbol();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Check that procedural assignment of unpacked array assignment patterns is
|
||||||
|
// supported and a entries are assigned in the right order.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed;
|
||||||
|
|
||||||
|
`define check(val, exp) do \
|
||||||
|
if (val !== exp) begin \
|
||||||
|
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
int x[3:0];
|
||||||
|
int y[0:3];
|
||||||
|
int z[4];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = '{1'b1, 1 + 1, 3.3, "TEST"};
|
||||||
|
y = '{1'b1, 1 + 1, 3.3, "TEST"};
|
||||||
|
z = '{1'b1, 1 + 1, 3.3, "TEST"};
|
||||||
|
|
||||||
|
`check(x[0], 1413829460);
|
||||||
|
`check(x[1], 3);
|
||||||
|
`check(x[2], 2);
|
||||||
|
`check(x[3], 1);
|
||||||
|
|
||||||
|
`check(y[0], 1);
|
||||||
|
`check(y[1], 2);
|
||||||
|
`check(y[2], 3);
|
||||||
|
`check(y[3], 1413829460);
|
||||||
|
|
||||||
|
`check(z[0], 1);
|
||||||
|
`check(z[1], 2);
|
||||||
|
`check(z[2], 3);
|
||||||
|
`check(z[3], 1413829460);
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Check that procedural assignment of unpacked array assignment patterns to
|
||||||
|
// multi-dimensional arrays is supported and entries are assigned in the right
|
||||||
|
// order.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed;
|
||||||
|
|
||||||
|
`define check(val, exp) do \
|
||||||
|
if (val !== exp) begin \
|
||||||
|
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
int x[1:0][1:0];
|
||||||
|
int y[1:0][0:1];
|
||||||
|
int z[2][2];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
y = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
z = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
|
||||||
|
`check(x[0][0], 1413829460);
|
||||||
|
`check(x[0][1], 3);
|
||||||
|
`check(x[1][0], 2);
|
||||||
|
`check(x[1][1], 1);
|
||||||
|
|
||||||
|
`check(y[0][0], 3);
|
||||||
|
`check(y[0][1], 1413829460);
|
||||||
|
`check(y[1][0], 1);
|
||||||
|
`check(y[1][1], 2);
|
||||||
|
|
||||||
|
`check(z[0][0], 1);
|
||||||
|
`check(z[0][1], 2);
|
||||||
|
`check(z[1][0], 3);
|
||||||
|
`check(z[1][1], 1413829460);
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Check that continuous assignment of unpacked array assignment patterns is
|
||||||
|
// supported and entries are assigned in the right order.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed;
|
||||||
|
|
||||||
|
`define check(val, exp) do \
|
||||||
|
if (val !== exp) begin \
|
||||||
|
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
int x[3:0];
|
||||||
|
int y[0:3];
|
||||||
|
int z[4];
|
||||||
|
|
||||||
|
assign x = '{1'b1, 1 + 1, 3.3, "TEST"};
|
||||||
|
assign y = '{1'b1, 1 + 1, 3.3, "TEST"};
|
||||||
|
assign z = '{1'b1, 1 + 1, 3.3, "TEST"};
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`check(x[0], 1413829460);
|
||||||
|
`check(x[1], 3);
|
||||||
|
`check(x[2], 2);
|
||||||
|
`check(x[3], 1);
|
||||||
|
|
||||||
|
`check(y[0], 1);
|
||||||
|
`check(y[1], 2);
|
||||||
|
`check(y[2], 3);
|
||||||
|
`check(y[3], 1413829460);
|
||||||
|
|
||||||
|
`check(z[0], 1);
|
||||||
|
`check(z[1], 2);
|
||||||
|
`check(z[2], 3);
|
||||||
|
`check(z[3], 1413829460);
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Check that continuous assignment of unpacked array assignment patterns to
|
||||||
|
// multi-dimensional arrays is supported and entries are assigned in the right
|
||||||
|
// order.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed;
|
||||||
|
|
||||||
|
`define check(val, exp) do \
|
||||||
|
if (val !== exp) begin \
|
||||||
|
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
int x[1:0][1:0];
|
||||||
|
int y[1:0][0:1];
|
||||||
|
int z[2][2];
|
||||||
|
|
||||||
|
assign x = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
assign y = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
assign z = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`check(x[0][0], 1413829460);
|
||||||
|
`check(x[0][1], 3);
|
||||||
|
`check(x[1][0], 2);
|
||||||
|
`check(x[1][1], 1);
|
||||||
|
|
||||||
|
`check(y[0][0], 3);
|
||||||
|
`check(y[0][1], 1413829460);
|
||||||
|
`check(y[1][0], 1);
|
||||||
|
`check(y[1][1], 2);
|
||||||
|
|
||||||
|
`check(z[0][0], 1);
|
||||||
|
`check(z[0][1], 2);
|
||||||
|
`check(z[1][0], 3);
|
||||||
|
`check(z[1][1], 1413829460);
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Check that procedural assignment of unpacked real array assignment patterns
|
||||||
|
// to multi-dimensional arrays is supported and entries are assigned in the
|
||||||
|
// right order.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed;
|
||||||
|
|
||||||
|
`define check(val, exp) do \
|
||||||
|
if (val != exp) begin \
|
||||||
|
$display("FAILED(%0d). '%s' expected %0f, got %0f", `__LINE__, `"val`", exp, val); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
real x[1:0][1:0];
|
||||||
|
real y[1:0][0:1];
|
||||||
|
real z[2][2];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
y = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
z = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}};
|
||||||
|
|
||||||
|
`check(x[0][0], 1413829460.0);
|
||||||
|
`check(x[0][1], 3.3);
|
||||||
|
`check(x[1][0], 2.0);
|
||||||
|
`check(x[1][1], 1.0);
|
||||||
|
|
||||||
|
`check(y[0][1], 1413829460.0);
|
||||||
|
`check(y[0][0], 3.3);
|
||||||
|
`check(y[1][1], 2.0);
|
||||||
|
`check(y[1][0], 1.0);
|
||||||
|
|
||||||
|
`check(z[0][0], 1.0);
|
||||||
|
`check(z[0][1], 2.0);
|
||||||
|
`check(z[1][0], 3.3);
|
||||||
|
`check(z[1][1], 1413829460.0);
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Check that procedural assignment of unpacked string array assignment patterns
|
||||||
|
// to multi-dimensional arrays is supported and entries are assigned in the
|
||||||
|
// right order.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed;
|
||||||
|
|
||||||
|
`define check(val, exp) do \
|
||||||
|
if (val != exp) begin \
|
||||||
|
$display("FAILED(%0d). '%s' expected %s, got %s", `__LINE__, `"val`", exp, val); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
string x[1:0][1:0];
|
||||||
|
string y[1:0][0:1];
|
||||||
|
string z[2][2];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = '{'{"Hello", "World"}, '{"Array", "Pattern"}};
|
||||||
|
y = '{'{"Hello", "World"}, '{"Array", "Pattern"}};
|
||||||
|
z = '{'{"Hello", "World"}, '{"Array", "Pattern"}};
|
||||||
|
|
||||||
|
`check(x[0][0], "Pattern");
|
||||||
|
`check(x[0][1], "Array");
|
||||||
|
`check(x[1][0], "World");
|
||||||
|
`check(x[1][1], "Hello");
|
||||||
|
|
||||||
|
`check(y[0][0], "Array");
|
||||||
|
`check(y[0][1], "Pattern");
|
||||||
|
`check(y[1][0], "Hello");
|
||||||
|
`check(y[1][1], "World");
|
||||||
|
|
||||||
|
`check(z[0][0], "Hello");
|
||||||
|
`check(z[0][1], "World");
|
||||||
|
`check(z[1][0], "Array");
|
||||||
|
`check(z[1][1], "Pattern");
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Check that an unpacked array assignment pattern with too many elements
|
||||||
|
// results in an error.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
int x[1:0];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = '{1, 2, 3}; // Should fail, more elements in assignment pattern than
|
||||||
|
// array size.
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Check that an unpacked array assignment pattern with not enough elements
|
||||||
|
// results in an error.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
int x[1:0];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = '{1}; // Should fail, less elements in assignment pattern than array
|
||||||
|
// size.
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Check that trying to do a procedural assign of a scalar to an array results
|
||||||
|
// in an error.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
integer x[1:0];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x = 10; // Error, scalar assigned to array
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Check that trying to do a continuous assign of a scalar to an array results
|
||||||
|
// in an error.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
integer x[1:0];
|
||||||
|
|
||||||
|
assign x = 10; // Error, scalar assigned to array
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -45,6 +45,16 @@ pv_wr_fn_vec2 vvp_tests/pv_wr_fn_vec2.json
|
||||||
pv_wr_fn_vec4 vvp_tests/pv_wr_fn_vec4.json
|
pv_wr_fn_vec4 vvp_tests/pv_wr_fn_vec4.json
|
||||||
struct_packed_write_read vvp_tests/struct_packed_write_read.json
|
struct_packed_write_read vvp_tests/struct_packed_write_read.json
|
||||||
struct_packed_write_read2 vvp_tests/struct_packed_write_read2.json
|
struct_packed_write_read2 vvp_tests/struct_packed_write_read2.json
|
||||||
|
sv_ap_uarray1 vvp_tests/sv_ap_uarray1.json
|
||||||
|
sv_ap_uarray2 vvp_tests/sv_ap_uarray2.json
|
||||||
|
sv_ap_uarray3 vvp_tests/sv_ap_uarray3.json
|
||||||
|
sv_ap_uarray4 vvp_tests/sv_ap_uarray4.json
|
||||||
|
sv_ap_uarray5 vvp_tests/sv_ap_uarray5.json
|
||||||
|
sv_ap_uarray6 vvp_tests/sv_ap_uarray6.json
|
||||||
|
sv_ap_uarray_fail1 vvp_tests/sv_ap_uarray_fail1.json
|
||||||
|
sv_ap_uarray_fail2 vvp_tests/sv_ap_uarray_fail2.json
|
||||||
|
sv_array_assign_fail1 vvp_tests/sv_array_assign_fail1.json
|
||||||
|
sv_array_assign_fail2 vvp_tests/sv_array_assign_fail2.json
|
||||||
sv_array_cassign6 vvp_tests/sv_array_cassign6.json
|
sv_array_cassign6 vvp_tests/sv_array_cassign6.json
|
||||||
sv_array_cassign7 vvp_tests/sv_array_cassign7.json
|
sv_array_cassign7 vvp_tests/sv_array_cassign7.json
|
||||||
sv_foreach9 vvp_tests/sv_foreach9.json
|
sv_foreach9 vvp_tests/sv_foreach9.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_ap_uarray1.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_ap_uarray2.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_ap_uarray3.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_ap_uarray4.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_ap_uarray5.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "sv_ap_uarray6.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_ap_uarray_fail1.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_ap_uarray_fail2.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_array_assign_fail1.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "CE",
|
||||||
|
"source" : "sv_array_assign_fail2.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -149,11 +149,10 @@ ivl_type_t NetAssign_::net_type() const
|
||||||
} else {
|
} else {
|
||||||
ivl_assert(*this, sig_);
|
ivl_assert(*this, sig_);
|
||||||
|
|
||||||
// We don't have types for array signals yet.
|
|
||||||
if (sig_->unpacked_dimensions() && !word_)
|
if (sig_->unpacked_dimensions() && !word_)
|
||||||
return nullptr;
|
ntype = sig_->array_type();
|
||||||
|
else
|
||||||
ntype = sig_->net_type();
|
ntype = sig_->net_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!member_.nil()) {
|
if (!member_.nil()) {
|
||||||
|
|
|
||||||
|
|
@ -401,7 +401,13 @@ NetEProperty::NetEProperty(NetNet*net, size_t pidx, NetExpr*idx)
|
||||||
ivl_assert(*this, use_type);
|
ivl_assert(*this, use_type);
|
||||||
|
|
||||||
ivl_type_t prop_type = use_type->get_prop_type(pidx_);
|
ivl_type_t prop_type = use_type->get_prop_type(pidx_);
|
||||||
set_net_type(prop_type);
|
if (idx) {
|
||||||
|
auto array_type = dynamic_cast<const netarray_t*>(prop_type);
|
||||||
|
ivl_assert(*this, array_type);
|
||||||
|
set_net_type(array_type->element_type());
|
||||||
|
} else {
|
||||||
|
set_net_type(prop_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEProperty::~NetEProperty()
|
NetEProperty::~NetEProperty()
|
||||||
|
|
|
||||||
11
netlist.cc
11
netlist.cc
|
|
@ -598,6 +598,9 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
|
|
||||||
initialize_dir_();
|
initialize_dir_();
|
||||||
|
|
||||||
|
if (!unpacked_dims_.empty())
|
||||||
|
array_type_ = new netuarray_t(unpacked_dims_, net_type_);
|
||||||
|
|
||||||
s->add_signal(this);
|
s->add_signal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -733,6 +736,14 @@ const netclass_t* NetNet::class_type(void) const
|
||||||
return dynamic_cast<const netclass_t*> (net_type_);
|
return dynamic_cast<const netclass_t*> (net_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const netarray_t* NetNet::array_type() const
|
||||||
|
{
|
||||||
|
if (array_type_)
|
||||||
|
return array_type_;
|
||||||
|
|
||||||
|
return darray_type();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "depth" is the number of index expressions that the user is using
|
* "depth" is the number of index expressions that the user is using
|
||||||
* to index this identifier. So consider if Net was declared like so:
|
* to index this identifier. So consider if Net was declared like so:
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ struct enum_type_t;
|
||||||
class netclass_t;
|
class netclass_t;
|
||||||
class netdarray_t;
|
class netdarray_t;
|
||||||
class netparray_t;
|
class netparray_t;
|
||||||
|
class netuarray_t;
|
||||||
class netqueue_t;
|
class netqueue_t;
|
||||||
class netenum_t;
|
class netenum_t;
|
||||||
class netstruct_t;
|
class netstruct_t;
|
||||||
|
|
@ -709,6 +710,7 @@ class NetNet : public NetObj, public PortType {
|
||||||
const netdarray_t*darray_type(void) const;
|
const netdarray_t*darray_type(void) const;
|
||||||
const netqueue_t*queue_type(void) const;
|
const netqueue_t*queue_type(void) const;
|
||||||
const netclass_t*class_type(void) const;
|
const netclass_t*class_type(void) const;
|
||||||
|
const netarray_t*array_type(void) const;
|
||||||
|
|
||||||
/* Attach a discipline to the net. */
|
/* Attach a discipline to the net. */
|
||||||
ivl_discipline_t get_discipline() const;
|
ivl_discipline_t get_discipline() const;
|
||||||
|
|
@ -803,6 +805,7 @@ class NetNet : public NetObj, public PortType {
|
||||||
PortType port_type_ : 3;
|
PortType port_type_ : 3;
|
||||||
bool local_flag_: 1;
|
bool local_flag_: 1;
|
||||||
ivl_type_t net_type_;
|
ivl_type_t net_type_;
|
||||||
|
netuarray_t *array_type_ = nullptr;
|
||||||
ivl_discipline_t discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
std::vector<netrange_t> unpacked_dims_;
|
std::vector<netrange_t> unpacked_dims_;
|
||||||
|
|
@ -2104,6 +2107,7 @@ class NetEArrayPattern : public NetExpr {
|
||||||
NetEArrayPattern* dup_expr() const;
|
NetEArrayPattern* dup_expr() const;
|
||||||
NexusSet* nex_input(bool rem_out = true, bool always_sens = false,
|
NexusSet* nex_input(bool rem_out = true, bool always_sens = false,
|
||||||
bool nested_func = false) const;
|
bool nested_func = false) const;
|
||||||
|
NetNet* synthesize(Design *des, NetScope *scope, NetExpr *root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<NetExpr*> items_;
|
std::vector<NetExpr*> items_;
|
||||||
|
|
|
||||||
18
netmisc.cc
18
netmisc.cc
|
|
@ -986,7 +986,23 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
|
|
||||||
ivl_variable_type_t cast_type = ivl_type_base(lv_net_type);
|
ivl_variable_type_t cast_type = ivl_type_base(lv_net_type);
|
||||||
ivl_variable_type_t expr_type = tmp->expr_type();
|
ivl_variable_type_t expr_type = tmp->expr_type();
|
||||||
if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != expr_type)) {
|
|
||||||
|
bool compatible;
|
||||||
|
// For arrays we need strict type checking here. Long term strict type
|
||||||
|
// checking should be used for all expressions, but at the moment not
|
||||||
|
// all expressions do have a ivl_type_t attached to it.
|
||||||
|
if (dynamic_cast<const netuarray_t*>(lv_net_type)) {
|
||||||
|
if (tmp->net_type())
|
||||||
|
compatible = lv_net_type->type_compatible(tmp->net_type());
|
||||||
|
else
|
||||||
|
compatible = false;
|
||||||
|
} else if (cast_type == IVL_VT_NO_TYPE) {
|
||||||
|
compatible = true;
|
||||||
|
} else {
|
||||||
|
compatible = cast_type == expr_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compatible) {
|
||||||
// Catch some special cases.
|
// Catch some special cases.
|
||||||
switch (cast_type) {
|
switch (cast_type) {
|
||||||
case IVL_VT_DARRAY:
|
case IVL_VT_DARRAY:
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,58 @@ static void store_vec4_to_lval(ivl_statement_t net)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int draw_array_pattern(ivl_signal_t var, ivl_expr_t rval,
|
||||||
|
unsigned int array_idx)
|
||||||
|
{
|
||||||
|
ivl_type_t var_type = ivl_signal_net_type(var);
|
||||||
|
|
||||||
|
for (unsigned int idx = 0; idx < ivl_expr_parms(rval); idx += 1) {
|
||||||
|
ivl_expr_t expr = ivl_expr_parm(rval, idx);
|
||||||
|
|
||||||
|
switch (ivl_expr_type(expr)) {
|
||||||
|
case IVL_EX_ARRAY_PATTERN:
|
||||||
|
/* Flatten nested array patterns */
|
||||||
|
array_idx = draw_array_pattern(var, expr, array_idx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
switch (ivl_type_base(var_type)) {
|
||||||
|
case IVL_VT_BOOL:
|
||||||
|
case IVL_VT_LOGIC:
|
||||||
|
draw_eval_vec4(expr);
|
||||||
|
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", array_idx);
|
||||||
|
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||||
|
fprintf(vvp_out, " %%store/vec4a v%p, 3, 0;\n", var);
|
||||||
|
break;
|
||||||
|
case IVL_VT_REAL:
|
||||||
|
draw_eval_real(expr);
|
||||||
|
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", array_idx);
|
||||||
|
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||||
|
fprintf(vvp_out, " %%store/reala v%p, 3;\n", var);
|
||||||
|
break;
|
||||||
|
case IVL_VT_STRING:
|
||||||
|
draw_eval_string(expr);
|
||||||
|
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", array_idx);
|
||||||
|
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||||
|
fprintf(vvp_out, " %%store/stra v%p, 3;\n", var);
|
||||||
|
break;
|
||||||
|
case IVL_VT_CLASS:
|
||||||
|
draw_eval_object(expr);
|
||||||
|
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", array_idx);
|
||||||
|
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||||
|
fprintf(vvp_out, " %%store/obja v%p, 3;\n", var);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
array_idx++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_idx;
|
||||||
|
}
|
||||||
|
|
||||||
static int show_stmt_assign_vector(ivl_statement_t net)
|
static int show_stmt_assign_vector(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
ivl_expr_t rval = ivl_stmt_rval(net);
|
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||||
|
|
@ -498,6 +550,13 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||||
struct vec_slice_info*slices = 0;
|
struct vec_slice_info*slices = 0;
|
||||||
int idx_reg;
|
int idx_reg;
|
||||||
|
|
||||||
|
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
||||||
|
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
||||||
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
|
draw_array_pattern(sig, rval, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If this is a compressed assignment, then get the contents
|
/* If this is a compressed assignment, then get the contents
|
||||||
of the l-value. We need these values as part of the r-value
|
of the l-value. We need these values as part of the r-value
|
||||||
calculation. */
|
calculation. */
|
||||||
|
|
@ -791,6 +850,13 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
assert(ivl_stmt_lvals(net) == 1);
|
assert(ivl_stmt_lvals(net) == 1);
|
||||||
lval = ivl_stmt_lval(net, 0);
|
lval = ivl_stmt_lval(net, 0);
|
||||||
|
|
||||||
|
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||||
|
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
||||||
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
|
draw_array_pattern(sig, rval, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If this is a compressed assignment, then get the contents
|
/* If this is a compressed assignment, then get the contents
|
||||||
of the l-value. We need this value as part of the r-value
|
of the l-value. We need this value as part of the r-value
|
||||||
calculation. */
|
calculation. */
|
||||||
|
|
@ -800,7 +866,7 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
get_real_from_lval(lval, slice);
|
get_real_from_lval(lval, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_eval_real(ivl_stmt_rval(net));
|
draw_eval_real(rval);
|
||||||
|
|
||||||
switch (ivl_stmt_opcode(net)) {
|
switch (ivl_stmt_opcode(net)) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -850,6 +916,11 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
|
||||||
assert(ivl_stmt_lvals(net) == 1);
|
assert(ivl_stmt_lvals(net) == 1);
|
||||||
assert(ivl_stmt_opcode(net) == 0);
|
assert(ivl_stmt_opcode(net) == 0);
|
||||||
|
|
||||||
|
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
||||||
|
draw_array_pattern(var, rval, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Special case: If the l-value signal (string) is named after
|
/* Special case: If the l-value signal (string) is named after
|
||||||
its scope, and the scope is a function, then this is an
|
its scope, and the scope is a function, then this is an
|
||||||
assign to a return value and should be handled
|
assign to a return value and should be handled
|
||||||
|
|
@ -1291,6 +1362,11 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
||||||
|
draw_array_pattern(sig, rval, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* There is no property select, so evaluate the r-value
|
/* There is no property select, so evaluate the r-value
|
||||||
as an object and assign the entire object to the
|
as an object and assign the entire object to the
|
||||||
variable. */
|
variable. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue