1# Copyright (c) 2012 ARM Limited 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions are 15# met: redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer; 17# redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution; 20# neither the name of the copyright holders nor the names of its 21# contributors may be used to endorse or promote products derived from 22# this software without specific prior written permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35# 36# Author: Uri Wiener 37# 38 39# Script which takes two config.ini files and generates a semantic diff. The 40# resulting diff shows which parts of the configurations differed, and in the 41# case that there is a difference it displays it. This allows rapid comparision 42# of two gem5 runs and therefore provides an easy method to ensure that 43# configurations are similar, or not. 44 45#!/usr/bin/perl 46use strict; 47 48die "Please check args... " unless ($#ARGV == 1); 49my $config1FileName = $ARGV[0]; 50my $config2FileName = $ARGV[1]; 51 52# Get just the name of the file, rather than the full path 53my $config1ShortName = getFilenameFromPath($config1FileName); 54my $config2ShortName = getFilenameFromPath($config2FileName); 55 56# If the file names are the same, use the full path 57if ($config1ShortName == $config2ShortName) { 58 $config1ShortName = $config1FileName; 59 $config2ShortName = $config2FileName; 60} 61 62print "\nComparing the following files:\n", 63 "\t$config1FileName\n", 64 "\tvs.\n", 65 "\t$config2FileName\n\n"; 66 67# Read in the two config files 68my %config1 = readConfig($config1FileName); 69my %config2 = readConfig($config2FileName); 70 71# Compare the two config files. For the first comparision we also compare the 72# values (setting the first parameter to 1). There is little point doing this 73# for the second comparison as it will yield the same information. 74compareConfigs( 1, \%config1, $config1ShortName, \%config2, $config2ShortName ); 75compareConfigs( 0, \%config2, $config2ShortName, \%config1, $config1ShortName ); 76 77 78######################################################## 79# Compare values and return unique values 80######################################################## 81sub compareValues { 82 my $values1 = shift; 83 my $values2 = shift; 84 my @splitValues1 = split(/ /, $values1); 85 my @splitValues2 = split(/ /, $values2); 86 my @uniqueValues; 87 88 foreach my $val1 (@splitValues1) { 89 my $foundMatch = 0; 90 91 # if both values equal set match flag, then break loop 92 foreach my $val2 (@splitValues2) { 93 if ($val1 eq $val2) { 94 $foundMatch = 1; 95 last; 96 } 97 98 # in case of ports, ignore port number and match port name only 99 if ($val1 =~ /\[/ and $val2 =~ /\[/) { 100 $val1 =~ m/^(.*)\[.*\]/; 101 my $val1Name = $1; 102 $val2 =~ m/^(.*)\[.*\]/; 103 my $val2Name = $1; 104 105 # if both values equal set match flag, then break loop 106 if ($val1Name eq $val2Name) { 107 $foundMatch = 1; 108 last; 109 } 110 } 111 } 112 113 # Otherwise, the value is unique. 114 if (not $foundMatch) { 115 push(@uniqueValues, $val1); 116 } 117 } 118 119 return join(", ", @uniqueValues); 120} 121 122 123######################################################## 124# Compare two config files. Print differences. 125######################################################## 126sub compareConfigs { 127 my $compareFields = shift; # Specfy if the fields should be compared 128 my $config1Ref = shift; # Config 1 129 my $config1Name = shift; # Config 1 name 130 my $config2Ref = shift; # Config 2 131 my $config2Name = shift; # Config 2 name 132 my @uniqueSections; 133 134 foreach my $sectionName ( sort keys %$config1Ref ) { 135 # check if section exists in config2 136 if ( not exists $config2Ref->{$sectionName} ) { 137 push(@uniqueSections, $sectionName); 138 next; 139 } 140 my %section1 = %{ $config1Ref->{$sectionName} }; 141 my %section2 = %{ $config2Ref->{$sectionName} }; 142 my $firstDifInSection = 1; 143 144 if (not $compareFields) { 145 next; 146 } 147 148 # Compare the values of each field; print any differences 149 foreach my $field ( sort keys %section1 ) { 150 if ($section1{$field} ne $section2{$field}) { 151 my $diff1 = compareValues($section1{$field}, $section2{$field}); 152 my $diff2 = compareValues($section2{$field}, $section1{$field}); 153 154 # If same, skip to next iteration 155 if ($diff1 eq "" and $diff2 eq "") { 156 next; 157 } 158 159 # If it is the first difference in this section, print section 160 # name 161 if ($firstDifInSection) { 162 print "$sectionName\n"; 163 $firstDifInSection = 0; 164 } 165 166 # Print the actual differences 167 print "\t$field\n"; 168 if ($diff1 ne "") { 169 print "\t\t$config1Name: ", $diff1, "\n"; 170 } 171 if ($diff2 ne "") { 172 print "\t\t$config2Name: ", $diff2, "\n"; 173 } 174 } # end if 175 } # end foreach field 176 } # end foreach section 177 178 # If there are unique sections, print them 179 if ($#uniqueSections != -1) { 180 print "Sections which exist only in $config1Name: ", 181 join(", ", @uniqueSections), "\n"; 182 } 183} 184 185 186######################################################## 187# Split the path to get just the filename 188######################################################## 189sub getFilenameFromPath { 190 my $filename = shift; # the input filename including path 191 my @splitName = split(/\//, $filename); 192 return $splitName[$#splitName]; # return just the filename, without path 193} 194 195 196######################################################## 197# Read in the config file section by section. 198######################################################## 199sub readConfig { 200 my $filename = shift; 201 my %config; 202 open CONFIG, "<$filename" or die $!; 203 while ( my $line = <CONFIG> ) { 204 if ( $line =~ /^\[.*\]$/ ) { 205 readSection( $line, \%config ); 206 } 207 } 208 close CONFIG; 209 return %config; 210} 211 212 213######################################################## 214# Read in each section of the config file. 215######################################################## 216sub readSection { 217 my $line = shift; 218 my $config_ref = shift; 219 $line =~ m/\[(.*)\]/; 220 my $sectionName = $1; 221 while ( my $line = <CONFIG> ) { 222 if ( $line =~ /^$/ ) { 223 last; 224 } 225 my @field = split( /=/, $line ); 226 my $fieldName = $field[0]; 227 my $value = $field[1]; 228 chomp $value; 229 $config_ref->{$sectionName}{$fieldName} = $value; 230 } 231} 232