fold position module and object position
simpler that way, aslo code is moving to listners
This commit is contained in:
parent
24f6e30b54
commit
c2d450f779
@ -25,7 +25,7 @@ module Arm
|
|||||||
super
|
super
|
||||||
my_pos = Risc::Position.get(self)
|
my_pos = Risc::Position.get(self)
|
||||||
# set my position to set next according to rules
|
# set my position to set next according to rules
|
||||||
Risc::Position::InstructionListener.init(instruction , my_pos.get_code)
|
Risc::InstructionListener.init(instruction , my_pos.get_code)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,7 +42,7 @@ module Parfait
|
|||||||
if Risc::Position.set?(self)
|
if Risc::Position.set?(self)
|
||||||
Risc::Position.log.debug "extending one in #{self}"
|
Risc::Position.log.debug "extending one in #{self}"
|
||||||
my_pos = Risc::Position.get(self)
|
my_pos = Risc::Position.get(self)
|
||||||
Risc::Position.reset(my_pos , my_pos.at , my_pos.method)
|
Risc::CodeListener.init( @next , my_pos + self.padded_length)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -49,12 +49,12 @@ module Risc
|
|||||||
raise "Not int #{pos}" unless pos.is_a? Numeric
|
raise "Not int #{pos}" unless pos.is_a? Numeric
|
||||||
position = Position.at(pos)
|
position = Position.at(pos)
|
||||||
raise "No position #{pos.to_s(16)}" unless position
|
raise "No position #{pos.to_s(16)}" unless position
|
||||||
if position.is_a?(Position::CodePosition)
|
if position.is_a?(CodePosition)
|
||||||
raise "Setting Code #{clock}-#{position}, #{position.method}"
|
raise "Setting Code #{clock}-#{position}, #{position.method}"
|
||||||
#return set_pc(position.at + Parfait::BinaryCode.byte_offset)
|
#return set_pc(position.at + Parfait::BinaryCode.byte_offset)
|
||||||
end
|
end
|
||||||
log.debug "Setting Position #{clock}-#{position}, #{position.binary}"
|
log.debug "Setting Position #{clock}-#{position}, #{position.binary}"
|
||||||
raise "not instruction position #{position}-#{position.class}-#{position.object.class}" unless position.is_a?(Position::InstructionPosition)
|
raise "not instruction position #{position}-#{position.class}-#{position.object.class}" unless position.is_a?(InstructionPosition)
|
||||||
set_instruction( position.instruction )
|
set_instruction( position.instruction )
|
||||||
@clock += 1
|
@clock += 1
|
||||||
@pc = position.at
|
@pc = position.at
|
||||||
|
@ -85,7 +85,7 @@ module Risc
|
|||||||
def position_all
|
def position_all
|
||||||
raise "Not translated " unless @translated
|
raise "Not translated " unless @translated
|
||||||
#need the initial jump at 0 and then functions
|
#need the initial jump at 0 and then functions
|
||||||
Position::ObjectPosition.init(cpu_init , -1)
|
Position.init(cpu_init , -1)
|
||||||
code_start = position_objects( @platform.padding )
|
code_start = position_objects( @platform.padding )
|
||||||
# and then everything code
|
# and then everything code
|
||||||
position_code(code_start)
|
position_code(code_start)
|
||||||
@ -101,8 +101,8 @@ module Risc
|
|||||||
sorted.each do | objekt|
|
sorted.each do | objekt|
|
||||||
next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label )
|
next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label )
|
||||||
before = at
|
before = at
|
||||||
position = Position::ObjectPosition.init(objekt,at)
|
position = Position.init(objekt,at)
|
||||||
previous.register_event(:position_changed , Position::ObjectListener.new(objekt)) if previous
|
previous.register_event(:position_changed , PositionListener.new(objekt)) if previous
|
||||||
previous = position
|
previous = position
|
||||||
at += objekt.padded_length
|
at += objekt.padded_length
|
||||||
log.debug "Object #{objekt.class}:#{before.to_s(16)} len: #{(at - before).to_s(16)}"
|
log.debug "Object #{objekt.class}:#{before.to_s(16)} len: #{(at - before).to_s(16)}"
|
||||||
@ -121,8 +121,8 @@ module Risc
|
|||||||
Parfait.object_space.types.values.each do |type|
|
Parfait.object_space.types.values.each do |type|
|
||||||
next unless type.methods
|
next unless type.methods
|
||||||
type.methods.each_method do |method|
|
type.methods.each_method do |method|
|
||||||
last_code = Position::CodeListener.init(method.binary , code_start)
|
last_code = CodeListener.init(method.binary , code_start)
|
||||||
Position::InstructionListener.init(method.cpu_instructions, method.binary)
|
InstructionListener.init(method.cpu_instructions, method.binary)
|
||||||
last_code.register_event(:position_changed , prev_code.object) if prev_code
|
last_code.register_event(:position_changed , prev_code.object) if prev_code
|
||||||
prev_code = last_code
|
prev_code = last_code
|
||||||
code_start = last_code.next_slot
|
code_start = last_code.next_slot
|
||||||
|
@ -1,79 +1,59 @@
|
|||||||
module Risc
|
module Risc
|
||||||
module Position
|
|
||||||
|
|
||||||
# BinaryCodes form a linked list
|
# BinaryCodes form a linked list
|
||||||
#
|
#
|
||||||
# We want to keep all code for a method continous, so we propagate Positions
|
# We want to keep all code for a method continous, so we propagate Positions
|
||||||
#
|
#
|
||||||
# At the end of the list the propagation spills into the next methods
|
# At the end of the list the propagation spills into the next methods
|
||||||
# binary and so on
|
# binary and so on
|
||||||
#
|
#
|
||||||
class CodeListener
|
class CodeListener
|
||||||
|
|
||||||
attr_reader :code , :method
|
attr_reader :code , :method
|
||||||
|
|
||||||
def initialize(code , method)
|
def initialize(code , method)
|
||||||
super(code,pos)
|
super(code,pos)
|
||||||
@code = code
|
@code = code
|
||||||
@method = method
|
@method = method
|
||||||
raise "Method nil" unless method
|
raise "Method nil" unless method
|
||||||
|
end
|
||||||
|
def set(at )
|
||||||
|
next_pos = at + code.padded_length
|
||||||
|
if code.next
|
||||||
|
Position.set(code.next , next_pos, method)
|
||||||
|
set_jump(at)
|
||||||
|
else
|
||||||
|
next_meth = next_method
|
||||||
|
return unless next_meth
|
||||||
|
Position.set( next_meth.binary , next_pos , next_meth)
|
||||||
|
next_cpu_pos = next_pos + Parfait::BinaryCode.byte_offset
|
||||||
|
Position.set( next_meth.cpu_instructions, next_cpu_pos , next_meth.binary)
|
||||||
end
|
end
|
||||||
def set(at )
|
end
|
||||||
next_pos = at + code.padded_length
|
|
||||||
|
# insert a jump to the next instruction, at the last instruction
|
||||||
|
# thus hopping over the object header
|
||||||
|
def set_jump(at)
|
||||||
|
jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next)
|
||||||
|
translator = Risc.machine.platform.translator
|
||||||
|
cpu_jump = translator.translate(jump)
|
||||||
|
pos = at + code.padded_length - cpu_jump.byte_length
|
||||||
|
Position.set( cpu_jump , pos , code)
|
||||||
|
cpu_jump.assemble(JumpWriter.new(code))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.init( code , at = -1)
|
||||||
|
while code
|
||||||
|
position = Position.new(code , at)
|
||||||
|
Position.set_to(position , at)
|
||||||
if code.next
|
if code.next
|
||||||
Position.set(code.next , next_pos, method)
|
listener = PositionListener.new(code.next)
|
||||||
set_jump(at)
|
position.register_event(:position_changed , listener)
|
||||||
else
|
|
||||||
next_meth = next_method
|
|
||||||
return unless next_meth
|
|
||||||
Position.set( next_meth.binary , next_pos , next_meth)
|
|
||||||
next_cpu_pos = next_pos + Parfait::BinaryCode.byte_offset
|
|
||||||
Position.set( next_meth.cpu_instructions, next_cpu_pos , next_meth.binary)
|
|
||||||
end
|
end
|
||||||
|
at += code.padded_length unless at < 0
|
||||||
|
code = code.next
|
||||||
end
|
end
|
||||||
|
position
|
||||||
# insert a jump to the next instruction, at the last instruction
|
|
||||||
# thus hopping over the object header
|
|
||||||
def set_jump(at)
|
|
||||||
jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next)
|
|
||||||
translator = Risc.machine.platform.translator
|
|
||||||
cpu_jump = translator.translate(jump)
|
|
||||||
pos = at + code.padded_length - cpu_jump.byte_length
|
|
||||||
Position.set( cpu_jump , pos , code)
|
|
||||||
cpu_jump.assemble(JumpWriter.new(code))
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_method
|
|
||||||
next_m = @method.next_method
|
|
||||||
return next_m if next_m
|
|
||||||
Position.log.debug "Type now #{@method.for_type.name}"
|
|
||||||
type = next_type(@method.for_type)
|
|
||||||
if type
|
|
||||||
Position.log.debug "Position for #{type.name}"
|
|
||||||
return type.methods
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
def next_type(type)
|
|
||||||
nekst = Parfait.object_space.types.next_value(type)
|
|
||||||
return nil unless nekst
|
|
||||||
return nekst if nekst.methods
|
|
||||||
return next_type(nekst)
|
|
||||||
end
|
|
||||||
def self.init( code , at = -1)
|
|
||||||
while code
|
|
||||||
position = ObjectPosition.new(code , at)
|
|
||||||
Position.set_to(position , at)
|
|
||||||
if code.next
|
|
||||||
listener = ObjectListener.new(code.next)
|
|
||||||
position.register_event(:position_changed , listener)
|
|
||||||
end
|
|
||||||
at += code.padded_length unless at < 0
|
|
||||||
code = code.next
|
|
||||||
end
|
|
||||||
position
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,75 +1,72 @@
|
|||||||
module Risc
|
module Risc
|
||||||
module Position
|
# Instructions are also a linked list, but their position is not really
|
||||||
|
# the position of the object.
|
||||||
# Instructions are also a linked list, but their position is not really
|
# Rather it is the position of the assembled code in the binary.
|
||||||
# the position of the object.
|
# (Luckily arm is sane, so this is realtively simple)
|
||||||
# Rather it is the position of the assembled code in the binary.
|
#
|
||||||
# (Luckily arm is sane, so this is realtively simple)
|
# Really we only need to calculate Positions at a jump, so between the
|
||||||
#
|
# Jump and the label it jumps too. The other instructions are "just" fill.
|
||||||
# Really we only need to calculate Positions at a jump, so between the
|
# But off course we need to propagate positions to get it right.
|
||||||
# Jump and the label it jumps too. The other instructions are "just" fill.
|
#
|
||||||
# But off course we need to propagate positions to get it right.
|
# Assembled instructions are kept in BinaryCode objects.
|
||||||
#
|
# When propagating positions we have to see that the next position assembles into
|
||||||
# Assembled instructions are kept in BinaryCode objects.
|
# the same BinaryCode, or else move it and the code along
|
||||||
# When propagating positions we have to see that the next position assembles into
|
#
|
||||||
# the same BinaryCode, or else move it and the code along
|
class InstructionListener
|
||||||
#
|
attr_reader :instruction , :binary
|
||||||
class InstructionListener
|
def initialize(instruction , binary)
|
||||||
attr_reader :instruction , :binary
|
pos = 0
|
||||||
def initialize(instruction , binary)
|
@instruction = instruction
|
||||||
pos = 0
|
@binary = binary
|
||||||
@instruction = instruction
|
end
|
||||||
@binary = binary
|
def init(at, binary)
|
||||||
|
@binary = binary
|
||||||
|
instruction.address.set_value(at) if instruction.is_a?(Label)
|
||||||
|
return if at == 0 and binary.nil?
|
||||||
|
raise "faux pas" if at < Position.get(binary).at
|
||||||
|
return unless @instruction.next
|
||||||
|
nekst = at + @instruction.byte_length
|
||||||
|
diff = nekst - Position.get(@binary).at
|
||||||
|
Position.log.debug "Diff: #{diff.to_s(16)} , next #{nekst.to_s(16)} , binary #{Position.get(@binary)}"
|
||||||
|
raise "Invalid position #{diff.to_s(16)} , next #{nekst.to_s(16)} #{self}" if diff < 8
|
||||||
|
if( (diff % (binary.padded_length - @instruction.byte_length)) == 0 )
|
||||||
|
binary.extend_one unless binary.next
|
||||||
|
binary = binary.next
|
||||||
|
raise "end of line " unless binary
|
||||||
|
nekst = Position.get(binary).at + Parfait::BinaryCode.byte_offset
|
||||||
|
Position.log.debug "Jump to: #{nekst.to_s(16)}"
|
||||||
end
|
end
|
||||||
def init(at, binary)
|
Position.set(@instruction.next, nekst , binary)
|
||||||
@binary = binary
|
end
|
||||||
instruction.address.set_value(at) if instruction.is_a?(Label)
|
|
||||||
return if at == 0 and binary.nil?
|
def reset_to(pos , binary)
|
||||||
raise "faux pas" if at < Position.get(binary).at
|
super(pos , binary)
|
||||||
return unless @instruction.next
|
init(pos , binary)
|
||||||
nekst = at + @instruction.byte_length
|
Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}"
|
||||||
diff = nekst - Position.get(@binary).at
|
end
|
||||||
Position.log.debug "Diff: #{diff.to_s(16)} , next #{nekst.to_s(16)} , binary #{Position.get(@binary)}"
|
|
||||||
raise "Invalid position #{diff.to_s(16)} , next #{nekst.to_s(16)} #{self}" if diff < 8
|
# initialize the dependency graph for instructions
|
||||||
if( (diff % (binary.padded_length - @instruction.byte_length)) == 0 )
|
#
|
||||||
binary.extend_one unless binary.next
|
# starting from the given instruction, create Positions
|
||||||
binary = binary.next
|
# for it and the whole chain. Then attach InstructionListeners
|
||||||
raise "end of line " unless binary
|
# for dependency tracking. All positions are initialized with -1
|
||||||
nekst = Position.get(binary).at + Parfait::BinaryCode.byte_offset
|
# and so setting the first will trigger a chain reaction
|
||||||
Position.log.debug "Jump to: #{nekst.to_s(16)}"
|
#
|
||||||
|
# return the position for the first instruction which may be used to
|
||||||
|
# set all positions in the chain
|
||||||
|
def self.init( instruction , code )
|
||||||
|
first = nil
|
||||||
|
while(instruction)
|
||||||
|
position = Position.new(instruction , -1)
|
||||||
|
first = position unless first
|
||||||
|
nekst = instruction.next
|
||||||
|
if nekst
|
||||||
|
listener = InstructionListener.new( nekst , code )
|
||||||
|
position.register_event(:position_changed , listener)
|
||||||
end
|
end
|
||||||
Position.set(@instruction.next, nekst , binary)
|
instruction = nekst
|
||||||
end
|
|
||||||
|
|
||||||
def reset_to(pos , binary)
|
|
||||||
super(pos , binary)
|
|
||||||
init(pos , binary)
|
|
||||||
Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# initialize the dependency graph for instructions
|
|
||||||
#
|
|
||||||
# starting from the given instruction, create ObjectPositions
|
|
||||||
# for it and the whole chain. Then attach InstructionListeners
|
|
||||||
# for dependency tracking. All positions are initialized with -1
|
|
||||||
# and so setting the first will trigger a chain reaction
|
|
||||||
#
|
|
||||||
# return the position for the first instruction which may be used to
|
|
||||||
# set all positions in the chain
|
|
||||||
def self.init( instruction , code )
|
|
||||||
first = nil
|
|
||||||
while(instruction)
|
|
||||||
position = ObjectPosition.new(instruction , -1)
|
|
||||||
first = position unless first
|
|
||||||
nekst = instruction.next
|
|
||||||
if nekst
|
|
||||||
listener = InstructionListener.new( nekst , code )
|
|
||||||
position.register_event(:position_changed , listener)
|
|
||||||
end
|
|
||||||
instruction = nekst
|
|
||||||
end
|
|
||||||
first
|
|
||||||
end
|
end
|
||||||
|
first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,31 +1,29 @@
|
|||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
module Position
|
|
||||||
|
|
||||||
# Listeners localise the changes that need to happen.
|
# Listeners localise the changes that need to happen.
|
||||||
|
#
|
||||||
|
# An object listener assmes it is set up to the previous object.
|
||||||
|
# so when position changes, it places itself just behind the previous object
|
||||||
|
#
|
||||||
|
# This is handy, since the "normal" chaining of object is forward
|
||||||
|
# But the dependencies are backwards. This way we don't clutter the
|
||||||
|
# actual object (or even the position), but keep the logic seperate.
|
||||||
|
class PositionListener
|
||||||
|
|
||||||
|
# initialize with the object that needs to react to change
|
||||||
|
def initialize(object)
|
||||||
|
@object = object
|
||||||
|
end
|
||||||
|
|
||||||
|
# when the argument changes position, we update the objects
|
||||||
|
# position to reflect that change
|
||||||
#
|
#
|
||||||
# An object listener assmes it is set up to the previous object.
|
def position_changed(previous)
|
||||||
# so when position changes, it places itself just behind the previous object
|
me = previous.at + previous.object.padded_length
|
||||||
#
|
object_pos = Position.get(@object)
|
||||||
# This is handy, since the "normal" chaining of object is forward
|
return if me == object_pos.at
|
||||||
# But the dependencies are backwards. This way we don't clutter the
|
Position.set(@object , me)
|
||||||
# actual object (or even the position), but keep the logic seperate.
|
|
||||||
class ObjectListener
|
|
||||||
|
|
||||||
# initialize with the object that needs to react to change
|
|
||||||
def initialize(object)
|
|
||||||
@object = object
|
|
||||||
end
|
|
||||||
|
|
||||||
# when the argument changes position, we update the objects
|
|
||||||
# position to reflect that change
|
|
||||||
#
|
|
||||||
def position_changed(previous)
|
|
||||||
me = previous.at + previous.object.padded_length
|
|
||||||
object_pos = Position.get(@object)
|
|
||||||
return if me == object_pos.at
|
|
||||||
Position.set(@object , me)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
require "util/eventable"
|
|
||||||
|
|
||||||
module Risc
|
|
||||||
module Position
|
|
||||||
class ObjectPosition
|
|
||||||
include Util::Eventable
|
|
||||||
|
|
||||||
attr_reader :at , :object
|
|
||||||
|
|
||||||
# initialize with a given object, first parameter
|
|
||||||
# The object ill be the key in global position map
|
|
||||||
# Give an integer as the actual position, where -1
|
|
||||||
# which means no legal position known
|
|
||||||
def initialize(object , pos )
|
|
||||||
@at = pos
|
|
||||||
@object = object
|
|
||||||
Position.set_to(self , pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
#look for InstructionListener and return its code if found
|
|
||||||
def get_code
|
|
||||||
listener = event_table.find{|one| one.class == InstructionListener}
|
|
||||||
return nil unless listener
|
|
||||||
listener.code
|
|
||||||
end
|
|
||||||
def +(offset)
|
|
||||||
offset = offset.at if offset.is_a?(ObjectPosition)
|
|
||||||
@at + offset
|
|
||||||
end
|
|
||||||
|
|
||||||
def -(offset)
|
|
||||||
offset = offset.at if offset.is_a?(ObjectPosition)
|
|
||||||
@at - offset
|
|
||||||
end
|
|
||||||
def to_s
|
|
||||||
"0x#{@at.to_s(16)}"
|
|
||||||
end
|
|
||||||
# just a callback after creation AND insertion
|
|
||||||
def init(pos , is_nil)
|
|
||||||
end
|
|
||||||
def reset_to(pos , guaranteed_nil )
|
|
||||||
return false if pos == at
|
|
||||||
if((at - pos).abs > 1000)
|
|
||||||
raise "position set too far off #{pos}!=#{at} for #{object}:#{object.class}"
|
|
||||||
end
|
|
||||||
@at = pos
|
|
||||||
trigger(:position_changed , self)
|
|
||||||
true
|
|
||||||
end
|
|
||||||
def next_slot
|
|
||||||
return -1 if at < 0
|
|
||||||
at + object.byte_length
|
|
||||||
end
|
|
||||||
def self.init(object , at = -1)
|
|
||||||
position = ObjectPosition.new(object , at)
|
|
||||||
Position.set_to( position , at)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,3 +1,5 @@
|
|||||||
|
require "util/eventable"
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
# Positions are very different during compilation and run-time.
|
# Positions are very different during compilation and run-time.
|
||||||
# At run-time they are inherrent to the object, and fixed.
|
# At run-time they are inherrent to the object, and fixed.
|
||||||
@ -14,10 +16,50 @@ module Risc
|
|||||||
# While the (different)Position objects transmit the change that (re) positioning
|
# While the (different)Position objects transmit the change that (re) positioning
|
||||||
# entails to affected objects.
|
# entails to affected objects.
|
||||||
|
|
||||||
module Position
|
class Position
|
||||||
include Util::Logging
|
include Util::Logging
|
||||||
log_level :info
|
log_level :info
|
||||||
|
|
||||||
|
include Util::Eventable
|
||||||
|
|
||||||
|
attr_reader :at , :object
|
||||||
|
|
||||||
|
# initialize with a given object, first parameter
|
||||||
|
# The object ill be the key in global position map
|
||||||
|
# Give an integer as the actual position, where -1
|
||||||
|
# which means no legal position known
|
||||||
|
def initialize(object , pos )
|
||||||
|
@at = pos
|
||||||
|
@object = object
|
||||||
|
Position.set_to(self , pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
#look for InstructionListener and return its code if found
|
||||||
|
def get_code
|
||||||
|
listener = event_table.find{|one| one.class == InstructionListener}
|
||||||
|
return nil unless listener
|
||||||
|
listener.code
|
||||||
|
end
|
||||||
|
|
||||||
|
def +(offset)
|
||||||
|
offset = offset.at if offset.is_a?(Position)
|
||||||
|
@at + offset
|
||||||
|
end
|
||||||
|
|
||||||
|
def -(offset)
|
||||||
|
offset = offset.at if offset.is_a?(Position)
|
||||||
|
@at - offset
|
||||||
|
end
|
||||||
|
def to_s
|
||||||
|
"0x#{@at.to_s(16)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_slot
|
||||||
|
return -1 if at < 0
|
||||||
|
at + object.byte_length
|
||||||
|
end
|
||||||
|
|
||||||
|
## class level forward and reverse cache
|
||||||
@positions = {}
|
@positions = {}
|
||||||
@reverse_cache = {}
|
@reverse_cache = {}
|
||||||
|
|
||||||
@ -41,7 +83,7 @@ module Risc
|
|||||||
def self.get(object)
|
def self.get(object)
|
||||||
pos = self.positions[object]
|
pos = self.positions[object]
|
||||||
if pos == nil
|
if pos == nil
|
||||||
str = "position accessed but not set, "
|
str = "position accessed but not initialized, "
|
||||||
str += "0x#{object.object_id.to_s(16)}\n"
|
str += "0x#{object.object_id.to_s(16)}\n"
|
||||||
str += "for #{object.class} "
|
str += "for #{object.class} "
|
||||||
str += "byte_length #{object.byte_length}" if object.respond_to?(:byte_length)
|
str += "byte_length #{object.byte_length}" if object.respond_to?(:byte_length)
|
||||||
@ -51,16 +93,11 @@ module Risc
|
|||||||
pos
|
pos
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.reset(obj)
|
|
||||||
old = self.get(obj)
|
|
||||||
old.reset_to( old.at )
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.set_to( position , to)
|
def self.set_to( position , to)
|
||||||
postest = Position.positions[position.object] unless to < 0
|
postest = Position.positions[position.object] unless to < 0
|
||||||
raise "Mismatch #{position}" if postest and postest != position
|
raise "Mismatch #{position}" if postest and postest != position
|
||||||
@reverse_cache.delete(position.at) unless position.object.is_a? Label
|
@reverse_cache.delete(position.at) unless position.object.is_a? Label
|
||||||
testing = self.at( position.at ) if position.at >= 0
|
testing = self.at( position.at ) unless position.at < 0
|
||||||
if testing and testing.class != position.class
|
if testing and testing.class != position.class
|
||||||
raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}"
|
raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}"
|
||||||
end
|
end
|
||||||
@ -71,7 +108,6 @@ module Risc
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
require_relative "object_position"
|
|
||||||
require_relative "object_listener"
|
require_relative "object_listener"
|
||||||
require_relative "instruction_listener"
|
require_relative "instruction_listener"
|
||||||
require_relative "code_listener"
|
require_relative "code_listener"
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
require_relative "../helper"
|
require_relative "../helper"
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
module Position
|
class Dummy
|
||||||
class Dummy
|
def padded_length
|
||||||
def padded_length
|
4
|
||||||
4
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,35 +1,33 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
module Position
|
# tests that require a boot and test propagation
|
||||||
# tests that require a boot and test propagation
|
class TestcodeListener < MiniTest::Test
|
||||||
class TestcodeListener < MiniTest::Test
|
def setup
|
||||||
def setup
|
Risc.machine.boot
|
||||||
Risc.machine.boot
|
@binary = Parfait::BinaryCode.new(1)
|
||||||
@binary = Parfait::BinaryCode.new(1)
|
@method = Parfait.object_space.types.values.first.methods
|
||||||
@method = Parfait.object_space.types.values.first.methods
|
@label = Risc.label("hi","ho")
|
||||||
@label = Risc.label("hi","ho")
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def test_has_init
|
def test_has_init
|
||||||
pos = CodeListener.init(@binary)
|
pos = CodeListener.init(@binary)
|
||||||
assert_equal pos, Position.get(@binary)
|
assert_equal pos, Position.get(@binary)
|
||||||
end
|
end
|
||||||
def test_init_returns_position
|
def test_init_returns_position
|
||||||
|
|
||||||
assert_equal Position::ObjectPosition , CodeListener.init(@binary).class
|
assert_equal Position , CodeListener.init(@binary).class
|
||||||
end
|
end
|
||||||
def test_init_listner
|
def test_init_listner
|
||||||
@binary.extend_one
|
@binary.extend_one
|
||||||
CodeListener.init(@binary)
|
CodeListener.init(@binary)
|
||||||
pos = Position.get(@binary)
|
pos = Position.get(@binary)
|
||||||
assert !pos.event_table[:position_changed].empty?
|
assert !pos.event_table[:position_changed].empty?
|
||||||
end
|
end
|
||||||
def test_not_init_listner
|
def test_not_init_listner
|
||||||
CodeListener.init(@binary)
|
CodeListener.init(@binary)
|
||||||
pos = Position.get(@binary)
|
pos = Position.get(@binary)
|
||||||
assert pos.event_table[:position_changed].empty?
|
assert pos.event_table[:position_changed].empty?
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,7 +11,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
def test_set_bin
|
def test_set_bin
|
||||||
pos = Position.set( @binary , 0 , @method)
|
pos = Position.set( @binary , 0 , @method)
|
||||||
assert_equal Position::CodePosition , pos.class
|
assert_equal CodePosition , pos.class
|
||||||
end
|
end
|
||||||
def test_type
|
def test_type
|
||||||
pos = Position.set( @binary , 0 , @method)
|
pos = Position.set( @binary , 0 , @method)
|
||||||
|
@ -1,63 +1,61 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
module Position
|
# tests that require a boot and test propagation
|
||||||
# tests that require a boot and test propagation
|
class TestInstructionListener < MiniTest::Test
|
||||||
class TestInstructionListener < MiniTest::Test
|
def setup
|
||||||
def setup
|
Risc.machine.boot
|
||||||
Risc.machine.boot
|
@binary = Parfait::BinaryCode.new(1)
|
||||||
@binary = Parfait::BinaryCode.new(1)
|
#Position.set(@binary , 0 , Parfait.object_space.get_main)
|
||||||
#Position.set(@binary , 0 , Parfait.object_space.get_main)
|
@label = Risc.label("hi","ho")
|
||||||
@label = Risc.label("hi","ho")
|
end
|
||||||
end
|
def test_init
|
||||||
def test_init
|
assert InstructionListener.init(@label , @binary)
|
||||||
assert InstructionListener.init(@label , @binary)
|
end
|
||||||
end
|
def pest_set_instr
|
||||||
def pest_set_instr
|
pos = Position.set( @label , 8 , @binary)
|
||||||
pos = Position.set( @label , 8 , @binary)
|
assert_equal InstructionPosition , pos.class
|
||||||
assert_equal InstructionPosition , pos.class
|
end
|
||||||
end
|
def pest_label_set_int
|
||||||
def pest_label_set_int
|
Position.set( @label , 8 , @binary)
|
||||||
Position.set( @label , 8 , @binary)
|
assert_equal 8 , @label.address.value
|
||||||
assert_equal 8 , @label.address.value
|
end
|
||||||
end
|
def pest_label_reset_int
|
||||||
def pest_label_reset_int
|
Position.set( @label , 8 , @binary)
|
||||||
Position.set( @label , 8 , @binary)
|
Position.set( @label , 18 , @binary)
|
||||||
Position.set( @label , 18 , @binary)
|
assert_equal 18 , @label.address.value
|
||||||
assert_equal 18 , @label.address.value
|
end
|
||||||
end
|
def pest_ins_propagates
|
||||||
def pest_ins_propagates
|
@label.set_next Arm::ArmMachine.b( @label)
|
||||||
@label.set_next Arm::ArmMachine.b( @label)
|
Position.set( @label , 8 , @binary)
|
||||||
Position.set( @label , 8 , @binary)
|
assert_equal 8 , Position.get(@label.next).at
|
||||||
assert_equal 8 , Position.get(@label.next).at
|
end
|
||||||
end
|
def pest_ins_propagates_again
|
||||||
def pest_ins_propagates_again
|
second = Arm::ArmMachine.b( @label)
|
||||||
second = Arm::ArmMachine.b( @label)
|
@label.set_next(second)
|
||||||
@label.set_next(second)
|
Position.set( @label , 8 , @binary)
|
||||||
Position.set( @label , 8 , @binary)
|
Position.set(second , 12 , @binary)
|
||||||
Position.set(second , 12 , @binary)
|
Position.set( @label , 8 , @binary)
|
||||||
Position.set( @label , 8 , @binary)
|
assert_equal 8 , Position.get(@label.next).at
|
||||||
assert_equal 8 , Position.get(@label.next).at
|
end
|
||||||
end
|
def pest_label_at
|
||||||
def pest_label_at
|
branch = Branch.new("b" , @label)
|
||||||
branch = Branch.new("b" , @label)
|
Position.set(@label , 8 , @binary)
|
||||||
Position.set(@label , 8 , @binary)
|
Position.set(branch , 8 , @binary)
|
||||||
Position.set(branch , 8 , @binary)
|
at_4 = Position.at(8)
|
||||||
at_4 = Position.at(8)
|
assert_equal InstructionPosition , at_4.class
|
||||||
assert_equal InstructionPosition , at_4.class
|
assert_equal Branch , at_4.instruction.class
|
||||||
assert_equal Branch , at_4.instruction.class
|
end
|
||||||
end
|
def pest_label_at_reverse
|
||||||
def pest_label_at_reverse
|
branch = Branch.new("b" , @label)
|
||||||
branch = Branch.new("b" , @label)
|
Position.set(branch , 8 , @binary)
|
||||||
Position.set(branch , 8 , @binary)
|
Position.set(@label , 8 , @binary)
|
||||||
Position.set(@label , 8 , @binary)
|
at_4 = Position.at(8)
|
||||||
at_4 = Position.at(8)
|
assert_equal InstructionPosition , at_4.class
|
||||||
assert_equal InstructionPosition , at_4.class
|
assert_equal Branch , at_4.instruction.class
|
||||||
assert_equal Branch , at_4.instruction.class
|
end
|
||||||
end
|
def pest_reset_false_type
|
||||||
def pest_reset_false_type
|
assert_raises {Position.set(@label , 0 , @binary)}
|
||||||
assert_raises {Position.set(@label , 0 , @binary)}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,29 +1,27 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
module Position
|
class TestPositionListener < MiniTest::Test
|
||||||
class TestObjectListener < MiniTest::Test
|
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@object = Dummy.new
|
@object = Dummy.new
|
||||||
@dependent = Dummy.new
|
@dependent = Dummy.new
|
||||||
@pos = ObjectPosition.new(@object,0)
|
@pos = Position.new(@object,0)
|
||||||
ObjectPosition.new(@dependent,0)
|
Position.new(@dependent,0)
|
||||||
@listener = ObjectListener.new(@dependent)
|
@listener = PositionListener.new(@dependent)
|
||||||
end
|
end
|
||||||
def test_register
|
def test_register
|
||||||
assert @pos.register_event(:position_changed , @listener)
|
assert @pos.register_event(:position_changed , @listener)
|
||||||
end
|
end
|
||||||
def test_no_fire
|
def test_no_fire
|
||||||
@pos.register_event(:position_changed , self)
|
@pos.register_event(:position_changed , self)
|
||||||
Position.set_to(@pos,0)
|
Position.set_to(@pos,0)
|
||||||
assert_equal 0 , Position.get(@object).at
|
assert_equal 0 , Position.get(@object).at
|
||||||
end
|
end
|
||||||
def test_reset
|
def test_reset
|
||||||
@pos.register_event(:position_changed , @listener)
|
@pos.register_event(:position_changed , @listener)
|
||||||
Position.set_to(@pos,4)
|
Position.set_to(@pos,4)
|
||||||
assert_equal 0 , Position.at(4).at
|
assert_equal 0 , Position.at(4).at
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
require_relative "helper"
|
|
||||||
|
|
||||||
module Risc
|
|
||||||
module Position
|
|
||||||
# tests that do no require a boot and only test basic positioning
|
|
||||||
class TestObjectPosition < MiniTest::Test
|
|
||||||
|
|
||||||
def test_init
|
|
||||||
assert ObjectPosition.init(self , -1)
|
|
||||||
end
|
|
||||||
def test_next_slot
|
|
||||||
mov = Arm::ArmMachine.mov(:r1 , :r1)
|
|
||||||
position = ObjectPosition.new(mov , 0)
|
|
||||||
assert_equal 4, position.next_slot
|
|
||||||
end
|
|
||||||
def test_has_get_code
|
|
||||||
assert_nil ObjectPosition.init(self , -1).get_code
|
|
||||||
end
|
|
||||||
def pest_creation_ok
|
|
||||||
assert ObjectPosition.new(self,0)
|
|
||||||
end
|
|
||||||
def pest_creation_fail
|
|
||||||
assert_raises {Position.new("0")}
|
|
||||||
end
|
|
||||||
def pest_add
|
|
||||||
res = ObjectPosition.new(self,0) + 5
|
|
||||||
assert_equal 5 , res
|
|
||||||
end
|
|
||||||
def pest_sub
|
|
||||||
res = ObjectPosition.new(self,0) - 1
|
|
||||||
assert_equal -1 , res
|
|
||||||
end
|
|
||||||
def pest_sub_pos
|
|
||||||
res = ObjectPosition.new(self,0) - ObjectPosition.new(self,0)
|
|
||||||
assert_equal 0 , res
|
|
||||||
end
|
|
||||||
def pest_set
|
|
||||||
pos = Position.set(self , 5)
|
|
||||||
assert_equal 5 , pos.at
|
|
||||||
end
|
|
||||||
def tet_tos
|
|
||||||
assert_equal "0x10" , Position.set(self).to_s
|
|
||||||
end
|
|
||||||
def pest_reset_ok
|
|
||||||
pos = Position.set(self , 5)
|
|
||||||
pos = Position.set(self , 10)
|
|
||||||
assert_equal 10 , pos.at
|
|
||||||
end
|
|
||||||
def pest_reset_fail
|
|
||||||
Position.set(self , 5)
|
|
||||||
assert_raises{Position.set(self , 10000)}
|
|
||||||
end
|
|
||||||
def pest_raises_set_nil
|
|
||||||
assert_raises { Position.set(self,nil)}
|
|
||||||
end
|
|
||||||
def pest_at
|
|
||||||
pos = Position.set(self , 5)
|
|
||||||
pos = Position.at(5)
|
|
||||||
assert_equal 5 , pos.at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
class TestPositionEvents < MiniTest::Test
|
|
||||||
def setup
|
|
||||||
@position = ObjectPosition.new(self)
|
|
||||||
end
|
|
||||||
def pest_has_register
|
|
||||||
assert @position.register_event(:position_changed , self)
|
|
||||||
end
|
|
||||||
def pest_can_unregister
|
|
||||||
assert @position.register_event(:position_changed ,self)
|
|
||||||
assert @position.unregister_event(:position_changed ,self)
|
|
||||||
end
|
|
||||||
def pest_fires
|
|
||||||
@position.register_event(:position_changed ,self)
|
|
||||||
@position.trigger(:position_changed , @position)
|
|
||||||
assert_equal @position , @trigger
|
|
||||||
end
|
|
||||||
def pest_no_fire_after_unregister
|
|
||||||
assert @position.register_event(:position_changed ,self)
|
|
||||||
assert @position.unregister_event(:position_changed ,self)
|
|
||||||
@position.trigger(:position_changed , @position)
|
|
||||||
assert_nil @trigger
|
|
||||||
end
|
|
||||||
def position_changed(pos)
|
|
||||||
@trigger = pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,5 +1,91 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
|
module Risc
|
||||||
|
# tests that do no require a boot and only test basic positioning
|
||||||
|
class TestPosition < MiniTest::Test
|
||||||
|
|
||||||
|
def test_new
|
||||||
|
assert Position.new(self , -1)
|
||||||
|
end
|
||||||
|
def test_next_slot
|
||||||
|
mov = Arm::ArmMachine.mov(:r1 , :r1)
|
||||||
|
position = Position.new(mov , 0)
|
||||||
|
assert_equal 4, position.next_slot
|
||||||
|
end
|
||||||
|
def test_has_get_code
|
||||||
|
assert_nil Position.new(self , -1).get_code
|
||||||
|
end
|
||||||
|
def pest_creation_ok
|
||||||
|
assert Position.new(self,0)
|
||||||
|
end
|
||||||
|
def pest_creation_fail
|
||||||
|
assert_raises {Position.new("0")}
|
||||||
|
end
|
||||||
|
def pest_add
|
||||||
|
res = Position.new(self,0) + 5
|
||||||
|
assert_equal 5 , res
|
||||||
|
end
|
||||||
|
def pest_sub
|
||||||
|
res = Position.new(self,0) - 1
|
||||||
|
assert_equal -1 , res
|
||||||
|
end
|
||||||
|
def pest_sub_pos
|
||||||
|
res = Position.new(self,0) - Position.new(self,0)
|
||||||
|
assert_equal 0 , res
|
||||||
|
end
|
||||||
|
def pest_set
|
||||||
|
pos = Position.set(self , 5)
|
||||||
|
assert_equal 5 , pos.at
|
||||||
|
end
|
||||||
|
def tet_tos
|
||||||
|
assert_equal "0x10" , Position.set(self).to_s
|
||||||
|
end
|
||||||
|
def pest_reset_ok
|
||||||
|
pos = Position.set(self , 5)
|
||||||
|
pos = Position.set(self , 10)
|
||||||
|
assert_equal 10 , pos.at
|
||||||
|
end
|
||||||
|
def pest_reset_fail
|
||||||
|
Position.set(self , 5)
|
||||||
|
assert_raises{Position.set(self , 10000)}
|
||||||
|
end
|
||||||
|
def pest_raises_set_nil
|
||||||
|
assert_raises { Position.set(self,nil)}
|
||||||
|
end
|
||||||
|
def pest_at
|
||||||
|
pos = Position.set(self , 5)
|
||||||
|
pos = Position.at(5)
|
||||||
|
assert_equal 5 , pos.at
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class TestPositionEvents < MiniTest::Test
|
||||||
|
def setup
|
||||||
|
@position = Position.new(self)
|
||||||
|
end
|
||||||
|
def pest_has_register
|
||||||
|
assert @position.register_event(:position_changed , self)
|
||||||
|
end
|
||||||
|
def pest_can_unregister
|
||||||
|
assert @position.register_event(:position_changed ,self)
|
||||||
|
assert @position.unregister_event(:position_changed ,self)
|
||||||
|
end
|
||||||
|
def pest_fires
|
||||||
|
@position.register_event(:position_changed ,self)
|
||||||
|
@position.trigger(:position_changed , @position)
|
||||||
|
assert_equal @position , @trigger
|
||||||
|
end
|
||||||
|
def pest_no_fire_after_unregister
|
||||||
|
assert @position.register_event(:position_changed ,self)
|
||||||
|
assert @position.unregister_event(:position_changed ,self)
|
||||||
|
@position.trigger(:position_changed , @position)
|
||||||
|
assert_nil @trigger
|
||||||
|
end
|
||||||
|
def position_changed(pos)
|
||||||
|
@trigger = pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
class TestMachinePositions < MiniTest::Test
|
class TestMachinePositions < MiniTest::Test
|
||||||
def setup
|
def setup
|
||||||
|
@ -51,7 +51,7 @@ module Risc
|
|||||||
assert_equal "0x5ecc" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s
|
assert_equal "0x5ecc" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s
|
||||||
end
|
end
|
||||||
def test_cpu_label
|
def test_cpu_label
|
||||||
assert_equal Position::InstructionPosition , Position.get(@machine.cpu_init.first).class
|
assert_equal InstructionPosition , Position.get(@machine.cpu_init.first).class
|
||||||
end
|
end
|
||||||
def test_first_binary_jump
|
def test_first_binary_jump
|
||||||
bin = Parfait.object_space.get_init.binary
|
bin = Parfait.object_space.get_init.binary
|
||||||
|
Loading…
Reference in New Issue
Block a user