Lesson5: Frontend given 5-stage pipeline CPU

1. Given MIPS instructions (cmd.txt), solve RAW hazards by adding NOPs among different instructions, then convert the updated instructions file with no RAW hazards to the vector file (0/1 signals).

2. MIPS instructions below contains: STOREI, STORE, LOAD, AND, ANDI, OR, ORI, XOR, XORI, NOP, ADD, ADDI, MUL, MULI.

3. No forwarding in the code.

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



sub subreverse_addr;
sub subreverse_data;
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;


my $file = 'cmd.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 = 'vector.txt';
open(my $fh, '>', $file_write) or die "Could not open file '$file_write' $!";




my $lines_count=-2;
my $n=0;
my $string;

print $fh "radix","\t",1,"\t",1,"\t",1,"\t",1,"\t",4,"\t",4,"\t",4,"\t",4,"\t",4,"\t",4,"\t",4,"\t",4,"\t",1,"\t",1,"\t",4,"\t",4,"\n";
print $fh "io","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\t","i","\n";
print $fh "vname","\t","precharge_en","\t","decoder_en","\t","read_en","\t","write_en","\t","Data[15:12]","\t","Data[11:8]","\t","Data[7:4]","\t","Data[3:0]","\t","Data_bar[15:12]","\t","Data_bar[11:8]","\t","Data_bar[7:4]","\t","Data_bar[3:0]","\t","A4","\t","A[3:0]","\t","A_bar4","\t","A_bar[3:0]","\n";

print $fh "slope","\t",0.01,"\n","vih","\t",1.8,"\n","tunit","\t","4ns","\n";

while($n<@lines)
{
    $string = $lines[$n];
    $n=$n+1;

    chomp $string;

    my @short = split(/[\s\t]+/, $string);

    if($short[0]=~/STOREI/)
    {
        &substore(@short);
    }
    
    elsif($short[0]=~/STORE/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/LOAD/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/AND/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/ANDI/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/OR/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/ORI/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/XOR/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/XORI/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/NOP/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/ADD/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/ADDI/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/MUL/)
    {
        &subload(@short);
    }

    elsif($short[0]=~/MULI/)
    {
        &subload(@short);
    }
    
    else
    {
        print "Error001: No Such Command Found!","\n";
    }

    
}


close $fh;
print "done\n";


#####subroutine#####

sub substore
{
    my @storestring = @_ ;
    shift @storestring;
    

    my @bin_judg = split(/[\t]*/, $storestring[0]);
    # print $fh @bin_judg, "\n";
    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] eq "2")
        {
            my @addr0=subreverse_addr(hex($storestring[0]));
            my @addr1=subreverse_addr(hex($storestring[0])+1);
            my @data0=subreverse_data($storestring[2]);
            my @data1=subreverse_data($storestring[3]);
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
            
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
        }
        
        elsif($storestring[1] eq "4")
        {
            my @addr0=subreverse_addr(hex($storestring[0]));
            my @addr1=subreverse_addr(hex($storestring[0])+1);
            my @addr2=subreverse_addr(hex($storestring[0])+2);
            my @addr3=subreverse_addr(hex($storestring[0])+3);
            my @data0=subreverse_data($storestring[2]);
            my @data1=subreverse_data($storestring[3]);
            my @data2=subreverse_data($storestring[4]);
            my @data3=subreverse_data($storestring[5]);

            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
            
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
            
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr2),"\t",join("\t", @data2),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @addr2),"\t",join("\t", @data2),"\n";
            
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr3),"\t",join("\t", @data3),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @addr3),"\t",join("\t", @data3),"\n";
            
        }
        
        elsif($storestring[1]=~"#")
        {
            my @addr=subreverse_addr(hex($storestring[0]));
            my @data=subreverse_data($storestring[1]);
            
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",1,"\t",0,"\t";
            print $fh join("\t", @data),"\t",join("\t", @addr),"\n";
            print $fh $lines_count+1,"\t",1,"\t",1,"\t",1,"\t",1,"\t";
            print $fh join("\t", @data),"\t",join("\t", @addr),"\n";
            
        }
        else
        {
            print "Error002: Invalid Store Format!","\n";
        }
    }
    
    
}



sub subload
{
    my @loadstring = @_ ;
    shift @loadstring;
    
    
    my @bin_judg_l = split(/[\t]*/, $loadstring[0]);

    if(@bin_judg_l==6)  #if it is binary, convert it to hex
    {
        chop($loadstring[0]);
        $loadstring[0] = oct("0b".$loadstring[0]);
        $loadstring[0] = (sprintf("%x",$loadstring[0])."H"); #convert binary to hex
    }
    
    
    
    if ($loadstring[0]=~ /H/)
    {
        chop($loadstring[0]);
  
        if(@loadstring==2)
        {
            if($loadstring[1] eq "2")
            {

                my @addr0=subreverse_addr(hex($loadstring[0]));
                my @addr1=subreverse_addr(hex($loadstring[0])+1);
                my @data0=("0","0","0","0","0","0","0","0");
                my @data1=("0","0","0","0","0","0","0","0");
              
                print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
                print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
                print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
                print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";

                
                print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
                print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
                print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
                print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
                
                
            }
        
            elsif($loadstring[1] eq "4")
            {
                my @addr0=subreverse_addr(hex($loadstring[0]));
                my @addr1=subreverse_addr(hex($loadstring[0])+1);
                my @addr2=subreverse_addr(hex($loadstring[0])+2);
                my @addr3=subreverse_addr(hex($loadstring[0])+3);
                my @data0=("0","0","0","0","0","0","0","0");
                my @data1=("0","0","0","0","0","0","0","0");
                my @data2=("0","0","0","0","0","0","0","0");
                my @data3=("0","0","0","0","0","0","0","0");
                
                print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
                print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
                print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
                print $fh join("\t", @addr0),"\t",join("\t", @data0),"\n";
             

                print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
                print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
                print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
                print $fh join("\t", @addr1),"\t",join("\t", @data1),"\n";
                   

                print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr2),"\t",join("\t", @data2),"\n";
                print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr2),"\t",join("\t", @data2),"\n";
                print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
                print $fh join("\t", @addr2),"\t",join("\t", @data2),"\n";
              

                print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr3),"\t",join("\t", @data3),"\n";
                print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
                print $fh join("\t", @addr3),"\t",join("\t", @data3),"\n";
                print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
                print $fh join("\t", @addr3),"\t",join("\t", @data3),"\n";
          
                
            }

        }
        
        elsif(@loadstring==1)
        {
            my @addr=subreverse_addr(hex($loadstring[0]));
            my @data=("0","0","0","0","0","0","0","0");
            
            print $fh $lines_count=$lines_count+2,"\t",0,"\t",0,"\t",0,"\t",0,"\t";
            print $fh join("\t", @addr),"\t",join("\t", @data),"\n";
            print $fh $lines_count=$lines_count+1,"\t",1,"\t",1,"\t",0,"\t",0,"\t";
            print $fh join("\t", @addr),"\t",join("\t", @data),"\n";
            print $fh $lines_count+0.5,"\t",1,"\t",1,"\t",1,"\t",0,"\t";
            print $fh join("\t", @addr),"\t",join("\t", @data),"\n";

            
        }
        
        else
        {
            print "Error003: Invalid Load Format!","\n";
        }

    }
    
    
}



sub subreverse_addr

{
    my $in_addr = $_[0] ;
    my $reverse_addr = ~$in_addr;

    $reverse_addr=$reverse_addr & 0b11111;

    my @out_addr0 = (split(/[\t]*/, uc(sprintf("%x",$in_addr))));
    my @out_addr1 = (split(/[\t]*/, uc(sprintf("%x",$reverse_addr))));
    if (@out_addr0<2)
    {
        unshift @out_addr0, "0";
    }
    if (@out_addr1<2)
    {
        unshift @out_addr1, "0";
    }
    
    my @out_addr=(@out_addr0,@out_addr1);
    return @out_addr;
}


sub subreverse_data

{
    my $in_data = hex(substr($_[0], 1));
    my $reverse_data = ~$in_data;
    $reverse_data=$reverse_data & 0xFFFF;

    my @out_data0 = (split(/[\t]*/, uc(sprintf("%x",$in_data))));
    my @out_data1 = (split(/[\t]*/, uc(sprintf("%x",$reverse_data))));

    while(@out_data0<4)
    {
        unshift @out_data0, "0";
    }
    
    while(@out_data1<4)
    {
        unshift @out_data1, "0";
    }
    
    
    my @out_data = (@out_data0,@out_data1);
    return @out_data;
}

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