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_parinseq.rb,
lib/HDLRuby/hruby_low_without_namespace.rb,
lib/HDLRuby/hruby_low_casts_without_expression.rb

Overview

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

Direct Known Subclasses

High::Case

Constant Summary

Constants included from Low2Symbol

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

Instance Attribute Summary collapse

Attributes included from Hdecorator

#hdr_id

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods inherited from Statement

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

Methods included from Low2Symbol

#to_sym

Methods included from Hdecorator

decorate_parent_id, dump, each, each_with_property, get, included, load, #properties

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)


3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
# File 'lib/HDLRuby/hruby_low.rb', line 3347

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

Instance Attribute Details

#defaultObject

The default block.



3342
3343
3344
# File 'lib/HDLRuby/hruby_low.rb', line 3342

def default
  @default
end

#valueObject (readonly)

The tested value



3339
3340
3341
# File 'lib/HDLRuby/hruby_low.rb', line 3339

def value
  @value
end

Instance Method Details

#add_when(w) ⇒ Object

Adds possible when case +w+.



3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
# File 'lib/HDLRuby/hruby_low.rb', line 3400

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

#casts_without_expression!Object

Extracts the expressions from the casts.



106
107
108
109
110
111
112
113
114
115
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 106

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

#cloneObject

Clones the Case (deeply)



3504
3505
3506
3507
3508
3509
3510
3511
# File 'lib/HDLRuby/hruby_low.rb', line 3504

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_related!(*names) ⇒ Object

Deletes the elements related to one of +names+: either they have one of the names or they use an element with these names. NOTE: only delete actual instantiated elements, types or systemTs are left as is.



900
901
902
903
904
905
906
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 900

def delete_related!(*names)
    # Delete the whens whose match contains a signal whoses name is
    # in names.
    @whens.delete_if { |w| w.match.use_name?(*names) }
    # Recurse on the whens.
    @whens.each { |w| w.delete_related!(*names) }
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.



854
855
856
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 854

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

#each_block(&ruby_block) ⇒ Object

Iterates over the sub blocks.



3463
3464
3465
3466
3467
3468
3469
3470
3471
# File 'lib/HDLRuby/hruby_low.rb', line 3463

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.



3474
3475
3476
3477
3478
3479
3480
3481
3482
# File 'lib/HDLRuby/hruby_low.rb', line 3474

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

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
# File 'lib/HDLRuby/hruby_low.rb', line 3366

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

Iterates over the children (including the value).

Returns an enumerator if no ruby block is given.



3441
3442
3443
3444
3445
3446
3447
3448
# File 'lib/HDLRuby/hruby_low.rb', line 3441

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.



3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
# File 'lib/HDLRuby/hruby_low.rb', line 3451

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.



3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
# File 'lib/HDLRuby/hruby_low.rb', line 3485

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.



3431
3432
3433
3434
3435
3436
# File 'lib/HDLRuby/hruby_low.rb', line 3431

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:



3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
# File 'lib/HDLRuby/hruby_low.rb', line 3380

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.



3395
3396
3397
# File 'lib/HDLRuby/hruby_low.rb', line 3395

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

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children (including the value).



859
860
861
862
863
864
865
866
867
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 859

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.



845
846
847
848
849
850
851
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 845

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:



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

#par_in_seq2seq!Object

Converts par blocks within seq blocks to seq blocks.



85
86
87
88
89
90
# 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) ⇒ 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.



875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 875

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.



839
840
841
842
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 839

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

#set_value!(value) ⇒ Object

Sets the value.



828
829
830
831
832
833
834
835
836
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 828

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.



1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
# File 'lib/HDLRuby/hruby_low2c.rb', line 1219

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_chObject

Generates the content of the h file.



1261
1262
1263
1264
1265
1266
1267
1268
# File 'lib/HDLRuby/hruby_low2c.rb', line 1261

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

Convert the block to seq.



93
94
95
96
97
98
# 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!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(spc = 3) ⇒ Object

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.



1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
# File 'lib/HDLRuby/hruby_verilog.rb', line 1569

def to_verilog(spc = 3)

    # 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 = " " * 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 << "      " + "   " *$space_count + "#{whens.match.to_verilog}: "
        result << " " * (spc+3) + "#{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
        if whens.statement.each_statement.count >= 1 then
            result << whens.statement.to_verilog(spc+3)
        else
            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
    if self.default then
        if self.default.each_statement.count >= 1 then
            result << self.default.each_statement.to_verilog(spc+3)
        else
            result << "\n"
        end
    end
    # result << "   " + "   " *$space_count + "endcase\n" # Conclusion.
    result << " " * spc + "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

#use_name?(*names) ⇒ Boolean

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

Returns:



3499
3500
3501
# File 'lib/HDLRuby/hruby_low.rb', line 3499

def use_name?(*names)
    return @value.use_name?(*name)
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