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