class HDLRuby::High::SystemT

Describes a high-level system type.

Constants

High

High-level libraries for describing digital hardware.

Attributes

instance_class[R]

The instantiation target class.

public_namespace[R]

The public namespace

NOTE: the private namespace is the namespace of the scope object.

Public Class Methods

new(name, *mixins, &ruby_block) click to toggle source

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.

Calls superclass method 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

add_generator(gen) click to toggle source

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
as(system) click to toggle source

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
call(i_name,*args)

Instantiation can also be done throw the call operator.

Alias for: instantiate
each_export(&ruby_block) click to toggle source

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
each_generator(&ruby_block) click to toggle source

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
each_instance_proc(&ruby_block) click to toggle source

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
each_on_instance(&ruby_block) click to toggle source

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
each_signal_with_included(&ruby_block) click to toggle source

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
eigenize(instance) click to toggle source

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
expand(name, *args) click to toggle source

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(system) click to toggle source

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
fill_interface(systemTlow) click to toggle source

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
fill_low(systemTlow) click to toggle source

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_interface_with_included(i) click to toggle source

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
get_output_with_included(name) click to toggle source

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
inout(*names) click to toggle source

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
input(*names) click to toggle source

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(i_name,*args) click to toggle source

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
Also aliased as: call
make_inouts(type, *names) click to toggle source

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
make_inputs(type, *names) click to toggle source

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
make_instantiater(name,klass,&ruby_block) click to toggle source

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
make_outputs(type, *names) click to toggle source

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
namespace() click to toggle source

Gets the private namespace of the system.

# File lib/HDLRuby/hruby_high.rb, line 505
def namespace
    return self.scope.namespace
end
on_instance(&ruby_block) click to toggle source

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
open(&ruby_block) click to toggle source

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
output(*names) click to toggle source

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
run(&ruby_block) click to toggle source

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
singleton_instance() click to toggle source

Gets class containing the extension for the instances.

# File lib/HDLRuby/hruby_high.rb, line 500
def singleton_instance
    @singleton_instanceO.singleton_class
end
to_low(name = self.name) click to toggle source

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
to_user() click to toggle source

Converts to a namespace user.

# File lib/HDLRuby/hruby_high.rb, line 361
def to_user
    # Returns the scope.
    return @scope
end