Rework data_type parsing to bring integer vectors into data_type_t method.

This adds the vector_type_t and real_type_t types to handle
vector and real types in tf_port items. This cleans up a lot
of the parsing for these items.
This commit is contained in:
Stephen Williams 2012-02-25 22:05:00 -08:00
parent dd3a7411cd
commit 410350ae5a
4 changed files with 101 additions and 184 deletions

221
parse.y
View File

@ -157,7 +157,7 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
return tmp;
}
static list<PExpr*>* copy_range(list<PExpr*>* orig)
list<PExpr*>* copy_range(list<PExpr*>* orig)
{
list<PExpr*>*copy = 0;
@ -317,7 +317,7 @@ static void current_task_set_statement(vector<Statement*>*s)
NetNet::Type nettype;
PGBuiltin::Type gatetype;
NetNet::PortType porttype;
ivl_variable_type_t datatype;
ivl_variable_type_t vartype;
PWire*wire;
svector<PWire*>*wires;
@ -461,9 +461,9 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt
%type <text> register_variable net_variable real_variable endname_opt
%type <text> register_variable net_variable endname_opt
%type <perm_strings> register_variable_list net_variable_list
%type <perm_strings> real_variable_list list_of_identifiers
%type <perm_strings> list_of_identifiers
%type <port_list> list_of_port_identifiers
%type <net_decl_assign> net_decl_assign net_decl_assigns
@ -506,7 +506,7 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <decl_assignment> variable_decl_assignment
%type <decl_assignments> list_of_variable_decl_assignments
%type <data_type> data_type
%type <data_type> data_type data_type_or_implicit
%type <struct_member> struct_union_member
%type <struct_members> struct_union_member_list
%type <struct_type> struct_data_type
@ -516,7 +516,8 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <nettype> net_type var_type net_type_opt
%type <gatetype> gatetype switchtype
%type <porttype> port_direction port_direction_opt
%type <datatype> primitive_type primitive_type_opt bit_logic
%type <vartype> primitive_type primitive_type_opt bit_logic
%type <vartype> integer_vector_type
%type <parmvalue> parameter_value_opt
%type <function_type> function_range_or_type_opt
@ -536,7 +537,7 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <specpath> specify_simple_path specify_simple_path_decl
%type <specpath> specify_edge_path specify_edge_path_decl
%type <int_val> atom2_type
%type <int_val> atom2_type non_integer_type
%type <int_val> module_start module_end
%token K_TAND
@ -642,7 +643,17 @@ class_item /* IEEE1800-2005: A.1.8 */
;
data_type /* IEEE1800-2005: A.2.2.1 */
: struct_data_type
: integer_vector_type unsigned_signed_opt range_opt
{ vector_type_t*tmp = new vector_type_t($1, $2, $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| non_integer_type
{ real_type_t*tmp = new real_type_t($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| struct_data_type
{ $$ = $1; }
| enum_data_type
{ $$ = $1; }
@ -659,6 +670,16 @@ data_type /* IEEE1800-2005: A.2.2.1 */
}
;
data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */
: data_type
{ $$ = $1; }
| unsigned_signed_opt range_opt
{ vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $1, $2);
FILE_NAME(tmp, @1);
$$ = tmp;
}
;
endnew_opt : ':' K_new | ;
for_step /* IEEE1800-2005: A.6.8 */
@ -708,6 +729,13 @@ inc_or_dec_expression /* IEEE1800-2005: A.4.3 */
}
;
integer_vector_type /* IEEE1800-2005: A.2.2.1 */
: K_reg { $$ = IVL_VT_LOGIC; }
| K_bit { $$ = IVL_VT_BOOL; }
| K_logic { $$ = IVL_VT_LOGIC; }
| K_bool { $$ = IVL_VT_BOOL; } /* Icarus Verilog xtypes extension */
;
/* Loop statements are kinds of statements. */
loop_statement /* IEEE1800-2005: A.6.8 */
@ -768,6 +796,12 @@ loop_statement /* IEEE1800-2005: A.6.8 */
;
non_integer_type /* IEEE1800-2005: A.2.2.1 */
: K_real { $$ = K_real; }
| K_realtime { $$ = K_real; }
| K_shortreal { $$ = K_shortreal; }
;
number : BASED_NUMBER
{ $$ = $1; based_size = 0;}
| DEC_NUMBER
@ -954,47 +988,9 @@ task_declaration /* IEEE1800-2005: A.2.7 */
tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction K_reg_opt unsigned_signed_opt range_opt IDENTIFIER range_opt tf_port_item_expr_opt
{ port_declaration_context.port_type = $1;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp = pform_make_task_ports(@5, $1, IVL_VT_LOGIC, $3,
$4, list_from_identifier($5));
$$ = tmp;
if ($6) {
yyerror(@6, "sorry: Port variable dimensions not supported yet.");
delete $6;
}
if ($7) {
yyerror(@7, "sorry: Port default expressions not supported yet.");
delete $7;
}
}
| port_direction_opt bit_logic unsigned_signed_opt range_opt IDENTIFIER range_opt tf_port_item_expr_opt
{ port_declaration_context.port_type = $1;
port_declaration_context.var_type = $2;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp = pform_make_task_ports(@5, $1, $2, $3,
$4, list_from_identifier($5));
$$ = tmp;
if ($6) {
yyerror(@6, "sorry: Port variable dimensions not supported yet.");
delete $6;
}
if ($7) {
yyerror(@7, "sorry: Port default expressions not supported yet.");
delete $7;
}
}
/* Ports can be integer with a width of [31:0]. */
| port_direction_opt K_integer IDENTIFIER range_opt tf_port_item_expr_opt
: port_direction_opt K_integer IDENTIFIER range_opt tf_port_item_expr_opt
{ list<PExpr*>*range_stub = make_range_from_width(integer_width);
port_declaration_context.port_type = $1;
port_declaration_context.var_type = IVL_VT_LOGIC;
@ -1038,28 +1034,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
}
}
/* Ports can be real or realtime. */
| port_direction_opt real_or_realtime IDENTIFIER range_opt tf_port_item_expr_opt
{ port_declaration_context.port_type = $1;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = 0;
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, IVL_VT_REAL, false,
0, list_from_identifier($3));
$$ = tmp;
if ($4) {
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
delete $4;
}
if ($5) {
yyerror(@5, "sorry: Port default expressions not supported yet.");
delete $5;
}
}
| port_direction_opt data_type IDENTIFIER range_opt tf_port_item_expr_opt
| port_direction data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
{ port_declaration_context.port_type = $1;
port_declaration_context.var_type = IVL_VT_NO_TYPE;
port_declaration_context.sign_flag = false;
@ -1111,7 +1086,7 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
| tf_port_list ',' IDENTIFIER
{ // The declaration is already parsed, apply it to IDENTIFIER
svector<PWire*>*new_decl;
svector<PWire*>*new_decl;
if (port_declaration_context.var_type == IVL_VT_NO_TYPE) {
assert(port_declaration_context.data_type);
new_decl = pform_make_task_ports(@3, port_declaration_context.port_type,
@ -1226,47 +1201,12 @@ attribute
rule has presumably set up the scope. */
block_item_decl
: attribute_list_opt K_reg
primitive_type_opt unsigned_signed_opt range
register_variable_list ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_set_net_range($6, $5, $4, dtype);
if ($1) delete $1;
}
/* This differs from the above pattern only in the absence of the
range. This is the rule for a scalar. */
| attribute_list_opt K_reg
primitive_type_opt unsigned_signed_opt
register_variable_list ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_set_net_range($5, 0, $4, dtype);
if ($1) delete $1;
}
| attribute_list_opt K_bit unsigned_signed_opt range_opt
register_variable_list ';'
{
pform_set_net_range($5, $4, $3, IVL_VT_BOOL);
if ($1) delete $1;
}
| attribute_list_opt K_logic unsigned_signed_opt range_opt
register_variable_list ';'
{
pform_set_net_range($5, $4, $3, IVL_VT_LOGIC);
if ($1) delete $1;
}
/* Integer atom declarations are simpler in that they do not have
all the trappings of a general variable declaration. All of that
is implicit in the "integer" of the declaration. */
| attribute_list_opt K_integer signed_unsigned_opt register_variable_list ';'
: attribute_list_opt K_integer signed_unsigned_opt register_variable_list ';'
{ pform_set_reg_integer($4);
if ($1) delete $1;
}
@ -1284,15 +1224,10 @@ block_item_decl
if ($1) delete $1;
}
/* real declarations are fairly simple as there is no range of
signed flag in the declaration. Create the real as a NetNet::REG
with real value. Note that real and realtime are interchangeable
in this context. */
| attribute_list_opt K_real real_variable_list ';'
{ delete $3; }
| attribute_list_opt K_realtime real_variable_list ';'
{ delete $3; }
| attribute_list_opt K_reg data_type register_variable_list ';'
{ if ($3) pform_set_data_type(@3, $3, $4);
if ($1) delete $1;
}
| K_event list_of_identifiers ';'
{ pform_make_events($2, @1.text, @1.first_line);
@ -1307,12 +1242,6 @@ block_item_decl
/* Recover from errors that happen within variable lists. Use the
trailing semi-colon to resync the parser. */
| attribute_list_opt K_reg error ';'
{ yyerror(@2, "error: syntax error in reg variable list.");
yyerrok;
if ($1) delete $1;
}
| attribute_list_opt K_integer error ';'
{ yyerror(@2, "error: syntax error in integer variable list.");
yyerrok;
@ -1322,14 +1251,7 @@ block_item_decl
{ yyerror(@2, "error: syntax error in time variable list.");
yyerrok;
}
| attribute_list_opt K_real error ';'
{ yyerror(@2, "error: syntax error in real variable list.");
yyerrok;
}
| attribute_list_opt K_realtime error ';'
{ yyerror(@2, "error: syntax error in realtime variable list.");
yyerrok;
}
| K_parameter error ';'
{ yyerror(@1, "error: syntax error in parameter list.");
yyerrok;
@ -3531,7 +3453,7 @@ module_item
/* block_item_decl rule is shared with task blocks and named
begin/end. */
| block_item_decl
| block_item_decl
/* */
@ -4648,45 +4570,6 @@ variable_decl_assignment
}
;
real_variable
: IDENTIFIER dimensions_opt
{ perm_string name = lex_strings.make($1);
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
if ($2 != 0) {
index_component_t index;
if ($2->size() > 1) {
yyerror(@2, "sorry: only 1 dimensional arrays "
"are currently supported.");
}
index = $2->front();
pform_set_reg_idx(name, index.msb, index.lsb);
delete $2;
}
$$ = $1;
}
| IDENTIFIER '=' expression
{ perm_string name = lex_strings.make($1);
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
pform_make_reginit(@1, name, $3);
$$ = $1;
}
;
real_variable_list
: real_variable
{ list<perm_string>*tmp = new list<perm_string>;
tmp->push_back(lex_strings.make($1));
$$ = tmp;
delete[]$1;
}
| real_variable_list ',' real_variable
{ list<perm_string>*tmp = $1;
tmp->push_back(lex_strings.make($3));
$$ = tmp;
delete[]$3;
}
;
net_variable
: IDENTIFIER dimensions_opt
{ perm_string name = lex_strings.make($1);

View File

@ -1527,10 +1527,10 @@ static void pform_set_net_range(perm_string name,
cur->set_data_type(dt);
}
void pform_set_net_range(list<perm_string>*names,
list<PExpr*>*range,
bool signed_flag,
ivl_variable_type_t dt)
static void pform_set_net_range(list<perm_string>*names,
list<PExpr*>*range,
bool signed_flag,
ivl_variable_type_t dt)
{
assert((range == 0) || (range->size()%2 == 0));
@ -2197,15 +2197,27 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
data_type_t*vtype,
list<perm_string>*names)
{
atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype);
if (atype == 0) {
VLerror(loc, "sorry: Given type not supported here.");
return 0;
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
list<PExpr*>*range_tmp = make_range_from_width(atype->type_code);
return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
atype->signed_flag,
range_tmp, names);
}
list<PExpr*>*range_tmp = make_range_from_width(atype->type_code);
return pform_make_task_ports(loc, pt, IVL_VT_BOOL, atype->signed_flag,
range_tmp, names);
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, vec_type->base_type,
vec_type->signed_flag,
copy_range(vec_type->pdims.get()),
names);
}
if (real_type_t*real_type = dynamic_cast<real_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_REAL,
true, 0, names);
}
VLerror(loc, "sorry: Given type not supported here.");
return 0;
}
/*
@ -2608,6 +2620,18 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
return;
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
pform_set_net_range(names, vec_type->pdims.get(),
vec_type->signed_flag,
vec_type->base_type);
return;
}
if (real_type_t*real_type = dynamic_cast<real_type_t*> (data_type)) {
pform_set_net_range(names, 0, true, IVL_VT_REAL);
return;
}
assert(0);
}

View File

@ -118,6 +118,7 @@ struct lgate {
};
extern std::list<PExpr*>* make_range_from_width(uint64_t wid);
extern list<PExpr*>* copy_range(list<PExpr*>* orig);
/* Use this function to transform the parted form of the attribute
list to the attribute map that is used later. */
@ -286,10 +287,6 @@ extern void pform_set_port_type(const struct vlltype&li,
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno);
extern void pform_set_net_range(list<perm_string>*names,
list<PExpr*>*,
bool signed_flag,
ivl_variable_type_t);
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names);

View File

@ -107,6 +107,19 @@ struct atom2_type_t : public data_type_t {
bool signed_flag;
};
struct vector_type_t : public data_type_t {
inline explicit vector_type_t(ivl_variable_type_t bt, bool sf, list<PExpr*>*pd)
: base_type(bt), signed_flag(sf), pdims(pd) { }
ivl_variable_type_t base_type;
bool signed_flag;
std::auto_ptr< list<PExpr*> > pdims;
};
struct real_type_t : public data_type_t {
inline explicit real_type_t(int tc) : type_code(tc) { }
int type_code;
};
/*
* The pform_name_t is the general form for a hierarchical
* identifier. It is an ordered list of name components. Each name