Lesson6: Backend verification given 5-stage pipeline CPU

Given MIPS instructions file(cmd.txt), the output file of waveform(verify.csv), verify if it is matched between the computation by perl and the signals from waveforms.

#!/usr/local/bin/perl
use strict;
use warnings;


sub substore_data;
sub subout_analysis;


sub substorei;
sub substore;
sub subload;
sub suband;
sub subandi;
sub subor;
sub subori;
sub subxor;
sub subxori;
sub subnop;
sub subadd;
sub subaddi;
sub submul;
sub submuli;
sub subreverse_addr;
sub subreverse_data;

#####################################
#            Part 1                 #
#####################################


my $file = '1.txt'; # Name the file
open(INFO, $file); # Open the file
my @lines = ; # Read it into an array
close(INFO); # Close the file

my $file_write = '2.txt';
open(my $fh, '>', $file_write) or die "Could not open file '$file_write' $!";

my $n=0;
my $string;
my @instructions = ();

while($n=3) {
                # STOREI 2 10H #0F0F #F0F0
                if($short_ID[1]==2) {
                    if($#short_ID==4) {
                        ##############################
                        # convert hex to binary addr #
                        ##############################
                        chop($short_ID[2]);
                        my @bin_judg = split(/[\t]*/, $short_ID[2]);
                        if(@bin_judg==2) {
                            $short_ID[2] = sprintf( "%b", hex( $short_ID[2]));
                            @bin_judg = split(/[\t]*/, $short_ID[2]);
                        }
                        if(@bin_judg==5) {
                            if($bin_judg[4]!=0) {
                                print "Error001: Command STOREI is not aligned properly\n";
                            } else {
                                $STOREI_flag = 1;
                                ##############################
                                # convert binary to hex addr #
                                ##############################
                                $short_ID[2] = oct("0b".$short_ID[2]);
                                $short_ID[2] = (sprintf("%x",$short_ID[2])."H");    
                                chop($short_ID[2]);
                                my $addr0=(hex($short_ID[2]));
                                my $addr1=(hex($short_ID[2])+1);
                                $addr0 = (sprintf("%x",$addr0)."H");
                                $addr1 = (sprintf("%x",$addr1)."H");
                                $instruction0 = "STOREI $addr0 $short_ID[3]";
                                $instruction1 = "STOREI $addr1 $short_ID[4]";
                            }
                        }
                    } else {
                        print "Error000: Command STOREI has invalid burst length\n";
                    }
                }
            }
            # STOREI 10H #0F0F
            elsif($#short_ID==2) {
                ####################
                # STOREI 10H #0F0F #
                ####################
            }
            else{
                print "Error000: Command STOREI has invalid burst length\n";
            }
        }

        # STORE has RAW with AND, ANDI, OR, ORI, XOR, XORI, ADD, ADDI, MUL, MULI
        elsif($short_ID[0] eq "STORE") {
                # WB stage
            if($short_WB[0] eq "AND" || $short_WB[0] eq "ANDI" || $short_WB[0] eq "OR" ||  $short_WB[0] eq "ORI" || $short_WB[0] eq "XOR"  || $short_WB[0] eq "XORI" || $short_WB[0] eq "ADD" ||  $short_WB[0] eq "ADDI" ||  $short_WB[0] eq "MUL" ||  $short_WB[0] eq "MULI") {
                #$BUBBLES = 1;
                chomp($short_WB[1]);
                chomp($short_ID[2]);
                if(($short_WB[1])eq($short_ID[2])) {
                $BUBBLES = 1;
                }
            }
            # MEM stage
            if($short_MEM[0] eq "AND" || $short_MEM[0] eq "ANDI" || $short_MEM[0] eq "OR" ||  $short_MEM[0] eq "ORI" || $short_MEM[0] eq "XOR"  || $short_MEM[0] eq "XORI" || $short_MEM[0] eq "ADD" ||  $short_MEM[0] eq "ADDI" ||  $short_MEM[0] eq "MUL" ||  $short_MEM[0] eq "MULI") {
                #$BUBBLES = 2;          
                chomp($short_MEM[1]);
                chomp($short_ID[2]);
                if(($short_MEM[1])eq($short_ID[2])) {
                $BUBBLES = 2;
                }
            }
            # EX stage
            if($short_EX[0] eq "AND" || $short_EX[0] eq "ANDI" || $short_EX[0] eq "OR" ||  $short_EX[0] eq "ORI" || $short_EX[0] eq "XOR"  || $short_EX[0] eq "XORI" || $short_EX[0] eq "ADD" ||  $short_EX[0] eq "ADDI" ||  $short_EX[0] eq "MUL" ||  $short_EX[0] eq "MULI") {
                #$BUBBLES = 3;
                chomp($short_EX[1]);
                chomp($short_ID[2]);
                if(($short_EX[1])eq($short_ID[2])) {
                $BUBBLES = 3;
                }
            } 
            my $i = 0;
            while($i< $BUBBLES) {
                print $fh "NOP\n";
                $i=$i+1;
            }
        }

        # LOAD has RAW with STORE, STOREI
        elsif($short_ID[0] eq "LOAD") {
            # WB stage
            if($short_WB[0]=~/STORE/ || $short_WB[0]=~/STOREI/) {
                #$BUBBLES = 1;
                if($short_WB[1]=~/H/ && $short_ID[2]=~/H/) {
                    chomp($short_WB[1]);
                    chomp($short_ID[2]);
                    if(($short_WB[1])eq($short_ID[2])) {
                    $BUBBLES = 1;
                    }
                }
            }
            # MEM stage
            if($short_MEM[0]=~/STORE/ || $short_MEM[0]=~/STOREI/) {
                #$BUBBLES = 2;
                if($short_MEM[1]=~/H/ && $short_ID[2]=~/H/) {
                    chomp($short_MEM[1]);
                    chomp($short_ID[2]);
                    if(($short_MEM[1])eq($short_ID[2])) {
                    $BUBBLES = 2;
                    }
                }
            }
            # EX stage
            if($short_EX[0]=~/STORE/ || $short_EX[0]=~/STOREI/) {
                #$BUBBLES = 3;
                if($short_EX[1]=~/H/ && $short_ID[2]=~/H/) {
                    chomp($short_EX[1]);
                    chomp($short_ID[2]);
                    if(($short_EX[1])eq($short_ID[2])) {
                    $BUBBLES = 3;
                    }
                }
            } 
            my $i = 0;
            while($i< $BUBBLES) {
                print $fh "NOP\n";
                $i=$i+1;
            }
        }

        # AND OR XOR ADD MUL has RAW with LOAD AND ANDI OR ORI XOR XORI ADD ADDI MUL MULI
        elsif($short_ID[0] eq "AND" || $short_ID[0] eq "OR" || $short_ID[0] eq "XOR" || $short_ID[0] eq "ADD" || $short_ID[0] eq "MUL") {
                # WB stage
            if($short_WB[0] eq "LOAD" || $short_WB[0] eq "AND" || $short_WB[0] eq "ANDI" || $short_WB[0] eq "OR" ||  $short_WB[0] eq "ORI" || $short_WB[0] eq "XOR"  || $short_WB[0] eq "XORI" || $short_WB[0] eq "ADD" ||  $short_WB[0] eq "ADDI" ||  $short_WB[0] eq "MUL" ||  $short_WB[0] eq "MULI") {
                #$BUBBLES = 1;
                chomp($short_WB[1]);
                chomp($short_ID[2]);
                chomp($short_ID[3]);
                if(($short_WB[1])eq($short_ID[2]) || ($short_WB[1])eq($short_ID[3])) {
                $BUBBLES = 1;
                }
            }
            # MEM stage
            if($short_MEM[0] eq "LOAD" || $short_MEM[0] eq "AND" || $short_MEM[0] eq "ANDI" || $short_MEM[0] eq "OR" ||  $short_MEM[0] eq "ORI" || $short_MEM[0] eq "XOR"  || $short_MEM[0] eq "XORI" || $short_MEM[0] eq "ADD" ||  $short_MEM[0] eq "ADDI" ||  $short_MEM[0] eq "MUL" ||  $short_MEM[0] eq "MULI") {
                #$BUBBLES = 2;
                chomp($short_MEM[1]);
                chomp($short_ID[2]);
                chomp($short_ID[3]);
                if(($short_MEM[1])eq($short_ID[2]) || ($short_MEM[1])eq($short_ID[3])) {
                $BUBBLES = 2;
                }
            }
            # EX stage
            if($short_EX[0] eq "LOAD" || $short_EX[0] eq "AND" || $short_EX[0] eq "ANDI" || $short_EX[0] eq "OR" ||  $short_EX[0] eq "ORI" || $short_EX[0] eq "XOR"  || $short_EX[0] eq "XORI" || $short_EX[0] eq "ADD" ||  $short_EX[0] eq "ADDI" ||  $short_EX[0] eq "MUL" ||  $short_EX[0] eq "MULI") {
                #$BUBBLES = 3;
                chomp($short_EX[1]);
                chomp($short_ID[2]);
                chomp($short_ID[3]);
                if(($short_EX[1])eq($short_ID[2]) || ($short_EX[1])eq($short_ID[3])) {
                $BUBBLES = 3;
                }   
            } 
            my $i = 0;
            while($i< $BUBBLES) {
                print $fh "NOP\n";
                $i=$i+1;
            }
        }
        # ANDI ORI XORI ADDI MULI has RAW with LOAD AND ANDI OR ORI XOR XORI ADD ADDI MUL MULI
        elsif($short_ID[0] eq "ANDI" || $short_ID[0] eq "ORI" || $short_ID[0] eq "XORI" || $short_ID[0] eq "ADDI" || $short_ID[0] eq "MULI") {
            # WB stage
            if($short_WB[0] eq "LOAD" || $short_WB[0] eq "AND" || $short_WB[0] eq "ANDI" || $short_WB[0] eq "OR" ||  $short_WB[0] eq "ORI" || $short_WB[0] eq "XOR"  || $short_WB[0] eq "XORI" || $short_WB[0] eq "ADD" ||  $short_WB[0] eq "ADDI" ||  $short_WB[0] eq "MUL" ||  $short_WB[0] eq "MULI") {
                #$BUBBLES = 1;
                chomp($short_WB[1]);
                chomp($short_ID[2]);
                if(($short_WB[1])eq($short_ID[2])) {
                $BUBBLES = 1;
                }
            }
            # MEM stage
            if($short_MEM[0] eq "LOAD" || $short_MEM[0] eq "AND" || $short_MEM[0] eq "ANDI" || $short_MEM[0] eq "OR" ||  $short_MEM[0] eq "ORI" || $short_MEM[0] eq "XOR"  || $short_MEM[0] eq "XORI" || $short_MEM[0] eq "ADD" ||  $short_MEM[0] eq "ADDI" ||  $short_MEM[0] eq "MUL" ||  $short_MEM[0] eq "MULI") {
                #$BUBBLES = 2;
                chomp($short_MEM[1]);
                chomp($short_ID[2]);
                if(($short_MEM[1])eq($short_ID[2])) {
                $BUBBLES = 2;
                }
            }
            # EX stage
            if($short_EX[0] eq "LOAD" || $short_EX[0] eq "AND" || $short_EX[0] eq "ANDI" || $short_EX[0] eq "OR" ||  $short_EX[0] eq "ORI" || $short_EX[0] eq "XOR"  || $short_EX[0] eq "XORI" || $short_EX[0] eq "ADD" ||  $short_EX[0] eq "ADDI" ||  $short_EX[0] eq "MUL" ||  $short_EX[0] eq "MULI") {
                #$BUBBLES = 3;
                chomp($short_EX[1]);
                chomp($short_ID[2]);
                if(($short_EX[1])eq($short_ID[2])) {
                $BUBBLES = 3;
                }   
            } 
            my $i = 0;
            while($i< $BUBBLES) {
                print $fh "NOP\n";
                $i=$i+1;
            }
        }
        elsif($short_ID[0]=~/NOP/) {
            # print $fh "NOP\n";
        }

        else {
        print "Error001: No Such Command Found!","\n";
        }
        
        my $j = 0;
        while($j< $BUBBLES) {
            $WB_instruction = $MEM_instruction;
            $MEM_instruction = $EX_instruction;
            $EX_instruction = "NOP";
            $BUBBLES = $BUBBLES-1;
        }
        if($STOREI_flag == 0) {
            print $fh "$ID_instruction\n";
            $WB_instruction = $MEM_instruction;
            $MEM_instruction = $EX_instruction;
            $EX_instruction = $ID_instruction;
        } elsif($STOREI_flag == 1) {
            print $fh "$instruction0\n";
            print $fh "$instruction1\n";
            $STOREI_flag = $STOREI_flag-1;

            $WB_instruction = $MEM_instruction;
            $MEM_instruction = $EX_instruction;
            $EX_instruction = $instruction0;

            $WB_instruction = $MEM_instruction;
            $MEM_instruction = $EX_instruction;
            $EX_instruction = $instruction1;
        }
}

print $fh "NOP\n";
print $fh "NOP\n";
print $fh "NOP\n";
print $fh "NOP\n";

close $fh;
print "Part 1 done\n";
print "\n";
print "\n";


#####################################
#            Part 2                 #
#####################################


$file = '2.txt'; # Name the file
open(INFO, $file); # Open the file
@lines = ; # Read it into an array
close(INFO); # Close the file


my @addr=(0,1,2,3,4,5,6,7,  8,9,10,11,12,13,14,15,  16,17,18,19,20,21,22,23,  24,25,26,27,28,29,30,31);
my @data=(0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0);
my $data_n=0;
my @load_addr=(0,0,0,0,0,0,0);
my $load_n=0;
my @reg=(0,0,0,0,0,0,0,0); 


$n=0;
while($n<@lines)
{
    $string = $lines[$n];
    $n=$n+1;
    chomp $string;
    my @short = split(/[\s]+/, $string);
    my $new = $string;
    chomp $new;
    if($new eq "") {
    #last;
    }
    else {
        print "$string\n";
        if($short[0] eq "STOREI")
        {
            &substorei(@short);
        }
        
        elsif($short[0] eq "STORE")
        {
            &substore(@short);
        }

        elsif($short[0] eq "LOAD")
        {
            &subload(@short);
        }

        elsif($short[0] eq "AND")
        {
            &suband(@short);
        }

        elsif($short[0] eq "ANDI")
        {
            &subandi(@short);
        }

        elsif($short[0] eq "OR")
        {
            &subor(@short);
        }

        elsif($short[0] eq "ORI")
        {
            &subori(@short);
        }

        elsif($short[0] eq "XOR")
        {
            &subxor(@short);
        }

        elsif($short[0] eq "XORI")
        {
            &subxori(@short);
        }

        elsif($short[0] eq "NOP")
        {
            &subnop(@short);
        }

        elsif($short[0] eq "ADD")
        {
            &subadd(@short);
        }

        elsif($short[0] eq "ADDI")
        {
            &subaddi(@short);
        }

        elsif($short[0] eq "MUL")
        {
            &submul(@short);
        }

        elsif($short[0] eq "MULI")
        {
            &submuli(@short);
        }
    }
}


my @string_com=subout_analysis($load_n);

print "\nload_n = $load_n\n\n";

for (my $i=0; $i < $load_n; $i++)
{
    # print "$string_com[$i]\t";
    for (my $j=0; $j <@load_addr; $j++)
    {
        if($load_addr[$i]==$addr[$j] && $string_com[$i]==$data[$j] )
        {
            print "load_addr=$load_addr[$i]\t\tdata=$data[$j]\n";
            $j=@load_addr;
            print "The $i data match!\n";
        }
    }
    # print "\n";
}

print "Part 2 done\n";

#####subroutine#####
sub substorei
{
    my @storestring = @_ ;
    shift @storestring;
      
    my @bin_judg = split(/[\t]*/, $storestring[0]);
    
    if(@bin_judg==6)  #if it is binary, convert it to hex
    {
        chop($storestring[0]);
        $storestring[0] = oct("0b".$storestring[0]);
        $storestring[0] = (sprintf("%x",$storestring[0])."H"); #convert binary to hex
    }
    
    if ($storestring[0]=~ /H/)
    {
        chop($storestring[0]);
        if($storestring[1]=~"#")
        {
            &substore_data(hex($storestring[0]),hex(substr($storestring[1], 1)));
            my $temp = hex(substr($storestring[1], 1));
            # print "$temp\n";
            # print "$storestring[1]\n";
        }
    }
 }

sub substore
{
    my @storestring = @_ ;
    shift @storestring;
      
    my @bin_judg = split(/[\t]*/, $storestring[0]);
    
    if(@bin_judg==6)  #if it is binary, convert it to hex
    {
        chop($storestring[0]);
        $storestring[0] = oct("0b".$storestring[0]);
        $storestring[0] = (sprintf("%x",$storestring[0])."H"); #convert binary to hex
    }
    
    if ($storestring[0]=~ /H/)
    {
        chop($storestring[0]);
        my @rt = split(/[\t]*/, $storestring[1]);      
        &substore_data(hex($storestring[0]),$reg[$rt[1]]);  
        # print "$rt[1] reg = $reg[$rt[1]]\n";
    }
 }

sub substore_data
{
    my $sign=0;
    for (my $i=0; $i <@addr; $i++)
    { 
        if($addr[$i]==$_[0])
        {
            $data[$i]=$_[1];
            $sign=1;
            # print "$i\t$addr[$i]\t$data[$i]\n";
        }
        if ($i==@addr-1 && $sign==0)
        {
            $addr[$data_n]=$_[0];
            $data[$data_n]=$_[1];
            # print "$i\t$data_n\t$addr[$data_n]\t$data[$data_n]\n";
            $data_n += 1;
        }
    }

}

sub subload
{
    my @loadstring = @_ ;
    shift @loadstring;
    
    
    my @bin_judg_l = split(/[\t]*/, $loadstring[1]);
    
    if(@bin_judg_l==6)  #if it is binary, convert it to hex
    {
        chop($loadstring[1]);
        $loadstring[1] = oct("0b".$loadstring[1]);
        $loadstring[1] = (sprintf("%x",$loadstring[1])."H"); #convert binary to hex
    }
    
    if ($loadstring[1]=~ /H/)
    {
        chop($loadstring[1]);
        my @rt = split(/[\t]*/, $loadstring[0]);
        if($rt[1]==0) {
            $load_addr[$load_n]=hex($loadstring[1]);  
            $load_n = $load_n+1;
        } else {
            # load value from addr to reg
            $reg[$rt[1]] = $data[hex($loadstring[1])];
            # print "$rt[1] reg = $reg[$rt[1]]\n";
        }  
    }
}

sub subout_analysis
{
    my $file1 = 'verify.csv'; # Name the file
    open(INFO, $file1); # Open the file
    my @lines1 = ; # Read it into an array
    close(INFO); # Close the file


    $lines1[0] = join("",@lines1);
    my @short1 = split(/[","\n\t\s]/, $lines1[0]);
    for (my $i=0; $i <= 63; $i++)
    {
        shift @short1;
    }


    my @string1;
    my @word;
    $word[15]=0;
    my $oa_n=2;
    # the number of load address
    for (my $i=0; $i < $load_n; $i++)
    {
        # print "$oa_n\t";
        for (my $j=0; $j <= 15; $j++)
        {   
            # print "$short1[$oa_n]\t";
            if($short1[$oa_n]=~/[Ee]/ || $short1[$oa_n] 0.9)
            {
                $short1[$oa_n]="1";
            }
            else
            {
                print "error!!!\n";
            }
            # print "$short1[$oa_n]\t";
            $word[$j]=$short1[$oa_n];
            $oa_n += 2;
        }
        # print "\n\n";
        $oa_n += 1;
        $string1[$i]=oct("0b".join("",@word));
    }
    return @string1;
}

sub suband {
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);
    my @rt = split(/[\t]*/, $substring[2]);
    # rs: $reg[$rs[1]]
    # rt: $reg[$rt[1]] 
    # rd: $reg[$rd[1]] = $rs AND $temp
    $reg[$rd[1]] = $reg[$rs[1]] & $reg[$rt[1]];
    print "$reg[$rd[1]]\t$reg[$rs[1]]\t$reg[$rt[1]]\n";
}

sub subandi{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);

    # rs: $reg[$rs[1]]
    my $temp = hex(substr($substring[2], 1));
    # rd: $reg[$rd[1]] = $rs AND $temp
    $reg[$rd[1]] = $reg[$rs[1]] & $temp;
}

sub subor{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);
    my @rt = split(/[\t]*/, $substring[2]);
    # rs: $reg[$rs[1]]
    # rt: $reg[$rt[1]]   
    # rd: $reg[$rd[1]] = $rs OR $temp
    $reg[$rd[1]] = $reg[$rs[1]] | $reg[$rt[1]];
}

sub subori{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);

    # rs: $reg[$rs[1]]
    my $temp = hex(substr($substring[2], 1));
    # rd: $reg[$rd[1]] = $rs OR $temp
    $reg[$rd[1]] = $reg[$rs[1]] | $temp;
}

sub subxor{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);
    my @rt = split(/[\t]*/, $substring[2]);
    # rs: $reg[$rs[1]]
    # rt: $reg[$rt[1]]   
    # rd: $reg[$rd[1]] = $rs XOR $temp
    $reg[$rd[1]] = $reg[$rs[1]] ^ $reg[$rt[1]];
}

sub subxori{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);

    # rs: $reg[$rs[1]]
    my $temp = hex(substr($substring[2], 1));
    # rd: $reg[$rd[1]] = $rs XOR $temp
    $reg[$rd[1]] = $reg[$rs[1]] ^ $temp;
}

sub subnop{

}

sub subadd{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);
    my @rt = split(/[\t]*/, $substring[2]);
    # rs: $reg[$rs[1]]
    # rt: $reg[$rt[1]]   
    # rd: $reg[$rd[1]] = $rs ADD $temp
    $reg[$rd[1]] = $reg[$rs[1]] + $reg[$rt[1]];
}

sub subaddi{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);

    # rs: $reg[$rs[1]]
    my $temp = hex(substr($substring[2], 1));
    # rd: $reg[$rd[1]] = $rs ADD $temp
    $reg[$rd[1]] = $reg[$rs[1]] + $temp;
}

sub submul{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);
    my @rt = split(/[\t]*/, $substring[2]);
    # rs: $reg[$rs[1]]
    # rt: $reg[$rt[1]]   
    # rd: $reg[$rd[1]] = $rs MUL $temp
    $reg[$rd[1]] = $reg[$rs[1]] * $reg[$rt[1]];
}

sub submuli{
    my @substring = @_ ;
    shift @substring;
    my @rd = split(/[\t]*/, $substring[0]);
    my @rs = split(/[\t]*/, $substring[1]);

    # rs: $reg[$rs[1]]
    my $temp = hex(substr($substring[2], 1));
    # rd: $reg[$rd[1]] = $rs MUL $temp
    $reg[$rd[1]] = $reg[$rs[1]] * $temp;
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s