diff --git a/Makefile.in b/Makefile.in index 32d78c3ad..879630141 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.24 1999/10/23 16:55:51 steve Exp $" +#ident "$Id: Makefile.in,v 1.25 1999/10/31 20:08:24 steve Exp $" # # SHELL = /bin/sh @@ -68,8 +68,8 @@ distclean: clean TT = t-null.o t-verilog.o t-vvm.o t-xnf.o FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.o -O = main.o cprop.o design_dump.o elaborate.o elab_expr.o emit.o eval.o \ -eval_tree.o functor.o \ +O = main.o cprop.o design_dump.o elaborate.o elab_expr.o elab_net.o \ +emit.o eval.o eval_tree.o functor.o \ lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o \ diff --git a/PExpr.h b/PExpr.h index 5af3859f1..c8bfb6513 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.h,v 1.21 1999/10/31 04:11:27 steve Exp $" +#ident "$Id: PExpr.h,v 1.22 1999/10/31 20:08:24 steve Exp $" #endif # include @@ -78,6 +78,7 @@ class PExpr : public LineInfo { // identifiers and any other module specific interpretations // of expresions. virtual bool is_constant(Module*) const; + }; ostream& operator << (ostream&, const PExpr&); @@ -241,6 +242,12 @@ class PEBinary : public PExpr { char op_; PExpr*left_; PExpr*right_; + + NetNet* elaborate_net_add_(Design*des, const string&path, + unsigned lwidth, + unsigned long rise, + unsigned long fall, + unsigned long decay) const; }; /* @@ -290,6 +297,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.22 1999/10/31 20:08:24 steve + * Include subtraction in LPM_ADD_SUB device. + * * Revision 1.21 1999/10/31 04:11:27 steve * Add to netlist links pin name and instance number, * and arrange in vvm for pin connections by name diff --git a/design_dump.cc b/design_dump.cc index 4487f7104..0e303bc48 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: design_dump.cc,v 1.51 1999/10/31 04:11:27 steve Exp $" +#ident "$Id: design_dump.cc,v 1.52 1999/10/31 20:08:24 steve Exp $" #endif /* @@ -127,6 +127,7 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl; dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); } void NetAssign::dump_node(ostream&o, unsigned ind) const @@ -797,6 +798,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.52 1999/10/31 20:08:24 steve + * Include subtraction in LPM_ADD_SUB device. + * * Revision 1.51 1999/10/31 04:11:27 steve * Add to netlist links pin name and instance number, * and arrange in vvm for pin connections by name diff --git a/elab_net.cc b/elab_net.cc new file mode 100644 index 000000000..db277f9d6 --- /dev/null +++ b/elab_net.cc @@ -0,0 +1,341 @@ +/* + * Copyright (c) 1999 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) +#ident "$Id: elab_net.cc,v 1.1 1999/10/31 20:08:24 steve Exp $" +#endif + +# include "PExpr.h" +# include "netlist.h" + +/* + * Elaborating binary operations generally involves elaborating the + * left and right expressions, then making an output wire and + * connecting the lot together with the right kind of gate. + */ +NetNet* PEBinary::elaborate_net(Design*des, const string&path, + unsigned width, + unsigned long rise, + unsigned long fall, + unsigned long decay) const +{ + switch (op_) { + case '+': + case '-': + return elaborate_net_add_(des, path, width, rise, fall, decay); + } + + NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0), + *rsig = right_->elaborate_net(des, path, width, 0, 0, 0); + if (lsig == 0) { + cerr << get_line() << ": error: Cannot elaborate "; + left_->dump(cerr); + cerr << endl; + return 0; + } + if (rsig == 0) { + cerr << get_line() << ": error: Cannot elaborate "; + right_->dump(cerr); + cerr << endl; + return 0; + } + + NetNet*osig; + NetNode*gate; + NetNode*gate_t; + + switch (op_) { + case '^': // XOR + assert(lsig->pin_count() == rsig->pin_count()); + osig = new NetNet(des->local_symbol(path), NetNet::WIRE, + lsig->pin_count()); + osig->local_flag(true); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + gate = new NetLogic(des->local_symbol(path), 3, + NetLogic::XOR); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + des->add_signal(osig); + break; + + case '&': // AND + assert(lsig->pin_count() == rsig->pin_count()); + osig = new NetNet(des->local_symbol(path), NetNet::WIRE, + lsig->pin_count()); + osig->local_flag(true); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + gate = new NetLogic(des->local_symbol(path), 3, + NetLogic::AND); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + des->add_signal(osig); + break; + + case '|': // Bitwise OR + assert(lsig->pin_count() == rsig->pin_count()); + osig = new NetNet(des->local_symbol(path), NetNet::WIRE, + lsig->pin_count()); + osig->local_flag(true); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + gate = new NetLogic(des->local_symbol(path), 3, + NetLogic::OR); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + des->add_signal(osig); + break; + + case 'a': // && (logical AND) + gate = new NetLogic(des->local_symbol(path), 3, NetLogic::AND); + + // The first OR gate returns 1 if the left value is true... + if (lsig->pin_count() > 1) { + gate_t = new NetLogic(des->local_symbol(path), + 1+lsig->pin_count(), NetLogic::OR); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) + connect(gate_t->pin(idx+1), lsig->pin(idx)); + connect(gate->pin(1), gate_t->pin(0)); + des->add_node(gate_t); + } else { + connect(gate->pin(1), lsig->pin(0)); + } + + // The second OR gate returns 1 if the right value is true... + if (rsig->pin_count() > 1) { + gate_t = new NetLogic(des->local_symbol(path), + 1+rsig->pin_count(), NetLogic::OR); + for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) + connect(gate_t->pin(idx+1), rsig->pin(idx)); + connect(gate->pin(2), gate_t->pin(0)); + des->add_node(gate_t); + } else { + connect(gate->pin(2), rsig->pin(0)); + } + + // The output is the AND of the two logic values. + osig = new NetNet(des->local_symbol(path), NetNet::WIRE); + osig->local_flag(true); + connect(gate->pin(0), osig->pin(0)); + des->add_signal(osig); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + break; + + case 'E': // === (Case equals) + + // The comparison generates gates to bitwise compare + // each pair, and AND all the comparison results. + assert(lsig->pin_count() == rsig->pin_count()); + osig = new NetNet(des->local_symbol(path), NetNet::WIRE); + osig->local_flag(true); + gate = new NetLogic(des->local_symbol(path), + 1+lsig->pin_count(), + NetLogic::AND); + connect(gate->pin(0), osig->pin(0)); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + gate_t = new NetCaseCmp(des->local_symbol(path)); + connect(gate_t->pin(1), lsig->pin(idx)); + connect(gate_t->pin(2), rsig->pin(idx)); + connect(gate_t->pin(0), gate->pin(idx+1)); + des->add_node(gate_t); + + // Attach a label to this intermediate wire + NetNet*tmp = new NetNet(des->local_symbol(path), + NetNet::WIRE); + tmp->local_flag(true); + connect(gate_t->pin(0), tmp->pin(0)); + des->add_signal(tmp); + } + des->add_signal(osig); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + break; + + case 'e': // == + assert(lsig->pin_count() == rsig->pin_count()); + osig = new NetNet(des->local_symbol(path), NetNet::WIRE); + osig->local_flag(true); + gate = new NetLogic(des->local_symbol(path), + 1+lsig->pin_count(), + NetLogic::AND); + connect(gate->pin(0), osig->pin(0)); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + gate_t = new NetLogic(des->local_symbol(path), 3, + NetLogic::XNOR); + connect(gate_t->pin(1), lsig->pin(idx)); + connect(gate_t->pin(2), rsig->pin(idx)); + connect(gate_t->pin(0), gate->pin(idx+1)); + des->add_node(gate_t); + } + des->add_signal(osig); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + break; + + case 'n': // != + assert(lsig->pin_count() == rsig->pin_count()); + osig = new NetNet(des->local_symbol(path), NetNet::WIRE); + osig->local_flag(true); + gate = new NetLogic(des->local_symbol(path), + 1+lsig->pin_count(), + NetLogic::OR); + connect(gate->pin(0), osig->pin(0)); + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + gate_t = new NetLogic(des->local_symbol(path), 3, + NetLogic::XOR); + connect(gate_t->pin(1), lsig->pin(idx)); + connect(gate_t->pin(2), rsig->pin(idx)); + connect(gate_t->pin(0), gate->pin(idx+1)); + des->add_node(gate_t); + } + des->add_signal(osig); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + break; + + case '+': + assert(0); + break; + + case 'l': + case 'r': + cerr << get_line() << ": sorry: combinational shift" + " not supported here." << endl; + des->errors += 1; + osig = 0; + break; + default: + cerr << get_line() << ": internal error: unsupported" + " combinational operator (" << op_ << ")." << endl; + des->errors += 1; + osig = 0; + } + + if (NetTmp*tmp = dynamic_cast(lsig)) + delete tmp; + if (NetTmp*tmp = dynamic_cast(rsig)) + delete tmp; + + return osig; +} + +/* + * Elaborate the structural +/- as an AddSub object. Connect DataA and + * DataB to the parameters, and connect the output signal to the + * Result. In this context, the device is a combinational adder with + * fixed direction, so leave Add_Sub unconnected and set the + * LPM_Direction property. + */ +NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path, + unsigned lwidth, + unsigned long rise, + unsigned long fall, + unsigned long decay) const +{ + NetNet*lsig = left_->elaborate_net(des, path, lwidth, 0, 0, 0), + *rsig = right_->elaborate_net(des, path, lwidth, 0, 0, 0); + if (lsig == 0) { + cerr << get_line() << ": error: Cannot elaborate "; + left_->dump(cerr); + cerr << endl; + return 0; + } + if (rsig == 0) { + cerr << get_line() << ": error: Cannot elaborate "; + right_->dump(cerr); + cerr << endl; + return 0; + } + + NetNet*osig; + NetNode*gate; + NetNode*gate_t; + + string name = des->local_symbol(path); + unsigned width = lsig->pin_count(); + if (rsig->pin_count() > lsig->pin_count()) + width = rsig->pin_count(); + + // Make the adder as wide as the widest operand + osig = new NetNet(des->local_symbol(path), NetNet::WIRE, width); + NetAddSub*adder = new NetAddSub(name, width); + + // Connect the adder to the various parts. + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) + connect(lsig->pin(idx), adder->pin_DataA(idx)); + for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) + connect(rsig->pin(idx), adder->pin_DataB(idx)); + for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) + connect(osig->pin(idx), adder->pin_Result(idx)); + + gate = adder; + des->add_signal(osig); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + + switch (op_) { + case '+': + gate->attribute("LPM_Direction", "ADD"); + break; + case '-': + gate->attribute("LPM_Direction", "SUB"); + break; + } + + if (NetTmp*tmp = dynamic_cast(lsig)) + delete tmp; + if (NetTmp*tmp = dynamic_cast(rsig)) + delete tmp; + + return osig; +} + +/* + * $Log: elab_net.cc,v $ + * Revision 1.1 1999/10/31 20:08:24 steve + * Include subtraction in LPM_ADD_SUB device. + * + */ + diff --git a/elaborate.cc b/elaborate.cc index 26320f93f..37ad2add3 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: elaborate.cc,v 1.119 1999/10/31 04:11:27 steve Exp $" +#ident "$Id: elaborate.cc,v 1.120 1999/10/31 20:08:24 steve Exp $" #endif /* @@ -591,263 +591,6 @@ void PGModule::elaborate(Design*des, const string&path) const cerr << get_line() << ": error: Unknown module: " << type_ << endl; } -/* - * Elaborating binary operations generally involves elaborating the - * left and right expressions, then making an output wire and - * connecting the lot together with the right kind of gate. - */ -NetNet* PEBinary::elaborate_net(Design*des, const string&path, - unsigned width, - unsigned long rise, - unsigned long fall, - unsigned long decay) const -{ - NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0), - *rsig = right_->elaborate_net(des, path, width, 0, 0, 0); - if (lsig == 0) { - cerr << get_line() << ": error: Cannot elaborate "; - left_->dump(cerr); - cerr << endl; - return 0; - } - if (rsig == 0) { - cerr << get_line() << ": error: Cannot elaborate "; - right_->dump(cerr); - cerr << endl; - return 0; - } - - NetNet*osig; - NetNode*gate; - NetNode*gate_t; - - switch (op_) { - case '^': // XOR - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::XOR); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); - break; - - case '&': // AND - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::AND); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); - break; - - case '|': // Bitwise OR - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::OR); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); - break; - - case 'a': // && (logical AND) - gate = new NetLogic(des->local_symbol(path), 3, NetLogic::AND); - - // The first OR gate returns 1 if the left value is true... - if (lsig->pin_count() > 1) { - gate_t = new NetLogic(des->local_symbol(path), - 1+lsig->pin_count(), NetLogic::OR); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) - connect(gate_t->pin(idx+1), lsig->pin(idx)); - connect(gate->pin(1), gate_t->pin(0)); - des->add_node(gate_t); - } else { - connect(gate->pin(1), lsig->pin(0)); - } - - // The second OR gate returns 1 if the right value is true... - if (rsig->pin_count() > 1) { - gate_t = new NetLogic(des->local_symbol(path), - 1+rsig->pin_count(), NetLogic::OR); - for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) - connect(gate_t->pin(idx+1), rsig->pin(idx)); - connect(gate->pin(2), gate_t->pin(0)); - des->add_node(gate_t); - } else { - connect(gate->pin(2), rsig->pin(0)); - } - - // The output is the AND of the two logic values. - osig = new NetNet(des->local_symbol(path), NetNet::WIRE); - osig->local_flag(true); - connect(gate->pin(0), osig->pin(0)); - des->add_signal(osig); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - break; - - case 'E': // === (Case equals) - - // The comparison generates gates to bitwise compare - // each pair, and AND all the comparison results. - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(des->local_symbol(path), NetNet::WIRE); - osig->local_flag(true); - gate = new NetLogic(des->local_symbol(path), - 1+lsig->pin_count(), - NetLogic::AND); - connect(gate->pin(0), osig->pin(0)); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate_t = new NetCaseCmp(des->local_symbol(path)); - connect(gate_t->pin(1), lsig->pin(idx)); - connect(gate_t->pin(2), rsig->pin(idx)); - connect(gate_t->pin(0), gate->pin(idx+1)); - des->add_node(gate_t); - - // Attach a label to this intermediate wire - NetNet*tmp = new NetNet(des->local_symbol(path), - NetNet::WIRE); - tmp->local_flag(true); - connect(gate_t->pin(0), tmp->pin(0)); - des->add_signal(tmp); - } - des->add_signal(osig); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - break; - - case 'e': // == - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(des->local_symbol(path), NetNet::WIRE); - osig->local_flag(true); - gate = new NetLogic(des->local_symbol(path), - 1+lsig->pin_count(), - NetLogic::AND); - connect(gate->pin(0), osig->pin(0)); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate_t = new NetLogic(des->local_symbol(path), 3, - NetLogic::XNOR); - connect(gate_t->pin(1), lsig->pin(idx)); - connect(gate_t->pin(2), rsig->pin(idx)); - connect(gate_t->pin(0), gate->pin(idx+1)); - des->add_node(gate_t); - } - des->add_signal(osig); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - break; - - case 'n': // != - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(des->local_symbol(path), NetNet::WIRE); - osig->local_flag(true); - gate = new NetLogic(des->local_symbol(path), - 1+lsig->pin_count(), - NetLogic::OR); - connect(gate->pin(0), osig->pin(0)); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate_t = new NetLogic(des->local_symbol(path), 3, - NetLogic::XOR); - connect(gate_t->pin(1), lsig->pin(idx)); - connect(gate_t->pin(2), rsig->pin(idx)); - connect(gate_t->pin(0), gate->pin(idx+1)); - des->add_node(gate_t); - } - des->add_signal(osig); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - break; - - // Elaborate the structural + as an AddSub - // object. Connect DataA and DataB to the parameters, - // and connect the output signal to the Result. - case '+': { - string name = des->local_symbol(path); - unsigned width = lsig->pin_count(); - if (rsig->pin_count() > lsig->pin_count()) - width = rsig->pin_count(); - - // Make the adder as wide as the widest operand - osig = new NetNet(des->local_symbol(path), - NetNet::WIRE, width); - NetAddSub*adder = new NetAddSub(name, width); - - // Connect the adder to the various parts. - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) - connect(lsig->pin(idx), adder->pin_DataA(idx)); - for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) - connect(rsig->pin(idx), adder->pin_DataB(idx)); - for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) - connect(osig->pin(idx), adder->pin_Result(idx)); - - gate = adder; - des->add_signal(osig); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - break; - } - - case 'l': - case 'r': - cerr << get_line() << ": sorry: combinational shift" - " not supported here." << endl; - des->errors += 1; - osig = 0; - break; - default: - cerr << get_line() << ": internal error: unsupported" - " combinational operator (" << op_ << ")." << endl; - des->errors += 1; - osig = 0; - } - - if (NetTmp*tmp = dynamic_cast(lsig)) - delete tmp; - if (NetTmp*tmp = dynamic_cast(rsig)) - delete tmp; - - return osig; -} - /* * The concatenation operator, as a net, is a wide signal that is * connected to all the pins of the elaborated expression nets. @@ -2661,6 +2404,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.120 1999/10/31 20:08:24 steve + * Include subtraction in LPM_ADD_SUB device. + * * Revision 1.119 1999/10/31 04:11:27 steve * Add to netlist links pin name and instance number, * and arrange in vvm for pin connections by name diff --git a/t-vvm.cc b/t-vvm.cc index 9b9138003..067846363 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-vvm.cc,v 1.69 1999/10/31 04:11:28 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.70 1999/10/31 20:08:24 steve Exp $" #endif # include @@ -824,6 +824,15 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate) emit_gate_outputfun_(gate, pin); } + if (gate->attribute("LPM_Direction") == "ADD") { + init_code << " " << mangle(gate->name()) << + ".init_Add_Sub(0, V1);" << endl; + + } else if (gate->attribute("LPM_Direction") == "SUB") { + init_code << " " << mangle(gate->name()) << + ".init_Add_Sub(0, V0);" << endl; + + } } void target_vvm::logic(ostream&os, const NetLogic*gate) @@ -1793,6 +1802,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.70 1999/10/31 20:08:24 steve + * Include subtraction in LPM_ADD_SUB device. + * * Revision 1.69 1999/10/31 04:11:28 steve * Add to netlist links pin name and instance number, * and arrange in vvm for pin connections by name diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index 7148741f1..ee624b2d3 100644 --- a/vvm/vvm_gates.h +++ b/vvm/vvm_gates.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_gates.h,v 1.16 1999/10/31 04:11:28 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.17 1999/10/31 20:08:24 steve Exp $" #endif # include "vvm.h" @@ -51,12 +51,15 @@ class vvm_out_event : public vvm_event { /* * This template implements the LPM_ADD_SUB device type. The width of - * the device is a template parameter. + * the device is a template parameter. The device handles addition and + * subtraction, selectable by the Add_Sub input. When configured as a + * subtractor, the device works by adding the 2s complement of + * DataB. */ template class vvm_add_sub { public: - vvm_add_sub() { } + vvm_add_sub() : ndir_(V0) { } void config_rout(unsigned idx, vvm_out_event::action_t a) { o_[idx] = a; @@ -70,6 +73,10 @@ template class vvm_add_sub { { b_[idx] = val; } + void init_Add_Sub(unsigned, vpip_bit_t val) + { ndir_ = not(val); + } + void set_DataA(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { a_[idx] = val; compute_(sim); @@ -84,13 +91,17 @@ template class vvm_add_sub { vpip_bit_t b_[WIDTH]; vpip_bit_t r_[WIDTH]; + // this is the inverse of the Add_Sub port. It is 0 for add, + // and 1 for subtract. + vpip_bit_t ndir_; + vvm_out_event::action_t o_[WIDTH]; void compute_(vvm_simulation*sim) - { vpip_bit_t carry = V0; + { vpip_bit_t carry = ndir_; for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) { vpip_bit_t val; - val = add_with_carry(a_[idx], b_[idx], carry); + val = add_with_carry(a_[idx], b_[idx] ^ ndir_, carry); if (val == r_[idx]) continue; r_[idx] = val; if (o_[idx] == 0) continue; @@ -588,6 +599,9 @@ template class vvm_pevent { /* * $Log: vvm_gates.h,v $ + * Revision 1.17 1999/10/31 20:08:24 steve + * Include subtraction in LPM_ADD_SUB device. + * * Revision 1.16 1999/10/31 04:11:28 steve * Add to netlist links pin name and instance number, * and arrange in vvm for pin connections by name