Add support for module instance arrays.

This commit is contained in:
steve 2004-09-05 17:44:41 +00:00
parent 62cffe16f4
commit 9de786fc44
7 changed files with 273 additions and 123 deletions

View File

@ -344,9 +344,6 @@ constructs.
- tran primitives, i.e. tran, tranif1, tranif0, rtran, rtranif1
and rtranif0 are not supported.
- Module instance arrays are not supported, although gate instance
arrays do work.
- Net delays, of the form "wire #N foo;" do not work. Delays in
every other context do work properly, including the V2001 form
"wire #5 foo = bar;"

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compiler.h,v 1.22 2004/03/10 04:51:24 steve Exp $"
#ident "$Id: compiler.h,v 1.23 2004/09/05 17:44:41 steve Exp $"
#endif
# include <list>
@ -81,6 +81,8 @@ extern bool warn_portbinding;
/* This is true if verbose output is requested. */
extern bool verbose_flag;
extern bool debug_scopes;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
@ -132,6 +134,9 @@ extern int load_sys_func_table(const char*path);
/*
* $Log: compiler.h,v $
* Revision 1.23 2004/09/05 17:44:41 steve
* Add support for module instance arrays.
*
* Revision 1.22 2004/03/10 04:51:24 steve
* Add support for system function table files.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.33 2004/08/26 04:02:03 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.34 2004/09/05 17:44:41 steve Exp $"
#endif
# include "config.h"
@ -46,6 +46,11 @@
bool Module::elaborate_scope(Design*des, NetScope*scope) const
{
if (debug_scopes) {
cerr << get_line() << ": debug: Elaborate scope "
<< scope->name() << "." << endl;
}
// Generate all the parameters that this instance of this
// module introduces to the design. This loop elaborates the
// parameters, but doesn't evaluate references to
@ -219,7 +224,6 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
// scan all of them to create those scopes.
typedef list<PGate*>::const_iterator gates_it_t;
for (gates_it_t cur = gates_.begin()
; cur != gates_.end() ; cur ++ ) {
@ -305,11 +309,66 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
return;
}
verinum*msb = msb_ ? msb_->eval_const(des, sc) : 0;
verinum*lsb = lsb_ ? lsb_->eval_const(des, sc) : 0;
assert( (msb == 0) || (lsb != 0) );
long instance_low = 0;
long instance_high = 0;
long instance_count = 1;
bool instance_array = false;
if (msb) {
instance_array = true;
instance_high = msb->as_long();
instance_low = lsb->as_long();
if (instance_high > instance_low)
instance_count = instance_high - instance_low + 1;
else
instance_count = instance_low - instance_high + 1;
}
NetScope::scope_vec_t instances (instance_count);
if (debug_scopes) {
cerr << get_line() << ": debug: Create " << instance_count
<< " instances of " << get_name()
<< "." << endl;
}
// Run through the module instances, and make scopes out of
// them. Also do parameter overrides that are done on the
// instantiation line.
for (int idx = 0 ; idx < instance_count ; idx += 1) {
perm_string use_name = get_name();
if (instance_array) {
char name_buf[128];
int instance_idx = idx;
if (instance_low < instance_high)
instance_idx = instance_low + idx;
else
instance_idx = instance_low - idx;
snprintf(name_buf, sizeof name_buf,
"%s[%d]", get_name().str(), instance_idx);
use_name = lex_strings.make(name_buf);
}
if (debug_scopes) {
cerr << get_line() << ": debug: Module instance " << use_name
<< " becomes child of " << sc->name()
<< "." << endl;
}
// Create the new scope as a MODULE with my name.
NetScope*my_scope = new NetScope(sc, get_name(), NetScope::MODULE);
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE);
my_scope->set_module_name(mod->mod_name());
my_scope->default_nettype(mod->default_nettype);
instances[idx] = my_scope;
// Set time units and precision.
my_scope->time_unit(mod->time_unit);
my_scope->time_precision(mod->time_precision);
@ -338,7 +397,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
if (overrides_) {
assert(parms_ == 0);
list<perm_string>::const_iterator cur = mod->param_names.begin();
list<perm_string>::const_iterator cur
= mod->param_names.begin();
unsigned idx = 0;
for (;;) {
if (idx >= overrides_->count())
@ -379,6 +439,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
<< sc->name() << "." << endl;
}
}
}
/* Stash the instance array of scopes into the parent
scope. Later elaboration passes will use this vector to
further elaborate the array. */
sc->instance_arrays[get_name()] = instances;
}
/*
@ -568,6 +634,9 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.34 2004/09/05 17:44:41 steve
* Add support for module instance arrays.
*
* Revision 1.33 2004/08/26 04:02:03 steve
* Add support for localparam ranges.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_sig.cc,v 1.34 2004/05/31 23:34:37 steve Exp $"
#ident "$Id: elab_sig.cc,v 1.35 2004/09/05 17:44:41 steve Exp $"
#endif
# include "config.h"
@ -211,23 +211,31 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
Module*rmod) const
{
// Missing module instance names have already been rejected.
assert(get_name() != "");
if (msb_) {
cerr << get_line() << ": sorry: Module instantiation arrays "
"are not yet supported." << endl;
des->errors += 1;
return false;
}
bool flag = true;
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
// I know a priori that the elaborate_scope created the scope
// already, so just look it up as a child of the current scope.
NetScope*my_scope = scope->child(get_name());
NetScope*my_scope = instance[idx];
assert(my_scope);
return rmod->elaborate_sig(des, my_scope);
if (my_scope->parent() != scope) {
cerr << get_line() << ": internal error: "
<< "Instance " << my_scope->name()
<< " is in parent " << my_scope->parent()->name()
<< " instead of " << scope->name()
<< endl;
}
assert(my_scope->parent() == scope);
if (! rmod->elaborate_sig(des, my_scope))
flag = false;
}
return flag;
}
/*
@ -607,6 +615,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
/*
* $Log: elab_sig.cc,v $
* Revision 1.35 2004/09/05 17:44:41 steve
* Add support for module instance arrays.
*
* Revision 1.34 2004/05/31 23:34:37 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.305 2004/06/30 15:32:02 steve Exp $"
#ident "$Id: elaborate.cc,v 1.306 2004/09/05 17:44:41 steve Exp $"
#endif
# include "config.h"
@ -492,23 +492,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
*/
void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
{
// Missing module instance names have already been rejected.
assert(get_name() != 0);
if (msb_) {
cerr << get_line() << ": sorry: Module instantiation arrays "
"are not yet supported." << endl;
des->errors += 1;
return;
}
assert(scope);
// I know a priori that the elaborate_scope created the scope
// already, so just look it up as a child of the current scope.
NetScope*my_scope = scope->child(get_name());
assert(my_scope);
// This is the array of pin expressions, shuffled to match the
// order of the declaration. If the source instantiation uses
// bind by order, this is the same as the source
@ -589,11 +575,18 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
pins = get_pins();
}
// Elaborate this instance of the module. The recursive
// Elaborate these instances of the module. The recursive
// elaboration causes the module to generate a netlist with
// the ports represented by NetNet objects. I will find them
// later.
rmod->elaborate(des, my_scope);
NetScope::scope_vec_t&instance = scope->instance_arrays[get_name()];
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
rmod->elaborate(des, instance[inst]);
}
// Now connect the ports of the newly elaborated designs to
// the expressions that are the instantiation parameters. Scan
@ -621,7 +614,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (mport.count() == 0)
continue;
NetNet*tmp = des->find_signal(my_scope,
NetNet*tmp = des->find_signal(instance[0],
mport[0]->path());
assert(tmp);
@ -639,36 +632,48 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
}
// Inside the module, the port is zero or more signals
// that were already elaborated. List all those signals
// and the NetNet equivalents.
// and the NetNet equivalents, for all the instances.
svector<PEIdent*> mport = rmod->get_port(idx);
svector<NetNet*>prts (mport.count());
svector<NetNet*>prts (mport.count() * instance.count());
// Count the internal pins of the port.
unsigned prts_pin_count = 0;
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
NetScope*inst_scope = instance[inst];
// Scan the module sub-ports for this instance...
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
unsigned lbase = inst * mport.count();
PEIdent*pport = mport[ldx];
assert(pport);
prts[ldx] = pport->elaborate_port(des, my_scope);
if (prts[ldx] == 0)
prts[lbase + ldx]
= pport->elaborate_port(des, inst_scope);
if (prts[lbase + ldx] == 0)
continue;
assert(prts[ldx]);
prts_pin_count += prts[ldx]->pin_count();
assert(prts[lbase + ldx]);
prts_pin_count += prts[lbase + ldx]->pin_count();
}
}
// If I find that the port in unconnected inside the
// module, then there is nothing to connect. Skip the
// parameter.
// argument.
if (prts_pin_count == 0) {
continue;
}
// Elaborate the expression that connects to the module
// port. sig is the thing outside the module that
// connects to the port.
// We know by design that each instance has the same
// width port. Therefore, the prts_pin_count must be an
// even multiple of the instance count.
assert(prts_pin_count % instance.count() == 0);
// Elaborate the expression that connects to the
// module[s] port. sig is the thing outside the module
// that connects to the port.
NetNet*sig;
if ((prts.count() >= 1)
@ -687,8 +692,17 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
}
} else {
/* Input to module. elaborate the expression to
the desired width. If this in an instance
array, then let the net determine it's own
width. We use that, then, to decide how to hook
it up. */
unsigned desired_pin_count = prts_pin_count;
if (instance.count() != 1)
desired_pin_count = 0;
sig = pins[idx]->elaborate_net(des, scope,
prts_pin_count,
desired_pin_count,
0, 0, 0);
if (sig == 0) {
cerr << pins[idx]->get_line()
@ -707,10 +721,25 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
}
#endif
/* If we are working with an instance array, then the
signal width must match the port width exactly. */
if ((instance.count() != 1)
&& (sig->pin_count() != prts_pin_count)
&& (sig->pin_count() != prts_pin_count/instance.count())) {
cerr << pins[idx]->get_line() << ": error: "
<< "Port expression width " << sig->pin_count()
<< " does not match expected width " << prts_pin_count
<< " or " << (prts_pin_count/instance.count())
<< "." << endl;
des->errors += 1;
continue;
}
// Check that the parts have matching pin counts. If
// not, they are different widths. Note that idx is 0
// based, but users count parameter positions from 1.
if (prts_pin_count != sig->pin_count()) {
if ((instance.count() == 1)
&& (prts_pin_count != sig->pin_count())) {
cerr << get_line() << ": warning: Port " << (idx+1)
<< " (" << rmod->ports[idx]->name << ") of "
<< type_ << " expects " << prts_pin_count <<
@ -741,9 +770,17 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// Connect this many of the port pins. If the expression
// is too small, the reduce the number of connects.
unsigned ccount = prts_pin_count;
if (sig->pin_count() < ccount)
if (instance.count() == 1 && sig->pin_count() < ccount)
ccount = sig->pin_count();
// The spin_modulus is the width of the signal (not the
// port) if this is an instance array. This causes
// signals wide enough for a single instance to be
// connected to all the instances.
unsigned spin_modulus = prts_pin_count;
if (instance.count() != 1)
spin_modulus = sig->pin_count();
// Now scan the concatenation that makes up the port,
// connecting pins until we run out of port pins or sig
// pins.
@ -754,7 +791,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (cnt > ccount)
cnt = ccount;
for (unsigned p = 0 ; p < cnt ; p += 1) {
connect(sig->pin(spin), prts[ldx-1]->pin(p));
connect(sig->pin(spin%spin_modulus),
prts[ldx-1]->pin(p));
ccount -= 1;
spin += 1;
}
@ -766,6 +804,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(sig))
delete tmp;
}
}
/*
@ -2720,6 +2759,9 @@ Design* elaborate(list<perm_string>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.306 2004/09/05 17:44:41 steve
* Add support for module instance arrays.
*
* Revision 1.305 2004/06/30 15:32:02 steve
* Propagate source line number in synthetic delay statements.
*

20
main.cc
View File

@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.82 2004/03/10 04:51:24 steve Exp $"
#ident "$Id: main.cc,v 1.83 2004/09/05 17:44:42 steve Exp $"
#endif
# include "config.h"
@ -106,6 +106,11 @@ bool warn_portbinding = false;
bool error_implicit = false;
/*
* Debug message class flags.
*/
bool debug_scopes = false;
/*
* Verbose messages enabled.
*/
@ -228,6 +233,9 @@ static void parm_to_flagmap(const string&flag)
* basedir:<path>
* Location to look for installed sub-components
*
* debug:<name>
* Activate a class of debug messages.
*
* depfile:<path>
* Give the path to an output dependency file.
*
@ -295,6 +303,13 @@ static void read_iconfig_file(const char*ipath)
if (strcmp(buf, "basedir") == 0) {
basedir = strdup(cp);
} else if (strcmp(buf, "debug") == 0) {
if (strcmp(cp, "scope") == 0) {
debug_scopes = true;
cerr << "debug: Enable scope debug" << endl;
} else {
}
} else if (strcmp(buf, "depfile") == 0) {
depfile_name = strdup(cp);
@ -722,6 +737,9 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.83 2004/09/05 17:44:42 steve
* Add support for module instance arrays.
*
* Revision 1.82 2004/03/10 04:51:24 steve
* Add support for system function table files.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.318 2004/09/04 04:24:15 steve Exp $"
#ident "$Id: netlist.h,v 1.319 2004/09/05 17:44:42 steve Exp $"
#endif
/*
@ -3168,6 +3168,11 @@ class NetScope : public Attrib {
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
/* Module instance arrays are collected here for access during
the multiple elaboration passes. */
typedef svector<NetScope*> scope_vec_t;
map<perm_string, scope_vec_t>instance_arrays;
private:
TYPE type_;
perm_string name_;
@ -3356,6 +3361,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.319 2004/09/05 17:44:42 steve
* Add support for module instance arrays.
*
* Revision 1.318 2004/09/04 04:24:15 steve
* PR1026: assignment statements can have sensitivities in the l-values.
*