class HDLRuby::High::Std::ChannelI

Describes a high-level channel instance.

Attributes

name[R]

The name of the channel instance.

namespace[R]

The namespace associated with the current execution when building a channel.

read_port[R]

The read port if any.

scope[R]

The scope the channel has been created in.

write_port[R]

The write port if any.

Public Class Methods

new(name,&ruby_block) click to toggle source

Creates a new channel instance with name built from ruby_block.

# File lib/HDLRuby/std/channel.rb, line 432
def initialize(name,&ruby_block)
    # Check and set the name of the channel.
    @name = name.to_sym
    # puts "my name is #{self.name}"
    # Generate a name for the scope containing the signals of
    # the channel.
    # @scope_name = HDLRuby.uniq_name
    @scope_name = HDLRuby.uniq_name(name)

    # # Sets the scope.
    # @scope = HDLRuby::High.cur_scope

    # Keep access to self.
    obj = self

    # At first there no read nor write port.
    @read_port = nil
    @write_port = nil

    # The reader input ports by name.
    @reader_inputs = {}
    # The reader output ports by name.
    @reader_outputs = {}
    # The reader inout ports by name.
    @reader_inouts = {}

    # The writer input ports by name.
    @writer_inputs = {}
    # The writer output ports by name.
    @writer_outputs = {}
    # The writer inout ports by name.
    @writer_inouts = {}

    # The accesser input ports by name.
    @accesser_inputs = {}
    # The accesser output ports by name.
    @accesser_outputs = {}
    # The accesser inout ports by name.
    @accesser_inouts = {}

    # The branch channels
    @branches = {}

    # Create the namespaces for building the channel, its readers
    # its writers and its accessers.

    # Creates the namespace of the channel.
    @namespace = Namespace.new(self)
    # Make it give access to the internal of the class.
    @namespace.add_method(:reader_input,   &method(:reader_input))
    @namespace.add_method(:reader_output,  &method(:reader_output))
    @namespace.add_method(:reader_inout,   &method(:reader_inout))
    @namespace.add_method(:writer_input,   &method(:writer_input))
    @namespace.add_method(:writer_output,  &method(:writer_output))
    @namespace.add_method(:writer_inout,   &method(:writer_inout))
    @namespace.add_method(:accesser_input, &method(:accesser_input))
    @namespace.add_method(:accesser_output,&method(:accesser_output))
    @namespace.add_method(:accesser_inout, &method(:accesser_inout))
    @namespace.add_method(:reader,         &method(:reader))
    @namespace.add_method(:writer,         &method(:writer))
    @namespace.add_method(:brancher,         &method(:brancher))

    # Creates the namespace of the reader.
    @reader_namespace = Namespace.new(self)
    # Creates the namespace of the writer.
    @writer_namespace = Namespace.new(self)
    # Creates the namespace of the accesser.
    @accesser_namespace = Namespace.new(self)

    # Builds the channel within a new scope.
    HDLRuby::High.space_push(@namespace)
    # puts "top_user=#{HDLRuby::High.top_user}"
    scope_name = @scope_name
    scope = nil
    HDLRuby::High.top_user.instance_eval do 
        sub(scope_name) do
            # Generate the channel code.
            ruby_block.call
        end
    end
    HDLRuby::High.space_pop

    # Keep access to the scope containing the code of the channel.
    @scope = @namespace.send(scope_name)
    # puts "@scope=#{@scope}"
    # Adds the name space of the scope to the namespace of the
    # channel
    @namespace.concat_namespace(@scope.namespace)

    # Gives access to the channel by registering its name.
    obj = self
    # HDLRuby::High.space_reg(@name) { self }
    HDLRuby::High.space_reg(@name) { obj }
end

Public Instance Methods

accesser_inout(*keys) click to toggle source

Sets the signals accessible through key to be accesser inout port.

# File lib/HDLRuby/std/channel.rb, line 652
def accesser_inout(*keys)
    # Registers each signal as accesser port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @accesser_inouts[name] = send(key)
    end
end
accesser_input(*keys) click to toggle source

Sets the signals accessible through key to be accesser input port.

# File lib/HDLRuby/std/channel.rb, line 628
def accesser_input(*keys)
    # Registers each signal as accesser port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @accesser_inputs[name] = send(key)
    end
end
accesser_output(*keys) click to toggle source

Sets the signals accessible through key to be accesser output port.

# File lib/HDLRuby/std/channel.rb, line 640
def accesser_output(*keys)
    # Registers each signal as accesser port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @accesser_outputs[name] = send(key)
    end
end
branch(name,*args) click to toggle source

Gets branch channel name. NOTE: name can be of any type on purpose.

# File lib/HDLRuby/std/channel.rb, line 744
def branch(name,*args)
    # Ensure name is a symbol.
    name = name.to_s unless name.respond_to?(:to_sym)
    name = name.to_sym
    # Get the branch.
    channelI = @branches[name]
    return @branches[name]
end
brancher(name,channelI = nil,&ruby_block) click to toggle source

Defines a branch in the channel named name built executing ruby_block. Alternatively, a ready channel instance can be passed as argument as channelI.

# File lib/HDLRuby/std/channel.rb, line 721
def brancher(name,channelI = nil,&ruby_block)
    # puts "self.name=#{self.name} and name=#{name}"
    # Ensure name is a symbol.
    name = name.to_s unless name.respond_to?(:to_sym)
    name = name.to_sym
    # Is there a ready channel instance.
    if channelI then
        # Yes, use it directly.
        @branches[name] = channelI
        return self
    end
    # Now, create the branch.
    channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
    # channelI = HDLRuby::High::Std.channel_instance("#{self.name}::#{name}", &ruby_block)
    @branches[name] = channelI
    return self
end
inout(name = nil) click to toggle source

Declares the accesser port and assigned them to name.

# File lib/HDLRuby/std/channel.rb, line 981
def inout(name = nil)
    # Ensure name is a symbol.
    name = HDLRuby.uniq_name unless name
    name = name.to_sym
    # Ensure the port is not already existing.
    if @read_port then
        raise "Read port already declared for channel instance: " +
            self.name.to_s
    end

    if @write_port then
        raise "Write port already declared for channel instance: " +
            self.name.to_s
    end

    # Access the ports
    loc_inputs  = @accesser_inputs.merge(@reader_inputs).
        merge(@writer_inputs)
    loc_outputs = @accesser_outputs.merge(@reader_outputs).
        merge(@writer_outputs)
    loc_inouts  = @accesser_inouts.merge(@reader_inouts).
        merge(@writer_inouts)
    locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
    # The generated port with corresponding channel port pairs.
    port_pairs = []
    if HDLRuby::High.cur_system == self.parent_system then
        # Port in same system as the channel case.
        # Add them to the current system.
        HDLRuby::High.cur_system.open do
            locs.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name)]
            end
        end
        obj = self
        # Make the inner connection
        port_pairs.each do |sig, port|
            sig.parent.open do
                port.to_ref <= sig
            end
        end
    else
        # Port in different system as the channel case.
        # Add them to the current system.
        HDLRuby::High.cur_system.open do
            # The inputs
            loc_inputs.each  do |name,sig|
                # puts "name=#{name} sig.name=#{sig.name}"
                port_pairs << [sig, sig.type.input(name)]
            end
            # The outputs
            loc_outputs.each do |name,sig| 
                port_pairs << [sig, sig.type.output(name)]
            end
            # The inouts
            loc_inouts.each  do |name,sig| 
                port_pairs << [sig, sig.type.inout(name)]
            end
        end
        obj = self
        # Make the connection of the instance.
        HDLRuby::High.cur_system.on_instance do |inst|
            obj.scope.open do
                port_pairs.each do |sig, port|
                    RefObject.new(inst,port.to_ref) <= sig
                end
            end
        end
    end

    # Fill the reader namespace with the access to the reader signals.
    loc_inputs.each do |name,sig|
        @accesser_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end
    loc_outputs.each do |name,sig|
        @accesser_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end
    loc_inouts.each do |name,sig|
        @accesser_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end

    # Give access to the ports through name.
    # NOTE: for now, simply associate the channel to name.
    chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
    HDLRuby::High.space_reg(name) { chp }
    # Save the port in the channe to avoid conflicting declaration.
    @read_port = chp
    @write_port = chp
    return chp
end
inout?() click to toggle source

Tells if the channel support inout port.

# File lib/HDLRuby/std/channel.rb, line 712
def inout?
    return @accesser_inputs.any? || @accesser_outputs.any? ||
           @accesser_inouts.any?
end
inout_reseter(&ruby_block) click to toggle source

Sets the inout port reset to be ruby_block.

# File lib/HDLRuby/std/channel.rb, line 690
def inout_reseter(&ruby_block)
    @inout_reseter_proc = ruby_block
end
input(name = nil) click to toggle source

Declares the reader port as and assigned them to name.

# File lib/HDLRuby/std/channel.rb, line 757
def input(name = nil)
    # Ensure name is a symbol.
    name = HDLRuby.uniq_name unless name
    name = name.to_sym
    # Ensure the port is not already existing.
    if @read_port then
        raise "Read port already declared for channel instance: " +
            self.name
    end

    # Access the ports
    # loc_inputs  = @reader_inputs
    # loc_outputs = @reader_outputs
    # loc_inouts  = @reader_inouts
    loc_inputs  = @reader_inputs.merge(@accesser_inputs)
    loc_outputs = @reader_outputs.merge(@accesser_outputs)
    loc_inouts  = @reader_inouts.merge(@accesser_inouts)
    locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
    # The generated port with corresponding channel port pairs.
    port_pairs = []
    if HDLRuby::High.cur_system == self.parent_system then
        # Port in same system as the channel case.
        # Add them to the current system.
        HDLRuby::High.cur_system.open do
            # locs.each  do |name,sig|
            #     port_pairs << [sig, sig.type.inner(name)]
            # end
            loc_inputs.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name),:input]
            end
            loc_outputs.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name),:output]
            end
            loc_inouts.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name),:inout]
            end
        end
        obj = self
        # Make the inner connection
        # port_pairs.each do |sig, port|
        port_pairs.each do |sig, port, dir|
            sig.parent.open do
                # port.to_ref <= sig
                if dir == :input then
                    port.to_ref <= sig
                else
                    sig <= port.to_ref
                end
            end
        end
    else
        # Port in different system as the channel case.
        # Add them to the current system.
        HDLRuby::High.cur_system.open do
            # The inputs
            loc_inputs.each  do |name,sig|
                # puts "name=#{name} sig.name=#{sig.name}"
                port_pairs << [sig, sig.type.input(name),:input]
            end
            # The outputs
            loc_outputs.each do |name,sig| 
                port_pairs << [sig, sig.type.output(name),:output]
            end
            # The inouts
            loc_inouts.each  do |name,sig| 
                port_pairs << [sig, sig.type.inout(name),:inout]
            end
        end
        obj = self
        # Make the connection of the instance.
        HDLRuby::High.cur_system.on_instance do |inst|
            obj.scope.open do
                port_pairs.each do |sig, port, dir|
                    # RefObject.new(inst,port.to_ref) <= sig
                    if dir == :input then
                        RefObject.new(inst,port.to_ref) <= sig
                    else
                        sig <= RefObject.new(inst,port.to_ref)
                    end
                end
            end
        end
    end

    # Fill the reader namespace with the access to the reader signals.
    loc_inputs.each do |name,sig|
        @reader_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end
    loc_outputs.each do |name,sig|
        @reader_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end
    loc_inouts.each do |name,sig|
        @reader_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end

    # Give access to the ports through name.
    # NOTE: for now, simply associate the channel to name.
    chp = ChannelPortR.new(@reader_namespace,@reader_proc,@input_reseter_proc)
    HDLRuby::High.space_reg(name) { chp }
    # Save the port in the channe to avoid conflicting declaration.
    @read_port = chp
    return chp
end
input_reseter(&ruby_block) click to toggle source

Sets the input port reset to be ruby_block.

# File lib/HDLRuby/std/channel.rb, line 680
def input_reseter(&ruby_block)
    @input_reseter_proc = ruby_block
end
output(name = nil) click to toggle source

Declares the ports for the writer and assigned them to name.

# File lib/HDLRuby/std/channel.rb, line 868
def output(name = nil)
    # Ensure name is a symbol.
    name = HDLRuby.uniq_name unless name
    name = name.to_sym
    # Ensure the port is not already existing.
    if @write_port then
        raise "Write port already declared for channel instance: " +
            self.name
    end
    # Access the ports
    # loc_inputs  = @writer_inputs
    # loc_outputs = @writer_outputs
    # loc_inouts  = @writer_inouts
    loc_inputs  = @writer_inputs.merge(@accesser_inputs)
    loc_outputs = @writer_outputs.merge(@accesser_outputs)
    loc_inouts  = @writer_inouts.merge(@accesser_inouts)
    locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
    # The generated port with corresponding channel port pairs.
    port_pairs = []
    # puts "cur_system=#{HDLRuby::High.cur_system} self.parent_system=#{self.parent_system}"
    if HDLRuby::High.cur_system == self.parent_system then
        # puts "Inner found!"
        # Port in same system as the channel case.
        # Add them to the current system.
        HDLRuby::High.cur_system.open do
            # locs.each  do |name,sig|
            #     port_pairs << [sig, sig.type.inner(name)]
            # end
            loc_inputs.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name),:input]
            end
            loc_outputs.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name),:output]
            end
            loc_inouts.each  do |name,sig|
                port_pairs << [sig, sig.type.inner(name),:inout]
            end
        end
        obj = self
        # Make the inner connection
        # port_pairs.each do |sig, port|
        port_pairs.each do |sig, port, dir|
            sig.parent.open do
                # port.to_ref <= sig
                if dir == :input then
                    port.to_ref <= sig
                else
                    sig <= port.to_ref
                end
            end
        end
    else
        # Portds in different system as the channel's case.
        # Add them to the current system.
        HDLRuby::High.cur_system.open do
            # The inputs
            loc_inputs.each  do |name,sig|
                port_pairs << [sig, sig.type.input(name),:input]
            end
            # The outputs
            loc_outputs.each do |name,sig| 
                port_pairs << [sig, sig.type.output(name),:output]
            end
            # The inouts
            loc_inouts.each  do |name,sig| 
                port_pairs << [sig, sig.type.inout(name),:inout]
            end
        end
        obj = self
        # Make the connection of the instance.
        HDLRuby::High.cur_system.on_instance do |inst|
            obj.scope.open do
                port_pairs.each do |sig, port, dir|
                    # RefObject.new(inst,port.to_ref) <= sig
                    # RefObject.new(inst,port.to_ref) <= sig
                    if dir == :input then
                        RefObject.new(inst,port.to_ref) <= sig
                    else
                        sig <= RefObject.new(inst,port.to_ref)
                    end
                end
            end
        end
    end

    # Fill the writer namespace with the access to the writer signals.
    loc_inputs.each do |name,sig|
        @writer_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end
    loc_outputs.each do |name,sig|
        @writer_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end
    loc_inouts.each do |name,sig|
        @writer_namespace.add_method(sig.name) do
            HDLRuby::High.top_user.send(name)
        end
    end

    # Give access to the ports through name.
    # NOTE: for now, simply associate the channel to name.
    chp = ChannelPortW.new(@writer_namespace,@writer_proc,@output_reseter_proc)
    HDLRuby::High.space_reg(name) { chp }
    # Save the port in the channe to avoid conflicting declaration.
    @write_port = chp
    return chp
end
output_reseter(&ruby_block) click to toggle source

Sets the output port reset to be ruby_block.

# File lib/HDLRuby/std/channel.rb, line 685
def output_reseter(&ruby_block)
    @output_reseter_proc = ruby_block
end
parent_system() click to toggle source

Get the parent system.

# File lib/HDLRuby/std/channel.rb, line 528
def parent_system
    return self.scope.parent_system
end
reader(&ruby_block) click to toggle source

Sets the read procedure to be ruby_block.

# File lib/HDLRuby/std/channel.rb, line 665
def reader(&ruby_block)
    @reader_proc = ruby_block
end
reader_inout(*keys) click to toggle source

Sets the signals accessible through key to be reader inout port.

# File lib/HDLRuby/std/channel.rb, line 580
def reader_inout(*keys)
    # Registers each signal as reader port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @reader_inouts[name] = send(key)
    end
end
reader_input(*keys) click to toggle source

Sets the signals accessible through key to be reader input port.

# File lib/HDLRuby/std/channel.rb, line 556
def reader_input(*keys)
    # Registers each signal as reader port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @reader_inputs[name] = send(key)
    end
end
reader_output(*keys) click to toggle source

Sets the signals accessible through key to be reader output port.

# File lib/HDLRuby/std/channel.rb, line 568
def reader_output(*keys)
    # Registers each signal as reader port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @reader_outputs[name] = send(key)
    end
end
reader_signals() click to toggle source

Gets the list of the signals of the channel to be connected to the reader.

# File lib/HDLRuby/std/channel.rb, line 699
def reader_signals
    return @reader_inputs.values + @reader_outputs.values +
           @reader_inouts.values
end
writer(&ruby_block) click to toggle source

Sets the writer procedure to be ruby_block.

# File lib/HDLRuby/std/channel.rb, line 670
def writer(&ruby_block)
    @writer_proc = ruby_block
end
writer_inout(*keys) click to toggle source

Sets the signals accessible through key to be writer inout port.

# File lib/HDLRuby/std/channel.rb, line 616
def writer_inout(*keys)
    # Registers each signal as writer port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @writer_inouts[name] = send(key)
    end
end
writer_input(*keys) click to toggle source

Sets the signals accessible through key to be writer input port.

# File lib/HDLRuby/std/channel.rb, line 592
def writer_input(*keys)
    # Registers each signal as writer port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @writer_inputs[name] = send(key)
    end
end
writer_output(*keys) click to toggle source

Sets the signals accessible through key to be writer output port.

# File lib/HDLRuby/std/channel.rb, line 604
def writer_output(*keys)
    # Registers each signal as writer port
    keys.each do |key|
        # Ensure the key is a symbol.
        key = key.to_sym
        # Register it with the corresponding signal.
        name = HDLRuby.uniq_name # The name of the signal is uniq.
        @writer_outputs[name] = send(key)
    end
end
writer_signals() click to toggle source

Gets the list of the signals of the channel to be connected to the writer.

# File lib/HDLRuby/std/channel.rb, line 706
def writer_signals
    return @writer_inputs.values + @writer_outputs.values +
           @writer_inouts.values
end