How to get full hierarchy ID path

From Verific Design Automation FAQ
Jump to: navigation, search

Note that this code sample requires "Hierarchy Tree" feature.

C++ code:

#include "VerificSystem.h"
#include "veri_file.h"
#include "VeriModuleItem.h"
#include "VeriModule.h"
#include "VeriId.h"
#include "VeriExpression.h"

#include "hier_tree.h"
#include "HierTreeNode.h"
#include "HierId.h"

#include <iostream>

using namespace Verific ;
using namespace std ;

void PrintHierIdPath(HierTreeNode *tree_node, HierId *hier_id)
{
    if (!tree_node || !hier_id) return ;
    std::cerr << "HierId " << hier_id->GetVeriNameRef()->GetPrettyPrintedString()
        << " full path nodes: ";

    Array *path_ids = hier_id->GetVeriElementIds(tree_node) ;
    Array* path = hier_id->FullPath() ;

    Map actual_vs_formal(POINTER_HASH) ;
    HierTreeNode *node ;
    VeriIdDef *interface_formal = 0 ;
    HierTreeNode *interface_actual = 0 ;
    VeriIdDef *id ;
    unsigned i ;
    // Here we assumed there can be only a single interface port in a hier path
    // This may not be true for a corner out of LRM case but still allowed by LRM
    // Eg: A interface has another interface instance inside it which has an interface
    // port. In that case we have to collect all such ports and iterate over it in the
    // next loop.
    FOREACH_ARRAY_ITEM(path_ids, i, id) {
        if (id && id->IsInterfacePort()) {
            interface_formal = id ;
            break ;
        }
    }

    FOREACH_ARRAY_ITEM(path, i, node) {
        if (!node) continue ;
        // Node actual {formal}
        std::cerr << " (" << node->GetName() ;
        if (interface_formal) { // find respective actual for this formal
            InterfaceInfo *id_info = node->GetParamValue(interface_formal) ;
            HierTreeNode *id_actual = (id_info) ? id_info->GetScope() : 0 ;
            if (id_actual) interface_actual = id_actual ;
        }
        if (interface_actual == node) std::cerr << " {" << interface_formal->GetName() << "}" ;
        std::cerr << ") " ;

        // Index actual {formal}
        if (node->IsArrayInstance() && i+1 < path->Size() && path->At(i+1)) {
            // works for single index
            std::cerr << " [" << node->GetChildName((HierTreeNode*)path->At(++i)) ;
            int pos = Strings::atoi(node->GetChildName((HierTreeNode*)path->At(i))) ;
            if (interface_formal) {
                VeriIdDef *actual = node->GetVeriInstanceId() ;
                // Obtain dimensions of formal and actual Ids
                VeriRange *actual_range = (actual) ? actual->GetDimensions() : 0 ;
                VeriRange *formal_range = interface_formal->GetDimensions() ;
                if (actual_range && formal_range) {
                    // Find corresponding index of formal wrt actual
                    int actual_left = actual_range->EvaluateLeft(0) ;
                    int offset = std::abs(actual_left - pos) ;
                    int formal_left = formal_range->EvaluateLeft(0) ;
                    int formal_right = formal_range->EvaluateRight(0) ;

                    if (formal_left > formal_right) std::cerr << " {" << (formal_left - offset) << "}" ;
                    else std::cerr << " {" << (formal_left + offset) << "}" ;
                }
            }
            std::cerr << "]";
        }
    }
    std::cerr<<std::endl;
}

void TraverseAndCollect(HierTreeNode *node, Array *instance_nodes, Array *path_name_stack)
{
    if (!node || !instance_nodes || !path_name_stack) return ;
    if (node->GetClassId() == ID_VERIINSTANCEHIERTREENODE) {
        instance_nodes->Insert(node) ;
        SetIter si ;
        HierId *hier_id ;
        FOREACH_SET_ITEM(node->GetHierIdTab(), si, &hier_id) {
            PrintHierIdPath(node, hier_id) ;
        }
    }
    MapIter mi ;
    char *inst_name ;
    HierTreeNode *child_node ;
    FOREACH_MAP_ITEM(node->GetChildren(), mi, &inst_name, &child_node) {
        if (!inst_name || !child_node) continue ;
        path_name_stack->InsertLast(inst_name) ;
        TraverseAndCollect(child_node, instance_nodes, path_name_stack) ;
        (void) path_name_stack->RemoveLast() ;
    }
}

int main()
{
    if (!veri_file::Analyze("test.v", veri_file::SYSTEM_VERILOG)) return 1 ;
    Array *top_modules = veri_file::GetTopModules() ;
    if (!top_modules) return 1 ;

    const Map *top_ht_nodes = hier_tree::CreateHierarchicalTree(top_modules, 0, 0) ;

    Array *instance_nodes = new Array(POINTER_HASH) ;
    HierTreeNode *root ;
    MapIter mi ;
    FOREACH_MAP_ITEM(top_ht_nodes, mi, 0, &root) {
        if (!root) continue ;
        Array path_name_stack ;
        path_name_stack.InsertLast(root->GetName()) ;
        TraverseAndCollect(root, instance_nodes, &path_name_stack) ;
        (void) path_name_stack.RemoveLast() ;
    }

    return 0 ;
}
 

Testcase:

interface i;
  bit b;
endinterface

module m0 (i ip [-1:0]);
endmodule

module m1 (i ip [ 1:0]);
  assert property (m0i.ip[-1].b == ip[1].b);
endmodule

module top;
  i ii [1:0] ();
  m0 m0i (ii);
  m1 m1i (ii);
endmodule
 

Output:

-- Analyzing Verilog file 'test.v' (VERI-1482)
HierId ii full path nodes:  (top)  (ii)
HierId ii full path nodes:  (top)  (ii)
HierId m0i.ip[(-1)].b full path nodes:  (top)  (m0i)  (ii {ip})  [1 {-1}]
HierId ip[1].b full path nodes:  (top)  (m1i)  (ii {ip})  [1 {1}]