rpicsim 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/Gemfile +7 -6
- data/Introduction.md +3 -1
- data/README.md +2 -2
- data/docs/ChangeLog.md +6 -0
- data/docs/Contributing.md +1 -1
- data/docs/DefiningSimulationClass.md +11 -10
- data/docs/HowMPLABXIsFound.md +1 -1
- data/docs/IntegrationTesting.md +1 -1
- data/docs/IntroductionToRSpec.md +8 -5
- data/docs/IntroductionToRuby.md +2 -2
- data/docs/KnownIssues.md +46 -57
- data/docs/Labels.md +5 -4
- data/docs/Manual.md +1 -1
- data/docs/Memories.md +70 -0
- data/docs/PersistentExpectations.md +31 -2
- data/docs/Pins.md +5 -7
- data/docs/PreventingCallStackOverflow.md +4 -6
- data/docs/QuickStartGuide.md +5 -5
- data/docs/RSpecIntegration.md +2 -2
- data/docs/RamWatcher.md +22 -11
- data/docs/Running.md +4 -6
- data/docs/Stubbing.md +4 -4
- data/docs/SupportedDevices.md +2 -11
- data/docs/SupportedMPLABXVersions.md +1 -0
- data/docs/SupportedOperatingSystems.md +3 -2
- data/docs/UnitTesting.md +1 -1
- data/docs/Variables.md +81 -25
- data/lib/rpicsim.rb +0 -12
- data/lib/rpicsim/call_stack_info.rb +43 -47
- data/lib/rpicsim/composite_memory.rb +53 -0
- data/lib/rpicsim/flaws.rb +34 -22
- data/lib/rpicsim/instruction.rb +204 -48
- data/lib/rpicsim/label.rb +4 -4
- data/lib/rpicsim/memory.rb +44 -23
- data/lib/rpicsim/memory_watcher.rb +14 -22
- data/lib/rpicsim/mplab.rb +38 -119
- data/lib/rpicsim/mplab/mplab_assembly.rb +23 -18
- data/lib/rpicsim/mplab/mplab_device_info.rb +9 -9
- data/lib/rpicsim/mplab/mplab_disassembler.rb +5 -6
- data/lib/rpicsim/mplab/mplab_instruction.rb +87 -16
- data/lib/rpicsim/mplab/mplab_loader.rb +106 -0
- data/lib/rpicsim/mplab/mplab_memory.rb +19 -6
- data/lib/rpicsim/mplab/mplab_nmmr_info.rb +4 -4
- data/lib/rpicsim/mplab/mplab_observer.rb +15 -10
- data/lib/rpicsim/mplab/mplab_pin.rb +3 -3
- data/lib/rpicsim/mplab/mplab_processor.rb +5 -5
- data/lib/rpicsim/mplab/mplab_program_file.rb +29 -17
- data/lib/rpicsim/mplab/mplab_register.rb +5 -5
- data/lib/rpicsim/mplab/mplab_sfr_info.rb +4 -4
- data/lib/rpicsim/mplab/mplab_simulator.rb +27 -30
- data/lib/rpicsim/pin.rb +6 -6
- data/lib/rpicsim/program_counter.rb +3 -3
- data/lib/rpicsim/program_file.rb +39 -81
- data/lib/rpicsim/rspec/be_predicate.rb +1 -1
- data/lib/rpicsim/rspec/helpers.rb +1 -1
- data/lib/rpicsim/rspec/persistent_expectations.rb +17 -2
- data/lib/rpicsim/rspec/sim_diagnostics.rb +5 -5
- data/lib/rpicsim/search.rb +1 -1
- data/lib/rpicsim/sim.rb +153 -228
- data/lib/rpicsim/stack_pointer.rb +41 -0
- data/lib/rpicsim/stack_trace.rb +1 -1
- data/lib/rpicsim/storage/memory_integer.rb +235 -0
- data/lib/rpicsim/{register.rb → storage/register.rb} +18 -18
- data/lib/rpicsim/variable.rb +25 -211
- data/lib/rpicsim/variable_set.rb +93 -0
- data/lib/rpicsim/version.rb +2 -2
- metadata +9 -4
- data/docs/SFRs.md +0 -71
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'storage/memory_integer'
|
2
|
+
require_relative 'variable'
|
3
|
+
|
4
|
+
module RPicSim
|
5
|
+
# This class is used internally by {Sim} to manage user-defined variables.
|
6
|
+
class VariableSet
|
7
|
+
attr_writer :address_increment
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@memory_types = []
|
11
|
+
@symbols_for_memory = {}
|
12
|
+
@vars_for_memory = {}
|
13
|
+
@vars_for_memory_by_address = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def def_memory_type(name, symbols)
|
17
|
+
name = name.to_sym
|
18
|
+
@memory_types << name
|
19
|
+
@symbols_for_memory[name] = symbols
|
20
|
+
@vars_for_memory[name] = {}
|
21
|
+
@vars_for_memory_by_address[name] = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def def_var(name, type, opts={})
|
25
|
+
allowed_keys = [:memory, :symbol, :address]
|
26
|
+
invalid_keys = opts.keys - allowed_keys
|
27
|
+
if !invalid_keys.empty?
|
28
|
+
raise ArgumentError, "Unrecognized options: #{invalid_keys.join(', ')}"
|
29
|
+
end
|
30
|
+
|
31
|
+
name = name.to_sym
|
32
|
+
|
33
|
+
memory_type = opts.fetch(:memory, :ram)
|
34
|
+
if !@memory_types.include?(memory_type)
|
35
|
+
raise "Invalid memory type '#{memory_type.inspect}'."
|
36
|
+
end
|
37
|
+
|
38
|
+
symbol_addresses = @symbols_for_memory[memory_type]
|
39
|
+
|
40
|
+
if opts[:address]
|
41
|
+
address = opts[:address].to_i
|
42
|
+
else
|
43
|
+
symbol = (opts[:symbol] || name).to_sym
|
44
|
+
if symbol.to_s.include?('@')
|
45
|
+
raise 'Limitations in MPLAB X code prevent us from accessing ' +
|
46
|
+
"variables with '@' in the name like '#{symbol}'"
|
47
|
+
end
|
48
|
+
address = symbol_addresses[symbol] or raise ArgumentError, "Cannot find variable in #{memory_type} named '#{symbol}'."
|
49
|
+
end
|
50
|
+
|
51
|
+
klass = case type
|
52
|
+
when Class then type
|
53
|
+
when :word then Storage::MemoryWord
|
54
|
+
when :uint8 then Storage::MemoryUInt8
|
55
|
+
when :int8 then Storage::MemoryInt8
|
56
|
+
when :uint16 then Storage::MemoryUInt16
|
57
|
+
when :int16 then Storage::MemoryInt16
|
58
|
+
when :uint24 then Storage::MemoryUInt24
|
59
|
+
when :int24 then Storage::MemoryInt24
|
60
|
+
when :uint32 then Storage::MemoryUInt32
|
61
|
+
when :int32 then Storage::MemoryInt32
|
62
|
+
else raise ArgumentError, "Unknown type '#{type}'."
|
63
|
+
end
|
64
|
+
|
65
|
+
variable = klass.new(name, address)
|
66
|
+
|
67
|
+
if variable.is_a?(Storage::MemoryWord) && memory_type == :program_memory
|
68
|
+
variable.size = @address_increment
|
69
|
+
end
|
70
|
+
|
71
|
+
vars_by_address = @vars_for_memory_by_address[memory_type]
|
72
|
+
variable.addresses.each do |address|
|
73
|
+
if vars_by_address[address]
|
74
|
+
raise 'Variable %s overlaps with %s at 0x%x' %
|
75
|
+
[variable, @vars_by_address[address], address]
|
76
|
+
end
|
77
|
+
vars_by_address[address] = variable
|
78
|
+
end
|
79
|
+
|
80
|
+
@vars_for_memory[memory_type][name] = variable
|
81
|
+
end
|
82
|
+
|
83
|
+
def bind(memories)
|
84
|
+
vars = {}
|
85
|
+
memories.each do |memory_type, memory|
|
86
|
+
@vars_for_memory[memory_type].each do |name, unbound_var|
|
87
|
+
vars[name] = Variable.new(unbound_var.bind(memory))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
vars
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/rpicsim/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module RPicSim
|
2
|
-
VERSION = '0.1
|
3
|
-
end
|
2
|
+
VERSION = '0.2.1'
|
3
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpicsim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pololu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -34,6 +34,7 @@ files:
|
|
34
34
|
- docs/Labels.md
|
35
35
|
- docs/MakingTestsRunFaster.md
|
36
36
|
- docs/Manual.md
|
37
|
+
- docs/Memories.md
|
37
38
|
- docs/PersistentExpectations.md
|
38
39
|
- docs/Pins.md
|
39
40
|
- docs/PreventingCallStackOverflow.md
|
@@ -41,7 +42,6 @@ files:
|
|
41
42
|
- docs/RSpecIntegration.md
|
42
43
|
- docs/RamWatcher.md
|
43
44
|
- docs/Running.md
|
44
|
-
- docs/SFRs.md
|
45
45
|
- docs/Stubbing.md
|
46
46
|
- docs/SupportedCompilers.md
|
47
47
|
- docs/SupportedDevices.md
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- docs/Variables.md
|
52
52
|
- lib/rpicsim.rb
|
53
53
|
- lib/rpicsim/call_stack_info.rb
|
54
|
+
- lib/rpicsim/composite_memory.rb
|
54
55
|
- lib/rpicsim/flaws.rb
|
55
56
|
- lib/rpicsim/instruction.rb
|
56
57
|
- lib/rpicsim/label.rb
|
@@ -61,6 +62,7 @@ files:
|
|
61
62
|
- lib/rpicsim/mplab/mplab_device_info.rb
|
62
63
|
- lib/rpicsim/mplab/mplab_disassembler.rb
|
63
64
|
- lib/rpicsim/mplab/mplab_instruction.rb
|
65
|
+
- lib/rpicsim/mplab/mplab_loader.rb
|
64
66
|
- lib/rpicsim/mplab/mplab_memory.rb
|
65
67
|
- lib/rpicsim/mplab/mplab_nmmr_info.rb
|
66
68
|
- lib/rpicsim/mplab/mplab_observer.rb
|
@@ -73,7 +75,6 @@ files:
|
|
73
75
|
- lib/rpicsim/pin.rb
|
74
76
|
- lib/rpicsim/program_counter.rb
|
75
77
|
- lib/rpicsim/program_file.rb
|
76
|
-
- lib/rpicsim/register.rb
|
77
78
|
- lib/rpicsim/rspec.rb
|
78
79
|
- lib/rpicsim/rspec/be_predicate.rb
|
79
80
|
- lib/rpicsim/rspec/helpers.rb
|
@@ -81,8 +82,12 @@ files:
|
|
81
82
|
- lib/rpicsim/rspec/sim_diagnostics.rb
|
82
83
|
- lib/rpicsim/search.rb
|
83
84
|
- lib/rpicsim/sim.rb
|
85
|
+
- lib/rpicsim/stack_pointer.rb
|
84
86
|
- lib/rpicsim/stack_trace.rb
|
87
|
+
- lib/rpicsim/storage/memory_integer.rb
|
88
|
+
- lib/rpicsim/storage/register.rb
|
85
89
|
- lib/rpicsim/variable.rb
|
90
|
+
- lib/rpicsim/variable_set.rb
|
86
91
|
- lib/rpicsim/version.rb
|
87
92
|
homepage: https://github.com/pololu/rpicsim
|
88
93
|
licenses:
|
data/docs/SFRs.md
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
SFRs
|
2
|
-
====
|
3
|
-
|
4
|
-
The Special Function Registers (SFRs) on a microcontroller enable the firmware to interact with the microcontroller's peripherals and talk to the outside world.
|
5
|
-
RPicSim supports reading and writing these SFRs from Ruby.
|
6
|
-
This can be useful if you want to put your PIC into a particular state and see how a part of your firmware responds.
|
7
|
-
Each SFR is represented as an instance of the {RPicSim::Register} class.
|
8
|
-
|
9
|
-
|
10
|
-
Getting a Register object
|
11
|
-
----
|
12
|
-
|
13
|
-
The {RPicSim::Sim#sfr} method can be called on your simulation object to retrieve a {RPicSim::Register} object:
|
14
|
-
|
15
|
-
!!!ruby
|
16
|
-
sim.sfr(:LATA) # => returns a Register object
|
17
|
-
|
18
|
-
If you are using RPicSim's {file:RSpecIntegration.md RSpec integration}, the `sfr` method inside an example automatically redirects to the `@sim` object:
|
19
|
-
|
20
|
-
!!!ruby
|
21
|
-
it "works" do
|
22
|
-
sfr(:LATA) # => returns a Register object
|
23
|
-
end
|
24
|
-
|
25
|
-
The first argument of {RPicSim::Sim#sfr} should be a symbol containing the name of the SFR.
|
26
|
-
The name comes from the MPLAB X code, but it should match the name given in the microcontroller's datasheet.
|
27
|
-
|
28
|
-
|
29
|
-
Using a register
|
30
|
-
----
|
31
|
-
|
32
|
-
Once you have obtained the {RPicSim::Register Register} object using one of the methods above, you can read and write the value of the SFR using the `value` attribute:
|
33
|
-
|
34
|
-
!!!ruby
|
35
|
-
sfr(:LATA).value = 0x7B
|
36
|
-
expect(sfr(:LATA).value).to eq 0x7B
|
37
|
-
|
38
|
-
|
39
|
-
Protected bits
|
40
|
-
----
|
41
|
-
|
42
|
-
When you write to the register with {RPicSim::Register#value=}, you are probably writing to it in the same way that the simulated microcontroller would write to it.
|
43
|
-
This means that some bits might not be writable or might have restrictions on what value can be written to them.
|
44
|
-
For example, the TO and PD bits of the STATUS register on the PIC10F322 are not writable by the microcontroller.
|
45
|
-
|
46
|
-
To get around this, you can use {RPicSim::Register#memory_value=} instead, which should allow you to write to any of the bits.
|
47
|
-
|
48
|
-
|
49
|
-
Peripheral updating
|
50
|
-
----
|
51
|
-
|
52
|
-
The MPLAB X code contains various objects that simulate the peripherals on a chip, such as the ADC.
|
53
|
-
It has not been determined whether writing to SFRs using the {RPicSim::Register} object updates the simulation of those peripherals in the proper way.
|
54
|
-
Also, whether the peripherals get updated might depend on whether the `value` or the `memory_value` attribute is used for writing.
|
55
|
-
|
56
|
-
|
57
|
-
Non-memory-mapped registers
|
58
|
-
----
|
59
|
-
|
60
|
-
The MPLAB X code considers "SFRs" to only be the special registers that have an address in memory.
|
61
|
-
The special registers without a memory address are called Non-Memory-Mapped Registers (NMMRs).
|
62
|
-
To access these registers, you can use {RPicSim::Sim#nmmr} which is similar to {RPicSim::Sim#sfr}.
|
63
|
-
|
64
|
-
On some chips, WREG and STKPTR are SFRs and on other chips they are NMMRs. To make it easier to access these two registers, RPicSim provides the methods {RPicSim::Sim#wreg} and {RPicSim::Sim#stkptr}. Those methods can be called directly in RSpec examples thanks to RPicSim's {file:RSpecIntegration.md RSpec integration}:
|
65
|
-
|
66
|
-
!!!ruby
|
67
|
-
it "sets W to 5" do
|
68
|
-
expect(wreg.value).to eq 5
|
69
|
-
end
|
70
|
-
|
71
|
-
To access other registers without worrying about what type they are, you can use {RPicSim::Sim#sfr_or_nmmr}.
|