diff --git a/Module.h b/Module.h index 3222a2838..68e841d65 100644 --- a/Module.h +++ b/Module.h @@ -75,16 +75,29 @@ class Module : public PScope, public LineInfo { NetNet::Type default_nettype; + struct range_t { + // True if this is an exclude + bool exclude_flag; + // lower bound + bool low_open_flag; + PExpr*low_expr; + // upper bound + bool high_open_flag; + PExpr*high_expr; + // Next range description in list + struct range_t*next; + }; + /* The module has parameters that are evaluated when the module is elaborated. During parsing, I put the parameters into this map. */ - struct param_expr_t { + struct param_expr_t : public LineInfo { PExpr*expr; PExpr*msb; PExpr*lsb; - perm_string file; - unsigned lineno; bool signed_flag; + // If there are range constrants, list them here + range_t*range; }; mapparameters; maplocalparams; @@ -158,8 +171,7 @@ class Module : public PScope, public LineInfo { map funcs_; static void elaborate_parm_item_(perm_string name, const param_expr_t&cur, - Design*des, NetScope*scope, - perm_string file, unsigned lineno); + Design*des, NetScope*scope); private: // Not implemented Module(const Module&); diff --git a/elab_scope.cc b/elab_scope.cc index 175d0474c..725785a32 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -45,8 +45,7 @@ # include void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, - Design*des, NetScope*scope, - perm_string file, unsigned lineno) + Design*des, NetScope*scope) { PExpr*ex = cur.expr; assert(ex); @@ -81,8 +80,8 @@ 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, file, lineno); + val = scope->set_parameter(name, val, msb, lsb, signed_flag, + cur.get_file(), cur.get_lineno()); assert(val); delete val; } @@ -121,7 +120,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, tmp->cast_signed( (*cur).second.signed_flag ); scope->set_parameter((*cur).first, tmp, 0, 0, false, - (*cur).second.file, (*cur).second.lineno); + (*cur).second.get_file(), + (*cur).second.get_lineno()); } for (mparm_it_t cur = localparams.begin() @@ -133,7 +133,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, tmp->cast_signed( (*cur).second.signed_flag ); scope->set_parameter((*cur).first, tmp, 0, 0, false, - (*cur).second.file, (*cur).second.lineno); + (*cur).second.get_file(), + (*cur).second.get_lineno()); } @@ -145,8 +146,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, for (mparm_it_t cur = parameters.begin() ; cur != parameters.end() ; cur ++) { - elaborate_parm_item_((*cur).first, (*cur).second, des, scope, - (*cur).second.file, (*cur).second.lineno); + elaborate_parm_item_((*cur).first, (*cur).second, des, scope); } /* run parameter replacements that were collected from the @@ -178,8 +178,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, for (mparm_it_t cur = localparams.begin() ; cur != localparams.end() ; cur ++) { - elaborate_parm_item_((*cur).first, (*cur).second, des, scope, - (*cur).second.file, (*cur).second.lineno); + elaborate_parm_item_((*cur).first, (*cur).second, des, scope); } // Run through the defparams for this module, elaborate the diff --git a/lexor_keyword.gperf b/lexor_keyword.gperf index 5d8c05035..980b33c89 100644 --- a/lexor_keyword.gperf +++ b/lexor_keyword.gperf @@ -79,6 +79,7 @@ hypot, GN_KEYWORDS_VAMS_2_3, K_hypot idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature if, GN_KEYWORDS_1364_1995, K_if ifnone, GN_KEYWORDS_1364_1995, K_ifnone +inf, GN_KEYWORDS_VAMS_2_3, K_inf initial, GN_KEYWORDS_1364_1995, K_initial inout, GN_KEYWORDS_1364_1995, K_inout input, GN_KEYWORDS_1364_1995, K_input diff --git a/parse.y b/parse.y index d375ea19c..0ec6c273b 100644 --- a/parse.y +++ b/parse.y @@ -156,6 +156,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) svector*gates; Module::port_t *mport; + Module::range_t* value_range; svector*mports; named_pexpr_t*named_pexpr; @@ -213,7 +214,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %token K_endprimitive K_endspecify K_endtable K_endtask K_event %token K_exclude K_exp K_floor K_flow K_from %token K_for K_force K_forever K_fork K_function K_generate K_genvar -%token K_ground K_highz0 K_highz1 K_hypot K_idt_nature K_if K_ifnone +%token K_ground K_highz0 K_highz1 K_hypot K_idt_nature K_if K_ifnone K_inf %token K_initial K_inout K_input K_integer K_join K_large K_ln K_localparam %token K_log K_logic K_macromodule K_max %token K_medium K_min K_module K_nand K_nature K_negedge @@ -235,6 +236,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %token KK_attribute +%type from_exclude %type number %type signed_opt udp_reg_opt edge_operator %type drive_strength drive_strength_opt dr_strength0 dr_strength1 @@ -256,6 +258,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %type port port_opt port_reference port_reference_list %type port_declaration %type list_of_ports module_port_list_opt list_of_port_declarations +%type parameter_value_range parameter_value_ranges +%type parameter_value_ranges_opt +%type value_range_expression %type task_item task_item_list task_item_list_opt %type task_port_item task_port_decl task_port_decl_list @@ -2375,22 +2380,43 @@ parameter_assign_list ; parameter_assign - : IDENTIFIER '=' expression - { PExpr*tmp = $3; - if (!pform_expression_is_constant(tmp)) { - yyerror(@3, "error: parameter value " - "must be a constant expression."); - delete tmp; - tmp = 0; - } else { - pform_set_parameter(lex_strings.make($1), - active_signed, - active_range, tmp, - @1.text, @1.first_line); - } - delete[]$1; - } - ; + : IDENTIFIER '=' expression parameter_value_ranges_opt + { PExpr*tmp = $3; + pform_set_parameter(@1, lex_strings.make($1), + active_signed, active_range, tmp, $4); + delete[]$1; + } + ; + +parameter_value_ranges_opt : parameter_value_ranges { $$ = $1; } | { $$ = 0; } ; + +parameter_value_ranges + : parameter_value_ranges parameter_value_range + { $$ = $2; $$->next = $1; } + | parameter_value_range + { $$ = $1; $$->next = 0; } + ; + +parameter_value_range + : from_exclude '[' value_range_expression ':' value_range_expression ']' + { $$ = pform_parameter_value_range($1, false, $3, false, $5); } + | from_exclude '[' value_range_expression ':' value_range_expression ')' + { $$ = pform_parameter_value_range($1, false, $3, true, $5); } + | from_exclude '(' value_range_expression ':' value_range_expression ']' + { $$ = pform_parameter_value_range($1, true, $3, false, $5); } + | from_exclude '(' value_range_expression ':' value_range_expression ')' + { $$ = pform_parameter_value_range($1, true, $3, true, $5); } + /* | K_exclude expression */ + ; + +value_range_expression + : expression { $$ = $1; } + | K_inf { $$ = 0; } + | '+' K_inf { $$ = 0; } + | '-' K_inf { $$ = 0; } + ; + +from_exclude : K_from { $$ = false; } | K_exclude { $$ = true; } ; /* Localparam assignments and assignment lists are broken into separate BNF so that I can call slightly different parameter @@ -2406,10 +2432,9 @@ localparam_assign delete tmp; tmp = 0; } else { - pform_set_localparam(lex_strings.make($1), + pform_set_localparam(@1, lex_strings.make($1), active_signed, - active_range, tmp, - @1.text, @1.first_line); + active_range, tmp); } delete[]$1; } diff --git a/pform.cc b/pform.cc index f964a85ca..22f4e9176 100644 --- a/pform.cc +++ b/pform.cc @@ -1634,50 +1634,69 @@ void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r) cur->set_memory_idx(l, r); } -void pform_set_parameter(perm_string name, bool signed_flag, +Module::range_t* pform_parameter_value_range(bool exclude_flag, + bool low_open, PExpr*low_expr, + bool hig_open, PExpr*hig_expr) +{ + Module::range_t*tmp = new Module::range_t; + tmp->exclude_flag = exclude_flag; + tmp->low_open_flag = low_open; + tmp->low_expr = low_expr; + tmp->high_open_flag = hig_open; + tmp->high_expr = hig_expr; + tmp->next = 0; + return tmp; +} + +void pform_set_parameter(const struct vlltype&loc, + perm_string name, bool signed_flag, svector*range, PExpr*expr, - const char*file, unsigned lineno) + Module::range_t*value_range) { assert(expr); - pform_cur_module->parameters[name].expr = expr; + Module::param_expr_t&parm = pform_cur_module->parameters[name]; + FILE_NAME(&parm, loc); + + parm.expr = expr; if (range) { assert(range->count() == 2); assert((*range)[0]); assert((*range)[1]); - pform_cur_module->parameters[name].msb = (*range)[0]; - pform_cur_module->parameters[name].lsb = (*range)[1]; + parm.msb = (*range)[0]; + parm.lsb = (*range)[1]; } else { - pform_cur_module->parameters[name].msb = 0; - pform_cur_module->parameters[name].lsb = 0; + parm.msb = 0; + parm.lsb = 0; } - pform_cur_module->parameters[name].signed_flag = signed_flag; - pform_cur_module->parameters[name].file = filename_strings.make(file); - pform_cur_module->parameters[name].lineno = lineno; + parm.signed_flag = signed_flag; + parm.range = value_range; pform_cur_module->param_names.push_back(name); } -void pform_set_localparam(perm_string name, bool signed_flag, - svector*range, PExpr*expr, - const char*file, unsigned lineno) +void pform_set_localparam(const struct vlltype&loc, + perm_string name, bool signed_flag, + svector*range, PExpr*expr) { assert(expr); - pform_cur_module->localparams[name].expr = expr; + Module::param_expr_t&parm = pform_cur_module->localparams[name]; + FILE_NAME(&parm, loc); + + parm.expr = expr; if (range) { assert(range->count() == 2); assert((*range)[0]); assert((*range)[1]); - pform_cur_module->localparams[name].msb = (*range)[0]; - pform_cur_module->localparams[name].lsb = (*range)[1]; + parm.msb = (*range)[0]; + parm.lsb = (*range)[1]; } else { - pform_cur_module->localparams[name].msb = 0; - pform_cur_module->localparams[name].lsb = 0; + parm.msb = 0; + parm.lsb = 0; } - pform_cur_module->localparams[name].signed_flag = signed_flag; - pform_cur_module->localparams[name].file = filename_strings.make(file); - pform_cur_module->localparams[name].lineno = lineno; + parm.signed_flag = signed_flag; + parm.range = 0; } void pform_set_specparam(perm_string name, PExpr*expr) diff --git a/pform.h b/pform.h index 3e971ecee..f5b18c344 100644 --- a/pform.h +++ b/pform.h @@ -266,16 +266,20 @@ extern void pform_set_attrib(perm_string name, perm_string key, extern void pform_set_type_attrib(perm_string name, const string&key, char*value); -extern void pform_set_parameter(perm_string name, +extern Module::range_t* pform_parameter_value_range(bool exclude_flag, + bool low_open, PExpr*low_expr, + bool hig_open, PExpr*hig_expr); + +extern void pform_set_parameter(const struct vlltype&loc, + perm_string name, bool signed_flag, svector*range, - PExpr*expr, - const char*file, unsigned lineno); -extern void pform_set_localparam(perm_string name, + PExpr*expr, Module::range_t*value_range); +extern void pform_set_localparam(const struct vlltype&loc, + perm_string name, bool signed_flag, svector*range, - PExpr*expr, - const char*file, unsigned lineno); + PExpr*expr); extern void pform_set_defparam(const pform_name_t&name, PExpr*expr); /* diff --git a/pform_dump.cc b/pform_dump.cc index da55b307f..bcc973031 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1002,9 +1002,34 @@ void Module::dump(ostream&out) const << *(*cur).second.lsb << "] "; out << (*cur).first << " = "; if ((*cur).second.expr) - out << *(*cur).second.expr << ";" << endl; + out << *(*cur).second.expr; else - out << "/* ERROR */;" << endl; + out << "/* ERROR */"; + for (Module::range_t*tmp = (*cur).second.range + ; tmp ; tmp = tmp->next) { + if (tmp->exclude_flag) + out << " exclude "; + else + out << " from "; + if (tmp->low_open_flag) + out << "("; + else + out << "["; + if (tmp->low_expr) + out << *(tmp->low_expr); + else + out << "<>"; + out << ":"; + if (tmp->high_expr) + out << *(tmp->high_expr); + else + out << "<>"; + if (tmp->high_open_flag) + out << ")"; + else + out << "]"; + } + out << ";" << endl; } for (parm_iter_t cur = localparams.begin()