| # Copyright (c) 2012 ARM Limited |
| # All rights reserved. |
| # |
| # The license below extends only to copyright in the software and shall |
| # not be construed as granting a license to any other intellectual |
| # property including but not limited to intellectual property relating |
| # to a hardware implementation of the functionality of the software |
| # licensed hereunder. You may use the software subject to the license |
| # terms below provided that you ensure that this notice is replicated |
| # unmodified and in its entirety in all distributions of the software, |
| # modified or unmodified, in source code or in binary form. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer; |
| # redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution; |
| # neither the name of the copyright holders nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| # |
| # Author: Uri Wiener |
| # |
| |
| # Script which takes two config.ini files and generates a semantic diff. The |
| # resulting diff shows which parts of the configurations differed, and in the |
| # case that there is a difference it displays it. This allows rapid comparision |
| # of two gem5 runs and therefore provides an easy method to ensure that |
| # configurations are similar, or not. |
| |
| #!/usr/bin/perl |
| use strict; |
| |
| die "Please check args... " unless ($#ARGV == 1); |
| my $config1FileName = $ARGV[0]; |
| my $config2FileName = $ARGV[1]; |
| |
| # Get just the name of the file, rather than the full path |
| my $config1ShortName = getFilenameFromPath($config1FileName); |
| my $config2ShortName = getFilenameFromPath($config2FileName); |
| |
| # If the file names are the same, use the full path |
| if ($config1ShortName == $config2ShortName) { |
| $config1ShortName = $config1FileName; |
| $config2ShortName = $config2FileName; |
| } |
| |
| print "\nComparing the following files:\n", |
| "\t$config1FileName\n", |
| "\tvs.\n", |
| "\t$config2FileName\n\n"; |
| |
| # Read in the two config files |
| my %config1 = readConfig($config1FileName); |
| my %config2 = readConfig($config2FileName); |
| |
| # Compare the two config files. For the first comparision we also compare the |
| # values (setting the first parameter to 1). There is little point doing this |
| # for the second comparison as it will yield the same information. |
| compareConfigs( 1, \%config1, $config1ShortName, \%config2, $config2ShortName ); |
| compareConfigs( 0, \%config2, $config2ShortName, \%config1, $config1ShortName ); |
| |
| |
| ######################################################## |
| # Compare values and return unique values |
| ######################################################## |
| sub compareValues { |
| my $values1 = shift; |
| my $values2 = shift; |
| my @splitValues1 = split(/ /, $values1); |
| my @splitValues2 = split(/ /, $values2); |
| my @uniqueValues; |
| |
| foreach my $val1 (@splitValues1) { |
| my $foundMatch = 0; |
| |
| # if both values equal set match flag, then break loop |
| foreach my $val2 (@splitValues2) { |
| if ($val1 eq $val2) { |
| $foundMatch = 1; |
| last; |
| } |
| |
| # in case of ports, ignore port number and match port name only |
| if ($val1 =~ /\[/ and $val2 =~ /\[/) { |
| $val1 =~ m/^(.*)\[.*\]/; |
| my $val1Name = $1; |
| $val2 =~ m/^(.*)\[.*\]/; |
| my $val2Name = $1; |
| |
| # if both values equal set match flag, then break loop |
| if ($val1Name eq $val2Name) { |
| $foundMatch = 1; |
| last; |
| } |
| } |
| } |
| |
| # Otherwise, the value is unique. |
| if (not $foundMatch) { |
| push(@uniqueValues, $val1); |
| } |
| } |
| |
| return join(", ", @uniqueValues); |
| } |
| |
| |
| ######################################################## |
| # Compare two config files. Print differences. |
| ######################################################## |
| sub compareConfigs { |
| my $compareFields = shift; # Specfy if the fields should be compared |
| my $config1Ref = shift; # Config 1 |
| my $config1Name = shift; # Config 1 name |
| my $config2Ref = shift; # Config 2 |
| my $config2Name = shift; # Config 2 name |
| my @uniqueSections; |
| |
| foreach my $sectionName ( sort keys %$config1Ref ) { |
| # check if section exists in config2 |
| if ( not exists $config2Ref->{$sectionName} ) { |
| push(@uniqueSections, $sectionName); |
| next; |
| } |
| my %section1 = %{ $config1Ref->{$sectionName} }; |
| my %section2 = %{ $config2Ref->{$sectionName} }; |
| my $firstDifInSection = 1; |
| |
| if (not $compareFields) { |
| next; |
| } |
| |
| # Compare the values of each field; print any differences |
| foreach my $field ( sort keys %section1 ) { |
| if ($section1{$field} ne $section2{$field}) { |
| my $diff1 = compareValues($section1{$field}, $section2{$field}); |
| my $diff2 = compareValues($section2{$field}, $section1{$field}); |
| |
| # If same, skip to next iteration |
| if ($diff1 eq "" and $diff2 eq "") { |
| next; |
| } |
| |
| # If it is the first difference in this section, print section |
| # name |
| if ($firstDifInSection) { |
| print "$sectionName\n"; |
| $firstDifInSection = 0; |
| } |
| |
| # Print the actual differences |
| print "\t$field\n"; |
| if ($diff1 ne "") { |
| print "\t\t$config1Name: ", $diff1, "\n"; |
| } |
| if ($diff2 ne "") { |
| print "\t\t$config2Name: ", $diff2, "\n"; |
| } |
| } # end if |
| } # end foreach field |
| } # end foreach section |
| |
| # If there are unique sections, print them |
| if ($#uniqueSections != -1) { |
| print "Sections which exist only in $config1Name: ", |
| join(", ", @uniqueSections), "\n"; |
| } |
| } |
| |
| |
| ######################################################## |
| # Split the path to get just the filename |
| ######################################################## |
| sub getFilenameFromPath { |
| my $filename = shift; # the input filename including path |
| my @splitName = split(/\//, $filename); |
| return $splitName[$#splitName]; # return just the filename, without path |
| } |
| |
| |
| ######################################################## |
| # Read in the config file section by section. |
| ######################################################## |
| sub readConfig { |
| my $filename = shift; |
| my %config; |
| open CONFIG, "<$filename" or die $!; |
| while ( my $line = <CONFIG> ) { |
| if ( $line =~ /^\[.*\]$/ ) { |
| readSection( $line, \%config ); |
| } |
| } |
| close CONFIG; |
| return %config; |
| } |
| |
| |
| ######################################################## |
| # Read in each section of the config file. |
| ######################################################## |
| sub readSection { |
| my $line = shift; |
| my $config_ref = shift; |
| $line =~ m/\[(.*)\]/; |
| my $sectionName = $1; |
| while ( my $line = <CONFIG> ) { |
| if ( $line =~ /^$/ ) { |
| last; |
| } |
| my @field = split( /=/, $line ); |
| my $fieldName = $field[0]; |
| my $value = $field[1]; |
| chomp $value; |
| $config_ref->{$sectionName}{$fieldName} = $value; |
| } |
| } |