Fanout cone and grouping
From Verific Design Automation FAQ
C++ code:
/* This application example collects instances in the fanout cone of a signal, and groups those instances into a new netlist */ #include "Set.h" #include "Array.h" #include "Message.h" #include "veri_file.h" #include "DataBase.h" #include "VeriWrite.h" #ifdef VERIFIC_NAMESPACE using namespace Verific ; #endif int main() { const char *file_name = "prep2.v"; const char *net_name = "compare_output"; Array files(1) ; files.Insert(file_name) ; if (!veri_file::AnalyzeMultipleFiles(&files, veri_file::VERILOG_2K)) { return 1 ; } const char *name = veri_file::TopModule() ; if (!veri_file::Elaborate(name /*module_name*/, "work" /*work_lib*/, 0 /*parameter_values_map*/)) return 4 ; // After elaboration, we can now delete the parse-trees (to conserve memory) since // we don't need them anymore. veri_file::RemoveAllModules() ; Netlist *top = Netlist::PresentDesign() ; if (!top) { Message::PrintLine("Cannot find any handle to the top-level netlist") ; return 5 ; } Message::Msg(VERIFIC_INFO, 0, top->Linefile(), "last elaborated design is %s(%s)", top->Owner()->Name(), top->Name()) ; VeriWrite veriWriter; veriWriter.WriteFile("netlist_out1.v", top); const Net *net = top->GetNet(net_name); if (!net) { Message::Msg(VERIFIC_ERROR, 0, 0, "can't find net '%s'", net_name); return 1 ; } Set fanout(POINTER_HASH) ; top->LabelFanOut (net, fanout, 0, 0, 0); SetIter si; DesignObj *designobj; Set group(POINTER_HASH) ; FOREACH_SET_ITEM (&fanout, si, &designobj) { if (designobj->IsInstance()) { Message::Msg(VERIFIC_INFO, 0, 0, ">> instance '%s'", designobj->Name()); // Insert it in the set that is used for grouping later group.Insert(designobj); } else { // Not an Instance, must be a Net Message::Msg(VERIFIC_INFO, 0, 0, ">> net '%s'", designobj->Name()); } } // Now, let's group the fan-out into a new netlist // Netlist::Group(const Set &instances, const char *inst_name, const char *cell_name, const char *netlist_name) top->Group(group, "new_instance", "new_cell", ""); veriWriter.WriteFile("netlist_out2.v", top); return 0 ; }
Perl script:
#!/usr/bin/perl # This application example collects instances in the fanout cone of a signal, # and groups those instances into a new netlist. push (@INC,"../../../perlmain/install"); require "Verific.pm"; $file_name = "prep2.v"; $net_name = "compare_output"; if (!Verific::veri_file::Analyze($file_name, $Verific::veri_file::VERILOG_2K)) { exit(1) ; } # Ok now let's elaborate this module. In case of failure return. if (!Verific::veri_file::ElaborateAll()) { exit(1) ; } # After elaboration, we can now delete the parse-trees (to conserve memory) since # we don't need them anymore. Verific::veri_file::RemoveAllModules() ; # Get a handle to the top-level netlist $top = Verific::Netlist::PresentDesign() ; if (!$top) { print "Cannot find any handle to the top-level netlist\n"; exit(1) ; } # Print out module that we have handle to vfcprintf("INFO: last elaborated design is %s(%s)",$top->Linefile(),$top->Owner()->Name(), $top->Name()); $veriWriter = Verific::VeriWrite->new(); $veriWriter->WriteFile("netlist1.v", $top) ; my $net = $top->GetNet($net_name); if (!$net) { print "Cannot find net $net_name"; exit(1) ; } my $fanout = Verific::Set::New(); $top->LabelFanOut($net, $fanout, 0, 0, 0); my $group = Verific::Set::New(); $fanout_iter = new Verific::DesignObjSetIter($fanout); if ($fanout_iter) { for ($designobj = $fanout_iter->First(); $fanout_iter->GetIndex() < $fanout_iter->Size(); $designobj = $fanout_iter->Next()) { if ($designobj->IsInstance()) { vfcprintf("INFO: instance %s", undef, $designobj->Name()); # insert the instance in a set that will be used later to create a new level of hierarchy $group->Insert($designobj); } else { vfcprintf("INFO: net %s", undef, $designobj->Name()); } } } # Group the fanout into a new level of hierarchy $top->Group($group, "new_instance", "new_cell", ""); $veriWriter->WriteFile("netlist2.v", $top) ; exit(0) ; # moved this to a subroutine to keep above code clean, # this subroutine shows how to resolve linefile information sub vfcprintf { my ($format) = (@_[0]); my ($lf) = (@_[1]); my @PARAMS; for (my $i = 2; $i < scalar(@_); $i++) { push(@PARAMS,"@_[$i]"); } my $lf_format = ""; if (Verific::LineFile::GetFileName($lf) && Verific::LineFile::GetLineNo($lf)) { my $lf_format = sprintf("%s(%s)",Verific::LineFile::GetFileName($lf), Verific::LineFile::GetLineNo($lf)); printf "%s: $format\n",$lf_format,@PARAMS; } else { printf "$format\n",@PARAMS; } return 0; }
Verilog testcase, prep2.v:
// PREP Benchmark 2, Timer/Counter /* PREP2 contains 8 bit registers, a mux, counter and comparator Copyright (c) 1994 Synplicity, Inc. You may distribute freely, as long as this header remains attached. */ module prep2(DATA0, CLK, RST, SEL, LDCOMP, LDPRE, DATA1, DATA2); output [7:0] DATA0; input CLK, RST, SEL, LDCOMP, LDPRE; input [7:0] DATA1, DATA2; reg [7:0] DATA0; reg [7:0] highreg_output, lowreg_output; // internal registers wire compare_output = DATA0 == lowreg_output; // comparator wire [7:0] mux_output = SEL ? DATA1 : highreg_output; // mux // registers always @ (posedge CLK or posedge RST) begin if (RST) begin highreg_output = 0; lowreg_output = 0; end else begin if (LDPRE) highreg_output = DATA2; if (LDCOMP) lowreg_output = DATA2; end end // counter always @(posedge CLK or posedge RST) begin if (RST) DATA0 = 0; else if (compare_output) // load DATA0 = mux_output; else DATA0 = DATA0 + 1; end endmodule <./nowiki>