class HDLRuby::Low::Case

Describes a case statement.

Describes a case statement.

Extends the Case class with generation of C text.

Extends the Case class with generation of hdr text.

Add the conversion to high.

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

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

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

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

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

Extends the Case class with fixing of types and constants.

Describes a case statement.

Extends the Case class with separation between signals and variables.

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

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

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

Used to translate case

Attributes

default[R]

The default block.

value[R]

The tested value

Public Class Methods

new(value, default = nil, whens = []) click to toggle source

Creates a new case statement whose excution flow is decided from value with a possible cases given in whens and +default + (can be set later)

Calls superclass method
# File lib/HDLRuby/hruby_low.rb, line 3421
def initialize(value, default = nil, whens = [])
    # Check and set the value.
    unless value.is_a?(Expression)
        raise AnyError, "Invalid class for a value: #{value.class}"
    end
    super()
    @value = value
    # And set its parent.
    value.parent = self
    # Checks and set the default case if any.
    self.default = default if default
    # Check and add the whens.
    @whens = []
    whens.each { |w| self.add_when(w) }
end

Public Instance Methods

add_when(w) click to toggle source

Adds possible when case w.

# File lib/HDLRuby/hruby_low.rb, line 3474
def add_when(w)
    # Check +w+.
    unless w.is_a?(When)
        raise AnyError, "Invalid class for a when: #{w.class}"
    end
    # Add it.
    @whens << w
    # And set the parent of +w+.
    w.parent = self
end
blocks2seq!() click to toggle source

Converts the par sub blocks to seq.

# File lib/HDLRuby/hruby_low2seq.rb, line 154
def blocks2seq!
    # Recurse on the whens.
    self.each_when(&:blocks2seq!)
    # Converts the default if any.
    self.default.blocks2seq! if self.default
    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 123
def boolean_in_assign2select!
    # No need to apply on the value!
    # # Apply on the value.
    # self.set_value!(self.value.boolean_in_assign2select)
    # Apply on the whens.
    self.each_when(&:boolean_in_assign2select!)
    # Apply on the default if any.
    self.default.boolean_in_assign2select! if self.default
    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 120
def casts_without_expression!
    # No need to apply on the value!
    # Apply on the value.
    self.set_value!(self.value.casts_without_expression)
    # Apply on the whens.
    self.each_when(&:casts_without_expression!)
    # Apply on the default if any.
    self.default.casts_without_expression! if self.default
    return self
end
clone() click to toggle source

Clones the Case (deeply)

# File lib/HDLRuby/hruby_low.rb, line 3591
def clone
    # Clone the default if any.
    default = @default ? @default.clone : nil
    # Clone the case.
    return Case.new(@value.clone,default,(@whens.map do |w|
        w.clone
    end) )
end
default=(default) click to toggle source

Sets the default block.

No can only be set once.

# File lib/HDLRuby/hruby_low.rb, line 3488
def default=(default)
    if @default != nil then
        raise AnyError, "Default already set in if statement."
    end
    # Check and set the yes statement.
    unless default.is_a?(Statement)
        raise AnyError,"Invalid class for a statement: #{default.class}"
    end
    @default = default
    # And set its parent.
    default.parent = self
    @default
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 157
def delete_unless!(keep)
    # Recurse on the whens.
    self.each_when {|w| w.delete_unless!(keep) }
    # Recurse on the default if any.
    self.default.delete_unless!(keep) if self.default
end
delete_when!(w) click to toggle source

Delete a when.

# File lib/HDLRuby/hruby_low_mutable.rb, line 912
def delete_when!(w)
    @whens.delete(w)
end
each_block(&ruby_block) click to toggle source

Iterates over the sub blocks.

# File lib/HDLRuby/hruby_low.rb, line 3550
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 each when's block.
    self.each_when { |w| w.each_block(&ruby_block) }
    # And apply it on the default if any.
    ruby_block.call(@default) if @default
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 3561
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 each when's block.
    self.each_when { |w| w.each_block_deep(&ruby_block) }
    # And apply it on the default if any.
    @default.each_block_deep(&ruby_block) if @default
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 3440
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 value.
    self.value.each_deep(&ruby_block)
    # Then apply on the whens.
    self.each_when do |w|
        w.each_deep(&ruby_block)
    end
end
each_node(&ruby_block) click to toggle source

Iterates over the children (including the value).

Returns an enumerator if no ruby block is given.

# File lib/HDLRuby/hruby_low.rb, line 3528
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 each child.
    ruby_block.call(@value)
    @whens.each(&ruby_block)
    ruby_block.call(@default) if @default
end
each_node_deep(&ruby_block) click to toggle source

Iterates over the nodes deeply if any.

# File lib/HDLRuby/hruby_low.rb, line 3538
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
    @value.each_node_deep(&ruby_block)
    @whens.each { |w| w.each_node_deep(&ruby_block) }
    @default.each_node_deep(&ruby_block) if @default
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 3505
def each_statement(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_statement) unless ruby_block
    # A ruby block?
    # Apply on each when.
    @whens.each { |w| w.each_statement(&ruby_block) }
    # And on the default if any.
    ruby_block.call(@default) if @default
end
each_statement_deep(&ruby_block) click to toggle source

Iterates over all the statements contained in the current statement.

# File lib/HDLRuby/hruby_low.rb, line 3572
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 apply it on each when's statement.
    self.each_when { |w| w.each_statement_deep(&ruby_block) }
    # And apply it on the default if any.
    @default.each_statement_deep(&ruby_block) if @default
end
each_when(&ruby_block) click to toggle source

Iterates over the match cases.

Returns an enumerator if no ruby block is given.

# File lib/HDLRuby/hruby_low.rb, line 3518
def each_when(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_when) unless ruby_block
    # A ruby block? Apply it on each when case.
    @whens.each(&ruby_block)
end
eql?(obj) click to toggle source

Comparison for hash: structural comparison.

# File lib/HDLRuby/hruby_low.rb, line 3454
def eql?(obj)
    return false unless obj.is_a?(Case)
    return false unless @value.eql?(obj.value)
    return false unless @whens.eql?(obj.instance_variable_get(:@whens))
    idx = 0
    obj.each_when do |w|
        return false unless @whens[idx].eql?(w)
        idx += 1
    end
    return false unless idx == @whens.size
    return false unless @default.eql?(obj.default)
    return true
end
explicit_types!() click to toggle source

Explicit the types conversions in the case.

# File lib/HDLRuby/hruby_low_fix_types.rb, line 143
def explicit_types!
    # Recurse on the value.
    self.set_value!(self.value.explicit_types)
    # Recurse on the whens, the match of each when must be of the
    # type of the value.
    self.each_when { |w| w.explicit_types!(self.value.type) }
    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 619
def extract_declares!
    # # Recurse on the whens.
    # return self.each_when.map(&:extract_declares!)
    # # Recurse on the default if any.
    # self.default.extract_declares! if self.default
    res = self.each_when.map(&:extract_declares!)
    res += self.default.extract_declares! if self.default
    return res
end
extract_selects!() click to toggle source

Extract the Select expressions.

Note: the default is not treated.

# File lib/HDLRuby/hruby_low_without_select.rb, line 214
def extract_selects!
    selects = []
    # Work on the value.
    self.set_value!(self.value.extract_selects_to!(selects))
    # Work on the whens.
    selects += self.each_when.map(&:extract_selects!).reduce(:+)
    return selects
end
hash() click to toggle source

Hash function.

# File lib/HDLRuby/hruby_low.rb, line 3469
def hash
    return [@value,@whens,@default].hash
end
map_nodes!(&ruby_block) click to toggle source

Maps on the children (including the value).

# File lib/HDLRuby/hruby_low_mutable.rb, line 917
def map_nodes!(&ruby_block)
    # A block? Apply it on each child.
    @value = ruby_block.call(@value)
    map_whens!(&ruby_block)
    if @default then
        @default = ruby_block.call(@default)
        @default.parent = self unless @default.parent
    end
end
map_whens!(&ruby_block) click to toggle source

Maps on the whens.

# File lib/HDLRuby/hruby_low_mutable.rb, line 903
def map_whens!(&ruby_block)
    @whens.map! do |w|
        w = ruby_block.call(w)
        w.parent = self unless w.parent
        w
    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 164
def mix?(mode = nil)
    # Recuse on the whens.
    return true if self.each_when.any? { |w| w.mix?(mode) }
    # Check the default if any.
    return self.default.mix?(mode)
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 85
def par_in_seq2seq!
    self.each_when do |w|
        w.statement.par_in_seq2seq!
    end
    self.default.par_in_seq2seq! if self.default
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 933
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 value?
    rep = node2rep[self.value]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = self.value
        # node.set_parent!(nil)
        self.set_value!(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 630
def replace_names!(former,nname)
    # Recurse on the value.
    self.value.replace_names!(former,nname)
    # Recurse on the whens.
    self.each_when {|w| w.replace_names!(former,nname) }
    # Recurse on the default.
    self.default.replace_names!(former,nname) if self.default
end
set_default!(default) click to toggle source

Sets the default.

# File lib/HDLRuby/hruby_low_mutable.rb, line 897
def set_default!(default)
    # Checks and set the default case if any.
    self.default = default
end
set_value!(value) click to toggle source

Sets the value.

# File lib/HDLRuby/hruby_low_mutable.rb, line 886
def set_value!(value)
    # Check and set the value.
    unless value.is_a?(Expression)
        raise AnyError, "Invalid class for a value: #{value.class}"
    end
    @value = value
    # And set its parent.
    value.parent = self
end
to_c(level = 0) click to toggle source

Generates the text of the equivalent HDLRuby code. level is the hierachical level of the object.

# File lib/HDLRuby/hruby_low2c.rb, line 1263
def to_c(level = 0)
    res = ""
    # Compute the selection value.
    res << "{\n"
    res << " " * (level+1)*3
    res << "Value value = " << self.value.to_c(level+1) << ";\n"
    # Ensure the selection value is testable.
    res << " " * (level+1)*3
    res << "if (is_defined_value(value)) {\n"
    # The condition is testable.
    # Generate the case as a succession of if statements.
    first = true
    self.each_when do |w|
        res << " " * (level+2)*3
        if first then
            first = false
        else
            res << "else "
        end
        res << "if (value2integer(value) == "
        res << "value2integer(" << w.match.to_c(level+2) << ")) {\n"
        res << w.statement.to_c(level+3)
        res << " " * (level+2)*3
        res << "}\n"
    end
    if self.default then
        res << " " * (level+2)*3
        res << "else {\n"
        res << self.default.to_c(level+3)
        res << " " * (level+2)*3
        res << "}\n"
    end
    # Close the case.
    res << " " * (level+1)*3
    res << "}\n"
    res << " " * (level)*3
    res << "}\n"
    # Return the resulting string.
    return res
end
to_ch() click to toggle source

Generates the content of the h file.

# File lib/HDLRuby/hruby_low2c.rb, line 1305
def to_ch
    res = ""
    # Recurse on the whens.
    self.each_when {|w| res << w.to_ch }
    # Recurse on the default statement.
    res << self.default.to_ch if self.default
    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 400
def to_hdr(level = 0)
    # The result string.
    res = " " * (level*3)
    # Generate the test.
    res << "hcase " << self.value.to_hdr(level) << "\n"
    # Generate the whens.
    self.each_when do |w|
        res << w.to_hdr(level)
    end
    # Generatethe default.
    if self.default then
        res << " " * (level*3)
        res << "helse do\n"
        res << self.default.to_hdr(level+1)
        res << " " * (level*3)
        res << "end\n"
    end
    # Return the resulting string.
    return res
end
to_high() click to toggle source

Creates a new high case statement.

# File lib/HDLRuby/hruby_low2high.rb, line 285
def to_high
    # Is there a default?
    if self.default then
        # Yes, create the new case statement with it.
        return HDLRuby::High::Case.new(self.value.to_high,
                                       self.default.to_high,
                             self.each_when.map { |w| w.to_high })
    end
end
to_seq!() click to toggle source

Convert the block to seq.

# File lib/HDLRuby/hruby_low_without_parinseq.rb, line 93
def to_seq!
    self.each_when do |w|
        w.statement.to_seq!
    end
    self.default.to_seq! if self.default
end
to_upper_space!() click to toggle source

Moves the declarations to the upper namespace.

# File lib/HDLRuby/hruby_low_without_namespace.rb, line 609
def to_upper_space!
    # Recurse on the whens.
    self.each_when(&:to_upper_space!)
    # Recurse on the default if any.
    self.default.to_upper_space! if self.default
end
to_verilog(spc = 3) click to toggle source

def to_verilog(mode = nil)

Converts to Verilog code, checking if variables are register or wire adding 'spc' spaces at the begining of each line.

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

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

    result = ""
    result << "case(#{self.value.to_verilog})\n"

    # n the case statement, each branch is partitioned by when. Process each time when.
    self.each_when do |whens| 
        # Reads and stores the numbers and expressions stored in when.
        result << " " * (spc+3) + "#{whens.match.to_verilog}: "

        if whens.statement.each_statement.count >= 1 then
            result << whens.statement.to_verilog(spc+3)
        else
            result << "\n"
        end
    end
    if self.default then
        if self.default.each_statement.count >= 1 then
            result << self.default.each_statement.map do |stmnt|
                stmnt.to_verilog(spc+3)
            end.join("\n")
        else
            result << "\n"
        end
    end
    result << " " * spc + "endcase\n" # Conclusion.

    return result               # Return case after translation.
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 987
def to_vhdl(vars,level = 0)
    # The result string.
    res = " " * (level*3)
    # Generate the test.
    res << "case " << self.value.to_vhdl(level) << " is\n"
    # Generate the whens.
    self.each_when do |w|
        res << w.to_vhdl(vars,self.value.type,level)
    end
    # Generate teh default if any.
    if self.default then
        res << " " * (level*3)
        res << "when others =>\n"
        res << self.default.to_vhdl(vars,level+1)
    else
        # NOTE: some VHDL parsers are very picky about others,
        # even though all the cases have been treated through
        # "when" statements.
        res << " " * (level*3)
        res << "when others =>\n"
    end
    # Close the case.
    res << " " * (level*3)
    res << "end case;\n"
    # Return the resulting string.
    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 case check only the value.

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

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

NOTE: the result is a new case.

# File lib/HDLRuby/hruby_low_with_var.rb, line 311
def with_var(upper = nil)
    ndefault = self.default ? self.default.clone : nil
    return Case.new(self.value.clone,ndefault,
                    self.each_when.map {|w| w.with_var(upper) })
end