cross_origen 0.5.0

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