class HDLRuby::High::SystemT
Describes a high-level system type.
Constants
- High
High-level libraries for describing digital hardware.
Attributes
The instantiation target class.
The public namespace
NOTE: the private namespace is the namespace of the scope object.
Public Class Methods
Creates a new high-level system type named name
and inheriting from mixins
.
# If
name is hash, it is considered the system is unnamed and the # table is used to rename its signals or instances.
The proc ruby_block
is executed when instantiating the system.
HDLRuby::Low::SystemT::new
# File lib/HDLRuby/hruby_high.rb, line 328 def initialize(name, *mixins, &ruby_block) # Initialize the system type structure. super(name,Scope.new(name,self)) # Initialize the set of extensions to transmit to the instances' # eigen class @singleton_instanceO = Namespace.new(self.scope) # Create the public namespace. @public_namespace = Namespace.new(self.scope) # Initialize the list of tasks to execute on the instance. @on_instances = [] # Check and set the mixins. mixins.each do |mixin| unless mixin.is_a?(SystemT) then raise AnyError, "Invalid class for inheriting: #{mixin.class}." end end @to_includes = mixins # The list of systems the current system is expanded from if any. # The first one is the main system, the other ones are the # mixins. @generators = [] # Prepare the instantiation methods make_instantiater(name,SystemI,&ruby_block) end
Public Instance Methods
Adds a generator system.
# File lib/HDLRuby/hruby_high.rb, line 482 def add_generator(gen) unless gen.is_a?(SystemT) then raise "Invalid class for a generator system" end @generators << gen end
Casts as an included system
.
NOTE: use the includes of the scope.
# File lib/HDLRuby/hruby_high.rb, line 725 def as(system) # return self.scope.as(system.scope) return self.scope.as(system) end
Iterates over the exported constructs
NOTE: look into the scope.
# File lib/HDLRuby/hruby_high.rb, line 477 def each_export(&ruby_block) @scope.each_export(&ruby_block) end
Iterates over the origin systems.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_high.rb, line 492 def each_generator(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_generator) unless ruby_block # A block? Apply it on each generator. @generators.each(&ruby_block) end
Iterates over the instance procedures.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_high.rb, line 538 def each_instance_proc(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_instance_proc) unless ruby_block # A block? Apply it on each input signal instance. @instance_procs.each(&ruby_block) end
Iterate over the task to apply on the instances of the system.
# File lib/HDLRuby/hruby_high.rb, line 600 def each_on_instance(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_on_instance) unless ruby_block # A block? Apply it on each overload if any. @on_instances.each(&ruby_block) end
Iterates over the all interface signals, i.e, also the ones of the included systems.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_high.rb, line 457 def each_signal_with_included(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_signal_with_included) unless ruby_block # Iterate on the signals of the current system. self.each_signal(&ruby_block) # Recurse on the included systems. self.scope.each_included do |included| included.each_signal_with_included(&ruby_block) end end
Make a system eigen of a given instance
.
# File lib/HDLRuby/hruby_high.rb, line 566 def eigenize(instance) unless instance.systemT == self then raise "Cannot eigenize system #{self.name} to instance #{instance.name}" end # The instance becames the owner. @owner = instance # Fill the public namespace space = self.public_namespace # Interface signals # puts "i_name=#{i_name} @to_includes=#{@to_includes.size}" self.each_signal do |signal| # puts "signal=#{signal.name}" space.send(:define_singleton_method,signal.name) do RefObject.new(instance.to_ref,signal) end end # Exported objects self.each_export do |export| # puts "export=#{export.name}" space.send(:define_singleton_method,export.name) do RefObject.new(instance.to_ref,export) end end return self end
Expands the system with possible arugments args
to a new system named name
.
# File lib/HDLRuby/hruby_high.rb, line 547 def expand(name, *args) # puts "expand #{self.name} to #{name}" # Create the new system. expanded = self.class.new(name.to_s) {} # Include the mixin systems given when declaring the system. @to_includes.each { |system| expanded.scope.include(system) } # Sets the generators of the expanded result. expanded.add_generator(self) @to_includes.each { |system| expanded.add_generator(system) } # Fills the scope of the expanded class. # puts "Build top with #{self.name} for #{name}" expanded.scope.build_top(self.scope,*args) # puts "Top built with #{self.name} for #{name}" return expanded end
Extend the class according to another system
.
# File lib/HDLRuby/hruby_high.rb, line 715 def extend(system) # Adds the singleton methods self.eigen_extend(system) # Adds the singleton methods for the instances. @singleton_instanceO.eigen_extend(system.singleton_instance) end
Fills the interface of a low level system.
# File lib/HDLRuby/hruby_high.rb, line 733 def fill_interface(systemTlow) # Adds its input signals. self.each_input { |input| systemTlow.add_input(input.to_low) } # Adds its output signals. self.each_output { |output| systemTlow.add_output(output.to_low) } # Adds its inout signals. self.each_inout { |inout| systemTlow.add_inout(inout.to_low) } # Adds the interface of its included systems. self.scope.each_included do |included| included.fill_interface(systemTlow) end end
Fills a low level system with self's contents.
NOTE: name conflicts are treated in the current NameStack state.
# File lib/HDLRuby/hruby_high.rb, line 749 def fill_low(systemTlow) # Fills the interface self.fill_interface(systemTlow) end
Get one of all the interface signal by index, i.e., also the ones of the included systems.
# File lib/HDLRuby/hruby_high.rb, line 470 def get_interface_with_included(i) return each_signal_with_included.to_a[i] end
Gets an output signal by name
considering also the included systems
# File lib/HDLRuby/hruby_high.rb, line 440 def get_output_with_included(name) # Look in self. found = self.get_output(name) return found if found # Not in self, look in the included systems. self.scope.each_included do |included| found = included.get_output_with_included(name) return found if found end # Not found return nil end
Declares high-level bit inout signals named names
.
Retuns the last declared input.
# File lib/HDLRuby/hruby_high.rb, line 710 def inout(*names) self.make_inouts(bit,*names) end
Declares high-level bit input signals named names
.
Retuns the last declared input.
# File lib/HDLRuby/hruby_high.rb, line 696 def input(*names) self.make_inputs(bit,*names) end
Instantiate the system type to an instance named i_name
with possible arguments args
.
# File lib/HDLRuby/hruby_high.rb, line 610 def instantiate(i_name,*args) # Create the eigen type. # eigen = self.expand(High.names_create(i_name.to_s + ":T"), *args) eigen = self.expand(HDLRuby.uniq_name(i_name.to_s + ":T"), *args) # Create the instance and sets its eigen system to +eigen+. instance = @instance_class.new(i_name,eigen) eigen.eigenize(instance) # puts "instance interface=#{instance.each_signal.to_a.size}" # puts "eigen interface=#{eigen.each_signal.to_a.size}" # Extend the instance. instance.eigen_extend(@singleton_instanceO) # puts "instance scope= #{instance.systemT.scope}" # Add the instance if instantiating within another system. High.top_user.send(:add_systemI,instance) if High.top_user # Execute the post instantiation tasks. eigen.each_on_instance { |task| task.(instance) } # Return the resulting instance return instance end
Creates and adds a set of inouts typed type
from a list of names
.
NOTE: a name can also be a signal, is which case it is duplicated.
# File lib/HDLRuby/hruby_high.rb, line 419 def make_inouts(type, *names) res = nil names.each do |name| if name.respond_to?(:to_sym) then res = self.add_inout(SignalI.new(name,type,:inout)) elsif name.is_a?(Hash) then # Names associated with values. names.each do |name,value| res = self.add_inner( SignalI.new(name,type,:inner,value)) end else raise AnyError, "Invalid class for a name: #{name.class}" end end return res end
Creates and adds a set of inputs typed type
from a list of names
.
NOTE: a name can also be a signal, is which case it is duplicated.
# File lib/HDLRuby/hruby_high.rb, line 369 def make_inputs(type, *names) # Check if called within the top scope of the block. if High.top_user != @scope then # No, cannot make an input from here. raise AnyError, "Input signals can only be declared in the top scope of a system." end res = nil names.each do |name| if name.respond_to?(:to_sym) then res = self.add_input(SignalI.new(name,type,:input)) elsif name.is_a?(Hash) then # Names associated with values. names.each do |name,value| res = self.add_inner( SignalI.new(name,type,:inner,value)) end else raise AnyError, "Invalid class for a name: #{name.class}" end end return res end
Generates the instantiation capabilities including an instantiation method name
for hdl-like instantiation, target instantiation as klass
, added to the calling object, and whose eigen type is initialized by ruby_block
.
NOTE: actually creates two instantiater, a general one, being
registered in the namespace stack, and one for creating an array of instances being registered in the Array class.
# File lib/HDLRuby/hruby_high.rb, line 645 def make_instantiater(name,klass,&ruby_block) # puts "make_instantiater with name=#{name}" # Set the instanciater. @instance_procs = [ ruby_block ] # Set the target instantiation class. @instance_class = klass # Unnamed types do not have associated access method. return if name.empty? obj = self # For using the right self within the proc # Create and register the general instantiater. High.space_reg(name) do |*args| # puts "Instantiating #{name} with args=#{args.size}" # If no arguments, return the system as is return obj if args.empty? # Are there any generic arguments? if ruby_block.arity > 0 then # Yes, must specialize the system with the arguments. # If arguments, create a new system specialized with them return SystemT.new(:"") { include(obj,*args) } end # It is the case where it is an instantiation # Get the names from the arguments. i_names = args.shift # puts "i_names=#{i_names}(#{i_names.class})" i_names = [*i_names] instance = nil # The current instance i_names.each do |i_name| # Instantiate. instance = obj.instantiate(i_name,*args) end # # Return the last instance. instance end # Create and register the array of instances instantiater. ::Array.class_eval do define_method(name) { |*args| make(name,*args) } end end
Creates and adds a set of outputs typed type
from a list of names
.
NOTE: a name can also be a signal, is which case it is duplicated.
# File lib/HDLRuby/hruby_high.rb, line 396 def make_outputs(type, *names) # puts "type=#{type.inspect}" res = nil names.each do |name| # puts "name=#{name}" if name.respond_to?(:to_sym) then res = self.add_output(SignalI.new(name,type,:output)) elsif name.is_a?(Hash) then # Names associated with values. names.each do |name,value| res = self.add_inner( SignalI.new(name,type,:inner,value)) end else raise AnyError, "Invalid class for a name: #{name.class}" end end return res end
Gets the private namespace of the system.
# File lib/HDLRuby/hruby_high.rb, line 505 def namespace return self.scope.namespace end
Adds a task to apply on the instances of the system.
# File lib/HDLRuby/hruby_high.rb, line 595 def on_instance(&ruby_block) @on_instances << ruby_block end
Opens for extension.
NOTE: actually executes ruby_block
in the context of the scope
of the system.
# File lib/HDLRuby/hruby_high.rb, line 518 def open(&ruby_block) # Are we instantiating current system? if (High.space_include?(self.scope.namespace)) then # Yes, execute the ruby block in the top context of the # system. # self.scope.open(&ruby_block) self.run(&ruby_block) else # No, add the ruby block to the list of block to execute # when instantiating. @instance_procs << ruby_block end end
Declares high-level bit output signals named names
.
Retuns the last declared input.
# File lib/HDLRuby/hruby_high.rb, line 703 def output(*names) self.make_outputs(bit,*names) end
Execute ruby_block
in the context of the system.
# File lib/HDLRuby/hruby_high.rb, line 510 def run(&ruby_block) self.scope.open(&ruby_block) end
Gets class containing the extension for the instances.
# File lib/HDLRuby/hruby_high.rb, line 500 def singleton_instance @singleton_instanceO.singleton_class end
Converts the system to HDLRuby::Low
and set its name
.
# File lib/HDLRuby/hruby_high.rb, line 755 def to_low(name = self.name) name = name.to_s if name.empty? then raise AnyError, "Cannot convert a system without a name to HDLRuby::Low." end # Create the resulting low system type. # systemTL = HDLRuby::Low::SystemT.new(High.names_create(name), systemTL = HDLRuby::Low::SystemT.new(HDLRuby.uniq_name(name), self.scope.to_low) # puts "New low from system #{self.name}: #{systemTL.name}" # For debugging: set the source high object systemTL.properties[:low2high] = self.hdr_id self.properties[:high2low] = systemTL # Fills the interface of the new system # from the included systems. self.fill_low(systemTL) # Return theresulting system. return systemTL end
Converts to a namespace user.
# File lib/HDLRuby/hruby_high.rb, line 361 def to_user # Returns the scope. return @scope end