synth_asych of if/else requires redirecting the target

if sub-statements. Use NetNet objects to manage the
 situation.
This commit is contained in:
steve 2002-07-01 00:54:21 +00:00
parent 3595b6d186
commit d5e9e13555
3 changed files with 140 additions and 34 deletions

View File

@ -17,11 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #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
#if !defined(WINNT)
#ident "$Id: net_nex_output.cc,v 1.1 2002/06/30 02:21:32 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -40,23 +36,38 @@ void NetProc::nex_output(NexusSet&out)
<< endl; << endl;
} }
void NetAssign::nex_output(NexusSet&out) void NetAssignBase::nex_output(NexusSet&out)
{ {
cerr << get_line() NetNet*lsig = lval_->sig();
<< ": internal error: NetProc::nex_output not implemented" assert(lsig);
<< endl; 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) void NetCondit::nex_output(NexusSet&out)
{ {
cerr << get_line() if (if_ != 0)
<< ": internal error: NetProc::nex_output not implemented" if_->nex_output(out);
<< endl; 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 $ * $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 * Revision 1.1 2002/06/30 02:21:32 steve
* Add structure for asynchronous logic synthesis. * Add structure for asynchronous logic synthesis.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #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 #endif
/* /*
@ -1204,7 +1204,8 @@ class NetProc : public LineInfo {
virtual bool is_asynchronous(); virtual bool is_asynchronous();
// synthesize as asynchronous logic, and return true. // 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; virtual void dump(ostream&, unsigned ind) const;
@ -1312,12 +1313,15 @@ class NetAssignBase : public NetProc {
const NetExpr* get_delay() const; const NetExpr* get_delay() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input();
virtual void nex_output(NexusSet&o);
// This returns the total width of the accumulated l-value. It // This returns the total width of the accumulated l-value. It
// accounts for any grouping of NetAssign_ objects that might happen. // accounts for any grouping of NetAssign_ objects that might happen.
unsigned lwidth() const; 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. // This dumps all the lval structures.
void dump_lval(ostream&) const; void dump_lval(ostream&) const;
@ -1336,8 +1340,6 @@ class NetAssign : public NetAssignBase {
bool is_asynchronous(); bool is_asynchronous();
void nex_output(NexusSet&o);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*); virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -1503,7 +1505,8 @@ class NetCondit : public NetProc {
virtual void nex_output(NexusSet&o); virtual void nex_output(NexusSet&o);
bool is_asynchronous(); 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 bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*); virtual int match_proc(struct proc_match_t*);
@ -1626,6 +1629,8 @@ class NetEvent : public LineInfo {
NetScope* scope(); NetScope* scope();
const NetScope* scope() const; const NetScope* scope() const;
void nex_output(NexusSet&);
// Locate the first event that matches my behavior and // Locate the first event that matches my behavior and
// monitors the same signals. // monitors the same signals.
NetEvent* find_similar_event(); NetEvent* find_similar_event();
@ -1708,7 +1713,10 @@ class NetEvWait : public NetProc {
// process. This method checks. // process. This method checks.
virtual bool is_asynchronous(); 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; virtual void dump(ostream&, unsigned ind) const;
@ -2985,6 +2993,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $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 * Revision 1.248 2002/06/30 02:21:32 steve
* Add structure for asynchronous logic synthesis. * Add structure for asynchronous logic synthesis.
* *

112
synth2.cc
View File

@ -17,54 +17,123 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #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 #endif
# include "config.h" # include "config.h"
# include "functor.h" # include "functor.h"
# include "netlist.h" # include "netlist.h"
# include "compiler.h"
# include <assert.h> # include <assert.h>
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 * Async synthesis of assignments is done by synthesizing the rvalue
* expression, then connecting the l-value directly to the output of * expression, then connecting the l-value directly to the output of
* the r-value. * 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); NetNet*rsig = rval_->synthesize(des);
assert(rsig);
NetNet*lsig = lval_->sig(); NetNet*lsig = lval_->sig();
assert(lsig); assert(lsig);
assert(lval_->more == 0); assert(lval_->more == 0);
assert(nex_map->pin_count() == rsig->pin_count());
assert(lsig->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; 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; return false;
} }
bool NetProcTop::synth_async(Design*des) 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 { 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 * Look at a process. If it is asynchronous, then synthesize it as an
* threads. * asynchronous process and delete the process itself for its gates.
*/ */
void synth2_f::process(class Design*des, class NetProcTop*top) 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; 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; return;
}
cerr << top->get_line() << ": info: thread is asynchronous." << endl;
des->delete_process(top); des->delete_process(top);
} }
@ -100,6 +177,11 @@ void synth2(Design*des)
/* /*
* $Log: synth2.cc,v $ * $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 * Revision 1.1 2002/06/30 02:21:32 steve
* Add structure for asynchronous logic synthesis. * Add structure for asynchronous logic synthesis.
* *