Traverse instances in parsetree

From Verific Design Automation FAQ
Revision as of 20:44, 22 July 2024 by Vince (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

C++:

// Verific utilities
#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...
// Verific Verilog parser
#include "VeriModule.h"
#include "veri_file.h"

// Verific VHDL parser
#include "vhdl_file.h"      
#include "VhdlIdDef.h"      
#include "VhdlScope.h"      
#include "VhdlStatement.h"  
#include "VhdlName.h"       // Definition of VhdlName
#include "VhdlUnits.h"      // Definition of VhdlLibrary

#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif

// Routines for traversing the entity instances in DFS order and print them.
static void PrintDesignUnit(const VhdlStatement *stmt) ;
static void TraverseVhdl(const VhdlPrimaryUnit *top, const char *arch_name) ;

int main(int argc, const char **argv)
{

    vhdl_file::SetDefaultLibraryPath("../vdbs") ;

    if (!veri_file::Analyze("test.v")) return 1 ;
    if (!vhdl_file::Analyze("test.vhd")) return 1 ;


    VhdlLibrary *lib = vhdl_file::GetLibrary("work") ;
    VhdlPrimaryUnit *top_entity = lib ? lib->GetPrimUnit("comp") : 0 ; // Get the top-level entity
    if (!top_entity) {
        return 1 ; 
    }

    if (!vhdl_file::Elaborate("comp", "work", 0, 0, 1)) {
        return 2 ;
    }

    Message::PrintLine("\n") ;
    top_entity->Info("Start hierarchy traversal here at VHDL top level unit '%s'", top_entity->Name()) ;
    Message::PrintLine("\n") ;
    TraverseVhdl(top_entity, 0 /*architecture name*/) ; // Traverse top level unit and the hierarchy under it
    return 0 ; // all good
}

// Traverse an entity and the hierarchy under it:
static void
TraverseVhdl(const VhdlPrimaryUnit *unit, const char *arch_name)
{
    // Find the architecture of the unit:
    VhdlSecondaryUnit *arch = unit? unit->GetSecondaryUnit(arch_name) : 0 ;
    // Find the scope:
    VhdlScope *scope = arch ? arch->LocalScope() : 0 ;

    // Get the declared ids from that scope:
    Map *ids = scope ? scope->DeclArea() : 0 ;
    MapIter mi ;
    VhdlIdDef *id ;
    FOREACH_MAP_ITEM(ids, mi, 0, &id) {
        if (!id) continue ;
        VhdlStatement *stmt = id->GetStatement() ;
        if (!stmt) continue ;
        // Routine to print the hierarchy:
        PrintDesignUnit(stmt) ;
    }
}

// Print the hierarchy
static void PrintDesignUnit(const VhdlStatement *stmt)
{
    if (!stmt) return ;

    // Get the array of statements, for loop/block statements
    // we get an array of statements and recursively go to the
    // inner most statement and print the hierarchy.
    Array *stmts = stmt->GetStatements() ;
    unsigned ai ;
    VhdlStatement *inner_stmt ;
    FOREACH_ARRAY_ITEM(stmts, ai, inner_stmt) {
        PrintDesignUnit(inner_stmt) ;
    }

    VhdlIdDef *inst_unit = stmt->GetInstantiatedUnit() ; // Get the instantiated unit id for instances only
    if (!inst_unit) return ; // Not an instance level

    // Processing instance
    VhdlIdDef *id = stmt->GetLabel() ;
    Message::PrintLine("Processing instance : ", id ? id->Name() : 0) ;

    if (inst_unit->IsComponent()) { // instance of component
        Message::PrintLine("Component instance, name of component is ", inst_unit->Name()) ;
        Message::PrintLine("\n") ;
    }

    VhdlPrimaryUnit *prim_unit = inst_unit ? inst_unit->GetPrimaryUnit() : 0 ; // Get the primary unit
    if (!prim_unit) return ;

    if (prim_unit->IsVerilogModule()) { // instance of Verilog module
        // Get instantiated verilog module
        VeriModule *veri_module = vhdl_file::GetVerilogModuleFromlib(inst_unit->GetContainingLibraryName(), inst_unit->Name()) ;
        if (!veri_module) return ;
        Message::PrintLine("instantiated Verilog module : ", veri_module->Name()) ;
        Message::PrintLine("\n") ;
    } else { // Instance of vhdl unit
        VhdlName *instantiated_unit_name = stmt->GetInstantiatedUnitNameNode() ;
        // Find the architecture name and traverse the vhdl design
        const char *arch_name = instantiated_unit_name ? instantiated_unit_name->ArchitectureNameAspect(): 0 ; 
        Message::PrintLine("instantiated VHDL unit : ", prim_unit->Name()) ;
        Message::PrintLine("architecture name : ", arch_name ? arch_name : 0) ;
        Message::PrintLine("\n") ;
        TraverseVhdl(prim_unit, arch_name) ; // Traverse the VHDL unit
    }
}
 

Python script:

#!/usr/bin/python

import sys
sys.path.append('../../pythonmain/install')
import Verific

def TraverseVhdl(unit, arch_name):
    # Find the architecture of the unit:
    if not unit: return
    arch = unit.GetSecondaryUnit(arch_name) 
    if not arch: return
    # Find the scope:
    scope = arch.LocalScope()
    if not scope: return

    # Get the declared ids from that scope:
    ids = Verific.VhdlIdDefMapIter(scope.DeclArea())
    id = ids.First()
    while (id):
        stmt = id.GetStatement() 
        if not stmt: 
            id = ids.Next()
            continue 
        # Routine to print the hierarchy:
        PrintDesignUnit(stmt) 
        id = ids.Next()

def PrintDesignUnit(stmt):
    if not stmt: return

    # Get the array of statements, for loop/block statements
    # we get an array of statements and recursively go to the
    # inner most statement and print the hierarchy.
    stmts = Verific.VhdlStatementArrayIter(stmt.GetStatements())
    inner_stmt = stmts.First()
    while (inner_stmt):
        PrintDesignUnit(inner_stmt) 
        inner_stmt = stmts.Next()

    inst_unit = stmt.GetInstantiatedUnit()  # Get the instantiated unit id for instances only
    if not inst_unit: return  # Not an instance level

    # Processing instance
    id = stmt.GetLabel() 
    if not id: return
    Verific.Message.PrintLine("Processing instance : ", id.Name())

    if inst_unit.IsComponent():
        Verific.Message.PrintLine("Component instance, name of component is ", inst_unit.Name())
        Verific.Message.PrintLine("\n") 

    prim_unit = inst_unit.GetPrimaryUnit() 
    if not prim_unit: return 

    if prim_unit.IsVerilogModule():
        # Get instantiated verilog module
        veri_module = Verific.vhdl_file.GetVerilogModuleFromlib(inst_unit.GetContainingLibraryName(), inst_unit.Name())
        if not veri_module: return 
        Verific.Message.PrintLine("instantiated Verilog module : ", veri_module.Name())
        Verific.Message.PrintLine("\n") 
    else: 
        instantiated_unit_name = stmt.GetInstantiatedUnitNameNode() 
        if not instantiated_unit_name: return
        # Find the architecture name and traverse the vhdl design
        arch_name = instantiated_unit_name.ArchitectureNameAspect()
        if not arch_name: return
        Verific.Message.PrintLine("instantiated VHDL unit : ", prim_unit.Name())
        Verific.Message.PrintLine("architecture name : ", arch_name)
        Verific.Message.PrintLine("\n") 
        TraverseVhdl(prim_unit, arch_name) # Traverse the VHDL unit

# Set default library path to auto-load standard packages
if not Verific.vhdl_file.SetDefaultLibraryPath("../../vhdl_packages/vdbs_1993"):
    print ("Error during analysis, exiting")
    sys.exit(1)

# Analyze the design
if not Verific.veri_file.Analyze("test.v", Verific.veri_file.SYSTEM_VERILOG, "work"):
    print ("Analyze failure. Exiting")
    sys.exit(2)

if not Verific.vhdl_file.Analyze("test.vhd", "work", Verific.vhdl_file.VHDL_93):
    print ("Analyze failure. Exiting")
    sys.exit(2)

# Get the library
lib = Verific.vhdl_file.GetLibrary("work")
if not lib:
    print ("Can't get library 'work'")
    sys.exit(3)

# Check all the primary units of the library
top_entity = lib.GetPrimUnit("comp")
if not top_entity:
    sys.exit(4)

if not Verific.vhdl_file.Elaborate("comp", "work", None, None, 1):
    sys.exit(5)

Verific.Message.PrintLine("\n")
top_entity.Info("Start hierarchy traversal here at VHDL top level unit '%s'", top_entity.Name())
Verific.Message.PrintLine("\n")
TraverseVhdl(top_entity, None)
 

test.vhd:

entity child is -- instantiated in test module in Verilog design
   generic (p : integer := 3);
   port (S1, S2: out bit_vector (p downto 0);
         I1 : in bit_vector (p downto 0));
end ;

architecture arch of child is
begin
    S1 <= I1 ;
    S2 <= not I1 ;
end ;

entity comp is -- top-level unit

   port(X, Y: in BIT_VECTOR(3 DOWNTO 0);
        S1, S2: out bit_vector (3 DOWNTO 0);
        S3, S4: out bit_vector (3 DOWNTO 0);
        Sum, Carry: out BIT);

end;

architecture Structure of comp is

    component child is
        generic (p : integer) ;
        port (S1, S2: out BIT_VECTOR(p DOWNTO 0);
              I1 : in BIT_VECTOR(p downto 0));
    end component;

begin

   L1: entity work.xor_gate generic map (4)
       port map (X, Y, Sum);

   L2 : component child generic map (3) port map(S1, S2, X) ;
   blk : block
       begin
           L3 : entity work.child(arch) generic map (3) port map(S3, S4, X) ;
       end block ;

end;
 

test.v:

module xor_gate (CompIn1, CompIn2, CompOut); // Instantiated in 'comp' entity in  VHDL file test.vhd
     parameter p = 10 ;
     input [3:0]CompIn1;
     input [3:0]CompIn2;
     output CompOut;
endmodule
 

Run:

[hoa@awing0 HD]$ test-linux 
-- Analyzing Verilog file 'test.v' (VERI-1482)
-- Analyzing VHDL file 'test.vhd' (VHDL-1481)
-- Restoring VHDL unit 'std.standard' from file '../vdbs/std/standard.vdb' (VHDL-1493)
test.vhd(1): INFO: analyzing entity 'child' (VHDL-1012)
test.vhd(7): INFO: analyzing architecture 'arch' (VHDL-1010)
test.vhd(13): INFO: analyzing entity 'comp' (VHDL-1012)
test.vhd(22): INFO: analyzing architecture 'structure' (VHDL-1010)
-- Restoring VHDL unit 'vl.vl_types' from file '../vdbs/vl/vl_types.vdb' (VHDL-1493)
test.vhd(13): INFO: processing 'comp(Structure)' (VHDL-1067)
test.vhd(33): INFO: switching to Verilog mode to elaborate module 'xor_gate' (VHDL-1399)
test.v(1): INFO: compiling module 'xor_gate(p=4)' (VERI-1018)
test.vhd(33): INFO: returning to VHDL mode to continue with elaboration (VHDL-1400)
test.vhd(1): INFO: processing 'child_default(arch)' (VHDL-1067)
--

test.vhd(20): INFO: Start hierarchy traversal here at VHDL top level unit 'comp'
--

-- Processing instance : l1
-- instantiated Verilog module : xor_gate(p=4)
--

-- Processing instance : l2
-- instantiated VHDL unit : child_default
-- architecture name : arch
--

-- Processing instance : l3
-- instantiated VHDL unit : child_default
-- architecture name : arch
--

[hoa@awing0 HD]$