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, Collector, 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.
-
#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 registers, associated with a feature,if no name is specified.
-
#reset_registers ⇒ Object
Resets all registers.
-
#respond_to?(sym) ⇒ 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:
29 30 31 32 33 34 35 |
# File 'lib/origen/registers.rb', line 29 def method_missing(method, *args, &block) # :nodoc: if _registers.key?(method) reg(method) else super 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
60 61 62 |
# File 'lib/origen/registers.rb', line 60 def @@bit_metadata ||= {} end |
.default_bit_meta_data(*args, &block) ⇒ Object
An alias for default_bit_metadata
92 93 94 |
# File 'lib/origen/registers.rb', line 92 def (*args, &block) (*args, &block) end |
.default_bit_metadata ⇒ Object
Can be called to add app specific meta data to all bits
81 82 83 84 85 86 87 88 89 |
# File 'lib/origen/registers.rb', line 81 def Origen::Registers.[:global] ||= {} if block_given? collector = 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
76 77 78 |
# File 'lib/origen/registers.rb', line 76 def (*args, &block) (*args, &block) end |
.default_reg_metadata ⇒ Object
Can be called to add app specific meta data to all registers
65 66 67 68 69 70 71 72 73 |
# File 'lib/origen/registers.rb', line 65 def Origen::Registers.[:global] ||= {} if block_given? collector = 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
53 54 55 |
# File 'lib/origen/registers.rb', line 53 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
101 102 103 |
# File 'lib/origen/registers.rb', line 101 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
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 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 |
# File 'lib/origen/registers.rb', line 287 def add_reg(id, address, size = nil, bit_info = {}, &_block) 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 @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 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
428 429 430 431 |
# File 'lib/origen/registers.rb', line 428 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
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
# File 'lib/origen/registers.rb', line 352 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 |
#contains_bits?(obj) ⇒ Boolean
Returns true if the given object is one of the recognized Origen bit containers (bit collection, reg or container).
262 263 264 |
# File 'lib/origen/registers.rb', line 262 def contains_bits?(obj) obj.respond_to?(:contains_bits?) && obj.contains_bits? end |
#default_bit_metadata ⇒ Object Also known as: default_bit_meta_data
403 404 405 406 407 408 409 410 411 |
# File 'lib/origen/registers.rb', line 403 def Origen::Registers.[self.class] ||= {} if block_given? collector = 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
392 393 394 395 396 397 398 399 400 |
# File 'lib/origen/registers.rb', line 392 def Origen::Registers.[self.class] ||= {} if block_given? collector = 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.
342 343 344 345 346 347 348 349 |
# File 'lib/origen/registers.rb', line 342 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
337 338 339 |
# File 'lib/origen/registers.rb', line 337 def del_reg(id) _registers.delete(id) end |
#delete_registers ⇒ Object
41 42 43 |
# File 'lib/origen/registers.rb', line 41 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.
616 617 618 |
# File 'lib/origen/registers.rb', line 616 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
456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/origen/registers.rb', line 456 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.
415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/origen/registers.rb', line 415 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
267 268 269 |
# File 'lib/origen/registers.rb', line 267 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
446 447 448 |
# File 'lib/origen/registers.rb', line 446 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
439 440 441 |
# File 'lib/origen/registers.rb', line 439 def max_reg_address @max_reg_address || 0 end |
#min_reg_address ⇒ Object
Returns the lowest address of all registers that have been added
434 435 436 |
# File 'lib/origen/registers.rb', line 434 def min_reg_address @min_reg_address || 0 end |
#read_register_missing!(reg) ⇒ Object
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 |
# File 'lib/origen/registers.rb', line 636 def read_register_missing!(reg) puts '' puts '' puts <<-EOT You have made a request to read register: #{reg.name}, however the #{self.class} class does not know how to do this yet. You must implement a read_register method in the #{self.class} 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 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.
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 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 |
# File 'lib/origen/registers.rb', line 474 def reg(*args, &block) if block_given? @reg_define_file = define_file(caller[0]) add_reg(*args, &block) else # Example use cases: # reg(:reg2) # reg(:name => :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] 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
451 452 453 |
# File 'lib/origen/registers.rb', line 451 def reset_registers regs.each { |_name, reg| reg.reset } end |
#respond_to?(sym) ⇒ Boolean
:nodoc:
37 38 39 |
# File 'lib/origen/registers.rb', line 37 def respond_to?(sym) # :nodoc: _registers.key?(sym) || super(sym) end |
#write_register_missing!(reg) ⇒ Object
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/origen/registers.rb', line 620 def write_register_missing!(reg) puts '' puts '' puts <<-EOT You have made a request to write register: #{reg.name}, however the #{self.class} class does not know how to do this yet. You must implement a write_register method in the #{self.class} like this: def write_register(reg, options={}) <logic to handle the writing of the reg object here> end EOT puts '' exit 1 end |