Created
December 12, 2013 19:31
-
-
Save dodeja/7933961 to your computer and use it in GitHub Desktop.
PDP 8 Benchmarking tool - Instruction Set Simulation Tool
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 | |
| # => Instruction Set Simulation Tool | |
| # => Akshay Dodeha | Matt Curren | David Richoux | Anil Palli | |
| #----------------------------------------------------------------------------------------------------- | |
| require 'PDP8_stats' | |
| class PDP8 | |
| # => Read the object file and load it into memory | |
| #----------------------------------------------------------------------------------------------------- | |
| print "Enter name of Object file: " | |
| test_file = gets | |
| test_file = test_file.strip | |
| f = File.open(test_file,"r") | |
| lines = f.readlines | |
| @n = 0 | |
| f.close | |
| # => Setup Data Structures | |
| prog_data = Hash.new { |hash, key| hash[key] = {:addr => "", :data => ""} } | |
| prog_addr = Hash.new | |
| @trace = Array.new | |
| @prog_branch = Hash.new { |hash, key| hash[key] = {:type => "", :exec => 0.0, :taken => 0.0, :percent_taken => 0.0} } | |
| 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 | |
| @lk == 0 ? 1 : 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 for direct access | |
| #----------------------------------------------------------------------------------------------------- | |
| 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 | |
| @trace << {:type => 0, :addr => @eaddr} # Read pointer | |
| @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 | |
| @trace << {:type => 0, :addr => @eaddr} # Read pointer | |
| @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) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| 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 }) | |
| @trace << {:type => 0, :addr => @eaddr} # => Read Eaddr | |
| end | |
| # => TAD Instruction [case 1] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.TAD_inst(current_data, prog_addr) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| 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 | |
| if(@ac.to_s.oct > 4095) | |
| @ac = (@ac.to_s.oct - 4096).to_s(8).to_i | |
| @lk == 0 ? 1 : 0 | |
| end | |
| Stat.update({:TAD =>1, :cycle =>2, :inst =>1}) | |
| @trace << {:type => 0, :addr => @eaddr} # => Read Eaddr | |
| end | |
| # => ISZ Instruction [case 2] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.ISZ_inst(current_data, prog_addr) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| 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) | |
| @prog_branch[@pc] | |
| @prog_branch[@pc][:type] = "conditional" | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:taken] += 1 | |
| @prog_branch[@pc][:percent_taken] = (@prog_branch[@pc][:taken] / @prog_branch[@pc][:exec] )*100 | |
| @pc = incre_oct(@pc) | |
| else | |
| @prog_branch[@pc] | |
| @prog_branch[@pc][:type] = "conditional" | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:percent_taken] = (@prog_branch[@pc][:taken] / @prog_branch[@pc][:exec] )*100 | |
| end | |
| Stat.update({:ISZ =>1, :cycle =>2, :inst =>1 }) | |
| @trace << {:type => 0, :addr => @eaddr} # => Read Eaddr | |
| @trace << {:type => 1, :addr => @eaddr} # => C(EAddr) <- C(EAddr) + 1 | |
| end | |
| # => DCA Instruction [case 3] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.DCA_inst(current_data, prog_addr) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| 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}) | |
| @trace << {:type => 1, :addr => @eaddr} # => C(AC) <- 0 | |
| end | |
| # => JMS Instruction [case 4] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.JMS_inst(current_data, prog_addr) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| @prog_branch[@pc] | |
| @prog_branch[@pc][:type] = "unconditional" | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:taken] += 1 | |
| @prog_branch[@pc][:percent_taken] = 100 | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = incre_oct(@pc.to_s) | |
| prog_addr[@eaddr.to_i] = @temp_data | |
| @pc = @eaddr.to_s | |
| Stat.update({:JMS =>1, :cycle =>2, :inst =>1 }) | |
| @trace << {:type => 1, :addr => @eaddr} # => C(EAddr) <- C(PC) | |
| @trace << {:type => 0, :addr => @eaddr} # => Read Eaddr | |
| end | |
| # => JMP Instruction [case 5] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.JMP_inst(current_data, prog_addr) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| @prog_branch[@pc] | |
| @prog_branch[@pc][:type] = "unconditional" | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:taken] += 1 | |
| @prog_branch[@pc][:percent_taken] = 100 | |
| get_eddr(current_data, prog_addr) | |
| @temp_data = @eaddr | |
| @pc = (@eaddr.to_s.to_i(8) - 1).to_s(8) | |
| Stat.update({:JMP => 1, :cycle => 1, :inst =>1}) | |
| @trace << {:type => 0, :addr => @pc} # => C(PC) <- Eaddr | |
| end | |
| # => MICRO Instruction [case 7] | |
| #----------------------------------------------------------------------------------------------------- | |
| def self.MICRO_inst(current_data, prog_addr) | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| code = prog_addr[@pc.to_i].to_i(8).to_s(2) | |
| skip = 0; | |
| if(code[3..3].to_i == 1 && code[11..11].to_i == 1) | |
| Stat.update({:uINS3 => 1}) | |
| elsif(code[3..3].to_i == 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) | |
| if(@lk == 0) | |
| @lk = 1 | |
| else | |
| @lk = 0 | |
| end | |
| 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 = incre_data(@ac.to_s) | |
| Stat.update({:IAC => 1}) | |
| end | |
| if(code[4..11].to_i == 0) | |
| Stat.update({:NOP => 1}) | |
| end | |
| elsif(code[3..3].to_i == 1 && code[11..11].to_i == 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 | |
| if((code[5..5].to_i | code[6..6].to_i | code[7..7].to_i) == 0) | |
| skip = 1 | |
| Stat.update({SKP => 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 | |
| end | |
| Stat.update({:SZA => 1}) | |
| end | |
| if(code[7..7].to_i == 1) | |
| if(@lk != 0) | |
| skip = 1 | |
| end | |
| Stat.update({:SNL => 1}) | |
| end | |
| end | |
| if(code[8..8].to_i == 1 || (code[5..7].to_i > 0 && code[8..8].to_i == 0)) | |
| if(skip == 1) | |
| @prog_branch[@pc] | |
| @prog_branch[@pc][:type] = "conditional" | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:taken] += 1 | |
| @prog_branch[@pc][:percent_taken] = (@prog_branch[@pc][:taken] / @prog_branch[@pc][:exec] )*100 | |
| @pc = incre_oct(@pc.to_s) | |
| else | |
| @prog_branch[@pc] | |
| @prog_branch[@pc][:type] = "conditional" | |
| @prog_branch[@pc][:exec] += 1 | |
| @prog_branch[@pc][:percent_taken] = (@prog_branch[@pc][:taken] / @prog_branch[@pc][:exec] )*100 | |
| end | |
| 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 | |
| if(prog_addr[@pc.to_i] == "0000") | |
| current_instruction = 8 | |
| end | |
| 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 6 | |
| @trace << {:type => 2, :addr => @pc} # => Instruction Fetch | |
| Stat.update({:IO => 1, :inst =>1}) | |
| when 7 | |
| MICRO_inst(current_data, prog_addr) | |
| when 8 | |
| @trace << {:type => 2, :addr => @pc} | |
| Stat.update({:inst => 1}) | |
| puts "Error: invalid instruction (0000) encountered" | |
| end | |
| puts "#{@pc} #{prog_addr[@pc.to_i]} | LK = #{@lk} AC = #{@ac} Eaddr = #{@eaddr}" | |
| if(prog_addr[@pc.to_i] == "7402") | |
| run_prog = false | |
| end | |
| @pc = incre_oct(@pc) | |
| end | |
| # => Display Stats and Output stats to a file | |
| #----------------------------------------------------------------------------------------------------- | |
| 0.upto(prog_data.length-1) do |k| | |
| puts "#{prog_data[k][:addr].to_i} - #{prog_addr[prog_data[k][:addr].to_i]}" | |
| end | |
| @prog_branch.each_pair {|key, value| puts "#{key} #{value[:type]} exec = #{value[:exec].round} taken = #{value[:taken].round} % = #{value[:percent_taken]}" } | |
| Stat.update({:lk => @lk, :ac => @ac, :pc => @pc.to_i}) | |
| Stat.display(test_file, @prog_branch) | |
| puts "TRACE FILE ------" | |
| f2 = File.open(test_file+".MEM.txt","w") | |
| @trace.each_index do |x| | |
| f2.puts "#{@trace[x][:type]} #{@trace[x][:addr].to_i}" | |
| puts "#{@trace[x][:type]} #{@trace[x][:addr].to_i}" | |
| end | |
| f2.close | |
| end | |
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
| class Stat | |
| @AND = 0 | |
| @TAD = 0 | |
| @ISZ = 0 | |
| @DCA = 0 | |
| @JMS = 0 | |
| @JMP = 0 | |
| @IO = 0 | |
| @uINS = 0 | |
| @cycles = 0 | |
| @insts = 0 | |
| @NOP = 0 | |
| @CLA1 = 0 | |
| @CLA2 = 0 | |
| @CLL = 0 | |
| @CMA = 0 | |
| @CML = 0 | |
| @IAC = 0 | |
| @RAR = 0 | |
| @RTR = 0 | |
| @RAL = 0 | |
| @RTL = 0 | |
| @SMA = 0 | |
| @SZA = 0 | |
| @SNL = 0 | |
| @SPA = 0 | |
| @SNA = 0 | |
| @SZL = 0 | |
| @SKP = 0 | |
| @OSR = 0 | |
| @HLT = 0 | |
| @uINS3 = 0 | |
| @lk = 0 | |
| @ac = 0 | |
| @pc = 0 | |
| def self.update(args) | |
| @AND += args[:AND] || 0 | |
| @TAD += args[:TAD] || 0 | |
| @ISZ += args[:ISZ] || 0 | |
| @DCA += args[:DCA] || 0 | |
| @JMS += args[:JMS] || 0 | |
| @JMP += args[:JMP] || 0 | |
| @IO += args[:IO] || 0 | |
| @uINS += args[:uINS] || 0 | |
| @cycles += args[:cycle] || 0 | |
| @insts += args[:inst] || 0 | |
| @NOP += args[:NOP] || 0 | |
| @CLA1 += args[:CLA1] || 0 | |
| @CLA2 += args[:CLA2] || 0 | |
| @CLL += args[:CLL] || 0 | |
| @CMA += args[:CMA] || 0 | |
| @CML += args[:CML] || 0 | |
| @IAC += args[:IAC] || 0 | |
| @RAR += args[:RAR] || 0 | |
| @RTR += args[:RTR] || 0 | |
| @RAL += args[:RAL] || 0 | |
| @RTL += args[:RTL] || 0 | |
| @SMA += args[:SMA] || 0 | |
| @SZA += args[:SZA] || 0 | |
| @SNL += args[:SNL] || 0 | |
| @SPA += args[:SPA] || 0 | |
| @SNA += args[:SNA] || 0 | |
| @SZL += args[:SZL] || 0 | |
| @SKP += args[:SKP] || 0 | |
| @OSR += args[:OSR] || 0 | |
| @HLT += args[:HLT] || 0 | |
| @uINS3 += args[:uINS3] || 0 | |
| @lk += args[:lk] || 0 | |
| @ac += args[:ac] || 0 | |
| @pc += args[:pc] || 0 | |
| end | |
| def self.display(file, branch) | |
| f3 = File.open(file+".STATS.txt","w") | |
| branch.each_pair do |key, value| | |
| f3.puts "#{key} #{value[:type]} exec = #{value[:exec].round} taken = #{value[:taken].round} % = #{value[:percent_taken]}" | |
| end | |
| f3.puts "Stats ____________" | |
| f3.puts " | AND = #{@AND}" | |
| f3.puts " | @TAD = #{@TAD}" | |
| f3.puts " | @ISZ = #{@ISZ}" | |
| f3.puts " | @DCA = #{@DCA}" | |
| f3.puts " | @JMS = #{@JMS}" | |
| f3.puts " | @JMP = #{@JMP}" | |
| f3.puts " | @IO = #{@IO}" | |
| f3.puts " | @uINS = #{@uINS}" | |
| f3.puts " | cycles = #{@cycles}" | |
| f3.puts " | insts = #{@insts}" | |
| f3.puts " | NOP = #{@NOP}" | |
| f3.puts " | CLA1 = #{@CLA1}" | |
| f3.puts " | CLA2 = #{@CLA2}" | |
| f3.puts " | CLL = #{@CLL}" | |
| f3.puts " | CMA = #{@CMA}" | |
| f3.puts " | CML = #{@CML}" | |
| f3.puts " | IAC = #{@IAC}" | |
| f3.puts " | RAR = #{@RAR}" | |
| f3.puts " | RTR = #{@RTR}" | |
| f3.puts " | RAL = #{@RAL}" | |
| f3.puts " | RTL = #{@RTL}" | |
| f3.puts " | SMA = #{@SMA}" | |
| f3.puts " | SZA = #{@SZA}" | |
| f3.puts " | SNL = #{@SNL}" | |
| f3.puts " | SPA = #{@SPA}" | |
| f3.puts " | SNA = #{@SNA}" | |
| f3.puts " | SZL = #{@SZL}" | |
| f3.puts " | SKP = #{@SKP}" | |
| f3.puts " | OSR = #{@OSR}" | |
| f3.puts " | HLT = #{@HLT}" | |
| f3.puts " | uINS3 = #{@uINS3}" | |
| f3.puts "Registers____________" | |
| f3.puts " | LK = #{@lk}" | |
| f3.puts " | AC = #{@ac}" | |
| f3.puts " | PC = #{@pc}" | |
| f3.close | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment