Rework rules for variable_dimensions, and support more syntax.
This commit is contained in:
parent
64ea328823
commit
f749867369
4
PTask.h
4
PTask.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -46,7 +46,7 @@ enum PTaskFuncEnum {
|
|||
|
||||
struct PTaskFuncArg {
|
||||
PTaskFuncEnum type;
|
||||
vector<PExpr*>*range;
|
||||
std::list<index_component_t>*range;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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)
|
||||
{
|
||||
bool rc_flag;
|
||||
assert(enum_type->range->size() == 2);
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, enum_type->range->front(), -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, enum_type->range->back(), -1);
|
||||
assert(enum_type->range->size() == 1);
|
||||
index_component_t index = enum_type->range->front();
|
||||
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;
|
||||
rc_flag = eval_as_long(msb, msb_ex);
|
||||
|
|
|
|||
33
elab_sig.cc
33
elab_sig.cc
|
|
@ -476,15 +476,12 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
case PTF_REG:
|
||||
case PTF_REG_S:
|
||||
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,
|
||||
return_type_.range->at(0), -1,
|
||||
true);
|
||||
NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
return_type_.range->at(1), -1,
|
||||
true);
|
||||
NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
|
||||
assert(le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
|
|
@ -550,17 +547,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
case PTF_ATOM2:
|
||||
case PTF_ATOM2_S:
|
||||
ivl_assert(*this, return_type_.range != 0);
|
||||
long use_wid;
|
||||
{
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1,
|
||||
true);
|
||||
assert(le);
|
||||
ivl_assert(*this, return_type_.range->size() == 1);
|
||||
index_component_t index = return_type_.range->front();
|
||||
NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
|
||||
ivl_assert(*this, me);
|
||||
NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
|
||||
ivl_assert(*this, le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
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_lsb = 0;
|
||||
if (curp->range.get() && ! curp->range->empty()) {
|
||||
ivl_assert(*curp, curp->range->size() == 2);
|
||||
PExpr*msb_pex = curp->range->front();
|
||||
PExpr*lsb_pex = curp->range->back();
|
||||
ivl_assert(*curp, curp->range->size() == 1);
|
||||
index_component_t index = curp->range->front();
|
||||
PExpr*msb_pex = index.msb;
|
||||
PExpr*lsb_pex = index.lsb;
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true);
|
||||
ivl_assert(*curp, tmp);
|
||||
|
|
|
|||
316
parse.y
316
parse.y
|
|
@ -38,7 +38,7 @@ extern void lex_end_table();
|
|||
bool have_timeunit_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 ivl_variable_type_t param_active_type = IVL_VT_LOGIC;
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ static struct {
|
|||
NetNet::PortType port_type;
|
||||
ivl_variable_type_t var_type;
|
||||
bool sign_flag;
|
||||
list<PExpr*>* range;
|
||||
list<index_component_t>* range;
|
||||
data_type_t* data_type;
|
||||
} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT,
|
||||
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;
|
||||
return tmp;
|
||||
}
|
||||
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string,
|
||||
PExpr*> >*tmp,
|
||||
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string, PExpr*> >*tmp,
|
||||
char*id, PExpr*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;
|
||||
}
|
||||
|
||||
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)));
|
||||
range->push_back(new PENumber(new verinum((uint64_t)0, integer_width)));
|
||||
index_component_t tmp;
|
||||
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;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* 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;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
/*
|
||||
* Make a range vector from a width. Generate the msb and lsb
|
||||
* 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));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#endif
|
||||
static list<perm_string>* list_from_identifier(char*id)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
copy = new list<PExpr*> (*orig);
|
||||
copy = new list<index_component_t> (*orig);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
|
@ -512,8 +515,8 @@ static void current_task_set_statement(vector<Statement*>*s)
|
|||
%type <struct_members> struct_union_member_list
|
||||
%type <struct_type> struct_data_type
|
||||
|
||||
%type <exprs> range range_opt variable_dimension
|
||||
%type <dimensions> dimensions_opt dimensions
|
||||
%type <dimensions> range range_opt
|
||||
%type <dimensions> dimensions_opt dimensions variable_dimension
|
||||
%type <nettype> net_type var_type net_type_opt
|
||||
%type <gatetype> gatetype switchtype
|
||||
%type <porttype> port_direction port_direction_opt
|
||||
|
|
@ -1015,13 +1018,6 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */
|
|||
delete[]$1;
|
||||
$$ = 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 '[' '$' ']'
|
||||
{ decl_assignment_t*tmp = new decl_assignment_t;
|
||||
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]. */
|
||||
|
||||
: 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;
|
||||
|
||||
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). */
|
||||
|
||||
| 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;
|
||||
|
||||
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 */
|
||||
: '[' expression ':' expression ']'
|
||||
{ list<PExpr*>*tmp = new list<PExpr*>;
|
||||
tmp->push_back($2);
|
||||
tmp->push_back($4);
|
||||
{ list<index_component_t> *tmp = new list<index_component_t>;
|
||||
index_component_t index;
|
||||
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;
|
||||
}
|
||||
| '[' ']'
|
||||
{ list<PExpr*>*tmp = new list<PExpr*>;
|
||||
tmp->push_back(0);
|
||||
tmp->push_back(0);
|
||||
{ list<index_component_t> *tmp = new list<index_component_t>;
|
||||
index_component_t index;
|
||||
index.msb = 0;
|
||||
index.lsb = 0;
|
||||
yyerror("sorry: Dynamic array ranges not supported.");
|
||||
tmp->push_back(index);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
;
|
||||
|
||||
/* Verilog-2001 supports attribute lists, which can be attached to a
|
||||
variety of different objects. The syntax inside the (* *) is a
|
||||
|
|
@ -2822,20 +2839,21 @@ gate_instance
|
|||
$$ = tmp;
|
||||
}
|
||||
|
||||
| IDENTIFIER range '(' expression_list_with_nuls ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
list<PExpr*>*rng = $2;
|
||||
tmp->name = $1;
|
||||
tmp->parms = $4;
|
||||
tmp->range[0] = rng->front(); rng->pop_front();
|
||||
tmp->range[1] = rng->front(); rng->pop_front();
|
||||
assert(rng->empty());
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
delete rng;
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER range '(' expression_list_with_nuls ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
list<index_component_t>*rng = $2;
|
||||
tmp->name = $1;
|
||||
tmp->parms = $4;
|
||||
tmp->range = rng->front();
|
||||
rng->pop_front();
|
||||
assert(rng->empty());
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
delete rng;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| '(' expression_list_with_nuls ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
tmp->name = "";
|
||||
|
|
@ -2847,50 +2865,50 @@ gate_instance
|
|||
|
||||
/* Degenerate modules can have no ports. */
|
||||
|
||||
| IDENTIFIER range
|
||||
{ lgate*tmp = new lgate;
|
||||
list<PExpr*>*rng = $2;
|
||||
tmp->name = $1;
|
||||
tmp->parms = 0;
|
||||
tmp->parms_by_name = 0;
|
||||
tmp->range[0] = rng->front(); rng->pop_front();
|
||||
tmp->range[1] = rng->front(); rng->pop_front();
|
||||
assert(rng->empty());
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
delete rng;
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER range
|
||||
{ lgate*tmp = new lgate;
|
||||
list<index_component_t>*rng = $2;
|
||||
tmp->name = $1;
|
||||
tmp->parms = 0;
|
||||
tmp->parms_by_name = 0;
|
||||
tmp->range = rng->front();
|
||||
rng->pop_front();
|
||||
assert(rng->empty());
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
delete rng;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Modules can also take ports by port-name expressions. */
|
||||
|
||||
| IDENTIFIER '(' port_name_list ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
tmp->name = $1;
|
||||
tmp->parms = 0;
|
||||
tmp->parms_by_name = $3;
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER '(' port_name_list ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
tmp->name = $1;
|
||||
tmp->parms = 0;
|
||||
tmp->parms_by_name = $3;
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| IDENTIFIER range '(' port_name_list ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
list<PExpr*>*rng = $2;
|
||||
tmp->name = $1;
|
||||
tmp->parms = 0;
|
||||
tmp->parms_by_name = $4;
|
||||
tmp->range[0] = rng->front(); rng->pop_front();
|
||||
tmp->range[1] = rng->front(); rng->pop_front();
|
||||
assert(rng->empty());
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
delete rng;
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER range '(' port_name_list ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
list<index_component_t>*rng = $2;
|
||||
tmp->name = $1;
|
||||
tmp->parms = 0;
|
||||
tmp->parms_by_name = $4;
|
||||
tmp->range = rng->front();
|
||||
rng->pop_front();
|
||||
assert(rng->empty());
|
||||
tmp->file = @1.text;
|
||||
tmp->lineno = @1.first_line;
|
||||
delete[]$1;
|
||||
delete rng;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| IDENTIFIER '(' error ')'
|
||||
{ lgate*tmp = new lgate;
|
||||
|
|
@ -3143,7 +3161,7 @@ port_declaration
|
|||
K_input atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
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,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT,
|
||||
|
|
@ -3289,7 +3307,7 @@ port_declaration
|
|||
K_output atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
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,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
|
|
@ -3308,7 +3326,7 @@ port_declaration
|
|||
K_output atom2_type signed_unsigned_opt IDENTIFIER '=' expression
|
||||
{ Module::port_t*ptmp;
|
||||
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,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
|
|
@ -4606,9 +4624,13 @@ port_reference_list
|
|||
/* The range is a list of variable dimensions. */
|
||||
range
|
||||
: variable_dimension
|
||||
{ $$ = $1; }
|
||||
| range variable_dimension
|
||||
{ list<PExpr*>*tmp = $1;
|
||||
if ($2) tmp->splice(tmp->end(), *$2);
|
||||
{ list<index_component_t>*tmp = $1;
|
||||
if ($2) {
|
||||
tmp->splice(tmp->end(), *$2);
|
||||
delete $2;
|
||||
}
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -4623,88 +4645,54 @@ dimensions_opt
|
|||
| dimensions { $$ = $1; }
|
||||
|
||||
dimensions
|
||||
: '[' expression ':' expression ']'
|
||||
{ list<index_component_t> *tmp = new list<index_component_t>;
|
||||
index_component_t index;
|
||||
index.msb = $2;
|
||||
index.lsb = $4;
|
||||
tmp->push_back(index);
|
||||
$$ = tmp;
|
||||
}
|
||||
| '[' 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 = 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;
|
||||
}
|
||||
: variable_dimension
|
||||
{ $$ = $1; }
|
||||
| dimensions variable_dimension
|
||||
{ list<index_component_t> *tmp = $1;
|
||||
if ($2) {
|
||||
tmp->splice(tmp->end(), *$2);
|
||||
delete $2;
|
||||
}
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* This is used to express the return type of a function. */
|
||||
function_range_or_type_opt
|
||||
: unsigned_signed_opt range_opt
|
||||
{
|
||||
/* the default type is reg unsigned and no range */
|
||||
$$.type = PTF_REG;
|
||||
$$.range = 0;
|
||||
if ($1)
|
||||
$$.type = PTF_REG_S;
|
||||
if ($2)
|
||||
$$.range = make_range_vector($2);
|
||||
}
|
||||
{ /* the default type is reg unsigned and no range */
|
||||
$$.type = PTF_REG;
|
||||
$$.range = 0;
|
||||
if ($1)
|
||||
$$.type = PTF_REG_S;
|
||||
if ($2)
|
||||
$$.range = $2;
|
||||
}
|
||||
| K_reg unsigned_signed_opt range_opt
|
||||
{
|
||||
/* the default type is reg unsigned and no range */
|
||||
$$.type = PTF_REG;
|
||||
$$.range = 0;
|
||||
if ($2)
|
||||
$$.type = PTF_REG_S;
|
||||
if ($3)
|
||||
$$.range = make_range_vector($3);
|
||||
}
|
||||
{ /* the default type is reg unsigned and no range */
|
||||
$$.type = PTF_REG;
|
||||
$$.range = 0;
|
||||
if ($2)
|
||||
$$.type = PTF_REG_S;
|
||||
if ($3)
|
||||
$$.range = $3;
|
||||
}
|
||||
| bit_logic unsigned_signed_opt range_opt
|
||||
{
|
||||
/* the default type is bit/logic unsigned and no range */
|
||||
$$.type = PTF_REG;
|
||||
$$.range = 0;
|
||||
if ($2)
|
||||
$$.type = PTF_REG_S;
|
||||
if ($3)
|
||||
$$.range = make_range_vector($3);
|
||||
}
|
||||
{ /* the default type is bit/logic unsigned and no range */
|
||||
$$.type = PTF_REG;
|
||||
$$.range = 0;
|
||||
if ($2)
|
||||
$$.type = PTF_REG_S;
|
||||
if ($3)
|
||||
$$.range = $3;
|
||||
}
|
||||
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
||||
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
||||
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
||||
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
||||
| atom2_type { $$.range = make_range_vector($1); $$.type = PTF_ATOM2_S; }
|
||||
| atom2_type K_signed { $$.range = make_range_vector($1); $$.type = PTF_ATOM2_S; }
|
||||
| atom2_type K_unsigned { $$.range = make_range_vector($1); $$.type = PTF_ATOM2; }
|
||||
| atom2_type { $$.range = make_range_from_width($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_from_width($1); $$.type = PTF_ATOM2; }
|
||||
;
|
||||
|
||||
/* 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. */
|
||||
|
||||
| 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,
|
||||
range_stub, $3, true);
|
||||
$$ = tmp;
|
||||
|
|
@ -5586,7 +5574,7 @@ task_port_item
|
|||
/* Ports can be time with a width of [63:0] (unsigned). */
|
||||
|
||||
| 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,
|
||||
range_stub, $3);
|
||||
$$ = tmp;
|
||||
|
|
|
|||
77
pform.cc
77
pform.cc
|
|
@ -1480,16 +1480,15 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
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
|
||||
// range. The parser will assure that for us.
|
||||
assert(range->size()%2 == 0);
|
||||
list<PExpr*>::const_iterator rcur = range->begin();
|
||||
while (rcur != range->end()) {
|
||||
// Convert a list of index_component_t to PWire::range_t.
|
||||
for (list<index_component_t>::const_iterator rcur = range->begin()
|
||||
; rcur != range->end() ; ++rcur) {
|
||||
PWire::range_t rng;
|
||||
rng.msb = *rcur; ++rcur;
|
||||
rng.lsb = *rcur; ++rcur;
|
||||
rng.msb = rcur->msb;
|
||||
rng.lsb = rcur->lsb;
|
||||
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.
|
||||
*/
|
||||
static void pform_set_net_range(perm_string name,
|
||||
const list<PExpr*>*range,
|
||||
const list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt,
|
||||
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,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
{
|
||||
assert((range == 0) || (range->size()%2 == 0));
|
||||
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ 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);
|
||||
PGBuiltin*cur = new PGBuiltin(type, dev_name, info.parms, delay);
|
||||
if (info.range[0])
|
||||
cur->set_range(info.range[0], info.range[1]);
|
||||
if (info.range.msb)
|
||||
cur->set_range(info.range.msb, info.range.lsb);
|
||||
|
||||
// The pform_makegates() that calls me will take care of
|
||||
// deleting the attr pointer, so tell the
|
||||
|
|
@ -1741,7 +1738,7 @@ void pform_make_modgates(perm_string type,
|
|||
if (cur.parms_by_name) {
|
||||
pform_make_modgate(type, cur_name, overrides,
|
||||
cur.parms_by_name,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.range.msb, cur.range.lsb,
|
||||
cur.file, cur.lineno);
|
||||
|
||||
} else if (cur.parms) {
|
||||
|
|
@ -1755,14 +1752,14 @@ void pform_make_modgates(perm_string type,
|
|||
}
|
||||
pform_make_modgate(type, cur_name, overrides,
|
||||
cur.parms,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.range.msb, cur.range.lsb,
|
||||
cur.file, cur.lineno);
|
||||
|
||||
} else {
|
||||
list<PExpr*>*wires = new list<PExpr*>;
|
||||
pform_make_modgate(type, cur_name, overrides,
|
||||
wires,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.range.msb, cur.range.lsb,
|
||||
cur.file, cur.lineno);
|
||||
}
|
||||
}
|
||||
|
|
@ -1875,7 +1872,7 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
NetNet::Type type,
|
||||
ivl_variable_type_t data_type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
|
|
@ -2011,7 +2008,7 @@ void pform_makewire(const vlltype&li, perm_string name,
|
|||
* pform_makewire above.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<perm_string>*names,
|
||||
NetNet::Type type,
|
||||
|
|
@ -2038,7 +2035,7 @@ void pform_makewire(const vlltype&li,
|
|||
* This form makes nets with delays and continuous assignments.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*delay,
|
||||
str_pair_t str,
|
||||
|
|
@ -2149,7 +2146,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
|||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<perm_string>*names,
|
||||
bool isint)
|
||||
{
|
||||
|
|
@ -2198,7 +2195,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
|||
list<perm_string>*names)
|
||||
{
|
||||
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,
|
||||
atype->signed_flag,
|
||||
range_tmp, names);
|
||||
|
|
@ -2211,7 +2208,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
|||
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,
|
||||
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,
|
||||
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*scope = lexical_scope;
|
||||
|
|
@ -2360,11 +2357,12 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
|
||||
parm.type = type;
|
||||
if (range) {
|
||||
assert(range->size() == 2);
|
||||
assert(range->front());
|
||||
assert(range->back());
|
||||
parm.msb = range->front();
|
||||
parm.lsb = range->back();
|
||||
assert(range->size() == 1);
|
||||
index_component_t index = range->front();
|
||||
assert(index.msb);
|
||||
assert(index.lsb);
|
||||
parm.msb = index.msb;
|
||||
parm.lsb = index.lsb;
|
||||
} else {
|
||||
parm.msb = 0;
|
||||
parm.lsb = 0;
|
||||
|
|
@ -2378,7 +2376,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
|
||||
void pform_set_localparam(const struct vlltype&loc,
|
||||
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;
|
||||
|
||||
|
|
@ -2408,11 +2406,12 @@ void pform_set_localparam(const struct vlltype&loc,
|
|||
|
||||
parm.type = type;
|
||||
if (range) {
|
||||
assert(range->size() == 2);
|
||||
assert(range->front());
|
||||
assert(range->back());
|
||||
parm.msb = range->front();
|
||||
parm.lsb = range->back();
|
||||
assert(range->size() == 1);
|
||||
index_component_t index = range->front();
|
||||
assert(index.msb);
|
||||
assert(index.lsb);
|
||||
parm.msb = index.msb;
|
||||
parm.lsb = index.lsb;
|
||||
} else {
|
||||
parm.msb = 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,
|
||||
list<perm_string>*names,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
NetNet::PortType pt)
|
||||
{
|
||||
|
|
@ -2627,7 +2626,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
|
|||
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);
|
||||
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);
|
||||
|
||||
assert(enum_type->range.get() != 0);
|
||||
assert(enum_type->range->size() == 2);
|
||||
assert(enum_type->range->size() == 1);
|
||||
list<PWire::range_t>rlist;
|
||||
ranges_from_list(rlist, enum_type->range.get());
|
||||
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->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.
|
||||
FILE_NAME(&(enum_type->li), li);
|
||||
|
|
|
|||
26
pform.h
26
pform.h
|
|
@ -101,24 +101,22 @@ struct net_decl_assign_t {
|
|||
|
||||
/* The lgate is gate instantiation information. */
|
||||
struct lgate {
|
||||
lgate(int =0)
|
||||
inline lgate(int =0)
|
||||
: parms(0), parms_by_name(0), file(NULL), lineno(0)
|
||||
{ range[0] = 0;
|
||||
range[1] = 0;
|
||||
}
|
||||
{ }
|
||||
|
||||
string name;
|
||||
list<PExpr*>*parms;
|
||||
list<named_pexpr_t>*parms_by_name;
|
||||
|
||||
PExpr*range[2];
|
||||
index_component_t range;
|
||||
|
||||
const char* file;
|
||||
unsigned lineno;
|
||||
};
|
||||
|
||||
extern std::list<PExpr*>* make_range_from_width(uint64_t wid);
|
||||
extern list<PExpr*>* copy_range(list<PExpr*>* orig);
|
||||
extern std::list<index_component_t>* make_range_from_width(uint64_t wid);
|
||||
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
|
||||
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,
|
||||
ivl_variable_type_t data_type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<named_pexpr_t>*attr);
|
||||
|
||||
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 */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<perm_string>*names,
|
||||
NetNet::Type type,
|
||||
|
|
@ -258,7 +256,7 @@ extern void pform_makewire(const struct vlltype&li,
|
|||
|
||||
/* This form handles assignment declarations. */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*delay,
|
||||
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. */
|
||||
extern void pform_set_port_type(const struct vlltype&li,
|
||||
list<perm_string>*names,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
NetNet::PortType);
|
||||
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,
|
||||
ivl_variable_type_t type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
PExpr*expr, LexicalScope::range_t*value_range);
|
||||
extern void pform_set_localparam(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
ivl_variable_type_t type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
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,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<perm_string>*names,
|
||||
bool isint = false);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* 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 {
|
||||
ivl_variable_type_t base_type;
|
||||
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;
|
||||
LineInfo li;
|
||||
};
|
||||
|
||||
struct struct_member_t : public LineInfo {
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
@ -108,11 +108,12 @@ struct atom2_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) { }
|
||||
ivl_variable_type_t base_type;
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue