systemverilog-plugin: use attributes instead of custom node type

Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc
index 1de8a5a..7915c5e 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -37,8 +37,7 @@
 enum AstNodeTypeExtended {
     AST_DOT = ::Yosys::AST::AST_BIND + 1, // here we always want to point to the last element of yosys' AstNodeType
     AST_BREAK,
-    AST_CONTINUE,
-    AST_LOW_HIGH_BOUND
+    AST_CONTINUE
 };
 }
 } // namespace AST
@@ -74,6 +73,12 @@
     return id;
 }
 
+/*static*/ const IdString &UhdmAst::low_high_bound()
+{
+    static const IdString id("\\low_high_bound");
+    return id;
+}
+
 static void sanitize_symbol_name(std::string &name)
 {
     if (!name.empty()) {
@@ -960,34 +965,6 @@
     for (size_t i = 0; i < current_node->children.size(); i++) {
         simplify(current_node->children[i], current_node);
     }
-    if (current_node->type == static_cast<AST::AstNodeType>(AST::Extended::AST_LOW_HIGH_BOUND)) {
-        log_assert(current_node->children.size() == 2);
-        while (current_node->children[0]->simplify(true, false, false, 1, -1, false, false)) {
-        };
-        while (current_node->children[1]->simplify(true, false, false, 1, -1, false, false)) {
-        };
-        log_assert(current_node->children[0]->type == AST::AST_CONSTANT);
-        log_assert(current_node->children[1]->type == AST::AST_CONSTANT);
-        const int low = current_node->children[0]->integer;
-        const int high = current_node->children[1]->integer;
-        int range = current_node->children[0]->range_left;
-        while (!current_node->children.empty()) {
-            delete current_node->children.back();
-            current_node->children.pop_back();
-        }
-        // According to standard:
-        // If the bound to the left of the colon is greater than the
-        // bound to the right, the range is empty and contains no values.
-        for (int i = low; i >= low && i <= high; i++) {
-            // TODO(krak): what should be correct constant range if we don't have
-            // information about range?
-            if (range == -1) {
-                range = 64;
-            }
-            parent_node->children.push_back(AST::AstNode::mkconst_int(i, false, range));
-        }
-        return;
-    }
     switch (current_node->type) {
     case AST::AST_TYPEDEF:
     case AST::AST_ENUM:
@@ -1060,9 +1037,40 @@
     case AST::AST_COND:
     case AST::AST_CONDX:
     case AST::AST_CONDZ:
-        if (!current_node->children.empty() && current_node->children[0]->type == static_cast<AST::AstNodeType>(AST::Extended::AST_LOW_HIGH_BOUND)) {
-            delete current_node->children[0];
-            current_node->children.erase(current_node->children.begin());
+        // handle custom low high bound
+        if (current_node->attributes.count(UhdmAst::low_high_bound())) {
+            log_assert(!current_node->children.empty());
+            log_assert(current_node->children[0]->type == AST::AST_BLOCK);
+            log_assert(current_node->children[0]->children.size() == 2);
+            auto low_high_bound = current_node->children[0];
+            // this is executed when condition is met
+            // save pointer that will be added later again
+            // as conditions needs to go before this block
+            auto result = current_node->children[1];
+            current_node->children.clear();
+            while (low_high_bound->children[0]->simplify(true, false, false, 1, -1, false, false)) {
+            };
+            while (low_high_bound->children[1]->simplify(true, false, false, 1, -1, false, false)) {
+            };
+            log_assert(low_high_bound->children[0]->type == AST::AST_CONSTANT);
+            log_assert(low_high_bound->children[1]->type == AST::AST_CONSTANT);
+            const int low = low_high_bound->children[0]->integer;
+            const int high = low_high_bound->children[1]->integer;
+            int range = low_high_bound->children[0]->range_left;
+            delete low_high_bound;
+            // According to standard:
+            // If the bound to the left of the colon is greater than the
+            // bound to the right, the range is empty and contains no values.
+            for (int i = low; i >= low && i <= high; i++) {
+                // TODO(krak): what should be correct constant range if we don't have
+                // information about range?
+                if (range == -1) {
+                    range = 64;
+                }
+                current_node->children.push_back(AST::AstNode::mkconst_int(i, false, range));
+            }
+            current_node->children.push_back(result);
+            current_node->attributes.erase(UhdmAst::low_high_bound());
         }
         break;
     default:
@@ -3525,7 +3533,6 @@
         // case ... inside statement, the operation is stored in UHDM inside case items
         // Retrieve just the InsideOp arguments here, we don't add any special handling
         if (vpi_get(vpiType, expr_h) == vpiOperation && vpi_get(vpiOpType, expr_h) == vpiInsideOp) {
-            std::vector<AST::AstNode *> nodes;
             visit_one_to_many({vpiOperand}, expr_h, [&](AST::AstNode *node) {
                 // Currently we are adding nodes directly to ancestor
                 // inside process_list_op, so after this function, we have
@@ -3537,11 +3544,14 @@
             // vpiListOp is returned in 2 cases:
             // a, b, c ... -> multiple vpiListOp with single item
             // [a : b] -> single vpiListOp with 2 items
+            // single item is handled by default,
+            // here handle 2 items with custom low_high_bound attribute
             if (current_node->children.size() == 2) {
-                auto bound = new AST::AstNode(static_cast<AST::AstNodeType>(AST::Extended::AST_LOW_HIGH_BOUND));
-                bound->children = current_node->children;
-                current_node->children.erase(current_node->children.begin(), current_node->children.end());
-                current_node->children.push_back(bound);
+                auto block = make_ast_node(AST::AST_BLOCK);
+                block->children = current_node->children;
+                current_node->children.clear();
+                current_node->children.push_back(block);
+                current_node->attributes[UhdmAst::low_high_bound()] = AST::AstNode::mkconst_int(1, false, 1);
             }
         } else {
             UhdmAst uhdm_ast(this, shared, indent + "  ");
diff --git a/systemverilog-plugin/UhdmAst.h b/systemverilog-plugin/UhdmAst.h
index bbd0460..81679e3 100644
--- a/systemverilog-plugin/UhdmAst.h
+++ b/systemverilog-plugin/UhdmAst.h
@@ -175,6 +175,7 @@
     static const ::Yosys::IdString &force_convert();
     static const ::Yosys::IdString &is_imported();
     static const ::Yosys::IdString &is_simplified_wire();
+    static const ::Yosys::IdString &low_high_bound();
 };
 
 } // namespace systemverilog_plugin