From 86d14e09b6954c79bc93b034795528e714f0010a Mon Sep 17 00:00:00 2001 From: Glen Gibb Date: Wed, 11 Mar 2026 19:09:33 -0700 Subject: [PATCH 1/2] product list: reduce instances visited Reduce the number of instances visited when traversing the instance tree and building the instance list. This is done by halting traversal down a branch when we encounter an instance with a filename we've previously encountered. Need to have separate tracking for synth and verif file names as Manager::create_product_lists wants to know if a module is in both the verify and synth lists. (Although this could potentially be simplified too.) In a test design, the number of nodes visited dropped from over 500K to 12K. Runtime dropped from 29.5s -> 27.1s (avg over 5 runs each). --- PerlLibs/Genesis2/Manager.pm | 4 +- PerlLibs/Genesis2/UniqueModule.pm | 78 +++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/PerlLibs/Genesis2/Manager.pm b/PerlLibs/Genesis2/Manager.pm index 9282ed9..f12f8ef 100644 --- a/PerlLibs/Genesis2/Manager.pm +++ b/PerlLibs/Genesis2/Manager.pm @@ -1326,8 +1326,8 @@ sub create_product_lists { #print { $product_fh } "+incdir+".$self->{SynthDir}." +incdir+".$self->{VerifDir}."\n"; #print { $synth_product_fh } "+incdir+".$self->{SynthDir}."\n"; - # Get a list of all instances in REVERSED DFS order - my @rev_dfs_list = $self->{TopObj}->get_all_insts(); + # Get the product list instances, obtained by a DFS traversal. + my @rev_dfs_list = $self->{TopObj}->get_prod_list_insts($self->{SynthTop}); # Process the list into synth and verif single appearance file list my %seen = (); diff --git a/PerlLibs/Genesis2/UniqueModule.pm b/PerlLibs/Genesis2/UniqueModule.pm index 47a8056..dc89979 100644 --- a/PerlLibs/Genesis2/UniqueModule.pm +++ b/PerlLibs/Genesis2/UniqueModule.pm @@ -973,6 +973,84 @@ sub _get_all_insts { push(@$results, $self); } +## get_prod_list_insts +## Get list of instances for use by Manager::create_product_list. +## This returns the first synth instance and first verif instance for each +## module file name. The list is built via a DFS traversal. +## +## Requires the SynthTop path to identify whether an instance is verif or synth. +sub get_prod_list_insts { + my $self = shift; + my $synth_top = shift; + + # Product list + my @results; + + # Track the file names of the synth and verif instances that are added to + # the list + my %synth_files; + my %verif_files; + + $self->_get_prod_list_insts(\@results, \%synth_files, \%verif_files, 1000, "", $synth_top); + return @results; +} + +## _get_prod_list_insts +## Internal function used to constrtuct the product list returned by +## get_prod_list_insts. +## +## Passes refernces to the array / hashes to avoid unnecessary copying. +sub _get_prod_list_insts { + my $self = shift; + my $results = shift; + my $synth_files = shift; + my $verif_files = shift; + my $depth = shift; + my $path = shift; + my $synth_top = shift; + + $path .= "." if defined $self->{Parent}; + $path .= $self->get_instance_name(); + + my $path_len = length($path); + my $synth_top_len = length($synth_top); + + # An instance is a synthesis instance if it is at or below synth_top. + my $is_synth = + $path eq $synth_top || (substr($path, 0, $synth_top_len + 1) eq $synth_top . "."); + + # An instance is on the synthesis path if it is a synthesis instance or if + # synth_top is below it. + my $on_synth_path = $is_synth || ($path . "." eq substr($synth_top, 0, $path_len + 1)); + + my $file = $self->get_out_file_name(); + +# Check if we've already added an instance with this file name to the synth/verif list as appropariate. + if ( ($is_synth && exists $synth_files->{$file}) + || (!$is_synth && exists $verif_files->{$file} && !$on_synth_path)) + { + return; + } + + # First time seeing this file for synth/verif + if ($is_synth) { + $synth_files->{$file} = 1; + } else { + $verif_files->{$file} = 1; + } + + # Recurse into the child nodes + if ($depth > 0) { + foreach my $inst_name (@{$self->{SubInstanceList}}) { + my $subinst = $self->get_subinst($inst_name); + $subinst->_get_prod_list_insts($results, $synth_files, $verif_files, $depth - 1, $path, + $synth_top); + } + } + + push(@$results, $self); +} + ## get_instance_path ## API method that returns a complete path to the instance object given ## Usage: my $inst_path = $inst_obj->get_instance_path(); From 64d9dd69bdb02113aa7e3a79c795f567d3db753b Mon Sep 17 00:00:00 2001 From: Glen Gibb Date: Thu, 12 Mar 2026 10:31:52 -0700 Subject: [PATCH 2/2] gracefully handle undefined SynthTop --- PerlLibs/Genesis2/UniqueModule.pm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/PerlLibs/Genesis2/UniqueModule.pm b/PerlLibs/Genesis2/UniqueModule.pm index dc89979..e0bc1f8 100644 --- a/PerlLibs/Genesis2/UniqueModule.pm +++ b/PerlLibs/Genesis2/UniqueModule.pm @@ -1009,19 +1009,22 @@ sub _get_prod_list_insts { my $path = shift; my $synth_top = shift; - $path .= "." if defined $self->{Parent}; - $path .= $self->get_instance_name(); + if (defined $synth_top) { + $path .= "." if defined $self->{Parent}; + $path .= $self->get_instance_name(); + } my $path_len = length($path); - my $synth_top_len = length($synth_top); + my $synth_top_len = defined($synth_top) ? length($synth_top) : 0; # An instance is a synthesis instance if it is at or below synth_top. - my $is_synth = - $path eq $synth_top || (substr($path, 0, $synth_top_len + 1) eq $synth_top . "."); + my $is_synth = defined($synth_top) + && ($path eq $synth_top || (substr($path, 0, $synth_top_len + 1) eq $synth_top . ".")); # An instance is on the synthesis path if it is a synthesis instance or if # synth_top is below it. - my $on_synth_path = $is_synth || ($path . "." eq substr($synth_top, 0, $path_len + 1)); + my $on_synth_path = + defined($synth_top) && ($is_synth || ($path . "." eq substr($synth_top, 0, $path_len + 1))); my $file = $self->get_out_file_name();