From d5e9e13555b35bc3c30219f643ddb939b11ba3f0 Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 1 Jul 2002 00:54:21 +0000 Subject: [PATCH] synth_asych of if/else requires redirecting the target if sub-statements. Use NetNet objects to manage the situation. --- net_nex_output.cc | 35 ++++++++++----- netlist.h | 27 ++++++++--- synth2.cc | 112 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 140 insertions(+), 34 deletions(-) diff --git a/net_nex_output.cc b/net_nex_output.cc index 5a0b32b15..b5414eae1 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -17,11 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: net_nex_output.cc,v 1.1 2002/06/30 02:21:32 steve Exp $" -#endif - -#if !defined(WINNT) -#ident "$Id: net_nex_output.cc,v 1.1 2002/06/30 02:21:32 steve Exp $" +#ident "$Id: net_nex_output.cc,v 1.2 2002/07/01 00:54:21 steve Exp $" #endif # include "config.h" @@ -40,23 +36,38 @@ void NetProc::nex_output(NexusSet&out) << endl; } -void NetAssign::nex_output(NexusSet&out) +void NetAssignBase::nex_output(NexusSet&out) { - cerr << get_line() - << ": internal error: NetProc::nex_output not implemented" - << endl; + NetNet*lsig = lval_->sig(); + assert(lsig); + assert(lval_->more == 0); + + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) + out.add(lsig->pin(idx).nexus()); + } void NetCondit::nex_output(NexusSet&out) { - cerr << get_line() - << ": internal error: NetProc::nex_output not implemented" - << endl; + if (if_ != 0) + if_->nex_output(out); + if (else_ != 0) + else_->nex_output(out); } +void NetEvWait::nex_output(NexusSet&out) +{ + assert(statement_); + statement_->nex_output(out); +} /* * $Log: net_nex_output.cc,v $ + * Revision 1.2 2002/07/01 00:54:21 steve + * synth_asych of if/else requires redirecting the target + * if sub-statements. Use NetNet objects to manage the + * situation. + * * Revision 1.1 2002/06/30 02:21:32 steve * Add structure for asynchronous logic synthesis. * diff --git a/netlist.h b/netlist.h index 2ea2b61d1..f692fbe3c 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) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.248 2002/06/30 02:21:32 steve Exp $" +#ident "$Id: netlist.h,v 1.249 2002/07/01 00:54:21 steve Exp $" #endif /* @@ -1204,7 +1204,8 @@ class NetProc : public LineInfo { virtual bool is_asynchronous(); // synthesize as asynchronous logic, and return true. - virtual bool synth_async(Design*, NetScope*scope); + virtual bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out); virtual void dump(ostream&, unsigned ind) const; @@ -1312,12 +1313,15 @@ class NetAssignBase : public NetProc { const NetExpr* get_delay() const; virtual NexusSet* nex_input(); + virtual void nex_output(NexusSet&o); + // This returns the total width of the accumulated l-value. It // accounts for any grouping of NetAssign_ objects that might happen. unsigned lwidth() const; - bool synth_async(Design*des, NetScope*scope); + bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out); // This dumps all the lval structures. void dump_lval(ostream&) const; @@ -1336,8 +1340,6 @@ class NetAssign : public NetAssignBase { bool is_asynchronous(); - void nex_output(NexusSet&o); - virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; @@ -1503,7 +1505,8 @@ class NetCondit : public NetProc { virtual void nex_output(NexusSet&o); bool is_asynchronous(); - bool synth_async(Design*des, NetScope*scope); + bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out); virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); @@ -1626,6 +1629,8 @@ class NetEvent : public LineInfo { NetScope* scope(); const NetScope* scope() const; + void nex_output(NexusSet&); + // Locate the first event that matches my behavior and // monitors the same signals. NetEvent* find_similar_event(); @@ -1708,7 +1713,10 @@ class NetEvWait : public NetProc { // process. This method checks. virtual bool is_asynchronous(); - virtual bool synth_async(Design*des, NetScope*scope); + virtual void nex_output(NexusSet&out); + + virtual bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out); virtual void dump(ostream&, unsigned ind) const; @@ -2985,6 +2993,11 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.249 2002/07/01 00:54:21 steve + * synth_asych of if/else requires redirecting the target + * if sub-statements. Use NetNet objects to manage the + * situation. + * * Revision 1.248 2002/06/30 02:21:32 steve * Add structure for asynchronous logic synthesis. * diff --git a/synth2.cc b/synth2.cc index d2ef3f502..6b72322f8 100644 --- a/synth2.cc +++ b/synth2.cc @@ -17,54 +17,123 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: synth2.cc,v 1.1 2002/06/30 02:21:32 steve Exp $" +#ident "$Id: synth2.cc,v 1.2 2002/07/01 00:54:21 steve Exp $" #endif # include "config.h" # include "functor.h" # include "netlist.h" +# include "compiler.h" # include +static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex) +{ + unsigned idx = 0; + for (idx = 0 ; idx < nset->pin_count() ; idx += 1) + if (nset->pin(idx).nexus() == nex) + return idx; + + return idx; +} /* * Async synthesis of assignments is done by synthesizing the rvalue * expression, then connecting the l-value directly to the output of * the r-value. + * + * The nex_map is the O-set for the statement, and lists the positions + * of the outputs as the caller wants results linked up. The nex_out, + * however, is the set of nexa that are to actually get linked to the + * r-value. */ -bool NetAssignBase::synth_async(Design*des, NetScope*scope) +bool NetAssignBase::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out) { NetNet*rsig = rval_->synthesize(des); + assert(rsig); NetNet*lsig = lval_->sig(); assert(lsig); assert(lval_->more == 0); + assert(nex_map->pin_count() == rsig->pin_count()); assert(lsig->pin_count() == rsig->pin_count()); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) - connect(lsig->pin(idx), rsig->pin(idx)); + + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus()); + connect(nex_out->pin(ptr), rsig->pin(idx)); + } return true; } -bool NetCondit::synth_async(Design*des, NetScope*scope) +bool NetCondit::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out) { - return false; + NetNet*ssig = expr_->synthesize(des); + assert(ssig); + + assert(if_ != 0); + assert(else_ != 0); + + NetNet*asig = new NetNet(scope, scope->local_hsymbol(), + NetNet::WIRE, nex_map->pin_count()); + asig->local_flag(true); + + if_->synth_async(des, scope, nex_map, asig); + + NetNet*bsig = new NetNet(scope, scope->local_hsymbol(), + NetNet::WIRE, nex_map->pin_count()); + bsig->local_flag(true); + + else_->synth_async(des, scope, nex_map, bsig); + + NetMux*mux = new NetMux(scope, scope->local_hsymbol(), + nex_out->pin_count(), 2, 1); + + connect(mux->pin_Sel(0), ssig->pin(0)); + + for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1) + connect(mux->pin_Data(idx, 1), asig->pin(idx)); + + for (unsigned idx = 0 ; idx < bsig->pin_count() ; idx += 1) + connect(mux->pin_Data(idx, 0), bsig->pin(idx)); + + for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) + connect(nex_out->pin(idx), mux->pin_Result(idx)); + + des->add_node(mux); + + return true; } -bool NetEvWait::synth_async(Design*des, NetScope*scope) +bool NetEvWait::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out) { - return statement_->synth_async(des, scope); + return statement_->synth_async(des, scope, nex_map, nex_out); } -bool NetProc::synth_async(Design*des, NetScope*scope) +bool NetProc::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out) { return false; } bool NetProcTop::synth_async(Design*des) { - return statement_->synth_async(des, scope()); + NexusSet nex_set; + statement_->nex_output(nex_set); + + NetNet*nex_out = new NetNet(scope(), "tmp", NetNet::WIRE, + nex_set.count()); + for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1) + connect(nex_set[idx], nex_out->pin(idx)); + + bool flag = statement_->synth_async(des, scope(), nex_out, nex_out); + + delete nex_out; + return flag; } class synth2_f : public functor_t { @@ -77,18 +146,26 @@ class synth2_f : public functor_t { /* - * Look at a process, and divide the problem into always and initial - * threads. + * Look at a process. If it is asynchronous, then synthesize it as an + * asynchronous process and delete the process itself for its gates. */ void synth2_f::process(class Design*des, class NetProcTop*top) { - if (! top->is_asynchronous()) + if (! top->is_asynchronous()) { + if (top->attribute("asynchronous").as_ulong() != 0) + cerr << top->get_line() << ": warning: " + << "Process is marked asynchronous," + << " but isn't really." << endl; return; + } - if (! top->synth_async(des)) + if (! top->synth_async(des)) { + cerr << top->get_line() << ": internal error: " + << "is_asynchronous does not match " + << "sync_async results." << endl; return; + } - cerr << top->get_line() << ": info: thread is asynchronous." << endl; des->delete_process(top); } @@ -100,6 +177,11 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.2 2002/07/01 00:54:21 steve + * synth_asych of if/else requires redirecting the target + * if sub-statements. Use NetNet objects to manage the + * situation. + * * Revision 1.1 2002/06/30 02:21:32 steve * Add structure for asynchronous logic synthesis. *