Post processing port resolution of black boxes

From Verific Design Automation FAQ
Revision as of 18:56, 16 February 2024 by Alice (Talk | contribs) (Created page with "C++ example: <nowiki> #include "Map.h" #include "Message.h" #include "veri_file.h" #include "DataBase.h" #include "VeriWrite.h" #include "Run...")

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

C++ example:

#include "Map.h"            
#include "Message.h"        
#include "veri_file.h"      
#include "DataBase.h"       
#include "VeriWrite.h"
#include "RuntimeFlags.h"
#include <iostream>

#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif

int main(int argc, char **argv)
{
    if (argc < 2) {
        Message::PrintLine("Default input file: test.v. Specify command line argument to override") ;
    }

    const char *file_name = 0 ;

    if (argc>1) {
        file_name = argv[1] ; // Set the file name as specified by the user
    } else {
        file_name = "test.v" ;
    }

    if (!veri_file::Analyze(file_name, veri_file::SYSTEM_VERILOG)) return 1 ;
    if (!veri_file::ElaborateAll()) return 1 ;

    Netlist *top = Netlist::PresentDesign() ;

    VeriWrite vw ;
    RuntimeFlags::SetVar("db_verilog_writer_write_blackboxes", 2) ;
    vw.WriteFile ("netlist_before.v", top) ;

    MapIter mi ;
    Instance * instance ;
    FOREACH_INSTANCE_OF_NETLIST(top, mi, instance) {
        Netlist *view = instance->View() ;
        if (!view) continue ;
        if (view->GetAtt(" unknown_design")) {
            std::cout << "===> Instance '" <<  instance->Name() << "' is of unknown module '"
                      << instance->View()->Owner()->Name() << "'"<< std::endl ;
            MapIter mi2 ;
            PortRef *portref ;
            FOREACH_PORTREF_OF_INST(instance, mi2, portref) {
                unsigned dir_known = 0 ;
                Port *port = portref->GetPort() ;
                std::cout << "===>     Port: '" << port->Name() << "'"<< std::endl ;
                Net *net = portref->GetNet() ;
                if (!net) {
                    std::cout << "===>     Does not connect to any Net" << std::endl ;
                    continue ;
                }
                // Is this port connected to any Port?
                Port *port2 ;
                SetIter si ;
                FOREACH_PORT_OF_NET(net, si, port2) {
                    if (port2->IsInput()) {
                        std::cout << "===>         Connected to input port '" << port2->Name() << "' of owning Netlist" << std::endl ;
                        std::cout << "===>             Set port '" << port->Name() << "' to input" << std::endl ;
                        view->GetPort(port->Name())->SetDir(DIR_IN) ;
                        dir_known = 1 ;
                    } else if (port2->IsOutput()) {
                        if (net->NumOfPortRefs() == 1 ) { // does not connected to any other instance
                            std::cout << "===>         Only connected to output port '" << port2->Name() << "' of owning Netlist" << std::endl ;
                            std::cout << "===>             Set port '" << port->Name() << "' to output" << std::endl ;
                            view->GetPort(port->Name())->SetDir(DIR_OUT) ;
                            dir_known = 1 ;
                        }
                    }
                }
                // If still don't know direction, check other connections
                if (!dir_known) {
                    PortRef *portref2 ;
                    SetIter si2 ;
                    FOREACH_PORTREF_OF_NET(net, si2, portref2) {
                        if (portref2 == portref) continue ; // not checking self
                        if (portref2->IsOutput()) { // connected to an output portref, must be an input port
                            Instance *instance2 = portref2->GetInst() ;
                            Port *port3 = portref2->GetPort() ;
                            std::cout << "===>         Connected to output port '" << port3->Name()
                                      << "' of instance ' " << instance2->Name() << "'" << std::endl ;
                            std::cout << "===>             Set port '" << port->Name() << "' to input" << std::endl ;
                            view->GetPort(port->Name())->SetDir(DIR_IN) ;
                            dir_known = 1 ;
                            break ;
                        } else if (portref2->IsInout()) { // connected to an inout portref, still don't know direction
                            break ;
                        } else { // all portrefs are inputs, must be an output port
                            std::cout << "===>             All other PortRefs are inputs" << std::endl ;
                            std::cout << "===>             Set port '" << port->Name() << "' to output" << std::endl ;
                            view->GetPort(port->Name())->SetDir(DIR_OUT) ;
                            dir_known = 1 ;
                        }
                    }
                }
                if (!dir_known) { // Still clueless
                    std::cout << "===>         Not enough data, remains inout" << std::endl ;
                }
            }
        }
    }

    vw.WriteFile ("netlist_after.v", top) ;

    return 0 ;
}
 


Run:

-- Default input file: test.v. Specify command line argument to override
-- Analyzing Verilog file 'test.v' (VERI-1482)
test.v(1): INFO: compiling module 'top' (VERI-1018)
test.v(9): INFO: compiling module 'known1' (VERI-1018)
test.v(12): INFO: compiling module 'known2' (VERI-1018)
test.v(5): WARNING: instantiating unknown module 'unknown1' (VERI-1063)
test.v(6): WARNING: instantiating unknown module 'unknown2' (VERI-1063)
-- Writing netlist 'top' to Verilog file 'netlist_before.v' (VDB-1030)
===> Instance 'iu1' is of unknown module 'unknown1'
===>     Port: 'p1'
===>         Connected to output port 'o' of instance ' ik1'
===>             Set port 'p1' to input
===>     Port: 'p2'
===>         Connected to input port 'i2' of owning Netlist
===>             Set port 'p2' to input
===>     Port: 'p3'
===>         Not enough data, remains inout
===>     Port: 'p4'
===>             All other PortRefs are inputs
===>             Set port 'p4' to output
===>     Port: 'p5'
===>         Only connected to output port 'o3' of owning Netlist
===>             Set port 'p5' to output
===>     Port: 'p6'
===>         Not enough data, remains inout
===>     Port: 'p7'
===>         Not enough data, remains inout
===> Instance 'iu2' is of unknown module 'unknown2'
===>     Port: 'p1'
===>         Not enough data, remains inout
===>     Port: 'p2'
===>         Not enough data, remains inout
===>     Port: 'p3'
===>         Connected to input port 'i3' of owning Netlist
===>             Set port 'p3' to input
-- Writing netlist 'top' to Verilog file 'netlist_after.v' (VDB-1030)
 


netlist_before.v

module top (i1, i2, i3, o1, o2, o3) ;   // test.v(1)
    input i1;   // test.v(1)
    input i2;   // test.v(1)
    input i3;   // test.v(1)
    output o1;   // test.v(1)
    output o2;   // test.v(1)
    output o3;   // test.v(1)
    
    wire t1;   // test.v(2)
    wire t2;   // test.v(2)
    wire t3;   // test.v(2)
    wire t4;   // test.v(2)
    wire t5;   // test.v(2)
    
    known1 ik1 (.i1(i3), .i2(t2), .o(t3));   // test.v(3)
    known2 ik2 (.i1(i1), .i2(t1), .o(o2));   // test.v(4)
    unknown1 iu1 (.p1(t3), .p2(i2), .p3(t2), .p4(t1), .p5(o3), .p6(t4), 
            .p7(t5));   // test.v(5)
    unknown2 iu2 (.p1(t4), .p2(t2), .p3(i3));   // test.v(6)
endmodule

module known1 (i1, i2, o) ;   // test.v(9)
    input i1;   // test.v(9)
    input i2;   // test.v(9)
    output o;   // test.v(9)
endmodule

module known2 (i1, i2, o) ;   // test.v(12)
    input i1;   // test.v(12)
    input i2;   // test.v(12)
    output o;   // test.v(12)  
endmodule

module unknown1 (p1, p2, p3, p4, p5, p6, p7) ;
    inout p1;
    inout p2;
    inout p3;
    inout p4;
    inout p5;
    inout p6;
    inout p7; 
endmodule

module unknown2 (p1, p2, p3) ;
    inout p1;
    inout p2;
    inout p3;   
endmodule

 


netlist_after.v

module top (i1, i2, i3, o1, o2, o3);   // test.v(1)
    input i1;   // test.v(1)
    input i2;   // test.v(1)
    input i3;   // test.v(1)
    output o1;   // test.v(1)
    output o2;   // test.v(1)
    output o3;   // test.v(1)
    
    wire t1;   // test.v(2)
    wire t2;   // test.v(2)
    wire t3;   // test.v(2)
    wire t4;   // test.v(2)
    wire t5;   // test.v(2)
    
    known1 ik1 (.i1(i3), .i2(t2), .o(t3));   // test.v(3)
    known2 ik2 (.i1(i1), .i2(t1), .o(o2));   // test.v(4)
    unknown1 iu1 (.p1(t3), .p2(i2), .p3(t2), .p4(t1), .p5(o3), .p6(t4), 
            .p7(t5));   // test.v(5)
    unknown2 iu2 (.p1(t4), .p2(t2), .p3(i3));   // test.v(6)
endmodule

module known1 (i1, i2, o) ;   // test.v(9)
    input i1;   // test.v(9)
    input i2;   // test.v(9)
    output o;   // test.v(9) 
endmodule

module known2 (i1, i2, o) ;   // test.v(12)
    input i1;   // test.v(12)
    input i2;   // test.v(12)
    output o;   // test.v(12)
endmodule

module unknown1 (p1, p2, p3, p4, p5, p6, p7) ;
    input p1;
    input p2;
    inout p3;
    output p4;
    output p5;
    inout p6;
    inout p7;
endmodule

module unknown2 (p1, p2, p3) ;
    inout p1;
    inout p2;
    input p3;
endmodule
 


test.v

module top (input i1, i2, i3, output o1, o2, o3);
    wire t1, t2, t3, t4, t5;
    known1 ik1 (.i1(i3), .i2(t2), .o(t3));
    known2 ik2 (.i1(i1), .i2(t1), .o(o2));
    unknown1 iu1 (.p1(t3), .p2(i2), .p3(t2), .p4(t1), .p5(o3), .p6(t4), .p7(t5));
    unknown2 iu2 (.p1(t4), .p2(t2), .p3(i3));
endmodule

module known1 (input i1, i2, output o);
endmodule

module known2 (input i1, i2, output o);
endmodule