Allow attributes on individual switch cases in RTLIL.
authorwhitequark <whitequark@whitequark.org>
Mon, 8 Jul 2019 11:34:58 +0000 (11:34 +0000)
committerwhitequark <whitequark@whitequark.org>
Mon, 8 Jul 2019 11:34:58 +0000 (11:34 +0000)
The parser changes are slightly awkward. Consider the following IL:

    process $0
      <point 1>
      switch \foo
        <point 2>
        case 1'1
          assign \bar \baz
          <point 3>
          ...
        case
      end
    end

Before this commit, attributes are valid in <point 1>, and <point 3>
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, <point 3> 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 <point 1> and <point 3> a part of case body,
and in <point 2> 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.

backends/ilang/ilang_backend.cc
frontends/ilang/ilang_parser.y
kernel/rtlil.h

index b4ba2b03f2d403ea6ca9b80d6de9b0ca19934ae0..313af7d5c60b1732169bd34bbb0b5d260dd19793 100644 (file)
@@ -204,6 +204,11 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const
 
        for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it)
        {
+               for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) {
+                       f << stringf("%s  attribute %s ", indent.c_str(), ait->first.c_str());
+                       dump_const(f, ait->second);
+                       f << stringf("\n");
+               }
                f << stringf("%s  case ", indent.c_str());
                for (size_t i = 0; i < (*it)->compare.size(); i++) {
                        if (i > 0)
index 44c99906a0a5188fbfca2f069f42879bdc301f7b..b4b9693dafb030db3c1839139332de2b049360bc 100644 (file)
@@ -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;
index f4fcf5dcfb6e2c4fe8928f98c5b93fceb293818a..82cbfaf28ab6408a0a957add83cd8e1f07722e55 100644 (file)
@@ -1327,7 +1327,7 @@ public:
 #endif
 };
 
-struct RTLIL::CaseRule
+struct RTLIL::CaseRule : public RTLIL::AttrObject
 {
        std::vector<RTLIL::SigSpec> compare;
        std::vector<RTLIL::SigSig> actions;