Difference between revisions of "Buffering signals and ungrouping"
From Verific Design Automation FAQ
(Created page with "During ungrouping (flattening) a hierarchical design, there are nets that need to be merged. The name of the resulting net from the merge will be the name in the highest level...") |
(No difference)
|
Revision as of 15:07, 19 April 2021
During ungrouping (flattening) a hierarchical design, there are nets that need to be merged. The name of the resulting net from the merge will be the name in the highest level of the design hierarchy.
This application example shows how to preserve the net name in the lower hierarchy level by adding a buffer to the net before ungrouping. In particular, it preserves the names of the output flip-flops in lower hierarchy levels.
#include "Map.h"
#include "Set.h"
#include "Message.h"
#include "veri_file.h"
#include "DataBase.h"
#include "Netlist.h"
#include "Array.h"
#include "VeriWrite.h"
#include "RuntimeFlags.h"
#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif
static void
Flatten(Netlist *top_netlist)
{
Set all_netlists(POINTER_HASH) ;
top_netlist->Hierarchy(all_netlists,1/*top-to-bottom*/) ;
// Iterate over all netlists in which we will do flattening :
SetIter si ;
Instance *inst ;
Netlist *netlist ;
FOREACH_SET_ITEM(&all_netlists, si, &netlist) {
if (!netlist) continue ;
// Collect all instances in this netlist :
Array insts(netlist->NumOfInsts()) ;
MapIter mi ;
FOREACH_INSTANCE_OF_NETLIST(netlist, mi, inst) {
insts.InsertLast(inst) ;
}
// Flatten the instances
while (insts.Size()!=0) {
inst = (Instance*)insts.RemoveLast() ;
if (inst->IsPrimitive()) continue ;
(void) inst->Flatten() ;
}
top_netlist->PropagateConstants() ;
}
}
static void
BufferFlipflops(Netlist *netlist)
{
if (!netlist) return ; // nothing to do.
if (netlist->IsBlackBox()) return; // nothing to do.
if (netlist->IsEmptyBox()) return; // nothing to do.
MapIter mii ;
Instance *inst ;
FOREACH_INSTANCE_OF_NETLIST(netlist, mii, inst) {
if (inst->Type()==PRIM_DFFRS) {
// This is the instantiation of a flip-flop, buffer its output
Net *onet = inst->GetOutput() ;
if (onet) {
Net *new_onet = netlist->Buf(onet, onet->Linefile()); // Add a buffer to the DFF output
char *new_name = Strings::save("new_", onet->Name()); // Name the output of the buffer
new_onet->SetName(new_name);
Strings::free(new_name);
SetIter si;
Port *port;
FOREACH_PORT_OF_NET (onet, si, port) { // move ports
if (!port) continue;
new_onet->Connect(port);
onet->Disconnect(port);
}
}
}
}
}
// This function is recursive in nature, and collects all other
// netlists that the incoming netlist depends on in a container.
void Accumulate(Netlist *netlist, Set &done)
{
if (!netlist) return ; // Ignore NULL netlists
SetItem *item = done.GetItem(netlist) ;
if (item) {
return ; // We've already been here
}
Instance *inst ;
MapIter mi ;
FOREACH_INSTANCE_OF_NETLIST(netlist, mi, inst) {
// Now go into the netlist associated with the instance
Accumulate(inst->View(), done) ;
}
// Insert the traversed Netlist
done.Insert(netlist) ;
}
int main(int argc, char **argv)
{
if (argc < 2) Message::PrintLine("reading 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" ; // Set default file name
}
// Now read in top-level design. In case of failure return.
if (!veri_file::Read(file_name,"work", veri_file::VERILOG_2K)) {
// Here, design analysis and elaboration failed
return 1 ;
}
// Get a handle to the top-level netlist
Netlist *top = Netlist::PresentDesign() ;
if (!top) {
Message::PrintLine("cannot find any handle to the top-level netlist") ;
return 4 ;
}
// Print out module that we have handle to
Message::Msg(VERIFIC_INFO, 0, top->Linefile(), "top level design is %s(%s)",
top->Owner()->Name(), top->Name()) ;
// RuntimeFlags::SetVar("db_verilog_writer_write_structural_instance_names", 1);
VeriWrite veriWriter;
veriWriter.WriteFile ("nl_before.v", top);
// Lets accumulate all netlist
Set netlists(POINTER_HASH) ;
Accumulate(top, netlists) ;
// Traverse the design and add buffers to output of flipflops
Netlist *netlist ;
SetIter si ;
FOREACH_SET_ITEM(&netlists, si, &netlist) {
BufferFlipflops(netlist) ;
}
veriWriter.WriteFile ("nl_after.v", top);
Flatten(top);
veriWriter.WriteFile ("flat_after.v", top);
// All done. Wasn't that easy ?
return 0 ;
}
RTL input:
module top (clk, reset, a, b, s);
input clk, reset;
input [1:0] a, b;
output [1:0] s;
wire [1:0] ta, tb, ts;
bot ia (clk, reset, a, ta);
bot ib (clk, reset, b, tb);
assign ts = ta + tb;
bot is (clk, reset, ts, s);
endmodule
module bot (clk, reset, input_d, output_q);
input clk, reset;
input [1:0] input_d;
output [1:0] output_q;
reg [1:0] output_q;
always @ (posedge clk or posedge reset) begin
if (reset)
output_q <= 2'b00;
else
output_q <= input_d;
end
endmodule
Final flattened netlist:
module top (clk, reset, a, b, s) ; // test.v(1)
input clk; // test.v(2)
input reset; // test.v(2)
input [1:0]a; // test.v(3)
input [1:0]b; // test.v(3)
output [1:0]s; // test.v(4)
wire [1:0]\is/output_q ; // test.v(15)
wire [1:0]ta; // test.v(5)
wire [1:0]tb; // test.v(5)
wire [1:0]ts; // test.v(5)
wire [1:0]\ib/output_q ; // test.v(15)
wire [1:0]\ia/output_q ; // test.v(15)
wire \is/new_output_q[1] , \ib/new_output_q[1] , \add_3/cout , \add_3/n2 ,
\is/new_output_q[0] , \ib/new_output_q[0] , \ia/new_output_q[1] ,
\ia/new_output_q[0] ;
buf (\is/new_output_q[0] , \is/output_q [0]) ; // test.v(15)
buf (\is/new_output_q[1] , \is/output_q [1]) ; // test.v(15)
VERIFIC_FADD \add_3/i1 (.cin(1'b0), .a(ta[0]), .b(tb[0]), .o(ts[0]),
.cout(\add_3/n2 )); // test.v(8)
VERIFIC_DFFRS \is/i6 (.d(ts[0]), .clk(clk), .s(1'b0), .r(reset),
.q(\is/output_q [0])); // test.v(21)
VERIFIC_DFFRS \is/i5 (.d(ts[1]), .clk(clk), .s(1'b0), .r(reset),
.q(\is/output_q [1])); // test.v(21)
VERIFIC_FADD \add_3/i2 (.cin(\add_3/n2 ), .a(ta[1]), .b(tb[1]), .o(ts[1]),
.cout(\add_3/cout )); // test.v(8)
buf (\ib/new_output_q[1] , \ib/output_q [1]) ; // test.v(15)
buf (\ib/new_output_q[0] , \ib/output_q [0]) ; // test.v(15)
VERIFIC_DFFRS \ib/i6 (.d(b[0]), .clk(clk), .s(1'b0), .r(reset),
.q(\ib/output_q [0])); // test.v(21)
VERIFIC_DFFRS \ib/i5 (.d(b[1]), .clk(clk), .s(1'b0), .r(reset),
.q(\ib/output_q [1])); // test.v(21)
buf (\ia/new_output_q[1] , \ia/output_q [1]) ; // test.v(15)
buf (\ia/new_output_q[0] , \ia/output_q [0]) ; // test.v(15)
VERIFIC_DFFRS \ia/i6 (.d(a[0]), .clk(clk), .s(1'b0), .r(reset),
.q(\ia/output_q [0])); // test.v(21)
VERIFIC_DFFRS \ia/i5 (.d(a[1]), .clk(clk), .s(1'b0), .r(reset),
.q(\ia/output_q [1])); // test.v(21)
endmodule