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;
|
bool local_flag;
|
||||||
// Whether the parameter can be overridden
|
// Whether the parameter can be overridden
|
||||||
bool overridable;
|
bool overridable;
|
||||||
|
// Whether the parameter is a type parameter
|
||||||
|
bool type_flag = false;
|
||||||
|
|
||||||
SymbolType symbol_type() const;
|
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
|
// 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
|
// don't try to elaborate it here, because there may be references to
|
||||||
// other parameters still being located during scope elaboration.
|
// other parameters still being located during scope elaboration.
|
||||||
scope->set_parameter(name, is_annotatable, cur.expr, cur.data_type,
|
scope->set_parameter(name, is_annotatable, cur, range_list);
|
||||||
cur.local_flag, cur.overridable, range_list, cur);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_scope_parameters(Design*des, NetScope*scope,
|
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;
|
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_basename
|
||||||
ivl_parameter_expr
|
ivl_parameter_expr
|
||||||
ivl_parameter_file
|
ivl_parameter_file
|
||||||
|
ivl_parameter_is_type
|
||||||
ivl_parameter_lineno
|
ivl_parameter_lineno
|
||||||
ivl_parameter_local
|
ivl_parameter_local
|
||||||
ivl_parameter_lsb
|
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)
|
* Return whether parameter was local (localparam, implicit genvar etc)
|
||||||
* or not.
|
* or not.
|
||||||
*
|
*
|
||||||
|
* ivl_parameter_is_type
|
||||||
|
* Return whether the parameter is a type parameter or not.
|
||||||
|
*
|
||||||
* ivl_parameter_file
|
* ivl_parameter_file
|
||||||
* ivl_parameter_lineno
|
* ivl_parameter_lineno
|
||||||
* Returns the file and line where this parameter is defined
|
* 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 unsigned ivl_parameter_width(ivl_parameter_t net);
|
||||||
extern int ivl_parameter_signed(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_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 const char* ivl_parameter_file(ivl_parameter_t net);
|
||||||
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ void NetScope::run_defparams(Design*des)
|
||||||
continue;
|
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,
|
// 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;
|
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
|
// We'll need to re-evaluate parameters in this scope
|
||||||
target_scopes.insert(targ_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
|
// Recover
|
||||||
// the type in the current scope, and not the scope of the expression.
|
cur->second.ivl_type = netvector_t::integer_type();
|
||||||
if (cur->second.val_type) {
|
return;
|
||||||
param_type = cur->second.val_type->elaborate_type(des, this);
|
|
||||||
cur->second.ivl_type = param_type;
|
|
||||||
cur->second.val_type = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 the parameter has already been evaluated, quietly return.
|
||||||
if (cur->second.val != 0)
|
if (cur->second.val || cur->second.ivl_type)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cur->second.val_expr == 0) {
|
if (cur->second.val_expr == 0) {
|
||||||
|
|
@ -840,6 +851,21 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
||||||
return;
|
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
|
// 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
|
// given type, then guess the type from the expression and use that to
|
||||||
// evaluate (this is currently handled in evaluate_parameter_logic_()).
|
// 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.
|
* member.
|
||||||
*/
|
*/
|
||||||
void NetScope::set_parameter(perm_string key, bool is_annotatable,
|
void NetScope::set_parameter(perm_string key, bool is_annotatable,
|
||||||
PExpr*val, data_type_t*val_type,
|
const LexicalScope::param_expr_t ¶m,
|
||||||
bool local_flag, bool overridable,
|
NetScope::range_t *range_list)
|
||||||
NetScope::range_t*range_list,
|
|
||||||
const LineInfo&file_line)
|
|
||||||
{
|
{
|
||||||
param_expr_t&ref = parameters[key];
|
param_expr_t&ref = parameters[key];
|
||||||
ref.is_annotatable = is_annotatable;
|
ref.is_annotatable = is_annotatable;
|
||||||
ref.val_expr = val;
|
ref.val_expr = param.expr;
|
||||||
ref.val_type = val_type;
|
ref.val_type = param.data_type;
|
||||||
ref.val_scope = this;
|
ref.val_scope = this;
|
||||||
ref.local_flag = local_flag;
|
ref.local_flag = param.local_flag;
|
||||||
ref.overridable = overridable;
|
ref.overridable = param.overridable;
|
||||||
ivl_assert(file_line, ref.range == 0);
|
ref.type_flag = param.type_flag;
|
||||||
|
ivl_assert(param, !ref.range);
|
||||||
ref.range = range_list;
|
ref.range = range_list;
|
||||||
ref.val = 0;
|
ref.val = 0;
|
||||||
ref.ivl_type = 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.
|
* Return false if the parameter does not already exist.
|
||||||
* A parameter is not automatically created.
|
* 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()) {
|
if (parameters.find(key) == parameters.end()) {
|
||||||
cerr << val->get_fileline() << ": error: parameter `"
|
cerr << val->get_fileline() << ": error: parameter `"
|
||||||
|
|
@ -376,6 +376,16 @@ void NetScope::replace_parameter(Design *des, perm_string key, PExpr*val, NetSco
|
||||||
return;
|
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_expr = val;
|
||||||
ref.val_scope = scope;
|
ref.val_scope = scope;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
netlist.h
23
netlist.h
|
|
@ -44,6 +44,7 @@
|
||||||
# include "HName.h"
|
# include "HName.h"
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
# include "Attrib.h"
|
# include "Attrib.h"
|
||||||
|
# include "PScope.h"
|
||||||
# include "PUdp.h"
|
# include "PUdp.h"
|
||||||
|
|
||||||
#ifdef HAVE_IOSFWD
|
#ifdef HAVE_IOSFWD
|
||||||
|
|
@ -952,10 +953,8 @@ class NetScope : public Definitions, public Attrib {
|
||||||
|
|
||||||
struct range_t;
|
struct range_t;
|
||||||
void set_parameter(perm_string name, bool is_annotatable,
|
void set_parameter(perm_string name, bool is_annotatable,
|
||||||
PExpr*val, data_type_t*data_type,
|
const LexicalScope::param_expr_t ¶m,
|
||||||
bool local_flag, bool overridable,
|
NetScope::range_t *range_list);
|
||||||
NetScope::range_t*range_list,
|
|
||||||
const LineInfo&file_line);
|
|
||||||
void set_parameter(perm_string name, NetExpr*val,
|
void set_parameter(perm_string name, NetExpr*val,
|
||||||
const LineInfo&file_line);
|
const LineInfo&file_line);
|
||||||
|
|
||||||
|
|
@ -968,7 +967,8 @@ class NetScope : public Definitions, public Attrib {
|
||||||
expression with a new expression, without affecting the
|
expression with a new expression, without affecting the
|
||||||
range or signed_flag. Return false if the name does not
|
range or signed_flag. Return false if the name does not
|
||||||
exist. */
|
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
|
/* This is used to ensure the value of a parameter cannot be
|
||||||
changed at run-time. This is required if a specparam is used
|
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?
|
// Is this a localparam?
|
||||||
bool local_flag;
|
bool local_flag;
|
||||||
// Can it be overriden?
|
// Can it be overriden?
|
||||||
bool overridable;
|
bool overridable = false;
|
||||||
|
// Is it a type parameter
|
||||||
|
bool type_flag = false;
|
||||||
// range constraints
|
// range constraints
|
||||||
struct range_t*range;
|
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;
|
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;
|
ivl_type_t ivl_type;
|
||||||
};
|
};
|
||||||
std::map<perm_string,param_expr_t>parameters;
|
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;
|
std::map<perm_string,LocalVar> loop_index_tmp;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void evaluate_type_parameter_(Design*des, param_ref_t cur);
|
||||||
void evaluate_parameter_logic_(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_real_(Design*des, param_ref_t cur);
|
||||||
void evaluate_parameter_string_(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 data_type_t* param_data_type = 0;
|
||||||
static bool param_is_local = false;
|
static bool param_is_local = false;
|
||||||
|
static bool param_is_type = false;
|
||||||
static std::list<pform_range_t>* specparam_active_range = 0;
|
static std::list<pform_range_t>* specparam_active_range = 0;
|
||||||
|
|
||||||
/* Port declaration lists use this structure for context. */
|
/* 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
|
module_parameter
|
||||||
: parameter param_type parameter_assign
|
: parameter param_type parameter_assign
|
||||||
| localparam param_type parameter_assign
|
| localparam param_type parameter_assign
|
||||||
|
|
@ -4742,20 +4747,28 @@ module_parameter_port_list
|
||||||
| data_type_opt
|
| data_type_opt
|
||||||
{ param_data_type = $1;
|
{ param_data_type = $1;
|
||||||
param_is_local = false;
|
param_is_local = false;
|
||||||
|
param_is_type = false;
|
||||||
}
|
}
|
||||||
parameter_assign
|
parameter_assign
|
||||||
{ pform_requires_sv(@3, "Omitting initial `parameter` in parameter port "
|
{ pform_requires_sv(@3, "Omitting initial `parameter` in parameter port "
|
||||||
"list");
|
"list");
|
||||||
}
|
}
|
||||||
|
| type_param
|
||||||
|
{
|
||||||
|
param_is_local = false;
|
||||||
|
}
|
||||||
|
parameter_assign
|
||||||
| module_parameter_port_list ',' module_parameter
|
| module_parameter_port_list ',' module_parameter
|
||||||
| module_parameter_port_list ',' data_type_opt
|
| module_parameter_port_list ',' data_type_opt
|
||||||
{ if ($3) {
|
{ if ($3) {
|
||||||
pform_requires_sv(@3, "Omitting `parameter`/`localparam` before "
|
pform_requires_sv(@3, "Omitting `parameter`/`localparam` before "
|
||||||
"data type in parameter port list");
|
"data type in parameter port list");
|
||||||
param_data_type = $3;
|
param_data_type = $3;
|
||||||
|
param_is_type = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parameter_assign
|
parameter_assign
|
||||||
|
| module_parameter_port_list ',' type_param parameter_assign
|
||||||
;
|
;
|
||||||
|
|
||||||
module_item
|
module_item
|
||||||
|
|
@ -5375,7 +5388,12 @@ net_type_or_var_opt
|
||||||
This is used by parameter_assign, which is found to the right of
|
This is used by parameter_assign, which is found to the right of
|
||||||
the param_type in various rules. */
|
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; };
|
parameter : K_parameter { param_is_local = false; };
|
||||||
localparam : K_localparam { param_is_local = true; };
|
localparam : K_localparam { param_is_local = true; };
|
||||||
|
|
@ -5401,7 +5419,7 @@ parameter_assign_list
|
||||||
parameter_assign
|
parameter_assign
|
||||||
: IDENTIFIER initializer_opt parameter_value_ranges_opt
|
: IDENTIFIER initializer_opt parameter_value_ranges_opt
|
||||||
{ pform_set_parameter(@1, lex_strings.make($1), param_is_local,
|
{ 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;
|
delete[]$1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
||||||
19
pform.cc
19
pform.cc
|
|
@ -2961,8 +2961,21 @@ LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
|
||||||
return tmp;
|
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,
|
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::range_t*value_range)
|
||||||
{
|
{
|
||||||
LexicalScope*scope = lexical_scope;
|
LexicalScope*scope = lexical_scope;
|
||||||
|
|
@ -3008,6 +3021,9 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
Module::param_expr_t*parm = new Module::param_expr_t();
|
Module::param_expr_t*parm = new Module::param_expr_t();
|
||||||
FILE_NAME(parm, loc);
|
FILE_NAME(parm, loc);
|
||||||
|
|
||||||
|
if (is_type)
|
||||||
|
pform_set_type_parameter(loc, name, value_range);
|
||||||
|
else
|
||||||
add_local_symbol(scope, name, parm);
|
add_local_symbol(scope, name, parm);
|
||||||
|
|
||||||
parm->expr = expr;
|
parm->expr = expr;
|
||||||
|
|
@ -3015,6 +3031,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
parm->range = value_range;
|
parm->range = value_range;
|
||||||
parm->local_flag = is_local;
|
parm->local_flag = is_local;
|
||||||
parm->overridable = overridable;
|
parm->overridable = overridable;
|
||||||
|
parm->type_flag = is_type;
|
||||||
|
|
||||||
scope->parameters[name] = parm;
|
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,
|
extern void pform_set_parameter(const struct vlltype&loc,
|
||||||
perm_string name,
|
perm_string name,
|
||||||
bool is_local,
|
bool is_local, bool is_type,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
PExpr*expr, LexicalScope::range_t*value_range);
|
PExpr*expr, LexicalScope::range_t*value_range);
|
||||||
extern void pform_set_specparam(const struct vlltype&loc,
|
extern void pform_set_specparam(const struct vlltype&loc,
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,13 @@ private:
|
||||||
typedef_t *type;
|
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 {
|
struct void_type_t : public data_type_t {
|
||||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
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;
|
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)
|
extern "C" int ivl_parameter_signed(ivl_parameter_t net)
|
||||||
{
|
{
|
||||||
assert(net);
|
assert(net);
|
||||||
|
|
|
||||||
14
t-dll.cc
14
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->basename = cur_pit->first;
|
||||||
cur_par->local = cur_pit->second.local_flag ||
|
cur_par->local = cur_pit->second.local_flag ||
|
||||||
!cur_pit->second.overridable;
|
!cur_pit->second.overridable;
|
||||||
calculate_param_range(cur_pit->second,
|
cur_par->is_type = cur_pit->second.type_flag;
|
||||||
cur_pit->second.ivl_type,
|
|
||||||
cur_par->msb, cur_par->lsb,
|
|
||||||
cur_pit->second.val->expr_width());
|
|
||||||
|
|
||||||
if (cur_pit->second.ivl_type == 0) {
|
if (cur_pit->second.ivl_type == 0) {
|
||||||
cerr << "?:?: internal error: "
|
cerr << "?:?: internal error: "
|
||||||
|
|
@ -525,6 +522,13 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
|
||||||
cur_par->scope = scop;
|
cur_par->scope = scop;
|
||||||
FILE_NAME(cur_par, &(cur_pit->second));
|
FILE_NAME(cur_par, &(cur_pit->second));
|
||||||
|
|
||||||
|
// 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;
|
NetExpr*etmp = cur_pit->second.val;
|
||||||
if (etmp == 0) {
|
if (etmp == 0) {
|
||||||
cerr << "?:?: internal error: What is the parameter "
|
cerr << "?:?: internal error: What is the parameter "
|
||||||
|
|
@ -533,6 +537,8 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
|
||||||
}
|
}
|
||||||
assert(etmp);
|
assert(etmp);
|
||||||
make_scope_param_expr(cur_par, etmp);
|
make_scope_param_expr(cur_par, etmp);
|
||||||
|
}
|
||||||
|
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
t-dll.h
1
t-dll.h
|
|
@ -638,6 +638,7 @@ struct ivl_parameter_s {
|
||||||
long lsb;
|
long lsb;
|
||||||
bool signed_flag;
|
bool signed_flag;
|
||||||
bool local;
|
bool local;
|
||||||
|
bool is_type;
|
||||||
perm_string file;
|
perm_string file;
|
||||||
unsigned lineno;
|
unsigned lineno;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -940,9 +940,15 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth)
|
||||||
unsigned nparams = ivl_scope_params(scope);
|
unsigned nparams = ivl_scope_params(scope);
|
||||||
for (unsigned i = 0; i < nparams; i++) {
|
for (unsigned i = 0; i < nparams; i++) {
|
||||||
ivl_parameter_t param = ivl_scope_param(scope, 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);
|
ivl_expr_t value = ivl_parameter_expr(param);
|
||||||
|
|
||||||
|
ss << "\n " << ivl_parameter_basename(param) << " = ";
|
||||||
|
|
||||||
switch (ivl_expr_type(value)) {
|
switch (ivl_expr_type(value)) {
|
||||||
case IVL_EX_STRING:
|
case IVL_EX_STRING:
|
||||||
ss << "\"" << ivl_expr_string(value) << "\"";
|
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)
|
ivl_parameter_basename(param_b)) != 0)
|
||||||
return false;
|
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_a = ivl_parameter_expr(param_a);
|
||||||
ivl_expr_t value_b = ivl_parameter_expr(param_b);
|
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);
|
count = ivl_scope_params(scope);
|
||||||
for (idx = 0; idx < count; idx += 1) {
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
ivl_parameter_t par = ivl_scope_param(scope, idx);
|
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);
|
ivl_expr_t pex = ivl_parameter_expr(par);
|
||||||
fprintf(vlog_out, "%*cparameter ", indent, ' ');
|
fprintf(vlog_out, "%*cparameter ", indent, ' ');
|
||||||
emit_id(ivl_parameter_basename(par));
|
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) {
|
for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) {
|
||||||
ivl_parameter_t par = ivl_scope_param(net, idx);
|
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);
|
ivl_expr_t pex = ivl_parameter_expr(par);
|
||||||
switch (ivl_expr_type(pex)) {
|
switch (ivl_expr_type(pex)) {
|
||||||
case IVL_EX_STRING:
|
case IVL_EX_STRING:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue