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