ivl: Casting vectors to dynamic arrays.

This commit is contained in:
Maciej Suminski 2015-01-21 10:03:20 +01:00
parent a52242745a
commit 8b3667f76e
3 changed files with 42 additions and 3 deletions

View File

@ -999,6 +999,9 @@ class PECastType : public PExpr {
void dump(ostream &out) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;

View File

@ -2541,6 +2541,39 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
return expr_width_;
}
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned) const
{
const netdarray_t*darray = NULL;
const netvector_t*vector = NULL;
// Casting array of vectors to dynamic array type
if((darray = dynamic_cast<const netdarray_t*>(type)) &&
(vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
PExpr::width_mode_t mode = PExpr::SIZED;
unsigned use_wid = base_->test_width(des, scope, mode);
NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
assert(vector->packed_width() > 0);
assert(base->expr_width() > 0);
// Find rounded up length that can fit the whole casted array of vectors
int len = base->expr_width() + vector->packed_width() - 1;
if(base->expr_width() > vector->packed_width()) {
len /= vector->packed_width();
} else {
len /= base->expr_width();
}
// Number of words in the created dynamic array
NetEConst*len_expr = new NetEConst(verinum(len));
return new NetENew(type, len_expr, base);
}
// Fallback
return elaborate_expr(des, scope, (unsigned) 0, 0);
}
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned) const
{

View File

@ -129,12 +129,15 @@ static int eval_darray_new(ivl_expr_t ex)
unsigned wid;
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
wid = width_of_packed_type(element_type);
draw_eval_vec4(init_expr);
resize_vec4_wid(init_expr, wid);
for (idx = 0 ; idx < cnt ; idx += 1) {
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
draw_eval_vec4(init_expr);
fprintf(vvp_out, " %%parti/%c %d, %ld, 6;\n",
ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid);
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1);
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
fprintf(vvp_out, " %%pop/vec4 1;\n");
}
break;
case IVL_VT_REAL: