Skip to content

Instantly share code, notes, and snippets.

@dodeja
Created February 8, 2009 04:44
Show Gist options
  • Select an option

  • Save dodeja/60189 to your computer and use it in GitHub Desktop.

Select an option

Save dodeja/60189 to your computer and use it in GitHub Desktop.
# 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