cross_origen 0.7.0 → 1.0.0
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 +4 -4
- data/bin/fix_my_workspace +10 -2
- data/config/{development.rb → boot.rb} +1 -5
- data/config/shared_commands.rb +10 -6
- data/config/version.rb +2 -2
- data/lib/cross_origen/cmsis_svd.rb +133 -121
- data/lib/cross_origen/ip_xact.rb +51 -7
- data/lib/cross_origen/xml_doc.rb +1 -1
- data/lib/cross_origen.rb +40 -28
- data/lib/cross_origen_dev/dut.rb +62 -0
- data/templates/web/index.md.erb +26 -9
- metadata +8 -12
- data/config/environment.rb +0 -36
- data/config/users.rb +0 -18
- data/lib/cross_origen/commands/import.rb +0 -32
- data/lib/cross_origen/origen_format.rb +0 -554
- data/lib/cross_origen/test/dut.rb +0 -64
@@ -1,554 +0,0 @@
|
|
1
|
-
module CrossOrigen
|
2
|
-
class OrigenFormat
|
3
|
-
require 'nokogiri'
|
4
|
-
|
5
|
-
SUB_BLOCK_ATTRS = {
|
6
|
-
base_address: 'IP base address',
|
7
|
-
byte_order: 'Describes endianness of the IP. Values possible are :big_endian and :little_endian',
|
8
|
-
lau: 'IP Least Addressable Unit: Values possible are (1..32)',
|
9
|
-
version: 'IP version',
|
10
|
-
instance: 'IP instance',
|
11
|
-
instance_module: 'IP module',
|
12
|
-
class_name: 'Class name',
|
13
|
-
instance: 'IP instance',
|
14
|
-
instance_module: 'IP module',
|
15
|
-
addr_block_name: 'Address block name',
|
16
|
-
space: 'Address block space'
|
17
|
-
}
|
18
|
-
|
19
|
-
FILE_COMMENTS = {
|
20
|
-
class: "\# This file is created by Origen via CrossOrigen::OrigenFormat#export, and is read-only.\n\# If you need to make changes, re-open the class\n",
|
21
|
-
incl: "\# This file is created by Origen via CrossOrigen::OrigenFormat#export, and is read-only"
|
22
|
-
}
|
23
|
-
|
24
|
-
attr_reader :obj, :top_level_class, :top_level_hierarchy, :output_dir, :top_level_path, :incl_path, :incl_dir, :file_content, :inst_level
|
25
|
-
|
26
|
-
def initialize(options = {})
|
27
|
-
options = {
|
28
|
-
obj: $dut,
|
29
|
-
path: "#{Origen.root!}/output",
|
30
|
-
instantiate_level: :top
|
31
|
-
}.update(options)
|
32
|
-
@obj = options[:obj]
|
33
|
-
@output_dir = options[:path]
|
34
|
-
@inst_level = options[:instantiate_level]
|
35
|
-
fail "@instantiate_level must be either set to ':top' or ':sub_block'" unless [:top, :sub_block].include?(@inst_level)
|
36
|
-
@top_level_path = "#{output_dir}/top_level.rb"
|
37
|
-
@incl_path = "#{output_dir}/sub_blocks.rb"
|
38
|
-
@incl_dir = "#{output_dir}/import"
|
39
|
-
@top_level_hierarchy = get_namespace(options)
|
40
|
-
@top_level_class = @top_level_hierarchy.keys.last
|
41
|
-
|
42
|
-
# first key is file type (:bom or :incl) and second is object name
|
43
|
-
@file_content = Hash.new do |h, k|
|
44
|
-
h[k] = {}
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def export
|
49
|
-
# Delete any previous files
|
50
|
-
FileUtils.rm_rf(@incl_dir) if File.exist?(@incl_dir)
|
51
|
-
FileUtils.mkdir_p(@incl_dir)
|
52
|
-
|
53
|
-
# Check if previous version of top-level files exist and delete them
|
54
|
-
File.delete(@top_level_path) if File.exist?(@top_level_path)
|
55
|
-
File.delete(@incl_path) if File.exist?(@incl_path)
|
56
|
-
|
57
|
-
# Create the sub_block objects in the top_level.rb file
|
58
|
-
# This method will create each required class file recursively (indirectly)
|
59
|
-
# and will gather all of the information required to create the include file.
|
60
|
-
# In essence it does it all
|
61
|
-
create_bom
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
# Creates the BoM file that creates the sub_blocks from the meta-modelled sub_blocks
|
67
|
-
def create_bom
|
68
|
-
indent = ''
|
69
|
-
file_content = {}
|
70
|
-
full_class = @top_level_hierarchy.keys.last
|
71
|
-
klass = @top_level_class.demodulize
|
72
|
-
Origen.log.info 'Exporting to Origen format...'
|
73
|
-
File.open(@top_level_path, 'w') do |bom_file|
|
74
|
-
# bom_file.chmod(0555)
|
75
|
-
bom_file.puts(FILE_COMMENTS[:incl])
|
76
|
-
bom_file.puts("require_relative 'sub_blocks'")
|
77
|
-
@top_level_hierarchy.each do |name, obj|
|
78
|
-
if @inst_level == :sub_block && @top_level_hierarchy.keys.last == name
|
79
|
-
obj = 'module'
|
80
|
-
name = 'SubBlocks'
|
81
|
-
end
|
82
|
-
bom_file.puts("#{indent}#{obj} #{name.split('::').last}")
|
83
|
-
indent += ' '
|
84
|
-
end
|
85
|
-
bom_file.puts("#{indent}include Origen::Model")
|
86
|
-
bom_file.puts('')
|
87
|
-
if @inst_level == :sub_block
|
88
|
-
bom_file.puts("#{indent}def instantiate_sub_blocks(options = {})")
|
89
|
-
elsif @inst_level == :top
|
90
|
-
bom_file.puts("#{indent}def initialize(options = {})")
|
91
|
-
else
|
92
|
-
fail '@instantiate_level not set to an acceptable value [:top, :sub_block]'
|
93
|
-
end
|
94
|
-
indent += ' '
|
95
|
-
# This method is recursive (indirectly) so file_content should find all BoM and include file strings
|
96
|
-
create_file_content(@obj, indent)
|
97
|
-
@file_content.each do |file_type, str_hash|
|
98
|
-
if file_type == :bom
|
99
|
-
str_hash.each do |_obj, str|
|
100
|
-
bom_file.puts(str)
|
101
|
-
end
|
102
|
-
elsif file_type == :incl
|
103
|
-
# Create the include file
|
104
|
-
File.open(@incl_path, 'w') do |incl_file|
|
105
|
-
str_hash.each do |_obj, str|
|
106
|
-
incl_file.puts(str)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
else
|
110
|
-
Origen.log.error 'Incorrect key for @file_content instance variable Hash, must be :incl or :bom'
|
111
|
-
end
|
112
|
-
end
|
113
|
-
if @obj.owns_registers?
|
114
|
-
@obj.regs.each do |_reg_name, r|
|
115
|
-
reg_path = r.path.gsub(/#{klass}./i, '')
|
116
|
-
reg_path.chop! if reg_path[-1] == '.'
|
117
|
-
r.description.each do |line|
|
118
|
-
bom_file.puts("#{indent}# #{line}")
|
119
|
-
end
|
120
|
-
reg_string = "#{indent}reg :#{r.name}, #{r.address.to_hex}, size: #{r.size}"
|
121
|
-
if r.respond_to? :bit_order
|
122
|
-
if r.bit_order.is_a?(String)
|
123
|
-
reg_string += ", bit_order: '#{r.bit_order}'"
|
124
|
-
elsif r.bit_order.is_a?(Symbol)
|
125
|
-
reg_string += ", bit_order: :#{r.bit_order}"
|
126
|
-
elsif r.bit_order.is_a?(NilClass)
|
127
|
-
# do not add bitorder if it is not available
|
128
|
-
else
|
129
|
-
reg_string += ", bit_order: #{r.bit_order}"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
if r.respond_to? :space
|
133
|
-
if r.space.is_a?(String)
|
134
|
-
reg_string += ", space: '#{r.space}'"
|
135
|
-
elsif r.space.is_a?(Symbol)
|
136
|
-
reg_string += ", space: :#{r.space}"
|
137
|
-
else
|
138
|
-
reg_string += ", space: #{r.space}"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
bom_file.puts("#{reg_string} do |reg|")
|
142
|
-
indent += ' '
|
143
|
-
r.named_bits do |field, bits|
|
144
|
-
if bits.size > 1
|
145
|
-
bit_index = "#{bits.position}..#{bits.position + bits.size - 1}"
|
146
|
-
else
|
147
|
-
bit_index = bits.position.to_s
|
148
|
-
end
|
149
|
-
bits.description.each do |line|
|
150
|
-
bom_file.puts("#{indent}# #{line}")
|
151
|
-
end
|
152
|
-
bom_file.puts("#{indent}reg.bit #{bit_index}, :#{field}, reset: 0b#{bits.reset_val.to_s(2)}, access: :#{bits.access}")
|
153
|
-
end
|
154
|
-
indent = indent[0..-3]
|
155
|
-
bom_file.puts("#{indent}end")
|
156
|
-
end
|
157
|
-
end
|
158
|
-
indent = indent[0..-3]
|
159
|
-
bom_file.puts("#{indent}end")
|
160
|
-
@top_level_hierarchy.each do |_name, _obj|
|
161
|
-
indent = indent[0..-3]
|
162
|
-
bom_file.puts("#{indent}end")
|
163
|
-
end
|
164
|
-
end
|
165
|
-
# Give a newline on console to sepearate out the '.' used for progress indicator
|
166
|
-
puts
|
167
|
-
end
|
168
|
-
|
169
|
-
# Create the bom string for the current object. Recursive method until no more sub_blocks are found for the current object
|
170
|
-
def create_file_content(obj, indent)
|
171
|
-
unless obj.respond_to?(:sub_blocks) && obj.send(:sub_blocks)
|
172
|
-
Origen.log.warn 'Object argument does not have sub_blocks, ignoring it...'
|
173
|
-
return
|
174
|
-
end
|
175
|
-
obj.sub_blocks.each do |name, sb|
|
176
|
-
@file_content[:bom][name] = "#{indent}sub_block :#{name}"
|
177
|
-
instance_vars_with_content(sb).each do |attr, value|
|
178
|
-
if value.is_a?(String)
|
179
|
-
@file_content[:bom][name] += ", #{attr}: '#{value}'"
|
180
|
-
elsif value.is_a?(Symbol)
|
181
|
-
@file_content[:bom][name] += ", #{attr} = :#{value}"
|
182
|
-
else
|
183
|
-
if attr == :base_address
|
184
|
-
@file_content[:bom][name] += ", #{attr}: #{value.to_hex}"
|
185
|
-
else
|
186
|
-
@file_content[:bom][name] += ", #{attr}: #{value}"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
@file_content[:bom][name] += ", abs_path: '#{sb.path}'"
|
191
|
-
# Add on the class_name attr as this is not part of the sub_block meta_model
|
192
|
-
class_name = sb.class.to_s.demodulize
|
193
|
-
if class_name == 'SubBlock'
|
194
|
-
file_content[:bom][name] += ", class_name: '#{sb.name.upcase}'"
|
195
|
-
else
|
196
|
-
file_content[:bom][name] += ", class_name: '#{class_name}'"
|
197
|
-
end
|
198
|
-
# Create the class file for this object
|
199
|
-
create_class_file(sb)
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def create_class_file(obj)
|
204
|
-
ivars_content = {}
|
205
|
-
ivars_content = instance_vars_with_content(obj)
|
206
|
-
indent = ''
|
207
|
-
klass = get_full_class(obj)
|
208
|
-
class_path_addition = (klass.split('::') - @top_level_class.split('::')).join('/').downcase
|
209
|
-
@file_content[:incl][klass] = "require_relative 'import/#{class_path_addition}'"
|
210
|
-
class_file_name = Pathname.new("#{@incl_dir}/#{class_path_addition}.rb")
|
211
|
-
class_file_dir = class_file_name.dirname
|
212
|
-
unless class_file_dir.exist?
|
213
|
-
Origen.log.debug "app: Directory #{class_file_dir} does not exist, creating it..."
|
214
|
-
FileUtils.mkdir_p(class_file_dir)
|
215
|
-
end
|
216
|
-
File.open(class_file_name, 'w') do |file|
|
217
|
-
# file.chmod(0555)
|
218
|
-
file.puts('# -*- encoding : utf-8 -*-') if RUBY_VERSION < '2.0.0'
|
219
|
-
file.puts(FILE_COMMENTS[:class])
|
220
|
-
# print out the top level object hierarchy
|
221
|
-
@top_level_hierarchy.each do |name, o|
|
222
|
-
file.puts("#{indent}#{o} #{name.split('::').last}")
|
223
|
-
indent += ' '
|
224
|
-
end
|
225
|
-
# print out the current object's sub-hierarchy
|
226
|
-
sub_array = klass.split('::') - @top_level_class.split('::')
|
227
|
-
object_type_array = %w(class) * sub_array.size
|
228
|
-
sub_hierarchy = Hash[sub_array.zip object_type_array]
|
229
|
-
sub_hierarchy.each do |name, o|
|
230
|
-
if o == sub_hierarchy.values.last
|
231
|
-
file.puts("#{indent}#{o} #{name.split('::').last} # rubocop:disable ClassLength")
|
232
|
-
else
|
233
|
-
file.puts("#{indent}#{o} #{name.split('::').last}")
|
234
|
-
end
|
235
|
-
indent += ' '
|
236
|
-
end
|
237
|
-
file.puts("#{indent}include Origen::Model")
|
238
|
-
file.puts('')
|
239
|
-
instance_vars_with_content(obj).each do |attr, _value|
|
240
|
-
file.puts("#{indent}# #{SUB_BLOCK_ATTRS[attr]}")
|
241
|
-
file.puts("#{indent}attr_reader :#{attr}")
|
242
|
-
file.puts('')
|
243
|
-
end
|
244
|
-
file.puts("#{indent}def initialize(options = {})")
|
245
|
-
indent += ' '
|
246
|
-
instance_vars_with_content(obj).each do |attr, value|
|
247
|
-
if value.is_a?(String)
|
248
|
-
file.puts("#{indent}\@#{attr} = '#{value}'")
|
249
|
-
elsif value.is_a?(Symbol)
|
250
|
-
file.puts("#{indent}\@#{attr} = :#{value}")
|
251
|
-
else
|
252
|
-
if attr == :base_address
|
253
|
-
file.puts("#{indent}\@#{attr} = #{value.to_hex}")
|
254
|
-
else
|
255
|
-
file.puts("#{indent}\@#{attr} = #{value}")
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
# If the current object has sub_block they need to be instantiated in the init
|
260
|
-
if obj.respond_to?(:sub_blocks)
|
261
|
-
obj.sub_blocks.each do |n, block|
|
262
|
-
bom_string = "#{indent}sub_block :#{n}"
|
263
|
-
instance_vars_with_content(block).each do |attr, value|
|
264
|
-
if value.is_a?(String)
|
265
|
-
bom_string += ", #{attr}: '#{value}'"
|
266
|
-
elsif value.is_a?(Symbol)
|
267
|
-
bom_string += ", #{attr}: :#{value}"
|
268
|
-
else
|
269
|
-
if attr == :base_address
|
270
|
-
bom_string += ", #{attr}: #{value.to_hex}"
|
271
|
-
else
|
272
|
-
bom_string += ", #{attr}: #{value}"
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
bom_string += ", abs_path: '#{block.path}'"
|
277
|
-
# Add on the class_name attr as this is not part of the sub_block meta_model
|
278
|
-
class_name = block.class.to_s.split('::').last
|
279
|
-
if class_name == 'SubBlock'
|
280
|
-
bom_string += ", class_name: '#{block.name.upcase}'"
|
281
|
-
else
|
282
|
-
bom_string += ", class_name: '#{class_name}'"
|
283
|
-
end
|
284
|
-
file.puts(bom_string)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
file.puts("#{indent}instantiate_registers(options)") if obj.owns_registers?
|
288
|
-
indent = indent[0..-3]
|
289
|
-
file.puts("#{indent}end")
|
290
|
-
if obj.owns_registers?
|
291
|
-
file.puts('')
|
292
|
-
file.puts("#{indent}# rubocop:disable LineLength")
|
293
|
-
# Need the register and bit_field descriptions to use double quotes
|
294
|
-
file.puts("#{indent}# rubocop:disable StringLiterals")
|
295
|
-
file.puts("#{indent}def instantiate_registers(options = {}) # rubocop:disable MethodLength")
|
296
|
-
indent += ' '
|
297
|
-
obj.regs.each do |_reg_name, r|
|
298
|
-
reg_addr_offset = (r.address - obj.base_address).to_hex
|
299
|
-
reg_path = r.path.gsub(/#{klass}./i, '')
|
300
|
-
reg_path.chop! if reg_path[-1] == '.'
|
301
|
-
r.description.each do |line|
|
302
|
-
file.puts("#{indent}# #{line}")
|
303
|
-
end
|
304
|
-
reg_string = "#{indent}reg :#{r.name}, #{reg_addr_offset}, size: #{r.size}"
|
305
|
-
if r.respond_to? :bit_order
|
306
|
-
if r.bit_order.is_a?(String)
|
307
|
-
reg_string += ", bit_order: '#{r.bit_order}'"
|
308
|
-
elsif r.bit_order.is_a?(Symbol)
|
309
|
-
reg_string += ", bit_order: :#{r.bit_order}"
|
310
|
-
elsif r.bit_order.is_a?(NilClass)
|
311
|
-
# do not add bitorder if it is not available
|
312
|
-
else
|
313
|
-
reg_string += ", bit_order: #{r.bit_order}"
|
314
|
-
end
|
315
|
-
end
|
316
|
-
if r.respond_to? :space
|
317
|
-
if r.space.is_a?(String)
|
318
|
-
reg_string += ", space: '#{r.space}'"
|
319
|
-
elsif r.space.is_a?(Symbol)
|
320
|
-
reg_string += ", space: :#{r.space}"
|
321
|
-
else
|
322
|
-
reg_string += ", space: #{r.space}"
|
323
|
-
end
|
324
|
-
end
|
325
|
-
file.puts("#{reg_string} do |reg|")
|
326
|
-
indent += ' '
|
327
|
-
r.named_bits do |field, bits|
|
328
|
-
plain_bit_description = Nokogiri::HTML(bits.description.join(' ').to_s).text
|
329
|
-
plain_bit_description.gsub!(/"/, "'")
|
330
|
-
if bits.size > 1
|
331
|
-
bit_index = "#{bits.position + bits.size - 1}..#{bits.position}"
|
332
|
-
else
|
333
|
-
bit_index = bits.position.to_s
|
334
|
-
end
|
335
|
-
bits.description.each do |line|
|
336
|
-
file.puts("#{indent}# #{line}")
|
337
|
-
end
|
338
|
-
file.puts("#{indent}reg.bit #{bit_index}, :#{field}, reset: 0b#{bits.reset_val.to_s(2)}, access: :#{bits.access}")
|
339
|
-
end
|
340
|
-
indent = indent[0..-3]
|
341
|
-
file.puts("#{indent}end")
|
342
|
-
end
|
343
|
-
indent = indent[0..-3]
|
344
|
-
file.puts("#{indent}end")
|
345
|
-
end
|
346
|
-
@top_level_hierarchy.each do |_name, _obj|
|
347
|
-
indent = indent[0..-3]
|
348
|
-
file.puts("#{indent}end")
|
349
|
-
end
|
350
|
-
sub_hierarchy.each do |_name, _obj|
|
351
|
-
indent = indent[0..-3]
|
352
|
-
file.puts("#{indent}end")
|
353
|
-
end
|
354
|
-
end
|
355
|
-
# Place a '.' to the console to indicate file write progress to the user
|
356
|
-
print '.'
|
357
|
-
# If the current obj has sub_blocks then write those class files
|
358
|
-
if obj.respond_to?(:sub_blocks) && obj.send(:sub_blocks)
|
359
|
-
obj.sub_blocks.each do |_name, sb|
|
360
|
-
create_class_file(sb)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
# Creates the class files for the sub_blocks instantiated in the BoM
|
366
|
-
def create_class_files
|
367
|
-
indent = ''
|
368
|
-
object_hierarchy = get_namespace(@obj)
|
369
|
-
klass = @obj.class.to_s.split('::').last
|
370
|
-
File.open(@incl_path, 'w') do |incl_file|
|
371
|
-
incl_file.chmod(0555)
|
372
|
-
incl_file.puts(FILE_COMMENTS[:incl])
|
373
|
-
@obj.sub_blocks.each do |_name, sb|
|
374
|
-
current_bist = nil
|
375
|
-
bypass_addr = 0
|
376
|
-
incl_file.puts("require_relative 'import/#{sb.name}.rb'")
|
377
|
-
File.open("#{@incl_dir}/#{sb.name}.rb", 'w') do |file|
|
378
|
-
file.chmod(0555)
|
379
|
-
file.puts('# -*- encoding : utf-8 -*-') if RUBY_VERSION < '2.0.0'
|
380
|
-
file.puts(FILE_COMMENTS[:class])
|
381
|
-
object_hierarchy.each do |name, obj|
|
382
|
-
file.puts("#{indent}#{obj} #{name.split('::').last}")
|
383
|
-
indent += ' '
|
384
|
-
end
|
385
|
-
file.puts("#{indent}class #{sb.name.upcase} # rubocop:disable ClassLength")
|
386
|
-
indent += ' '
|
387
|
-
file.puts("#{indent}include Origen::Model")
|
388
|
-
file.puts('')
|
389
|
-
SUB_BLOCK_ATTRS.each do |attr, comment|
|
390
|
-
attr_sym = ":#{attr}"
|
391
|
-
# First check that the attribute has content
|
392
|
-
if sb.respond_to?(attr)
|
393
|
-
next if sb.send(eval(attr_sym)).nil?
|
394
|
-
file.puts("#{indent}# #{comment}")
|
395
|
-
file.puts("#{indent}attr_reader :#{attr}")
|
396
|
-
file.puts('')
|
397
|
-
end
|
398
|
-
end
|
399
|
-
file.puts("#{indent}def initialize(options = {})")
|
400
|
-
indent += ' '
|
401
|
-
SUB_BLOCK_ATTRS.keys.each do |attr|
|
402
|
-
case attr
|
403
|
-
when /base_address/
|
404
|
-
attr_var = ":@reg_#{attr}"
|
405
|
-
file.puts("#{indent}\@#{attr} = #{sb.instance_variable_get(eval(attr_var)).to_hex}")
|
406
|
-
else
|
407
|
-
attr_var = ":@#{attr}"
|
408
|
-
attr_sym = ":#{attr}"
|
409
|
-
# First check that the attribute has content
|
410
|
-
if sb.respond_to?(attr)
|
411
|
-
next if sb.send(eval(attr_sym)).nil?
|
412
|
-
if sb.instance_variable_get(eval(attr_var)).is_a?(String)
|
413
|
-
file.puts("#{indent}\@#{attr} = '#{sb.instance_variable_get(eval(attr_var))}'")
|
414
|
-
elsif sb.instance_variable_get(eval(attr_var)).is_a?(Symbol)
|
415
|
-
file.puts("#{indent}\@#{attr} = :#{sb.instance_variable_get(eval(attr_var))}")
|
416
|
-
else
|
417
|
-
file.puts("#{indent}\@#{attr} = #{sb.instance_variable_get(eval(attr_var))}")
|
418
|
-
end
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
422
|
-
file.puts("#{indent}instantiate_registers(options)")
|
423
|
-
indent = indent[0..-3]
|
424
|
-
file.puts("#{indent}end")
|
425
|
-
file.puts('')
|
426
|
-
file.puts("#{indent}# rubocop:disable LineLength")
|
427
|
-
# Need the register and bit_field descriptions to use double quotes
|
428
|
-
file.puts("#{indent}# rubocop:disable StringLiterals")
|
429
|
-
file.puts("#{indent}def instantiate_registers(options = {}) # rubocop:disable MethodLength")
|
430
|
-
indent += ' '
|
431
|
-
sb.regs.each do |_reg_name, r|
|
432
|
-
reg_addr_offset = (r.address - sb.base_address).to_hex
|
433
|
-
reg_path = r.path.gsub(/#{klass}./i, '')
|
434
|
-
reg_path.chop! if reg_path[-1] == '.'
|
435
|
-
r.description.each do |line|
|
436
|
-
file.puts("#{indent}# #{line}")
|
437
|
-
end
|
438
|
-
reg_string = "#{indent}reg :#{r.name}, #{reg_addr_offset}, size: #{r.size}"
|
439
|
-
if r.respond_to? :bit_order
|
440
|
-
if r.bit_order.is_a?(String)
|
441
|
-
reg_string += ", bit_order: '#{r.bit_order}'"
|
442
|
-
elsif r.bit_order.is_a?(Symbol)
|
443
|
-
reg_string += ", bit_order: :#{r.bit_order}"
|
444
|
-
elsif r.bit_order.is_a?(NilClass)
|
445
|
-
# do not add bitorder if it is not available
|
446
|
-
else
|
447
|
-
reg_string += ", bit_order: #{r.bit_order}"
|
448
|
-
end
|
449
|
-
end
|
450
|
-
if r.respond_to? :space
|
451
|
-
if r.space.is_a?(String)
|
452
|
-
reg_string += ", space: '#{r.space}'"
|
453
|
-
elsif r.space.is_a?(Symbol)
|
454
|
-
reg_string += ", space: :#{r.space}"
|
455
|
-
else
|
456
|
-
reg_string += ", space: #{r.space}"
|
457
|
-
end
|
458
|
-
end
|
459
|
-
file.puts("#{reg_string} do |reg|")
|
460
|
-
indent += ' '
|
461
|
-
r.named_bits do |field, bits|
|
462
|
-
plain_bit_description = Nokogiri::HTML(bits.description.join(' ').to_s).text
|
463
|
-
plain_bit_description.gsub!(/"/, "'")
|
464
|
-
if bits.size > 1
|
465
|
-
bit_index = "#{bits.position + bits.size - 1}..#{bits.position}"
|
466
|
-
else
|
467
|
-
bit_index = bits.position.to_s
|
468
|
-
end
|
469
|
-
bits.description.each do |line|
|
470
|
-
file.puts("#{indent}# #{line}")
|
471
|
-
end
|
472
|
-
file.puts("#{indent}reg.bit #{bit_index}, :#{field}, reset: 0b#{bits.reset_val.to_s(2)}, access: :#{bits.access}")
|
473
|
-
end
|
474
|
-
indent = indent[0..-3]
|
475
|
-
file.puts("#{indent}end")
|
476
|
-
end
|
477
|
-
indent = indent[0..-3]
|
478
|
-
file.puts("#{indent}end")
|
479
|
-
indent = indent[0..-3]
|
480
|
-
file.puts("#{indent}end")
|
481
|
-
object_hierarchy.each do |_name, _obj|
|
482
|
-
indent = indent[0..-3]
|
483
|
-
file.puts("#{indent}end")
|
484
|
-
end
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
end
|
489
|
-
|
490
|
-
# Returns a hash (key == scope, value is 'module' or 'class') needed to
|
491
|
-
# reconstruct the application hierarchy
|
492
|
-
def get_namespace(options)
|
493
|
-
obj = options[:obj]
|
494
|
-
namespace = []
|
495
|
-
object_hierarchy = {}
|
496
|
-
namespace = obj.class.to_s.split('::')
|
497
|
-
namespace.pop if options[:class_name]
|
498
|
-
curr_eval = nil
|
499
|
-
scope = nil
|
500
|
-
namespace.each_with_index do |e, _i|
|
501
|
-
scope.nil? ? scope = e : scope += "::#{e}"
|
502
|
-
curr_eval = "#{scope}.class"
|
503
|
-
object_hierarchy["#{scope}"] = eval(curr_eval).to_s.downcase
|
504
|
-
end
|
505
|
-
if options[:class_name]
|
506
|
-
if object_hierarchy.empty?
|
507
|
-
object_hierarchy[options[:class_name]] = 'class'
|
508
|
-
else
|
509
|
-
object_hierarchy["#{object_hierarchy.keys.last}::#{options[:class_name]}"] = 'class'
|
510
|
-
end
|
511
|
-
end
|
512
|
-
object_hierarchy
|
513
|
-
end
|
514
|
-
|
515
|
-
# Returns a hash of all of the non-nil instance_variables for an instance
|
516
|
-
def instance_vars_with_content(obj)
|
517
|
-
ivars_content = {}
|
518
|
-
obj.instance_variables.each do |ivar|
|
519
|
-
ivar_sym = ivar.to_s.gsub('@', '').to_sym
|
520
|
-
# Check for reg_base_address as method base_address refers to this instance variable
|
521
|
-
# Could use reg_base_address but all docs show to use base_address in the sub_block calls
|
522
|
-
# If not reg_base_address the ivar must be included in SUB_BLOCK_ATTRS
|
523
|
-
next unless ivar_sym == :reg_base_address || SUB_BLOCK_ATTRS.include?(ivar_sym)
|
524
|
-
# Skip the instance variable if it is nil
|
525
|
-
next if obj.send(ivar_sym).nil?
|
526
|
-
if ivar_sym == :reg_base_address
|
527
|
-
ivars_content[:base_address] = obj.send(ivar_sym)
|
528
|
-
else
|
529
|
-
ivars_content[ivar_sym] = obj.send(ivar_sym)
|
530
|
-
end
|
531
|
-
end
|
532
|
-
ivars_content
|
533
|
-
end
|
534
|
-
|
535
|
-
# Recursively work through the object hierarchy and return the full class string
|
536
|
-
def get_full_class(obj)
|
537
|
-
class_str = ''
|
538
|
-
until obj.nil?
|
539
|
-
if obj == Origen.top_level
|
540
|
-
class_str.prepend @top_level_hierarchy.keys.last
|
541
|
-
else
|
542
|
-
# If the class method produces "SubBlock" then use the object name instead
|
543
|
-
if obj.class.to_s.split('::').last == 'SubBlock'
|
544
|
-
class_str.prepend "::#{obj.name.upcase}"
|
545
|
-
else
|
546
|
-
class_str.prepend "::#{obj.class.to_s.split('::').last}"
|
547
|
-
end
|
548
|
-
end
|
549
|
-
obj = obj.parent
|
550
|
-
end
|
551
|
-
class_str
|
552
|
-
end
|
553
|
-
end
|
554
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
module CrossOrigen
|
2
|
-
module Test
|
3
|
-
# Simple DUT class used for testing
|
4
|
-
class DUT
|
5
|
-
include Origen::TopLevel
|
6
|
-
include CrossOrigen
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@path = :hidden
|
10
|
-
sub_block :atx, class_name: 'D_IP_ANA_TEST_ANNEX_SYN', base_address: 0x4000_0000
|
11
|
-
|
12
|
-
# Register defined solely to test out the top level register export
|
13
|
-
reg :dut_top_level_reg, 0x0, size: 32, bit_order: :msb0, lau: 8 do
|
14
|
-
bit 15, :pls_work, reset: 1, access: :rw
|
15
|
-
bit 14, :second_bit, reset: 0, access: :rw
|
16
|
-
end
|
17
|
-
# Register defined solely to test out the top level register export
|
18
|
-
reg :dut_top_level_reg_number_two, 0x10, size: 32, bit_order: :lsb0, lau: 16 do
|
19
|
-
bit 0, :pls_work, reset: 0, access: :ro
|
20
|
-
bit 1, :second_bit, reset: 1, access: :rw
|
21
|
-
end
|
22
|
-
# Import some data from IP-XACT
|
23
|
-
cr_import(path: "#{Origen.root}/imports/ipxact.xml")
|
24
|
-
end
|
25
|
-
|
26
|
-
def add_atx2
|
27
|
-
sub_block :atx2, class_name: 'ATX2', base_address: 0x6000_0000
|
28
|
-
end
|
29
|
-
|
30
|
-
class ATX2
|
31
|
-
include Origen::Model
|
32
|
-
include CrossOrigen
|
33
|
-
|
34
|
-
def initialize
|
35
|
-
cr_import(path: "#{Origen.root}/approved/ip_xact_sub_block.xml")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class D_IP_ANA_TEST_ANNEX_SYN # rubocop:disable ClassAndModuleCamelCase
|
40
|
-
include Origen::Model
|
41
|
-
include CrossOrigen
|
42
|
-
|
43
|
-
def initialize
|
44
|
-
# A manually defined register for testing the conversion of any specific attributes
|
45
|
-
|
46
|
-
# ** MGATE Clock Divider Register **
|
47
|
-
# The MCLKDIV register is used to divide down the frequency of the HBOSCCLK input. If the MCLKDIV
|
48
|
-
# register is set to value "N", then the output (beat) frequency of the clock divider is OSCCLK / (N+1). The
|
49
|
-
# resulting beats are, in turn, counted by the PTIMER module to control the duration of Flash high-voltage
|
50
|
-
# operations.
|
51
|
-
# This is a test of potentially problematic characters ' " \' \" < >
|
52
|
-
reg :mclkdiv, 0x0, size: 16, bit_order: 'decrement' do
|
53
|
-
# **Oscillator (Hi)** - Firmware FMU clk source selection. (Note that in addition to this firmware-controlled bit, the
|
54
|
-
# FMU clock source is also dependent on test and power control discretes).
|
55
|
-
#
|
56
|
-
# 0 | FMU clock is the externally supplied bus clock ipg_clk
|
57
|
-
# 1 | FMU clock is the internal oscillator from the TFS hardblock
|
58
|
-
bit 15, :osch, reset: 1, access: :rw
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|