Add support for generate loops w/ wires and gates.

This commit is contained in:
steve 2006-04-10 00:37:42 +00:00
parent decfbff2b1
commit f001d0001a
19 changed files with 567 additions and 114 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.174 2006/02/15 18:42:42 steve Exp $" #ident "$Id: Makefile.in,v 1.175 2006/04/10 00:37:42 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -111,7 +111,7 @@ parse.o parse_misc.o pform.o pform_dump.o \
set_width.o symbol_search.o sync.o sys_funcs.o \ set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \ verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \ Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o \ PExpr.o PGate.o PGenerate.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \ PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT) $(FF) $(TT)

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: Module.h,v 1.39 2006/03/30 01:49:07 steve Exp $" #ident "$Id: Module.h,v 1.40 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include <list> # include <list>
@ -34,6 +34,7 @@ class PEvent;
class PExpr; class PExpr;
class PEIdent; class PEIdent;
class PGate; class PGate;
class PGenerate;
class PTask; class PTask;
class PFunction; class PFunction;
class PWire; class PWire;
@ -113,6 +114,14 @@ class Module : public LineInfo {
set by the `timescale directive. */ set by the `timescale directive. */
int time_unit, time_precision; int time_unit, time_precision;
/* The module has a list of genvars that may be used in
various generate schemes. */
list<perm_string> genvars;
/* the module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
perm_string mod_name() const { return name_; } perm_string mod_name() const { return name_; }
void add_gate(PGate*gate); void add_gate(PGate*gate);
@ -164,51 +173,13 @@ class Module : public LineInfo {
/* /*
* $Log: Module.h,v $ * $Log: Module.h,v $
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.39 2006/03/30 01:49:07 steve * Revision 1.39 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters. * Fix instance arrays indexed by overridden parameters.
* *
* Revision 1.38 2005/07/11 16:56:50 steve * Revision 1.38 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures. * Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.37 2004/06/13 04:56:53 steve
* Add support for the default_nettype directive.
*
* Revision 1.36 2004/05/25 19:21:06 steve
* More identifier lists use perm_strings.
*
* Revision 1.35 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.34 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
* Revision 1.33 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.32 2003/06/20 00:53:19 steve
* Module attributes from the parser
* through to elaborated form.
*
* Revision 1.31 2003/06/13 19:10:45 steve
* Properly manage real variables in subscopes.
*
* Revision 1.30 2003/03/06 04:37:12 steve
* lex_strings.add module names earlier.
*
* Revision 1.29 2003/02/27 06:45:11 steve
* specparams as far as pform.
*
* Revision 1.28 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.27 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
* Revision 1.26 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.25 2002/05/19 23:37:28 steve
* Parse port_declaration_lists from the 2001 Standard.
*/ */
#endif #endif

13
PGate.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.h,v 1.31 2006/01/03 05:22:14 steve Exp $" #ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "svector.h" # include "svector.h"
@ -94,7 +94,7 @@ class PGate : public LineInfo {
map<perm_string,PExpr*> attributes; map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out) const; virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const; virtual void elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const; virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -128,7 +128,7 @@ class PGAssign : public PGate {
explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels); explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels);
~PGAssign(); ~PGAssign();
void dump(ostream&out) const; void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const; virtual void elaborate(Design*des, NetScope*scope) const;
private: private:
@ -165,7 +165,7 @@ class PGBuiltin : public PGate {
Type type() const { return type_; } Type type() const { return type_; }
void set_range(PExpr*msb, PExpr*lsb); void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out) const; virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const; virtual void elaborate(Design*, NetScope*scope) const;
private: private:
@ -208,7 +208,7 @@ class PGModule : public PGate {
// method to pass the range to the pform. // method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb); void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out) const; virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const; virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const; virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -239,6 +239,9 @@ class PGModule : public PGate {
/* /*
* $Log: PGate.h,v $ * $Log: PGate.h,v $
* Revision 1.32 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.31 2006/01/03 05:22:14 steve * Revision 1.31 2006/01/03 05:22:14 steve
* Handle complex net node delays. * Handle complex net node delays.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.h,v 1.18 2005/07/07 16:22:49 steve Exp $" #ident "$Id: PWire.h,v 1.19 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -81,7 +81,7 @@ class PWire : public LineInfo {
map<perm_string,PExpr*> attributes; map<perm_string,PExpr*> attributes;
// Write myself to the specified stream. // Write myself to the specified stream.
void dump(ostream&out) const; void dump(ostream&out, unsigned ind=4) const;
void elaborate_sig(Design*, NetScope*scope) const; void elaborate_sig(Design*, NetScope*scope) const;
@ -110,6 +110,9 @@ class PWire : public LineInfo {
/* /*
* $Log: PWire.h,v $ * $Log: PWire.h,v $
* Revision 1.19 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.18 2005/07/07 16:22:49 steve * Revision 1.18 2005/07/07 16:22:49 steve
* Generalize signals to carry types. * Generalize signals to carry types.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.164 2006/02/02 02:43:57 steve Exp $" #ident "$Id: design_dump.cc,v 1.165 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -811,6 +811,9 @@ void NetScope::dump(ostream&o) const
case TASK: case TASK:
o << " task"; o << " task";
break; break;
case GENBLOCK:
o << " generate block";
break;
} }
o << endl; o << endl;
@ -1170,6 +1173,9 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $Log: design_dump.cc,v $
* Revision 1.165 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.164 2006/02/02 02:43:57 steve * Revision 1.164 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values. * Allow part selects of memory words in l-values.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.38 2006/03/30 01:49:07 steve Exp $" #ident "$Id: elab_scope.cc,v 1.39 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -37,6 +37,7 @@
# include "PEvent.h" # include "PEvent.h"
# include "PExpr.h" # include "PExpr.h"
# include "PGate.h" # include "PGate.h"
# include "PGenerate.h"
# include "PTask.h" # include "PTask.h"
# include "PWire.h" # include "PWire.h"
# include "Statement.h" # include "Statement.h"
@ -220,6 +221,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
delete[]attr; delete[]attr;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
// Tasks introduce new scopes, so scan the tasks in this // Tasks introduce new scopes, so scan the tasks in this
// module. Create a scope for the task and pass that to the // module. Create a scope for the task and pass that to the
@ -289,6 +301,101 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
return des->errors == 0; return des->errors == 0;
} }
bool PGenerate::generate_scope(Design*des, NetScope*container)
{
switch (scheme_type) {
case GS_LOOP:
return generate_scope_loop_(des, container);
default:
cerr << get_line() << ": sorry: Generate of this sort"
<< " is not supported yet!" << endl;
return false;
}
}
/*
* This is the elaborate scope method for a generate loop.
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// We're going to need a genvar...
int genvar;
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other paramter value is evaluated.
NetExpr*init_ex = elab_and_eval(des, container, loop_init);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
cerr << get_line() << ": error: Cannot evaluate genvar"
<< " init expression: " << *loop_init << endl;
des->errors += 1;
return false;
}
genvar = init->value().as_long();
delete init_ex;
if (debug_elaborate)
cerr << get_line() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = 0;
verinum*test = loop_test->eval_const(des, container);
assert(test);
while (test->as_long()) {
// The actual name of the scope includes the genvar so
// that each instance has a unique name in the
// container. The format of using [] is part of the
// Verilog standard.
char name_buf[128];
snprintf(name_buf, sizeof name_buf,
"%s[%d]", scope_name.str(), genvar);
perm_string use_name = lex_strings.make(name_buf);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Create generated scope " << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
// block. Code within this scope thus has access to the
// genvar as a constant.
{
verinum genvar_verinum(genvar);
genvar_verinum.has_sign(true);
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
genvar_verinum);
scope->set_localparam(loop_index, gp);
}
scope_list_.push_back(scope);
// Calculate the step for the loop variable.
verinum*step = loop_step->eval_const(des, container);
assert(step);
if (debug_elaborate)
cerr << get_line() << ": debug: genvar step from "
<< genvar << " to " << step->as_long() << endl;
genvar = step->as_long();
container->genvar_tmp_val = genvar;
delete step;
delete test;
test = loop_test->eval_const(des, container);
}
container->genvar_tmp = perm_string();
return true;
}
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
{ {
if (get_name() == "") { if (get_name() == "") {
@ -635,6 +742,9 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/* /*
* $Log: elab_scope.cc,v $ * $Log: elab_scope.cc,v $
* Revision 1.39 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.38 2006/03/30 01:49:07 steve * Revision 1.38 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters. * Fix instance arrays indexed by overridden parameters.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_sig.cc,v 1.40 2005/07/11 16:56:50 steve Exp $" #ident "$Id: elab_sig.cc,v 1.41 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -27,6 +27,7 @@
# include "Module.h" # include "Module.h"
# include "PExpr.h" # include "PExpr.h"
# include "PGate.h" # include "PGate.h"
# include "PGenerate.h"
# include "PTask.h" # include "PTask.h"
# include "PWire.h" # include "PWire.h"
# include "compiler.h" # include "compiler.h"
@ -158,6 +159,16 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
des->errors += 1; des->errors += 1;
} }
}
// Run through all the generate schemes to enaborate the
// signals that they hold. Note that the generate schemes hold
// the scopes that they instantiated, so we don't pass any
// scope in.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> elaborate_sig(des);
} }
// Get all the gates of the module and elaborate them by // Get all the gates of the module and elaborate them by
@ -238,6 +249,44 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
return flag; return flag;
} }
bool PGenerate::elaborate_sig(Design*des) const
{
bool flag = true;
typedef list<NetScope*>::const_iterator scope_list_it_t;
for (scope_list_it_t cur = scope_list_.begin()
; cur != scope_list_.end() ; cur ++ ) {
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate nets in "
<< "scope " << (*cur)->name() << endl;
flag = elaborate_sig_(des, *cur) & flag;
}
return flag;
}
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
// in the current scope.
typedef map<hname_t,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
PWire*cur = (*wt).second;
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate PWire "
<< cur->path() << " in scope " << scope->name() << endl;
cur->elaborate_sig(des, scope);
}
return true;
}
/* /*
* A function definition exists within an elaborated module. This * A function definition exists within an elaborated module. This
* matters when elaborating signals, as the ports of the function are * matters when elaborating signals, as the ports of the function are
@ -671,6 +720,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
/* /*
* $Log: elab_sig.cc,v $ * $Log: elab_sig.cc,v $
* Revision 1.41 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.40 2005/07/11 16:56:50 steve * Revision 1.40 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures. * Remove NetVariable and ivl_variable_t structures.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.335 2006/03/30 01:49:07 steve Exp $" #ident "$Id: elaborate.cc,v 1.336 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -34,6 +34,7 @@
# include <list> # include <list>
# include "pform.h" # include "pform.h"
# include "PEvent.h" # include "PEvent.h"
# include "PGenerate.h"
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
# include "util.h" # include "util.h"
@ -2846,6 +2847,12 @@ bool Module::elaborate(Design*des, NetScope*scope) const
{ {
bool result_flag = true; bool result_flag = true;
// Elaborate within the generate blocks.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur)->elaborate(des);
}
// Elaborate functions. // Elaborate functions.
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t; typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
@ -2966,6 +2973,35 @@ bool Module::elaborate(Design*des, NetScope*scope) const
return result_flag; return result_flag;
} }
bool PGenerate::elaborate(Design*des) const
{
bool flag = true;
typedef list<NetScope*>::const_iterator scope_list_it_t;
for (scope_list_it_t cur = scope_list_.begin()
; cur != scope_list_.end() ; cur ++ ) {
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate in "
<< "scope " << (*cur)->name() << endl;
flag = elaborate_(des, *cur) & flag;
}
return flag;
}
bool PGenerate::elaborate_(Design*des, NetScope*scope) const
{
typedef list<PGate*>::const_iterator gates_it_t;
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ ) {
(*cur)->elaborate(des, scope);
}
return true;
}
struct root_elem { struct root_elem {
Module *mod; Module *mod;
NetScope *scope; NetScope *scope;
@ -2981,6 +3017,7 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find. // module and elaborate what I find.
Design*des = new Design; Design*des = new Design;
// Scan the root modules, and elaborate their scopes.
for (list<perm_string>::const_iterator root = roots.begin() for (list<perm_string>::const_iterator root = roots.begin()
; root != roots.end() ; root != roots.end()
; root++) { ; root++) {
@ -2996,6 +3033,7 @@ Design* elaborate(list<perm_string>roots)
continue; continue;
} }
// Get the module definition for this root instance.
Module *rmod = (*mod).second; Module *rmod = (*mod).second;
// Make the root scope. // Make the root scope.
@ -3006,7 +3044,9 @@ Design* elaborate(list<perm_string>roots)
des->set_precision(rmod->time_precision); des->set_precision(rmod->time_precision);
Module::replace_t stub; Module::replace_t stub;
// Recursively elaborate from this root scope down.
// Recursively elaborate from this root scope down. This
// does a lot of the grunt work of creating sub-scopes, etc.
if (! rmod->elaborate_scope(des, scope, stub)) { if (! rmod->elaborate_scope(des, scope, stub)) {
delete des; delete des;
return 0; return 0;
@ -3071,6 +3111,9 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.336 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.335 2006/03/30 01:49:07 steve * Revision 1.335 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters. * Fix instance arrays indexed by overridden parameters.
* *

15
eval.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: eval.cc,v 1.39 2005/12/07 04:04:23 steve Exp $" #ident "$Id: eval.cc,v 1.40 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -168,11 +168,19 @@ verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
{ {
assert(scope); assert(scope);
//const NetExpr*expr = des->find_parameter(scope, path_);
NetNet*net; NetNet*net;
NetMemory*mem; NetMemory*mem;
NetEvent*eve; NetEvent*eve;
const NetExpr*expr; const NetExpr*expr;
// Handle the special case that this ident is a genvar
// variable name. In that case, the genvar meaning preempts
// everything and we just return that value immediately.
if (scope->genvar_tmp
&& strcmp(path_.peek_tail_name(),scope->genvar_tmp) == 0) {
return new verinum(scope->genvar_tmp_val);
}
NetScope*found_in = symbol_search(des, scope, path_, NetScope*found_in = symbol_search(des, scope, path_,
net, mem, expr, eve); net, mem, expr, eve);
@ -263,6 +271,9 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
/* /*
* $Log: eval.cc,v $ * $Log: eval.cc,v $
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.39 2005/12/07 04:04:23 steve * Revision 1.39 2005/12/07 04:04:23 steve
* Allow constant concat expressions. * Allow constant concat expressions.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.165 2006/02/02 02:43:58 steve Exp $" #ident "$Id: ivl_target.h,v 1.166 2006/04/10 00:37:42 steve Exp $"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -266,7 +266,8 @@ typedef enum ivl_scope_type_e {
IVL_SCT_FUNCTION= 1, IVL_SCT_FUNCTION= 1,
IVL_SCT_TASK = 2, IVL_SCT_TASK = 2,
IVL_SCT_BEGIN = 3, IVL_SCT_BEGIN = 3,
IVL_SCT_FORK = 4 IVL_SCT_FORK = 4,
IVL_SCT_GENERATE= 5
} ivl_scope_type_t; } ivl_scope_type_t;
/* Signals (ivl_signal_t) that are ports into the scope that contains /* Signals (ivl_signal_t) that are ports into the scope that contains
@ -1707,6 +1708,9 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $Log: ivl_target.h,v $
* Revision 1.166 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.165 2006/02/02 02:43:58 steve * Revision 1.165 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values. * Allow part selects of memory words in l-values.
* *

View File

@ -31,6 +31,7 @@ else, K_else
end, K_end end, K_end
endcase, K_endcase endcase, K_endcase
endfunction, K_endfunction endfunction, K_endfunction
endgenerate, K_endgenerate
endmodule, K_endmodule endmodule, K_endmodule
endprimitive, K_endprimitive endprimitive, K_endprimitive
endspecify, K_endspecify endspecify, K_endspecify
@ -42,6 +43,8 @@ force, K_force
forever, K_forever forever, K_forever
fork, K_fork fork, K_fork
function, K_function function, K_function
generate, K_generate
genvar, K_genvar
highz0, K_highz0 highz0, K_highz0
highz1, K_highz1 highz1, K_highz1
if, K_if if, K_if

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.356 2006/03/18 22:53:04 steve Exp $" #ident "$Id: netlist.h,v 1.357 2006/04/10 00:37:42 steve Exp $"
#endif #endif
/* /*
@ -3137,7 +3137,7 @@ class NetESignal : public NetExpr {
class NetScope : public Attrib { class NetScope : public Attrib {
public: public:
enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN }; enum TYPE { 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. */
@ -3281,6 +3281,12 @@ class NetScope : public Attrib {
typedef svector<NetScope*> scope_vec_t; typedef svector<NetScope*> scope_vec_t;
map<perm_string, scope_vec_t>instance_arrays; map<perm_string, scope_vec_t>instance_arrays;
/* Loop generate uses this as scratch space during
elaboration. Expression evaluation can use this to match
names. */
perm_string genvar_tmp;
long genvar_tmp_val;
private: private:
TYPE type_; TYPE type_;
perm_string name_; perm_string name_;
@ -3458,6 +3464,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.357 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.356 2006/03/18 22:53:04 steve * Revision 1.356 2006/03/18 22:53:04 steve
* Properly handle signedness in compare. * Properly handle signedness in compare.
* *

43
parse.y
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.212 2006/03/30 05:22:34 steve Exp $" #ident "$Id: parse.y,v 1.213 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -137,9 +137,10 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER %token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case %token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable %token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
%token K_edge K_else K_end K_endcase K_endfunction K_endmodule %token K_edge K_else K_end K_endcase K_endfunction K_endgenerate K_endmodule
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for %token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
%token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if %token K_force K_forever K_fork K_function K_generate K_genvar
%token K_highz0 K_highz1 K_if
%token K_initial K_inout K_input K_integer K_join K_large K_localparam %token K_initial K_inout K_input K_integer K_join K_large K_localparam
%token K_logic K_macromodule %token K_logic K_macromodule
%token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0 %token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0
@ -1807,6 +1808,27 @@ module_item
delete $3; delete $3;
} }
/* A generate region can contain further module items. Actually, it
is supposed to be limited to certain kinds of module items, but
the semantic tests will check that for us. */
| K_generate module_item_list_opt K_endgenerate
| K_genvar list_of_identifiers ';'
{ pform_genvars($2); }
| K_for '(' IDENTIFIER '=' expression ';'
expression ';'
IDENTIFIER '=' expression ')'
{ pform_start_generate_for(@1, $3, $5, $7, $9, $11); }
generate_block
{ pform_endgenerate(); }
| K_if '(' expression ')' generate_block_opt K_else generate_block
{ yyerror(@1, "sorry: Condition generate not supported yet.");
}
/* specify blocks are parsed but ignored. */ /* specify blocks are parsed but ignored. */
| K_specify K_endspecify | K_specify K_endspecify
@ -1873,6 +1895,21 @@ module_item_list_opt
| |
; ;
/* A generate block is the thing within a generate scheme. It may be
a single module item, an anonymous block of module items, or a
named module item. In all cases, the meat is in the module items
inside, and the processing is done by the module_item rules. We
only need to take note here of the scope name, if any. */
generate_block
: module_item
| K_begin module_item_list_opt K_end
| K_begin ':' IDENTIFIER module_item_list_opt K_end
{ pform_generate_block_name($3); }
;
generate_block_opt : generate_block | ;
/* A net declaration assignment allows the programmer to combine the /* A net declaration assignment allows the programmer to combine the
net declaration and the continuous assignment into a single net declaration and the continuous assignment into a single

130
pform.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.134 2006/03/30 05:22:34 steve Exp $" #ident "$Id: pform.cc,v 1.135 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -28,6 +28,7 @@
# include "parse_api.h" # include "parse_api.h"
# include "PEvent.h" # include "PEvent.h"
# include "PUdp.h" # include "PUdp.h"
# include "PGenerate.h"
# include <list> # include <list>
# include <map> # include <map>
# include <assert.h> # include <assert.h>
@ -44,7 +45,17 @@ string vl_file = "";
extern int VLparse(); extern int VLparse();
/* This tracks the current module being processed. There can only be
exactly one module currently being parsed, since verilog does not
allow nested module definitions. */
static Module*pform_cur_module = 0; static Module*pform_cur_module = 0;
/* increment this for generate schemes within a module, and set it
to zero when a new module starts. */
static unsigned scope_generate_counter = 1;
/* This tracks the current generate scheme being processed. This is
always within a module. */
static PGenerate*pform_cur_generate = 0;
static NetNet::Type pform_default_nettype = NetNet::WIRE; static NetNet::Type pform_default_nettype = NetNet::WIRE;
@ -63,10 +74,13 @@ static unsigned pform_timescale_line = 0;
* of scope. As I enter a scope, the push function is called, and as I * of scope. As I enter a scope, the push function is called, and as I
* leave a scope the pop function is called. Entering tasks, functions * leave a scope the pop function is called. Entering tasks, functions
* and named blocks causes scope to be pushed and popped. The module * and named blocks causes scope to be pushed and popped. The module
* name is not included it this scope stack. * name is not included in this scope stack.
* *
* The hier_name function, therefore, returns the name path of a * The hier_name function, therefore, converts the name to the scope
* function relative the current function. * of the module currently in progress.
*
* The scope stack does not include any scope created by a generate
* scheme.
*/ */
static hname_t scope_stack; static hname_t scope_stack;
@ -90,6 +104,18 @@ static hname_t hier_name(const char*tail)
return name; return name;
} }
static PWire*get_wire_in_module(const hname_t&name)
{
/* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes
cannot be within sub-scopes. Only directly in
modules. */
if (pform_cur_generate)
return pform_cur_generate->get_wire(name);
return pform_cur_module->get_wire(name);
}
void pform_set_default_nettype(NetNet::Type type, void pform_set_default_nettype(NetNet::Type type,
const char*file, unsigned lineno) const char*file, unsigned lineno)
{ {
@ -216,6 +242,10 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
pform_cur_module->set_file(file); pform_cur_module->set_file(file);
pform_cur_module->set_lineno(lineno); pform_cur_module->set_lineno(lineno);
/* The generate scheme numbering starts with *1*, not
zero. That's just the way it is, thanks to the standard. */
scope_generate_counter = 1;
if (warn_timescale && pform_timescale_file if (warn_timescale && pform_timescale_file
&& (strcmp(pform_timescale_file,file) != 0)) { && (strcmp(pform_timescale_file,file) != 0)) {
@ -292,6 +322,58 @@ void pform_endmodule(const char*name)
pform_cur_module = 0; pform_cur_module = 0;
} }
void pform_genvars(list<perm_string>*names)
{
list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) {
pform_cur_module->genvars.push_back( *cur );
}
delete names;
}
void pform_start_generate_for(const struct vlltype&li,
char*ident1, PExpr*init,
PExpr*test,
char*ident2, PExpr*next)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
gen->set_file(li.text);
gen->set_lineno(li.first_line);
// For now, assume that generates do not nest.
assert(pform_cur_generate == 0);
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
pform_cur_generate->loop_index = lex_strings.make(ident1);
pform_cur_generate->loop_init = init;
pform_cur_generate->loop_test = test;
pform_cur_generate->loop_step = next;
delete[]ident1;
delete[]ident2;
}
void pform_generate_block_name(char*name)
{
assert(pform_cur_generate != 0);
assert(pform_cur_generate->scope_name == 0);
pform_cur_generate->scope_name = lex_strings.make(name);
delete[]name;
}
void pform_endgenerate()
{
assert(pform_cur_generate != 0);
assert(pform_cur_module);
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
pform_cur_generate = 0;
}
bool pform_expression_is_constant(const PExpr*ex) bool pform_expression_is_constant(const PExpr*ex)
{ {
return ex->is_constant(pform_cur_module); return ex->is_constant(pform_cur_module);
@ -695,8 +777,7 @@ static void pform_set_net_range(const char* name,
bool signed_flag, bool signed_flag,
ivl_variable_type_t dt) ivl_variable_type_t dt)
{ {
PWire*cur = get_wire_in_module(hier_name(name));
PWire*cur = pform_cur_module->get_wire(hier_name(name));
if (cur == 0) { if (cur == 0) {
VLerror("error: name is not a valid net."); VLerror("error: name is not a valid net.");
return; return;
@ -796,6 +877,9 @@ void pform_makegate(PGBuiltin::Type type,
cur->set_file(info.file); cur->set_file(info.file);
cur->set_lineno(info.lineno); cur->set_lineno(info.lineno);
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur); pform_cur_module->add_gate(cur);
} }
@ -854,6 +938,9 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order); cur->set_parameters(overrides->by_order);
} }
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur); pform_cur_module->add_gate(cur);
} }
@ -956,7 +1043,11 @@ static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
cur->strength0(str.str0); cur->strength0(str.str0);
cur->strength1(str.str1); cur->strength1(str.str1);
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur); pform_cur_module->add_gate(cur);
return cur; return cur;
} }
@ -1089,13 +1180,22 @@ void pform_module_define_port(const struct vlltype&li,
* do check to see if the name has already been declared, as this * do check to see if the name has already been declared, as this
* function is called for every declaration. * function is called for every declaration.
*/ */
/*
* this is the basic form of pform_makwire. This takes a single simple
* name, port type, net type, data type, and attributes, and creates
* the variable/net. Other forms of pform_makewire ultimately call
* this one to create the wire and stash it.
*/
void pform_makewire(const vlltype&li, const char*nm, void pform_makewire(const vlltype&li, const char*nm,
NetNet::Type type, NetNet::PortType pt, NetNet::Type type, NetNet::PortType pt,
ivl_variable_type_t dt, ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr) svector<named_pexpr_t*>*attr)
{ {
hname_t name = hier_name(nm); hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
PWire*cur = get_wire_in_module(name);
if (cur) { if (cur) {
if ((cur->get_wire_type() != NetNet::IMPLICIT) if ((cur->get_wire_type() != NetNet::IMPLICIT)
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) { && (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
@ -1130,9 +1230,17 @@ void pform_makewire(const vlltype&li, const char*nm,
} }
} }
if (pform_cur_generate)
pform_cur_generate->add_wire(cur);
else
pform_cur_module->add_wire(cur); pform_cur_module->add_wire(cur);
} }
/*
* This form takes a list of names and some type information, and
* generates a bunch of variables/nets. We hse the basic
* pform_makewire above.
*/
void pform_makewire(const vlltype&li, void pform_makewire(const vlltype&li,
svector<PExpr*>*range, svector<PExpr*>*range,
bool signed_flag, bool signed_flag,
@ -1155,6 +1263,9 @@ void pform_makewire(const vlltype&li,
delete range; delete range;
} }
/*
* This form makes nets with delays and continuous assignments.
*/
void pform_makewire(const vlltype&li, void pform_makewire(const vlltype&li,
svector<PExpr*>*range, svector<PExpr*>*range,
bool signed_flag, bool signed_flag,
@ -1174,7 +1285,7 @@ void pform_makewire(const vlltype&li,
pform_set_net_range(first->name, range, signed_flag, dt); pform_set_net_range(first->name, range, signed_flag, dt);
hname_t name = hier_name(first->name); hname_t name = hier_name(first->name);
PWire*cur = pform_cur_module->get_wire(name); PWire*cur = get_wire_in_module(name);
if (cur != 0) { if (cur != 0) {
PEIdent*lval = new PEIdent(hname_t(first->name)); PEIdent*lval = new PEIdent(hname_t(first->name));
lval->set_file(li.text); lval->set_file(li.text);
@ -1596,6 +1707,9 @@ int pform_parse(const char*path, FILE*file)
/* /*
* $Log: pform.cc,v $ * $Log: pform.cc,v $
* Revision 1.135 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.134 2006/03/30 05:22:34 steve * Revision 1.134 2006/03/30 05:22:34 steve
* task/function ports can have types. * task/function ports can have types.
* *

21
pform.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.85 2006/03/30 05:22:34 steve Exp $" #ident "$Id: pform.h,v 1.86 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -167,6 +167,22 @@ extern void pform_pop_scope();
extern verinum* pform_verinum_with_size(verinum*s, verinum*val, extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
const char*file, unsigned loneno); const char*file, unsigned loneno);
/*
* This function takes the list of names as new genvars to declare in
* the current module scope.
*/
extern void pform_genvars(list<perm_string>*names);
extern void pform_start_generate_for(const struct vlltype&li,
char*ident1,
PExpr*init,
PExpr*test,
char*ident2,
PExpr*next);
extern void pform_generate_block_name(char*name);
extern void pform_endgenerate();
/* /*
* The makewire functions announce to the pform code new wires. These * The makewire functions announce to the pform code new wires. These
* go into a module that is currently opened. * go into a module that is currently opened.
@ -307,6 +323,9 @@ extern void pform_dump(ostream&out, Module*mod);
/* /*
* $Log: pform.h,v $ * $Log: pform.h,v $
* Revision 1.86 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.85 2006/03/30 05:22:34 steve * Revision 1.85 2006/03/30 05:22:34 steve
* task/function ports can have types. * task/function ports can have types.
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.91 2005/10/04 04:09:26 steve Exp $" #ident "$Id: pform_dump.cc,v 1.92 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -30,6 +30,7 @@
*/ */
# include "pform.h" # include "pform.h"
# include "PEvent.h" # include "PEvent.h"
# include "PGenerate.h"
# include <iostream> # include <iostream>
# include <iomanip> # include <iomanip>
# include <typeinfo> # include <typeinfo>
@ -211,9 +212,9 @@ void PEBinary::dump(ostream&out) const
} }
void PWire::dump(ostream&out) const void PWire::dump(ostream&out, unsigned ind) const
{ {
out << " " << type_; out << setw(ind) << "" << type_;
switch (port_type_) { switch (port_type_) {
case NetNet::PIMPLICIT: case NetNet::PIMPLICIT:
@ -303,9 +304,9 @@ void PGate::dump_delays(ostream&out) const
delay_.dump_delays(out); delay_.dump_delays(out);
} }
void PGate::dump(ostream&out) const void PGate::dump(ostream&out, unsigned ind) const
{ {
out << " " << typeid(*this).name() << " "; out << setw(ind) << "" << typeid(*this).name() << " ";
delay_.dump_delays(out); delay_.dump_delays(out);
out << " " << get_name() << "("; out << " " << get_name() << "(";
dump_pins(out); dump_pins(out);
@ -313,45 +314,47 @@ void PGate::dump(ostream&out) const
} }
void PGAssign::dump(ostream&out) const void PGAssign::dump(ostream&out, unsigned ind) const
{ {
out << " assign (" << strength0() << "0 " << strength1() << "1) "; out << setw(ind) << "";
out << "assign (" << strength0() << "0 " << strength1() << "1) ";
dump_delays(out); dump_delays(out);
out << " " << *pin(0) << " = " << *pin(1) << ";" << endl; out << " " << *pin(0) << " = " << *pin(1) << ";" << endl;
} }
void PGBuiltin::dump(ostream&out) const void PGBuiltin::dump(ostream&out, unsigned ind) const
{ {
out << setw(ind) << "";
switch (type()) { switch (type()) {
case PGBuiltin::BUFIF0: case PGBuiltin::BUFIF0:
out << " bufif0 "; out << "bufif0 ";
break; break;
case PGBuiltin::BUFIF1: case PGBuiltin::BUFIF1:
out << " bufif1 "; out << "bufif1 ";
break; break;
case PGBuiltin::NOTIF0: case PGBuiltin::NOTIF0:
out << " bufif0 "; out << "bufif0 ";
break; break;
case PGBuiltin::NOTIF1: case PGBuiltin::NOTIF1:
out << " bufif1 "; out << "bufif1 ";
break; break;
case PGBuiltin::NAND: case PGBuiltin::NAND:
out << " nand "; out << "nand ";
break; break;
case PGBuiltin::NMOS: case PGBuiltin::NMOS:
out << " nmos "; out << "nmos ";
break; break;
case PGBuiltin::RNMOS: case PGBuiltin::RNMOS:
out << " rnmos "; out << "rnmos ";
break; break;
case PGBuiltin::RPMOS: case PGBuiltin::RPMOS:
out << " rpmos "; out << "rpmos ";
break; break;
case PGBuiltin::PMOS: case PGBuiltin::PMOS:
out << " pmos "; out << "pmos ";
break; break;
default: default:
out << " builtin gate "; out << "builtin gate ";
} }
out << "(" << strength0() << "0 " << strength1() << "1) "; out << "(" << strength0() << "0 " << strength1() << "1) ";
@ -367,9 +370,9 @@ void PGBuiltin::dump(ostream&out) const
out << ");" << endl; out << ");" << endl;
} }
void PGModule::dump(ostream&out) const void PGModule::dump(ostream&out, unsigned ind) const
{ {
out << " " << type_ << " "; out << setw(ind) << "" << type_ << " ";
// If parameters are overridden by order, dump them. // If parameters are overridden by order, dump them.
if (overrides_) { if (overrides_) {
@ -731,6 +734,44 @@ void PProcess::dump(ostream&out, unsigned ind) const
statement_->dump(out, ind+2); statement_->dump(out, ind+2);
} }
void PGenerate::dump(ostream&out) const
{
out << " generate(" << id_number << ")";
switch (scheme_type) {
case GS_NONE:
break;
case GS_LOOP:
out << " for ("
<< loop_index
<< "=" << *loop_init
<< "; " << *loop_test
<< "; " << loop_index
<< "=" << *loop_step << ")";
break;
case GS_CONDIT:
break;
}
if (scope_name)
out << " : " << scope_name;
out << endl;
for (map<hname_t,PWire*>::const_iterator idx = wires.begin()
; idx != wires.end() ; idx++) {
(*idx).second->dump(out, 6);
}
for (list<PGate*>::const_iterator idx = gates.begin()
; idx != gates.end() ; idx++) {
(*idx)->dump(out, 6);
}
out << " endgenerate" << endl;
}
void Module::dump(ostream&out) const void Module::dump(ostream&out) const
{ {
if (attributes.begin() != attributes.end()) { if (attributes.begin() != attributes.end()) {
@ -796,6 +837,18 @@ void Module::dump(ostream&out) const
out << "/* ERROR */;" << endl; out << "/* ERROR */;" << endl;
} }
typedef list<perm_string>::const_iterator genvar_iter_t;
for (genvar_iter_t cur = genvars.begin()
; cur != genvars.end() ; cur++) {
out << " genvar " << (*cur) << ";" << endl;
}
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
for (genscheme_iter_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur++) {
(*cur)->dump(out);
}
typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t; typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t;
for (specparm_iter_t cur = specparams.begin() for (specparm_iter_t cur = specparams.begin()
; cur != specparams.end() ; cur ++) { ; cur != specparams.end() ; cur ++) {
@ -914,6 +967,9 @@ void PUdp::dump(ostream&out) const
/* /*
* $Log: pform_dump.cc,v $ * $Log: pform_dump.cc,v $
* Revision 1.92 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.91 2005/10/04 04:09:26 steve * Revision 1.91 2005/10/04 04:09:26 steve
* Add support for indexed select attached to parameters. * Add support for indexed select attached to parameters.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.155 2006/01/02 05:33:19 steve Exp $" #ident "$Id: t-dll.cc,v 1.156 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -2018,6 +2018,10 @@ void dll_target::scope(const NetScope*net)
scope->type_ = IVL_SCT_FORK; scope->type_ = IVL_SCT_FORK;
scope->tname_ = scope->name_; scope->tname_ = scope->name_;
break; break;
case NetScope::GENBLOCK:
scope->type_ = IVL_SCT_GENERATE;
scope->tname_ = scope->name_;
break;
} }
assert(scope->parent != 0); assert(scope->parent != 0);
@ -2163,6 +2167,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.156 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.155 2006/01/02 05:33:19 steve * Revision 1.155 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.142 2006/03/18 22:53:38 steve Exp $" #ident "$Id: vvp_scope.c,v 1.143 2006/04/10 00:37:42 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -2107,6 +2107,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
case IVL_SCT_TASK: type = "task"; break; case IVL_SCT_TASK: type = "task"; break;
case IVL_SCT_BEGIN: type = "begin"; break; case IVL_SCT_BEGIN: type = "begin"; break;
case IVL_SCT_FORK: type = "fork"; break; case IVL_SCT_FORK: type = "fork"; break;
case IVL_SCT_GENERATE: type = "generate"; break;
default: type = "?"; assert(0); default: type = "?"; assert(0);
} }
@ -2204,6 +2205,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/* /*
* $Log: vvp_scope.c,v $ * $Log: vvp_scope.c,v $
* Revision 1.143 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.142 2006/03/18 22:53:38 steve * Revision 1.142 2006/03/18 22:53:38 steve
* Support more parameter syntax. * Support more parameter syntax.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_scope.cc,v 1.35 2006/03/06 05:43:15 steve Exp $" #ident "$Id: vpi_scope.cc,v 1.36 2006/04/10 00:37:43 steve Exp $"
#endif #endif
# include "compile.h" # include "compile.h"
@ -292,23 +292,21 @@ compile_scope_decl(char*label, char*type, char*name, char*tname, char*parent)
struct __vpiScope*scope = new struct __vpiScope; struct __vpiScope*scope = new struct __vpiScope;
count_vpi_scopes += 1; count_vpi_scopes += 1;
switch(type[2]) { if (strcmp(type,"module") == 0)
case 'd': /* type == moDule */
scope->base.vpi_type = &vpip_scope_module_rt; scope->base.vpi_type = &vpip_scope_module_rt;
break; else if (strcmp(type,"function") == 0)
case 'n': /* type == fuNction */
scope->base.vpi_type = &vpip_scope_function_rt; scope->base.vpi_type = &vpip_scope_function_rt;
break; else if (strcmp(type,"task") == 0)
case 's': /* type == taSk */
scope->base.vpi_type = &vpip_scope_task_rt; scope->base.vpi_type = &vpip_scope_task_rt;
break; else if (strcmp(type,"fork") == 0)
case 'r': /* type == foRk */
scope->base.vpi_type = &vpip_scope_fork_rt; scope->base.vpi_type = &vpip_scope_fork_rt;
break; else if (strcmp(type,"begin") == 0)
case 'g': /* type == beGin */
scope->base.vpi_type = &vpip_scope_begin_rt; scope->base.vpi_type = &vpip_scope_begin_rt;
break; else if (strcmp(type,"generate") == 0)
default: // Generate blocks are not really modules, but this is a
// hack that will work for now.
scope->base.vpi_type = &vpip_scope_module_rt;
else {
scope->base.vpi_type = &vpip_scope_module_rt; scope->base.vpi_type = &vpip_scope_module_rt;
assert(0); assert(0);
} }
@ -389,6 +387,9 @@ void vpip_attach_to_current_scope(vpiHandle obj)
/* /*
* $Log: vpi_scope.cc,v $ * $Log: vpi_scope.cc,v $
* Revision 1.36 2006/04/10 00:37:43 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.35 2006/03/06 05:43:15 steve * Revision 1.35 2006/03/06 05:43:15 steve
* Cleanup vpi_const to use vec4 values. * Cleanup vpi_const to use vec4 values.
* *