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

left[R]

The left child.

right[R]

The right child.

Public Class Methods

new(type,operator,left,right) click to toggle source

Creates a new binary expression with type applying operator on left and right children expressions. def initialize(operator,left,right)

Calls superclass method
# 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

boolean?() click to toggle source

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
boolean_in_assign2select() click to toggle source

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
casts_without_expression() click to toggle source

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
clone() click to toggle source

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
each_deep(&ruby_block) click to toggle source

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
each_expression(&ruby_block)
Alias for: each_node
each_node(&ruby_block) click to toggle source

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
Also aliased as: each_expression
each_node_deep(&ruby_block) click to toggle source

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
each_ref_deep(&ruby_block) click to toggle source

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
eql?(obj) click to toggle source

Comparison for hash: structural comparison.

Calls superclass method
# 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_types(type = nil) click to toggle source

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() click to toggle source

Hash function.

Calls superclass method
# File lib/HDLRuby/hruby_low.rb, line 4828
def hash
    return [super,@left,@right].hash
end
immutable?() click to toggle source

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
map_nodes!(&ruby_block) click to toggle source

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
replace_expressions!(node2rep) click to toggle source

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
set_left!(left) click to toggle source

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
set_right!(right) click to toggle source

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
to_c(level = 0) click to toggle source

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
to_change(mode) click to toggle source

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
to_hdr(level = 0) click to toggle source

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
to_high() click to toggle source

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
to_verilog() click to toggle source

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
to_vhdl(level = 0, std_logic = false) click to toggle source

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
use_name?(*names) click to toggle source

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