Parse parameter value ranges into pform.

Handle parameter value ranges as far as the pform. The +-inf expressions
are not handled yet, nor is the single value exclude, but the other
cases are handled.
This commit is contained in:
Stephen Williams 2008-05-12 21:26:38 -07:00
parent cbf96d73ee
commit 2172c8a503
7 changed files with 149 additions and 64 deletions

View File

@ -75,16 +75,29 @@ class Module : public PScope, public LineInfo {
NetNet::Type default_nettype; 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 /* The module has parameters that are evaluated when the
module is elaborated. During parsing, I put the parameters module is elaborated. During parsing, I put the parameters
into this map. */ into this map. */
struct param_expr_t { struct param_expr_t : public LineInfo {
PExpr*expr; PExpr*expr;
PExpr*msb; PExpr*msb;
PExpr*lsb; PExpr*lsb;
perm_string file;
unsigned lineno;
bool signed_flag; bool signed_flag;
// If there are range constrants, list them here
range_t*range;
}; };
map<perm_string,param_expr_t>parameters; map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams; map<perm_string,param_expr_t>localparams;
@ -158,8 +171,7 @@ class Module : public PScope, public LineInfo {
map<perm_string,PFunction*> funcs_; map<perm_string,PFunction*> funcs_;
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur, static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope, Design*des, NetScope*scope);
perm_string file, unsigned lineno);
private: // Not implemented private: // Not implemented
Module(const Module&); Module(const Module&);

View File

@ -45,8 +45,7 @@
# include <assert.h> # include <assert.h>
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope, Design*des, NetScope*scope)
perm_string file, unsigned lineno)
{ {
PExpr*ex = cur.expr; PExpr*ex = cur.expr;
assert(ex); assert(ex);
@ -81,8 +80,8 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
signed_flag = val->has_sign(); signed_flag = val->has_sign();
} }
val = scope->set_parameter(name, val, val = scope->set_parameter(name, val, msb, lsb, signed_flag,
msb, lsb, signed_flag, file, lineno); cur.get_file(), cur.get_lineno());
assert(val); assert(val);
delete val; delete val;
} }
@ -121,7 +120,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
tmp->cast_signed( (*cur).second.signed_flag ); tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false, 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() 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 ); tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false, 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() for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) { ; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope, elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
(*cur).second.file, (*cur).second.lineno);
} }
/* run parameter replacements that were collected from the /* 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() for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) { ; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope, elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
(*cur).second.file, (*cur).second.lineno);
} }
// Run through the defparams for this module, elaborate the // Run through the defparams for this module, elaborate the

View File

@ -79,6 +79,7 @@ hypot, GN_KEYWORDS_VAMS_2_3, K_hypot
idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature
if, GN_KEYWORDS_1364_1995, K_if if, GN_KEYWORDS_1364_1995, K_if
ifnone, GN_KEYWORDS_1364_1995, K_ifnone ifnone, GN_KEYWORDS_1364_1995, K_ifnone
inf, GN_KEYWORDS_VAMS_2_3, K_inf
initial, GN_KEYWORDS_1364_1995, K_initial initial, GN_KEYWORDS_1364_1995, K_initial
inout, GN_KEYWORDS_1364_1995, K_inout inout, GN_KEYWORDS_1364_1995, K_inout
input, GN_KEYWORDS_1364_1995, K_input input, GN_KEYWORDS_1364_1995, K_input

65
parse.y
View File

@ -156,6 +156,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
svector<lgate>*gates; svector<lgate>*gates;
Module::port_t *mport; Module::port_t *mport;
Module::range_t* value_range;
svector<Module::port_t*>*mports; svector<Module::port_t*>*mports;
named_pexpr_t*named_pexpr; 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_endprimitive K_endspecify K_endtable K_endtask K_event
%token K_exclude K_exp K_floor K_flow K_from %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_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_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_log K_logic K_macromodule K_max
%token K_medium K_min K_module K_nand K_nature K_negedge %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 %token KK_attribute
%type <flag> from_exclude
%type <number> number %type <number> number
%type <flag> signed_opt udp_reg_opt edge_operator %type <flag> signed_opt udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1 %type <drive> 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 <mport> port port_opt port_reference port_reference_list %type <mport> port port_opt port_reference port_reference_list
%type <mport> port_declaration %type <mport> port_declaration
%type <mports> list_of_ports module_port_list_opt list_of_port_declarations %type <mports> list_of_ports module_port_list_opt list_of_port_declarations
%type <value_range> parameter_value_range parameter_value_ranges
%type <value_range> parameter_value_ranges_opt
%type <expr> value_range_expression
%type <wires> task_item task_item_list task_item_list_opt %type <wires> task_item task_item_list task_item_list_opt
%type <wires> task_port_item task_port_decl task_port_decl_list %type <wires> task_port_item task_port_decl task_port_decl_list
@ -2375,22 +2380,43 @@ parameter_assign_list
; ;
parameter_assign parameter_assign
: IDENTIFIER '=' expression : IDENTIFIER '=' expression parameter_value_ranges_opt
{ PExpr*tmp = $3; { PExpr*tmp = $3;
if (!pform_expression_is_constant(tmp)) { pform_set_parameter(@1, lex_strings.make($1),
yyerror(@3, "error: parameter value " active_signed, active_range, tmp, $4);
"must be a constant expression."); delete[]$1;
delete tmp; }
tmp = 0; ;
} else {
pform_set_parameter(lex_strings.make($1), parameter_value_ranges_opt : parameter_value_ranges { $$ = $1; } | { $$ = 0; } ;
active_signed,
active_range, tmp, parameter_value_ranges
@1.text, @1.first_line); : parameter_value_ranges parameter_value_range
} { $$ = $2; $$->next = $1; }
delete[]$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 /* Localparam assignments and assignment lists are broken into
separate BNF so that I can call slightly different parameter separate BNF so that I can call slightly different parameter
@ -2406,10 +2432,9 @@ localparam_assign
delete tmp; delete tmp;
tmp = 0; tmp = 0;
} else { } else {
pform_set_localparam(lex_strings.make($1), pform_set_localparam(@1, lex_strings.make($1),
active_signed, active_signed,
active_range, tmp, active_range, tmp);
@1.text, @1.first_line);
} }
delete[]$1; delete[]$1;
} }

View File

@ -1634,50 +1634,69 @@ void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
cur->set_memory_idx(l, 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<PExpr*>*range, PExpr*expr, svector<PExpr*>*range, PExpr*expr,
const char*file, unsigned lineno) Module::range_t*value_range)
{ {
assert(expr); 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) { if (range) {
assert(range->count() == 2); assert(range->count() == 2);
assert((*range)[0]); assert((*range)[0]);
assert((*range)[1]); assert((*range)[1]);
pform_cur_module->parameters[name].msb = (*range)[0]; parm.msb = (*range)[0];
pform_cur_module->parameters[name].lsb = (*range)[1]; parm.lsb = (*range)[1];
} else { } else {
pform_cur_module->parameters[name].msb = 0; parm.msb = 0;
pform_cur_module->parameters[name].lsb = 0; parm.lsb = 0;
} }
pform_cur_module->parameters[name].signed_flag = signed_flag; parm.signed_flag = signed_flag;
pform_cur_module->parameters[name].file = filename_strings.make(file); parm.range = value_range;
pform_cur_module->parameters[name].lineno = lineno;
pform_cur_module->param_names.push_back(name); pform_cur_module->param_names.push_back(name);
} }
void pform_set_localparam(perm_string name, bool signed_flag, void pform_set_localparam(const struct vlltype&loc,
svector<PExpr*>*range, PExpr*expr, perm_string name, bool signed_flag,
const char*file, unsigned lineno) svector<PExpr*>*range, PExpr*expr)
{ {
assert(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) { if (range) {
assert(range->count() == 2); assert(range->count() == 2);
assert((*range)[0]); assert((*range)[0]);
assert((*range)[1]); assert((*range)[1]);
pform_cur_module->localparams[name].msb = (*range)[0]; parm.msb = (*range)[0];
pform_cur_module->localparams[name].lsb = (*range)[1]; parm.lsb = (*range)[1];
} else { } else {
pform_cur_module->localparams[name].msb = 0; parm.msb = 0;
pform_cur_module->localparams[name].lsb = 0; parm.lsb = 0;
} }
pform_cur_module->localparams[name].signed_flag = signed_flag; parm.signed_flag = signed_flag;
pform_cur_module->localparams[name].file = filename_strings.make(file); parm.range = 0;
pform_cur_module->localparams[name].lineno = lineno;
} }
void pform_set_specparam(perm_string name, PExpr*expr) void pform_set_specparam(perm_string name, PExpr*expr)

16
pform.h
View File

@ -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, extern void pform_set_type_attrib(perm_string name, const string&key,
char*value); 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, bool signed_flag,
svector<PExpr*>*range, svector<PExpr*>*range,
PExpr*expr, PExpr*expr, Module::range_t*value_range);
const char*file, unsigned lineno); extern void pform_set_localparam(const struct vlltype&loc,
extern void pform_set_localparam(perm_string name, perm_string name,
bool signed_flag, bool signed_flag,
svector<PExpr*>*range, svector<PExpr*>*range,
PExpr*expr, PExpr*expr);
const char*file, unsigned lineno);
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr); extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
/* /*

View File

@ -1002,9 +1002,34 @@ void Module::dump(ostream&out) const
<< *(*cur).second.lsb << "] "; << *(*cur).second.lsb << "] ";
out << (*cur).first << " = "; out << (*cur).first << " = ";
if ((*cur).second.expr) if ((*cur).second.expr)
out << *(*cur).second.expr << ";" << endl; out << *(*cur).second.expr;
else 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() for (parm_iter_t cur = localparams.begin()