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
*/
#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.
*

View File

@ -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.
*

112
synth2.cc
View File

@ -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 <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
* 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.
*