class HDLRuby::Low::Binary
Describes an binary operation.
Describes an binary operation.
Extends the Binary
class with generation of C text.
Extends the Binary
class with generation of hdr text.
Add the conversion to high.
Extends the Binary
class with generation of HDLRuby::High
text.
Extends the Binary
class with functionality for converting booleans in assignments to select operators.
Extends the Binary
class with functionality for extracting expressions from cast.
Extends the Binary
class with fixing of types and constants.
Describes an binary operation.
Extends the Binary
class for checking if it is a boolean expression or not.
A class that translates the left-hand side, operator, and right-hand side into form of expression.
Attributes
The left child.
The right child.
Public Class Methods
Creates a new binary expression with type
applying operator
on left
and right
children expressions. def initialize(operator,left,right)
# File lib/HDLRuby/hruby_low.rb, line 4778 def initialize(type,operator,left,right) # Initialize as a general operation. super(type,operator) # Check and set the children. unless left.is_a?(Expression) raise AnyError, "Invalid class for an expression: #{left.class}" end unless right.is_a?(Expression) raise AnyError,"Invalid class for an expression: #{right.class}" end @left = left @right = right # And set their parents. left.parent = right.parent = self end
Public Instance Methods
Tells if the expression is boolean.
# File lib/HDLRuby/hruby_low_with_bool.rb, line 116 def boolean? case(self.operator) when :==,:!=,:>,:<,:>=,:<= then # Comparison, it is a boolean. return true when :&,:|,:^ then # AND, OR or XOR, boolean if both subs are boolean. return self.left.boolean? && self.right.boolean? else # Other cases: not boolean. return false end end
Converts booleans in assignments to select operators.
# File lib/HDLRuby/hruby_low_bool2select.rb, line 211 def boolean_in_assign2select # Recurse on the sub nodes. nleft = self.left.boolean_in_assign2select nright = self.right.boolean_in_assign2select # Is it a comparison but the parent is not a boolean? # or a transmit to a boolean. if [:==,:>,:<,:>=,:<=].include?(self.operator) && ( (self.parent.is_a?(Expression) && !self.parent.type.boolean?) || (self.parent.is_a?(Transmit) && !self.parent.left.type.boolean?)) then # Yes, create a select. nself = Binary.new(self.type,self.operator,nleft,nright) # return Select.new(self.type, "?", nself, return Select.new(HDLRuby::Low::Bit, "?", nself, # Value.new(self.type,1), Value.new(self.type,0) ) Value.new(HDLRuby::Low::Bit,0), Value.new(HDLRuby::Low::Bit,1) ) # Value.new(HDLRuby::Low::Boolean,0), # Value.new(HDLRuby::Low::Boolean,1) ) else # No return it as is. # self.set_left!(nleft) # self.set_right!(nright) # return self return Binary.new(self.type,self.operator,nleft,nright) end end
Extracts the expressions from the casts.
# File lib/HDLRuby/hruby_low_casts_without_expression.rb, line 238 def casts_without_expression # Recurse on the sub nodes. return Binary.new(self.type,self.operator, self.left.casts_without_expression, self.right.casts_without_expression) end
Clones the binary operator (deeply)
# File lib/HDLRuby/hruby_low.rb, line 4874 def clone return Binary.new(@type, self.operator, @left.clone, @right.clone) end
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 4803 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 type. self.type.each_deep(&ruby_block) # 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 expression children if any.
# File lib/HDLRuby/hruby_low.rb, line 4833 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 4844 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 references encountered in the expression.
NOTE: do not iterate inside the references.
# File lib/HDLRuby/hruby_low.rb, line 4857 def each_ref_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_ref_deep) unless ruby_block # puts "each_ref_deep for Binary" # A ruby block? # Recurse on the children. @left.each_ref_deep(&ruby_block) @right.each_ref_deep(&ruby_block) end
Comparison for hash: structural comparison.
# File lib/HDLRuby/hruby_low.rb, line 4817 def eql?(obj) # General comparison. return false unless super(obj) # Specific comparison. return false unless obj.is_a?(Binary) return false unless @left.eql?(obj.left) return false unless @right.eql?(obj.right) return true end
Explicit the types conversions in the binary operation where type
is the expected type of the condition if any.
# File lib/HDLRuby/hruby_low_fix_types.rb, line 269 def explicit_types(type = nil) # Find the larger child type. ctype = self.left.type.width > self.right.type.width ? self.left.type : self.right.type # Recurse on the children: match the larger type. op = Binary.new(self.type,self.operator, self.left.explicit_types(ctype), self.right.explicit_types(ctype)) # Does the type match the operation? if type && !self.type.eql?(type) then # No create a cast. return Cast.new(type,op) else # Yes, return the operation as is. return op end end
Hash
function.
# File lib/HDLRuby/hruby_low.rb, line 4828 def hash return [super,@left,@right].hash end
Tells if the expression is immutable (cannot be written.)
# File lib/HDLRuby/hruby_low.rb, line 4795 def immutable? # Immutable if both children are immutable. return left.immutable? && right.immutable? end
Maps on the child.
# File lib/HDLRuby/hruby_low_mutable.rb, line 1491 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 1504 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 1469 def set_left!(left) # Check and set the left. unless left.is_a?(Expression) raise AnyError,"Invalid class for an expression: #{left.class}" end @left = left # And set its parent. left.parent = self end
Sets the right.
# File lib/HDLRuby/hruby_low_mutable.rb, line 1480 def set_right!(right) # Check and set the right. unless right.is_a?(Expression) raise AnyError,"Invalid class for an expression: #{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 1699 def to_c(level = 0) # res = " " * (level*3) res = "({\n" # Overrides the upper src0, src1 and dst... # And allocates a new value for dst. res << (" " * ((level+1)*3)) res << "Value src0,src1,dst = get_value();\n" # Save the state of the value pool. res << (" " * ((level+1)*3)) res << "unsigned int pool_state = get_value_pos();\n" # Compute the left. res << (" " * ((level+1)*3)) res << "src0 = #{self.left.to_c(level+2)};\n" # Compute the right. res << (" " * ((level+1)*3)) res << "src1 = #{self.right.to_c(level+2)};\n" res << (" " * ((level+1)*3)) # Compute the current binary operation. case self.operator when :+ then res += "dst = add_value(src0,src1,dst);\n" when :- then res += "dst = sub_value(src0,src1,dst);\n" when :* then res += "dst = mul_value(src0,src1,dst);\n" when :/ then res += "dst = div_value(src0,src1,dst);\n" when :% then res += "dst = mod_value(src0,src1,dst);\n" when :** then res += "dst = pow_value(src0,src1,dst);\n" when :& then res += "dst = and_value(src0,src1,dst);\n" when :| then res += "dst = or_value(src0,src1,dst);\n" when :^ then res += "dst = xor_value(src0,src1,dst);\n" when :<<,:ls then res += "dst = shift_left_value(src0,src1,dst);\n" when :>>,:rs then res += "dst = shift_right_value(src0,src1,dst);\n" when :lr then res += "dst = rotate_left_value(src0,src1,dst);\n" when :rr then res += "dst = rotate_right_value(src0,src1,dst);\n" when :== then res += "dst = equal_value(src0,src1,dst);\n" + "dst = reduce_or_value(dst,dst);" when :!= then # res += "dst = not_equal_value(src0,src1,dst);\n" res += "dst = xor_value(src0,src1,dst);\n" + "dst = reduce_or_value(dst,dst);" when :> then res += "dst = greater_value(src0,src1,dst);\n" when :< then res += "dst = lesser_value(src0,src1,dst);\n" when :>= then res += "dst = greater_equal_value(src0,src1,dst);\n" when :<= then res += "dst = lesser_equal_value(src0,src1,dst);\n" else raise "Invalid binary operator: #{self.operator}." end # Restore the state of the value pool. res << (" " * ((level+1)*3)) res << "set_value_pos(pool_state);\n" # Close the computation. res << (" " * (level*3)) res << "dst; })" return res end
Method called when two or more expression terms are present. When
translating par into seq mode = seq, when translating seq to par mode = par. Search recursively and replace if hash matches identifier.
# File lib/HDLRuby/hruby_verilog.rb, line 71 def to_change(mode) # Recursively search the left side and the right side, check the identifier and replace it. if self.left.is_a? (Binary) then # If there is an expression on the left side of the right side, to_chang is executed again. left = self.left.to_change(mode) else # If you need to replace the variable, replace it. Otherwise we will get a clone. if $fm.fm_par.has_key?(self.left.to_verilog) && mode == :par then left = $fm.fm_par["#{self.left.to_verilog}"] elsif $fm.fm_seq.has_key?(self.left.to_verilog) && mode == :seq then left = $fm.fm_seq["#{self.left.to_verilog}"] else left = self.left.clone end end if self.right.is_a? (Binary) then # Recursively search the right side and the right side, check the identifier and replace it. right = self.right.to_change(mode) else # If you need to replace the variable, replace it. Otherwise we will get a clone. if $fm.fm_par.has_key?(self.right.to_verilog) && mode == :par then right = $fm.fm_par["#{self.right.to_verilog}"] elsif $fm.fm_seq.has_key?(self.right.to_verilog) && mode == :seq then right = $fm.fm_seq["#{self.right.to_verilog}"] else right = self.right.clone end end # After confirmation, we create and return an expression. return Binary.new(self.type,self.operator,left.clone,right.clone) end
Generates the text of the equivalent hdr text. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2hdr.rb, line 599 def to_hdr(level = 0) return "(" + self.left.to_hdr(level) + self.operator.to_s + self.right.to_hdr(level) + ")" end
Creates a new high binary expression.
# File lib/HDLRuby/hruby_low2high.rb, line 426 def to_high return HDLRuby::High::Binary.new(self.type.to_high,self.operator, self.left.to_high, self.right.to_high) end
Converts the system to Verilog
code.
# File lib/HDLRuby/hruby_verilog.rb, line 64 def to_verilog return "(#{self.left.to_verilog} #{self.operator} #{self.right.to_verilog})" end
Generates the text of the equivalent HDLRuby::High
code. level
is the hierachical level of the object. std_logic
tells if std_logic computation is to be done.
# File lib/HDLRuby/hruby_low2vhd.rb, line 1273 def to_vhdl(level = 0, std_logic = false) # Shifts/rotate require function call. if [:<<, :>>, :ls, :rs, :lr, :rr].include?(self.operator) then # Generate the function name. case self.operator when :<<, :ls func = "shift_left" when :>>, :rs func = "shift_right" when :lr func = "rotate_left" when :rr function = "rotate_right" else raise AnyError, "Internal unexpected error." end res = Low2VHDL.unarith_cast(self) + "(#{func}(" + Low2VHDL.to_arith(self.left) + "," + Low2VHDL.to_arith(self.right) + "))" res += "(0)" if std_logic # Force std_logic if required. return res end # Usual operators. # Generate the operator string. case self.operator when :& # puts "self.left.to_vhdl=#{self.left.to_vhdl}" # puts "self.right.to_vhdl=#{self.right.to_vhdl}" # puts "self.left.type=#{self.left.type.to_vhdl}" # puts "self.right.type=#{self.right.type.to_vhdl}" # puts "self.type=#{self.type.to_vhdl}" opr = " and " when :| opr = " or " when :^ opr = " xor " when :== opr = " = " when :!= opr = " /= " else opr = self.operator.to_s end # Is the operator arithmetic? if [:+, :-, :*, :/, :%].include?(self.operator) then # Yes, type conversion my be required by VHDL standard. res = "#{Low2VHDL.unarith_cast(self)}(" + Low2VHDL.to_arith(self.left) + opr + Low2VHDL.to_arith(self.right) + ")" res += "(0)" if std_logic # Force std_logic if required. return res # Is it a comparison ? elsif [:>, :<, :>=, :<=, :==, :!=].include?(self.operator) then # Generate comparison operation return "(" + self.left.to_vhdl(level) + opr + Low2VHDL.to_type(self.left.type,self.right) + ")" else # No, simply generate the binary operation if std_logic then return "(" + self.left.to_vhdl(level,std_logic) + opr + self.right.to_vhdl(level,std_logic) + ")" else return "(" + self.left.to_vhdl(level) + opr + Low2VHDL.to_type(self.left.type,self.right) + ")" end end end
Tell if the expression includes a signal whose name is one of names
.
# File lib/HDLRuby/hruby_low.rb, line 4868 def use_name?(*names) # Recurse on the left and the right. return @left.use_name?(*names) || @right.use_name?(*names) end