Change case compare from logic to an LPM node.

This commit is contained in:
steve 2005-01-22 01:06:55 +00:00
parent b86fdd6bbc
commit e28636776a
12 changed files with 250 additions and 115 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2005 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: elab_net.cc,v 1.142 2005/01/16 04:20:32 steve Exp $" #ident "$Id: elab_net.cc,v 1.143 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -633,44 +633,18 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
} }
case 'E': // Case equals (===) case 'E': // Case equals (===)
case 'N': // Case equals (!==) gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth);
// The comparison generates gates to bitwise compare
// each pair, and AND all the comparison results.
#if 0
gate = new NetLogic(scope, scope->local_symbol(),
1+dwidth,
(op_ == 'E')? NetLogic::AND : NetLogic::NAND, 1);
connect(gate->pin(0), osig->pin(0)); connect(gate->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) { connect(gate->pin(1), lsig->pin(0));
NetCaseCmp*cmp = new NetCaseCmp(scope, connect(gate->pin(2), rsig->pin(0));
scope->local_symbol());
if (idx < lsig->pin_count())
connect(cmp->pin(1), lsig->pin(idx));
else
connect(cmp->pin(1), padbit->pin(0));
if (idx < rsig->pin_count())
connect(cmp->pin(2), rsig->pin(idx));
else
connect(cmp->pin(2), padbit->pin(0));
connect(cmp->pin(0), gate->pin(idx+1));
des->add_node(cmp);
// Attach a label to this intermediate wire
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE);
tmp->local_flag(true);
connect(cmp->pin(0), tmp->pin(0));
}
#else
cerr << get_line() << ": internal error: Forgot how to "
<< "elab_net === operators." << endl;
des->errors += 1;
#endif
break; break;
case 'N': // Case equals (!==)
cerr << get_line() << ": internal error: "
<< "Forgot how to elaborate !==." << endl;
des->errors += 1;
gate = 0;
break;
case 'e': // == case 'e': // ==
@ -2482,6 +2456,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $Log: elab_net.cc,v $
* Revision 1.143 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.142 2005/01/16 04:20:32 steve * Revision 1.142 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors. * Implement LPM_COMPARE nodes as two-input vector functors.
* *

37
emit.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: emit.cc,v 1.79 2004/12/29 23:55:43 steve Exp $" #ident "$Id: emit.cc,v 1.80 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -361,13 +361,12 @@ void NetWhile::emit_proc_recurse(struct target_t*tgt) const
proc_->emit_proc(tgt); proc_->emit_proc(tgt);
} }
bool Design::emit(struct target_t*tgt) const int Design::emit(struct target_t*tgt) const
{ {
bool rc = true; int rc = 0;
rc = rc && tgt->start_design(this); if (tgt->start_design(this) == false)
if (rc == false) return -2;
return false;
// enumerate the scopes // enumerate the scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin(); for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
@ -376,27 +375,36 @@ bool Design::emit(struct target_t*tgt) const
// emit nodes // emit nodes
bool nodes_rc = true;
if (nodes_) { if (nodes_) {
NetNode*cur = nodes_->node_next_; NetNode*cur = nodes_->node_next_;
do { do {
rc = rc && cur->emit_node(tgt); nodes_rc = nodes_rc && cur->emit_node(tgt);
cur = cur->node_next_; cur = cur->node_next_;
} while (cur != nodes_->node_next_); } while (cur != nodes_->node_next_);
} }
// emit task and function definitions // emit task and function definitions
bool tasks_rc = true;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin(); for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); scope++) scope != root_scopes_.end(); scope++)
rc &= (*scope)->emit_defs(tgt); tasks_rc &= (*scope)->emit_defs(tgt);
// emit the processes // emit the processes
bool proc_rc = true;
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_) for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
rc = rc && idx->emit(tgt); proc_rc &= idx->emit(tgt);
if (tgt->end_design(this) != 0) rc = tgt->end_design(this);
rc = false;
if (nodes_rc == false)
return -1;
if (tasks_rc == false)
return -2;
if (proc_rc == false)
return -3;
return rc; return rc;
} }
@ -492,7 +500,7 @@ void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_variable(this); tgt->expr_variable(this);
} }
bool emit(const Design*des, const char*type) int emit(const Design*des, const char*type)
{ {
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) { for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx]; const struct target*tgt = target_table[idx];
@ -503,12 +511,15 @@ bool emit(const Design*des, const char*type)
cerr << "error: Code generator type " << type cerr << "error: Code generator type " << type
<< " not found." << endl; << " not found." << endl;
return false; return -1;
} }
/* /*
* $Log: emit.cc,v $ * $Log: emit.cc,v $
* Revision 1.80 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.79 2004/12/29 23:55:43 steve * Revision 1.79 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

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.131 2005/01/09 20:16:01 steve Exp $" #ident "$Id: ivl_target.h,v 1.132 2005/01/22 01:06:55 steve Exp $"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -87,6 +87,10 @@ _BEGIN_DECL
* this includes just about every directional device that has a * this includes just about every directional device that has a
* single output, including logic gates and nmos, pmos and cmos * single output, including logic gates and nmos, pmos and cmos
* devices. There is also the occasional Icarus Verilog creation. * devices. There is also the occasional Icarus Verilog creation.
* What is common about these devices is that they are
* bitwise. That is, when fed a vector, they produce a vector
* result where each bit of the output is made only from the same
* bits in the vector inputs.
* *
* ivl_nexus_t * ivl_nexus_t
* Structural links within an elaborated design are connected * Structural links within an elaborated design are connected
@ -214,8 +218,6 @@ typedef enum ivl_logic_e {
IVL_LO_XNOR = 18, IVL_LO_XNOR = 18,
IVL_LO_XOR = 19, IVL_LO_XOR = 19,
IVL_LO_EEQ = 20,
IVL_LO_UDP = 21 IVL_LO_UDP = 21
} ivl_logic_t; } ivl_logic_t;
@ -223,10 +225,12 @@ typedef enum ivl_logic_e {
typedef enum ivl_lpm_type_e { typedef enum ivl_lpm_type_e {
IVL_LPM_ADD = 0, IVL_LPM_ADD = 0,
IVL_LPM_CONCAT = 16, IVL_LPM_CONCAT = 16,
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQ = 10, IVL_LPM_CMP_EQ = 10,
IVL_LPM_CMP_GE = 1, IVL_LPM_CMP_GE = 1,
IVL_LPM_CMP_GT = 2, IVL_LPM_CMP_GT = 2,
IVL_LPM_CMP_NE = 11, IVL_LPM_CMP_NE = 11,
IVL_LPM_CMP_NEE= 19, //* Case NE (!==) */
IVL_LPM_DIVIDE = 12, IVL_LPM_DIVIDE = 12,
IVL_LPM_FF = 3, IVL_LPM_FF = 3,
IVL_LPM_MOD = 13, IVL_LPM_MOD = 13,
@ -753,6 +757,12 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* still correct. The output being written to the wider vector is * still correct. The output being written to the wider vector is
* indeed the width of the part, even though it is written to a wider * indeed the width of the part, even though it is written to a wider
* gate. The target will need to handle this case specially. * gate. The target will need to handle this case specially.
*
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE)
* These devices have two inputs, available by the ivl_lpm_data()
* function, and one output available by the ivl_lpm_q function. The
* output width is always 1, but the ivl_lpm_width() returns the width
* of the inputs. Both inputs must have the same width.
*/ */
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
@ -1403,6 +1413,12 @@ extern DLLEXPORT int target_design(ivl_design_t des);
is processed and available to the target. The target doesn't return is processed and available to the target. The target doesn't return
from this function until it is finished with the design. from this function until it is finished with the design.
The return value of this function should normally be zero. If the
code generator detects errors, however, then the code generator
returns a positive number to indicate the approximate number of
errors detected (before it gave up.) Return values <0 are reserved
for system and infrastructure errors.
This function is implemented in the loaded target, and not in the This function is implemented in the loaded target, and not in the
ivl core. This function is how the target module is invoked. */ ivl core. This function is how the target module is invoked. */
@ -1413,6 +1429,9 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $Log: ivl_target.h,v $
* Revision 1.132 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.131 2005/01/09 20:16:01 steve * Revision 1.131 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports. * Use PartSelect/PV and VP to handle part selects through ports.
* *

17
main.cc
View File

@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* 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: main.cc,v 1.87 2004/12/11 02:31:26 steve Exp $" #ident "$Id: main.cc,v 1.88 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -701,12 +701,18 @@ int main(int argc, char*argv[])
cout << "CODE GENERATION -t "<<target<< endl; cout << "CODE GENERATION -t "<<target<< endl;
} }
bool emit_rc; int emit_rc;
emit_rc = emit(des, target); emit_rc = emit(des, target);
if (!emit_rc) { if (emit_rc > 0) {
cerr << "error: Code generation had errors." << endl; cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1; return 1;
} }
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
if (verbose_flag) { if (verbose_flag) {
if (times_flag) { if (times_flag) {
@ -748,6 +754,9 @@ int main(int argc, char*argv[])
/* /*
* $Log: main.cc,v $ * $Log: main.cc,v $
* Revision 1.88 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.87 2004/12/11 02:31:26 steve * Revision 1.87 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead * Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes * of single bits. Make the ivl, tgt-vvp and vvp initial changes

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: netlist.cc,v 1.230 2005/01/16 04:20:32 steve Exp $" #ident "$Id: netlist.cc,v 1.231 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1650,8 +1650,8 @@ unsigned NetBUFZ::width() const
return width_; return width_;
} }
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n) NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid)
: NetNode(s, n, 3) : NetNode(s, n, 3), width_(wid)
{ {
pin(0).set_dir(Link::OUTPUT); pin(0).set_name(perm_string::literal("O"),0); pin(0).set_dir(Link::OUTPUT); pin(0).set_name(perm_string::literal("O"),0);
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("I"),0); pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("I"),0);
@ -1662,6 +1662,11 @@ NetCaseCmp::~NetCaseCmp()
{ {
} }
unsigned NetCaseCmp::width() const
{
return width_;
}
NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e) NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e)
: expr_(ex), if_(i), else_(e) : expr_(ex), if_(i), else_(e)
{ {
@ -2342,6 +2347,9 @@ const NetProc*NetTaskDef::proc() const
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.231 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.230 2005/01/16 04:20:32 steve * Revision 1.230 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors. * Implement LPM_COMPARE nodes as two-input vector functors.
* *

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.326 2005/01/16 04:20:32 steve Exp $" #ident "$Id: netlist.h,v 1.327 2005/01/22 01:06:55 steve Exp $"
#endif #endif
/* /*
@ -1241,7 +1241,10 @@ class NetBUFZ : public NetNode {
/* /*
* This node is used to represent case equality in combinational * This node is used to represent case equality in combinational
* logic. Although this is not normally synthesizable, it makes sense * logic. Although this is not normally synthesizable, it makes sense
* to support an abstract gate that can compare x and z. * to support an abstract gate that can compare x and z. This node
* always generates a single bit result, no matter the width of the
* input. The elaboration, btw, needs to make sure the input widths
* match.
* *
* This pins are assigned as: * This pins are assigned as:
* *
@ -1252,11 +1255,16 @@ class NetBUFZ : public NetNode {
class NetCaseCmp : public NetNode { class NetCaseCmp : public NetNode {
public: public:
explicit NetCaseCmp(NetScope*s, perm_string n); explicit NetCaseCmp(NetScope*s, perm_string n, unsigned wid);
~NetCaseCmp(); ~NetCaseCmp();
unsigned width() const;
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const; virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
}; };
/* /*
@ -3336,7 +3344,7 @@ class Design {
// Iterate over the design... // Iterate over the design...
void dump(ostream&) const; void dump(ostream&) const;
void functor(struct functor_t*); void functor(struct functor_t*);
bool emit(struct target_t*) const; int emit(struct target_t*) const;
// This is incremented by elaboration when an error is // This is incremented by elaboration when an error is
// detected. It prevents code being emitted. // detected. It prevents code being emitted.
@ -3411,6 +3419,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.327 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.326 2005/01/16 04:20:32 steve * Revision 1.326 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors. * Implement LPM_COMPARE nodes as two-input vector functors.
* *

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-api.cc,v 1.113 2005/01/09 20:16:01 steve Exp $" #ident "$Id: t-dll-api.cc,v 1.114 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -759,6 +759,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(net); assert(net);
switch (net->type) { switch (net->type) {
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
@ -911,6 +912,7 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_EEQ:
assert(idx == 0); assert(idx == 0);
return net->u_.arith.q; return net->u_.arith.q;
@ -1013,6 +1015,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_MUX: case IVL_LPM_MUX:
return 0; return 0;
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
@ -1067,6 +1070,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
case IVL_LPM_MUX: case IVL_LPM_MUX:
return net->u_.mux.width; return net->u_.mux.width;
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
@ -1968,6 +1972,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/* /*
* $Log: t-dll-api.cc,v $ * $Log: t-dll-api.cc,v $
* Revision 1.114 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.113 2005/01/09 20:16:01 steve * Revision 1.113 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports. * Use PartSelect/PV and VP to handle part selects through ports.
* *

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.135 2005/01/16 04:20:32 steve Exp $" #ident "$Id: t-dll.cc,v 1.136 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -914,35 +914,36 @@ void dll_target::logic(const NetLogic*net)
void dll_target::net_case_cmp(const NetCaseCmp*net) void dll_target::net_case_cmp(const NetCaseCmp*net)
{ {
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s; struct ivl_lpm_s*obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_CMP_EEQ;
obj->name = net->name();
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->type_ = IVL_LO_EEQ; obj->u_.arith.width = net->width();
obj->u_.arith.signed_flag = 0;
/* Connect all the ivl_nexus_t objects to the pins of the const Nexus*nex;
device. */
obj->npins_ = 3; nex = net->pin(1).nexus();
obj->pins_ = new ivl_nexus_t[obj->npins_]; assert(nex->t_cookie());
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus();
assert(nex->t_cookie());
obj->pins_[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_log_add(obj->pins_[idx], obj, idx);
}
//assert(net->scope()); obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
//ivl_scope_t scope = find_scope(des_, net->scope()); nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
//assert(scope);
ivl_scope_t scope = des_.roots_[0];
obj->scope_= scope; nex = net->pin(2).nexus();
obj->name_ = net->name(); assert(nex->t_cookie());
obj->delay[0] = net->rise_time(); obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
obj->delay[1] = net->fall_time(); nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
obj->delay[2] = net->decay_time();
scope_add_logic(scope, obj); nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
scope_add_lpm(obj->scope, obj);
} }
/* /*
@ -2225,6 +2226,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.136 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.135 2005/01/16 04:20:32 steve * Revision 1.135 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors. * Implement LPM_COMPARE nodes as two-input vector functors.
* *

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: target.h,v 1.67 2004/12/29 23:55:43 steve Exp $" #ident "$Id: target.h,v 1.68 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -154,7 +154,7 @@ struct expr_scan_t {
/* The emit functions take a design and emit it to the output stream /* The emit functions take a design and emit it to the output stream
using the specified target. If the target is given by name, it is using the specified target. If the target is given by name, it is
located in the target_table and used. */ located in the target_table and used. */
extern bool emit(const Design*des, const char*type); extern int emit(const Design*des, const char*type);
/* This function takes a fully qualified verilog name (which may have, /* This function takes a fully qualified verilog name (which may have,
for example, dots in it) and produces a mangled version that can be for example, dots in it) and produces a mangled version that can be
@ -171,6 +171,9 @@ extern const struct target *target_table[];
/* /*
* $Log: target.h,v $ * $Log: target.h,v $
* Revision 1.68 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.67 2004/12/29 23:55:43 steve * Revision 1.67 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

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: priv.h,v 1.1 2004/12/12 18:15:06 steve Exp $" #ident "$Id: priv.h,v 1.2 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include <ivl_target.h> # include <ivl_target.h>
@ -29,6 +29,12 @@
*/ */
extern FILE*out; extern FILE*out;
/*
* Keep a running count of errors that the stub detects. This will be
* the error count returned to the ivl_target environment.
*/
extern int stub_errors;
/* /*
* Show the details of the expression. * Show the details of the expression.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2005 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: stub.c,v 1.96 2005/01/16 04:20:32 steve Exp $" #ident "$Id: stub.c,v 1.97 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -25,6 +25,30 @@
# include <assert.h> # include <assert.h>
FILE*out; FILE*out;
int stub_errors = 0;
/*
* This function finds the vector width of a signal. It relies on the
* assumption that all the signal inputs to the nexus have the same
* width. The ivl_target API should assert that condition.
*/
unsigned width_of_nexus(ivl_nexus_t nex)
{
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig != 0) {
return ivl_signal_width(sig);
}
}
/* ERROR: A nexus should have at least one signal to carry
properties like width. */
return 0;
}
/* /*
* This is a sample target module. All this does is write to the * This is a sample target module. All this does is write to the
@ -179,6 +203,54 @@ void show_expression(ivl_expr_t net, unsigned ind)
} }
} }
/*
* The compare-like LPM nodes have input widths that match the
* ivl_lpm_width() value, and an output width of 1. This function
* checks that that is so, and indicates errors otherwise.
*/
static void check_cmp_widths(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
/* Check that the input widths are as expected. The inputs
must be the width of the ivl_lpm_width() for this device,
even though the output for this device is 1 bit. */
if (width != width_of_nexus(ivl_lpm_data(net,0))) {
fprintf(out, " ERROR: Width of A is %u, not %u\n",
width_of_nexus(ivl_lpm_data(net,0)), width);
stub_errors += 1;
}
if (width != width_of_nexus(ivl_lpm_data(net,1))) {
fprintf(out, " ERROR: Width of B is %u, not %u\n",
width_of_nexus(ivl_lpm_data(net,1)), width);
stub_errors += 1;
}
if (width_of_nexus(ivl_lpm_q(net,0)) != 1) {
fprintf(out, " ERROR: Width of Q is %u, not 1\n",
width_of_nexus(ivl_lpm_q(net,0)));
stub_errors += 1;
}
}
/* IVL_LPM_CMP_EEQ
* This LPM node supports two-input compare. The output width is
* actually always 1, the lpm_width is the expected width of the inputs.
*/
static void show_lpm_cmp_eeq(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_CMP_EEQ %s: <width=%u>\n",
ivl_lpm_basename(net), width);
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
fprintf(out, " B: %s\n", ivl_nexus_name(ivl_lpm_data(net,1)));
check_cmp_widths(net);
}
/* IVL_LPM_CMP_GE /* IVL_LPM_CMP_GE
* This LPM node supports two-input compare. * This LPM node supports two-input compare.
*/ */
@ -192,6 +264,7 @@ static void show_lpm_cmp_ge(ivl_lpm_t net)
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0))); fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0))); fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
fprintf(out, " B: %s\n", ivl_nexus_name(ivl_lpm_data(net,1))); fprintf(out, " B: %s\n", ivl_nexus_name(ivl_lpm_data(net,1)));
check_cmp_widths(net);
} }
/* IVL_LPM_CONCAT /* IVL_LPM_CONCAT
@ -213,18 +286,8 @@ static void show_lpm_concat(ivl_lpm_t net)
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0))); fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) { 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); ivl_nexus_t nex = ivl_lpm_data(net, idx);
unsigned signal_width = width_of_nexus(nex);
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, fprintf(out, " I%u: %s (width=%u)\n", idx,
ivl_nexus_name(nex), signal_width); ivl_nexus_name(nex), signal_width);
@ -276,6 +339,10 @@ static void show_lpm(ivl_lpm_t net)
break; break;
} }
case IVL_LPM_CMP_EEQ:
show_lpm_cmp_eeq(net);
break;
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
show_lpm_cmp_ge(net); show_lpm_cmp_ge(net);
break; break;
@ -616,10 +683,17 @@ static void show_signal(ivl_signal_t net)
/* Only pin-0 of signals is used. If this is /* Only pin-0 of signals is used. If this is
something other then pin-0, report an error. */ something other then pin-0, report an error. */
if (ivl_nexus_ptr_pin(ptr) != 0) if (ivl_nexus_ptr_pin(ptr) != 0) {
fprintf(out, " (pin=%u, should be 0)", fprintf(out, " (pin=%u, should be 0)",
ivl_nexus_ptr_pin(ptr)); ivl_nexus_ptr_pin(ptr));
stub_errors += 1;
}
if (ivl_signal_width(sig) != ivl_signal_width(net)) {
fprintf(out, " (ERROR: Width=%u)",
ivl_signal_width(sig));
stub_errors += 1;
}
fprintf(out, "\n"); fprintf(out, "\n");
} else if ((log = ivl_nexus_ptr_log(ptr))) { } else if ((log = ivl_nexus_ptr_log(ptr))) {
@ -839,12 +913,15 @@ int target_design(ivl_design_t des)
ivl_design_process(des, show_process, 0); ivl_design_process(des, show_process, 0);
fclose(out); fclose(out);
return 0; return stub_errors;
} }
/* /*
* $Log: stub.c,v $ * $Log: stub.c,v $
* Revision 1.97 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.96 2005/01/16 04:20:32 steve * Revision 1.96 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors. * Implement LPM_COMPARE nodes as two-input vector functors.
* *

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.110 2005/01/16 04:20:32 steve Exp $" #ident "$Id: vvp_scope.c,v 1.111 2005/01/22 01:06:55 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -432,6 +432,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_RAM: case IVL_LPM_RAM:
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
@ -442,7 +443,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_MOD: case IVL_LPM_MOD:
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
case IVL_LPM_PART_VP: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV: /* NOTE: This is onlt a partial driver. */ case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
if (ivl_lpm_q(lpm, 0) == nex) { if (ivl_lpm_q(lpm, 0) == nex) {
sprintf(result, "L_%p", lpm); sprintf(result, "L_%p", lpm);
return result; return result;
@ -881,10 +882,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
ltype = "XOR"; ltype = "XOR";
break; break;
case IVL_LO_EEQ:
ltype = "EEQ";
break;
case IVL_LO_PMOS: case IVL_LO_PMOS:
ltype = "PMOS"; ltype = "PMOS";
break; break;
@ -1264,6 +1261,10 @@ static void draw_lpm_cmp(ivl_lpm_t net)
width = ivl_lpm_width(net); width = ivl_lpm_width(net);
switch (ivl_lpm_type(net)) { switch (ivl_lpm_type(net)) {
case IVL_LPM_CMP_EEQ:
type = "eeq";
signed_string = "";
break;
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
type = "ge"; type = "ge";
break; break;
@ -1381,9 +1382,7 @@ static void draw_lpm_concat(ivl_lpm_t net)
} }
/* /*
* Draw == and != gates. This is done as XNOR functors to compare each * XXXX OBSOLETE
* pair of bits. The result is combined with a wide and, or a NAND if
* this is a NE.
*/ */
static void draw_lpm_eq(ivl_lpm_t net) static void draw_lpm_eq(ivl_lpm_t net)
{ {
@ -1683,6 +1682,7 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_ff(net); draw_lpm_ff(net);
return; return;
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
draw_lpm_cmp(net); draw_lpm_cmp(net);
@ -1824,6 +1824,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/* /*
* $Log: vvp_scope.c,v $ * $Log: vvp_scope.c,v $
* Revision 1.111 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.110 2005/01/16 04:20:32 steve * Revision 1.110 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors. * Implement LPM_COMPARE nodes as two-input vector functors.
* *