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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/Gemfile +7 -6
  4. data/Introduction.md +3 -1
  5. data/README.md +2 -2
  6. data/docs/ChangeLog.md +6 -0
  7. data/docs/Contributing.md +1 -1
  8. data/docs/DefiningSimulationClass.md +11 -10
  9. data/docs/HowMPLABXIsFound.md +1 -1
  10. data/docs/IntegrationTesting.md +1 -1
  11. data/docs/IntroductionToRSpec.md +8 -5
  12. data/docs/IntroductionToRuby.md +2 -2
  13. data/docs/KnownIssues.md +46 -57
  14. data/docs/Labels.md +5 -4
  15. data/docs/Manual.md +1 -1
  16. data/docs/Memories.md +70 -0
  17. data/docs/PersistentExpectations.md +31 -2
  18. data/docs/Pins.md +5 -7
  19. data/docs/PreventingCallStackOverflow.md +4 -6
  20. data/docs/QuickStartGuide.md +5 -5
  21. data/docs/RSpecIntegration.md +2 -2
  22. data/docs/RamWatcher.md +22 -11
  23. data/docs/Running.md +4 -6
  24. data/docs/Stubbing.md +4 -4
  25. data/docs/SupportedDevices.md +2 -11
  26. data/docs/SupportedMPLABXVersions.md +1 -0
  27. data/docs/SupportedOperatingSystems.md +3 -2
  28. data/docs/UnitTesting.md +1 -1
  29. data/docs/Variables.md +81 -25
  30. data/lib/rpicsim.rb +0 -12
  31. data/lib/rpicsim/call_stack_info.rb +43 -47
  32. data/lib/rpicsim/composite_memory.rb +53 -0
  33. data/lib/rpicsim/flaws.rb +34 -22
  34. data/lib/rpicsim/instruction.rb +204 -48
  35. data/lib/rpicsim/label.rb +4 -4
  36. data/lib/rpicsim/memory.rb +44 -23
  37. data/lib/rpicsim/memory_watcher.rb +14 -22
  38. data/lib/rpicsim/mplab.rb +38 -119
  39. data/lib/rpicsim/mplab/mplab_assembly.rb +23 -18
  40. data/lib/rpicsim/mplab/mplab_device_info.rb +9 -9
  41. data/lib/rpicsim/mplab/mplab_disassembler.rb +5 -6
  42. data/lib/rpicsim/mplab/mplab_instruction.rb +87 -16
  43. data/lib/rpicsim/mplab/mplab_loader.rb +106 -0
  44. data/lib/rpicsim/mplab/mplab_memory.rb +19 -6
  45. data/lib/rpicsim/mplab/mplab_nmmr_info.rb +4 -4
  46. data/lib/rpicsim/mplab/mplab_observer.rb +15 -10
  47. data/lib/rpicsim/mplab/mplab_pin.rb +3 -3
  48. data/lib/rpicsim/mplab/mplab_processor.rb +5 -5
  49. data/lib/rpicsim/mplab/mplab_program_file.rb +29 -17
  50. data/lib/rpicsim/mplab/mplab_register.rb +5 -5
  51. data/lib/rpicsim/mplab/mplab_sfr_info.rb +4 -4
  52. data/lib/rpicsim/mplab/mplab_simulator.rb +27 -30
  53. data/lib/rpicsim/pin.rb +6 -6
  54. data/lib/rpicsim/program_counter.rb +3 -3
  55. data/lib/rpicsim/program_file.rb +39 -81
  56. data/lib/rpicsim/rspec/be_predicate.rb +1 -1
  57. data/lib/rpicsim/rspec/helpers.rb +1 -1
  58. data/lib/rpicsim/rspec/persistent_expectations.rb +17 -2
  59. data/lib/rpicsim/rspec/sim_diagnostics.rb +5 -5
  60. data/lib/rpicsim/search.rb +1 -1
  61. data/lib/rpicsim/sim.rb +153 -228
  62. data/lib/rpicsim/stack_pointer.rb +41 -0
  63. data/lib/rpicsim/stack_trace.rb +1 -1
  64. data/lib/rpicsim/storage/memory_integer.rb +235 -0
  65. data/lib/rpicsim/{register.rb → storage/register.rb} +18 -18
  66. data/lib/rpicsim/variable.rb +25 -211
  67. data/lib/rpicsim/variable_set.rb +93 -0
  68. data/lib/rpicsim/version.rb +2 -2
  69. metadata +9 -4
  70. 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
@@ -1,3 +1,3 @@
1
1
  module RPicSim
2
- VERSION = '0.1.0'
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.0
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-01-22 00:00:00.000000000 Z
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:
@@ -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}.