How to traverse scope hierarchy

From Verific Design Automation FAQ
Jump to: navigation, search

C++ code:

#include <iostream>
#include <cstring> // strchr
#include "veri_file.h"
#include "VeriModule.h"
#include "VeriExpression.h"
#include "VeriConstVal.h"
#include "VeriScope.h"
#include "Array.h"
#include "Map.h"
#include "Set.h"
#include "VeriId.h"

#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif

void PrintScopeHierarchy(VeriScope *scope, unsigned depth)
{
    if (!scope) return ;
    char *prefix = 0 ;
    if (depth) {
        prefix = Strings::allocate(depth*4 +3) ;
        unsigned i ;
        for (i = 0; i < (depth *4); i++) prefix[i] = ' ' ;
        prefix[i] = 0 ;
    }
    VeriIdDef *owner = scope->GetOwner() ;
    VeriScope *upper = scope->Upper() ;
    Map *declared_ids = scope->DeclArea() ;
    MapIter mi ;
    char *name ;
    char *ids = 0 ;
    FOREACH_MAP_ITEM(declared_ids, mi, &name, 0) {
        const char *first_space = std::strchr(name, ' ') ;
        if (first_space && Strings::compare(first_space, name)) continue ;

        if (!ids) {
            ids = Strings::save(name) ;
        } else {
            char *tmp = ids ;
            ids = Strings::save(ids, ", ", name) ;
            Strings::free(tmp) ;
        }
    }
    if (upper) {
        (void) Message::Msg(VERIFIC_INFO, 0, 0, "%s |---Owner : %s : (defines : %s )",prefix ? prefix : "",
                            owner ? owner->Name(): (scope->IsEmptyScope() ? "empty": "none"), ids) ;
    } else {
        (void) Message::Msg(VERIFIC_INFO, 0, 0, "Owner : %s : (defines : %s )",
                            owner ? owner->Name(): (scope->IsEmptyScope() ? "empty": "none"), ids) ;
    }
    Strings::free(ids) ;
    Strings::free(prefix) ;

    Set *children = scope->GetChildrenScopes() ;
    SetIter si ;
    VeriScope *child ;
    FOREACH_SET_ITEM(children, si, &child) {
        PrintScopeHierarchy(child, depth+1) ;
    }
}

int main(int argc, char **argv)
{
    Array files ;
    files.InsertLast("test.sv") ;
    if (!veri_file::AnalyzeMultipleFiles(&files, veri_file::SYSTEM_VERILOG)) return 1 ;

    // need to run static elaboration if any interface/module is parameterized
    if (!veri_file::ElaborateAllStatic()) return 1 ;

    MapIter mi ;
    VeriModule *module ;
    FOREACH_VERILOG_MODULE(mi, module) {
        if (!module) continue ;
        if (module->IsInterface()) continue ;

        PrintScopeHierarchy(module->GetScope(), 0) ;
    }

    return 0 ;
}
 

Verilog testcase:

module array8(data_in, data_out);

input [0:127] data_in;
output [0:3] data_out;

wire [7:0] arr[3:0][3:0]; // 2d array with word size 8
wire [4:0] out_arr[3:0];
genvar i, j;

    generate
    for (i = 0; i < 4; i = i + 1) begin : l1
        for (j = 0; j < 4; j = j + 1) begin : l2
        assign arr[i][j] = data_in[(4*i*8 + 8*j) +: 8];
        end
    end
    endgenerate

    generate
    for (i = 0; i < 4; i = i + 1) begin : l3
        adder_4_4 I (arr[i][0][7 -: 4], arr[i][1][6:3],
                      arr[i][2][3:0], arr[i][3][4 -: 4],
              out_arr[i]);
        assign data_out[i] = out_arr[i][4];
    end
    endgenerate
endmodule

module adder_4_4(in1, in2, in3, in4, out1);
input [3:0] in1;
input [3:0] in2;
input [3:0] in3;
input [3:0] in4;
output [4:0] out1;
reg [4:0] out1;

    always@(in1, in2, in3, in4)
    begin
        out1 = in1 + in2 + in3 + in4;
    end
endmodule
 

Run:

$ test-linux
-- Analyzing Verilog file 'test.sv' (VERI-1482)
INFO: Owner : array8 : (defines : data_in, data_out, arr, out_arr, i, j, l1, l3 )
INFO:      |---Owner : empty : (defines : (null) )
INFO:          |---Owner : l1 : (defines : i, l2 )
INFO:              |---Owner : empty : (defines : (null) )
INFO:                  |---Owner : l2 : (defines : j )
INFO:      |---Owner : empty : (defines : (null) )
INFO:          |---Owner : l3 : (defines : i, I )
INFO: Owner : adder_4_4 : (defines : in1, in2, in3, in4, out1 )
INFO:      |---Owner : empty : (defines : (null) )
$