Skip to content

Commit dcbd824

Browse files
author
Pierre-Henri Horrein
committed
Preliminary unpacked support for localparam
1 parent cf0bf4d commit dcbd824

File tree

18 files changed

+374
-56
lines changed

18 files changed

+374
-56
lines changed

PExpr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,12 @@ class PEIdent : public PExpr {
456456
NetScope*found_in,
457457
ivl_type_t par_type,
458458
bool need_const) const;
459+
NetExpr*elaborate_expr_param_word_(Design*des,
460+
NetScope*scope,
461+
const NetExpr*par,
462+
NetScope*found_in,
463+
ivl_type_t par_type,
464+
bool need_const) const;
459465
NetExpr*elaborate_expr_param_part_(Design*des,
460466
NetScope*scope,
461467
const NetExpr*par,

design_dump.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
109109
case IVL_VT_STRING:
110110
o << "string";
111111
break;
112+
case IVL_VT_UARRAY:
113+
o << "uarray";
114+
break;
112115
case IVL_VT_DARRAY:
113116
o << "darray";
114117
break;
@@ -1673,6 +1676,19 @@ void NetEArrayPattern::dump(ostream&fd) const
16731676
fd << "}";
16741677
}
16751678

1679+
void NetEArrayPatternParam::dump(ostream&fd) const
1680+
{
1681+
fd << "'{";
1682+
if (items_.size() >= 1) {
1683+
if (items_[0]) fd << *items_[0];
1684+
}
1685+
for (size_t idx = 1 ; idx < items_.size() ; idx += 1) {
1686+
fd << ", ";
1687+
if (items_[idx]) fd << *items_[idx];
1688+
}
1689+
fd << "}";
1690+
}
1691+
16761692
void NetEBinary::dump(ostream&o) const
16771693
{
16781694
if (op_ == 'm' || op_ == 'M') {

dup_expr.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ NetEArrayPattern*NetEArrayPattern::dup_expr() const
4343
return res;
4444
}
4545

46+
NetEArrayPatternParam*NetEArrayPatternParam::dup_expr() const
47+
{
48+
vector<NetExpr*>tmp (items_.size());
49+
for (size_t idx = 0 ; idx < tmp.size() ; idx += 1)
50+
tmp[idx] = items_[idx]->dup_expr();
51+
52+
NetEArrayPatternParam*res = new NetEArrayPatternParam(scope_, name_, net_type(), tmp);
53+
res->set_line(*this);
54+
return res;
55+
}
56+
4657
NetEBinary* NetEBinary::dup_expr() const
4758
{
4859
ivl_assert(*this, 0);

elab_expr.cc

Lines changed: 130 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
109109
int context_wid = -1;
110110
switch (lv_type) {
111111
case IVL_VT_DARRAY:
112+
case IVL_VT_UARRAY:
112113
case IVL_VT_QUEUE:
113114
case IVL_VT_CLASS:
114115
// For these types, use a different elab_and_eval that
@@ -186,11 +187,11 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
186187
*/
187188
unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&)
188189
{
189-
expr_type_ = IVL_VT_DARRAY;
190-
expr_width_ = 1;
191-
min_width_ = 1;
190+
expr_type_ = IVL_VT_UARRAY;
191+
expr_width_ = parms_.size();
192+
min_width_ = expr_width_;
192193
signed_flag_= false;
193-
return 1;
194+
return expr_width_;
194195
}
195196

196197
NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
@@ -208,7 +209,8 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
208209
}
209210

210211
if (ntype->base_type()==IVL_VT_DARRAY ||
211-
ntype->base_type()==IVL_VT_QUEUE)
212+
ntype->base_type()==IVL_VT_QUEUE ||
213+
ntype->base_type()==IVL_VT_UARRAY)
212214
return elaborate_expr_darray_(des, scope, ntype, flags);
213215

214216
cerr << get_fileline() << ": sorry: I don't know how to elaborate "
@@ -222,7 +224,7 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
222224
NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope,
223225
ivl_type_t ntype, unsigned flags) const
224226
{
225-
const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype);
227+
const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype);
226228
ivl_assert(*this, array_type);
227229

228230
// This is an array pattern, so run through the elements of
@@ -3558,6 +3560,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
35583560
switch (ntype->base_type()) {
35593561
case IVL_VT_QUEUE:
35603562
// FIXME: Does a DARRAY support a zero size?
3563+
case IVL_VT_UARRAY:
35613564
case IVL_VT_DARRAY:
35623565
if (parms_.size() == 0) {
35633566
NetENull*tmp = new NetENull;
@@ -3728,6 +3731,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
37283731
switch (net->data_type()) {
37293732
case IVL_VT_STRING:
37303733
case IVL_VT_DARRAY:
3734+
case IVL_VT_UARRAY:
37313735
case IVL_VT_QUEUE:
37323736
dimensions += 1;
37333737
default:
@@ -4061,6 +4065,27 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
40614065
return expr_width_;
40624066
}
40634067

4068+
if (par != 0 && par->expr_type() == IVL_VT_UARRAY) {
4069+
const netuarray_t*array = dynamic_cast<const netuarray_t*> (par->net_type());
4070+
ivl_assert(*this, array);
4071+
switch (use_sel) {
4072+
case index_component_t::SEL_BIT:
4073+
case index_component_t::SEL_BIT_LAST:
4074+
expr_type_ = array->element_type()->base_type();
4075+
expr_width_ = array->element_type()->packed_width();
4076+
min_width_ = expr_width_;
4077+
signed_flag_ = array->element_type()->get_signed();
4078+
break;
4079+
default:
4080+
expr_type_ = array->base_type();
4081+
expr_width_ = array->static_dimensions()[0].width();
4082+
min_width_ = expr_width_;
4083+
signed_flag_ = false;
4084+
break;
4085+
}
4086+
return expr_width_;
4087+
}
4088+
40644089
// Look for a class property.
40654090
if (gn_system_verilog() && cls_val) {
40664091
expr_type_ = cls_val->base_type();
@@ -4255,6 +4280,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
42554280

42564281
symbol_search(this, des, use_scope, path_, net, par, eve, par_type, cls_val);
42574282

4283+
if (par != 0) {
4284+
return (NetExpr *)par;
4285+
}
4286+
42584287
if (net == 0 && gn_system_verilog() && path_.size() >= 2) {
42594288
// NOTE: this is assuming the member_path is only one
42604289
// component long, and that the use_path will wind up
@@ -4615,9 +4644,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
46154644
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
46164645
par_type, expr_wid, flags);
46174646

4618-
if (!tmp) return 0;
4647+
if (!tmp) return 0;
46194648

4620-
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
4649+
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
46214650
}
46224651

46234652
// If the identifier names a signal (a variable or a net)
@@ -5132,6 +5161,78 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope,
51325161
return tmp;
51335162
}
51345163

5164+
NetExpr* PEIdent::elaborate_expr_param_word_(Design*des, NetScope*scope,
5165+
const NetExpr*par,
5166+
NetScope*found_in,
5167+
ivl_type_t par_type,
5168+
bool need_const) const
5169+
{
5170+
const NetEArrayPattern*par_ex = dynamic_cast<const NetEArrayPattern*> (par);
5171+
ivl_assert(*this, par_ex);
5172+
const netuarray_t*array = dynamic_cast<const netuarray_t*> (par->net_type());
5173+
if (!array) {
5174+
cerr << get_fileline() << "tried to get a word from non-array expression" << endl;
5175+
return 0;
5176+
}
5177+
5178+
long par_msv, par_lsv;
5179+
if(! calculate_param_range(*this, par_type, par_msv, par_lsv,
5180+
par_ex->item_size())) return 0;
5181+
5182+
const name_component_t&name_tail = path_.back();
5183+
ivl_assert(*this, !name_tail.index.empty());
5184+
const index_component_t&index_tail = name_tail.index.back();
5185+
ivl_assert(*this, index_tail.msb);
5186+
ivl_assert(*this, !index_tail.lsb);
5187+
5188+
NetExpr*sel = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
5189+
if (sel == 0) return 0;
5190+
5191+
if (debug_elaborate)
5192+
cerr << get_fileline() << ": debug: Calculate bit select "
5193+
<< "[" << *sel << "] from range "
5194+
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
5195+
5196+
perm_string name = peek_tail_name(path_);
5197+
5198+
// Handle the special case that the selection is constant. In this
5199+
// case, just precalculate the entire constant result.
5200+
NetEConst*sel_c = dynamic_cast<NetEConst*> (sel);
5201+
if (!sel_c) {
5202+
cerr << get_fileline() << "tried to get a word with non constant selector" << endl;
5203+
return 0;
5204+
}
5205+
// Special case: If the bit select is constant and not fully
5206+
// defined, then we know that the result must be 1'bx.
5207+
if (! sel_c->value().is_defined()) {
5208+
if (warn_ob_select) {
5209+
cerr << get_fileline() << ": warning: "
5210+
"Constant undefined bit select ["
5211+
<< sel_c->value() << "] for parameter '"
5212+
<< name << "'." << endl;
5213+
cerr << get_fileline() << ": : "
5214+
"Replacing select with a constant 1'bx."
5215+
<< endl;
5216+
}
5217+
5218+
// This is a convenience function for getting the width of an
5219+
// element. Strictly speaking it's not necessary.
5220+
NetEConst*res = make_const_x(array->element_type()->packed_width());
5221+
res->set_line(*this);
5222+
return res;
5223+
}
5224+
// Calculate the canonical index value.
5225+
long sel_v = sel_c->value().as_long();
5226+
if (par_msv >= par_lsv) sel_v = par_msv - sel_v - par_lsv;
5227+
else sel_v -= par_msv;
5228+
5229+
// Select a bit from the parameter.
5230+
NetExpr*res = (NetExpr *)(par_ex->item(sel_v)->dup_expr());
5231+
//NetEConst*res = new NetEConst(rtn);
5232+
res->set_line(*this);
5233+
return res;
5234+
}
5235+
51355236
NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
51365237
const NetExpr*par,
51375238
NetScope*,
@@ -5458,6 +5559,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
54585559

54595560
const name_component_t&name_tail = path_.back();
54605561
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
5562+
// FIXME: this won't work with multidimensional array
54615563
if (!name_tail.index.empty())
54625564
use_sel = name_tail.index.back().sel;
54635565

@@ -5473,8 +5575,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
54735575
ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST);
54745576

54755577
if (use_sel == index_component_t::SEL_BIT)
5476-
return elaborate_expr_param_bit_(des, scope, par, found_in,
5477-
par_type, need_const);
5578+
if (par->expr_type() == IVL_VT_UARRAY) {
5579+
return elaborate_expr_param_word_(des, scope, par, found_in,
5580+
par_type, need_const);
5581+
} else {
5582+
return elaborate_expr_param_bit_(des, scope, par, found_in,
5583+
par_type, need_const);
5584+
}
54785585

54795586
if (use_sel == index_component_t::SEL_PART)
54805587
return elaborate_expr_param_part_(des, scope, par, found_in,
@@ -5530,6 +5637,19 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
55305637
<< "Elaborate parameter <" << name
55315638
<< "> as constant " << *tmp << endl;
55325639
}
5640+
5641+
const NetEArrayPattern*atmp = dynamic_cast<const NetEArrayPattern*>(par);
5642+
if (atmp) {
5643+
std::vector<NetExpr*> items(atmp->item_size());
5644+
for (unsigned i = 0; i < atmp->item_size(); i++) {
5645+
items[i] = (NetExpr*)atmp->item(i)->dup_expr();
5646+
}
5647+
tmp = new NetEArrayPatternParam(found_in, name, atmp->net_type(), items);
5648+
if (debug_elaborate)
5649+
cerr << get_fileline() << ": debug: "
5650+
<< "Elaborate parameter <" << name
5651+
<< "> as constant " << *tmp << endl;
5652+
}
55335653
/* The numeric parameter value needs to have the file and line
55345654
* information for the actual parameter not the expression. */
55355655
assert(tmp);

emit.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,11 @@ void NetEArrayPattern::expr_scan(struct expr_scan_t*tgt) const
593593
tgt->expr_array_pattern(this);
594594
}
595595

596+
void NetEArrayPatternParam::expr_scan(struct expr_scan_t*tgt) const
597+
{
598+
tgt->expr_array_pattern(this);
599+
}
600+
596601
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
597602
{
598603
tgt->expr_binary(this);

ivl_target.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,10 @@ typedef enum ivl_variable_type_e ENUM_UNSIGNED_INT {
460460
IVL_VT_BOOL = 3,
461461
IVL_VT_LOGIC = 4,
462462
IVL_VT_STRING = 5,
463-
IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
464-
IVL_VT_CLASS = 7, /* SystemVerilog class instances */
465-
IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */
463+
IVL_VT_UARRAY = 6, /* Array (esp. unpacked array) */
464+
IVL_VT_DARRAY = 7, /* Array (esp. dynamic array) */
465+
IVL_VT_CLASS = 8, /* SystemVerilog class instances */
466+
IVL_VT_QUEUE = 9, /* SystemVerilog queue instances */
466467
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
467468
} ivl_variable_type_t;
468469

net_design.cc

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,31 @@ void Design::evaluate_parameters()
508508
}
509509
}
510510

511+
void NetScope::evaluate_parameter_array_(Design*des, param_ref_t cur)
512+
{
513+
PExpr*val_expr = (*cur).second.val_expr;
514+
NetScope*val_scope = (*cur).second.val_scope;
515+
ivl_type_t param_type = cur->second.ivl_type;
516+
517+
ivl_assert(cur->second, val_expr);
518+
ivl_assert(cur->second, param_type);
519+
520+
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, param_type, true);
521+
if (! expr)
522+
return;
523+
524+
cur->second.val = expr;
525+
526+
if (debug_elaborate) {
527+
cerr << cur->second.get_fileline() << ": " << __func__ << ": "
528+
<< "Parameter type: " << *param_type << endl;
529+
cerr << cur->second.get_fileline() << ": " << __func__ << ": "
530+
<< "Parameter value: " << *val_expr << endl;
531+
cerr << cur->second.get_fileline() << ": " << __func__ << ": "
532+
<< "Elaborated value: " << *expr << endl;
533+
}
534+
535+
}
511536
void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
512537
{
513538
/* Evaluate the parameter expression. */
@@ -840,7 +865,7 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
840865
if (cur->second.val_expr == 0)
841866
return;
842867

843-
// Guess the varaiable type of the parameter. If the parameter has no
868+
// Guess the variable type of the parameter. If the parameter has no
844869
// given type, then guess the type from the expression and use that to
845870
// evaluate.
846871
ivl_variable_type_t use_type;
@@ -849,6 +874,14 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
849874
else
850875
use_type = cur->second.val_expr->expr_type();
851876

877+
if (debug_elaborate) {
878+
cerr << cur->second.get_fileline() << ": evaluating parameter " << cur->first
879+
<< ", param_type: " << param_type;
880+
if (param_type)
881+
cerr << "(base type: " << param_type->base_type() << ")";
882+
cerr << ", use_type: " << use_type
883+
<< "." << endl;
884+
}
852885
if (cur->second.solving) {
853886
cerr << cur->second.get_fileline() << ": error: "
854887
<< "Recursive parameter reference found involving "
@@ -868,9 +901,13 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
868901
evaluate_parameter_real_(des, cur);
869902
break;
870903

871-
case IVL_VT_STRING:
872-
evaluate_parameter_string_(des, cur);
873-
break;
904+
case IVL_VT_UARRAY:
905+
evaluate_parameter_array_(des, cur);
906+
break;
907+
908+
case IVL_VT_STRING:
909+
evaluate_parameter_string_(des, cur);
910+
break;
874911

875912
default:
876913
cerr << cur->second.get_fileline() << ": internal error: "

0 commit comments

Comments
 (0)