Permalink
Browse files

Rework of parameter expression elaboration.

The compiler currently performs parameter expression elaboration before
performing parameter overrides. This means that the information needed
to correctly determine the expression type and width may not be available
at the time elaboration is performed. This patch reworks the code to
delay elaboration until after all overrides have been performed. It
also provides a new -g option that controls how the width of parameter
expressions is calculated when the parameter itself is unsized.
  • Loading branch information...
1 parent fd5bc3f commit 275dde77120e5fa5f3c4ba2ae210ee19bd721fdf @martinwhitaker martinwhitaker committed with steveicarus Dec 5, 2010
Showing with 333 additions and 517 deletions.
  1. +1 −1 Module.h
  2. +4 −0 compiler.h
  3. +6 −5 design_dump.cc
  4. +10 −1 driver/main.c
  5. +23 −25 elab_expr.cc
  6. +3 −3 elab_pexpr.cc
  7. +63 −215 elab_scope.cc
  8. +1 −1 elab_sig.cc
  9. +1 −2 elaborate.cc
  10. +3 −116 eval_tree.cc
  11. +7 −0 main.cc
  12. +129 −100 net_design.cc
  13. +46 −31 net_scope.cc
  14. +28 −14 netlist.h
  15. +5 −0 netmisc.h
  16. +1 −1 symbol_search.cc
  17. +2 −2 t-dll.cc
View
@@ -138,7 +138,7 @@ class Module : public PScope, public LineInfo {
void dump(ostream&out) const;
bool elaborate(Design*, NetScope*scope) const;
- typedef map<perm_string,NetExpr*> replace_t;
+ typedef map<perm_string,PExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
bool elaborate_sig(Design*, NetScope*scope) const;
View
@@ -151,6 +151,10 @@ extern bool gn_io_range_error_flag;
re-evaluated. */
extern bool gn_strict_ca_eval_flag;
+/* If this flag is true, then force strict conformance to the IEEE
+ standard expression width rules. */
+extern bool gn_strict_expr_width_flag;
+
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign, then return true. This will be true
for SystemVerilog */
View
@@ -29,6 +29,7 @@
# include "compiler.h"
# include "discipline.h"
# include "ivl_assert.h"
+# include "PExpr.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
@@ -1128,8 +1129,8 @@ void NetScope::dump(ostream&o) const
<< ":" << *(*pp).second.lsb << "] ";
o << (*pp).first << " = ";
- if (pp->second.expr)
- o << *(*pp).second.expr;
+ if (pp->second.val)
+ o << *(*pp).second.val;
else
o << "<nil>";
@@ -1167,13 +1168,13 @@ void NetScope::dump(ostream&o) const
for (pp = localparams.begin()
; pp != localparams.end() ; ++ pp ) {
o << " localparam " << (*pp).first << " = " <<
- *(*pp).second.expr << ";" << endl;
+ *(*pp).second.val << ";" << endl;
}
}
/* Dump the saved defparam assignments here. */
{
- list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
+ list<pair<pform_name_t,PExpr*> >::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; ++ pp ) {
o << " defparam " << (*pp).first << " = " <<
@@ -1182,7 +1183,7 @@ void NetScope::dump(ostream&o) const
}
{
- list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
+ list<pair<list<hname_t>,PExpr*> >::const_iterator pp;
for (pp = defparams_later.begin()
; pp != defparams_later.end() ; ++ pp ) {
o << " defparam(later) " << pp->first << " = " <<
View
@@ -121,6 +121,7 @@ const char*gen_xtypes = "xtypes";
const char*gen_icarus = "icarus-misc";
const char*gen_io_range_error = "io-range-error";
const char*gen_strict_ca_eval = "no-strict-ca-eval";
+const char*gen_strict_expr_width = "no-strict-expr-width";
const char*gen_verilog_ams = "no-verilog-ams";
/* Boolean: true means use a default include dir, false means don't */
@@ -680,6 +681,12 @@ int process_generation(const char*name)
else if (strcmp(name,"no-strict-ca-eval") == 0)
gen_strict_ca_eval = "no-strict-ca-eval";
+ else if (strcmp(name,"strict-expr-width") == 0)
+ gen_strict_expr_width = "strict-expr-width";
+
+ else if (strcmp(name,"no-strict-expr-width") == 0)
+ gen_strict_expr_width = "no-strict-expr-width";
+
else if (strcmp(name,"verilog-ams") == 0)
gen_verilog_ams = "verilog-ams";
@@ -702,7 +709,8 @@ int process_generation(const char*name)
" xtypes | no-xtypes\n"
" icarus-misc | no-icarus-misc\n"
" io-range-error | no-io-range-error\n"
- " strict-ca-eval | no-strict-ca-eval\n");
+ " strict-ca-eval | no-strict-ca-eval\n"
+ " strict-expr-width | no-strict-expr-width\n");
return 1;
}
@@ -1043,6 +1051,7 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
+ fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
View
@@ -2089,33 +2089,14 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
return expr_width_;
}
- // The width of a parameter name is the width of the range for
- // the parameter name, if a range is declared. Otherwise, the
- // width is undefined.
+ // The width of a parameter is the width of the parameter value
+ // (as evaluated earlier).
if (par != 0) {
expr_type_ = par->expr_type();
- expr_type__ = expr_type_;
- if (ex1) {
- ivl_assert(*this, ex2);
- const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1);
- const NetEConst*ex2_const = dynamic_cast<const NetEConst*> (ex2);
- ivl_assert(*this, ex1_const && ex2_const);
-
- long msb = ex1_const->value().as_long();
- long lsb = ex2_const->value().as_long();
- if (msb >= lsb)
- expr_width_ = msb - lsb + 1;
- else
- expr_width_ = lsb - msb + 1;
- return expr_width_;
- }
-
- // This is a parameter. If it is sized (meaning it was
- // declared with range expressions) then the range
- // expressions would have been caught above. So if we
- // got here then we know this is an unsized constant.
expr_width_ = par->expr_width();
- unsized_flag = true;
+ expr_type__ = expr_type_;
+ if (!par->has_width())
+ unsized_flag = true;
return expr_width_;
}
@@ -2154,6 +2135,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
const NetExpr*ex1, *ex2;
+ if (is_param_expr && path_.size() > 1) {
+ cerr << get_fileline() << ": error: parameter r-value expression "
+ "does not support hierarchical references `" << path_
+ << "`." << endl;
+ des->errors += 1;
+ return 0;
+ }
+
NetScope*found_in = symbol_search(this, des, scope, path_,
net, par, eve,
ex1, ex2);
@@ -2163,6 +2152,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (par != 0)
return elaborate_expr_param_(des, scope, par, found_in, ex1, ex2, expr_wid);
+ // If this is a parameter expression, no other identifiers are valid.
+ if (is_param_expr) {
+ cerr << get_fileline() << ": error: identifier `"
+ << path_ << "` is not a parameter in "
+ << scope_path(scope) << "." << endl;
+ des->errors += 1;
+ return 0;
+ }
// If the identifier names a signal (a register or wire)
// then create a NetESignal node to handle it.
@@ -3461,7 +3458,8 @@ NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
// the self-determined size.
if (expr_width__ > 0) {
tvalue = pad_to_width(tvalue, expr_width__);
- if (tvalue.len() > (unsigned)expr_width__) {
+ if ( (tvalue.len() > (unsigned)expr_width__) ||
+ (is_param_expr && !tvalue.has_len()) ) {
verinum tmp (tvalue, expr_width__);
tmp.has_sign(tvalue.has_sign());
tvalue = tmp;
View
@@ -229,7 +229,7 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
// name is not found in the pscope, look in containing scopes,
// but do not go outside the containing module instance.
for (;;) {
- ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
+ ex = pscope->get_parameter(des, name_tail.name, ex_msb, ex_lsb);
if (ex != 0)
break;
if (pscope->type() == NetScope::MODULE)
@@ -509,7 +509,7 @@ void NetEParam::resolve_pexpr_type(void)
if (reference_->second.signed_flag) {
cast_signed_base_(true);
- } else if (reference_->second.expr) {
- cast_signed_base_( reference_->second.expr->has_sign() );
+ } else if (reference_->second.val) {
+ cast_signed_base_( reference_->second.val->has_sign() );
}
}
Oops, something went wrong.

0 comments on commit 275dde7

Please sign in to comment.