CommunityForums Functional Verification report unused verilog packages

Stats

  • Replies 4
  • Subscribers 75
  • Views 1570
  • Members are here 0

report unused verilog packages

Max Bjurling
Max Bjurling 4 months ago

Hi,

Is there any tool from Cadence that can report unused Verilog packages?

Often the import MyPackage::* statements are left at the top of a module declaration even though the code that was using them has been removed from the module. This causes unnecessary dependencies that may not be detected. So can I get a report of such unused packages from xmelab, JasperGold, Genus, or any other Cadence tool?

Thanks,

Max

  • Reply
  • Cancel
  • Cancel
Parents
  • StephenH
    StephenH 4 months ago

    Hello Max.

    I'm not aware of a built-in way to do this in Xcelium and am not an expert in the other tools like Genus. I can see a way to do this in Xcelium, using a bit of Tcl scripting.

    Just for fun, as it's Friday afternoon, I played around and built an example for you:

    /*
    File: pkg_ref_test.sv

    Run with:
      xrun -clean pkg_ref_test.sv -input "@source chk_pkgs.tcl;chk_pkgs top;exit" ; cat pkgs.log
    */
    package p1;
      parameter P1P = 1;
      typedef enum bit {OK,BAD} p1e;
    endpackage
    package p2;
      localparam P2P = 2;
      class p2c;
        bit b;
      endclass
    endpackage
    module m;
      import p1::*;
      import p2::*;  // redundant
      bit [P1P-1:0] data;
      p1e myenum;
      initial $display(P1P);
    endmodule
    module top;
      m u_m();
    endmodule

    And the script:

    # File: chk_pkgs.tcl
    proc chk_pkgs {top} {
      scope -set $top
      set ofile [open {pkgs.log} "w"]
      puts $ofile "Starting with $top"
      foreach inst [find -instances * -recursive all -absolute] {
        puts $ofile "Checking $inst"
        puts $ofile [describe $inst]

        scope -set $inst
        set desc [scope -describe]

        regexp -line {Dependent packages (.*)\n} $desc -> pkglist
        set pkglist [regexp -all -inline {[a-zA-Z0-9_]+} $pkglist]
        puts $ofile "$inst references packages ($pkglist)"

        # Iterate all the package-qualified names in the scope
        set refs [regexp -all -inline {([a-zA-Z0-9_]+)::[a-zA-Z0-9_]} $desc]
        set num_refs [llength $refs]
        array unset refpkgs
        array set refpkgs {}
        for {set i 1} {$i<$num_refs} {incr i 2} {
          set refpkgs([lindex $refs $i]) 1
        }
        puts $ofile "Used packages: [array names refpkgs]"

        foreach p $pkglist {
          set matches [array names refpkgs -exact $p]
          if {$matches == ""} {
            puts $ofile "Package $p was NOT used in $inst"
          } else {
            puts $ofile "Package $p is required by $inst"
          }
        }
      }
      puts "Done"
      close $ofile
    }

    Run it with the xrun command listed in the SV file, and you should get an output file "pkgs.log" listing each design instance and which packages are used or not used.

    Starting with top
    Checking top.u_m
    top.u_m....instance of module m

    top.u_m references packages (p1 p2)
    Used packages: p1
    Package p1 is required by top.u_m
    Package p2 was NOT used in top.u_m

    It's probably not the most efficient or pretty Tcl code, but hopefully this helps solve your requirement! There is scope to optimise it by caching the results per-module and skipping repeated module instances, but I leave that as an exercise for you ;-)

    Steve

    • Cancel
    • Up +1 Down
    • Reply
    • Cancel
  • Max Bjurling
    Max Bjurling 4 months ago in reply to StephenH

    Wow, thanks a lot! This was really helpful.

    The scope -set $inst command fails if $inst is an instance array, but I added a catch to get further:

    if { [catch {scope -set $inst}]} {
      puts "skipping $inst"
      continue
    }

    Then I will probably add the code to avoid analysing and reporting the same module multiple times, like you suggested. 

    Thanks again!

    Max

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • StephenH
    StephenH 4 months ago in reply to Max Bjurling

    Thanks for the feedback Max.

    Here's a version that handles instance arrays as well:

    proc chk_pkgs {top} {
      scope -set $top
      set ofile [open {pkgs.log} "w"]
      puts $ofile "Starting with $top"
      foreach inst [find -instances * -recursive all -absolute] {
        puts $ofile ">>>>>>>"
        puts $ofile "Checking $inst"
        puts $ofile [describe $inst]
    
        if { [catch {scope -set $inst}] } {
          # catch instance arrays
          if { [regexp {instance array \[\d+:(\d+)\]} [describe $inst]  -> lowerbound] } {
              puts "Found array instance $inst"
              set inst "$inst\[$lowerbound\]"
              puts "Trying to index into array instance: $inst"
              if { [catch {scope -set $inst}] } {
                puts "Failed, skipping $inst"
                continue
              }
          } else {
            puts "Skipping $inst"
            continue
          }
        }
        set desc [scope -describe]
    
        regexp -line {Dependent packages (.*)\n} $desc -> pkglist
        set pkglist [regexp -all -inline {[a-zA-Z0-9_]+} $pkglist]
        puts $ofile "$inst references packages ($pkglist)"
    
        # Iterate all the package-qualified names in the scope
        set refs [regexp -all -inline {([a-zA-Z0-9_]+)::[a-zA-Z0-9_]} $desc]
        set num_refs [llength $refs]
        array unset refpkgs
        array set refpkgs {}
        for {set i 1} {$i<$num_refs} {incr i 2} {
          set refpkgs([lindex $refs $i]) 1
        }
        puts $ofile "Used packages: [array names refpkgs]"
    
        foreach p $pkglist {
          set matches [array names refpkgs -exact $p]
          if {$matches == ""} {
            puts $ofile "Package $p was NOT used in $inst"
          } else {
            puts $ofile "Package $p is required by $inst"
          }
        }
      }
      puts "Done"
      close $ofile
    }
    
    
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Reply
  • StephenH
    StephenH 4 months ago in reply to Max Bjurling

    Thanks for the feedback Max.

    Here's a version that handles instance arrays as well:

    proc chk_pkgs {top} {
      scope -set $top
      set ofile [open {pkgs.log} "w"]
      puts $ofile "Starting with $top"
      foreach inst [find -instances * -recursive all -absolute] {
        puts $ofile ">>>>>>>"
        puts $ofile "Checking $inst"
        puts $ofile [describe $inst]
    
        if { [catch {scope -set $inst}] } {
          # catch instance arrays
          if { [regexp {instance array \[\d+:(\d+)\]} [describe $inst]  -> lowerbound] } {
              puts "Found array instance $inst"
              set inst "$inst\[$lowerbound\]"
              puts "Trying to index into array instance: $inst"
              if { [catch {scope -set $inst}] } {
                puts "Failed, skipping $inst"
                continue
              }
          } else {
            puts "Skipping $inst"
            continue
          }
        }
        set desc [scope -describe]
    
        regexp -line {Dependent packages (.*)\n} $desc -> pkglist
        set pkglist [regexp -all -inline {[a-zA-Z0-9_]+} $pkglist]
        puts $ofile "$inst references packages ($pkglist)"
    
        # Iterate all the package-qualified names in the scope
        set refs [regexp -all -inline {([a-zA-Z0-9_]+)::[a-zA-Z0-9_]} $desc]
        set num_refs [llength $refs]
        array unset refpkgs
        array set refpkgs {}
        for {set i 1} {$i<$num_refs} {incr i 2} {
          set refpkgs([lindex $refs $i]) 1
        }
        puts $ofile "Used packages: [array names refpkgs]"
    
        foreach p $pkglist {
          set matches [array names refpkgs -exact $p]
          if {$matches == ""} {
            puts $ofile "Package $p was NOT used in $inst"
          } else {
            puts $ofile "Package $p is required by $inst"
          }
        }
      }
      puts "Done"
      close $ofile
    }
    
    
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Children
  • Max Bjurling
    Max Bjurling 8 days ago in reply to StephenH

    Thanks again! I have added the code to only report each module once, and some minor corrections:

    #-------------------------------------------------------------------------------
    # list all unused packages
    #
    # This script is based on the script provided by StephenH in the Cadence
    # Functional Verification forum:
    # community.cadence.com/.../report-unused-verilog-packages
    #-------------------------------------------------------------------------------
    proc list_unused_packages {top} {
        scope -set $top
        set logfile_name "./log/list_unused_packages.log"
        set ofile_name "./report/${top}_unused_packages.txt"
        set logfile [open $logfile_name "w"]
        set ofile [open $ofile_name "w"]

        puts "Listing unused packages in $top and subdesigns."
        puts "  Report file: ${ofile_name}"
        #puts "  Log file: ${logfile_name}"

        puts ${ofile} "--------------------------------------------------------------------------------"
        puts ${ofile} "Unused packages in $top and submodules"
        puts ${ofile} "--------------------------------------------------------------------------------"

        set insts [concat $top [find -instances * -recursive all -absolute]]
    #    lappend insts $top

        foreach inst $insts {
            puts $logfile ">>>>>>>"
            puts $logfile "Checking $inst"
            set dscr [describe $inst]
            puts $logfile $dscr

            # module/interface name is the last word in description
            set mod [lindex $dscr [expr [llength $dscr] - 1] ]

            # Top level module is descibed differently
            if {$mod eq "module"} {
                set mod [lindex [split $dscr {.}] 0]
            }

            if { [catch {scope -set $inst}] } {
                # catch instance arrays
                if { [regexp {instance array \[\d+:(\d+)\]} [describe $inst]  -> lowerbound] } {
                    puts $logfile "Found array instance $inst"
                    set inst "$inst\[$lowerbound\]"
                    puts $logfile "Trying to index into array instance: $inst"
                    if { [catch {scope -set $inst}] } {
                        puts $logfile "Failed, skipping $inst"
                        continue
                    }
                } else {
                    puts $logfile "Skipping $inst"
                    continue
                }
            }

            if { ![info exists modules($mod)] } {
                puts $logfile "Analyzing module $mod"
                puts $logfile [scope -describe]
                set desc [scope -describe]

                set pkglist {}
                regexp -line {Dependent packages (.*)\n} $desc -> pkglist
                set pkglist [regexp -all -inline {[a-zA-Z0-9_]+} $pkglist]
                puts $logfile "$inst references packages ($pkglist)"

                # Iterate all the package-qualified names in the scope
                set refs [regexp -all -inline {([a-zA-Z0-9_]+)::[a-zA-Z0-9_]} $desc]
                set num_refs [llength $refs]
                array unset refpkgs
                array set refpkgs {}
                for {set i 1} {$i<$num_refs} {incr i 2} {
                    set refpkgs([lindex $refs $i]) 1
                }
                puts $logfile "Used packages: [array names refpkgs]"

                foreach p $pkglist {
                    set matches [array names refpkgs -exact $p]
                    if {$matches == ""} {
                        puts $ofile "$mod : $p"
                        puts $logfile "Package $p is NOT used in $inst"
                    } else {
                        puts $logfile "Package $p is required by $inst"
                    }
                }
                set modules($mod) 1
            } else {
                puts $logfile "Already analyzed module $mod"
            }

        }
        puts "Done"
        close $logfile
        close $ofile
    }

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.