#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <limits>
#include <regex>
#include <string>
#include <utility>
#include <vector>

#include "UhdmAst.h"
#include "frontends/ast/ast.h"
#include "libs/sha1/sha1.h"

#include "utils/memory.h"

// UHDM
#include <uhdm/ExprEval.h>
#include <uhdm/uhdm.h>
#include <uhdm/vpi_user.h>

#include "third_party/yosys/const2ast.h"
#include "third_party/yosys/simplify.h"

YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND
{
extern bool sv_mode;
}
YOSYS_NAMESPACE_END

namespace systemverilog_plugin
{

using namespace ::Yosys;

namespace AST
{
using namespace ::Yosys::AST;

namespace Extended
{
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
};
}
} // namespace AST

namespace attr_id
{
static bool already_initialized = false;
static IdString partial;
static IdString packed_ranges;
static IdString unpacked_ranges;
static IdString force_convert;
static IdString is_imported;
static IdString is_simplified_wire;
static IdString low_high_bound;
static IdString is_type_parameter;
static IdString is_elaborated_module;
}; // namespace attr_id

// TODO(mglb): use attr_id::* directly everywhere and remove those methods.
/*static*/ const IdString &UhdmAst::partial() { return attr_id::partial; }
/*static*/ const IdString &UhdmAst::packed_ranges() { return attr_id::packed_ranges; }
/*static*/ const IdString &UhdmAst::unpacked_ranges() { return attr_id::unpacked_ranges; }
/*static*/ const IdString &UhdmAst::force_convert() { return attr_id::force_convert; }
/*static*/ const IdString &UhdmAst::is_imported() { return attr_id::is_imported; }
/*static*/ const IdString &UhdmAst::is_simplified_wire() { return attr_id::is_simplified_wire; }
/*static*/ const IdString &UhdmAst::low_high_bound() { return attr_id::low_high_bound; }
/*static*/ const IdString &UhdmAst::is_elaborated_module() { return attr_id::is_elaborated_module; }

#define MAKE_INTERNAL_ID(X) IdString("$systemverilog_plugin$" #X)

void attr_id_init()
{
    // Initialize only once
    if (attr_id::already_initialized)
        return;
    attr_id::already_initialized = true;

    // Actual initialization

    // Register IdStrings. Can't be done statically, as the IdString class uses resources created during Yosys initialization which happens after
    // static initialization of the plugin when everything is statically linked.
    attr_id::partial = MAKE_INTERNAL_ID(partial);
    attr_id::packed_ranges = MAKE_INTERNAL_ID(packed_ranges);
    attr_id::unpacked_ranges = MAKE_INTERNAL_ID(unpacked_ranges);
    attr_id::force_convert = MAKE_INTERNAL_ID(force_convert);
    attr_id::is_imported = MAKE_INTERNAL_ID(is_imported);
    attr_id::is_simplified_wire = MAKE_INTERNAL_ID(is_simplified_wire);
    attr_id::low_high_bound = MAKE_INTERNAL_ID(low_high_bound);
    attr_id::is_type_parameter = MAKE_INTERNAL_ID(is_type_parameter);
    attr_id::is_elaborated_module = MAKE_INTERNAL_ID(is_elaborated_module);
}

void attr_id_cleanup()
{
    // Release static copies of private IdStrings.
    attr_id::low_high_bound = IdString();
    attr_id::is_simplified_wire = IdString();
    attr_id::is_imported = IdString();
    attr_id::force_convert = IdString();
    attr_id::unpacked_ranges = IdString();
    attr_id::packed_ranges = IdString();
    attr_id::partial = IdString();
    attr_id::is_type_parameter = IdString();
    attr_id::is_elaborated_module = IdString();
    attr_id::already_initialized = false;
}

static AST::AstNode *get_attribute(AST::AstNode *node, const IdString &attribute)
{
    log_assert(node);
    if (!node->attributes.count(attribute))
        return nullptr;

    return node->attributes[attribute];
}

// Consumes attr_node.
static void set_attribute(AST::AstNode *node, const IdString &attribute, AST::AstNode *attr_node)
{
    log_assert(node);
    log_assert(attr_node);
    delete node->attributes[attribute];
    node->attributes[attribute] = attr_node;
}

// Delete the selected attribute if it exists.
// Does nothing if the node doesn't exist, or the attribute doesn't exists.
static void delete_attribute(AST::AstNode *node, const IdString &attribute)
{
    if (!node)
        return;

    if (node->attributes.count(attribute)) {
        delete node->attributes[attribute];
        node->attributes.erase(attribute);
    }
}

// Delete all attributes that belong to the SV plugin.
// The attributes beloning to Yosys are *not* deleted here.
static void delete_internal_attributes(AST::AstNode *node)
{
    if (!node)
        return;

    for (auto &attr : {UhdmAst::partial(), UhdmAst::packed_ranges(), UhdmAst::unpacked_ranges(), UhdmAst::force_convert(), UhdmAst::is_imported(),
                       UhdmAst::is_simplified_wire(), UhdmAst::low_high_bound(), attr_id::is_type_parameter, attr_id::is_elaborated_module}) {
        delete_attribute(node, attr);
    }
}

// Delete all children nodes.
// Does *not* delete attributes.
// This function exists as Yosys's function node->delete_children() does remove all children and attributes.
static void delete_children(AST::AstNode *node)
{
    if (!node)
        return;

    for (auto *child : node->children) {
        delete child;
    }
    node->children.clear();
}

static void simplify_sv(AST::AstNode *current_node, AST::AstNode *parent_node);

static void sanitize_symbol_name(std::string &name)
{
    if (!name.empty()) {
        auto pos = name.find_last_of('@');
        name = name.substr(pos + 1);
        // symbol names must begin with '\'
        name.insert(0, "\\");
    }
}

static std::string get_parent_name(vpiHandle parent_h)
{
    std::string parent_name;
    if (auto p = vpi_get_str(vpiFullName, parent_h)) {
        parent_name = p;
    } else if (auto p = vpi_get_str(vpiName, parent_h)) {
        parent_name = p;
    } else if (auto p = vpi_get_str(vpiDefName, parent_h)) {
        parent_name = p;
    }
    return parent_name;
}

// Warning: Takes ownership of `parent_h` and releases it.
static void find_ancestor_name(vpiHandle parent_h, std::string &name, std::string &parent_name)
{

    while (!parent_name.empty()) {
        parent_name = parent_name + ".";
        if ((name.rfind(parent_name) != std::string::npos)) {
            name = name.substr(name.rfind(parent_name) + parent_name.size());
            break;
        } else {
            auto old_parent_h = parent_h;
            parent_h = vpi_handle(vpiParent, parent_h);
            vpi_release_handle(old_parent_h);

            if (parent_h) {
                parent_name = get_parent_name(parent_h);
            } else {
                parent_name.clear();
            }
        }
    }
    vpi_release_handle(parent_h);
}

static std::string get_name(vpiHandle obj_h, bool prefer_full_name = false)
{
    auto first_check = prefer_full_name ? vpiFullName : vpiName;
    auto last_check = prefer_full_name ? vpiName : vpiFullName;
    std::string name;
    if (auto s = vpi_get_str(first_check, obj_h)) {
        name = s;
    } else if (auto s = vpi_get_str(vpiDefName, obj_h)) {
        name = s;
    } else if (auto s = vpi_get_str(last_check, obj_h)) {
        name = s;
    }
    // We are looking for the ancestor name to use it as a delimeter
    // when stripping the name of the current node.
    // We used to strip the name by searching for "." in it, but this
    // approach didn't work for the names whith "." as an escaped
    // character.
    vpiHandle parent_h = vpi_handle(vpiParent, obj_h);

    if (parent_h) {
        std::string parent_name;
        parent_name = get_parent_name(parent_h);

        if (parent_name.empty()) {
            // Nodes of certain types, like param_assign, don't have
            // a name, so we need to look further for the ancestor.
            auto old_parent_h = parent_h;
            parent_h = vpi_handle(vpiParent, parent_h);
            vpi_release_handle(old_parent_h);

            if (parent_h) {
                parent_name = get_parent_name(parent_h);
            }
        }
        find_ancestor_name(parent_h, name, parent_name);
    }
    sanitize_symbol_name(name);
    return name;
}

static std::string strip_package_name(std::string name)
{
    auto sep_index = name.find("::");
    if (sep_index != string::npos) {
        name = name.substr(sep_index + 1);
        name[0] = '\\';
    }
    return name;
}

static std::string get_object_name(vpiHandle obj_h, const std::vector<int> &name_fields = {vpiName})
{
    std::string objectName;
    for (auto name : name_fields) {
        if (auto s = vpi_get_str(name, obj_h)) {
            objectName = s;
            sanitize_symbol_name(objectName);
            break;
        }
    }
    return objectName;
}

static AST::AstNode *mkconst_real(double d)
{
    AST::AstNode *node = new AST::AstNode(AST::AST_REALVALUE);
    node->realvalue = d;
    return node;
}

static AST::AstNode *make_range(int left, int right, bool is_signed = false)
{
    // generate a pre-validated range node for a fixed signal range.
    auto range = new AST::AstNode(AST::AST_RANGE);
    range->range_left = left;
    range->range_right = right;
    range->range_valid = true;
    range->children.push_back(AST::AstNode::mkconst_int(left, true));
    range->children.push_back(AST::AstNode::mkconst_int(right, true));
    range->is_signed = is_signed;
    return range;
}

static void copy_packed_unpacked_attribute(AST::AstNode *from, AST::AstNode *to)
{
    if (!to->attributes.count(UhdmAst::packed_ranges()))
        to->attributes[UhdmAst::packed_ranges()] = AST::AstNode::mkconst_int(1, false, 1);
    if (!to->attributes.count(UhdmAst::unpacked_ranges()))
        to->attributes[UhdmAst::unpacked_ranges()] = AST::AstNode::mkconst_int(1, false, 1);
    if (from->attributes.count(UhdmAst::packed_ranges())) {
        for (auto r : from->attributes[UhdmAst::packed_ranges()]->children) {
            to->attributes[UhdmAst::packed_ranges()]->children.push_back(r->clone());
        }
    }
    if (from->attributes.count(UhdmAst::unpacked_ranges())) {
        for (auto r : from->attributes[UhdmAst::unpacked_ranges()]->children) {
            to->attributes[UhdmAst::unpacked_ranges()]->children.push_back(r->clone());
        }
    }
}

static int get_max_offset_struct(AST::AstNode *node)
{
    // get the width from the MS member in the struct
    // as members are laid out from left to right in the packed wire
    log_assert(node->type == AST::AST_STRUCT || node->type == AST::AST_UNION);
    while (node->range_left < 0) {
        node = node->children[0];
    }
    return node->range_left;
}

static void visitEachDescendant(AST::AstNode *node, const std::function<void(AST::AstNode *)> &f)
{
    for (auto child : node->children) {
        f(child);
        visitEachDescendant(child, f);
    }
}

static void add_multirange_wire(AST::AstNode *node, std::vector<AST::AstNode *> packed_ranges, std::vector<AST::AstNode *> unpacked_ranges,
                                bool reverse = true)
{
    delete_attribute(node, UhdmAst::packed_ranges());
    node->attributes[UhdmAst::packed_ranges()] = AST::AstNode::mkconst_int(1, false, 1);
    if (!packed_ranges.empty()) {
        if (reverse)
            std::reverse(packed_ranges.begin(), packed_ranges.end());
        node->attributes[UhdmAst::packed_ranges()]->children = std::move(packed_ranges);
    }

    delete_attribute(node, UhdmAst::unpacked_ranges());
    node->attributes[UhdmAst::unpacked_ranges()] = AST::AstNode::mkconst_int(1, false, 1);
    if (!unpacked_ranges.empty()) {
        if (reverse)
            std::reverse(unpacked_ranges.begin(), unpacked_ranges.end());
        node->attributes[UhdmAst::unpacked_ranges()]->children = std::move(unpacked_ranges);
    }
}

static size_t add_multirange_attribute(AST::AstNode *wire_node, const std::vector<AST::AstNode *> ranges)
{
    // node->multirange_dimensions stores dimensions' offsets and widths.
    // It shall have even number of elements.
    // For a range of [A:B] it should be appended with {min(A,B)} and {max(A,B)-min(A,B)+1}
    // For a range of [A] it should be appended with {0} and {A}

    size_t size = 1;
    for (size_t i = 0; i < ranges.size(); i++) {
        log_assert(AST_INTERNAL::current_ast_mod);
        if (ranges[i]->children.size() == 1) {
            ranges[i]->children.push_back(ranges[i]->children[0]->clone());
        }
        simplify_sv(ranges[i], wire_node);
        while (simplify(ranges[i], true, false, false, 1, -1, false, false)) {
        }
        // this workaround case, where yosys doesn't follow id2ast and simplifies it to resolve constant
        if (ranges[i]->children[0]->id2ast) {
            simplify_sv(ranges[i]->children[0]->id2ast, ranges[i]->children[0]);
            while (simplify(ranges[i]->children[0]->id2ast, true, false, false, 1, -1, false, false)) {
            }
        }
        if (ranges[i]->children[1]->id2ast) {
            simplify_sv(ranges[i]->children[1]->id2ast, ranges[i]->children[1]);
            while (simplify(ranges[i]->children[1]->id2ast, true, false, false, 1, -1, false, false)) {
            }
        }
        simplify_sv(ranges[i], wire_node);
        while (simplify(ranges[i], true, false, false, 1, -1, false, false)) {
        }
        log_assert(ranges[i]->children[0]->type == AST::AST_CONSTANT);
        log_assert(ranges[i]->children[1]->type == AST::AST_CONSTANT);

        const auto low = min(ranges[i]->children[0]->integer, ranges[i]->children[1]->integer);
        const auto high = max(ranges[i]->children[0]->integer, ranges[i]->children[1]->integer);
        const auto elem_size = high - low + 1;

        wire_node->multirange_dimensions.push_back(low);
        wire_node->multirange_dimensions.push_back(elem_size);
        wire_node->multirange_swapped.push_back(ranges[i]->range_swapped);
        size *= elem_size;
    }
    log_assert(wire_node->multirange_dimensions.size() % 2 == 0);

    return size;
}

static AST::AstNode *convert_range(AST::AstNode *id, int packed_ranges_size, int unpacked_ranges_size, int i)
{
    log_assert(AST_INTERNAL::current_ast_mod);
    log_assert(AST_INTERNAL::current_scope.count(id->str));
    AST::AstNode *wire_node = AST_INTERNAL::current_scope[id->str];
    log_assert(!wire_node->multirange_dimensions.empty());
    int elem_size = 1;
    std::vector<int> single_elem_size;
    single_elem_size.push_back(elem_size);
    for (size_t j = 0; (j + 1) < wire_node->multirange_dimensions.size(); j = j + 2) {
        // The ranges' widths are placed on odd indices of multirange_dimensions.
        elem_size *= wire_node->multirange_dimensions[j + 1];
        single_elem_size.push_back(elem_size);
    }
    std::reverse(single_elem_size.begin(), single_elem_size.end());
    log_assert(i < (unpacked_ranges_size + packed_ranges_size));
    log_assert(!id->children.empty());
    AST::AstNode *result = nullptr;
    // we want to start converting from the end
    if (i < static_cast<int>(id->children.size()) - 1) {
        result = convert_range(id, packed_ranges_size, unpacked_ranges_size, i + 1);
    }
    // special case, we want to select whole wire
    if (id->children.size() == 0 && i == 0) {
        result = make_range(single_elem_size[i] - 1, 0);
    } else {
        AST::AstNode *range_left = nullptr;
        AST::AstNode *range_right = nullptr;
        if (id->children[i]->children.size() == 2) {
            range_left = id->children[i]->children[0]->clone();
            range_right = id->children[i]->children[1]->clone();
        } else {
            range_left = id->children[i]->children[0]->clone();
            range_right = id->children[i]->children[0]->clone();
        }
        if (!wire_node->multirange_swapped.empty()) {
            bool is_swapped = wire_node->multirange_swapped[wire_node->multirange_swapped.size() - i - 1];
            auto right_idx = wire_node->multirange_dimensions.size() - (i * 2) - 2;
            if (is_swapped) {
                auto left_idx = wire_node->multirange_dimensions.size() - (i * 2) - 1;
                auto elem_size = wire_node->multirange_dimensions[left_idx] - wire_node->multirange_dimensions[right_idx];
                range_left = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_left);
                range_right = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_right);
            } else if (wire_node->multirange_dimensions[right_idx] != 0) {
                range_left =
                  new AST::AstNode(AST::AST_SUB, range_left, AST::AstNode::mkconst_int(wire_node->multirange_dimensions[right_idx], false));
                range_right =
                  new AST::AstNode(AST::AST_SUB, range_right, AST::AstNode::mkconst_int(wire_node->multirange_dimensions[right_idx], false));
            }
        }
        if (!result) {
            range_left =
              new AST::AstNode(AST::AST_SUB,
                               new AST::AstNode(AST::AST_MUL, new AST::AstNode(AST::AST_ADD, range_left, AST::AstNode::mkconst_int(1, false)),
                                                AST::AstNode::mkconst_int(single_elem_size[i + 1], false)),
                               AST::AstNode::mkconst_int(1, false));
        }
        range_right = new AST::AstNode(AST::AST_MUL, range_right, AST::AstNode::mkconst_int(single_elem_size[i + 1], false));
        if (result) {
            range_right = new AST::AstNode(AST::AST_ADD, range_right, result->children[1]->clone());
            delete range_left;
            range_left = new AST::AstNode(AST::AST_SUB, new AST::AstNode(AST::AST_ADD, range_right->clone(), result->children[0]->clone()),
                                          result->children[1]->clone());
            delete result;
            result = nullptr;
        }
        result = new AST::AstNode(AST::AST_RANGE, range_left, range_right);
    }
    // return range from *current* selected range
    // in the end, it results in whole selected range
    id->basic_prep = true;
    return result;
}

static void resolve_wiretype(AST::AstNode *wire_node)
{
    AST::AstNode *wiretype_node = nullptr;
    if (!wire_node->children.empty()) {
        if (wire_node->children[0]->type == AST::AST_WIRETYPE) {
            wiretype_node = wire_node->children[0];
        }
    }
    if (wire_node->children.size() > 1) {
        if (wire_node->children[1]->type == AST::AST_WIRETYPE) {
            wiretype_node = wire_node->children[1];
        }
    }
    if (wiretype_node == nullptr)
        return;

    unique_resource<std::vector<AST::AstNode *>> packed_ranges = wire_node->attributes.count(attr_id::packed_ranges)
                                                                   ? std::move(wire_node->attributes[attr_id::packed_ranges]->children)
                                                                   : std::vector<AST::AstNode *>{};
    delete_attribute(wire_node, attr_id::packed_ranges);
    unique_resource<std::vector<AST::AstNode *>> unpacked_ranges = wire_node->attributes.count(attr_id::unpacked_ranges)
                                                                     ? std::move(wire_node->attributes[attr_id::unpacked_ranges]->children)
                                                                     : std::vector<AST::AstNode *>{};
    delete_attribute(wire_node, attr_id::unpacked_ranges);

    AST::AstNode *wiretype_ast = nullptr;
    log_assert(AST_INTERNAL::current_scope.count(wiretype_node->str));
    wiretype_ast = AST_INTERNAL::current_scope[wiretype_node->str];
    // we need to setup current top ast as this simplify
    // needs to have access to all already defined ids
    simplify_sv(wiretype_ast, nullptr);
    while (simplify(wire_node, true, false, false, 1, -1, false, false)) {
    }
    log_assert(!wiretype_ast->children.empty());
    if ((wiretype_ast->children[0]->type == AST::AST_STRUCT || wiretype_ast->children[0]->type == AST::AST_UNION) &&
        wire_node->type == AST::AST_WIRE) {
        auto struct_width = get_max_offset_struct(wiretype_ast->children[0]);
        wire_node->range_left = struct_width;
        wire_node->children[0]->range_left = struct_width;
        wire_node->children[0]->children[0]->integer = struct_width;
    }
    if (wiretype_ast) {
        log_assert(wire_node->attributes.count(ID::wiretype));
        log_assert(wiretype_ast->type == AST::AST_TYPEDEF);
        wire_node->attributes[ID::wiretype]->id2ast = wiretype_ast->children[0];
    }
    if (((wire_node->children.size() > 0 && wire_node->children[0]->type == AST::AST_RANGE) ||
         (wire_node->children.size() > 1 && wire_node->children[1]->type == AST::AST_RANGE)) &&
        wire_node->multirange_dimensions.empty()) {
        // We need to save order in which ranges appear in wiretype and add them before wire range
        // We need to copy this ranges, so create new vector for them
        std::vector<AST::AstNode *> packed_ranges_wiretype;
        std::vector<AST::AstNode *> unpacked_ranges_wiretype;
        if (wiretype_ast && !wiretype_ast->children.empty() && wiretype_ast->children[0]->attributes.count(UhdmAst::packed_ranges()) &&
            wiretype_ast->children[0]->attributes.count(UhdmAst::unpacked_ranges())) {
            for (auto r : wiretype_ast->children[0]->attributes[UhdmAst::packed_ranges()]->children) {
                packed_ranges_wiretype.push_back(r->clone());
            }
            for (auto r : wiretype_ast->children[0]->attributes[UhdmAst::unpacked_ranges()]->children) {
                unpacked_ranges_wiretype.push_back(r->clone());
            }
        } else {
            if (wire_node->children[0]->type == AST::AST_RANGE)
                packed_ranges_wiretype.push_back(wire_node->children[0]->clone());
            else if (wire_node->children[1]->type == AST::AST_RANGE)
                packed_ranges_wiretype.push_back(wire_node->children[1]->clone());
            else
                log_error("Unhandled case in resolve_wiretype!\n");
        }
        // add wiretype range before current wire ranges
        std::reverse(packed_ranges_wiretype.begin(), packed_ranges_wiretype.end());
        std::reverse(unpacked_ranges_wiretype.begin(), unpacked_ranges_wiretype.end());
        std::reverse(packed_ranges->begin(), packed_ranges->end());
        std::reverse(unpacked_ranges->begin(), unpacked_ranges->end());
        packed_ranges->insert(packed_ranges->begin(), packed_ranges_wiretype.begin(), packed_ranges_wiretype.end());
        unpacked_ranges->insert(unpacked_ranges->begin(), unpacked_ranges_wiretype.begin(), unpacked_ranges_wiretype.end());
        AST::AstNode *value = nullptr;
        if (wire_node->children[0]->type != AST::AST_RANGE) {
            value = wire_node->children[0]->clone();
        }
        delete_children(wire_node);
        if (value)
            wire_node->children.push_back(value);
        add_multirange_wire(wire_node, packed_ranges.release(), unpacked_ranges.release(), false /* reverse */);
    }
}

static void add_force_convert_attribute(AST::AstNode *wire_node, uint32_t val = 1)
{
    AST::AstNode *&attr = wire_node->attributes[UhdmAst::force_convert()];
    if (!attr) {
        attr = AST::AstNode::mkconst_int(val, true);
    } else if (attr->integer != val) {
        attr->integer = val;
    }
}

static void check_memories(AST::AstNode *node, std::string scope, std::map<std::string, AST::AstNode *> &memories)
{
    for (auto *child : node->children) {
        check_memories(child, node->type == AST::AST_GENBLOCK ? scope + "." + node->str : scope, memories);
    }

    if (node->str == "\\$readmemh") {
        if (node->children.size() != 2 || node->children[1]->str.empty() || node->children[1]->type != AST::AST_IDENTIFIER) {
            log_error("%s:%d: Wrong usage of '\\$readmemh'\n", node->filename.c_str(), node->location.first_line);
        }
        // TODO: Look for the memory in all other scope levels, like we do in case of AST::AST_IDENTIFIER,
        // as here the memory can also be defined before before the current scope.
        std::string name = scope + "." + node->children[1]->str;
        const auto iter = memories.find(name);
        if (iter != memories.end()) {
            add_force_convert_attribute(iter->second, 0);
        }
    }

    if (node->type == AST::AST_WIRE) {
        const std::size_t packed_ranges_count =
          node->attributes.count(UhdmAst::packed_ranges()) ? node->attributes[UhdmAst::packed_ranges()]->children.size() : 0;
        const std::size_t unpacked_ranges_count =
          node->attributes.count(UhdmAst::unpacked_ranges()) ? node->attributes[UhdmAst::unpacked_ranges()]->children.size() : 0;

        if (packed_ranges_count == 1 && unpacked_ranges_count == 1) {
            std::string name = scope + "." + node->str;
            auto [iter, did_insert] = memories.insert_or_assign(std::move(name), node);
            log_assert(did_insert);
        }
        return;
    }

    if (node->type == AST::AST_IDENTIFIER) {
        std::string full_id = scope;
        std::size_t scope_end_pos = scope.size();

        for (;;) {
            full_id += "." + node->str;
            const auto iter = memories.find(full_id);
            if (iter != memories.end()) {
                // Memory node found!
                if (!iter->second->attributes.count(UhdmAst::force_convert())) {
                    const bool is_full_memory_access = (node->children.size() == 0);
                    const bool is_slice_memory_access = (node->children.size() == 1 && node->children[0]->children.size() != 1);
                    // convert memory to list of registers
                    // in case of access to whole memory
                    // or slice of memory
                    // e.g.
                    // logic [3:0] mem [8:0];
                    // always_ff @ (posedge clk) begin
                    //   mem <= '{default:0};
                    //   mem[7:1] <= mem[6:0];
                    // end
                    // don't convert in case of accessing
                    // memory using address, e.g.
                    // mem[0] <= '{default:0}
                    if (is_full_memory_access || is_slice_memory_access) {
                        add_force_convert_attribute(iter->second);
                    }
                }
                break;
            } else {
                if (scope_end_pos == 0) {
                    // We reached the top scope and the memory node wasn't found.
                    break;
                } else {
                    // Memory node wasn't found.
                    // Erase node name and last segment of the scope to check the previous scope.
                    // FIXME: This doesn't work with escaped identifiers containing a dot.
                    scope_end_pos = full_id.find_last_of('.', scope_end_pos - 1);
                    if (scope_end_pos == std::string::npos) {
                        scope_end_pos = 0;
                    }
                    full_id.erase(scope_end_pos);
                }
            }
        }
    }
}

static void check_memories(AST::AstNode *node)
{
    std::map<std::string, AST::AstNode *> memories;
    check_memories(node, "", memories);
}

static void warn_start_range(const std::vector<AST::AstNode *> ranges)
{
    for (size_t i = 0; i < ranges.size(); i++) {
        auto start_elem = min(ranges[i]->children[0]->integer, ranges[i]->children[1]->integer);
        if (start_elem != 0) {
            log_file_warning(ranges[i]->filename, ranges[i]->location.first_line, "Limited support for multirange wires that don't start from 0\n");
        }
    }
}

// This function is workaround missing support for multirange (with n-ranges) packed/unpacked nodes
// It converts multirange node to single-range node and translates access to this node
// to correct range
static void convert_packed_unpacked_range(AST::AstNode *wire_node)
{
    resolve_wiretype(wire_node);
    const std::vector<AST::AstNode *> packed_ranges = wire_node->attributes.count(UhdmAst::packed_ranges())
                                                        ? wire_node->attributes[UhdmAst::packed_ranges()]->children
                                                        : std::vector<AST::AstNode *>();
    const std::vector<AST::AstNode *> unpacked_ranges = wire_node->attributes.count(UhdmAst::unpacked_ranges())
                                                          ? wire_node->attributes[UhdmAst::unpacked_ranges()]->children
                                                          : std::vector<AST::AstNode *>();
    if (packed_ranges.empty() && unpacked_ranges.empty()) {
        delete_attribute(wire_node, UhdmAst::packed_ranges());
        delete_attribute(wire_node, UhdmAst::unpacked_ranges());
        wire_node->range_left = 0;
        wire_node->range_right = 0;
        wire_node->range_valid = true;
        return;
    }
    std::vector<AST::AstNode *> ranges;

    // Convert only when node is not a memory and at least 1 of the ranges has more than 1 range
    const bool convert_node = [&]() {
        if (wire_node->type == AST::AST_MEMORY)
            return false;
        if (packed_ranges.size() > 1)
            return true;
        if (unpacked_ranges.size() > 1)
            return true;
        if (wire_node->attributes.count(ID::wiretype))
            return true;
        if (wire_node->type == AST::AST_PARAMETER)
            return true;
        if (wire_node->type == AST::AST_LOCALPARAM)
            return true;
        if ((wire_node->is_input || wire_node->is_output) && (packed_ranges.size() > 0 || unpacked_ranges.size() > 0))
            return true;
        if (wire_node->attributes.count(UhdmAst::force_convert()) && wire_node->attributes[UhdmAst::force_convert()]->integer == 1)
            return true;
        return false;
    }();
    if (convert_node) {
        // if not already converted
        if (wire_node->multirange_dimensions.empty()) {
            const size_t packed_size = add_multirange_attribute(wire_node, packed_ranges);
            const size_t unpacked_size = add_multirange_attribute(wire_node, unpacked_ranges);
            if (packed_ranges.size() == 1 && unpacked_ranges.empty()) {
                ranges.push_back(packed_ranges[0]->clone());
            } else if (unpacked_ranges.size() == 1 && packed_ranges.empty()) {
                ranges.push_back(unpacked_ranges[0]->clone());
            } else {
                // currently we have limited support
                // for multirange wires that doesn't start from 0
                warn_start_range(packed_ranges);
                warn_start_range(unpacked_ranges);
                const size_t size = packed_size * unpacked_size;
                log_assert(size >= 1);
                ranges.push_back(make_range(size - 1, 0));
            }
        }
    } else {
        for (auto r : packed_ranges) {
            ranges.push_back(r->clone());
        }
        for (auto r : unpacked_ranges) {
            ranges.push_back(r->clone());
        }
        // if there is only one packed and one unpacked range,
        // and wire is not port wire, change type to AST_MEMORY
        if (wire_node->type == AST::AST_WIRE && packed_ranges.size() == 1 && unpacked_ranges.size() == 1 && !wire_node->is_input &&
            !wire_node->is_output) {
            wire_node->type = AST::AST_MEMORY;
            wire_node->is_logic = true;
        }
    }

    // Insert new range
    wire_node->children.insert(wire_node->children.end(), ranges.begin(), ranges.end());
}

// Assert macro that prints location in C++ code and location of currently processed UHDM object.
// Use only inside UhdmAst methods.
#ifndef NDEBUG
#if __GNUC__
// gcc/clang's __builtin_trap() makes gdb stop on the line containing an assertion.
#define uhdmast_assert(expr)                                                                                                                         \
    if ((expr)) {                                                                                                                                    \
    } else {                                                                                                                                         \
        this->uhdmast_assert_log(#expr, __PRETTY_FUNCTION__, __FILE__, __LINE__);                                                                    \
        __builtin_trap();                                                                                                                            \
    }
#else // #if __GNUC__
// Just abort when using compiler other than gcc/clang.
#define uhdmast_assert(expr)                                                                                                                         \
    if ((expr)) {                                                                                                                                    \
    } else {                                                                                                                                         \
        this->uhdmast_assert_log(#expr, __func__, __FILE__, __LINE__);                                                                               \
        std::abort();                                                                                                                                \
    }
#endif // #if __GNUC__
#else  // #ifndef NDEBUG
#define uhdmast_assert(expr)                                                                                                                         \
    if ((expr)) {                                                                                                                                    \
    } else {                                                                                                                                         \
    }
#endif // #ifndef NDEBUG

void UhdmAst::uhdmast_assert_log(const char *expr_str, const char *func, const char *file, int line) const
{
    std::cerr << file << ':' << line << ": error: Assertion failed: " << expr_str << std::endl;
    std::cerr << file << ':' << line << ": note: In function: " << func << std::endl;
    if (obj_h != 0) {
        const char *const svfile = vpi_get_str(vpiFile, obj_h);
        int svline = vpi_get(vpiLineNo, obj_h);
        int svcolumn = vpi_get(vpiColumnNo, obj_h);
        std::string obj_type_name = UHDM::VpiTypeName(obj_h);
        const char *obj_name = vpi_get_str(vpiName, obj_h);
        std::cerr << svfile << ':' << svline << ':' << svcolumn << ": note: When processing object of type '" << obj_type_name << '\'';
        if (obj_name && obj_name[0] != '\0') {
            std::cerr << " named '" << obj_name << '\'';
        }
        std::cerr << '.' << std::endl;
    }
}

static AST::AstNode *expand_dot(const AST::AstNode *current_struct, const AST::AstNode *search_node)
{
    AST::AstNode *current_struct_elem = nullptr;
    auto search_str = search_node->str.find("\\") == 0 ? search_node->str.substr(1) : search_node->str;
    auto struct_elem_it =
      std::find_if(current_struct->children.begin(), current_struct->children.end(), [&](AST::AstNode *node) { return node->str == search_str; });
    if (struct_elem_it == current_struct->children.end()) {
        current_struct->dumpAst(NULL, "struct >");
        log_error("Couldn't find search elem: %s in struct\n", search_str.c_str());
    }
    current_struct_elem = *struct_elem_it;

    AST::AstNode *sub_dot = nullptr;
    std::vector<AST::AstNode *> struct_ranges;

    for (auto c : search_node->children) {
        if (c->type == static_cast<int>(AST::Extended::AST_DOT)) {
            // There should be only 1 AST_DOT node children
            log_assert(!sub_dot);
            sub_dot = expand_dot(current_struct_elem, c);
        }
        if (c->type == AST::AST_RANGE) {
            struct_ranges.push_back(c);
        }
    }
    AST::AstNode *left = nullptr, *right = nullptr;
    switch (current_struct_elem->type) {
    case AST::AST_STRUCT_ITEM:
        left = AST::AstNode::mkconst_int(current_struct_elem->range_left, true);
        right = AST::AstNode::mkconst_int(current_struct_elem->range_right, true);
        break;
    case AST::AST_STRUCT:
    case AST::AST_UNION:
        // TODO(krak): add proper support for accessing struct/union elements
        // with multirange
        // Currently support only special access to 2 dimensional packed element
        // when selecting single range
        log_assert(current_struct_elem->multirange_dimensions.size() % 2 == 0);
        if (!struct_ranges.empty() && (current_struct_elem->multirange_dimensions.size() / 2) == 2) {
            // get element size in number of bits
            const int single_elem_size = current_struct_elem->children.front()->range_left + 1;
            left = AST::AstNode::mkconst_int(single_elem_size * current_struct_elem->multirange_dimensions.back(), true);
            right =
              AST::AstNode::mkconst_int(current_struct_elem->children.back()->range_right * current_struct_elem->multirange_dimensions.back(), true);
        } else {
            left = AST::AstNode::mkconst_int(current_struct_elem->children.front()->range_left, true);
            right = AST::AstNode::mkconst_int(current_struct_elem->children.back()->range_right, true);
        }
        break;
    default:
        // Structs currently can only have AST_STRUCT, AST_STRUCT_ITEM, or AST_UNION.
        log_file_error(current_struct_elem->filename, current_struct_elem->location.first_line,
                       "Accessing struct member of type %s is unsupported.\n", type2str(current_struct_elem->type).c_str());
    };

    auto elem_size =
      new AST::AstNode(AST::AST_ADD, new AST::AstNode(AST::AST_SUB, left->clone(), right->clone()), AST::AstNode::mkconst_int(1, true));

    if (sub_dot) {
        // First select correct element in first struct
        std::swap(left, sub_dot->children[0]);
        std::swap(right, sub_dot->children[1]);
        delete sub_dot;
    }

    for (size_t i = 0; i < struct_ranges.size(); i++) {
        const auto *struct_range = struct_ranges[i];
        auto const range_width_idx = i * 2 + 1;
        auto const range_offset_idx = i * 2;

        int range_width = 0;
        if (current_struct_elem->multirange_dimensions.empty()) {
            range_width = 1;
        } else if (current_struct_elem->multirange_dimensions.size() > range_width_idx) {
            range_width = current_struct_elem->multirange_dimensions[range_width_idx];
            const auto range_offset = current_struct_elem->multirange_dimensions[range_offset_idx];
            if (range_offset != 0) {
                log_file_error(struct_range->filename, struct_range->location.first_line,
                               "Accessing ranges that do not start from 0 is not supported.");
            }
        } else {
            struct_range->dumpAst(NULL, "range >");
            log_file_error(struct_range->filename, struct_range->location.first_line, "Couldn't find range width.");
        }
        // now we have correct element set,
        // but we still need to set correct struct
        log_assert(!struct_range->children.empty());
        if (current_struct_elem->type == AST::AST_STRUCT_ITEM) {
            // if we selecting range of struct item, just add this range
            // to our current select
            if (current_struct_elem->multirange_dimensions.size() > 2 && struct_range->children.size() == 2) {
                log_error("Selecting a range of positions from a multirange is not supported in the dot notation.\n");
            }
            if (struct_range->children.size() == 2) {
                auto range_size = new AST::AstNode(
                  AST::AST_ADD, new AST::AstNode(AST::AST_SUB, struct_range->children[0]->clone(), struct_range->children[1]->clone()),
                  AST::AstNode::mkconst_int(1, true));
                right = new AST::AstNode(AST::AST_ADD, right, struct_range->children[1]->clone());
                delete left;
                left = new AST::AstNode(AST::AST_ADD, right->clone(), new AST::AstNode(AST::AST_SUB, range_size, AST::AstNode::mkconst_int(1, true)));

            } else if (struct_range->children.size() == 1) {
                // Selected a single position, as in `foo.bar[i]`.
                if (range_width > 1 && current_struct_elem->multirange_dimensions.size() > range_width_idx + 2) {
                    // if it's not the last dimension.
                    right = new AST::AstNode(
                      AST::AST_ADD, right,
                      new AST::AstNode(AST::AST_MUL, struct_range->children[0]->clone(), AST::AstNode::mkconst_int(range_width, true)));
                    delete left;
                    left = new AST::AstNode(AST::AST_ADD, right->clone(), AST::AstNode::mkconst_int(range_width - 1, true));
                } else {
                    right = new AST::AstNode(AST::AST_ADD, right, struct_range->children[0]->clone());
                    delete left;
                    left = right->clone();
                }
            } else {
                struct_range->dumpAst(NULL, "range >");
                log_error("Unhandled range select (AST_STRUCT_ITEM) in AST_DOT!\n");
            }
        } else if (current_struct_elem->type == AST::AST_STRUCT) {
            if (struct_range->children.size() == 2) {
                right = new AST::AstNode(AST::AST_ADD, right, struct_range->children[1]->clone());
                auto range_size = new AST::AstNode(
                  AST::AST_ADD, new AST::AstNode(AST::AST_SUB, struct_range->children[0]->clone(), struct_range->children[1]->clone()),
                  AST::AstNode::mkconst_int(1, true));
                left = new AST::AstNode(AST::AST_ADD, left, new AST::AstNode(AST::AST_SUB, range_size, elem_size->clone()));
            } else if (struct_range->children.size() == 1) {
                AST::AstNode *mul = new AST::AstNode(AST::AST_MUL, elem_size->clone(), struct_range->children[0]->clone());

                left = new AST::AstNode(AST::AST_ADD, left, mul);
                right = new AST::AstNode(AST::AST_ADD, right, mul->clone());
            } else {
                struct_range->dumpAst(NULL, "range >");
                log_error("Unhandled range select (AST_STRUCT) in AST_DOT!\n");
            }
        } else {
            log_file_error(current_struct_elem->filename, current_struct_elem->location.first_line,
                           "Accessing member of a slice of type %s is unsupported.\n", type2str(current_struct_elem->type).c_str());
        }
    }
    delete elem_size;
    // Return range from the begining of *current* struct
    // When all AST_DOT are expanded it will return range
    // from original wire
    return new AST::AstNode(AST::AST_RANGE, left, right);
}

static AST::AstNode *convert_dot(AST::AstNode *wire_node, AST::AstNode *node, AST::AstNode *dot)
{
    AST::AstNode *struct_node = nullptr;
    if (wire_node->type == AST::AST_STRUCT || wire_node->type == AST::AST_UNION) {
        struct_node = wire_node;
    } else if (wire_node->attributes.count(ID::wiretype)) {
        log_assert(wire_node->attributes[ID::wiretype]->id2ast);
        struct_node = wire_node->attributes[ID::wiretype]->id2ast;
    } else {
        log_file_error(wire_node->filename, wire_node->location.first_line, "Unsupported node type: %s\n", type2str(wire_node->type).c_str());
    }
    log_assert(struct_node);
    auto expanded = expand_dot(struct_node, dot);
    // Now expand ranges that are at instance part of dotted reference
    // `expand_dot` returns AST_RANGE with 2 children that selects member pointed by dotted reference
    // now we need to move this range to select correct struct
    std::vector<AST::AstNode *> struct_ranges;
    for (auto c : node->children) {
        if (c->type == AST::AST_RANGE) {
            struct_ranges.push_back(c);
        }
    }
    log_assert(wire_node->attributes.count(UhdmAst::unpacked_ranges()));
    log_assert(wire_node->attributes.count(UhdmAst::packed_ranges()));
    log_assert(struct_ranges.size() <= (wire_node->multirange_dimensions.size() / 2));
    const auto wire_node_unpacked_ranges_size = wire_node->attributes[UhdmAst::unpacked_ranges()]->children.size();
    // TODO(krak): wire ranges are sometimes under wiretype node (e.g. in case of typedef)
    // but wiretype ranges contains also struct range that is already expanded in 'expand_dot'
    // we need to find a way to calculate size of wire ranges without struct range here to enable this assert
    // const auto wire_node_packed_ranges_size = wire_node->attributes[UhdmAst::packed_ranges()]->children.size();
    // const auto wire_node_ranges_size = wire_node_packed_ranges_size + wire_node_unpacked_ranges_size;
    // log_assert(struct_ranges.size() == (wire_node_ranges_size - 1));

    // Get size of single structure
    int struct_size_int = get_max_offset_struct(struct_node) + 1;
    auto wire_dimension_size_it = wire_node->multirange_dimensions.rbegin();
    unsigned long range_id = 0;
    for (auto it = struct_ranges.rbegin(); it != struct_ranges.rend(); it++) {
        // in 'dot' context, we need to select specific struct element,
        // so assert that there is only 1 child in struct range (range with single child)
        log_assert((*it)->children.size() == 1);
        bool is_unpacked_range = range_id < wire_node_unpacked_ranges_size;
        // if unpacked range, select from back
        auto elem = is_unpacked_range
                      ? new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(*wire_dimension_size_it - 1, true, 32), (*it)->children[0]->clone())
                      : (*it)->children[0]->clone();
        // calculate which struct we selected
        auto move_offset = new AST::AstNode(AST::AST_MUL, AST::AstNode::mkconst_int(struct_size_int, true, 32), elem);
        // move our expanded dot to currently selected struct
        expanded->children[0] = new AST::AstNode(AST::AST_ADD, move_offset->clone(), expanded->children[0]);
        expanded->children[1] = new AST::AstNode(AST::AST_ADD, move_offset, expanded->children[1]);
        struct_size_int *= *wire_dimension_size_it;
        // wire_dimension_size stores interleaved offset and size. Move to next dimension's size
        wire_dimension_size_it += 2;
        range_id++;
    }
    return expanded;
}

static void setup_current_scope(std::unordered_map<std::string, AST::AstNode *> top_nodes, AST::AstNode *current_top_node)
{
    for (auto it = top_nodes.begin(); it != top_nodes.end(); it++) {
        if (!it->second)
            continue;
        if (it->second->type == AST::AST_PACKAGE) {
            for (auto &o : it->second->children) {
                // import only parameters
                if (o->type == AST::AST_TYPEDEF || o->type == AST::AST_PARAMETER || o->type == AST::AST_LOCALPARAM) {
                    // add imported nodes to current scope
                    AST_INTERNAL::current_scope[it->second->str + std::string("::") + o->str.substr(1)] = o;
                    AST_INTERNAL::current_scope[o->str] = o;
                } else if (o->type == AST::AST_ENUM) {
                    AST_INTERNAL::current_scope[o->str] = o;
                    for (auto c : o->children) {
                        AST_INTERNAL::current_scope[c->str] = c;
                    }
                }
            }
        }
    }
    for (auto &o : current_top_node->children) {
        if (o->type == AST::AST_TYPEDEF || o->type == AST::AST_PARAMETER || o->type == AST::AST_LOCALPARAM) {
            AST_INTERNAL::current_scope[o->str] = o;
        } else if (o->type == AST::AST_ENUM) {
            AST_INTERNAL::current_scope[o->str] = o;
            for (auto c : o->children) {
                AST_INTERNAL::current_scope[c->str] = c;
            }
        }
    }
    // hackish way of setting current_ast_mod as it is required
    // for simplify to get references for already defined ids
    AST_INTERNAL::current_ast_mod = current_top_node;
    log_assert(AST_INTERNAL::current_ast_mod != nullptr);
}

static int range_width_local(AST::AstNode *node, AST::AstNode *rnode)
{
    log_assert(rnode->type == AST::AST_RANGE);
    if (!rnode->range_valid) {
        log_file_error(node->filename, node->location.first_line, "Size must be constant in packed struct/union member %s\n", node->str.c_str());
    }
    // note: range swapping has already been checked for
    return rnode->range_left - rnode->range_right + 1;
}

static void save_struct_array_width_local(AST::AstNode *node, int width)
{
    // stash the stride for the array
    node->multirange_dimensions.push_back(width);
}

static int simplify_struct(AST::AstNode *snode, int base_offset, AST::AstNode *parent_node)
{
    // Struct members will be laid out in the structure contiguously from left to right.
    // Union members all have zero offset from the start of the union.
    // Determine total packed size and assign offsets.  Store these in the member node.
    bool is_union = (snode->type == AST::AST_UNION);
    int offset = 0;
    int packed_width = -1;
    for (auto s : snode->children) {
        if (s->type == AST::AST_RANGE) {
            while (simplify(s, true, false, false, 1, -1, false, false)) {
            };
        }
    }
    // embeded struct or union with range?
    auto it = std::remove_if(snode->children.begin(), snode->children.end(), [](AST::AstNode *node) { return node->type == AST::AST_RANGE; });
    std::vector<AST::AstNode *> ranges(it, snode->children.end());
    snode->children.erase(it, snode->children.end());
    if (!ranges.empty()) {
        for (auto range : ranges) {
            snode->multirange_dimensions.push_back(min(range->range_left, range->range_right));
            snode->multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1);
            snode->multirange_swapped.push_back(range->range_swapped);
            delete range;
        }
    }
    // examine members from last to first
    for (auto it = snode->children.rbegin(); it != snode->children.rend(); ++it) {
        auto node = *it;
        int width;
        if (node->type == AST::AST_STRUCT || node->type == AST::AST_UNION) {
            // embedded struct or union
            width = simplify_struct(node, base_offset + offset, parent_node);
            if (!node->multirange_dimensions.empty()) {
                // Multiply widths of all dimensions.
                // `multirange_dimensions` stores (repeating) pairs of [offset, width].
                for (size_t i = 1; i < node->multirange_dimensions.size(); i += 2) {
                    width *= node->multirange_dimensions[i];
                }
            }
            // set range of struct
            node->range_right = base_offset + offset;
            node->range_left = base_offset + offset + width - 1;
            node->range_valid = true;
        } else {
            log_assert(node->type == AST::AST_STRUCT_ITEM);
            if (node->children.size() > 0 && node->children[0]->type == AST::AST_RANGE) {
                // member width e.g. bit [7:0] a
                width = range_width_local(node, node->children[0]);
                if (node->children.size() == 2) {
                    if (node->children[1]->type == AST::AST_RANGE) {
                        // unpacked array e.g. bit [63:0] a [0:3]
                        auto rnode = node->children[1];
                        int array_count = range_width_local(node, rnode);
                        if (array_count == 1) {
                            // C-type array size e.g. bit [63:0] a [4]
                            array_count = rnode->range_left;
                        }
                        save_struct_array_width_local(node, width);
                        width *= array_count;
                    } else {
                        // array element must be single bit for a packed array
                        log_file_error(node->filename, node->location.first_line, "Unpacked array in packed struct/union member %s\n",
                                       node->str.c_str());
                    }
                }
                // range nodes are now redundant
                for (AST::AstNode *child : node->children)
                    delete child;
                node->children.clear();
            } else if (node->children.size() == 1 && node->children[0]->type == AST::AST_MULTIRANGE) {
                // packed 2D array, e.g. bit [3:0][63:0] a
                auto rnode = node->children[0];
                if (rnode->children.size() != 2) {
                    // packed arrays can only be 2D
                    log_file_error(node->filename, node->location.first_line, "Unpacked array in packed struct/union member %s\n", node->str.c_str());
                }
                int array_count = range_width_local(node, rnode->children[0]);
                width = range_width_local(node, rnode->children[1]);
                save_struct_array_width_local(node, width);
                width *= array_count;
                // range nodes are now redundant
                for (AST::AstNode *child : node->children)
                    delete child;
                node->children.clear();
            } else if (node->range_left < 0) {
                // 1 bit signal: bit, logic or reg
                width = 1;
            } else {
                // already resolved and compacted
                width = node->range_left - node->range_right + 1;
            }
            if (is_union) {
                node->range_right = base_offset;
                node->range_left = base_offset + width - 1;
            } else {
                node->range_right = base_offset + offset;
                node->range_left = base_offset + offset + width - 1;
            }
            node->range_valid = true;
        }
        if (is_union) {
            // check that all members have the same size
            if (packed_width == -1) {
                // first member
                packed_width = width;
            } else {
                if (packed_width != width) {

                    log_file_error(node->filename, node->location.first_line, "member %s of a packed union has %d bits, expecting %d\n",
                                   node->str.c_str(), width, packed_width);
                }
            }
        } else {
            offset += width;
        }
    }
    if (!snode->str.empty() && parent_node && parent_node->type != AST::AST_TYPEDEF && parent_node->type != AST::AST_STRUCT &&
        AST_INTERNAL::current_scope.count(snode->str) != 0) {
        AST_INTERNAL::current_scope[snode->str]->attributes[ID::wiretype] = AST::AstNode::mkconst_str(snode->str);
        AST_INTERNAL::current_scope[snode->str]->attributes[ID::wiretype]->id2ast = snode;
    }
    return (is_union ? packed_width : offset);
}

static void add_members_to_scope_local(AST::AstNode *snode, std::string name)
{
    // add all the members in a struct or union to local scope
    // in case later referenced in assignments
    log_assert(snode->type == AST::AST_STRUCT || snode->type == AST::AST_UNION);
    for (auto *node : snode->children) {
        auto member_name = name + "." + node->str;
        AST_INTERNAL::current_scope[member_name] = node;
        if (node->type != AST::AST_STRUCT_ITEM) {
            // embedded struct or union
            add_members_to_scope_local(node, name + "." + node->str);
        }
    }
}

static AST::AstNode *make_packed_struct_local(AST::AstNode *template_node, std::string &name)
{
    // create a wire for the packed struct
    auto wnode = new AST::AstNode(AST::AST_WIRE);
    wnode->str = name;
    wnode->is_logic = true;
    wnode->range_valid = true;
    wnode->is_signed = template_node->is_signed;
    int offset = get_max_offset_struct(template_node);
    auto range = make_range(offset, 0);
    copy_packed_unpacked_attribute(template_node, wnode);
    wnode->attributes[UhdmAst::packed_ranges()]->children.insert(wnode->attributes[UhdmAst::packed_ranges()]->children.begin(), range);
    // make sure this node is the one in scope for this name
    AST_INTERNAL::current_scope[name] = wnode;
    // add all the struct members to scope under the wire's name
    add_members_to_scope_local(template_node, name);
    return wnode;
}

static void simplify_format_string(AST::AstNode *current_node)
{
    std::string sformat = current_node->children[0]->str;
    std::string preformatted_string = "";
    int next_arg = 1;
    for (size_t i = 0; i < sformat.length(); i++) {
        if (sformat[i] == '%') {
            AST::AstNode *node_arg = current_node->children[next_arg];
            char cformat = sformat[++i];
            if (cformat == 'b' or cformat == 'B') {
                simplify(node_arg, true, false, false, 1, -1, false, false);
                if (node_arg->type != AST::AST_CONSTANT)
                    log_file_error(current_node->filename, current_node->location.first_line,
                                   "Failed to evaluate system task `%s' with non-constant argument.\n", current_node->str.c_str());

                RTLIL::Const val = node_arg->bitsAsConst();
                for (int j = val.size() - 1; j >= 0; j--) {
                    // We add ACII value of 0 to convert number to character
                    preformatted_string += ('0' + val[j]);
                }
                delete current_node->children[next_arg];
                current_node->children.erase(current_node->children.begin() + next_arg);
            } else {
                next_arg++;
                preformatted_string += std::string("%") + cformat;
            }
        } else {
            preformatted_string += sformat[i];
        }
    }
    delete current_node->children[0];
    current_node->children[0] = AST::AstNode::mkconst_str(preformatted_string);
}

// A wrapper for Yosys simplify function.
// Simplifies AST constructs specific to this plugin to a form understandable by Yosys' simplify and then calls the latter if necessary.
// Since simplify from Yosys has been forked to this codebase, all new code should be added there instead.
static void simplify_sv(AST::AstNode *current_node, AST::AstNode *parent_node)
{
    auto dot_it = std::find_if(current_node->children.begin(), current_node->children.end(),
                               [](auto c) { return c->type == static_cast<int>(AST::Extended::AST_DOT); });
    AST::AstNode *dot = (dot_it != current_node->children.end()) ? *dot_it : nullptr;

    AST::AstNode *expanded = nullptr;
    if (dot) {
        if (!AST_INTERNAL::current_scope.count(current_node->str)) {
            // for accessing elements currently unsupported with AST_DOT
            // fallback to "." notation
            AST::AstNode *prefix_node = nullptr;
            AST::AstNode *parent_node = current_node;
            while (dot && !dot->str.empty()) {
                // it is not possible for AST_RANGE to be after AST::DOT (see process_hier_path function)
                if (parent_node->children[0]->type == AST::AST_RANGE) {
                    if (parent_node->children[1]->type == AST::AST_RANGE)
                        log_error("Multirange in AST_DOT is currently unsupported\n");

                    dot->type = AST::AST_IDENTIFIER;
                    simplify_sv(dot, nullptr);
                    AST::AstNode *range_const = parent_node->children[0]->children[0];
                    prefix_node = new AST::AstNode(AST::AST_PREFIX, range_const->clone(), dot->clone());
                    break;
                } else {
                    current_node->str += "." + dot->str.substr(1);
                    dot_it = std::find_if(dot->children.begin(), dot->children.end(),
                                          [](auto c) { return c->type == static_cast<int>(AST::Extended::AST_DOT); });
                    parent_node = dot;
                    dot = (dot_it != dot->children.end()) ? *dot_it : nullptr;
                }
            }
            delete_children(current_node);
            if (prefix_node != nullptr) {
                current_node->type = AST::AST_PREFIX;
                current_node->children = prefix_node->children;

                prefix_node->children.clear();
                delete prefix_node;
            }
        } else {
            auto wire_node = AST_INTERNAL::current_scope[current_node->str];
            // make sure wire_node is already simplified
            simplify_sv(wire_node, nullptr);
            expanded = convert_dot(wire_node, current_node, dot);
        }
    }
    if (expanded) {
        delete_children(current_node);
        current_node->children.push_back(expanded->clone());
        current_node->basic_prep = true;
        delete expanded;
        expanded = nullptr;
    }
    // First simplify children
    for (size_t i = 0; i < current_node->children.size(); i++) {
        simplify_sv(current_node->children[i], current_node);
    }
    switch (current_node->type) {
    case AST::AST_TYPEDEF:
    case AST::AST_ENUM:
    case AST::AST_FUNCTION:
        AST_INTERNAL::current_scope[current_node->str] = current_node;
        break;
    case AST::AST_WIRE:
    case AST::AST_PARAMETER:
    case AST::AST_LOCALPARAM:
        if (!current_node->attributes.count(UhdmAst::is_simplified_wire())) {
            current_node->attributes[UhdmAst::is_simplified_wire()] = AST::AstNode::mkconst_int(1, true);
            AST_INTERNAL::current_scope[current_node->str] = current_node;
            convert_packed_unpacked_range(current_node);
        }
        break;
    case AST::AST_IDENTIFIER:
        if (!current_node->children.empty() && !current_node->basic_prep) {
            log_assert(AST_INTERNAL::current_ast_mod);
            if (!AST_INTERNAL::current_scope.count(current_node->str)) {
                break;
            }
            AST::AstNode *wire_node = AST_INTERNAL::current_scope[current_node->str];

            // if a wire is simplified multiple times, its ranges may be added multiple times and be redundant as a result
            if (!wire_node->attributes.count(UhdmAst::is_simplified_wire())) {
                simplify_sv(wire_node, nullptr);
            }
            const int packed_ranges_size =
              wire_node->attributes.count(UhdmAst::packed_ranges()) ? wire_node->attributes[UhdmAst::packed_ranges()]->children.size() : 0;
            const int unpacked_ranges_size =
              wire_node->attributes.count(UhdmAst::unpacked_ranges()) ? wire_node->attributes[UhdmAst::unpacked_ranges()]->children.size() : 0;
            if ((wire_node->type == AST::AST_WIRE || wire_node->type == AST::AST_PARAMETER || wire_node->type == AST::AST_LOCALPARAM) &&
                (packed_ranges_size + unpacked_ranges_size > 1)) {
                auto *result = convert_range(current_node, packed_ranges_size, unpacked_ranges_size, 0);
                delete_children(current_node);
                current_node->children.push_back(result);
            }
        }
        break;
    case AST::AST_STRUCT:
    case AST::AST_UNION:
        if (!current_node->attributes.count(UhdmAst::is_simplified_wire())) {
            current_node->attributes[UhdmAst::is_simplified_wire()] = AST::AstNode::mkconst_int(1, true);
            simplify_struct(current_node, 0, parent_node);
            // instance rather than just a type in a typedef or outer struct?
            if (!current_node->str.empty() && current_node->str[0] == '\\') {
                // instance so add a wire for the packed structure
                auto wnode = make_packed_struct_local(current_node, current_node->str);
                convert_packed_unpacked_range(wnode);
                log_assert(AST_INTERNAL::current_ast_mod);
                AST_INTERNAL::current_ast_mod->children.push_back(wnode);
                AST_INTERNAL::current_scope[wnode->str]->attributes[ID::wiretype] = AST::AstNode::mkconst_str(current_node->str);
                AST_INTERNAL::current_scope[wnode->str]->attributes[ID::wiretype]->id2ast = current_node;
            }

            current_node->basic_prep = true;
        }
        break;
    case AST::AST_STRUCT_ITEM:
        if (!current_node->attributes.count(UhdmAst::is_simplified_wire())) {
            current_node->attributes[UhdmAst::is_simplified_wire()] = AST::AstNode::mkconst_int(1, true);
            AST_INTERNAL::current_scope[current_node->str] = current_node;
            convert_packed_unpacked_range(current_node);
            while (simplify(current_node, true, false, false, 1, -1, false, false)) {
            };
        }
        break;
    case AST::AST_TCALL:
        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:
        // 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[0] = nullptr;
            current_node->children[1] = nullptr;
            delete_children(current_node);
            while (simplify(low_high_bound->children[0], true, false, false, 1, -1, false, false)) {
            };
            while (simplify(low_high_bound->children[1], 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;
            const int range = low_high_bound->children[1]->range_valid
                                ? low_high_bound->children[1]->range_left
                                : low_high_bound->children[0]->range_valid ? low_high_bound->children[0]->range_left : 32;
            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++) {
                current_node->children.push_back(AST::AstNode::mkconst_int(i, false, range));
            }
            current_node->children.push_back(result);
            delete_attribute(current_node, UhdmAst::low_high_bound());
        }
        break;
    default:
        break;
    }
}

static void clear_current_scope()
{
    // Remove clear current_scope from package nodes
    AST_INTERNAL::current_scope.clear();
    // unset current_ast_mod
    AST_INTERNAL::current_ast_mod = nullptr;
}

void UhdmAst::visit_one_to_many(const std::vector<int> child_node_types, vpiHandle parent_handle, const std::function<void(AST::AstNode *)> &f)
{
    for (auto child : child_node_types) {
        vpiHandle itr = vpi_iterate(child, parent_handle);
        while (vpiHandle vpi_child_obj = vpi_scan(itr)) {
            UhdmAst uhdm_ast(this, shared, indent + "  ");
            auto *child_node = uhdm_ast.process_object(vpi_child_obj);
            f(child_node);
            vpi_release_handle(vpi_child_obj);
        }
        vpi_release_handle(itr);
    }
}

void UhdmAst::visit_one_to_one(const std::vector<int> child_node_types, vpiHandle parent_handle, const std::function<void(AST::AstNode *)> &f)
{
    for (auto child : child_node_types) {
        vpiHandle itr = vpi_handle(child, parent_handle);
        if (itr) {
            UhdmAst uhdm_ast(this, shared, indent + "  ");
            auto *child_node = uhdm_ast.process_object(itr);
            f(child_node);
        }
        vpi_release_handle(itr);
    }
}

void UhdmAst::visit_range(vpiHandle obj_h, const std::function<void(AST::AstNode *)> &f)
{
    std::vector<AST::AstNode *> range_nodes;
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { range_nodes.push_back(node); });
    if (range_nodes.size() > 1) {
        auto multirange_node = new AST::AstNode(AST::AST_MULTIRANGE);
        multirange_node->children = range_nodes;
        f(multirange_node);
    } else if (!range_nodes.empty()) {
        f(range_nodes[0]);
    }
}

void UhdmAst::visit_default_expr(vpiHandle obj_h)
{
    UhdmAst initial_ast(parent, shared, indent);
    UhdmAst block_ast(&initial_ast, shared, indent);
    block_ast.visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *expr_node) {
        auto mod = find_ancestor({AST::AST_MODULE});
        AST::AstNode *initial_node = nullptr;
        AST::AstNode *block_node = nullptr;
        auto assign_node = new AST::AstNode(AST::AST_ASSIGN_EQ);
        auto id_node = new AST::AstNode(AST::AST_IDENTIFIER);
        id_node->str = current_node->str;

        for (auto child : mod->children) {
            if (child->type == AST::AST_INITIAL) {
                initial_node = child;
                break;
            }
        }
        // Ensure single AST_INITIAL node is located in AST_MODULE
        // before any AST_ALWAYS
        if (initial_node == nullptr) {
            initial_node = new AST::AstNode(AST::AST_INITIAL);
            auto insert_it = find_if(mod->children.begin(), mod->children.end(), [](AST::AstNode *node) { return (node->type == AST::AST_ALWAYS); });
            mod->children.insert(insert_it, initial_node);
        }
        // Ensure single AST_BLOCK node in AST_INITIAL
        if (!initial_node->children.empty() && initial_node->children[0]) {
            block_node = initial_node->children[0];
        } else {
            block_node = new AST::AstNode(AST::AST_BLOCK);
            initial_node->children.push_back(block_node);
        }
        auto block_child =
          find_if(block_node->children.begin(), block_node->children.end(), [](AST::AstNode *node) { return (node->type == AST::AST_ASSIGN_EQ); });
        // Insert AST_ASSIGN_EQ nodes that came from
        // custom_var or int_var before any other AST_ASSIGN_EQ
        // Especially before ones explicitly placed in initial block in source code
        block_node->children.insert(block_child, assign_node);
        assign_node->children.push_back(id_node);
        initial_ast.current_node = initial_node;
        block_ast.current_node = block_node;
        assign_node->children.push_back(expr_node);
    });
}

AST::AstNode *UhdmAst::process_value(vpiHandle obj_h)
{
    s_vpi_value val;
    vpi_get_value(obj_h, &val);
    std::string strValType = "'";
    bool is_signed = false;
    if (vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h)) {
        is_signed = vpi_get(vpiSigned, typespec_h);
        if (is_signed) {
            strValType += "s";
        }
        vpi_release_handle(typespec_h);
    }
    std::string val_str;
    if (val.format) { // Needed to handle parameter nodes without typespecs and constants
        switch (val.format) {
        case vpiScalarVal:
            return AST::AstNode::mkconst_int(val.value.scalar, false, 1);
        case vpiBinStrVal: {
            strValType += "b";
            val_str = val.value.str;
            break;
        }
        case vpiDecStrVal: {
            strValType += "d";
            val_str = val.value.str;
            break;
        }
        case vpiHexStrVal: {
            strValType += "h";
            val_str = val.value.str;
            break;
        }
        case vpiOctStrVal: {
            strValType += "o";
            val_str = val.value.str;
            break;
        }
        // Surelog reports constant integers as a unsigned, but by default int is signed
        // so we are treating here UInt in the same way as if they would be Int
        case vpiUIntVal:
            if (val.value.uint > std::numeric_limits<std::uint32_t>::max()) {
                // an integer is by default signed, so use 'sd despite the variant vpiUIntVal
                strValType = "'sd";
                val_str = std::to_string(val.value.uint);
                break;
            }
            [[fallthrough]];
        case vpiIntVal: {
            if (val.value.integer > std::numeric_limits<std::int32_t>::max()) {
                strValType = "'sd";
                val_str = std::to_string(val.value.integer);
                break;
            }

            auto size = vpi_get(vpiSize, obj_h);
            // Surelog by default returns 64 bit numbers and stardard says that they shall be at least 32bits
            // yosys is assuming that int/uint is 32 bit, so we are setting here correct size
            // NOTE: it *shouldn't* break on explicite 64 bit const values, as they *should* be handled
            // above by vpi*StrVal
            if (size == 64) {
                size = 32;
                is_signed = true;
            }
            auto c = AST::AstNode::mkconst_int(val.format == vpiUIntVal ? val.value.uint : val.value.integer, is_signed, size > 0 ? size : 32);
            if (size == 0 || size == -1)
                c->is_unsized = true;
            return c;
        }
        case vpiRealVal:
            return mkconst_real(val.value.real);
        case vpiStringVal:
            return AST::AstNode::mkconst_str(val.value.str);
        default: {
            const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
            const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
            report_error("%.*s:%d: Encountered unhandled constant format %d\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                         object->VpiLineNo(), val.format);
        }
        }
        // if this constant is under case/casex/casez
        // get current case type
        char caseType = ' ';
        if (vpiHandle caseItem_h = vpi_handle(vpiParent, obj_h)) {
            if (vpiHandle case_h = vpi_handle(vpiParent, caseItem_h)) {
                switch (vpi_get(vpiCaseType, case_h)) {
                case vpiCaseExact:
                    caseType = ' ';
                    break;
                case vpiCaseX:
                    caseType = 'x';
                    break;
                case vpiCaseZ:
                    caseType = 'z';
                    break;
                default: {
                    caseType = ' ';
                    break;
                }
                }
                vpi_release_handle(case_h);
            }
            vpi_release_handle(caseItem_h);
        }
        // handle vpiBinStrVal, vpiDecStrVal and vpiHexStrVal
        if (val_str.find('\'') != std::string::npos) {
            return ::systemverilog_plugin::const2ast(std::move(val_str), caseType, false);
        } else {
            auto size = vpi_get(vpiSize, obj_h);
            std::string size_str;
            if (size > 0) {
                size_str = std::to_string(size);
            } else if (strValType == "\'b") {
                // probably unsized unbased const
                // but to make sure parse vpiDecompile
                auto decompile = vpi_get_str(vpiDecompile, obj_h);
                if (decompile && !std::strchr(decompile, 'b')) {
                    // unsized unbased
                    // we can't left size_str empty, as then yosys parses this const as 32bit value
                    size_str = "1";
                }
            }
            auto c = ::systemverilog_plugin::const2ast(size_str + strValType + val_str, caseType, false);
            if (size <= 0) {
                // unsized unbased const
                c->is_unsized = true;
            }
            return c;
        }
    }
    return nullptr;
}

void UhdmAst::transform_breaks_continues(AST::AstNode *loop, AST::AstNode *decl_block)
{
    AST::AstNode *break_wire = nullptr;
    AST::AstNode *continue_wire = nullptr;
    // Creates a 1-bit wire with the given name
    const auto make_cond_var = [this](const std::string &var_name) {
        auto cond_var =
          make_ast_node(AST::AST_WIRE, {make_ast_node(AST::AST_RANGE, {AST::AstNode::mkconst_int(0, false), AST::AstNode::mkconst_int(0, false)}),
                                        AST::AstNode::mkconst_int(0, false)});
        cond_var->str = var_name;
        cond_var->is_reg = true;
        return cond_var;
    };
    // Creates a conditional like 'if (!casevar) block'
    auto make_case = [this](AST::AstNode *block, const std::string &casevar_name) {
        auto *case_node = make_ast_node(AST::AST_CASE);
        auto *id = make_identifier(casevar_name);
        case_node->children.push_back(id);
        auto *constant = AST::AstNode::mkconst_int(0, false, 1);
        auto *cond_node = make_ast_node(AST::AST_COND);
        cond_node->children.push_back(constant);
        cond_node->children.push_back(block);
        case_node->children.push_back(cond_node);
        return case_node;
    };
    // Pre-declare this function to be able to call it recursively
    std::function<bool(AST::AstNode *)> transform_block;
    // Transforms the given block if it has a break or continue; recurses into child blocks; return true if a break/continue was encountered
    transform_block = [&](AST::AstNode *block) {
        auto wrap_and_transform = [&](decltype(block->children)::iterator it) {
            // Move the (it, end()) statements into a new block under 'if (!continue) {...}'
            auto *new_block = make_ast_node(AST::AST_BLOCK, {it, block->children.end()});
            block->children.erase(it, block->children.end());
            auto *case_node = make_case(new_block, continue_wire->str);
            block->children.push_back(case_node);
            transform_block(new_block);
        };

        for (auto it = block->children.begin(); it != block->children.end(); it++) {
            auto type = static_cast<int>((*it)->type);
            switch (type) {
            case AST::AST_BLOCK: {
                if (transform_block(*it)) {
                    // If there was a break/continue, we need to wrap the rest of the block in an if
                    wrap_and_transform(it + 1);
                    return true;
                }
                break;
            }
            case AST::AST_CASE: {
                // Go over each block in a case
                bool has_jump = false;
                for (auto *node : (*it)->children) {
                    if (node->type == AST::AST_COND)
                        has_jump = has_jump || transform_block(node->children.back());
                }
                if (has_jump) {
                    // If there was a break/continue, we need to wrap the rest of the block in an if
                    wrap_and_transform(it + 1);
                    return true;
                }
                break;
            }
            case AST::Extended::AST_BREAK:
            case AST::Extended::AST_CONTINUE: {
                std::for_each(it, block->children.end(), [](auto *node) { delete node; });
                block->children.erase(it, block->children.end());
                if (!continue_wire)
                    continue_wire = make_cond_var("$continue");
                auto *continue_id = make_identifier(continue_wire->str);
                block->children.push_back(make_ast_node(AST::AST_ASSIGN_EQ, {continue_id, AST::AstNode::mkconst_int(1, false)}));
                if (type == AST::Extended::AST_BREAK) {
                    if (!break_wire)
                        break_wire = make_cond_var("$break");
                    auto *break_id = make_identifier(break_wire->str);
                    block->children.push_back(make_ast_node(AST::AST_ASSIGN_EQ, {break_id, AST::AstNode::mkconst_int(1, false)}));
                }
                return true;
            }
            }
        }
        return false;
    };

    // Actual transformation starts here
    transform_block(loop->children.back());
    if (continue_wire) {
        auto *continue_id = make_identifier(continue_wire->str);
        // Reset $continue each iteration
        auto *continue_assign = make_ast_node(AST::AST_ASSIGN_EQ, {continue_id, AST::AstNode::mkconst_int(0, false)});
        decl_block->children.insert(decl_block->children.begin(), continue_wire);
        loop->children.back()->children.insert(loop->children.back()->children.begin(), continue_assign);
    }
    if (break_wire) {
        auto *break_id = make_identifier(break_wire->str);
        // Reset $break before the loop
        auto *break_assign = make_ast_node(AST::AST_ASSIGN_EQ, {break_id, AST::AstNode::mkconst_int(0, false)});
        decl_block->children.insert(decl_block->children.begin(), break_assign);
        decl_block->children.insert(decl_block->children.begin(), break_wire);
        if (loop->type == AST::AST_REPEAT || loop->type == AST::AST_FOR) {
            // Wrap loop body in 'if (!break) {...}'
            // Changing the for loop condition won't work here,
            // as then simplify fails with error "2nd expression of procedural for-loop is not constant!"
            auto *case_node = make_case(loop->children.back(), break_wire->str);
            auto *new_block = make_ast_node(AST::AST_BLOCK);
            new_block->children.push_back(case_node);
            new_block->str = loop->children.back()->str;
            loop->children.back() = new_block;
        } else if (loop->type == AST::AST_WHILE) {
            // Add the break var to the loop condition
            auto *break_id = make_identifier(break_wire->str);
            AST::AstNode *&loop_cond = loop->children[0];
            loop_cond = make_ast_node(AST::AST_LOGIC_AND, {make_ast_node(AST::AST_LOGIC_NOT, {break_id}), loop_cond});
        } else {
            log_error("break unsupported for this loop type");
        }
    }
}

void UhdmAst::apply_location_from_current_obj(AST::AstNode &target_node) const
{
    if (auto filename = vpi_get_str(vpiFile, obj_h)) {
        target_node.filename = filename;
    }
    if (unsigned int first_line = vpi_get(vpiLineNo, obj_h)) {
        target_node.location.first_line = first_line;
    }
    if (unsigned int last_line = vpi_get(vpiEndLineNo, obj_h)) {
        target_node.location.last_line = last_line;
    } else {
        target_node.location.last_line = target_node.location.first_line;
    }
    if (unsigned int first_col = vpi_get(vpiColumnNo, obj_h)) {
        target_node.location.first_column = first_col;
    }
    if (unsigned int last_col = vpi_get(vpiEndColumnNo, obj_h)) {
        target_node.location.last_column = last_col;
    } else {
        target_node.location.last_column = target_node.location.first_column;
    }
}

void UhdmAst::apply_name_from_current_obj(AST::AstNode &target_node, bool prefer_full_name) const
{
    target_node.str = get_name(obj_h, prefer_full_name);
    auto it = node_renames.find(target_node.str);
    if (it != node_renames.end())
        target_node.str = it->second;
}

AstNodeBuilder UhdmAst::make_node(AST::AstNodeType type) const
{
    auto node = std::make_unique<AST::AstNode>(type);
    apply_location_from_current_obj(*node);
    return AstNodeBuilder(std::move(node));
};

AstNodeBuilder UhdmAst::make_named_node(AST::AstNodeType type, bool prefer_full_name) const
{
    auto node = std::make_unique<AST::AstNode>(type);
    apply_location_from_current_obj(*node);
    apply_name_from_current_obj(*node, prefer_full_name);
    return AstNodeBuilder(std::move(node));
};

AstNodeBuilder UhdmAst::make_ident(std::string id) const { return make_node(::Yosys::AST::AST_IDENTIFIER).str(std::move(id)); };

AstNodeBuilder UhdmAst::make_const(int32_t value, uint8_t width) const
{
    // Limited to width of the `value` argument.
    log_assert(width <= 32);
    return make_node(AST::AST_CONSTANT).value(value, true, width);
};

AstNodeBuilder UhdmAst::make_const(uint32_t value, uint8_t width) const
{
    // Limited to width of the `value` argument.
    log_assert(width <= 32);
    return make_node(AST::AST_CONSTANT).value(value, false, width);
};

AST::AstNode *UhdmAst::make_ast_node(AST::AstNodeType type, std::vector<AST::AstNode *> children, bool prefer_full_name)
{
    auto node = new AST::AstNode(type);
    apply_name_from_current_obj(*node, prefer_full_name);
    apply_location_from_current_obj(*node);
    node->children = children;
    return node;
}

AST::AstNode *UhdmAst::make_identifier(std::string name)
{
    auto *node = make_ast_node(AST::AST_IDENTIFIER);
    node->str = std::move(name);
    return node;
}

void UhdmAst::process_packed_array_typespec()
{
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    current_node = make_ast_node(AST::AST_WIRE);
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
    visit_one_to_one({vpiElemTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node && node->type == AST::AST_STRUCT) {
            auto str = current_node->str;
            // unnamed array of named (struct) array
            if (str.empty() && !node->str.empty())
                str = node->str;
            node->cloneInto(current_node);
            current_node->str = str;
            delete node;
        } else if (node) {
            if (!node->str.empty()) {
                AST::AstNode *const wiretype_node = make_named_node(AST::AST_WIRETYPE);
                wiretype_node->str = node->str;
                current_node->children.push_back(wiretype_node);
                current_node->is_custom_type = true;
                auto it = shared.param_types.find(wiretype_node->str);
                if (it == shared.param_types.end())
                    shared.param_types.insert(std::make_pair(wiretype_node->str, node));
                else
                    delete node;
            } else {
                delete node;
            }
        }
    });
    add_multirange_wire(current_node, std::move(packed_ranges), std::move(unpacked_ranges));
}

static void add_or_replace_child(AST::AstNode *parent, AST::AstNode *child)
{
    if (!child->str.empty()) {
        auto it = std::find_if(parent->children.begin(), parent->children.end(),
                               [child](AST::AstNode *existing_child) { return existing_child->str == child->str; });
        if (it != parent->children.end()) {
            // If port direction is already set, copy it to replaced child node
            if ((*it)->is_input || (*it)->is_output) {
                child->is_input = (*it)->is_input;
                child->is_output = (*it)->is_output;
                child->port_id = (*it)->port_id;
                if (child->type == AST::AST_MEMORY)
                    child->type = AST::AST_WIRE;
            }
            child->is_signed = child->is_signed || (*it)->is_signed;
            if (!(*it)->children.empty() && child->children.empty()) {
                // This is a bit ugly, but if the child we're replacing has children and
                // our node doesn't, we copy its children to not lose any information
                for (auto grandchild : (*it)->children) {
                    child->children.push_back(grandchild->clone());
                    if (child->type == AST::AST_WIRE && grandchild->type == AST::AST_WIRETYPE)
                        child->is_custom_type = true;
                }
            }
            if ((*it)->attributes.count(UhdmAst::packed_ranges()) && child->attributes.count(UhdmAst::packed_ranges())) {
                if ((!(*it)->attributes[UhdmAst::packed_ranges()]->children.empty() &&
                     child->attributes[UhdmAst::packed_ranges()]->children.empty())) {

                    delete_attribute(child, UhdmAst::packed_ranges());
                    child->attributes[UhdmAst::packed_ranges()] = (*it)->attributes[UhdmAst::packed_ranges()]->clone();
                }
            }
            if ((*it)->attributes.count(UhdmAst::unpacked_ranges()) && child->attributes.count(UhdmAst::unpacked_ranges())) {
                if ((!(*it)->attributes[UhdmAst::unpacked_ranges()]->children.empty() &&
                     child->attributes[UhdmAst::unpacked_ranges()]->children.empty())) {

                    delete_attribute(child, UhdmAst::unpacked_ranges());
                    child->attributes[UhdmAst::unpacked_ranges()] = (*it)->attributes[UhdmAst::unpacked_ranges()]->clone();
                }
            }
            // Surelog doesn't report correct sign value for param_assign nodes
            // and only default vpiParameter node have correct sign value, so
            // if we are overriding parameter, copy sign value from current node to the new node
            if (((*it)->type == AST::AST_PARAMETER || (*it)->type == AST::AST_LOCALPARAM) && child->children.size() && (*it)->children.size()) {
                child->children[0]->is_signed = (*it)->children[0]->is_signed;
            }
            delete *it;
            *it = child;
            return;
        }
        parent->children.push_back(child);
    } else if (child->type == AST::AST_INITIAL) {
        // Special case for initials
        // Ensure that there is only one AST_INITIAL in the design
        // And there is only one AST_BLOCK inside that initial
        // Copy nodes from child initial to parent initial
        auto initial_node_it =
          find_if(parent->children.begin(), parent->children.end(), [](AST::AstNode *node) { return (node->type == AST::AST_INITIAL); });
        if (initial_node_it != parent->children.end()) {
            AST::AstNode *initial_node = *initial_node_it;

            // simplify assumes that initial has a block under it
            // In case we don't have one (there were no statements under the initial), let's add it
            if (initial_node->children.empty()) {
                initial_node->children.push_back(new AST::AstNode(AST::AST_BLOCK));
            }

            log_assert(initial_node->children[0]->type == AST::AST_BLOCK);
            log_assert(!(child->children.empty()));
            log_assert(child->children[0]->type == AST::AST_BLOCK);

            AST::AstNode *block_node = initial_node->children[0];
            AST::AstNode *child_block_node = child->children[0];

            // Place the contents of child block node inside parent block
            for (auto child_block_child : child_block_node->children)
                block_node->children.push_back(child_block_child->clone());
            // Place the remaining contents of child initial node inside the parent initial
            for (auto initial_child = child->children.begin() + 1; initial_child != child->children.end(); ++initial_child) {
                initial_node->children.push_back((*initial_child)->clone());
            }
            delete child;
        } else {
            // Parent AST_INITIAL does not exist
            // Place child AST_INITIAL before AST_ALWAYS if found
            auto insert_it =
              find_if(parent->children.begin(), parent->children.end(), [](AST::AstNode *node) { return (node->type == AST::AST_ALWAYS); });
            parent->children.insert(insert_it, 1, child);
        }
    } else {
        parent->children.push_back(child);
    }
}

void UhdmAst::make_cell(vpiHandle obj_h, AST::AstNode *cell_node, AST::AstNode *type_node)
{
    if (cell_node->children.empty() || (!cell_node->children.empty() && cell_node->children[0]->type != AST::AST_CELLTYPE)) {
        auto typeNode = new AST::AstNode(AST::AST_CELLTYPE);
        typeNode->str = type_node->str;
        cell_node->children.insert(cell_node->children.begin(), typeNode);
    }
    // Add port connections as arguments
    vpiHandle port_itr = vpi_iterate(vpiPort, obj_h);
    while (vpiHandle port_h = vpi_scan(port_itr)) {
        std::string arg_name;
        if (auto s = vpi_get_str(vpiName, port_h)) {
            arg_name = s;
            sanitize_symbol_name(arg_name);
        }
        auto arg_node = new AST::AstNode(AST::AST_ARGUMENT);
        arg_node->str = arg_name;
        arg_node->filename = cell_node->filename;
        arg_node->location = cell_node->location;
        visit_one_to_one({vpiHighConn}, port_h, [&](AST::AstNode *node) {
            if (node) {
                if (node->type == AST::AST_PARAMETER || node->type == AST::AST_LOCALPARAM) {
                    node->type = AST::AST_IDENTIFIER;
                }
                arg_node->children.push_back(node);
            }
        });
        cell_node->children.push_back(arg_node);
        shared.report.mark_handled(port_h);
        vpi_release_handle(port_h);
    }
    vpi_release_handle(port_itr);
}

void UhdmAst::move_type_to_new_typedef(AST::AstNode *current_node, AST::AstNode *type_node)
{
    auto typedef_node = new AST::AstNode(AST::AST_TYPEDEF);
    typedef_node->location = type_node->location;
    typedef_node->filename = type_node->filename;
    typedef_node->str = strip_package_name(type_node->str);
    for (auto c : current_node->children) {
        if (c->str == typedef_node->str) {
            return;
        }
    }
    if (type_node->type == AST::AST_STRUCT) {
        type_node->str.clear();
        typedef_node->children.push_back(type_node);
        current_node->children.push_back(typedef_node);
    } else if (type_node->type == AST::AST_ENUM) {
        if (type_node->attributes.count("\\enum_base_type")) {
            auto base_type = type_node->attributes["\\enum_base_type"];
            auto wire_node = new AST::AstNode(AST::AST_WIRE);
            wire_node->is_reg = true;
            for (auto c : base_type->children) {
                std::string enum_item_str = "\\enum_value_";
                log_assert(!c->children.empty());
                log_assert(c->children[0]->type == AST::AST_CONSTANT);
                int width = 1;
                bool is_signed = c->children[0]->is_signed;
                if (c->children.size() == 2) {
                    width = c->children[1]->children[0]->integer + 1;
                }
                RTLIL::Const val = c->children[0]->bitsAsConst(width, is_signed);
                enum_item_str.append(val.as_string());
                wire_node->attributes[enum_item_str.c_str()] = AST::AstNode::mkconst_str(c->str);
            }
            typedef_node->children.push_back(wire_node);
            current_node->children.push_back(typedef_node);
            delete type_node;
        } else {
            type_node->str = "$enum" + std::to_string(shared.next_enum_id());
            std::vector<AST::AstNode *> packed_ranges;
            auto wire_node = new AST::AstNode(AST::AST_WIRE);
            wire_node->is_reg = true;
            wire_node->attributes["\\enum_type"] = AST::AstNode::mkconst_str(type_node->str);
            if (!type_node->children.empty() && type_node->children[0]->children.size() > 1) {
                packed_ranges.push_back(type_node->children[0]->children[1]->clone());
            } else {
                // Add default range
                packed_ranges.push_back(make_range(31, 0));
            }
            add_multirange_wire(wire_node, std::move(packed_ranges), {});
            typedef_node->children.push_back(wire_node);
            current_node->children.push_back(type_node);
            current_node->children.push_back(typedef_node);
        }
    } else {
        type_node->str.clear();
        typedef_node->children.push_back(type_node);
        current_node->children.push_back(typedef_node);
    }
}

AST::AstNode *UhdmAst::find_ancestor(const std::unordered_set<AST::AstNodeType> &types)
{
    auto searched_node = this;
    while (searched_node) {
        if (searched_node->current_node) {
            if (types.find(searched_node->current_node->type) != types.end()) {
                return searched_node->current_node;
            }
        }
        searched_node = searched_node->parent;
    }
    return nullptr;
}

void UhdmAst::process_design()
{
    current_node = make_ast_node(AST::AST_DESIGN);
    visit_one_to_many({UHDM::uhdmallInterfaces, UHDM::uhdmtopPackages, UHDM::uhdmallModules, UHDM::uhdmtopModules, vpiTaskFunc}, obj_h,
                      [&](AST::AstNode *node) {
                          if (node) {
                              shared.top_nodes[node->str] = node;
                          }
                      });
    visit_one_to_many({vpiParameter, vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
        if (get_attribute(node, attr_id::is_type_parameter)) {
            // Don't process type parameters.
            delete node;
            return;
        }
        add_or_replace_child(current_node, node);
    });
    visit_one_to_many({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
        if (node)
            move_type_to_new_typedef(current_node, node);
    });
    // Add top level typedefs and params to scope
    setup_current_scope(shared.top_nodes, current_node);
    for (auto pair : shared.top_nodes) {
        if (!pair.second)
            continue;
        if (pair.second->type == AST::AST_PACKAGE) {
            check_memories(pair.second);
            clear_current_scope();
            setup_current_scope(shared.top_nodes, pair.second);
            simplify_sv(pair.second, nullptr);
            clear_current_scope();
        }
    }
    setup_current_scope(shared.top_nodes, current_node);
    // Once we walked everything, unroll that as children of this node
    for (auto &pair : shared.top_nodes) {
        if (!pair.second)
            continue;
        if (!pair.second->get_bool_attribute(UhdmAst::partial())) {
            if (pair.second->type == AST::AST_PACKAGE)
                current_node->children.insert(current_node->children.begin(), pair.second);
            else {
                check_memories(pair.second);
                setup_current_scope(shared.top_nodes, pair.second);
                simplify_sv(pair.second, nullptr);
                clear_current_scope();
                current_node->children.push_back(pair.second);
            }
        } else {
            log_warning("Removing unelaborated module: %s from the design.\n", pair.second->str.c_str());
            // TODO: This should be properly erased from the module, but it seems that it's
            // needed to resolve scope
            delete pair.second;
            pair.second = nullptr;
        }
    }
}

void UhdmAst::simplify_parameter(AST::AstNode *parameter, AST::AstNode *module_node)
{
    setup_current_scope(shared.top_nodes, shared.current_top_node);
    visitEachDescendant(shared.current_top_node, [&](AST::AstNode *current_scope_node) {
        if (current_scope_node->type == AST::AST_TYPEDEF || current_scope_node->type == AST::AST_PARAMETER ||
            current_scope_node->type == AST::AST_LOCALPARAM) {
            AST_INTERNAL::current_scope[current_scope_node->str] = current_scope_node;
        }
    });
    if (module_node) {
        visitEachDescendant(module_node, [&](AST::AstNode *current_scope_node) {
            if (current_scope_node->type == AST::AST_TYPEDEF || current_scope_node->type == AST::AST_PARAMETER ||
                current_scope_node->type == AST::AST_LOCALPARAM) {
                AST_INTERNAL::current_scope[current_scope_node->str] = current_scope_node;
            }
        });
    }
    // first apply custom simplification step if needed
    simplify_sv(parameter, module_node);
    // workaround for yosys sometimes not simplifying parameters children
    // parameters can have 2 children:
    // first child should be parameter value
    // second child should be parameter range (optional)
    log_assert(!parameter->children.empty());
    simplify_sv(parameter->children[0], parameter);
    while (simplify(parameter->children[0], true, false, false, 1, -1, false, false)) {
    }
    // follow id2ast as yosys doesn't do it by default
    if (parameter->children[0]->id2ast) {
        simplify_sv(parameter->children[0]->id2ast, parameter);
        while (simplify(parameter->children[0]->id2ast, true, false, false, 1, -1, false, false)) {
        }
    }
    if (parameter->children.size() > 1) {
        simplify_sv(parameter->children[1], parameter);
        while (simplify(parameter->children[1], true, false, false, 1, -1, false, false)) {
        }
        if (parameter->children[1]->id2ast) {
            simplify_sv(parameter->children[1]->id2ast, parameter);
            while (simplify(parameter->children[1]->id2ast, true, false, false, 1, -1, false, false)) {
            }
        }
    }
    // then simplify parameter to AST_CONSTANT or AST_REALVALUE
    while (simplify(parameter, true, false, false, 1, -1, false, false)) {
    }
    clear_current_scope();
}

void UhdmAst::process_module()
{
    std::string type = vpi_get_str(vpiDefName, obj_h);
    std::string name = vpi_get_str(vpiName, obj_h) ? vpi_get_str(vpiName, obj_h) : type;
    bool is_module_instance = type != name;
    sanitize_symbol_name(type);
    sanitize_symbol_name(name);
    type = strip_package_name(type);
    name = strip_package_name(name);
    if (!is_module_instance) {
        if (shared.top_nodes.find(type) != shared.top_nodes.end()) {
            current_node = shared.top_nodes[type];
            shared.current_top_node = current_node;
            auto process_it = std::find_if(current_node->children.begin(), current_node->children.end(),
                                           [](auto node) { return node->type == AST::AST_INITIAL || node->type == AST::AST_ALWAYS; });
            auto children_after_process = std::vector<AST::AstNode *>(process_it, current_node->children.end());
            current_node->children.erase(process_it, current_node->children.end());
            auto old_top = shared.current_top_node;
            shared.current_top_node = current_node;
            visit_one_to_many({vpiModule, vpiInterface, vpiParameter, vpiParamAssign, vpiPort, vpiNet, vpiArrayNet, vpiTaskFunc, vpiGenScopeArray,
                               vpiContAssign, vpiVariables},
                              obj_h, [&](AST::AstNode *node) {
                                  if (node) {
                                      if (get_attribute(node, attr_id::is_type_parameter)) {
                                          // Don't process type parameters.
                                          delete node;
                                          return;
                                      }
                                      add_or_replace_child(current_node, node);
                                  }
                              });
            // Primitives will have the same names (like "and"), so we need to make sure we don't replace them
            visit_one_to_many({vpiPrimitive}, obj_h, [&](AST::AstNode *node) {
                if (node) {
                    current_node->children.push_back(node);
                }
            });
            shared.current_top_node = old_top;
            current_node->children.insert(current_node->children.end(), children_after_process.begin(), children_after_process.end());

            delete_attribute(current_node, UhdmAst::partial());
        } else {
            // processing nodes belonging to 'uhdmallModules'
            current_node = make_ast_node(AST::AST_MODULE);
            current_node->str = type;
            shared.top_nodes[current_node->str] = current_node;
            shared.current_top_node = current_node;
            current_node->attributes[UhdmAst::partial()] = AST::AstNode::mkconst_int(1, false, 1);
            visit_one_to_many({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
                if (node) {
                    move_type_to_new_typedef(current_node, node);
                }
            });
            visit_one_to_many({vpiModule, vpiParameter, vpiParamAssign, vpiNet, vpiArrayNet, vpiProcess}, obj_h, [&](AST::AstNode *node) {
                if (node) {
                    if (get_attribute(node, attr_id::is_type_parameter)) {
                        // Don't process type parameters.
                        delete node;
                        return;
                    }
                    if ((node->type == AST::AST_ASSIGN && node->children.size() < 2)) {
                        delete node;
                        return;
                    }
                    add_or_replace_child(current_node, node);
                }
            });
        }
    } else {
        // Not a top module, create instance
        current_node = make_ast_node(AST::AST_CELL);
        std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> parameters;

        auto parameter_typedefs = make_unique_resource<std::vector<AST::AstNode *>>();

        visit_one_to_many({vpiParameter}, obj_h, [&](AST::AstNode *node) {
            log_assert(node);
            AST::AstNode *attr = get_attribute(node, attr_id::is_type_parameter);

            if (!attr) {
                // Process type parameters only.
                delete node;
                return;
            }

            if (node->children.size() == 0) {
                log_assert(!attr->str.empty());
                // Anonymous types have no chidren, and store the parameter name in attr->str.
                parameters.push_back(std::make_pair(node->str, attr->str));
                delete node;
                return;
            }

            for (auto child : node->children) {
                if (child->type == AST::AST_TYPEDEF && !child->str.empty()) {
                    // process_type_parameter should have created a node with the parameter name
                    //   and a child with the name of the value assigned to the parameter.
                    parameters.push_back(std::make_pair(node->str, child->str));
                }

                if (child->type == AST::AST_TYPEDEF || child->type == AST::AST_ENUM) {
                    // Copy definition of the type provided as parameter.
                    parameter_typedefs->push_back(child->clone());
                }
            }
            delete node;
        });

        visit_one_to_many({vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
            if (node && node->type == AST::AST_PARAMETER) {
                log_assert(!node->children.empty());
                if (node->children[0]->type != AST::AST_CONSTANT) {
                    if (shared.top_nodes.count(type)) {
                        simplify_parameter(node, shared.top_nodes[type]);
                    } else {
                        simplify_parameter(node, nullptr);
                    }
                }
                log_assert(node->children[0]->type == AST::AST_CONSTANT || node->children[0]->type == AST::AST_REALVALUE);
                parameters.push_back(std::make_pair(node->str, node->children[0]->asParaConst()));
            }
            delete node;
        });
        // We need to rename module to prevent name collision with the same module, but with different parameters
        std::string module_name = !parameters.empty() ? AST::derived_module_name(type, parameters).c_str() : type;
        auto module_node = shared.top_nodes[module_name];
        // true, when Surelog don't have definition of module while parsing design
        // if so, we leaving module parameters to yosys and don't rename module
        // as it will be done by yosys
        bool isPrimitive = false;
        if (!module_node) {
            module_node = shared.top_nodes[type];
            if (!module_node) {
                module_node = new AST::AstNode(AST::AST_MODULE);
                module_node->str = type;
                module_node->attributes[UhdmAst::partial()] = AST::AstNode::mkconst_int(2, false, 1);
                module_node->attributes[ID::whitebox] = AST::AstNode::mkconst_int(1, false, 1);
            }
            isPrimitive = module_node->attributes.count(UhdmAst::partial()) && module_node->attributes[UhdmAst::partial()]->integer == 2;
            if (!parameters.empty() && !isPrimitive) {
                module_node = module_node->clone();
                module_node->str = module_name;
            }
        } else if (auto attribute = get_attribute(module_node, attr_id::is_elaborated_module); attribute && attribute->integer == 1) {
            // we already processed module with this parameters, just create cell node
            make_cell(obj_h, current_node, module_node);
            return;
        }
        shared.top_nodes[module_node->str] = module_node;
        visit_one_to_many({vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
            if (node) {
                if (node->children[0]->type != AST::AST_CONSTANT) {
                    if (shared.top_nodes[type]) {
                        simplify_parameter(node, module_node);
                        log_assert(node->children[0]->type == AST::AST_CONSTANT || node->children[0]->type == AST::AST_REALVALUE);
                    }
                }
                // if module is primitive
                // Surelog doesn't have definition of this module,
                // so we need to left setting of parameters to yosys
                if (isPrimitive) {
                    node->type = AST::AST_PARASET;
                    current_node->children.push_back(node);
                } else {
                    add_or_replace_child(module_node, node);
                }
            }
        });
        module_node->children.insert(std::end(module_node->children), std::begin(*parameter_typedefs), std::end(*parameter_typedefs));
        parameter_typedefs->clear();
        parameter_typedefs.reset();
        if (module_node->attributes.count(UhdmAst::partial())) {
            AST::AstNode *attr = module_node->attributes.at(UhdmAst::partial());
            if (attr->type == AST::AST_CONSTANT)
                if (attr->integer == 1) {
                    delete_attribute(module_node, UhdmAst::partial());
                }
        }
        auto typeNode = new AST::AstNode(AST::AST_CELLTYPE);
        typeNode->str = module_node->str;
        current_node->children.insert(current_node->children.begin(), typeNode);
        auto old_top = shared.current_top_node;
        shared.current_top_node = module_node;
        visit_one_to_many({vpiVariables, vpiNet, vpiArrayNet, vpiInterface, vpiModule, vpiPort, vpiGenScopeArray, vpiContAssign, vpiTaskFunc}, obj_h,
                          [&](AST::AstNode *node) {
                              if (node) {
                                  add_or_replace_child(module_node, node);
                              }
                          });
        make_cell(obj_h, current_node, module_node);
        shared.current_top_node = old_top;
        set_attribute(module_node, attr_id::is_elaborated_module, AST::AstNode::mkconst_int(1, true));
    }
}

void UhdmAst::process_struct_typespec()
{
    current_node = make_ast_node(AST::AST_STRUCT);
    visit_one_to_many({vpiTypespecMember}, obj_h, [&](AST::AstNode *node) {
        if (node->children.size() > 0 && node->children[0]->type == AST::AST_ENUM) {
            log_assert(node->children.size() == 1);
            log_assert(!node->children[0]->children.empty());
            log_assert(!node->children[0]->children[0]->children.empty());
            // TODO: add missing enum_type attribute
            AST::AstNode *range = nullptr;
            // check if single enum element is larger than 1 bit
            if (node->children[0]->children[0]->children.size() == 2) {
                range = node->children[0]->children[0]->children[1]->clone();
            } else {
                range = make_range(0, 0);
            }
            delete_children(node);
            node->children.push_back(range);
        }
        current_node->children.push_back(node);
    });
}

void UhdmAst::process_union_typespec()
{
    current_node = make_ast_node(AST::AST_UNION);
    visit_one_to_many({vpiTypespecMember}, obj_h, [&](AST::AstNode *node) {
        if (node->children.size() > 0 && node->children[0]->type == AST::AST_ENUM) {
            log_assert(node->children.size() == 1);
            log_assert(!node->children[0]->children.empty());
            log_assert(!node->children[0]->children[0]->children.empty());
            // TODO: add missing enum_type attribute
            AST::AstNode *range = nullptr;
            // check if single enum element is larger than 1 bit
            if (node->children[0]->children[0]->children.size() == 2) {
                range = node->children[0]->children[0]->children[1]->clone();
            } else {
                range = make_range(0, 0);
            }
            delete_children(node);
            node->children.push_back(range);
        }
        current_node->children.push_back(node);
    });
}

void UhdmAst::process_array_typespec()
{
    current_node = make_ast_node(AST::AST_WIRE);
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    visit_one_to_one({vpiElemTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node && node->type == AST::AST_STRUCT) {
            auto str = current_node->str;
            node->cloneInto(current_node);
            current_node->str = str;
            delete node;
        }
    });
    if (auto elemtypespec_h = vpi_handle(vpiElemTypespec, obj_h)) {
        visit_one_to_many({vpiRange}, elemtypespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
        vpi_release_handle(elemtypespec_h);
    }
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_typespec_member()
{
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    current_node = make_ast_node(AST::AST_STRUCT_ITEM);
    current_node->str = current_node->str.substr(1);
    vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h);
    int typespec_type = vpi_get(vpiType, typespec_h);
    const uhdm_handle *const handle = (const uhdm_handle *)typespec_h;
    const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
    switch (typespec_type) {
    case vpiBitTypespec:
    case vpiLogicTypespec: {
        current_node->is_logic = true;
        visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
        shared.report.mark_handled(typespec_h);
        break;
    }
    case vpiByteTypespec: {
        current_node->is_signed = vpi_get(vpiSigned, typespec_h);
        packed_ranges.push_back(make_range(7, 0));
        shared.report.mark_handled(typespec_h);
        break;
    }
    case vpiShortIntTypespec: {
        current_node->is_signed = vpi_get(vpiSigned, typespec_h);
        packed_ranges.push_back(make_range(15, 0));
        shared.report.mark_handled(typespec_h);
        break;
    }
    case vpiIntTypespec:
    case vpiIntegerTypespec: {
        current_node->is_signed = vpi_get(vpiSigned, typespec_h);
        packed_ranges.push_back(make_range(31, 0));
        shared.report.mark_handled(typespec_h);
        break;
    }
    case vpiTimeTypespec:
    case vpiLongIntTypespec: {
        current_node->is_signed = vpi_get(vpiSigned, typespec_h);
        packed_ranges.push_back(make_range(63, 0));
        shared.report.mark_handled(typespec_h);
        break;
    }
    case vpiStructTypespec:
    case vpiUnionTypespec:
    case vpiEnumTypespec: {
        visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
            if (typespec_type == vpiStructTypespec || typespec_type == vpiUnionTypespec) {
                auto str = current_node->str;
                node->cloneInto(current_node);
                current_node->str = str;
                delete node;
            } else if (typespec_type == vpiEnumTypespec) {
                current_node->children.push_back(node);
            } else {
                delete node;
            }
        });
        break;
    }
    case vpiPackedArrayTypespec:
        visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
            if (node && node->type == AST::AST_STRUCT) {
                auto str = current_node->str;
                if (node->attributes.count(UhdmAst::packed_ranges())) {
                    for (auto r : node->attributes[UhdmAst::packed_ranges()]->children) {
                        packed_ranges.push_back(r->clone());
                    }
                    std::reverse(packed_ranges.begin(), packed_ranges.end());
                    delete_attribute(node, UhdmAst::packed_ranges());
                }
                if (node->attributes.count(UhdmAst::unpacked_ranges())) {
                    for (auto r : node->attributes[UhdmAst::unpacked_ranges()]->children) {
                        unpacked_ranges.push_back(r->clone());
                    }
                    delete_attribute(node, UhdmAst::unpacked_ranges());
                }
                node->cloneInto(current_node);
                current_node->str = str;
                current_node->children.insert(current_node->children.end(), packed_ranges.begin(), packed_ranges.end());
                packed_ranges.clear();
                delete node;
            } else if (node) {
                auto str = current_node->str;
                if (node->attributes.count(UhdmAst::packed_ranges())) {
                    for (auto r : node->attributes[UhdmAst::packed_ranges()]->children) {
                        packed_ranges.push_back(r->clone());
                    }
                    std::reverse(packed_ranges.begin(), packed_ranges.end());
                    delete_attribute(node, UhdmAst::packed_ranges());
                }
                if (node->attributes.count(UhdmAst::unpacked_ranges())) {
                    for (auto r : node->attributes[UhdmAst::unpacked_ranges()]->children) {
                        unpacked_ranges.push_back(r->clone());
                    }
                    delete_attribute(node, UhdmAst::unpacked_ranges());
                }
                node->cloneInto(current_node);
                current_node->str = str;
                current_node->type = AST::AST_STRUCT_ITEM;
                delete node;
            }
        });
        break;
    case vpiVoidTypespec: {
        report_error("%.*s:%d: Void typespecs are currently unsupported", (int)object->VpiFile().length(), object->VpiFile().data(),
                     object->VpiLineNo());
        break;
    }
    case vpiClassTypespec: {
        report_error("%.*s:%d: Class typespecs are unsupported", (int)object->VpiFile().length(), object->VpiFile().data(), object->VpiLineNo());
        break;
    }
    default: {
        report_error("%.*s:%d: Encountered unhandled typespec in process_typespec_member: '%.*s' of type '%s'\n", (int)object->VpiFile().length(),
                     object->VpiFile().data(), object->VpiLineNo(), (int)object->VpiName().length(), object->VpiName().data(),
                     UHDM::VpiTypeName(typespec_h).c_str());
        break;
    }
    }
    vpi_release_handle(typespec_h);
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

static UHDM::expr *reduce_expression(const UHDM::any *expr, const UHDM::any *inst, const UHDM::any *pexpr)
{
    log_assert(expr);
    log_assert(inst);
    log_assert(pexpr);

    bool invalidvalue = false;
    UHDM::ExprEval eval;
    UHDM::expr *resolved_operation = eval.reduceExpr(expr, invalidvalue, inst, pexpr);
    if (invalidvalue) {
        log_file_warning(std::string(expr->VpiFile()), expr->VpiLineNo(), "Could not reduce expression.\n");
    }
    return resolved_operation;
}

void UhdmAst::process_enum_typespec()
{
    // BaseTypespec specifies underlying type of the enum.
    // The BaseTypespec has at most one explicit packed dimension (range).
    // When base type is not specified in SystemVerilog code, it is assumed to be an int.
    // Type of enum items (constants) is the same as the enum type.
    current_node = make_ast_node(AST::AST_ENUM);

    const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
    const auto *enum_object = (const UHDM::enum_typespec *)handle->object;
    const auto *typespec = enum_object->Base_typespec();

    if (current_node->str.empty()) {
        // anonymous typespec, check if not already created
        log_assert(shared.current_top_node);
        auto check_created_anonymous_enums = [enum_object, this](std::string top_module_name) -> bool {
            for (auto pair : shared.anonymous_enums[top_module_name]) {
                UHDM::AnySet visited;
                if (pair.first->Compare(enum_object, visited) == 0) {
                    // we already created typedef for this.
                    delete current_node;
                    current_node = make_node(AST::AST_WIRETYPE);
                    current_node->str = pair.second;
                    return true;
                }
            }
            return false;
        };
        std::string top_module_name = shared.current_top_node->str;
        if (check_created_anonymous_enums(top_module_name)) {
            return;
        }
        // in case of parametrized module, also check unparametrized top module
        // as we could add this enum there and then copy it to parametrized
        // version
        if (top_module_name.find("$paramod") != std::string::npos) {
            // possible names:
            // $paramod\module_name\PARAM=VAL
            // $paramod$81af6bf473845aee480c993b90a1ed0117ae9091\module_name
            top_module_name = top_module_name.substr(top_module_name.find("\\"));
            if (auto params = top_module_name.find("\\", 1 /* skip first \ */) != std::string::npos)
                top_module_name = top_module_name.substr(0, params);
        }
        if (check_created_anonymous_enums(top_module_name)) {
            return;
        }
    }

    if (typespec && typespec->UhdmType() == UHDM::uhdmlogic_typespec) {
        // If it's a logic_typespec, try to reduce expressions inside of it.
        // The `reduceExpr` function needs the whole context of the enum typespec
        //   so it's called here instead of `process_operation` or any other more specific function.

        const UHDM::logic_typespec *logic_typespec_obj = enum_object->Base_typespec()->Cast<const UHDM::logic_typespec *>();
        std::vector<UHDM::range *> ranges;
        // Check if ranges exist, as Ranges() returns a pointer to std::vector.
        if (logic_typespec_obj->Ranges()) {
            ranges = *(logic_typespec_obj->Ranges());
        }
        for (UHDM::range *range_obj : ranges) {
            // For each range, take both left and right and reduce them if they're of type uhdmoperation.
            const auto *leftrange_obj = range_obj->Left_expr();
            const auto *rightrange_obj = range_obj->Right_expr();
            log_assert(leftrange_obj);
            log_assert(rightrange_obj);

            if (leftrange_obj->UhdmType() == UHDM::uhdmoperation) {
                // Substitute the previous leftrange with the resolved operation result.
                range_obj->Left_expr(reduce_expression(leftrange_obj, enum_object->Instance() ? enum_object->Instance() : enum_object->VpiParent(),
                                                       enum_object->VpiParent()));
            }
            if (rightrange_obj->UhdmType() == UHDM::uhdmoperation) {
                // Substitute the previous rightrange with the resolved operation result.
                range_obj->Right_expr(reduce_expression(rightrange_obj, enum_object->Instance() ? enum_object->Instance() : enum_object->VpiParent(),
                                                        enum_object->VpiParent()));
            }
        }
    }

    bool has_base_type = false;
    visit_one_to_one({vpiBaseTypespec}, obj_h, [&](AST::AstNode *node) {
        has_base_type = true;
        current_node->children = std::move(node->children);
        current_node->attributes = std::move(node->attributes);
        current_node->is_signed = node->is_signed;
        current_node->is_logic = node->is_logic;
        delete node;
    });
    if (!has_base_type) {
        // Base typespec is `int` by default
        // TODO (mglb): This is almost the same code as in `process_int_typespec()`. Put common code in dedicated function.
        std::vector<AST::AstNode *> packed_ranges;
        packed_ranges.push_back(make_range(31, 0));
        add_multirange_wire(current_node, std::move(packed_ranges), {});
        current_node->is_signed = true;
    }
    // We have to restore node's range_* properties if there's no range.
    const auto range_left = current_node->range_left;
    const auto range_right = current_node->range_right;
    const auto range_valid = current_node->range_valid;
    // Create a range from the typespec just for the purpose of copying it to consts.
    convert_packed_unpacked_range(current_node);
    const auto range_it = std::find_if(current_node->children.cbegin(), current_node->children.cend(),
                                       [](const AST::AstNode *n) { return n->type == AST::AST_RANGE || n->type == AST::AST_MULTIRANGE; });
    const auto *const range = range_it != current_node->children.cend() ? *range_it : nullptr;
    if (range) {
        current_node->children.erase(range_it);
    } else {
        current_node->range_left = range_left;
        current_node->range_right = range_right;
        current_node->range_valid = range_valid;
    }

    visit_one_to_one({vpiTypedefAlias}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->attributes["\\enum_base_type"] = node;
        }
    });
    visit_one_to_many({vpiEnumConst}, obj_h, [&](AST::AstNode *node) {
        // Enum const must have the same type and ranges as the enum.
        node->is_logic = current_node->is_logic;
        node->is_signed = current_node->is_signed;
        if (range) {
            node->children.push_back(range->clone());
            node->range_valid = true;
        } else {
            node->range_left = range_left;
            node->range_right = range_right;
            node->range_valid = range_valid;
        }
        // IMPORTANT: invalidates `range_it`!
        current_node->children.push_back(node);
    });
    if (range) {
        delete range;
    }
    if (current_node->str.empty()) {
        // anonymous typespec
        std::string typedef_name = "$systemverilog_plugin$anonymous_enum" + std::to_string(shared.next_anonymous_enum_typedef_id());
        current_node->str = typedef_name;
        uhdmast_assert(shared.current_top_node != nullptr);
        move_type_to_new_typedef(shared.current_top_node, current_node);
        current_node = make_node(AST::AST_WIRETYPE);
        current_node->str = typedef_name;
        shared.anonymous_enums[shared.current_top_node->str][enum_object] = std::move(typedef_name);
    }
}

void UhdmAst::process_enum_const()
{
    current_node = make_ast_node(AST::AST_ENUM_ITEM);
    AST::AstNode *constant_node = process_value(obj_h);
    if (constant_node) {
        constant_node->filename = current_node->filename;
        constant_node->location = current_node->location;
        current_node->children.push_back(constant_node);
    }
}

void UhdmAst::process_custom_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node->str.empty()) {
            // anonymous typespec, move the children to variable
            current_node->type = node->type;
            copy_packed_unpacked_attribute(node, current_node);
            current_node->children = std::move(node->children);
        } else {
            auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
            wiretype_node->str = node->str;
            current_node->children.push_back(wiretype_node);
        }
        delete node;
    });
    auto type = vpi_get(vpiType, obj_h);
    if (type == vpiEnumVar || type == vpiStructVar || type == vpiUnionVar) {
        visit_default_expr(obj_h);
    }
    current_node->is_custom_type = true;
}

void UhdmAst::process_int_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    auto left_const = AST::AstNode::mkconst_int(31, true);
    auto right_const = AST::AstNode::mkconst_int(0, true);
    auto range = new AST::AstNode(AST::AST_RANGE, left_const, right_const);
    current_node->children.push_back(range);
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
    visit_default_expr(obj_h);
}

void UhdmAst::process_real_var()
{
    auto module_node = find_ancestor({AST::AST_MODULE});
    auto wire_node = make_ast_node(AST::AST_WIRE);
    auto left_const = AST::AstNode::mkconst_int(63, true);
    auto right_const = AST::AstNode::mkconst_int(0, true);
    auto range = new AST::AstNode(AST::AST_RANGE, left_const, right_const);
    wire_node->children.push_back(range);
    wire_node->is_signed = true;
    module_node->children.push_back(wire_node);
    current_node = make_ast_node(AST::AST_IDENTIFIER);
    visit_default_expr(obj_h);
}

void UhdmAst::process_array_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node->str.empty()) {
            // anonymous typespec, move the children to variable
            current_node->type = node->type;
            current_node->children = std::move(node->children);
        } else {
            auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
            wiretype_node->str = node->str;
            current_node->children.push_back(wiretype_node);
            current_node->is_custom_type = true;
        }
        delete node;
    });
    vpiHandle itr = vpi_iterate(vpi_get(vpiType, obj_h) == vpiArrayVar ? vpiReg : vpiElement, obj_h);
    while (vpiHandle reg_h = vpi_scan(itr)) {
        if (vpi_get(vpiType, reg_h) == vpiStructVar || vpi_get(vpiType, reg_h) == vpiEnumVar) {
            visit_one_to_one({vpiTypespec}, reg_h, [&](AST::AstNode *node) {
                if (node->str.empty()) {
                    // anonymous typespec, move the children to variable
                    current_node->type = node->type;
                    current_node->children = std::move(node->children);
                } else {
                    auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                    current_node->is_custom_type = true;
                }
                delete node;
            });
        } else if (vpi_get(vpiType, reg_h) == vpiLogicVar) {
            current_node->is_logic = true;
            visit_one_to_one({vpiTypespec}, reg_h, [&](AST::AstNode *node) {
                if (node->str.empty()) {
                    // anonymous typespec, move the children to variable
                    current_node->type = node->type;
                    current_node->children = std::move(node->children);
                } else {
                    auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                    current_node->is_custom_type = true;
                }
                delete node;
            });
            visit_one_to_many({vpiRange}, reg_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
        } else if (vpi_get(vpiType, reg_h) == vpiIntVar) {
            packed_ranges.push_back(make_range(31, 0));
            visit_default_expr(reg_h);
        }
        vpi_release_handle(reg_h);
    }
    vpi_release_handle(itr);
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    visit_default_expr(obj_h);
}

void UhdmAst::process_packed_array_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node->str.empty()) {
            // anonymous typespec, move the children to variable
            current_node->type = node->type;
            current_node->children = std::move(node->children);
        } else {
            auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
            wiretype_node->str = node->str;
            current_node->children.push_back(wiretype_node);
            current_node->is_custom_type = true;
        }
        delete node;
    });
    vpiHandle itr = vpi_iterate(vpi_get(vpiType, obj_h) == vpiArrayVar ? vpiReg : vpiElement, obj_h);
    while (vpiHandle reg_h = vpi_scan(itr)) {
        if (vpi_get(vpiType, reg_h) == vpiStructVar || vpi_get(vpiType, reg_h) == vpiEnumVar) {
            visit_one_to_one({vpiTypespec}, reg_h, [&](AST::AstNode *node) {
                if (node->str.empty()) {
                    // anonymous typespec, move the children to variable
                    current_node->type = node->type;
                    current_node->children = std::move(node->children);
                } else {
                    auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                    current_node->is_custom_type = true;
                }
                delete node;
            });
        } else if (vpi_get(vpiType, reg_h) == vpiLogicVar) {
            current_node->is_logic = true;
            visit_one_to_one({vpiTypespec}, reg_h, [&](AST::AstNode *node) {
                if (node->str.empty()) {
                    // anonymous typespec, move the children to variable
                    current_node->type = node->type;
                    current_node->children = std::move(node->children);
                } else {
                    auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                    current_node->is_custom_type = true;
                }
                delete node;
            });
            visit_one_to_many({vpiRange}, reg_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
        } else if (vpi_get(vpiType, reg_h) == vpiIntVar) {
            packed_ranges.push_back(make_range(31, 0));
            visit_default_expr(reg_h);
        }
        vpi_release_handle(reg_h);
    }
    vpi_release_handle(itr);
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    visit_default_expr(obj_h);
}

void UhdmAst::process_param_assign()
{
    current_node = make_ast_node(AST::AST_PARAMETER);
    visit_one_to_one({vpiLhs}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->type = node->type;
            current_node->str = node->str;
            // Here we need to copy any ranges that is already present in lhs,
            // but we want to skip actual value, as it is set in rhs
            for (auto *c : node->children) {
                if (c->type != AST::AST_CONSTANT) {
                    current_node->children.push_back(c->clone());
                }
            }
            delete_children(node);
            copy_packed_unpacked_attribute(node, current_node);
            current_node->is_custom_type = node->is_custom_type;
            auto it = shared.param_types.find(current_node->str);
            if (it == shared.param_types.end())
                shared.param_types[current_node->str] = shared.param_types[node->str];
            delete node;
        }
    });
    visit_one_to_one({vpiRhs}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->children.size() > 1 && (node->children[1]->type == AST::AST_PARAMETER || node->children[1]->type == AST::AST_LOCALPARAM)) {
                node->children[1]->type = AST::AST_IDENTIFIER;
            }
            current_node->children.insert(current_node->children.begin(), node);
        }
    });
}

void UhdmAst::process_cont_assign_var_init()
{
    current_node = make_ast_node(AST::AST_INITIAL);
    auto block_node = make_ast_node(AST::AST_BLOCK);
    auto assign_node = make_ast_node(AST::AST_ASSIGN_LE);
    block_node->children.push_back(assign_node);
    current_node->children.push_back(block_node);

    visit_one_to_one({vpiLhs, vpiRhs}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->type == AST::AST_WIRE || node->type == AST::AST_PARAMETER || node->type == AST::AST_LOCALPARAM) {
                assign_node->children.push_back(new AST::AstNode(AST::AST_IDENTIFIER));
                assign_node->children.back()->str = node->str;
                delete node;
            } else {
                assign_node->children.push_back(node);
            }
        }
    });
}

void UhdmAst::process_cont_assign_net()
{
    current_node = make_ast_node(AST::AST_ASSIGN);

    visit_one_to_one({vpiLhs, vpiRhs}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->type == AST::AST_WIRE || node->type == AST::AST_PARAMETER || node->type == AST::AST_LOCALPARAM) {
                current_node->children.push_back(new AST::AstNode(AST::AST_IDENTIFIER));
                current_node->children.back()->str = node->str;
            } else {
                current_node->children.push_back(node->clone());
            }
            delete node;
        }
    });
}

void UhdmAst::process_cont_assign()
{
    auto net_decl_assign = vpi_get(vpiNetDeclAssign, obj_h);
    vpiHandle node_lhs_h = vpi_handle(vpiLhs, obj_h);
    auto lhs_net_type = vpi_get(vpiNetType, node_lhs_h);
    vpi_release_handle(node_lhs_h);

    // Check if lhs is a subtype of a net
    bool isNet;
    if (lhs_net_type >= vpiWire && lhs_net_type <= vpiUwire)
        isNet = true;
    else
        // lhs is a variable
        isNet = false;
    if (net_decl_assign && !isNet)
        process_cont_assign_var_init();
    else
        process_cont_assign_net();
}

void UhdmAst::process_assignment(const UHDM::BaseClass *object)
{
    auto type = vpi_get(vpiBlocking, obj_h) == 1 ? AST::AST_ASSIGN_EQ : AST::AST_ASSIGN_LE;
    bool shift_unsigned = false;
    int op_type = vpi_get(vpiOpType, obj_h);
    AST::AstNodeType node_type;
    current_node = make_ast_node(type);

    visit_one_to_one({vpiLhs, vpiRhs}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            // fix node types for some assignments
            // yosys requires that declaration of variable
            // and assignment are separated
            switch (node->type) {
            case AST::AST_WIRE:
                // wires can be declarated inside initialization block of for block
                if (AST::AstNode *for_block = find_ancestor({AST::AST_BLOCK})) {
                    if (for_block->str.find("$fordecl_block") != std::string::npos)
                        break;
                }
                [[fallthrough]];
            case AST::AST_PARAMETER:
            case AST::AST_LOCALPARAM:
                node->type = AST::AST_IDENTIFIER;
                delete_children(node);
                delete_attribute(node, UhdmAst::packed_ranges());
                delete_attribute(node, UhdmAst::unpacked_ranges());
                break;
            default:
                break;
            };
            current_node->children.push_back(node);
        }
    });
    if (op_type && op_type != vpiAssignmentOp) {
        switch (op_type) {
        case vpiSubOp:
            node_type = AST::AST_SUB;
            break;
        case vpiDivOp:
            node_type = AST::AST_DIV;
            break;
        case vpiModOp:
            node_type = AST::AST_MOD;
            break;
        case vpiLShiftOp:
            node_type = AST::AST_SHIFT_LEFT;
            shift_unsigned = true;
            break;
        case vpiRShiftOp:
            node_type = AST::AST_SHIFT_RIGHT;
            shift_unsigned = true;
            break;
        case vpiAddOp:
            node_type = AST::AST_ADD;
            break;
        case vpiMultOp:
            node_type = AST::AST_MUL;
            break;
        case vpiBitAndOp:
            node_type = AST::AST_BIT_AND;
            break;
        case vpiBitOrOp:
            node_type = AST::AST_BIT_OR;
            break;
        case vpiBitXorOp:
            node_type = AST::AST_BIT_XOR;
            break;
        case vpiArithLShiftOp:
            node_type = AST::AST_SHIFT_SLEFT;
            shift_unsigned = true;
            break;
        case vpiArithRShiftOp:
            node_type = AST::AST_SHIFT_SRIGHT;
            shift_unsigned = true;
            break;
        default:
            delete current_node;
            current_node = nullptr;
            report_error("%.*s:%d: Encountered unhandled compound assignment with operation type %d\n", (int)object->VpiFile().length(),
                         object->VpiFile().data(), object->VpiLineNo(), op_type);
            return;
        }
        log_assert(current_node->children.size() == 2);
        auto child_node = new AST::AstNode(node_type, current_node->children[0]->clone(), current_node->children[1]);
        current_node->children[1] = child_node;
        if (shift_unsigned) {
            log_assert(current_node->children[1]->children.size() == 2);
            auto unsigned_node = new AST::AstNode(AST::AST_TO_UNSIGNED, current_node->children[1]->children[1]);
            current_node->children[1]->children[1] = unsigned_node;
        }
    }
    if (current_node->children.size() == 1 && current_node->children[0]->type == AST::AST_WIRE) {
        auto top_node = find_ancestor({AST::AST_MODULE});
        if (!top_node)
            return;
        top_node->children.push_back(std::move(current_node->children[0]));
        delete current_node;
        current_node = nullptr;
    }
}

void UhdmAst::process_packed_array_net()
{
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    current_node = make_ast_node(AST::AST_WIRE);
    visit_one_to_many({vpiElement}, obj_h, [&](AST::AstNode *node) {
        if (node && GetSize(node->children) == 1)
            current_node->children.push_back(node->children[0]->clone());
        current_node->is_custom_type = node->is_custom_type;
        delete node;
    });
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_array_net(const UHDM::BaseClass *object)
{
    current_node = make_ast_node(AST::AST_WIRE);
    vpiHandle itr = vpi_iterate(vpiNet, obj_h);
    std::vector<AST::AstNode *> packed_ranges;
    std::vector<AST::AstNode *> unpacked_ranges;
    while (vpiHandle net_h = vpi_scan(itr)) {
        auto net_type = vpi_get(vpiType, net_h);
        if (net_type == vpiLogicNet) {
            current_node->is_logic = true;
            current_node->is_signed = vpi_get(vpiSigned, net_h);
            vpiHandle typespec_h = vpi_handle(vpiTypespec, net_h);
            if (!typespec_h) {
                typespec_h = vpi_handle(vpiTypespec, obj_h);
            }
            if (typespec_h) {
                visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
                vpi_release_handle(typespec_h);
            } else {
                visit_one_to_many({vpiRange}, net_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
            }
            shared.report.mark_handled(net_h);
        } else if (net_type == vpiStructNet) {
            visit_one_to_one({vpiTypespec}, net_h, [&](AST::AstNode *node) {
                if (node->str.empty()) {
                    // anonymous typespec, move the children to variable
                    current_node->type = node->type;
                    current_node->children = std::move(node->children);
                } else {
                    auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                    current_node->is_custom_type = true;
                }
                delete node;
            });
        }
        vpi_release_handle(net_h);
    }
    vpi_release_handle(itr);
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_package()
{
    current_node = make_ast_node(AST::AST_PACKAGE);
    shared.current_top_node = current_node;
    visit_one_to_many({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            move_type_to_new_typedef(current_node, node);
        }
    });
    visit_one_to_many({vpiParameter, vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (get_attribute(node, attr_id::is_type_parameter)) {
                // Don't process type parameters.
                delete node;
                return;
            }
            node->str = strip_package_name(node->str);
            for (auto c : node->children) {
                c->str = strip_package_name(c->str);
            }
            add_or_replace_child(current_node, node);
        }
    });
    visit_one_to_many({vpiTaskFunc}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_interface()
{
    std::string type = vpi_get_str(vpiDefName, obj_h);
    std::string name = vpi_get_str(vpiName, obj_h) ? vpi_get_str(vpiName, obj_h) : type;
    sanitize_symbol_name(type);
    sanitize_symbol_name(name);
    AST::AstNode *elaboratedInterface;
    // Check if we have encountered this object before
    if (shared.top_nodes.find(type) != shared.top_nodes.end()) {
        // Was created before, fill missing
        elaboratedInterface = shared.top_nodes[type];
        visit_one_to_many({vpiPort, vpiVariables}, obj_h, [&](AST::AstNode *node) {
            if (node) {
                add_or_replace_child(elaboratedInterface, node);
            }
        });
    } else {
        // Encountered for the first time
        elaboratedInterface = new AST::AstNode(AST::AST_INTERFACE);
        elaboratedInterface->str = name;
        visit_one_to_many({vpiNet, vpiPort, vpiModport}, obj_h, [&](AST::AstNode *node) {
            if (node) {
                add_or_replace_child(elaboratedInterface, node);
            }
        });
    }
    shared.top_nodes[elaboratedInterface->str] = elaboratedInterface;
    if (name != type) {
        // Not a top module, create instance
        current_node = make_ast_node(AST::AST_CELL);
        make_cell(obj_h, current_node, elaboratedInterface);
    } else {
        current_node = elaboratedInterface;
    }
}

void UhdmAst::process_modport()
{
    current_node = make_ast_node(AST::AST_MODPORT);
    visit_one_to_many({vpiIODecl}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_io_decl()
{
    current_node = nullptr;
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *node) { current_node = node; });
    if (current_node == nullptr) {
        current_node = make_ast_node(AST::AST_MODPORTMEMBER);
        visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
    }
    std::reverse(unpacked_ranges.begin(), unpacked_ranges.end());

    visit_one_to_one({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (!node->str.empty()) {
                auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                wiretype_node->str = node->str;
                // wiretype needs to be 1st node (if port have also another range nodes)
                current_node->children.insert(current_node->children.begin(), wiretype_node);
                current_node->is_custom_type = true;
            } else {
                // anonymous typedef, just move children
                for (auto child : node->children) {
                    current_node->children.push_back(child->clone());
                }
                if (node->attributes.count(UhdmAst::packed_ranges())) {
                    for (auto r : node->attributes[UhdmAst::packed_ranges()]->children) {
                        packed_ranges.push_back(r->clone());
                    }
                }
                if (node->attributes.count(UhdmAst::unpacked_ranges())) {
                    for (auto r : node->attributes[UhdmAst::unpacked_ranges()]->children) {
                        unpacked_ranges.push_back(r->clone());
                    }
                }
                current_node->is_logic = node->is_logic;
                current_node->is_reg = node->is_reg;
            }
            current_node->is_signed = node->is_signed;
            delete node;
        }
    });
    if (const int n = vpi_get(vpiDirection, obj_h)) {
        if (n == vpiInput) {
            current_node->is_input = true;
        } else if (n == vpiOutput) {
            current_node->is_output = true;
        } else if (n == vpiInout) {
            current_node->is_input = true;
            current_node->is_output = true;
        }
    }
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges, false);
}

void UhdmAst::process_always()
{
    current_node = make_ast_node(AST::AST_ALWAYS);
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->type != AST::AST_BLOCK) {
                // Create implicit block.
                AST::AstNode *block = make_ast_node(AST::AST_BLOCK);
                // There are (at least) two cases where something could have been inserted into AST_ALWAYS node when `node` is not an AST_BLOCK:
                // - stream_op inserts a block.
                // - event_control inserts a non-block statement.
                // Move the block inserted by a stream_op into an implicit group. Everything else stays where it is.
                if (!current_node->children.empty() && current_node->children.back()->type == AST::AST_BLOCK) {
                    block->children.push_back(current_node->children.back());
                    current_node->children.pop_back();
                }
                block->children.push_back(node);
                current_node->children.push_back(block);
            } else {
                // Child is an explicit block.
                current_node->children.push_back(node);
            }
        } else {
            // TODO (mglb): This branch is probably unreachable? Is it possible to have empty `always`?
            // No children, so nothing should have been inserted into the always node during visitation.
            log_assert(current_node->children.empty());
            // Create implicit empty block.
            current_node->children.push_back(make_ast_node(AST::AST_BLOCK));
        }
    });
    switch (vpi_get(vpiAlwaysType, obj_h)) {
    case vpiAlwaysComb:
        current_node->attributes[ID::always_comb] = AST::AstNode::mkconst_int(1, false);
        break;
    case vpiAlwaysFF:
        current_node->attributes[ID::always_ff] = AST::AstNode::mkconst_int(1, false);
        break;
    case vpiAlwaysLatch:
        current_node->attributes[ID::always_latch] = AST::AstNode::mkconst_int(1, false);
        break;
    default:
        break;
    }
}

void UhdmAst::process_event_control(const UHDM::BaseClass *object)
{
    current_node = make_ast_node(AST::AST_BLOCK);
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            auto process_node = find_ancestor({AST::AST_ALWAYS});
            if (!process_node) {
                log_error("%.*s:%d: Currently supports only event control stmts inside 'always'\n", (int)object->VpiFile().length(),
                          object->VpiFile().data(), object->VpiLineNo());
            }
            process_node->children.push_back(node);
        }
        // is added inside vpiOperation
    });
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_initial()
{
    current_node = make_ast_node(AST::AST_INITIAL);
    // TODO (mglb): handler below is identical as in `process_always`. Extract it to avoid duplication.
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->type != AST::AST_BLOCK) {
                // Create an implicit block.
                AST::AstNode *block = make_ast_node(AST::AST_BLOCK);
                // There is (at least) one case where something could have been inserted into AST_INITIAL node when `node` is not an AST_BLOCK:
                // - stream_op inserts a block.
                // Move the block inserted by a stream_op into an implicit group.
                if (!current_node->children.empty() && current_node->children.back()->type == AST::AST_BLOCK) {
                    block->children.push_back(current_node->children.back());
                    current_node->children.pop_back();
                }
                block->children.push_back(node);
                current_node->children.push_back(block);
            } else {
                // Child is an explicit block.
                current_node->children.push_back(node);
            }
        } else {
            // TODO (mglb): This branch is probably unreachable? Is it possible to have empty `initial`?
            // No children, so nothing should have been inserted into the always node during visitation.
            log_assert(current_node->children.empty());
            // Create implicit empty block.
            current_node->children.push_back(make_ast_node(AST::AST_BLOCK));
        }
    });
}

void UhdmAst::process_begin(bool is_named)
{
    current_node = make_ast_node(AST::AST_BLOCK);
    if (!is_named) {
        // for unnamed block, reset block name
        current_node->str = "";
    }
    AST::AstNode *hierarchy_node = nullptr;
    static int unnamed_block_idx = 0;
    visit_one_to_many({vpiVariables}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (!is_named) {
                if (!hierarchy_node) {
                    // Create an implicit hierarchy scope
                    // simplify checks if sv_mode is set to true when wire is declared inside unnamed block
                    VERILOG_FRONTEND::sv_mode = true;
                    hierarchy_node = make_ast_node(AST::AST_BLOCK);
                    hierarchy_node->str = "$unnamed_block$" + std::to_string(unnamed_block_idx++);
                }
                hierarchy_node->children.push_back(node);
            } else {
                current_node->children.push_back(node);
            }
        }
    });
    visit_one_to_many({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if ((node->type == AST::AST_ASSIGN_EQ || node->type == AST::AST_ASSIGN_LE) && node->children.size() == 1) {
                auto func_node = find_ancestor({AST::AST_FUNCTION, AST::AST_TASK});
                if (!func_node) {
                    delete node;
                    return;
                }
                auto wire_node = new AST::AstNode(AST::AST_WIRE);
                wire_node->type = AST::AST_WIRE;
                wire_node->str = node->children[0]->str;
                func_node->children.push_back(wire_node);
                delete node;
            } else {
                if (hierarchy_node)
                    hierarchy_node->children.push_back(node);
                else
                    current_node->children.push_back(node);
            }
        }
    });
    if (hierarchy_node)
        current_node->children.push_back(hierarchy_node);
}

void UhdmAst::process_operation(const UHDM::BaseClass *object)
{
    auto operation = vpi_get(vpiOpType, obj_h);
    switch (operation) {
    case vpiStreamRLOp:
        process_stream_op();
        break;
    case vpiEventOrOp:
    case vpiListOp:
        process_list_op();
        break;
    case vpiCastOp:
        process_cast_op();
        break;
    case vpiInsideOp:
        process_inside_op();
        break;
    case vpiAssignmentPatternOp:
        process_assignment_pattern_op();
        break;
    case vpiWildEqOp:
    case vpiWildNeqOp: {
        report_error("%.*s:%d: Wildcard operators are not supported yet\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                     object->VpiLineNo());
        break;
    }
    default: {
        current_node = make_ast_node(AST::AST_NONE);
        visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
            if (node) {
                current_node->children.push_back(node);
            }
        });
        switch (operation) {
        case vpiMinusOp:
            current_node->type = AST::AST_NEG;
            break;
        case vpiPlusOp:
            current_node->type = AST::AST_POS;
            break;
        case vpiPosedgeOp:
            current_node->type = AST::AST_POSEDGE;
            break;
        case vpiNegedgeOp:
            current_node->type = AST::AST_NEGEDGE;
            break;
        case vpiUnaryAndOp:
            current_node->type = AST::AST_REDUCE_AND;
            break;
        case vpiUnaryOrOp:
            current_node->type = AST::AST_REDUCE_OR;
            break;
        case vpiUnaryXorOp:
            current_node->type = AST::AST_REDUCE_XOR;
            break;
        case vpiUnaryXNorOp:
            current_node->type = AST::AST_REDUCE_XNOR;
            break;
        case vpiUnaryNandOp: {
            auto not_node = new AST::AstNode(AST::AST_NONE, current_node);
            if (current_node->children.size() == 2) {
                current_node->type = AST::AST_BIT_AND;
                not_node->type = AST::AST_BIT_NOT;
            } else {
                current_node->type = AST::AST_REDUCE_AND;
                not_node->type = AST::AST_LOGIC_NOT;
            }
            current_node = not_node;
            break;
        }
        case vpiUnaryNorOp: {
            auto not_node = new AST::AstNode(AST::AST_NONE, current_node);
            if (current_node->children.size() == 2) {
                current_node->type = AST::AST_BIT_OR;
                not_node->type = AST::AST_BIT_NOT;
            } else {
                current_node->type = AST::AST_REDUCE_OR;
                not_node->type = AST::AST_LOGIC_NOT;
            }
            current_node = not_node;
            break;
        }
        case vpiBitNegOp:
            current_node->type = AST::AST_BIT_NOT;
            break;
        case vpiBitAndOp:
            current_node->type = AST::AST_BIT_AND;
            break;
        case vpiBitOrOp:
            current_node->type = AST::AST_BIT_OR;
            break;
        case vpiBitXorOp:
            current_node->type = AST::AST_BIT_XOR;
            break;
        case vpiBitXnorOp:
            current_node->type = AST::AST_BIT_XNOR;
            break;
        case vpiLShiftOp: {
            current_node->type = AST::AST_SHIFT_LEFT;
            log_assert(current_node->children.size() == 2);
            auto unsigned_node = new AST::AstNode(AST::AST_TO_UNSIGNED, current_node->children[1]);
            current_node->children[1] = unsigned_node;
            break;
        }
        case vpiRShiftOp: {
            current_node->type = AST::AST_SHIFT_RIGHT;
            log_assert(current_node->children.size() == 2);
            auto unsigned_node = new AST::AstNode(AST::AST_TO_UNSIGNED, current_node->children[1]);
            current_node->children[1] = unsigned_node;
            break;
        }
        case vpiNotOp:
            current_node->type = AST::AST_LOGIC_NOT;
            break;
        case vpiLogAndOp:
            current_node->type = AST::AST_LOGIC_AND;
            break;
        case vpiLogOrOp:
            current_node->type = AST::AST_LOGIC_OR;
            break;
        case vpiEqOp:
            current_node->type = AST::AST_EQ;
            break;
        case vpiNeqOp:
            current_node->type = AST::AST_NE;
            break;
        case vpiCaseEqOp:
            current_node->type = AST::AST_EQX;
            break;
        case vpiCaseNeqOp:
            current_node->type = AST::AST_NEX;
            break;
        case vpiGtOp:
            current_node->type = AST::AST_GT;
            break;
        case vpiGeOp:
            current_node->type = AST::AST_GE;
            break;
        case vpiLtOp:
            current_node->type = AST::AST_LT;
            break;
        case vpiLeOp:
            current_node->type = AST::AST_LE;
            break;
        case vpiSubOp:
            current_node->type = AST::AST_SUB;
            if (!current_node->children.empty() && current_node->children[0]->type == AST::AST_LOCALPARAM) {
                current_node->children[0]->type = AST::AST_IDENTIFIER;
            }
            break;
        case vpiAddOp:
            current_node->type = AST::AST_ADD;
            break;
        case vpiMultOp:
            current_node->type = AST::AST_MUL;
            break;
        case vpiDivOp:
            current_node->type = AST::AST_DIV;
            break;
        case vpiModOp:
            current_node->type = AST::AST_MOD;
            break;
        case vpiArithLShiftOp: {
            current_node->type = AST::AST_SHIFT_SLEFT;
            log_assert(current_node->children.size() == 2);
            auto unsigned_node = new AST::AstNode(AST::AST_TO_UNSIGNED, current_node->children[1]);
            current_node->children[1] = unsigned_node;
            break;
        }
        case vpiArithRShiftOp: {
            current_node->type = AST::AST_SHIFT_SRIGHT;
            log_assert(current_node->children.size() == 2);
            auto unsigned_node = new AST::AstNode(AST::AST_TO_UNSIGNED, current_node->children[1]);
            current_node->children[1] = unsigned_node;
            break;
        }
        case vpiPowerOp:
            current_node->type = AST::AST_POW;
            break;
        case vpiPostIncOp: {
            // TODO: Make this an actual post-increment op (currently it's a pre-increment)
            log_warning("%.*s:%d: Post-incrementation operations are handled as pre-incrementation.\n", (int)object->VpiFile().length(),
                        object->VpiFile().data(), object->VpiLineNo());
            [[fallthrough]];
        }
        case vpiPreIncOp: {
            current_node->type = AST::AST_ASSIGN_EQ;
            auto id = current_node->children[0]->clone();
            auto add_node = new AST::AstNode(AST::AST_ADD, id, AST::AstNode::mkconst_int(1, true));
            add_node->filename = current_node->filename;
            add_node->location = current_node->location;
            current_node->children.push_back(add_node);
            break;
        }
        case vpiPostDecOp: {
            // TODO: Make this an actual post-decrement op (currently it's a pre-decrement)
            log_warning("%.*s:%d: Post-decrementation operations are handled as pre-decrementation.\n", (int)object->VpiFile().length(),
                        object->VpiFile().data(), object->VpiLineNo());
            [[fallthrough]];
        }
        case vpiPreDecOp: {
            current_node->type = AST::AST_ASSIGN_EQ;
            auto id = current_node->children[0]->clone();
            auto add_node = new AST::AstNode(AST::AST_SUB, id, AST::AstNode::mkconst_int(1, true));
            add_node->filename = current_node->filename;
            add_node->location = current_node->location;
            current_node->children.push_back(add_node);
            break;
        }
        case vpiConditionOp:
            current_node->type = AST::AST_TERNARY;
            break;
        case vpiConcatOp: {
            current_node->type = AST::AST_CONCAT;
            std::reverse(current_node->children.begin(), current_node->children.end());
            break;
        }
        case vpiMultiConcatOp:
        case vpiMultiAssignmentPatternOp:
            current_node->type = AST::AST_REPLICATE;
            break;
        case vpiAssignmentOp:
            current_node->type = AST::AST_ASSIGN_EQ;
            break;
        case vpiStreamLROp: {
            auto concat_node = current_node->children.back();
            current_node->children.pop_back();
            delete current_node;
            current_node = concat_node;
            break;
        }
        case vpiNullOp: {
            delete current_node;
            current_node = nullptr;
            break;
        }
        case vpiMinTypMaxOp: {
            // ignore min and max and set only typ
            log_assert(current_node->children.size() == 3);
            auto tmp = current_node->children[1]->clone();
            delete current_node;
            current_node = tmp;
            break;
        }
        default: {
            delete current_node;
            current_node = nullptr;
            report_error("%.*s:%d: Encountered unhandled operation type %d\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                         object->VpiLineNo(), operation);
        }
        }
    }
    }
}

void UhdmAst::process_stream_op()
{
    // Closest ancestor where new statements can be inserted.
    AST::AstNode *stmt_list_node = find_ancestor({
      AST::AST_MODULE,
      AST::AST_PACKAGE,
      AST::AST_BLOCK,
      AST::AST_INITIAL,
      AST::AST_ALWAYS,
      AST::AST_FUNCTION,
    });
    uhdmast_assert(stmt_list_node != nullptr);

    // Detect whether we're in a procedural context. If yes, `for` loop will be generated, and `generate for` otherwise.
    const AST::AstNode *const proc_ctx = find_ancestor({AST::AST_ALWAYS, AST::AST_INITIAL, AST::AST_FUNCTION});
    const bool is_proc_ctx = (proc_ctx != nullptr);

    // Get a prefix for internal identifiers.
    const auto stream_op_id = shared.next_loop_id();
    const auto make_id_str = [stream_op_id](const char *suffix) {
        return std::string("$systemverilog_plugin$stream_op_") + std::to_string(stream_op_id) + "_" + suffix;
    };

    if (is_proc_ctx) {
        // Put logic inside a sub-block to avoid issues with declarations not being at the beginning of a block.
        AST::AstNode *block = make_node(Yosys::AST::AST_BLOCK).str(make_id_str("impl"));
        stmt_list_node->children.push_back(block);
        stmt_list_node = block;
    }

    // TODO (mglb): Only concat expression's size factors are supported as a slice size. Add support for other slice sizes as well.
    AST::AstNode *slice_size_arg = nullptr;
    AST::AstNode *stream_concat_arg = nullptr;
    {
        std::vector<AST::AstNode *> operands;
        // Expected operands: [slice_size] stream_concatenation
        visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
            uhdmast_assert(node != nullptr);
            uhdmast_assert(operands.size() < 2);
            operands.push_back(node);
        });
        uhdmast_assert(operands.size() > 0);

        if (operands.size() == 2) {
            slice_size_arg = operands.at(0);
            // SV spec says slice_size can be a constant or a type. However, Surelog converts type to its width, so we always expect a const.
            uhdmast_assert(slice_size_arg->type == AST::AST_CONSTANT);
        } else {
            slice_size_arg = make_const(1u);
        }
        stream_concat_arg = operands.back();
    }

    AST::AstNode *const stream_concat_width_lp = //
      (make_node(AST::AST_LOCALPARAM).str(make_id_str("width")))({
        (make_node(AST::AST_FCALL).str("\\$bits"))({
          (stream_concat_arg->clone()),
        }),
        (make_range(31, 0, true)),
      });

    // TODO (mglb): src_wire and dst_wire should probably take argument signedness and logicness into account.
    AST::AstNode *const src_wire = //
      (make_node(AST::AST_WIRE).str(make_id_str("src")).is_reg(is_proc_ctx))({
        (make_node(AST::AST_RANGE))({
          (make_const(0)),
          (make_node(AST::AST_SUB))({
            (make_ident(stream_concat_width_lp->str)),
            (make_const(1)),
          }),
        }),
      });

    AST::AstNode *const dst_wire = //
      (make_node(AST::AST_WIRE).str(make_id_str("dst")).is_reg(is_proc_ctx))({
        (make_node(AST::AST_RANGE))({
          (make_node(AST::AST_SUB))({
            (make_ident(stream_concat_width_lp->str)),
            (make_const(1)),
          }),
          (make_const(0)),
        }),
      });

    AST::AstNode *const assign_stream_concat_to_src_wire = //
      (make_node(is_proc_ctx ? AST::AST_ASSIGN_EQ : AST::AST_ASSIGN))({
        (make_ident(src_wire->str)),
        (stream_concat_arg),
      });

    AST::AstNode *const loop_counter = //
      (make_node(is_proc_ctx ? AST::AST_WIRE : AST::AST_GENVAR).str(make_id_str("counter")).is_reg(true))({
        (make_range(31, 0, true)),
      });

    AST::AstNode *const for_loop = //
      (make_node(is_proc_ctx ? AST::AST_FOR : AST::AST_GENFOR))({
        // init statement
        (make_node(AST::AST_ASSIGN_EQ))({
          (make_ident(loop_counter->str)),
          (make_const(0)),
        }),
        // condition
        (make_node(AST::AST_LT))({
          (make_ident(loop_counter->str)),
          (make_ident(stream_concat_width_lp->str)),
        }),
        // iteration expression
        (make_node(AST::AST_ASSIGN_EQ))({
          (make_ident(loop_counter->str)),
          (make_node(Yosys::AST::AST_ADD))({
            (make_ident(loop_counter->str)),
            (slice_size_arg->clone()),
          }),
        }),
        // loop body
        (make_node(is_proc_ctx ? AST::AST_BLOCK : AST::AST_GENBLOCK).str(make_id_str("loop_body")))({
          (make_node(is_proc_ctx ? AST::AST_ASSIGN_EQ : AST::AST_ASSIGN))({
            (make_ident(dst_wire->str))({
              (make_node(AST::AST_RANGE))({
                (make_node(Yosys::AST::AST_SUB))({
                  (make_node(Yosys::AST::AST_ADD))({
                    (make_node(Yosys::AST::AST_SELFSZ))({
                      (make_ident(loop_counter->str)),
                    }),
                    (slice_size_arg->clone()),
                  }),
                  (make_const(1)),
                }),
                (make_node(Yosys::AST::AST_ADD))({
                  (make_node(Yosys::AST::AST_SELFSZ))({
                    (make_ident(loop_counter->str)),
                  }),
                  (make_const(0)),
                }),
              }),
            }),
            (make_ident(src_wire->str))({
              (make_node(AST::AST_RANGE))({
                (make_node(Yosys::AST::AST_SUB))({
                  (make_node(Yosys::AST::AST_ADD))({
                    (make_node(Yosys::AST::AST_SELFSZ))({
                      (make_ident(loop_counter->str)),
                    }),
                    (slice_size_arg),
                  }),
                  (make_const(1)),
                }),
                (make_node(Yosys::AST::AST_ADD))({
                  (make_node(Yosys::AST::AST_SELFSZ))({
                    (make_ident(loop_counter->str)),
                  }),
                  (make_const(0)),
                }),
              }),
            }),
          }),
        }),
      });

    stmt_list_node->children.insert(stmt_list_node->children.end(), {
                                                                      stream_concat_width_lp,
                                                                      src_wire,
                                                                      dst_wire,
                                                                      assign_stream_concat_to_src_wire,
                                                                      loop_counter,
                                                                      for_loop,
                                                                    });

    current_node = make_ident(is_proc_ctx ? (stmt_list_node->str + '.' + dst_wire->str) : dst_wire->str);
}

void UhdmAst::process_list_op()
{
    // Add all operands as children of process node
    if (auto parent_node = find_ancestor({AST::AST_ALWAYS, AST::AST_COND})) {
        visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
            // add directly to process/cond node
            if (node) {
                parent_node->children.push_back(node);
            }
        });
    } else {
        log_error("Unhandled list op, couldn't find parent node.");
    }
    // Do not create a node
    shared.report.mark_handled(obj_h);
}

void UhdmAst::process_cast_op()
{
    current_node = make_ast_node(AST::AST_NONE);
    visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
        node->cloneInto(current_node);
        delete node;
    });
    vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h);
    shared.report.mark_handled(typespec_h);
    vpi_release_handle(typespec_h);
}

void UhdmAst::process_inside_op()
{
    current_node = make_ast_node(AST::AST_EQ);
    AST::AstNode *lhs = nullptr;
    visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
        if (!lhs) {
            lhs = node;
        }
        if (current_node->children.size() < 2) {
            current_node->children.push_back(node);
        } else {
            auto or_node = new AST::AstNode(AST::AST_LOGIC_OR);
            or_node->filename = current_node->filename;
            or_node->location = current_node->location;
            auto eq_node = new AST::AstNode(AST::AST_EQ);
            eq_node->filename = current_node->filename;
            eq_node->location = current_node->location;
            or_node->children.push_back(current_node);
            or_node->children.push_back(eq_node);
            eq_node->children.push_back(lhs->clone());
            eq_node->children.push_back(node);
            current_node = or_node;
        }
    });
}

void UhdmAst::process_assignment_pattern_op()
{
    current_node = make_ast_node(AST::AST_CONCAT);
    if (auto param_node = find_ancestor({AST::AST_PARAMETER, AST::AST_LOCALPARAM})) {
        std::map<size_t, AST::AstNode *> ordered_children;
        visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
            if (node->type == AST::AST_ASSIGN || node->type == AST::AST_ASSIGN_EQ || node->type == AST::AST_ASSIGN_LE) {
                // Get the name of the parameter or it's child, to which the pattern is assigned.
                std::string key;
                if (!node->children.empty() && !node->children[0]->children.empty() &&
                    node->children[0]->children[0]->type == static_cast<AST::AstNodeType>(AST::Extended::AST_DOT)) {
                    key = node->children[0]->children[0]->str;
                } else if (!node->children.empty()) {
                    key = node->children[0]->str;
                } else {
                    log_file_error(node->filename, node->location.first_line, "Couldn't find `key` in assignment pattern.\n");
                }
                auto param_type = shared.param_types[param_node->str];
                if (!param_type) {
                    log_error("Couldn't find parameter type for node: %s\n", param_node->str.c_str());
                }
                // Place the child node holding the value assigned in the pattern, in the right order,
                // so the overall value of the param_node is correct.
                size_t pos =
                  std::find_if(param_type->children.begin(), param_type->children.end(), [key](AST::AstNode *child) { return child->str == key; }) -
                  param_type->children.begin();
                ordered_children.insert(std::make_pair(pos, node->children[1]->clone()));
                delete node;
            } else {
                current_node->children.push_back(node);
            }
        });
        for (auto p : ordered_children) {
            current_node->children.push_back(p.second);
        }
        std::reverse(current_node->children.begin(), current_node->children.end());
        return;
    }
    auto assign_node = find_ancestor({AST::AST_ASSIGN, AST::AST_ASSIGN_EQ, AST::AST_ASSIGN_LE});

    auto proc_node =
      find_ancestor({AST::AST_BLOCK, AST::AST_GENBLOCK, AST::AST_ALWAYS, AST::AST_INITIAL, AST::AST_MODULE, AST::AST_PACKAGE, AST::AST_CELL});
    if (proc_node && proc_node->type == AST::AST_CELL && shared.top_nodes.count(proc_node->children[0]->str)) {
        proc_node = shared.top_nodes[proc_node->children[0]->str];
    }
    std::vector<AST::AstNode *> assignments;
    visit_one_to_many({vpiOperand}, obj_h, [&](AST::AstNode *node) {
        if (node->type == AST::AST_ASSIGN || node->type == AST::AST_ASSIGN_EQ || node->type == AST::AST_ASSIGN_LE) {
            assignments.push_back(node);
        } else {
            current_node->children.push_back(node);
        }
    });
    std::reverse(current_node->children.begin(), current_node->children.end());
    if (!assignments.empty()) {
        if (current_node->children.empty()) {
            delete assign_node->children[0];
            assign_node->children[0] = assignments[0]->children[0];
            delete current_node;
            current_node = assignments[0]->children[1];
            assignments[0]->children.clear();
            delete assignments[0];
            proc_node->children.insert(proc_node->children.end(), assignments.begin() + 1, assignments.end());
        } else {
            proc_node->children.insert(proc_node->children.end(), assignments.begin(), assignments.end());
        }
    }
}

void UhdmAst::process_bit_select()
{
    current_node = make_ast_node(AST::AST_IDENTIFIER);
    visit_one_to_one({vpiIndex}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(make_node(AST::AST_RANGE)({node})); });
}

void UhdmAst::process_part_select()
{
    current_node = make_ast_node(AST::AST_IDENTIFIER);
    AST::AstNode *range_node = make_node(AST::AST_RANGE);
    visit_one_to_one({vpiLeftRange, vpiRightRange}, obj_h, [&](AST::AstNode *node) { range_node->children.push_back(node); });
    current_node->children.push_back(range_node);
}

void UhdmAst::process_indexed_part_select()
{
    current_node = make_ast_node(AST::AST_IDENTIFIER);
    // TODO: check if there are other types, for now only handle 1 and 2 (+: and -:)
    auto indexed_part_select_type = vpi_get(vpiIndexedPartSelectType, obj_h) == 1 ? AST::AST_ADD : AST::AST_SUB;
    AST::AstNode *range_node = make_node(AST::AST_RANGE);
    visit_one_to_one({vpiBaseExpr}, obj_h, [&](AST::AstNode *node) { range_node->children.push_back(node); });
    visit_one_to_one({vpiWidthExpr}, obj_h, [&](AST::AstNode *node) {
        AST::AstNode *right_range_node = make_node(indexed_part_select_type);
        right_range_node->children.push_back(range_node->children[0]->clone());
        right_range_node->children.push_back(node);
        AST::AstNode *sub = make_node(indexed_part_select_type == AST::AST_ADD ? AST::AST_SUB : AST::AST_ADD);
        sub->children.push_back(right_range_node);
        sub->children.push_back(AST::AstNode::mkconst_int(1, false, 1));
        range_node->children.push_back(sub);
    });
    if (indexed_part_select_type == AST::AST_ADD) {
        std::reverse(range_node->children.begin(), range_node->children.end());
    }
    current_node->children.push_back(range_node);
}

void UhdmAst::process_if_else()
{
    current_node = make_ast_node(AST::AST_CASE);
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) {
        if (!node) {
            log_error("Couldn't find node in if stmt. This can happend if unsupported '$value$plusargs' function is used inside if.\n");
        }
        auto reduce_node = new AST::AstNode(AST::AST_REDUCE_BOOL, node);
        current_node->children.push_back(reduce_node);
    });
    // If true:
    auto *condition = new AST::AstNode(AST::AST_COND);
    auto *constant = AST::AstNode::mkconst_int(1, false, 1);
    condition->children.push_back(constant);
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        auto *statements = new AST::AstNode(AST::AST_BLOCK);
        if (node)
            statements->children.push_back(node);
        condition->children.push_back(statements);
    });
    current_node->children.push_back(condition);
    // Else:
    if (vpi_get(vpiType, obj_h) == vpiIfElse) {
        auto *condition = new AST::AstNode(AST::AST_COND);
        auto *elseBlock = new AST::AstNode(AST::AST_DEFAULT);
        condition->children.push_back(elseBlock);
        visit_one_to_one({vpiElseStmt}, obj_h, [&](AST::AstNode *node) {
            auto *statements = new AST::AstNode(AST::AST_BLOCK);
            if (node)
                statements->children.push_back(node);
            condition->children.push_back(statements);
        });
        current_node->children.push_back(condition);
    }
}

void UhdmAst::process_for()
{
    current_node = make_ast_node(AST::AST_BLOCK);
    auto loop_id = shared.next_loop_id();
    current_node->str = "$fordecl_block" + std::to_string(loop_id);
    auto loop = make_ast_node(AST::AST_FOR);
    loop->str = "$loop" + std::to_string(loop_id);
    visit_one_to_many({vpiForInitStmt}, obj_h, [&](AST::AstNode *node) {
        if (node->type == AST::AST_ASSIGN_LE)
            node->type = AST::AST_ASSIGN_EQ;
        auto lhs = node->children[0];
        if (lhs->type == AST::AST_WIRE) {
            auto *wire = lhs->clone();
            wire->is_logic = true;
            current_node->children.push_back(wire);
            lhs->type = AST::AST_IDENTIFIER;
            lhs->is_signed = false;
            lhs->delete_children();
        }
        loop->children.push_back(node);
    });
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) { loop->children.push_back(node); });
    visit_one_to_many({vpiForIncStmt}, obj_h, [&](AST::AstNode *node) {
        if (node->type == AST::AST_ASSIGN_LE)
            node->type = AST::AST_ASSIGN_EQ;
        loop->children.push_back(node);
    });
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node->type != AST::AST_BLOCK) {
            auto *statements = make_ast_node(AST::AST_BLOCK);
            statements->str = current_node->str; // Needed in simplify step
            statements->children.push_back(node);
            loop->children.push_back(statements);
        } else {
            if (node->str == "") {
                node->str = loop->str;
            }
            loop->children.push_back(node);
        }
    });
    current_node->children.push_back(loop);
    transform_breaks_continues(loop, current_node);
}

void UhdmAst::process_gen_scope()
{
    current_node = make_ast_node(AST::AST_GENBLOCK);
    visit_one_to_many({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            move_type_to_new_typedef(current_node, node);
        }
    });

    visit_one_to_many(
      {vpiParameter, vpiParamAssign, vpiNet, vpiArrayNet, vpiVariables, vpiContAssign, vpiProcess, vpiModule, vpiGenScopeArray, vpiTaskFunc}, obj_h,
      [&](AST::AstNode *node) {
          if (node) {
              if (get_attribute(node, attr_id::is_type_parameter)) {
                  // Don't process type parameters.
                  delete node;
                  return;
              }
              add_or_replace_child(current_node, node);
          }
      });
}

void UhdmAst::process_case()
{
    current_node = make_ast_node(AST::AST_CASE);
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
    visit_one_to_many({vpiCaseItem}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
}

void UhdmAst::process_case_item()
{
    auto cond_type = AST::AST_COND;
    if (vpiHandle parent_h = vpi_handle(vpiParent, obj_h)) {
        switch (vpi_get(vpiCaseType, parent_h)) {
        case vpiCaseExact:
            cond_type = AST::AST_COND;
            break;
        case vpiCaseX:
            cond_type = AST::AST_CONDX;
            break;
        case vpiCaseZ:
            cond_type = AST::AST_CONDZ;
            break;
        default: {
            const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
            const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
            report_error("%.*s:%d: Unknown case type", (int)object->VpiFile().length(), object->VpiFile().data(), object->VpiLineNo());
        }
        }
        vpi_release_handle(parent_h);
    }
    current_node = make_ast_node(cond_type);
    vpiHandle itr = vpi_iterate(vpiExpr, obj_h);
    while (vpiHandle expr_h = vpi_scan(itr)) {
        // 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) {
            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
                // nodes already in `current_node`.
                // We should probably refactor this to return node instead.
                // For now, make sure this function doesn't return any nodes.
                log_assert(node == nullptr);
            });
            // 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 block = make_ast_node(AST::AST_BLOCK);
                block->children = std::move(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 + "  ");
            auto *node = uhdm_ast.process_object(expr_h);
            if (node) {
                current_node->children.push_back(node);
            }
        }
        vpi_release_handle(expr_h);
    }
    vpi_release_handle(itr);
    if (current_node->children.empty()) {
        current_node->children.push_back(new AST::AstNode(AST::AST_DEFAULT));
    }
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->type != AST::AST_BLOCK) {
                auto block_node = new AST::AstNode(AST::AST_BLOCK);
                block_node->children.push_back(node);
                node = block_node;
            }
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_range(const UHDM::BaseClass *object)
{
    current_node = make_ast_node(AST::AST_RANGE);
    visit_one_to_one({vpiLeftRange, vpiRightRange}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
    if (current_node->children.size() > 0) {
        if (current_node->children[0]->str == "unsized") {
            log_error("%.*s:%d: Currently not supported object of type 'unsized range'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                      object->VpiLineNo());
        }
    }
    if (current_node->children.size() > 1) {
        if (current_node->children[1]->str == "unsized") {
            log_error("%.*s:%d: Currently not supported object of type 'unsized range'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                      object->VpiLineNo());
        }
    }
}

void UhdmAst::process_return()
{
    current_node = make_ast_node(AST::AST_ASSIGN_EQ);
    auto func_node = find_ancestor({AST::AST_FUNCTION, AST::AST_TASK});
    if (!func_node->children.empty()) {
        auto lhs = new AST::AstNode(AST::AST_IDENTIFIER);
        lhs->str = func_node->children[0]->str;
        current_node->children.push_back(lhs);
    }
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
}

void UhdmAst::process_function()
{
    current_node = make_ast_node(vpi_get(vpiType, obj_h) == vpiFunction ? AST::AST_FUNCTION : AST::AST_TASK);
    visit_one_to_one({vpiReturn}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            auto net_type = vpi_get(vpiNetType, obj_h);
            node->is_reg = net_type == vpiReg;
            node->str = current_node->str;
            current_node->children.push_back(node);
        }
    });
    visit_one_to_many({vpiParameter, vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (get_attribute(node, attr_id::is_type_parameter)) {
                // Don't process type parameters.
                delete node;
                return;
            }
            add_or_replace_child(current_node, node);
        }
    });
    visit_one_to_many({vpiIODecl}, obj_h, [&](AST::AstNode *node) {
        node->type = AST::AST_WIRE;
        node->port_id = shared.next_port_id();
        current_node->children.push_back(node);
    });
    visit_one_to_many({vpiVariables}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_hier_path()
{
    current_node = make_ast_node(AST::AST_IDENTIFIER);
    current_node->str = "\\";
    AST::AstNode *top_node = nullptr;
    visit_one_to_many({vpiActual}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->str.find('[') != std::string::npos)
                node->str = node->str.substr(0, node->str.find('['));
            // for first node, just set correct string and move any children
            if (!top_node) {
                current_node->str += node->str.substr(1);
                current_node->children = std::move(node->children);
                node->children.clear();
                top_node = current_node;
                delete node;
            } else {
                if (node->type == AST::AST_IDENTIFIER) {
                    node->type = static_cast<AST::AstNodeType>(AST::Extended::AST_DOT);
                    top_node->children.push_back(node);
                    top_node = node;
                } else {
                    top_node->children.push_back(node->children[0]);
                    node->children.erase(node->children.begin());
                    delete node;
                }
            }
        }
    });
}

void UhdmAst::process_gen_scope_array()
{
    current_node = make_ast_node(AST::AST_GENBLOCK);
    visit_one_to_many({vpiGenScope}, obj_h, [&](AST::AstNode *genscope_node) {
        for (auto *child : genscope_node->children) {
            if (child->type == AST::AST_PARAMETER || child->type == AST::AST_LOCALPARAM) {
                auto param_str = child->str.substr(1);
                auto array_str = "[" + param_str + "]";
                visitEachDescendant(genscope_node, [&](AST::AstNode *node) {
                    auto pos = node->str.find(array_str);
                    if (pos != std::string::npos) {
                        node->type = AST::AST_PREFIX;
                        auto *param = new AST::AstNode(AST::AST_IDENTIFIER);
                        param->str = child->str;
                        node->children.push_back(param);
                        auto bracket = node->str.rfind(']');
                        if (bracket + 2 <= node->str.size()) {
                            auto *field = new AST::AstNode(AST::AST_IDENTIFIER);
                            field->str = "\\" + node->str.substr(bracket + 2);
                            node->children.push_back(field);
                        }
                        node->str = node->str.substr(0, node->str.find('['));
                    }
                });
            }
        }
        current_node->children.insert(current_node->children.end(), genscope_node->children.begin(), genscope_node->children.end());
        genscope_node->children.clear();
        delete genscope_node;
    });
}

void UhdmAst::process_tagged_pattern()
{
    auto assign_node = find_ancestor({AST::AST_ASSIGN, AST::AST_ASSIGN_EQ, AST::AST_ASSIGN_LE});
    auto assign_type = AST::AST_ASSIGN;
    AST::AstNode *lhs_node = nullptr;
    if (assign_node) {
        assign_type = assign_node->type;
        lhs_node = assign_node->children[0]->clone();
    } else {
        lhs_node = new AST::AstNode(AST::AST_IDENTIFIER);
        auto ancestor = find_ancestor({AST::AST_WIRE, AST::AST_MEMORY, AST::AST_PARAMETER, AST::AST_LOCALPARAM});
        if (!ancestor) {
            const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
            const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
            report_error("%.*s:%d: Couldn't find ancestor for tagged pattern!\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                         object->VpiLineNo());
        }
        lhs_node->str = ancestor->str;
    }
    current_node = new AST::AstNode(assign_type);
    current_node->children.push_back(lhs_node);
    auto typespec_h = vpi_handle(vpiTypespec, obj_h);
    if (vpi_get(vpiType, typespec_h) == vpiStringTypespec) {
        std::string field_name = vpi_get_str(vpiName, typespec_h);
        if (field_name != "default") { // TODO: better support of the default keyword
            auto field = new AST::AstNode(static_cast<AST::AstNodeType>(AST::Extended::AST_DOT));
            field->str = field_name;
            current_node->children[0]->children.push_back(field);
        }
    } else if (vpi_get(vpiType, typespec_h) == vpiIntegerTypespec) {
        s_vpi_value val;
        vpi_get_value(typespec_h, &val);
        auto range = new AST::AstNode(AST::AST_RANGE);
        auto index = AST::AstNode::mkconst_int(val.value.integer, false);
        range->children.push_back(index);
        current_node->children[0]->children.push_back(range);
    }
    vpi_release_handle(typespec_h);
    visit_one_to_one({vpiPattern}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
}

void UhdmAst::process_logic_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->is_logic = true;
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    // TODO: add const attribute, but it seems it is little more
    // then just setting boolean value
    // current_node->is_const = vpi_get(vpiConstantVariable, obj_h);
    visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node->str.empty()) {
            // anonymous typespec, move the children to variable
            current_node->type = node->type;
            current_node->children = std::move(node->children);
        } else {
            auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
            wiretype_node->str = node->str;
            current_node->children.push_back(wiretype_node);
            current_node->is_custom_type = true;
        }
        current_node->is_signed = node->is_signed;
        delete node;
    });
    // TODO: Handling below seems similar to other typespec accesses for range. Candidate for extraction to a function.
    if (auto typespec_h = vpi_handle(vpiTypespec, obj_h)) {
        visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
        vpi_release_handle(typespec_h);
    } else {
        visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
    }
    visit_default_expr(obj_h);
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_sys_func_call()
{
    current_node = make_ast_node(AST::AST_FCALL);

    std::string task_calls[] = {"\\$display", "\\$monitor", "\\$write", "\\$time", "\\$readmemh", "\\$readmemb", "\\$finish", "\\$stop"};

    if (current_node->str == "\\$signed") {
        current_node->type = AST::AST_TO_SIGNED;
    } else if (current_node->str == "\\$unsigned") {
        current_node->type = AST::AST_TO_UNSIGNED;
    } else if (std::find(std::begin(task_calls), std::end(task_calls), current_node->str) != std::end(task_calls)) {
        current_node->type = AST::AST_TCALL;
    }

    visit_one_to_many({vpiArgument}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });

    if (current_node->str == "\\$display" || current_node->str == "\\$write") {
        // According to standard, %h and %x mean the same, but %h is currently unsupported by mainline yosys
        std::string replaced_string = std::regex_replace(current_node->children[0]->str, std::regex("%[h|H]"), "%x");
        delete current_node->children[0];
        current_node->children[0] = AST::AstNode::mkconst_str(replaced_string);
    }

    std::string remove_backslash[] = {"\\$display", "\\$strobe",   "\\$write",    "\\$monitor", "\\$time",    "\\$finish",
                                      "\\$stop",    "\\$dumpfile", "\\$dumpvars", "\\$dumpon",  "\\$dumpoff", "\\$dumpall"};

    if (std::find(std::begin(remove_backslash), std::end(remove_backslash), current_node->str) != std::end(remove_backslash))
        current_node->str = current_node->str.substr(1);
}

void UhdmAst::process_tf_call(AST::AstNodeType type)
{
    current_node = make_ast_node(type);
    visit_one_to_many({vpiArgument}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (node->type == AST::AST_PARAMETER || node->type == AST::AST_LOCALPARAM) {
                node->type = AST::AST_IDENTIFIER;
                node->children.clear();
            }
            current_node->children.push_back(node);
        }
    });
    // Prefer fully qualified name of a function (prefixed with a scope).
    // This is important when a single function which has been imported from a package
    // calls another function that is not imported in the calling scope.
    if (vpiHandle function_h = vpi_handle(vpiFunction, obj_h)) {
        current_node->str = get_name(function_h, true);
        vpi_release_handle(function_h);
    }
}

void UhdmAst::process_immediate_assert()
{
    current_node = make_ast_node(AST::AST_ASSERT);
    visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *n) {
        if (n) {
            current_node->children.push_back(n);
        }
    });
}

void UhdmAst::process_logic_typespec()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->is_logic = true;
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    if (!current_node->str.empty() && current_node->str.find("::") == std::string::npos) {
        std::string package_name = "";
        if (vpiHandle instance_h = vpi_handle(vpiInstance, obj_h)) {
            if (vpi_get(vpiType, instance_h) == vpiPackage) {
                package_name = get_object_name(instance_h, {vpiDefName});
                current_node->str = package_name + "::" + current_node->str.substr(1);
            }
            vpi_release_handle(instance_h);
        }
    }
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
    if (packed_ranges.empty())
        packed_ranges.push_back(make_range(0, 0));
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_int_typespec()
{
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    current_node = make_ast_node(AST::AST_WIRE);
    packed_ranges.push_back(make_range(31, 0));
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_shortint_typespec()
{
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    current_node = make_ast_node(AST::AST_WIRE);
    packed_ranges.push_back(make_range(15, 0));
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_longint_typespec()
{
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    current_node = make_ast_node(AST::AST_WIRE);
    packed_ranges.push_back(make_range(63, 0));
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_byte_typespec()
{
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    current_node = make_ast_node(AST::AST_WIRE);
    packed_ranges.push_back(make_range(7, 0));
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_time_typespec()
{
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    current_node = make_ast_node(AST::AST_WIRE);
    packed_ranges.push_back(make_range(63, 0));
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
    current_node->is_signed = false;
}

void UhdmAst::process_string_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->is_string = true;
    // FIXME:
    // this is only basic support for strings,
    // currently yosys doesn't support dynamic resize of wire
    // based on string size
    // here we try to get size of string based on provided const string
    // if it is not available, we are setting size to explicite 64 bits
    visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *expr_node) {
        if (expr_node->type == AST::AST_CONSTANT) {
            auto left_const = AST::AstNode::mkconst_int(expr_node->range_left, true);
            auto right_const = AST::AstNode::mkconst_int(expr_node->range_right, true);
            auto range = make_ast_node(AST::AST_RANGE, {left_const, right_const});
            current_node->children.push_back(range);
        }
    });
    if (current_node->children.empty()) {
        auto left_const = AST::AstNode::mkconst_int(64, true);
        auto right_const = AST::AstNode::mkconst_int(0, true);
        auto range = make_ast_node(AST::AST_RANGE, {left_const, right_const});
        current_node->children.push_back(range);
    }
    visit_default_expr(obj_h);
}

void UhdmAst::process_string_typespec()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->is_string = true;
    // FIXME:
    // this is only basic support for strings,
    // currently yosys doesn't support dynamic resize of wire
    // based on string size
    // here, we are setting size to explicite 64 bits
    auto left_const = AST::AstNode::mkconst_int(64, true);
    auto right_const = AST::AstNode::mkconst_int(0, true);
    auto range = make_ast_node(AST::AST_RANGE, {left_const, right_const});
    current_node->children.push_back(range);
}

void UhdmAst::process_bit_typespec()
{
    current_node = make_ast_node(AST::AST_WIRE);
    visit_range(obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_repeat()
{
    auto loop_id = shared.next_loop_id();
    current_node = make_ast_node(AST::AST_BLOCK);
    current_node->str = "$repeatdecl_block" + std::to_string(loop_id);
    auto *loop = make_ast_node(AST::AST_REPEAT);
    loop->str = "$loop" + std::to_string(loop_id);
    current_node->children.push_back(loop);
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) { loop->children.push_back(node); });
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node->type != AST::AST_BLOCK) {
            node = new AST::AstNode(AST::AST_BLOCK, node);
        }
        if (node->str.empty()) {
            node->str = loop->str; // Needed in simplify step
        }
        loop->children.push_back(node);
    });
    transform_breaks_continues(loop, current_node);
}

void UhdmAst::process_var_select()
{
    current_node = make_ast_node(AST::AST_IDENTIFIER);
    visit_one_to_many({vpiIndex}, obj_h, [&](AST::AstNode *node) {
        if (node->str == current_node->str) {
            for (auto child : node->children) {
                current_node->children.push_back(child);
            }
            node->children.clear();
            delete node;
        } else {
            auto range_node = new AST::AstNode(AST::AST_RANGE);
            range_node->filename = current_node->filename;
            range_node->location = current_node->location;
            range_node->children.push_back(node);
            current_node->children.push_back(range_node);
        }
    });
}

void UhdmAst::process_port()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->port_id = shared.next_port_id();
    vpiHandle lowConn_h = vpi_handle(vpiLowConn, obj_h);
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    if (lowConn_h) {
        vpiHandle actual_h = vpi_handle(vpiActual, lowConn_h);
        auto actual_type = vpi_get(vpiType, actual_h);
        switch (actual_type) {
        case vpiModport: {
            vpiHandle iface_h = vpi_handle(vpiInterface, actual_h);
            if (iface_h) {
                std::string cellName, ifaceName;
                if (auto s = vpi_get_str(vpiName, actual_h)) {
                    cellName = s;
                    sanitize_symbol_name(cellName);
                }
                if (auto s = vpi_get_str(vpiDefName, iface_h)) {
                    ifaceName = s;
                    sanitize_symbol_name(ifaceName);
                }
                current_node->type = AST::AST_INTERFACEPORT;
                auto typeNode = new AST::AstNode(AST::AST_INTERFACEPORTTYPE);
                // Skip '\' in cellName
                typeNode->str = ifaceName + '.' + cellName.substr(1, cellName.length());
                current_node->children.push_back(typeNode);
                shared.report.mark_handled(actual_h);
                shared.report.mark_handled(iface_h);
                vpi_release_handle(iface_h);
            }
            break;
        }
        case vpiInterface: {
            auto typeNode = new AST::AstNode(AST::AST_INTERFACEPORTTYPE);
            if (auto s = vpi_get_str(vpiDefName, actual_h)) {
                typeNode->str = s;
                sanitize_symbol_name(typeNode->str);
            }
            current_node->type = AST::AST_INTERFACEPORT;
            current_node->children.push_back(typeNode);
            shared.report.mark_handled(actual_h);
            break;
        }
        case vpiLogicVar:
        case vpiLogicNet: {
            current_node->is_logic = true;
            current_node->is_signed = vpi_get(vpiSigned, actual_h);
            visit_one_to_many({vpiRange}, actual_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
            shared.report.mark_handled(actual_h);
            break;
        }
        case vpiPackedArrayVar:
            visit_one_to_many({vpiElement}, actual_h, [&](AST::AstNode *node) {
                if (node && GetSize(node->children) == 1) {
                    current_node->children.push_back(node->children[0]->clone());
                    if (node->children[0]->type == AST::AST_WIRETYPE) {
                        current_node->is_custom_type = true;
                    }
                }
                delete node;
            });
            visit_one_to_many({vpiRange}, actual_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
            shared.report.mark_handled(actual_h);
            break;
        case vpiPackedArrayNet:
            visit_one_to_many({vpiRange}, actual_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
            shared.report.mark_handled(actual_h);
            break;
        case vpiArrayVar:
            visit_one_to_many({vpiRange}, actual_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
            shared.report.mark_handled(actual_h);
            break;
        case vpiEnumNet:
        case vpiStructNet:
        case vpiArrayNet:
        case vpiStructVar:
        case vpiUnionVar:
        case vpiEnumVar:
        case vpiBitVar:
        case vpiByteVar:
        case vpiShortIntVar:
        case vpiLongIntVar:
        case vpiIntVar:
        case vpiIntegerVar:
            break;
        default: {
            const uhdm_handle *const handle = (const uhdm_handle *)actual_h;
            const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
            report_error("%.*s:%d: Encountered unhandled type in process_port: %s\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                         object->VpiLineNo(), UHDM::VpiTypeName(actual_h).c_str());
            break;
        }
        }
        shared.report.mark_handled(lowConn_h);
        vpi_release_handle(actual_h);
        vpi_release_handle(lowConn_h);
    }
    visit_one_to_one({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            if (current_node->children.empty() || current_node->children[0]->type != AST::AST_WIRETYPE) {
                if (!node->str.empty()) {
                    auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    // wiretype needs to be 1st node (if port have also another range nodes)
                    current_node->children.insert(current_node->children.begin(), wiretype_node);
                    current_node->is_custom_type = true;
                } else {
                    // anonymous typedef, just move children
                    current_node->children = std::move(node->children);
                }
            }
            current_node->is_signed = current_node->is_signed || node->is_signed;
            delete node;
        }
    });
    if (const int n = vpi_get(vpiDirection, obj_h)) {
        if (n == vpiInput) {
            current_node->is_input = true;
        } else if (n == vpiOutput) {
            current_node->is_output = true;
        } else if (n == vpiInout) {
            current_node->is_input = true;
            current_node->is_output = true;
        }
    }
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_net()
{
    current_node = make_ast_node(AST::AST_WIRE);
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    auto net_type = vpi_get(vpiNetType, obj_h);
    current_node->is_reg = net_type == vpiReg;
    current_node->is_output = net_type == vpiOutput;
    current_node->is_logic = !current_node->is_reg;
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
    visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
        if (node && !node->str.empty()) {
            auto wiretype_node = new AST::AstNode(AST::AST_WIRETYPE);
            wiretype_node->str = node->str;
            // wiretype needs to be 1st node
            current_node->children.insert(current_node->children.begin(), wiretype_node);
            current_node->is_custom_type = true;
        }
        delete node;
    });
    if (vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h)) {
        visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
        vpi_release_handle(typespec_h);
    }
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_parameter()
{
    auto type = vpi_get(vpiLocalParam, obj_h) == 1 ? AST::AST_LOCALPARAM : AST::AST_PARAMETER;
    current_node = make_ast_node(type, {}, true);
    std::vector<AST::AstNode *> packed_ranges;   // comes before wire name
    std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name
    visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
    vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h);
    if (typespec_h) {
        int typespec_type = vpi_get(vpiType, typespec_h);
        switch (typespec_type) {
        case vpiBitTypespec:
        case vpiLogicTypespec: {
            current_node->is_logic = true;
            visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
            shared.report.mark_handled(typespec_h);
            break;
        }
        case vpiByteTypespec: {
            packed_ranges.push_back(make_range(7, 0));
            shared.report.mark_handled(typespec_h);
            break;
        }
        case vpiEnumTypespec:
        case vpiRealTypespec:
        case vpiStringTypespec: {
            shared.report.mark_handled(typespec_h);
            break;
        }
        case vpiIntTypespec:
        case vpiIntegerTypespec: {
            visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
            if (packed_ranges.empty()) {
                packed_ranges.push_back(make_range(31, 0));
            }
            shared.report.mark_handled(typespec_h);
            break;
        }
        case vpiShortIntTypespec: {
            packed_ranges.push_back(make_range(15, 0));
            shared.report.mark_handled(typespec_h);
            break;
        }
        case vpiTimeTypespec:
        case vpiLongIntTypespec: {
            packed_ranges.push_back(make_range(63, 0));
            shared.report.mark_handled(typespec_h);
            break;
        }
        case vpiStructTypespec: {
            visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
                if (node && !node->str.empty()) {
                    auto wiretype_node = make_ast_node(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                }
                current_node->is_custom_type = true;
                auto it = shared.param_types.find(current_node->str);
                if (it == shared.param_types.end()) {
                    shared.param_types.insert(std::make_pair(current_node->str, node));
                } else {
                    delete node;
                }
            });
            break;
        }
        case vpiPackedArrayTypespec:
        case vpiArrayTypespec: {
            shared.report.mark_handled(typespec_h);
            visit_one_to_one({vpiElemTypespec}, typespec_h, [&](AST::AstNode *node) {
                if (!node->str.empty()) {
                    auto wiretype_node = make_ast_node(AST::AST_WIRETYPE);
                    wiretype_node->str = node->str;
                    current_node->children.push_back(wiretype_node);
                    current_node->is_custom_type = true;
                    auto it = shared.param_types.find(current_node->str);
                    if (it == shared.param_types.end())
                        shared.param_types.insert(std::make_pair(current_node->str, node->clone()));
                }
                if (node && node->attributes.count(UhdmAst::packed_ranges())) {
                    for (auto r : node->attributes[UhdmAst::packed_ranges()]->children) {
                        packed_ranges.push_back(r->clone());
                    }
                }
                delete node;
            });
            break;
        }
        default: {
            const uhdm_handle *const handle = (const uhdm_handle *)typespec_h;
            const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
            report_error("%.*s:%d: Encountered unhandled typespec in process_parameter: '%.*s' of type '%s'\n", (int)object->VpiFile().length(),
                         object->VpiFile().data(), object->VpiLineNo(), (int)object->VpiName().length(), object->VpiName().data(),
                         UHDM::VpiTypeName(typespec_h).c_str());
            break;
        }
        }
        vpi_release_handle(typespec_h);
    }
    AST::AstNode *constant_node = process_value(obj_h);
    if (constant_node) {
        constant_node->filename = current_node->filename;
        constant_node->location = current_node->location;
        current_node->children.push_back(constant_node);
    }
    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
}

void UhdmAst::process_byte_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->children.push_back(make_range(7, 0));
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_long_int_var()
{
    current_node = make_ast_node(AST::AST_WIRE);
    current_node->children.push_back(make_range(63, 0));
    current_node->is_signed = vpi_get(vpiSigned, obj_h);
}

void UhdmAst::process_immediate_cover()
{
    current_node = make_ast_node(AST::AST_COVER);
    visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_immediate_assume()
{
    current_node = make_ast_node(AST::AST_ASSUME);
    visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *node) {
        if (node) {
            current_node->children.push_back(node);
        }
    });
}

void UhdmAst::process_while()
{
    auto loop_id = shared.next_loop_id();
    current_node = make_ast_node(AST::AST_BLOCK);
    current_node->str = "$whiledecl_block" + std::to_string(loop_id);
    auto *loop = make_ast_node(AST::AST_WHILE);
    loop->str = "$loop" + std::to_string(loop_id);
    current_node->children.push_back(loop);
    visit_one_to_one({vpiCondition}, obj_h, [&](AST::AstNode *node) { loop->children.push_back(node); });
    visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
        if (node->type != AST::AST_BLOCK) {
            node = make_ast_node(AST::AST_BLOCK, {node});
        }
        if (node->str.empty()) {
            node->str = loop->str; // Needed in simplify step
        }
        loop->children.push_back(node);
    });
    transform_breaks_continues(loop, current_node);
}

void UhdmAst::process_gate()
{
    current_node = make_ast_node(AST::AST_PRIMITIVE);
    switch (vpi_get(vpiPrimType, obj_h)) {
    case vpiAndPrim:
        current_node->str = "and";
        break;
    case vpiNandPrim:
        current_node->str = "nand";
        break;
    case vpiNorPrim:
        current_node->str = "nor";
        break;
    case vpiOrPrim:
        current_node->str = "or";
        break;
    case vpiXorPrim:
        current_node->str = "xor";
        break;
    case vpiXnorPrim:
        current_node->str = "xnor";
        break;
    case vpiBufPrim:
        current_node->str = "buf";
        break;
    case vpiNotPrim:
        current_node->str = "not";
        break;
    default:
        log_file_error(current_node->filename, current_node->location.first_line, "Encountered unhandled gate type: %s", current_node->str.c_str());
        break;
    }
    visit_one_to_many({vpiPrimTerm}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
}

void UhdmAst::process_primterm()
{
    current_node = make_ast_node(AST::AST_ARGUMENT);
    visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
}

void UhdmAst::process_unsupported_stmt(const UHDM::BaseClass *object, bool is_error)
{
    const auto log_func = is_error ? log_error : log_warning;
    std::string prefix = object->VpiLineNo() ? (std::string(object->VpiFile()) + ":" + std::to_string(object->VpiLineNo()) + ": ") : "";
    log_func("%sCurrently not supported object of type '%s'\n", prefix.c_str(), UHDM::VpiTypeName(obj_h).c_str());
}

void UhdmAst::process_type_parameter()
{
    current_node = make_ast_node(AST::AST_PARAMETER);

    // Use an attribute to distinguish "type parameters" from other parameters
    set_attribute(current_node, attr_id::is_type_parameter, AST::AstNode::mkconst_int(1, false, 1));
    std::string renamed_enum;

    visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
        if (!node)
            return;

        if (node->type == AST::AST_WIRE && node->str.empty()) {
            // anonymous type
            get_attribute(current_node, attr_id::is_type_parameter)->str = "anonymous_parameter" + std::to_string(shared.next_anonymous_type_id());
            delete node;
            return;
        }

        if (node->type == AST::AST_ENUM) {
            // Enum typedefs are composed of AST_ENUM and AST_TYPEDEF where the enum shall be renamed,
            // so that the original name used in code is assigned to the AST_TYPEDEF node,
            // and a mangled name is assigned to the AST_ENUM node.
            renamed_enum = node->str + "$enum" + std::to_string(shared.next_enum_id());
        }

        current_node->children.push_back(node->clone());

        // The child stores information about the type assigned to the parameter
        //   this information will be used to rename the module

        // find the typedef for `node` in the upper scope and copy it to .children of the AST_PARAMETER node
        // if unable to find the typedef, continue without error as this could be a globally available type

        if (shared.current_top_node) {
            for (auto child : shared.current_top_node->children) {
                // name of the type we're looking for
                if (child->str == node->str && child->type == AST::AST_TYPEDEF) {
                    current_node->children.push_back(child->clone());
                    break;
                }
            }
        }
        delete node;
    });

    if (!renamed_enum.empty()) {
        for (auto child : current_node->children) {
            if (child->type == AST::AST_TYPEDEF) {
                log_assert(child->children.size() > 0);
                set_attribute(child->children[0], ID::enum_type, AST::AstNode::mkconst_str(renamed_enum));
            }
            if (child->type == AST::AST_ENUM) {
                child->str = renamed_enum;
                // Names of enum variants need to be unique even accross Enums, otherwise Yosys fails.
                for (auto grandchild : child->children) {
                    grandchild->str = renamed_enum + "." + grandchild->str;
                }
            }
        }
    }
}

AST::AstNode *UhdmAst::process_object(vpiHandle obj_handle)
{
    obj_h = obj_handle;
    const unsigned object_type = vpi_get(vpiType, obj_h);
    const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
    const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
    for (auto *obj : shared.nonSynthesizableObjects) {
        if (!object->Compare(obj)) {
            log_warning("%.*s:%d: Skipping non-synthesizable object of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                        object->VpiLineNo(), UHDM::VpiTypeName(obj_h).c_str());
            return nullptr;
        }
    }

    if (shared.debug_flag) {
        std::cout << indent << "Object '" << object->VpiName() << "' of type '" << UHDM::VpiTypeName(obj_h) << '\'' << std::endl;
    }

    switch (object_type) {
    case vpiDesign:
        process_design();
        break;
    case vpiParameter:
        process_parameter();
        break;
    case vpiPort:
        process_port();
        break;
    case vpiModule:
        process_module();
        break;
    case vpiStructTypespec:
        process_struct_typespec();
        break;
    case vpiUnionTypespec:
        process_union_typespec();
        break;
    case vpiPackedArrayTypespec:
        process_packed_array_typespec();
        break;
    case vpiArrayTypespec:
        process_array_typespec();
        break;
    case vpiTypespecMember:
        process_typespec_member();
        break;
    case vpiEnumTypespec:
        process_enum_typespec();
        break;
    case vpiEnumConst:
        process_enum_const();
        break;
    case vpiEnumVar:
    case vpiEnumNet:
    case vpiStructVar:
    case vpiStructNet:
    case vpiUnionVar:
        process_custom_var();
        break;
    case vpiShortIntVar:
    case vpiIntVar:
    case vpiIntegerVar:
        process_int_var();
        break;
    case vpiShortRealVar:
    case vpiRealVar:
        process_real_var();
        break;
    case vpiPackedArrayVar:
        process_packed_array_var();
        break;
    case vpiArrayVar:
        process_array_var();
        break;
    case vpiParamAssign:
        process_param_assign();
        break;
    case vpiContAssign:
        process_cont_assign();
        break;
    case vpiAssignStmt:
    case vpiAssignment:
        process_assignment(object);
        break;
    case vpiInterfaceTypespec:
    case vpiRefVar:
    case vpiRefObj:
        current_node = make_ast_node(AST::AST_IDENTIFIER);
        break;
    case vpiNet:
        process_net();
        break;
    case vpiArrayNet:
        process_array_net(object);
        break;
    case vpiPackedArrayNet:
        process_packed_array_net();
        break;
    case vpiPackage:
        process_package();
        break;
    case vpiInterface:
        process_interface();
        break;
    case vpiModport:
        process_modport();
        break;
    case vpiIODecl:
        process_io_decl();
        break;
    case vpiAlways:
        process_always();
        break;
    case vpiEventControl:
        process_event_control(object);
        break;
    case vpiInitial:
        process_initial();
        break;
    case vpiFinal:
        process_unsupported_stmt(object, false);
        break;
    case vpiNamedBegin:
        process_begin(true);
        break;
    case vpiBegin:
        process_begin(false);
        break;
    case vpiCondition:
    case vpiOperation:
        process_operation(object);
        break;
    case vpiTaggedPattern:
        process_tagged_pattern();
        break;
    case vpiBitSelect:
        process_bit_select();
        break;
    case vpiPartSelect:
        process_part_select();
        break;
    case vpiIndexedPartSelect:
        process_indexed_part_select();
        break;
    case vpiVarSelect:
        process_var_select();
        break;
    case vpiIf:
    case vpiIfElse:
        process_if_else();
        break;
    case vpiFor:
        process_for();
        break;
    case vpiBreak:
        // Will be resolved later by loop processor
        current_node = make_ast_node(static_cast<AST::AstNodeType>(AST::Extended::AST_BREAK));
        break;
    case vpiContinue:
        // Will be resolved later by loop processor
        current_node = make_ast_node(static_cast<AST::AstNodeType>(AST::Extended::AST_CONTINUE));
        break;
    case vpiGenScopeArray:
        process_gen_scope_array();
        break;
    case vpiGenScope:
        process_gen_scope();
        break;
    case vpiCase:
        process_case();
        break;
    case vpiCaseItem:
        process_case_item();
        break;
    case vpiConstant:
        current_node = process_value(obj_h);
        break;
    case vpiRange:
        process_range(object);
        break;
    case vpiReturn:
        process_return();
        break;
    case vpiFunction:
    case vpiTask:
        process_function();
        break;
    case vpiBitVar:
    case vpiLogicVar:
        process_logic_var();
        break;
    case vpiSysFuncCall:
        process_sys_func_call();
        break;
    case vpiFuncCall:
        process_tf_call(AST::AST_FCALL);
        break;
    case vpiTaskCall:
        process_tf_call(AST::AST_TCALL);
        break;
    case vpiImmediateAssert:
        if (!shared.no_assert)
            process_immediate_assert();
        break;
    case vpiAssert:
        if (!shared.no_assert)
            process_unsupported_stmt(object);
        break;
    case vpiHierPath:
        process_hier_path();
        break;
    case UHDM::uhdmimport_typespec:
        break;
    case vpiLogicTypespec:
        process_logic_typespec();
        break;
    case vpiIntTypespec:
    case vpiIntegerTypespec:
        process_int_typespec();
        break;
    case vpiShortIntTypespec:
        process_shortint_typespec();
        break;
    case vpiLongIntTypespec:
        process_longint_typespec();
        break;
    case vpiTimeTypespec:
        process_time_typespec();
        break;
    case vpiBitTypespec:
        process_bit_typespec();
        break;
    case vpiByteTypespec:
        process_byte_typespec();
        break;
    case vpiStringVar:
        process_string_var();
        break;
    case vpiStringTypespec:
        process_string_typespec();
        break;
    case vpiRepeat:
        process_repeat();
        break;
    case vpiByteVar:
        process_byte_var();
        break;
    case vpiLongIntVar:
        process_long_int_var();
        break;
    case vpiImmediateCover:
        process_immediate_cover();
        break;
    case vpiImmediateAssume:
        process_immediate_assume();
        break;
    case vpiAssume:
        process_unsupported_stmt(object);
        break;
    case vpiWhile:
        process_while();
        break;
    case vpiGate:
        process_gate();
        break;
    case vpiPrimTerm:
        process_primterm();
        break;
    case vpiClockingBlock:
        process_unsupported_stmt(object);
        break;
    case vpiTypeParameter:
        process_type_parameter();
        break;
    case vpiProgram:
    default:
        report_error("%.*s:%d: Encountered unhandled object '%.*s' of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
                     object->VpiLineNo(), (int)object->VpiName().length(), object->VpiName().data(), UHDM::VpiTypeName(obj_h).c_str());
        break;
    }

    // Check if we initialized the node in switch-case
    if (current_node) {
        if (current_node->type != AST::AST_NONE) {
            shared.report.mark_handled(object);
            return current_node;
        }
    }
    return nullptr;
}

AST::AstNode *UhdmAst::visit_designs(const std::vector<vpiHandle> &designs)
{
    attr_id_init();

    current_node = new AST::AstNode(AST::AST_DESIGN);
    for (auto design : designs) {
        UhdmAst ast(this, shared, indent);
        auto *processed_design_node = ast.process_object(design);
        // Flatten multiple designs into one
        current_node->children = std::move(processed_design_node->children);
        delete processed_design_node;
    }

    for (auto &[name, node] : shared.param_types) {
        delete node;
    }
    shared.param_types.clear();

    // Remove all internal attributes from the AST.
    visitEachDescendant(current_node, delete_internal_attributes);

    attr_id_cleanup();

    return current_node;
}

void UhdmAst::report_error(const char *format, ...) const
{
    va_list args;
    va_start(args, format);
    if (shared.stop_on_error) {
        logv_error(format, args);
    } else {
        logv_warning(format, args);
    }
}

} // namespace systemverilog_plugin
