From 0fc10d0262ae1cb1eda7cbc6157ccb92fd894978 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 25 Oct 2007 13:20:18 -0700 Subject: [PATCH] v0_8: fix @* to correctly handle non-input nets. This is a slightly modified version of the patch from the development branch. Specifically it only allows outputs in the sensitivity list for non-synthesis back ends. The text from the development patch follows. @* was only expanding to input nets. nex_input() for blocks was removing any output net that was also an input. There was also a bug in how output nets were removed. Only outputs currently defined were removed from the input list. always @(*) begin y = a; z = y; end would report "a" as an input. While always @(*) begin z = y; y = a; end would report both "a" and "y" as inputs. To fix this all nex_inputs now take a flag that when true (the default) correctly removes any output from the input list. Both the above cases will now return "a". If the flag is false outputs which are also inputs will be included in the input list. This is what the @* elaboration code uses to get the correct sensitivity list. --- elaborate.cc | 8 ++- net_nex_input.cc | 146 +++++++++++++++++++++++------------------------ netlist.h | 62 ++++++++++---------- 3 files changed, 111 insertions(+), 105 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 686d39b6a..09e5d5b31 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1964,7 +1964,13 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, if (expr_.count() == 0) { assert(enet); - NexusSet*nset = enet->nex_input(); + /* For synthesis we want just the inputs, but for the rest we + * want inputs and outputs that may cause a value to change. */ + extern const char *target; /* Target backend from main.cc */ + bool rem_out = false; + if (!strcmp(target, "edif") || !strcmp(target, "fpga") || + !strcmp(target, "xnf")) rem_out = true; + NexusSet*nset = enet->nex_input(rem_out); if (nset == 0) { cerr << get_line() << ": internal error: No NexusSet" << " from statement." << endl; diff --git a/net_nex_input.cc b/net_nex_input.cc index a18581e18..1f0d48e9c 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -29,7 +29,7 @@ # include "netlist.h" # include "netmisc.h" -NexusSet* NetExpr::nex_input() +NexusSet* NetExpr::nex_input(bool rem_out) { cerr << get_line() << ": internal error: nex_input not implemented: " @@ -37,7 +37,7 @@ NexusSet* NetExpr::nex_input() return 0; } -NexusSet* NetProc::nex_input() +NexusSet* NetProc::nex_input(bool rem_out) { cerr << get_line() << ": internal error: NetProc::nex_input not implemented" @@ -45,29 +45,29 @@ NexusSet* NetProc::nex_input() return 0; } -NexusSet* NetEBinary::nex_input() +NexusSet* NetEBinary::nex_input(bool rem_out) { - NexusSet*result = left_->nex_input(); - NexusSet*tmp = right_->nex_input(); + NexusSet*result = left_->nex_input(rem_out); + NexusSet*tmp = right_->nex_input(rem_out); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEBitSel::nex_input() +NexusSet* NetEBitSel::nex_input(bool rem_out) { - NexusSet*result = sig_->nex_input(); - NexusSet*tmp = idx_->nex_input(); + NexusSet*result = sig_->nex_input(rem_out); + NexusSet*tmp = idx_->nex_input(rem_out); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEConcat::nex_input() +NexusSet* NetEConcat::nex_input(bool rem_out) { - NexusSet*result = parms_[0]->nex_input(); + NexusSet*result = parms_[0]->nex_input(rem_out); for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { - NexusSet*tmp = parms_[idx]->nex_input(); + NexusSet*tmp = parms_[idx]->nex_input(rem_out); result->add(*tmp); delete tmp; } @@ -77,19 +77,19 @@ NexusSet* NetEConcat::nex_input() /* * A constant has not inputs, so always return an empty set. */ -NexusSet* NetEConst::nex_input() +NexusSet* NetEConst::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetECReal::nex_input() +NexusSet* NetECReal::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetEMemory::nex_input() +NexusSet* NetEMemory::nex_input(bool rem_out) { - NexusSet*result = idx_->nex_input(); + NexusSet*result = idx_->nex_input(rem_out); return result; } @@ -97,45 +97,45 @@ NexusSet* NetEMemory::nex_input() * A parameter by definition has no inputs. It represents a constant * value, even if that value is a constant expression. */ -NexusSet* NetEParam::nex_input() +NexusSet* NetEParam::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetEEvent::nex_input() +NexusSet* NetEEvent::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetEScope::nex_input() +NexusSet* NetEScope::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetESelect::nex_input() +NexusSet* NetESelect::nex_input(bool rem_out) { - NexusSet*result = base_? base_->nex_input() : new NexusSet(); - NexusSet*tmp = expr_->nex_input(); + NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet(); + NexusSet*tmp = expr_->nex_input(rem_out); result->add(*tmp); delete tmp; return result; } -NexusSet* NetESFunc::nex_input() +NexusSet* NetESFunc::nex_input(bool rem_out) { if (nparms_ == 0) return new NexusSet; - NexusSet*result = parms_[0]->nex_input(); + NexusSet*result = parms_[0]->nex_input(rem_out); for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) { - NexusSet*tmp = parms_[idx]->nex_input(); + NexusSet*tmp = parms_[idx]->nex_input(rem_out); result->add(*tmp); delete tmp; } return result; } -NexusSet* NetESignal::nex_input() +NexusSet* NetESignal::nex_input(bool rem_out) { NexusSet*result = new NexusSet; assert(msi_ <= net_->pin_count()); @@ -145,27 +145,27 @@ NexusSet* NetESignal::nex_input() return result; } -NexusSet* NetETernary::nex_input() +NexusSet* NetETernary::nex_input(bool rem_out) { NexusSet*tmp; - NexusSet*result = cond_->nex_input(); + NexusSet*result = cond_->nex_input(rem_out); - tmp = true_val_->nex_input(); + tmp = true_val_->nex_input(rem_out); result->add(*tmp); delete tmp; - tmp = false_val_->nex_input(); + tmp = false_val_->nex_input(rem_out); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEUFunc::nex_input() +NexusSet* NetEUFunc::nex_input(bool rem_out) { NexusSet*result = new NexusSet; for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { - NexusSet*tmp = parms_[idx]->nex_input(); + NexusSet*tmp = parms_[idx]->nex_input(rem_out); result->add(*tmp); delete tmp; } @@ -173,33 +173,33 @@ NexusSet* NetEUFunc::nex_input() return result; } -NexusSet* NetEUnary::nex_input() +NexusSet* NetEUnary::nex_input(bool rem_out) { - return expr_->nex_input(); + return expr_->nex_input(rem_out); } -NexusSet* NetEVariable::nex_input() +NexusSet* NetEVariable::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetAssign_::nex_input() +NexusSet* NetAssign_::nex_input(bool rem_out) { if (bmux_ == 0) return new NexusSet; else - return bmux_->nex_input(); + return bmux_->nex_input(rem_out); } -NexusSet* NetAssignBase::nex_input() +NexusSet* NetAssignBase::nex_input(bool rem_out) { - NexusSet*result = rval_->nex_input(); + NexusSet*result = rval_->nex_input(rem_out); /* It is possible that the lval_ can hav nex_input values. In particular, index expressions are statement inputs as well, so should be addressed here. */ for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { - NexusSet*tmp = cur->nex_input(); + NexusSet*tmp = cur->nex_input(rem_out); result->add(*tmp); delete tmp; } @@ -224,7 +224,7 @@ NexusSet* NetAssignBase::nex_input() * In this example, "t" should not be in the input set because it is * used by the sequence as a temporary value. */ -NexusSet* NetBlock::nex_input() +NexusSet* NetBlock::nex_input(bool rem_out) { if (last_ == 0) return new NexusSet; @@ -244,24 +244,24 @@ NexusSet* NetBlock::nex_input() do { /* Get the inputs for the current statement. */ - NexusSet*tmp = cur->nex_input(); + NexusSet*tmp = cur->nex_input(rem_out); - /* Remove from the input set those bits that are outputs - from previous statements. They aren't really inputs - to the block, just internal intermediate values. */ - tmp->rem(*prev); - - /* Add the corrected set to the accumulated input set. */ + /* Add the current input set to the accumulated input set. */ result->add(*tmp); delete tmp; - /* Add the current outputs to the accumulated output - set, for processing of later statements. */ + /* Add the current outputs to the accumulated output set, + so they can be removed from the input set below. */ cur->nex_output(*prev); cur = cur->next_; } while (cur != last_->next_); + /* Remove from the input set those bits that are outputs + from other statements. They aren't really inputs + to the block, just internal intermediate values. */ + if (rem_out) result->rem(*prev); + return result; } @@ -270,9 +270,9 @@ NexusSet* NetBlock::nex_input() * the inputs to all the guards, and the inputs to all the guarded * statements. */ -NexusSet* NetCase::nex_input() +NexusSet* NetCase::nex_input(bool rem_out) { - NexusSet*result = expr_->nex_input(); + NexusSet*result = expr_->nex_input(rem_out); if (result == 0) return 0; @@ -282,7 +282,7 @@ NexusSet* NetCase::nex_input() if (items_[idx].statement == 0) continue; - NexusSet*tmp = items_[idx].statement->nex_input(); + NexusSet*tmp = items_[idx].statement->nex_input(rem_out); assert(tmp); result->add(*tmp); delete tmp; @@ -291,7 +291,7 @@ NexusSet* NetCase::nex_input() case is special and is identified by a null guard. The default guard obviously has no input. */ if (items_[idx].guard) { - tmp = items_[idx].guard->nex_input(); + tmp = items_[idx].guard->nex_input(rem_out); assert(tmp); result->add(*tmp); delete tmp; @@ -301,24 +301,24 @@ NexusSet* NetCase::nex_input() return result; } -NexusSet* NetCAssign::nex_input() +NexusSet* NetCAssign::nex_input(bool rem_out) { cerr << get_line() << ": internal warning: NetCAssign::nex_input()" << " not implemented." << endl; return new NexusSet; } -NexusSet* NetCondit::nex_input() +NexusSet* NetCondit::nex_input(bool rem_out) { - NexusSet*result = expr_->nex_input(); + NexusSet*result = expr_->nex_input(rem_out); if (if_ != 0) { - NexusSet*tmp = if_->nex_input(); + NexusSet*tmp = if_->nex_input(rem_out); result->add(*tmp); delete tmp; } if (else_ != 0) { - NexusSet*tmp = else_->nex_input(); + NexusSet*tmp = else_->nex_input(rem_out); result->add(*tmp); delete tmp; } @@ -326,16 +326,16 @@ NexusSet* NetCondit::nex_input() return result; } -NexusSet* NetForce::nex_input() +NexusSet* NetForce::nex_input(bool rem_out) { cerr << get_line() << ": internal warning: NetForce::nex_input()" << " not implemented." << endl; return new NexusSet; } -NexusSet* NetForever::nex_input() +NexusSet* NetForever::nex_input(bool rem_out) { - NexusSet*result = statement_->nex_input(); + NexusSet*result = statement_->nex_input(rem_out); return result; } @@ -348,29 +348,29 @@ NexusSet* NetForever::nex_input() * include the input set of the because it does not affect the * result. */ -NexusSet* NetPDelay::nex_input() +NexusSet* NetPDelay::nex_input(bool rem_out) { - NexusSet*result = statement_->nex_input(); + NexusSet*result = statement_->nex_input(rem_out); return result; } -NexusSet* NetRepeat::nex_input() +NexusSet* NetRepeat::nex_input(bool rem_out) { - NexusSet*result = statement_->nex_input(); - NexusSet*tmp = expr_->nex_input(); + NexusSet*result = statement_->nex_input(rem_out); + NexusSet*tmp = expr_->nex_input(rem_out); result->add(*tmp); delete tmp; return result; } -NexusSet* NetSTask::nex_input() +NexusSet* NetSTask::nex_input(bool rem_out) { if (parms_.count() == 0) return new NexusSet; - NexusSet*result = parms_[0]->nex_input(); + NexusSet*result = parms_[0]->nex_input(rem_out); for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { - NexusSet*tmp = parms_[idx]->nex_input(); + NexusSet*tmp = parms_[idx]->nex_input(rem_out); result->add(*tmp); delete tmp; } @@ -383,15 +383,15 @@ NexusSet* NetSTask::nex_input() * parameters to consider, because the compiler already removed them * and converted them to blocking assignments. */ -NexusSet* NetUTask::nex_input() +NexusSet* NetUTask::nex_input(bool rem_out) { return new NexusSet; } -NexusSet* NetWhile::nex_input() +NexusSet* NetWhile::nex_input(bool rem_out) { - NexusSet*result = proc_->nex_input(); - NexusSet*tmp = cond_->nex_input(); + NexusSet*result = proc_->nex_input(rem_out); + NexusSet*tmp = cond_->nex_input(rem_out); result->add(*tmp); delete tmp; return result; diff --git a/netlist.h b/netlist.h index 98e4a93d0..06b0524bd 100644 --- a/netlist.h +++ b/netlist.h @@ -1130,7 +1130,7 @@ class NetExpr : public LineInfo { // Get the Nexus that are the input to this // expression. Normally this descends down to the reference to // a signal that reads from its input. - virtual NexusSet* nex_input() =0; + virtual NexusSet* nex_input(bool rem_out = true) =0; // Return a version of myself that is structural. This is used // for converting expressions to gates. @@ -1171,7 +1171,7 @@ class NetEConst : public NetExpr { virtual NetEConst* dup_expr() const; virtual NetNet*synthesize(Design*); - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); private: verinum value_; @@ -1223,7 +1223,7 @@ class NetECReal : public NetExpr { virtual NetECReal* dup_expr() const; virtual NetNet*synthesize(Design*); - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); private: verireal value_; @@ -1451,7 +1451,7 @@ class NetProc : public virtual LineInfo, public Attrib { // Find the Nexa that are input by the statement. This is used // for example by @* to find the inputs to the process for the // sensitivity list. - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); // Find the nexa that are set by the statement. Add the output // values to the set passed as a parameter. @@ -1583,7 +1583,7 @@ class NetAssign_ { // being outputs. For example foo[idx] = ... is the l-value // (NetAssign_ object) with a foo l-value and the input // expression idx. - NexusSet* nex_input(); + NexusSet* nex_input(bool rem_out = true); // This pointer is for keeping simple lists. NetAssign_* more; @@ -1622,7 +1622,7 @@ class NetAssignBase : public NetProc { void set_delay(NetExpr*); const NetExpr* get_delay() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&o); @@ -1722,7 +1722,7 @@ class NetBlock : public NetProc { // for sequential blocks. void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); @@ -1762,7 +1762,7 @@ class NetCase : public NetProc { const NetExpr*expr(unsigned idx) const { return items_[idx].guard;} const NetProc*stat(unsigned idx) const { return items_[idx].statement; } - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&out); virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag, @@ -1809,7 +1809,7 @@ class NetCAssign : public NetProc, public NetNode { const Link& lval_pin(unsigned) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void dump(ostream&, unsigned ind) const; virtual bool emit_proc(struct target_t*) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -1849,7 +1849,7 @@ class NetCondit : public NetProc { bool emit_recurse_if(struct target_t*) const; bool emit_recurse_else(struct target_t*) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&o); bool is_asynchronous(); @@ -2153,7 +2153,7 @@ class NetForce : public NetProc, public NetNode { const NetNet*lval() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void dump(ostream&, unsigned ind) const; virtual bool emit_proc(struct target_t*) const; @@ -2176,7 +2176,7 @@ class NetForever : public NetProc { void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2250,7 +2250,7 @@ class NetPDelay : public NetProc { unsigned long delay() const; const NetExpr*expr() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; @@ -2276,7 +2276,7 @@ class NetRepeat : public NetProc { const NetExpr*expr() const; void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2328,7 +2328,7 @@ class NetSTask : public NetProc { const NetExpr* parm(unsigned idx) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2434,7 +2434,7 @@ class NetEUFunc : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEUFunc*dup_expr() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual NetNet* synthesize(Design*); @@ -2464,7 +2464,7 @@ class NetUTask : public NetProc { const NetScope* task() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2487,7 +2487,7 @@ class NetWhile : public NetProc { void emit_proc_recurse(struct target_t*) const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2597,7 +2597,7 @@ class NetEBinary : public NetExpr { virtual bool has_width() const; virtual NetEBinary* dup_expr() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -2815,7 +2815,7 @@ class NetEConcat : public NetExpr { unsigned nparms() const { return parms_.count() ; } NetExpr* parm(unsigned idx) const { return parms_[idx]; } - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool has_width() const; virtual bool set_width(unsigned w); virtual NetEConcat* dup_expr() const; @@ -2848,7 +2848,7 @@ class NetEVariable : public NetExpr { void dump(ostream&) const; NetEVariable*dup_expr() const; - NexusSet* nex_input(); + NexusSet* nex_input(bool rem_out = true); private: NetVariable*var_; @@ -2869,7 +2869,7 @@ class NetEParam : public NetExpr { NetEParam(class Design*des, NetScope*scope, perm_string name); ~NetEParam(); - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool set_width(unsigned w); virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; @@ -2905,7 +2905,7 @@ class NetESelect : public NetExpr { const NetExpr*sub_expr() const; const NetExpr*select() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool set_width(unsigned w); virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; @@ -2932,7 +2932,7 @@ class NetEEvent : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEEvent* dup_expr() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void dump(ostream&os) const; @@ -2955,7 +2955,7 @@ class NetEScope : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEScope* dup_expr() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void dump(ostream&os) const; @@ -2983,7 +2983,7 @@ class NetESFunc : public NetExpr { const NetExpr* parm(unsigned idx) const; virtual TYPE expr_type() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual bool set_width(unsigned); virtual void dump(ostream&) const; @@ -3021,7 +3021,7 @@ class NetETernary : public NetExpr { virtual NetETernary* dup_expr() const; virtual NetExpr* eval_tree(); - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; virtual NetNet*synthesize(Design*); @@ -3061,7 +3061,7 @@ class NetEUnary : public NetExpr { virtual NetEUnary* dup_expr() const; virtual NetEConst* eval_tree(); - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -3115,7 +3115,7 @@ class NetEMemory : public NetExpr { NetExpr* eval_tree(); virtual NetEMemory*dup_expr() const; - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -3149,7 +3149,7 @@ class NetESignal : public NetExpr { virtual NetESignal* dup_expr() const; NetNet* synthesize(Design*des); - NexusSet* nex_input(); + NexusSet* nex_input(bool rem_out = true); // These methods actually reference the properties of the // NetNet object that I point to. @@ -3193,7 +3193,7 @@ class NetEBitSel : public NetExpr { NetEBitSel* dup_expr() const; NetNet* synthesize(Design*des); - virtual NexusSet* nex_input(); + virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const;