rpicsim 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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}.