OpenCores
URL https://opencores.org/ocsvn/wb_lcd/wb_lcd/trunk

Subversion Repositories wb_lcd

[/] [wb_lcd/] [trunk/] [verilog/] [wb_lcd/] [tools/] [xdlanalyze/] [xdlanalyze.pl] - Rev 2

Compare with Previous | Blame | View Log

#!/usr/bin/perl -w
#
# xdlanalyze.pl - A script to view some statistics about XDL-files
#
# Copyright (c) 2006 Andreas Ehliar <ehliar@isy.liu.se>
# You may copy or modify this program under the terms of the GNU
# General Public License (version 2 or later)
#
# Usage: xdlanalyze.pl foo.xdl [hierarchy levels]
#
# Example usage:
# $ perl xdlanalyze.pl dafk.xdl
# XDLAnalyze V1.1 by Andreas Ehliar <ehliar@isy.liu.se>
# Analyzing the file dafk.xdl...................................................
# +-------------+--------+--------+--------+-----------+--------+--------+
# | Module      |   LUTS |     FF | RAMB16 | MULT18x18 |    IOB |    DCM |
# +-------------+--------+--------+--------+-----------+--------+--------+
# | /           |     64 |        |        |           |    216 |        |
# | cpu         |   5065 |   1345 |     12 |         4 |        |        |
# | dma0        |    654 |    254 |      1 |           |        |        |
# | dvga        |    816 |    755 |      4 |           |        |        |
# | eth3        |   2995 |   2337 |      4 |           |        |        |
# | jpg0        |   1682 |    681 |      2 |        13 |        |        |
# | leela       |    684 |    552 |      4 |         2 |        |        |
# | pia         |      9 |        |        |           |        |        |
# | pkmc_mc     |    219 |    122 |        |           |        |        |
# | rom0        |    111 |      3 |     12 |           |        |        |
# | sys_sig_gen |        |      6 |        |           |        |      2 |
# | uart2       |    824 |    346 |        |           |        |        |
# | wb_conbus   |    618 |     10 |        |           |        |        |
# +-------------+--------+--------+--------+-----------+--------+--------+
# | Total       |  13741 |   6411 |     39 |        19 |    216 |      2 |
# +-------------+--------+--------+--------+-----------+--------+--------+
#
# Example 2 (showing off hierarchical view of the same design)
# perl xdlanalyze.pl dafk.xdl 1
# XDLAnalyze V1.1 by Andreas Ehliar <ehliar@isy.liu.se>
# Analyzing the file dafk.xdl...................................................
# +-----------------------------+--------+--------+--------+-----------+--------+--------+
# | Module                      |   LUTS |     FF | RAMB16 | MULT18x18 |    IOB |    DCM |
# +-----------------------------+--------+--------+--------+-----------+--------+--------+
# | /                           |     64 |        |        |           |    216 |        |
# | cpu                         |      1 |        |        |           |        |        |
# | cpu/dwb_biu                 |     10 |     72 |        |           |        |        |
# | cpu/iwb_biu                 |     64 |     73 |        |           |        |        |
# | cpu/or1200_cpu              |   4441 |    987 |      2 |         4 |        |        |
# | cpu/or1200_dc_top           |    208 |     40 |      5 |           |        |        |
# | cpu/or1200_ic_top           |    182 |     38 |      5 |           |        |        |
# | cpu/or1200_immu_top         |     11 |     33 |        |           |        |        |
# | cpu/or1200_pic              |     32 |     38 |        |           |        |        |
# | cpu/or1200_tt               |    116 |     64 |        |           |        |        |
# | dma0                        |    617 |    235 |        |           |        |        |
# | dma0/fifo                   |     37 |     19 |      1 |           |        |        |
# | dvga                        |      5 |        |        |           |        |        |
# | dvga/regs                   |    279 |    360 |      3 |           |        |        |
# | dvga/rend                   |    174 |    110 |      1 |           |        |        |
# | dvga/spr                    |    358 |    285 |        |           |        |        |
# | eth3                        |     73 |     51 |        |           |        |        |
# | eth3/Mshreg_WillTransmit_q2 |      1 |        |        |           |        |        |
# | eth3/ethreg1                |    368 |    302 |        |           |        |        |
# | eth3/maccontrol1            |    295 |    103 |        |           |        |        |
# | eth3/macstatus1             |     60 |     18 |        |           |        |        |
# | eth3/miim1                  |    127 |     74 |        |           |        |        |
# | eth3/rxethmac1              |    311 |    107 |        |           |        |        |
# | eth3/txethmac1              |    369 |    119 |        |           |        |        |
# | eth3/wishbone               |   1391 |   1563 |      4 |           |        |        |
# | jpg0                        |    302 |     57 |      2 |           |        |        |
# | jpg0/dct0                   |    599 |    618 |        |        13 |        |        |
# | jpg0/tmem                   |    781 |      6 |        |           |        |        |
# | leela                       |     36 |        |        |           |        |        |
# | leela/cam0                  |    349 |    291 |      4 |         2 |        |        |
# | leela/mc0                   |    129 |     25 |        |           |        |        |
# | leela/regs0                 |    170 |    236 |        |           |        |        |
# | pia                         |      9 |        |        |           |        |        |
# | pkmc_mc/mem_fpga_board_if   |     40 |      1 |        |           |        |        |
# | pkmc_mc/pkmc_mc             |    179 |    121 |        |           |        |        |
# | rom0                        |     77 |      1 |        |           |        |        |
# | rom0/boot_prog_bram         |     34 |      2 |      8 |           |        |        |
# | rom0/boot_ram               |        |        |      4 |           |        |        |
# | sys_sig_gen                 |        |      6 |        |           |        |        |
# | sys_sig_gen/del0            |        |        |        |           |        |      1 |
# | sys_sig_gen/div0            |        |        |        |           |        |      1 |
# | uart2                       |      1 |        |        |           |        |        |
# | uart2/dbg                   |     33 |        |        |           |        |        |
# | uart2/regs                  |    725 |    266 |        |           |        |        |
# | uart2/wb_interface          |     65 |     80 |        |           |        |        |
# | wb_conbus                   |    618 |        |        |           |        |        |
# | wb_conbus/arb               |        |     10 |        |           |        |        |
# +-----------------------------+--------+--------+--------+-----------+--------+--------+
# | Total                       |  13741 |   6411 |     39 |        19 |    216 |      2 |
# +-----------------------------+--------+--------+--------+-----------+--------+--------+
# 
# If you don't want to print all fields, change the @print_order
# declaration below.
# 
# Note that the figures will usually not be exactly the same as the
# figures reported by map. This is partly because map does not count a 
# LUT with a constant output as a LUT, at least not in ISE 8.1.
#
# The program will also automatically convert a .ncd-file to a temporary
# .xdl file before running.
#
# This program has been tested on designs targetted at Virtex-2 and
# Virtex-4 from ISE 8.1 and ISE 8.2 on a Linux based computer. Note
# that it assumes that your path separator is set to /.
#
# Missing features:
#   * Slice count would be nice
#   * Show number of LUTs used as distributed RAM and SRL16
#   * Virtex-5 support
#
# NOTE:
#   The synthesizer will probably optimize your design across module boundaries
#   in some cases. This means that your figures cannot be entirely correct.
 
use strict;
use IO::Handle;
use IO::File;
use POSIX qw(tmpnam);
 
 
use constant {
    LUTS => 1,
    FF => 2,
    IOB => 3,
    RAMB16 => 4,
    MULT_18X18 => 5,
    DSP48 => 6,
    DCM => 7,
    DCM_ADV => 8,
    BUFG => 9,
    };
 
my @translation = ( "UNKNOWN", "LUTS","FF","IOB","RAMB16","MULT18x18",
		    "DSP48", "DCM", "DCM_ADV", "BUFG" );
 
 
# Modify this line to include what you want printed and in what order
my @print_order = ( LUTS, FF, RAMB16, DSP48, MULT_18X18, IOB, DCM,
		    DCM_ADV, BUFG );
 
 
 
########################################################################
my %themodules;
my %hierarchical_usageinfo;
my %usageinfo;
 
# This variable controls how many levels we will keep track of
my $hierarchical_level = 0;
 
######################################################################
# Add a component to the statistics
######################################################################
sub add_component {
    my $thename = $_[0];
    my $thetype = $_[1];
 
    my @temppath = split("/",$thename);
    my @list = ();
    my $currname = $temppath[0];
    my $i;
 
    push(@list,$currname);
 
    for($i = 1; $i < $#temppath; $i = $i  + 1) {
	$currname = "$currname/$temppath[$i]";
	push(@list,$currname);
    }
 
    for($i = $hierarchical_level; $i < $#temppath; $i = $i + 1) {
	$currname = pop(@list);
	if($themodules{$currname}) {
	    $i = $#temppath;
	}
    }
 
 
    if($thename =~ /\//) {
    }else{
# If there is no slash in the name => a component of the top level
	$currname = "/";
    }
 
    my %thehash;
 
    $hierarchical_usageinfo{$currname}{$thetype}++;
    $usageinfo{$thetype}++;
 
    $themodules{$currname} = 1;
}
 
######################################################################
# Analyze an XDL file and collect statistics about component
# usage
######################################################################
 
sub analyze_file {
 
    print "Analyzing the file $_[0]...";
    STDOUT->autoflush(1);
 
    open THEFILE, '<', $_[0] or die;
 
    my $line = 0;
    while (<THEFILE>){
 
	# Progress meter
	$line++;
	if($line == 10000){
	    $line = 0;
	    print(".");
	    STDOUT->autoflush(1);
	}
 
	# Quick and dirty parser that does not keep any state.
	# A real parser would remember what kind of instance we are
	# currently inside in order to keep track of more things such
	# as for example slice usage, etc.
 
	# Both an F and a G LUT can be on the same line
	# So we can't use elseif here.
	if(/ F:([a-zA-Z0-9_\/\[\]<>\.]+:\#([A-Z]+):D=)/) {
	    &add_component($1,LUTS);
	}
 
	if(/ G:([a-zA-Z0-9_\/\[\]<>\.]+:\#([A-Z]+):D=)/) {
	    &add_component($1,LUTS);
	}
 
 
	# Both an FFX and a FFY flip flop can be on the same line
	# So we can't use elseif here.
	if(/FFX:([a-zA-Z0-9_\/\[\]<>\.]+:\#[A-Z]+)/) {
	    &add_component($1,FF);
	}
 
	if(/FFY:([a-zA-Z0-9_\/\[\]<>\.]+:\#[A-Z]+)/) {
	    &add_component($1,FF);
	}
 
	# Check if there is an instance defined on this line
	if(/^inst/) {
	    if(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"IOB\"/){
		&add_component($1,IOB);
	    }elsif(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"RAMB16\"/){
		&add_component($1,RAMB16);
	    }elsif(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"MULT18X18\"/){
		&add_component($1,MULT_18X18);
	    }elsif(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"DSP48\"/){
		&add_component($1,DSP48);
	    }elsif(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"DCM\"/){
		# FIXME - Do we need a check for a dummy DCM?
		&add_component($1,DCM);
	    }elsif(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"DCM_ADV\"/){
		# Check for unused dummy instantiation of DCM_ADV
		if(! /^inst \"XIL_ML_UNUSED_DCM/){
		    &add_component($1,DCM_ADV);
		}
	    }elsif(/^inst \"([a-zA-Z0-9_\/\[\]<>\.]+)\" \"BUFG\"/){
		&add_component($1,BUFG);
	    }
	    # Adding more components here should be easy
	}
 
    }
 
    print "\n";
 
}
 
######################################################################
# Print a line consisting of dashes and plus like the marked lines in
# the following output:
# --> +-------------------+--------+--------+--------+
#     | Module            |   LUTS |     FF |    IOB |
# --> +-------------------+--------+--------+--------+
######################################################################
 
sub print_dashes {
    my $firstlen = $_[0];
    my $inst_order = $_[1];
    my $insttype;
    print "+" . "-" x ($firstlen + 2);
    foreach $insttype (@$inst_order) {
	my $maxlen = length($translation[$insttype]);
	$maxlen = $maxlen < 6 ? 6 : $maxlen;
	print "+" . "-" x ($maxlen + 2);
    }
    printf("+\n");
 
}
 
######################################################################
# Print statistics collected in the %themodules, %usageinfo, and
# %hierarchical_usageinfo hashes.
######################################################################
 
sub print_stats {
 
    my $firstlen;
    my @thekeys = keys %themodules;
    @thekeys = sort(@thekeys);
    my $i;
    my $name;
    my $foo;
    my @inst_order;
 
# Find maximum length of the first field
    $firstlen = length("Module");
    foreach $i (@thekeys) {
	if($firstlen < length($i)){
	    $firstlen = length($i);
	}
    }
 
    my $insttype;
    my $maxlen;
 
# Create inst_order so that we only print statistics about components
# that are actually used in the design.
    foreach $name (@print_order) {
	if($usageinfo{$name}) {
	    push(@inst_order,$name);
	}
    }
 
# Print header
    &print_dashes($firstlen,\@inst_order);
    printf("| %- ${firstlen}s ","Module");
    foreach $insttype (@inst_order) {
	printf("| % 6s ", $translation[$insttype]);
    }
    printf("|\n");
    &print_dashes($firstlen,\@inst_order);
 
 
# Print hierarchical statistics
    foreach $name (@thekeys) {
	printf("| %- ${firstlen}s ",$name);
	foreach $insttype (@inst_order) {
	    $maxlen = length($translation[$insttype]);
	    $maxlen = $maxlen < 6 ? 6 : $maxlen;
	    if($hierarchical_usageinfo{$name}{$insttype}) {
		printf("| % ${maxlen}d ",$hierarchical_usageinfo{$name}{$insttype});
	    }else {
		printf("| % ${maxlen}s "," ");
	    }
	}
	printf("|\n");
    }
 
# Print footer with total number of all components
    &print_dashes($firstlen,\@inst_order);
 
    printf("| %- ${firstlen}s ","Total");
    foreach $insttype (@inst_order) {
	$maxlen = length($translation[$insttype]);
	$maxlen = $maxlen < 6 ? 6 : $maxlen;
	if($usageinfo{$insttype}){
	    printf("| % ${maxlen}d ",$usageinfo{$insttype});
	}else{
	    printf("| % ${maxlen}s "," ");
	}
    }
    printf("|\n");
 
    &print_dashes($firstlen,\@inst_order);
}
 
 
######################################################################
# Main program starts here
######################################################################
 
printf('XDLAnalyze V1.1 by Andreas Ehliar <ehliar@isy.liu.se>'. "\n");
 
if(! $ARGV[0]){
    print STDERR "Usage: xdlanalyze.pl <design.xdl> [hierarchical levels]\n";
    exit 1;
}
 
if($ARGV[1]) {
    $hierarchical_level = $ARGV[1];
}
 
# If the input has a .ncd file extension it will be converted to an .xdl file
if( $ARGV[0] =~ /.ncd$/ ) {
    my $tempname;
    my $fh;
 
    printf("Calling xdl -ncd2xdl to convert .ncd file to .xdl file before running analyzer\n");
 
    # try new temporary filenames until we get one that didn't already exist as per
    # the perl cookbook
    do { $tempname = tmpnam() . ".xdl" }
        until $fh = IO::File->new($tempname, O_RDWR|O_CREAT|O_EXCL);
 
    # Call the xdl tool to convert the file...
    system ("xdl", "-ncd2xdl", $ARGV[0], $tempname) == 0 or die "Couldn't call xdl: $!";
    &analyze_file($tempname);
 
    unlink($tempname) or die "Couldn't unlink $tempname : $!";
 
}else {
    &analyze_file($ARGV[0]);
}
 
 
&print_stats;
 
exit 0;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.