class HDLRuby::Low::If

Describes an if statement.

Describes an if statement.

Extends the If class with generation of C text.

Extends the If class with generation of hdr text.

Add the conversion to high.

Extends the If class with functionality for converting par block to seq.

Extends the If class with generation of HDLRuby::High text.

Extends the If class with functionality for converting booleans in assignments to select operators.

Extends the If class with functionality for extracting expressions from cast.

Extends the If class with functionality for breaking assingments to concats.

Extends the If class with fixing of types and constants.

Describes an if statement.

Extends the If class with separation between signals and variables.

Extends the If class with functionality for moving the declarations to the upper namespace.

Extends the If class with functionality for breaking assingments to concats.

Extends the If class with functionality for converting select expressions to case statements.

Used to transrate if. Enhance If with generation of verilog code.

Attributes

condition[R]

The condition

no[R]

The yes and no statements

yes[R]

The yes and no statements

Public Class Methods

new(condition, yes, no = nil) click to toggle source

Creates a new if statement with a condition and a yes and no blocks.

Calls superclass method
# File lib/HDLRuby/hruby_low.rb, line 3049
def initialize(condition, yes, no = nil)
    # Check and set the condition.
    unless condition.is_a?(Expression)
        raise AnyError,
              "Invalid class for a condition: #{condition.class}"
    end
    super()
    @condition = condition
    # And set its parent.
    condition.parent = self
    # Check and set the yes statement.
    unless yes.is_a?(Statement)
        raise AnyError, "Invalid class for a statement: #{yes.class}"
    end
    @yes = yes
    # And set its parent.
    yes.parent = self
    # Check and set the yes statement.
    if no and !no.is_a?(Statement)
        raise AnyError, "Invalid class for a statement: #{no.class}"
    end
    @no = no
    # And set its parent.
    no.parent = self if no

    # Initialize the list of alternative if statements (elsif)
    @noifs = []
end

Public Instance Methods

add_noif(next_cond, next_yes) click to toggle source

Adds an alternative if statement (elsif) testing next_cond and executing next_yes when the condition is met.

# File lib/HDLRuby/hruby_low.rb, line 3132
def add_noif(next_cond, next_yes)
    # Check the condition.
    unless next_cond.is_a?(Expression)
        raise AnyError, 
              "Invalid class for a condition: #{next_cond.class}"
    end
    # And set its parent.
    next_cond.parent = self
    # Check yes statement.
    unless next_yes.is_a?(Statement)
        raise AnyError, 
              "Invalid class for a statement: #{next_yes.class}"
    end
    # And set its parent.
    next_yes.parent = self
    # Add the statement.
    @noifs << [next_cond,next_yes]
end
blocks2seq!() click to toggle source

Converts the par sub blocks to seq.

# File lib/HDLRuby/hruby_low2seq.rb, line 102
def blocks2seq!
    # Convert each sub block.
    # If block.
    self.yes.blocks2seq!
    # Elsif blocks
    self.each_noif do |cond, stmnt|
        stmnt.blocks2seq!
    end
    # Else block if any.
    self.no.blocks2seq! if self.no
    return self
end
boolean_in_assign2select!() click to toggle source

Converts booleans in assignments to select operators.

# File lib/HDLRuby/hruby_low_bool2select.rb, line 84
def boolean_in_assign2select!
    # No need to apply on condition!
    # # Apply on the condition.
    # self.set_condition!(self.condition.boolean_in_assign2select)
    # Apply on the yes.
    self.yes.boolean_in_assign2select!
    # Apply on the noifs.
    @noifs.map! do |cond,stmnt|
        # No need to apply on condition!
        # [cond.boolean_in_assign2select,stmnt.boolean_in_assign2select!]
        [cond,stmnt.boolean_in_assign2select!]
    end
    # Apply on the no if any.
    self.no.boolean_in_assign2select! if self.no
    return self
end
casts_without_expression!() click to toggle source

Extracts the expressions from the casts.

# File lib/HDLRuby/hruby_low_casts_without_expression.rb, line 85
def casts_without_expression!
    # Apply on the condition.
    self.set_condition!(self.condition.casts_without_expression)
    # Apply on the yes.
    self.yes.casts_without_expression!
    # Apply on the noifs.
    @noifs.map! do |cond,stmnt|
        [cond.casts_without_expression,stmnt.casts_without_expression!]
    end
    # Apply on the no if any.
    self.no.casts_without_expression! if self.no
    return self
end
clone() click to toggle source

Clones the If (deeply)

# File lib/HDLRuby/hruby_low.rb, line 3259
def clone
    # Duplicate the if.
    res = If.new(@condition.clone, @yes.clone, @no ? @no.clone : nil)
    # Duplicate the alternate ifs
    @noifs.each do |next_cond,next_yes|
        res.add_noif(next_cond.clone,next_yes.clone)
    end
    return res
end
delete_noif!(noif) click to toggle source

Deletes an alternate if.

# File lib/HDLRuby/hruby_low_mutable.rb, line 726
def delete_noif!(noif)
    if @noifs.include?(noif) then
        # The noif is present, delete it.
        @noifs.delete(noif)
        # And remove its parent.
        noif.parent = nil
    end
    noif
end
delete_unless!(keep) click to toggle source

Removes the signals and corresponding assignments whose name is not in keep.

# File lib/HDLRuby/hruby_low_cleanup.rb, line 128
def delete_unless!(keep)
    # Recurse on the sub statements.
    # Yes.
    self.yes.delete_unless!(keep)
    # Noifs.
    self.each_noif { |cond,stmnt| stmnt.delete_unless!(keep) }
    # No if any.
    self.no.delete_unless!(keep) if self.no
end
each_block(&ruby_block) click to toggle source

Iterates over the sub blocks.

# File lib/HDLRuby/hruby_low.rb, line 3211
def each_block(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_block) unless ruby_block
    # A ruby block?
    # Apply it on the yes, the alternate ifs and the no blocks.
    ruby_block.call(@yes) if @yes.is_a?(Block)
    @noifs.each do |next_cond,next_yes|
        ruby_block.call(next_yes) if next_yes.is_a?(Block)
    end
    ruby_block.call(@no) if @no.is_a?(Block)
end
each_block_deep(&ruby_block) click to toggle source

Iterates over all the blocks contained in the current block.

# File lib/HDLRuby/hruby_low.rb, line 3239
def each_block_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_block_deep) unless ruby_block
    # A ruby block?
    # Apply it on the yes, the alternate ifs and the no blocks.
    @yes.each_block_deep(&ruby_block)
    @noifs.each do |next_cond,next_yes|
        next_yes.each_block_deep(&ruby_block)
    end
    # @no.each_block_deep(&ruby_block) if @no.is_a?(Block)
    @no.each_block_deep(&ruby_block) if @no
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 3081
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 condition.
    self.condition.each_deep(&ruby_block)
    # Then apply on the yes.
    self.yes.each_deep(&ruby_block)
    # The apply on the no.
    self.no.each_deep(&ruby_block)
    # Then apply on the alternate ifs.
    self.each_noif do |cond,stmnt|
        cond.each_deep(&ruby_block)
        stmnt.each_deep(&ruby_block)
    end
end
each_node(&ruby_block) click to toggle source

Iterates over the children (including the condition).

Returns an enumerator if no ruby block is given.

# File lib/HDLRuby/hruby_low.rb, line 3180
def each_node(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_node) unless ruby_block
    # A ruby block?
    # Appy it on the children.
    ruby_block.call(@condition)
    ruby_block.call(@yes)
    self.each_noif do |next_cond,next_yes|
        ruby_block.call(next_cond)
        ruby_block.call(next_yes)
    end
    ruby_block.call(@no) if @no
end
each_node_deep(&ruby_block) click to toggle source

Iterates over the nodes deeply if any.

# File lib/HDLRuby/hruby_low.rb, line 3195
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
    @condition.each_node_deep(&ruby_block)
    @yes.each_node_deep(&ruby_block)
    self.each_noif do |next_cond,next_yes|
        next_cond.each_node_deep(&ruby_block)
        next_yes.each_node_deep(&ruby_block)
    end
    @no.each_node_deep(&ruby_block) if @no
end
each_noif() { |next_cond,next_yes| ... } click to toggle source

Iterates over the alternate if statements (elsif).

# File lib/HDLRuby/hruby_low.rb, line 3152
def each_noif(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_noif) unless ruby_block
    # A ruby block?
    # Appy it on the alternate if statements.
    @noifs.each do |next_cond,next_yes|
        yield(next_cond,next_yes)
    end
end
each_statement(&ruby_block) click to toggle source

Iterates over each sub statement if any.

Returns an enumerator if no ruby block is given.

# File lib/HDLRuby/hruby_low.rb, line 3165
def each_statement(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_statement) unless ruby_block
    # A ruby block?
    # Appy it on the statement children.
    ruby_block.call(@yes)
    self.each_noif do |next_cond,next_yes|
        ruby_block.call(next_yes)
    end
    ruby_block.call(@no) if @no
end
each_statement_deep(&ruby_block) click to toggle source

Iterates over all the stamements of the block and its sub blocks.

# File lib/HDLRuby/hruby_low.rb, line 3224
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)
    # And recurse on the alternate ifs and the no statements.
    @yes.each_statement_deep(&ruby_block)
    @noifs.each do |next_cond,next_yes|
        next_yes.each_statement_deep(&ruby_block)
    end
    @no.each_statement_deep(&ruby_block) if @no.is_a?(Block)
end
eql?(obj) click to toggle source

Comparison for hash: structural comparison.

# File lib/HDLRuby/hruby_low.rb, line 3100
def eql?(obj)
    return false unless obj.is_a?(If)
    return false unless @condition.eql?(obj.condition)
    return false unless @yes.eql?(obj.yes)
    return false unless @no.eql?(obj.no)
    return true
end
explicit_types!() click to toggle source

Explicit the types conversions in the if.

# File lib/HDLRuby/hruby_low_fix_types.rb, line 110
def explicit_types!
    # Recurse on the condition: it must be a Bit.
    self.set_condition!(self.condition.explicit_types(Bit))
    # Recurse on the yes block.
    self.yes.explicit_types!
    # Recruse on the alternative ifs, the conditions must be Bit.
    self.map_noifs! do |cond,block|
        [ cond.explicit_types(Bit), block.explicit_types! ]
    end
    # Recurse on the no block.
    self.no.explicit_types! if self.no
    return self
end
extract_declares!() click to toggle source

Extract the declares from the scope and returns them into an array.

NOTE: do not recurse into the sub scopes or behaviors!

# File lib/HDLRuby/hruby_low_without_namespace.rb, line 533
def extract_declares!
    # The extracted declares.
    decls = []
    # Recurse on the sub blocks.
    # Yes.
    decls << self.yes.extract_declares!
    # Noifs.
    decls << self.each_noif.map do |cond,stmnt|
        stmnt.extract_declares!
    end
    # No if any.
    decls << self.no.extract_declares! if self.no
    # Returns the extracted declares.
    return decls
end
extract_selects!() click to toggle source

Extract the Select expressions.

NOTE: work on the condition only.

# File lib/HDLRuby/hruby_low_without_select.rb, line 186
def extract_selects!
    selects = []
    self.set_condition!(self.condition.extract_selects_to!(selects))
    return selects
end
hash() click to toggle source

Hash function.

# File lib/HDLRuby/hruby_low.rb, line 3109
def hash
    return [@condition,@yes,@no].hash
end
map_nodes!(&ruby_block) click to toggle source

Maps on the children (including the condition).

# File lib/HDLRuby/hruby_low_mutable.rb, line 748
def map_nodes!(&ruby_block)
    @condition = ruby_block.call(@condition)
    @yes = ruby_block.call(@yes)
    self.map_noifs! do |cond,stmnt|
        [ruby_block.call(cond), ruby_block.call(stmnt)]
    end
    # @noifs.map! do |cond,stmnt|
    #     cond  = ruby_block.call(cond)
    #     stmnt = ruby_block.call(stmnt)
    #     cond.parent  = self unless cond.parent
    #     stmnt.parent = self unless stmnt.parent
    #     [cond,stmnt]
    # end
    @no = ruby_block.call(@no) if @no
end
map_noifs!(&ruby_block) click to toggle source

Maps on the noifs.

# File lib/HDLRuby/hruby_low_mutable.rb, line 737
def map_noifs!(&ruby_block)
    @noifs.map! do |cond,stmnt|
        cond,stmnt  = ruby_block.call(cond,stmnt)
        # cond, stmnt  = ruby_block.call(cond), ruby_block.call(stmnt)
        cond.parent  = self unless cond.parent
        stmnt.parent = self unless stmnt.parent
        [cond,stmnt]
    end
end
mix?(mode = nil) click to toggle source

Tell if there is a mix block. mode is the mode of the upper block.

# File lib/HDLRuby/hruby_low2seq.rb, line 117
def mix?(mode = nil)
    # Check each sub block.
    # If block.
    return true if self.yes.mix?(mode)
    # Elsif blocks
    self.each_noif do |cond, stmnt|
        return true if stmnt.mix?(mode)
    end
    # Else block if any.
    true if self.no && self.no.mix?(mode)
end
no=(no) click to toggle source

Sets the no block.

No shoud only be set once, but this is not checked here for sake of flexibility.

# File lib/HDLRuby/hruby_low.rb, line 3117
def no=(no)
    # if @no != nil then
    #     raise AnyError, "No already set in if statement."
    # end # Actually better not lock no here.
    # Check and set the yes statement.
    unless no.is_a?(Statement)
        raise AnyError, "Invalid class for a statement: #{no.class}"
    end
    @no = no
    # And set its parent.
    no.parent = self
end
par_in_seq2seq!() click to toggle source

Converts par blocks within seq blocks to seq blocks.

# File lib/HDLRuby/hruby_low_without_parinseq.rb, line 62
def par_in_seq2seq!
    self.yes.par_in_seq2seq!
    self.each_noif do |cond,blk|
        blk.par_in_seq2seq!
    end
    self.no.par_in_seq2seq! if self.no
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 770
def replace_expressions!(node2rep)
    # First recurse on the children.
    res = {}
    self.each_node do |node|
        res.merge!(node.replace_expressions!(node2rep))
    end
    # Is there a replacement to do on the condition?
    rep = node2rep[self.condition]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = self.condition
        # node.set_parent!(nil)
        self.set_condition!(rep)
        # And register the replacement.
        res[node] = rep
    end

    return res
end
replace_names!(former,nname) click to toggle source

Replaces recursively former name by nname until it is redeclared.

# File lib/HDLRuby/hruby_low_without_namespace.rb, line 550
def replace_names!(former,nname)
    # Recurse on the condition.
    self.condition.replace_names!(former,nname)
    # Recurse on the yes.
    self.yes.replace_names!(former,nname)
    # Recurse on the alternate ifs.
    self.each_noif do |cond,stmnt| 
        cond.replace_names!(former,nname)
        stmnt.replace_names!(former,nname)
    end
    # Recurse on the no if any.
    self.no.replace_names!(former,nname) if self.no
end
set_condition!(condition) click to toggle source

Sets the condition.

# File lib/HDLRuby/hruby_low_mutable.rb, line 692
def set_condition!(condition)
    # Check and set the condition.
    unless condition.is_a?(Expression)
        raise AnyError,
              "Invalid class for a condition: #{condition.class}"
    end
    @condition = condition
    # And set its parent.
    condition.parent = self
end
set_no!(no) click to toggle source

Sets the no block.

# File lib/HDLRuby/hruby_low_mutable.rb, line 715
def set_no!(no)
    # Check and set the yes statement.
    if no and !no.is_a?(Statement)
        raise AnyError, "Invalid class for a statement: #{no.class}"
    end
    @no = no
    # And set its parent.
    no.parent = self if no
end
set_yes!(yes) click to toggle source

Sets the yes block.

# File lib/HDLRuby/hruby_low_mutable.rb, line 704
def set_yes!(yes)
    # Check and set the yes statement.
    unless yes.is_a?(Statement)
        raise AnyError, "Invalid class for a statement: #{yes.class}"
    end
    @yes = yes
    # And set its parent.
    yes.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 1169
def to_c(level = 0)
    # The result string.
    res = " " * level*3
    # Compute the condition.
    res << "{\n"
    res << " " * (level+1)*3
    res << "Value cond = " << self.condition.to_c(level+1) << ";\n"
    # Ensure the condition is testable.
    res << " " * (level+1)*3
    res << "if (is_defined_value(cond)) {\n"
    # The condition is testable.
    res << " " * (level+2)*3
    res << "if (value2integer(cond)) {\n"
    # Generate the yes part.
    res << self.yes.to_c(level+3)
    res << " " * level*3
    res << "}\n"
    # Generate the alternate if parts.
    self.each_noif do |cond,stmnt|
        res << " " * level*3
        res << "else if (value2integer(" << cond.to_c(level+1) << ")) {\n"
        res << stmnt.to_c(level+1)
        res << " " * level*3
        res << "}\n"
    end
    # Generate the no part if any.
    if self.no then
        res << " " * level*3
        res << "else {\n" << self.no.to_c(level+1)
        res << " " * level*3
        res << "}\n"
    end
    # Close the if.
    res << " " * (level+1)*3
    res << "}\n"
    res << " " * (level)*3
    res << "}\n"
    # Return the result.
    return res
end
to_ch() click to toggle source

Generates the content of the h file.

# File lib/HDLRuby/hruby_low2c.rb, line 1211
def to_ch
    res = ""
    # Recurse on the sub statements.
    res << self.yes.to_ch
    self.each_noif do |cond,stmnt|
        res << stmnt.to_ch
    end
    res << self.no.to_ch if self.no
    return res
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 350
def to_hdr(level = 0)
    # The result string.
    res = " " * (level*3)
    # Generate the test.
    res << "hif " << self.condition.to_hdr(level) << " do\n"
    # Generate the yes part.
    res << self.yes.to_hdr(level+1)
    res << " " * (level*3) << "end\n"
    # Generate the alternate if parts.
    self.each_noif do |cond,stmnt|
        res << " " * (level*3)
        res << "helsif " << cond.to_hdr(level) << " do\n"
        res << stmnt.to_hdr(level+1)
        res << " " * (level*3) << "end\n"
    end
    # Generate the no part if any.
    if self.no then
        res << " " * (level*3)
        res << "helse do\n" << self.no.to_hdr(level+1)
        res << " " * (level*3) << "end\n"
    end
    # Return the result.
    return res
end
to_high() click to toggle source

Creates a new high if statement.

# File lib/HDLRuby/hruby_low2high.rb, line 252
def to_high
    # Is there a no?
    if self.no then
        # Yes, create a new if statement with it.
        res = HDLRuby::High::If.new(self.condition.to_high,
                                self.yes.to_high,self.no.to_high)
    else
        # No, create a new if statement without it.
        res = HDLRuby::High::If.new(self.condition.to_high,
                                self.yes.to_high)
    end
    # Add the noifs if any.
    self.each_noif do |cond,stmnt| 
        res.add_noif(cond.to_high,stmt.to_high)
    end
    return res
end
to_seq!() click to toggle source

Convert the block to seq.

# File lib/HDLRuby/hruby_low_without_parinseq.rb, line 71
def to_seq!
    self.to_seq!
    self.each_noif do |cond,blk|
        blk.to_seq!
    end
    self.no.to_seq! if self.no
end
to_upper_space!() click to toggle source

Moves the declarations to the upper namespace.

# File lib/HDLRuby/hruby_low_without_namespace.rb, line 520
def to_upper_space!
    # Recurse on the sub blocks.
    # Yes.
    self.yes.to_upper_space!
    # Noifs.
    self.each_noif {|cond,stmnt| stmnt.to_upper_space! }
    # No if any.
    self.no.to_upper_space! if self.no
end
to_verilog(spc = 3) click to toggle source

# Converts the system to Verilog code. def to_verilog(mode = nil) Converts to Verilog code, checking adding 'spc' spaces at the begining of each line.

# File lib/HDLRuby/hruby_verilog.rb, line 1490
def to_verilog(spc = 3)

    $blocking = false

    result = " " * spc  # Indented based on space_count.

    result << "if (#{self.condition.to_verilog}) "


    # Check if there is yes (if) and output yes or less.
    if self.respond_to? (:yes)
        result << self.yes.to_verilog(spc)
    end

    # If noif (else if) exists, it outputs it.
    # Since noif is directly under, respond_to is unnecessary.
    self.each_noif do |condition, block|
        result << "\n#{" "*spc}else if (#{condition.to_verilog}) "
        result << block.to_verilog(spc)
    end

    # Check if there is no (else) and output no or less.
    if self.no.respond_to?(:mode)
        result << "\n#{" " * spc}else "
        result << self.no.to_verilog(spc)
    end

    return result
end
to_vhdl(vars,level = 0) click to toggle source

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 935
def to_vhdl(vars,level = 0)
    # The result string.
    res = " " * (level*3)
    # Generate the test.
    res << "if (" << Low2VHDL.to_boolean(self.condition) << ") then\n"
    # Generate the yes part.
    res << self.yes.to_vhdl(vars,level+1)
    # Generate the alternate if parts.
    self.each_noif do |cond,stmnt|
        res << " " * (level*3)
        # res << "elsif (" << cond.to_vhdl(level) << ") then\n"
        res << "elsif (" << Low2VHDL.to_boolean(cond) << ") then\n"
        res << stmnt.to_vhdl(vars,level+1)
    end
    # Generate the no part if any.
    if self.no then
        res << " " * (level*3)
        res << "else\n" << self.no.to_vhdl(vars,level+1)
    end
    # Close the if.
    res << " " * (level*3)
    res << "end if;\n"
    # Return the result.
    return res
end
use_name?(*names) click to toggle source

Tell if the statement includes a signal whose name is one of names. NOTE: for the if check only the condition.

# File lib/HDLRuby/hruby_low.rb, line 3254
def use_name?(*names)
    return @condition.use_name?(*name)
end
with_var(upper = nil) click to toggle source

Converts to a variable-compatible if where upper is the upper block if any.

NOTE: the result is a new if.

# File lib/HDLRuby/hruby_low_with_var.rb, line 271
def with_var(upper = nil)
    # Treat the sub nodes.
    # Condition.
    ncond = self.condition.clone
    # Yes.
    nyes =self.yes.with_var(upper)
    # Noifs.
    noifs = self.each_noif.map do |cond,stmnt|
        [cond.clone,stmnt.with_var(upper)]
    end
    # No.
    nno = self.no ? self.no.with_var(upper) : nil
    # Create the resulting If.
    res= If.new(ncond,nyes, nno)
    noifs.each do |cond,stmnt|
        res.add_noif(cond,stmnt)
    end
    return res
end