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