Post processing port resolution of black boxes

From Verific Design Automation FAQ
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) ;

    // Lets accumulate all netlist
    Set netlists(POINTER_HASH) ;
    top->Hierarchy(netlists, 0 /* bottom to top */) ;

    Netlist *netlist ;
    SetIter si ;

    unsigned changed = 0 ;
    unsigned pass = 1 ;
    do { // do this until there are no changes in port directions of 'unknown' modules
        std::cout << std::endl << "=> Pass " <<  pass++ << std::endl ;
        changed = 0 ;
        FOREACH_SET_ITEM(&netlists, si, &netlist) {
            if (!netlist->GetAtt(" unknown_design")) continue ; // Skip if not 'unknown'
            Instance *instance ;
            SetIter si2 ;
            // Iterate over all references (Instances) of this Netlist
            FOREACH_REFERENCE_OF_NETLIST(netlist, si2, instance) {
                std::cout << "===> Instance '" <<  instance->Name() << "' of unknown module '"
                          << netlist->Owner()->Name() << "'"<< std::endl ;
                MapIter mi2 ;
                PortRef *portref ;
                FOREACH_PORTREF_OF_INST(instance, mi2, portref) {
                    Port *port = portref->GetPort() ;
                    if (!port->IsInout()) continue ; // Only look at inout ports
                    unsigned dir_known = 0 ;
                    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 ;
                            netlist->GetPort(port->Name())->SetDir(DIR_IN) ;
                            dir_known = 1 ;
                            changed = 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 ;
                                netlist->GetPort(port->Name())->SetDir(DIR_OUT) ;
                                dir_known = 1 ;
                                changed = 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 ;
                                netlist->GetPort(port->Name())->SetDir(DIR_IN) ;
                                dir_known = 1 ;
                                changed = 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 ;
                                netlist->GetPort(port->Name())->SetDir(DIR_OUT) ;
                                dir_known = 1 ;
                                changed = 1 ;
                            }
                        }
                    }
                    if (!dir_known) { // Still clueless
                        std::cout << "===>         Not enough data, remains inout" << std::endl ;
                    }
                }
            }
        }
    } while (changed) ;

    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(11): INFO: compiling module 'known1' (VERI-1018)
test.v(14): 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)

=> Pass 1
===> Instance 'iu1' 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 'iu2a' 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
===> Instance 'iu2b' of unknown module 'unknown2'
===>     Port: 'p1'
===>         Connected to input port 'i1' of owning Netlist
===>             Set port 'p1' to input
===>     Port: 'p2'
===>         Not enough data, remains inout
===> Instance 'iu2c' of unknown module 'unknown2'
===>     Port: 'p2'
===>         Only connected to output port 'o4' of owning Netlist
===>             Set port 'p2' to output

=> Pass 2
===> Instance 'iu1' of unknown module 'unknown1'
===>     Port: 'p3'
===>         Connected to output port 'p2' of instance ' iu2a'
===>             Set port 'p3' to input
===>     Port: 'p6'
===>             All other PortRefs are inputs
===>             Set port 'p6' to output
===>     Port: 'p7'
===>         Not enough data, remains inout
===> Instance 'iu2a' of unknown module 'unknown2'
===> Instance 'iu2b' of unknown module 'unknown2'
===> Instance 'iu2c' of unknown module 'unknown2'

=> Pass 3
===> Instance 'iu1' of unknown module 'unknown1'
===>     Port: 'p7'
===>         Not enough data, remains inout
===> Instance 'iu2a' of unknown module 'unknown2'
===> Instance 'iu2b' of unknown module 'unknown2'
===> Instance 'iu2c' of unknown module 'unknown2'
-- Writing netlist 'top' to Verilog file 'netlist_after.v' (VDB-1030)
 


netlist_before.v

module top (i1, i2, i3, o1, o2, o3, o4) ;   // 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)
    output o4;   // 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)
    wire t6;   // 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 iu2a (.p1(t4), .p2(t2), .p3(i3));   // test.v(6)
    unknown2 iu2b (.p1(i1), .p2(t2), .p3(i3));   // test.v(7)
    unknown2 iu2c (.p1(t6), .p2(o4), .p3(i3));   // test.v(8)
    
endmodule

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

module known2 (i1, i2, o) ;   // test.v(14)
    input i1;   // test.v(14)
    input i2;   // test.v(14)
    output o;   // test.v(14)    
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, o4) ;   // 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)
    output o4;   // 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)
    wire t6;   // 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 iu2a (.p1(t4), .p2(t2), .p3(i3));   // test.v(6)
    unknown2 iu2b (.p1(i1), .p2(t2), .p3(i3));   // test.v(7)
    unknown2 iu2c (.p1(t6), .p2(o4), .p3(i3));   // test.v(8)
    
endmodule

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

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

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

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


test.v

module top (input i1, i2, i3, output o1, o2, o3, o4);
    wire t1, t2, t3, t4, t5, t6;
    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 iu2a (.p1(t4), .p2(t2), .p3(i3));
    unknown2 iu2b (.p1(i1), .p2(t2), .p3(i3));
    unknown2 iu2c (.p1(t6), .p2(o4), .p3(i3));
endmodule

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

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