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/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, 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:
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/origen/registers.rb', line 43 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
86 87 88 |
# File 'lib/origen/registers.rb', line 86 def @@bit_metadata ||= {} end |
.default_bit_meta_data(*args, &block) ⇒ Object
An alias for default_bit_metadata
118 119 120 |
# File 'lib/origen/registers.rb', line 118 def (*args, &block) (*args, &block) end |
.default_bit_metadata ⇒ Object
Can be called to add app specific meta data to all bits
107 108 109 110 111 112 113 114 115 |
# File 'lib/origen/registers.rb', line 107 def Origen::Registers.[:global] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[:global].merge!(collector.store) end Origen::Registers.[:global] end |
.default_reg_meta_data(*args, &block) ⇒ Object
An alias for default_reg_metadata
102 103 104 |
# File 'lib/origen/registers.rb', line 102 def (*args, &block) (*args, &block) end |
.default_reg_metadata ⇒ Object
Can be called to add app specific meta data to all registers
91 92 93 94 95 96 97 98 99 |
# File 'lib/origen/registers.rb', line 91 def Origen::Registers.[:global] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[:global].merge!(collector.store) 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
79 80 81 |
# File 'lib/origen/registers.rb', line 79 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
127 128 129 |
# File 'lib/origen/registers.rb', line 127 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
305 306 307 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 |
# File 'lib/origen/registers.rb', line 305 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] aliases += [:aliases] if [:aliases] aliases.each { |_a| local_vars[attribute] = bit_info.delete(attribute) if bit_info.key?(attribute) } 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 unless @max_address_reg_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
458 459 460 461 |
# File 'lib/origen/registers.rb', line 458 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
382 383 384 385 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 |
# File 'lib/origen/registers.rb', line 382 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 = temparray.push(@new_reg_attrs[name]) else temparray = @new_reg_attrs[name] end temparray = 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 40 41 |
# File 'lib/origen/registers.rb', line 33 def bit_order @bit_order ||= begin if parent parent.bit_order else :lsb0 end 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).
280 281 282 |
# File 'lib/origen/registers.rb', line 280 def contains_bits?(obj) obj.respond_to?(:contains_bits?) && obj.contains_bits? end |
#default_bit_metadata ⇒ Object Also known as: default_bit_meta_data
433 434 435 436 437 438 439 440 441 |
# File 'lib/origen/registers.rb', line 433 def Origen::Registers.[self.class] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[self.class].merge!(collector.store) 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
422 423 424 425 426 427 428 429 430 |
# File 'lib/origen/registers.rb', line 422 def Origen::Registers.[self.class] ||= {} if block_given? collector = Origen::Utility::Collector.new yield collector Origen::Registers.[self.class].merge!(collector.store) 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.
372 373 374 375 376 377 378 379 |
# File 'lib/origen/registers.rb', line 372 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
367 368 369 |
# File 'lib/origen/registers.rb', line 367 def del_reg(id) _registers.delete(id) end |
#delete_registers ⇒ Object
67 68 69 |
# File 'lib/origen/registers.rb', line 67 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.
661 662 663 |
# File 'lib/origen/registers.rb', line 661 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
486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/origen/registers.rb', line 486 def has_reg?(name, params = {}) params = { test_for_true_false: true }.update(params) if params.key?(:enabled_features) || params.key?(:enabled_feature) return !!get_registers(params).include?(name) else params[:enabled_features] = :default return !!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.
445 446 447 448 449 450 451 452 453 454 455 456 |
# File 'lib/origen/registers.rb', line 445 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
285 286 287 |
# File 'lib/origen/registers.rb', line 285 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
476 477 478 |
# File 'lib/origen/registers.rb', line 476 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
469 470 471 |
# File 'lib/origen/registers.rb', line 469 def max_reg_address @max_reg_address || 0 end |
#min_reg_address ⇒ Object
Returns the lowest address of all registers that have been added
464 465 466 |
# File 'lib/origen/registers.rb', line 464 def min_reg_address @min_reg_address || 0 end |
#read_register_missing!(reg) ⇒ Object
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
# File 'lib/origen/registers.rb', line 682 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.
506 507 508 509 510 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 |
# File 'lib/origen/registers.rb', line 506 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) return _registers[name] elsif name =~ /\/(.+)\// regex = Regexp.last_match(1) return 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) return 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? return _registers else return 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
481 482 483 |
# File 'lib/origen/registers.rb', line 481 def reset_registers regs.each { |_name, reg| reg.reset } end |
#respond_to?(sym, include_private = false) ⇒ Boolean
:nodoc:
58 59 60 61 62 63 64 65 |
# File 'lib/origen/registers.rb', line 58 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
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 |
# File 'lib/origen/registers.rb', line 665 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 |