Rework rules for variable_dimensions, and support more syntax.

This commit is contained in:
Stephen Williams 2012-03-02 18:34:43 -08:00
parent 64ea328823
commit f749867369
7 changed files with 229 additions and 247 deletions

View File

@ -1,7 +1,7 @@
#ifndef __PTask_H #ifndef __PTask_H
#define __PTask_H #define __PTask_H
/* /*
* Copyright (c) 1999-2008,2010 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2008,2010,2012 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -46,7 +46,7 @@ enum PTaskFuncEnum {
struct PTaskFuncArg { struct PTaskFuncArg {
PTaskFuncEnum type; PTaskFuncEnum type;
vector<PExpr*>*range; std::list<index_component_t>*range;
}; };
/* /*

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -133,9 +133,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type) enum_type_t*enum_type)
{ {
bool rc_flag; bool rc_flag;
assert(enum_type->range->size() == 2); assert(enum_type->range->size() == 1);
NetExpr*msb_ex = elab_and_eval(des, scope, enum_type->range->front(), -1); index_component_t index = enum_type->range->front();
NetExpr*lsb_ex = elab_and_eval(des, scope, enum_type->range->back(), -1); NetExpr*msb_ex = elab_and_eval(des, scope, index.msb, -1);
NetExpr*lsb_ex = elab_and_eval(des, scope, index.lsb, -1);
long msb = 0; long msb = 0;
rc_flag = eval_as_long(msb, msb_ex); rc_flag = eval_as_long(msb, msb_ex);

View File

@ -476,15 +476,12 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG: case PTF_REG:
case PTF_REG_S: case PTF_REG_S:
if (return_type_.range) { if (return_type_.range) {
ivl_assert(*this, return_type_.range->size() == 2); ivl_assert(*this, return_type_.range->size() == 1);
index_component_t index = return_type_.range->front();
NetExpr*me = elab_and_eval(des, scope, NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
return_type_.range->at(0), -1,
true);
assert(me); assert(me);
NetExpr*le = elab_and_eval(des, scope, NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
return_type_.range->at(1), -1,
true);
assert(le); assert(le);
long mnum = 0, lnum = 0; long mnum = 0, lnum = 0;
@ -550,17 +547,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_ATOM2: case PTF_ATOM2:
case PTF_ATOM2_S: case PTF_ATOM2_S:
ivl_assert(*this, return_type_.range != 0);
long use_wid; long use_wid;
{ {
NetExpr*me = elab_and_eval(des, scope, ivl_assert(*this, return_type_.range->size() == 1);
(*return_type_.range)[0], -1, index_component_t index = return_type_.range->front();
true); NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
assert(me); ivl_assert(*this, me);
NetExpr*le = elab_and_eval(des, scope, NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
(*return_type_.range)[1], -1, ivl_assert(*this, le);
true);
assert(le);
long mnum = 0, lnum = 0; long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) { if ( ! get_const_argument(me, mnum) ) {
@ -805,9 +799,10 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
long use_msb = 0; long use_msb = 0;
long use_lsb = 0; long use_lsb = 0;
if (curp->range.get() && ! curp->range->empty()) { if (curp->range.get() && ! curp->range->empty()) {
ivl_assert(*curp, curp->range->size() == 2); ivl_assert(*curp, curp->range->size() == 1);
PExpr*msb_pex = curp->range->front(); index_component_t index = curp->range->front();
PExpr*lsb_pex = curp->range->back(); PExpr*msb_pex = index.msb;
PExpr*lsb_pex = index.lsb;
NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true); NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true);
ivl_assert(*curp, tmp); ivl_assert(*curp, tmp);

316
parse.y
View File

@ -38,7 +38,7 @@ extern void lex_end_table();
bool have_timeunit_decl = false; bool have_timeunit_decl = false;
bool have_timeprec_decl = false; bool have_timeprec_decl = false;
static list<PExpr*>* param_active_range = 0; static list<index_component_t>* param_active_range = 0;
static bool param_active_signed = false; static bool param_active_signed = false;
static ivl_variable_type_t param_active_type = IVL_VT_LOGIC; static ivl_variable_type_t param_active_type = IVL_VT_LOGIC;
@ -48,7 +48,7 @@ static struct {
NetNet::PortType port_type; NetNet::PortType port_type;
ivl_variable_type_t var_type; ivl_variable_type_t var_type;
bool sign_flag; bool sign_flag;
list<PExpr*>* range; list<index_component_t>* range;
data_type_t* data_type; data_type_t* data_type;
} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT, } port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT,
IVL_VT_NO_TYPE, false, 0, 0}; IVL_VT_NO_TYPE, false, 0, 0};
@ -98,8 +98,7 @@ static list<pair<perm_string,PExpr*> >* make_port_list(char*id, PExpr*expr)
delete[]id; delete[]id;
return tmp; return tmp;
} }
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string, static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string, PExpr*> >*tmp,
PExpr*> >*tmp,
char*id, PExpr*expr) char*id, PExpr*expr)
{ {
tmp->push_back(make_pair(lex_strings.make(id), expr)); tmp->push_back(make_pair(lex_strings.make(id), expr));
@ -107,16 +106,19 @@ static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string,
return tmp; return tmp;
} }
list<PExpr*>* make_range_from_width(uint64_t wid) list<index_component_t>* make_range_from_width(uint64_t wid)
{ {
list<PExpr*>*range = new list<PExpr*>; list<index_component_t>*range = new list<index_component_t>;
range->push_back(new PENumber(new verinum(wid-1, integer_width))); index_component_t tmp;
range->push_back(new PENumber(new verinum((uint64_t)0, integer_width))); tmp.msb = new PENumber(new verinum(wid-1, integer_width));
tmp.lsb = new PENumber(new verinum((uint64_t)0, integer_width));
range->push_back(tmp);
return range; return range;
} }
#if 0
/* /*
* Make a range vector from an existing pair of expressions. * Make a range vector from an existing pair of expressions.
*/ */
@ -129,7 +131,8 @@ static vector<PExpr*>* make_range_vector(list<PExpr*>*that)
delete that; delete that;
return tmp; return tmp;
} }
#endif
#if 0
/* /*
* Make a range vector from a width. Generate the msb and lsb * Make a range vector from a width. Generate the msb and lsb
* expressions to get the canonical range for the given width. * expressions to get the canonical range for the given width.
@ -141,7 +144,7 @@ static vector<PExpr*>* make_range_vector(uint64_t wid)
tmp->at(1) = new PENumber(new verinum((uint64_t)0, integer_width)); tmp->at(1) = new PENumber(new verinum((uint64_t)0, integer_width));
return tmp; return tmp;
} }
#endif
static list<perm_string>* list_from_identifier(char*id) static list<perm_string>* list_from_identifier(char*id)
{ {
list<perm_string>*tmp = new list<perm_string>; list<perm_string>*tmp = new list<perm_string>;
@ -157,12 +160,12 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
return tmp; return tmp;
} }
list<PExpr*>* copy_range(list<PExpr*>* orig) list<index_component_t>* copy_range(list<index_component_t>* orig)
{ {
list<PExpr*>*copy = 0; list<index_component_t>*copy = 0;
if (orig) if (orig)
copy = new list<PExpr*> (*orig); copy = new list<index_component_t> (*orig);
return copy; return copy;
} }
@ -512,8 +515,8 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <struct_members> struct_union_member_list %type <struct_members> struct_union_member_list
%type <struct_type> struct_data_type %type <struct_type> struct_data_type
%type <exprs> range range_opt variable_dimension %type <dimensions> range range_opt
%type <dimensions> dimensions_opt dimensions %type <dimensions> dimensions_opt dimensions variable_dimension
%type <nettype> net_type var_type net_type_opt %type <nettype> net_type var_type net_type_opt
%type <gatetype> gatetype switchtype %type <gatetype> gatetype switchtype
%type <porttype> port_direction port_direction_opt %type <porttype> port_direction port_direction_opt
@ -1015,13 +1018,6 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER '[' ']'
{ decl_assignment_t*tmp = new decl_assignment_t;
tmp->name = lex_strings.make($1);
yyerror("sorry: Dynamic arrays not yet supported here.");
delete[]$1;
$$ = tmp;
}
| IDENTIFIER '[' '$' ']' | IDENTIFIER '[' '$' ']'
{ decl_assignment_t*tmp = new decl_assignment_t; { decl_assignment_t*tmp = new decl_assignment_t;
tmp->name = lex_strings.make($1); tmp->name = lex_strings.make($1);
@ -1272,7 +1268,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
/* Ports can be integer with a width of [31:0]. */ /* 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); { list<index_component_t>*range_stub = make_range_from_width(integer_width);
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1; NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
port_declaration_context.port_type = use_port_type; port_declaration_context.port_type = use_port_type;
@ -1297,7 +1293,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
/* Ports can be time with a width of [63:0] (unsigned). */ /* Ports can be time with a width of [63:0] (unsigned). */
| port_direction_opt K_time IDENTIFIER range_opt tf_port_item_expr_opt | port_direction_opt K_time IDENTIFIER range_opt tf_port_item_expr_opt
{ list<PExpr*>*range_stub = make_range_from_width(64); { list<index_component_t>*range_stub = make_range_from_width(64);
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1; NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
port_declaration_context.port_type = use_port_type; port_declaration_context.port_type = use_port_type;
@ -1414,18 +1410,39 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
variable_dimension /* IEEE1800-2005: A.2.5 */ variable_dimension /* IEEE1800-2005: A.2.5 */
: '[' expression ':' expression ']' : '[' expression ':' expression ']'
{ list<PExpr*>*tmp = new list<PExpr*>; { list<index_component_t> *tmp = new list<index_component_t>;
tmp->push_back($2); index_component_t index;
tmp->push_back($4); index.sel = index_component_t::SEL_PART;
index.msb = $2;
index.lsb = $4;
tmp->push_back(index);
$$ = tmp;
}
| '[' expression ']'
{ // SystemVerilog canonical range
if (generation_flag < GN_VER2005_SV) {
warn_count += 1;
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
<< "Use at least -g2005-sv to remove this warning." << endl;
}
list<index_component_t> *tmp = new list<index_component_t>;
index_component_t index;
index.sel = index_component_t::SEL_PART;
index.lsb = new PENumber(new verinum((uint64_t)0, integer_width));
index.msb = new PEBinary('-', $2, new PENumber(new verinum((uint64_t)1, integer_width)));
tmp->push_back(index);
$$ = tmp; $$ = tmp;
} }
| '[' ']' | '[' ']'
{ list<PExpr*>*tmp = new list<PExpr*>; { list<index_component_t> *tmp = new list<index_component_t>;
tmp->push_back(0); index_component_t index;
tmp->push_back(0); index.msb = 0;
index.lsb = 0;
yyerror("sorry: Dynamic array ranges not supported.");
tmp->push_back(index);
$$ = tmp; $$ = tmp;
} }
; ;
/* Verilog-2001 supports attribute lists, which can be attached to a /* Verilog-2001 supports attribute lists, which can be attached to a
variety of different objects. The syntax inside the (* *) is a variety of different objects. The syntax inside the (* *) is a
@ -2822,20 +2839,21 @@ gate_instance
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER range '(' expression_list_with_nuls ')' | IDENTIFIER range '(' expression_list_with_nuls ')'
{ lgate*tmp = new lgate; { lgate*tmp = new lgate;
list<PExpr*>*rng = $2; list<index_component_t>*rng = $2;
tmp->name = $1; tmp->name = $1;
tmp->parms = $4; tmp->parms = $4;
tmp->range[0] = rng->front(); rng->pop_front(); tmp->range = rng->front();
tmp->range[1] = rng->front(); rng->pop_front(); rng->pop_front();
assert(rng->empty()); assert(rng->empty());
tmp->file = @1.text; tmp->file = @1.text;
tmp->lineno = @1.first_line; tmp->lineno = @1.first_line;
delete[]$1; delete[]$1;
delete rng; delete rng;
$$ = tmp; $$ = tmp;
} }
| '(' expression_list_with_nuls ')' | '(' expression_list_with_nuls ')'
{ lgate*tmp = new lgate; { lgate*tmp = new lgate;
tmp->name = ""; tmp->name = "";
@ -2847,50 +2865,50 @@ gate_instance
/* Degenerate modules can have no ports. */ /* Degenerate modules can have no ports. */
| IDENTIFIER range | IDENTIFIER range
{ lgate*tmp = new lgate; { lgate*tmp = new lgate;
list<PExpr*>*rng = $2; list<index_component_t>*rng = $2;
tmp->name = $1; tmp->name = $1;
tmp->parms = 0; tmp->parms = 0;
tmp->parms_by_name = 0; tmp->parms_by_name = 0;
tmp->range[0] = rng->front(); rng->pop_front(); tmp->range = rng->front();
tmp->range[1] = rng->front(); rng->pop_front(); rng->pop_front();
assert(rng->empty()); assert(rng->empty());
tmp->file = @1.text; tmp->file = @1.text;
tmp->lineno = @1.first_line; tmp->lineno = @1.first_line;
delete[]$1; delete[]$1;
delete rng; delete rng;
$$ = tmp; $$ = tmp;
} }
/* Modules can also take ports by port-name expressions. */ /* Modules can also take ports by port-name expressions. */
| IDENTIFIER '(' port_name_list ')' | IDENTIFIER '(' port_name_list ')'
{ lgate*tmp = new lgate; { lgate*tmp = new lgate;
tmp->name = $1; tmp->name = $1;
tmp->parms = 0; tmp->parms = 0;
tmp->parms_by_name = $3; tmp->parms_by_name = $3;
tmp->file = @1.text; tmp->file = @1.text;
tmp->lineno = @1.first_line; tmp->lineno = @1.first_line;
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER range '(' port_name_list ')' | IDENTIFIER range '(' port_name_list ')'
{ lgate*tmp = new lgate; { lgate*tmp = new lgate;
list<PExpr*>*rng = $2; list<index_component_t>*rng = $2;
tmp->name = $1; tmp->name = $1;
tmp->parms = 0; tmp->parms = 0;
tmp->parms_by_name = $4; tmp->parms_by_name = $4;
tmp->range[0] = rng->front(); rng->pop_front(); tmp->range = rng->front();
tmp->range[1] = rng->front(); rng->pop_front(); rng->pop_front();
assert(rng->empty()); assert(rng->empty());
tmp->file = @1.text; tmp->file = @1.text;
tmp->lineno = @1.first_line; tmp->lineno = @1.first_line;
delete[]$1; delete[]$1;
delete rng; delete rng;
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER '(' error ')' | IDENTIFIER '(' error ')'
{ lgate*tmp = new lgate; { lgate*tmp = new lgate;
@ -3143,7 +3161,7 @@ port_declaration
K_input atom2_type signed_unsigned_opt IDENTIFIER K_input atom2_type signed_unsigned_opt IDENTIFIER
{ Module::port_t*ptmp; { Module::port_t*ptmp;
perm_string name = lex_strings.make($5); perm_string name = lex_strings.make($5);
list<PExpr*>*use_range = make_range_from_width($3); list<index_component_t>*use_range = make_range_from_width($3);
ptmp = pform_module_port_reference(name, @2.text, ptmp = pform_module_port_reference(name, @2.text,
@2.first_line); @2.first_line);
pform_module_define_port(@2, name, NetNet::PINPUT, pform_module_define_port(@2, name, NetNet::PINPUT,
@ -3289,7 +3307,7 @@ port_declaration
K_output atom2_type signed_unsigned_opt IDENTIFIER K_output atom2_type signed_unsigned_opt IDENTIFIER
{ Module::port_t*ptmp; { Module::port_t*ptmp;
perm_string name = lex_strings.make($5); perm_string name = lex_strings.make($5);
list<PExpr*>*use_range = make_range_from_width($3); list<index_component_t>*use_range = make_range_from_width($3);
ptmp = pform_module_port_reference(name, @2.text, ptmp = pform_module_port_reference(name, @2.text,
@2.first_line); @2.first_line);
pform_module_define_port(@2, name, NetNet::POUTPUT, pform_module_define_port(@2, name, NetNet::POUTPUT,
@ -3308,7 +3326,7 @@ port_declaration
K_output atom2_type signed_unsigned_opt IDENTIFIER '=' expression K_output atom2_type signed_unsigned_opt IDENTIFIER '=' expression
{ Module::port_t*ptmp; { Module::port_t*ptmp;
perm_string name = lex_strings.make($5); perm_string name = lex_strings.make($5);
list<PExpr*>*use_range = make_range_from_width($3); list<index_component_t>*use_range = make_range_from_width($3);
ptmp = pform_module_port_reference(name, @2.text, ptmp = pform_module_port_reference(name, @2.text,
@2.first_line); @2.first_line);
pform_module_define_port(@2, name, NetNet::POUTPUT, pform_module_define_port(@2, name, NetNet::POUTPUT,
@ -4606,9 +4624,13 @@ port_reference_list
/* The range is a list of variable dimensions. */ /* The range is a list of variable dimensions. */
range range
: variable_dimension : variable_dimension
{ $$ = $1; }
| range variable_dimension | range variable_dimension
{ list<PExpr*>*tmp = $1; { list<index_component_t>*tmp = $1;
if ($2) tmp->splice(tmp->end(), *$2); if ($2) {
tmp->splice(tmp->end(), *$2);
delete $2;
}
$$ = tmp; $$ = tmp;
} }
; ;
@ -4623,88 +4645,54 @@ dimensions_opt
| dimensions { $$ = $1; } | dimensions { $$ = $1; }
dimensions dimensions
: '[' expression ':' expression ']' : variable_dimension
{ list<index_component_t> *tmp = new list<index_component_t>; { $$ = $1; }
index_component_t index; | dimensions variable_dimension
index.msb = $2; { list<index_component_t> *tmp = $1;
index.lsb = $4; if ($2) {
tmp->push_back(index); tmp->splice(tmp->end(), *$2);
$$ = tmp; delete $2;
} }
| '[' expression ']' $$ = tmp;
{ if (generation_flag < GN_VER2005_SV) { }
warn_count += 1; ;
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
<< "Use at least -g2005-sv to remove this warning." << endl;
}
list<index_component_t> *tmp = new list<index_component_t>;
index_component_t index;
index.msb = new PENumber(new verinum((uint64_t)0, integer_width));
index.lsb = new PEBinary('-', $2, new PENumber(new verinum((uint64_t)1, integer_width)));
tmp->push_back(index);
$$ = tmp;
}
| dimensions '[' expression ':' expression ']'
{ list<index_component_t> *tmp = $1;
index_component_t index;
index.msb = $3;
index.lsb = $5;
tmp->push_back(index);
$$ = tmp;
}
| dimensions '[' expression ']'
{ if (generation_flag < GN_VER2005_SV) {
warn_count += 1;
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
<< "Use at least -g2005-sv to remove this warning." << endl;
}
list<index_component_t> *tmp = $1;
index_component_t index;
index.msb = new PENumber(new verinum((uint64_t)0, integer_width));
index.lsb = new PEBinary('-', $3, new PENumber(new verinum((uint64_t)1, integer_width)));
tmp->push_back(index);
$$ = tmp;
}
/* This is used to express the return type of a function. */ /* This is used to express the return type of a function. */
function_range_or_type_opt function_range_or_type_opt
: unsigned_signed_opt range_opt : unsigned_signed_opt range_opt
{ { /* the default type is reg unsigned and no range */
/* the default type is reg unsigned and no range */ $$.type = PTF_REG;
$$.type = PTF_REG; $$.range = 0;
$$.range = 0; if ($1)
if ($1) $$.type = PTF_REG_S;
$$.type = PTF_REG_S; if ($2)
if ($2) $$.range = $2;
$$.range = make_range_vector($2); }
}
| K_reg unsigned_signed_opt range_opt | K_reg unsigned_signed_opt range_opt
{ { /* the default type is reg unsigned and no range */
/* the default type is reg unsigned and no range */ $$.type = PTF_REG;
$$.type = PTF_REG; $$.range = 0;
$$.range = 0; if ($2)
if ($2) $$.type = PTF_REG_S;
$$.type = PTF_REG_S; if ($3)
if ($3) $$.range = $3;
$$.range = make_range_vector($3); }
}
| bit_logic unsigned_signed_opt range_opt | bit_logic unsigned_signed_opt range_opt
{ { /* the default type is bit/logic unsigned and no range */
/* the default type is bit/logic unsigned and no range */ $$.type = PTF_REG;
$$.type = PTF_REG; $$.range = 0;
$$.range = 0; if ($2)
if ($2) $$.type = PTF_REG_S;
$$.type = PTF_REG_S; if ($3)
if ($3) $$.range = $3;
$$.range = make_range_vector($3); }
}
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; } | K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
| K_real { $$.range = 0; $$.type = PTF_REAL; } | K_real { $$.range = 0; $$.type = PTF_REAL; }
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; } | K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
| K_time { $$.range = 0; $$.type = PTF_TIME; } | K_time { $$.range = 0; $$.type = PTF_TIME; }
| atom2_type { $$.range = make_range_vector($1); $$.type = PTF_ATOM2_S; } | atom2_type { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
| atom2_type K_signed { $$.range = make_range_vector($1); $$.type = PTF_ATOM2_S; } | atom2_type K_signed { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
| atom2_type K_unsigned { $$.range = make_range_vector($1); $$.type = PTF_ATOM2; } | atom2_type K_unsigned { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2; }
; ;
/* The register_variable rule is matched only when I am parsing /* The register_variable rule is matched only when I am parsing
@ -5577,7 +5565,7 @@ task_port_item
shape. Generate a range ([31:0]) to make it work. */ shape. Generate a range ([31:0]) to make it work. */
| port_direction K_integer list_of_identifiers ';' | port_direction K_integer list_of_identifiers ';'
{ list<PExpr*>*range_stub = make_range_from_width(integer_width); { list<index_component_t>*range_stub = make_range_from_width(integer_width);
svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true, svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true,
range_stub, $3, true); range_stub, $3, true);
$$ = tmp; $$ = tmp;
@ -5586,7 +5574,7 @@ task_port_item
/* Ports can be time with a width of [63:0] (unsigned). */ /* Ports can be time with a width of [63:0] (unsigned). */
| port_direction K_time list_of_identifiers ';' | port_direction K_time list_of_identifiers ';'
{ list<PExpr*>*range_stub = make_range_from_width(64); { list<index_component_t>*range_stub = make_range_from_width(64);
svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false, svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false,
range_stub, $3); range_stub, $3);
$$ = tmp; $$ = tmp;

View File

@ -1480,16 +1480,15 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
delete init_expr; delete init_expr;
} }
static void ranges_from_list(list<PWire::range_t>&rlist, const list<PExpr*>*range) static void ranges_from_list(list<PWire::range_t>&rlist,
const list<index_component_t>*range)
{ {
// There must be an even number of expressions in the // Convert a list of index_component_t to PWire::range_t.
// range. The parser will assure that for us. for (list<index_component_t>::const_iterator rcur = range->begin()
assert(range->size()%2 == 0); ; rcur != range->end() ; ++rcur) {
list<PExpr*>::const_iterator rcur = range->begin();
while (rcur != range->end()) {
PWire::range_t rng; PWire::range_t rng;
rng.msb = *rcur; ++rcur; rng.msb = rcur->msb;
rng.lsb = *rcur; ++rcur; rng.lsb = rcur->lsb;
rlist.push_back(rng); rlist.push_back(rng);
} }
} }
@ -1500,7 +1499,7 @@ static void ranges_from_list(list<PWire::range_t>&rlist, const list<PExpr*>*rang
* and the name that I receive only has the tail component. * and the name that I receive only has the tail component.
*/ */
static void pform_set_net_range(perm_string name, static void pform_set_net_range(perm_string name,
const list<PExpr*>*range, const list<index_component_t>*range,
bool signed_flag, bool signed_flag,
ivl_variable_type_t dt, ivl_variable_type_t dt,
PWSRType rt) PWSRType rt)
@ -1528,12 +1527,10 @@ static void pform_set_net_range(perm_string name,
} }
static void pform_set_net_range(list<perm_string>*names, static void pform_set_net_range(list<perm_string>*names,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
ivl_variable_type_t dt) ivl_variable_type_t dt)
{ {
assert((range == 0) || (range->size()%2 == 0));
for (list<perm_string>::iterator cur = names->begin() for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) { ; cur != names->end() ; ++ cur ) {
perm_string txt = *cur; perm_string txt = *cur;
@ -1601,8 +1598,8 @@ static void pform_makegate(PGBuiltin::Type type,
perm_string dev_name = lex_strings.make(info.name); perm_string dev_name = lex_strings.make(info.name);
PGBuiltin*cur = new PGBuiltin(type, dev_name, info.parms, delay); PGBuiltin*cur = new PGBuiltin(type, dev_name, info.parms, delay);
if (info.range[0]) if (info.range.msb)
cur->set_range(info.range[0], info.range[1]); cur->set_range(info.range.msb, info.range.lsb);
// The pform_makegates() that calls me will take care of // The pform_makegates() that calls me will take care of
// deleting the attr pointer, so tell the // deleting the attr pointer, so tell the
@ -1741,7 +1738,7 @@ void pform_make_modgates(perm_string type,
if (cur.parms_by_name) { if (cur.parms_by_name) {
pform_make_modgate(type, cur_name, overrides, pform_make_modgate(type, cur_name, overrides,
cur.parms_by_name, cur.parms_by_name,
cur.range[0], cur.range[1], cur.range.msb, cur.range.lsb,
cur.file, cur.lineno); cur.file, cur.lineno);
} else if (cur.parms) { } else if (cur.parms) {
@ -1755,14 +1752,14 @@ void pform_make_modgates(perm_string type,
} }
pform_make_modgate(type, cur_name, overrides, pform_make_modgate(type, cur_name, overrides,
cur.parms, cur.parms,
cur.range[0], cur.range[1], cur.range.msb, cur.range.lsb,
cur.file, cur.lineno); cur.file, cur.lineno);
} else { } else {
list<PExpr*>*wires = new list<PExpr*>; list<PExpr*>*wires = new list<PExpr*>;
pform_make_modgate(type, cur_name, overrides, pform_make_modgate(type, cur_name, overrides,
wires, wires,
cur.range[0], cur.range[1], cur.range.msb, cur.range.lsb,
cur.file, cur.lineno); cur.file, cur.lineno);
} }
} }
@ -1875,7 +1872,7 @@ void pform_module_define_port(const struct vlltype&li,
NetNet::Type type, NetNet::Type type,
ivl_variable_type_t data_type, ivl_variable_type_t data_type,
bool signed_flag, bool signed_flag,
list<PExpr*>*range, list<index_component_t>*range,
list<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);
@ -2011,7 +2008,7 @@ void pform_makewire(const vlltype&li, perm_string name,
* pform_makewire above. * pform_makewire above.
*/ */
void pform_makewire(const vlltype&li, void pform_makewire(const vlltype&li,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
list<perm_string>*names, list<perm_string>*names,
NetNet::Type type, NetNet::Type type,
@ -2038,7 +2035,7 @@ void pform_makewire(const vlltype&li,
* This form makes nets with delays and continuous assignments. * This form makes nets with delays and continuous assignments.
*/ */
void pform_makewire(const vlltype&li, void pform_makewire(const vlltype&li,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
list<PExpr*>*delay, list<PExpr*>*delay,
str_pair_t str, str_pair_t str,
@ -2149,7 +2146,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t vtype, ivl_variable_type_t vtype,
bool signed_flag, bool signed_flag,
list<PExpr*>*range, list<index_component_t>*range,
list<perm_string>*names, list<perm_string>*names,
bool isint) bool isint)
{ {
@ -2198,7 +2195,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
list<perm_string>*names) list<perm_string>*names)
{ {
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) { if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
list<PExpr*>*range_tmp = make_range_from_width(atype->type_code); list<index_component_t>*range_tmp = make_range_from_width(atype->type_code);
return pform_make_task_ports(loc, pt, IVL_VT_BOOL, return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
atype->signed_flag, atype->signed_flag,
range_tmp, names); range_tmp, names);
@ -2211,7 +2208,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
names); names);
} }
if (real_type_t*real_type = dynamic_cast<real_type_t*> (vtype)) { if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_REAL, return pform_make_task_ports(loc, pt, IVL_VT_REAL,
true, 0, names); true, 0, names);
} }
@ -2325,7 +2322,7 @@ LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
void pform_set_parameter(const struct vlltype&loc, void pform_set_parameter(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type, perm_string name, ivl_variable_type_t type,
bool signed_flag, list<PExpr*>*range, PExpr*expr, bool signed_flag, list<index_component_t>*range, PExpr*expr,
LexicalScope::range_t*value_range) LexicalScope::range_t*value_range)
{ {
LexicalScope*scope = lexical_scope; LexicalScope*scope = lexical_scope;
@ -2360,11 +2357,12 @@ void pform_set_parameter(const struct vlltype&loc,
parm.type = type; parm.type = type;
if (range) { if (range) {
assert(range->size() == 2); assert(range->size() == 1);
assert(range->front()); index_component_t index = range->front();
assert(range->back()); assert(index.msb);
parm.msb = range->front(); assert(index.lsb);
parm.lsb = range->back(); parm.msb = index.msb;
parm.lsb = index.lsb;
} else { } else {
parm.msb = 0; parm.msb = 0;
parm.lsb = 0; parm.lsb = 0;
@ -2378,7 +2376,7 @@ void pform_set_parameter(const struct vlltype&loc,
void pform_set_localparam(const struct vlltype&loc, void pform_set_localparam(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type, perm_string name, ivl_variable_type_t type,
bool signed_flag, list<PExpr*>*range, PExpr*expr) bool signed_flag, list<index_component_t>*range, PExpr*expr)
{ {
LexicalScope*scope = lexical_scope; LexicalScope*scope = lexical_scope;
@ -2408,11 +2406,12 @@ void pform_set_localparam(const struct vlltype&loc,
parm.type = type; parm.type = type;
if (range) { if (range) {
assert(range->size() == 2); assert(range->size() == 1);
assert(range->front()); index_component_t index = range->front();
assert(range->back()); assert(index.msb);
parm.msb = range->front(); assert(index.lsb);
parm.lsb = range->back(); parm.msb = index.msb;
parm.lsb = index.lsb;
} else { } else {
parm.msb = 0; parm.msb = 0;
parm.lsb = 0; parm.lsb = 0;
@ -2511,7 +2510,7 @@ extern void pform_module_specify_path(PSpecPath*obj)
void pform_set_port_type(const struct vlltype&li, void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names, list<perm_string>*names,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
NetNet::PortType pt) NetNet::PortType pt)
{ {
@ -2627,7 +2626,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
return; return;
} }
if (real_type_t*real_type = dynamic_cast<real_type_t*> (data_type)) { if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
pform_set_net_range(names, 0, true, IVL_VT_REAL); pform_set_net_range(names, 0, true, IVL_VT_REAL);
return; return;
} }
@ -2645,7 +2644,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
cur->set_signed(enum_type->signed_flag); cur->set_signed(enum_type->signed_flag);
assert(enum_type->range.get() != 0); assert(enum_type->range.get() != 0);
assert(enum_type->range->size() == 2); assert(enum_type->range->size() == 1);
list<PWire::range_t>rlist; list<PWire::range_t>rlist;
ranges_from_list(rlist, enum_type->range.get()); ranges_from_list(rlist, enum_type->range.get());
cur->set_range(rlist, SR_NET); cur->set_range(rlist, SR_NET);
@ -2659,7 +2658,7 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
assert(enum_type->base_type==IVL_VT_LOGIC || enum_type->base_type==IVL_VT_BOOL); assert(enum_type->base_type==IVL_VT_LOGIC || enum_type->base_type==IVL_VT_BOOL);
assert(enum_type->range.get() != 0); assert(enum_type->range.get() != 0);
assert(enum_type->range->size() == 2); assert(enum_type->range->size() == 1);
// Add the file and line information to the enumeration type. // Add the file and line information to the enumeration type.
FILE_NAME(&(enum_type->li), li); FILE_NAME(&(enum_type->li), li);

26
pform.h
View File

@ -101,24 +101,22 @@ struct net_decl_assign_t {
/* The lgate is gate instantiation information. */ /* The lgate is gate instantiation information. */
struct lgate { struct lgate {
lgate(int =0) inline lgate(int =0)
: parms(0), parms_by_name(0), file(NULL), lineno(0) : parms(0), parms_by_name(0), file(NULL), lineno(0)
{ range[0] = 0; { }
range[1] = 0;
}
string name; string name;
list<PExpr*>*parms; list<PExpr*>*parms;
list<named_pexpr_t>*parms_by_name; list<named_pexpr_t>*parms_by_name;
PExpr*range[2]; index_component_t range;
const char* file; const char* file;
unsigned lineno; unsigned lineno;
}; };
extern std::list<PExpr*>* make_range_from_width(uint64_t wid); extern std::list<index_component_t>* make_range_from_width(uint64_t wid);
extern list<PExpr*>* copy_range(list<PExpr*>* orig); extern std::list<index_component_t>* copy_range(std::list<index_component_t>* orig);
/* 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. */
@ -161,7 +159,7 @@ extern void pform_module_define_port(const struct vlltype&li,
NetNet::Type type, NetNet::Type type,
ivl_variable_type_t data_type, ivl_variable_type_t data_type,
bool signed_flag, bool signed_flag,
list<PExpr*>*range, list<index_component_t>*range,
list<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,
@ -241,7 +239,7 @@ extern void pform_makewire(const struct vlltype&li, perm_string name,
/* 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,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
list<perm_string>*names, list<perm_string>*names,
NetNet::Type type, NetNet::Type type,
@ -258,7 +256,7 @@ extern void pform_makewire(const struct vlltype&li,
/* This form handles assignment declarations. */ /* This form handles assignment declarations. */
extern void pform_makewire(const struct vlltype&li, extern void pform_makewire(const struct vlltype&li,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
list<PExpr*>*delay, list<PExpr*>*delay,
str_pair_t str, str_pair_t str,
@ -281,7 +279,7 @@ extern void pform_make_reginit(const struct vlltype&li,
it. The second form takes a single name. */ it. The second form takes a single name. */
extern void pform_set_port_type(const struct vlltype&li, extern void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names, list<perm_string>*names,
list<PExpr*>*range, list<index_component_t>*range,
bool signed_flag, bool signed_flag,
NetNet::PortType); NetNet::PortType);
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt, extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
@ -316,13 +314,13 @@ extern void pform_set_parameter(const struct vlltype&loc,
perm_string name, perm_string name,
ivl_variable_type_t type, ivl_variable_type_t type,
bool signed_flag, bool signed_flag,
list<PExpr*>*range, list<index_component_t>*range,
PExpr*expr, LexicalScope::range_t*value_range); PExpr*expr, LexicalScope::range_t*value_range);
extern void pform_set_localparam(const struct vlltype&loc, extern void pform_set_localparam(const struct vlltype&loc,
perm_string name, perm_string name,
ivl_variable_type_t type, ivl_variable_type_t type,
bool signed_flag, bool signed_flag,
list<PExpr*>*range, list<index_component_t>*range,
PExpr*expr); PExpr*expr);
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr); extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
@ -386,7 +384,7 @@ extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t vtype, ivl_variable_type_t vtype,
bool signed_flag, bool signed_flag,
list<PExpr*>*range, list<index_component_t>*range,
list<perm_string>*names, list<perm_string>*names,
bool isint = false); bool isint = false);

View File

@ -1,7 +1,7 @@
#ifndef __pform_types_H #ifndef __pform_types_H
#define __pform_types_H #define __pform_types_H
/* /*
* Copyright (c) 2007-2011 Stephen Williams (steve@icarus.com) * Copyright (c) 2007-2012 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -84,14 +84,14 @@ struct data_type_t : public LineInfo {
struct enum_type_t : public data_type_t { struct enum_type_t : public data_type_t {
ivl_variable_type_t base_type; ivl_variable_type_t base_type;
bool signed_flag; bool signed_flag;
std::auto_ptr< list<PExpr*> > range; std::auto_ptr< list<index_component_t> > range;
std::auto_ptr< list<named_pexpr_t> > names; std::auto_ptr< list<named_pexpr_t> > names;
LineInfo li; LineInfo li;
}; };
struct struct_member_t : public LineInfo { struct struct_member_t : public LineInfo {
ivl_variable_type_t type; ivl_variable_type_t type;
std::auto_ptr< list<PExpr*> > range; std::auto_ptr< list<index_component_t> > range;
std::auto_ptr< list<decl_assignment_t*> > names; std::auto_ptr< list<decl_assignment_t*> > names;
}; };
@ -108,11 +108,12 @@ struct atom2_type_t : public data_type_t {
}; };
struct vector_type_t : public data_type_t { struct vector_type_t : public data_type_t {
inline explicit vector_type_t(ivl_variable_type_t bt, bool sf, list<PExpr*>*pd) inline explicit vector_type_t(ivl_variable_type_t bt, bool sf,
std::list<index_component_t>*pd)
: base_type(bt), signed_flag(sf), pdims(pd) { } : base_type(bt), signed_flag(sf), pdims(pd) { }
ivl_variable_type_t base_type; ivl_variable_type_t base_type;
bool signed_flag; bool signed_flag;
std::auto_ptr< list<PExpr*> > pdims; std::auto_ptr< list<index_component_t> > pdims;
}; };
struct real_type_t : public data_type_t { struct real_type_t : public data_type_t {