Allow specparam declarations outside specify blocks.
This patch extends the compiler to support all specparam declarations allowed by the 1364-2005 standard. For compatibility with other simulators, it allows specparam values to be used in any constant expression, but outputs a warning message and disables run-time annotation of a specparam if it is used in an expression that must be evaluated at compile time.
This commit is contained in:
parent
5d05d97eb0
commit
44c5a37ab8
11
Module.h
11
Module.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __Module_H
|
||||
#define __Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2010,2012 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -79,10 +79,10 @@ class Module : public PScopeExtra, public LineInfo {
|
|||
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||
UCDriveType uc_drive;
|
||||
|
||||
/* specparams are simpler than other params, in that they have
|
||||
no type information. They are merely constant
|
||||
expressions. */
|
||||
map<perm_string,PExpr*>specparams;
|
||||
/* specparams are simpler than other parameters, in that they
|
||||
can have a range, but not an explicit type. The restrictions
|
||||
are enforced by the parser. */
|
||||
map<perm_string,param_expr_t>specparams;
|
||||
|
||||
/* The module also has defparam assignments which don't create
|
||||
new parameters within the module, but may be used to set
|
||||
|
|
@ -140,6 +140,7 @@ class Module : public PScopeExtra, public LineInfo {
|
|||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
void dump_specparams_(ostream&out, unsigned indent) const;
|
||||
list<PGate*> gates_;
|
||||
|
||||
private: // Not implemented
|
||||
|
|
|
|||
1
PExpr.h
1
PExpr.h
|
|
@ -49,6 +49,7 @@ class PExpr : public LineInfo {
|
|||
static const unsigned NO_FLAGS = 0x0;
|
||||
static const unsigned NEED_CONST = 0x1;
|
||||
static const unsigned SYS_TASK_ARG = 0x2;
|
||||
static const unsigned ANNOTATABLE = 0x4;
|
||||
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
|
|
|||
|
|
@ -1141,7 +1141,10 @@ void NetScope::dump(ostream&o) const
|
|||
map<perm_string,param_expr_t>::const_iterator pp;
|
||||
for (pp = parameters.begin()
|
||||
; pp != parameters.end() ; ++ pp ) {
|
||||
o << " parameter ";
|
||||
if ((*pp).second.is_annotatable)
|
||||
o << " specparam ";
|
||||
else
|
||||
o << " parameter ";
|
||||
|
||||
o << pp->second.type << " ";
|
||||
|
||||
|
|
@ -1245,27 +1248,6 @@ void NetScope::dump(ostream&o) const
|
|||
cur->second->dump_net(o, 4);
|
||||
}
|
||||
|
||||
// Dump specparams
|
||||
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
|
||||
for (specparam_it_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; ++ cur ) {
|
||||
o << " specparam " << (*cur).first
|
||||
<< " = ";
|
||||
spec_val_t value = (*cur).second;
|
||||
switch (value.type) {
|
||||
case IVL_VT_REAL:
|
||||
o << "R:" << value.real_val;
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
o << "I:" << value.integer;
|
||||
break;
|
||||
default:
|
||||
o << "<bad type>";
|
||||
break;
|
||||
}
|
||||
o << endl;
|
||||
}
|
||||
|
||||
switch (type_) {
|
||||
case FUNC:
|
||||
if (func_def())
|
||||
|
|
|
|||
64
elab_expr.cc
64
elab_expr.cc
|
|
@ -2172,32 +2172,6 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
// The width of a specparam is the width of the specparam value
|
||||
// (as evaluated earlier). Note that specparams aren't fully
|
||||
// supported yet, so this code is likely to need rework when
|
||||
// they are.
|
||||
map<perm_string,NetScope::spec_val_t>::const_iterator specp;
|
||||
perm_string key = peek_tail_name(path_);
|
||||
if (path_.size() == 1 &&
|
||||
((specp = scope->specparams.find(key)) != scope->specparams.end())) {
|
||||
NetScope::spec_val_t value = (*specp).second;
|
||||
if (value.type == IVL_VT_REAL) {
|
||||
expr_type_ = IVL_VT_REAL;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
signed_flag_ = true;
|
||||
} else {
|
||||
verinum val (value.integer);
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = val.len();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = true;
|
||||
|
||||
if (mode < LOSSLESS) mode = LOSSLESS;
|
||||
}
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
// If this is SystemVerilog then maybe this is a structure element.
|
||||
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
|
|
@ -2371,34 +2345,6 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// A specparam? Look up the name to see if it is a
|
||||
// specparam. If we find it, then turn it into a NetEConst
|
||||
// value and return that.
|
||||
map<perm_string,NetScope::spec_val_t>::const_iterator specp;
|
||||
perm_string key = peek_tail_name(path_);
|
||||
if (path_.size() == 1 &&
|
||||
((specp = scope->specparams.find(key)) != scope->specparams.end())) {
|
||||
NetScope::spec_val_t value = (*specp).second;
|
||||
NetExpr*tmp = 0;
|
||||
switch (value.type) {
|
||||
case IVL_VT_BOOL:
|
||||
tmp = new NetEConst(verinum(value.integer));
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
tmp = new NetECReal(verireal(value.real_val));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: " << path_
|
||||
<< " is a specparam" << endl;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Maybe this is a method attached to an enumeration name? If
|
||||
// this is system verilog, then test to see if the name is
|
||||
// really a method attached to an object.
|
||||
|
|
@ -2862,6 +2808,16 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
{
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
if (need_const && !(ANNOTATABLE & flags)) {
|
||||
perm_string name = peek_tail_name(path_);
|
||||
if (found_in->make_parameter_unannotatable(name)) {
|
||||
cerr << get_fileline() << ": warning: specparam '" << name
|
||||
<< "' is being used in a constant expression." << endl;
|
||||
cerr << get_fileline() << ": : This will prevent it "
|
||||
"being annotated at run time." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@
|
|||
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,
|
||||
const LexicalScope::param_expr_t&cur)
|
||||
const LexicalScope::param_expr_t&cur,
|
||||
bool is_annotatable)
|
||||
{
|
||||
NetScope::range_t*range_list = 0;
|
||||
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
|
||||
|
|
@ -87,8 +88,8 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
|||
range_list = tmp;
|
||||
}
|
||||
|
||||
scope->set_parameter(name, cur.expr, cur.type, cur.msb, cur.lsb,
|
||||
cur.signed_flag, range_list, cur);
|
||||
scope->set_parameter(name, is_annotatable, cur.expr, cur.type, cur.msb,
|
||||
cur.lsb, cur.signed_flag, range_list, cur);
|
||||
}
|
||||
|
||||
static void collect_scope_parameters_(Design*des, NetScope*scope,
|
||||
|
|
@ -106,7 +107,7 @@ static void collect_scope_parameters_(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
collect_parm_item_(des, scope, (*cur).first, (*cur).second);
|
||||
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +126,26 @@ static void collect_scope_localparams_(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
collect_parm_item_(des, scope, (*cur).first, (*cur).second);
|
||||
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_scope_specparams_(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>&specparams)
|
||||
{
|
||||
for (mparm_it_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; ++ cur ) {
|
||||
|
||||
// A specparam can not have the same name as a genvar.
|
||||
if (scope->find_genvar((*cur).first)) {
|
||||
cerr << cur->second.get_fileline()
|
||||
<< ": error: specparam and genvar in '"
|
||||
<< scope->fullname() << "' have the same name '"
|
||||
<< (*cur).first << "'." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -469,6 +489,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
|||
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
|
||||
collect_scope_specparams_(des, scope, specparams);
|
||||
|
||||
// Run parameter replacements that were collected from the
|
||||
// containing scope and meant for me.
|
||||
|
||||
|
|
|
|||
45
elaborate.cc
45
elaborate.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2012 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -4447,49 +4447,6 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
bool result_flag = true;
|
||||
|
||||
// Elaborate specparams
|
||||
typedef map<perm_string,PExpr*>::const_iterator specparam_it_t;
|
||||
for (specparam_it_t cur = specparams.begin() ;
|
||||
cur != specparams.end() ; ++ cur ) {
|
||||
|
||||
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1, true);
|
||||
NetScope::spec_val_t value;
|
||||
|
||||
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {
|
||||
|
||||
value.type = IVL_VT_REAL;
|
||||
value.real_val = val_cr->value().as_double();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate "
|
||||
<< "specparam " << (*cur).first
|
||||
<< " value=" << value.real_val << endl;
|
||||
}
|
||||
|
||||
} else if (NetEConst*val_c = dynamic_cast<NetEConst*> (val)) {
|
||||
|
||||
value.type = IVL_VT_BOOL;
|
||||
value.integer = val_c->value().as_long();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate "
|
||||
<< "specparam " << (*cur).first
|
||||
<< " value=" << value.integer << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
value.type = IVL_VT_NO_TYPE;
|
||||
cerr << (*cur).second->get_fileline() << ": error: "
|
||||
<< "specparam " << (*cur).first
|
||||
<< " value is not constant: " << *val << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
assert(val);
|
||||
delete val;
|
||||
scope->specparams[(*cur).first] = value;
|
||||
}
|
||||
|
||||
// Elaborate within the generate blocks.
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
|
|
|
|||
|
|
@ -370,7 +370,8 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
if (range_flag)
|
||||
lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true);
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true,
|
||||
(*cur).second.is_annotatable);
|
||||
if (! expr)
|
||||
return;
|
||||
|
||||
|
|
@ -491,7 +492,8 @@ 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;
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true);
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true,
|
||||
(*cur).second.is_annotatable);
|
||||
if (! expr)
|
||||
return;
|
||||
|
||||
|
|
|
|||
21
net_scope.cc
21
net_scope.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -114,13 +114,14 @@ void NetScope::set_line(perm_string file, perm_string def_file,
|
|||
def_lineno_ = def_lineno;
|
||||
}
|
||||
|
||||
void NetScope::set_parameter(perm_string key, PExpr*val,
|
||||
ivl_variable_type_t type__,
|
||||
void NetScope::set_parameter(perm_string key, bool is_annotatable,
|
||||
PExpr*val, ivl_variable_type_t type__,
|
||||
PExpr*msb, PExpr*lsb, bool signed_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;
|
||||
|
|
@ -188,6 +189,19 @@ bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
|
|||
return flag;
|
||||
}
|
||||
|
||||
bool NetScope::make_parameter_unannotatable(perm_string key)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
if (parameters.find(key) != parameters.end()) {
|
||||
param_expr_t&ref = parameters[key];
|
||||
flag = ref.is_annotatable;
|
||||
ref.is_annotatable = false;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is not really complete (msb, lsb, sign). It is currently only
|
||||
* used to add a genvar to the local parameter list.
|
||||
|
|
@ -197,6 +211,7 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*val,
|
|||
{
|
||||
param_expr_t&ref = localparams[key];
|
||||
NetExpr* res = ref.val;
|
||||
ref.is_annotatable = false;
|
||||
ref.msb_expr = 0;
|
||||
ref.lsb_expr = 0;
|
||||
ref.val_expr = 0;
|
||||
|
|
|
|||
25
netlist.h
25
netlist.h
|
|
@ -766,8 +766,8 @@ class NetScope : public Attrib {
|
|||
previous expression, if there was one. */
|
||||
|
||||
struct range_t;
|
||||
void set_parameter(perm_string name, PExpr*val,
|
||||
ivl_variable_type_t type,
|
||||
void set_parameter(perm_string name, bool is_annotatable,
|
||||
PExpr*val, ivl_variable_type_t type,
|
||||
PExpr*msb, PExpr*lsb, bool signed_flag,
|
||||
NetScope::range_t*range_list,
|
||||
const LineInfo&file_line);
|
||||
|
|
@ -789,6 +789,13 @@ class NetScope : public Attrib {
|
|||
exist. */
|
||||
bool replace_parameter(perm_string name, PExpr*val, NetScope*scope);
|
||||
|
||||
/* This is used to ensure the value of a parameter cannot be
|
||||
changed at run-time. This is required if a specparam is used
|
||||
in an expression that must be evaluated at compile-time.
|
||||
Returns true if the named parameter is a specparam and has
|
||||
not already been set to be unannotatable. */
|
||||
bool make_parameter_unannotatable(perm_string name);
|
||||
|
||||
/* These methods set or access events that live in this
|
||||
scope. */
|
||||
|
||||
|
|
@ -955,7 +962,8 @@ class NetScope : public Attrib {
|
|||
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),
|
||||
solving(false), type(IVL_VT_NO_TYPE), signed_flag(false),
|
||||
solving(false), is_annotatable(false),
|
||||
type(IVL_VT_NO_TYPE), signed_flag(false),
|
||||
msb(0), lsb(0), range(0), val(0) { }
|
||||
// Source expressions
|
||||
PExpr*msb_expr;
|
||||
|
|
@ -965,6 +973,8 @@ class NetScope : public Attrib {
|
|||
NetScope*val_scope;
|
||||
// Evaluation status
|
||||
bool solving;
|
||||
// specparam status
|
||||
bool is_annotatable;
|
||||
// Type information
|
||||
ivl_variable_type_t type;
|
||||
bool signed_flag;
|
||||
|
|
@ -982,15 +992,6 @@ class NetScope : public Attrib {
|
|||
|
||||
param_ref_t find_parameter(perm_string name);
|
||||
|
||||
struct spec_val_t {
|
||||
ivl_variable_type_t type;
|
||||
union {
|
||||
double real_val; // type == IVL_VT_REAL
|
||||
long integer; // type == IVL_VT_BOOL
|
||||
};
|
||||
};
|
||||
map<perm_string,spec_val_t>specparams;
|
||||
|
||||
/* Module instance arrays are collected here for access during
|
||||
the multiple elaboration passes. */
|
||||
typedef vector<NetScope*> scope_vec_t;
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ static const char*width_mode_name(PExpr::width_mode_t mode)
|
|||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const)
|
||||
int context_width, bool need_const, bool annotatable)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
||||
|
|
@ -562,6 +562,8 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
|||
unsigned flags = PExpr::NO_FLAGS;
|
||||
if (need_const)
|
||||
flags |= PExpr::NEED_CONST;
|
||||
if (annotatable)
|
||||
flags |= PExpr::ANNOTATABLE;
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
|
|
|||
|
|
@ -192,7 +192,8 @@ class PExpr;
|
|||
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
PExpr*pe, int context_width,
|
||||
bool need_const =false);
|
||||
bool need_const =false,
|
||||
bool annotatable =false);
|
||||
|
||||
/*
|
||||
* This function is a variant of elab_and_eval that elaborates and
|
||||
|
|
|
|||
26
parse.y
26
parse.y
|
|
@ -4296,6 +4296,10 @@ module_item
|
|||
pform_endgenerate();
|
||||
}
|
||||
|
||||
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
|
||||
|
||||
| attribute_list_opt K_specparam specparam_decl ';'
|
||||
|
||||
/* specify blocks are parsed but ignored. */
|
||||
|
||||
| K_specify K_endspecify
|
||||
|
|
@ -5126,7 +5130,7 @@ net_variable_list
|
|||
;
|
||||
|
||||
specify_item
|
||||
: K_specparam specparam_list ';'
|
||||
: K_specparam specparam_decl ';'
|
||||
| specify_simple_path_decl ';'
|
||||
{ pform_module_specify_path($1);
|
||||
}
|
||||
|
|
@ -5332,7 +5336,8 @@ specify_path_identifiers
|
|||
specparam
|
||||
: IDENTIFIER '=' expression
|
||||
{ PExpr*tmp = $3;
|
||||
pform_set_specparam(lex_strings.make($1), tmp);
|
||||
pform_set_specparam(@1, lex_strings.make($1),
|
||||
param_active_range, tmp);
|
||||
delete[]$1;
|
||||
}
|
||||
| IDENTIFIER '=' expression ':' expression ':' expression
|
||||
|
|
@ -5370,7 +5375,8 @@ specparam
|
|||
cerr << " expression." << endl;
|
||||
min_typ_max_warn -= 1;
|
||||
}
|
||||
pform_set_specparam(lex_strings.make($1), tmp);
|
||||
pform_set_specparam(@1, lex_strings.make($1),
|
||||
param_active_range, tmp);
|
||||
delete[]$1;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' expression
|
||||
|
|
@ -5385,9 +5391,17 @@ specparam
|
|||
;
|
||||
|
||||
specparam_list
|
||||
: specparam
|
||||
| specparam_list ',' specparam
|
||||
;
|
||||
: specparam
|
||||
| specparam_list ',' specparam
|
||||
;
|
||||
|
||||
specparam_decl
|
||||
: specparam_list
|
||||
| range
|
||||
{ param_active_range = $1; }
|
||||
specparam_list
|
||||
{ param_active_range = 0; }
|
||||
;
|
||||
|
||||
spec_polarity
|
||||
: '+' { $$ = '+'; }
|
||||
|
|
|
|||
67
pform.cc
67
pform.cc
|
|
@ -2331,6 +2331,15 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
<< "' have the same name '" << name << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if ((scope == pform_cur_module) &&
|
||||
(pform_cur_module->specparams.find(name) != pform_cur_module->specparams.end())) {
|
||||
LineInfo tloc;
|
||||
FILE_NAME(&tloc, loc);
|
||||
cerr << tloc.get_fileline() << ": error: specparam and "
|
||||
"parameter in '" << pform_cur_module->mod_name()
|
||||
<< "' have the same name '" << name << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
assert(expr);
|
||||
Module::param_expr_t&parm = scope->parameters[name];
|
||||
|
|
@ -2380,6 +2389,15 @@ void pform_set_localparam(const struct vlltype&loc,
|
|||
<< "' have the same name '" << name << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if ((scope == pform_cur_module) &&
|
||||
(pform_cur_module->specparams.find(name) != pform_cur_module->specparams.end())) {
|
||||
LineInfo tloc;
|
||||
FILE_NAME(&tloc, loc);
|
||||
cerr << tloc.get_fileline() << ": error: specparam and "
|
||||
"localparam in '" << pform_cur_module->mod_name()
|
||||
<< "' have the same name '" << name << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
assert(expr);
|
||||
Module::param_expr_t&parm = scope->localparams[name];
|
||||
|
|
@ -2403,19 +2421,58 @@ void pform_set_localparam(const struct vlltype&loc,
|
|||
parm.range = 0;
|
||||
}
|
||||
|
||||
void pform_set_specparam(perm_string name, PExpr*expr)
|
||||
void pform_set_specparam(const struct vlltype&loc, perm_string name,
|
||||
list<pform_range_t>*range, PExpr*expr)
|
||||
{
|
||||
Module*scope = pform_cur_module;
|
||||
assert(scope == lexical_scope);
|
||||
|
||||
// Check if the specparam name is already in the dictionary.
|
||||
if (pform_cur_module->specparams.find(name) !=
|
||||
pform_cur_module->specparams.end()) {
|
||||
cerr << expr->get_fileline() << ": error: duplicate definition "
|
||||
if (scope->specparams.find(name) != scope->specparams.end()) {
|
||||
LineInfo tloc;
|
||||
FILE_NAME(&tloc, loc);
|
||||
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||
"for specparam '" << name << "' in '"
|
||||
<< pform_cur_module->mod_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (scope->parameters.find(name) != scope->parameters.end()) {
|
||||
LineInfo tloc;
|
||||
FILE_NAME(&tloc, loc);
|
||||
cerr << tloc.get_fileline() << ": error: parameter and "
|
||||
"specparam in '" << pform_cur_module->mod_name()
|
||||
<< "' have the same name '" << name << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (scope->localparams.find(name) != scope->localparams.end()) {
|
||||
LineInfo tloc;
|
||||
FILE_NAME(&tloc, loc);
|
||||
cerr << tloc.get_fileline() << ": error: localparam and "
|
||||
"specparam in '" << pform_cur_module->mod_name()
|
||||
<< "' have the same name '" << name << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
assert(expr);
|
||||
pform_cur_module->specparams[name] = expr;
|
||||
Module::param_expr_t&parm = scope->specparams[name];
|
||||
FILE_NAME(&parm, loc);
|
||||
|
||||
parm.expr = expr;
|
||||
|
||||
parm.type = IVL_VT_LOGIC;
|
||||
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 = false;
|
||||
parm.range = 0;
|
||||
}
|
||||
|
||||
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
|
||||
|
|
|
|||
6
pform.h
6
pform.h
|
|
@ -331,13 +331,15 @@ extern void pform_set_localparam(const struct vlltype&loc,
|
|||
bool signed_flag,
|
||||
list<pform_range_t>*range,
|
||||
PExpr*expr);
|
||||
extern void pform_set_specparam(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
list<pform_range_t>*range,
|
||||
PExpr*expr);
|
||||
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
|
||||
|
||||
/*
|
||||
* Functions related to specify blocks.
|
||||
*/
|
||||
extern void pform_set_specparam(perm_string name, PExpr*expr);
|
||||
|
||||
extern PSpecPath*pform_make_specify_path(const struct vlltype&li,
|
||||
list<perm_string>*src, char pol,
|
||||
bool full_flag, list<perm_string>*dst);
|
||||
|
|
|
|||
|
|
@ -1194,6 +1194,23 @@ void LexicalScope::dump_wires_(ostream&out, unsigned indent) const
|
|||
}
|
||||
}
|
||||
|
||||
void Module::dump_specparams_(ostream&out, unsigned indent) const
|
||||
{
|
||||
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
|
||||
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 << "] ";
|
||||
out << (*cur).first << " = ";
|
||||
if ((*cur).second.expr)
|
||||
out << *(*cur).second.expr << ";" << endl;
|
||||
else
|
||||
out << "/* ERROR */;" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Module::dump(ostream&out) const
|
||||
{
|
||||
if (attributes.begin() != attributes.end()) {
|
||||
|
|
@ -1237,6 +1254,8 @@ void Module::dump(ostream&out) const
|
|||
|
||||
dump_localparams_(out, 4);
|
||||
|
||||
dump_specparams_(out, 4);
|
||||
|
||||
dump_enumerations_(out, 4);
|
||||
|
||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
|
||||
|
|
@ -1251,13 +1270,6 @@ void Module::dump(ostream&out) const
|
|||
(*cur)->dump(out, 4);
|
||||
}
|
||||
|
||||
typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t;
|
||||
for (specparm_iter_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; ++ cur ) {
|
||||
out << " specparam " << (*cur).first << " = "
|
||||
<< *(*cur).second << ";" << endl;
|
||||
}
|
||||
|
||||
typedef list<Module::named_expr_t>::const_iterator parm_hiter_t;
|
||||
for (parm_hiter_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; ++ cur ) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue