From 93bc5affd3fc635dafec3a37bf4c5b94c252036f Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 11:34:58 +0000 Subject: Allow attributes on individual switch cases in RTLIL. The parser changes are slightly awkward. Consider the following IL: process $0 switch \foo case 1'1 assign \bar \baz ... case end end Before this commit, attributes are valid in , and iff it is immediately followed by a `switch`. (They are essentially attached to the switch.) But, after this commit, and because switch cases do not have an ending delimiter, becomes ambiguous: the attribute could attach to either the following `case`, or to the following `switch`. This isn't expressible in LALR(1) and results in a reduce/reduce conflict. To address this, attributes inside processes are now valid anywhere inside the process: in and a part of case body, and in as a separate rule. As a consequence, attributes can now precede `assign`s, which is made illegal in the same way it is illegal to attach attributes to `connect`. Attributes are tracked separately from the parser state, so this does not affect collection of attributes at all, other than allowing them on `case`s. The grammar change serves purely to allow attributes in more syntactic places. --- frontends/ilang/ilang_parser.y | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'frontends/ilang') diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 44c99906a..b4b9693da 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -282,14 +282,14 @@ proc_stmt: } case_body sync_list TOK_END EOL; switch_stmt: - attr_list TOK_SWITCH sigspec EOL { + TOK_SWITCH sigspec EOL { RTLIL::SwitchRule *rule = new RTLIL::SwitchRule; - rule->signal = *$3; + rule->signal = *$2; rule->attributes = attrbuf; switch_stack.back()->push_back(rule); attrbuf.clear(); - delete $3; - } switch_body TOK_END EOL; + delete $2; + } attr_list switch_body TOK_END EOL; attr_list: /* empty */ | @@ -298,9 +298,11 @@ attr_list: switch_body: switch_body TOK_CASE { RTLIL::CaseRule *rule = new RTLIL::CaseRule; + rule->attributes = attrbuf; switch_stack.back()->back()->cases.push_back(rule); switch_stack.push_back(&rule->switches); case_stack.push_back(rule); + attrbuf.clear(); } compare_list EOL case_body { switch_stack.pop_back(); case_stack.pop_back(); @@ -319,12 +321,15 @@ compare_list: /* empty */; case_body: + case_body attr_stmt | case_body switch_stmt | case_body assign_stmt | /* empty */; assign_stmt: TOK_ASSIGN sigspec sigspec EOL { + if (attrbuf.size() != 0) + rtlil_frontend_ilang_yyerror("dangling attribute"); case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3)); delete $2; delete $3; -- cgit v1.2.3