Fanout cone and grouping

From Verific Design Automation FAQ
Jump to: navigation, search

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 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>