Class: Origen::Registers::Reg
- Includes:
- SubBlocks::Domains, SubBlocks::Path
- Defined in:
- lib/origen/registers/reg.rb
Overview
The register class can be used to represent not only h/ware resgisters, but really any entity which has an address and data component, such as a specific RAM location.
Any registers instantiated through Origen::Registers#add_reg are instances of this class.
All methods in BitCollection can also be called on a Reg object.
Constant Summary collapse
- REG_LEVEL_ATTRIBUTES =
These attributes can be defined on a register at definition time and will get applied to all of its contained bits unless a specific bit has its own definition of the same attribute
{ _feature: {}, _reset: { aliases: [:res] }, _memory: {}, _path: { aliases: [:hdl_path] }, _abs_path: { aliases: [:absolute_path] }, _access: {}, _bit_order: {} }
Instance Attribute Summary collapse
-
#address(options = {}) ⇒ Object
(also: #addr)
Returns the register address added to its current base_address value (if any).
-
#base_address ⇒ Object
The base address of the register, this will be set dynamically by Origen based on the parent’s base address.
-
#define_file ⇒ Object
readonly
Returns a full path to the file in which the register was defined.
-
#feature ⇒ Object
Any feature associated with the register.
-
#grows_backwards ⇒ Object
:nodoc:.
-
#lookup ⇒ Object
:nodoc:.
-
#memory ⇒ Object
If the given register’s reset data is backed by memory, the memory address can be recorded in this attribute.
-
#meta ⇒ Object
(also: #meta_data, #metadata)
Returns any application-specific meta-data attatched to the given register.
-
#name ⇒ Object
The register name.
-
#owner ⇒ Object
(also: #parent)
readonly
Returns the object that own the register.
-
#size ⇒ Object
readonly
Returns an integer representing the number of bits in the register.
Class Method Summary collapse
-
.clean_value(value) ⇒ Object
Cleans an input value, in some cases it could be a register object, or an explicit value.
-
.dummy(size = 16) ⇒ Object
Returns a dummy register object that can be used on the fly, this can sometimes be useful to configure an intricate read operation.
Instance Method Summary collapse
-
#&(val) ⇒ Object
Returns the BITWISE AND of reg with another reg or a number, the state of both registers remains unchanged ==== Example reg(:data).write(0x5555) reg(:data2).write(0xFFFF) reg(:data) & 0xFF00 # => 0x5500 reg(:data) & reg(:data2) # => 0x5555.
-
#*(val) ⇒ Object
Returns the PRODUCT of reg with another reg or a number, the state of both registers remains unchanged.
-
#+(val) ⇒ Object
Returns the SUM of reg with another reg or a number, the state of both registers remains unchanged.
-
#-(val) ⇒ Object
Returns the SUBTRACTION of reg with another reg or a number, the state of both registers remains unchanged.
-
#/(val) ⇒ Object
Returns the DIVISION of reg with another reg or a number, the state of both registers remains unchanged.
-
#add_bit(id, position, options = {}) ⇒ Object
Add a bit to the register, should only be called internally.
- #add_bits_from_options(options = {}) ⇒ Object private
-
#add_bus(id, position, size, options = {}) ⇒ Object
Add a bus to the register, should only be called internally.
- #add_bus_scramble(id, array_of_hashes = []) ⇒ Object
- #bind(bitname, live_parameter) ⇒ Object
-
#bit(*args) ⇒ Object
(also: #bits, #[])
Returns the bit object(s) responding to the given name, wrapped in a BitCollection.
-
#bit_order ⇒ Object
Returns the bit order attribute of the register (either :msb0 or :lsb0).
- #bit_value_descriptions(bitname, options = {}) ⇒ Object
- #contains_bits? ⇒ Boolean
-
#copy(reg) ⇒ Object
Copies data and overlays from one reg object to another, it does not copy read or store flags.
-
#copy_data_from(reg) ⇒ Object
Copies data from one reg object to another ==== Example reg(:data_copy).data # => 0 reg(:data).write(0x1234) reg(:data_copy).copy_data_from(reg(:data)) reg(:data_copy).data # => 0x1234.
-
#copy_overlays_from(reg, options = {}) ⇒ Object
Copy overlays from one reg object to another ==== Example reg(:data_copy).has_overlay? # => false reg(:data).overlay(“data_val”) reg(:data_copy).copy_overlays_from(reg(:data)) reg(:data_copy).has_overlay? # => true.
-
#default_reg_metadata ⇒ Object
Returns any application specific metadata that has been inherited by the given register.
-
#delete_bit(collection) ⇒ Object
(also: #delete_bits)
Delete the bits in the collection from the register.
-
#description(bitname = :_reg, options = {}) ⇒ Object
(also: #descriptions)
Returns the description of this register if any, if none then an empty array will be returned.
-
#description_lookup ⇒ Object
private
Returns a hash containing all register descriptions that have been parsed so far.
-
#empty_bits(_options = {}) ⇒ Object
Returns an array of unoccupied bit positions ==== Example reg :fstat, @base + 0x0000, :size => 8 do bit 7, :ccif bit 6, :rdcolerr bit 5, :accerr bit 4, :pviol bit 0, :mgstat0 end regs(:fstat).empty_bits => [1, 2, 3].
-
#empty_bits?(_options = {}) ⇒ Boolean
Returns true if any named_bits exist, false if used_bits is an empty array.
-
#enabled? ⇒ Boolean
Query the owner heirarchy to see if this register is enabled.
-
#enabled_by_feature?(name = nil) ⇒ Boolean
(also: #has_feature_constraint?)
Returns true if the register is constrained by the given/any feature.
-
#escape_special_char(str) ⇒ Object
Escapes brackets and parenthesis.
- #expand_range(range, wbo = :lsb0) ⇒ Object private
- #extract_feature_params(args) ⇒ Object
- #extract_meta_data(method, *args) ⇒ Object
- #freeze ⇒ Object
-
#full_name(bitname = :_reg, _options = {}) ⇒ Object
Returns the full name of the register when this has been specified in the register description like this:.
- #get_bits_with_constraint(number, params, options = {}) ⇒ Object
- #get_lookup_feature_bits(bit_name, params, split_group_reg) ⇒ Object
-
#has_bit?(name) ⇒ Boolean
(also: #has_bits?, #has_bit, #has_bits)
Returns true if the register contains a bit(s) matching the given name ==== Example add_reg :control, 0x55, :status => => 1.
-
#has_bits_enabled_by_feature?(name = nil) ⇒ Boolean
Returns true if any of the bits within this register has feature associated with it.
- #has_parameter_bound_bits? ⇒ Boolean
-
#initialize(owner, address, size, name, options = {}) ⇒ Reg
constructor
Normally shouldn’t be called directly, instantiate through add_reg Upon initialization bits are stored as follows: An array of bit objects in position order, @bits corresponds to the bit as position r A Hash lookup table for quickly accessing bit objects by name.
-
#initialize_copy(orig) ⇒ Object
This method is called whenever reg.clone is called to make a copy of a given register.
- #inspect(options = {}) ⇒ Object
- #lookup_operation_handler(operation) ⇒ Object private
- #meta_data_method?(method) ⇒ Boolean private
-
#method_missing(method, *args, &block) ⇒ Object
All other Reg methods are delegated to BitCollection.
-
#named_bits(options = {}) ⇒ Object
Returns each named bit collection contained in the register,.
-
#offset ⇒ Object
Returns the relative address of the given register, equivalent to calling reg.address(:relative => true).
-
#owned_by?(name) ⇒ Boolean
Returns true if the register owner matches the given name.
- #parse_descriptions ⇒ Object private
-
#reader ⇒ Object
Returns the object that will be responsible for reading the given register.
-
#request(operation, options = {}) ⇒ Object
Proxies requests from bit collections to the register owner.
-
#respond_to?(*args) ⇒ Boolean
Recognize that Reg responds to all BitCollection methods methods based on application-specific meta data properties.
-
#reverse_named_bits(_options = {}) ⇒ Object
Returns each named bit collection contained in self.
- #to_bit_collection(options = {}) ⇒ Object
- #to_json(*args) ⇒ Object
- #update_bound_bits ⇒ Object
- #updating_bound_bits? ⇒ Boolean
-
#used_bits(_options = {}) ⇒ Object
Returns an array of occupied bit positions ==== Example reg :fstat, @base + 0x0000, :size => 8 do bit 7, :ccif bit 6, :rdcolerr bit 5, :accerr bit 4, :pviol bit 0, :mgstat0 end regs(:fstat).used_bits => [0, 4, 5, 6, 7].
-
#used_bits?(_options = {}) ⇒ Boolean
Returns true if any named_bits exist, false if used_bits is an empty array.
- #with_lsb0 ⇒ Object
- #with_msb0 ⇒ Object
-
#writer ⇒ Object
Returns the object that will be responsible for writing the given register.
-
#|(val) ⇒ Object
Returns the BITWISE OR of reg with another reg or a number, the state of both registers remains unchanged.
Methods included from SubBlocks::Domains
#domain, #domain_specified?, #domains
Methods included from SubBlocks::Path
#abs_path, #abs_path=, #path, #path=, #path_var
Constructor Details
#initialize(owner, address, size, name, options = {}) ⇒ Reg
Normally shouldn’t be called directly, instantiate through add_reg Upon initialization bits are stored as follows: An array of bit objects in position order, @bits corresponds to the bit as position r A Hash lookup table for quickly accessing bit objects by name
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/origen/registers/reg.rb', line 63 def initialize(owner, address, size, name, = {}) # :nodoc: @owner = owner @address = address @size = size @bits = [] @lookup = {} @name = name @init_as_writable = .delete(:init_as_writable) @define_file = .delete(:define_file) @from_placeholder = .delete(:from_placeholder) || false REG_LEVEL_ATTRIBUTES.each do |attribute, | if @from_placeholder instance_variable_set("@#{attribute[1..-1]}", .delete(attribute)) else # If register creation is coming directly from Reg.new, instead of Placeholder, # it may not have attributes with '_' prefix instance_variable_set("@#{attribute[1..-1]}", .delete(attribute[1..-1].to_sym)) end end @description_from_api = {} description = .delete(:description) if description @description_from_api[:_reg] = description.split(/\r?\n/) end @meta = .merge(.delete(:meta) || {}) # Initialize with unwritable bits that read back as zero, can override this # to make all writable by default by setting the :init_writable option to true @size.times do |n| @bits << Bit.new(self, n, writable: @init_as_writable, undefined: true) end # Internally re-map msb0 register descriptions as lsb0 .each_value { |bit_desc| bit_desc[:pos] = @size - bit_desc[:pos] - bit_desc[:bits] } if bit_order == :msb0 () @msb0_delegator = Msb0Delegator.new(self, @bits) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
All other Reg methods are delegated to BitCollection
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 |
# File 'lib/origen/registers/reg.rb', line 1265 def method_missing(method, *args, &block) # :nodoc: wbo = :lsb0 if args.last.is_a?(Hash) wbo = args.last[:with_bit_order] if args.last.key?(:with_bit_order) end if method.to_sym == :to_ary || method.to_sym == :to_hash nil elsif (method) (method, *args) else if BitCollection.instance_methods.include?(method) to_bit_collection(with_bit_order: wbo).send(method, *args, &block) elsif has_bits?(method) bits(method, with_bit_order: wbo) else super end end end |
Instance Attribute Details
#address(options = {}) ⇒ Object Also known as: addr
Returns the register address added to its current base_address value (if any).
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
# File 'lib/origen/registers/reg.rb', line 837 def address( = {}) = { relative: false }.merge() address = @address domain_option = [:domains] || [:domain] @domain_option ||= domain_option unless frozen? # Blow the cache when the domain option changes @base_address_applied = nil unless @domain_option == domain_option unless @base_address_applied # Give highest priority to the original API which allowed the object # doing register read/write to define a base_address method if (writer && writer.methods.include?(:base_address) && writer.method(:base_address).arity != 0) || (reader && reader.methods.include?(:base_address) && reader.method(:base_address).arity != 0) # This currently assumes that the base address is always the same # for reading and writing if writer && writer.respond_to?(:base_address) && writer.method(:base_address).arity != 0 self.base_address = writer.base_address(self) elsif reader && reader.respond_to?(:base_address) && reader.method(:base_address).arity != 0 self.base_address = reader.base_address(self) end else o = owner.is_a?(Container) ? owner.owner : owner d = domain_option || domains if o && o.reg_base_address(domain: d) self.base_address = o.reg_base_address(domain: d) end end @base_address_applied = true end unless [:relative] address += base_address if base_address end if [:address_type] Origen.deprecate 'Specifying the address_type of a register address will be removed from Origen 3' case [:address_type] when :byte address = address * 2 when :word address = address when :longword address = address / 2 else fail 'Unknown address type requested!' end end address end |
#base_address ⇒ Object
The base address of the register, this will be set dynamically by Origen based on the parent’s base address
34 35 36 |
# File 'lib/origen/registers/reg.rb', line 34 def base_address @base_address end |
#define_file ⇒ Object (readonly)
Returns a full path to the file in which the register was defined
46 47 48 |
# File 'lib/origen/registers/reg.rb', line 46 def define_file @define_file end |
#feature ⇒ Object
Any feature associated with the register
41 42 43 |
# File 'lib/origen/registers/reg.rb', line 41 def feature @feature end |
#grows_backwards ⇒ Object
:nodoc:
43 44 45 |
# File 'lib/origen/registers/reg.rb', line 43 def grows_backwards @grows_backwards end |
#lookup ⇒ Object
:nodoc:
44 45 46 |
# File 'lib/origen/registers/reg.rb', line 44 def lookup @lookup end |
#memory ⇒ Object
If the given register’s reset data is backed by memory, the memory address can be recorded in this attribute
53 54 55 |
# File 'lib/origen/registers/reg.rb', line 53 def memory @memory end |
#meta ⇒ Object Also known as: meta_data, metadata
Returns any application-specific meta-data attatched to the given register
48 49 50 |
# File 'lib/origen/registers/reg.rb', line 48 def @meta end |
#name ⇒ Object
The register name
39 40 41 |
# File 'lib/origen/registers/reg.rb', line 39 def name @name end |
#owner ⇒ Object (readonly) Also known as: parent
Returns the object that own the register.
Example
$soc.reg(:blah).owner # Returns the $soc object
30 31 32 |
# File 'lib/origen/registers/reg.rb', line 30 def owner @owner end |
#size ⇒ Object (readonly)
Returns an integer representing the number of bits in the register
37 38 39 |
# File 'lib/origen/registers/reg.rb', line 37 def size @size end |
Class Method Details
.clean_value(value) ⇒ Object
Cleans an input value, in some cases it could be a register object, or an explicit value. This will return an explicit value in either case.
1384 1385 1386 1387 |
# File 'lib/origen/registers/reg.rb', line 1384 def self.clean_value(value) # :nodoc: value = value.val if value.respond_to?('val') # Pull out the data value if a reg object has been passed in value end |
.dummy(size = 16) ⇒ Object
Returns a dummy register object that can be used on the fly, this can sometimes be useful to configure an intricate read operation.
Example
# Read bit 5 of RAM address 0xFFFF1280
dummy = Reg.dummy # Create a dummy reg to configure the read operation
dummy.address = 0xFFFF1280 # Set the address
dummy.bit(5).read!(1) # Read bit 5 expecting a 1
563 564 565 |
# File 'lib/origen/registers/reg.rb', line 563 def self.dummy(size = 16) Reg.new(self, 0, size, :dummy, init_as_writable: true) end |
Instance Method Details
#&(val) ⇒ Object
Returns the BITWISE AND of reg with another reg or a number, the state of both registers remains unchanged
Example
reg(:data).write(0x5555)
reg(:data2).write(0xFFFF)
reg(:data) & 0xFF00 # => 0x5500
reg(:data) & reg(:data2) # => 0x5555
1348 1349 1350 |
# File 'lib/origen/registers/reg.rb', line 1348 def &(val) data & Reg.clean_value(val) end |
#*(val) ⇒ Object
Returns the PRODUCT of reg with another reg or a number, the state of both registers remains unchanged
1378 1379 1380 |
# File 'lib/origen/registers/reg.rb', line 1378 def *(val) data * Reg.clean_value(val) end |
#+(val) ⇒ Object
Returns the SUM of reg with another reg or a number, the state of both registers remains unchanged
1360 1361 1362 |
# File 'lib/origen/registers/reg.rb', line 1360 def +(val) data + Reg.clean_value(val) end |
#-(val) ⇒ Object
Returns the SUBTRACTION of reg with another reg or a number, the state of both registers remains unchanged
1366 1367 1368 |
# File 'lib/origen/registers/reg.rb', line 1366 def -(val) data - Reg.clean_value(val) end |
#/(val) ⇒ Object
Returns the DIVISION of reg with another reg or a number, the state of both registers remains unchanged
1372 1373 1374 |
# File 'lib/origen/registers/reg.rb', line 1372 def /(val) data / Reg.clean_value(val) end |
#add_bit(id, position, options = {}) ⇒ Object
Add a bit to the register, should only be called internally
960 961 962 963 964 965 966 967 968 969 970 |
# File 'lib/origen/registers/reg.rb', line 960 def add_bit(id, position, = {}) # :nodoc: = { data: @bits[position].data, # If undefined preserve any data/reset value that has res: @bits[position].data, # already been applied at reg level }.merge() @lookup[id] = { pos: position, bits: 1, feature: [:feature] } @bits.delete_at(position) # Remove the initial bit from this position @bits.insert(position, Bit.new(self, position, )) self end |
#add_bits_from_options(options = {}) ⇒ 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.
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 |
# File 'lib/origen/registers/reg.rb', line 504 def ( = {}) # :nodoc: # options is now an array for split bit groups or a hash if single bit/range bits # Now add the requested bits to the register, removing the unwritable bits as required .each do |bit_id, bit_params| if bit_params.is_a? Hash description = bit_params.delete(:description) if description @description_from_api[bit_id] = description.split(/\r?\n/) end bind(bit_id, bit_params.delete(:bind)) if bit_params[:bind] position = bit_params[:pos] || 0 num_bits = bit_params[:bits] || 1 if @reset if @reset.is_a?(Symbol) bit_params[:res] = @reset else bit_params[:res] = @reset[(num_bits + position - 1), position] end end bit_params[:access] = @access if bit_params[:access].nil? bit_params[:res] = bit_params[:data] if bit_params[:data] bit_params[:res] = bit_params[:reset] if bit_params[:reset] if num_bits == 1 add_bit(bit_id, position, bit_params) # and add the new one else add_bus(bit_id, position, num_bits, bit_params) end elsif bit_params.is_a? Array description = bit_params.map { |h| h.delete(:description) }.compact.join("\n") unless description.empty? @description_from_api[bit_id] = description.split(/\r?\n/) end add_bus_scramble(bit_id, bit_params) end end self end |
#add_bus(id, position, size, options = {}) ⇒ Object
Add a bus to the register, should only be called internally
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 |
# File 'lib/origen/registers/reg.rb', line 973 def add_bus(id, position, size, = {}) # :nodoc: default_data = 0 size.times do |n| default_data |= @bits[position + n].data << n end = { data: default_data, # If undefined preserve any data/reset value that has res: default_data, # already been applied at reg level }.merge() @lookup[id] = { pos: position, bits: size } size.times do |n| = .dup [:data] = [:data][n] if [:res].is_a?(Symbol) [:res] = [:res] else [:res] = [:res][n] end @bits.delete_at(position + n) @bits.insert(position + n, Bit.new(self, position + n, )) end self end |
#add_bus_scramble(id, array_of_hashes = []) ⇒ Object
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 |
# File 'lib/origen/registers/reg.rb', line 997 def add_bus_scramble(id, array_of_hashes = []) array_of_hashes.each do || bind(id, .delete(:bind)) if [:bind] position = [:pos] || 0 num_bits = [:bits] || 1 size = [:bits] [:data] = [:data] if [:data] [:res] = [:reset] if [:reset] default_data = 0 size.times do |n| default_data |= @bits[position + n].data << n end = { data: default_data, # If undefined preserve any data/reset value that has res: default_data, # already been applied at reg level }.merge() @lookup[id] = [] if @lookup[id].nil? @lookup[id] = @lookup[id].push(pos: position, bits: size) size.times do |n| = .dup [:data] = [:data][n] [:res] = [:res][n] @bits.delete_at(position + n) @bits.insert(position + n, Bit.new(self, position + n, )) end self end end |
#bind(bitname, live_parameter) ⇒ Object
126 127 128 129 130 131 132 |
# File 'lib/origen/registers/reg.rb', line 126 def bind(bitname, live_parameter) unless live_parameter.respond_to?(:is_a_live_parameter?) && live_parameter.is_a_live_parameter? fail 'Only live updating parameters should be bound, make sure you have not missed .live in the path to the parameter!' end @parameter_bound_bits ||= {} @parameter_bound_bits[bitname] = live_parameter end |
#bit(*args) ⇒ Object Also known as: bits, []
Returns the bit object(s) responding to the given name, wrapped in a BitCollection. This method also accepts multiple name possibilities, if neither bit exists in the register it will raise an error, otherwise it will return the first match. If no args passed in, it will return a BitCollection containing all bits. If a number is passed in then the bits from those positions are returned.
Example
add_reg :control, 0x55, :status => {:pos => 1, :bits => 2},
:fail => {:pos => 0}
reg(:control).bit(:fail) # => Returns a BitCollection containing the fail bit
reg(:control).bits(:status) # => Returns a BifCollection containing the status bits
reg(:control).bit(:bist_fail, :fail) # => Returns a BitCollection containing the fail bit
reg(:control).bit(0) # => Returns a BitCollection containing the fail bit
reg(:control).bit(1) # => Returns a BitCollection containing status bit
reg(:control).bit(1,2) # => Returns a BitCollection containing both status bits
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 |
# File 'lib/origen/registers/reg.rb', line 1066 def bit(*args) # allow msb0 bit numbering if requested wbo = :lsb0 if args.last.is_a?(Hash) wbo = args.last.delete(:with_bit_order) || :lsb0 args.pop if args.last.size == 0 end multi_bit_names = false # return get_bits_with_constraint(nil,:default) if args.size == 0 constraint = extract_feature_params(args) if constraint.nil? constraint = :default end collection = BitCollection.new(self, :unknown, [], with_bit_order: wbo) if args.size == 0 collection.add_name(name) @bits.each do |bit| collection << get_bits_with_constraint(bit.position, constraint) end else args.flatten! args.sort! args.reverse! if wbo == :msb0 args.each do |arg_item| if arg_item.is_a?(Integer) b = get_bits_with_constraint(arg_item, constraint, with_bit_order: wbo) collection << b if b elsif arg_item.is_a?(Range) (arg_item, wbo) do |bit_number| collection << get_bits_with_constraint(bit_number, constraint, with_bit_order: wbo) end else multi_bit_names = args.size > 1 # Reaches here if bit name is specified if @lookup.include?(arg_item) split_bits = false @lookup.each { |_k, v| split_bits = true if v.is_a? Array } coll = get_lookup_feature_bits(arg_item, constraint, split_bits) if coll coll.each do |b| collection.add_name(arg_item) collection << b end end end end end end if collection.size == 0 # Originally Origen returned nil when asking for a bit via an index which does not # exist, e.g. reg[1000] => nil # The args numeric clause here is to maintain that behavior if Origen.config.strict_errors && !args.all? { |arg| arg.is_a?(Numeric) } puts "Register #{@name} does not have a bits(s) named :#{args.join(', :')} or it might not be enabled." puts 'This could also be a typo, these are the valid bit names:' puts @lookup.keys fail 'Missing bits error!' end nil else if multi_bit_names collection.sort_by!(&:position) wbo == :msb0 ? collection.with_msb0 : collection.with_lsb0 end wbo == :msb0 ? collection.with_msb0 : collection.with_lsb0 end end |
#bit_order ⇒ Object
Returns the bit order attribute of the register (either :msb0 or :lsb0). If not explicitly defined on this register it will be inherited from the parent and will default to :lsb0 at the top-level
114 115 116 |
# File 'lib/origen/registers/reg.rb', line 114 def bit_order @bit_order ||= parent.respond_to?(:bit_order) ? parent.bit_order : :lsb0 end |
#bit_value_descriptions(bitname, options = {}) ⇒ Object
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
# File 'lib/origen/registers/reg.rb', line 387 def bit_value_descriptions(bitname, = {}) = { format: :binary }.merge() base = case [:format] when :bin, :binary 2 when :hex, :hexadecimal 16 when :dec, :decimal 10 else fail "Unknown integer format: #{[:format]}" end desc = {} description(bitname).each do |line| if line =~ /^\s*(\d+)\s+\|\s+(.+)/ desc[Regexp.last_match[1].to_i(base)] = Regexp.last_match[2] end end desc end |
#contains_bits? ⇒ Boolean
499 500 501 |
# File 'lib/origen/registers/reg.rb', line 499 def contains_bits? true end |
#copy(reg) ⇒ Object
Copies data and overlays from one reg object to another, it does not copy read or store flags
1332 1333 1334 1335 1336 1337 1338 1339 |
# File 'lib/origen/registers/reg.rb', line 1332 def copy(reg) size.times do |i| source_bit = reg.bit[i] @bits[i].(source_bit.) if source_bit. @bits[i].write(source_bit.data) end self end |
#copy_data_from(reg) ⇒ Object
Copies data from one reg object to another
Example
reg(:data_copy).data # => 0
reg(:data).write(0x1234)
reg(:data_copy).copy_data_from(reg(:data))
reg(:data_copy).data # => 0x1234
1323 1324 1325 1326 1327 1328 |
# File 'lib/origen/registers/reg.rb', line 1323 def copy_data_from(reg) size.times do |i| @bits[i].write(reg.bit[i].data) end self end |
#copy_overlays_from(reg, options = {}) ⇒ Object
Copy overlays from one reg object to another
Example
reg(:data_copy). # => false
reg(:data).("data_val")
reg(:data_copy).(reg(:data))
reg(:data_copy). # => true
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 |
# File 'lib/origen/registers/reg.rb', line 1303 def (reg, = {}) size.times do |i| source_bit = reg.bit[i] if source_bit. ov = source_bit. # If an id has been supplied make sure any trailing ID in the source is # changed to supplied identifier ov.gsub!(/_\d$/, "_#{[:update_id]}") if [:update_id] @bits[i].(ov) end end self end |
#default_reg_metadata ⇒ Object
Returns any application specific metadata that has been inherited by the given register. This does not account for any overridding that may have been applied to this register specifically however, use the meta method to get that.
382 383 384 385 |
# File 'lib/origen/registers/reg.rb', line 382 def Origen::Registers..merge( Origen::Registers.[owner.class] || {}) end |
#delete_bit(collection) ⇒ Object Also known as: delete_bits
Delete the bits in the collection from the register
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 |
# File 'lib/origen/registers/reg.rb', line 1027 def delete_bit(collection) [collection.name].flatten.each do |name| @lookup.delete(name) end collection.each do |bit| @bits.delete_at(bit.position) # Remove the bit @bits.insert(bit.position, Bit.new(self, bit.position, writable: @init_as_writable)) end self end |
#description(bitname = :_reg, options = {}) ⇒ Object Also known as: descriptions
Returns the description of this register if any, if none then an empty array will be returned
Note Adding a description field will override any comment-driven documentation of a register (ie markdown style comments)
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/origen/registers/reg.rb', line 440 def description(bitname = :_reg, = {}) bitname, = :_reg, bitname if bitname.is_a?(Hash) = { include_name: true, include_bit_values: true }.merge() if @description_from_api[bitname] desc = @description_from_api[bitname] else parse_descriptions unless description_lookup[define_file] begin desc = description_lookup[define_file][name][bitname] || [] rescue desc = [] end end desc = desc.reject do |line| if bitname != :_reg unless [:include_bit_values] !!(line =~ /^\s*(\d+)\s+\|\s+(.+)/) end else false end end if desc.first unless [:include_name] desc[0] = desc.first.sub(/\s*\*\*\s*#{escape_special_char(full_name(bitname))}\s*\*\*\s*-?\s*/, '') end end desc.shift while desc.first && desc.first.strip.empty? desc.pop while desc.last && desc.last.strip.empty? desc end |
#description_lookup ⇒ 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 hash containing all register descriptions that have been parsed so far.
374 375 376 |
# File 'lib/origen/registers/reg.rb', line 374 def description_lookup @@description_lookup ||= {} end |
#empty_bits(_options = {}) ⇒ Object
Returns an array of unoccupied bit positions
Example
reg :fstat, @base + 0x0000, :size => 8 do
bit 7, :ccif
bit 6, :rdcolerr
bit 5, :accerr
bit 4, :pviol
bit 0, :mgstat0
end
regs(:fstat).empty_bits
=> [1, 2, 3]
Example
reg :aguahb2, @base + 0x2A, :size => 8 do
bit 5..2, :m0b_hbstrb, :reset => 0x0
bit 1..0, :m0b_htrans, :reset => 0x2
end
regs(:aguahb2).empty_bits
=> [6, 7]
779 780 781 782 783 |
# File 'lib/origen/registers/reg.rb', line 779 def empty_bits( = {}) array_span = (0..(size - 1)).to_a empty_bits = array_span - used_bits empty_bits end |
#empty_bits?(_options = {}) ⇒ Boolean
Returns true if any named_bits exist, false if used_bits is an empty array
786 787 788 |
# File 'lib/origen/registers/reg.rb', line 786 def empty_bits?( = {}) empty_bits.size > 0 end |
#enabled? ⇒ Boolean
Query the owner heirarchy to see if this register is enabled
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 |
# File 'lib/origen/registers/reg.rb', line 1432 def enabled? if feature value = false current_owner = self if feature.class == Array feature.each do |f| current_owner = self loop do if current_owner.respond_to?(:owner) current_owner = current_owner.owner if current_owner.respond_to?(:has_feature?) if current_owner.has_feature?(f) value = true break end end else # if current owner does not have a owner value = false break end end # loop end unless value if Origen.top_level && \ Origen.top_level.respond_to?(:has_feature?) && \ Origen.top_level.has_feature?(f) value = true unless value break end end end unless value break # break if feature not found and return false end end # iterated through all features in array return value else # if feature.class != Array loop do if current_owner.respond_to?(:owner) current_owner = current_owner.owner if current_owner.respond_to?(:has_feature?) if current_owner.has_feature?(feature) value = true break end end else # if current owner does not have a owner value = false break end end # loop end unless value if Origen.top_level && \ Origen.top_level.respond_to?(:has_feature?) && \ Origen.top_level.has_feature?(feature) value = true end end return value end else return true end end |
#enabled_by_feature?(name = nil) ⇒ Boolean Also known as: has_feature_constraint?
Returns true if the register is constrained by the given/any feature
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 |
# File 'lib/origen/registers/reg.rb', line 1413 def enabled_by_feature?(name = nil) if !name !!feature else if feature.class == Array feature.each do |f| if f == name return true end end return false else return feature == name end end end |
#escape_special_char(str) ⇒ Object
Escapes brackets and parenthesis. Helper for description method.
431 432 433 |
# File 'lib/origen/registers/reg.rb', line 431 def escape_special_char(str) str.gsub('[', '\[').gsub(']', '\]').gsub('(', '\(').gsub(')', '\)') if str end |
#expand_range(range, wbo = :lsb0) ⇒ 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.
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
# File 'lib/origen/registers/reg.rb', line 1040 def (range, wbo = :lsb0) if range.first > range.last range = Range.new(range.last, range.first) end range = range.to_a range.reverse! if wbo == :msb0 range.each do |i| yield i end end |
#extract_feature_params(args) ⇒ Object
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 |
# File 'lib/origen/registers/reg.rb', line 1249 def extract_feature_params(args) index = args.find_index { |arg| arg.class == Hash } if index params = args.delete_at(index) else params = nil end if params return params[:enabled_features] || params[:enabled_feature] else return nil end end |
#extract_meta_data(method, *args) ⇒ Object
1403 1404 1405 1406 1407 1408 1409 1410 |
# File 'lib/origen/registers/reg.rb', line 1403 def (method, *args) method = method.to_s.sub('?', '') if method =~ /=/ instance_variable_set("@#{method.sub('=', '')}", args.first) else instance_variable_get("@#{method}") || [method.to_sym] end end |
#freeze ⇒ Object
118 119 120 121 122 123 124 |
# File 'lib/origen/registers/reg.rb', line 118 def freeze bits.each(&:freeze) # Call any methods which cache results to generate the instance variables # before they are frozen address super end |
#full_name(bitname = :_reg, _options = {}) ⇒ Object
Returns the full name of the register when this has been specified in the register description like this:
# ** This is the Register Full Name **
# This register blah blah
This method will also be called by bit collections to look up the name when defined in a similar manner in the bit description.
If no name has been specified this will return nil.
420 421 422 423 424 425 426 427 428 |
# File 'lib/origen/registers/reg.rb', line 420 def full_name(bitname = :_reg, = {}) bitname, = :_reg, bitname if bitname.is_a?(Hash) desc = description(bitname).first # Capture something like this: # ** This is the full name ** - This bit blah blah if desc && desc =~ /\s*\*\*\s*([^\*.]*)\s*\*\*/ Regexp.last_match[1].strip end end |
#get_bits_with_constraint(number, params, options = {}) ⇒ Object
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 |
# File 'lib/origen/registers/reg.rb', line 1139 def get_bits_with_constraint(number, params, = {}) = { with_bit_order: :lsb0 }.merge() # remap to lsb0 number to grab correct bit if [:with_bit_order] == :msb0 number = size - number - 1 end return nil unless @bits[number] if (params == :default || !params) && @bits[number].enabled? @bits[number] elsif params == :none && !@bits[number].has_feature_constraint? @bits[number] elsif params == :all @bits[number] elsif params.class == Array params.each do |param| unless @bits[number].enabled_by_feature?(param) return nil end @bits[number] end elsif @bits[number].enabled_by_feature?(params) @bits[number] else return Bit.new(self, number, writable: false) end end |
#get_lookup_feature_bits(bit_name, params, split_group_reg) ⇒ Object
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
# File 'lib/origen/registers/reg.rb', line 1167 def get_lookup_feature_bits(bit_name, params, split_group_reg) ## if split_group_reg == false # if this register has single bits and continuous ranges if @lookup.include?(bit_name) collection = BitCollection.new(self, bit_name) (@lookup[bit_name][:bits]).times do |i| collection << @bits[@lookup[bit_name][:pos] + i] end if !params || params == :default if collection.enabled? return collection end elsif params == :none unless collection.has_feature_constraint? return collection end elsif params == :all return collection elsif params.class == Array if params.all? { |param| collection.enabled_by_feature?(param) } return collection end else if collection.enabled_by_feature?(params) return collection end end return BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name][:pos]) else return [] end elsif split_group_reg == true # if this registers has split bits in its range if @lookup.is_a?(Hash) # && @lookup.include?(bit_name) collection = false @lookup.each do |k, v| # k is the bitname, v is the hash of bit data if k == bit_name collection ||= BitCollection.new(self, k) if v.is_a?(Array) v.reverse_each do |pb| # loop each piece of bit group data (pb[:bits]).times do |i| collection << @bits[pb[:pos] + i] end end else (v[:bits]).times do |i| collection << @bits[v[:pos] + i] end end end end if !params || params == :default if collection.enabled? return collection end elsif params == :none unless collection.has_feature_constraint? return collection end elsif params == :all return collection elsif params.class == Array if params.all? { |param| collection.enabled_by_feature?(param) } return collection end else if collection.enabled_by_feature?(params) return collection end end if @lookup.is_a?(Hash) && @lookup[bit_name].is_a?(Array) return BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name][0][:pos]) else return BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name[:pos]]) end else return [] end end end |
#has_bit?(name) ⇒ Boolean Also known as: has_bits?, has_bit, has_bits
Returns true if the register contains a bit(s) matching the given name
Example
add_reg :control, 0x55, :status => {:pos => 1}
reg(:control).has_bit?(:result) # => false
reg(:control).has_bit?(:status) # => true
952 953 954 |
# File 'lib/origen/registers/reg.rb', line 952 def has_bit?(name) @lookup.include?(name) end |
#has_bits_enabled_by_feature?(name = nil) ⇒ Boolean
Returns true if any of the bits within this register has feature associated with it.
1499 1500 1501 1502 1503 1504 1505 |
# File 'lib/origen/registers/reg.rb', line 1499 def has_bits_enabled_by_feature?(name = nil) if !name bits.any?(&:has_feature_constraint?) else bits.any? { |bit| bit.enabled_by_feature?(name) } end end |
#has_parameter_bound_bits? ⇒ Boolean
134 135 136 |
# File 'lib/origen/registers/reg.rb', line 134 def has_parameter_bound_bits? @parameter_bound_bits && !@parameter_bound_bits.empty? end |
#initialize_copy(orig) ⇒ Object
This method is called whenever reg.clone is called to make a copy of a given register. Ruby will correctly copy all instance variables but it will not drill down to copy nested attributes, like the bits contained in @bits. This function will therefore correctly clone all bits contained in the register also.
547 548 549 550 551 552 553 554 |
# File 'lib/origen/registers/reg.rb', line 547 def initialize_copy(orig) # :nodoc: @bits = [] orig.bits.each do |bit| @bits << bit.clone end @lookup = orig.lookup.clone self end |
#inspect(options = {}) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 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 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 369 |
# File 'lib/origen/registers/reg.rb', line 150 def inspect( = {}) wbo = [:with_bit_order] || :lsb0 domsb0 = wbo == :msb0 dolsb0 = !domsb0 if wbo != bit_order Origen.log.warn "Register displayed with #{wbo} numbering, but defined with #{bit_order} numbering" Origen.log.warn 'Access (and display) this register with explicit numbering like this:' Origen.log.warn '' Origen.log.warn " reg(:#{name}).with_msb0 # bit numbering scheme is msb0" Origen.log.warn " reg(:#{name}).with_lsb0 # bit numbering scheme is lsb0 (default)" Origen.log.warn " reg(:#{name}) # bit numbering scheme is lsb0 (default)" end # This fancy_output option is passed in via option hash # Even better, the output could auto-detect 7-bit vs 8-bit terminal output and adjust the parameter, but that's for another day fancy_output = [:fancy_output].nil? ? true : [:fancy_output] if fancy_output horiz_double_line = '═' horiz_double_tee_down = '╤' horiz_double_tee_up = '╧' corner_double_up_left = '╒' corner_double_up_right = '╕' horiz_single_line = '─' horiz_single_tee_down = '┬' horiz_single_tee_up = '┴' horiz_single_cross = '┼' horiz_double_cross = '╪' corner_single_down_left = '└' corner_single_down_right = '┘' vert_single_line = '│' vert_single_tee_left = '┤' vert_single_tee_right = '├' else horiz_double_line = '=' horiz_double_tee_down = '=' horiz_double_tee_up = '=' corner_double_up_left = '.' corner_double_up_right = '.' horiz_single_line = '-' horiz_single_tee_down = '-' horiz_single_tee_up = '-' horiz_single_cross = '+' horiz_double_cross = '=' corner_single_down_left = '`' corner_single_down_right = '\'' vert_single_line = '|' vert_single_tee_left = '<' vert_single_tee_right = '>' end bit_width = 13 desc = ["\n0x%X - :#{name}" % address] r = size % 8 if r == 0 # || (size > 8 && domsb0) desc << (' ' + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * 8)).chop + corner_double_up_right else desc << (' ' + (' ' * (bit_width + 1) * (8 - r)) + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * r)).chop + corner_double_up_right end # "<#{self.class}: #{self.name}>" num_bytes = (size / 8.0).ceil num_bytes.times do |byte_index| # Need to add support for little endian regs here? byte_number = num_bytes - byte_index max_bit = (byte_number * 8) - 1 min_bit = max_bit - 8 + 1 # BIT INDEX ROW line = ' ' line_complete = false 8.times do |i| bit_num = (byte_number * 8) - i - 1 if bit_num > size - 1 line << ' ' + ''.center(bit_width) unless line_complete else if dolsb0 line << vert_single_line + "#{bit_num}".center(bit_width) else line << vert_single_line + "#{size - bit_num - 1}".center(bit_width) end end end line += vert_single_line unless line_complete desc << line # BIT NAME ROW line = ' ' first_done = false line_complete = false named_bits include_spacers: true do |name, bit, bitcounter| if _bit_in_range?(bit, max_bit, min_bit) if max_bit > (size - 1) && !first_done (max_bit - (size - 1)).times do line << ' ' * (bit_width + 1) end end if bit.size > 1 if name if bitcounter.nil? bit_name = "#{name}[#{_max_bit_in_range(bit, max_bit, min_bit, )}:#{_min_bit_in_range(bit, max_bit, min_bit, )}]" bit_span = _num_bits_in_range(bit, max_bit, min_bit) else upper = _max_bit_in_range(bit, max_bit, min_bit, ) + bitcounter - bit.size lower = _min_bit_in_range(bit, max_bit, min_bit, ) + bitcounter - bit.size if dolsb0 bit_name = "#{name}[#{upper}:#{lower}]" else bit_name = "#{name}[#{upper}:#{lower}]" end bit_span = upper - lower + 1 end width = (bit_width * bit_span) + bit_span - 1 if bit_name.length > width line << vert_single_line + "#{bit_name[0..width - 2]}*" else line << vert_single_line + bit_name.center(width) end else bit.shift_out_left do |bit| if _index_in_range?(bit.position, max_bit, min_bit) line << vert_single_line + ''.center(bit_width) end end end else if name bit_name = "#{name}" if bit_name.length > bit_width txt = "#{bit_name[0..bit_width - 2]}*" else txt = bit_name end else txt = '' end line << vert_single_line + txt.center(bit_width) end end first_done = true end line += vert_single_line desc << line # BIT STATE ROW line = ' ' first_done = false named_bits include_spacers: true do |name, bit, _bitcounter| if _bit_in_range?(bit, max_bit, min_bit) if max_bit > (size - 1) && !first_done (max_bit - (size - 1)).times do line << ' ' * (bit_width + 1) end end if bit.size > 1 if name if bit.has_known_value? value = '0x%X' % bit.val[_max_bit_in_range(bit, max_bit, min_bit).._min_bit_in_range(bit, max_bit, min_bit)] else if bit.reset_val == :undefined value = 'X' else value = 'M' end end value += _state_desc(bit) bit_span = _num_bits_in_range(bit, max_bit, min_bit) width = bit_width * bit_span line << vert_single_line + value.center(width + bit_span - 1) else bit.shift_out_left do |bit| if _index_in_range?(bit.position, max_bit, min_bit) line << vert_single_line + ''.center(bit_width) end end end else if name if bit.has_known_value? val = bit.val else if bit.reset_val == :undefined val = 'X' else val = 'M' end end value = "#{val}" + _state_desc(bit) line << vert_single_line + value.center(bit_width) else line << vert_single_line + ''.center(bit_width) end end end first_done = true end line += vert_single_line desc << line if size >= 8 r = size % 8 if byte_index == 0 && r != 0 desc << (' ' + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * (8 - r)).chop + horiz_double_cross + (horiz_single_line * (bit_width + 1) * r)).chop + vert_single_tee_left else if byte_index == num_bytes - 1 desc << (' ' + corner_single_down_left + ((horiz_single_line * bit_width + horiz_single_tee_up) * 8)).chop + corner_single_down_right else desc << (' ' + vert_single_tee_right + ((horiz_single_line * bit_width + horiz_single_cross) * 8)).chop + vert_single_tee_left end end else desc << (' ' + (' ' * (bit_width + 1) * (8 - size)) + corner_single_down_left + ((horiz_single_line * bit_width + horiz_single_tee_up) * size)).chop + corner_single_down_right end end desc.join("\n") end |
#lookup_operation_handler(operation) ⇒ 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.
814 815 816 817 818 819 820 821 822 823 824 825 |
# File 'lib/origen/registers/reg.rb', line 814 def lookup_operation_handler(operation) # Could have made the controller be the owner when assigned above, but may have run # into problems with the reg meta data stuff reg_owner = owner.respond_to?(:controller) && owner.controller ? owner.controller : owner if reg_owner.respond_to?(operation) reg_owner elsif reg_owner.respond_to?(:owner) && reg_owner.owner.respond_to?(operation) reg_owner.owner elsif Origen.top_level && Origen.top_level.respond_to?(operation) Origen.top_level end end |
#meta_data_method?(method) ⇒ Boolean
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.
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 |
# File 'lib/origen/registers/reg.rb', line 1390 def (method) attr_name = method.to_s.gsub(/\??=?/, '').to_sym if .key?(attr_name) if method.to_s =~ /\?/ [true, false].include?([attr_name]) else true end else false end end |
#named_bits(options = {}) ⇒ Object
Returns each named bit collection contained in the register,
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 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 |
# File 'lib/origen/registers/reg.rb', line 568 def named_bits( = {}) = { include_spacers: false }.merge() result = [] # test if @lookup has any values stored as an array # if so it means there is a split group of bits # process that differently to a single bit or continuous range of bits # which are typically stored in a hash split_bits = false @lookup.each { |_k, v| split_bits = true if v.is_a? Array } if split_bits == false current_pos = size # Sort by position @lookup.sort_by { |_name, details| -details[:pos] }.each do |name, details| pos = details[:bits] + details[:pos] if [:include_spacers] && (pos != current_pos) collection = BitCollection.dummy(self, nil, size: current_pos - pos, pos: pos) unless collection.size == 0 if block_given? yield nil, collection else result << [nil, collection] end end end collection = BitCollection.new(self, name) details[:bits].times do |i| collection << @bits[details[:pos] + i] end unless collection.size == 0 if block_given? yield name, collection else result << [name, collection] end end current_pos = details[:pos] end if [:include_spacers] && (current_pos != 0) collection = BitCollection.dummy(self, nil, size: current_pos, pos: 0) unless collection.size == 0 if block_given? yield nil, collection else result << [nil, collection] end end end elsif split_bits == true # if there are split bits, need to convert all register bit values to array elements to allow sorting # if the register has bits split up across it, then store the bits in order of decreasing reg position # but first, stuff all the bits in a simple array, as single bits, or ranges of bits @lookup_splits = [] @lookup.each do |k, v| tempbit = {} bitcounter = {} if v.is_a? Hash # then this is already a single bit or a continuous range so just stuff it into the array tempbit[k] = v @lookup_splits << tempbit.clone elsif v.is_a? Array # if the bitgroup is split, then decompose into single bits and continuous ranges v.each_with_index do |bitdetail, _i| if bitcounter.key?(k) bitcounter[k] = bitcounter[k] + bitdetail[:bits] else bitcounter[k] = bitdetail[:bits] end tempbit[k] = bitdetail @lookup_splits << tempbit.clone end end if v.is_a? Array @lookup_splits.each_with_index do |_e, q| groupname = @lookup_splits[q].to_a[0][0] if groupname == k @lookup_splits[q][groupname][:bitgrouppos] = bitcounter[groupname] if groupname == k bitcounter[groupname] = bitcounter[groupname] - @lookup_splits[q][groupname][:bits] end end end end # Now sort the array in descending order # Does adding the bitgrouppos need to happen after the sort ? @lookup_splits = @lookup_splits.sort do |a, b| b.to_a[0][1][:pos] <=> a.to_a[0][1][:pos] end current_pos = size countbits = {} # if countbits.method == nil @master = {} bitgroup = {} bitinfo = {} info = {} @lookup_splits.each_with_index do |hash, _i| name = hash.to_a[0][0] details = hash.to_a[0][1] bitcounter = hash.to_a[0][1][:bitgrouppos] pos = details[:bits] + details[:pos] if [:include_spacers] && (pos != current_pos) collection = BitCollection.dummy(self, nil, size: current_pos - pos, pos: pos) unless collection.size == 0 if block_given? yield nil, collection, bitcounter else result << [nil, collection, bitcounter] end end end collection = BitCollection.new(self, name) details[:bits].times do |i| collection << @bits[details[:pos] + i] end unless collection.size == 0 if block_given? yield name, collection, bitcounter else result << [name, collection, bitcounter] end end current_pos = details[:pos] end if [:include_spacers] && current_pos != 0 collection = BitCollection.dummy(self, nil, size: current_pos, pos: 0) unless collection.size == 0 if block_given? yield nil, collection, bitcounter else result << [nil, collection, bitcounter] end end end end unless block_given? result end end |
#offset ⇒ Object
Returns the relative address of the given register, equivalent to calling reg.address(:relative => true)
829 830 831 |
# File 'lib/origen/registers/reg.rb', line 829 def offset address(relative: true) end |
#owned_by?(name) ⇒ Boolean
Returns true if the register owner matches the given name. A match will be detected if the class names of the register’s owner contains the given name.
Alternatively if the register owner implements a method called reg_owner_alias then the value that this returns instead will also be considered when checking if the given name matches. This method can return an array of names if multiple aliases are required.
Aliases can be useful for de-coupling the commonly used name, e.g. “NVM” from the actual class name.
934 935 936 937 938 939 940 941 942 943 944 |
# File 'lib/origen/registers/reg.rb', line 934 def owned_by?(name) !!(owner.class.to_s =~ /#{name}/i) || begin if owner.respond_to?(:reg_owner_alias) [owner.reg_owner_alias].flatten.any? do |al| al.to_s =~ /#{name}/i end else false end end end |
#parse_descriptions ⇒ 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.
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
# File 'lib/origen/registers/reg.rb', line 477 def parse_descriptions desc = [] File.readlines(define_file).each do |line| if line =~ /^\s*#(.*)/ desc << Regexp.last_match[1].strip # http://rubular.com/r/D8lg2P5kK1 http://rubular.com/r/XP4ydPV8Fd elsif line =~ /^\s*reg\(?\s*[:"'](\w+)["']?\s*,.*\sdo/ || line =~ /^\s*.*add_reg\(?\s*[:"'](\w+)["']?\s*,.*/ @current_reg_name = Regexp.last_match[1].to_sym description_lookup[define_file] ||= {} description_lookup[define_file][@current_reg_name] ||= {} description_lookup[define_file][@current_reg_name][:_reg] = desc.dup desc = [] # http://www.rubular.com/r/7FidbC1JRA elsif @current_reg_name && line =~ /^\s*(add_bit|bit|reg\.bit)s?\(?\s*\d+\.?\.?\d*\s*,\s*:(\w+)/ description_lookup[define_file][@current_reg_name][Regexp.last_match[2].to_sym] = desc.dup desc = [] else desc = [] end end end |
#reader ⇒ Object
Returns the object that will be responsible for reading the given register
809 810 811 |
# File 'lib/origen/registers/reg.rb', line 809 def reader @reader ||= lookup_operation_handler(:read_register) end |
#request(operation, options = {}) ⇒ Object
Proxies requests from bit collections to the register owner
791 792 793 794 795 796 797 798 799 800 801 |
# File 'lib/origen/registers/reg.rb', line 791 def request(operation, = {}) # :nodoc: if operation == :read_register object = reader (Origen.top_level || owner).read_register_missing!(self) unless object else object = writer (Origen.top_level || owner).write_register_missing!(self) unless object end object.send(operation, self, ) self end |
#respond_to?(*args) ⇒ Boolean
Recognize that Reg responds to all BitCollection methods methods based on application-specific meta data properties
1292 1293 1294 1295 |
# File 'lib/origen/registers/reg.rb', line 1292 def respond_to?(*args) # :nodoc: sym = args.first.to_sym (sym) || has_bits?(sym) || super(sym) || BitCollection.instance_methods.include?(sym) end |
#reverse_named_bits(_options = {}) ⇒ Object
Returns each named bit collection contained in self
715 716 717 718 719 720 721 |
# File 'lib/origen/registers/reg.rb', line 715 def reverse_named_bits( = {}) bits = [] named_bits { |name, bit| bits << [name, bit] } bits.each do |bit| yield bit[0], bit[1] end end |
#to_bit_collection(options = {}) ⇒ Object
1286 1287 1288 |
# File 'lib/origen/registers/reg.rb', line 1286 def to_bit_collection( = {}) BitCollection.new(self, name, @bits, ) end |
#to_json(*args) ⇒ Object
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 |
# File 'lib/origen/registers/reg.rb', line 1507 def to_json(*args) JSON.pretty_generate({ name: name, full_name: full_name, address: address, offset: offset, size: size, path: path, reset_value: reset_value, description: description(include_name: false, include_bit_values: false), bits: named_bits.map do |name, bit| { name: name, full_name: bit.full_name, position: bit.position, size: bit.size, reset_value: bit.reset_value, access: bit.access, description: bit.description(include_name: false, include_bit_values: false), bit_values: bit.bit_value_descriptions.map do |val, desc| { value: val, description: desc } end } end }, *args) end |
#update_bound_bits ⇒ Object
138 139 140 141 142 143 144 |
# File 'lib/origen/registers/reg.rb', line 138 def update_bound_bits @updating_bound_bits = true @parameter_bound_bits.each do |name, val| bits(name).write(val) end @updating_bound_bits = false end |
#updating_bound_bits? ⇒ Boolean
146 147 148 |
# File 'lib/origen/registers/reg.rb', line 146 def updating_bound_bits? @updating_bound_bits end |
#used_bits(_options = {}) ⇒ Object
Returns an array of occupied bit positions
Example
reg :fstat, @base + 0x0000, :size => 8 do
bit 7, :ccif
bit 6, :rdcolerr
bit 5, :accerr
bit 4, :pviol
bit 0, :mgstat0
end
regs(:fstat).used_bits
=> [0, 4, 5, 6, 7]
Example
reg :aguahb2, @base + 0x2A, :size => 8 do
bit 5..2, :m0b_hbstrb, :reset => 0x0
bit 1..0, :m0b_htrans, :reset => 0x2
end
regs(:aguahb2).used_bits
=> [0, 1, 2, 3, 4, 5]
742 743 744 745 746 747 748 749 750 751 752 753 |
# File 'lib/origen/registers/reg.rb', line 742 def used_bits( = {}) used_bits = [] named_bits do |_name, bit| used_bits << bit.position if bit.size == 1 if bit.size > 1 used_bits << ((bit.position)..(bit.position + bit.size - 1)).to_a end end used_bits.flatten! used_bits.sort! used_bits end |
#used_bits?(_options = {}) ⇒ Boolean
Returns true if any named_bits exist, false if used_bits is an empty array
756 757 758 |
# File 'lib/origen/registers/reg.rb', line 756 def used_bits?( = {}) used_bits.size > 0 end |
#with_lsb0 ⇒ Object
107 108 109 |
# File 'lib/origen/registers/reg.rb', line 107 def with_lsb0 self end |
#with_msb0 ⇒ Object
103 104 105 |
# File 'lib/origen/registers/reg.rb', line 103 def with_msb0 @msb0_delegator end |
#writer ⇒ Object
Returns the object that will be responsible for writing the given register
804 805 806 |
# File 'lib/origen/registers/reg.rb', line 804 def writer @writer ||= lookup_operation_handler(:write_register) end |
#|(val) ⇒ Object
Returns the BITWISE OR of reg with another reg or a number, the state of both registers remains unchanged
1354 1355 1356 |
# File 'lib/origen/registers/reg.rb', line 1354 def |(val) data | Reg.clean_value(val) end |