From ec0c66ff25cce86095396b218332ae01bf79ae46 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 24 Apr 2014 18:36:49 -0700 Subject: [PATCH] Fix internal error elaborating types used in different scopes Some types, i.e. vector types with parameterized dimensions, may have different elaboration results in different scopes. Handle those cases in the elaboration caches. --- elab_sig.cc | 14 ++++++++++---- elab_type.cc | 15 +++++++++++++++ expr_synth.cc | 6 ++++++ pform_dump.cc | 24 +++++++++++++++++------- pform_types.cc | 9 --------- pform_types.h | 6 ++++-- synth2.cc | 24 +++++++++++++++++++++++- 7 files changed, 75 insertions(+), 23 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index 2d6fdcf9b..980e198b1 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -563,7 +563,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const // Special case: this is a constructor, so the return // signal is also the first argument. For example, the // source code for the definition may be: - // function new(...); + // function new(...); // endfunction // In this case, the "@" port is the synthetic "this" // argument and we also use it as a return value at the @@ -594,6 +594,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const } if (ret_type) { + if (debug_elaborate) { + cerr << get_fileline() << ": PFunction::elaborate_sig: " + << "return type: " << *ret_type << endl; + return_type_->pform_dump(cerr, 8); + } list ret_unpacked; ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type); @@ -615,9 +620,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef); if (debug_elaborate) - cerr << get_fileline() << ": debug: " - << "Attach function definition to scope " - << scope_path(scope) << "." << endl; + cerr << get_fileline() << ": PFunction::elaborate_sig: " + << "Attach function definition " << scope_path(scope) + << " with ret_sig width=" << (ret_sig? ret_sig->vector_width() : 0) + << "." << endl; scope->set_func_def(def); diff --git a/elab_type.cc b/elab_type.cc index c4c97eaa7..1167c1902 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -31,6 +31,21 @@ using namespace std; +/* + * Elaborations of types may vary depending on the scope that it is + * done in, so keep a per-scope cache of the results. + */ +ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) +{ + map::iterator pos = cache_type_elaborate_.lower_bound(scope); + if (pos->first == scope) + return pos->second; + + ivl_type_s*tmp = elaborate_type_raw(des, scope); + cache_type_elaborate_.insert(pos, pair(scope, tmp)); + return tmp; +} + ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const { cerr << get_fileline() << ": internal error: " diff --git a/expr_synth.cc b/expr_synth.cc index 89242ec9b..8812f23f0 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1440,6 +1440,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) osig->local_flag(true); connect(net->pin(0), osig->pin(0)); + if (debug_synth2) { + cerr << get_fileline() << ": NetEUFunc::synthesize: " + << "result_sig_->vector_width()=" << result_sig_->vector_width() + << ", osig->vector_width()=" << osig->vector_width() << endl; + } + /* Connect the pins to the arguments. */ NetFuncDef*def = func_->func_def(); for (unsigned idx = 0; idx < eparms.size(); idx += 1) { diff --git a/pform_dump.cc b/pform_dump.cc index a8b08c04b..65fcdbfe4 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -160,13 +160,6 @@ void parray_type_t::pform_dump(ostream&out, unsigned indent) const base_type->pform_dump(out, indent+4); } -void uarray_type_t::pform_dump(ostream&out, unsigned indent) const -{ - out << setw(indent) << "" << "Unpacked array " << "[...]" - << " of:" << endl; - base_type->pform_dump(out, indent+4); -} - void struct_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked") @@ -181,6 +174,23 @@ void struct_type_t::pform_dump(ostream&out, unsigned indent) const } } +void uarray_type_t::pform_dump(ostream&out, unsigned indent) const +{ + out << setw(indent) << "" << "Unpacked array " << "[...]" + << " of:" << endl; + base_type->pform_dump(out, indent+4); +} + +void vector_type_t::pform_dump(ostream&fd, unsigned indent) const +{ + fd << setw(indent) << "" << "vector of " << base_type; + for (list::iterator cur = pdims->begin() + ; cur != pdims->end() ; ++cur) { + fd << "[" << *(cur->first) << ":" << *(cur->second) << "]"; + } + fd << endl; +} + void class_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "class " << name; diff --git a/pform_types.cc b/pform_types.cc index c809ffbf6..5a7868bef 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -24,15 +24,6 @@ data_type_t::~data_type_t() { } -ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) -{ - if (cache_type_elaborate_) - return cache_type_elaborate_; - - cache_type_elaborate_ = elaborate_type_raw(des, scope); - return cache_type_elaborate_; -} - string_type_t::~string_type_t() { } diff --git a/pform_types.h b/pform_types.h index 32758f5e4..97149dcb4 100644 --- a/pform_types.h +++ b/pform_types.h @@ -88,7 +88,7 @@ struct pform_tf_port_t { */ class data_type_t : public LineInfo { public: - inline explicit data_type_t() : cache_type_elaborate_(0) { } + inline explicit data_type_t() { } virtual ~data_type_t() = 0; // This method is used to figure out the base type of a packed // compound object. Return IVL_VT_NO_TYPE if the type is not packed. @@ -102,7 +102,8 @@ class data_type_t : public LineInfo { // Elaborate the type to an ivl_type_s type. virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; - ivl_type_s*cache_type_elaborate_; + // Keep per-scope elaboration results cached. + std::map cache_type_elaborate_; }; struct void_type_t : public data_type_t { @@ -175,6 +176,7 @@ struct vector_type_t : public data_type_t { std::list*pd) : base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { } virtual ivl_variable_type_t figure_packed_base_type(void)const; + virtual void pform_dump(std::ostream&out, unsigned indent) const; ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; ivl_variable_type_t base_type; diff --git a/synth2.cc b/synth2.cc index ad3c7ddc3..560d553f6 100644 --- a/synth2.cc +++ b/synth2.cc @@ -89,6 +89,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, << "r-value signal is " << rsig->vector_width() << " bits." << endl; cerr << get_fileline() << ": NetAssignBase::synth_async: " << "lval_->lwidth()=" << lval_->lwidth() << endl; + cerr << get_fileline() << ": NetAssignBase::synth_async: " + << "lsig = " << scope_path(scope) << "." << lsig->name() << endl; if (const NetExpr*base = lval_->get_base()) { cerr << get_fileline() << ": NetAssignBase::synth_async: " << "base_=" << *base << endl; @@ -450,6 +452,12 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, connect(bsig.pin(idx), accumulated_nex_out.pin(idx)); accumulated_nex_out.pin(idx).unlink(); } + + if (debug_synth2) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "synthesize else clause at " << else_->get_fileline() + << " is done." << endl; + } } ivl_assert(*this, nex_out.pin_count()==asig.pin_count()); @@ -470,9 +478,23 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, cerr << get_fileline() << ": internal error: " << "NetCondit::synth_async: " << "Mux input sizes do not match." - << "A size=" << mux_width + << " A size=" << mux_width << ", B size=" << bsig.pin(idx).nexus()->vector_width() << endl; + cerr << get_fileline() << ": : " + << "asig node pins:" << endl; + asig.dump_node_pins(cerr, 8); + cerr << get_fileline() << ": : " + << "if_ statement:" << endl; + if_->dump(cerr, 8); + cerr << get_fileline() << ": : " + << "bsig node pins:" << endl; + bsig.dump_node_pins(cerr, 4); + if (else_) { + cerr << get_fileline() << ": : " + << "else_ statement:" << endl; + else_->dump(cerr, 8); + } rc_flag = false; }