Difference between revisions of "Getting design hierarchy from input RTL files"

From Verific Design Automation FAQ
Jump to: navigation, search
(Created page with "C++ application: <nowiki> #include <sstream> #include <iostream> #include <fstream> #include <string> #include "Array.h" // Make class Array available #include "Set....")
(No difference)

Revision as of 11:12, 14 July 2025

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]})
$