Getting design hierarchy from input RTL files
From Verific Design Automation FAQ
Revision as of 11:12, 14 July 2025 by Hoa (Talk | contribs) (Created page with "C++ application: <nowiki> #include <sstream> #include <iostream> #include <fstream> #include <string> #include "Array.h" // Make class Array available #include "Set....")
C++ application:
#include <sstream>
#include <iostream>
#include <fstream>
#include <string>
#include "Array.h" // Make class Array available
#include "Set.h" // Make class Set available
#include "Message.h" // Make message handlers available
#include "Strings.h" // Definition of class to manipulate copy, concatenate, create etc...
#include "LineFile.h"
#include "veri_file.h" // Make verilog reader available
#include "VeriModule.h" // Definition of a VeriModule and VeriPrimitive
#include "VeriExpression.h" // Definition of VeriName
#include "VeriId.h" // Definitions of all verilog identifier nodes
#include "VeriScope.h"
#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif
std::string PrintLocation(const linefile_type lf)
{
std::ostringstream result("") ;
if (lf) {
#ifdef VERIFIC_LINEFILE_INCLUDES_COLUMNS
result << lf->GetFileName() ;
result << "[" ;
result << lf->GetLeftLine() ;
result << ":" ;
result << lf->GetLeftCol() ;
result << "]-[" ;
result << lf->GetRightLine() ;
result << ":" ;
result << lf->GetRightCol() ;
result << "]" ;
#else
result << LineFile::GetFileName(lf) ;
result << "[" ;
result << LineFile::GetLineNo(lf) ;
result << "]" ;
#endif
}
return result.str() ;
}
void PrintHierarchy(VeriModule *module, unsigned depth)
{
if (!module) return ; // Ignore NULL netlists
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 ;
}
// Get the scope of the module:
VeriScope *scope = module->GetScope() ;
// Find all the declared ids in this scope:
Map *ids = scope ? scope->DeclArea() : 0 ;
MapIter mi ;
VeriIdDef *id ;
FOREACH_MAP_ITEM(ids, mi, 0, &id) { // Traverse declared ids
if (!id || !id->IsInst()) continue ; // Consider only the instance ids
VeriModuleInstantiation *mod_inst = id->GetModuleInstance() ; // Take the module instance
VeriModule *mod = mod_inst ? mod_inst->GetInstantiatedModule() : 0 ; // The module instance is a module
if (mod) { // This is module instantiation
linefile_type lf = mod->Linefile() ;
const char *location = PrintLocation(lf).c_str() ;
char *inst_mod = Strings::save(prefix ? prefix : "", id->Name(), " (", mod->Name());
Message::PrintLine(inst_mod, " {", location, "})") ;
PrintHierarchy(mod, depth+1) ;
}
}
}
int main()
{
const char *file_name = "top.v" ;
const char *top_name = "top" ;
const char *work_lib = "work" ;
veri_file::AddVFile("mbot.v") ;
veri_file::AddYDir(".") ;
veri_file::AddIncludeDir(".") ;
veri_file::AddLibExt(".v") ;
if (!veri_file::Analyze(file_name, veri_file::VERILOG_2K /*Verilog 2000*/, work_lib)) return 1 ;
if (veri_file::GetModule(top_name)) {
// Optional - statically elaborate all the top Verilog module. Return if any error shows up.
if (!veri_file::ElaborateStatic(top_name)) return 2 ; // statically elaborates all verilog modules in the "work" libarary
VeriModule *top_module = veri_file::GetModule(top_name) ; // Get the pointer to the top-level module
if (!top_module) {
return 3 ; // Exit from application if there is no top module by the given name in the given Verilog designs
}
linefile_type lf = top_module->Linefile() ;
const char *location = PrintLocation(lf).c_str() ;
Message::PrintLine("Top module: ", top_module->Name(), " {", location, "}") ;
PrintHierarchy(top_module, 1) ;
}
return 0 ; // all good
}
Python script:
#! /usr/bin/python
import sys
sys.path.append('../../pythonmain/install')
import Verific
def PrintLocation(lf):
result = '';
if lf:
# if 'VERIFIC_LINEFILE_INCLUDES_COLUMNS' is enabled
result = result + lf.GetFileName() + '[' + Verific.Strings.itoa(lf.GetLeftLine()) + ':' \
+ Verific.Strings.itoa(lf.GetLeftCol()) + ']-[' \
+ Verific.Strings.itoa(lf.GetRightLine()) + ':' \
+ Verific.Strings.itoa(lf.GetRightCol()) + ']'
# if 'VERIFIC_LINEFILE_INCLUDES_COLUMNS' is disabled
# result = result + Verific.LineFile.GetFileName(lf) + '[' + Verific.Strings.itoa(Verific.LineFile.GetLineNo(lf)) + ']'
return result
def PrintHierarchy(module, depth):
if not module:
return
prefix = ''
for i in range (depth):
prefix = prefix + ' '
scope = module.GetScope()
ids = scope.DeclArea() # Map of VeriIdDefs
id_iter = Verific.VeriIdDefMapIter(ids)
id = id_iter.First()
while (id):
if (not id.IsInst()):
id = id_iter.Next()
continue
mod_inst = id.GetModuleInstance() # Take the module instance - VeriModuleInstantiation
mod = mod_inst.GetInstantiatedModule() # The module instance is a module - VeriModule
if (not mod):
id = id_iter.Next()
continue
location = PrintLocation(mod.Linefile());
print ('%sInstance %s (%s {%s})' % (prefix, id.Name(), mod.Name(), location))
id = id_iter.Next()
PrintHierarchy(mod, depth+1);
# main
reader = Verific.veri_file()
file_name = 'top.v'
top_name = 'top'
work_lib = 'work'
reader.AddVFile("mbot.v") ;
reader.AddYDir(".") ;
reader.AddIncludeDir(".") ;
reader.AddLibExt(".v") ;
if (not reader.Analyze(file_name, reader.VERILOG_2K, work_lib)):
print ('Error in Analyze')
sys.exit(1)
top_module = reader.GetModule(top_name) ;
if (not top_module):
print ('Error in GetModule')
sys.exit(2)
# Static elaboration is optional
if (not reader.ElaborateStatic(top_name)):
print ('Error in ElaborateStatic')
sys.exit(3)
location = PrintLocation(top_module.Linefile());
print ('\nTop module: %s {%s}' % (top_module.Name(), location))
PrintHierarchy(top_module, 1)
print ('\nDone')
sys.exit(0)
Input RTL:
$ cat top.v
// top module
module top(a, b, c, d, e, f, out, m, n, o) ;
input a, b, c, d, e, f, m, n ;
output out, o ;
wire tmp1, tmp2 ;
mid1 i1(a, b, c, d, tmp1) ;
mid1 i2(a, d, e, f, tmp2) ;
mid1 i3(tmp1, tmp2, e, f, out) ;
bot bi(o, m, n);
endmodule
$ cat mid1.v
module mid1 (mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4, mid1_out,
mid1b_inp1, mid1b_inp2, mid1b_out) ;
input mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4 ;
output mid1_out ;
input mid1b_inp1, mid1b_inp2 ;
output mid1b_out ;
wire tmp1, tmp2 ;
mid2 m1(mid1_inp1, mid1_inp2, tmp1) ;
mid2 m2(mid1_inp3, mid1_inp4, tmp2) ;
mid2 m3(tmp1, tmp2, mid1_out) ;
bot b(mid1b_inp1, mid1b_inp2, mid1b_out) ;
endmodule
$ cat mid2.v
module mid2 (mid2_inp1, mid2_inp2, mid2_out) ;
input mid2_inp1, mid2_inp2 ;
output mid2_out ;
bot b(mid2_inp1, mid2_inp2, mid2_out) ;
endmodule
$ cat mbot.v
module bot (bot_inp1, bot_inp2, bot_out) ;
input bot_inp1, bot_inp2 ;
output bot_out ;
assign bot_out = bot_inp1 & bot_inp2 ;
endmodule
$
Run:
$ test-linux
-- Analyzing Verilog file 'top.v' (VERI-1482)
-- Parsing library file mbot.v (VERI-1482)
-- Analyzing Verilog file 'mbot.v' (VERI-1482)
-- Resolving module 'bot' (VERI-1489)
-- Analyzing Verilog file './mid1.v' (VERI-1482)
-- Resolving module 'mid1' (VERI-1489)
-- Analyzing Verilog file './mid2.v' (VERI-1482)
-- Resolving module 'mid2' (VERI-1489)
top.v(2): INFO: compiling module 'top' (VERI-1018)
top.v(8): WARNING: port 'mid1b_inp1' is not connected on this instance (VERI-2435)
top.v(8): WARNING: port 'mid1b_out' remains unconnected for this instance (VERI-1927)
top.v(9): WARNING: port 'mid1b_inp1' is not connected on this instance (VERI-2435)
top.v(9): WARNING: port 'mid1b_out' remains unconnected for this instance (VERI-1927)
top.v(10): WARNING: port 'mid1b_inp1' is not connected on this instance (VERI-2435)
top.v(10): WARNING: port 'mid1b_out' remains unconnected for this instance (VERI-1927)
top.v(11): WARNING: assignment to input 'n' (VERI-1214)
-- Top module: top {top.v[2:1]-[13:10]}
-- i1 (mid1 {./mid1.v[1:1]-[15:10]})
-- m1 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- m2 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- m3 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- i2 (mid1 {./mid1.v[1:1]-[15:10]})
-- m1 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- m2 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- m3 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- i3 (mid1 {./mid1.v[1:1]-[15:10]})
-- m1 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- m2 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- m3 (mid2 {./mid2.v[1:1]-[7:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- b (bot {mbot.v[2:1]-[8:10]})
-- bi (bot {mbot.v[2:1]-[8:10]})
$