Post processing port resolution of black boxes
From Verific Design Automation FAQ
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