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