rpicsim 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +3 -1
- data/Introduction.md +1 -3
- data/README.md +1 -3
- data/docs/ChangeLog.md +13 -0
- data/docs/KnownIssues.md +2 -2
- data/docs/Manual.md +0 -1
- data/docs/RSpecIntegration.md +24 -1
- data/docs/SupportedMPLABXVersions.md +2 -0
- data/lib/rpicsim.rb +6 -1
- data/lib/rpicsim/composite_memory.rb +3 -0
- data/lib/rpicsim/flaws.rb +28 -4
- data/lib/rpicsim/label.rb +7 -0
- data/lib/rpicsim/memory.rb +4 -0
- data/lib/rpicsim/memory_watcher.rb +11 -4
- data/lib/rpicsim/mplab.rb +1 -0
- data/lib/rpicsim/mplab/mplab_assembly.rb +0 -1
- data/lib/rpicsim/pin.rb +7 -0
- data/lib/rpicsim/program_counter.rb +4 -0
- data/lib/rpicsim/program_file.rb +20 -17
- data/lib/rpicsim/rspec.rb +6 -3
- data/lib/rpicsim/rspec/helpers.rb +13 -5
- data/lib/rpicsim/rspec/persistent_expectations.rb +5 -3
- data/lib/rpicsim/rspec/sim_diagnostics.rb +1 -0
- data/lib/rpicsim/sim.rb +8 -3
- data/lib/rpicsim/stack_pointer.rb +6 -0
- data/lib/rpicsim/stack_trace.rb +32 -1
- data/lib/rpicsim/storage/memory_integer.rb +1 -0
- data/lib/rpicsim/symbol_set.rb +3 -1
- data/lib/rpicsim/variable.rb +14 -0
- data/lib/rpicsim/variable_set.rb +2 -0
- data/lib/rpicsim/version.rb +4 -1
- data/lib/rpicsim/xc8_sym_file.rb +63 -11
- metadata +2 -7
- data/docs/PreventingCallStackOverflow.md +0 -92
- data/lib/rpicsim/call_stack_info.rb +0 -303
- data/lib/rpicsim/instruction.rb +0 -337
- data/lib/rpicsim/mplab/mplab_disassembler.rb +0 -20
- data/lib/rpicsim/search.rb +0 -20
data/lib/rpicsim/rspec.rb
CHANGED
@@ -5,7 +5,10 @@ require_relative 'rspec/helpers'
|
|
5
5
|
require_relative 'rspec/sim_diagnostics'
|
6
6
|
require_relative 'rspec/be_predicate'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# See {file:RSpecIntegration.md}.
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
module RPicSim::RSpec
|
11
12
|
end
|
13
|
+
|
14
|
+
|
@@ -9,10 +9,12 @@ module RPicSim
|
|
9
9
|
#
|
10
10
|
# It provides the {#start_sim} method and includes all the methods from
|
11
11
|
# {PersistentExpectations}.
|
12
|
-
#
|
13
|
-
#
|
12
|
+
#
|
13
|
+
# For more information, see {file:RSpecIntegration.md}.
|
14
|
+
#
|
15
|
+
# @api public
|
14
16
|
module Helpers
|
15
|
-
include
|
17
|
+
include PersistentExpectations
|
16
18
|
|
17
19
|
# This attribute allows you to type +sim+ in your specs instead of +@sim+ to
|
18
20
|
# get access to the {RPicSim::Sim} instance which represents the simulation.
|
@@ -20,8 +22,8 @@ module RPicSim
|
|
20
22
|
attr_reader :sim
|
21
23
|
|
22
24
|
# Starts a new simulation with the specified class, makes it
|
23
|
-
# accessible via the attribute {#sim}, and adds
|
24
|
-
# methods
|
25
|
+
# accessible via the attribute {#sim}, and adds convenient
|
26
|
+
# shortcut methods that can be used in the RSpec example.
|
25
27
|
# @param klass [Class] This should be a subclass of {RPicSim::Sim} or at least act like it.
|
26
28
|
# @param args A list of arguments to pass on to the the +new+ method of the class.
|
27
29
|
# This should usually be empty unless you have modified your class to take arguments in its
|
@@ -32,6 +34,7 @@ module RPicSim
|
|
32
34
|
sim.every_step { check_expectations }
|
33
35
|
end
|
34
36
|
|
37
|
+
# @api private
|
35
38
|
def add_shortcuts
|
36
39
|
configuration_value = ::RSpec.configuration.sim_shortcuts
|
37
40
|
case configuration_value
|
@@ -45,3 +48,8 @@ module RPicSim
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
51
|
+
|
52
|
+
RSpec.configure do |config|
|
53
|
+
config.add_setting :sim_shortcuts, default: :all
|
54
|
+
config.include RPicSim::RSpec::Helpers
|
55
|
+
end
|
@@ -13,6 +13,10 @@ module RPicSim
|
|
13
13
|
# b << 0
|
14
14
|
# check_expectations # => raises an error once b has 10 elements
|
15
15
|
# end
|
16
|
+
#
|
17
|
+
# For more information, see {file:PersistentExpectations.md}.
|
18
|
+
#
|
19
|
+
# @api public
|
16
20
|
module PersistentExpectations
|
17
21
|
# Returns the current set of persistent expectations.
|
18
22
|
# The keys are the objects under test and the values are matchers that
|
@@ -26,9 +30,7 @@ module RPicSim
|
|
26
30
|
# it raises an error.
|
27
31
|
def check_expectations
|
28
32
|
expectations.each do |subject, matcher|
|
29
|
-
if matcher
|
30
|
-
expect(subject).to matcher
|
31
|
-
end
|
33
|
+
expect(subject).to matcher if matcher
|
32
34
|
end
|
33
35
|
nil
|
34
36
|
end
|
data/lib/rpicsim/sim.rb
CHANGED
@@ -14,10 +14,13 @@ require_relative 'program_file'
|
|
14
14
|
require_relative 'stack_pointer'
|
15
15
|
require_relative 'stack_trace'
|
16
16
|
|
17
|
+
# @api public
|
17
18
|
module RPicSim
|
18
19
|
# This class represents a PIC microcontroller simulation.
|
19
20
|
# This class keeps track of the state of the simulation and provides methods for
|
20
21
|
# running the simulation, reading the state, and changing the state.
|
22
|
+
#
|
23
|
+
# @api public
|
21
24
|
class Sim
|
22
25
|
# These methods should be called while defining a subclass of {Sim}.
|
23
26
|
module ClassDefinitionMethods
|
@@ -50,7 +53,7 @@ module RPicSim
|
|
50
53
|
end
|
51
54
|
|
52
55
|
# Define a symbol.
|
53
|
-
# Normally symbols are loaded by {#use_file} or {#import_symbols}, but
|
56
|
+
# Normally symbols are loaded by {#use_file} or {#import_symbols}, but
|
54
57
|
# this method allows for adding additional symbols one at a time.
|
55
58
|
#
|
56
59
|
# See {RPicSim::ProgramFile#def_symbol} for details about the parameters
|
@@ -118,6 +121,7 @@ module RPicSim
|
|
118
121
|
|
119
122
|
# A {VariableSet} that holds information about all the variables that were defined
|
120
123
|
# with {ClassDefinitionMethods#def_var def_var}.
|
124
|
+
# @api private
|
121
125
|
attr_reader :variable_set
|
122
126
|
|
123
127
|
# The {ProgramFile} object representing the firmware.
|
@@ -213,12 +217,12 @@ module RPicSim
|
|
213
217
|
|
214
218
|
# Returns a {Variable} object corresponding to WREG. You can use this
|
215
219
|
# to read and write the value of the W register.
|
216
|
-
# @return [
|
220
|
+
# @return [Variable]
|
217
221
|
attr_reader :wreg
|
218
222
|
|
219
223
|
# Returns a {Variable} object corresponding to the stack pointer register.
|
220
224
|
# You can use this to read and write the value of the stack pointer.
|
221
|
-
# @return [
|
225
|
+
# @return [Variable]
|
222
226
|
attr_reader :stkptr
|
223
227
|
|
224
228
|
# Returns a {StackPointer} object that is like {#stkptr} but it works
|
@@ -619,6 +623,7 @@ module RPicSim
|
|
619
623
|
|
620
624
|
public
|
621
625
|
|
626
|
+
# @return [String]
|
622
627
|
def inspect
|
623
628
|
"#<#{self.class}:0x%x, #{pc_description}, stack_pointer = #{stack_pointer.value}>" % object_id
|
624
629
|
end
|
@@ -1,18 +1,23 @@
|
|
1
|
+
# @api public
|
1
2
|
module RPicSim
|
2
3
|
# Instances of this class represent the call stack pointer in a running
|
3
4
|
# simulation.
|
4
5
|
# A value of 0 means that the stack is empty, regardless of what device
|
5
6
|
# architecture you are simulating.
|
7
|
+
#
|
8
|
+
# @api public
|
6
9
|
class StackPointer
|
7
10
|
# Initializes the StackPointer object.
|
8
11
|
# This be called when the call stack is empty, because this object uses
|
9
12
|
# the initial value of stkptr to deduce how it works.
|
10
13
|
# @param stkptr The STKPTR register of the simulation.
|
14
|
+
# @api private
|
11
15
|
def initialize(stkptr)
|
12
16
|
@stkptr = stkptr
|
13
17
|
@stkptr_initial_value = @stkptr.value
|
14
18
|
end
|
15
19
|
|
20
|
+
# @return [Integer]
|
16
21
|
def value
|
17
22
|
if @stkptr_initial_value > 0
|
18
23
|
raw_value = @stkptr.value
|
@@ -26,6 +31,7 @@ module RPicSim
|
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
34
|
+
# @param value [Integer]
|
29
35
|
def value=(value)
|
30
36
|
@stkptr.value = if @stkptr_initial_value > 0
|
31
37
|
if value == 0
|
data/lib/rpicsim/stack_trace.rb
CHANGED
@@ -1,30 +1,61 @@
|
|
1
|
+
# @api public
|
1
2
|
module RPicSim
|
3
|
+
# Represents a stack trace from the simulated firmware.
|
4
|
+
#
|
5
|
+
# @api public
|
2
6
|
class StackTrace
|
7
|
+
# Array of {StackTraceEntry} objects. The last one represents where the
|
8
|
+
# program counter (PC) is. The entries before the last one approximately
|
9
|
+
# represent addresses of CALL or RCALL instructions that have not yet
|
10
|
+
# returned.
|
11
|
+
#
|
12
|
+
# @return An array of {StackTraceEntry} objects.
|
3
13
|
attr_reader :entries
|
4
14
|
|
15
|
+
# @api private
|
5
16
|
def initialize(entries = [])
|
6
17
|
@entries = entries
|
7
18
|
end
|
8
19
|
|
20
|
+
# Prints the stack trace to the specified IO object, preceding
|
21
|
+
# each line with the specified padding string.
|
22
|
+
#
|
23
|
+
# Example usage:
|
24
|
+
#
|
25
|
+
# stack_trace.output($stdout, ' ')
|
26
|
+
#
|
27
|
+
# @param io An object that behaves like a writable IO object.
|
28
|
+
# @param padding [String]
|
9
29
|
def output(io, padding = '')
|
10
30
|
@entries.reverse_each do |entry|
|
11
31
|
output_entry(entry, io, padding)
|
12
32
|
end
|
13
33
|
end
|
14
34
|
|
35
|
+
private
|
36
|
+
|
15
37
|
def output_entry(entry, io, padding)
|
16
38
|
io.puts padding + entry.description
|
17
39
|
end
|
18
40
|
end
|
19
41
|
|
42
|
+
# Represents an entry in a {StackTrace}.
|
43
|
+
#
|
44
|
+
# @api public
|
20
45
|
class StackTraceEntry
|
21
|
-
|
46
|
+
# @return [Integer]
|
47
|
+
attr_reader :address
|
48
|
+
|
49
|
+
# @return [String]
|
50
|
+
attr_reader :description
|
22
51
|
|
52
|
+
# @api private
|
23
53
|
def initialize(address, description)
|
24
54
|
@address = address
|
25
55
|
@description = description
|
26
56
|
end
|
27
57
|
|
58
|
+
# @return [String]
|
28
59
|
def to_s
|
29
60
|
description
|
30
61
|
end
|
data/lib/rpicsim/symbol_set.rb
CHANGED
data/lib/rpicsim/variable.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
+
# @api public
|
1
2
|
module RPicSim
|
3
|
+
# Instances of this class represents a variable in the memory of the simulated
|
4
|
+
# microcontroller. This class provides methods for reading, writing, and getting
|
5
|
+
# address of the variable.
|
6
|
+
#
|
7
|
+
# @api public
|
2
8
|
class Variable
|
3
9
|
# Creates a new Variable object.
|
4
10
|
# @param storage The internal storage for the variable.
|
11
|
+
# @api private
|
5
12
|
def initialize(storage)
|
6
13
|
@storage = storage
|
7
14
|
end
|
@@ -31,18 +38,25 @@ module RPicSim
|
|
31
38
|
@storage.memory_value
|
32
39
|
end
|
33
40
|
|
41
|
+
# @return [String]
|
34
42
|
def to_s
|
35
43
|
@storage.to_s
|
36
44
|
end
|
37
45
|
|
46
|
+
# The addresses in memory occupied by this variable.
|
47
|
+
# @return [Array(Integer)]
|
38
48
|
def addresses
|
39
49
|
@storage.addresses
|
40
50
|
end
|
41
51
|
|
52
|
+
# The main (lowest) address of this variable.
|
53
|
+
# @return [Integer]
|
42
54
|
def address
|
43
55
|
@storage.address
|
44
56
|
end
|
45
57
|
|
58
|
+
# The name of the variable.
|
59
|
+
# @return [Symbol]
|
46
60
|
def name
|
47
61
|
@storage.name
|
48
62
|
end
|
data/lib/rpicsim/variable_set.rb
CHANGED
data/lib/rpicsim/version.rb
CHANGED
data/lib/rpicsim/xc8_sym_file.rb
CHANGED
@@ -1,14 +1,66 @@
|
|
1
1
|
require 'scanf'
|
2
2
|
|
3
|
+
# @api public
|
3
4
|
module RPicSim
|
5
|
+
# This class can be used to load an XC8 sym file and get the information about
|
6
|
+
# the symbols in it. This is useful because the COF file produced by XC8 does
|
7
|
+
# not have enough information to identify what memory space every symbol is
|
8
|
+
# in.
|
9
|
+
#
|
10
|
+
# Example usage:
|
11
|
+
#
|
12
|
+
# class MySim < RPicSim::Sim
|
13
|
+
# use_device 'PIC18F25K50'
|
14
|
+
# use_file DistDir + 'TestXC8.hex'
|
15
|
+
# import_symbols RPicSim::Xc8SymFile.new(DistDir + 'TestXC8.sym')
|
16
|
+
#
|
17
|
+
# # ...
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @api public
|
4
21
|
class Xc8SymFile
|
22
|
+
# Returns all the symbols.
|
23
|
+
# The return value is a hash where the keys are the names of the symbols
|
24
|
+
# (represented as Ruby symbols) and the values are the addresses of the symbols.
|
25
|
+
#
|
26
|
+
# @return [Hash]
|
5
27
|
attr_reader :symbols
|
28
|
+
|
29
|
+
# Returns all the symbols in RAM.
|
30
|
+
# The return value is a hash where the keys are the names of the symbols
|
31
|
+
# (represented as Ruby symbols) and the values are the addresses of the symbols.
|
32
|
+
#
|
33
|
+
# @return [Hash]
|
6
34
|
attr_reader :symbols_in_ram
|
35
|
+
|
36
|
+
# Returns all the symbols in EEPROM.
|
37
|
+
# The return value is a hash where the keys are the names of the symbols
|
38
|
+
# (represented as Ruby symbols) and the values are the addresses of the symbols.
|
39
|
+
#
|
40
|
+
# @return [Hash]
|
7
41
|
attr_reader :symbols_in_eeprom
|
42
|
+
|
43
|
+
# Returns all the symbols in program memory.
|
44
|
+
# The return value is a hash where the keys are the names of the symbols
|
45
|
+
# (represented as Ruby symbols) and the values are the addresses of the symbols.
|
46
|
+
#
|
47
|
+
# @return [Hash]
|
8
48
|
attr_reader :symbols_in_program_memory
|
9
49
|
|
50
|
+
# @api private
|
10
51
|
attr_reader :symbol_raw_data
|
11
52
|
|
53
|
+
# Creates a new instance of this class containing information from the
|
54
|
+
# specified file.
|
55
|
+
#
|
56
|
+
# @param filename [String]
|
57
|
+
# @param opts [Hash] Specified additional options. The options are:
|
58
|
+
# * +:user_ram_sections+: Array of strings of section names that
|
59
|
+
# should be considered to be in RAM.
|
60
|
+
# * +:user_program_memory_sections+: Array of strings of section names that
|
61
|
+
# should be considered to be in program memory.
|
62
|
+
# * +:user_eeprom_sections+: Array of strings of section names that
|
63
|
+
# should be considered to be in EEPROM.
|
12
64
|
def initialize(filename, opts = {})
|
13
65
|
@symbols = {}
|
14
66
|
@symbols_in_ram = {}
|
@@ -21,7 +73,10 @@ module RPicSim
|
|
21
73
|
@sections_in_code = %w{CODE CONST IDLOC MEDIUMCONST SMALLCONST}
|
22
74
|
@sections_in_eeprom = %w{EEDATA}
|
23
75
|
|
24
|
-
allowed_keys = [:
|
76
|
+
allowed_keys = [:user_ram_sections,
|
77
|
+
:user_program_memory_sections,
|
78
|
+
:user_eeprom_sections,
|
79
|
+
:custom_ram_sections,
|
25
80
|
:custom_code_sections,
|
26
81
|
:custom_eeprom_sections]
|
27
82
|
invalid_keys = opts.keys - allowed_keys
|
@@ -29,17 +84,14 @@ module RPicSim
|
|
29
84
|
raise "Invalid options: #{invalid_keys.inspect}"
|
30
85
|
end
|
31
86
|
|
32
|
-
|
33
|
-
|
34
|
-
|
87
|
+
@sections_in_ram += opts.fetch(:user_ram_sections, [])
|
88
|
+
@sections_in_code += opts.fetch(:user_program_memory_sections, [])
|
89
|
+
@sections_in_eeprom += opts.fetch(:user_eeprom_sections, [])
|
35
90
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
if opts[:custom_eeprom_sections]
|
41
|
-
@sections_in_eeprom += opts[:custom_eeprom_sections]
|
42
|
-
end
|
91
|
+
# Legacy options introduced in 0.4.0, but deprecated now.
|
92
|
+
@sections_in_ram += opts.fetch(:custom_ram_sections, [])
|
93
|
+
@sections_in_code += opts.fetch(:custom_code_sections, [])
|
94
|
+
@sections_in_eeprom += opts.fetch(:custom_eeprom_sections, [])
|
43
95
|
|
44
96
|
read_data
|
45
97
|
sort_data
|
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.
|
4
|
+
version: 1.0.0
|
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-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -17,10 +17,8 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- lib/rpicsim.rb
|
20
|
-
- lib/rpicsim/call_stack_info.rb
|
21
20
|
- lib/rpicsim/composite_memory.rb
|
22
21
|
- lib/rpicsim/flaws.rb
|
23
|
-
- lib/rpicsim/instruction.rb
|
24
22
|
- lib/rpicsim/label.rb
|
25
23
|
- lib/rpicsim/memory.rb
|
26
24
|
- lib/rpicsim/memory_watcher.rb
|
@@ -29,7 +27,6 @@ files:
|
|
29
27
|
- lib/rpicsim/program_counter.rb
|
30
28
|
- lib/rpicsim/program_file.rb
|
31
29
|
- lib/rpicsim/rspec.rb
|
32
|
-
- lib/rpicsim/search.rb
|
33
30
|
- lib/rpicsim/sim.rb
|
34
31
|
- lib/rpicsim/stack_pointer.rb
|
35
32
|
- lib/rpicsim/stack_trace.rb
|
@@ -40,7 +37,6 @@ files:
|
|
40
37
|
- lib/rpicsim/xc8_sym_file.rb
|
41
38
|
- lib/rpicsim/mplab/mplab_assembly.rb
|
42
39
|
- lib/rpicsim/mplab/mplab_device_info.rb
|
43
|
-
- lib/rpicsim/mplab/mplab_disassembler.rb
|
44
40
|
- lib/rpicsim/mplab/mplab_instruction.rb
|
45
41
|
- lib/rpicsim/mplab/mplab_loader.rb
|
46
42
|
- lib/rpicsim/mplab/mplab_memory.rb
|
@@ -78,7 +74,6 @@ files:
|
|
78
74
|
- docs/Memories.md
|
79
75
|
- docs/PersistentExpectations.md
|
80
76
|
- docs/Pins.md
|
81
|
-
- docs/PreventingCallStackOverflow.md
|
82
77
|
- docs/QuickStartGuide.md
|
83
78
|
- docs/RamWatcher.md
|
84
79
|
- docs/RSpecIntegration.md
|