Support type parameters
SystemVerilog supports type parameters. These are similar to value parameters, but they allow to pass a type to a module or similar when instantiating it. E.g. ``` module A #(parameter type T = int); endmodule module B; A #(.T(real)) i_a; endmodule ``` Add support for handling type parameters. For the vlog95 and vhdl backends type parameters, similar to typedefs, get replaced with their actual value. For modules with non-local type parameters for each module instance a unique module or architecture is generated with the actual type. Querying type parameters through VPI is not yet supported. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
3509cc86f8
commit
5ef847ea87
2
PScope.h
2
PScope.h
|
|
@ -113,6 +113,8 @@ class LexicalScope {
|
|||
bool local_flag;
|
||||
// Whether the parameter can be overridden
|
||||
bool overridable;
|
||||
// Whether the parameter is a type parameter
|
||||
bool type_flag = false;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -128,9 +128,7 @@ static void collect_parm_item(Design*des, NetScope*scope, perm_string name,
|
|||
// 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,
|
||||
cur.local_flag, cur.overridable, range_list, cur);
|
||||
|
||||
scope->set_parameter(name, is_annotatable, cur, range_list);
|
||||
}
|
||||
|
||||
static void collect_scope_parameters(Design*des, NetScope*scope,
|
||||
|
|
|
|||
13
elab_type.cc
13
elab_type.cc
|
|
@ -476,3 +476,16 @@ ivl_type_t typedef_t::elaborate_type(Design *des, NetScope *scope)
|
|||
|
||||
return elab_type;
|
||||
}
|
||||
|
||||
ivl_type_t type_parameter_t::elaborate_type_raw(Design *des, NetScope*scope) const
|
||||
{
|
||||
ivl_type_t type;
|
||||
|
||||
scope->get_parameter(des, name, type);
|
||||
|
||||
// Recover
|
||||
if (!type)
|
||||
return netvector_t::integer_type();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
|
|
|||
1
ivl.def
1
ivl.def
|
|
@ -172,6 +172,7 @@ ivl_nexus_ptr_switch
|
|||
ivl_parameter_basename
|
||||
ivl_parameter_expr
|
||||
ivl_parameter_file
|
||||
ivl_parameter_is_type
|
||||
ivl_parameter_lineno
|
||||
ivl_parameter_local
|
||||
ivl_parameter_lsb
|
||||
|
|
|
|||
|
|
@ -1695,6 +1695,9 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
|||
* Return whether parameter was local (localparam, implicit genvar etc)
|
||||
* or not.
|
||||
*
|
||||
* ivl_parameter_is_type
|
||||
* Return whether the parameter is a type parameter or not.
|
||||
*
|
||||
* ivl_parameter_file
|
||||
* ivl_parameter_lineno
|
||||
* Returns the file and line where this parameter is defined
|
||||
|
|
@ -1707,6 +1710,7 @@ extern int ivl_parameter_lsb(ivl_parameter_t net);
|
|||
extern unsigned ivl_parameter_width(ivl_parameter_t net);
|
||||
extern int ivl_parameter_signed(ivl_parameter_t net);
|
||||
extern int ivl_parameter_local(ivl_parameter_t net);
|
||||
extern int ivl_parameter_is_type(ivl_parameter_t net);
|
||||
extern const char* ivl_parameter_file(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ void NetScope::run_defparams(Design*des)
|
|||
continue;
|
||||
}
|
||||
|
||||
targ_scope->replace_parameter(des, perm_name, val, this);
|
||||
targ_scope->replace_parameter(des, perm_name, val, this, true);
|
||||
}
|
||||
|
||||
// If some of the defparams didn't find a scope in the name,
|
||||
|
|
@ -468,7 +468,7 @@ void NetScope::run_defparams_later(Design*des)
|
|||
continue;
|
||||
}
|
||||
|
||||
targ_scope->replace_parameter(des, name, val, this);
|
||||
targ_scope->replace_parameter(des, name, val, this, true);
|
||||
|
||||
// We'll need to re-evaluate parameters in this scope
|
||||
target_scopes.insert(targ_scope);
|
||||
|
|
@ -814,20 +814,31 @@ void NetScope::evaluate_parameter_string_(Design*des, param_ref_t cur)
|
|||
}
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
||||
void NetScope::evaluate_type_parameter_(Design *des, param_ref_t cur)
|
||||
{
|
||||
ivl_type_t param_type = cur->second.ivl_type;
|
||||
const PETypename *type_expr = dynamic_cast<const PETypename*>(cur->second.val_expr);
|
||||
if (!type_expr) {
|
||||
cerr << this->get_fileline() << ": error: "
|
||||
<< "Type parameter `" << cur->first << "` value `"
|
||||
<< *cur->second.val_expr << "` is not a type."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
|
||||
// If the parameter type is present, then elaborate it now. Elaborate
|
||||
// the type in the current scope, and not the scope of the expression.
|
||||
if (cur->second.val_type) {
|
||||
param_type = cur->second.val_type->elaborate_type(des, this);
|
||||
cur->second.ivl_type = param_type;
|
||||
cur->second.val_type = 0;
|
||||
// Recover
|
||||
cur->second.ivl_type = netvector_t::integer_type();
|
||||
return;
|
||||
}
|
||||
|
||||
data_type_t *type = type_expr->get_type();
|
||||
NetScope *type_scope = cur->second.val_scope;
|
||||
cur->second.ivl_type = type->elaborate_type(des, type_scope);
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
||||
{
|
||||
|
||||
// If the parameter has already been evaluated, quietly return.
|
||||
if (cur->second.val != 0)
|
||||
if (cur->second.val || cur->second.ivl_type)
|
||||
return;
|
||||
|
||||
if (cur->second.val_expr == 0) {
|
||||
|
|
@ -840,6 +851,21 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cur->second.type_flag) {
|
||||
evaluate_type_parameter_(des, cur);
|
||||
return;
|
||||
}
|
||||
|
||||
ivl_type_t param_type = cur->second.ivl_type;
|
||||
|
||||
// If the parameter type is present, then elaborate it now. Elaborate
|
||||
// the type in the current scope, and not the scope of the expression.
|
||||
if (cur->second.val_type) {
|
||||
param_type = cur->second.val_type->elaborate_type(des, this);
|
||||
cur->second.ivl_type = param_type;
|
||||
cur->second.val_type = 0;
|
||||
}
|
||||
|
||||
// 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 (this is currently handled in evaluate_parameter_logic_()).
|
||||
|
|
|
|||
32
net_scope.cc
32
net_scope.cc
|
|
@ -269,23 +269,22 @@ NetScope*NetScope::find_typedef_scope(const Design*des, const typedef_t*type)
|
|||
* member.
|
||||
*/
|
||||
void NetScope::set_parameter(perm_string key, bool is_annotatable,
|
||||
PExpr*val, data_type_t*val_type,
|
||||
bool local_flag, bool overridable,
|
||||
NetScope::range_t*range_list,
|
||||
const LineInfo&file_line)
|
||||
const LexicalScope::param_expr_t ¶m,
|
||||
NetScope::range_t *range_list)
|
||||
{
|
||||
param_expr_t&ref = parameters[key];
|
||||
ref.is_annotatable = is_annotatable;
|
||||
ref.val_expr = val;
|
||||
ref.val_type = val_type;
|
||||
ref.val_expr = param.expr;
|
||||
ref.val_type = param.data_type;
|
||||
ref.val_scope = this;
|
||||
ref.local_flag = local_flag;
|
||||
ref.overridable = overridable;
|
||||
ivl_assert(file_line, ref.range == 0);
|
||||
ref.local_flag = param.local_flag;
|
||||
ref.overridable = param.overridable;
|
||||
ref.type_flag = param.type_flag;
|
||||
ivl_assert(param, !ref.range);
|
||||
ref.range = range_list;
|
||||
ref.val = 0;
|
||||
ref.ivl_type = 0;
|
||||
ref.set_line(file_line);
|
||||
ref.set_line(param);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -348,7 +347,8 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
|||
* Return false if the parameter does not already exist.
|
||||
* A parameter is not automatically created.
|
||||
*/
|
||||
void NetScope::replace_parameter(Design *des, perm_string key, PExpr*val, NetScope*scope)
|
||||
void NetScope::replace_parameter(Design *des, perm_string key, PExpr*val,
|
||||
NetScope*scope, bool defparam)
|
||||
{
|
||||
if (parameters.find(key) == parameters.end()) {
|
||||
cerr << val->get_fileline() << ": error: parameter `"
|
||||
|
|
@ -376,6 +376,16 @@ void NetScope::replace_parameter(Design *des, perm_string key, PExpr*val, NetSco
|
|||
return;
|
||||
}
|
||||
|
||||
if (ref.type_flag && defparam) {
|
||||
cerr << val->get_fileline() << ": error: "
|
||||
<< "Cannot override type parameter `" << key << "` in `"
|
||||
<< scope_path(this) << "`. It is not allowed to override type"
|
||||
<< " parameters using a defparam statement."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
return;
|
||||
}
|
||||
|
||||
ref.val_expr = val;
|
||||
ref.val_scope = scope;
|
||||
}
|
||||
|
|
|
|||
23
netlist.h
23
netlist.h
|
|
@ -44,6 +44,7 @@
|
|||
# include "HName.h"
|
||||
# include "LineInfo.h"
|
||||
# include "Attrib.h"
|
||||
# include "PScope.h"
|
||||
# include "PUdp.h"
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
|
|
@ -952,10 +953,8 @@ class NetScope : public Definitions, public Attrib {
|
|||
|
||||
struct range_t;
|
||||
void set_parameter(perm_string name, bool is_annotatable,
|
||||
PExpr*val, data_type_t*data_type,
|
||||
bool local_flag, bool overridable,
|
||||
NetScope::range_t*range_list,
|
||||
const LineInfo&file_line);
|
||||
const LexicalScope::param_expr_t ¶m,
|
||||
NetScope::range_t *range_list);
|
||||
void set_parameter(perm_string name, NetExpr*val,
|
||||
const LineInfo&file_line);
|
||||
|
||||
|
|
@ -968,7 +967,8 @@ class NetScope : public Definitions, public Attrib {
|
|||
expression with a new expression, without affecting the
|
||||
range or signed_flag. Return false if the name does not
|
||||
exist. */
|
||||
void replace_parameter(Design *des, perm_string name, PExpr*val, NetScope*scope);
|
||||
void replace_parameter(Design *des, perm_string name, PExpr*val,
|
||||
NetScope*scope, bool defparam = false);
|
||||
|
||||
/* This is used to ensure the value of a parameter cannot be
|
||||
changed at run-time. This is required if a specparam is used
|
||||
|
|
@ -1213,11 +1213,19 @@ class NetScope : public Definitions, public Attrib {
|
|||
// Is this a localparam?
|
||||
bool local_flag;
|
||||
// Can it be overriden?
|
||||
bool overridable;
|
||||
bool overridable = false;
|
||||
// Is it a type parameter
|
||||
bool type_flag = false;
|
||||
// range constraints
|
||||
struct range_t*range;
|
||||
// Expression value and type (elaborated versoins of val_expr/val_type)
|
||||
|
||||
// Expression value. Elaborated version of val_expr.
|
||||
// For type parameters this will always be 0.
|
||||
NetExpr*val;
|
||||
|
||||
// For non-type parameter this contains the elaborate type of the
|
||||
// parameter itself. For type parameters this contains the
|
||||
// elaborated assigned type value.
|
||||
ivl_type_t ivl_type;
|
||||
};
|
||||
std::map<perm_string,param_expr_t>parameters;
|
||||
|
|
@ -1240,6 +1248,7 @@ class NetScope : public Definitions, public Attrib {
|
|||
std::map<perm_string,LocalVar> loop_index_tmp;
|
||||
|
||||
private:
|
||||
void evaluate_type_parameter_(Design*des, param_ref_t cur);
|
||||
void evaluate_parameter_logic_(Design*des, param_ref_t cur);
|
||||
void evaluate_parameter_real_(Design*des, param_ref_t cur);
|
||||
void evaluate_parameter_string_(Design*des, param_ref_t cur);
|
||||
|
|
|
|||
22
parse.y
22
parse.y
|
|
@ -41,6 +41,7 @@ extern void lex_end_table();
|
|||
|
||||
static data_type_t* param_data_type = 0;
|
||||
static bool param_is_local = false;
|
||||
static bool param_is_type = false;
|
||||
static std::list<pform_range_t>* specparam_active_range = 0;
|
||||
|
||||
/* Port declaration lists use this structure for context. */
|
||||
|
|
@ -4730,6 +4731,10 @@ module_parameter_port_list_opt
|
|||
')'
|
||||
;
|
||||
|
||||
type_param
|
||||
: K_type { param_is_type = true; }
|
||||
;
|
||||
|
||||
module_parameter
|
||||
: parameter param_type parameter_assign
|
||||
| localparam param_type parameter_assign
|
||||
|
|
@ -4742,20 +4747,28 @@ module_parameter_port_list
|
|||
| data_type_opt
|
||||
{ param_data_type = $1;
|
||||
param_is_local = false;
|
||||
param_is_type = false;
|
||||
}
|
||||
parameter_assign
|
||||
{ pform_requires_sv(@3, "Omitting initial `parameter` in parameter port "
|
||||
"list");
|
||||
}
|
||||
| type_param
|
||||
{
|
||||
param_is_local = false;
|
||||
}
|
||||
parameter_assign
|
||||
| module_parameter_port_list ',' module_parameter
|
||||
| module_parameter_port_list ',' data_type_opt
|
||||
{ if ($3) {
|
||||
pform_requires_sv(@3, "Omitting `parameter`/`localparam` before "
|
||||
"data type in parameter port list");
|
||||
param_data_type = $3;
|
||||
param_is_type = false;
|
||||
}
|
||||
}
|
||||
parameter_assign
|
||||
| module_parameter_port_list ',' type_param parameter_assign
|
||||
;
|
||||
|
||||
module_item
|
||||
|
|
@ -5375,7 +5388,12 @@ net_type_or_var_opt
|
|||
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; }
|
||||
param_type
|
||||
: data_type_or_implicit
|
||||
{ param_is_type = false;
|
||||
param_data_type = $1;
|
||||
}
|
||||
| type_param
|
||||
|
||||
parameter : K_parameter { param_is_local = false; };
|
||||
localparam : K_localparam { param_is_local = true; };
|
||||
|
|
@ -5401,7 +5419,7 @@ parameter_assign_list
|
|||
parameter_assign
|
||||
: IDENTIFIER initializer_opt parameter_value_ranges_opt
|
||||
{ pform_set_parameter(@1, lex_strings.make($1), param_is_local,
|
||||
param_data_type, $2, $3);
|
||||
param_is_type, param_data_type, $2, $3);
|
||||
delete[]$1;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
21
pform.cc
21
pform.cc
|
|
@ -2961,8 +2961,21 @@ LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
static void pform_set_type_parameter(const struct vlltype&loc, perm_string name,
|
||||
LexicalScope::range_t*value_range)
|
||||
{
|
||||
pform_requires_sv(loc, "Type parameter");
|
||||
|
||||
if (value_range)
|
||||
VLerror(loc, "error: type parameter must not have value range.");
|
||||
|
||||
type_parameter_t *type = new type_parameter_t(name);
|
||||
pform_set_typedef(loc, name, type, 0);
|
||||
}
|
||||
|
||||
void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name, bool is_local, data_type_t*data_type, PExpr*expr,
|
||||
perm_string name, bool is_local, bool is_type,
|
||||
data_type_t*data_type, PExpr*expr,
|
||||
LexicalScope::range_t*value_range)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
|
|
@ -3008,13 +3021,17 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
Module::param_expr_t*parm = new Module::param_expr_t();
|
||||
FILE_NAME(parm, loc);
|
||||
|
||||
add_local_symbol(scope, name, parm);
|
||||
if (is_type)
|
||||
pform_set_type_parameter(loc, name, value_range);
|
||||
else
|
||||
add_local_symbol(scope, name, parm);
|
||||
|
||||
parm->expr = expr;
|
||||
parm->data_type = data_type;
|
||||
parm->range = value_range;
|
||||
parm->local_flag = is_local;
|
||||
parm->overridable = overridable;
|
||||
parm->type_flag = is_type;
|
||||
|
||||
scope->parameters[name] = parm;
|
||||
|
||||
|
|
|
|||
2
pform.h
2
pform.h
|
|
@ -390,7 +390,7 @@ extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
|
|||
|
||||
extern void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
bool is_local,
|
||||
bool is_local, bool is_type,
|
||||
data_type_t*data_type,
|
||||
PExpr*expr, LexicalScope::range_t*value_range);
|
||||
extern void pform_set_specparam(const struct vlltype&loc,
|
||||
|
|
|
|||
|
|
@ -212,6 +212,13 @@ private:
|
|||
typedef_t *type;
|
||||
};
|
||||
|
||||
struct type_parameter_t : data_type_t {
|
||||
explicit type_parameter_t(perm_string n) : name(n) { }
|
||||
ivl_type_t elaborate_type_raw(Design *des, NetScope *scope) const;
|
||||
|
||||
perm_string name;
|
||||
};
|
||||
|
||||
struct void_type_t : public data_type_t {
|
||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1877,6 +1877,12 @@ extern "C" int ivl_parameter_local(ivl_parameter_t net)
|
|||
return net->local;
|
||||
}
|
||||
|
||||
extern "C" int ivl_parameter_is_type(ivl_parameter_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->is_type;
|
||||
}
|
||||
|
||||
extern "C" int ivl_parameter_signed(ivl_parameter_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
|
|||
28
t-dll.cc
28
t-dll.cc
|
|
@ -509,10 +509,7 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
|
|||
cur_par->basename = cur_pit->first;
|
||||
cur_par->local = cur_pit->second.local_flag ||
|
||||
!cur_pit->second.overridable;
|
||||
calculate_param_range(cur_pit->second,
|
||||
cur_pit->second.ivl_type,
|
||||
cur_par->msb, cur_par->lsb,
|
||||
cur_pit->second.val->expr_width());
|
||||
cur_par->is_type = cur_pit->second.type_flag;
|
||||
|
||||
if (cur_pit->second.ivl_type == 0) {
|
||||
cerr << "?:?: internal error: "
|
||||
|
|
@ -525,14 +522,23 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
|
|||
cur_par->scope = scop;
|
||||
FILE_NAME(cur_par, &(cur_pit->second));
|
||||
|
||||
NetExpr*etmp = cur_pit->second.val;
|
||||
if (etmp == 0) {
|
||||
cerr << "?:?: internal error: What is the parameter "
|
||||
<< "expression for " << cur_pit->first
|
||||
<< " in " << net->fullname() << "?" << endl;
|
||||
// Type parameters don't have a range or expression
|
||||
if (!cur_pit->second.type_flag) {
|
||||
calculate_param_range(cur_pit->second,
|
||||
cur_pit->second.ivl_type,
|
||||
cur_par->msb, cur_par->lsb,
|
||||
cur_pit->second.val->expr_width());
|
||||
|
||||
NetExpr*etmp = cur_pit->second.val;
|
||||
if (etmp == 0) {
|
||||
cerr << "?:?: internal error: What is the parameter "
|
||||
<< "expression for " << cur_pit->first
|
||||
<< " in " << net->fullname() << "?" << endl;
|
||||
}
|
||||
assert(etmp);
|
||||
make_scope_param_expr(cur_par, etmp);
|
||||
}
|
||||
assert(etmp);
|
||||
make_scope_param_expr(cur_par, etmp);
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
t-dll.h
1
t-dll.h
|
|
@ -638,6 +638,7 @@ struct ivl_parameter_s {
|
|||
long lsb;
|
||||
bool signed_flag;
|
||||
bool local;
|
||||
bool is_type;
|
||||
perm_string file;
|
||||
unsigned lineno;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -940,9 +940,15 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth)
|
|||
unsigned nparams = ivl_scope_params(scope);
|
||||
for (unsigned i = 0; i < nparams; i++) {
|
||||
ivl_parameter_t param = ivl_scope_param(scope, i);
|
||||
ss << "\n " << ivl_parameter_basename(param) << " = ";
|
||||
|
||||
// Type parameter usages get replaced with their actual type
|
||||
if (ivl_parameter_is_type(param))
|
||||
continue;
|
||||
|
||||
ivl_expr_t value = ivl_parameter_expr(param);
|
||||
|
||||
ss << "\n " << ivl_parameter_basename(param) << " = ";
|
||||
|
||||
switch (ivl_expr_type(value)) {
|
||||
case IVL_EX_STRING:
|
||||
ss << "\"" << ivl_expr_string(value) << "\"";
|
||||
|
|
|
|||
|
|
@ -264,6 +264,14 @@ static bool same_scope_type_name(ivl_scope_t a, ivl_scope_t b)
|
|||
ivl_parameter_basename(param_b)) != 0)
|
||||
return false;
|
||||
|
||||
if (ivl_parameter_local(param_a) && ivl_parameter_local(param_b))
|
||||
continue;
|
||||
|
||||
// If this is a type parameter consider the scopes not equal since we do
|
||||
// not have support for comparing the actual types yet.
|
||||
if (ivl_parameter_is_type(param_a) || ivl_parameter_is_type(param_b))
|
||||
return false;
|
||||
|
||||
ivl_expr_t value_a = ivl_parameter_expr(param_a);
|
||||
ivl_expr_t value_b = ivl_parameter_expr(param_b);
|
||||
|
||||
|
|
|
|||
|
|
@ -309,6 +309,13 @@ void emit_scope_variables(ivl_scope_t scope)
|
|||
count = ivl_scope_params(scope);
|
||||
for (idx = 0; idx < count; idx += 1) {
|
||||
ivl_parameter_t par = ivl_scope_param(scope, idx);
|
||||
// vlog95 does not support type parameters. Places where type
|
||||
// parameters have been used it will be replaced with the actual
|
||||
// type that the module was instantiated with. Similar to
|
||||
// typedefs.
|
||||
if (ivl_parameter_is_type(par))
|
||||
continue;
|
||||
|
||||
ivl_expr_t pex = ivl_parameter_expr(par);
|
||||
fprintf(vlog_out, "%*cparameter ", indent, ' ');
|
||||
emit_id(ivl_parameter_basename(par));
|
||||
|
|
|
|||
|
|
@ -2415,6 +2415,13 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) {
|
||||
ivl_parameter_t par = ivl_scope_param(net, idx);
|
||||
|
||||
// Skip type parameters for now. Support for type parameters
|
||||
// should be added together with support for quering types through
|
||||
// VPI.
|
||||
if (ivl_parameter_is_type(par))
|
||||
continue;
|
||||
|
||||
ivl_expr_t pex = ivl_parameter_expr(par);
|
||||
switch (ivl_expr_type(pex)) {
|
||||
case IVL_EX_STRING:
|
||||
|
|
|
|||
Loading…
Reference in New Issue