diff --git a/PGenerate.h b/PGenerate.h index a9af52120..74082a27a 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -65,7 +65,7 @@ class PGenerate : public LineInfo, public LexicalScope { PScope*lexical_scope; enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE, - GS_CASE, GS_CASE_ITEM}; + GS_CASE, GS_CASE_ITEM, GS_NBLOCK}; scheme_t scheme_type; // generate loops have an index variable and three @@ -102,6 +102,7 @@ class PGenerate : public LineInfo, public LexicalScope { bool generate_scope_loop_(Design*des, NetScope*container); bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag); bool generate_scope_case_(Design*des, NetScope*container); + bool generate_scope_nblock_(Design*des, NetScope*container); // Elaborate_scope within a generated scope. void elaborate_subscope_(Design*des, NetScope*scope); diff --git a/elab_scope.cc b/elab_scope.cc index 083808430..2fcc1017b 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -461,7 +461,9 @@ bool PGenerate::generate_scope(Design*des, NetScope*container) case GS_CASE: return generate_scope_case_(des, container); - return true; + + case GS_NBLOCK: + return generate_scope_nblock_(des, container); case GS_CASE_ITEM: cerr << get_fileline() << ": internal error: " @@ -718,6 +720,29 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container) return true; } +bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container) +{ + hname_t use_name (scope_name); + if (container->child(use_name)) { + cerr << get_fileline() << ": error: block/scope name " + << scope_name << " already used in this context." + << endl; + des->errors += 1; + return false; + } + if (debug_scopes) + cerr << get_fileline() << ": debug: Generate named block " + << ": Generate scope=" << use_name << endl; + + NetScope*scope = new NetScope(container, use_name, + NetScope::GENBLOCK); + scope->set_line(get_file(), get_lineno()); + + elaborate_subscope_(des, scope); + + return true; +} + void PGenerate::elaborate_subscope_(Design*des, NetScope*scope) { // Scan the generated scope for nested generate schemes, diff --git a/parse.y b/parse.y index 6ea228b8c..1a0f29bd6 100644 --- a/parse.y +++ b/parse.y @@ -2235,6 +2235,16 @@ module_item cerr << @2 << ": warning: Anachronistic use of begin/end to surround generate schemes." << endl; } } + | K_generate K_begin ':' IDENTIFIER { + pform_start_generate_nblock(@1, $4); + } module_item_list_opt K_end K_endgenerate + { /* Detect and warn about anachronistic named begin/end use */ + if (generation_flag > GN_VER2001) { + warn_count += 1; + cerr << @2 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl; + } + pform_endgenerate(); + } /* specify blocks are parsed but ignored. */ diff --git a/pform.cc b/pform.cc index 814e8aa8d..ef3ceacd4 100644 --- a/pform.cc +++ b/pform.cc @@ -530,6 +530,28 @@ void pform_start_generate_case(const struct vlltype&li, PExpr*expr) pform_cur_generate->loop_step = 0; } +/* + * The named block generate case. + */ +void pform_start_generate_nblock(const struct vlltype&li, char*name) +{ + PGenerate*gen = new PGenerate(scope_generate_counter++); + + FILE_NAME(gen, li); + + gen->parent = pform_cur_generate; + pform_cur_generate = gen; + + pform_cur_generate->scheme_type = PGenerate::GS_NBLOCK; + + pform_cur_generate->loop_init = 0; + pform_cur_generate->loop_test = 0; + pform_cur_generate->loop_step = 0; + + pform_cur_generate->scope_name = lex_strings.make(name); + delete[]name; +} + /* * The generate case item is a special case schema that takes its id * from the case schema that it is a part of. The idea is that the diff --git a/pform.h b/pform.h index a11a73f1f..27330573b 100644 --- a/pform.h +++ b/pform.h @@ -204,6 +204,7 @@ extern void pform_start_generate_for(const struct vlltype&li, extern void pform_start_generate_if(const struct vlltype&li, PExpr*test); extern void pform_start_generate_else(const struct vlltype&li); extern void pform_start_generate_case(const struct vlltype&lp, PExpr*test); +extern void pform_start_generate_nblock(const struct vlltype&lp, char*name); extern void pform_generate_case_item(const struct vlltype&lp, PExpr*test); extern void pform_generate_block_name(char*name); extern void pform_endgenerate(); diff --git a/pform_dump.cc b/pform_dump.cc index 87159644a..8d301ff40 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1002,6 +1002,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const else out << " default:"; break; + case GS_NBLOCK: + out << " begin"; } if (scope_name) @@ -1035,7 +1037,11 @@ void PGenerate::dump(ostream&out, unsigned indent) const (*idx)->dump(out, indent+2); } - out << setw(indent) << "" << "endgenerate" << endl; + if (scheme_type == GS_NBLOCK) { + out << setw(indent) << "" << "end endgenerate" << endl; + } else { + out << setw(indent) << "" << "endgenerate" << endl; + } } void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const