diff --git a/t-vvm.cc b/t-vvm.cc index 3f3dea0dc..b46390cf2 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) && !defined(macintosh) -#ident "$Id: t-vvm.cc,v 1.110 2000/03/16 23:13:49 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.111 2000/03/17 02:22:03 steve Exp $" #endif # include @@ -1072,9 +1072,9 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate) void target_vvm::lpm_clshift(ostream&os, const NetCLShift*gate) { - os << "static vvm_clshift<" << gate->width() << "," << - gate->width_dist() << "> " << mangle(gate->name()) << ";" - << endl; + os << "static vvm_clshift " << mangle(gate->name()) << "(" << + gate->width() << "," << gate->width_dist() << ");" << + endl; /* Connect the Data input pins... */ for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { @@ -1370,104 +1370,8 @@ void target_vvm::udp(ostream&os, const NetUDP*gate) } -/* - * The non-blocking assignment works by creating an event to do the - * assignment at the right time. The value to be assigned is saved in - * the event and the event function performs the actual assignment. - * - * The net part of the assign generates a type ot represent the - * assignment. Creating instances of this event will be dealt with - * later. - */ void target_vvm::net_assign_nb(ostream&os, const NetAssignNB*net) { -#ifdef REMOVE_ME_WHEN_NB_ASSIGN_IS_DONE - const string name = mangle(net->name()); - unsigned iwid = net->pin_count(); - os << "class " << name << " : public vvm_event {" << endl; - os << " public:" << endl; - - if (net->bmux()) { - os << " " << name << "(const vvm_bitset_t<" - << iwid << ">&v, unsigned idx)" << endl; - os << " : value_(v), idx_(idx) { }" << endl; - } else { - os << " " << name << "(const vvm_bits_t&v)" - << endl; - os << " : value_(v) { }" << endl; - } - os << " void event_function();" << endl; - - os << " private:" << endl; - os << " vvm_bitset_t<" << iwid << ">value_;" << endl; - - if (net->bmux()) - os << " unsigned idx_;" << endl; - - os << "};" << endl; - - - /* Write the event_function to do the actual assignment. */ - - delayed << "void " << name << "::event_function()" << endl; - delayed << "{" << endl; - - if (net->bmux()) { - /* If the assignment is to a single bit (with a mux) - then write a switch statement that selects which pins - to write to. */ - delayed << " switch (idx_) {" << endl; - for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { - const NetObj*cur; - unsigned pin; - - delayed << " case " << idx << ":" << endl; - for (net->pin(idx).next_link(cur, pin) - ; net->pin(idx) != cur->pin(pin) - ; cur->pin(pin).next_link(cur, pin)) { - - const NetObj::Link&lnk = cur->pin(pin); - - // Skip output only pins. - if (cur->pin(pin).get_dir() == NetObj::Link::OUTPUT) - continue; - - delayed << " " << mangle(cur->name()) - << ".set_" << lnk.get_name() - << lnk.get_inst() << ", value_[0]);" << endl; - } - - delayed << " break;" << endl; - } - delayed << " }" << endl; - - } else { - - /* If there is no BMUX, then write all the bits of the - value to all the pins. */ - for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { - const NetObj*cur; - unsigned pin; - - for (net->pin(idx).next_link(cur, pin) - ; net->pin(idx) != cur->pin(pin) - ; cur->pin(pin).next_link(cur, pin)) { - - const NetObj::Link&lnk = cur->pin(pin); - - // Skip output only pins. - if (cur->pin(pin).get_dir() == NetObj::Link::OUTPUT) - continue; - - delayed << " " << mangle(cur->name()) << - ".set_" << lnk.get_name() << "(" - << lnk.get_inst() << ", value_[" << - idx << "]);" << endl; - } - } - } - delayed << "}" << endl; -#endif } void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate) @@ -1597,6 +1501,8 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net) if (net->bmux()) { + //XXXX Not updated to nexus style?? + // This is a bit select. Assign the low bit of the rval // to the selected bit of the lval. string bval = emit_proc_rval(defn, 8, net->bmux()); @@ -1637,45 +1543,11 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net) defn << " }" << endl; } else { -#if 0 - /* Not only is the lvalue signal assigned to, send the - bits to all the other pins that are connected to this - signal. */ - - for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { - const NetObj*cur; - unsigned pin; - map written; - - for (net->pin(idx).next_link(cur, pin) - ; net->pin(idx) != cur->pin(pin) - ; cur->pin(pin).next_link(cur, pin)) { - - // Skip output only pins. - if (cur->pin(pin).get_dir() == NetObj::Link::OUTPUT) - continue; - - // It is possible for a named device to show up - // several times in a link. This is the classic - // case with NetESignal objects, which are - // repeated for each expression that uses it. - if (written[cur->name()]) - continue; - - written[cur->name()] = true; - defn << " " << mangle(cur->name()) << - ".set_" << cur->pin(pin).get_name() << - "(" << cur->pin(pin).get_inst() << - ", " << rval << "[" << idx << "]);" << endl; - } - } -#else for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { string nexus = mangle(nexus_from_link(&net->pin(idx))); defn << " " << nexus << "_nex.reg_assign(" << rval << "[" << idx << "]);" << endl; } -#endif } } @@ -1713,26 +1585,38 @@ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem) void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net) { string rval = emit_proc_rval(defn, 8, net->rval()); + const unsigned long delay = net->rise_time(); if (net->bmux()) { + /* If the l-value has a bit select, set the output bit + to only the desired bit. Evaluate the index and use + that to drive a switch statement. + + XXXX I'm not fully satisfied with this, I might like + better generating a demux device and doing the assign + to the device input. Food for thought. */ + string bval = emit_proc_rval(defn, 8, net->bmux()); - defn << " (new " << mangle(net->name()) << "(" - << rval << ", " << bval << ".as_unsigned())) " - << "-> schedule(" << net->rise_time() << ");" << endl; + defn << " switch (" << bval << ".as_unsigned()) {" << endl; + + for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { + string nexus = mangle(nexus_from_link(&net->pin(idx))); + + defn << " case " << idx << ":" << endl; + defn << " vvm_delyed_assign(" << nexus << + "_nex, " << rval << ", " << delay << ");" << endl; + defn << " break;" << endl; + } + + defn << " }" << endl; } else { - const unsigned long delay = net->rise_time(); for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { string nexus = mangle(nexus_from_link(&net->pin(idx))); defn << " vvm_delayed_assign(" << nexus << "_nex, " << rval << "[" << idx << "], " << delay << ");" << endl; } -#ifdef REMOVE_ME_WHEN_NB_ASSIGN_IS_DONE - defn << " (new " << mangle(net->name()) << "(" - << rval << ")) -> schedule(" << net->rise_time() << - ");" << endl; -#endif } } @@ -2297,6 +2181,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.111 2000/03/17 02:22:03 steve + * vvm_clshift implementation without templates. + * * Revision 1.110 2000/03/16 23:13:49 steve * Update LPM_MUX to nexus style. * diff --git a/vvm/Makefile.in b/vvm/Makefile.in index dac048464..957200ee4 100644 --- a/vvm/Makefile.in +++ b/vvm/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.21 2000/03/16 19:03:04 steve Exp $" +#ident "$Id: Makefile.in,v 1.22 2000/03/17 02:22:03 steve Exp $" # # SHELL = /bin/sh @@ -58,7 +58,8 @@ all: libvvm.a $(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_func.o vvm_gates.o vvm_mult.o \ +O = vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_event.o vvm_func.o \ +vvm_gates.o vvm_mult.o \ vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vpip.o P = vpi_callback.o \ diff --git a/vvm/vvm_clshift.cc b/vvm/vvm_clshift.cc new file mode 100644 index 000000000..171c57321 --- /dev/null +++ b/vvm/vvm_clshift.cc @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2000 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) && !defined(macintosh) +#ident "$Id: vvm_clshift.cc,v 1.1 2000/03/17 02:22:03 steve Exp $" +#endif + +# include "vvm_gates.h" + +/* + * This is the implementation of the LMP_CLSHIFT device. + * + * The device has input/output width if width_ bits, and a distance + * input of wdist_ bits. The inputs are stored in the ibits_ array, + * the data bits first, then the select bits. + */ + +vvm_clshift::vvm_clshift(unsigned wid, unsigned wid_dist) +: width_(wid), wdist_(wid_dist) +{ + ibits_ = new vpip_bit_t[width_ + wdist_]; + out_ = new vvm_nexus::drive_t[width_]; + dist_val_ = width_; + dir_ = V0; + + for (unsigned idx = 0 ; idx < width_+wdist_ ; idx += 1) + ibits_[idx] = Vx; +} + +vvm_clshift::~vvm_clshift() +{ + delete[]out_; + delete[]ibits_; +} + +vvm_nexus::drive_t* vvm_clshift::config_rout(unsigned idx) +{ + return out_+idx; +} + +unsigned vvm_clshift::key_Data(unsigned idx) const +{ + return idx; +} + +unsigned vvm_clshift::key_Distance(unsigned idx) const +{ + return idx+width_; +} + +unsigned vvm_clshift::key_Direction(unsigned) const +{ + return 0x20000; +} + +void vvm_clshift::init_Data(unsigned idx, vpip_bit_t val) +{ + ibits_[idx] = val; +} + +void vvm_clshift::init_Distance(unsigned idx, vpip_bit_t val) +{ + ibits_[width_+idx] = val; + calculate_dist_(); +} + +void vvm_clshift::init_Direction(unsigned, vpip_bit_t val) +{ + dir_ = val; +} + +void vvm_clshift::take_value(unsigned key, vpip_bit_t val) +{ + if (key == 0x20000) { + if (dir_ == val) return; + dir_ = val; + calculate_dist_(); + compute_(); + return; + } + + if (ibits_[key] == val) return; + + ibits_[key] = val; + + if (key < width_) { + if ((dist_val_ + key) >= width_) return; + if ((dist_val_ + key) < 0) return; + out_[dist_val_ + key].set_value(val); + + } else { + calculate_dist_(); + compute_(); + } +} + +void vvm_clshift::compute_() +{ + // The dist_val_ is set to width_ if its value is not fully + // known. In this case, just set the output to unknown. + + if (dist_val_ == (int)width_) { + for (unsigned idx = 0 ; idx < width_ ; idx += 1) + out_[idx].set_value(Vx); + return; + } + + for (unsigned idx = 0 ; idx < width_ ; idx += 1) { + vpip_bit_t val; + if ((idx-dist_val_) >= width_) val = V0; + else if ((idx-dist_val_) < 0) val = V0; + else val = ibits_[idx-dist_val_]; + out_[idx].set_value(val); + } +} + +void vvm_clshift::calculate_dist_() +{ + int tmp = 0; + for (unsigned idx = 0 ; idx < wdist_ ; idx += 1) + switch (ibits_[width_+idx]) { + case V0: + break; + case V1: + tmp |= 1< (int)width_) + tmp = width_; + else if (dir_ == V1) + tmp = -tmp; + dist_val_ = tmp; +} + +/* + * $Log: vvm_clshift.cc,v $ + * Revision 1.1 2000/03/17 02:22:03 steve + * vvm_clshift implementation without templates. + * + */ + diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index b0b4648aa..9cf709e95 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) && !defined(macintosh) -#ident "$Id: vvm_gates.h,v 1.40 2000/03/16 23:13:49 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.41 2000/03/17 02:22:03 steve Exp $" #endif # include "vvm.h" @@ -182,120 +182,42 @@ class vvm_and : public vvm_1bit_out, public vvm_nexus::recvr_t { vpip_bit_t input_[WIDTH]; }; -template +/* + * This class implements LPM_CLSHIFT devices with specified data width + * and selector input width. The direction bit is a single bit input. + */ class vvm_clshift : public vvm_nexus::recvr_t { public: - explicit vvm_clshift() - { dir_ = V0; - dist_val_ = WIDTH; - for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) - data_[idx] = Vx; - for (unsigned idx = 0 ; idx < WDIST ; idx += 1) - dist_[idx] = Vx; - } + vvm_clshift(unsigned wid, unsigned dwid); + ~vvm_clshift(); - ~vvm_clshift() { } + void init_Data(unsigned idx, vpip_bit_t val); + void init_Distance(unsigned idx, vpip_bit_t val); + void init_Direction(unsigned, vpip_bit_t val); - void init_Data(unsigned idx, vpip_bit_t val) - { data_[idx] = val; - } - void init_Distance(unsigned idx, vpip_bit_t val) - { dist_[idx] = val; - calculate_dist_(); - } - void init_Direction(unsigned, vpip_bit_t val) - { dir_ = val; } + vvm_nexus::drive_t* config_rout(unsigned idx); - vvm_nexus::drive_t* config_rout(unsigned idx) - { return out_+idx; } - - unsigned key_Data(unsigned idx) const { return idx; } - unsigned key_Distance(unsigned idx) const { return 0x10000+idx; } - unsigned key_Direction(unsigned) const { return 0x20000; } + unsigned key_Data(unsigned idx) const; + unsigned key_Distance(unsigned idx) const; + unsigned key_Direction(unsigned) const; private: - void take_value(unsigned key, vpip_bit_t val) - { unsigned code = key>>16; - unsigned idx = key & 0xffff; - switch (code) { - case 0: - set_Data(idx, val); - break; - case 1: - set_Distance(idx, val); - break; - default: - set_Direction(idx, val); - break; - } - } - - void set_Data(unsigned idx, vpip_bit_t val) - { if (data_[idx] == val) return; - data_[idx] = val; - if ((dist_val_ + idx) >= WIDTH) return; - if ((dist_val_ + idx) < 0) return; - out_[dist_val_+idx].set_value(val); - } - - void set_Distance(unsigned idx, vpip_bit_t val) - { if (dist_[idx] == val) return; - dist_[idx] = val; - calculate_dist_(); - compute_(); - } - - void set_Direction(unsigned, vpip_bit_t val) - { if (dir_ == val) return; - dir_ = val; - calculate_dist_(); - compute_(); - } + void take_value(unsigned key, vpip_bit_t val); private: + unsigned width_, wdist_; vpip_bit_t dir_; - vpip_bit_t data_[WIDTH]; - vpip_bit_t dist_[WDIST]; - vvm_nexus::drive_t out_[WIDTH]; int dist_val_; - void calculate_dist_() - { int tmp = 0; - for (unsigned idx = 0 ; idx < WDIST ; idx += 1) - switch (dist_[idx]) { - case V0: - break; - case V1: - tmp |= 1< WIDTH) - tmp = WIDTH; - else if (dir_ == V1) - tmp = -tmp; - dist_val_ = tmp; - } + vpip_bit_t*ibits_; + vvm_nexus::drive_t*out_; - void compute_() - { vvm_event*ev; - if (dist_val_ == WIDTH) { - for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) - out_[idx].set_value(Vx); - return; - } - for (int idx = 0 ; idx < WIDTH ; idx += 1) { - vpip_bit_t val; - if ((idx-dist_val_) >= WIDTH) val = V0; - else if ((idx-dist_val_) < 0) val = V0; - else val = data_[idx-dist_val_]; - out_[idx].set_value(val); - } - } + void calculate_dist_(); + void compute_(); }; + template class vvm_compare { public: @@ -1004,6 +926,9 @@ template class vvm_pevent : public vvm_nexus::recvr_t { /* * $Log: vvm_gates.h,v $ + * Revision 1.41 2000/03/17 02:22:03 steve + * vvm_clshift implementation without templates. + * * Revision 1.40 2000/03/16 23:13:49 steve * Update LPM_MUX to nexus style. * @@ -1036,47 +961,5 @@ template class vvm_pevent : public vvm_nexus::recvr_t { * * Revision 1.31 1999/12/05 02:24:09 steve * Synthesize LPM_RAM_DQ for writes into memories. - * - * Revision 1.30 1999/12/02 16:58:58 steve - * Update case comparison (Eric Aardoom). - * - * Revision 1.29 1999/12/02 04:54:11 steve - * Handle mux sel of X, if inputs are equal. - * - * Revision 1.28 1999/11/25 01:34:04 steve - * Reduce more gate templates to use vvm_1bit_out (Eric Aardoom) - * - * Revision 1.27 1999/11/24 04:38:49 steve - * LT and GT fixes from Eric Aardoom. - * - * Revision 1.26 1999/11/22 00:30:52 steve - * Detemplate some and, or and nor methods. - * - * Revision 1.25 1999/11/21 01:16:51 steve - * Fix coding errors handling names of logic devices, - * and add support for buf device in vvm. - * - * Revision 1.24 1999/11/21 00:13:09 steve - * Support memories in continuous assignments. - * - * Revision 1.23 1999/11/15 00:42:31 steve - * Fixup to include right shift support. - * - * Revision 1.22 1999/11/14 23:43:46 steve - * Support combinatorial comparators. - * - * Revision 1.21 1999/11/14 20:24:28 steve - * Add support for the LPM_CLSHIFT device. - * - * Revision 1.20 1999/11/14 18:22:12 steve - * Fix NAND gate support to use named pins. - * - * Revision 1.19 1999/11/13 03:46:52 steve - * Support the LPM_MUX in vvm. - * - * Revision 1.18 1999/11/01 02:07:41 steve - * Add the synth functor to do generic synthesis - * and add the LPM_FF device to handle rows of - * flip-flops. */ #endif