How Verific elaborator handles blackboxes/unknown boxes
Q: After RTL elaboration on a Verilog design, I see Netlist with names such as 'NamedPorts' or 'OrderedPorts.'
Sometimes in the Verilog netlist output, I see modules with names such as 'foo_NamedPorts' or 'bar_OrderedPorts.'
They are not in the original RTL design. Where do they come from?
First, please read the article on Black box, empty box, and unknown box.
When the elaborator sees an instance of an unknown box, it creates a dummy Netlist object so that it can create an Instance object to instantiate it in the Netlist that owns the instance.
Verilog module instantiations can be in two styles: ordered port connections and named port connections.
- Named port connection example:
bb_mod b2 (.clk(d), .data(e), .out(f)) ;
- Ordered port connection example:
bb_mod b1 (a, b, c) ;
For such instances of unknown modules, the elaborator has no info about the size, type and direction of the ports.
For (1) it has names of some ports (there may be some more ports which are unconnected).
For (2) it doesn't even have the name of any of the ports.
Also note that port connections for (1) may not be in the same port expression order as in the declaration of the (unavailable) instantiated module. For example, bb_mod can very well be declared as: "module bb_mod(out, clk, data)." Therefore, even the module name is the same, the elaborator cannot use the same dummy netlist for both (1) and (2).
Thus it has to create two Netlists with name "NamedPorts" for (1) and "OrderedPorts" for (2). Both are under the Cell with name "bb_mod" and have direction of all Ports set to inout.
Also port names for (2) have made-up names p_0, p_1, etc..
Now when both style of the instances are used in the same design, there are multiple Instances of the Netlists from same Cell but they are actually different (since there is no actual definition).
In writing out the Netlist output file, the writer writes out the first instance with the name of the cell ('foo'), but the instances of other style is written with the name of the netlist appended with the cell name ('foo_OrderedPorts') to avoid conflict and to make the output legal/correct.
To avoid this you can use any of the following:
- Read in a stub of the module (with only port type/direction/size) before elaborating the design.
- You can also read in the stub after elaboration which will overwrite the created dummy Netlists.
- Hook up your own routine which we query to get the port names/size/direction, etc. using these APIs:
- static void veri_file::RegisterIsLibertyCellDefinedCB(unsigned (*cb)(const char *cell_name)) ; - static void veri_file::RegisterLibertyCellInterfaceNCB(unsigned (*cb)(const char *cell_name, const char *port_name, int &left_bound, int &right_bound, unsigned &port_direction, unsigned ignore_case)) ; - static void veri_file::RegisterLibertyCellInterfacePCB(const char * (*cb)(const char *cell_name, unsigned port_pos, int &left_bound, int &right_bound, unsigned &port_direction, unsigned ignore_case)) ; - static void veri_file::RegisterLibertyCellInterfaceNames(Set * (*cb)(const char *cell_name)) ; - static void veri_file::RegisterLibertySingleBitBusPort(unsigned (*cb)(const char *cell_name, const char *port_name, unsigned ignore_case)) ;
To use the above APIs, you have to define your own function and hook them up. We pass cell_name, port_name, port_pos and ignore_case when appropriate. You also have to set/return left_bound, right_bound and port_direction accordingly.
A simple testcase:
module test (); unknown_mod b2 (.clk(m), .data(n), .out(q)) ; unknown_mod b1 (a, b, c) ; endmodule
Verilog Netlist output:
// // Verific Verilog Description of module test // module test (); // test.v(1) wire m; // test.v(2) wire n; // test.v(2) wire q; // test.v(2) wire a; // test.v(3) wire b; // test.v(3) wire c; // test.v(3) unknown_mod b2 (.clk(m), .data(n), .out(q)); // test.v(2) unknown_mod_OrderedPorts b1 (a, b, c); // test.v(3) endmodule // // Verific Verilog Description of module unknown_mod // module unknown_mod (clk, data, out); inout clk; inout data; inout out; endmodule // // Verific Verilog Description of module unknown_mod_OrderedPorts // module unknown_mod_OrderedPorts (p_0, p_1, p_2); inout p_0; inout p_1; inout p_2; endmodule