Replacing Verific built-in primitives/operators with user implementations
From Verific Design Automation FAQ
Below is a C++ application illustrating how to replace Verific's built-in primitives/operators with user implementations.
#include <iostream> #include "veri_file.h" #include "DataBase.h" #include "VeriWrite.h" #include "Strings.h" using namespace std ; #ifdef VERIFIC_NAMESPACE using namespace Verific ; #endif int main(int argc, const char **argv) { // Analyze & elaborate my design: if (!veri_file::Analyze("test.v")) return 1 ; if (!veri_file::Elaborate("test")) return 1 ; // Get the FADD primitive. It is in "Primitives" library" Library *prims = Library::Primitives() ; if (!prims) return 2 ; // Name of the cell is "VERIFIC_FADD": Cell *cell_fadd = prims->GetCell("VERIFIC_FADD") ; if (!cell_fadd) return 3 ; // And name of the netlist is "INTERFACE": Netlist *prim_fadd = cell_fadd->GetNetlist("INTERFACE") ; if (!prim_fadd) return 4 ; // Get my top level design: Netlist *top = Netlist::PresentDesign() ; if (!top) return 5 ; // Write out the original synthesized design: VeriWrite vw ; vw.WriteFile("test.v.golden.new", top) ; // Now read my own version of "fadd" having internal logic: if (!veri_file::Analyze("fadd.v")) return 6 ; if (!veri_file::Elaborate("fadd")) return 6 ; // Get the netlist for my "fadd" // Current top-level design is the one elaborated last. Netlist *fadd = Netlist::PresentDesign() ; if (!fadd) return 6 ; // Make previous top-level design as top: top->SetPresentDesign() ; SetIter si ; Instance *inst ; // Now replace ALL references of Primitives.VERIFIC_FADD with my version of "fadd" prim_fadd->ReplaceReferences(fadd) ; // If one wants to selectively replace, (s)he can use the following instead: #ifdef SELECTIVE FOREACH_REFERENCE_OF_NETLIST(prim_fadd, si, inst) { // Here one can skip some instances depending on whatever condition: inst->ReplaceView(fadd) ; } #endif // Write out the design with Verific's primitive FADD replaced with my own "fadd": vw.WriteFile("replaced.v.golden.new", top) ; // Now, flatten the instantiations of my "fadd". // This will inline the logic added into its container: FOREACH_REFERENCE_OF_NETLIST(fadd, si, inst) { // One can choose to selectively flatten some instances as well: inst->Flatten(0, "_" /* path seprator */) ; } // Now this is VERIFIC_FADD replaced with my "fadd" logic: vw.WriteFile("flattened.v.golden.new", top) ; return 0 ; }
Input testcase (test.v):
module test (input a, b, output s) ; assign s = a + b; endmodule
User's implementation of fadd (fadd.v):
// Important: This module must have the same ports (name and size) // as the primitive it is to replace. module fadd (input cin, a, b, output o, cout) ; assign o = (a ^ b) ^ cin ; assign cout = ((a ^ b) & cin) | (a & b) ; endmodule
Final netlist (flattened.v.golden.new):
// // Verific Verilog Description of module test // module test (a, b, s); // test.v(1) input a; // test.v(1) input b; // test.v(1) output s; // test.v(1) add_1u_1u add_3 (.cin(1'b0), .a({a}), .b({b}), .o({s})); // test.v(2) endmodule // // Verific Verilog Description of OPERATOR add_1u_1u // module add_1u_1u (cin, a, b, o, cout); input cin; input [0:0]a; input [0:0]b; output [0:0]o; output cout; wire i1_n4, i1_n7, i1_n8; xor (i1_n4, a[0], b[0]) ; // fadd.v(2) xor (o[0], i1_n4, cin) ; // fadd.v(2) and (i1_n7, i1_n4, cin) ; // fadd.v(3) and (i1_n8, a[0], b[0]) ; // fadd.v(3) or (cout, i1_n7, i1_n8) ; // fadd.v(3) endmodule