Allow modules (and program blocks in particular) to nest.
An important advantage of program blocks is its ability to nest within a module. This winds up also allowing modules to nest, which is legal but presumably less used feature.
This commit is contained in:
parent
580c44c015
commit
dfe7beec31
|
|
@ -27,8 +27,8 @@
|
||||||
list<Module::named_expr_t> Module::user_defparms;
|
list<Module::named_expr_t> Module::user_defparms;
|
||||||
|
|
||||||
/* n is a permallocated string. */
|
/* n is a permallocated string. */
|
||||||
Module::Module(perm_string n)
|
Module::Module(LexicalScope*parent, perm_string n)
|
||||||
: PScopeExtra(n)
|
: PScopeExtra(n, parent)
|
||||||
{
|
{
|
||||||
library_flag = false;
|
library_flag = false;
|
||||||
is_cell = false;
|
is_cell = false;
|
||||||
|
|
|
||||||
6
Module.h
6
Module.h
|
|
@ -65,7 +65,7 @@ class Module : public PScopeExtra, public LineInfo {
|
||||||
public:
|
public:
|
||||||
/* The name passed here is the module name, not the instance
|
/* The name passed here is the module name, not the instance
|
||||||
name. This make must be a permallocated string. */
|
name. This make must be a permallocated string. */
|
||||||
explicit Module(perm_string name);
|
explicit Module(LexicalScope*parent, perm_string name);
|
||||||
~Module();
|
~Module();
|
||||||
|
|
||||||
/* Initially false. This is set to true if the module has been
|
/* Initially false. This is set to true if the module has been
|
||||||
|
|
@ -121,6 +121,10 @@ class Module : public PScopeExtra, public LineInfo {
|
||||||
the module definition. These are used at elaboration time. */
|
the module definition. These are used at elaboration time. */
|
||||||
list<PGenerate*> generate_schemes;
|
list<PGenerate*> generate_schemes;
|
||||||
|
|
||||||
|
/* Nested modules are placed here, and are not elaborated
|
||||||
|
unless they are instantiated, implicitly or explicitly. */
|
||||||
|
std::map<perm_string,Module*> nested_modules;
|
||||||
|
|
||||||
list<PSpecPath*> specify_paths;
|
list<PSpecPath*> specify_paths;
|
||||||
|
|
||||||
// The mod_name() is the name of the module type.
|
// The mod_name() is the name of the module type.
|
||||||
|
|
|
||||||
10
PGate.cc
10
PGate.cc
|
|
@ -260,7 +260,7 @@ const char* PGBuiltin::gate_name() const
|
||||||
}
|
}
|
||||||
|
|
||||||
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
|
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
|
||||||
: PGate(name, pins), overrides_(0), pins_(0),
|
: PGate(name, pins), bound_type_(0), overrides_(0), pins_(0),
|
||||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||||
{
|
{
|
||||||
type_ = type;
|
type_ = type;
|
||||||
|
|
@ -268,12 +268,18 @@ PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
|
||||||
|
|
||||||
PGModule::PGModule(perm_string type, perm_string name,
|
PGModule::PGModule(perm_string type, perm_string name,
|
||||||
named<PExpr*>*pins, unsigned npins)
|
named<PExpr*>*pins, unsigned npins)
|
||||||
: PGate(name, 0), overrides_(0), pins_(pins),
|
: PGate(name, 0), bound_type_(0), overrides_(0), pins_(pins),
|
||||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||||
{
|
{
|
||||||
type_ = type;
|
type_ = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PGModule::PGModule(Module*type, perm_string name)
|
||||||
|
: PGate(name, 0), bound_type_(type), overrides_(0), pins_(0),
|
||||||
|
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PGModule::~PGModule()
|
PGModule::~PGModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
PGate.h
4
PGate.h
|
|
@ -201,6 +201,9 @@ class PGModule : public PGate {
|
||||||
explicit PGModule(perm_string type, perm_string name,
|
explicit PGModule(perm_string type, perm_string name,
|
||||||
named<PExpr*>*pins, unsigned npins);
|
named<PExpr*>*pins, unsigned npins);
|
||||||
|
|
||||||
|
// If the module type is known by design, then use this
|
||||||
|
// constructor.
|
||||||
|
explicit PGModule(Module*type, perm_string name);
|
||||||
|
|
||||||
~PGModule();
|
~PGModule();
|
||||||
|
|
||||||
|
|
@ -223,6 +226,7 @@ class PGModule : public PGate {
|
||||||
perm_string get_type() const;
|
perm_string get_type() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Module*bound_type_;
|
||||||
perm_string type_;
|
perm_string type_;
|
||||||
list<PExpr*>*overrides_;
|
list<PExpr*>*overrides_;
|
||||||
named<PExpr*>*pins_;
|
named<PExpr*>*pins_;
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,11 @@ static inline bool gn_system_verilog(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool gn_modules_nest(void)
|
||||||
|
{
|
||||||
|
return gn_system_verilog();
|
||||||
|
}
|
||||||
|
|
||||||
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
|
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
|
||||||
sets of keywords. The compiler enables groups of keywords by setting
|
sets of keywords. The compiler enables groups of keywords by setting
|
||||||
lexor_keyword_mask with the OR of the bits for the keywords to be
|
lexor_keyword_mask with the OR of the bits for the keywords to be
|
||||||
|
|
|
||||||
|
|
@ -693,7 +693,7 @@ NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
|
||||||
*/
|
*/
|
||||||
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
assert(scope->type() == NetScope::MODULE);
|
assert(scope->type_is_module());
|
||||||
NetNet*sig = des->find_signal(scope, path_);
|
NetNet*sig = des->find_signal(scope, path_);
|
||||||
if (sig == 0) {
|
if (sig == 0) {
|
||||||
cerr << get_fileline() << ": error: no wire/reg " << path_
|
cerr << get_fileline() << ": error: no wire/reg " << path_
|
||||||
|
|
|
||||||
|
|
@ -541,6 +541,19 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||||
|
|
||||||
elaborate_scope_funcs(des, scope, funcs);
|
elaborate_scope_funcs(des, scope, funcs);
|
||||||
|
|
||||||
|
// Look for implicit modules and implicit gates for them.
|
||||||
|
|
||||||
|
for (map<perm_string,Module*>::iterator cur = nested_modules.begin()
|
||||||
|
; cur != nested_modules.end() ; ++cur) {
|
||||||
|
// Skip modules that must be explicitly instantiated.
|
||||||
|
if (cur->second->port_count() > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PGModule*nested_gate = new PGModule(cur->second, cur->second->mod_name());
|
||||||
|
nested_gate->set_line(*cur->second);
|
||||||
|
gates_.push_back(nested_gate);
|
||||||
|
}
|
||||||
|
|
||||||
// Gates include modules, which might introduce new scopes, so
|
// Gates include modules, which might introduce new scopes, so
|
||||||
// scan all of them to create those scopes.
|
// scan all of them to create those scopes.
|
||||||
|
|
||||||
|
|
@ -1212,7 +1225,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scn->type() != NetScope::MODULE) continue;
|
if (! scn->type_is_module()) continue;
|
||||||
|
|
||||||
if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue;
|
if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue;
|
||||||
|
|
||||||
|
|
@ -1329,8 +1342,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
<< "." << endl;
|
<< "." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the new scope as a MODULE with my name.
|
// Create the new scope as a MODULE with my name. Note
|
||||||
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE);
|
// that if this is a nested module, mark it thus so that
|
||||||
|
// scope searches will continue into the parent scope.
|
||||||
|
NetScope*my_scope = new NetScope(sc, use_name, bound_type_? NetScope::NESTED_MODULE : NetScope::MODULE);
|
||||||
my_scope->set_line(get_file(), mod->get_file(),
|
my_scope->set_line(get_file(), mod->get_file(),
|
||||||
get_lineno(), mod->get_lineno());
|
get_lineno(), mod->get_lineno());
|
||||||
my_scope->set_module_name(mod->mod_name());
|
my_scope->set_module_name(mod->mod_name());
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||||
reg, then report an error. */
|
reg, then report an error. */
|
||||||
|
|
||||||
if (sig && (sig->scope() == scope)
|
if (sig && (sig->scope() == scope)
|
||||||
&& (scope->type() == NetScope::MODULE)
|
&& (scope->type_is_module())
|
||||||
&& (sig->port_type() == NetNet::PINPUT)
|
&& (sig->port_type() == NetNet::PINPUT)
|
||||||
&& (sig->type() == NetNet::REG)) {
|
&& (sig->type() == NetNet::REG)) {
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sig && (sig->scope() == scope)
|
if (sig && (sig->scope() == scope)
|
||||||
&& (scope->type() == NetScope::MODULE)
|
&& (scope->type_is_module())
|
||||||
&& (sig->port_type() == NetNet::PINOUT)
|
&& (sig->port_type() == NetNet::PINOUT)
|
||||||
&& (sig->type() == NetNet::REG)) {
|
&& (sig->type() == NetNet::REG)) {
|
||||||
|
|
||||||
|
|
@ -122,7 +122,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sig && (sig->scope() == scope)
|
if (sig && (sig->scope() == scope)
|
||||||
&& (scope->type() == NetScope::MODULE)
|
&& scope->type_is_module()
|
||||||
&& (sig->port_type() == NetNet::PINOUT)
|
&& (sig->port_type() == NetNet::PINOUT)
|
||||||
&& (sig->data_type() == IVL_VT_REAL)) {
|
&& (sig->data_type() == IVL_VT_REAL)) {
|
||||||
|
|
||||||
|
|
|
||||||
20
elaborate.cc
20
elaborate.cc
|
|
@ -2068,6 +2068,10 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||||
|
|
||||||
bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
|
bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
|
if (bound_type_) {
|
||||||
|
return elaborate_sig_mod_(des, scope, bound_type_);
|
||||||
|
}
|
||||||
|
|
||||||
// Look for the module type
|
// Look for the module type
|
||||||
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
|
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
|
||||||
if (mod != pform_modules.end())
|
if (mod != pform_modules.end())
|
||||||
|
|
@ -2087,6 +2091,11 @@ bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
void PGModule::elaborate(Design*des, NetScope*scope) const
|
void PGModule::elaborate(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
|
if (bound_type_) {
|
||||||
|
elaborate_mod_(des, bound_type_, scope);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Look for the module type
|
// Look for the module type
|
||||||
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
|
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
|
||||||
if (mod != pform_modules.end()) {
|
if (mod != pform_modules.end()) {
|
||||||
|
|
@ -2108,10 +2117,16 @@ void PGModule::elaborate(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
void PGModule::elaborate_scope(Design*des, NetScope*sc) const
|
void PGModule::elaborate_scope(Design*des, NetScope*sc) const
|
||||||
{
|
{
|
||||||
|
// If the module type is known by design, then go right to it.
|
||||||
|
if (bound_type_) {
|
||||||
|
elaborate_scope_mod_(des, bound_type_, sc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Look for the module type
|
// Look for the module type
|
||||||
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
|
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
|
||||||
if (mod != pform_modules.end()) {
|
if (mod != pform_modules.end()) {
|
||||||
elaborate_scope_mod_(des, (*mod).second, sc);
|
elaborate_scope_mod_(des, mod->second, sc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2128,7 +2143,7 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
|
||||||
// Try again to find the module type
|
// Try again to find the module type
|
||||||
mod = pform_modules.find(type_);
|
mod = pform_modules.find(type_);
|
||||||
if (mod != pform_modules.end()) {
|
if (mod != pform_modules.end()) {
|
||||||
elaborate_scope_mod_(des, (*mod).second, sc);
|
elaborate_scope_mod_(des, mod->second, sc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3241,6 +3256,7 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case NetScope::MODULE:
|
case NetScope::MODULE:
|
||||||
|
case NetScope::NESTED_MODULE:
|
||||||
cerr << get_fileline() << ": error: Cannot disable modules." << endl;
|
cerr << get_fileline() << ": error: Cannot disable modules." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
13
net_scope.cc
13
net_scope.cc
|
|
@ -302,6 +302,9 @@ void NetScope::print_type(ostream&stream) const
|
||||||
case FUNC:
|
case FUNC:
|
||||||
stream << "function";
|
stream << "function";
|
||||||
break;
|
break;
|
||||||
|
case NESTED_MODULE:
|
||||||
|
stream << "nested_module <" << (module_name_ ? module_name_.str() : "")
|
||||||
|
<< "> instance";
|
||||||
case MODULE:
|
case MODULE:
|
||||||
stream << "module <" << (module_name_ ? module_name_.str() : "")
|
stream << "module <" << (module_name_ ? module_name_.str() : "")
|
||||||
<< "> instance";
|
<< "> instance";
|
||||||
|
|
@ -360,31 +363,31 @@ const NetFuncDef* NetScope::func_def() const
|
||||||
|
|
||||||
void NetScope::set_module_name(perm_string n)
|
void NetScope::set_module_name(perm_string n)
|
||||||
{
|
{
|
||||||
assert(type_ == MODULE);
|
assert(type_ == MODULE || type_ == NESTED_MODULE);
|
||||||
module_name_ = n; /* NOTE: n must have been permallocated. */
|
module_name_ = n; /* NOTE: n must have been permallocated. */
|
||||||
}
|
}
|
||||||
|
|
||||||
perm_string NetScope::module_name() const
|
perm_string NetScope::module_name() const
|
||||||
{
|
{
|
||||||
assert(type_ == MODULE);
|
assert(type_ == MODULE || type_ == NESTED_MODULE);
|
||||||
return module_name_;
|
return module_name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetScope::add_module_port(NetNet*port)
|
void NetScope::add_module_port(NetNet*port)
|
||||||
{
|
{
|
||||||
assert(type_ == MODULE);
|
assert(type_ == MODULE || type_ == NESTED_MODULE);
|
||||||
ports_.push_back(port);
|
ports_.push_back(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NetScope::module_ports() const
|
unsigned NetScope::module_ports() const
|
||||||
{
|
{
|
||||||
assert(type_ == MODULE);
|
assert(type_ == MODULE || type_ == NESTED_MODULE);
|
||||||
return ports_.size();
|
return ports_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetNet* NetScope::module_port(unsigned idx) const
|
NetNet* NetScope::module_port(unsigned idx) const
|
||||||
{
|
{
|
||||||
assert(type_ == MODULE);
|
assert(type_ == MODULE || type_ == NESTED_MODULE);
|
||||||
assert(idx < ports_.size());
|
assert(idx < ports_.size());
|
||||||
return ports_[idx];
|
return ports_[idx];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -724,7 +724,7 @@ extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&r
|
||||||
class NetScope : public Attrib {
|
class NetScope : public Attrib {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK };
|
enum TYPE { MODULE, NESTED_MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK };
|
||||||
|
|
||||||
/* Create a new scope, and attach it to the given parent. The
|
/* Create a new scope, and attach it to the given parent. The
|
||||||
name is expected to have been permallocated. */
|
name is expected to have been permallocated. */
|
||||||
|
|
@ -806,6 +806,7 @@ class NetScope : public Attrib {
|
||||||
const NetScope* child(const hname_t&name) const;
|
const NetScope* child(const hname_t&name) const;
|
||||||
|
|
||||||
TYPE type() const;
|
TYPE type() const;
|
||||||
|
bool type_is_module() const { return type()==MODULE || type()==NESTED_MODULE; }
|
||||||
void print_type(ostream&) const;
|
void print_type(ostream&) const;
|
||||||
|
|
||||||
void set_task_def(NetTaskDef*);
|
void set_task_def(NetTaskDef*);
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ void nodangle_f::signal(Design*, NetNet*sig)
|
||||||
if ((sig->port_type() != NetNet::NOT_A_PORT) &&
|
if ((sig->port_type() != NetNet::NOT_A_PORT) &&
|
||||||
((sig->scope()->type() == NetScope::TASK) ||
|
((sig->scope()->type() == NetScope::TASK) ||
|
||||||
(sig->scope()->type() == NetScope::FUNC) ||
|
(sig->scope()->type() == NetScope::FUNC) ||
|
||||||
|
(sig->scope()->type() == NetScope::NESTED_MODULE) ||
|
||||||
(sig->scope()->type() == NetScope::MODULE)))
|
(sig->scope()->type() == NetScope::MODULE)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
68
parse.y
68
parse.y
|
|
@ -3866,43 +3866,46 @@ module_parameter_port_list
|
||||||
|
|
||||||
module_item
|
module_item
|
||||||
|
|
||||||
|
/* Modules can contain further sub-module definitions. */
|
||||||
|
: module
|
||||||
|
|
||||||
/* This rule detects net declarations that possibly include a
|
/* This rule detects net declarations that possibly include a
|
||||||
primitive type, an optional vector range and signed flag. This
|
primitive type, an optional vector range and signed flag. This
|
||||||
also includes an optional delay set. The values are then applied
|
also includes an optional delay set. The values are then applied
|
||||||
to a list of names. If the primitive type is not specified, then
|
to a list of names. If the primitive type is not specified, then
|
||||||
resort to the default type LOGIC. */
|
resort to the default type LOGIC. */
|
||||||
|
|
||||||
: attribute_list_opt net_type
|
| attribute_list_opt net_type
|
||||||
primitive_type_opt unsigned_signed_opt range_opt
|
primitive_type_opt unsigned_signed_opt range_opt
|
||||||
delay3_opt
|
delay3_opt
|
||||||
net_variable_list ';'
|
net_variable_list ';'
|
||||||
|
|
||||||
{ ivl_variable_type_t dtype = $3;
|
{ ivl_variable_type_t dtype = $3;
|
||||||
if (dtype == IVL_VT_NO_TYPE)
|
if (dtype == IVL_VT_NO_TYPE)
|
||||||
dtype = IVL_VT_LOGIC;
|
dtype = IVL_VT_LOGIC;
|
||||||
pform_makewire(@2, $5, $4, $7, $2,
|
pform_makewire(@2, $5, $4, $7, $2, NetNet::NOT_A_PORT, dtype, $1);
|
||||||
NetNet::NOT_A_PORT, dtype, $1);
|
if ($6 != 0) {
|
||||||
if ($6 != 0) {
|
yyerror(@6, "sorry: net delays not supported.");
|
||||||
yyerror(@6, "sorry: net delays not supported.");
|
delete $6;
|
||||||
delete $6;
|
}
|
||||||
}
|
delete $1;
|
||||||
delete $1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
| attribute_list_opt K_wreal delay3 net_variable_list ';'
|
| attribute_list_opt K_wreal delay3 net_variable_list ';'
|
||||||
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE,
|
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE,
|
||||||
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
|
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
|
||||||
if ($3 != 0) {
|
if ($3 != 0) {
|
||||||
yyerror(@3, "sorry: net delays not supported.");
|
yyerror(@3, "sorry: net delays not supported.");
|
||||||
delete $3;
|
delete $3;
|
||||||
}
|
}
|
||||||
delete $1;
|
delete $1;
|
||||||
}
|
}
|
||||||
| attribute_list_opt K_wreal net_variable_list ';'
|
|
||||||
{ pform_makewire(@2, 0, true, $3, NetNet::WIRE,
|
| attribute_list_opt K_wreal net_variable_list ';'
|
||||||
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
|
{ pform_makewire(@2, 0, true, $3, NetNet::WIRE,
|
||||||
delete $1;
|
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
|
||||||
}
|
delete $1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Very similar to the rule above, but this takes a list of
|
/* Very similar to the rule above, but this takes a list of
|
||||||
net_decl_assigns, which are <name> = <expr> assignment
|
net_decl_assigns, which are <name> = <expr> assignment
|
||||||
|
|
@ -4248,13 +4251,6 @@ module_item
|
||||||
module items. These rules try to catch them at a point where a
|
module items. These rules try to catch them at a point where a
|
||||||
reasonable error message can be produced. */
|
reasonable error message can be produced. */
|
||||||
|
|
||||||
| K_module error ';'
|
|
||||||
{ yyerror(@1, "error: missing endmodule or attempt to "
|
|
||||||
"nest modules.");
|
|
||||||
pform_error_nested_modules();
|
|
||||||
yyerrok;
|
|
||||||
}
|
|
||||||
|
|
||||||
| error ';'
|
| error ';'
|
||||||
{ yyerror(@2, "error: invalid module item.");
|
{ yyerror(@2, "error: invalid module item.");
|
||||||
yyerrok;
|
yyerrok;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ std::ostream& operator << (std::ostream&o, const YYLTYPE&loc)
|
||||||
{
|
{
|
||||||
if (loc.text)
|
if (loc.text)
|
||||||
o << loc.text << ":";
|
o << loc.text << ":";
|
||||||
|
else
|
||||||
|
o << "<>:";
|
||||||
o << loc.first_line;
|
o << loc.first_line;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
189
pform.cc
189
pform.cc
|
|
@ -41,7 +41,13 @@
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
# include "ivl_alloc.h"
|
# include "ivl_alloc.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The pform_modules is a map of the modules that have been defined in
|
||||||
|
* the top level. This should not contain nested modules/programs.
|
||||||
|
*/
|
||||||
map<perm_string,Module*> pform_modules;
|
map<perm_string,Module*> pform_modules;
|
||||||
|
/*
|
||||||
|
*/
|
||||||
map<perm_string,PUdp*> pform_primitives;
|
map<perm_string,PUdp*> pform_primitives;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -217,7 +223,7 @@ extern int VLparse();
|
||||||
/* This tracks the current module being processed. There can only be
|
/* This tracks the current module being processed. There can only be
|
||||||
exactly one module currently being parsed, since Verilog does not
|
exactly one module currently being parsed, since Verilog does not
|
||||||
allow nested module definitions. */
|
allow nested module definitions. */
|
||||||
static Module*pform_cur_module = 0;
|
static list<Module*>pform_cur_module;
|
||||||
|
|
||||||
bool pform_library_flag = false;
|
bool pform_library_flag = false;
|
||||||
|
|
||||||
|
|
@ -307,7 +313,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
||||||
pform_cur_generate->tasks.end()) {
|
pform_cur_generate->tasks.end()) {
|
||||||
cerr << task->get_fileline() << ": error: duplicate "
|
cerr << task->get_fileline() << ": error: duplicate "
|
||||||
"definition for task '" << name << "' in '"
|
"definition for task '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "' (generate)."
|
<< pform_cur_module.front()->mod_name() << "' (generate)."
|
||||||
<< endl;
|
<< endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -350,7 +356,7 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
|
||||||
pform_cur_generate->funcs.end()) {
|
pform_cur_generate->funcs.end()) {
|
||||||
cerr << func->get_fileline() << ": error: duplicate "
|
cerr << func->get_fileline() << ": error: duplicate "
|
||||||
"definition for function '" << name << "' in '"
|
"definition for function '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "' (generate)."
|
<< pform_cur_module.front()->mod_name() << "' (generate)."
|
||||||
<< endl;
|
<< endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -402,16 +408,16 @@ void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
|
||||||
|
|
||||||
bool pform_in_program_block()
|
bool pform_in_program_block()
|
||||||
{
|
{
|
||||||
if (pform_cur_module == 0)
|
if (pform_cur_module.size() == 0)
|
||||||
return false;
|
return false;
|
||||||
if (pform_cur_module->program_block)
|
if (pform_cur_module.front()->program_block)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pform_at_module_level()
|
static bool pform_at_module_level()
|
||||||
{
|
{
|
||||||
return (lexical_scope == pform_cur_module)
|
return (lexical_scope == pform_cur_module.front())
|
||||||
|| (lexical_scope == pform_cur_generate);
|
|| (lexical_scope == pform_cur_generate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -488,15 +494,15 @@ void pform_set_default_nettype(NetNet::Type type,
|
||||||
{
|
{
|
||||||
pform_default_nettype = type;
|
pform_default_nettype = type;
|
||||||
|
|
||||||
if (pform_cur_module) {
|
if (pform_cur_module.size() > 0) {
|
||||||
cerr << file<<":"<<lineno << ": error: "
|
cerr << file<<":"<<lineno << ": error: "
|
||||||
<< "`default_nettype directives must appear" << endl;
|
<< "`default_nettype directives must appear" << endl;
|
||||||
cerr << file<<":"<<lineno << ": : "
|
cerr << file<<":"<<lineno << ": : "
|
||||||
<< "outside module definitions. The containing" << endl;
|
<< "outside module definitions. The containing" << endl;
|
||||||
cerr << file<<":"<<lineno << ": : "
|
cerr << file<<":"<<lineno << ": : "
|
||||||
<< "module " << pform_cur_module->mod_name()
|
<< "module " << pform_cur_module.back()->mod_name()
|
||||||
<< " starts on line "
|
<< " starts on line "
|
||||||
<< pform_cur_module->get_fileline() << "." << endl;
|
<< pform_cur_module.back()->get_fileline() << "." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -699,14 +705,14 @@ void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
|
||||||
|
|
||||||
if (in_module) {
|
if (in_module) {
|
||||||
if (!only_check) {
|
if (!only_check) {
|
||||||
pform_cur_module->time_unit = val;
|
pform_cur_module.front()->time_unit = val;
|
||||||
tu_decl_flag = true;
|
tu_decl_flag = true;
|
||||||
tu_local_flag = true;
|
tu_local_flag = true;
|
||||||
} else if (!tu_decl_flag) {
|
} else if (!tu_decl_flag) {
|
||||||
VLerror(yylloc, "error: repeat timeunit found and the "
|
VLerror(yylloc, "error: repeat timeunit found and the "
|
||||||
"initial module timeunit is missing.");
|
"initial module timeunit is missing.");
|
||||||
return;
|
return;
|
||||||
} else if (pform_cur_module->time_unit != val) {
|
} else if (pform_cur_module.front()->time_unit != val) {
|
||||||
VLerror(yylloc, "error: repeat timeunit does not match "
|
VLerror(yylloc, "error: repeat timeunit does not match "
|
||||||
"the initial module timeunit "
|
"the initial module timeunit "
|
||||||
"declaration.");
|
"declaration.");
|
||||||
|
|
@ -723,7 +729,7 @@ void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
|
||||||
|
|
||||||
int pform_get_timeunit()
|
int pform_get_timeunit()
|
||||||
{
|
{
|
||||||
return pform_cur_module->time_unit;
|
return pform_cur_module.front()->time_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
|
void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
|
||||||
|
|
@ -734,14 +740,14 @@ void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
|
||||||
|
|
||||||
if (in_module) {
|
if (in_module) {
|
||||||
if (!only_check) {
|
if (!only_check) {
|
||||||
pform_cur_module->time_precision = val;
|
pform_cur_module.front()->time_precision = val;
|
||||||
tp_decl_flag = true;
|
tp_decl_flag = true;
|
||||||
tp_local_flag = true;
|
tp_local_flag = true;
|
||||||
} else if (!tp_decl_flag) {
|
} else if (!tp_decl_flag) {
|
||||||
VLerror(yylloc, "error: repeat timeprecision found and the "
|
VLerror(yylloc, "error: repeat timeprecision found and the "
|
||||||
"initial module timeprecision is missing.");
|
"initial module timeprecision is missing.");
|
||||||
return;
|
return;
|
||||||
} else if (pform_cur_module->time_precision != val) {
|
} else if (pform_cur_module.front()->time_precision != val) {
|
||||||
VLerror(yylloc, "error: repeat timeprecision does not match "
|
VLerror(yylloc, "error: repeat timeprecision does not match "
|
||||||
"the initial module timeprecision "
|
"the initial module timeprecision "
|
||||||
"declaration.");
|
"declaration.");
|
||||||
|
|
@ -808,26 +814,32 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||||
void pform_startmodule(const struct vlltype&loc, const char*name,
|
void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
bool program_block, list<named_pexpr_t>*attr)
|
bool program_block, list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
assert( pform_cur_module == 0 );
|
if (pform_cur_module.size() > 0 && !gn_system_verilog()) {
|
||||||
|
cerr << loc << ": error: Module definition " << name
|
||||||
|
<< " cannot nest into module " << pform_cur_module.front()->mod_name() << "." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
perm_string lex_name = lex_strings.make(name);
|
perm_string lex_name = lex_strings.make(name);
|
||||||
pform_cur_module = new Module(lex_name);
|
Module*cur_module = new Module(lexical_scope, lex_name);
|
||||||
pform_cur_module->program_block = program_block;
|
cur_module->program_block = program_block;
|
||||||
/* Set the local time unit/precision to the global value. */
|
/* Set the local time unit/precision to the global value. */
|
||||||
pform_cur_module->time_unit = pform_time_unit;
|
cur_module->time_unit = pform_time_unit;
|
||||||
pform_cur_module->time_precision = pform_time_prec;
|
cur_module->time_precision = pform_time_prec;
|
||||||
tu_local_flag = tu_global_flag;
|
tu_local_flag = tu_global_flag;
|
||||||
tp_local_flag = tp_global_flag;
|
tp_local_flag = tp_global_flag;
|
||||||
|
|
||||||
/* If we have a timescale file then the time information is from
|
/* If we have a timescale file then the time information is from
|
||||||
* a timescale directive. */
|
* a timescale directive. */
|
||||||
pform_cur_module->time_from_timescale = pform_timescale_file != 0;
|
cur_module->time_from_timescale = pform_timescale_file != 0;
|
||||||
|
|
||||||
FILE_NAME(pform_cur_module, loc);
|
FILE_NAME(cur_module, loc);
|
||||||
pform_cur_module->library_flag = pform_library_flag;
|
cur_module->library_flag = pform_library_flag;
|
||||||
|
|
||||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
pform_cur_module.push_front(cur_module);
|
||||||
lexical_scope = pform_cur_module;
|
|
||||||
|
lexical_scope = cur_module;
|
||||||
|
|
||||||
/* The generate scheme numbering starts with *1*, not
|
/* The generate scheme numbering starts with *1*, not
|
||||||
zero. That's just the way it is, thanks to the standard. */
|
zero. That's just the way it is, thanks to the standard. */
|
||||||
|
|
@ -836,13 +848,13 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
if (warn_timescale && pform_timescale_file
|
if (warn_timescale && pform_timescale_file
|
||||||
&& (strcmp(pform_timescale_file,loc.text) != 0)) {
|
&& (strcmp(pform_timescale_file,loc.text) != 0)) {
|
||||||
|
|
||||||
cerr << pform_cur_module->get_fileline() << ": warning: "
|
cerr << cur_module->get_fileline() << ": warning: "
|
||||||
<< "timescale for " << name
|
<< "timescale for " << name
|
||||||
<< " inherited from another file." << endl;
|
<< " inherited from another file." << endl;
|
||||||
cerr << pform_timescale_file << ":" << pform_timescale_line
|
cerr << pform_timescale_file << ":" << pform_timescale_line
|
||||||
<< ": ...: The inherited timescale is here." << endl;
|
<< ": ...: The inherited timescale is here." << endl;
|
||||||
}
|
}
|
||||||
pform_bind_attributes(pform_cur_module->attributes, attr);
|
pform_bind_attributes(cur_module->attributes, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -852,13 +864,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
*/
|
*/
|
||||||
void pform_check_timeunit_prec()
|
void pform_check_timeunit_prec()
|
||||||
{
|
{
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module.size() > 0);
|
||||||
if ((generation_flag & (GN_VER2005_SV | GN_VER2009)) &&
|
if ((generation_flag & (GN_VER2005_SV | GN_VER2009)) &&
|
||||||
(pform_cur_module->time_unit < pform_cur_module->time_precision)) {
|
(pform_cur_module.front()->time_unit < pform_cur_module.front()->time_precision)) {
|
||||||
VLerror("error: a timeprecision is missing or is too "
|
VLerror("error: a timeprecision is missing or is too large!");
|
||||||
"large!");
|
} else assert(pform_cur_module.front()->time_unit >=
|
||||||
} else assert(pform_cur_module->time_unit >=
|
pform_cur_module.front()->time_precision);
|
||||||
pform_cur_module->time_precision);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -881,7 +892,7 @@ Module::port_t* pform_module_port_reference(perm_string name,
|
||||||
|
|
||||||
void pform_module_set_ports(vector<Module::port_t*>*ports)
|
void pform_module_set_ports(vector<Module::port_t*>*ports)
|
||||||
{
|
{
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module.size() > 0);
|
||||||
|
|
||||||
/* The parser parses ``module foo()'' as having one
|
/* The parser parses ``module foo()'' as having one
|
||||||
unconnected port, but it is really a module with no
|
unconnected port, but it is really a module with no
|
||||||
|
|
@ -892,7 +903,7 @@ void pform_module_set_ports(vector<Module::port_t*>*ports)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ports != 0) {
|
if (ports != 0) {
|
||||||
pform_cur_module->ports = *ports;
|
pform_cur_module.front()->ports = *ports;
|
||||||
delete ports;
|
delete ports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -900,34 +911,44 @@ void pform_module_set_ports(vector<Module::port_t*>*ports)
|
||||||
void pform_endmodule(const char*name, bool inside_celldefine,
|
void pform_endmodule(const char*name, bool inside_celldefine,
|
||||||
Module::UCDriveType uc_drive_def)
|
Module::UCDriveType uc_drive_def)
|
||||||
{
|
{
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module.size() > 0);
|
||||||
pform_cur_module->time_from_timescale = (tu_local_flag &&
|
Module*cur_module = pform_cur_module.front();
|
||||||
tp_local_flag) ||
|
pform_cur_module.pop_front();
|
||||||
(pform_timescale_file != 0);
|
|
||||||
perm_string mod_name = pform_cur_module->mod_name();
|
cur_module->time_from_timescale = (tu_local_flag && tp_local_flag)
|
||||||
|
|| (pform_timescale_file != 0);
|
||||||
|
perm_string mod_name = cur_module->mod_name();
|
||||||
assert(strcmp(name, mod_name) == 0);
|
assert(strcmp(name, mod_name) == 0);
|
||||||
pform_cur_module->is_cell = inside_celldefine;
|
cur_module->is_cell = inside_celldefine;
|
||||||
pform_cur_module->uc_drive = uc_drive_def;
|
cur_module->uc_drive = uc_drive_def;
|
||||||
|
|
||||||
|
// If this is a root module, then there is no parent module
|
||||||
|
// and we try to put this newly defined module into the global
|
||||||
|
// root list of modules. Otherwise, this is a nested module
|
||||||
|
// and we put it into the parent module scope to be elaborated
|
||||||
|
// if needed.
|
||||||
|
map<perm_string,Module*>&use_module_map = (pform_cur_module.size() == 0)
|
||||||
|
? pform_modules
|
||||||
|
: pform_cur_module.front()->nested_modules;
|
||||||
|
|
||||||
map<perm_string,Module*>::const_iterator test =
|
map<perm_string,Module*>::const_iterator test =
|
||||||
pform_modules.find(mod_name);
|
use_module_map.find(mod_name);
|
||||||
|
|
||||||
if (test != pform_modules.end()) {
|
if (test != use_module_map.end()) {
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
msg << "Module " << name << " was already declared here: "
|
msg << "Module " << name << " was already declared here: "
|
||||||
<< (*test).second->get_fileline() << endl;
|
<< test->second->get_fileline() << endl;
|
||||||
VLerror(msg.str().c_str());
|
VLerror(msg.str().c_str());
|
||||||
} else {
|
} else {
|
||||||
pform_modules[mod_name] = pform_cur_module;
|
use_module_map[mod_name] = cur_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The current lexical scope should be this module by now, and
|
// The current lexical scope should be this module by now, and
|
||||||
// this module should not have a parent lexical scope.
|
// this module should not have a parent lexical scope.
|
||||||
ivl_assert(*pform_cur_module, lexical_scope == pform_cur_module);
|
ivl_assert(*cur_module, lexical_scope == cur_module);
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
ivl_assert(*cur_module, pform_cur_module.size()>0 || lexical_scope == 0);
|
||||||
|
|
||||||
pform_cur_module = 0;
|
|
||||||
tp_decl_flag = false;
|
tp_decl_flag = false;
|
||||||
tu_decl_flag = false;
|
tu_decl_flag = false;
|
||||||
tu_local_flag = false;
|
tu_local_flag = false;
|
||||||
|
|
@ -958,7 +979,7 @@ void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||||
if (pform_cur_generate)
|
if (pform_cur_generate)
|
||||||
pform_add_genvar(li, *cur, pform_cur_generate->genvars);
|
pform_add_genvar(li, *cur, pform_cur_generate->genvars);
|
||||||
else
|
else
|
||||||
pform_add_genvar(li, *cur, pform_cur_module->genvars);
|
pform_add_genvar(li, *cur, pform_cur_module.front()->genvars);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete names;
|
delete names;
|
||||||
|
|
@ -1113,7 +1134,7 @@ void pform_generate_block_name(char*name)
|
||||||
void pform_endgenerate()
|
void pform_endgenerate()
|
||||||
{
|
{
|
||||||
assert(pform_cur_generate != 0);
|
assert(pform_cur_generate != 0);
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module.size() > 0);
|
||||||
|
|
||||||
// If there is no explicit block name then generate a temporary
|
// If there is no explicit block name then generate a temporary
|
||||||
// name. This will be replaced by the correct name later, once
|
// name. This will be replaced by the correct name later, once
|
||||||
|
|
@ -1137,7 +1158,7 @@ void pform_endgenerate()
|
||||||
parent_generate->generate_schemes.push_back(pform_cur_generate);
|
parent_generate->generate_schemes.push_back(pform_cur_generate);
|
||||||
} else {
|
} else {
|
||||||
assert(pform_cur_generate->scheme_type != PGenerate::GS_CASE_ITEM);
|
assert(pform_cur_generate->scheme_type != PGenerate::GS_CASE_ITEM);
|
||||||
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
|
pform_cur_module.front()->generate_schemes.push_back(pform_cur_generate);
|
||||||
}
|
}
|
||||||
pform_cur_generate = parent_generate;
|
pform_cur_generate = parent_generate;
|
||||||
}
|
}
|
||||||
|
|
@ -1593,7 +1614,7 @@ static void pform_make_event(perm_string name, const char*fn, unsigned ln)
|
||||||
FILE_NAME(&tloc, fn, ln);
|
FILE_NAME(&tloc, fn, ln);
|
||||||
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
"for named event '" << name << "' in '"
|
"for named event '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "'." << endl;
|
<< pform_cur_module.front()->mod_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1653,7 +1674,7 @@ static void pform_makegate(PGBuiltin::Type type,
|
||||||
if (pform_cur_generate)
|
if (pform_cur_generate)
|
||||||
pform_cur_generate->add_gate(cur);
|
pform_cur_generate->add_gate(cur);
|
||||||
else
|
else
|
||||||
pform_cur_module->add_gate(cur);
|
pform_cur_module.front()->add_gate(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_makegates(PGBuiltin::Type type,
|
void pform_makegates(PGBuiltin::Type type,
|
||||||
|
|
@ -1719,7 +1740,7 @@ static void pform_make_modgate(perm_string type,
|
||||||
if (pform_cur_generate)
|
if (pform_cur_generate)
|
||||||
pform_cur_generate->add_gate(cur);
|
pform_cur_generate->add_gate(cur);
|
||||||
else
|
else
|
||||||
pform_cur_module->add_gate(cur);
|
pform_cur_module.front()->add_gate(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pform_make_modgate(perm_string type,
|
static void pform_make_modgate(perm_string type,
|
||||||
|
|
@ -1763,7 +1784,7 @@ static void pform_make_modgate(perm_string type,
|
||||||
if (pform_cur_generate)
|
if (pform_cur_generate)
|
||||||
pform_cur_generate->add_gate(cur);
|
pform_cur_generate->add_gate(cur);
|
||||||
else
|
else
|
||||||
pform_cur_module->add_gate(cur);
|
pform_cur_module.front()->add_gate(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_make_modgates(perm_string type,
|
void pform_make_modgates(perm_string type,
|
||||||
|
|
@ -1833,7 +1854,7 @@ static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||||
if (pform_cur_generate)
|
if (pform_cur_generate)
|
||||||
pform_cur_generate->add_gate(cur);
|
pform_cur_generate->add_gate(cur);
|
||||||
else
|
else
|
||||||
pform_cur_module->add_gate(cur);
|
pform_cur_module.front()->add_gate(cur);
|
||||||
|
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
@ -2305,7 +2326,7 @@ void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||||
if (PWire*cur = lexical_scope->wires_find(name)) {
|
if (PWire*cur = lexical_scope->wires_find(name)) {
|
||||||
cur->attributes[key] = new PEString(value);
|
cur->attributes[key] = new PEString(value);
|
||||||
|
|
||||||
} else if (PGate*curg = pform_cur_module->get_gate(name)) {
|
} else if (PGate*curg = pform_cur_module.front()->get_gate(name)) {
|
||||||
curg->attributes[key] = new PEString(value);
|
curg->attributes[key] = new PEString(value);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2384,23 +2405,23 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
"for parameter '" << name << "' in '"
|
"for parameter '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "'." << endl;
|
<< pform_cur_module.front()->mod_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
if (scope->localparams.find(name) != scope->localparams.end()) {
|
if (scope->localparams.find(name) != scope->localparams.end()) {
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: localparam and "
|
cerr << tloc.get_fileline() << ": error: localparam and "
|
||||||
"parameter in '" << pform_cur_module->mod_name()
|
<< "parameter in '" << pform_cur_module.front()->mod_name()
|
||||||
<< "' have the same name '" << name << "'." << endl;
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
if ((scope == pform_cur_module) &&
|
if ((scope == pform_cur_module.front()) &&
|
||||||
(pform_cur_module->specparams.find(name) != pform_cur_module->specparams.end())) {
|
(pform_cur_module.front()->specparams.find(name) != pform_cur_module.front()->specparams.end())) {
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: specparam and "
|
cerr << tloc.get_fileline() << ": error: specparam and "
|
||||||
"parameter in '" << pform_cur_module->mod_name()
|
"parameter in '" << pform_cur_module.front()->mod_name()
|
||||||
<< "' have the same name '" << name << "'." << endl;
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2426,8 +2447,8 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
parm.signed_flag = signed_flag;
|
parm.signed_flag = signed_flag;
|
||||||
parm.range = value_range;
|
parm.range = value_range;
|
||||||
|
|
||||||
if (scope == pform_cur_module)
|
if (scope == pform_cur_module.front())
|
||||||
pform_cur_module->param_names.push_back(name);
|
pform_cur_module.front()->param_names.push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_localparam(const struct vlltype&loc,
|
void pform_set_localparam(const struct vlltype&loc,
|
||||||
|
|
@ -2442,23 +2463,23 @@ void pform_set_localparam(const struct vlltype&loc,
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
"for localparam '" << name << "' in '"
|
"for localparam '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "'." << endl;
|
<< pform_cur_module.front()->mod_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
if (scope->parameters.find(name) != scope->parameters.end()) {
|
if (scope->parameters.find(name) != scope->parameters.end()) {
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: parameter and "
|
cerr << tloc.get_fileline() << ": error: parameter and "
|
||||||
"localparam in '" << pform_cur_module->mod_name()
|
<< "localparam in '" << pform_cur_module.front()->mod_name()
|
||||||
<< "' have the same name '" << name << "'." << endl;
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
if ((scope == pform_cur_module) &&
|
if ((scope == pform_cur_module.front()) &&
|
||||||
(pform_cur_module->specparams.find(name) != pform_cur_module->specparams.end())) {
|
(pform_cur_module.front()->specparams.find(name) != pform_cur_module.front()->specparams.end())) {
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: specparam and "
|
cerr << tloc.get_fileline() << ": error: specparam and "
|
||||||
"localparam in '" << pform_cur_module->mod_name()
|
"localparam in '" << pform_cur_module.front()->mod_name()
|
||||||
<< "' have the same name '" << name << "'." << endl;
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2488,23 +2509,25 @@ void pform_set_localparam(const struct vlltype&loc,
|
||||||
void pform_set_specparam(const struct vlltype&loc, perm_string name,
|
void pform_set_specparam(const struct vlltype&loc, perm_string name,
|
||||||
list<pform_range_t>*range, PExpr*expr)
|
list<pform_range_t>*range, PExpr*expr)
|
||||||
{
|
{
|
||||||
Module*scope = pform_cur_module;
|
assert(pform_cur_module.size() > 0);
|
||||||
|
Module*scope = pform_cur_module.front();
|
||||||
assert(scope == lexical_scope);
|
assert(scope == lexical_scope);
|
||||||
|
|
||||||
// Check if the specparam name is already in the dictionary.
|
// Check if the specparam name is already in the dictionary.
|
||||||
if (scope->specparams.find(name) != scope->specparams.end()) {
|
if (pform_cur_module.front()->specparams.find(name) !=
|
||||||
|
pform_cur_module.front()->specparams.end()) {
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
"for specparam '" << name << "' in '"
|
"for specparam '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "'." << endl;
|
<< pform_cur_module.front()->mod_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
if (scope->parameters.find(name) != scope->parameters.end()) {
|
if (scope->parameters.find(name) != scope->parameters.end()) {
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: parameter and "
|
cerr << tloc.get_fileline() << ": error: parameter and "
|
||||||
"specparam in '" << pform_cur_module->mod_name()
|
"specparam in '" << pform_cur_module.front()->mod_name()
|
||||||
<< "' have the same name '" << name << "'." << endl;
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2512,13 +2535,14 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name,
|
||||||
LineInfo tloc;
|
LineInfo tloc;
|
||||||
FILE_NAME(&tloc, loc);
|
FILE_NAME(&tloc, loc);
|
||||||
cerr << tloc.get_fileline() << ": error: localparam and "
|
cerr << tloc.get_fileline() << ": error: localparam and "
|
||||||
"specparam in '" << pform_cur_module->mod_name()
|
"specparam in '" << pform_cur_module.front()->mod_name()
|
||||||
<< "' have the same name '" << name << "'." << endl;
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(expr);
|
assert(expr);
|
||||||
Module::param_expr_t&parm = scope->specparams[name];
|
|
||||||
|
Module::param_expr_t&parm = pform_cur_module.front()->specparams[name];
|
||||||
FILE_NAME(&parm, loc);
|
FILE_NAME(&parm, loc);
|
||||||
|
|
||||||
parm.expr = expr;
|
parm.expr = expr;
|
||||||
|
|
@ -2542,7 +2566,7 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name,
|
||||||
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
|
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
|
||||||
{
|
{
|
||||||
assert(expr);
|
assert(expr);
|
||||||
pform_cur_module->defparms.push_back(make_pair(name,expr));
|
pform_cur_module.front()->defparms.push_back(make_pair(name,expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2609,7 +2633,7 @@ extern void pform_module_specify_path(PSpecPath*obj)
|
||||||
{
|
{
|
||||||
if (obj == 0)
|
if (obj == 0)
|
||||||
return;
|
return;
|
||||||
pform_cur_module->specify_paths.push_back(obj);
|
pform_cur_module.front()->specify_paths.push_back(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2860,8 +2884,8 @@ PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
|
||||||
|
|
||||||
pform_put_behavior_in_scope(pp);
|
pform_put_behavior_in_scope(pp);
|
||||||
|
|
||||||
ivl_assert(*st, pform_cur_module);
|
ivl_assert(*st, pform_cur_module.size() > 0);
|
||||||
if (pform_cur_module->program_block && type == IVL_PR_ALWAYS) {
|
if (pform_cur_module.front()->program_block && type == IVL_PR_ALWAYS) {
|
||||||
cerr << st->get_fileline() << ": error: Always statements not allowed"
|
cerr << st->get_fileline() << ": error: Always statements not allowed"
|
||||||
<< " in program blocks." << endl;
|
<< " in program blocks." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
|
|
@ -2908,10 +2932,3 @@ int pform_parse(const char*path, FILE*file)
|
||||||
destroy_lexor();
|
destroy_lexor();
|
||||||
return error_count;
|
return error_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_error_nested_modules()
|
|
||||||
{
|
|
||||||
assert( pform_cur_module != 0 );
|
|
||||||
cerr << pform_cur_module->get_fileline() << ": error: original module "
|
|
||||||
"(" << pform_cur_module->mod_name() << ") defined here." << endl;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
6
pform.h
6
pform.h
|
|
@ -424,12 +424,6 @@ extern PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc,
|
||||||
*/
|
*/
|
||||||
extern void pform_dump(ostream&out, Module*mod);
|
extern void pform_dump(ostream&out, Module*mod);
|
||||||
|
|
||||||
/*
|
|
||||||
* Used to report the original module location when a nested module
|
|
||||||
* (missing endmodule) is found by the parser.
|
|
||||||
*/
|
|
||||||
extern void pform_error_nested_modules();
|
|
||||||
|
|
||||||
/* ** pform_discipline.cc
|
/* ** pform_discipline.cc
|
||||||
* Functions for handling the parse of natures and disciplines. These
|
* Functions for handling the parse of natures and disciplines. These
|
||||||
* functions are in pform_disciplines.cc
|
* functions are in pform_disciplines.cc
|
||||||
|
|
|
||||||
|
|
@ -1249,6 +1249,11 @@ void Module::dump(ostream&out) const
|
||||||
out << ")" << endl;
|
out << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (map<perm_string,Module*>::const_iterator cur = nested_modules.begin()
|
||||||
|
; cur != nested_modules.end() ; ++cur) {
|
||||||
|
out << setw(4) << "" << "Nested module " << cur->first << ";" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
dump_typedefs_(out, 4);
|
dump_typedefs_(out, 4);
|
||||||
|
|
||||||
dump_parameters_(out, 4);
|
dump_parameters_(out, 4);
|
||||||
|
|
|
||||||
1
t-dll.cc
1
t-dll.cc
|
|
@ -2297,6 +2297,7 @@ void dll_target::scope(const NetScope*net)
|
||||||
|
|
||||||
switch (net->type()) {
|
switch (net->type()) {
|
||||||
case NetScope::MODULE:
|
case NetScope::MODULE:
|
||||||
|
case NetScope::NESTED_MODULE:
|
||||||
scop->type_ = IVL_SCT_MODULE;
|
scop->type_ = IVL_SCT_MODULE;
|
||||||
scop->tname_ = net->module_name();
|
scop->tname_ = net->module_name();
|
||||||
scop->ports = net->module_ports();
|
scop->ports = net->module_ports();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue