Unify elaboration of l-values for all proceedural assignments,
including assing, cassign and force. Generate NetConcat devices for gate outputs that feed into a vector results. Use this to hande gate arrays. Also let gate arrays handle vectors of gates when the outputs allow for it.
This commit is contained in:
parent
83423c978b
commit
8f2d679c8a
31
PExpr.h
31
PExpr.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.66 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.67 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -83,8 +83,13 @@ class PExpr : public LineInfo {
|
|||
bool implicit_net_ok =false) const;
|
||||
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
// assignments can be elaborated with this method. If the
|
||||
// is_force flag is true, then the set of valid l-value types
|
||||
// is slightly modified to accomodate the Verilog force
|
||||
// statement
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
// a verinum as a result. If the expression cannot be
|
||||
|
|
@ -133,7 +138,9 @@ class PEConcat : public PExpr {
|
|||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
|
|
@ -213,7 +220,9 @@ class PEIdent : public PExpr {
|
|||
bool implicit_net_ok =false) const;
|
||||
|
||||
// Identifiers are also allowed as procedural assignment l-values.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
// Structural r-values are OK.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
|
|
@ -288,7 +297,9 @@ class PENumber : public PExpr {
|
|||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
|
|
@ -492,6 +503,14 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.67 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.66 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.150 2004/12/11 02:31:25 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.151 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -213,6 +213,16 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConcat::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetConcat: "
|
||||
<< name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDivide::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl;
|
||||
|
|
@ -1087,6 +1097,14 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.151 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.150 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
130
elab_lval.cc
130
elab_lval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.30 2004/12/11 02:31:25 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.31 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -66,7 +66,9 @@
|
|||
* is to try to make a net elaboration, and see if the result is
|
||||
* suitable for assignment.
|
||||
*/
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet*ll = 0;
|
||||
if (ll == 0) {
|
||||
|
|
@ -92,7 +94,9 @@ NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
|||
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
|
||||
* NetAssign_ object.
|
||||
*/
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
{
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": error: Repeat concatenations make "
|
||||
|
|
@ -112,7 +116,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
|||
continue;
|
||||
}
|
||||
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
|
||||
|
||||
/* If the l-value doesn't elaborate, the error was
|
||||
already detected and printed. We just skip it and let
|
||||
|
|
@ -140,7 +144,9 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
|||
* Handle the ident as an l-value. This includes bit and part selects
|
||||
* of that ident.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
NetMemory* mem = 0;
|
||||
|
|
@ -151,6 +157,15 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
|||
symbol_search(des, scope, path_, reg, mem, var, par, eve);
|
||||
|
||||
if (mem) {
|
||||
if (is_force) {
|
||||
cerr << get_line() << ": error: Memories "
|
||||
<< "(" << path_ << " in this case)"
|
||||
<< " are not allowed"
|
||||
<< " as l-values to force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
|
||||
|
|
@ -171,8 +186,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
|||
assert(reg);
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. (Wires are not allows in this context. */
|
||||
if (reg->type() != NetNet::REG) {
|
||||
it is a register. Wires are not allows in this context,
|
||||
unless this is the l-value of a force. */
|
||||
if ((reg->type() != NetNet::REG) && !is_force) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
"." << endl;
|
||||
|
|
@ -340,7 +356,7 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
|||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
{
|
||||
cerr << get_line() << ": error: Constant values not allowed "
|
||||
<< "in l-value expressions." << endl;
|
||||
|
|
@ -350,6 +366,14 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
|||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.31 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.30 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
@ -363,95 +387,5 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
|||
*
|
||||
* Revision 1.27 2003/09/19 03:30:05 steve
|
||||
* Fix name search in elab_lval.
|
||||
*
|
||||
* Revision 1.26 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.25 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.24 2003/01/19 00:35:39 steve
|
||||
* Detect null arguments to concatenation operator.
|
||||
*
|
||||
* Revision 1.23 2002/11/21 23:27:51 steve
|
||||
* Precalculate indices to l-value arrays.
|
||||
*
|
||||
* Revision 1.22 2002/11/21 18:15:40 steve
|
||||
* Fix const test of msb in assignment l-values.
|
||||
*
|
||||
* Revision 1.21 2002/11/02 01:10:49 steve
|
||||
* Detect memories without work index in l-value.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.18 2002/03/09 04:02:26 steve
|
||||
* Constant expressions are not l-values for task ports.
|
||||
*
|
||||
* Revision 1.17 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.16 2001/11/08 05:15:50 steve
|
||||
* Remove string paths from PExpr elaboration.
|
||||
*
|
||||
* Revision 1.15 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
*
|
||||
* Revision 1.14 2001/08/25 23:50:02 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.13 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.12 2001/02/09 03:16:48 steve
|
||||
* Report bit/part select out of range errors. (PR#133)
|
||||
*
|
||||
* Revision 1.11 2001/01/10 03:13:23 steve
|
||||
* Build task outputs as lval instead of nets. (PR#98)
|
||||
*
|
||||
* Revision 1.10 2001/01/06 06:31:58 steve
|
||||
* declaration initialization for time variables.
|
||||
*
|
||||
* Revision 1.9 2001/01/06 02:29:36 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.8 2000/12/12 06:14:51 steve
|
||||
* sorry for concatenated memories in l-values. (PR#76)
|
||||
*
|
||||
* Revision 1.7 2000/12/01 02:55:37 steve
|
||||
* Detect part select errors on l-values.
|
||||
*
|
||||
* Revision 1.6 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.5 2000/10/26 17:09:46 steve
|
||||
* Fix handling of errors in behavioral lvalues. (PR#28)
|
||||
*
|
||||
* Revision 1.4 2000/09/10 15:43:59 steve
|
||||
* Some error checking.
|
||||
*
|
||||
* Revision 1.3 2000/09/10 03:59:59 steve
|
||||
* Agressively merge NetAssign_ within concatenations.
|
||||
*
|
||||
* Revision 1.2 2000/09/10 02:18:16 steve
|
||||
* elaborate complex l-values
|
||||
*
|
||||
* Revision 1.1 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
150
elaborate.cc
150
elaborate.cc
|
|
@ -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.311 2004/12/15 17:09:11 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.312 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -246,6 +246,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
unsigned count = 1;
|
||||
unsigned instance_width = 1;
|
||||
long low = 0, high = 0;
|
||||
string name = string(get_name());
|
||||
|
||||
|
|
@ -289,8 +290,33 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
low = lsb.as_long();
|
||||
high = msb.as_long();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: PGBuiltin: Make arrray "
|
||||
<< "[" << high << ":" << low << "]"
|
||||
<< " of " << count << " gates for " << name << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have a gate count. Elaborate the output expression
|
||||
only. We do it early so that we can see if we can make a
|
||||
wide gate instead of an array of gates. */
|
||||
|
||||
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope, true);
|
||||
assert(lval_sig);
|
||||
|
||||
/* Detect the special case that the l-value width exactly
|
||||
matches the gate count. In this case, we will make a single
|
||||
gate that has the desired vector width. */
|
||||
if (lval_sig->vector_width() == (long)count) {
|
||||
instance_width = count;
|
||||
count = 1;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: PGBuiltin: "
|
||||
"Collapsed gate array into single wide "
|
||||
"(" << instance_width << ") instance." << endl;
|
||||
}
|
||||
|
||||
/* Allocate all the netlist nodes for the gates. */
|
||||
NetLogic**cur = new NetLogic*[count];
|
||||
|
|
@ -334,75 +360,75 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
switch (type()) {
|
||||
case AND:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::AND, 1);
|
||||
NetLogic::AND, instance_width);
|
||||
break;
|
||||
case BUF:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUF, 1);
|
||||
NetLogic::BUF, instance_width);
|
||||
break;
|
||||
case BUFIF0:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF0, 1);
|
||||
NetLogic::BUFIF0, instance_width);
|
||||
break;
|
||||
case BUFIF1:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF1, 1);
|
||||
NetLogic::BUFIF1, instance_width);
|
||||
break;
|
||||
case NAND:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NAND, 1);
|
||||
NetLogic::NAND, instance_width);
|
||||
break;
|
||||
case NMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NMOS, 1);
|
||||
NetLogic::NMOS, instance_width);
|
||||
break;
|
||||
case NOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOR, 1);
|
||||
NetLogic::NOR, instance_width);
|
||||
break;
|
||||
case NOT:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOT, 1);
|
||||
NetLogic::NOT, instance_width);
|
||||
break;
|
||||
case NOTIF0:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF0, 1);
|
||||
NetLogic::NOTIF0, instance_width);
|
||||
break;
|
||||
case NOTIF1:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF1, 1);
|
||||
NetLogic::NOTIF1, instance_width);
|
||||
break;
|
||||
case OR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::OR, 1);
|
||||
NetLogic::OR, instance_width);
|
||||
break;
|
||||
case RNMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RNMOS, 1);
|
||||
NetLogic::RNMOS, instance_width);
|
||||
break;
|
||||
case RPMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RPMOS, 1);
|
||||
NetLogic::RPMOS, instance_width);
|
||||
break;
|
||||
case PMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PMOS, 1);
|
||||
NetLogic::PMOS, instance_width);
|
||||
break;
|
||||
case PULLDOWN:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLDOWN, 1);
|
||||
NetLogic::PULLDOWN, instance_width);
|
||||
break;
|
||||
case PULLUP:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLUP, 1);
|
||||
NetLogic::PULLUP, instance_width);
|
||||
break;
|
||||
case XNOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XNOR, 1);
|
||||
NetLogic::XNOR, instance_width);
|
||||
break;
|
||||
case XOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XOR, 1);
|
||||
NetLogic::XOR, instance_width);
|
||||
break;
|
||||
default:
|
||||
cerr << get_line() << ": internal error: unhandled "
|
||||
|
|
@ -434,25 +460,67 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
const PExpr*ex = pin(idx);
|
||||
NetNet*sig = (idx == 0)
|
||||
? ex->elaborate_lnet(des, scope, true)
|
||||
? lval_sig
|
||||
: ex->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
if (sig == 0)
|
||||
continue;
|
||||
|
||||
assert(sig);
|
||||
|
||||
if (sig->pin_count() == 1)
|
||||
if (count == 1) {
|
||||
/* Handle the case where there is one gate that
|
||||
carries the whole vector width. */
|
||||
connect(cur[0]->pin(idx), sig->pin(0));
|
||||
|
||||
} else if (sig->vector_width() == 1) {
|
||||
/* Handle the case where a single bit is connected
|
||||
repetitively to all the instances. */
|
||||
for (unsigned gdx = 0 ; gdx < count ; gdx += 1)
|
||||
connect(cur[gdx]->pin(idx), sig->pin(0));
|
||||
|
||||
else if (sig->pin_count() == count)
|
||||
for (unsigned gdx = 0 ; gdx < count ; gdx += 1)
|
||||
connect(cur[gdx]->pin(idx), sig->pin(gdx));
|
||||
} else if (sig->vector_width() == (long)count) {
|
||||
|
||||
else {
|
||||
/* Handle the general case that each bit of the
|
||||
value is connected to a different instance. In
|
||||
this case, the output is handled slightly
|
||||
different from the inputs. */
|
||||
if (idx == 0) {
|
||||
NetConcat*cc = new NetConcat(scope,
|
||||
scope->local_symbol(),
|
||||
sig->vector_width(),
|
||||
count);
|
||||
des->add_node(cc);
|
||||
|
||||
/* Connect the concat to the signal. */
|
||||
connect(cc->pin(0), sig->pin(0));
|
||||
|
||||
/* Connect the outputs of the gates to the concat. */
|
||||
for (unsigned gdx = 0 ; gdx < count ; gdx += 1) {
|
||||
connect(cur[gdx]->pin(0), cc->pin(gdx+1));
|
||||
|
||||
NetNet*tmp2 = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
connect(cc->pin(gdx+1), tmp2->pin(0));
|
||||
}
|
||||
|
||||
} else for (unsigned gdx = 0 ; gdx < count ; gdx += 1) {
|
||||
/* Use part selects to get the bits
|
||||
connected to the inputs of out gate. */
|
||||
NetPartSelect*tmp1 = new NetPartSelect(sig, gdx, 1);
|
||||
tmp1->set_line(*this);
|
||||
des->add_node(tmp1);
|
||||
connect(tmp1->pin(1), sig->pin(0));
|
||||
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
connect(tmp1->pin(0), tmp2->pin(0));
|
||||
connect(cur[gdx]->pin(idx), tmp1->pin(0));
|
||||
}
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Gate count of " <<
|
||||
count << " does not match net width of " <<
|
||||
sig->pin_count() << " at pin " << idx << "."
|
||||
sig->vector_width() << " at pin " << idx << "."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
|
@ -1031,7 +1099,7 @@ NetProc* Statement::elaborate(Design*des, NetScope*) const
|
|||
NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(lval_);
|
||||
return lval_->elaborate_lval(des, scope);
|
||||
return lval_->elaborate_lval(des, scope, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1667,7 +1735,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
detailed message. */
|
||||
NetAssign_*lv;
|
||||
if (parms_[idx]) {
|
||||
lv = parms_[idx]->elaborate_lval(des, scope);
|
||||
lv = parms_[idx]->elaborate_lval(des, scope, false);
|
||||
if (lv == 0) {
|
||||
cerr << parms_[idx]->get_line() << ": error: "
|
||||
<< "I give up on task port " << (idx+1)
|
||||
|
|
@ -1702,7 +1770,7 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
|||
NetCAssign*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1733,7 +1801,7 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -2216,12 +2284,22 @@ NetProc* PForever::elaborate(Design*des, NetScope*scope) const
|
|||
return proc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force is like a procedural assignment, most notably prodedural
|
||||
* continuous assignment:
|
||||
*
|
||||
* force <lval> = <rval>
|
||||
*
|
||||
* The <lval> can be anything that a normal behavioral assignment can
|
||||
* take, plus net signals. This is a little bit more lax then the
|
||||
* other proceedural assignments.
|
||||
*/
|
||||
NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetForce*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -2396,7 +2474,7 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -2767,6 +2845,14 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.312 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.311 2004/12/15 17:09:11 steve
|
||||
* Force r-value padded to width.
|
||||
*
|
||||
|
|
|
|||
15
emit.cc
15
emit.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.78 2004/12/11 02:31:26 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.79 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -75,6 +75,11 @@ bool NetCompare::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetConcat::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->concat(this);
|
||||
}
|
||||
|
||||
bool NetConst::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_const(this);
|
||||
|
|
@ -504,6 +509,14 @@ bool emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.79 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.78 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
54
ivl_target.h
54
ivl_target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.129 2004/12/18 18:56:18 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.130 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -222,6 +222,7 @@ typedef enum ivl_logic_e {
|
|||
/* This is the type of an LPM object. */
|
||||
typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
|
|
@ -627,6 +628,12 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
|||
* These support iterating over logic attributes. The _cnt method
|
||||
* returns the number of attributes attached to the gate, and the
|
||||
* ivl_logic_attr_val returns the value of the attribute.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
* The ivl_logic_width and ivl_logic_pins are *not* related. A logic
|
||||
* device has a number of pins that is the number of inputs to a logic
|
||||
* array of identical gates, and the ivl_logic_width, is the width of
|
||||
* the vector into each input pin and out of the output pin.
|
||||
*/
|
||||
|
||||
extern const char* ivl_logic_name(ivl_net_logic_t net);
|
||||
|
|
@ -637,6 +644,7 @@ extern ivl_nexus_t ivl_logic_pin(ivl_net_logic_t net, unsigned pin);
|
|||
extern unsigned ivl_logic_pins(ivl_net_logic_t net);
|
||||
extern ivl_udp_t ivl_logic_udp(ivl_net_logic_t net);
|
||||
extern unsigned ivl_logic_delay(ivl_net_logic_t net, unsigned transition);
|
||||
extern unsigned ivl_logic_width(ivl_net_logic_t net);
|
||||
|
||||
/* DEPRECATED */
|
||||
extern const char* ivl_logic_attr(ivl_net_logic_t net, const char*key);
|
||||
|
|
@ -659,7 +667,8 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
/* LPM
|
||||
* These functions support access to the properties of LPM
|
||||
* devices. LPM devices are a variety of devices that handle more
|
||||
* complex structural semantics.
|
||||
* complex structural semantics. They are based on EIA LPM standard
|
||||
* devices, but vary to suite the technical situation.
|
||||
*
|
||||
* These are the functions that apply to all LPM devices:
|
||||
*
|
||||
|
|
@ -689,13 +698,12 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* of the part select. The ivl_lpm_width is the size of the part.
|
||||
*
|
||||
* ivl_lpm_data
|
||||
* Return the input data nexus for device types that have a single
|
||||
* input vector. This is also used to the get nexa of the first
|
||||
* vector for devices that have more inputs.
|
||||
* Return the input data nexus for device types that have input
|
||||
* vectors. The "idx" parameter selects which data input is selected.
|
||||
*
|
||||
* ivl_lpm_datab
|
||||
* Return the input data nexus for device types that have a second
|
||||
* input vector. For example, arithmetic devices are like this.
|
||||
* ivl_lpm_datab (ANACHRONISM)
|
||||
* This is the same as ivl_lpm_data(net,1), in other words the
|
||||
* second data input. Use the ivl_lpm_data method instead.
|
||||
*
|
||||
* ivl_lpm_q
|
||||
* Return the output data nexus for device types that have a single
|
||||
|
|
@ -713,6 +721,18 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* In addition to a width, some devices have a size. The size is
|
||||
* often the number of inputs per out, i.e., the number of inputs
|
||||
* per bit for a MUX.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* - Concatenation (IVL_LPM_CONCAT)
|
||||
* These devices take vectors in and combine them to form a single
|
||||
* output the width specified by ivl_lpm_width.
|
||||
*
|
||||
* The ivl_lpm_q nexus is the output from the concatenation.
|
||||
*
|
||||
* The ivl_lpm_data function returns the connections for the inputs to
|
||||
* the concatentation. The ivl_lpm_size function returns the number of
|
||||
* inputs help by the device.
|
||||
*/
|
||||
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
|
||||
|
|
@ -737,8 +757,8 @@ extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
|||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT IVL_LPM_RAM
|
||||
IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
|
||||
IVL_LPM_RAM IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_MUX IVL_LPM_UFUNC */
|
||||
|
|
@ -753,7 +773,7 @@ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
|||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX */
|
||||
/* IVL_LPM_CONCAT IVL_LPM_MUX */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
|
@ -1260,7 +1280,9 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
|||
*
|
||||
* - IVL_ST_FORCE
|
||||
* This is very much like IVL_ST_CASSIGN, but adds that l-values can
|
||||
* include nets (tri, wire, etc).
|
||||
* include nets (tri, wire, etc). Memory words are restricted from
|
||||
* force l-values, and also non-constant bit or part selects. The
|
||||
* compiler will assure these constraints are met.
|
||||
*
|
||||
* - IVL_ST_TRIGGER
|
||||
* This represents the "-> name" statement that sends a trigger to a
|
||||
|
|
@ -1371,6 +1393,14 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.130 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.129 2004/12/18 18:56:18 steve
|
||||
* Add ivl_event_scope, and better document ivl_event_X methods.
|
||||
*
|
||||
|
|
|
|||
30
netlist.cc
30
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.cc,v 1.227 2004/12/11 02:31:26 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.228 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -532,6 +532,26 @@ const NetScope* NetProcTop::scope() const
|
|||
return scope_;
|
||||
}
|
||||
|
||||
NetConcat::NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt)
|
||||
: NetNode(scope, n, cnt+1), width_(wid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
for (unsigned idx = 1 ; idx < cnt+1 ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx-1);
|
||||
}
|
||||
}
|
||||
|
||||
NetConcat::~NetConcat()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetConcat::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetFF class represents an LPM_FF device. The pinout is assigned
|
||||
* like so:
|
||||
|
|
@ -2306,6 +2326,14 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.228 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.227 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
41
netlist.h
41
netlist.h
|
|
@ -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.322 2004/12/11 02:31:27 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.323 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -582,6 +582,32 @@ class NetCompare : public NetNode {
|
|||
bool signed_flag_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This node is a means to connect net inputs together to form a wider
|
||||
* vector. The output (pin 0) is a concatenation of the input vectors,
|
||||
* with pin-1 at the LSB, pin-2 next, and so on. This node is most
|
||||
* like the NetLogic node, as it has one output at pin 0 and the
|
||||
* remaining pins are the input that are combined to make the
|
||||
* output. It is seperated out because it it generally a special case
|
||||
* for the code generators.
|
||||
*/
|
||||
class NetConcat : public NetNode {
|
||||
|
||||
public:
|
||||
NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt);
|
||||
~NetConcat();
|
||||
|
||||
unsigned width() const;
|
||||
|
||||
void dump_node(ostream&, unsigned ind) const;
|
||||
bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class represents a theoretical (though not necessarily
|
||||
* practical) integer divider gate. This is not to represent any real
|
||||
|
|
@ -1242,6 +1268,11 @@ class NetConst : public NetNode {
|
|||
* The pullup and pulldown gates have no inputs at all, and pin0 is
|
||||
* the output 1 or 0, depending on the gate type. It is the strength
|
||||
* of that value that is important.
|
||||
*
|
||||
* All these devices process vectors bitwise, so each bit can be
|
||||
* logically seperated. The exception is the CONCAT gate, which is
|
||||
* really an abstract gate that takes the inputs and turns it into a
|
||||
* vector of bits.
|
||||
*/
|
||||
class NetLogic : public NetNode {
|
||||
|
||||
|
|
@ -3349,6 +3380,14 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.323 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.322 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
31
t-dll-api.cc
31
t-dll-api.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.111 2004/12/18 18:56:18 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.112 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -766,8 +766,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.a;
|
||||
assert(idx <= 1);
|
||||
if (idx == 0)
|
||||
return net->u_.arith.a;
|
||||
else
|
||||
return net->u_.arith.b;
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
|
|
@ -782,6 +785,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.d.pins[idx];
|
||||
|
||||
case IVL_LPM_CONCAT:
|
||||
assert(idx < net->u_.concat.inputs);
|
||||
return net->u_.concat.pins[idx+1];
|
||||
|
||||
case IVL_LPM_PART:
|
||||
assert(idx == 0);
|
||||
return net->u_.part.a;
|
||||
|
|
@ -794,6 +801,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
|
||||
extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
||||
{
|
||||
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_datab." << endl;
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
|
||||
|
|
@ -928,6 +936,9 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.ufunc.port_wid[0]);
|
||||
return net->u_.ufunc.pins[idx];
|
||||
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.pins[0];
|
||||
|
||||
case IVL_LPM_PART:
|
||||
assert(idx == 0);
|
||||
return net->u_.part.q;
|
||||
|
|
@ -982,6 +993,8 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
|||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.select;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1012,6 +1025,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
return 0;
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_CONCAT: // Concatenations are always unsigned
|
||||
return 0;
|
||||
case IVL_LPM_PART:
|
||||
return net->u_.part.signed_flag;
|
||||
default:
|
||||
|
|
@ -1062,6 +1077,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
|||
return net->u_.shift.width;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.port_wid[0];
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.width;
|
||||
case IVL_LPM_PART:
|
||||
return net->u_.part.width;
|
||||
default:
|
||||
|
|
@ -1946,6 +1963,14 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.112 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.111 2004/12/18 18:56:18 steve
|
||||
* Add ivl_event_scope, and better document ivl_event_X methods.
|
||||
*
|
||||
|
|
|
|||
38
t-dll.cc
38
t-dll.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.132 2004/12/11 02:31:28 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.133 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1867,6 +1867,34 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
|
||||
}
|
||||
|
||||
bool dll_target::concat(const NetConcat*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_CONCAT;
|
||||
obj->name = net->name(); // NetConcat names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.concat.width = net->width();
|
||||
|
||||
obj->u_.concat.inputs = net->pin_count() - 1;
|
||||
obj->u_.concat.pins = new ivl_nexus_t[obj->u_.concat.inputs+1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->u_.concat.inputs+1 ; idx += 1) {
|
||||
ivl_drive_t dr = idx == 0? IVL_DR_STRONG : IVL_DR_HiZ;
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.concat.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.concat.pins[idx], obj, 0, dr, dr);
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dll_target::part_select(const NetPartSelect*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
|
|
@ -2179,6 +2207,14 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.133 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.132 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
17
t-dll.h
17
t-dll.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.116 2004/12/11 02:31:28 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.117 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -82,6 +82,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_mult(const NetMult*);
|
||||
void lpm_mux(const NetMux*);
|
||||
void lpm_ram_dq(const NetRamDq*);
|
||||
bool concat(const NetConcat*);
|
||||
bool part_select(const NetPartSelect*);
|
||||
void net_assign(const NetAssign_*);
|
||||
bool net_function(const NetUserFunc*);
|
||||
|
|
@ -347,6 +348,12 @@ struct ivl_lpm_s {
|
|||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_concat_s {
|
||||
unsigned width;
|
||||
unsigned inputs;
|
||||
ivl_nexus_t*pins;
|
||||
} concat;
|
||||
|
||||
struct ivl_part_s {
|
||||
unsigned width;
|
||||
unsigned base;
|
||||
|
|
@ -680,6 +687,14 @@ struct ivl_variable_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.117 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.116 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
17
target.cc
17
target.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.70 2004/12/11 02:31:28 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.71 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -137,6 +137,13 @@ void target_t::lpm_ram_dq(const NetRamDq*)
|
|||
"Unhandled NetRamDq." << endl;
|
||||
}
|
||||
|
||||
bool target_t::concat(const NetConcat*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetConcat." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::part_select(const NetPartSelect*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -412,6 +419,14 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.71 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.70 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
11
target.h
11
target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.66 2004/12/11 02:31:28 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.67 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -86,6 +86,7 @@ struct target_t {
|
|||
virtual void lpm_mux(const NetMux*);
|
||||
virtual void lpm_ram_dq(const NetRamDq*);
|
||||
|
||||
virtual bool concat(const NetConcat*);
|
||||
virtual bool part_select(const NetPartSelect*);
|
||||
|
||||
/* Output a gate (called for each gate) */
|
||||
|
|
@ -170,6 +171,14 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.67 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.66 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stub.c,v 1.93 2004/12/18 18:55:08 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.94 2004/12/29 23:55:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -179,6 +179,50 @@ void show_expression(ivl_expr_t net, unsigned ind)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* IVL_LPM_CONCAT
|
||||
* The concat device takes N inputs (N=ivl_lpm_selects) and generates
|
||||
* a single output. The total output is known from the ivl_lpm_width
|
||||
* function. The widths of all the inputs are inferred from the widths
|
||||
* of the signals connected to the nexus of the inputs. The compiler
|
||||
* makes sure the input widths add up to the output width.
|
||||
*/
|
||||
static void show_lpm_concat(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
unsigned width_sum = 0;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n",
|
||||
ivl_lpm_basename(net), width, ivl_lpm_selects(net));
|
||||
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
|
||||
unsigned ndx;
|
||||
unsigned signal_width = 0;
|
||||
ivl_nexus_t nex = ivl_lpm_data(net, idx);
|
||||
|
||||
for (ndx = 0 ; ndx < ivl_nexus_ptrs(nex) ; ndx += 1) {
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, ndx);
|
||||
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
|
||||
if (sig != 0) {
|
||||
signal_width = ivl_signal_width(sig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(out, " I%u: %s (width=%u)\n", idx,
|
||||
ivl_nexus_name(nex), signal_width);
|
||||
width_sum += signal_width;
|
||||
}
|
||||
|
||||
if (width_sum != width) {
|
||||
fprintf(out, " ERROR! Got %u bits input, expecting %u!\n",
|
||||
width_sum, width);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_lpm(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
|
@ -235,6 +279,10 @@ static void show_lpm(ivl_lpm_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
case IVL_LPM_CONCAT:
|
||||
show_lpm_concat(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SHIFTL: {
|
||||
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n",
|
||||
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
|
||||
|
|
@ -762,6 +810,14 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.94 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.93 2004/12/18 18:55:08 steve
|
||||
* Better detail on event trigger and wait statements.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue