origen_memory_image 0.6.0 → 0.8.2
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 +5 -5
- data/config/version.rb +2 -3
- data/lib/origen_memory_image.rb +4 -1
- data/lib/origen_memory_image/base.rb +9 -1
- data/lib/origen_memory_image/binary.rb +3 -3
- data/lib/origen_memory_image/hex.rb +5 -1
- data/lib/origen_memory_image/intel_hex.rb +98 -0
- data/lib/origen_memory_image/s_record.rb +30 -3
- data/templates/web/index.md.erb +40 -2
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2d9b91a3a905b3801a9d96ee96fe7494baf3c201d1b3ee34107599923ff0763a
|
4
|
+
data.tar.gz: d66b83fcd77afac1ed13754871d9fab2952760f2ad5fc17b6709904ef6a48c6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6fedde88b97b4661fb9773d6780497ba995f07114661ba3c94b5ca842c818dc59592e40758c387ce7f8361b1cf68977c40aba88c0a864a3a3ab751a9a118e0b
|
7
|
+
data.tar.gz: 7a712d8374d57ae31dd11454cc7985084988ca90e3d883205b3738bc1ac48c2e45bb89054c6a9a816efd1b57096e17220da099508a634eb915af9760a7114a8d
|
data/config/version.rb
CHANGED
data/lib/origen_memory_image.rb
CHANGED
@@ -6,6 +6,7 @@ module OrigenMemoryImage
|
|
6
6
|
autoload :SRecord, 'origen_memory_image/s_record'
|
7
7
|
autoload :Hex, 'origen_memory_image/hex'
|
8
8
|
autoload :Binary, 'origen_memory_image/binary'
|
9
|
+
autoload :IntelHex, 'origen_memory_image/intel_hex'
|
9
10
|
|
10
11
|
def self.new(file, options = {})
|
11
12
|
unless options[:source] == String
|
@@ -20,7 +21,7 @@ module OrigenMemoryImage
|
|
20
21
|
if options[:source] == String
|
21
22
|
snippet = file.split("\n")
|
22
23
|
else
|
23
|
-
snippet = File.foreach(file.to_s).first(
|
24
|
+
snippet = File.foreach(file.to_s).first(10)
|
24
25
|
end
|
25
26
|
case
|
26
27
|
# Always do the binary first since the others won't be able to process
|
@@ -31,6 +32,8 @@ module OrigenMemoryImage
|
|
31
32
|
Binary
|
32
33
|
when options[:type] == :srecord || SRecord.match?(snippet)
|
33
34
|
SRecord
|
35
|
+
when options[:type] == :intel_hex || IntelHex.match?(snippet)
|
36
|
+
IntelHex
|
34
37
|
when options[:type] == :hex || Hex.match?(snippet)
|
35
38
|
Hex
|
36
39
|
else
|
@@ -8,6 +8,7 @@ module OrigenMemoryImage
|
|
8
8
|
else
|
9
9
|
@file = file
|
10
10
|
end
|
11
|
+
@ljust_partial_data = options[:ljust_partial_data]
|
11
12
|
end
|
12
13
|
|
13
14
|
# Returns the code execution start address as an int
|
@@ -15,6 +16,13 @@ module OrigenMemoryImage
|
|
15
16
|
fail "#{self.class} has not implemented the start_address method!"
|
16
17
|
end
|
17
18
|
|
19
|
+
# Returns true if a start (jump address) record exists
|
20
|
+
def has_start_record
|
21
|
+
start_address unless @start_address
|
22
|
+
@start_record_found = false if @start_record_found.nil?
|
23
|
+
@start_record_found
|
24
|
+
end
|
25
|
+
|
18
26
|
# Returns the s-record as an array of addresses and data
|
19
27
|
#
|
20
28
|
# @param [hash] options, allows the selection of endianness swapping - ie the output will have the endianness changed
|
@@ -50,7 +58,7 @@ module OrigenMemoryImage
|
|
50
58
|
|
51
59
|
if options[:flip_endianness] || options[:endianness_change]
|
52
60
|
data.map do |v|
|
53
|
-
[v[0], flip_endianness(v[1],
|
61
|
+
[v[0], flip_endianness(v[1], options[:data_width_in_bytes])]
|
54
62
|
end
|
55
63
|
else
|
56
64
|
data
|
@@ -1,12 +1,12 @@
|
|
1
|
-
require 'ptools'
|
2
|
-
|
3
1
|
module OrigenMemoryImage
|
4
2
|
class Binary < Base
|
5
3
|
def self.match?(file, snippet = false)
|
6
4
|
if snippet
|
7
5
|
file.all? { |l| l.strip =~ /^[01]*$/ }
|
8
6
|
else
|
9
|
-
|
7
|
+
# detect whether the data is mostly not alpha numeric
|
8
|
+
filedata = (File.read(file, 256) || '')
|
9
|
+
(filedata.gsub(/\s+/, '').gsub(/\w/, '').length.to_f / filedata.length.to_f) > 0.3
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -46,7 +46,11 @@ module OrigenMemoryImage
|
|
46
46
|
end
|
47
47
|
# If a partial word is left over
|
48
48
|
if (remainder = data.length % (2 * options[:data_width_in_bytes])) > 0
|
49
|
-
|
49
|
+
if @ljust_partial_data
|
50
|
+
result << [@address, data[data.length - remainder..data.length].ljust(options[:data_width_in_bytes] * 2, '0').to_i(16)]
|
51
|
+
else
|
52
|
+
result << [@address, data[data.length - remainder..data.length].to_i(16)]
|
53
|
+
end
|
50
54
|
end
|
51
55
|
end
|
52
56
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module OrigenMemoryImage
|
2
|
+
class IntelHex < Base
|
3
|
+
def self.match?(snippet)
|
4
|
+
snippet.all? do |line|
|
5
|
+
line.empty? || line =~ /^:[0-9A-Fa-f]{6}0[0-5]/
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def start_address
|
10
|
+
@start_address ||= begin
|
11
|
+
addrs = []
|
12
|
+
lines.each do |line|
|
13
|
+
line = line.strip
|
14
|
+
if start_linear_address?(line)
|
15
|
+
addrs << decode(line)[:data].to_i(16)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
addrs.last || 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def decode(line)
|
25
|
+
d = {}
|
26
|
+
if line =~ /^:([0-9A-Fa-f]{2})([0-9A-Fa-f]{4})(\d\d)([0-9A-Fa-f]+)([0-9A-Fa-f]{2})$/
|
27
|
+
d[:byte_count] = Regexp.last_match(1).to_i(16)
|
28
|
+
d[:address] = Regexp.last_match(2).to_i(16)
|
29
|
+
d[:record_type] = Regexp.last_match(3).to_i(16)
|
30
|
+
d[:data] = Regexp.last_match(4)
|
31
|
+
d[:checksum] = Regexp.last_match(5).to_i(16)
|
32
|
+
else
|
33
|
+
fail "Invalid line encountered in Intel Hex formatted file: #{line}"
|
34
|
+
end
|
35
|
+
d
|
36
|
+
end
|
37
|
+
|
38
|
+
def data?(line)
|
39
|
+
!!(line =~ /^:[0-9A-Fa-f]{6}00/)
|
40
|
+
end
|
41
|
+
|
42
|
+
def extended_segment_address?(line)
|
43
|
+
!!(line =~ /^:[0-9A-Fa-f]{6}02/)
|
44
|
+
end
|
45
|
+
|
46
|
+
def extended_linear_address?(line)
|
47
|
+
!!(line =~ /^:[0-9A-Fa-f]{6}04/)
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_linear_address?(line)
|
51
|
+
!!(line =~ /^:[0-9A-Fa-f]{6}05/)
|
52
|
+
end
|
53
|
+
|
54
|
+
def upper_addr
|
55
|
+
@upper_addr || 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def segment_address
|
59
|
+
@segment_address || 0
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns an array containing all address/data from the given s-record
|
63
|
+
# No address manipulation is performed, that is left to the caller to apply
|
64
|
+
# any scrambling as required by the target system
|
65
|
+
def extract_addr_data(options = {})
|
66
|
+
options = {
|
67
|
+
data_width_in_bytes: 4
|
68
|
+
}.merge(options)
|
69
|
+
|
70
|
+
result = []
|
71
|
+
lines.each do |line|
|
72
|
+
line = line.strip
|
73
|
+
if extended_segment_address?(line)
|
74
|
+
@segment_address = decode(line)[:data].to_i(16) * 16
|
75
|
+
|
76
|
+
elsif extended_linear_address?(line)
|
77
|
+
@upper_addr = (decode(line)[:data].to_i(16)) << 16
|
78
|
+
|
79
|
+
elsif data?(line)
|
80
|
+
d = decode(line)
|
81
|
+
addr = d[:address] + segment_address + upper_addr
|
82
|
+
|
83
|
+
data = d[:data]
|
84
|
+
data_matcher = '\w\w' * options[:data_width_in_bytes]
|
85
|
+
data.scan(/#{data_matcher}/).each do |data_packet|
|
86
|
+
result << [addr, data_packet.to_i(16)]
|
87
|
+
addr += options[:data_width_in_bytes]
|
88
|
+
end
|
89
|
+
# If a partial word is left over
|
90
|
+
if (remainder = data.length % (2 * options[:data_width_in_bytes])) > 0
|
91
|
+
result << [addr, data[data.length - remainder..data.length].to_i(16)]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
result
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -156,9 +156,16 @@ module OrigenMemoryImage
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def start_address
|
159
|
+
if @call_order_warn
|
160
|
+
Origen.log.warn 'Previously srec.start_address returned the lowest address when to_a was called first. Now the start record is always returned if present.'
|
161
|
+
@call_order_warn = false
|
162
|
+
end
|
163
|
+
|
164
|
+
lowest_address = nil
|
159
165
|
@start_address ||= begin
|
160
166
|
lines.each do |line|
|
161
167
|
if line =~ /^S([789])(.*)/
|
168
|
+
@start_record_found = true
|
162
169
|
type = Regexp.last_match[1]
|
163
170
|
case type
|
164
171
|
when '7'
|
@@ -169,7 +176,19 @@ module OrigenMemoryImage
|
|
169
176
|
return line.slice(4, 4).to_i(16)
|
170
177
|
end
|
171
178
|
end
|
179
|
+
if line =~ /^S([1-3])/
|
180
|
+
type = Regexp.last_match[1].to_i(16) # S-record type, 1-3
|
181
|
+
# Set the matcher to capture x number of bytes dependent on the s-rec type
|
182
|
+
addr_matcher = '\w\w' * (1 + type)
|
183
|
+
line.strip =~ /^S\d\w\w(#{addr_matcher})(\w*)\w\w$/ # $1 = address, $2 = data
|
184
|
+
addr = Regexp.last_match[1].to_i(16)
|
185
|
+
lowest_address ||= addr
|
186
|
+
lowest_address = addr if addr < lowest_address
|
187
|
+
end
|
172
188
|
end
|
189
|
+
# if no start_address record is found, return lowest address
|
190
|
+
@start_record_found = false
|
191
|
+
lowest_address
|
173
192
|
end
|
174
193
|
end
|
175
194
|
|
@@ -183,6 +202,12 @@ module OrigenMemoryImage
|
|
183
202
|
data_width_in_bytes: 4
|
184
203
|
}.merge(options)
|
185
204
|
|
205
|
+
# guarantee that the start_address will be the jump address if provided
|
206
|
+
if @start_address.nil?
|
207
|
+
start_address
|
208
|
+
@call_order_warn = @start_record_found ? true : false
|
209
|
+
end
|
210
|
+
|
186
211
|
result = []
|
187
212
|
lines.each do |line|
|
188
213
|
# Only if the line is an s-record with data...
|
@@ -192,8 +217,6 @@ module OrigenMemoryImage
|
|
192
217
|
addr_matcher = '\w\w' * (1 + type)
|
193
218
|
line.strip =~ /^S\d\w\w(#{addr_matcher})(\w*)\w\w$/ # $1 = address, $2 = data
|
194
219
|
addr = Regexp.last_match[1].to_i(16)
|
195
|
-
@start_address ||= addr
|
196
|
-
@start_address = addr if addr < @start_address
|
197
220
|
data = Regexp.last_match[2]
|
198
221
|
data_matcher = '\w\w' * options[:data_width_in_bytes]
|
199
222
|
data.scan(/#{data_matcher}/).each do |data_packet|
|
@@ -202,7 +225,11 @@ module OrigenMemoryImage
|
|
202
225
|
end
|
203
226
|
# If a partial word is left over
|
204
227
|
if (remainder = data.length % (2 * options[:data_width_in_bytes])) > 0
|
205
|
-
|
228
|
+
if @ljust_partial_data
|
229
|
+
result << [addr, data[data.length - remainder..data.length].ljust(options[:data_width_in_bytes] * 2, '0').to_i(16)]
|
230
|
+
else
|
231
|
+
result << [addr, data[data.length - remainder..data.length].to_i(16)]
|
232
|
+
end
|
206
233
|
end
|
207
234
|
end
|
208
235
|
end
|
data/templates/web/index.md.erb
CHANGED
@@ -58,6 +58,25 @@ my_srec = OrigenMemoryImage.new("source_files/test_atd.abs.S19")
|
|
58
58
|
my_hex = OrigenMemoryImage.new("source_files/math.hex")
|
59
59
|
~~~
|
60
60
|
|
61
|
+
By default any partial data words are right justified. Change this behavior to left justified like this:
|
62
|
+
|
63
|
+
~~~ruby
|
64
|
+
my_srec = OrigenMemoryImage.new("source_files/test_atd.abs.S19", ljust_partial_data: true)
|
65
|
+
my_hex = OrigenMemoryImage.new("source_files/math.hex", ljust_partial_data: true)
|
66
|
+
~~~
|
67
|
+
|
68
|
+
Partial data example:
|
69
|
+
|
70
|
+
~~~
|
71
|
+
0304FE
|
72
|
+
|
73
|
+
# Default interpretation into 32-bit word:
|
74
|
+
0x0003_04FE
|
75
|
+
|
76
|
+
# Left justified interpretation into 32-bit word:
|
77
|
+
0x0304_FE00
|
78
|
+
~~~
|
79
|
+
|
61
80
|
Memory images can also be created directly from a string:
|
62
81
|
|
63
82
|
~~~ruby
|
@@ -72,10 +91,14 @@ my_hex = OrigenMemoryImage.new(str, source: String)
|
|
72
91
|
|
73
92
|
Every memory image object then supports a common API.
|
74
93
|
|
75
|
-
The <code>start_address</code> method returns the start (execution start) address
|
94
|
+
The <code>start_address</code> method returns the start (execution start) address. If the memory image
|
95
|
+
contains an indication of the execution start address that record value will be returned. If there is
|
96
|
+
no start address record, the lowest address will be returned. The <code>has_start_record</code> method
|
97
|
+
indicates whether a start address record was found:
|
76
98
|
|
77
99
|
~~~ruby
|
78
|
-
my_srec.start_address
|
100
|
+
my_srec.start_address # => 0x3000_F000
|
101
|
+
my_srec.has_start_record # => true
|
79
102
|
~~~
|
80
103
|
|
81
104
|
The <code>to_a</code> method returns the file content as an array of address/data pairs,
|
@@ -146,6 +169,21 @@ A binary file:
|
|
146
169
|
00000100000000110000010100000110
|
147
170
|
~~~
|
148
171
|
|
172
|
+
#### Intel Hex
|
173
|
+
|
174
|
+
Any valid Intel Hex file:
|
175
|
+
|
176
|
+
~~~text
|
177
|
+
:020000040022D8
|
178
|
+
:10010000214601360121470136007EFE09D2190140
|
179
|
+
:100110002146017E17C20001FF5F16002148011928
|
180
|
+
:020000040023D7
|
181
|
+
:10012000194E79234623965778239EDA3F01B2CAA7
|
182
|
+
:100130003F0156702B5E712B722B732146013421C7
|
183
|
+
:0400000500000000F7
|
184
|
+
:00000001FF
|
185
|
+
~~~
|
186
|
+
|
149
187
|
### How To Setup a Development Environment
|
150
188
|
|
151
189
|
[Clone the repository from Github](https://github.com/Origen-SDK/origen_memory_image).
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: origen_memory_image
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McGinty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.2.2
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: ptools
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '1'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: origen_doc_helpers
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,6 +53,7 @@ files:
|
|
67
53
|
- lib/origen_memory_image/base.rb
|
68
54
|
- lib/origen_memory_image/binary.rb
|
69
55
|
- lib/origen_memory_image/hex.rb
|
56
|
+
- lib/origen_memory_image/intel_hex.rb
|
70
57
|
- lib/origen_memory_image/s_record.rb
|
71
58
|
- templates/web/index.md.erb
|
72
59
|
- templates/web/layouts/_basic.html.erb
|
@@ -90,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
77
|
- !ruby/object:Gem::Version
|
91
78
|
version: 1.8.11
|
92
79
|
requirements: []
|
93
|
-
|
94
|
-
rubygems_version: 2.6.7
|
80
|
+
rubygems_version: 3.1.4
|
95
81
|
signing_key:
|
96
82
|
specification_version: 4
|
97
83
|
summary: Provides a standard API for consuming memory image files in any format e.g.
|