diff --git a/design_dump.cc b/design_dump.cc index 4fca92f57..84d16c39c 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.61 1999/11/28 23:42:02 steve Exp $" +#ident "$Id: design_dump.cc,v 1.62 1999/12/05 02:24:08 steve Exp $" #endif /* @@ -428,9 +428,7 @@ void NetAssignMem::dump(ostream&o, unsigned ind) const o << setw(ind) << ""; o << "/* " << get_line() << " */" << endl; o << setw(ind) << ""; - o << memory()->name() << "["; - index()->dump(o); - o << "] = "; + o << memory()->name() << "[" << index()->name() << "] = "; rval()->dump(o); o << ";" << endl; } @@ -440,9 +438,7 @@ void NetAssignMemNB::dump(ostream&o, unsigned ind) const o << setw(ind) << ""; o << "/* " << get_line() << " */" << endl; o << setw(ind) << ""; - o << memory()->name() << "["; - index()->dump(o); - o << "] <= "; + o << memory()->name() << "[" << index()->name() << "] <= "; rval()->dump(o); o << ";" << endl; } @@ -866,6 +862,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.62 1999/12/05 02:24:08 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.61 1999/11/28 23:42:02 steve * NetESignal object no longer need to be NetNode * objects. Let them keep a pointer to NetNet objects. diff --git a/elaborate.cc b/elaborate.cc index 2a2a52a0d..77ef66a68 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.132 1999/12/02 04:08:10 steve Exp $" +#ident "$Id: elaborate.cc,v 1.133 1999/12/05 02:24:08 steve Exp $" #endif /* @@ -860,7 +860,7 @@ NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix, assert(rv); rv->set_width(mem->width()); - NetExpr*idx = ix->elaborate_expr(des, path); + NetNet*idx = ix->elaborate_net(des, path, 0, 0, 0, 0); assert(idx); NetAssignMem*am = new NetAssignMem(mem, idx, rv); @@ -1170,7 +1170,7 @@ NetProc* PAssignNB::assign_to_memory_(NetMemory*mem, PExpr*ix, rv->set_width(mem->width()); /* Elaborate the expression to calculate the index, ... */ - NetExpr*idx = ix->elaborate_expr(des, path); + NetNet*idx = ix->elaborate_net(des, path, 0, 0, 0, 0); assert(idx); /* And connect them together in an assignment NetProc. */ @@ -2090,6 +2090,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.133 1999/12/05 02:24:08 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.132 1999/12/02 04:08:10 steve * Elaborate net repeat concatenations. * diff --git a/functor.cc b/functor.cc index 15ee3158c..94b806a95 100644 --- a/functor.cc +++ b/functor.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.cc,v 1.5 1999/12/01 06:06:16 steve Exp $" +#ident "$Id: functor.cc,v 1.6 1999/12/05 02:24:08 steve Exp $" #endif # include "functor.h" @@ -99,6 +99,16 @@ int NetAssign::match_proc(proc_match_t*that) return that->assign(this); } +int proc_match_t::assign_mem(NetAssignMem*) +{ + return 0; +} + +int NetAssignMem::match_proc(proc_match_t*that) +{ + return that->assign_mem(this); +} + int proc_match_t::condit(NetCondit*) { return 0; @@ -121,6 +131,9 @@ int NetPEvent::match_proc(proc_match_t*that) /* * $Log: functor.cc,v $ + * Revision 1.6 1999/12/05 02:24:08 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.5 1999/12/01 06:06:16 steve * Redo synth to use match_proc_t scanner. * diff --git a/functor.h b/functor.h index d9edf0a5d..72602eb3a 100644 --- a/functor.h +++ b/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.h,v 1.3 1999/12/01 06:06:16 steve Exp $" +#ident "$Id: functor.h,v 1.4 1999/12/05 02:24:08 steve Exp $" #endif /* @@ -50,6 +50,7 @@ struct proc_match_t { virtual ~proc_match_t(); virtual int assign(class NetAssign*); + virtual int assign_mem(class NetAssignMem*); virtual int condit(class NetCondit*); virtual int pevent(class NetPEvent*); }; @@ -57,6 +58,9 @@ struct proc_match_t { /* * $Log: functor.h,v $ + * Revision 1.4 1999/12/05 02:24:08 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.3 1999/12/01 06:06:16 steve * Redo synth to use match_proc_t scanner. * diff --git a/netlist.cc b/netlist.cc index 8f932d208..9f14d0555 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.cc,v 1.97 1999/12/02 16:58:58 steve Exp $" +#ident "$Id: netlist.cc,v 1.98 1999/12/05 02:24:09 steve Exp $" #endif # include @@ -1052,10 +1052,25 @@ NetRamDq::NetRamDq(const string&n, NetMemory*mem, unsigned awid) pin(3+awidth_+width()+idx).set_dir(NetObj::Link::OUTPUT); pin(3+awidth_+width()+idx).set_name("Q", idx); } + + next_ = mem_->ram_list_; + mem_->ram_list_ = this; } NetRamDq::~NetRamDq() { + if (mem_->ram_list_ == this) { + mem_->ram_list_ = next_; + + } else { + NetRamDq*cur = mem_->ram_list_; + while (cur->next_ != this) { + assert(cur->next_); + cur = cur->next_; + } + assert(cur->next_ == this); + cur->next_ = next_; + } } unsigned NetRamDq::width() const @@ -1078,6 +1093,73 @@ const NetMemory* NetRamDq::mem() const return mem_; } +void NetRamDq::absorb_partners() +{ + NetRamDq*cur, *tmp; + for (cur = mem_->ram_list_, tmp = 0 + ; cur||tmp ; cur = cur? cur->next_ : tmp) { + tmp = 0; + if (cur == this) continue; + + bool ok_flag = true; + for (unsigned idx = 0 ; idx < awidth() ; idx += 1) + ok_flag &= pin_Address(idx).is_linked(cur->pin_Address(idx)); + + if (!ok_flag) continue; + + if (pin_InClock().is_linked() + && cur->pin_InClock().is_linked() + && ! pin_InClock().is_linked(cur->pin_InClock())) + continue; + + if (pin_OutClock().is_linked() + && cur->pin_OutClock().is_linked() + && ! pin_OutClock().is_linked(cur->pin_OutClock())) + continue; + + if (pin_WE().is_linked() + && cur->pin_WE().is_linked() + && ! pin_WE().is_linked(cur->pin_WE())) + continue; + + for (unsigned idx = 0 ; idx < width() ; idx += 1) { + if (!pin_Data(idx).is_linked()) continue; + if (! cur->pin_Data(idx).is_linked()) continue; + + ok_flag &= pin_Data(idx).is_linked(cur->pin_Data(idx)); + } + + if (! ok_flag) continue; + + for (unsigned idx = 0 ; idx < width() ; idx += 1) { + if (!pin_Q(idx).is_linked()) continue; + if (! cur->pin_Q(idx).is_linked()) continue; + + ok_flag &= pin_Q(idx).is_linked(cur->pin_Q(idx)); + } + + if (! ok_flag) continue; + + // I see no other reason to reject cur, so link up all + // my pins and delete it. + connect(pin_InClock(), cur->pin_InClock()); + connect(pin_OutClock(), cur->pin_OutClock()); + connect(pin_WE(), cur->pin_WE()); + + for (unsigned idx = 0 ; idx < awidth() ; idx += 1) + connect(pin_Address(idx), cur->pin_Address(idx)); + + for (unsigned idx = 0 ; idx < width() ; idx += 1) { + connect(pin_Data(idx), cur->pin_Data(idx)); + connect(pin_Q(idx), cur->pin_Q(idx)); + } + + tmp = cur->next_; + delete cur; + cur = 0; + } +} + NetObj::Link& NetRamDq::pin_InClock() { return pin(0); @@ -1249,16 +1331,18 @@ NetAssignNB::~NetAssignNB() } -NetAssignMem_::NetAssignMem_(NetMemory*m, NetExpr*i, NetExpr*r) +NetAssignMem_::NetAssignMem_(NetMemory*m, NetNet*i, NetExpr*r) : mem_(m), index_(i), rval_(r) { + index_->incr_eref(); } NetAssignMem_::~NetAssignMem_() { + index_->decr_eref(); } -NetAssignMem::NetAssignMem(NetMemory*m, NetExpr*i, NetExpr*r) +NetAssignMem::NetAssignMem(NetMemory*m, NetNet*i, NetExpr*r) : NetAssignMem_(m, i, r) { } @@ -1267,7 +1351,7 @@ NetAssignMem::~NetAssignMem() { } -NetAssignMemNB::NetAssignMemNB(NetMemory*m, NetExpr*i, NetExpr*r) +NetAssignMemNB::NetAssignMemNB(NetMemory*m, NetNet*i, NetExpr*r) : NetAssignMem_(m, i, r) { } @@ -1757,7 +1841,7 @@ NetEMemory::~NetEMemory() } NetMemory::NetMemory(const string&n, long w, long s, long e) -: name_(n), width_(w), idxh_(s), idxl_(e) +: name_(n), width_(w), idxh_(s), idxl_(e), ram_list_(0) { } @@ -2641,6 +2725,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.98 1999/12/05 02:24:09 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.97 1999/12/02 16:58:58 steve * Update case comparison (Eric Aardoom). * diff --git a/netlist.h b/netlist.h index 6d07534b4..165055238 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.h,v 1.97 1999/12/01 06:06:16 steve Exp $" +#ident "$Id: netlist.h,v 1.98 1999/12/05 02:24:09 steve Exp $" #endif /* @@ -480,6 +480,9 @@ class NetMemory { long idxl_; map attributes_; + + friend class NetRamDq; + NetRamDq* ram_list_; }; /* @@ -561,8 +564,12 @@ class NetRamDq : public NetNode { virtual void dump_node(ostream&, unsigned ind) const; virtual void emit_node(ostream&, struct target_t*) const; + // Use this method to absorb other NetRamDq objects that are + // connected to the same memory, and have compatible pin + // connections. + void absorb_partners(); + private: - friend class NetMemory; NetMemory*mem_; NetRamDq*next_; unsigned awidth_; @@ -957,25 +964,29 @@ class NetAssignNB : public NetAssign_ { class NetAssignMem_ : public NetProc { public: - explicit NetAssignMem_(NetMemory*, NetExpr*idx, NetExpr*rv); + explicit NetAssignMem_(NetMemory*, NetNet*idx, NetExpr*rv); ~NetAssignMem_(); + NetMemory*memory() { return mem_; } + NetNet*index() { return index_; } + const NetMemory*memory()const { return mem_; } - const NetExpr*index()const { return index_; } - const NetExpr*rval()const { return rval_; } + const NetNet*index()const { return index_; } + const NetExpr*rval()const { return rval_; } private: NetMemory*mem_; - NetExpr* index_; + NetNet * index_; NetExpr* rval_; }; class NetAssignMem : public NetAssignMem_ { public: - explicit NetAssignMem(NetMemory*, NetExpr*idx, NetExpr*rv); + explicit NetAssignMem(NetMemory*, NetNet*idx, NetExpr*rv); ~NetAssignMem(); + virtual int match_proc(struct proc_match_t*); virtual bool emit_proc(ostream&, struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -985,7 +996,7 @@ class NetAssignMem : public NetAssignMem_ { class NetAssignMemNB : public NetAssignMem_ { public: - explicit NetAssignMemNB(NetMemory*, NetExpr*idx, NetExpr*rv); + explicit NetAssignMemNB(NetMemory*, NetNet*idx, NetExpr*rv); ~NetAssignMemNB(); virtual bool emit_proc(ostream&, struct target_t*) const; @@ -2051,6 +2062,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.98 1999/12/05 02:24:09 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.97 1999/12/01 06:06:16 steve * Redo synth to use match_proc_t scanner. * diff --git a/synth.cc b/synth.cc index e25a9ae18..b899f8b7b 100644 --- a/synth.cc +++ b/synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: synth.cc,v 1.3 1999/12/01 06:06:16 steve Exp $" +#ident "$Id: synth.cc,v 1.4 1999/12/05 02:24:09 steve Exp $" #endif /* @@ -39,6 +39,14 @@ * always @(posedge CLK) if (CE) Q = D; * always @(negedge CLK) if (CE) Q = D; * + * These are memory assignments: + * + * always @(posedge CLK) M[a] = D + * always @(negedge CLK) M[a] = D + * + * always @(posedge CLK) if (CE) M[a] = D; + * always @(negedge CLK) if (CE) M[a] = D; + * * The r-value of the assignments must be identifiers (i.e. wires or * registers) and the CE must be single-bit identifiers. The generated * device will be wide enough to accomodate Q and D. @@ -48,7 +56,7 @@ class match_dff : public proc_match_t { public: match_dff(Design*d, NetProcTop*t) : des_(d), top_(t), pclk_(0), nclk_(0), con_(0), ce_(0), - asn_(0), d_(0) + asn_(0), asm_(0), d_(0) { } ~match_dff() { } @@ -56,7 +64,11 @@ class match_dff : public proc_match_t { void make_it(); private: + void make_dff_(); + void make_ram_(); + virtual int assign(NetAssign*); + virtual int assign_mem(NetAssignMem*); virtual int condit(NetCondit*); virtual int pevent(NetPEvent*); @@ -67,7 +79,9 @@ class match_dff : public proc_match_t { NetCondit *con_; NetNet*ce_; + NetAssign *asn_; + NetAssignMem*asm_; NetNet*d_; }; @@ -76,7 +90,7 @@ int match_dff::assign(NetAssign*as) { if (!pclk_) return 0; - if (asn_) + if (asn_ || asm_) return 0; asn_ = as; @@ -87,11 +101,26 @@ int match_dff::assign(NetAssign*as) return 1; } +int match_dff::assign_mem(NetAssignMem*as) +{ + if (!pclk_) + return 0; + if (asn_ || asm_) + return 0; + + asm_ = as; + d_ = asm_->rval()->synthesize(des_); + if (d_ == 0) + return 0; + + return 1; +} + int match_dff::condit(NetCondit*co) { if (!pclk_) return 0; - if (con_ || asn_) + if (con_ || asn_ || asm_) return 0; con_ = co; @@ -106,7 +135,7 @@ int match_dff::condit(NetCondit*co) int match_dff::pevent(NetPEvent*pe) { - if (pclk_ || con_ || asn_) + if (pclk_ || con_ || asn_ || asm_) return 0; pclk_ = pe; @@ -125,6 +154,17 @@ int match_dff::pevent(NetPEvent*pe) } void match_dff::make_it() +{ + if (asn_) { + assert(asm_ == 0); + make_dff_(); + } else { + assert(asm_); + make_ram_(); + } +} + +void match_dff::make_dff_() { NetFF*ff = new NetFF(asn_->name(), asn_->pin_count()); @@ -143,6 +183,28 @@ void match_dff::make_it() des_->add_node(ff); } +void match_dff::make_ram_() +{ + NetMemory*mem = asm_->memory(); + NetNet*adr = asm_->index(); + NetRamDq*ram = new NetRamDq(des_->local_symbol(mem->name()), mem, + adr->pin_count()); + for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1) + connect(adr->pin(idx), ram->pin_Address(idx)); + + for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) + connect(ram->pin_Data(idx), d_->pin(idx)); + + if (ce_) + connect(ram->pin_WE(), ce_->pin(0)); + + assert(nclk_->type() == NetNEvent::POSEDGE); + connect(ram->pin_InClock(), nclk_->pin(0)); + + ram->absorb_partners(); + des_->add_node(ram); +} + class synth_f : public functor_t { public: @@ -191,6 +253,9 @@ void synth(Design*des) /* * $Log: synth.cc,v $ + * Revision 1.4 1999/12/05 02:24:09 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.3 1999/12/01 06:06:16 steve * Redo synth to use match_proc_t scanner. * diff --git a/t-vvm.cc b/t-vvm.cc index 5d3aed0ea..6836c8f3b 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.87 1999/12/02 16:58:58 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.88 1999/12/05 02:24:09 steve Exp $" #endif # include @@ -1466,7 +1466,7 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net) */ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem) { - string index = emit_proc_rval(defn, 8, amem->index()); + string index = mangle(amem->index()->name()) + "_bits"; string rval = emit_proc_rval(defn, 8, amem->rval()); const NetMemory*mem = amem->memory(); @@ -1958,6 +1958,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.88 1999/12/05 02:24:09 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.87 1999/12/02 16:58:58 steve * Update case comparison (Eric Aardoom). * diff --git a/vvm/vvm.h b/vvm/vvm.h index d7bc10f95..4dae229d0 100644 --- a/vvm/vvm.h +++ b/vvm/vvm.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm.h,v 1.24 1999/12/02 03:36:01 steve Exp $" +#ident "$Id: vvm.h,v 1.25 1999/12/05 02:24:09 steve Exp $" #endif # include @@ -271,6 +271,14 @@ class vvm_memory_t : public __vpiMemory { call_list_(sim, addr); } + void set_word(vvm_simulation*sim, unsigned addr, + const vpip_bit_t val[WIDTH]) + { unsigned base = WIDTH * addr; + for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) + bits[base+idx] = val[idx]; + call_list_(sim, addr); + } + vvm_bitset_t get_word(unsigned addr) const { vvm_bitset_t val; unsigned base = WIDTH * addr; @@ -294,6 +302,9 @@ class vvm_memory_t : public __vpiMemory { /* * $Log: vvm.h,v $ + * Revision 1.25 1999/12/05 02:24:09 steve + * Synthesize LPM_RAM_DQ for writes into memories. + * * Revision 1.24 1999/12/02 03:36:01 steve * shiftl and shiftr take unsized second parameter. * diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index 18599e5f6..6f2420d7f 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.30 1999/12/02 16:58:58 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.31 1999/12/05 02:24:09 steve Exp $" #endif # include "vvm.h" @@ -504,6 +504,15 @@ class vvm_nor : private vvm_1bit_out { vpip_bit_t input_[WIDTH]; }; +/* + * This object implements a LPM_RAM_DQ device, except for the actual + * contents of the memory, which are stored in a vvm_memory_t + * object. Note that there may be many vvm_ram_dq items referencing + * the same memory. + * + * XXXX Only asynchronous reads are supported. + * XXXX Only *synchronous* writes with WE are supported. + */ template class vvm_ram_dq : protected vvm_ram_callback { @@ -520,6 +529,15 @@ class vvm_ram_dq : protected vvm_ram_callback { void init_Address(unsigned idx, vpip_bit_t val) { addr_[idx] = val; } + void init_Data(unsigned idx, vpip_bit_t val) + { data_[idx] = val; } + + void init_WE(unsigned, vpip_bit_t val) + { we_ = val; } + + void init_InClock(unsigned, vpip_bit_t val) + { iclk_ = val; } + void set_Address(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (addr_[idx] == val) return; addr_[idx] = val; @@ -527,6 +545,20 @@ class vvm_ram_dq : protected vvm_ram_callback { send_out_(sim); } + void set_Data(vvm_simulation*, unsigned idx, vpip_bit_t val) + { data_[idx] = val; } + + void set_WE(vvm_simulation*, unsigned, vpip_bit_t val) + { we_ = val; } + + void set_InClock(vvm_simulation*sim, unsigned, vpip_bit_t val) + { if (val == iclk_) return; + vpip_bit_t tmp = iclk_; + iclk_ = val; + if (we_ != V1) return; + if (posedge(tmp, val)) mem_->set_word(sim, addr_val_, data_); + } + void handle_write(vvm_simulation*sim, unsigned idx) { if (idx == addr_val_) send_out_(sim); } @@ -535,7 +567,12 @@ class vvm_ram_dq : protected vvm_ram_callback { private: vvm_memory_t*mem_; + vpip_bit_t addr_[AWIDTH]; + vpip_bit_t data_[WIDTH]; + vpip_bit_t we_; + vpip_bit_t iclk_; + vvm_out_event::action_t out_[WIDTH]; unsigned long addr_val_; @@ -897,6 +934,9 @@ template class vvm_pevent { /* * $Log: vvm_gates.h,v $ + * 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). *