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
-
#changed_bits(options = {}) ⇒ Object
Shows the bits that have changed from the reset value of the register/bits.
- #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
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 |
# File 'lib/origen/registers/reg.rb', line 1290 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).
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 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
# File 'lib/origen/registers/reg.rb', line 859 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.
1409 1410 1411 1412 |
# File 'lib/origen/registers/reg.rb', line 1409 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
569 570 571 |
# File 'lib/origen/registers/reg.rb', line 569 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
1373 1374 1375 |
# File 'lib/origen/registers/reg.rb', line 1373 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
1403 1404 1405 |
# File 'lib/origen/registers/reg.rb', line 1403 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
1385 1386 1387 |
# File 'lib/origen/registers/reg.rb', line 1385 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
1391 1392 1393 |
# File 'lib/origen/registers/reg.rb', line 1391 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
1397 1398 1399 |
# File 'lib/origen/registers/reg.rb', line 1397 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
984 985 986 987 988 989 990 991 992 993 994 |
# File 'lib/origen/registers/reg.rb', line 984 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.
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 |
# File 'lib/origen/registers/reg.rb', line 510 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
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 |
# File 'lib/origen/registers/reg.rb', line 997 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
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 |
# File 'lib/origen/registers/reg.rb', line 1021 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 # rubocop:disable Lint/Void end end |
#bind(bitname, live_parameter) ⇒ Object
126 127 128 129 130 131 132 133 |
# 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
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 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 |
# File 'lib/origen/registers/reg.rb', line 1091 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
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
# File 'lib/origen/registers/reg.rb', line 389 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 |
#changed_bits(options = {}) ⇒ Object
Shows the bits that have changed from the reset value of the register/bits. Currently logs it to the console window using Origen logger.
582 583 584 585 586 587 588 |
# File 'lib/origen/registers/reg.rb', line 582 def changed_bits( = {}) temp = named_bits.select { |name, bits| bits.data != bits.reset_val } temp.each do |r| Origen.log.info "\t\t#{self.name}.#{r[0]} : #{r[1].value.to_hex}".bold.blue end Origen.log.info ' ' end |
#contains_bits? ⇒ Boolean
505 506 507 |
# File 'lib/origen/registers/reg.rb', line 505 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
1357 1358 1359 1360 1361 1362 1363 1364 |
# File 'lib/origen/registers/reg.rb', line 1357 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
1348 1349 1350 1351 1352 1353 |
# File 'lib/origen/registers/reg.rb', line 1348 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
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 |
# File 'lib/origen/registers/reg.rb', line 1328 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.
383 384 385 386 387 |
# File 'lib/origen/registers/reg.rb', line 383 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
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 |
# File 'lib/origen/registers/reg.rb', line 1052 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)
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 474 475 |
# File 'lib/origen/registers/reg.rb', line 442 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.
375 376 377 |
# File 'lib/origen/registers/reg.rb', line 375 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]
795 796 797 798 799 |
# File 'lib/origen/registers/reg.rb', line 795 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
802 803 804 |
# File 'lib/origen/registers/reg.rb', line 802 def empty_bits?( = {}) empty_bits.size > 0 end |
#enabled? ⇒ Boolean
Query the owner heirarchy to see if this register is enabled
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 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 |
# File 'lib/origen/registers/reg.rb', line 1457 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 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 value end else 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
1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 |
# File 'lib/origen/registers/reg.rb', line 1438 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 false else feature == name end end end |
#escape_special_char(str) ⇒ Object
Escapes brackets and parenthesis. Helper for description method.
433 434 435 |
# File 'lib/origen/registers/reg.rb', line 433 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.
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 |
# File 'lib/origen/registers/reg.rb', line 1065 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
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 |
# File 'lib/origen/registers/reg.rb', line 1276 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 params[:enabled_features] || params[:enabled_feature] end end |
#extract_meta_data(method, *args) ⇒ Object
1428 1429 1430 1431 1432 1433 1434 1435 |
# File 'lib/origen/registers/reg.rb', line 1428 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.
422 423 424 425 426 427 428 429 430 |
# File 'lib/origen/registers/reg.rb', line 422 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
1164 1165 1166 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 |
# File 'lib/origen/registers/reg.rb', line 1164 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 Bit.new(self, number, writable: false) end end |
#get_lookup_feature_bits(bit_name, params, split_group_reg) ⇒ Object
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 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 |
# File 'lib/origen/registers/reg.rb', line 1194 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 BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name][:pos]) else [] 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) BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name][0][:pos]) else BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name[:pos]]) end else [] 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
974 975 976 |
# File 'lib/origen/registers/reg.rb', line 974 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.
1524 1525 1526 1527 1528 1529 1530 |
# File 'lib/origen/registers/reg.rb', line 1524 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
135 136 137 |
# File 'lib/origen/registers/reg.rb', line 135 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.
553 554 555 556 557 558 559 560 |
# File 'lib/origen/registers/reg.rb', line 553 def initialize_copy(orig) # :nodoc: @bits = [] orig.bits.each do |bit| @bits << bit.clone end @lookup = orig.lookup.clone self end |
#inspect(options = {}) ⇒ Object
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 370 |
# File 'lib/origen/registers/reg.rb', line 151 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.
836 837 838 839 840 841 842 843 844 845 846 847 |
# File 'lib/origen/registers/reg.rb', line 836 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.
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 |
# File 'lib/origen/registers/reg.rb', line 1415 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,
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 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 |
# File 'lib/origen/registers/reg.rb', line 574 def named_bits( = {}) = { include_spacers: false }.merge() result = [] # Shows the bits that have changed from the reset value of the register/bits. # Currently logs it to the console window using Origen logger. def changed_bits( = {}) temp = named_bits.select { |name, bits| bits.data != bits.reset_val } temp.each do |r| Origen.log.info "\t\t#{self.name}.#{r[0]} : #{r[1].value.to_hex}".bold.blue end Origen.log.info ' ' end # 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)
851 852 853 |
# File 'lib/origen/registers/reg.rb', line 851 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.
956 957 958 959 960 961 962 963 964 965 966 |
# File 'lib/origen/registers/reg.rb', line 956 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.
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 |
# File 'lib/origen/registers/reg.rb', line 479 def parse_descriptions desc = [] unless File.exist?(define_file) return desc end 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
831 832 833 |
# File 'lib/origen/registers/reg.rb', line 831 def reader @reader ||= lookup_operation_handler(:read_register) end |
#request(operation, options = {}) ⇒ Object
Proxies requests from bit collections to the register owner
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 |
# File 'lib/origen/registers/reg.rb', line 807 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 if tester && tester.respond_to?(operation) tester.send(operation, self, ) do object.send(operation, self, ) end else object.send(operation, self, ) end self end |
#respond_to?(*args) ⇒ Boolean
Recognize that Reg responds to all BitCollection methods methods based on application-specific meta data properties
1317 1318 1319 1320 |
# File 'lib/origen/registers/reg.rb', line 1317 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
731 732 733 734 735 736 737 |
# File 'lib/origen/registers/reg.rb', line 731 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
1311 1312 1313 |
# File 'lib/origen/registers/reg.rb', line 1311 def to_bit_collection( = {}) BitCollection.new(self, name, @bits, ) end |
#to_json(*args) ⇒ Object
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 |
# File 'lib/origen/registers/reg.rb', line 1532 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
139 140 141 142 143 144 145 |
# File 'lib/origen/registers/reg.rb', line 139 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
147 148 149 |
# File 'lib/origen/registers/reg.rb', line 147 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]
758 759 760 761 762 763 764 765 766 767 768 769 |
# File 'lib/origen/registers/reg.rb', line 758 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
772 773 774 |
# File 'lib/origen/registers/reg.rb', line 772 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
826 827 828 |
# File 'lib/origen/registers/reg.rb', line 826 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
1379 1380 1381 |
# File 'lib/origen/registers/reg.rb', line 1379 def |(val) data | Reg.clean_value(val) end |