systemverilog-plugin: handle identifiers as list op arguments Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc index 4b5ced1..1de8a5a 100644 --- a/systemverilog-plugin/UhdmAst.cc +++ b/systemverilog-plugin/UhdmAst.cc
@@ -37,7 +37,8 @@ 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_CONTINUE, + AST_LOW_HIGH_BOUND }; } } // namespace AST @@ -959,6 +960,34 @@ 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: @@ -1028,6 +1057,14 @@ if (current_node->str == "$display" || current_node->str == "$write") simplify_format_string(current_node); break; + 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()); + } + break; default: break; } @@ -3501,25 +3538,10 @@ // a, b, c ... -> multiple vpiListOp with single item // [a : b] -> single vpiListOp with 2 items if (current_node->children.size() == 2) { - // TODO(krak): we should actually simplify this nodes first, - // but that would require to delay this to later. - // For now check that they are constants. - 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; - // TODO(krak): get proper width of constant - log_assert(current_node->children[0]->range_left == 31); - // 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. - while (!current_node->children.empty()) { - delete current_node->children.back(); - current_node->children.pop_back(); - } - for (int i = low; i >= low && i <= high; i++) { - current_node->children.push_back(AST::AstNode::mkconst_int(i, false, 32)); - } + 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); } } else { UhdmAst uhdm_ast(this, shared, indent + " ");