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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: caf8c439a35b5f220e8274b6626673ee7525271a
4
- data.tar.gz: ec7fbf5149451f4ec2f92f4f9e9cbb4757ffd897
2
+ SHA256:
3
+ metadata.gz: 2d9b91a3a905b3801a9d96ee96fe7494baf3c201d1b3ee34107599923ff0763a
4
+ data.tar.gz: d66b83fcd77afac1ed13754871d9fab2952760f2ad5fc17b6709904ef6a48c6d
5
5
  SHA512:
6
- metadata.gz: 94959863f2afed01b3300650b793209631118c11fca988b89b30bdc162497974a53423c87c2538c84569448f98f1ed7ba77f198983c24b11e67f27fc5e0b929d
7
- data.tar.gz: feb360c36844b949e4463956ab81d69e5e0dfee76b094fee1acf149ef946cb27b3f0c79ec77748dc6003be23bbe918d7bb35fa77665a7e40a7c0eb528a7f2553
6
+ metadata.gz: f6fedde88b97b4661fb9773d6780497ba995f07114661ba3c94b5ca842c818dc59592e40758c387ce7f8361b1cf68977c40aba88c0a864a3a3ab751a9a118e0b
7
+ data.tar.gz: 7a712d8374d57ae31dd11454cc7985084988ca90e3d883205b3738bc1ac48c2e45bb89054c6a9a816efd1b57096e17220da099508a634eb915af9760a7114a8d
data/config/version.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  module OrigenMemoryImage
2
2
  MAJOR = 0
3
- MINOR = 6
4
- BUGFIX = 0
3
+ MINOR = 8
4
+ BUGFIX = 2
5
5
  DEV = nil
6
-
7
6
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
7
  end
@@ -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(1)
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], 4)]
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
- File.binary?(file)
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
- result << [@address, data[data.length - remainder..data.length].to_i(16)]
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
- result << [addr, data[data.length - remainder..data.length].to_i(16)]
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
@@ -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 # => 0x3000_F000
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.6.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: 2017-03-20 00:00:00.000000000 Z
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
- rubyforge_project:
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.