V0.9: Fix for br930 - support attributes on old-style port declarations.

This commit is contained in:
Martin Whitaker 2013-05-19 11:05:01 +01:00
parent c8c0a298e4
commit 4efb601fee
3 changed files with 57 additions and 47 deletions

76
parse.y
View File

@ -2093,7 +2093,6 @@ module_item
yyerror(@6, "sorry: net delays not supported."); yyerror(@6, "sorry: net delays not supported.");
delete $6; delete $6;
} }
if ($1) delete $1;
} }
/* Very similar to the rule above, but this takes a list of /* Very similar to the rule above, but this takes a list of
@ -2140,58 +2139,55 @@ module_item
delete $4; delete $4;
} }
| port_type signed_opt range_opt delay3_opt list_of_identifiers ';' | attribute_list_opt port_type signed_opt range_opt delay3_opt list_of_identifiers ';'
{ pform_set_port_type(@1, $5, $3, $2, $1); { pform_set_port_type(@2, $6, $4, $3, $2, $1); }
}
/* The next two rules handle Verilog 2001 statements of the form: /* The next two rules handle Verilog 2001 statements of the form:
input wire signed [h:l] <list>; input wire signed [h:l] <list>;
This creates the wire and sets the port type all at once. */ This creates the wire and sets the port type all at once. */
| port_type net_type signed_opt range_opt list_of_identifiers ';' | attribute_list_opt port_type net_type signed_opt range_opt list_of_identifiers ';'
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0, { pform_makewire(@2, $5, $4, $6, $3, $2, IVL_VT_NO_TYPE, $1, SR_BOTH); }
SR_BOTH);
}
| K_output var_type signed_opt range_opt list_of_port_identifiers ';' | attribute_list_opt K_output var_type signed_opt range_opt list_of_port_identifiers ';'
{ list<pair<perm_string,PExpr*> >::const_iterator pp; { list<pair<perm_string,PExpr*> >::const_iterator pp;
list<perm_string>*tmp = new list<perm_string>; list<perm_string>*tmp = new list<perm_string>;
for (pp = $5->begin(); pp != $5->end(); pp++) { for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
tmp->push_back((*pp).first); tmp->push_back((*pp).first);
} }
pform_makewire(@1, $4, $3, tmp, $2, NetNet::POUTPUT, pform_makewire(@2, $5, $4, tmp, $3, NetNet::POUTPUT,
IVL_VT_NO_TYPE, 0, SR_BOTH); IVL_VT_NO_TYPE, $1, SR_BOTH);
for (pp = $5->begin(); pp != $5->end(); pp++) { for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
if ((*pp).second) { if ((*pp).second) {
pform_make_reginit(@1, (*pp).first, (*pp).second); pform_make_reginit(@2, (*pp).first, (*pp).second);
} }
} }
delete $5; delete $6;
} }
/* var_type declaration (reg variables) cannot be input or output, /* var_type declaration (reg variables) cannot be input or output,
because the port declaration implies an external driver, which because the port declaration implies an external driver, which
cannot be attached to a reg. These rules catch that error early. */ cannot be attached to a reg. These rules catch that error early. */
| K_input var_type signed_opt range_opt list_of_identifiers ';' | attribute_list_opt K_input var_type signed_opt range_opt list_of_identifiers ';'
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINPUT, { pform_makewire(@2, $5, $4, $6, $3, NetNet::PINPUT,
IVL_VT_NO_TYPE, 0); IVL_VT_NO_TYPE, $1);
yyerror(@2, "error: reg variables cannot be inputs."); yyerror(@3, "error: reg variables cannot be inputs.");
} }
| K_inout var_type signed_opt range_opt list_of_identifiers ';' | attribute_list_opt K_inout var_type signed_opt range_opt list_of_identifiers ';'
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINOUT, { pform_makewire(@2, $5, $4, $6, $3, NetNet::PINOUT,
IVL_VT_NO_TYPE, 0); IVL_VT_NO_TYPE, $1);
yyerror(@2, "error: reg variables cannot be inouts."); yyerror(@3, "error: reg variables cannot be inouts.");
} }
| port_type signed_opt range_opt delay3_opt error ';' | attribute_list_opt port_type signed_opt range_opt delay3_opt error ';'
{ yyerror(@1, "error: Invalid variable list" { yyerror(@2, "error: Invalid variable list in port declaration.");
" in port declaration."); if ($1) delete $1;
if ($3) delete $3; if ($4) delete $4;
if ($4) delete $4; if ($5) delete $5;
yyerrok; yyerrok;
} }
/* Maybe this is a discipline declaration? If so, then the lexor /* Maybe this is a discipline declaration? If so, then the lexor
will see the discipline name as an identifier. We match it to the will see the discipline name as an identifier. We match it to the

View File

@ -1094,7 +1094,8 @@ static void pform_set_net_range(perm_string name,
const svector<PExpr*>*range, const svector<PExpr*>*range,
bool signed_flag, bool signed_flag,
ivl_variable_type_t dt, ivl_variable_type_t dt,
PWSRType rt) PWSRType rt,
svector<named_pexpr_t*>*attr)
{ {
PWire*cur = pform_get_wire_in_scope(name); PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) { if (cur == 0) {
@ -1117,6 +1118,13 @@ static void pform_set_net_range(perm_string name,
if (dt != IVL_VT_NO_TYPE) if (dt != IVL_VT_NO_TYPE)
cur->set_data_type(dt); cur->set_data_type(dt);
if (attr) {
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
named_pexpr_t*tmp = (*attr)[idx];
cur->attributes[tmp->name] = tmp->parm;
}
}
} }
void pform_set_net_range(list<perm_string>*names, void pform_set_net_range(list<perm_string>*names,
@ -1131,7 +1139,7 @@ void pform_set_net_range(list<perm_string>*names,
; cur != names->end() ; cur != names->end()
; cur ++ ) { ; cur ++ ) {
perm_string txt = *cur; perm_string txt = *cur;
pform_set_net_range(txt, range, signed_flag, dt, rt); pform_set_net_range(txt, range, signed_flag, dt, rt, 0);
} }
delete names; delete names;
@ -1614,13 +1622,15 @@ void pform_makewire(const vlltype&li,
pform_makewire(li, txt, type, pt, dt, attr); pform_makewire(li, txt, type, pt, dt, attr);
/* This has already been done for real variables. */ /* This has already been done for real variables. */
if (dt != IVL_VT_REAL) { if (dt != IVL_VT_REAL) {
pform_set_net_range(txt, range, signed_flag, dt, rt); pform_set_net_range(txt, range, signed_flag, dt, rt, 0);
} }
} }
delete names; delete names;
if (range) if (range)
delete range; delete range;
if (attr)
delete attr;
} }
/* /*
@ -1645,7 +1655,7 @@ void pform_makewire(const vlltype&li,
/* This has already been done for real variables. */ /* This has already been done for real variables. */
if (dt != IVL_VT_REAL) { if (dt != IVL_VT_REAL) {
pform_set_net_range(first->name, range, signed_flag, dt, pform_set_net_range(first->name, range, signed_flag, dt,
SR_NET); SR_NET, 0);
} }
PWire*cur = pform_get_wire_in_scope(first->name); PWire*cur = pform_get_wire_in_scope(first->name);
@ -2044,7 +2054,8 @@ void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names, list<perm_string>*names,
svector<PExpr*>*range, svector<PExpr*>*range,
bool signed_flag, bool signed_flag,
NetNet::PortType pt) NetNet::PortType pt,
svector<named_pexpr_t*>*attr)
{ {
for (list<perm_string>::iterator cur = names->begin() for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; cur != names->end()
@ -2052,12 +2063,14 @@ void pform_set_port_type(const struct vlltype&li,
perm_string txt = *cur; perm_string txt = *cur;
pform_set_port_type(txt, pt, li.text, li.first_line); pform_set_port_type(txt, pt, li.text, li.first_line);
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE, pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE,
SR_PORT); SR_PORT, attr);
} }
delete names; delete names;
if (range) if (range)
delete range; delete range;
if (attr)
delete attr;
} }
static void pform_set_reg_integer(perm_string name) static void pform_set_reg_integer(perm_string name)

View File

@ -254,7 +254,8 @@ extern void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names, list<perm_string>*names,
svector<PExpr*>*range, svector<PExpr*>*range,
bool signed_flag, bool signed_flag,
NetNet::PortType); NetNet::PortType,
svector<named_pexpr_t*>*attr);
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt, extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno); const char*file, unsigned lineno);