Class: HDLRuby::Low::Case

Inherits:
Statement
  • Object
show all
Defined in:
lib/HDLRuby/hruby_db.rb,
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.rb,
lib/HDLRuby/hruby_low2seq.rb,
lib/HDLRuby/hruby_low2vhd.rb,
lib/HDLRuby/hruby_verilog.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_cleanup.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/hruby_low_with_var.rb,
lib/HDLRuby/hruby_low_fix_types.rb,
lib/HDLRuby/hruby_low_bool2select.rb,
lib/HDLRuby/hruby_low_without_select.rb,
lib/HDLRuby/hruby_low_without_namespace.rb

Overview

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

Direct Known Subclasses

High::Case

Constant Summary

Constants included from Low2Symbol

Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable

Instance Attribute Summary collapse

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods inherited from Statement

#add_blocks_code, #block, #break_types!, #parent_system, #scope, #top_block, #top_scope, #with_boolean!

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#scope

Constructor Details

#initialize(value, default = nil, whens = []) ⇒ Case

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)


3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
# File 'lib/HDLRuby/hruby_low.rb', line 3056

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
    @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

Instance Attribute Details

#defaultObject

The default block.



3051
3052
3053
# File 'lib/HDLRuby/hruby_low.rb', line 3051

def default
  @default
end

#valueObject (readonly)

The tested value



3048
3049
3050
# File 'lib/HDLRuby/hruby_low.rb', line 3048

def value
  @value
end

Instance Method Details

#add_when(w) ⇒ Object

Adds possible when case +w+.



3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
# File 'lib/HDLRuby/hruby_low.rb', line 3092

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!Object

Converts the par sub blocks to seq.



154
155
156
157
158
159
160
# 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!Object

Converts booleans in assignments to select operators.



109
110
111
112
113
114
115
116
117
118
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 109

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

#cloneObject

Clones the Case (deeply)



3190
3191
3192
3193
3194
3195
3196
3197
# File 'lib/HDLRuby/hruby_low.rb', line 3190

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

#delete_unless!(keep) ⇒ Object

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



157
158
159
160
161
162
# 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) ⇒ Object

Delete a when.



795
796
797
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 795

def delete_when!(w)
    @whens.delete(w)
end

#each_block(&ruby_block) ⇒ Object

Iterates over the sub blocks.



3155
3156
3157
3158
3159
3160
3161
3162
3163
# File 'lib/HDLRuby/hruby_low.rb', line 3155

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) ⇒ Object

Iterates over all the blocks contained in the current block.



3166
3167
3168
3169
3170
3171
3172
3173
3174
# File 'lib/HDLRuby/hruby_low.rb', line 3166

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_node(&ruby_block) ⇒ Object

Iterates over the children (including the value).

Returns an enumerator if no ruby block is given.



3133
3134
3135
3136
3137
3138
3139
3140
# File 'lib/HDLRuby/hruby_low.rb', line 3133

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) ⇒ Object

Iterates over the nodes deeply if any.



3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
# File 'lib/HDLRuby/hruby_low.rb', line 3143

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_deep(&ruby_block) ⇒ Object

Iterates over all the statements contained in the current statement.



3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
# File 'lib/HDLRuby/hruby_low.rb', line 3177

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) ⇒ Object

Iterates over the match cases.

Returns an enumerator if no ruby block is given.



3123
3124
3125
3126
3127
3128
# File 'lib/HDLRuby/hruby_low.rb', line 3123

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) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
# File 'lib/HDLRuby/hruby_low.rb', line 3072

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!Object

Explicit the types conversions in the case.



129
130
131
132
133
134
135
136
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 129

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!Object

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

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



619
620
621
622
623
624
# 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
end

#extract_selects!Object

Extract the Select expressions.

Note: the default is not treated.



201
202
203
204
205
206
207
208
# File 'lib/HDLRuby/hruby_low_without_select.rb', line 201

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

#hashObject

Hash function.



3087
3088
3089
# File 'lib/HDLRuby/hruby_low.rb', line 3087

def hash
    return [@value,@whens,@default].hash
end

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children (including the value).



800
801
802
803
804
805
806
807
808
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 800

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) ⇒ Object

Maps on the whens.



786
787
788
789
790
791
792
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 786

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) ⇒ Boolean

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

Returns:

  • (Boolean)


164
165
166
167
168
169
# 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

#replace_expressions!(node2rep) ⇒ Object

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.



816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 816

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) ⇒ Object

Replaces recursively +former+ name by +nname+ until it is redeclared.



627
628
629
630
631
632
633
634
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 627

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) ⇒ Object

Sets the default.



780
781
782
783
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 780

def set_default!(default)
    # Checks and set the default case if any.
    self.default = default
end

#set_value!(value) ⇒ Object

Sets the value.



769
770
771
772
773
774
775
776
777
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 769

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) ⇒ Object

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



1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
# File 'lib/HDLRuby/hruby_low2c.rb', line 1176

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_high(level = 0) ⇒ Object

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



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# File 'lib/HDLRuby/hruby_low2high.rb', line 400

def to_high(level = 0)
    # The result string.
    res = " " * (level*3)
    # Generate the test.
    res << "hcase " << self.value.to_high(level) << "\n"
    # Generate the whens.
    self.each_when do |w|
        res << w.to_high(level)
    end
    # Generatethe default.
    if self.default then
        res << " " * (level*3)
        res << "helse do\n"
        res << self.default.to_high(level+1)
        res << " " * (level*3)
        res << "end\n"
    end
    # Return the resulting string.
    return res
end

#to_upper_space!Object

Moves the declarations to the upper namespace.



609
610
611
612
613
614
# 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(mode = nil) ⇒ Object



1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
# File 'lib/HDLRuby/hruby_verilog.rb', line 1478

def to_verilog(mode = nil)

    if ($space_count == 0) then
        result = "   " * ($space_count) # Indented based on space_count.
    else
        result = ""
    end
    $space_count += 1                 # Add count to be used for indentation.

    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 << "      " + "   " *$space_count + "#{whens.match.to_verilog}: "
        if whens.statement.each_statement.count > 1 then
            result << "begin\n"
            whens.statement.each_statement do |statement|
                result << "                  "+ "   " *$space_count +"#{statement.to_verilog}"
            end
            result << "             " + "   " *$space_count + "end\n"
        elsif whens.statement.each_statement.count == 1 then
            whens.statement.each_statement do |statement|
                result << "#{statement.to_verilog}"
            end
        else
            # Empty statement case.
            result << "\n"
        end
    end
    # The default part is stored in default instead of when. Reads and processes in the same way as when.
    if self.default then
        if self.default.each_statement.count > 1 then
            result << "      " + "   " *$space_count + "default: begin\n"
            self.default.each_statement do |statement|
                result << "                  " + "   " *$space_count + "#{statement.to_verilog}"
            end
            result << "                  end\n"
        elsif self.default.each_statement.count == 1 then
            result << "      " + "   " *$space_count + "default: "
            self.default.each_statement do |statement|
                result << "#{statement.to_verilog}"
            end
        end  
    end
    result << "   " + "   " *$space_count + "endcase\n" # Conclusion.

    $space_count -= 1           # Since the output ends, reduce the count.
    return result               # Return case after translation.
end

#to_vhdl(vars, level = 0) ⇒ Object

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.



963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 963

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

#with_var(upper = nil) ⇒ Object

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

NOTE: the result is a new case.



311
312
313
314
315
# 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