synth_asych of if/else requires redirecting the target
if sub-statements. Use NetNet objects to manage the situation.
This commit is contained in:
parent
3595b6d186
commit
d5e9e13555
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
27
netlist.h
27
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.
|
||||
*
|
||||
|
|
|
|||
112
synth2.cc
112
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 <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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue