class HDLRuby::High::Scope
Describes a scope for a system type
Constants
- High
High-level libraries for describing digital hardware.
Attributes
The name of the scope if any.
The namespace
The return value when building the scope.
Public Class Methods
Creates a new scope with possible name
. If
the scope is a top scope of a system, this systemT is given by systemT
.
The proc ruby_block
is executed for building the scope. If
no block is provided, the scope is the top of a system and is filled by the instantiation procedure of the system.
HDLRuby::Low::Scope::new
# File lib/HDLRuby/hruby_high.rb, line 807 def initialize(name = :"", systemT = nil, &ruby_block) # Initialize the scope structure super(name) # Initialize the set of grouped system instances. @groupIs = {} # Creates the namespace. @namespace = Namespace.new(self) # Register the scope if it is not the top scope of a system # (in which case the system has already be registered with # the same name). unless name.empty? or systemT then # Named scope, set the hdl-like access to the scope. obj = self # For using the right self within the proc High.space_reg(name) { obj } end # Initialize the set of exported inner signals and instances @exports = {} # Initialize the set of included systems. @includes = {} # Builds the scope if a ruby block is provided # (which means the scope is not the top of a system). self.build(&ruby_block) if block_given? end
Public Instance Methods
Adds a name
to export.
NOTE: if the name do not corresponds to any inner signal nor instance, raise an exception.
# File lib/HDLRuby/hruby_high.rb, line 878 def add_export(name) # Check the name. name = name.to_sym # Look for construct to make public. # Maybe it is an inner signals. inner = self.get_inner(name) if inner then # Yes set it as export. @exports[name] = inner return end # No, maybe it is an instance. instance = self.get_systemI(name) if instance then # Yes, set it as export. @exports[name] = instance return end # No, error. raise AnyError, "Invalid name for export: #{name}" end
Adds a group of system instances
named name
.
# File lib/HDLRuby/hruby_high.rb, line 843 def add_groupI(name, *instances) # Ensure name is a symbol and is not already used for another # group. name = name.to_sym if @groupIs.key?(name) raise AnyError, "Group of system instances named #{name} already exist." end # Add the group. @groupIs[name.to_sym] = instances # Sets the parent of the instances. instances.each { |instance| instance.parent = self } end
Adds inout signal
in the current system.
# File lib/HDLRuby/hruby_high.rb, line 991 def add_inout(signal) self.parent.add_inout(signal) end
Adds input signal
in the current system.
# File lib/HDLRuby/hruby_high.rb, line 981 def add_input(signal) self.parent.add_input(signal) end
Adds output signal
in the current system.
# File lib/HDLRuby/hruby_high.rb, line 986 def add_output(signal) self.parent.add_output(signal) end
Casts as an included system
.
# File lib/HDLRuby/hruby_high.rb, line 1244 def as(system) # puts "as with name: #{system.name}" system = system.name if system.respond_to?(:name) # puts "includes are: #{@includes.keys}" return @includes[system].namespace end
Build the scope by executing ruby_block
.
NOTE: used when the scope is not the top of a system.
# File lib/HDLRuby/hruby_high.rb, line 939 def build(&ruby_block) # Set the namespace for buidling the scope. High.space_push(@namespace) # Build the scope. # @return_value = High.top_user.instance_eval(&ruby_block) res = High.top_user.instance_eval(&ruby_block) High.space_pop # Now gain access to the result within the sub scope. if (res.is_a?(HRef)) then @return_value = res.type.inner(HDLRuby.uniq_name) High.space_push(@namespace) @return_value <= res High.space_pop else @return_value = res end # This will be the return value. @return_value end
Builds the scope using base
as model scope with possible arguments args
.
NOTE: Used by the instantiation procedure of a system.
# File lib/HDLRuby/hruby_high.rb, line 964 def build_top(base,*args) # Fills its namespace with the content of the base scope # (this latter may already contains access points if it has been # opended for extension previously). @namespace.concat_namespace(base.namespace) High.space_push(@namespace) # Execute the instantiation block base.parent.each_instance_proc do |instance_proc| @return_value = High.top_user.instance_exec(*args,&instance_proc) end High.space_pop end
Declares a non-HDLRuby set of code chunks described by content
and completed from ruby_block
execution result. NOTE: content includes the events to activate the code on and
a description of the code as a hash assotiating names to code text.
# File lib/HDLRuby/hruby_high.rb, line 1052 def code(*content, &ruby_block) # Process the content. # Separate events from code chunks descriptions. events, chunks = content.partition {|elem| elem.is_a?(Event) } # Generates a large hash from the code. chunks = chunks.reduce(:merge) # Adds the result of the ruby block if any. if ruby_block then chunks.merge(HDLRuby::High.top_user.instance_eval(&ruby_block)) end # Create the chunk objects. chunks = chunks.each.map do |name,content| content = [*content] # Process the lumps content.map! do |lump| lump.respond_to?(:to_expr) ? lump.to_expr : lump end Chunk.new(name,*content) end # Create the code object. res = Code.new # Adds the events. events.each(&res.method(:add_event)) # Adds the chunks. chunks.each(&res.method(:add_chunk)) # Adds the resulting code to the current scope. HDLRuby::High.top_user.add_code(res) # Return the resulting code return res end
Gets the current system.
# File lib/HDLRuby/hruby_high.rb, line 1253 def cur_system return HDLRuby::High.cur_system end
Iterates over the exported constructs.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_high.rb, line 903 def each_export(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_export) unless ruby_block # A block? Apply it on each input signal instance. @exports.each_value(&ruby_block) # And apply on the sub scopes if any. @scopes.each {|scope| scope.each_export(&ruby_block) } end
Iterates over the group of system instances.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_high.rb, line 867 def each_groupI(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_groupI) unless ruby_block # A block? Apply it on each input signal instance. @groupIs.each(&ruby_block) end
Iterates over the included systems.
# File lib/HDLRuby/hruby_high.rb, line 913 def each_included(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_included) unless ruby_block # A block? Apply it on each included system. @includes.each_value(&ruby_block) # And apply on the sub scopes if any. @scopes.each {|scope| scope.each_included(&ruby_block) } end
Sets the constructs corresponding to names
as exports.
# File lib/HDLRuby/hruby_high.rb, line 1199 def export(*names) names.each {|name| self.add_export(name) } end
Fills a low level scope with self's contents.
NOTE: name conflicts are treated in the current NameStack state.
# File lib/HDLRuby/hruby_high.rb, line 1262 def fill_low(scopeL) # Adds the content of its included systems. @includes.each_value {|system| system.scope.fill_low(scopeL) } # Adds the declared local system types. # NOTE: in the current version of HDLRuby::High, there should not # be any of them (only eigen systems are real system types). self.each_systemT { |systemT| scopeL.add_systemT(systemT.to_low) } # Adds the local types. self.each_type { |type| scopeL.add_type(type.to_low) } # Adds the inner scopes. self.each_scope { |scope| scopeL.add_scope(scope.to_low) } # Adds the inner signals. self.each_inner { |inner| scopeL.add_inner(inner.to_low) } # Adds the instances. # Single ones. self.each_systemI do |systemI| # puts "Filling with systemI=#{systemI.name}" systemI_low = scopeL.add_systemI(systemI.to_low) # Also add the eigen system to the list of local systems. scopeL.add_systemT(systemI_low.systemT) end # Grouped ones. self.each_groupI do |name,systemIs| systemIs.each.with_index { |systemI,i| # Sets the name of the system instance # (required for conversion of further accesses). # puts "systemI.respond_to?=#{systemI.respond_to?(:name=)}" systemI.name = name.to_s + "[#{i}]" # And convert it to low systemI_low = scopeL.add_systemI(systemI.to_low()) # Also add the eigen system to the list of local systems. scopeL.add_systemT(systemI_low.systemT) } end # Adds the code chunks. self.each_code { |code| scopeL.add_code(code.to_low) } # Adds the connections. self.each_connection { |connection| # puts "connection=#{connection}" scopeL.add_connection(connection.to_low) } # Adds the behaviors. self.each_behavior { |behavior| scopeL.add_behavior(behavior.to_low) } end
Access a group of system instances by name
.
NOTE: the result is a copy of the group for avoiding side effects.
# File lib/HDLRuby/hruby_high.rb, line 860 def get_groupI(name) return @groupIs[name.to_sym].clone end
Creates a new case statement with a value
used for deciding which block to execute.
NOTE:
* the when part is defined through the hwhen method. * a new behavior is created to enclose the hcase.
# File lib/HDLRuby/hruby_high.rb, line 1176 def hcase(value) self.par do hcase(value) end end
Sets the block executed when the condition is not met to the block in mode
generated by the execution of ruby_block
.
Can only be used once.
NOTE: added to the hif of the last behavior.
# File lib/HDLRuby/hruby_high.rb, line 1145 def helse(mode = nil, &ruby_block) # There is a ruby_block: the helse is assumed to be with # the last statement of the last behavior. statement = self.last_behavior.last_statement # Completes the hif or the hcase statement. unless statement.is_a?(If) or statement.is_a?(Case) then raise AnyError, "Error: helse statement without hif nor hcase (#{statement.class})." end statement.helse(mode, &ruby_block) end
Sets the condition check when the condition is not met to the block, with a condition
that when met lead to the execution of the block in mode
generated by the ruby_block
.
# File lib/HDLRuby/hruby_high.rb, line 1159 def helsif(condition, mode = nil, &ruby_block) # There is a ruby_block: the helse is assumed to be with # the last statement of the last behavior. statement = self.last_behavior.last_statement # Completes the hif statement. unless statement.is_a?(If) then raise AnyError, "Error: helsif statement without hif (#{statement.class})." end statement.helsif(condition, mode, &ruby_block) end
Creates a new if statement with a condition
that when met lead to the execution of the block in mode
generated by the ruby_block
.
NOTE:
* the else part is defined through the helse method. * a behavior is created to enclose the hif.
# File lib/HDLRuby/hruby_high.rb, line 1133 def hif(condition, mode = nil, &ruby_block) self.par do hif(condition,mode,&ruby_block) end end
Sets the block of a case structure executed when the match
is met to the block in mode
generated by the execution of ruby_block
.
Can only be used once.
# File lib/HDLRuby/hruby_high.rb, line 1186 def hwhen(match, mode = nil, &ruby_block) # There is a ruby_block: the helse is assumed to be with # the last statement of the last behavior. statement = @behaviors.last.last_statement # Completes the hcase statement. unless statement.is_a?(Case) then raise AnyError, "Error: hwhen statement without hcase (#{statement.class})." end statement.hwhen(match, mode, &ruby_block) end
Include a system
type with possible args
instanciation arguments.
# File lib/HDLRuby/hruby_high.rb, line 1205 def include(system,*args) if @includes.key?(system.name) then raise AnyError, "Cannot include twice the same system." end # puts "Include system=#{system.name}" # Save the name of the included system, it will serve as key # for looking for the included expanded version. include_name = system.name # Expand the system to include system = system.expand(:"",*args) # Add the included system interface to the current one. if self.parent.is_a?(SystemT) then space = self.namespace # Interface signals # puts "i_name=#{i_name} @to_includes=#{@to_includes.size}" system.each_signal_with_included do |signal| # puts "signal=#{signal.name}" space.send(:define_singleton_method,signal.name) do signal end end # Exported objects system.each_export do |export| # puts "export=#{export.name}" space.send(:define_singleton_method,export.name) do export end end # Adds the task to execute on the instance. system.each_on_instance do |task| self.parent.on_instance(&task) end end # Adds it the list of includeds @includes[include_name] = system end
Declares high-level bit inout signals named names
in the current system.
# File lib/HDLRuby/hruby_high.rb, line 1043 def inout(*names) self.parent.inout(*names) end
Declares high-level bit input signals named names
in the current system.
# File lib/HDLRuby/hruby_high.rb, line 1031 def input(*names) self.parent.input(*names) end
Creates and adds a set of inouts typed type
from a list of names
in the current system.
NOTE: a name can also be a signal, is which case it is duplicated.
# File lib/HDLRuby/hruby_high.rb, line 1015 def make_inouts(type, *names) self.parent.make_inouts(type,*names) end
Creates and adds a set of inputs typed type
from a list of names
in the current system.
NOTE: a name can also be a signal, is which case it is duplicated.
# File lib/HDLRuby/hruby_high.rb, line 999 def make_inputs(type, *names) self.parent.make_inputs(type,*names) end
Creates and adds a set of outputs typed type
from a list of names
in the current system.
NOTE: a name can also be a signal, is which case it is duplicated.
# File lib/HDLRuby/hruby_high.rb, line 1007 def make_outputs(type, *names) self.parent.make_outputs(type,*names) end
Opens for extension.
NOTE: actually executes ruby_block
in the context.
# File lib/HDLRuby/hruby_high.rb, line 926 def open(&ruby_block) High.space_push(@namespace) res = High.top_user.instance_eval(&ruby_block) High.space_pop # Return the result of the execution so that it can be used # as an expression res end
Declares high-level bit output signals named names
in the current system.
# File lib/HDLRuby/hruby_high.rb, line 1037 def output(*names) self.parent.output(*names) end
Declares a high-level parallel behavior activated on a list of events
, and built by executing ruby_block
.
# File lib/HDLRuby/hruby_high.rb, line 1109 def par(*events, &ruby_block) # Preprocess the events. events.map! do |event| event.respond_to?(:to_event) ? event.to_event : event end # Create and add the resulting behavior. self.add_behavior(Behavior.new(:par,*events,&ruby_block)) end
Declares a high-level sequential behavior activated on a list of events
, and built by executing ruby_block
.
# File lib/HDLRuby/hruby_high.rb, line 1098 def seq(*events, &ruby_block) # Preprocess the events. events.map! do |event| event.respond_to?(:to_event) ? event.to_event : event end # Create and add the resulting behavior. self.add_behavior(Behavior.new(:seq,*events,&ruby_block)) end
Declares a sub scope with possible name
and built from ruby_block
.
# File lib/HDLRuby/hruby_high.rb, line 1084 def sub(name = :"", &ruby_block) # Creates the new scope. scope = Scope.new(name,&ruby_block) # puts "new scope=#{scope}" # Add it self.add_scope(scope) # puts "self=#{self}" # puts "self scopes=#{self.each_scope.to_a.join(",")}" # Use its return value return scope.return_value end
Declares a high-level timed behavior built by executing ruby_block
. By default, timed behavior are sequential.
# File lib/HDLRuby/hruby_high.rb, line 1120 def timed(&ruby_block) # Create and add the resulting behavior. self.add_behavior(TimeBehavior.new(:seq,&ruby_block)) end
Converts the scope to HDLRuby::Low
.
# File lib/HDLRuby/hruby_high.rb, line 1310 def to_low() # Create the resulting low scope. # scopeL = HDLRuby::Low::Scope.new() scopeL = HDLRuby::Low::Scope.new(self.name) # For debugging: set the source high object scopeL.properties[:low2high] = self.hdr_id self.properties[:high2low] = scopeL # Push the private namespace for the low generation. High.space_push(@namespace) # Pushes on the name stack for converting the internals of # the system. High.names_push # Adds the content of the actual system. self.fill_low(scopeL) # Restores the name stack. High.names_pop # Restores the namespace stack. High.space_pop # Return theresulting system. return scopeL end
Converts to a new reference.
# File lib/HDLRuby/hruby_high.rb, line 1020 def to_ref return RefObject.new(this,self) end
Converts to a namespace user.
# File lib/HDLRuby/hruby_high.rb, line 837 def to_user # Already a user. return self end