cross_origen 0.7.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/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
|