From 53156793fe096062df5c1cfdf6fa919c81d38989 Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 22 Aug 2005 01:00:41 +0000 Subject: [PATCH] Add support for implicit defaults in case and conditions. --- netlist.h | 12 ++++- synth2.cc | 159 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 137 insertions(+), 34 deletions(-) diff --git a/netlist.h b/netlist.h index e4c7610ad..29e4b681c 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.321.2.2 2005/08/13 00:45:54 steve Exp $" +#ident "$Id: netlist.h,v 1.321.2.3 2005/08/22 01:00:41 steve Exp $" #endif /* @@ -1352,6 +1352,9 @@ class NetProc : public virtual LineInfo { // synthesize as asynchronous logic, and return true. virtual bool synth_async(Design*des, NetScope*scope, const NetNet*nex_map, NetNet*nex_out); + virtual bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out, + NetNet*accum_in); virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff, const NetNet*nex_map, NetNet*nex_out, @@ -1609,6 +1612,8 @@ class NetCase : public NetProc { bool synth_async(Design*des, NetScope*scope, const NetNet*nex_map, NetNet*nex_out); + bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out, NetNet*accum_in); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -1691,6 +1696,8 @@ class NetCondit : public NetProc { bool is_asynchronous(); bool synth_async(Design*des, NetScope*scope, const NetNet*nex_map, NetNet*nex_out); + bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out, NetNet*accum); bool synth_sync(Design*des, NetScope*scope, NetFF*ff, const NetNet*nex_map, NetNet*nex_out, @@ -3360,6 +3367,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.321.2.3 2005/08/22 01:00:41 steve + * Add support for implicit defaults in case and conditions. + * * Revision 1.321.2.2 2005/08/13 00:45:54 steve * Fix compilation warnings/errors with newer compilers. * diff --git a/synth2.cc b/synth2.cc index 07c7ef031..be7bc2d5f 100644 --- a/synth2.cc +++ b/synth2.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: synth2.cc,v 1.39.2.1 2005/08/21 22:49:54 steve Exp $" +#ident "$Id: synth2.cc,v 1.39.2.2 2005/08/22 01:00:42 steve Exp $" #endif # include "config.h" @@ -47,6 +47,13 @@ bool NetProc::synth_async(Design*des, NetScope*scope, return false; } +bool NetProc::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out, + NetNet*accum_in) +{ + return synth_async(des, scope, nex_map, nex_out); +} + bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff, const NetNet*nex_map, NetNet*nex_out, const svector&events) @@ -152,6 +159,8 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool flag = true; NetProc*cur = last_; do { + NetNet*new_accum; + cur = cur->next_; /* Create a temporary nex_map for the substatement. */ @@ -167,14 +176,32 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE, tmp_set.count()); - bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out); + /* Make a temporary set of currently accumulated outputs + that we can pass to the synth_async of the + sub-statement. Some sub-statements will use this to + handle default cases specially. We will delete this + temporary map as soon as the synth_async is done. */ + new_accum = new NetNet(scope, tmp3, NetNet::WIRE, tmp_set.count()); + for (unsigned idx = 0 ; idx < tmp_set.count() ; idx += 1) { + unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]); + if (accum_out->pin(ptr).is_linked()) + connect(new_accum->pin(idx), accum_out->pin(ptr)); + } + + bool ok_flag = cur->synth_async(des, scope, + tmp_map, tmp_out, new_accum); flag = flag && ok_flag; + delete new_accum; + if (ok_flag == false) continue; - NetNet*new_accum = new NetNet(scope, tmp3, NetNet::WIRE, - nex_out->pin_count()); + /* Now start building a new set of accumulated outputs + that we will pass to the next statement of the block, + or that will be the output of the block. */ + new_accum = new NetNet(scope, tmp3, NetNet::WIRE, + nex_out->pin_count()); /* Use the nex_map to link up the output from the substatement to the output of the block as a whole. */ @@ -215,6 +242,16 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool NetCase::synth_async(Design*des, NetScope*scope, const NetNet*nex_map, NetNet*nex_out) +{ + const perm_string tmp = perm_string::literal("tmp"); + NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count()); + bool flag = synth_async(des, scope, nex_map, nex_out, stub); + delete stub; + return flag; +} + +bool NetCase::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out, NetNet*accum) { DEBUG_SYNTH2_ENTRY("NetCase") unsigned cur; @@ -300,10 +337,23 @@ bool NetCase::synth_async(Design*des, NetScope*scope, statement_map[sel_idx] = items_[item].statement; } + /* Set up a default default_sig that uses the accumulated + input pins. This binding is suppressed by an actual default + statement if one exists. */ + NetNet*default_sig = 0; + if (default_statement == 0) { + default_sig = accum; + for (unsigned idx = 0 ; idx < accum->pin_count() ; idx += 1) { + if (! accum->pin(idx).is_linked()) { + default_sig = 0; + break; + } + } + } + /* Now that statements match with mux inputs, synthesize the sub-statements. If I get to an input that has no statement, then use the default statement there. */ - NetNet*default_sig = 0; for (unsigned item = 0 ; item < (1U<synth_async(des, scope, nex_map, sig); @@ -346,49 +396,90 @@ bool NetCase::synth_async(Design*des, NetScope*scope, return true; } +/* + * If the synth_async method is called without an accumulated input + * (in other words not from within a block) then stub the input signal + * with an unconnected net. + */ bool NetCondit::synth_async(Design*des, NetScope*scope, - const NetNet*nex_map, NetNet*nex_out) + const NetNet*nex_map, NetNet*nex_out) +{ + const perm_string tmp = perm_string::literal("tmp"); + NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count()); + bool flag = synth_async(des, scope, nex_map, nex_out, stub); + delete stub; + return flag; +} + +bool NetCondit::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out, + NetNet*accum) { DEBUG_SYNTH2_ENTRY("NetCondit") NetNet*ssig = expr_->synthesize(des); assert(ssig); - if (if_ == 0) { - DEBUG_SYNTH2_EXIT("NetCondit",false) - return false; - } - if (else_ == 0) { - cerr << get_line() << ": error: Asynchronous if statement" - << " is missing the else clause." << endl; - DEBUG_SYNTH2_EXIT("NetCondit",false) - return false; + /* Use the accumulated input net as a default input for + covering a missing clause, except that if I find portions + are unconnected, then give up on that idea. */ + NetNet*default_sig = accum; + for (unsigned idx = 0 ; idx < default_sig->pin_count() ; idx += 1) { + if (! default_sig->pin(idx).is_linked()) { + default_sig = 0; + break; + } } - assert(if_ != 0); - assert(else_ != 0); + if (default_sig == 0) { + if (if_ == 0) { + cerr << get_line() << ": error: Asynchronous if statement" + << " is missing the if clause." << endl; + return false; + } + if (else_ == 0) { + cerr << get_line() << ": error: Asynchronous if statement" + << " is missing the else clause." << endl; + return false; + } + } + + assert(if_ != 0 || else_ != 0); NetNet*asig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, nex_map->pin_count()); asig->local_flag(true); - bool flag; - flag = if_->synth_async(des, scope, nex_map, asig); - if (!flag) { - delete asig; - DEBUG_SYNTH2_EXIT("NetCondit",false) - return false; + if (if_ == 0) { + for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1) + connect(asig->pin(idx), default_sig->pin(idx)); + + } else { + bool flag = if_->synth_async(des, scope, nex_map, asig); + if (!flag) { + delete asig; + cerr << get_line() << ": error: Asynchronous if statement" + << " true clause failed to synthesize." << endl; + return false; + } } NetNet*bsig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, nex_map->pin_count()); bsig->local_flag(true); - flag = else_->synth_async(des, scope, nex_map, bsig); - if (!flag) { - delete asig; - delete bsig; - DEBUG_SYNTH2_EXIT("NetCondit",false) - return false; + if (else_ == 0) { + for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1) + connect(bsig->pin(idx), default_sig->pin(idx)); + + } else { + bool flag = else_->synth_async(des, scope, nex_map, bsig); + if (!flag) { + delete asig; + delete bsig; + cerr << get_line() << ": error: Asynchronous if statement" + << " else clause failed to synthesize." << endl; + return false; + } } NetMux*mux = new NetMux(scope, scope->local_symbol(), @@ -407,7 +498,6 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, des->add_node(mux); - DEBUG_SYNTH2_EXIT("NetCondit",true) return true; } @@ -1017,6 +1107,9 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.39.2.2 2005/08/22 01:00:42 steve + * Add support for implicit defaults in case and conditions. + * * Revision 1.39.2.1 2005/08/21 22:49:54 steve * Handle statements in blocks overriding previous statement outputs. *