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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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; direct_nested_ = false;
scheme_type = GS_NONE; scheme_type = GS_NONE;
local_index = false;
loop_init = 0; loop_init = 0;
loop_test = 0; loop_test = 0;
loop_step = 0; loop_step = 0;

View File

@ -1,7 +1,7 @@
#ifndef IVL_PGenerate_H #ifndef IVL_PGenerate_H
#define 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 // generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>) // 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; perm_string loop_index;
PExpr*loop_init; PExpr*loop_init;
PExpr*loop_test; 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) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * 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) bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{ {
// Check that the loop_index variable was declared in a if (!local_index) {
// genvar statement. // Check that the loop_index variable was declared in a
NetScope*cscope = container; // genvar statement.
while (cscope && !cscope->find_genvar(loop_index)) NetScope*cscope = container;
cscope = cscope->parent(); while (cscope && !cscope->find_genvar(loop_index))
if (!cscope) { cscope = cscope->parent();
cerr << get_fileline() << ": error: genvar is missing for " if (!cscope) {
"generate \"loop\" variable '" << loop_index << "'." cerr << get_fileline() << ": error: genvar is missing for "
<< endl; "generate \"loop\" variable '" << loop_index << "'."
des->errors += 1; << endl;
return false; des->errors += 1;
return false;
}
} }
// We're going to need a genvar... // 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 <number> number pos_neg_number
%type <flag> signing unsigned_signed_opt signed_unsigned_opt %type <flag> signing unsigned_signed_opt signed_unsigned_opt
%type <flag> import_export %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 <flag> udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1 %type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
%type <letter> udp_input_sym udp_output_sym %type <letter> udp_input_sym udp_output_sym
@ -5275,10 +5275,10 @@ module_item
| K_genvar list_of_identifiers ';' | K_genvar list_of_identifiers ';'
{ pform_genvars(@1, $2); } { pform_genvars(@1, $2); }
| K_for '(' IDENTIFIER '=' expression ';' | K_for '(' K_genvar_opt IDENTIFIER '=' expression ';'
expression ';' expression ';'
genvar_iteration ')' 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 generate_block
{ pform_endgenerate(false); } { pform_endgenerate(false); }
@ -7341,6 +7341,7 @@ unique_priority
presence is significant. This is a fairly common pattern so presence is significant. This is a fairly common pattern so
collect those rules here. */ collect those rules here. */
K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ;
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ; K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ; K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
K_static_opt : K_static { $$ = 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, void pform_start_generate_for(const struct vlltype&li,
bool local_index,
char*ident1, PExpr*init, char*ident1, PExpr*init,
PExpr*test, PExpr*test,
char*ident2, PExpr*next) 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->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_index = lex_strings.make(ident1);
pform_cur_generate->loop_init = init; pform_cur_generate->loop_init = init;
pform_cur_generate->loop_test = test; 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_genvars(const struct vlltype&li, list<perm_string>*names);
extern void pform_start_generate_for(const struct vlltype&li, extern void pform_start_generate_for(const struct vlltype&li,
bool local_index,
char*ident1, char*ident1,
PExpr*init, PExpr*init,
PExpr*test, 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) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * 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) { while (scope) {
if (scope->genvar_tmp.str() && path_tail.name == scope->genvar_tmp)
return false;
if (path_tail.name == "#") { if (path_tail.name == "#") {
cerr << li->get_fileline() << ": sorry: " cerr << li->get_fileline() << ": sorry: "
<< "Implicit class handle \"super\" not supported." << endl; << "Implicit class handle \"super\" not supported." << endl;