Add support for local genvar declaration in generate loops.

As requested in GitHub issue #304.
This commit is contained in:
Martin Whitaker 2020-01-31 20:29:22 +00:00
parent 0023804777
commit 33b822d997
7 changed files with 31 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2020 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
@ -26,6 +26,7 @@ PGenerate::PGenerate(LexicalScope*parent, unsigned id)
{
direct_nested_ = false;
scheme_type = GS_NONE;
local_index = false;
loop_init = 0;
loop_test = 0;
loop_step = 0;

View File

@ -1,7 +1,7 @@
#ifndef IVL_PGenerate_H
#define IVL_PGenerate_H
/*
* Copyright (c) 2006-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2020 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
@ -71,6 +71,9 @@ class PGenerate : public PNamedItem, public LexicalScope {
// generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>)
// the index is local if it was declared in the init expression,
// e.g. for (genvar index = <init>; <test>; index=<step>)
bool local_index;
perm_string loop_index;
PExpr*loop_init;
PExpr*loop_test;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -899,17 +899,19 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// Check that the loop_index variable was declared in a
// genvar statement.
NetScope*cscope = container;
while (cscope && !cscope->find_genvar(loop_index))
cscope = cscope->parent();
if (!cscope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
des->errors += 1;
return false;
if (!local_index) {
// Check that the loop_index variable was declared in a
// genvar statement.
NetScope*cscope = container;
while (cscope && !cscope->find_genvar(loop_index))
cscope = cscope->parent();
if (!cscope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
des->errors += 1;
return false;
}
}
// We're going to need a genvar...

View File

@ -567,7 +567,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <number> number pos_neg_number
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
%type <flag> import_export
%type <flag> K_packed_opt K_reg_opt K_static_opt K_virtual_opt
%type <flag> K_genvar_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
%type <flag> udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
%type <letter> udp_input_sym udp_output_sym
@ -5275,10 +5275,10 @@ module_item
| K_genvar list_of_identifiers ';'
{ pform_genvars(@1, $2); }
| K_for '(' IDENTIFIER '=' expression ';'
| K_for '(' K_genvar_opt IDENTIFIER '=' expression ';'
expression ';'
genvar_iteration ')'
{ pform_start_generate_for(@1, $3, $5, $7, $9.text, $9.expr); }
{ pform_start_generate_for(@2, $3, $4, $6, $8, $10.text, $10.expr); }
generate_block
{ pform_endgenerate(false); }
@ -7341,6 +7341,7 @@ unique_priority
presence is significant. This is a fairly common pattern so
collect those rules here. */
K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ;
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;

View File

@ -1486,6 +1486,7 @@ void pform_genvars(const struct vlltype&li, list<perm_string>*names)
}
void pform_start_generate_for(const struct vlltype&li,
bool local_index,
char*ident1, PExpr*init,
PExpr*test,
char*ident2, PExpr*next)
@ -1499,6 +1500,7 @@ void pform_start_generate_for(const struct vlltype&li,
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
pform_cur_generate->local_index = local_index;
pform_cur_generate->loop_index = lex_strings.make(ident1);
pform_cur_generate->loop_init = init;
pform_cur_generate->loop_test = test;

View File

@ -292,6 +292,7 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
extern void pform_start_generate_for(const struct vlltype&li,
bool local_index,
char*ident1,
PExpr*init,
PExpr*test,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2020 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -108,6 +108,9 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
}
while (scope) {
if (scope->genvar_tmp.str() && path_tail.name == scope->genvar_tmp)
return false;
if (path_tail.name == "#") {
cerr << li->get_fileline() << ": sorry: "
<< "Implicit class handle \"super\" not supported." << endl;