From 51e96a2d8ba535e77f83a81f4ad8265357b9e6be Mon Sep 17 00:00:00 2001 From: steve Date: Fri, 17 Mar 2000 17:25:53 +0000 Subject: [PATCH] Adder and comparator in nexus style. --- t-vvm.cc | 100 +++++++++++++++++------- vvm/Makefile.in | 7 +- vvm/vvm_add_sub.cc | 121 +++++++++++++++++++++++++++++ vvm/vvm_compare.cc | 123 ++++++++++++++++++++++++++++++ vvm/vvm_gates.h | 186 +++++++++++++-------------------------------- 5 files changed, 375 insertions(+), 162 deletions(-) create mode 100644 vvm/vvm_add_sub.cc create mode 100644 vvm/vvm_compare.cc diff --git a/t-vvm.cc b/t-vvm.cc index 8298cfb88..530ba82ff 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.112 2000/03/17 03:05:13 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.113 2000/03/17 17:25:53 steve Exp $" #endif # include @@ -1014,8 +1014,8 @@ void target_vvm::emit_gate_outputfun_(const NetNode*gate, unsigned gpin) void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate) { - os << "static vvm_add_sub<" << gate->width() << "> " << - mangle(gate->name()) << ";" << endl; + os << "static vvm_add_sub " << + mangle(gate->name()) << "(" << gate->width() << ");" << endl; /* Connect the DataA inputs. */ @@ -1103,39 +1103,50 @@ void target_vvm::lpm_clshift(ostream&os, const NetCLShift*gate) void target_vvm::lpm_compare(ostream&os, const NetCompare*gate) { - os << "static vvm_compare<" << gate->width() << "> " << - mangle(gate->name()) << ";" << endl; + string mname = mangle(gate->name()); - if (gate->pin_ALB().is_linked()) { - unsigned pin = gate->pin_ALB().get_pin(); - string outfun = defn_gate_outputfun_(os,gate,pin); - init_code << " " << mangle(gate->name()) << - ".config_ALB_out(&" << outfun << ");" << endl; - emit_gate_outputfun_(gate,pin); + os << "static vvm_compare " << mname << "(" << gate->width() << + ");" << endl; + + /* Connect DataA inputs... */ + for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { + string nexus = mangle(nexus_from_link(&gate->pin_DataA(idx))); + init_code << " " << nexus << "_nex.connect(&" << mname + << ", " << mname << ".key_DataA(" << idx + << "));" << endl; } - if (gate->pin_ALEB().is_linked()) { - unsigned pin = gate->pin_ALEB().get_pin(); - string outfun = defn_gate_outputfun_(os, gate, pin); - init_code << " " << mangle(gate->name()) << - ".config_ALEB_out(&" << outfun << ");" << endl; - emit_gate_outputfun_(gate, pin); + /* Connect DataB inputs... */ + for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { + string nexus = mangle(nexus_from_link(&gate->pin_DataB(idx))); + init_code << " " << nexus << "_nex.connect(&" << mname + << ", " << mname << ".key_DataB(" << idx + << "));" << endl; + } + + if (gate->pin_ALB().is_linked()) { + string nexus = mangle(nexus_from_link(&gate->pin_ALB())); + init_code << " " << nexus << "_nex.connect(" << mname + << ".config_ALB_out());" << endl; } if (gate->pin_AGB().is_linked()) { - unsigned pin = gate->pin_AGB().get_pin(); - string outfun = defn_gate_outputfun_(os,gate,pin); - init_code << " " << mangle(gate->name()) << - ".config_AGB_out(&" << outfun << ");" << endl; - emit_gate_outputfun_(gate,pin); + string nexus = mangle(nexus_from_link(&gate->pin_AGB())); + init_code << " " << nexus << "_nex.connect(" << mname + << ".config_AGB_out());" << endl; + } + + + if (gate->pin_ALEB().is_linked()) { + string nexus = mangle(nexus_from_link(&gate->pin_ALEB())); + init_code << " " << nexus << "_nex.connect(" << mname + << ".config_ALEB_out());" << endl; } if (gate->pin_AGEB().is_linked()) { - unsigned pin = gate->pin_AGEB().get_pin(); - string outfun = defn_gate_outputfun_(os, gate, pin); - init_code << " " << mangle(gate->name()) << - ".config_AGEB_out(&" << outfun << ");" << endl; - emit_gate_outputfun_(gate, pin); + string nexus = mangle(nexus_from_link(&gate->pin_AGEB())); + init_code << " " << nexus << "_nex.connect(" << mname + << ".config_AGEB_out());" << endl; } } @@ -1510,6 +1521,38 @@ void target_vvm::start_process(ostream&os, const NetProcTop*proc) */ void target_vvm::proc_assign(ostream&os, const NetAssign*net) { + + /* Detect the very special (and very common) case that the + rvalue is a constant in this assignment. I this case, there + is no reason to go scan the expression, and in the process + generate bunches of temporaries. */ + + if (const NetEConst*rc = dynamic_cast(net->rval())) { + assert(net->bmux() == 0); + const verinum value = rc->value(); + + for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { + string nexus = mangle(nexus_from_link(&net->pin(idx))); + defn << " " << nexus << "_nex.reg_assign("; + switch (value.get(idx)) { + case verinum::V0: + defn << "V0"; + break; + case verinum::V1: + defn << "V1"; + break; + case verinum::Vx: + defn << "Vx"; + break; + case verinum::Vz: + defn << "Vz"; + break; + } + defn << ");" << endl; + } + return; + } + string rval = emit_proc_rval(defn, 8, net->rval()); defn << " // " << net->get_line() << ": " << endl; @@ -2196,6 +2239,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.113 2000/03/17 17:25:53 steve + * Adder and comparator in nexus style. + * * Revision 1.112 2000/03/17 03:05:13 steve * Update vvm_mult to nexus style. * diff --git a/vvm/Makefile.in b/vvm/Makefile.in index 957200ee4..dad5cdf0c 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.22 2000/03/17 02:22:03 steve Exp $" +#ident "$Id: Makefile.in,v 1.23 2000/03/17 17:25:53 steve Exp $" # # SHELL = /bin/sh @@ -58,8 +58,9 @@ all: libvvm.a $(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_event.o vvm_func.o \ -vvm_gates.o vvm_mult.o \ +O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.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_add_sub.cc b/vvm/vvm_add_sub.cc new file mode 100644 index 000000000..81402f4ca --- /dev/null +++ b/vvm/vvm_add_sub.cc @@ -0,0 +1,121 @@ +/* + * 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_add_sub.cc,v 1.1 2000/03/17 17:25:53 steve Exp $" +#endif + +# include "vvm_gates.h" +# include + +vvm_add_sub::vvm_add_sub(unsigned wid) +: width_(wid), ndir_(V0) +{ + ibits_ = new vpip_bit_t[width_*3]; + ro_ = new vvm_nexus::drive_t[width_]; + + c_ = Vx; + for (unsigned idx = 0 ; idx < width_*3 ; idx += 1) + ibits_[idx] = Vx; +} + +vvm_add_sub::~vvm_add_sub() +{ + delete[]ro_; + delete[]ibits_; +} + +vvm_nexus::drive_t* vvm_add_sub::config_rout(unsigned idx) +{ + assert(idx < width_); + return ro_+idx; +} + +vvm_nexus::drive_t* vvm_add_sub::config_cout() +{ + return &co_; +} + +unsigned vvm_add_sub::key_DataA(unsigned idx) const +{ + assert(idx < width_); + return idx; +} + +unsigned vvm_add_sub::key_DataB(unsigned idx) const +{ + assert(idx < width_); + return idx+width_; +} + +void vvm_add_sub::init_DataA(unsigned idx, vpip_bit_t val) +{ + assert(idx < width_); + ibits_[idx] = val; +} + +void vvm_add_sub::init_DataB(unsigned idx, vpip_bit_t val) +{ + assert(idx < width_); + ibits_[width_+idx] = val; +} + +void vvm_add_sub::init_Add_Sub(unsigned, vpip_bit_t val) +{ + ndir_ = v_not(val); +} + +void vvm_add_sub::start() +{ + compute_(); +} + +void vvm_add_sub::take_value(unsigned key, vpip_bit_t val) +{ + if (ibits_[key] == val) return; + ibits_[key] = val; + compute_(); +} + +void vvm_add_sub::compute_() +{ + vpip_bit_t carry = ndir_; + + vpip_bit_t*a = ibits_; + vpip_bit_t*b = ibits_+width_; + vpip_bit_t*r = ibits_+2*width_; + + for (unsigned idx = 0 ; idx < width_ ; idx += 1) { + vpip_bit_t val; + val = add_with_carry(a[idx], b[idx] ^ ndir_, carry); + if (val == r[idx]) continue; + r[idx] = val; + vvm_event*ev = new vvm_out_event(val, ro_+idx); + ev->schedule(); + } + if (carry != c_) + (new vvm_out_event(carry, &co_)) -> schedule(); +} + +/* + * $Log: vvm_add_sub.cc,v $ + * Revision 1.1 2000/03/17 17:25:53 steve + * Adder and comparator in nexus style. + * + */ + diff --git a/vvm/vvm_compare.cc b/vvm/vvm_compare.cc new file mode 100644 index 000000000..a935f3ad9 --- /dev/null +++ b/vvm/vvm_compare.cc @@ -0,0 +1,123 @@ +/* + * 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_compare.cc,v 1.1 2000/03/17 17:25:53 steve Exp $" +#endif + +# include "vvm_gates.h" +# include + +vvm_compare::vvm_compare(unsigned wid) +: width_(wid) +{ + gt_ = Vx; + lt_ = Vx; + + ibits_ = new vpip_bit_t[2*width_]; + for (unsigned idx = 0 ; idx < 2*width_ ; idx += 1) + ibits_[idx] = Vx; +} + +vvm_compare::~vvm_compare() +{ + delete[]ibits_; +} + +void vvm_compare::init_DataA(unsigned idx, vpip_bit_t val) +{ + assert(idx < width_); + ibits_[idx] = val; +} + +void vvm_compare::init_DataB(unsigned idx, vpip_bit_t val) +{ + assert(idx < width_); + ibits_[width_+idx] = val; +} + +vvm_nexus::drive_t* vvm_compare::config_ALB_out() +{ + return &out_lt_; +} + +vvm_nexus::drive_t* vvm_compare::config_ALEB_out() +{ + return &out_le_; +} + +vvm_nexus::drive_t* vvm_compare::config_AGB_out() +{ + return &out_gt_; +} + +vvm_nexus::drive_t* vvm_compare::config_AGEB_out() +{ + return &out_ge_; +} + +unsigned vvm_compare::key_DataA(unsigned idx) const +{ + assert(idx < width_); + return idx; +} + +unsigned vvm_compare::key_DataB(unsigned idx) const +{ + assert(idx < width_); + return width_ + idx; +} + +void vvm_compare::take_value(unsigned key, vpip_bit_t val) +{ + if (ibits_[key] == val) + return; + + ibits_[key] = val; + compute_(); +} + +void vvm_compare::compute_() +{ + vpip_bit_t gt = V0; + vpip_bit_t lt = V0; + + vpip_bit_t*a = ibits_; + vpip_bit_t*b = ibits_+width_; + + for (unsigned idx = 0 ; idx < width_ ; idx += 1) { + gt = greater_with_cascade(a[idx], b[idx], gt); + lt = less_with_cascade(a[idx], b[idx], lt); + } + + if ((gt_ == gt) && (lt_ == lt)) return; + gt_ = gt; + lt_ = lt; + out_lt_.set_value(lt_); + out_le_.set_value(v_not(gt_)); + out_gt_.set_value(gt_); + out_ge_.set_value(v_not(lt_)); +} + +/* + * $Log: vvm_compare.cc,v $ + * Revision 1.1 2000/03/17 17:25:53 steve + * Adder and comparator in nexus style. + * + */ + diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index bd035bfa6..e61aeb779 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.43 2000/03/17 03:36:07 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.44 2000/03/17 17:25:53 steve Exp $" #endif # include "vvm.h" @@ -74,88 +74,52 @@ class vvm_1bit_out : public vvm_nexus::drive_t { }; /* - * This template implements the LPM_ADD_SUB device type. The width of - * the device is a template parameter. The device handles addition and + * This class implements the LPM_ADD_SUB device type. The width of + * the device is a constructor 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_nexus::recvr_t { +class vvm_add_sub : public vvm_nexus::recvr_t { public: - vvm_add_sub() : ndir_(V0) { } + explicit vvm_add_sub(unsigned width); + ~vvm_add_sub(); - vvm_nexus::drive_t* config_rout(unsigned idx) - { r_[idx] = Vx; - assert(idx < WIDTH); - return ro_+idx; - } + vvm_nexus::drive_t* config_rout(unsigned idx); + vvm_nexus::drive_t* config_cout(); - vvm_nexus::drive_t* config_cout() - { c_ = Vx; - return &co_; - } + unsigned key_DataA(unsigned idx) const; + unsigned key_DataB(unsigned idx) const; - unsigned key_DataA(unsigned idx) const { return idx; } - unsigned key_DataB(unsigned idx) const { return idx|0x10000; } + void init_DataA(unsigned idx, vpip_bit_t val); + void init_DataB(unsigned idx, vpip_bit_t val); + void init_Add_Sub(unsigned, vpip_bit_t val); - void init_DataA(unsigned idx, vpip_bit_t val) - { a_[idx] = val; - } - - void init_DataB(unsigned idx, vpip_bit_t val) - { b_[idx] = val; - } - - void init_Add_Sub(unsigned, vpip_bit_t val) - { ndir_ = v_not(val); - } - - void start() { compute_(); } - - void set_DataA(unsigned idx, vpip_bit_t val) - { a_[idx] = val; - compute_(); - } - void set_DataB(unsigned idx, vpip_bit_t val) - { b_[idx] = val; - compute_(); - } + void start(); private: - void take_value(unsigned key, vpip_bit_t val) - { if (key&0x10000) set_DataB(key&0xffff, val); - else set_DataA(key&0xffff, val); - } + void take_value(unsigned key, vpip_bit_t val); - private: - vpip_bit_t a_[WIDTH]; - vpip_bit_t b_[WIDTH]; - vpip_bit_t r_[WIDTH]; + unsigned width_; + vpip_bit_t*ibits_; vpip_bit_t c_; // this is the inverse of the Add_Sub port. It is 0 for add, // and 1 for subtract. vpip_bit_t ndir_; - vvm_nexus::drive_t ro_[WIDTH]; + vvm_nexus::drive_t*ro_; vvm_nexus::drive_t co_; - void compute_() - { 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] ^ ndir_, carry); - if (val == r_[idx]) continue; - r_[idx] = val; - vvm_event*ev = new vvm_out_event(val, ro_+idx); - ev->schedule(); - } - if (carry != c_) - (new vvm_out_event(carry, &co_)) -> schedule(); - } + void compute_(); + + private: // not implemented + vvm_add_sub(const vvm_add_sub&); + vvm_add_sub& operator= (const vvm_add_sub&); }; + template class vvm_and : public vvm_1bit_out, public vvm_nexus::recvr_t { @@ -218,91 +182,46 @@ class vvm_clshift : public vvm_nexus::recvr_t { }; -template class vvm_compare { +/* + * This class implements structural comparators, specifically the + * LPM_COMPARE device type. + */ +class vvm_compare : public vvm_nexus::recvr_t { public: - explicit vvm_compare() - { out_lt_ = 0; - out_le_ = 0; - gt_ = Vx; - lt_ = Vx; - for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) { - a_[idx] = Vx; - b_[idx] = Vx; - } - } - ~vvm_compare() { } + explicit vvm_compare(unsigned w); + ~vvm_compare(); - void init_DataA(unsigned idx, vpip_bit_t val) - { a_[idx] = val; } - void init_DataB(unsigned idx, vpip_bit_t val) - { b_[idx] = val; } + void init_DataA(unsigned idx, vpip_bit_t val); + void init_DataB(unsigned idx, vpip_bit_t val); - void set_DataA(unsigned idx, vpip_bit_t val) - { if (a_[idx] == val) return; - a_[idx] = val; - compute_(); - } + unsigned key_DataA(unsigned idx) const; + unsigned key_DataB(unsigned idx) const; - void set_DataB(unsigned idx, vpip_bit_t val) - { if (b_[idx] == val) return; - b_[idx] = val; - compute_(); - } - - void config_ALB_out(vvm_out_event::action_t o) - { out_lt_ = o; } - - void config_ALEB_out(vvm_out_event::action_t o) - { out_le_ = o; } - - void config_AGB_out(vvm_out_event::action_t o) - { out_gt_ = o; } - - void config_AGEB_out(vvm_out_event::action_t o) - { out_ge_ = o; } + vvm_nexus::drive_t* config_ALB_out(); + vvm_nexus::drive_t* config_ALEB_out(); + vvm_nexus::drive_t* config_AGB_out(); + vvm_nexus::drive_t* config_AGEB_out(); private: - vpip_bit_t a_[WIDTH]; - vpip_bit_t b_[WIDTH]; + void take_value(unsigned key, vpip_bit_t val); + + unsigned width_; + vpip_bit_t*ibits_; vpip_bit_t gt_; vpip_bit_t lt_; - vvm_out_event::action_t out_lt_; - vvm_out_event::action_t out_le_; - vvm_out_event::action_t out_gt_; - vvm_out_event::action_t out_ge_; + vvm_nexus::drive_t out_lt_; + vvm_nexus::drive_t out_le_; + vvm_nexus::drive_t out_gt_; + vvm_nexus::drive_t out_ge_; - void compute_() - { vpip_bit_t gt = V0; - vpip_bit_t lt = V0; - vvm_event*ev; - for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) { - gt = greater_with_cascade(a_[idx], b_[idx], gt); - lt = less_with_cascade(a_[idx], b_[idx], lt); - } + void compute_(); - if ((gt_ == gt) && (lt_ == lt)) return; - gt_ = gt; - lt_ = lt; - if (out_lt_) { - ev = new vvm_out_event(lt_, out_lt_); - ev->schedule(); - } - if (out_le_) { - ev = new vvm_out_event(v_not(gt_), out_le_); - ev->schedule(); - } - if (out_gt_) { - ev = new vvm_out_event(gt_, out_gt_); - ev->schedule(); - } - if (out_ge_) { - ev = new vvm_out_event(v_not(lt_), out_ge_); - ev->schedule(); - } - } + private: // not implemented + vvm_compare(const vvm_compare&); + vvm_compare& operator= (const vvm_compare&); }; @@ -895,6 +814,9 @@ template class vvm_pevent : public vvm_nexus::recvr_t { /* * $Log: vvm_gates.h,v $ + * Revision 1.44 2000/03/17 17:25:53 steve + * Adder and comparator in nexus style. + * * Revision 1.43 2000/03/17 03:36:07 steve * Remove some useless template parameters. *