How to traverse scope hierarchy
From Verific Design Automation FAQ
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) ) $