Created
February 8, 2009 04:44
-
-
Save dodeja/60189 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ECE 486 Project 1 | |
| # PDP 8 Benchmarking tool | |
| # | |
| require 'PDP8_stats' | |
| class PDP8 | |
| # Read the object file and load it to | |
| f = File.open("TestJMS.obj","r") | |
| lines = f.readlines | |
| @n = 0 | |
| f.close | |
| prog_data = Hash.new { |hash, key| hash[key] = {:addr => "", :data => ""} } | |
| prog_addr = Hash.new | |
| @prog_branch = Hash.new | |
| ins = 0 # => Instruction Counter | |
| first_addr = false # => First Instruction | |
| @branch_addr = 0 | |
| # => Increment Octal by 1 (address) | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.incre_oct(val) | |
| new_val = (val.to_i(8) + 1).to_s(8) | |
| if(new_val.length > 3) | |
| return new_val | |
| else | |
| return "0"+new_val | |
| end | |
| end | |
| # => Increment Octal (DATA) by 1 | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.incre_data(val) | |
| new_val = (val.to_i(8) + 1).to_s(8) | |
| if(new_val.to_i > 7777) | |
| return 0 | |
| else | |
| return new_val | |
| end | |
| end | |
| # => Increment Octal (DATA) by 1 | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.comp_oct(val) | |
| new_val = val | |
| 0.upto(val.length-1) do |x| | |
| case val[x..x].to_i | |
| when 0 | |
| new_val[x..x] = '7' | |
| when 1 | |
| new_val[x..x] = '6' | |
| when 2 | |
| new_val[x..x] = '5' | |
| when 3 | |
| new_val[x..x] = '4' | |
| when 4 | |
| new_val[x..x] = '3' | |
| when 5 | |
| new_val[x..x] = '2' | |
| when 6 | |
| new_val[x..x] = '1' | |
| when 7 | |
| new_val[x..x] = '0' | |
| end | |
| end | |
| return new_val | |
| end | |
| # => Parse the Lines into a 2-D Array | |
| #----------------------------------------------------------------------------------------------------- | |
| first_inst = 0 | |
| lines.each_index do |x| | |
| if(x % 2 == 0) | |
| if(lines[x].index('1') == 0) | |
| n = 0 | |
| prog_data[ins][:addr] = "0" + lines[x][1..2].to_i.to_s + lines[x + 1][1..2] | |
| prog_data[ins][:data] = lines[x + 2][1..2] + lines[x + 3][1..2] | |
| ins = ins + 1 | |
| first_addr = true | |
| else | |
| if(!first_addr) | |
| new_oct = incre_oct(prog_data[ins-1][:addr]) | |
| prog_data[ins][:addr] = "0" + new_oct | |
| prog_data[ins][:data] = lines[x][1..2] + lines[x + 1][1..2] | |
| ins = ins + 1 | |
| else | |
| first_addr = false | |
| end | |
| end | |
| end | |
| end | |
| # Set up another data Structure | |
| last_inst = 0 | |
| 0.upto(prog_data.length-1) do |k| | |
| if(prog_data[k][:data] == "7402") | |
| last_inst = k | |
| elsif(prog_data[k][:addr] == "0200") | |
| first_inst = k | |
| end | |
| prog_addr[prog_data[k][:addr].to_i] = prog_data[k][:data] | |
| puts "#{prog_data[k][:addr].to_i} - #{prog_addr[prog_data[k][:addr].to_i]}" | |
| end | |
| @lk = 0 | |
| @ac = 0 # => Accumulator | |
| @pc = "200" # => Program Counter starts at 200 | |
| @eaddr = "" | |
| @temp_data = 0 | |
| # => Get Effective address | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.get_eddr(current_data, prog_addr) | |
| if(current_data[1..1].to_i < 4) | |
| if(current_data[1..1].to_i < 2) | |
| @eaddr = ((current_data[1..1].to_i % 2).to_s + current_data[2..3]).to_i | |
| else | |
| @eaddr = ((@pc[0..1].to_i*100 + (current_data[1..1].to_i % 2)*100 + current_data[2..3].to_i).to_s).to_i | |
| end | |
| elsif( current_data[1..1].to_i > 3 && current_data[1..1].to_i < 6) | |
| @eaddr = ((current_data[1..1].to_i % 2).to_s + current_data[2..3]).to_i | |
| @eaddr = prog_addr[@eaddr] | |
| else | |
| @eaddr = ((@pc[0..1].to_i*100 + (current_data[1..1].to_i % 2)*100 + current_data[2..3].to_i).to_s).to_i | |
| @eaddr = prog_addr[@eaddr] | |
| end | |
| if(current_data[1..1].to_i > 3) | |
| if(current_data.to_i >= 10 && current_data.to_i <= 17) | |
| @eaddr = incre_oct(prog_adr[@eaddr]) | |
| end | |
| Stat.update({:cycle =>1 }) | |
| end | |
| end | |
| # => AND Instruction [case 0] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.AND_inst(current_data, prog_addr) | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = prog_addr[@eaddr.to_i] | |
| @ac = @temp_data.to_s.oct & @ac.to_s.oct | |
| @ac = @ac.to_s(8).to_i | |
| Stat.update({:AND =>1, :cycle =>2, :inst =>1 }) | |
| end | |
| # => TAD Instruction [case 1] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.TAD_inst(current_data, prog_addr) | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = prog_addr[@eaddr.to_i] | |
| @ac = @temp_data.to_s.oct + @ac.to_s.oct | |
| @ac = @ac.to_s(8).to_i | |
| Stat.update({:TAD =>1, :cycle =>2, :inst =>1}) | |
| end | |
| # => ISZ Instruction [case 2] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.ISZ_inst(current_data, prog_addr) | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = prog_addr[@eaddr.to_i] | |
| @temp_data = incre_data(@temp_data) | |
| prog_addr[@eaddr.to_i] = @temp_data | |
| if(@temp_data.to_i == 0) | |
| if(@prog_branch[@pc]) | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:taken] += 1 | |
| @prog_branch[@pc][:percent_taken] = @prog_branch[@pc][:taken] / @prog_branch[@pc][:exec] | |
| else | |
| @prog_branch[@pc] = { :type => "conditional", :exec => 1, :taken => 1, :percent_taken => 1} | |
| end | |
| @pc = incre_oct(@pc) | |
| else | |
| if(@prog_branch[@pc]) | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:percent_taken] = @prog_branch[@pc][:taken] / @prog_branch[@pc][:exec] | |
| else | |
| @prog_branch[@pc] = { :type => "conditional", :exec => 1, :taken => 0, :percent_taken => 0} | |
| end | |
| end | |
| Stat.update({:ISZ =>1, :cycle =>2, :inst =>1 }) | |
| # TRACE FILE | |
| end | |
| # => DCA Instruction [case 3] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.DCA_inst(current_data, prog_addr) | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = @ac.to_s | |
| prog_addr[@eaddr.to_i] = @temp_data | |
| @ac = 0 | |
| Stat.update({:DCA =>1, :cycle =>2, :inst =>1}) | |
| end | |
| # => JMS Instruction [case 4] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.JMS_inst(current_data, prog_addr) | |
| @prog_branch[@pc] = { :type => "unconditional", :exec => 1, :taken => 1, :percent_taken => 100} | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = @pc | |
| prog_addr[@eaddr.to_i] = @temp_data | |
| @pc = @eaddr.to_s | |
| Stat.update({:JMS =>1, :cycle =>2, :inst =>1 }) | |
| # Trance File Update | |
| # Update branch count? | |
| end | |
| # => JMP Instruction [case 5] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.JMP_inst(current_data, prog_addr) | |
| @prog_branch[@pc] = { :type => "unconditional", :exec => 1, :taken => 1, :percent_taken => 100} | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = @eaddr | |
| @pc = @eaddr | |
| Stat.update({:JMP => 1, :cycle => 1, :inst =>1}) | |
| # Trance File Update | |
| # Update branch count? | |
| end | |
| # => MICRO Instruction [case 7] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.MICRO_inst(current_data, prog_addr) | |
| code = prog_addr[@pc.to_i].to_i(8).to_s(2) | |
| skip = 0; | |
| if(code[3..3].to_i == 1 && code[11..11] == 1) | |
| Stat.update({:uINS3 => 1}) | |
| elsif(code[3..3] == 0) | |
| if(code[4..4].to_i == 1) | |
| @ac = 0 | |
| Stat.update({:CLA1 => 1}) | |
| end | |
| if(code[5..5].to_i == 1) | |
| @lk = 0 | |
| Stat.update({:CLL => 1}) | |
| end | |
| if(code[6..6].to_i == 1) | |
| @ac = comp_oct(@ac.to_s) | |
| Stat.update({:CMA => 1}) | |
| end | |
| if(code[7..7].to_i == 1) | |
| @lk == 0 ? 1 : 0 | |
| Stat.update({:CML => 1}) | |
| end | |
| if(code[8..8].to_i == 1) | |
| if(code[10..10].to_i == 1) | |
| iter = 2 | |
| Stat.update({:RTR => 1}) | |
| else | |
| iter 1 | |
| Stat.update({:RAR => 1}) | |
| end | |
| 1.upto(iter) do | |
| bin = @ac.to_s.to_i(8).to_s(2) | |
| bin = @lk.to_s + "0" * (12-bin.length) + bin | |
| @ac = (bin[0..11].to_i(2).to_s(8)).to_i | |
| @lk = bin[12..12].to_i | |
| end | |
| end | |
| if(code[9..9].to_i == 1) | |
| if(code[10..10].to_i == 1) | |
| Stat.update({:RTL => 1}) | |
| iter = 2 | |
| else | |
| iter 1 | |
| Stat.update({:RAL => 1}) | |
| end | |
| 1.upto(iter) do | |
| bin = @ac.to_s.to_i(8).to_s(2) | |
| bin = "0" * (12-bin.length) + bin + @lk.to_s | |
| @ac = (bin[1..12].to_i(2).to_s(8)).to_i | |
| @lk = bin[0..0].to_i | |
| end | |
| end | |
| if(code[11..11].to_i == 1) | |
| @ac = incr_data(@ac.to_s) # take care of overflow foor TAD and increments in incre_data | |
| Stat.update({:IAC => 1}) | |
| end | |
| elsif(code[3..3] == 1 && code[11..11] == 0) | |
| if(code[4..4].to_i == 1) | |
| @ac = 0 | |
| Stat.update({:CLA2 => 1}) | |
| end | |
| if(code[8..8].to_i == 1) | |
| skip = 1 | |
| if(code[5..5].to_i == 1) | |
| if((@ac.to_s.length == 4 && @ac.to_s[0..0].to_i < 4) || @ac.to_s.length < 4) | |
| skip = skip & 1 | |
| else | |
| skip = 0 | |
| end | |
| Stat.update({:SPA => 1}) | |
| end | |
| if(code[6..6].to_i == 1) | |
| if(@ac != 0) | |
| skip = skip & 1 | |
| else | |
| skip = 0 | |
| end | |
| Stat.update({:SNA => 1}) | |
| end | |
| if(code[7..7].to_i == 1) | |
| if(@lk == 0) | |
| skip = skip & 1 | |
| else | |
| skip = 0 | |
| end | |
| Stat.update({:SZL => 1}) | |
| end | |
| else | |
| skip = 0 | |
| if(code[5..5].to_i == 1) | |
| if(@ac.to_s.length == 4 && @ac.to_s[0..0].to_i > 3) | |
| skip = 1 | |
| end | |
| Stat.update({:SMA => 1}) | |
| end | |
| if(code[6..6].to_i == 1) | |
| if(@ac == 0) | |
| skip = 1 | |
| Stat.update({:SZA => 1}) | |
| end | |
| end | |
| if(code[7..7].to_i == 1) | |
| if(@lk != 0) | |
| skip = 1 | |
| Stat.update({:SNL => 1}) | |
| end | |
| end | |
| end | |
| if(skip == 1) | |
| @pc = incre_oct(@pc) | |
| end | |
| if(code[9..9].to_i == 1) | |
| Stat.update({:OSR => 1}) | |
| end | |
| if(code[10..10].to_i == 1) | |
| Stat.update({:HLT => 1}) | |
| end | |
| end | |
| Stat.update({:uINS => 1, :inst => 1, :cycle => 1}) | |
| # DO TRACE | |
| end | |
| # => Run Loop | |
| #----------------------------------------------------------------------------------------------------- | |
| run_prog = true | |
| while run_prog do | |
| current_data = prog_addr[@pc.to_i] | |
| current_instruction = current_data[0..0].to_i | |
| case current_instruction | |
| when 0 | |
| AND_inst(current_data, prog_addr) | |
| when 1 | |
| TAD_inst(current_data, prog_addr) | |
| when 2 | |
| ISZ_inst(current_data, prog_addr) | |
| when 3 | |
| DCA_inst(current_data, prog_addr) | |
| when 4 | |
| JMS_inst(current_data, prog_addr) | |
| when 5 | |
| JMP_inst(current_data, prog_addr) | |
| when 7 | |
| JMP_inst(current_data, prog_addr) | |
| end | |
| if(prog_addr[@pc.to_i] == "7402") | |
| run_prog = false | |
| end | |
| @pc = incre_oct(@pc) | |
| puts "#{@pc} #{prog_addr[@pc.to_i]} | AC = #{@ac} Eaddr = #{@eaddr}" | |
| end | |
| puts @prog_branch | |
| 0.upto(prog_data.length-1) do |k| | |
| puts "#{prog_data[k][:addr].to_i} - #{prog_addr[prog_data[k][:addr].to_i]}" | |
| end | |
| Stat.display | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment