Skip to content

Commit

Permalink
Allow modules (and program blocks in particular) to nest.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
steveicarus committed May 28, 2012
1 parent 580c44c commit dfe7bee
Show file tree
Hide file tree
Showing 18 changed files with 218 additions and 148 deletions.
4 changes: 2 additions & 2 deletions Module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
list<Module::named_expr_t> Module::user_defparms;

/* n is a permallocated string. */
Module::Module(perm_string n)
: PScopeExtra(n)
Module::Module(LexicalScope*parent, perm_string n)
: PScopeExtra(n, parent)
{
library_flag = false;
is_cell = false;
Expand Down
6 changes: 5 additions & 1 deletion Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Module : public PScopeExtra, public LineInfo {
public:
/* The name passed here is the module name, not the instance
name. This make must be a permallocated string. */
explicit Module(perm_string name);
explicit Module(LexicalScope*parent, perm_string name);
~Module();

/* Initially false. This is set to true if the module has been
Expand Down Expand Up @@ -121,6 +121,10 @@ class Module : public PScopeExtra, public LineInfo {
the module definition. These are used at elaboration time. */
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;

// The mod_name() is the name of the module type.
Expand Down
10 changes: 8 additions & 2 deletions PGate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,26 @@ const char* PGBuiltin::gate_name() const
}

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)
{
type_ = type;
}

PGModule::PGModule(perm_string type, perm_string name,
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)
{
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()
{
}
Expand Down
4 changes: 4 additions & 0 deletions PGate.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ class PGModule : public PGate {
explicit PGModule(perm_string type, perm_string name,
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();

Expand All @@ -223,6 +226,7 @@ class PGModule : public PGate {
perm_string get_type() const;

private:
Module*bound_type_;
perm_string type_;
list<PExpr*>*overrides_;
named<PExpr*>*pins_;
Expand Down
5 changes: 5 additions & 0 deletions compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ static inline bool gn_system_verilog(void)
return false;
}

static inline bool gn_modules_nest(void)
{
return gn_system_verilog();
}

/* The bits of these GN_KEYWORDS_* constants define non-intersecting
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
Expand Down
2 changes: 1 addition & 1 deletion elab_net.cc
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ NetNet* PEIdent::elaborate_bi_net(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_);
if (sig == 0) {
cerr << get_fileline() << ": error: no wire/reg " << path_
Expand Down
21 changes: 18 additions & 3 deletions elab_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,19 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,

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
// scan all of them to create those scopes.

Expand Down Expand Up @@ -1212,7 +1225,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
continue;
}

if (scn->type() != NetScope::MODULE) continue;
if (! scn->type_is_module()) continue;

if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue;

Expand Down Expand Up @@ -1329,8 +1342,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
<< "." << endl;
}

// Create the new scope as a MODULE with my name.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE);
// Create the new scope as a MODULE with my name. Note
// 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(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
Expand Down
6 changes: 3 additions & 3 deletions elab_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
reg, then report an error. */

if (sig && (sig->scope() == scope)
&& (scope->type() == NetScope::MODULE)
&& (scope->type_is_module())
&& (sig->port_type() == NetNet::PINPUT)
&& (sig->type() == NetNet::REG)) {

Expand All @@ -110,7 +110,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
}

if (sig && (sig->scope() == scope)
&& (scope->type() == NetScope::MODULE)
&& (scope->type_is_module())
&& (sig->port_type() == NetNet::PINOUT)
&& (sig->type() == NetNet::REG)) {

Expand All @@ -122,7 +122,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
}

if (sig && (sig->scope() == scope)
&& (scope->type() == NetScope::MODULE)
&& scope->type_is_module()
&& (sig->port_type() == NetNet::PINOUT)
&& (sig->data_type() == IVL_VT_REAL)) {

Expand Down
20 changes: 18 additions & 2 deletions elaborate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,10 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, 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
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
if (mod != pform_modules.end())
Expand All @@ -2087,6 +2091,11 @@ bool PGModule::elaborate_sig(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
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
if (mod != pform_modules.end()) {
Expand All @@ -2108,10 +2117,16 @@ void PGModule::elaborate(Design*des, NetScope*scope) 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
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
if (mod != pform_modules.end()) {
elaborate_scope_mod_(des, (*mod).second, sc);
elaborate_scope_mod_(des, mod->second, sc);
return;
}

Expand All @@ -2128,7 +2143,7 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
// Try again to find the module type
mod = pform_modules.find(type_);
if (mod != pform_modules.end()) {
elaborate_scope_mod_(des, (*mod).second, sc);
elaborate_scope_mod_(des, mod->second, sc);
return;
}

Expand Down Expand Up @@ -3241,6 +3256,7 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
return 0;

case NetScope::MODULE:
case NetScope::NESTED_MODULE:
cerr << get_fileline() << ": error: Cannot disable modules." << endl;
des->errors += 1;
return 0;
Expand Down
13 changes: 8 additions & 5 deletions net_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ void NetScope::print_type(ostream&stream) const
case FUNC:
stream << "function";
break;
case NESTED_MODULE:
stream << "nested_module <" << (module_name_ ? module_name_.str() : "")
<< "> instance";
case MODULE:
stream << "module <" << (module_name_ ? module_name_.str() : "")
<< "> instance";
Expand Down Expand Up @@ -360,31 +363,31 @@ const NetFuncDef* NetScope::func_def() const

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. */
}

perm_string NetScope::module_name() const
{
assert(type_ == MODULE);
assert(type_ == MODULE || type_ == NESTED_MODULE);
return module_name_;
}

void NetScope::add_module_port(NetNet*port)
{
assert(type_ == MODULE);
assert(type_ == MODULE || type_ == NESTED_MODULE);
ports_.push_back(port);
}

unsigned NetScope::module_ports() const
{
assert(type_ == MODULE);
assert(type_ == MODULE || type_ == NESTED_MODULE);
return ports_.size();
}

NetNet* NetScope::module_port(unsigned idx) const
{
assert(type_ == MODULE);
assert(type_ == MODULE || type_ == NESTED_MODULE);
assert(idx < ports_.size());
return ports_[idx];
}
Expand Down
3 changes: 2 additions & 1 deletion netlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&r
class NetScope : public Attrib {

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
name is expected to have been permallocated. */
Expand Down Expand Up @@ -806,6 +806,7 @@ class NetScope : public Attrib {
const NetScope* child(const hname_t&name) const;

TYPE type() const;
bool type_is_module() const { return type()==MODULE || type()==NESTED_MODULE; }
void print_type(ostream&) const;

void set_task_def(NetTaskDef*);
Expand Down
1 change: 1 addition & 0 deletions nodangle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ void nodangle_f::signal(Design*, NetNet*sig)
if ((sig->port_type() != NetNet::NOT_A_PORT) &&
((sig->scope()->type() == NetScope::TASK) ||
(sig->scope()->type() == NetScope::FUNC) ||
(sig->scope()->type() == NetScope::NESTED_MODULE) ||
(sig->scope()->type() == NetScope::MODULE)))
return;

Expand Down
68 changes: 32 additions & 36 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -3866,43 +3866,46 @@ module_parameter_port_list

module_item

/* Modules can contain further sub-module definitions. */
: module

/* This rule detects net declarations that possibly include a
primitive type, an optional vector range and signed flag. This
also includes an optional delay set. The values are then applied
to a list of names. If the primitive type is not specified, then
resort to the default type LOGIC. */

: attribute_list_opt net_type
primitive_type_opt unsigned_signed_opt range_opt
delay3_opt
net_variable_list ';'
| attribute_list_opt net_type
primitive_type_opt unsigned_signed_opt range_opt
delay3_opt
net_variable_list ';'

{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_makewire(@2, $5, $4, $7, $2, NetNet::NOT_A_PORT, dtype, $1);
if ($6 != 0) {
yyerror(@6, "sorry: net delays not supported.");
delete $6;
}
delete $1;
}

{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_makewire(@2, $5, $4, $7, $2,
NetNet::NOT_A_PORT, dtype, $1);
if ($6 != 0) {
yyerror(@6, "sorry: net delays not supported.");
delete $6;
}
delete $1;
}
| attribute_list_opt K_wreal delay3 net_variable_list ';'
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
if ($3 != 0) {
yyerror(@3, "sorry: net delays not supported.");
delete $3;
}
delete $1;
}

| attribute_list_opt K_wreal delay3 net_variable_list ';'
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
if ($3 != 0) {
yyerror(@3, "sorry: net delays not supported.");
delete $3;
}
delete $1;
}
| attribute_list_opt K_wreal net_variable_list ';'
{ pform_makewire(@2, 0, true, $3, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
delete $1;
}
| attribute_list_opt K_wreal net_variable_list ';'
{ pform_makewire(@2, 0, true, $3, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
delete $1;
}

/* Very similar to the rule above, but this takes a list of
net_decl_assigns, which are <name> = <expr> assignment
Expand Down Expand Up @@ -4248,13 +4251,6 @@ module_item
module items. These rules try to catch them at a point where a
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 ';'
{ yyerror(@2, "error: invalid module item.");
yyerrok;
Expand Down
2 changes: 2 additions & 0 deletions parse_misc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ std::ostream& operator << (std::ostream&o, const YYLTYPE&loc)
{
if (loc.text)
o << loc.text << ":";
else
o << "<>:";
o << loc.first_line;
return o;
}
Expand Down
Loading

0 comments on commit dfe7bee

Please sign in to comment.