Enumeration element values can be expressions
Allow more complex enumeration expressions, which means putting off the evaluation of the expression values until elaboration.
This commit is contained in:
parent
2f474358d9
commit
27dfdf99dd
|
|
@ -226,12 +226,40 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||||
|
|
||||||
scope->add_enumeration_set(use_enum);
|
scope->add_enumeration_set(use_enum);
|
||||||
|
|
||||||
for (list<named_number_t>::const_iterator cur = enum_type->names->begin()
|
verinum cur_value (0);
|
||||||
|
verinum one_value (1);
|
||||||
|
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
||||||
; cur != enum_type->names->end() ; ++ cur) {
|
; cur != enum_type->names->end() ; ++ cur) {
|
||||||
|
|
||||||
|
|
||||||
|
if (cur->parm) {
|
||||||
|
// There is an explicit value. elaborate/evaluate
|
||||||
|
// the value and assign it to the enumeration name.
|
||||||
|
NetExpr*val = elab_and_eval(des, scope, cur->parm, -1);
|
||||||
|
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
|
||||||
|
if (val_const == 0) {
|
||||||
|
cerr << "<>:0: error: Enumeration expression is not constant." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cur_value = val_const->value();
|
||||||
|
|
||||||
|
if (enum_type->base_type==IVL_VT_BOOL && ! cur_value.is_defined()) {
|
||||||
|
cerr << "<>:0: error: Enumeration name " << cur->name
|
||||||
|
<< " cannot have a logic value." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (! cur_value.is_defined()) {
|
||||||
|
cerr << "<>:0: error: Enumeration name " << cur->name
|
||||||
|
<< " cannot have an inferred value." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// The values are explicitly sized to the width of the
|
// The values are explicitly sized to the width of the
|
||||||
// base type of the enumeration.
|
// base type of the enumeration.
|
||||||
verinum tmp_val (cur->parm, use_enum->base_width());
|
verinum tmp_val (cur_value, use_enum->base_width());
|
||||||
tmp_val.has_sign(enum_type->signed_flag);
|
tmp_val.has_sign(enum_type->signed_flag);
|
||||||
|
|
||||||
rc_flag = use_enum->insert_name(cur->name, tmp_val);
|
rc_flag = use_enum->insert_name(cur->name, tmp_val);
|
||||||
|
|
@ -240,6 +268,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||||
cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl;
|
cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case the next name has an implicit value,
|
||||||
|
// increment the current value by one.
|
||||||
|
if (cur_value.is_defined())
|
||||||
|
cur_value = cur_value + one_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1102,7 +1102,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
// the new signal. This turns it into an enumeration.
|
// the new signal. This turns it into an enumeration.
|
||||||
if (enum_type_) {
|
if (enum_type_) {
|
||||||
ivl_assert(*this, enum_type_->names->size() > 0);
|
ivl_assert(*this, enum_type_->names->size() > 0);
|
||||||
list<named_number_t>::const_iterator sample_name = enum_type_->names->begin();
|
list<named_pexpr_t>::const_iterator sample_name = enum_type_->names->begin();
|
||||||
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
|
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
|
||||||
sig->set_enumeration(use_enum);
|
sig->set_enumeration(use_enum);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
195
parse.y
195
parse.y
|
|
@ -193,35 +193,26 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static list<named_number_t>* make_named_number(perm_string name)
|
static list<named_pexpr_t>* make_named_numbers(perm_string name, long first, long last, PExpr*val =0)
|
||||||
{
|
{
|
||||||
list<named_number_t>*lst = new list<named_number_t>;
|
list<named_pexpr_t>*lst = new list<named_pexpr_t>;
|
||||||
named_number_t tmp;
|
named_pexpr_t tmp;
|
||||||
tmp.name = name;
|
|
||||||
lst->push_back(tmp);
|
|
||||||
return lst;
|
|
||||||
}
|
|
||||||
|
|
||||||
static list<named_number_t>* make_named_numbers(perm_string name, long first, long last, verinum*val =0)
|
|
||||||
{
|
|
||||||
list<named_number_t>*lst = new list<named_number_t>;
|
|
||||||
named_number_t tmp;
|
|
||||||
assert(first <= last);
|
assert(first <= last);
|
||||||
for (long idx = first ; idx <= last ; idx += 1) {
|
for (long idx = first ; idx <= last ; idx += 1) {
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << name.str() << idx << ends;
|
buf << name.str() << idx << ends;
|
||||||
tmp.name = lex_strings.make(buf.str());
|
tmp.name = lex_strings.make(buf.str());
|
||||||
tmp.parm = val ? *val : verinum();
|
tmp.parm = val;
|
||||||
val = 0;
|
val = 0;
|
||||||
lst->push_back(tmp);
|
lst->push_back(tmp);
|
||||||
}
|
}
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static list<named_number_t>* make_named_number(perm_string name, const verinum&val)
|
static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
|
||||||
{
|
{
|
||||||
list<named_number_t>*lst = new list<named_number_t>;
|
list<named_pexpr_t>*lst = new list<named_pexpr_t>;
|
||||||
named_number_t tmp;
|
named_pexpr_t tmp;
|
||||||
tmp.name = name;
|
tmp.name = name;
|
||||||
tmp.parm = val;
|
tmp.parm = val;
|
||||||
lst->push_back(tmp);
|
lst->push_back(tmp);
|
||||||
|
|
@ -267,7 +258,7 @@ static list<named_number_t>* make_named_number(perm_string name, const verinum&v
|
||||||
list<named_number_t>* named_numbers;
|
list<named_number_t>* named_numbers;
|
||||||
|
|
||||||
named_pexpr_t*named_pexpr;
|
named_pexpr_t*named_pexpr;
|
||||||
svector<named_pexpr_t*>*named_pexprs;
|
list<named_pexpr_t>*named_pexprs;
|
||||||
struct parmvalue_t*parmvalue;
|
struct parmvalue_t*parmvalue;
|
||||||
|
|
||||||
PExpr*expr;
|
PExpr*expr;
|
||||||
|
|
@ -418,7 +409,7 @@ static list<named_number_t>* make_named_number(perm_string name, const verinum&v
|
||||||
%type <value_range> parameter_value_ranges_opt
|
%type <value_range> parameter_value_ranges_opt
|
||||||
%type <expr> value_range_expression
|
%type <expr> value_range_expression
|
||||||
|
|
||||||
%type <named_numbers> enum_name_list enum_name
|
%type <named_pexprs> enum_name_list enum_name
|
||||||
%type <enum_type> enum_data_type
|
%type <enum_type> enum_data_type
|
||||||
|
|
||||||
%type <wires> task_item task_item_list task_item_list_opt
|
%type <wires> task_item task_item_list task_item_list_opt
|
||||||
|
|
@ -531,18 +522,19 @@ attribute_list_opt
|
||||||
;
|
;
|
||||||
|
|
||||||
attribute_list
|
attribute_list
|
||||||
: attribute_list ',' attribute
|
: attribute_list ',' attribute
|
||||||
{ svector<named_pexpr_t*>*tmp =
|
{ list<named_pexpr_t>*tmp = $1;
|
||||||
new svector<named_pexpr_t*>(*$1,$3);
|
tmp->push_back(*$3);
|
||||||
delete $1;
|
delete $3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| attribute
|
| attribute
|
||||||
{ svector<named_pexpr_t*>*tmp = new svector<named_pexpr_t*>(1);
|
{ list<named_pexpr_t>*tmp = new list<named_pexpr_t>;
|
||||||
(*tmp)[0] = $1;
|
tmp->push_back(*$1);
|
||||||
$$ = tmp;
|
delete $1;
|
||||||
}
|
$$ = tmp;
|
||||||
;
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
attribute
|
attribute
|
||||||
|
|
@ -719,7 +711,7 @@ enum_name_list
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
}
|
}
|
||||||
| enum_name_list ',' enum_name
|
| enum_name_list ',' enum_name
|
||||||
{ list<named_number_t>*lst = $1;
|
{ list<named_pexpr_t>*lst = $1;
|
||||||
lst->splice(lst->end(), *$3);
|
lst->splice(lst->end(), *$3);
|
||||||
delete $3;
|
delete $3;
|
||||||
$$ = lst;
|
$$ = lst;
|
||||||
|
|
@ -746,27 +738,24 @@ enum_name
|
||||||
delete $3;
|
delete $3;
|
||||||
delete $5;
|
delete $5;
|
||||||
}
|
}
|
||||||
| IDENTIFIER '=' number
|
| IDENTIFIER '=' expression
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ perm_string name = lex_strings.make($1);
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
$$ = make_named_number(name, *$3);
|
$$ = make_named_number(name, $3);
|
||||||
delete $3;
|
|
||||||
}
|
}
|
||||||
| IDENTIFIER '[' DEC_NUMBER ']' '=' number
|
| IDENTIFIER '[' DEC_NUMBER ']' '=' expression
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ perm_string name = lex_strings.make($1);
|
||||||
long count = $3->as_ulong();
|
long count = $3->as_ulong();
|
||||||
$$ = make_named_numbers(name, 0, count-1, $6);
|
$$ = make_named_numbers(name, 0, count-1, $6);
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
delete $3;
|
delete $3;
|
||||||
delete $6;
|
|
||||||
}
|
}
|
||||||
| IDENTIFIER '[' DEC_NUMBER ':' DEC_NUMBER ']' '=' number
|
| IDENTIFIER '[' DEC_NUMBER ':' DEC_NUMBER ']' '=' expression
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ perm_string name = lex_strings.make($1);
|
||||||
$$ = make_named_numbers(name, $3->as_long(), $5->as_long(), $8);
|
$$ = make_named_numbers(name, $3->as_long(), $5->as_long(), $8);
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
delete $3;
|
delete $3;
|
||||||
delete $5;
|
delete $5;
|
||||||
delete $8;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -3165,18 +3154,19 @@ parameter_value_byname
|
||||||
;
|
;
|
||||||
|
|
||||||
parameter_value_byname_list
|
parameter_value_byname_list
|
||||||
: parameter_value_byname
|
: parameter_value_byname
|
||||||
{ svector<named_pexpr_t*>*tmp = new svector<named_pexpr_t*>(1);
|
{ list<named_pexpr_t>*tmp = new list<named_pexpr_t>;
|
||||||
(*tmp)[0] = $1;
|
tmp->push_back(*$1);
|
||||||
$$ = tmp;
|
delete $1;
|
||||||
}
|
$$ = tmp;
|
||||||
| parameter_value_byname_list ',' parameter_value_byname
|
}
|
||||||
{ svector<named_pexpr_t*>*tmp =
|
| parameter_value_byname_list ',' parameter_value_byname
|
||||||
new svector<named_pexpr_t*>(*$1,$3);
|
{ list<named_pexpr_t>*tmp = $1;
|
||||||
delete $1;
|
tmp->push_back(*$3);
|
||||||
$$ = tmp;
|
delete $3;
|
||||||
}
|
$$ = tmp;
|
||||||
;
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/* The port (of a module) is a fairly complex item. Each port is
|
/* The port (of a module) is a fairly complex item. Each port is
|
||||||
|
|
@ -3234,6 +3224,58 @@ port_opt
|
||||||
| { $$ = 0; }
|
| { $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* The port_name rule is used with a module is being *instantiated*,
|
||||||
|
and not when it is being declared. See the port rule if you are
|
||||||
|
looking for the ports of a module declaration. */
|
||||||
|
|
||||||
|
port_name
|
||||||
|
: '.' IDENTIFIER '(' expression ')'
|
||||||
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
||||||
|
tmp->name = lex_strings.make($2);
|
||||||
|
tmp->parm = $4;
|
||||||
|
delete[]$2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| '.' IDENTIFIER '(' error ')'
|
||||||
|
{ yyerror(@3, "error: invalid port connection expression.");
|
||||||
|
named_pexpr_t*tmp = new named_pexpr_t;
|
||||||
|
tmp->name = lex_strings.make($2);
|
||||||
|
tmp->parm = 0;
|
||||||
|
delete[]$2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| '.' IDENTIFIER '(' ')'
|
||||||
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
||||||
|
tmp->name = lex_strings.make($2);
|
||||||
|
tmp->parm = 0;
|
||||||
|
delete[]$2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| '.' IDENTIFIER
|
||||||
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
||||||
|
tmp->name = lex_strings.make($2);
|
||||||
|
tmp->parm = new PEIdent(lex_strings.make($2), true);
|
||||||
|
FILE_NAME(tmp->parm, @1);
|
||||||
|
delete[]$2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
port_name_list
|
||||||
|
: port_name_list ',' port_name
|
||||||
|
{ list<named_pexpr_t>*tmp = $1;
|
||||||
|
tmp->push_back(*$3);
|
||||||
|
delete $3;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| port_name
|
||||||
|
{ list<named_pexpr_t>*tmp = new list<named_pexpr_t>;
|
||||||
|
tmp->push_back(*$1);
|
||||||
|
delete $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/* A port reference is an internal (to the module) name of the port,
|
/* A port reference is an internal (to the module) name of the port,
|
||||||
possibly with a part of bit select to attach it to specific bits
|
possibly with a part of bit select to attach it to specific bits
|
||||||
|
|
@ -3324,57 +3366,6 @@ port_reference_list
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
/* The port_name rule is used with a module is being *instantiated*,
|
|
||||||
and not when it is being declared. See the port rule if you are
|
|
||||||
looking for the ports of a module declaration. */
|
|
||||||
|
|
||||||
port_name
|
|
||||||
: '.' IDENTIFIER '(' expression ')'
|
|
||||||
{ named_pexpr_t*tmp = new named_pexpr_t;
|
|
||||||
tmp->name = lex_strings.make($2);
|
|
||||||
tmp->parm = $4;
|
|
||||||
delete[]$2;
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| '.' IDENTIFIER '(' error ')'
|
|
||||||
{ yyerror(@3, "error: invalid port connection expression.");
|
|
||||||
named_pexpr_t*tmp = new named_pexpr_t;
|
|
||||||
tmp->name = lex_strings.make($2);
|
|
||||||
tmp->parm = 0;
|
|
||||||
delete[]$2;
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| '.' IDENTIFIER '(' ')'
|
|
||||||
{ named_pexpr_t*tmp = new named_pexpr_t;
|
|
||||||
tmp->name = lex_strings.make($2);
|
|
||||||
tmp->parm = 0;
|
|
||||||
delete[]$2;
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| '.' IDENTIFIER
|
|
||||||
{ named_pexpr_t*tmp = new named_pexpr_t;
|
|
||||||
tmp->name = lex_strings.make($2);
|
|
||||||
tmp->parm = new PEIdent(lex_strings.make($2), true);
|
|
||||||
FILE_NAME(tmp->parm, @1);
|
|
||||||
delete[]$2;
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
port_name_list
|
|
||||||
: port_name_list ',' port_name
|
|
||||||
{ svector<named_pexpr_t*>*tmp;
|
|
||||||
tmp = new svector<named_pexpr_t*>(*$1, $3);
|
|
||||||
delete $1;
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| port_name
|
|
||||||
{ svector<named_pexpr_t*>*tmp = new svector<named_pexpr_t*>(1);
|
|
||||||
(*tmp)[0] = $1;
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
port_type
|
port_type
|
||||||
: K_input { $$ = NetNet::PINPUT; }
|
: K_input { $$ = NetNet::PINPUT; }
|
||||||
| K_output { $$ = NetNet::POUTPUT; }
|
| K_output { $$ = NetNet::POUTPUT; }
|
||||||
|
|
|
||||||
141
pform.cc
141
pform.cc
|
|
@ -350,16 +350,18 @@ PGenerate* pform_parent_generate(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
|
void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr, bool keep_attrs)
|
||||||
{
|
{
|
||||||
if (attr == 0)
|
if (attr == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
while (attr->size() > 0) {
|
||||||
named_pexpr_t*tmp = (*attr)[idx];
|
named_pexpr_t tmp = attr->front();
|
||||||
attributes[tmp->name] = tmp->parm;
|
attr->pop_front();
|
||||||
|
attributes[tmp.name] = tmp.parm;
|
||||||
}
|
}
|
||||||
delete attr;
|
if (!keep_attrs)
|
||||||
|
delete attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pform_at_module_level()
|
static bool pform_at_module_level()
|
||||||
|
|
@ -689,7 +691,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
assert( pform_cur_module == 0 );
|
assert( pform_cur_module == 0 );
|
||||||
|
|
||||||
|
|
@ -724,12 +726,7 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||||
cerr << pform_timescale_file << ":" << pform_timescale_line
|
cerr << pform_timescale_file << ":" << pform_timescale_line
|
||||||
<< ": ...: The inherited timescale is here." << endl;
|
<< ": ...: The inherited timescale is here." << endl;
|
||||||
}
|
}
|
||||||
if (attr) {
|
pform_bind_attributes(pform_cur_module->attributes, attr);
|
||||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
|
||||||
named_pexpr_t*tmp = (*attr)[idx];
|
|
||||||
pform_cur_module->attributes[tmp->name] = tmp->parm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1505,11 +1502,11 @@ void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
|
||||||
* are ready to be instantiated. The function runs through the list of
|
* are ready to be instantiated. The function runs through the list of
|
||||||
* gates and calls the pform_makegate function to make the individual gate.
|
* gates and calls the pform_makegate function to make the individual gate.
|
||||||
*/
|
*/
|
||||||
void pform_makegate(PGBuiltin::Type type,
|
static void pform_makegate(PGBuiltin::Type type,
|
||||||
struct str_pair_t str,
|
struct str_pair_t str,
|
||||||
list<PExpr*>* delay,
|
list<PExpr*>* delay,
|
||||||
const lgate&info,
|
const lgate&info,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
if (info.parms_by_name) {
|
if (info.parms_by_name) {
|
||||||
cerr << info.file << ":" << info.lineno << ": Gates do not "
|
cerr << info.file << ":" << info.lineno << ": Gates do not "
|
||||||
|
|
@ -1528,12 +1525,10 @@ void pform_makegate(PGBuiltin::Type type,
|
||||||
if (info.range[0])
|
if (info.range[0])
|
||||||
cur->set_range(info.range[0], info.range[1]);
|
cur->set_range(info.range[0], info.range[1]);
|
||||||
|
|
||||||
if (attr) {
|
// The pform_makegates() that calls me will take care of
|
||||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
// deleting the attr pointer, so tell the
|
||||||
named_pexpr_t*tmp = (*attr)[idx];
|
// pform_bind_attributes function to keep the attr object.
|
||||||
cur->attributes[tmp->name] = tmp->parm;
|
pform_bind_attributes(cur->attributes, attr, true);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur->strength0(str.str0);
|
cur->strength0(str.str0);
|
||||||
cur->strength1(str.str1);
|
cur->strength1(str.str1);
|
||||||
|
|
@ -1549,20 +1544,13 @@ void pform_makegates(PGBuiltin::Type type,
|
||||||
struct str_pair_t str,
|
struct str_pair_t str,
|
||||||
list<PExpr*>*delay,
|
list<PExpr*>*delay,
|
||||||
svector<lgate>*gates,
|
svector<lgate>*gates,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
for (unsigned idx = 0 ; idx < gates->count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < gates->count() ; idx += 1) {
|
||||||
pform_makegate(type, str, delay, (*gates)[idx], attr);
|
pform_makegate(type, str, delay, (*gates)[idx], attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr) {
|
if (attr) delete attr;
|
||||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
|
||||||
named_pexpr_t*cur = (*attr)[idx];
|
|
||||||
delete cur;
|
|
||||||
}
|
|
||||||
delete attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete gates;
|
delete gates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1597,13 +1585,13 @@ static void pform_make_modgate(perm_string type,
|
||||||
cur->set_range(msb,lsb);
|
cur->set_range(msb,lsb);
|
||||||
|
|
||||||
if (overrides && overrides->by_name) {
|
if (overrides && overrides->by_name) {
|
||||||
unsigned cnt = overrides->by_name->count();
|
unsigned cnt = overrides->by_name->size();
|
||||||
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
list<named_pexpr_t>::iterator by_name_cur = overrides->by_name->begin();
|
||||||
named_pexpr_t*curp = (*overrides->by_name)[idx];
|
for (unsigned idx = 0 ; idx < cnt ; idx += 1, ++ by_name_cur) {
|
||||||
byname[idx].name = curp->name;
|
byname[idx].name = by_name_cur->name;
|
||||||
byname[idx].parm = curp->parm;
|
byname[idx].parm = by_name_cur->parm;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur->set_parameters(byname, cnt);
|
cur->set_parameters(byname, cnt);
|
||||||
|
|
@ -1621,17 +1609,17 @@ static void pform_make_modgate(perm_string type,
|
||||||
static void pform_make_modgate(perm_string type,
|
static void pform_make_modgate(perm_string type,
|
||||||
perm_string name,
|
perm_string name,
|
||||||
struct parmvalue_t*overrides,
|
struct parmvalue_t*overrides,
|
||||||
svector<named_pexpr_t*>*bind,
|
list<named_pexpr_t>*bind,
|
||||||
PExpr*msb, PExpr*lsb,
|
PExpr*msb, PExpr*lsb,
|
||||||
const char*fn, unsigned ln)
|
const char*fn, unsigned ln)
|
||||||
{
|
{
|
||||||
unsigned npins = bind->count();
|
unsigned npins = bind->size();
|
||||||
named<PExpr*>*pins = new named<PExpr*>[npins];
|
named<PExpr*>*pins = new named<PExpr*>[npins];
|
||||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
list<named_pexpr_t>::iterator bind_cur = bind->begin();
|
||||||
named_pexpr_t*curp = (*bind)[idx];
|
for (unsigned idx = 0 ; idx < npins ; idx += 1, ++bind_cur) {
|
||||||
pins[idx].name = curp->name;
|
pins[idx].name = bind_cur->name;
|
||||||
pins[idx].parm = curp->parm;
|
pins[idx].parm = bind_cur->parm;
|
||||||
pform_declare_implicit_nets(curp->parm);
|
pform_declare_implicit_nets(bind_cur->parm);
|
||||||
}
|
}
|
||||||
|
|
||||||
PGModule*cur = new PGModule(type, name, pins, npins);
|
PGModule*cur = new PGModule(type, name, pins, npins);
|
||||||
|
|
@ -1639,13 +1627,13 @@ static void pform_make_modgate(perm_string type,
|
||||||
cur->set_range(msb,lsb);
|
cur->set_range(msb,lsb);
|
||||||
|
|
||||||
if (overrides && overrides->by_name) {
|
if (overrides && overrides->by_name) {
|
||||||
unsigned cnt = overrides->by_name->count();
|
unsigned cnt = overrides->by_name->size();
|
||||||
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
list<named_pexpr_t>::iterator by_name_cur = overrides->by_name->begin();
|
||||||
named_pexpr_t*curp = (*overrides->by_name)[idx];
|
for (unsigned idx = 0 ; idx < cnt ; idx += 1, ++by_name_cur) {
|
||||||
byname[idx].name = curp->name;
|
byname[idx].name = by_name_cur->name;
|
||||||
byname[idx].parm = curp->parm;
|
byname[idx].parm = by_name_cur->parm;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur->set_parameters(byname, cnt);
|
cur->set_parameters(byname, cnt);
|
||||||
|
|
@ -1809,7 +1797,7 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
ivl_variable_type_t data_type,
|
ivl_variable_type_t data_type,
|
||||||
bool signed_flag,
|
bool signed_flag,
|
||||||
list<PExpr*>*range,
|
list<PExpr*>*range,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
PWire*cur = pform_get_wire_in_scope(name);
|
PWire*cur = pform_get_wire_in_scope(name);
|
||||||
if (cur) {
|
if (cur) {
|
||||||
|
|
@ -1844,12 +1832,7 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr) {
|
pform_bind_attributes(cur->attributes, attr);
|
||||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
|
||||||
named_pexpr_t*tmp = (*attr)[idx];
|
|
||||||
cur->attributes[tmp->name] = tmp->parm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pform_put_wire_in_scope(name, cur);
|
pform_put_wire_in_scope(name, cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1881,7 +1864,7 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
void pform_makewire(const vlltype&li, perm_string name,
|
void pform_makewire(const vlltype&li, perm_string name,
|
||||||
NetNet::Type type, NetNet::PortType pt,
|
NetNet::Type type, NetNet::PortType pt,
|
||||||
ivl_variable_type_t dt,
|
ivl_variable_type_t dt,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
PWire*cur = pform_get_wire_in_scope(name);
|
PWire*cur = pform_get_wire_in_scope(name);
|
||||||
|
|
||||||
|
|
@ -1929,9 +1912,9 @@ void pform_makewire(const vlltype&li, perm_string name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr) {
|
if (attr) {
|
||||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
for (list<named_pexpr_t>::iterator attr_cur = attr->begin()
|
||||||
named_pexpr_t*tmp = (*attr)[idx];
|
; attr_cur != attr->end() ; ++attr_cur) {
|
||||||
cur->attributes[tmp->name] = tmp->parm;
|
cur->attributes[attr_cur->name] = attr_cur->parm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1951,7 +1934,7 @@ void pform_makewire(const vlltype&li,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
NetNet::PortType pt,
|
NetNet::PortType pt,
|
||||||
ivl_variable_type_t dt,
|
ivl_variable_type_t dt,
|
||||||
svector<named_pexpr_t*>*attr,
|
list<named_pexpr_t>*attr,
|
||||||
PWSRType rt)
|
PWSRType rt)
|
||||||
{
|
{
|
||||||
for (list<perm_string>::iterator cur = names->begin()
|
for (list<perm_string>::iterator cur = names->begin()
|
||||||
|
|
@ -2484,40 +2467,6 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
||||||
assert(enum_type->range.get() != 0);
|
assert(enum_type->range.get() != 0);
|
||||||
assert(enum_type->range->size() == 2);
|
assert(enum_type->range->size() == 2);
|
||||||
|
|
||||||
// Scan the list of enum name declarations and evaluate them
|
|
||||||
// to a map of names with values. This expands out the
|
|
||||||
// inferred values (if any) and checks for duplicates.
|
|
||||||
verinum cur_value (0);
|
|
||||||
verinum one_value (1);
|
|
||||||
for (list<named_number_t>::iterator cur = enum_type->names->begin()
|
|
||||||
; cur != enum_type->names->end() ; ++ cur) {
|
|
||||||
|
|
||||||
verinum next_value = cur->parm;
|
|
||||||
if (next_value.len() == 0) {
|
|
||||||
if (! cur_value.is_defined()) {
|
|
||||||
cerr << li.text << ":" << li.first_line << ": "
|
|
||||||
<< "error: Enumeration name " << cur->name
|
|
||||||
<< " cannot have inferred value." << endl;
|
|
||||||
next_value = cur_value;
|
|
||||||
error_count += 1;
|
|
||||||
} else {
|
|
||||||
next_value = cur_value;
|
|
||||||
cur_value = cur_value + one_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur->parm = next_value;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (enum_type->base_type==IVL_VT_BOOL && ! next_value.is_defined()) {
|
|
||||||
cerr << li.text << ":" << li.first_line << ": "
|
|
||||||
<< "error: Enumeration name " << cur->name
|
|
||||||
<< " Cannot have logic value " << next_value << "." << endl;
|
|
||||||
error_count += 1;
|
|
||||||
}
|
|
||||||
cur_value = next_value + one_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach the enumeration to the current scope.
|
// Attach the enumeration to the current scope.
|
||||||
pform_put_enum_type_in_scope(enum_type);
|
pform_put_enum_type_in_scope(enum_type);
|
||||||
|
|
||||||
|
|
@ -2554,7 +2503,7 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||||
}
|
}
|
||||||
|
|
||||||
PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
|
PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
|
||||||
svector<named_pexpr_t*>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
PProcess*pp = new PProcess(type, st);
|
PProcess*pp = new PProcess(type, st);
|
||||||
|
|
||||||
|
|
|
||||||
20
pform.h
20
pform.h
|
|
@ -84,11 +84,10 @@ extern bool pform_library_flag;
|
||||||
/* This is information about port name information for named port
|
/* This is information about port name information for named port
|
||||||
connections. */
|
connections. */
|
||||||
|
|
||||||
typedef named<PExpr*> named_pexpr_t;
|
|
||||||
|
|
||||||
struct parmvalue_t {
|
struct parmvalue_t {
|
||||||
list<PExpr*>*by_order;
|
list<PExpr*>*by_order;
|
||||||
svector<named_pexpr_t*>*by_name;
|
list<named_pexpr_t>*by_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct str_pair_t { ivl_drive_t str0, str1; };
|
struct str_pair_t { ivl_drive_t str0, str1; };
|
||||||
|
|
@ -110,7 +109,7 @@ struct lgate {
|
||||||
|
|
||||||
string name;
|
string name;
|
||||||
list<PExpr*>*parms;
|
list<PExpr*>*parms;
|
||||||
svector<named_pexpr_t*>*parms_by_name;
|
list<named_pexpr_t>*parms_by_name;
|
||||||
|
|
||||||
PExpr*range[2];
|
PExpr*range[2];
|
||||||
|
|
||||||
|
|
@ -121,7 +120,8 @@ struct lgate {
|
||||||
/* Use this function to transform the parted form of the attribute
|
/* Use this function to transform the parted form of the attribute
|
||||||
list to the attribute map that is used later. */
|
list to the attribute map that is used later. */
|
||||||
extern void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
|
extern void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
|
||||||
svector<named_pexpr_t*>*attr);
|
list<named_pexpr_t>*attr,
|
||||||
|
bool keep_attr =false);
|
||||||
|
|
||||||
/* The lexor calls this function to change the default nettype. */
|
/* The lexor calls this function to change the default nettype. */
|
||||||
extern void pform_set_default_nettype(NetNet::Type net,
|
extern void pform_set_default_nettype(NetNet::Type net,
|
||||||
|
|
@ -143,7 +143,7 @@ extern PWire* pform_get_wire_in_scope(perm_string name);
|
||||||
* pform to close up and finish the named module.
|
* pform to close up and finish the named module.
|
||||||
*/
|
*/
|
||||||
extern void pform_startmodule(const char*, const char*file, unsigned lineno,
|
extern void pform_startmodule(const char*, const char*file, unsigned lineno,
|
||||||
svector<named_pexpr_t*>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
extern void pform_check_timeunit_prec();
|
extern void pform_check_timeunit_prec();
|
||||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||||
|
|
||||||
|
|
@ -157,7 +157,7 @@ extern void pform_module_define_port(const struct vlltype&li,
|
||||||
ivl_variable_type_t data_type,
|
ivl_variable_type_t data_type,
|
||||||
bool signed_flag,
|
bool signed_flag,
|
||||||
list<PExpr*>*range,
|
list<PExpr*>*range,
|
||||||
svector<named_pexpr_t*>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||||
const char*file,
|
const char*file,
|
||||||
|
|
@ -230,7 +230,7 @@ extern void pform_makewire(const struct vlltype&li, perm_string name,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
NetNet::PortType pt,
|
NetNet::PortType pt,
|
||||||
ivl_variable_type_t,
|
ivl_variable_type_t,
|
||||||
svector<named_pexpr_t*>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
/* This form handles simple declarations */
|
/* This form handles simple declarations */
|
||||||
extern void pform_makewire(const struct vlltype&li,
|
extern void pform_makewire(const struct vlltype&li,
|
||||||
|
|
@ -240,7 +240,7 @@ extern void pform_makewire(const struct vlltype&li,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
NetNet::PortType,
|
NetNet::PortType,
|
||||||
ivl_variable_type_t,
|
ivl_variable_type_t,
|
||||||
svector<named_pexpr_t*>*attr,
|
list<named_pexpr_t>*attr,
|
||||||
PWSRType rt = SR_NET);
|
PWSRType rt = SR_NET);
|
||||||
|
|
||||||
/* This form handles assignment declarations. */
|
/* This form handles assignment declarations. */
|
||||||
|
|
@ -329,7 +329,7 @@ extern void pform_module_specify_path(PSpecPath*obj);
|
||||||
* or initial items.
|
* or initial items.
|
||||||
*/
|
*/
|
||||||
extern PProcess* pform_make_behavior(ivl_process_type_t, Statement*,
|
extern PProcess* pform_make_behavior(ivl_process_type_t, Statement*,
|
||||||
svector<named_pexpr_t*>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
extern svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*);
|
extern svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*);
|
||||||
|
|
||||||
|
|
@ -349,7 +349,7 @@ extern void pform_makegates(PGBuiltin::Type type,
|
||||||
struct str_pair_t str,
|
struct str_pair_t str,
|
||||||
list<PExpr*>*delay,
|
list<PExpr*>*delay,
|
||||||
svector<lgate>*gates,
|
svector<lgate>*gates,
|
||||||
svector<named_pexpr_t*>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
extern void pform_make_modgates(perm_string type,
|
extern void pform_make_modgates(perm_string type,
|
||||||
struct parmvalue_t*overrides,
|
struct parmvalue_t*overrides,
|
||||||
|
|
|
||||||
|
|
@ -1112,7 +1112,7 @@ void LexicalScope::dump_enumerations_(ostream&out, unsigned indent) const
|
||||||
; cur != enum_sets.end() ; ++ cur) {
|
; cur != enum_sets.end() ; ++ cur) {
|
||||||
out << setw(indent) << "" << "enum {" << endl;
|
out << setw(indent) << "" << "enum {" << endl;
|
||||||
|
|
||||||
for (list<named_number_t>::const_iterator idx = (*cur)->names->begin()
|
for (list<named_pexpr_t>::const_iterator idx = (*cur)->names->begin()
|
||||||
; idx != (*cur)->names->end() ; ++ idx) {
|
; idx != (*cur)->names->end() ; ++ idx) {
|
||||||
out << setw(indent+4) << "" << idx->name
|
out << setw(indent+4) << "" << idx->name
|
||||||
<< " = " << idx->parm << endl;
|
<< " = " << idx->parm << endl;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@
|
||||||
* parse-form types.
|
* parse-form types.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class PExpr;
|
||||||
typedef named<verinum> named_number_t;
|
typedef named<verinum> named_number_t;
|
||||||
|
typedef named<PExpr*> named_pexpr_t;
|
||||||
|
|
||||||
struct index_component_t {
|
struct index_component_t {
|
||||||
enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO };
|
enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO };
|
||||||
|
|
@ -63,7 +65,7 @@ struct enum_type_t {
|
||||||
ivl_variable_type_t base_type;
|
ivl_variable_type_t base_type;
|
||||||
bool signed_flag;
|
bool signed_flag;
|
||||||
auto_ptr< list<PExpr*> > range;
|
auto_ptr< list<PExpr*> > range;
|
||||||
auto_ptr< list<named_number_t> > names;
|
auto_ptr< list<named_pexpr_t> > names;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue