class HDLRuby::Low::SystemT
Extends the SystemT
class with support for C allocation of signals.
Describes system type.
Describes a system type.
NOTE: delegates its content-related methods to its Scope
object.
Extends the SystemT
class with generation of C text.
Extends the SystemT
class with generation of hdr text.
Add the conversion to high.
Extends the SystemT
class with functionality for converting par block to seq.
Extends the SystemT
class with conversion to symbol.
Extends the SystemT
class with generation of HDLRuby::High
text.
Extends the SystemT
class with functionality for converting booleans in assignments to select operators.
Extends the SystemT
class with functionality for extracting expressions from cast.
Extends the SystemT
class with functionality for cleaning up the structure.
Extends the SystemT
class with fixing of types and constants.
Describes a system type.
NOTE: delegates its content-related methods to its Scope
object.
Extends SystemT
with the capability of finding one of its inner object by name.
Skeleton of the HRuby::Low class structure.
Can be used as basis for extending HDLRuby::Low
Extends the SystemT
class for converting types of comparison and operations on it to boolean type.
Extends SystemT
with generation of port wires.
Extends the SystemT
class with separation between signals and variables.
Extends the SystemT
class for removing bit to vector conversions.
Extends the SystemT
class with functionality for breaking assingments to concats.
Extends the SystemT
class with functionality for breaking assingments to concats.
Extends the SystemT
class with functionality for moving the declarations to the upper namespace.
Extends the SystemT
class for remove read of output signal.
Extends the SystemT
class with functionality for converting par blocks within seq blocks to seq blocks.
Extends the SystemT
class with functionality for converting select expressions to case statements.
Enhance SystemT
with generation of verilog code.
Constants
- SystemTs
Library of the existing system types.
Attributes
The name of the system.
The scope of the system type.
Public Class Methods
Get an existing system type by name
.
# File lib/HDLRuby/hruby_db.rb, line 25 def self.get(name) return name if name.is_a?(SystemT) return SystemTs[name.to_sym] end
Creates a new system type named name
.
# File lib/HDLRuby/hruby_db.rb, line 31 def initialize(name) # Initialize the system type structure. super(name) # Update the library of existing system types. # Note: no check is made so an exisiting system type with a same # name is overwritten. SystemTs[@name] = self end
Public Instance Methods
Adds inout signal
.
# File lib/HDLRuby/hruby_low.rb, line 197 def add_inout(signal) # Check and add the signal. unless signal.is_a?(SignalI) raise AnyError, "Invalid class for a signal instance: #{signal.class}" end if @inouts.include?(signal) then raise AnyError, "SignalI #{signal.name} already present." end # Set the parent of the signal. signal.parent = self # And add the signal. @inouts.add(signal) @interface << signal return signal end
Adds input signal
.
# File lib/HDLRuby/hruby_low.rb, line 160 def add_input(signal) # print "add_input with signal: #{signal.name}\n" # Check and add the signal. unless signal.is_a?(SignalI) raise AnyError, "Invalid class for a signal instance: #{signal.class}" end if @inputs.include?(signal) then raise AnyError, "SignalI #{signal.name} already present." end # Set the parent of the signal. signal.parent = self # And add the signal. @inputs.add(signal) @interface << signal return signal end
Adds output signal
.
# File lib/HDLRuby/hruby_low.rb, line 179 def add_output(signal) # Check and add the signal. unless signal.is_a?(SignalI) raise AnyError, "Invalid class for a signal instance: #{signal.class}" end if @outputs.include?(signal) then raise AnyError, "SignalI #{signal.name} already present." end # Set the parent of the signal. signal.parent = self # And add the signal. @outputs.add(signal) @interface << signal return signal end
Replace bit to vector conversions by assignment to on bit of an intermediate inner vector.
NOTE: the result is the same systemT.
# File lib/HDLRuby/hruby_low_without_bit2vector.rb, line 23 def bit2vector2inner! # puts "For system: #{self.name}" # First gather the bit conversions to vector. bits2vectors = Set.new gather_bits2vectors = proc do |node| if node.is_a?(Expression) && node.type == Bit && node.parent.is_a?(Expression) && # References are not relevant parents !node.parent.is_a?(Ref) && # Neither do concat that are processed separatly !node.parent.is_a?(Concat) && node.parent.type != Bit then # puts "node=#{node.to_high}, node.parent=#{node.parent}" bits2vectors.add(node) end end # Apply the procedure for gathering the read on outputs signals. self.scope.each_scope_deep do |scope| scope.each_connection do |connection| # Recurse on the connection. connection.each_node_deep(&gather_bits2vectors) end scope.each_behavior do |behavior| behavior.each_event do |event| gather_bits2vectors.(event.ref) end behavior.each_statement do |statement| # puts "statement=#{statement.class}" statement.each_node_deep(&gather_bits2vectors) end end end # puts "bits2vectors=#{bits2vectors.size}" # Create the 1-bit-vector type. vec1T = TypeVector.new(:"bit1",Bit,0..0) # Generate one inner 1-bit-vector signal per read output. bit2inner = {} bits2vectors.each do |node| # Generate the inner variable. sig = self.scope.add_inner(SignalI.new(HDLRuby::uniq_name,vec1T)) ref = RefName.new(vec1T,RefThis.new,sig.name) bit2inner[node] = [ ref, RefIndex.new(Bit,ref,Value.new(Integer,0)) ] # puts "new inner=#{out2inner[name].name}" end # Apply the replacement procedure on the code self.scope.each_scope_deep do |scope| scope.each_connection.to_a.each do |connection| connection.reassign_expressions!(bit2inner) end scope.each_behavior do |behavior| behavior.each_event do |event| event.reassign_expressions!(bit2inner) end behavior.block.reassign_expressions!(bit2inner) end end return self end
Converts the par sub blocks to seq.
# File lib/HDLRuby/hruby_low2seq.rb, line 21 def blocks2seq! # Recurse on the scope. self.scope.to_seq! return self end
Converts booleans in assignments to select operators.
# File lib/HDLRuby/hruby_low_bool2select.rb, line 22 def boolean_in_assign2select! self.scope.boolean_in_assign2select! return self end
Breaks the assignments to concats.
# File lib/HDLRuby/hruby_low_without_concat.rb, line 21 def break_concat_assigns! self.scope.break_concat_assigns! end
Breaks the hierarchical types into sequences of type definitions.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 74 def break_types! self.scope.break_types! end
Allocates signals within C code using allocator
.
# File lib/HDLRuby/backend/hruby_c_allocator.rb, line 18 def c_code_allocate(allocator) self.scope.c_code_allocate(allocator) end
Extracts the expressions from the casts.
# File lib/HDLRuby/hruby_low_casts_without_expression.rb, line 23 def casts_without_expression! self.scope.casts_without_expression! return self end
Cleans up.
# File lib/HDLRuby/hruby_low_cleanup.rb, line 22 def cleanup! # Gather the output and inout signals' names, they are used to # identify the signals that can be removed. keep = self.each_output.map {|sig| sig.name } + self.each_inout.map {|sig| sig.name } self.scope.cleanup!(keep) end
Remove the connections and replace them by behaviors. NOTE: one behavior is created for input connections and
one for output ones while inout/inner-only connections are copied in both behaviors.
# File lib/HDLRuby/hruby_low_without_connection.rb, line 25 def connections_to_behaviors! # Process the connections: create a behavior containing # them all within a par block. self.scope.each_scope_deep do |scope| if scope.each_connection.to_a.any? then inputs_blk = Block.new(:par) outputs_blk = Block.new(:par) timed_blk = TimeBlock.new(:seq) scope.each_connection do |connection| # puts "For connection: #{connection}" # Check the left and right of the connection # for input or output port. left = connection.left left_r = left.resolve # puts "left_r=#{left_r.name}" if left_r # puts "left_r.parent=#{left_r.parent.name}" if left_r && left_r.parent right = connection.right right_r = right.resolve if right.respond_to?(:resolve) # puts "right_r=#{right_r.name}" if right_r # puts "right_r.parent=#{right_r.parent.name}" if right_r && right_r.parent # if right.is_a?(Value) then if right.immutable? then # Right is value, the new transmit is to add # to the timed block. timed_blk.add_statement( Transmit.new(left.clone,right.clone)) # No more process for this connection. next end # Check if left is an input or an output. left_is_i = left_is_o = false if left_r && left_r.parent.is_a?(SystemT) then if left_r.parent.each_input.include?(left_r) then # puts "Left is input." # puts "Left is from systemI: #{left.from_systemI?}" left_is_i = left.from_systemI? left_is_o = !left_is_i elsif left_r.parent.each_output.include?(left_r) then # puts "Left is output." # puts "Left is from systemI: #{left.from_systemI?}" left_is_o = left.from_systemI? left_is_i = !left_is_o end end # Check if right is an input or an output. right_is_i = right_is_o = false if right_r && right_r.parent.is_a?(SystemT) then if right_r.parent.each_input.include?(right_r) then # puts "Right is input." # puts "Right is from systemI: #{right.from_systemI?}" right_is_i = right.from_systemI? right_is_o = !right_is_i elsif right_r.parent.each_output.include?(right_r) then # puts "Right is output." # puts "Right is from systemI: #{right.from_systemI?}" right_is_o = right.from_systemI? right_is_i = !right_is_o end end # puts "left_is_i=#{left_is_i} left_is_o=#{left_is_o}" # puts "right_is_i=#{right_is_i} right_is_o=#{right_is_o}" # Fills the relevant block. if (left_is_i) then inputs_blk.add_statement( Transmit.new(left.clone,right.clone)) elsif (right_is_i) then inputs_blk.add_statement( Transmit.new(right.clone,left.clone)) elsif (left_is_o) then outputs_blk.add_statement( Transmit.new(right.clone,left.clone)) elsif (right_is_o) then outputs_blk.add_statement( Transmit.new(left.clone,right.clone)) else # # puts "left/right is inout" # if (left.is_a?(Ref)) then # inputs_blk.add_statement( # Transmit.new(left.clone,right.clone)) # end # if (right.is_a?(Ref)) then # outputs_blk.add_statement( # Transmit.new(right.clone,left.clone)) # end # Both or neither input/output, make a behavior # for each. if (left.is_a?(Ref) && !(left_r && left_r.immutable?)) then blk = Block.new(:par) blk.add_statement( Transmit.new(left.clone,right.clone)) scope.add_behavior(Behavior.new(blk)) end if (right.is_a?(Ref) && !(right_r && right_r.immutable?)) then blk = Block.new(:par) blk.add_statement( Transmit.new(right.clone,left.clone)) scope.add_behavior(Behavior.new(blk)) end end end # Adds the behaviors. if inputs_blk.each_statement.any? then scope.add_behavior(Behavior.new(inputs_blk)) end if outputs_blk.each_statement.any? then scope.add_behavior(Behavior.new(outputs_blk)) end if timed_blk.each_statement.any? then scope.add_behavior(TimeBehavior.new(timed_blk)) end end end end
Deletes an inout.
# File lib/HDLRuby/hruby_low_mutable.rb, line 87 def delete_inout!(signal) if @inouts.key?(signal.name) then # The signal is present, delete it. @inouts.delete(signal.name) @interface.delete(signal) # And remove its parent. signal.parent = nil end signal end
Deletes an input.
# File lib/HDLRuby/hruby_low_mutable.rb, line 63 def delete_input!(signal) if @inputs.key?(signal.name) then # The signal is present, delete it. @inputs.delete(signal.name) @interface.delete(signal) # And remove its parent. signal.parent = nil end signal end
Deletes an output.
# File lib/HDLRuby/hruby_low_mutable.rb, line 75 def delete_output!(signal) if @outputs.key?(signal.name) then # The signal is present, delete it. @outputs.delete(signal.name) @interface.delete(signal) # And remove its parent. signal.parent = nil end signal end
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 391 def each_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_deep) unless ruby_block # A ruby block? First apply it to current. ruby_block.call(self) # Then apply on each signal. self.each_signal do |signal| signal.each_deep(&ruby_block) end # Then apply on each scope. self.each_scope do |scope| scope.each_deep(&ruby_block) end end
Iterates over the inout signals.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 237 def each_inout(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_inout) unless ruby_block # A ruby block? Apply it on each inout signal instance. @inouts.each(&ruby_block) end
Iterates over the input signals.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 217 def each_input(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_input) unless ruby_block # A ruby block? Apply it on each input signal instance. @inputs.each(&ruby_block) end
Iterates over the output signals.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 227 def each_output(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_output) unless ruby_block # A ruby block? Apply it on each output signal instance. @outputs.each(&ruby_block) end
Iterates over all the signals of the interface of the system.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 248 def each_signal(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_signal) unless ruby_block # A ruby block? Apply it on each signal instance. @interface.each(&ruby_block) end
Iterates over all the signals of the system including its scope (input, output, inout, inner).
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 259 def each_signal_all(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_signal) unless ruby_block # A ruby block? Apply it on each signal instance. @inputs.each(&ruby_block) @outputs.each(&ruby_block) @inouts.each(&ruby_block) end
Iterates over all the signals of the system type and its scope.
# File lib/HDLRuby/hruby_low.rb, line 269 def each_signal_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_signal_deep) unless ruby_block # A ruby block? # First iterate over the current system type's signals. self.each_signal_all(&ruby_block) # Then apply on the behaviors (since in HDLRuby:High, blocks can # include signals). @scope.each_signal_deep(&ruby_block) end
Iterates over the systemT deeply if any.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 409 def each_systemT_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_systemT_deep) unless ruby_block # A ruby block? First apply it to current. ruby_block.call(self) # And recurse on the systemT accessible through the instances. self.scope.each_scope_deep do |scope| scope.each_systemI do |systemI| # systemI.systemT.each_systemT_deep(&ruby_block) systemI.each_systemT do |systemT| systemT.each_systemT_deep(&ruby_block) end end end end
Comparison for hash: structural comparison.
# File lib/HDLRuby/hruby_low.rb, line 125 def eql?(obj) return false unless obj.is_a?(SystemT) return false unless @name.eql?(obj.name) return false unless @scope.eql?(obj.scope) idx = 0 obj.each_input do |input| return false unless @inputs[input.name].eql?(input) idx += 1 end return false unless idx == @inputs.size idx = 0 obj.each_output do |output| return false unless @outputs[output.name].eql?(output) idx += 1 end return false unless idx == @outputs.size idx = 0 obj.each_inout do |inout| return false unless @inouts[inout.name].eql?(inout) idx += 1 end return false unless idx == @inouts.size return true end
Explicit the types conversions in the system.
# File lib/HDLRuby/hruby_low_fix_types.rb, line 18 def explicit_types! # No direct fix required in the system, recurse on the scope. self.scope.explicit_types! return self end
Extracts the assignments to port systemI.signal
and returns the resulting reference to a port wire.
NOTE: assumes to_upper_space! and with_port! has been called.
# File lib/HDLRuby/hruby_verilog.rb, line 1773 def extract_port_assign!(systemI,signal) # Extract the assignment. assign = nil self.each_connection.to_a.each do |connection| if self.port_assign?(connection.left,systemI,signal) then # The left is the port. # Delete the connection. self.scope.delete_connection!(connection) # And return a copy of the right. return connection.right.clone elsif self.port_assign?(connection.right,systemI,signal) then # The right is the port. # Delete the connection. self.scope.delete_connection!(connection) # And return a copy of the left. return connection.left.clone end end # No port found, nothing to do return nil end
Gets an array containing all the inout signals.
# File lib/HDLRuby/hruby_low.rb, line 312 def get_all_inouts return each_inout.to_a end
Gets an array containing all the input signals.
# File lib/HDLRuby/hruby_low.rb, line 302 def get_all_inputs return each_input.to_a end
Gets an array containing all the output signals.
# File lib/HDLRuby/hruby_low.rb, line 307 def get_all_outputs return each_output.to_a end
Gets an array containing all the signals.
# File lib/HDLRuby/hruby_low.rb, line 317 def get_all_signals return each_signal.to_a end
Find an inner object by name
. NOTE: return nil if not found.
# File lib/HDLRuby/hruby_low_resolve.rb, line 20 def get_by_name(name) # Ensure the name is a symbol. name = name.to_sym # Look in the interface. found = self.get_signal(name) return found if found # Maybe it is the scope. return self.scope if self.scope.name == name # Look in the scope. return self.scope.get_by_name(name) end
Gets an inout signal by name
.
# File lib/HDLRuby/hruby_low.rb, line 332 def get_inout(name) return @inouts[name.to_sym] end
Gets an input signal by name
.
# File lib/HDLRuby/hruby_low.rb, line 322 def get_input(name) return @inputs[name.to_sym] end
Gets an interface signal by order of declaration i
.
# File lib/HDLRuby/hruby_low.rb, line 348 def get_interface(i) return @interface[i] end
Gets an output signal by name
.
# File lib/HDLRuby/hruby_low.rb, line 327 def get_output(name) return @outputs[name.to_sym] end
Gets a signal by name
.
# File lib/HDLRuby/hruby_low.rb, line 342 def get_signal(name) return get_input(name) || get_output(name) || get_inout(name) # || # get_inner(name) end
Tells if there is any output signal.
# File lib/HDLRuby/hruby_low.rb, line 291 def has_inout? return !@inouts.empty? end
Tells if there is any input signal.
# File lib/HDLRuby/hruby_low.rb, line 281 def has_input? return !@inputs.empty? end
Tells if there is any output signal.
# File lib/HDLRuby/hruby_low.rb, line 286 def has_output? return !@outputs.empty? end
Tells if there is any signal (including in the scope of the system).
# File lib/HDLRuby/hruby_low.rb, line 296 def has_signal? return ( self.has_input? or self.has_output? or self.has_inout? or self.has_inner? ) end
Hash
function.
# File lib/HDLRuby/hruby_low.rb, line 151 def hash return [@name,@scope,@inputs,@outputs,@inouts].hash end
Converts initial concat of values of signals to assignment in timed blocks (for making the code compatible with verilog translation).
NOTE: Assumes such array as at the top level.
# File lib/HDLRuby/hruby_low_without_concat.rb, line 30 def initial_concat_to_timed! self.scope.initial_concat_to_timed! end
Maps on the inouts.
# File lib/HDLRuby/hruby_low_mutable.rb, line 54 def map_inouts!(&ruby_block) @inouts.map! do |inout| inout = ruby_block.call(inout) inout.parent = self unless inout.parent inout end end
Maps on the inputs.
# File lib/HDLRuby/hruby_low_mutable.rb, line 36 def map_inputs!(&ruby_block) @inputs.map! do |input| input = ruby_block.call(input) input.parent = self unless input.parent input end end
Maps on the outputs.
# File lib/HDLRuby/hruby_low_mutable.rb, line 45 def map_outputs!(&ruby_block) @outputs.map! do |output| output = ruby_block.call(output) output.parent = self unless output.parent output end end
Converts the par sub blocks to seq if they are not full par.
# File lib/HDLRuby/hruby_low2seq.rb, line 28 def mixblocks2seq! # Recurse on the scope. self.scope.mixblocks2seq! end
Replace read of output signal to read of intermediate inner signal.
NOTE: the result is the same systemT.
# File lib/HDLRuby/hruby_low_without_outread.rb, line 23 def outread2inner! # puts "For system: #{self.name}" # First gather the read on output signals. outreads = {} gather_outreads = proc do |node| # puts "node=#{node.name}" if node.is_a?(RefName) if node.is_a?(RefName) && !node.leftvalue? then name = node.name # puts "name=#{name}" sig = self.get_output(name) outreads[node.name] = node if sig end end # Apply the procedure for gathering the read on outputs signals. self.scope.each_scope_deep do |scope| scope.each_connection do |connection| connection.each_node_deep(&gather_outreads) end scope.each_behavior do |behavior| behavior.each_event do |event| gather_outreads.(event.ref) end behavior.each_statement do |statement| # puts "statement=#{statement.class}" statement.each_node_deep(&gather_outreads) end end end # puts "outreads=#{outreads.keys}" # Generate one inner signal per read output. out2inner = {} outreads.each do |name,node| # Generate the inner variable. out2inner[name] = self.scope.add_inner(SignalI.new(HDLRuby::uniq_name,node.type)) # puts "new inner=#{out2inner[name].name}" end # Replace the output by the corresponding inner in the # expressions. replace_name = proc do |node| # The replacement procedure. # Only single name reference are to be replaced, the others # cannot correspond to output signal. if node.is_a?(RefName) && node.ref.is_a?(RefThis) && !node.parent.is_a?(RefName) then inner = out2inner[node.name] # puts "node=#{node.name} inner=#{inner}" # puts "Replace name: #{node.name} by #{inner.name}" if inner node.set_name!(inner.name) if inner end end # Apply the replacement procedure on the code self.scope.each_scope_deep do |scope| scope.each_connection do |connection| connection.each_node_deep do |node| replace_name.(node) end end scope.each_behavior do |behavior| behavior.each_event do |event| event.ref.each_node_deep do |node| replace_name.(node) end end behavior.each_statement do |statement| statement.each_node_deep do |node| replace_name.(node) end end end end # Finally connect the inner to the output. out2inner.each do |out,inner| self.scope.add_connection( Connection.new(RefName.new(inner.type,RefThis.new,out), RefName.new(inner.type,RefThis.new,inner.name))) end return self end
Converts par blocks within seq blocks to seq blocks.
# File lib/HDLRuby/hruby_low_without_parinseq.rb, line 21 def par_in_seq2seq! self.scope.par_in_seq2seq! end
Tells if an expression is a reference to port systemI.signal
.
# File lib/HDLRuby/hruby_verilog.rb, line 1764 def port_assign?(expr, systemI, signal) return expr.is_a?(RefName) && expr.name == signal.name && expr.ref.is_a?(RefName) && expr.ref.name == systemI.name end
Tells if a connection is actually a port connection.
# File lib/HDLRuby/hruby_verilog.rb, line 1750 def port_output_connection?(connection) return self.each_systemI.find do |systemI| if connection.right.is_a?(RefName) && connection.right.ref.is_a?(RefName) && systemI.name == connection.right.ref.name puts "port_connection for right=#{connection.right.name} and systemI=#{systemI.name}" true else false end end end
Replaces recursively former
name by nname
until it is redeclared.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 60 def replace_names!(former,nname) # Replace owns name if required. if self.name == former then self.set_name!(nname) end # Recurse on the interface. self.each_input {|input| input.replace_names!(former,nname) } self.each_output {|output| output.replace_names!(former,nname) } self.each_inout {|inout| inout.replace_names!(former,nname) } # Recurse on the scope. self.scope.replace_names!(former,nname) end
Sets the name
.
# File lib/HDLRuby/hruby_low_mutable.rb, line 22 def set_name!(name) @name = name.to_sym end
Sets the scope
.
# File lib/HDLRuby/hruby_low_mutable.rb, line 27 def set_scope!(scope) unless scope.is_a?(Scope) then raise AnyError, "Invalid class for a scope: #{scope.class}" end scope.parent = self @scope = scope end
Generates the text of the equivalent HDLRuby
code. level
is the hierachical level of the object and hnames
is the list of extra h files to include.
# File lib/HDLRuby/hruby_low2c.rb, line 155 def to_c(level = 0, *hnames) # The header res = Low2C.includes(*hnames) # Declare the global variable holding the system. res << "SystemT #{Low2C.obj_name(self)};\n\n" # Generate the signals of the system. self.each_signal { |signal| res << signal.to_c(level) } # Generate the code for all the blocks included in the system. self.scope.each_scope_deep do |scope| scope.each_behavior do |behavior| res << behavior.block.to_c_code(level) end end # Generate the code for all the values included in the system. self.each_signal do |signal| # res << signal.value.to_c_make(level) if signal.value signal.value.each_node_deep do |node| res << node.to_c_make(level) if node.respond_to?(:to_c_make) end if signal.value end self.scope.each_scope_deep do |scope| scope.each_inner do |signal| # res << signal.value.to_c_make(level) if signal.value signal.value.each_node_deep do |node| res << node.to_c_make(level) if node.respond_to?(:to_c_make) end if signal.value end end self.scope.each_block_deep do |block| # puts "treating for block=#{Low2C.obj_name(block)} with=#{block.each_inner.count} inners" block.each_inner do |signal| # res << signal.value.to_c_make(level) if signal.value signal.value.each_node_deep do |node| res << node.to_c_make(level) if node.respond_to?(:to_c_make) end if signal.value end end self.scope.each_node_deep do |node| res << node.to_c_make(level) if node.is_a?(Value) end # Generate the scope. res << self.scope.to_c(level) # Generate the entity res << "SystemT #{Low2C.make_name(self)}() {\n" # Creates the structure. res << " " * (level+1)*3 res << "SystemT systemT = malloc(sizeof(SystemTS));\n" res << " " * (level+1)*3 res << "systemT->kind = SYSTEMT;\n"; # Sets the global variable of the system. res << "\n" res << " " * (level+1)*3 res << "#{Low2C.obj_name(self)} = systemT;\n" # Set the owner if any. if @owner then res << " " * (level+1)*3 res << "systemT->owner = (Object)" + "#{Low2C.obj_name(@owner)};\n" else res << "systemT->owner = NULL;\n" end # The name res << " " * (level+1)*3 res << "systemT->name = \"#{self.name}\";\n" # The ports # Inputs res << " " * (level+1)*3 res << "systemT->num_inputs = #{self.each_input.to_a.size};\n" res << " " * (level+1)*3 res << "systemT->inputs = calloc(sizeof(SignalI)," + "systemT->num_inputs);\n" self.each_input.with_index do |input,i| res << " " * (level+1)*3 res << "systemT->inputs[#{i}] = " + "#{Low2C.make_name(input)}();\n" end # Outputs res << " " * (level+1)*3 res << "systemT->num_outputs = #{self.each_output.to_a.size};\n" res << " " * (level+1)*3 res << "systemT->outputs = calloc(sizeof(SignalI)," + "systemT->num_outputs);\n" self.each_output.with_index do |output,i| res << " " * (level+1)*3 res << "systemT->outputs[#{i}] = " + "#{Low2C.make_name(output)}();\n" end # Inouts res << " " * (level+1)*3 res << "systemT->num_inouts = #{self.each_inout.to_a.size};\n" res << " " * (level+1)*3 res << "systemT->inouts = calloc(sizeof(SignalI)," + "systemT->num_inouts);\n" self.each_inout.with_index do |inout,i| res << " " * (level+1)*3 res << "systemT->inouts[#{i}] = " + "#{Low2C.make_name(inout)}();\n" end # Adds the scope. res << "\n" res << " " * (level+1)*3 res << "systemT->scope = #{Low2C.make_name(self.scope)}();\n" # Generate the Returns of the result. res << "\n" res << " " * (level+1)*3 res << "return systemT;\n" # End of the system. res << " " * level*3 res << "}" # Return the result. return res end
Generates the code for an execution starting from the system.
level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2c.rb, line 283 def to_c_code(level) res << " " * (level*3) res << "#{Low2C.code_name(self)}() {\n" # res << "printf(\"Executing #{Low2C.code_name(self)}...\\n\");" # Launch the execution of all the time behaviors of the # system. self.each_behavior_deep do |behavior| if behavior.is_a?(HDLRuby::Low::TimeBehavior) then res << " " * (level+1)*3 res << "#{Low2C.code_name(behavior.block)}();\n" end end # Close the execution procedure. res << " " * level*3 res << "}\n" # Return the result. return res end
Generates the content of the h file.
# File lib/HDLRuby/hruby_low2c.rb, line 304 def to_ch res = "" # Declare the global variable holding the signal. res << "extern SystemT #{Low2C.obj_name(self)};\n\n" # Generate the access to the function making the systemT. */ res << "extern SystemT #{Low2C.make_name(self)}();\n\n" # Generate the accesses to the values. self.each_signal do |signal| # res << signal.value.to_ch if signal.value if signal.value then signal.value.each_node_deep do |node| res << node.to_ch if node.is_a?(Value) end end end self.scope.each_scope_deep do |scope| scope.each_inner do |signal| # res << signal.value.to_ch if signal.value if signal.value then signal.value.each_node_deep do |node| res << node.to_ch if node.is_a?(Value) end end end end self.scope.each_block_deep do |block| block.each_inner do |signal| res << signal.value.to_ch if signal.value end block.each_node_deep do |node| res << node.to_ch if node.is_a?(Value) end end # Generate the accesses to the ports. self.each_input { |input| res << input.to_ch } self.each_output { |output| res << output.to_ch } self.each_inout { |inout| res << inout.to_ch } # Generate the accesses to the scope. res << self.scope.to_ch << "\n" return res; end
Moves local systemTs to global.
NOTE: assumes to_upper_space! has been called.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 44 def to_global_systemTs! # Force a name if not. self.force_name! # For each local systemT self.scope.each_systemT.to_a.each do |systemT| # Rename it for globalization. former = systemT.name self.extend_name!(systemT) # Apply the renaming to all the inner objects. self.scope.replace_names_subs!(former,systemT.name) # Remove it. self.scope.delete_systemT!(systemT) end end
Generates the text of the equivalent hdr text. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2hdr.rb, line 64 def to_hdr(level = 0) # The resulting string. res = "" # Generate the header. res << " " * (level*3) res << "system :#{Low2HDR.hdr_decl_name(self.name)} do\n" # Generate the interface. # Inputs. self.each_input do |input| res << " " * ((level+1)*3) res << input.type.to_hdr(level+1) res << ".input :" << Low2HDR.hdr_decl_name(input.name) res << "\n" end # Outputs. self.each_output do |output| res << " " * ((level+1)*3) res << output.type.to_hdr(level+1) res << ".output :" << Low2HDR.hdr_decl_name(output.name) res << "\n" end # Inouts. self.each_inout do |inout| res << " " * ((level+1)*3) res << inout.type.to_hdr(level+1) res << ".inout :" << Low2HDR.hdr_decl_name(inout.name) res << "\n" end # Generate the scope. res << " " * (level*3) res << "\n" res << self.scope.to_hdr(level+1,false) # End of the system. res << " " * (level*3) res << "end\n\n" # Return the result. return res end
Creates a new high system type named name
with scope
.
# File lib/HDLRuby/hruby_low2high.rb, line 17 def to_high # Create the high system type. res = HDLRuby::High::SystemT.new(self.name,self.scope.to_high) # Add the inputs. self.each_input { |i| res.add_input(i.to_high) } # Add the outputs. self.each_output { |o| res.add_output(o.to_high) } # Add the inouts. self.each_inout { |io| res.add_inout(io.to_high) } return res end
Moves the declarations to the upper namespace.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 37 def to_upper_space! self.scope.to_upper_space! end
Converts the system to Verilog
code.
# File lib/HDLRuby/hruby_verilog.rb, line 1798 def to_verilog # Detect the registers HDLRuby::Low::VERILOG_REGS.clear # The left values. self.each_behavior do |behavior| behavior.each_block_deep do |block| block.each_statement do |statement| if statement.is_a?(Transmit) HDLRuby::Low::VERILOG_REGS << statement.left.to_verilog end end end end # And the initialized signals. self.each_output do |output| # regs << output.to_verilog if output.value HDLRuby::Low::VERILOG_REGS << output.to_verilog if output.value end self.each_inner do |inner| # regs << inner.to_verilog if inner.value HDLRuby::Low::VERILOG_REGS << inner.to_verilog if inner.value end # And the array types signals. self.each_signal do |sig| if sig.type.vector? && sig.type.base.vector? then HDLRuby::Low::VERILOG_REGS << sig.to_verilog end end self.each_inner do |sig| if sig.type.vector? && sig.type.base.vector? then HDLRuby::Low::VERILOG_REGS << sig.to_verilog end end # Code generation inputs = 0 outputs = 0 inout = 0 inputs = self.each_input.to_a outputs = self.each_output.to_a inout = self.each_inout.to_a # Spelling necessary for simulation. code = "`timescale 1ps/1ps\n\n" vname = name_to_verilog(self.name) self.properties[:verilog_name] = vname # Output the module name. code << "module #{vname}(" # Output the last two to the input. inputs[0..-2].each do |input| code << " #{input.to_verilog}," end # When only input is used, it is necessary to close (), so it branches with if. if outputs.empty? && inout.empty? then if (inputs.empty?) code << " ); \n" end else code << " #{inputs.last.to_verilog}," unless inputs.empty? end # Output the last two to the output. outputs[0..-2].each do |output| code << " #{output.to_verilog}," end # When only input and output are used, it is necessary to close (), so it branches with if. if inout.empty? then code << " #{outputs.last.to_verilog} ); \n" unless outputs.empty? else code << " #{outputs.last.to_verilog}," unless outputs.empty? end # Output the last two to the inout. inout[0..-2].each do |inout| code << " #{inout.to_verilog}," end # There is no comma as it is the last one code << " #{inout.last.to_verilog} ); \n" unless inout.empty? # Declare "input" self.each_input do |input| if input.type.respond_to? (:each_type) then $vector_reg = "#{input.to_verilog}" $vector_cnt = 0 input.type.each_type do |type| code << "input #{type.to_verilog} #{$vector_reg}:#{$vector_cnt};\n" $vector_cnt += 1 end else code << " input#{input.type.to_verilog} #{input.to_verilog};\n" end end # Declare "output" self.each_output do |output| if output.type.respond_to? (:each_type) then $vector_reg = "#{output.to_verilog}" $vector_cnt = 0 output.type.each_type do |type| # if regs.include?(type.name) then if HDLRuby::Low::VERILOG_REGS.include?(type.name) then code << " output reg" else code << " output" end code << "#{type.to_verilog} #{$vector_reg}:#{$vector_cnt}" if output.value then # There is an initial value. code << " = #{output.value.to_verilog}" end code << ";\n" $vector_cnt += 1 end else if HDLRuby::Low::VERILOG_REGS.include?(output.to_verilog) then code << " output reg" else code << " output" end code << "#{output.type.to_verilog} #{output.to_verilog}" if output.value then # There is an initial value. code << " = #{output.value.to_verilog}" end code << ";\n" end end # Declare "inout" self.each_inout do |inout| if inout.type.respond_to? (:each_type) then $vector_reg = "#{inout.to_verilog}" $vector_cnt = 0 inout.type.each_type do |type| code << "inout #{type.to_verilog} #{$vector_reg}:#{$vector_cnt};\n" $vector_cnt += 1 end else code << " inout#{inout.type.to_verilog} #{inout.to_verilog};\n" end end # Declare "inner". self.each_inner do |inner| if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then code << " reg" else code << " wire" end if inner.type.base? if inner.type.base.base? code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog}" else code << "#{inner.type.to_verilog} #{inner.to_verilog}" end else code << " #{inner.type.to_verilog}#{inner.to_verilog}" end if inner.value then # There is an initial value. code << " = #{inner.value.to_verilog}" end code << ";\n" end # If there is scope in scope, translate it. self.each_scope do |scope| scope.each_inner do |inner| if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then code << " reg " else code << " wire " end if inner.type.respond_to? (:base) if inner.type.base.base? code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog}" else code << "#{inner.type.to_verilog} #{inner.to_verilog}" end else code << "inner #{inner.type.to_verilog} #{inner.to_verilog}" end if inner.value then # There is an initial value. code << " = #{inner.value.to_verilog}" end code << ";\n" end scope.each_connection do |connection| code << "\n" code << "#{connection.to_verilog}" end end code << "\n" # puts "For system=#{self.name}" # transliation of the instantiation part. # Generate the instances connections. self.each_systemI do |systemI| # puts "Processing systemI = #{systemI.name}" # Its Declaration. code << " " * 3 systemT = systemI.systemT code << name_to_verilog(systemT.name) << " " vname = name_to_verilog(systemI.name) systemI.properties[:verilog_name] = vname code << vname << "(" # Its ports connections # Inputs systemT.each_input do |input| ref = self.extract_port_assign!(systemI,input) if ref then code << "." << name_to_verilog(input.name) << "(" code << ref.to_verilog code << ")," end end # Outputs systemT.each_output do |output| ref = self.extract_port_assign!(systemI,output) if ref then code << "." << name_to_verilog(output.name) << "(" code << ref.to_verilog code << ")," end end # Inouts systemT.each_inout do |inout| ref = self.extract_port_assign!(systemI,inout) if ref then code << "." << name_to_verilog(inout.name) << "(" code << ref.to_verilog code << ")," end end # Remove the last "," for conforming with Verilog syntax. # and close the port connection. code[-1] = ");\n" end # translation of the connection part (assigen). self.each_connection do |connection| code << "#{connection.to_verilog}\n" end # Translation of behavior part (always). self.each_behavior do |behavior| if behavior.block.is_a?(TimeBlock) then # Extract and translate the TimeRepeat separately. behavior.each_block_deep do |blk| code << blk.repeat_to_verilog! end # And generate an initial block. code << " initial " else # Generate a standard process. code << " always @( " # If there is no "always" condition, it is always @("*"). if behavior.each_event.to_a.empty? then code << "*" else event = behavior.each_event.to_a event[0..-2].each do |event| # If "posedge" or "negedge" does not exist, the variable is set to condition. if (event.type.to_s != "posedge" && event.type.to_s != "negedge") then code << "#{event.ref.to_verilog}, " else # Otherwise, it outputs "psoedge" or "negedge" as a condition. code << "#{event.type.to_s} #{event.ref.to_verilog}, " end end # Since no comma is necessary at the end, we try not to separate commas separately at the end. if (event.last.type.to_s != "posedge" && event.last.type.to_s != "negedge") then code << "#{event.last.ref.to_verilog}" else code << "#{event.last.type.to_s} #{event.last.ref.to_verilog}" end end code << " ) " end code << behavior.block.to_verilog end # Conclusion. code << "\nendmodule" return code end
Generates the text of the equivalent HDLRuby::High
code. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2vhd.rb, line 348 def to_vhdl(level = 0) # The resulting string. res = "" # Generate the entity # The header res << Low2VHDL.packages(" " * (level*3)) res << " " * (level*3) res << "entity #{Low2VHDL.entity_name(self.name)} is\n" # The ports if self.each_input.any? || self.each_output.any? || self.each_inout.any? then res << " " * ((level+1)*3) res << "port (\n" # Inputs self.each_input do |input| res << " " * ((level+2)*3) res << Low2VHDL.vhdl_name(input.name) << ": in " res << input.type.to_vhdl << ";\n" end # Outputs self.each_output do |output| res << " " * ((level+2)*3) res << Low2VHDL.vhdl_name(output.name) << ": out " res << output.type.to_vhdl << ";\n" end # Inouts self.each_inout do |inout| res << " " * ((level+2)*3) res << Low2VHDL.vhdl_name(inout.name) << ": inout " res << inout.type.to_vhdl << ";\n" end # Remove the last ";" for conforming with VHDL syntax. res[-2..-1] = "\n" if res[-2] == ";" res << " " * ((level+1)*3) # Close the port declaration. res << ");\n" end # Close the entity res << " " * (level*3) res << "end #{Low2VHDL.entity_name(self.name)};\n\n" # Generate the architecture. res << " " * (level*3) res << "architecture #{Low2VHDL.architecture_name(self.name)} " res << "of #{Low2VHDL.entity_name(self.name)} is\n" # Generate the scope. res << "\n" res << self.scope.to_vhdl(level+1) # End of the system. res << " " * (level*3) res << "end #{Low2VHDL.architecture_name(self.name)};\n\n" # Return the result. return res end
Converts to a variable-compatible system.
NOTE: the result is the same systemT.
# File lib/HDLRuby/hruby_low_with_bool.rb, line 59 def with_boolean! self.scope.each_scope_deep do |scope| scope.each_connection { |connection| connection.with_boolean! } scope.each_behavior { |behavior| behavior.with_boolean! } end return self end
Converts to a port-compatible system.
NOTE: the result is the same systemT.
# File lib/HDLRuby/hruby_low_with_port.rb, line 27 def with_port! self.scope.with_port! return self end
Converts to a variable-compatible system.
NOTE: the result is the same systemT.
# File lib/HDLRuby/hruby_low_with_var.rb, line 21 def with_var! self.each_behavior { |behavior| behavior.with_var! } return self end