From 15e4533a2ffa38885e34a019d16c993613163e82 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Thu, 17 May 2018 20:14:59 +0300 Subject: [PATCH] fix interpreter to use positions tick from one (simulated memory) position to the next (not from one instruction to the next) --- lib/risc/interpreter.rb | 40 +++++++++++++++-------- lib/risc/interpreter_platform.rb | 5 ++- test/risc/test_interpreter.rb | 54 ++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 14 deletions(-) create mode 100644 test/risc/test_interpreter.rb diff --git a/lib/risc/interpreter.rb b/lib/risc/interpreter.rb index c6a62e4b..2274dfd4 100644 --- a/lib/risc/interpreter.rb +++ b/lib/risc/interpreter.rb @@ -31,10 +31,11 @@ module Risc end end - def start( instruction ) + def start_machine initialize + init = Risc.machine.cpu_init set_state(:running) - set_instruction( instruction ) + set_pc( Position.get(init).at ) end def set_state( state ) @@ -44,12 +45,22 @@ module Risc trigger(:state_changed , old , state ) 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 ) raise "set to same instruction #{instruction}:#{instruction.class}" if @instruction == instruction + log.debug "Setting Instruction #{instruction}" old = @instruction @instruction = instruction trigger(:instruction_changed, old , instruction) - set_state( :exited) unless instruction + set_state( :exited ) unless instruction end def get_register( reg ) @@ -77,29 +88,32 @@ module Risc end def tick - return unless @instruction - @clock += 1 + unless @instruction + log.debug "No Instruction , No Tick" + return @clock + end name = @instruction.class.name.split("::").last log.debug "#{@clock.to_s}: #{@instruction.to_s}" fetch = send "execute_#{name}" log.debug register_dump - return unless fetch - set_instruction @instruction.next - end - - # Label is a noop. - def execute_Label - true + if fetch + clock = @clock + @instruction.byte_length + set_pc(clock) + else + log.debug "No Fetch" + end + @clock end # Instruction interpretation starts here def execute_DynamicJump method = get_register(@instruction.register) set_instruction( method.risc_instructions ) + false end def execute_Branch label = @instruction.label - set_instruction label + set_pc Position.get(label).at false end diff --git a/lib/risc/interpreter_platform.rb b/lib/risc/interpreter_platform.rb index ce9192da..c809f031 100644 --- a/lib/risc/interpreter_platform.rb +++ b/lib/risc/interpreter_platform.rb @@ -30,7 +30,10 @@ module Risc end class IdentityTranslator 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.nil_next ret diff --git a/test/risc/test_interpreter.rb b/test/risc/test_interpreter.rb new file mode 100644 index 00000000..1bb86709 --- /dev/null +++ b/test/risc/test_interpreter.rb @@ -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