Class: AVR::CPU
Instance Attribute Summary collapse
-
#clock ⇒ Object
readonly
Returns the value of attribute clock.
-
#decoder ⇒ Object
readonly
Returns the value of attribute decoder.
-
#device ⇒ Object
readonly
Returns the value of attribute device.
-
#io_registers ⇒ Object
readonly
Returns the value of attribute io_registers.
-
#next_pc ⇒ Object
Returns the value of attribute next_pc.
-
#pc ⇒ Object
Returns the value of attribute pc.
-
#ports ⇒ Object
readonly
Returns the value of attribute ports.
-
#registers ⇒ Object
readonly
Returns the value of attribute registers.
-
#sp ⇒ Object
readonly
Returns the value of attribute sp.
-
#sram ⇒ Object
readonly
Returns the value of attribute sram.
-
#sreg ⇒ Object
readonly
Returns the value of attribute sreg.
-
#tracer ⇒ Object
readonly
Returns the value of attribute tracer.
Instance Method Summary collapse
- #decode ⇒ Object
- #fetch ⇒ Object
-
#initialize(device) ⇒ CPU
constructor
A new instance of CPU.
- #instruction(mnemonic, *args) ⇒ Object
- #interrupt(name_or_vector_number) ⇒ Object
- #notify_at_tick(tick, &block) ⇒ Object
- #peek ⇒ Object
- #print_status ⇒ Object
- #r0 ⇒ Object
- #r0=(value) ⇒ Object
- #r1 ⇒ Object
- #r1=(value) ⇒ Object
- #reset ⇒ Object
- #reset_to_clean_state ⇒ Object
- #step ⇒ Object
- #trace(&block) ⇒ Object
- #X ⇒ Object
- #Y ⇒ Object
- #Z ⇒ Object
Constructor Details
#initialize(device) ⇒ CPU
Returns a new instance of CPU.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/avr/cpu.rb', line 82 def initialize(device) @device = device @pc = 0 @next_pc = 0 @sram = SRAM.new(device.ram_start + device.sram_size) @registers = RegisterFile.new(self) device.register_count.times do |n| registers.add(MemoryByteRegister.new(self, "r#{n}", @sram.memory[n])) end device.word_register_map.each do |name, map| registers.add(RegisterPair.new(self, @registers[map[:l]], @registers[map[:h]], name)) end @io_registers = RegisterFile.new(self) device.io_registers.each do |name| address = device.data_memory_map[name] next unless address bit_names = device.register_bit_names_map[name] if bit_names io_registers.add(MemoryByteRegisterWithNamedBits.new(self, name.to_s, @sram.memory[address], bit_names)) else io_registers.add(MemoryByteRegister.new(self, name.to_s, @sram.memory[address])) end end @sreg = SREG.new(self) @sp = SP.new( self, @sram.memory[device.data_memory_map[:SPL]], @sram.memory[device.data_memory_map[:SPH]], device.ram_end ) @decoder = OpcodeDecoder.new @ports = {} device.port_map.each do |name, addr| @ports[name] = Port.new(self, name, addr[:pin], addr[:ddr], addr[:port]) end @clock = Clock.new('cpu') @clock.push_sink(Clock::Sink.new('cpu') { step }) @tracer = nil end |
Instance Attribute Details
#clock ⇒ Object (readonly)
Returns the value of attribute clock.
76 77 78 |
# File 'lib/avr/cpu.rb', line 76 def clock @clock end |
#decoder ⇒ Object (readonly)
Returns the value of attribute decoder.
70 71 72 |
# File 'lib/avr/cpu.rb', line 70 def decoder @decoder end |
#device ⇒ Object (readonly)
Returns the value of attribute device.
9 10 11 |
# File 'lib/avr/cpu.rb', line 9 def device @device end |
#io_registers ⇒ Object (readonly)
Returns the value of attribute io_registers.
59 60 61 |
# File 'lib/avr/cpu.rb', line 59 def io_registers @io_registers end |
#next_pc ⇒ Object
Returns the value of attribute next_pc.
15 16 17 |
# File 'lib/avr/cpu.rb', line 15 def next_pc @next_pc end |
#pc ⇒ Object
Returns the value of attribute pc.
12 13 14 |
# File 'lib/avr/cpu.rb', line 12 def pc @pc end |
#ports ⇒ Object (readonly)
Returns the value of attribute ports.
73 74 75 |
# File 'lib/avr/cpu.rb', line 73 def ports @ports end |
#registers ⇒ Object (readonly)
Returns the value of attribute registers.
21 22 23 |
# File 'lib/avr/cpu.rb', line 21 def registers @registers end |
#sp ⇒ Object (readonly)
Returns the value of attribute sp.
67 68 69 |
# File 'lib/avr/cpu.rb', line 67 def sp @sp end |
#sram ⇒ Object (readonly)
Returns the value of attribute sram.
18 19 20 |
# File 'lib/avr/cpu.rb', line 18 def sram @sram end |
#sreg ⇒ Object (readonly)
Returns the value of attribute sreg.
64 65 66 |
# File 'lib/avr/cpu.rb', line 64 def sreg @sreg end |
#tracer ⇒ Object (readonly)
Returns the value of attribute tracer.
79 80 81 |
# File 'lib/avr/cpu.rb', line 79 def tracer @tracer end |
Instance Method Details
#decode ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/avr/cpu.rb', line 212 def decode offset = next_pc word = fetch decoded_opcode = decoder.decode(word) unless decoded_opcode raise 'Unable to decode 0x%04x at offset 0x%04x words (0x%04x bytes)' % [ word, offset, offset * 2, ] end decoded_opcode.opcode_definition.parse( self, decoded_opcode.opcode_definition, decoded_opcode.prepare_operands(self) ) end |
#fetch ⇒ Object
187 188 189 190 191 |
# File 'lib/avr/cpu.rb', line 187 def fetch word = device.flash.word(next_pc) @next_pc += 1 word end |
#instruction(mnemonic, *args) ⇒ Object
194 195 196 |
# File 'lib/avr/cpu.rb', line 194 def instruction(mnemonic, *args) Instruction.new(self, mnemonic, args) end |
#interrupt(name_or_vector_number) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/avr/cpu.rb', line 199 def interrupt(name_or_vector_number) sreg.I = false case name_or_vector_number when Integer address = name_or_vector_number * 2 when Symbol address = device.interrupt_vector_map[name_or_vector_number] end instruction(:call, Value.new(address)).execute end |
#notify_at_tick(tick, &block) ⇒ Object
133 134 135 |
# File 'lib/avr/cpu.rb', line 133 def notify_at_tick(tick, &block) clock.notify_at_tick(tick, Clock::Sink.new("notify #{block} at #{tick}", block.to_proc)) end |
#peek ⇒ Object
232 233 234 235 236 237 238 239 |
# File 'lib/avr/cpu.rb', line 232 def peek save_pc = pc save_next_pc = next_pc i = decode @pc = save_pc @next_pc = save_next_pc i end |
#print_status ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/avr/cpu.rb', line 144 def print_status puts 'Status:' puts '%8s = %d' % ['Ticks', clock.ticks] puts '%8s = %d opcodes' % ['Cache', decoder.cache.size] puts '%8s = 0x%04x words' % ['PC', pc] puts '%8s = 0x%04x bytes' % ['PC', pc * 2] puts '%8s = 0x%04x (%d bytes used)' % ['SP', sp.value, device.ram_end - sp.value] puts '%8s = 0x%02x [%s]' % ['SREG', sreg.value, sreg.bit_values] puts puts 'Registers:' registers.print_status puts puts 'IO Registers:' io_registers.print_status puts puts 'IO Ports:' puts '%4s %s' % ['', Port::PINS.join(' ')] ports.each do |name, port| puts '%4s: %s' % [name, port.pin_states.join(' ')] end puts puts 'Next instruction:' puts ' ' + peek.to_s puts end |
#r0 ⇒ Object
24 25 26 |
# File 'lib/avr/cpu.rb', line 24 def r0 registers.fetch(:r0) end |
#r0=(value) ⇒ Object
29 30 31 |
# File 'lib/avr/cpu.rb', line 29 def r0=(value) registers.fetch(:r0).value = value end |
#r1 ⇒ Object
34 35 36 |
# File 'lib/avr/cpu.rb', line 34 def r1 registers.fetch(:r1) end |
#r1=(value) ⇒ Object
39 40 41 |
# File 'lib/avr/cpu.rb', line 39 def r1=(value) registers.fetch(:r1).value = value end |
#reset ⇒ Object
180 181 182 183 184 |
# File 'lib/avr/cpu.rb', line 180 def reset @pc = 0 @next_pc = 0 sreg.reset end |
#reset_to_clean_state ⇒ Object
171 172 173 174 175 176 177 |
# File 'lib/avr/cpu.rb', line 171 def reset_to_clean_state reset registers.reset io_registers.reset sram.reset sp.value = device.ram_end end |
#step ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/avr/cpu.rb', line 242 def step i = decode @tracer&.call(i) begin i.execute rescue StandardError puts "*** Caught exception while executing #{i}, CPU status:" print_status raise end end |
#trace(&block) ⇒ Object
138 139 140 141 |
# File 'lib/avr/cpu.rb', line 138 def trace(&block) @tracer = nil @tracer = block.to_proc if block_given? end |
#X ⇒ Object
44 45 46 |
# File 'lib/avr/cpu.rb', line 44 def X registers.fetch(:X) end |
#Y ⇒ Object
49 50 51 |
# File 'lib/avr/cpu.rb', line 49 def Y registers.fetch(:Y) end |
#Z ⇒ Object
54 55 56 |
# File 'lib/avr/cpu.rb', line 54 def Z registers.fetch(:Z) end |