diff --git a/elab_net.cc b/elab_net.cc index 65ddc71e9..15f2f328f 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -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 * 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 */ #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 # include "config.h" @@ -633,44 +633,18 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, } case 'E': // Case equals (===) - case 'N': // Case equals (!==) - // 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); + gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth); connect(gate->pin(0), osig->pin(0)); - for (unsigned idx = 0 ; idx < dwidth ; idx += 1) { - NetCaseCmp*cmp = new NetCaseCmp(scope, - 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 + connect(gate->pin(1), lsig->pin(0)); + connect(gate->pin(2), rsig->pin(0)); break; + case 'N': // Case equals (!==) + cerr << get_line() << ": internal error: " + << "Forgot how to elaborate !==." << endl; + des->errors += 1; + gate = 0; + break; case 'e': // == @@ -2482,6 +2456,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $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 * Implement LPM_COMPARE nodes as two-input vector functors. * diff --git a/emit.cc b/emit.cc index 0456a65f2..d15eb5722 100644 --- a/emit.cc +++ b/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.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 # include "config.h" @@ -361,13 +361,12 @@ void NetWhile::emit_proc_recurse(struct target_t*tgt) const 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 (rc == false) - return false; + if (tgt->start_design(this) == false) + return -2; // enumerate the scopes for (list::const_iterator scope = root_scopes_.begin(); @@ -376,27 +375,36 @@ bool Design::emit(struct target_t*tgt) const // emit nodes + bool nodes_rc = true; if (nodes_) { NetNode*cur = nodes_->node_next_; do { - rc = rc && cur->emit_node(tgt); + nodes_rc = nodes_rc && cur->emit_node(tgt); cur = cur->node_next_; } while (cur != nodes_->node_next_); } // emit task and function definitions + bool tasks_rc = true; for (list::const_iterator scope = root_scopes_.begin(); scope != root_scopes_.end(); scope++) - rc &= (*scope)->emit_defs(tgt); + tasks_rc &= (*scope)->emit_defs(tgt); // emit the processes + bool proc_rc = true; 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 = false; + rc = tgt->end_design(this); + + if (nodes_rc == false) + return -1; + if (tasks_rc == false) + return -2; + if (proc_rc == false) + return -3; return rc; } @@ -492,7 +500,7 @@ void NetEVariable::expr_scan(struct expr_scan_t*tgt) const 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) { 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 << " not found." << endl; - return false; + return -1; } /* * $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 * Unify elaboration of l-values for all proceedural assignments, * including assing, cassign and force. diff --git a/ivl_target.h b/ivl_target.h index 853a92635..5767e0444 100644 --- a/ivl_target.h +++ b/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.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 #ifdef __cplusplus @@ -87,6 +87,10 @@ _BEGIN_DECL * this includes just about every directional device that has a * single output, including logic gates and nmos, pmos and cmos * 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 * Structural links within an elaborated design are connected @@ -214,8 +218,6 @@ typedef enum ivl_logic_e { IVL_LO_XNOR = 18, IVL_LO_XOR = 19, - IVL_LO_EEQ = 20, - IVL_LO_UDP = 21 } ivl_logic_t; @@ -223,10 +225,12 @@ typedef enum ivl_logic_e { typedef enum ivl_lpm_type_e { IVL_LPM_ADD = 0, IVL_LPM_CONCAT = 16, + IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */ IVL_LPM_CMP_EQ = 10, IVL_LPM_CMP_GE = 1, IVL_LPM_CMP_GT = 2, IVL_LPM_CMP_NE = 11, + IVL_LPM_CMP_NEE= 19, //* Case NE (!==) */ IVL_LPM_DIVIDE = 12, IVL_LPM_FF = 3, 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 * indeed the width of the part, even though it is written to a wider * 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) */ @@ -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 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 ivl core. This function is how the target module is invoked. */ @@ -1413,6 +1429,9 @@ _END_DECL /* * $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 * Use PartSelect/PV and VP to handle part selects through ports. * diff --git a/main.cc b/main.cc index b7b6024cc..73ae96d4e 100644 --- a/main.cc +++ b/main.cc @@ -19,7 +19,7 @@ const char COPYRIGHT[] = * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: main.cc,v 1.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 # include "config.h" @@ -701,12 +701,18 @@ int main(int argc, char*argv[]) cout << "CODE GENERATION -t "< 0) { + cerr << "error: Code generation had " + << emit_rc << " errors." + << endl; return 1; } + if (emit_rc < 0) { + cerr << "error: Code generator failure: " << emit_rc << endl; + return -1; + } if (verbose_flag) { if (times_flag) { @@ -748,6 +754,9 @@ int main(int argc, char*argv[]) /* * $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 * Rework of internals to carry vectors through nexus instead * of single bits. Make the ivl, tgt-vvp and vvp initial changes diff --git a/netlist.cc b/netlist.cc index 9dc09eae6..ae4f2f7e3 100644 --- a/netlist.cc +++ b/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.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 # include "config.h" @@ -1650,8 +1650,8 @@ unsigned NetBUFZ::width() const return width_; } -NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n) -: NetNode(s, n, 3) +NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid) +: NetNode(s, n, 3), width_(wid) { 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); @@ -1662,6 +1662,11 @@ NetCaseCmp::~NetCaseCmp() { } +unsigned NetCaseCmp::width() const +{ + return width_; +} + NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e) : expr_(ex), if_(i), else_(e) { @@ -2342,6 +2347,9 @@ const NetProc*NetTaskDef::proc() const /* * $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 * Implement LPM_COMPARE nodes as two-input vector functors. * diff --git a/netlist.h b/netlist.h index 9f976aaad..0ad237804 100644 --- a/netlist.h +++ b/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.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 /* @@ -1241,7 +1241,10 @@ class NetBUFZ : public NetNode { /* * This node is used to represent case equality in combinational * 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: * @@ -1252,11 +1255,16 @@ class NetBUFZ : public NetNode { class NetCaseCmp : public NetNode { public: - explicit NetCaseCmp(NetScope*s, perm_string n); + explicit NetCaseCmp(NetScope*s, perm_string n, unsigned wid); ~NetCaseCmp(); + unsigned width() const; + virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; + + private: + unsigned width_; }; /* @@ -3336,7 +3344,7 @@ class Design { // Iterate over the design... void dump(ostream&) const; 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 // detected. It prevents code being emitted. @@ -3411,6 +3419,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $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 * Implement LPM_COMPARE nodes as two-input vector functors. * diff --git a/t-dll-api.cc b/t-dll-api.cc index 02c449688..c2f5725da 100644 --- a/t-dll-api.cc +++ b/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.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 # include "config.h" @@ -759,6 +759,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) assert(net); switch (net->type) { case IVL_LPM_ADD: + case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_GE: 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_EQ: case IVL_LPM_CMP_NE: + case IVL_LPM_CMP_EEQ: assert(idx == 0); return net->u_.arith.q; @@ -1013,6 +1015,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net) case IVL_LPM_MUX: return 0; case IVL_LPM_ADD: + case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: @@ -1067,6 +1070,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) case IVL_LPM_MUX: return net->u_.mux.width; case IVL_LPM_ADD: + case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_GE: 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 $ + * 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 * Use PartSelect/PV and VP to handle part selects through ports. * diff --git a/t-dll.cc b/t-dll.cc index f75ad0904..7ca669d12 100644 --- a/t-dll.cc +++ b/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.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 # include "config.h" @@ -914,35 +914,36 @@ void dll_target::logic(const NetLogic*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 - device. */ + const Nexus*nex; - obj->npins_ = 3; - obj->pins_ = new ivl_nexus_t[obj->npins_]; - 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); - } + nex = net->pin(1).nexus(); + assert(nex->t_cookie()); - //assert(net->scope()); - //ivl_scope_t scope = find_scope(des_, net->scope()); - //assert(scope); - ivl_scope_t scope = des_.roots_[0]; + obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); - obj->scope_= scope; - obj->name_ = net->name(); + nex = net->pin(2).nexus(); + assert(nex->t_cookie()); - obj->delay[0] = net->rise_time(); - obj->delay[1] = net->fall_time(); - obj->delay[2] = net->decay_time(); + obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); - 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 $ + * 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 * Implement LPM_COMPARE nodes as two-input vector functors. * diff --git a/target.h b/target.h index 6be0280e0..954aaa75a 100644 --- a/target.h +++ b/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.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 # include "netlist.h" @@ -154,7 +154,7 @@ struct expr_scan_t { /* 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 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, 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 $ + * 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 * Unify elaboration of l-values for all proceedural assignments, * including assing, cassign and force. diff --git a/tgt-stub/priv.h b/tgt-stub/priv.h index 77c26c758..7205a32b2 100644 --- a/tgt-stub/priv.h +++ b/tgt-stub/priv.h @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include @@ -29,6 +29,12 @@ */ 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. */ diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index b6fc0a014..78ad12c2c 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -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 * 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 */ #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 # include "config.h" @@ -25,6 +25,30 @@ # include 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 @@ -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: \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 * 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, " 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_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))); 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; - } - } + unsigned signal_width = width_of_nexus(nex); fprintf(out, " I%u: %s (width=%u)\n", idx, ivl_nexus_name(nex), signal_width); @@ -276,6 +339,10 @@ static void show_lpm(ivl_lpm_t net) break; } + case IVL_LPM_CMP_EEQ: + show_lpm_cmp_eeq(net); + break; + case IVL_LPM_CMP_GE: show_lpm_cmp_ge(net); break; @@ -616,10 +683,17 @@ static void show_signal(ivl_signal_t net) /* Only pin-0 of signals is used. If this is 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)", 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"); } 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); fclose(out); - return 0; + return stub_errors; } /* * $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 * Implement LPM_COMPARE nodes as two-input vector functors. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index ddab11957..7a373dfe0 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # 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_ADD: case IVL_LPM_CONCAT: + case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: 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_UFUNC: 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) { sprintf(result, "L_%p", lpm); return result; @@ -881,10 +882,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) ltype = "XOR"; break; - case IVL_LO_EEQ: - ltype = "EEQ"; - break; - case IVL_LO_PMOS: ltype = "PMOS"; break; @@ -1264,6 +1261,10 @@ static void draw_lpm_cmp(ivl_lpm_t net) width = ivl_lpm_width(net); switch (ivl_lpm_type(net)) { + case IVL_LPM_CMP_EEQ: + type = "eeq"; + signed_string = ""; + break; case IVL_LPM_CMP_GE: type = "ge"; 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 - * pair of bits. The result is combined with a wide and, or a NAND if - * this is a NE. + * XXXX OBSOLETE */ 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); return; + case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: draw_lpm_cmp(net); @@ -1824,6 +1824,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $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 * Implement LPM_COMPARE nodes as two-input vector functors. *