diff --git a/Module.h b/Module.h index 68e841d65..09932947a 100644 --- a/Module.h +++ b/Module.h @@ -79,9 +79,11 @@ class Module : public PScope, public LineInfo { // True if this is an exclude bool exclude_flag; // lower bound + // If low_open_flag is false and low_expr=0, then use -inf bool low_open_flag; PExpr*low_expr; // upper bound + // If high_open_flag is false and high_expr=0, then use +inf bool high_open_flag; PExpr*high_expr; // Next range description in list diff --git a/design_dump.cc b/design_dump.cc index 82eb6919f..1e8fddbf7 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -966,8 +966,37 @@ void NetScope::dump(ostream&o) const o << "[" << *(*pp).second.msb << ":" << *(*pp).second.lsb << "] "; - o << (*pp).first << " = " << - *(*pp).second.expr << ";" << endl; + o << (*pp).first << " = " << *(*pp).second.expr; + + for (range_t*ran = (*pp).second.range ; ran ; ran = ran->next) { + if (ran->exclude_flag) + o << " exclude "; + else + o << " from "; + + if (ran->low_open_flag) + o << "("; + else + o << "["; + if (ran->low_expr) + o << *ran->low_expr; + else if (ran->low_open_flag==false) + o << "-inf"; + else + o << ""; + if (ran->high_expr) + o << ":" << *ran->high_expr; + else if (ran->high_open_flag==false) + o << ":inf"; + else + o << ":"; + if (ran->high_open_flag) + o << ")"; + else + o << "]"; + } + + o << ";" << endl; } for (pp = localparams.begin() diff --git a/elab_scope.cc b/elab_scope.cc index 725785a32..d2619d20a 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -43,6 +43,7 @@ # include "util.h" # include # include +# include "ivl_assert.h" void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, Design*des, NetScope*scope) @@ -80,8 +81,28 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, signed_flag = val->has_sign(); } - val = scope->set_parameter(name, val, msb, lsb, signed_flag, - cur.get_file(), cur.get_lineno()); + NetScope::range_t*range_list = 0; + for (Module::range_t*range = cur.range ; range ; range = range->next) { + NetScope::range_t*tmp = new NetScope::range_t; + tmp->exclude_flag = range->exclude_flag; + tmp->low_open_flag = range->low_open_flag; + tmp->high_open_flag = range->high_open_flag; + + if (range->low_expr) { + tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1); + ivl_assert(*range->low_expr, tmp->low_expr); + } + + if (range->high_expr) { + tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1); + ivl_assert(*range->high_expr, tmp->high_expr); + } + + tmp->next = range_list; + range_list = tmp; + } + + val = scope->set_parameter(name, val, msb, lsb, signed_flag, range_list, cur); assert(val); delete val; } @@ -119,9 +140,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, tmp->set_line(*((*cur).second.expr)); tmp->cast_signed( (*cur).second.signed_flag ); - scope->set_parameter((*cur).first, tmp, 0, 0, false, - (*cur).second.get_file(), - (*cur).second.get_lineno()); + scope->set_parameter((*cur).first, tmp, 0, 0, false, 0, (*cur).second); } for (mparm_it_t cur = localparams.begin() @@ -132,9 +151,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, if ((*cur).second.msb) tmp->cast_signed( (*cur).second.signed_flag ); - scope->set_parameter((*cur).first, tmp, 0, 0, false, - (*cur).second.get_file(), - (*cur).second.get_lineno()); + scope->set_parameter((*cur).first, tmp, 0, 0, false, 0, (*cur).second); } @@ -420,9 +437,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) genvar_verinum); // The file and line information should really come // from the genvar statement, not the for loop. - scope->set_localparam(loop_index, gp, get_file(), - get_lineno()); - + scope->set_localparam(loop_index, gp, *this); if (debug_scopes) cerr << get_fileline() << ": debug: " << "Create implicit localparam " diff --git a/net_scope.cc b/net_scope.cc index 01799f107..cdfa67a91 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -23,6 +23,7 @@ # include "netlist.h" # include # include +# include "ivl_assert.h" /* * The NetScope class keeps a scope tree organized. Each node of the @@ -105,7 +106,8 @@ void NetScope::set_line(perm_string file, perm_string def_file, NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr, NetExpr*msb, NetExpr*lsb, bool signed_flag, - perm_string file, unsigned lineno) + NetScope::range_t*range_list, + const LineInfo&file_line) { param_expr_t&ref = parameters[key]; NetExpr* res = ref.expr; @@ -113,8 +115,9 @@ NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr, ref.msb = msb; ref.lsb = lsb; ref.signed_flag = signed_flag; - ref.file = file; - ref.lineno = lineno; + ivl_assert(file_line, ref.range == 0); + ref.range = range_list; + ref.set_line(file_line); return res; } @@ -160,7 +163,7 @@ bool NetScope::replace_parameter(perm_string key, NetExpr*expr) * used to add a genver to the local parameter list. */ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr, - perm_string file, unsigned lineno) + const LineInfo&file_line) { param_expr_t&ref = localparams[key]; NetExpr* res = ref.expr; @@ -168,8 +171,7 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr, ref.msb = 0; ref.lsb = 0; ref.signed_flag = false; - ref.file = file; - ref.lineno = lineno; + ref.set_line(file_line); return res; } diff --git a/netlist.h b/netlist.h index afd3c89b1..2b8c0b3c3 100644 --- a/netlist.h +++ b/netlist.h @@ -3314,11 +3314,13 @@ class NetScope : public Attrib { the scope. The return value from set_parameter is the previous expression, if there was one. */ + struct range_t; NetExpr* set_parameter(perm_string name, NetExpr*val, NetExpr*msb, NetExpr*lsb, bool signed_flag, - perm_string file, unsigned lineno); + NetScope::range_t*range_list, + const LineInfo&file_line); NetExpr* set_localparam(perm_string name, NetExpr*val, - perm_string file, unsigned lineno); + const LineInfo&file_line); const NetExpr*get_parameter(const char* name, const NetExpr*&msb, @@ -3427,15 +3429,30 @@ class NetScope : public Attrib { mapdefparams; public: + struct range_t { + bool exclude_flag; + // Lower bound + bool low_open_flag; + NetExpr*low_expr; + // Upper bound + bool high_open_flag; + NetExpr*high_expr; + // Link to the next range specification + struct range_t*next; + }; + /* After everything is all set up, the code generators like access to these things to make up the parameter lists. */ - struct param_expr_t { - NetExpr*expr; + struct param_expr_t : public LineInfo { + param_expr_t() : range(0) { } + // Type information + bool signed_flag; NetExpr*msb; NetExpr*lsb; - perm_string file; - unsigned lineno; - bool signed_flag; + // range constraints + struct range_t*range; + // Expression value + NetExpr*expr; }; mapparameters; maplocalparams; diff --git a/pform.cc b/pform.cc index 22f4e9176..a800b9f50 100644 --- a/pform.cc +++ b/pform.cc @@ -1638,6 +1638,11 @@ Module::range_t* pform_parameter_value_range(bool exclude_flag, bool low_open, PExpr*low_expr, bool hig_open, PExpr*hig_expr) { + // Detect +-inf and make the the *_open flags false to force + // the range interpretation as inf. + if (low_expr == 0) low_open = false; + if (hig_expr == 0) hig_open = false; + Module::range_t*tmp = new Module::range_t; tmp->exclude_flag = exclude_flag; tmp->low_open_flag = low_open; diff --git a/pform_dump.cc b/pform_dump.cc index bcc973031..8728d280e 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1017,13 +1017,17 @@ void Module::dump(ostream&out) const out << "["; if (tmp->low_expr) out << *(tmp->low_expr); + else if (tmp->low_open_flag==false) + out << "-inf"; else - out << "<>"; + out << ""; out << ":"; if (tmp->high_expr) out << *(tmp->high_expr); + else if (tmp->high_open_flag==false) + out << "inf"; else - out << "<>"; + out << ""; if (tmp->high_open_flag) out << ")"; else diff --git a/t-dll.cc b/t-dll.cc index c7232e721..c7c383342 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -470,8 +470,8 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net) ivl_parameter_t cur_par = scope->param_ + idx; cur_par->basename = (*cur_pit).first; cur_par->scope = scope; - cur_par->file = (*cur_pit).second.file; - cur_par->lineno = (*cur_pit).second.lineno; + cur_par->file = (*cur_pit).second.get_file(); + cur_par->lineno = (*cur_pit).second.get_lineno(); NetExpr*etmp = (*cur_pit).second.expr; make_scope_param_expr(cur_par, etmp); @@ -484,8 +484,8 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net) ivl_parameter_t cur_par = scope->param_ + idx; cur_par->basename = (*cur_pit).first; cur_par->scope = scope; - cur_par->file = (*cur_pit).second.file; - cur_par->lineno = (*cur_pit).second.lineno; + cur_par->file = (*cur_pit).second.get_file(); + cur_par->lineno = (*cur_pit).second.get_lineno(); NetExpr*etmp = (*cur_pit).second.expr; make_scope_param_expr(cur_par, etmp);