class HDLRuby::Low::Transmit
Decribes a transmission statement.
Decribes a transmission statement.
Extends the Transmit
class with generation of C text.
Extends the Transmit
class with generation of hdr text.
Add the conversion to high.
Extends the Transmit
class with generation of HDLRuby::High
text.
Extends the Transmit
class with functionality for converting booleans in assignments to select operators.
Extends the Transmit
class with functionality for extracting expressions from cast.
Extends the Transmit
class with fixing of types and constants.
Decribes a transmission statement.
Extends the Transmit
class with functionality for breaking assingments to concats.
Extends the Transmit
class with functionality for converting select expressions to case statements.
class of Represent blocking substitution or nonblocking assignment. Enhance Transmit
with generation of verilog code.
Attributes
The left reference.
The right expression.
Public Class Methods
Creates a new transmission from a right
expression to a left
reference.
# File lib/HDLRuby/hruby_low.rb, line 2933 def initialize(left,right) # Check and set the left reference. unless left.is_a?(Ref) raise AnyError, "Invalid class for a reference (left value): #{left.class}" end super() @left = left # and set its parent. left.parent = self # Check and set the right expression. unless right.is_a?(Expression) raise AnyError, "Invalid class for an expression (right value): #{right.class}" end @right = right # and set its parent. right.parent = self end
Public Instance Methods
Converts booleans in assignments to select operators.
# File lib/HDLRuby/hruby_low_bool2select.rb, line 56 def boolean_in_assign2select! # Apply on the left value. self.set_left!(self.left.boolean_in_assign2select) # Apply on the right value. self.set_right!(self.right.boolean_in_assign2select) return self end
Break the assignments to concats.
NOTE: when breaking generates a new Block
containing the broken
assignments.
# File lib/HDLRuby/hruby_low_without_concat.rb, line 133 def break_concat_assigns # puts "break_concat_assigns with self=#{self}" # Is the left value a RefConcat? self.left.each_node_deep do |node| if node.is_a?(RefConcat) then # Yes, must break. Create the resulting sequential # block that will contain the new assignements. block = Block.new(:seq) # Create an intermediate signal for storing the # right value. Put it in the top scope. top_block = self.top_block top_scope = top_block.top_scope aux = top_scope.add_inner( SignalI.new(HDLRuby.uniq_name,self.right.type) ) # puts "new signal: #{aux.name}" aux = RefName.new(aux.type,RefThis.new,aux.name) # Is a default value required to avoid latch generation? unless top_block.parent.each_event. find {|ev| ev.type!=:change} then # Yes, generate it. top_block.insert_statement!(0, Transmit.new(aux.clone,Value.new(aux.type,0))) end # Replace the concat in the copy of the left value. if left.eql?(node) then # node was the top of left, replace here. nleft = aux else # node was inside left, replace within left. nleft = self.left.clone nleft.each_node_deep do |ref| ref.map_nodes! do |sub| sub.eql?(node) ? aux.clone : sub end end end # Recreate the transmit and add it to the block. block.add_statement( Transmit.new(nleft,self.right.clone) ) # And assign its part to each reference of the # concat. pos = 0 node.each_ref.reverse_each do |ref| # Compute the range to assign. range = ref.type.width-1+pos .. pos # Single or multi-bit range? sbit = range.first == range.last # Convert the range to an HDLRuby range for # using is the resulting statement. # Create and add the statement. if sbit then # Single bit. # Generate the index. idx = Value.new(Integer,range.first) # Generate the assignment. block.add_statement( Transmit.new(ref.clone, # RefIndex.new(aux.type.base, aux.clone, idx))) RefIndex.new(bit, aux.clone, idx))) else # Multi-bits. # Compute the type of the right value. # rtype = TypeVector.new(:"",aux.type.base,range) rtype = TypeVector.new(:"",bit,range) # Generate the range. range = Value.new(Integer,range.first) .. Value.new(Integer,range.last) # Generate the assignment. block.add_statement( Transmit.new(ref.clone, RefRange.new(rtype, aux.clone, range))) end pos += ref.type.width end # puts "Resulting block=#{block.to_vhdl}" # Return the resulting block return block end end # No, nothing to do. return self end
Extracts the expressions from the casts.
# File lib/HDLRuby/hruby_low_casts_without_expression.rb, line 57 def casts_without_expression! # Apply on the left value. self.set_left!(self.left.casts_without_expression) # Apply on the right value. self.set_right!(self.right.casts_without_expression) return self end
Clones the transmit (deeply)
# File lib/HDLRuby/hruby_low.rb, line 2980 def clone return Transmit.new(@left.clone, @right.clone) end
Iterates over the sub blocks.
# File lib/HDLRuby/hruby_low.rb, line 3016 def each_block(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_block) unless ruby_block # A ruby block? # Nothing to do. end
Iterates over all the blocks contained in the current block.
# File lib/HDLRuby/hruby_low.rb, line 3024 def each_block_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_block_deep) unless ruby_block # A ruby block? # Nothing to do. end
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 2955 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 the left. self.left.each_deep(&ruby_block) # Then apply on the right. self.right.each_deep(&ruby_block) end
Iterates over the children if any.
# File lib/HDLRuby/hruby_low.rb, line 2985 def each_node(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_node) unless ruby_block # A ruby block? Apply it on the children. ruby_block.call(@left) ruby_block.call(@right) end
Iterates over the nodes deeply if any.
# File lib/HDLRuby/hruby_low.rb, line 2996 def each_node_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_node_deep) unless ruby_block # A ruby block? First apply it to current. ruby_block.call(self) # And recurse on the children @left.each_node_deep(&ruby_block) @right.each_node_deep(&ruby_block) end
Iterates over all the stamements of the block and its sub blocks.
# File lib/HDLRuby/hruby_low.rb, line 3007 def each_statement_deep(&ruby_block) # No ruby statement? Return an enumerator. return to_enum(:each_statement_deep) unless ruby_block # A ruby block? # Apply it on self. ruby_block.call(self) end
Comparison for hash: structural comparison.
# File lib/HDLRuby/hruby_low.rb, line 2967 def eql?(obj) return false unless obj.is_a?(Transmit) return false unless @left.eql?(obj.left) return false unless @right.eql?(obj.right) return true end
Explicit the types conversions in the statement.
# File lib/HDLRuby/hruby_low_fix_types.rb, line 82 def explicit_types! # Recurse on the left and the right. self.set_left!(self.left.explicit_types) # The right have to match the left type. self.set_right!(self.right.explicit_types(self.left.type)) return self end
Extract the Select
expressions.
# File lib/HDLRuby/hruby_low_without_select.rb, line 158 def extract_selects! selects = [] self.set_left!(self.left.extract_selects_to!(selects)) self.set_right!(self.right.extract_selects_to!(selects)) return selects end
Hash
function.
# File lib/HDLRuby/hruby_low.rb, line 2975 def hash return [@left,@right].hash end
Maps on the children.
# File lib/HDLRuby/hruby_low_mutable.rb, line 584 def map_nodes!(&ruby_block) @left = ruby_block.call(@left) left.parent = self unless left.parent @right = ruby_block.call(@right) right.parent = self unless right.parent end
Replaces sub expressions using node2rep
table indicating the node to replace and the corresponding replacement. Returns the actually replaced nodes and their corresponding replacement.
NOTE: the replacement is duplicated.
# File lib/HDLRuby/hruby_low_mutable.rb, line 597 def replace_expressions!(node2rep) # First recurse on the children. res = self.left.replace_expressions!(node2rep) res.merge!(self.right.replace_expressions!(node2rep)) # Is there a replacement to do on the left? rep = node2rep[self.left] if rep then # Yes, do it. rep = rep.clone node = self.left # node.set_parent!(nil) self.set_left!(rep) # And register the replacement. res[node] = rep end # Is there a replacement to do on the right? rep = node2rep[self.right] if rep then # Yes, do it. rep = rep.clone node = self.right # node.set_parent!(nil) self.set_right!(rep) # And register the replacement. res[node] = rep end return res end
Sets the left.
# File lib/HDLRuby/hruby_low_mutable.rb, line 561 def set_left!(left) # Check and set the left reference. unless left.is_a?(Ref) raise AnyError, "Invalid class for a reference (left value): #{left.class}" end @left = left # and set its parent. left.parent = self end
Sets the right.
# File lib/HDLRuby/hruby_low_mutable.rb, line 573 def set_right!(right) # Check and set the right expression. unless right.is_a?(Expression) raise AnyError, "Invalid class for an expression (right value): #{right.class}" end @right = right # and set its parent. right.parent = self end
Generates the C text of the equivalent HDLRuby
code. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2c.rb, line 1096 def to_c(level = 0) # Save the state of the value pool. res = (" " * ((level)*3)) res << "{\n" res << (" " * ((level+1)*3)) res << "unsigned int pool_state = get_value_pos();\n" # Perform the copy and the touching only if the new content # is different. res << (" " * ((level+1)*3)) # Is it a sequential execution model? seq = self.block.mode == :seq ? "_seq" : "" # Generate the assignment. if (self.left.is_a?(RefName)) then # Direct assignment to a signal, simple transmission. res << "transmit_to_signal#{seq}(#{self.right.to_c(level)},"+ "#{self.left.to_c_signal(level)});\n" else # Assignment inside a signal (RefIndex or RefRange). res << "transmit_to_signal_range#{seq}(#{self.right.to_c(level)},"+ "#{self.left.to_c_signal(level)});\n" end # Restore the value pool state. res << (" " * ((level+1)*3)) res << "set_value_pos(pool_state);\n" res << (" " * ((level)*3)) res << "}\n" return res end
Generates the text of the equivalent hdr text. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2hdr.rb, line 338 def to_hdr(level = 0) return " " * (level*3) + self.left.to_hdr(level) + " <= " + self.right.to_hdr(level) + "\n" end
Creates a new high transmit statement.
# File lib/HDLRuby/hruby_low2high.rb, line 242 def to_high return HDLRuby::High::Transmit.new(self.left.to_high, self.right.to_high) end
Converts the system to Verilog
code.
# File lib/HDLRuby/hruby_verilog.rb, line 108 def to_verilog(spc = 3) # Determine blocking assignment or nonblocking substitution from mode and return it. code = "#{" " * spc}#{self.left.to_verilog} #{self.block.mode == :seq ? "=" : "<="} #{self.right.to_verilog};" return code end
Generates the text of the equivalent HDLRuby::High
code. vars
is the list of the variables and level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2vhd.rb, line 903 def to_vhdl(vars,level = 0) # Generate the assign operator. assign = vars.any? do |var| self.left.respond_to?(:name) && var.name == self.left.name end ? " := " : " <= " # Generate the assignment. return " " * (level*3) + self.left.to_vhdl(level) + assign + Low2VHDL.to_type(self.left.type,self.right) + ";\n" end
Tell if the statement includes a signal whose name is one of names
.
# File lib/HDLRuby/hruby_low.rb, line 3032 def use_name?(*names) return @left.use_name?(*names) || @right.use_name?(*names) end