add attributes for enumerated values in ilang
authorJeff Wang <jjj11x@gmail.com>
Mon, 3 Feb 2020 06:12:24 +0000 (01:12 -0500)
committerJeff Wang <jeff.wang@utexas.edu>
Mon, 17 Feb 2020 09:42:42 +0000 (04:42 -0500)
- information also useful for strongly-typed enums (not implemented)
- resolves enum values in ilang part of #1594
- still need to output enums to VCD (or better yet FST) files

frontends/ast/ast.cc
frontends/ast/simplify.cc
frontends/verilog/verilog_parser.y
tests/svtypes/enum_simple.sv
tests/svtypes/typedef_scopes.sv

index 135750837bb95ece188ecc3eb779e97d59bc11f1..2398138100beb60d16ad1ddc27d33c80f86da0ef 100644 (file)
@@ -1222,6 +1222,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
                }
                else {
                        // must be global definition
+                       (*it)->simplify(false, false, false, 1, -1, false, false); //process enum/other declarations
                        design->verilog_globals.push_back((*it)->clone());
                }
        }
index 95c50cda01af4b74079d575fc363c0efbf4d811d..b9fb37d5003378add7a78f03874aabe50faea92d 100644 (file)
@@ -413,6 +413,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                current_scope[node->str] = node;
                        }
                        if (node->type == AST_ENUM) {
+                               current_scope[node->str] = node;
                                for (auto enode : node->children) {
                                        log_assert(enode->type==AST_ENUM_ITEM);
                                        if (current_scope.count(enode->str) == 0) {
@@ -862,6 +863,63 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        range_swapped = templ->range_swapped;
                        range_left = templ->range_left;
                        range_right = templ->range_right;
+                       attributes["\\wiretype"] = mkconst_str(resolved_type->str);
+                       //check if enum
+                       if (templ->attributes.count("\\enum_type")){
+                               //get reference to enum node:
+                               std::string enum_type = templ->attributes["\\enum_type"]->str.c_str();
+                               //                              log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
+                               //                              log("current scope:\n");
+                               //                              for (auto &it : current_scope)
+                               //                                      log("  %s\n", it.first.c_str());
+                               log_assert(current_scope.count(enum_type) == 1);
+                               AstNode *enum_node = current_scope.at(enum_type);
+                               log_assert(enum_node->type == AST_ENUM);
+                               //get width from 1st enum item:
+                               log_assert(enum_node->children.size() >= 1);
+                               AstNode *enum_item0 = enum_node->children[0];
+                               log_assert(enum_item0->type == AST_ENUM_ITEM);
+                               int width;
+                               if (!enum_item0->range_valid)
+                                       width = 1;
+                               else if (enum_item0->range_swapped)
+                                       width = enum_item0->range_right - enum_item0->range_left + 1;
+                               else
+                                       width = enum_item0->range_left - enum_item0->range_right + 1;
+                               log_assert(width > 0);
+                               //add declared enum items:
+                               for (auto enum_item : enum_node->children){
+                                       log_assert(enum_item->type == AST_ENUM_ITEM);
+                                       //get is_signed
+                                       bool is_signed;
+                                       if (enum_item->children.size() == 1){
+                                               is_signed = false;
+                                       } else if (enum_item->children.size() == 2){
+                                               log_assert(enum_item->children[1]->type == AST_RANGE);
+                                               is_signed = enum_item->children[1]->is_signed;
+                                       } else {
+                                               log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
+                                                                 enum_item->children.size(),
+                                                                 enum_item->str.c_str(), enum_node->str.c_str()
+                                               );
+                                       }
+                                       //start building attribute string
+                                       std::string enum_item_str = "\\enum_";
+                                       enum_item_str.append(std::to_string(width));
+                                       enum_item_str.append("_");
+                                       //get enum item value
+                                       if(enum_item->children[0]->type != AST_CONSTANT){
+                                               log_error("expected const, got %s for %s (%s)\n",
+                                                                 type2str(enum_item->children[0]->type).c_str(),
+                                                                 enum_item->str.c_str(), enum_node->str.c_str()
+                                                               );
+                                       }
+                                       int val = enum_item->children[0]->asInt(is_signed);
+                                       enum_item_str.append(std::to_string(val));
+                                       //set attribute for available val to enum item name mappings
+                                       attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str);
+                               }
+                       }
 
                        // Insert clones children from template at beginning
                        for (int i  = 0; i < GetSize(templ->children); i++)
@@ -908,6 +966,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        range_swapped = templ->range_swapped;
                        range_left = templ->range_left;
                        range_right = templ->range_right;
+                       attributes["\\wiretype"] = mkconst_str(resolved_type->str);
                        for (auto template_child : templ->children)
                                children.push_back(template_child->clone());
                        did_something = true;
@@ -1104,10 +1163,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                        }
                                        break;
                                case AST_ENUM:
+                                       current_scope[node->str] = node;
                                        for (auto enum_node : node->children) {
                                                log_assert(enum_node->type==AST_ENUM_ITEM);
                                                if (str == enum_node->str) {
-                                                       log("\nadding enum %s to scope\n", str.c_str());
+                                                       //log("\nadding enum item %s to scope\n", str.c_str());
                                                        current_scope[str] = enum_node;
                                                }
                                        }
@@ -2577,6 +2637,10 @@ skip_dynamic_range_lvalue_expansion:;
                                        wire->is_output = false;
                                        wire->is_reg = true;
                                        wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+                                       if (child->type == AST_ENUM_ITEM){
+                                               wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"];
+
+                                       }
                                        wire_cache[child->str] = wire;
 
                                        current_ast_mod->children.push_back(wire);
@@ -3109,6 +3173,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
                        current_scope[new_name] = child;
                }
                if (child->type == AST_ENUM){
+                       current_scope[child->str] = child;
                        for (auto enode : child->children){
                                log_assert(enode->type == AST_ENUM_ITEM);
                                if (backup_name_map.size() == 0)
@@ -3872,6 +3937,7 @@ void AstNode::allocateDefaultEnumValues()
        int last_enum_int = -1;
        for (auto node : children) {
                log_assert(node->type==AST_ENUM_ITEM);
+               node->attributes["\\enum_base_type"] = mkconst_str(str);
                for (size_t i = 0; i < node->children.size(); i++) {
                        switch (node->children[i]->type) {
                        case AST_NONE:
index ea0a09599cc154813904992b4e61bc78e39cf939..f25a8de28e084401b6c7383b75cab054c2ee23f6 100644 (file)
@@ -1243,9 +1243,12 @@ single_defparam_decl:
        };
 
 enum_type: TOK_ENUM {
+               static int enum_count;
                // create parent node for the enum
                astbuf2 = new AstNode(AST_ENUM);
                ast_stack.back()->children.push_back(astbuf2);
+               astbuf2->str = std::string("$enum");
+               astbuf2->str += std::to_string(enum_count++);
                // create the template for the names
                astbuf1 = new AstNode(AST_ENUM_ITEM);
                astbuf1->children.push_back(AstNode::mkconst_int(0, true));
@@ -1254,6 +1257,7 @@ enum_type: TOK_ENUM {
                                                                delete astbuf1;
                                                                astbuf1 = tnode;
                                                                tnode->type = AST_WIRE;
+                                                               tnode->attributes["\\enum_type"] = AstNode::mkconst_str(astbuf2->str);
                                                                // drop constant but keep any range
                                                                delete tnode->children[0];
                                                                tnode->children.erase(tnode->children.begin()); }
@@ -1311,7 +1315,10 @@ enum_var: TOK_ID {
        }
        ;
 
-enum_decl: enum_type enum_var_list ';'                 { delete astbuf1; }
+enum_decl: enum_type enum_var_list ';'                 {
+               //enum_type creates astbuf1 for use by typedef only
+               delete astbuf1;
+       }
        ;
 
 wire_decl:
index 0c3f55c34a299e55388a3399287a9014e2dac45e..ccaf50da03226b207a8a1441194e2e68e8c8a46f 100644 (file)
@@ -6,7 +6,7 @@ module enum_simple(input clk, input rst);
                ts0, ts1, ts2, ts3
        } states_t;
        (states_t) state;
-       (states_t) enum_const = s1;
+       (states_t) enum_const = ts1;
 
        always @(posedge clk) begin
                if (rst) begin
@@ -41,7 +41,7 @@ module enum_simple(input clk, input rst);
                assert(state != 2'h3);
                assert(s0 == '0);
                assert(ts0 == '0);
-               assert(enum_const == s1);
+               assert(enum_const == ts1);
        end
 
 endmodule
index 9b3331c60e2146c06b8ce866b4c4f687306b6f1e..1c45c7057b2484d39b2c29f713c26ed0efd16561 100644 (file)
@@ -27,7 +27,7 @@ module top;
        end
 
        (inner_type) inner_i2 = 8'h42;
-       (inner_type) inner_enum2 = s4;
+       (inner_enum_t) inner_enum2 = s4;
        always @(*) assert(inner_i2 == 4'h2);
        always @(*) assert(inner_enum2 == 3'h4);