diff --git a/parse.y b/parse.y index 07063d4dd..7ba6caba5 100644 --- a/parse.y +++ b/parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -448,6 +448,11 @@ static void current_function_set_statement(const YYLTYPE&loc, vector list*exprs; } class_declaration_extends; + struct { + char*text; + PExpr*expr; + } genvar_iter; + verinum* number; verireal* realtime; @@ -680,6 +685,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type unique_priority +%type genvar_iteration + %token K_TAND %right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ %right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ @@ -1492,6 +1499,19 @@ function_declaration /* IEEE1800-2005: A.2.6 */ ; +genvar_iteration /* IEEE1800-2012: A.4.2 */ + : IDENTIFIER '=' expression + { $$ = { $1, $3 }; } + | IDENTIFIER K_INCR + { $$ = { $1, pform_genvar_inc_dec(@1, $1, true) }; } + | IDENTIFIER K_DECR + { $$ = { $1, pform_genvar_inc_dec(@1, $1, false) }; } + | K_INCR IDENTIFIER + { $$ = { $2, pform_genvar_inc_dec(@1, $2, true) }; } + | K_DECR IDENTIFIER + { $$ = { $2, pform_genvar_inc_dec(@1, $2, false) }; } + ; + import_export /* IEEE1800-2012: A.2.9 */ : K_import { $$ = true; } | K_export { $$ = false; } @@ -5257,8 +5277,8 @@ module_item | K_for '(' IDENTIFIER '=' expression ';' expression ';' - IDENTIFIER '=' expression ')' - { pform_start_generate_for(@1, $3, $5, $7, $9, $11); } + genvar_iteration ')' + { pform_start_generate_for(@1, $3, $5, $7, $9.text, $9.expr); } generate_block { pform_endgenerate(false); } diff --git a/pform.cc b/pform.cc index 121f21586..cc0862c9d 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -3079,6 +3079,25 @@ PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*ex return tmp; } +PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_flag) +{ + if (!gn_system_verilog()) { + cerr << loc << ": error: Increment/decrement operators " + "require SystemVerilog." << endl; + error_count += 1; + } + + PExpr*lval = new PEIdent(lex_strings.make(name)); + PExpr*rval = new PENumber(new verinum((uint64_t)1, 1)); + FILE_NAME(lval, loc); + FILE_NAME(rval, loc); + + PEBinary*tmp = new PEBinary(inc_flag ? '+' : '-', lval, rval); + FILE_NAME(tmp, loc); + + return tmp; +} + void pform_set_attrib(perm_string name, perm_string key, char*value) { if (PWire*cur = lexical_scope->wires_find(name)) { diff --git a/pform.h b/pform.h index aba405ad0..62723b447 100644 --- a/pform.h +++ b/pform.h @@ -1,7 +1,7 @@ #ifndef IVL_pform_H #define IVL_pform_H /* - * Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-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 @@ -519,6 +519,13 @@ extern std::vector*pform_make_task_ports(const struct vlltype&l extern PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*exp); +/* + * The parser uses this function to convert a genvar increment/decrement + * expression to the equivalent binary add/subtract expression. + */ +extern PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, + bool inc_flag); + /* * These are functions that the outside-the-parser code uses the do * interesting things to the Verilog. The parse function reads and