fix interpreter to use positions

tick from one (simulated memory) position to the next
(not from one instruction to the next)
This commit is contained in:
Torsten Ruger 2018-05-17 20:14:59 +03:00
parent 8966a50a8a
commit 15e4533a2f
3 changed files with 85 additions and 14 deletions

View File

@ -31,10 +31,11 @@ module Risc
end end
end end
def start( instruction ) def start_machine
initialize initialize
init = Risc.machine.cpu_init
set_state(:running) set_state(:running)
set_instruction( instruction ) set_pc( Position.get(init).at )
end end
def set_state( state ) def set_state( state )
@ -44,12 +45,22 @@ module Risc
trigger(:state_changed , old , state ) trigger(:state_changed , old , state )
end end
def set_pc( pos )
raise "Not int #{pos}" unless pos.is_a? Numeric
position = Position.at(pos)
log.debug "Setting Position #{pos}"
raise "not instruction position #{position}-#{position.class}-#{position.object.class}" unless position.is_a?(Position::InstructionPosition)
set_instruction( position.instruction)
@clock = position.at
end
def set_instruction( instruction ) def set_instruction( instruction )
raise "set to same instruction #{instruction}:#{instruction.class}" if @instruction == instruction raise "set to same instruction #{instruction}:#{instruction.class}" if @instruction == instruction
log.debug "Setting Instruction #{instruction}"
old = @instruction old = @instruction
@instruction = instruction @instruction = instruction
trigger(:instruction_changed, old , instruction) trigger(:instruction_changed, old , instruction)
set_state( :exited) unless instruction set_state( :exited ) unless instruction
end end
def get_register( reg ) def get_register( reg )
@ -77,29 +88,32 @@ module Risc
end end
def tick def tick
return unless @instruction unless @instruction
@clock += 1 log.debug "No Instruction , No Tick"
return @clock
end
name = @instruction.class.name.split("::").last name = @instruction.class.name.split("::").last
log.debug "#{@clock.to_s}: #{@instruction.to_s}" log.debug "#{@clock.to_s}: #{@instruction.to_s}"
fetch = send "execute_#{name}" fetch = send "execute_#{name}"
log.debug register_dump log.debug register_dump
return unless fetch if fetch
set_instruction @instruction.next clock = @clock + @instruction.byte_length
end set_pc(clock)
else
# Label is a noop. log.debug "No Fetch"
def execute_Label end
true @clock
end end
# Instruction interpretation starts here # Instruction interpretation starts here
def execute_DynamicJump def execute_DynamicJump
method = get_register(@instruction.register) method = get_register(@instruction.register)
set_instruction( method.risc_instructions ) set_instruction( method.risc_instructions )
false
end end
def execute_Branch def execute_Branch
label = @instruction.label label = @instruction.label
set_instruction label set_pc Position.get(label).at
false false
end end

View File

@ -30,7 +30,10 @@ module Risc
end end
class IdentityTranslator class IdentityTranslator
def translate(code) def translate(code)
return Label.new( code.source , code.name ) if code.is_a?(Label) #return Label.new( code.source , code.name ) if code.is_a?(Label)
if( code.is_a?(Branch))
return code.class.new(code.source , code.label.to_cpu(self))
end
ret = code.dup ret = code.dup
ret.nil_next ret.nil_next
ret ret

View File

@ -0,0 +1,54 @@
require_relative "helper"
module Risc
class TestInterpreterBasics < MiniTest::Test
def test_class
assert_equal Risc::Interpreter , Interpreter.new.class
end
def test_starts_stopped
assert_equal :stopped , Interpreter.new.state
end
def test_has_regs
assert_equal 12 , Interpreter.new.registers.length
end
def test_has_r0
assert_equal :r0 , Interpreter.new.registers.keys.first
end
end
class TestInterpreterStarts < MiniTest::Test
def setup
@machine = Risc.machine.boot
@machine.translate(:interpreter)
@machine.position_all
@interpreter = Interpreter.new
end
def test_starts
assert_equal 0 , @interpreter.start_machine
end
def test_started
@interpreter.start_machine
assert_equal :running , @interpreter.state
end
def test_pos
@interpreter.start_machine
assert_equal 0 , @interpreter.clock
end
end
class TestInterpreterTicks < MiniTest::Test
def setup
@machine = Risc.machine.boot
@machine.translate(:interpreter)
@machine.position_all
@interpreter = Interpreter.new
@interpreter.start_machine
end
def test_tick
assert_equal 19484 , @interpreter.tick
end
def test_tick
assert_equal 19484 , @interpreter.tick
assert_equal 19488 , @interpreter.tick
end
end
end