Module: Origen::Registers
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/origen/registers.rb,
lib/origen/registers/bit.rb,
lib/origen/registers/reg.rb,
lib/origen/registers/domain.rb,
lib/origen/registers/container.rb,
lib/origen/registers/bit_collection.rb,
lib/origen/registers/msb0_delegator.rb,
lib/origen/registers/reg_collection.rb
Overview
Origen provides a powerful register class which you are encouraged to use when you wish to interact with a silicon register (or RAM location). By interacting with the register on silicon through the register API your pattern will automatically track silicon state, so you can set and forget bits in the patgen the same as you would do with a physical register. Include this module to add registers to your block, then use the macros described below to instantiate register objects
include Origen::Registers
Defined Under Namespace
Classes: Bit, BitCollection, Container, Domain, Msb0Delegator, Placeholder, Reg, RegCollection
Constant Summary collapse
- @@reg_metadata =
{}
- @@bit_metadata =
{}
Class Method Summary collapse
-
.bit_metadata ⇒ Object
private
Returns a lookup table containing all custom bit metadata defined by objects in an application.
-
.default_bit_meta_data(*args, &block) ⇒ Object
An alias for default_bit_metadata.
-
.default_bit_metadata ⇒ Object
Can be called to add app specific meta data to all bits.
-
.default_reg_meta_data(*args, &block) ⇒ Object
An alias for default_reg_metadata.
-
.default_reg_metadata ⇒ Object
Can be called to add app specific meta data to all registers.
-
.reg_metadata ⇒ Object
private
Returns a lookup table containing all custom register metadata defined by objects in an application.
Instance Method Summary collapse
-
#_registers ⇒ Object
private
All register objects are stored here, but they should be accessed via the _reg method to ensure that feature scoping is applied.
-
#add_reg(id, address, size = nil, bit_info = {}, &_block) ⇒ Object
Add a register.
- #add_reg32(id, address, args = {}, &block) ⇒ Object
-
#bit(index, name, attrs = {}) ⇒ Object
(also: #bits)
Called within an add_reg block to define bits.
-
#bit_order ⇒ Object
Returns the bit order attribute of the model (either :msb0 or :lsb0).
-
#contains_bits?(obj) ⇒ Boolean
Returns true if the given object is one of the recognized Origen bit containers (bit collection, reg or container).
- #default_bit_metadata ⇒ Object (also: #default_bit_meta_data)
-
#default_reg_metadata ⇒ Object
(also: #default_reg_meta_data)
Can be called to add app specific meta data that is isolated to all registers defined within a given class.
- #define_file(file) ⇒ Object private
-
#del_reg(id) ⇒ Object
Delete an existing register.
- #delete_registers ⇒ Object
-
#dummy_reg(size = 16) ⇒ Object
Creates a dummy register.
-
#has_reg?(name, params = {}) ⇒ Boolean
(also: #has_reg)
Returns true if the object contains a register matching the given name.
- #instantiate_reg(id, attrs) ⇒ Object private
-
#is_a_bit?(obj) ⇒ Boolean
Returns true if the given object is an Origen bit.
-
#max_address_reg_size ⇒ Object
Returns the size (in bits) of the register with the highest address, can be useful in combination with max_reg_address to work out the range of addresses containing registers.
-
#max_reg_address ⇒ Object
Returns the highest address of all registers that have been added.
-
#method_missing(method, *args, &block) ⇒ Object
:nodoc:.
-
#min_reg_address ⇒ Object
Returns the lowest address of all registers that have been added.
- #read_register_missing!(reg) ⇒ Object
-
#reg(*args, &block) ⇒ Object
(also: #regs)
Returns -the register object matching the given name -or a hash of all registes matching a given regular expression -or a hash of all registers, associated with a feature, if no name is specified.
-
#reset_registers ⇒ Object
Resets all registers.
-
#respond_to?(sym, include_private = false) ⇒ Boolean
:nodoc:.
- #write_register_missing!(reg) ⇒ Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
:nodoc:
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/origen/registers.rb', line 41 def method_missing(method, *args, &block) # :nodoc: orig_method = method if method[-1] == '!' bang = true method = method.to_s.chop.to_sym end if _registers.key?(method) r = reg(method) r.sync if bang r else super(orig_method, *args, &block) end end |
Class Method Details
.bit_metadata ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a lookup table containing all custom bit metadata defined by objects in an application
84 85 86 |
# File 'lib/origen/registers.rb', line 84 def @@bit_metadata ||= {} end |
.default_bit_meta_data(*args, &block) ⇒ Object
An alias for default_bit_metadata
116 117 118 |
# File 'lib/origen/registers.rb', line 116 def (*args, &block) (*args, &block) end |
.default_bit_metadata ⇒ Object
Can be called to add app specific meta data to all bits
105 106 107 108 109 110 111 112 113 |
# File 'lib/origen/registers.rb', line 105 def Origen::Registers.[:global] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[:global].merge!(collector.to_h) end Origen::Registers.[:global] end |
.default_reg_meta_data(*args, &block) ⇒ Object
An alias for default_reg_metadata
100 101 102 |
# File 'lib/origen/registers.rb', line 100 def (*args, &block) (*args, &block) end |
.default_reg_metadata ⇒ Object
Can be called to add app specific meta data to all registers
89 90 91 92 93 94 95 96 97 |
# File 'lib/origen/registers.rb', line 89 def Origen::Registers.[:global] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[:global].merge!(collector.to_h) end Origen::Registers.[:global] end |
.reg_metadata ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a lookup table containing all custom register metadata defined by objects in an application
77 78 79 |
# File 'lib/origen/registers.rb', line 77 def @@reg_metadata ||= {} end |
Instance Method Details
#_registers ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
All register objects are stored here, but they should be accessed via the _reg method to ensure that feature scoping is applied
125 126 127 |
# File 'lib/origen/registers.rb', line 125 def _registers @_registers ||= RegCollection.new(self) end |
#add_reg(id, address, size = nil, bit_info = {}, &_block) ⇒ Object
Add a register. When adding a register you must supply a name, an address, size in bits, and bit definitions, any bits that are not declared will be filled with dummy bit objects that are not writable and will read back as 0.
add_reg :control, 0x00, 16 :mode => { :pos => 8, :bits => 8 },
# Leaving out bits does 1 by default
:launch => { :pos => 6 },
# The default reset state is 0, specify an alternative..
:status => { :pos => 4, :bits => 2, :res => 0b11 },
:fail => { :pos => 2 },
:done => { :pos => 0 }
Can be called on any object to add a register to it
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/origen/registers.rb', line 308 def add_reg(id, address, size = nil, bit_info = {}, &_block) if address.is_a?(Hash) fail 'add_reg requires the address to be supplied as the 2nd argument, e.g. add_reg :my_reg, 0x1000' end size, bit_info = nil, size if size.is_a?(Hash) size ||= bit_info.delete(:size) || 32 description = bit_info.delete(:description) local_vars = {} Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, | aliases = [attribute[1..-1].to_sym] aliases += [:aliases] if [:aliases] aliases.each { |_a| local_vars[attribute] = bit_info.delete(_a) if bit_info.key?(_a) } end local_vars[:_reset] ||= :memory if local_vars[:_memory] @min_reg_address ||= address @max_reg_address ||= address # Must set an initial value, otherwise max_address_reg_size will be nil if a sub_block contains only # a single register. @max_address_reg_size ||= size @min_reg_address = address if address < @min_reg_address if address > @max_reg_address @max_address_reg_size = size @max_reg_address = address end @reg_define_file ||= define_file(caller[0]) if block_given? @new_reg_attrs = { meta: bit_info } yield self bit_info = @new_reg_attrs else # If no block given then init with all writable bits unless bit_info has # been supplied unless bit_info.any? { |k, v| v.is_a?(Hash) && v[:pos] } bit_info = { d: { pos: 0, bits: size }.merge(bit_info) } end end if _registers[id] && Origen.config.strict_errors puts '' puts "Add register error, you have already added a register named #{id} to #{self.class}" puts '' fail 'Duplicate register error!' else attributes = { define_file: @reg_define_file, address: address, size: size, bit_info: bit_info, description: description } Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, | attributes[attribute] = local_vars[attribute] end _registers[id] = Placeholder.new(self, id, attributes) end @reg_define_file = nil end |
#add_reg32(id, address, args = {}, &block) ⇒ Object
463 464 465 466 |
# File 'lib/origen/registers.rb', line 463 def add_reg32(id, address, args = {}, &block) @reg_define_file = define_file(caller[0]) add_reg(id, address, 32, args, &block) end |
#bit(index, name, attrs = {}) ⇒ Object Also known as: bits
Called within an add_reg block to define bits
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/origen/registers.rb', line 386 def bit(index, name, attrs = {}) if index.is_a?(Range) msb = index.first lsb = index.last msb, lsb = lsb, msb if lsb > msb pos = lsb bits = (msb - lsb).abs + 1 elsif index.is_a?(Numeric) pos = index bits = 1 else fail 'No valid index supplied when defining a register bit!' end # Traynor, this could be more elegant # its just a dirty way to make the value of the # key in @new_reg_atts hash array (ie name) tie to # a value that is an array of hashes describing # data for each scrambled bit attrs = attrs.merge(pos: pos, bits: bits) temparray = [] if @new_reg_attrs[name].nil? @new_reg_attrs[name] = attrs else if @new_reg_attrs[name].is_a? Hash temparray.push(@new_reg_attrs[name]) else temparray = @new_reg_attrs[name] end temparray.push(attrs) # added the sort so that the order the registers bits is described is not important @new_reg_attrs[name] = temparray.sort { |a, b| b[:pos] <=> a[:pos] } end end |
#bit_order ⇒ Object
Returns the bit order attribute of the model (either :msb0 or :lsb0). If not explicitly defined on this model it will be inherited from the parent and will default to :lsb0 at the top-level
33 34 35 36 37 38 39 |
# File 'lib/origen/registers.rb', line 33 def bit_order @bit_order ||= if parent parent.bit_order else :lsb0 end end |
#contains_bits?(obj) ⇒ Boolean
Returns true if the given object is one of the recognized Origen bit containers (bit collection, reg or container).
283 284 285 |
# File 'lib/origen/registers.rb', line 283 def contains_bits?(obj) obj.respond_to?(:contains_bits?) && obj.contains_bits? end |
#default_bit_metadata ⇒ Object Also known as: default_bit_meta_data
437 438 439 440 441 442 443 444 445 |
# File 'lib/origen/registers.rb', line 437 def Origen::Registers.[self.class] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[self.class].merge!(collector.to_h) end Origen::Registers.[self.class] end |
#default_reg_metadata ⇒ Object Also known as: default_reg_meta_data
Can be called to add app specific meta data that is isolated to all registers defined within a given class
426 427 428 429 430 431 432 433 434 |
# File 'lib/origen/registers.rb', line 426 def Origen::Registers.[self.class] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[self.class].merge!(collector.to_h) end Origen::Registers.[self.class] end |
#define_file(file) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
376 377 378 379 380 381 382 383 |
# File 'lib/origen/registers.rb', line 376 def define_file(file) if Origen.running_on_windows? fields = file.split(':') "#{fields[0]}:#{fields[1]}" else file.split(':').first end end |
#del_reg(id) ⇒ Object
Delete an existing register
371 372 373 |
# File 'lib/origen/registers.rb', line 371 def del_reg(id) _registers.delete(id) end |
#delete_registers ⇒ Object
65 66 67 |
# File 'lib/origen/registers.rb', line 65 def delete_registers @_registers = nil end |
#dummy_reg(size = 16) ⇒ Object
Creates a dummy register. Equivalent to Reg.dummy except the reg owner is assigned as the caller rather than Reg. Use this if you need to call read! or write! on the dummy register object.
667 668 669 |
# File 'lib/origen/registers.rb', line 667 def dummy_reg(size = 16) Reg.new(self, 0, size, :dummy, init_as_writable: true) end |
#has_reg?(name, params = {}) ⇒ Boolean Also known as: has_reg
Returns true if the object contains a register matching the given name
491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/origen/registers.rb', line 491 def has_reg?(name, params = {}) params = { test_for_true_false: true }.update(params) if params.key?(:enabled_features) || params.key?(:enabled_feature) !!get_registers(params).include?(name) else params[:enabled_features] = :default !!get_registers(params).include?(name) end end |
#instantiate_reg(id, attrs) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
449 450 451 452 453 454 455 456 457 458 459 460 461 |
# File 'lib/origen/registers.rb', line 449 def instantiate_reg(id, attrs) return _registers[id] unless _registers[id].is_a?(Origen::Registers::Placeholder) attributes = { define_file: attrs[:define_file], description: attrs[:description] } Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, | attributes[attribute] = attrs[attribute] end _registers[id] = Reg.new(self, attrs[:address], attrs[:size], id, attrs[:bit_info].merge(attributes)) end |
#is_a_bit?(obj) ⇒ Boolean
Returns true if the given object is an Origen bit
288 289 290 |
# File 'lib/origen/registers.rb', line 288 def is_a_bit?(obj) obj.is_a?(Origen::Registers::Bit) end |
#max_address_reg_size ⇒ Object
Returns the size (in bits) of the register with the highest address, can be useful in combination with max_reg_address to work out the range of addresses containing registers
481 482 483 |
# File 'lib/origen/registers.rb', line 481 def max_address_reg_size @max_address_reg_size end |
#max_reg_address ⇒ Object
Returns the highest address of all registers that have been added
474 475 476 |
# File 'lib/origen/registers.rb', line 474 def max_reg_address @max_reg_address || 0 end |
#min_reg_address ⇒ Object
Returns the lowest address of all registers that have been added
469 470 471 |
# File 'lib/origen/registers.rb', line 469 def min_reg_address @min_reg_address || 0 end |
#read_register_missing!(reg) ⇒ Object
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
# File 'lib/origen/registers.rb', line 688 def read_register_missing!(reg) klass = (try(:controller) || self).class puts '' puts '' puts <<-EOT You have made a request to read register: #{reg.name}, however the #{klass} class does not know how to do this yet. You should implement a read_register method in the #{klass} like this: def read_register(reg, options={}) <logic to handle reading the reg object here> end EOT puts '' exit 1 end |
#reg(*args, &block) ⇒ Object Also known as: regs
Returns
-the register object matching the given name
-or a hash of all registes matching a given regular expression
-or a hash of all registers, associated with a feature, if no name is specified.
Can also be used to define a new register if a block is supplied in which case it is equivalent to calling add_reg with a block.
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 |
# File 'lib/origen/registers.rb', line 511 def reg(*args, &block) if block_given? || (args[1].is_a?(Integer) && !try(:_initialized?)) @reg_define_file = define_file(caller[0]) add_reg(*args, &block) else # Example use cases: # reg(:reg2) # reg(:name => :reg2) # reg('/reg2/') if !args.empty? && args.size == 1 && (args[0].class != Hash || (args[0].key?(:name) && args[0].size == 1)) if args[0].class == Hash name = args[0][:name] else name = args.first end if has_reg(name) _registers[name] elsif name =~ /\/(.+)\// regex = Regexp.last_match(1) match_registers(regex) else if Origen.config.strict_errors puts '' if regs.empty? puts "#{self.class} does not have a register named #{name} or it is not enabled." else puts "#{self.class} does not have a register named #{name} or it is not enabled." puts 'You may need to add it. This could also be a typo, these are the valid register names:' puts regs.keys end puts '' fail 'Missing register error!' end end # Example use cases: # reg(:enabled_features => :all) # reg(:name => :reg2, enabled_features => :all) # reg(:name => :reg2, enabled_features => :fac) elsif !args.empty? && args.size == 1 && args[0].class == Hash params = args[0] # Example use case: # reg(:name => :reg2, :enabled_features => :all) if (params.key?(:enabled_features) || params.key?(:enabled_feature)) && params.key?(:name) name = params[:name] if has_reg(name, params) _registers[name] else reg_missing_error(params) end # Example use case: # reg(:enabled_features =>[:fac, fac2]) elsif params.size == 1 && params.key?(:enabled_features) get_registers(enabled_features: params[:enabled_features]) end # Example use case: # reg(:reg2, :enabled_features => :all) # reg(:reg2, :enabled_features => :default) # reg(:reg2, :enabled_features => :fac) elsif !args.empty? && args.size == 2 name = args[0] params = args[1] name, params = params, name if name.class == Hash if has_reg(name, params) _registers[name] else reg_missing_error(params) end elsif args.empty? if _registers.empty? _registers else get_registers(enabled_features: :default) end else if Origen.config.strict_errors fail 'Invalid call to reg method or invalid arguments specified' end end end end |
#reset_registers ⇒ Object
Resets all registers
486 487 488 |
# File 'lib/origen/registers.rb', line 486 def reset_registers regs.each { |_name, reg| reg.reset } end |
#respond_to?(sym, include_private = false) ⇒ Boolean
:nodoc:
56 57 58 59 60 61 62 63 |
# File 'lib/origen/registers.rb', line 56 def respond_to?(sym, include_private = false) # :nodoc: if sym[-1] == '!' r = sym.to_s.chop.to_sym _registers.key?(r) || super(sym) else _registers.key?(sym) || super(sym) end end |
#write_register_missing!(reg) ⇒ Object
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
# File 'lib/origen/registers.rb', line 671 def write_register_missing!(reg) klass = (try(:controller) || self).class puts '' puts '' puts <<-EOT You have made a request to write register: #{reg.name}, however the #{klass} class does not know how to do this yet. You should implement a write_register method in the #{klass} like this: def write_register(reg, options={}) <logic to handle the writing of the reg object here> end EOT puts '' exit 1 end |