diff --git a/net_func_eval.cc b/net_func_eval.cc index 68e660ec9..0a616fe08 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -55,9 +55,9 @@ static NetExpr* fix_assign_value(const NetNet*lhs, NetExpr*rhs) NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector&args) const { - // Make the context map; - map::iterator ptr; - mapcontext_map; + // Make the context map. + map::iterator ptr; + mapcontext_map; if (debug_eval_tree) { cerr << loc.get_fileline() << ": debug: " @@ -65,13 +65,17 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vectorbasename()] = 0; + LocalVar&return_var = context_map[scope_->basename()]; + return_var.nwords = 0; + return_var.value = 0; // Load the input ports into the map... ivl_assert(loc, ports_.size() == args.size()); for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) { perm_string aname = ports_[idx]->name(); - context_map[aname] = fix_assign_value(ports_[idx], args[idx]); + LocalVar&input_var = context_map[aname]; + input_var.nwords = 0; + input_var.value = fix_assign_value(ports_[idx], args[idx]); if (debug_eval_tree) { cerr << loc.get_fileline() << ": debug: " @@ -90,13 +94,22 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vectorbasename()); - NetExpr*res = ptr->second; + NetExpr*res = ptr->second.value; context_map.erase(ptr); - // Cleanup the rest of the context. for (ptr = context_map.begin() ; ptr != context_map.end() ; ++ptr) { - delete ptr->second; + + unsigned nwords = ptr->second.nwords; + if (nwords > 0) { + NetExpr**array = ptr->second.array; + for (unsigned idx = 0 ; idx < nwords ; idx += 1) { + delete array[idx]; + } + delete [] ptr->second.array; + } else { + delete ptr->second.value; + } } // Done. @@ -108,7 +121,7 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector&context_map) const + map&context_map) const { for (map::const_iterator cur = signals_map_.begin() ; cur != signals_map_.end() ; ++cur) { @@ -118,17 +131,33 @@ void NetScope::evaluate_function_find_locals(const LineInfo&loc, if (tmp->port_type() != NetNet::NOT_A_PORT) continue; - context_map[tmp->name()] = 0; + unsigned nwords = 0; + if (tmp->unpacked_dimensions() > 0) + nwords = tmp->unpacked_count(); + + LocalVar&local_var = context_map[tmp->name()]; + local_var.nwords = nwords; + + if (nwords > 0) { + NetExpr**array = new NetExpr*[nwords]; + for (unsigned idx = 0 ; idx < nwords ; idx += 1) { + array[idx] = 0; + } + local_var.array = array; + } else { + local_var.value = 0; + } if (debug_eval_tree) { cerr << loc.get_fileline() << ": debug: " - << " (local) " << tmp->name() << endl; + << " (local) " << tmp->name() + << (nwords > 0 ? "[]" : "") << endl; } } } NetExpr* NetExpr::evaluate_function(const LineInfo&, - map&) const + map&) const { cerr << get_fileline() << ": sorry: I don't know how to evaluate this expression at compile time." << endl; cerr << get_fileline() << ": : Expression type:" << typeid(*this).name() << endl; @@ -137,7 +166,7 @@ NetExpr* NetExpr::evaluate_function(const LineInfo&, } bool NetProc::evaluate_function(const LineInfo&, - map&) const + map&) const { cerr << get_fileline() << ": sorry: I don't know how to evaluate this statement at compile time." << endl; cerr << get_fileline() << ": : Statement type:" << typeid(*this).name() << endl; @@ -146,14 +175,33 @@ bool NetProc::evaluate_function(const LineInfo&, } bool NetAssign::eval_func_lval_(const LineInfo&loc, - map&context_map, + map&context_map, const NetAssign_*lval, NetExpr*rval_result) const { - map::iterator ptr = context_map.find(lval->name()); + map::iterator ptr = context_map.find(lval->name()); ivl_assert(*this, ptr != context_map.end()); - // Do not support having l-values that are unpacked arrays. - ivl_assert(loc, lval->word() == 0); + NetExpr*old_lval; + unsigned word = 0; + if (ptr->second.nwords > 0) { + NetExpr*word_result = lval->word()->evaluate_function(loc, context_map); + if (word_result == 0) { + delete rval_result; + return false; + } + + NetEConst*word_const = dynamic_cast(word_result); + ivl_assert(loc, word_const); + + word = word_const->value().as_long(); + + if (word >= ptr->second.nwords) + return true; + + old_lval = ptr->second.array[word]; + } else { + old_lval = ptr->second.value; + } if (const NetExpr*base_expr = lval->get_base()) { NetExpr*base_result = base_expr->evaluate_function(loc, context_map); @@ -170,13 +218,13 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc, listprefix (0); base = lval->sig()->sb_to_idx(prefix, base); - if (ptr->second == 0) - ptr->second = make_const_x(lval->sig()->vector_width()); + if (old_lval == 0) + old_lval = make_const_x(lval->sig()->vector_width()); - ivl_assert(loc, base + lval->lwidth() <= ptr->second->expr_width()); + ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width()); - NetEConst*ptr_const = dynamic_cast(ptr->second); - verinum lval_v = ptr_const->value(); + NetEConst*lval_const = dynamic_cast(old_lval); + verinum lval_v = lval_const->value(); NetEConst*rval_const = dynamic_cast(rval_result); verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth()); @@ -190,8 +238,8 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc, rval_result = fix_assign_value(lval->sig(), rval_result); } - if (ptr->second) - delete ptr->second; + if (old_lval) + delete old_lval; if (debug_eval_tree) { cerr << get_fileline() << ": debug: " @@ -199,13 +247,16 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc, << " = " << *rval_result << endl; } - ptr->second = rval_result; + if (ptr->second.nwords > 0) + ptr->second.array[word] = rval_result; + else + ptr->second.value = rval_result; return true; } bool NetAssign::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { // Evaluate the r-value expression. NetExpr*rval_result = rval()->evaluate_function(loc, context_map); @@ -247,10 +298,12 @@ bool NetAssign::evaluate_function(const LineInfo&loc, * evaluating the statements in order. */ bool NetBlock::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { bool flag = true; NetProc*cur = last_; + if (cur == 0) return true; + do { cur = cur->next_; bool cur_flag = cur->evaluate_function(loc, context_map); @@ -263,7 +316,7 @@ bool NetBlock::evaluate_function(const LineInfo&loc, } bool NetCase::evaluate_function_vect_(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetExpr*case_expr = expr_->evaluate_function(loc, context_map); if (case_expr == 0) @@ -325,7 +378,7 @@ bool NetCase::evaluate_function_vect_(const LineInfo&loc, } bool NetCase::evaluate_function_real_(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetExpr*case_expr = expr_->evaluate_function(loc, context_map); if (case_expr == 0) @@ -369,7 +422,7 @@ bool NetCase::evaluate_function_real_(const LineInfo&loc, } bool NetCase::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { if (expr_->expr_type() == IVL_VT_REAL) return evaluate_function_real_(loc, context_map); @@ -378,7 +431,7 @@ bool NetCase::evaluate_function(const LineInfo&loc, } bool NetCondit::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetExpr*cond = expr_->evaluate_function(loc, context_map); if (cond == 0) @@ -399,14 +452,14 @@ bool NetCondit::evaluate_function(const LineInfo&loc, } bool NetDisable::evaluate_function(const LineInfo&, - map&) const + map&) const { disable = target_; return true; } bool NetForever::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { bool flag = true; @@ -428,7 +481,7 @@ bool NetForever::evaluate_function(const LineInfo&loc, } bool NetRepeat::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { bool flag = true; @@ -462,14 +515,14 @@ bool NetRepeat::evaluate_function(const LineInfo&loc, } bool NetSTask::evaluate_function(const LineInfo&, - map&) const + map&) const { // system tasks within a constant function are ignored return true; } bool NetWhile::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { bool flag = true; @@ -513,7 +566,7 @@ bool NetWhile::evaluate_function(const LineInfo&loc, } NetExpr* NetEBinary::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetExpr*lval = left_->evaluate_function(loc, context_map); NetExpr*rval = right_->evaluate_function(loc, context_map); @@ -531,7 +584,7 @@ NetExpr* NetEBinary::evaluate_function(const LineInfo&loc, } NetExpr* NetEConcat::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { vectorvals(parms_.size()); unsigned gap = 0; @@ -558,7 +611,7 @@ NetExpr* NetEConcat::evaluate_function(const LineInfo&loc, } NetExpr* NetEConst::evaluate_function(const LineInfo&, - map&) const + map&) const { NetEConst*res = new NetEConst(value_); res->set_line(*this); @@ -566,7 +619,7 @@ NetExpr* NetEConst::evaluate_function(const LineInfo&, } NetExpr* NetECReal::evaluate_function(const LineInfo&, - map&) const + map&) const { NetECReal*res = new NetECReal(value_); res->set_line(*this); @@ -574,7 +627,7 @@ NetExpr* NetECReal::evaluate_function(const LineInfo&, } NetExpr* NetESelect::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetExpr*sub_exp = expr_->evaluate_function(loc, context_map); ivl_assert(loc, sub_exp); @@ -608,43 +661,53 @@ NetExpr* NetESelect::evaluate_function(const LineInfo&loc, return res_const; } -NetExpr* NetESignal::evaluate_function(const LineInfo&, - map&context_map) const +NetExpr* NetESignal::evaluate_function(const LineInfo&loc, + map&context_map) const { - if (word_) { - cerr << get_fileline() << ": sorry: I don't know how to evaluate signal word selects at compile time." << endl; - return 0; - } - - map::iterator ptr = context_map.find(name()); + map::iterator ptr = context_map.find(name()); if (ptr == context_map.end()) { cerr << get_fileline() << ": error: Cannot evaluate " << name() << " in this context." << endl; return 0; } - if (ptr->second == 0) { + NetExpr*value = 0; + if (ptr->second.nwords > 0) { + ivl_assert(loc, word_); + NetExpr*word_result = word_->evaluate_function(loc, context_map); + if (word_result == 0) + return 0; + + NetEConst*word_const = dynamic_cast(word_result); + ivl_assert(loc, word_const); + + unsigned word = word_const->value().as_long(); + + if (word < ptr->second.nwords) + value = ptr->second.array[word]; + } else { + value = ptr->second.value; + } + + if (value == 0) { switch (expr_type()) { case IVL_VT_REAL: - ptr->second = new NetECReal( verireal(0.0) ); - break; + return new NetECReal( verireal(0.0) ); case IVL_VT_BOOL: - ptr->second = make_const_0(expr_width()); - break; + return make_const_0(expr_width()); case IVL_VT_LOGIC: - ptr->second = make_const_x(expr_width()); - break; + return make_const_x(expr_width()); default: cerr << get_fileline() << ": sorry: I don't know how to initialize " << *this << endl; return 0; } } - return ptr->second->dup_expr(); + return value->dup_expr(); } NetExpr* NetETernary::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { auto_ptr cval (cond_->evaluate_function(loc, context_map)); @@ -671,7 +734,7 @@ NetExpr* NetETernary::evaluate_function(const LineInfo&loc, } NetExpr* NetEUnary::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetExpr*val = expr_->evaluate_function(loc, context_map); if (val == 0) return 0; @@ -682,7 +745,7 @@ NetExpr* NetEUnary::evaluate_function(const LineInfo&loc, } NetExpr* NetESFunc::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { ID id = built_in_id_(); ivl_assert(*this, id != NOT_BUILT_IN); @@ -712,7 +775,7 @@ NetExpr* NetESFunc::evaluate_function(const LineInfo&loc, } NetExpr* NetEUFunc::evaluate_function(const LineInfo&loc, - map&context_map) const + map&context_map) const { NetFuncDef*def = func_->func_def(); ivl_assert(*this, def); diff --git a/netlist.h b/netlist.h index 67a097065..3a5c78ca4 100644 --- a/netlist.h +++ b/netlist.h @@ -755,6 +755,17 @@ class NetNet : public NetObj, public PortType { int port_index_; }; +/* + * This object type is used for holding local variable values when + * evaluating constant user functions. + */ +struct LocalVar { + unsigned nwords; // zero for a simple variable + union { + NetExpr* value; // a simple variable + NetExpr** array; // an array variable + }; +}; /* * This object type is used to contain a logical scope within a @@ -867,7 +878,7 @@ class NetScope : public Attrib { // This is used by the evaluate_function setup to collect // local variables from the scope. void evaluate_function_find_locals(const LineInfo&loc, - map&context_map) const; + map&ctx) const; void set_line(perm_string file, perm_string def_file, unsigned lineno, unsigned def_lineno); @@ -1817,7 +1828,7 @@ class NetExpr : public LineInfo { // allocated constant, or nil if the expression cannot be // evaluated for any reason. virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; // Get the Nexus that are the input to this // expression. Normally this descends down to the reference to @@ -1882,7 +1893,7 @@ class NetEConst : public NetExpr { virtual NexusSet* nex_input(bool rem_out = true); virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; private: verinum value_; @@ -1951,11 +1962,12 @@ class NetECReal : public NetExpr { virtual void dump(ostream&) const; virtual NetECReal* dup_expr() const; - virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*); virtual NexusSet* nex_input(bool rem_out = true); + virtual NetExpr*evaluate_function(const LineInfo&loc, + map&ctx) const; + private: verireal value_; }; @@ -2361,7 +2373,7 @@ class NetProc : public virtual LineInfo { // identifiers to values. The function returns true if the // processing succeeds, or false otherwise. virtual bool evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; // This method is called by functors that want to scan a // process in search of matchable patterns. @@ -2576,11 +2588,11 @@ class NetAssign : public NetAssignBase { virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; - virtual bool evaluate_function(const LineInfo&loc, std::map&context_map) const; + virtual bool evaluate_function(const LineInfo&loc, + map&ctx) const; private: - bool eval_func_lval_(const LineInfo&loc, - std::map&context_map, + bool eval_func_lval_(const LineInfo&loc, map&ctx, const NetAssign_*lval, NetExpr*rval_result) const; char op_; @@ -2631,7 +2643,7 @@ class NetBlock : public NetProc { const NetProc*proc_next(const NetProc*cur) const; bool evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; // synthesize as asynchronous logic, and return true. bool synth_async(Design*des, NetScope*scope, @@ -2697,13 +2709,13 @@ class NetCase : public NetProc { virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; virtual bool evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; private: bool evaluate_function_vect_(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; bool evaluate_function_real_(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; TYPE type_; @@ -2777,7 +2789,7 @@ class NetCondit : public NetProc { virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; virtual bool evaluate_function(const LineInfo&loc, - map&ctx) const; + map&ctx) const; private: NetExpr* expr_; @@ -2844,11 +2856,10 @@ class NetDisable : public NetProc { const NetScope*target() const; - bool evaluate_function(const LineInfo&loc, - std::map&ctx) const; - virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool evaluate_function(const LineInfo&loc, + map&ctx) const; private: NetScope*target_; @@ -3094,7 +3105,7 @@ class NetForever : public NetProc { virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; virtual bool evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; private: NetProc*statement_; @@ -3217,7 +3228,7 @@ class NetRepeat : public NetProc { virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; virtual bool evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; private: NetExpr*expr_; @@ -3263,13 +3274,12 @@ class NetSTask : public NetProc { const NetExpr* parm(unsigned idx) const; - virtual bool evaluate_function(const LineInfo&loc, - map&ctx) const; - 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; + virtual bool evaluate_function(const LineInfo&loc, + map&ctx) const; private: const char* name_; @@ -3343,7 +3353,7 @@ class NetEUFunc : public NetExpr { virtual NexusSet* nex_input(bool rem_out = true); virtual NetExpr* eval_tree(); virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; virtual NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root); @@ -3429,7 +3439,7 @@ class NetWhile : public NetProc { virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; virtual bool evaluate_function(const LineInfo&loc, - map&ctx) const; + map&ctx) const; private: NetExpr* cond_; @@ -3559,7 +3569,7 @@ class NetEBinary : public NetExpr { virtual NetEBinary* dup_expr() const; virtual NetExpr* eval_tree(); virtual NetExpr* evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; @@ -3818,7 +3828,7 @@ class NetEConcat : public NetExpr { virtual NetEConcat* dup_expr() const; virtual NetEConst* eval_tree(); virtual NetExpr* evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*root); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -3866,7 +3876,7 @@ class NetESelect : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEConst* eval_tree(); virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; virtual NetESelect* dup_expr() const; virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root); virtual void dump(ostream&) const; @@ -4034,7 +4044,7 @@ class NetESFunc : public NetExpr { virtual NetExpr* eval_tree(); virtual NetExpr* evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(bool rem_out = true); @@ -4108,10 +4118,8 @@ class NetETernary : public NetExpr { virtual NetETernary* dup_expr() const; virtual NetExpr* eval_tree(); - virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; - + map&ctx) const; virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; @@ -4164,7 +4172,7 @@ class NetEUnary : public NetExpr { virtual NetEUnary* dup_expr() const; virtual NetExpr* eval_tree(); virtual NetExpr* evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); virtual ivl_variable_type_t expr_type() const; @@ -4247,7 +4255,7 @@ class NetESignal : public NetExpr { netenum_t*enumeration() const; virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; + map&ctx) const; // This is the expression for selecting an array word, if this // signal refers to an array.