diff --git a/PGenerate.cc b/PGenerate.cc index b69b56887..977c6b418 100644 --- a/PGenerate.cc +++ b/PGenerate.cc @@ -24,8 +24,8 @@ PGenerate::PGenerate(LexicalScope*parent, unsigned id) : LexicalScope(parent), id_number(id) { - direct_nested_ = false; scheme_type = GS_NONE; + directly_nested = false; local_index = false; loop_init = 0; loop_test = 0; @@ -41,52 +41,6 @@ void PGenerate::add_gate(PGate*gate) gates.push_back(gate); } -void PGenerate::probe_for_direct_nesting_(void) -{ - direct_nested_ = false; - - ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE); - - // If this scheme has received an explicit name, then it - // cannot be direct nested. - if (scope_name[0] != '$') return; - - if (! tasks.empty()) return; - if (! funcs.empty()) return; - if (! gates.empty()) return; - if (! parameters.empty()) return; - if (! localparams.empty()) return; - if (! events.empty()) return; - if (! wires.empty()) return; - if (! genvars.empty()) return; - if (! behaviors.empty()) return; - if (! analog_behaviors.empty()) return; - if (! elab_tasks.empty()) return; - - if (generate_schemes.empty()) return; - - switch (generate_schemes.size()) { - case 1: { - PGenerate*child = generate_schemes.front(); - if (child->scheme_type == GS_CONDIT) - direct_nested_ = true; - if (child->scheme_type == GS_CASE) - direct_nested_ = true; - break; - } - - case 2: { - PGenerate*child1 = generate_schemes.front(); - PGenerate*child2 = generate_schemes.back(); - if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE) - direct_nested_ = true; - if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE) - direct_nested_ = true; - break; - } - } -} - ostream& operator << (ostream&out, PGenerate::scheme_t type) { switch (type) { diff --git a/PGenerate.h b/PGenerate.h index 4bdb4e985..e0136793a 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -1,7 +1,7 @@ #ifndef IVL_PGenerate_H #define IVL_PGenerate_H /* - * Copyright (c) 2006-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006-2021 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -69,6 +69,8 @@ class PGenerate : public PNamedItem, public LexicalScope { GS_CASE, GS_CASE_ITEM, GS_NBLOCK}; scheme_t scheme_type; + bool directly_nested; + // generate loops have an index variable and three // expressions: for (index = ; ; index=) // the index is local if it was declared in the init expression, @@ -118,13 +120,6 @@ class PGenerate : public PNamedItem, public LexicalScope { bool generate_scope_case_(Design*des, NetScope*container); bool generate_scope_nblock_(Design*des, NetScope*container); - // Call probe during elaborate_scope to calculate the - // direct_nested_ flag. It is OK to store the direct_nested_ - // information here because "direct nested" is a property of - // the lexical generate code. - void probe_for_direct_nesting_(void); - bool direct_nested_; - // Elaborate_scope within a generated scope. void elaborate_subscope_(Design*des, NetScope*scope); void elaborate_subscope_direct_(Design*des, NetScope*scope); diff --git a/elab_scope.cc b/elab_scope.cc index 7459a8055..d410e1d43 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1093,8 +1093,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else << " value=" << test->value() << ": Generate scope=" << use_name << endl; - probe_for_direct_nesting_(); - if (direct_nested_) { + if (directly_nested) { if (debug_scopes) cerr << get_fileline() << ": debug: Generate condition " << (else_flag? "(else)" : "(if)") @@ -1192,8 +1191,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container) // The name of the scope to generate, whatever that item is. hname_t use_name (item->scope_name); - item->probe_for_direct_nesting_(); - if (item->direct_nested_) { + if (item->directly_nested) { if (debug_scopes) cerr << get_fileline() << ": debug: Generate case item " << scope_name << " detected direct nesting." << endl; diff --git a/elab_sig.cc b/elab_sig.cc index d61cfa61f..561f61d6b 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -430,7 +430,7 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const bool PGenerate::elaborate_sig(Design*des, NetScope*container) const { - if (direct_nested_) + if (directly_nested) return elaborate_sig_direct_(des, container); bool flag = true; @@ -449,7 +449,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const for (generate_it_t cur = generate_schemes.begin() ; cur != generate_schemes.end() ; ++ cur ) { PGenerate*item = *cur; - if (item->direct_nested_ || !item->scope_list_.empty()) { + if (item->directly_nested || !item->scope_list_.empty()) { flag &= item->elaborate_sig(des, container); } } @@ -497,12 +497,12 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const for (generate_it_t icur = item->generate_schemes.begin() ; icur != item->generate_schemes.end() ; ++ icur ) { PGenerate*case_item = *icur; - if (case_item->direct_nested_ || !case_item->scope_list_.empty()) { + if (case_item->directly_nested || !case_item->scope_list_.empty()) { flag &= case_item->elaborate_sig(des, container); } } } else { - if (item->direct_nested_ || !item->scope_list_.empty()) { + if (item->directly_nested || !item->scope_list_.empty()) { // Found the item, and it is direct nested. flag &= item->elaborate_sig(des, container); } diff --git a/elaborate.cc b/elaborate.cc index a625d09db..03ba20a02 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6400,7 +6400,7 @@ void netclass_t::elaborate(Design*des, PClass*pclass) bool PGenerate::elaborate(Design*des, NetScope*container) const { - if (direct_nested_) + if (directly_nested) return elaborate_direct_(des, container); bool flag = true; @@ -6425,7 +6425,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const for (generate_it_t cur = generate_schemes.begin() ; cur != generate_schemes.end() ; ++ cur ) { PGenerate*item = *cur; - if (item->direct_nested_ || !item->scope_list_.empty()) { + if (item->directly_nested || !item->scope_list_.empty()) { flag &= item->elaborate(des, container); } } @@ -6487,7 +6487,7 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const cerr << get_fileline() << ": PGenerate::elaborate_direct_: " << "item->scope_name=" << item->scope_name << ", item->scheme_type=" << item->scheme_type - << ", item->direct_nested_=" << item->direct_nested_ + << ", item->directly_nested=" << item->directly_nested << ", item->scope_list_.size()=" << item->scope_list_.size() << "." << endl; } @@ -6500,12 +6500,12 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const for (generate_it_t icur = item->generate_schemes.begin() ; icur != item->generate_schemes.end() ; ++ icur ) { PGenerate*case_item = *icur; - if (case_item->direct_nested_ || !case_item->scope_list_.empty()) { + if (case_item->directly_nested || !case_item->scope_list_.empty()) { flag &= case_item->elaborate(des, container); } } } else { - if (item->direct_nested_ || !item->scope_list_.empty()) { + if (item->directly_nested || !item->scope_list_.empty()) { // Found the item, and it is direct nested. flag &= item->elaborate(des, container); } diff --git a/parse.y b/parse.y index 21d0e090d..8fe5179a8 100644 --- a/parse.y +++ b/parse.y @@ -5566,7 +5566,7 @@ generate_item_list ; generate_item_list_opt - : generate_item_list + : { pform_generate_single_item = false; } generate_item_list | ; @@ -5577,7 +5577,9 @@ generate_item_list_opt only need to take note here of the scope name, if any. */ generate_block - : module_item + : { pform_generate_single_item = true; } + module_item + { pform_generate_single_item = false; } | K_begin generate_item_list_opt K_end | K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt { pform_generate_block_name($3); diff --git a/pform.cc b/pform.cc index a04c301de..f2f5568c2 100644 --- a/pform.cc +++ b/pform.cc @@ -349,6 +349,10 @@ static unsigned scope_generate_counter = 1; always within a module. */ static PGenerate*pform_cur_generate = 0; + /* This indicates whether a new generate construct can be directly + nested in the current generate construct. */ +bool pform_generate_single_item = false; + /* Blocks within the same conditional generate construct may have the same name. Here we collect the set of names used in each construct, so they can be added to the local scope without @@ -1369,6 +1373,8 @@ void pform_startmodule(const struct vlltype&loc, const char*name, allow_timeunit_decl = true; allow_timeprec_decl = true; + pform_generate_single_item = false; + add_local_symbol(lexical_scope, lex_name, cur_module); lexical_scope = cur_module; @@ -1511,6 +1517,22 @@ void pform_genvars(const struct vlltype&li, list*names) delete names; } +static void detect_directly_nested_generate() +{ + if (pform_cur_generate && pform_generate_single_item) + switch (pform_cur_generate->scheme_type) { + case PGenerate::GS_CASE_ITEM: + // fallthrough + case PGenerate::GS_CONDIT: + // fallthrough + case PGenerate::GS_ELSE: + pform_cur_generate->directly_nested = true; + break; + default: + break; + } +} + void pform_start_generate_for(const struct vlltype&li, bool local_index, char*ident1, PExpr*init, @@ -1538,6 +1560,8 @@ void pform_start_generate_for(const struct vlltype&li, void pform_start_generate_if(const struct vlltype&li, PExpr*test) { + detect_directly_nested_generate(); + PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++); lexical_scope = gen; @@ -1582,6 +1606,8 @@ void pform_start_generate_else(const struct vlltype&li) */ void pform_start_generate_case(const struct vlltype&li, PExpr*expr) { + detect_directly_nested_generate(); + PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++); lexical_scope = gen; @@ -1640,6 +1666,8 @@ void pform_generate_case_item(const struct vlltype&li, list*expr_list) FILE_NAME(gen, li); + gen->directly_nested = pform_cur_generate->directly_nested; + pform_cur_generate = gen; pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM; diff --git a/pform.h b/pform.h index 8531fccdb..3091bf484 100644 --- a/pform.h +++ b/pform.h @@ -294,6 +294,13 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val, */ extern void pform_genvars(const struct vlltype&li, list*names); +/* + * This flag is set by the parser to indicate the current generate block + * was not enclosed in a begin-end pair. This is a pre-requisite for + * directly nesting generate constructs. + */ +extern bool pform_generate_single_item; + extern void pform_start_generate_for(const struct vlltype&li, bool local_index, char*ident1,