#!/usr/bin/perl use List::Util 'max'; use warnings; use strict; my $filename = shift || die("Please provide a input STL file"); my $numberOfRows = 16384; my $numberOfBanks = 8; my $numberOfColumns = 1024; my $numberOfBytes = 8; # Byte Offset from e.g. DIMM my $numberOfBits = 32; my $burstLength = 8; my $addressCorrection = 1; my $numberOfRowBits = log($numberOfRows)/log(2); my $numberOfBankBits = log($numberOfBanks)/log(2); my $numberOfColumnBits = log($numberOfColumns)/log(2); my $numberOfByteBits = log($numberOfBytes)/log(2); my $numberOfBurstBits = log($burstLength)/log(2); print "Number of Address Bits:\t".$numberOfBits."\n\n"; print "Number of Row Bits:\t".$numberOfRowBits."\n"; print "Number of Bank Bits:\t".$numberOfBankBits."\n"; print "Number of Col Bits:\t".$numberOfColumnBits."\n"; print ">Burst Bits in Col:\t".$numberOfBurstBits."\n"; print "Number of Byte Bits:\t".$numberOfByteBits."\n"; my $numberOfXBits = $numberOfBits - $numberOfRowBits - $numberOfBankBits - $numberOfColumnBits - $numberOfByteBits; print "Number of Unused Bits:\t".$numberOfXBits."\n"; print "\n"; print "\n"; open(FH, "$filename"); my @activityCounter; my @mapping; # Initialize: for(my $i = 0; $i < $numberOfBits; $i++) { $activityCounter[$i] = 0; } for(my $i = $numberOfXBits-1; $i >= 0; $i--) { $mapping[$numberOfBits-($numberOfXBits-$i)] = "X".$i; } my $old_address = "00000000000000000000000000000000"; while() { # Get the adress: $_ =~ /\d+:\s+\w+\s+0x([\w\d]+)\s*[\d\w]*/; my $address = $1; $address = sprintf( "%0".$numberOfBits."b", hex( $address ) * $addressCorrection ); # $i = 0 :: most significant bit for(my $i = 0; $i < $numberOfBits; $i++) { my $new = substr($address, $i, 1); my $old = substr($old_address, $i, 1); if($new ne $old) { $activityCounter[$numberOfBits-1-$i]++; } } $old_address = $address; } close(FH); # Make Consistency Check: for(my $i = 0; $i < ($numberOfByteBits+$numberOfBankBits); $i++) { if($activityCounter[$i] != 0) { print "Bits of lower C part or Y have toggled, this should not happen\n"; exit -1; } } # Print bit numbers: print "Bits\t\t"; for(my $i = $numberOfBits-1; $i >= 0; $i--) { print $i."\t"; } #Print Activity print "\nActivity\t"; for(my $i = $numberOfBits-1; $i >= 0; $i--) { print $activityCounter[$i]."\t"; } #Print relative Activity print "\nPercent\t\t"; my $sum = 0; my @percent; for(my $i = $numberOfBits-1; $i >= 0; $i--) { $sum = $sum + $activityCounter[$i]; } for(my $i = $numberOfBits-1; $i >= 0; $i--) { my $string = $activityCounter[$i]/$sum*100; $string = sprintf("%.2f", $string); $string =~ s/\./,/g; $percent[$i] = $string."%"; $string .= "%\t"; print $string; } #Fix Byte Offset: for(my $i = 0; $i < $numberOfByteBits; $i++) { $activityCounter[$i] = -1; $mapping[$i] = "Y$i"; } #Fix Constant 0 Bits in Column due to Burstlength: for(my $i=0; $i < $numberOfBurstBits; $i++) { $activityCounter[$numberOfByteBits + $i] = -1; $mapping[$numberOfByteBits + $i] = "C$i"; } #Search Column Locations for(my $i = $numberOfBurstBits; $i < $numberOfColumnBits; $i++) { my $maximum = max(@activityCounter); my ($index) = grep $activityCounter[$_] == $maximum , 0.. $#activityCounter; $mapping[$index] = "C$i"; $activityCounter[$index] = -1; } #Search Bank Locations for(my $i = 0; $i < $numberOfBankBits; $i++) { my $maximum = max(@activityCounter); my ($index) = grep $activityCounter[$_] == $maximum , 0.. $#activityCounter; $mapping[$index] = "B$i"; $activityCounter[$index] = -1; } #Search Row Locations for(my $i = 0; $i < $numberOfRowBits; $i++) { my $maximum = max(@activityCounter); my ($index) = grep $activityCounter[$_] == $maximum , 0.. $#activityCounter; $mapping[$index] = "R$i"; $activityCounter[$index] = -1; } #Print final mapping my $header = ' strict graph G { forcelabels=true; rankdir=LR; { graph [fontname = "courier"]; node [shape=square, fontname="courier", fixedsize=true, width=0.85, height=0.85] edge [fontname = "courier"]; '; for(my $i = $numberOfBits-1; $i >= 0; $i--) { $header .= " $i [pos=\"".($numberOfBits-1-$i).",0!\", xlp=\"-5,0\", label=\"$i\n".$percent[$i]."\" ]\n"; } my $pos = 0; for(my $i = $numberOfXBits-1; $i >= 0; $i--) { my $pos2 = $numberOfBits-$pos-1; $header .= " X$i [ label=\"$pos2\nX$i\" pos=\"$pos,-5!\"]\n"; $pos++; } for(my $i = $numberOfBankBits-1; $i >= 0; $i--) { my $pos2 = $numberOfBits-$pos-1; $header .= " B$i [ label=\"$pos2\nB$i\" pos=\"$pos,-5!\"]\n"; $pos++; } for(my $i = $numberOfRowBits-1; $i >= 0; $i--) { my $pos2 = $numberOfBits-$pos-1; $header .= " R$i [ label=\"$pos2\nR$i\" pos=\"$pos,-5!\"]\n"; $pos++; } for(my $i = $numberOfColumnBits-1; $i >= 0; $i--) { my $pos2 = $numberOfBits-$pos-1; $header .= " C$i [ label=\"$pos2\nC$i\" pos=\"$pos,-5!\"]\n"; $pos++; } for(my $i = $numberOfByteBits-1; $i >= 0; $i--) { my $pos2 = $numberOfBits-$pos-1; $header .= " Y$i [ label=\"$pos2\nY$i\" pos=\"$pos,-5!\"]\n"; $pos++; } $header .= " }\n"; print "\nMapping\t\t"; my $maximum = max(@activityCounter); for(my $i = $numberOfBits-1; $i >= 0; $i--) { if($mapping[$i] =~ /X\d/) { $header .= "$i -- ".$mapping[$i]." [ color=\"grey\"];\n"; } elsif($mapping[$i] =~ /B\d/) { $header .= "$i -- ".$mapping[$i]." [ color=\"green\"];\n"; } elsif($mapping[$i] =~ /R\d/) { $header .= "$i -- ".$mapping[$i]." [ color=\"blue\"];\n"; } elsif($mapping[$i] =~ /C\d/) { $header .= "$i -- ".$mapping[$i]." [ color=\"red\"];\n"; } elsif($mapping[$i] =~ /Y\d/) { $header .= "$i -- ".$mapping[$i]." [ color=\"grey\"];\n"; } print $mapping[$i]."\t"; } $header .= "}"; print "\n"; #Generate Scrambled Trace: #Generate Configuration for 32x32 MUX: # Assumption e.g. 32 bit: # B R C # X X B B B R R R R R R R R R R R R R R C C C C C C C C C C Y Y Y # 31 30 29 27 26 13 12 3 2 0 # A B C D E F # #print "A:".($numberOfBits-1)."\n"; #print "B:".($numberOfBits-$numberOfXBits-1)."\n"; #print "C:".($numberOfBits-$numberOfXBits-$numberOfBankBits-1)."\n"; #print "D:".($numberOfBits-$numberOfXBits-$numberOfBankBits-$numberOfRowBits-1)."\n"; #print "E:".($numberOfBits-$numberOfXBits-$numberOfBankBits-$numberOfRowBits-$numberOfColumnBits-1)."\n"; #print "F:".($numberOfBits-$numberOfXBits-$numberOfBankBits-$numberOfRowBits-$numberOfColumnBits-$numberOfByteBits)."\n"; my @confVectorDecimal; my @checkVector; my $XCounter = 0; my $rowCounter = 0; my $bankCounter = 0; my $columnCounter = 0; my $byteCounter = 0; for(my $i = $numberOfBits-1; $i >= 0; $i--) { if($mapping[$i] =~ /X(\d+)/) { my $idx = $numberOfBits-$numberOfXBits+$1; #print "\$1=".$1." i=".$i." idx=".$idx." mapping=".$mapping[$i]."\n"; $confVectorDecimal[$idx] = $i; $checkVector[$idx] = "X"; } elsif($mapping[$i] =~ /B(\d+)/) { my $idx = $numberOfBits-$numberOfXBits-$numberOfBankBits+$1; #print "\$1=".$1." i=".$i." idx=".$idx." mapping=".$mapping[$i]."\n"; $confVectorDecimal[$idx] = $i; $checkVector[$idx] = "B"; } elsif($mapping[$i] =~ /R(\d+)/) { my $idx = $numberOfBits-$numberOfXBits-$numberOfBankBits-$numberOfRowBits+$1; #print "\$1=".$1." i=".$i." idx=".$idx." mapping=".$mapping[$i]."\n"; $confVectorDecimal[$idx] = $i; $checkVector[$idx] = "R"; } elsif($mapping[$i] =~ /C(\d+)/) { my $idx = $numberOfBits-$numberOfXBits-$numberOfBankBits-$numberOfRowBits-$numberOfColumnBits+$1; #print "\$1=".$1." i=".$i." idx=".$idx." mapping=".$mapping[$i]."\n"; $confVectorDecimal[$idx] = $i; $checkVector[$idx] = "C"; } elsif($mapping[$i] =~ /Y(\d+)/) { my $idx = $numberOfBits-$numberOfXBits-$numberOfBankBits-$numberOfRowBits-$numberOfColumnBits-$numberOfByteBits+$1; #print "\$1=".$1." i=".$i." idx=".$idx." mapping=".$mapping[$i]."\n"; $confVectorDecimal[$idx] = $i; $checkVector[$idx] = "Y"; } } print "\n"; print "\n"; print "Configuration Vector for the mapping "; for(my $m = $numberOfBits-1; $m >= 0; $m--) { print $checkVector[$m]; } print ":\n\n"; for(my $m = $numberOfBits-1; $m >= 0; $m--) { #Debug: print "mux: $m\t-->\t".$confVectorDecimal[$m]."\n"; } print "\n"; print "\n"; for(my $m = $numberOfBits-1; $m >= 0; $m--) { print sprintf( "%05b", $confVectorDecimal[$m] ); } print "\n"; print "\n"; # Generate Graph my $dotname; my $pdfname; my $stlname; if($filename =~ /(.+)\.stl/) { $dotname = $1.".dot"; $pdfname = $1.".pdf"; $stlname = $1."_scram.stl"; open(FH,">$dotname"); print FH $header; close(FH); system("neato -o $pdfname -Tpdf $dotname"); } open(FH, "$filename"); open(SH, ">$stlname"); while() { # Get all the data adress: $_ =~ /(\d+):\s+(\w+)\s+0x([\w\d]+)/; # XXX my $time = $1; my $command = $2; my $address = $3; my $new_address; # Convert to binary: $address = sprintf( "%032b", hex( $address ) ); # Swap adresses: $new_address = ""; for(my $m = $numberOfBits-1; $m >= 0; $m--) { #print $confVectorDecimal[$m]."\n"; $new_address .= substr($address,$numberOfBits-1-$confVectorDecimal[$m],1); } # Convert to Hex: $new_address = sprintf("%X", oct( "0b$new_address" ) ); print SH $time.":\t".$command."\t0x".$new_address."\n"; } close(FH); close(SH);