So far we’ve covered SubBlocks, Fuses, Power Domains and other objects. Each of these has its particular use, and its instantiation and customized behavior reflects that, but what about a generic component container?
Origen has one of those too, and it behaves similarly to the aforementioned models. The advantage
is that you can get a
Fuse-like interface without having your
generic components registered as a
Fuse and without any extra overhead. The
disadvantage is that it does nothing else, and functions much like a stripped-down
However, this allows you to add and use generic components that could be anything. These components don’t require a base
address, or any other options (otherwise you’d use a
SubBlock) but will still initialize and be kept
track for you.
For example, if I have a class:
scan_helper, which I’ve implemented as something similar to a
SubBlock, but that doesn’t have a base_address, registers, or anything like that, I can
instantiate it as a component instead:
component(:scan_helper, class_name: ScanHelper) #=> ScanHelper instance with name :scan_helper
I can then get this item as I would a
components[:scan_helper] #=> ScanHelper instance self.scan_helper #=> ScanHelper instance
Seems pretty basic, right? Good! That’s what we’re going for! Below is the API that you can do with components.
You can add components in a few different ways:
# Add a component with default class Origen::Component::Default component(:comp1) # Add another component. Notice the use component(s). components(:comp2) # Add a component of class MyComponent add_component(:mine, class_name: MyComponent) # Method add_components also works, as does using a string as the class name add_components(:also_mine, class_name: 'MyComponent') # Add a component using block notation add_components(:block_add) do |comp| comp.class_name 'MyComponent' end # Add another one using block notation components(:block_add_2) do |c| c.class_name 'MyComponent' end
Now, if we call just
components, we’ll get the resulting Hash storing these. So,
components.keys #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "block_add_2"]
Notice the switch from
"comp1". This is because the underlying
Therefore, you can get components from the Hash using either a
String or a
but when listing, comparing, etc., the keys will be returned as a
You can add multiple instances at once by passing in the
:instances option. This will auto-append an
appendix number to each item.
add_component(:multiple, instances: 4) components.keys #=> ["multiple0", "multiple1", "multiple2", "multiple3"] # In addition, this will make an accessor for each one. So, the following are now defined: multiple0 #=> :multiple0 Component multiple1 #=> :multiple1 Component multiple2 #=> :multiple2 Component multiple3 #=> :multiple3 Component
You can pass other options in as well. Single options will be applied to all instances. A single option being
either not an
Array object, or an
Array object of size 1.
Options that are
Arrays longer than size 1 will be indexed to each instances. For example, if you indicate
four instances of a component, Array index 0 will go to instance 0, Array index index 1 to instance 1, and so on. Providing
an incompatible Array length will result in an
add_component(:multiple, instances: 4, letter: ['A', 'B', 'C', 'D'], number: 0) multiple0 #=> :multiple0 Component with parameters: letter: 'A', number: 0 multiple1 #=> :multiple1 Component with parameters: letter: 'B', number: 0 multiple2 #=> :multiple2 Component with parameters: letter: 'C', number: 0 multiple3 #=> :multiple3 Component with parameters: letter: 'D', number: 0 add_component(:more, instances: 3, letter: ['A', 'B', 'C', 'D'], number: 0) #=> Origen::Componentable::Error
The corner case of wanting a static-sized array given to each instance can be overcome by embedding that Array in
another Array of size 1. For example, the options
instance: 2, cores: [:cm0, :cm3, :cm4] will result in
instance: 2, cores: [[:cm0, :cm3, :cm4]] will be fine
and results in both instances getting the option
cores: [:cm0, :cm3, :cm4].
You can copy and move components using these methods:
copy_component(:comp1, :comp1_copy) # Method copy_components is an alias components.keys #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "block_add_2", "comp1_copy"] move_component(:comp1_copy, :comp1_moved) # Method move_components is an alias components.keys #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "block_add_2", "comp1_moved"]
Note that copying components will actually clone the component. So, you get an independent instance of the object that you copied from.
Listing the components will show you just the names. This is the equivalent of using
list_components #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "block_add_2", "comp1_moved"]
You can check if a component has been added using the
has_component?("comp1") #=> true has_component?(:comp1) #=> true has_component?("comp_dne") #=> false has_component?(:comp_dne) #=> false # component?(name) is an alias method name
You can get components using either the index notation or by utiliting the accessor given
components[:comp1] #=> component at name :comp1 comp1 #=> same as calling components[:comp1]
There’s a method available that can query the current classes of the added components.
components_of_class(MyComponent) #=> ["mine", "also_mine", "block_add"] # components_instances_of and components_of_type are aliases
Component exposes two commonly used enumerable methods:
# All of these call the :each method components.each do |name, component| # do something end each_component do |name, component| # do something end all_components do |name, component| # do something end
select_components do |name, component| # do something end
You can use other enumerable methods provided by the
Hash class by using
You can delete components that you’ve previously added. This will return the deleted item, or raise an exception if the name does not exist.
list_components #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "block_add_2", "comp1_moved"] delete_component("comp1_moved") #=> Component at comp1_moved list_components #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "block_add_2"] # Methods delete_components, remove_component, and remove_components, are all aliases
You can also clear the entire component structure and start fresh. Note this this will not return any components.
list_components #=> ["comp1", "comp2", "mine", "also_mine", "block_add", "comp1_moved"] delete_all_components list_components #=>  # Methods clear_components and remove_all_components are aliases
If you add lots of components, or if you add lots of components, subblocks, fuses, etc., it may get messy having each
one try to put its own accessor on your model. If you find yourself not wanting components to place accessors on your
model, you can define a method
:disable_componentable_accessors(klass) and have it return
klass is of type
Origen::Component. In other words:
def disable_componentable_accessors(klass) if klass == Origen::Component true else false end end
truevalue will result in all
Componentableobjects withholding accessors from your model, including
components. For more details on this, please see the Componentable Guide.
Component is an example of a
Origen::Componentable mixin. For information on using this module
in your own classes to get a component-like interface, please see the topic here