Rework parsing of parameter types

Use the common data_type_or_implicit rules to support type
definitions for parameters. This eliminates a bunch of special
rules in parse.y, and opens the door for parameters having
more complex types.
This commit is contained in:
Stephen Williams 2020-12-24 18:12:06 -08:00
parent 51025149a9
commit 16646c547c
23 changed files with 468 additions and 417 deletions

View File

@ -434,11 +434,10 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
{
NetNet* net = 0;
const NetExpr*par = 0;
ivl_type_t par_type;
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
scope = symbol_search(this, des, scope, path_, net, par, eve, ex1, ex2);
scope = symbol_search(this, des, scope, path_, net, par, eve, par_type);
if (scope)
return scope->is_auto();

19
PExpr.h
View File

@ -407,10 +407,6 @@ class PEIdent : public PExpr {
// flag is set to *false*.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
bool calculate_param_range_(Design*, NetScope*,
const NetExpr*msb_ex, long&msb,
const NetExpr*lsb_ex, long&lsb,
long length) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
@ -450,37 +446,32 @@ class PEIdent : public PExpr {
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
unsigned expr_wid,
unsigned flags) const;
NetExpr*elaborate_expr_param_bit_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
unsigned expr_wid) const;
NetExpr*elaborate_expr_param_idx_up_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_do_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,

View File

@ -98,12 +98,9 @@ class LexicalScope {
is elaborated. During parsing, I put the parameters into
this map. */
struct param_expr_t : public PNamedItem {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
inline param_expr_t() : data_type(0), expr(0), range(0) { }
// Type information.
data_type_t*data_type;
// Value expression
PExpr*expr;
// If there are range constraints, list them here

View File

@ -1465,14 +1465,8 @@ void NetScope::dump(ostream&o) const
else
o << " parameter ";
o << pp->second.type << " ";
if ((*pp).second.signed_flag)
o << "signed ";
if ((*pp).second.msb)
o << "[" << *(*pp).second.msb
<< ":" << *(*pp).second.lsb << "] ";
if (pp->second.ivl_type)
pp->second.ivl_type->debug_dump(o);
o << (*pp).first << " = ";
if (pp->second.val)

View File

@ -1333,11 +1333,10 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
NetNet *net = 0;
const NetExpr *par;
ivl_type_t par_type = 0;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
symbol_search(this, des, scope, use_path, net, par, eve, par_type);
const netdarray_t*use_darray = 0;
@ -1354,7 +1353,7 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
net = 0;
symbol_search(this, des, scope, tmp_path,
net, par, eve, ex1, ex2);
net, par, eve, par_type);
if (net && net->class_type()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
@ -2647,11 +2646,10 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
NetNet *net = 0;
const NetExpr *par;
ivl_type_t par_type;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
symbol_search(this, des, scope, use_path, net, par, eve, par_type);
if (net == 0)
return 0;
@ -3429,33 +3427,6 @@ NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope,
return tmp;
}
bool PEIdent::calculate_param_range_(Design*, NetScope*,
const NetExpr*par_msb, long&par_msv,
const NetExpr*par_lsb, long&par_lsv,
long length) const
{
if (par_msb == 0) {
// If the parameter doesn't have an explicit range, then
// just return range values of [length-1:0].
ivl_assert(*this, par_lsb == 0);
par_msv = length-1;
par_lsv = 0;
return true;
}
const NetEConst*tmp = dynamic_cast<const NetEConst*> (par_msb);
ivl_assert(*this, tmp);
par_msv = tmp->value().as_long();
tmp = dynamic_cast<const NetEConst*> (par_lsb);
ivl_assert(*this, tmp);
par_lsv = tmp->value().as_long();
return true;
}
unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
{
if (!gn_system_verilog())
@ -3475,9 +3446,9 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
NetNet*net = 0;
const NetExpr*par = 0;
ivl_type_t par_type = 0;
NetEvent*eve = 0;
const NetExpr*ex1 = 0, *ex2 = 0;
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
symbol_search(this, des, scope, use_path, net, par, eve, par_type);
if (net == 0) {
if (debug_elaborate)
cerr << get_fileline() << ": PEIdent::test_width_method_: "
@ -3521,10 +3492,9 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
{
NetNet* net = 0;
const NetExpr*par = 0;
ivl_type_t par_type = 0;
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
NetScope*use_scope = scope;
if (package_) {
use_scope = des->find_package(package_->pscope_name());
@ -3536,8 +3506,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
}
NetScope*found_in = symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
net, par, eve, par_type);
// If there is a part/bit select expression, then process it
// here. This constrains the results no matter what kind the
@ -3713,7 +3682,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
use_path.pop_back();
ivl_assert(*this, net == 0);
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
symbol_search(this, des, scope, use_path, net, par, eve, par_type);
// Check to see if we have a net and if so is it a structure?
if (net != 0) {
@ -3775,8 +3744,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetNet* net = 0;
const NetExpr*par = 0;
ivl_type_t par_type = 0;
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
NetScope*use_scope = scope;
if (package_) {
@ -3788,9 +3757,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp;
}
/* NetScope*found_in = */ symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
symbol_search(this, des, use_scope, path_, net, par, eve, par_type);
if (net == 0 && gn_system_verilog() && path_.size() >= 2) {
// NOTE: this is assuming the member_path is only one
@ -3802,7 +3769,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
use_path.pop_back();
ivl_assert(*this, net == 0);
symbol_search(this, des, use_scope, use_path, net, par, eve, ex1, ex2);
symbol_search(this, des, use_scope, use_path, net, par, eve, par_type);
if (net == 0) {
// Nope, no struct/class with member.
@ -4051,10 +4018,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetNet* net = 0;
const NetExpr*par = 0;
ivl_type_t par_type = 0;
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "path_=" << path_
@ -4112,7 +4078,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetScope*found_in = 0;
while (net==0 && par==0 && eve==0 && base_path.size()>0) {
found_in = symbol_search(this, des, use_scope, base_path,
net, par, eve, ex1, ex2);
net, par, eve, par_type);
if (net) break;
if (par) break;
if (eve) break;
@ -4144,7 +4110,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
ex1, ex2, expr_wid, flags);
par_type, expr_wid, flags);
if (!tmp) return 0;
@ -4463,16 +4429,14 @@ static verinum param_part_select_bits(const verinum&par_val, long wid,
NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
bool need_const) const
{
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
long par_msv, par_lsv;
if(! calculate_param_range_(des, scope, par_msb, par_msv,
par_lsb, par_lsv,
if(! calculate_param_range(*this, par_type, par_msv, par_lsv,
par_ex->value().len())) return 0;
const name_component_t&name_tail = path_.back();
@ -4559,8 +4523,7 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope,
NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
unsigned expr_wid) const
{
long msv, lsv;
@ -4574,8 +4537,7 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
long par_msv, par_lsv;
if (! calculate_param_range_(des, scope, par_msb, par_msv,
par_lsb, par_lsv,
if (! calculate_param_range(*this, par_type, par_msv, par_lsv,
par_ex->value().len())) return 0;
if (! parts_defined_flag) {
@ -4685,16 +4647,14 @@ static void warn_param_ob(long par_msv, long par_lsv, bool defined,
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
bool need_const) const
{
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
long par_msv, par_lsv;
if(! calculate_param_range_(des, scope, par_msb, par_msv,
par_lsb, par_lsv,
if(! calculate_param_range(*this, par_type, par_msv, par_lsv,
par_ex->value().len())) return 0;
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
@ -4737,8 +4697,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
if (warn_ob_select) {
bool defined = true;
// Check to see if the parameter has a defined range.
if (par_msb == 0) {
assert(par_lsb == 0);
if (par_type == 0) {
defined = false;
}
// Get the parameter values width.
@ -4769,16 +4728,14 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
bool need_const) const
{
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
long par_msv, par_lsv;
if(! calculate_param_range_(des, scope, par_msb, par_msv,
par_lsb, par_lsv,
if(! calculate_param_range(*this, par_type, par_msv, par_lsv,
par_ex->value().len())) return 0;
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
@ -4821,8 +4778,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
if (warn_ob_select) {
bool defined = true;
// Check to see if the parameter has a defined range.
if (par_msb == 0) {
assert(par_lsb == 0);
if (par_type == 0) {
defined = false;
}
// Get the parameter values width.
@ -4860,8 +4816,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
ivl_type_t par_type,
unsigned expr_wid, unsigned flags) const
{
bool need_const = NEED_CONST & flags;
@ -4894,19 +4849,19 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
if (use_sel == index_component_t::SEL_BIT)
return elaborate_expr_param_bit_(des, scope, par, found_in,
par_msb, par_lsb, need_const);
par_type, need_const);
if (use_sel == index_component_t::SEL_PART)
return elaborate_expr_param_part_(des, scope, par, found_in,
par_msb, par_lsb, expr_wid);
par_type, expr_wid);
if (use_sel == index_component_t::SEL_IDX_UP)
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
par_msb, par_lsb, need_const);
par_type, need_const);
if (use_sel == index_component_t::SEL_IDX_DO)
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
par_msb, par_lsb, need_const);
par_type, need_const);
NetExpr*tmp = 0;

View File

@ -65,11 +65,26 @@ void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
typedef map<perm_string,LexicalScope::param_expr_t*>::const_iterator mparm_it_t;
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
static void collect_parm_item(Design*des, NetScope*scope, perm_string name,
const LexicalScope::param_expr_t&cur,
bool is_annotatable,
bool local_flag)
bool is_annotatable, bool local_flag)
{
if (debug_scopes) {
cerr << cur.get_fileline() << ": " << __func__ << ": "
<< "parameter " << name << " ";
if (cur.data_type)
cerr << *cur.data_type;
else
cerr << "(nil type)";
ivl_assert(cur, cur.expr);
cerr << " = " << *cur.expr << "; ";
if (cur.range)
cerr << "with ranges ";
else
cerr << "without ranges ";
cerr << "; in scope " << scope_path(scope) << endl;
}
NetScope::range_t*range_list = 0;
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
@ -104,38 +119,57 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
range_list = tmp;
}
// The type of the parameter, if unspecified in the source, will come
// from the type of the value assigned to it. Therefore, if the type is
// not yet known, don't try to guess here, put the type guess off. Also
// don't try to elaborate it here, because there may be references to
// other parameters still being located during scope elaboration.
scope->set_parameter(name, is_annotatable, cur.expr, cur.data_type, local_flag, range_list, cur);
scope->set_parameter(name, is_annotatable, cur.expr, cur.type, cur.msb,
cur.lsb, cur.signed_flag, local_flag, range_list, cur);
}
static void collect_scope_parameters_(Design*des, NetScope*scope,
static void collect_scope_parameters(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t*>&parameters)
{
if (debug_scopes) {
cerr << scope->get_fileline() << ": " << __func__ << ": "
<< "collect parameters for " << scope_path(scope) << "." << endl;
}
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
collect_parm_item_(des, scope, cur->first, *(cur->second), false, false);
collect_parm_item(des, scope, cur->first, *(cur->second), false, false);
}
}
static void collect_scope_localparams_(Design*des, NetScope*scope,
static void collect_scope_localparams(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t*>&localparams)
{
if (debug_scopes) {
cerr << scope->get_fileline() << ": " << __func__ << ": "
<< "collect localparams for " << scope_path(scope) << "." << endl;
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
collect_parm_item_(des, scope, cur->first, *(cur->second), false, true);
collect_parm_item(des, scope, cur->first, *(cur->second), false, true);
}
}
static void collect_scope_specparams_(Design*des, NetScope*scope,
static void collect_scope_specparams(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t*>&specparams)
{
if (debug_scopes) {
cerr << scope->get_fileline() << ": " << __func__ << ": "
<< "collect specparams for " << scope_path(scope) << "." << endl;
}
for (mparm_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
collect_parm_item_(des, scope, cur->first, *(cur->second), true, false);
collect_parm_item(des, scope, cur->first, *(cur->second), true, false);
}
}
@ -356,6 +390,13 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
static void elaborate_scope_enumerations(Design*des, NetScope*scope,
const set<enum_type_t*>&enum_types)
{
if (debug_scopes) {
cerr << scope->get_fileline() << ": " << __func__ << ": "
<< "Elaborate " << enum_types.size() << " enumerations"
<< " in scope " << scope_path(scope) << "."
<< endl;
}
for (set<enum_type_t*>::const_iterator cur = enum_types.begin()
; cur != enum_types.end() ; ++ cur) {
enum_type_t*curp = *cur;
@ -564,15 +605,27 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
static void elaborate_scope_classes(Design*des, NetScope*scope,
const vector<PClass*>&classes)
{
if (debug_scopes) {
cerr << scope->get_fileline() << ": " << __func__ << ": "
<< "Elaborate " << classes.size() << " classes"
<< " in scope " << scope_path(scope) << "."
<< endl;
}
for (size_t idx = 0 ; idx < classes.size() ; idx += 1) {
blend_class_constructors(classes[idx]);
elaborate_scope_class(des, scope, classes[idx]);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
static void replace_scope_parameters(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
if (debug_scopes) {
cerr << scope->get_fileline() << ": " << __func__ << ": "
<< "Replace scope parameters for " << scope_path(scope) << "." << endl;
}
for (Module::replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; ++ cur ) {
@ -712,8 +765,8 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
scope->add_typedefs(&typedefs);
collect_scope_parameters_(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
collect_scope_parameters(des, scope, parameters);
collect_scope_localparams(des, scope, localparams);
if (debug_scopes) {
cerr << get_fileline() << ": PPackage::elaborate_scope: "
@ -751,23 +804,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// will be evaluated later, once all parameter overrides for this
// module have been done.
collect_scope_parameters_(des, scope, parameters);
collect_scope_parameters(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
collect_scope_localparams(des, scope, localparams);
collect_scope_specparams_(des, scope, specparams);
collect_scope_specparams(des, scope, specparams);
// Run parameter replacements that were collected from the
// containing scope and meant for me.
replace_scope_parameters_(scope, *this, replacements);
replace_scope_parameters(scope, *this, replacements);
if (debug_scopes) {
cerr << get_fileline() << ": Module::elaborate_scope: "
<< "Elaborate " << enum_sets.size() << " enumerations"
<< " in scope " << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, scope, enum_sets);
assert(classes.size() == classes_lexical.size());
@ -796,7 +843,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// we can not do that until defparams are run, so push it off
// into an elaborate work item.
if (debug_scopes)
cerr << get_fileline() << ": debug: "
cerr << get_fileline() << ": " << __func__ << ": "
<< "Schedule generates within " << scope_path(scope)
<< " for elaboration after defparams." << endl;
@ -1216,7 +1263,7 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
// needed to evaluate the parameter expressions. The expressions
// will be evaluated later, once all parameter overrides for this
// module have been done.
collect_scope_localparams_(des, scope, localparams);
collect_scope_localparams(des, scope, localparams);
// Run through the defparams for this scope and save the result
// in a table for later final override.
@ -1564,9 +1611,9 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
// Scan the parameters in the function, and store the information
// needed to evaluate the parameter expressions.
collect_scope_parameters_(des, scope, parameters);
collect_scope_parameters(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
collect_scope_localparams(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@ -1584,9 +1631,9 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
// Scan the parameters in the task, and store the information
// needed to evaluate the parameter expressions.
collect_scope_parameters_(des, scope, parameters);
collect_scope_parameters(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
collect_scope_localparams(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@ -1634,9 +1681,9 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
// Scan the parameters in the scope, and store the information
// needed to evaluate the parameter expressions.
collect_scope_parameters_(des, my_scope, parameters);
collect_scope_parameters(des, my_scope, parameters);
collect_scope_localparams_(des, my_scope, localparams);
collect_scope_localparams(des, my_scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);

View File

@ -3780,8 +3780,8 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
NetNet *net;
const NetExpr *par;
ivl_type_t par_type = 0;
NetEvent *eve;
const NetExpr *ex1, *ex2;
/* Add the implicit this reference when requested. */
if (add_this_flag) {
@ -3796,8 +3796,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
// resolve to a class object. Note that the "this" symbol
// (internally represented as "@") is handled by there being a
// "this" object in the instance scope.
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
symbol_search(this, des, scope, use_path, net, par, eve, par_type);
if (net == 0)
return 0;

View File

@ -29,6 +29,8 @@
*/
# include "netlist.h"
# include "netscalar.h"
# include "netvector.h"
# include "util.h"
# include "compiler.h"
# include "netmisc.h"
@ -508,56 +510,71 @@ void Design::evaluate_parameters()
void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
{
long msb = 0;
long lsb = 0;
bool range_flag = false;
/* Evaluate the msb expression, if it is present. */
PExpr*msb_expr = (*cur).second.msb_expr;
if (msb_expr) {
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1, true);
if (! eval_as_long(msb, (*cur).second.msb)) {
cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": "
<< *(*cur).second.msb << endl;
des->errors += 1;
return;
}
range_flag = true;
}
/* Evaluate the lsb expression, if it is present. */
PExpr*lsb_expr = (*cur).second.lsb_expr;
if (lsb_expr) {
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1, true);
if (! eval_as_long(lsb, (*cur).second.lsb)) {
cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": "
<< *(*cur).second.lsb << endl;
des->errors += 1;
return;
}
range_flag = true;
}
/* Evaluate the parameter expression. */
PExpr*val_expr = (*cur).second.val_expr;
NetScope*val_scope = (*cur).second.val_scope;
// The param_type may be nil if the parameter has no declared type. In
// this case, we'll try to take our type from the r-value.
ivl_type_t param_type = cur->second.ivl_type;
// Most parameter declarations are packed vectors, of the form:
// parameter [H:L] foo == bar;
// so get the netvector_t. Note that this may also be the special
// case of a netvector_t with no dimensions, that exists only to carry
// signed-ness, e.g.:
// parameter signed foo = bar;
// (Scalars are handled differently, not by a netvector_t with no
// dimensions.)
const netvector_t* param_vect = dynamic_cast<const netvector_t*> (param_type);
if (debug_elaborate) {
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "parameter=" << cur->first << endl;
if (param_type)
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "param_type=" << *param_type << endl;
else
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "param_type=(nil)" << endl;
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "val_expr=" << *val_expr << endl;
}
ivl_variable_type_t use_type;
int lv_width = -2;
if (range_flag)
lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
if (param_type) {
use_type = param_type->base_type();
// Is this a netvector_t with no dimenions?
if (param_vect && param_vect->packed_dims().size()==0)
lv_width = -2;
else if (param_type->packed())
lv_width = param_type->packed_width();
} else {
use_type = val_expr->expr_type();
}
if (debug_elaborate) {
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "use_type = " << use_type << endl;
}
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true,
(*cur).second.is_annotatable,
(*cur).second.type);
cur->second.is_annotatable, use_type);
if (! expr)
return;
// Make sure to carry the signed-ness from a vector type.
if (param_vect)
expr->cast_signed(param_vect->get_signed());
if (debug_elaborate) {
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "expr = " << *expr << endl;
cerr << val_expr->get_fileline() << ": " << __func__ << ": "
<< "expr type = " << expr->expr_type() << endl;
}
switch (expr->expr_type()) {
case IVL_VT_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) {
@ -567,6 +584,13 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
des->errors += 1;
return;
}
// If the parameter has no type, then infer its type from the
// r-value expression.
if (param_type==0) {
param_type = &netreal_t::type_real;
cur->second.ivl_type = param_type;
}
break;
case IVL_VT_LOGIC:
@ -579,17 +603,20 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
return;
}
// If the parameter has type or range information, then
// make sure the type is set right. Note that if the
// parameter doesn't have an explicit type or range,
// then it will get the signedness from the expression itself.
if (cur->second.type != IVL_VT_NO_TYPE) {
expr->cast_signed(cur->second.signed_flag);
} else if (cur->second.signed_flag) {
expr->cast_signed(true);
// If the parameter has no type, then infer its type from the
// r-value expression.
if (param_type==0) {
param_type = new netvector_t(expr->expr_type(), expr->expr_width()-1,
0, expr->has_sign());
cur->second.ivl_type = param_type;
}
if (!range_flag && !expr->has_width()) {
if (param_type->base_type() != IVL_VT_NO_TYPE)
expr->cast_signed(param_type->get_signed());
if (!expr->has_width()) {
expr = pad_to_width(expr, integer_width, *expr);
} else if (param_type->slice_dimensions().size()==0 && !expr->has_width()) {
expr = pad_to_width(expr, integer_width, *expr);
}
break;
@ -597,18 +624,25 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
default:
cerr << expr->get_fileline()
<< ": internal error: "
<< "Unhandled expression type?" << endl;
<< "Unhandled expression type "
<< expr->expr_type() << "?" << endl;
cerr << expr->get_fileline()
<< ": : "
<< "param_type: " << *param_type << endl;
des->errors += 1;
return;
}
// By the time we're done with the above, we should certainly know the
// type of the parameter.
ivl_assert(*expr, cur->second.ivl_type);
cur->second.val = expr;
// If there are no value ranges to test the value against,
// then we are done.
if ((*cur).second.range == 0) {
if ((*cur).second.range == 0)
return;
}
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.val);
ivl_assert(*(*cur).second.val, (*cur).second.val);
@ -671,10 +705,12 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
{
PExpr*val_expr = (*cur).second.val_expr;
NetScope*val_scope = (*cur).second.val_scope;
ivl_type_t param_type = cur->second.ivl_type;
ivl_assert(*val_expr, param_type);
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true,
(*cur).second.is_annotatable,
(*cur).second.type);
cur->second.is_annotatable,
param_type->base_type());
if (! expr)
return;
@ -755,18 +791,37 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
{
ivl_type_t param_type = cur->second.ivl_type;
// If the parameter type is present, then elaborate it now.
if (cur->second.val_type) {
param_type = cur->second.val_type->elaborate_type(des, cur->second.val_scope);
cur->second.ivl_type = param_type;
cur->second.val_type = 0;
}
// If the parameter has already been evaluated, quietly return.
if (cur->second.val_expr == 0)
return;
// Guess the varaiable type of the parameter. If the parameter has no
// given type, then guess the type from the expression and use that to
// evaluate.
ivl_variable_type_t use_type;
if (param_type)
use_type = param_type->base_type();
else
use_type = cur->second.val_expr->expr_type();
if (cur->second.solving) {
cerr << cur->second.get_fileline() << ": error: "
<< "Recursive parameter reference found involving "
<< cur->first << "." << endl;
des->errors += 1;
} else {
cur->second.solving = true;
switch (cur->second.type) {
switch (use_type) {
case IVL_VT_NO_TYPE:
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
@ -779,7 +834,7 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
default:
cerr << cur->second.get_fileline() << ": internal error: "
<< "Unexpected expression type " << cur->second.type
<< "Unexpected expression type " << use_type
<< "." << endl;
cerr << cur->second.get_fileline() << ": : "
<< "Parameter name: " << cur->first << endl;

View File

@ -198,6 +198,22 @@ void NetScope::set_line(perm_string file, unsigned lineno)
def_lineno_ = lineno;
}
string NetScope::get_fileline() const
{
ostringstream buf;
buf << (file_? file_ : "") << ":" << lineno_;
string res = buf.str();
return res;
}
string NetScope::get_def_fileline() const
{
ostringstream buf;
buf << (def_file_? def_file_ : "") << ":" << def_lineno_;
string res = buf.str();
return res;
}
void NetScope::set_line(perm_string file, perm_string def_file,
unsigned lineno, unsigned def_lineno)
{
@ -279,27 +295,28 @@ const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_strin
return cur_scope->enum_names_[name]->enumeration();
}
/*
* Attach to the a parameter name in the scope a value and a type. The value
* (val_expr) is the PExpr form that is not yet elaborated. Later, when
* elaboration happens, the val_expr is elaborated and written to the val
* member.
*/
void NetScope::set_parameter(perm_string key, bool is_annotatable,
PExpr*val, ivl_variable_type_t type__,
PExpr*msb, PExpr*lsb, bool signed_flag,
PExpr*val, data_type_t*val_type,
bool local_flag,
NetScope::range_t*range_list,
const LineInfo&file_line)
{
param_expr_t&ref = parameters[key];
ref.is_annotatable = is_annotatable;
ref.msb_expr = msb;
ref.lsb_expr = lsb;
ref.val_expr = val;
ref.val_type = val_type;
ref.val_scope = this;
ref.type = type__;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = signed_flag;
ref.local_flag = local_flag;
ivl_assert(file_line, ref.range == 0);
ref.range = range_list;
ref.val = 0;
ref.ivl_type = 0;
ref.set_line(file_line);
}
@ -313,14 +330,11 @@ void NetScope::set_parameter(perm_string key, NetExpr*val,
{
param_expr_t&ref = parameters[key];
ref.is_annotatable = false;
ref.msb_expr = 0;
ref.lsb_expr = 0;
ref.val_expr = 0;
ref.val_type = 0;
ref.val_scope = this;
ref.type = IVL_VT_BOOL;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
ref.ivl_type = netvector_t::integer_type();
ivl_assert(file_line, ref.ivl_type);
ref.val = val;
ref.set_line(file_line);
}
@ -399,18 +413,14 @@ bool NetScope::make_parameter_unannotatable(perm_string key)
* perm_string::literal method to fake the compiler into doing the
* compare without actually creating a perm_string.
*/
const NetExpr* NetScope::get_parameter(Design*des,
const char* key,
const NetExpr*&msb,
const NetExpr*&lsb)
const NetExpr* NetScope::get_parameter(Design*des, const char* key,
ivl_type_t&ivl_type)
{
return get_parameter(des, perm_string::literal(key), msb, lsb);
return get_parameter(des, perm_string::literal(key), ivl_type);
}
const NetExpr* NetScope::get_parameter(Design*des,
perm_string key,
const NetExpr*&msb,
const NetExpr*&lsb)
const NetExpr* NetScope::get_parameter(Design*des, perm_string key,
ivl_type_t&ivl_type)
{
map<perm_string,param_expr_t>::iterator idx;
@ -419,13 +429,11 @@ const NetExpr* NetScope::get_parameter(Design*des,
if (idx->second.val_expr)
evaluate_parameter_(des, idx);
msb = idx->second.msb;
lsb = idx->second.lsb;
ivl_type = idx->second.ivl_type;
return idx->second.val;
}
msb = 0;
lsb = 0;
ivl_type = 0;
const NetExpr*tmp = enumeration_expr(key);
return tmp;
}

View File

@ -79,6 +79,7 @@ class PExpr;
class PFunction;
class PPackage;
class PTaskFunc;
class data_type_t;
struct enum_type_t;
class netclass_t;
class netdarray_t;
@ -965,22 +966,17 @@ class NetScope : public Definitions, public Attrib {
struct range_t;
void set_parameter(perm_string name, bool is_annotatable,
PExpr*val, ivl_variable_type_t type,
PExpr*msb, PExpr*lsb, bool signed_flag,
PExpr*val, data_type_t*data_type,
bool local_flag,
NetScope::range_t*range_list,
const LineInfo&file_line);
void set_parameter(perm_string name, NetExpr*val,
const LineInfo&file_line);
const NetExpr*get_parameter(Design*des,
const char* name,
const NetExpr*&msb,
const NetExpr*&lsb);
const NetExpr*get_parameter(Design*des,
perm_string name,
const NetExpr*&msb,
const NetExpr*&lsb);
const NetExpr*get_parameter(Design*des, const char* name,
ivl_type_t&ivl_type);
const NetExpr*get_parameter(Design*des, perm_string name,
ivl_type_t&ivl_type);
/* These are used by defparam elaboration to replace the
expression with a new expression, without affecting the
@ -1073,6 +1069,9 @@ class NetScope : public Definitions, public Attrib {
unsigned get_lineno() const { return lineno_; };
unsigned get_def_lineno() const { return def_lineno_; };
std::string get_fileline() const;
std::string get_def_fileline() const;
bool in_func() const;
/* Provide a link back to the pform to allow early elaboration of
@ -1210,31 +1209,26 @@ class NetScope : public Definitions, public Attrib {
/* After everything is all set up, the code generators like
access to these things to make up the parameter lists. */
struct param_expr_t : public LineInfo {
param_expr_t() : msb_expr(0), lsb_expr(0), val_expr(0), val_scope(0),
param_expr_t() : val_expr(0), val_type(0), val_scope(0),
solving(false), is_annotatable(false),
type(IVL_VT_NO_TYPE), signed_flag(false),
local_flag(false),
msb(0), lsb(0), range(0), val(0) { }
// Source expressions
PExpr*msb_expr;
PExpr*lsb_expr;
range(0), val(0), ivl_type(0) { }
// Source expression and data type (before elaboration)
PExpr*val_expr;
data_type_t*val_type;
// Scope information
NetScope*val_scope;
// Evaluation status
bool solving;
// specparam status
bool is_annotatable;
// Type information
ivl_variable_type_t type;
bool signed_flag;
// Is this a localparam?
bool local_flag;
NetExpr*msb;
NetExpr*lsb;
// range constraints
struct range_t*range;
// Expression value
// Expression value and type (elaborated versoins of val_expr/val_type)
NetExpr*val;
ivl_type_t ivl_type;
};
map<perm_string,param_expr_t>parameters;

View File

@ -1809,3 +1809,52 @@ void check_for_inconsistent_delays(NetScope*scope)
display_ts_dly_warning = false;
}
}
/*
* Calculate the bit vector range for a parameter, from the type of the
* parameter. This is expecting that the type is a vector type. The parameter
* is presumably declared something like this:
*
* parameter [4:1] foo = <value>;
*
* In this case, the par_type is a netvector with a single dimension. The
* par_msv gets 4, and par_lsv get 1. The caller uses these values to
* interpret things like bit selects.
*/
bool calculate_param_range(const LineInfo&line, ivl_type_t par_type,
long&par_msv, long&par_lsv, long length)
{
const netvector_t*vector_type = dynamic_cast<const netvector_t*> (par_type);
if (vector_type == 0) {
// If the parameter doesn't have an explicit range, then
// just return range values of [length-1:0].
par_msv = length-1;
par_lsv = 0;
return true;
}
ivl_assert(line, vector_type->packed());
const std::vector<netrange_t>& packed_dims = vector_type->packed_dims();
// This is a netvector_t with 0 dimensions, then the parameter was
// declared with a statement like this:
//
// parameter signed foo = <value>;
//
// The netvector_t is just here to carry the signed-ness, which we don't
// even need here. So act like the type is defined by the r-value
// length.
if (packed_dims.size() == 0) {
par_msv = length-1;
par_lsv = 0;
return true;
}
ivl_assert(line, packed_dims.size() == 1);
netrange_t use_range = packed_dims[0];
par_msv = use_range.get_msb();
par_lsv = use_range.get_lsb();
return true;
}

View File

@ -45,7 +45,7 @@ extern NetScope* symbol_search(const LineInfo*li,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter/expr */
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
ivl_type_t&par_type);
inline NetScope* symbol_search(const LineInfo*li,
Design*des,
@ -55,8 +55,8 @@ inline NetScope* symbol_search(const LineInfo*li,
const NetExpr*&par,/* parameter/expr */
NetEvent*&eve /* named event */)
{
const NetExpr*ex1, *ex2;
return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
ivl_type_t par_type;
return symbol_search(li, des, start, path, net, par, eve, par_type);
}
/*

View File

@ -160,3 +160,4 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
return true;
}

View File

@ -27,6 +27,7 @@
# include <cassert>
class netrange_t;
class LineInfo;
/*
* This is a fully abstract type that is a type that can be attached
@ -135,6 +136,15 @@ extern std::ostream&operator << (std::ostream&out, const std::vector<netrange_t>
extern unsigned long netrange_width(const std::vector<netrange_t>&dims);
/*
* There are a few cases where we need to know about the single-level
* dimensions of a parameter declaration, for example:
*
* parameter [msv:lsv] foo ...;
*/
extern bool calculate_param_range(const LineInfo&line, ivl_type_t par_type,
long&par_msv, long&par_lsv, long length);
/*
* Take as input a list of packed dimensions and a list of prefix
* indices, and calculate the offset/width of the resulting slice into

View File

@ -18,6 +18,7 @@
*/
# include "netvector.h"
# include "compiler.h"
# include <iostream>
using namespace std;
@ -31,6 +32,17 @@ netvector_t netvector_t::atom2u16 (IVL_VT_BOOL, 15, 0, false);
netvector_t netvector_t::atom2s8 (IVL_VT_BOOL, 7, 0, true);
netvector_t netvector_t::atom2u8 (IVL_VT_BOOL, 7, 0, false);
static netvector_t* save_integer_type = 0;
const netvector_t* netvector_t::integer_type()
{
if (save_integer_type)
return save_integer_type;
save_integer_type = new netvector_t(IVL_VT_LOGIC, integer_width-1, 0, true);
save_integer_type->set_isint(true);
return save_integer_type;
}
//netvector_t netvector_t::scalar_bool (IVL_VT_BOOL);
netvector_t netvector_t::scalar_logic (IVL_VT_LOGIC);

View File

@ -78,6 +78,7 @@ class netvector_t : public ivl_type_s {
static netvector_t atom2u8;
static netvector_t scalar_bool;
static netvector_t scalar_logic;
static const netvector_t*integer_type();
private:
bool test_compatibility(ivl_type_t that) const;

73
parse.y
View File

@ -35,9 +35,8 @@ class PSpecPath;
extern void lex_end_table();
static list<pform_range_t>* param_active_range = 0;
static bool param_active_signed = false;
static ivl_variable_type_t param_active_type = IVL_VT_LOGIC;
static data_type_t* param_data_type = 0;
static list<pform_range_t>* specparam_active_range = 0;
/* Port declaration lists use this structure for context. */
static struct {
@ -649,7 +648,6 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <nettype> net_type net_type_opt
%type <gatetype> gatetype switchtype
%type <porttype> port_direction port_direction_opt
%type <vartype> bit_logic bit_logic_opt
%type <vartype> integer_vector_type
%type <parmvalue> parameter_value_opt
@ -5484,17 +5482,6 @@ net_decl_assigns
}
;
bit_logic
: K_logic { $$ = IVL_VT_LOGIC; }
| K_bool { $$ = IVL_VT_BOOL; /* Icarus misc */}
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
;
bit_logic_opt
: bit_logic
| { $$ = IVL_VT_NO_TYPE; }
;
net_type
: K_wire { $$ = NetNet::WIRE; }
| K_tri { $$ = NetNet::TRI; }
@ -5514,42 +5501,12 @@ net_type
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
;
param_type
: bit_logic_opt unsigned_signed_opt dimensions_opt
{ param_active_range = $3;
param_active_signed = $2;
if (($1 == IVL_VT_NO_TYPE) && ($3 != 0))
param_active_type = IVL_VT_LOGIC;
else
param_active_type = $1;
}
| K_integer signed_unsigned_opt
{ param_active_range = make_range_from_width(integer_width);
param_active_signed = $2;
param_active_type = IVL_VT_LOGIC;
}
| K_time unsigned_signed_opt
{ param_active_range = make_range_from_width(64);
param_active_signed = $2;
param_active_type = IVL_VT_LOGIC;
}
| real_or_realtime
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
}
| atom2_type signed_unsigned_opt
{ param_active_range = make_range_from_width($1);
param_active_signed = $2;
param_active_type = IVL_VT_BOOL;
}
| TYPE_IDENTIFIER
{ pform_set_type_referenced(@1, $1.text);
pform_set_param_from_type(@1, $1.type, $1.text, param_active_range,
param_active_signed, param_active_type);
delete[]$1.text;
}
;
/* The param_type rule is just the data_type_or_implicit rule wrapped
with an assignment to para_data_type with the figured data type.
This is used by parameter_assign, which is found to the right of
the param_type in various rules. */
param_type : data_type_or_implicit { param_data_type = $1; }
/* parameter and localparam assignment lists are broken into
separate BNF so that I can call slightly different parameter
@ -5569,8 +5526,7 @@ localparam_assign_list
parameter_assign
: IDENTIFIER '=' expression parameter_value_ranges_opt
{ PExpr*tmp = $3;
pform_set_parameter(@1, lex_strings.make($1), param_active_type,
param_active_signed, param_active_range, tmp, $4);
pform_set_parameter(@1, lex_strings.make($1), param_data_type, tmp, $4);
delete[]$1;
}
;
@ -5578,8 +5534,7 @@ parameter_assign
localparam_assign
: IDENTIFIER '=' expression
{ PExpr*tmp = $3;
pform_set_localparam(@1, lex_strings.make($1), param_active_type,
param_active_signed, param_active_range, tmp);
pform_set_localparam(@1, lex_strings.make($1), param_data_type, tmp);
delete[]$1;
}
;
@ -6305,7 +6260,7 @@ specparam
: IDENTIFIER '=' expression
{ PExpr*tmp = $3;
pform_set_specparam(@1, lex_strings.make($1),
param_active_range, tmp);
specparam_active_range, tmp);
delete[]$1;
}
| IDENTIFIER '=' expression ':' expression ':' expression
@ -6344,7 +6299,7 @@ specparam
min_typ_max_warn -= 1;
}
pform_set_specparam(@1, lex_strings.make($1),
param_active_range, tmp);
specparam_active_range, tmp);
delete[]$1;
}
| PATHPULSE_IDENTIFIER '=' expression
@ -6366,9 +6321,9 @@ specparam_list
specparam_decl
: specparam_list
| dimensions
{ param_active_range = $1; }
{ specparam_active_range = $1; }
specparam_list
{ param_active_range = 0; }
{ specparam_active_range = 0; }
;
spec_polarity

View File

@ -3168,8 +3168,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<pform_range_t>*range, PExpr*expr,
perm_string name, data_type_t*data_type, PExpr*expr,
LexicalScope::range_t*value_range)
{
LexicalScope*scope = lexical_scope;
@ -3190,20 +3189,7 @@ void pform_set_parameter(const struct vlltype&loc,
scope->parameters[name] = parm;
parm->expr = expr;
parm->type = type;
if (range) {
assert(range->size() == 1);
pform_range_t&rng = range->front();
assert(rng.first);
assert(rng.second);
parm->msb = rng.first;
parm->lsb = rng.second;
} else {
parm->msb = 0;
parm->lsb = 0;
}
parm->signed_flag = signed_flag;
parm->data_type = data_type;
parm->range = value_range;
// Only a Module keeps the position of the parameter.
@ -3212,8 +3198,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<pform_range_t>*range, PExpr*expr)
perm_string name, data_type_t*data_type, PExpr*expr)
{
LexicalScope*scope = lexical_scope;
if (is_compilation_unit(scope) && !gn_system_verilog()) {
@ -3229,20 +3214,7 @@ void pform_set_localparam(const struct vlltype&loc,
scope->localparams[name] = parm;
parm->expr = expr;
parm->type = type;
if (range) {
assert(range->size() == 1);
pform_range_t&rng = range->front();
assert(rng.first);
assert(rng.second);
parm->msb = rng.first;
parm->lsb = rng.second;
} else {
parm->msb = 0;
parm->lsb = 0;
}
parm->signed_flag = signed_flag;
parm->data_type = data_type;
parm->range = 0;
}
@ -3261,23 +3233,14 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name,
pform_cur_module.front()->specparams[name] = parm;
parm->expr = expr;
parm->range = 0;
if (range) {
assert(range->size() == 1);
pform_range_t&rng = range->front();
assert(rng.first);
assert(rng.second);
parm->type = IVL_VT_LOGIC;
parm->msb = rng.first;
parm->lsb = rng.second;
} else {
parm->type = IVL_VT_NO_TYPE;
parm->msb = 0;
parm->lsb = 0;
}
parm->signed_flag = false;
parm->data_type = new vector_type_t(IVL_VT_LOGIC, false, range);
parm->range = 0;
}
}
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
{

View File

@ -418,15 +418,11 @@ extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
extern void pform_set_parameter(const struct vlltype&loc,
perm_string name,
ivl_variable_type_t type,
bool signed_flag,
list<pform_range_t>*range,
data_type_t*data_type,
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<pform_range_t>*range,
data_type_t*data_type,
PExpr*expr);
extern void pform_set_specparam(const struct vlltype&loc,
perm_string name,

View File

@ -165,6 +165,12 @@ void data_type_t::pform_dump(ostream&out, unsigned indent) const
out << setw(indent) << "" << typeid(*this).name() << endl;
}
ostream& data_type_t::debug_dump(ostream&out) const
{
out << typeid(*this).name();
return out;
}
void void_type_t::pform_dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << "void" << endl;
@ -213,6 +219,25 @@ void vector_type_t::pform_dump(ostream&fd, unsigned indent) const
fd << endl;
}
ostream& vector_type_t::debug_dump(ostream&fd) const
{
if (signed_flag)
fd << "signed ";
if (pdims==nullptr) {
fd << "/* vector_type_t nil */";
return fd;
}
for (list<pform_range_t>::iterator cur = pdims->begin()
; cur != pdims->end() ; ++cur) {
fd << "[";
if (cur->first) fd << *(cur->first);
if (cur->second) fd << ":" << *(cur->second);
fd << "]";
}
return fd;
}
void class_type_t::pform_dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << "class " << name;
@ -1389,14 +1414,12 @@ void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const
typedef map<perm_string,param_expr_t*>::const_iterator parm_iter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
out << setw(indent) << "" << "parameter "
<< (*cur).second->type << " ";
if ((*cur).second->signed_flag)
out << "signed ";
if ((*cur).second->msb)
out << "[" << *(*cur).second->msb << ":"
<< *(*cur).second->lsb << "] ";
out << (*cur).first << " = ";
out << setw(indent) << "" << "parameter ";
if (cur->second->data_type)
cur->second->data_type->debug_dump(out);
else
out << "(nil type)";
out << " " << (*cur).first << " = ";
if ((*cur).second->expr)
out << *(*cur).second->expr;
else
@ -1439,9 +1462,10 @@ void LexicalScope::dump_localparams_(ostream&out, unsigned indent) const
for (parm_iter_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
out << setw(indent) << "" << "localparam ";
if ((*cur).second->msb)
out << "[" << *(*cur).second->msb << ":"
<< *(*cur).second->lsb << "] ";
if (cur->second->data_type) {
cur->second->data_type->debug_dump(out);
out << " ";
}
out << (*cur).first << " = ";
if ((*cur).second->expr)
out << *(*cur).second->expr << ";" << endl;
@ -1544,9 +1568,11 @@ void Module::dump_specparams_(ostream&out, unsigned indent) const
for (parm_iter_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
out << setw(indent) << "" << "specparam ";
if ((*cur).second->msb)
out << "[" << *(*cur).second->msb << ":"
<< *(*cur).second->lsb << "] ";
if (cur->second->data_type)
cur->second->data_type->debug_dump(out);
else
out << "(nil type)";
out << (*cur).first << " = ";
if ((*cur).second->expr)
out << *(*cur).second->expr << ";" << endl;

View File

@ -144,8 +144,11 @@ class data_type_t : public PNamedItem {
// This method is used to figure out the base type of a packed
// compound object. Return IVL_VT_NO_TYPE if the type is not packed.
virtual ivl_variable_type_t figure_packed_base_type(void)const;
// This method is used by the pform dumper to diagnostic dump.
// This method is used by the pform dumper to diagnostic dump. The
// pform_dump dumps type type in pform format, and the debug_dump
// prints the output in a linear form.
virtual void pform_dump(std::ostream&out, unsigned indent) const;
virtual std::ostream& debug_dump(std::ostream&out) const;
ivl_type_s* elaborate_type(Design*des, NetScope*scope);
@ -237,6 +240,7 @@ struct vector_type_t : public data_type_t {
: base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { }
virtual ivl_variable_type_t figure_packed_base_type(void)const;
virtual void pform_dump(std::ostream&out, unsigned indent) const;
virtual std::ostream& debug_dump(std::ostream&out) const;
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
ivl_variable_type_t base_type;
@ -389,6 +393,11 @@ inline perm_string peek_tail_name(const pform_name_t&that)
# define SUPER_TOKEN "#"
# define THIS_TOKEN "@"
static inline std::ostream& operator<< (std::ostream&out, const data_type_t&that)
{
return that.debug_dump(out);
}
extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);

View File

@ -31,8 +31,7 @@ struct symbol_search_results {
scope = 0;
net = 0;
par_val = 0;
par_msb = 0;
par_lsb = 0;
par_type = 0;
eve = 0;
}
@ -52,8 +51,7 @@ struct symbol_search_results {
// If this was a parameter, the value expression and the
// optional value dimensions.
const NetExpr*par_val;
const NetExpr*par_msb;
const NetExpr*par_lsb;
ivl_type_t par_type;
// If this is a named event, ...
NetEvent*eve;
};
@ -129,7 +127,7 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
return true;
}
if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->par_msb, res->par_lsb)) {
if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->par_type)) {
res->scope = scope;
res->par_val = par;
return true;
@ -191,14 +189,13 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
NetNet*&net,
const NetExpr*&par,
NetEvent*&eve,
const NetExpr*&ex1, const NetExpr*&ex2)
ivl_type_t&par_type)
{
symbol_search_results recurse;
bool flag = symbol_search(li, des, scope, path, &recurse);
net = recurse.net;
par = recurse.par_val;
ex1 = recurse.par_msb;
ex2 = recurse.par_lsb;
par_type = recurse.par_type;
eve = recurse.eve;
if (! flag) {
return 0;

View File

@ -506,26 +506,19 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
ivl_parameter_t cur_par = &scop->param[idx];
cur_par->basename = cur_pit->first;
cur_par->local = cur_pit->second.local_flag;
/* Either both the MSB and LSB expressions are provided or
* neither are provided. */
if (cur_pit->second.msb) {
assert(cur_pit->second.lsb);
/* The MSB and LSB expressions must be integral constants. */
const NetEConst *msbc =
dynamic_cast<const NetEConst*>(cur_pit->second.msb);
const NetEConst *lsbc =
dynamic_cast<const NetEConst*>(cur_pit->second.lsb);
assert(msbc);
assert(lsbc);
cur_par->msb = msbc->value().as_long();
cur_par->lsb = lsbc->value().as_long();
} else {
assert(! cur_pit->second.lsb);
cur_par->msb = cur_pit->second.val->expr_width() - 1;
assert(cur_par->msb >= 0);
cur_par->lsb = 0;
calculate_param_range(cur_pit->second,
cur_pit->second.ivl_type,
cur_par->msb, cur_par->lsb,
cur_pit->second.val->expr_width());
if (cur_pit->second.ivl_type == 0) {
cerr << "?:?: internal error: "
<< "No type for parameter " << cur_pit->first
<< " in scope " << net->fullname() << "?" << endl;
}
cur_par->signed_flag = cur_pit->second.signed_flag;
assert(cur_pit->second.ivl_type);
cur_par->signed_flag = cur_pit->second.ivl_type->get_signed();
cur_par->scope = scop;
FILE_NAME(cur_par, &(cur_pit->second));