Class: HDLRuby::Low::Select

Inherits:
Operation show all
Defined in:
lib/HDLRuby/hruby_db.rb,
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.rb,
lib/HDLRuby/hruby_low2vhd.rb,
lib/HDLRuby/hruby_verilog.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/hruby_low_fix_types.rb,
lib/HDLRuby/hruby_low_with_bool.rb,
lib/HDLRuby/hruby_low_bool2select.rb

Overview

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

Direct Known Subclasses

High::Select

Constant Summary

Constants included from Low2Symbol

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

Instance Attribute Summary collapse

Attributes inherited from Operation

#operator

Attributes inherited from Expression

#type

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods inherited from Operation

#set_operator!

Methods inherited from Expression

#break_types!, #extract_selects_to!, #leftvalue?, #replace_names!, #rightvalue?, #set_type!, #statement

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#scope

Constructor Details

#initialize(type, operator, select, *choices) ⇒ Select

Creates a new operator with +type+ selecting from the value of +select+ one of the +choices+. def initialize(operator,select,*choices)



4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
# File 'lib/HDLRuby/hruby_low.rb', line 4190

def initialize(type,operator,select,*choices)
    # Initialize as a general operation.
    # super(operator)
    super(type,operator)
    # Check and set the selection.
    unless select.is_a?(Expression)
        raise AnyError,
              "Invalid class for an expression: #{select.class}"
    end
    @select = select
    # And set its parent.
    select.parent = self
    # Check and set the choices.
    @choices = []
    choices.each do |choice|
        self.add_choice(choice)
    end
end

Instance Attribute Details

#selectObject (readonly)

The selection child (connection).



4185
4186
4187
# File 'lib/HDLRuby/hruby_low.rb', line 4185

def select
  @select
end

Instance Method Details

#add_choice(choice) ⇒ Object

Adds a +choice+.



4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
# File 'lib/HDLRuby/hruby_low.rb', line 4231

def add_choice(choice)
    unless choice.is_a?(Expression)
        raise AnyError,
              "Invalid class for an expression: #{choice.class}"
    end
    # Set the parent of the choice.
    choice.parent = self
    # And add it.
    @choices << choice
    choice
end

#boolean?Boolean

Tells if the expression is boolean.

Returns:

  • (Boolean)


135
136
137
138
# File 'lib/HDLRuby/hruby_low_with_bool.rb', line 135

def boolean?
    # Boolean if all the choices are boolean.
    return !self.each_choice.any? {|c| !c.boolean? }
end

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



231
232
233
234
235
236
237
238
239
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 231

def boolean_in_assign2select
    # Recurse on the sub node.
    return Select.new(self.type,"?", 
                      self.select.boolean_in_assign2select,
                      *self.each_choice.map do |choice|
                          choice.boolean_in_assign2select
                      end )
    return self
end

#cloneObject

Clones the select (deeply)



4296
4297
4298
4299
# File 'lib/HDLRuby/hruby_low.rb', line 4296

def clone
    return Select.new(@type, self.operator, @select.clone,
                      *@choices.map {|choice| choice.clone } )
end

#delete_choice!(choice) ⇒ Object

Deletes a choice.



1406
1407
1408
1409
1410
1411
1412
1413
1414
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1406

def delete_choice!(choice)
    if @choices.include?(choice) then
        # The choice is present, delete it.
        @choices.delete(choice)
        # And remove its parent.
        choice.parent = nil
    end
    choice
end

#each_choice(&ruby_block) ⇒ Object

Iterates over the choices.

Returns an enumerator if no ruby block is given.



4246
4247
4248
4249
4250
4251
# File 'lib/HDLRuby/hruby_low.rb', line 4246

def each_choice(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_choice) unless ruby_block
    # A ruby block? Apply it on each choice.
    @choices.each(&ruby_block)
end

#each_node(&ruby_block) ⇒ Object Also known as: each_expression

Iterates over the expression children if any.



4259
4260
4261
4262
4263
4264
4265
# File 'lib/HDLRuby/hruby_low.rb', line 4259

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(@select)
    @choices.each(&ruby_block)
end

#each_node_deep(&ruby_block) ⇒ Object

Iterates over the nodes deeply if any.



4270
4271
4272
4273
4274
4275
4276
4277
4278
# File 'lib/HDLRuby/hruby_low.rb', line 4270

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.
    @select.each_node_deep(&ruby_block)
    @choices.each { |choice| choice.each_node_deep(&ruby_block) }
end

#each_ref_deep(&ruby_block) ⇒ Object

Iterates over all the references encountered in the expression.

NOTE: do not iterate inside the references.



4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
# File 'lib/HDLRuby/hruby_low.rb', line 4283

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 Select"
    # A ruby block?
    # Recurse on the children.
    self.select.each_ref_deep(&ruby_block)
    self.each_choice do |choice|
        choice.each_ref_deep(&ruby_block)
    end
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
# File 'lib/HDLRuby/hruby_low.rb', line 4210

def eql?(obj)
    # General comparison.
    return false unless super(obj)
    # Specific comparison.
    return false unless obj.is_a?(Select)
    return false unless @select.eql?(obj.select)
    idx = 0
    obj.each_choice do |choice|
        return false unless @choices[idx].eql?(choice)
        idx += 1
    end
    return false unless idx == @choices.size
    return true
end

#explicit_types(type = nil) ⇒ Object

Explicit the types conversions in the selection where +type+ is the expected type of the condition if any.



279
280
281
282
283
284
285
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 279

def explicit_types(type = nil)
    # If there is no type to match, use the one of the selection.
    type = self.type unless type
    # Each choice child must match the type.
    return Select.new(type,self.operator,self.select.clone,
          *self.each_choice.map { |choice| choice.explicit_types(type)})
end

#get_choice(index) ⇒ Object

Gets a choice by +index+.



4254
4255
4256
# File 'lib/HDLRuby/hruby_low.rb', line 4254

def get_choice(index)
    return @choices[index]
end

#hashObject

Hash function.



4226
4227
4228
# File 'lib/HDLRuby/hruby_low.rb', line 4226

def hash
    return [super,@select,@choices].hash
end

#map_choices!(&ruby_block) ⇒ Object

Maps on the choices.



1397
1398
1399
1400
1401
1402
1403
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1397

def map_choices!(&ruby_block)
    @choices.map! do |choice|
        choice = ruby_block.call(choice)
        choice.parent = self unless choice.parent
        choice
    end
end

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children.



1417
1418
1419
1420
1421
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1417

def map_nodes!(&ruby_block)
    @select = ruby_block.call(@select)
    @select.parent = self unless @select.parent
    map_choices!(&ruby_block)
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.



1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1429

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 select?
    rep = node2rep[self.select]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = self.select
        # node.set_parent!(nil)
        self.set_select!(rep)
        # And register the replacement.
        res[node] = rep
    end
    # Is there a replacement of on a choice.
    self.map_choices! do |choice|
        rep = node2rep[choice]
        if rep then
            # Yes, do it.
            rep = rep.clone
            node = choice
            # node.set_parent!(nil)
            # And register the replacement.
            res[node] = rep
            rep
        else
            choice
        end
    end
    return res
end

#set_select!(select) ⇒ Object

Sets the select.



1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1385

def set_select!(select)
    # Check and set the selection.
    unless select.is_a?(Expression)
        raise AnyError,
              "Invalid class for an expression: #{select.class}"
    end
    @select = select
    # And set its parent.
    select.parent = self
end

#to_c(level = 0) ⇒ Object

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



1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
# File 'lib/HDLRuby/hruby_low2c.rb', line 1714

def to_c(level = 0)
    # res = "select_value(#{self.select.to_c(level)}," + 
    #       "#{self.each_choice.to_a.size}"
    # self.each_choice { |choice| res << ",#{choice.to_c(level)}" }
    # res << ")"
    # return res
    # Gather the possible selection choices.
    expressions = self.each_choice.to_a
    # Create the resulting string.
    # res = " " * (level*3)
    res = "({\n"
    # Overrides the upper sel, src0, src1, ..., and dst...
    # And allocates a new value for dst.
    res << (" " * ((level+1)*3))
    res << "Value sel;\n"
    res << (" " * ((level+1)*3))
    res << "Value #{expressions.size.times.map do |i| 
        "src#{i}"
    end.join(",")};\n"
    res << (" " * ((level+1)*3))
    res << "Value 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 selection.
    res << (" " * ((level+1)*3))
    res << "sel = #{self.select.to_c(level+2)};\n"
    # Compute each choice expression.
    expressions.each_with_index do |expr,i|
        res << (" " * ((level+1)*3))
        res << "src#{i} = #{expr.to_c(level+2)};\n"
    end
    # Compute the resulting selection.
    res << (" " * ((level+1)*3))
    res << "select_value(sel,dst,#{expressions.size},"
    res << "#{expressions.size.times.map { |i| "src#{i}" }.join(",")}"
    res << ");\n"
    # 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; })"
end

#to_high(level = 0) ⇒ Object

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



610
611
612
613
614
615
616
617
618
619
620
621
622
623
# File 'lib/HDLRuby/hruby_low2high.rb', line 610

def to_high(level = 0)
    # The resulting string.
    res = ""
    # Generate the header.
    res << "mux(" + self.select.to_high(level) << ", "
    # Generate the choices
    res << self.each_choice.map do |choice|
        choice.to_high(level+1)
    end.join(", ")
    # Close the select.
    res << ")"
    # Return the resulting string.
    return res
end

#to_verilogObject

Converts the system to Verilog code.



1395
1396
1397
1398
# File 'lib/HDLRuby/hruby_verilog.rb', line 1395

def to_verilog
    # Outputs the first and second choices (choice (0) and choice (1)).
    return "#{self.select.to_verilog} == 1 #{self.operator} #{self.get_choice(0).to_verilog} : #{self.get_choice(1).to_verilog}"
end

#to_vhdl(level = 0, std_logic = false) ⇒ Object

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

NOTE: assumes the existance of the mux function.



1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1325

def to_vhdl(level = 0, std_logic = false)
    # The resulting string.
    res = ""
    # The number of arguments.
    num = @choices.size
    # Generate the header.
    res << "#{Low2VHDL.mux_name(self.type.to_vhdl(level),num)}(" +
            self.select.to_vhdl(level) << ", "
    # Generate the choices
    res << self.each_choice.map do |choice|
        choice.to_vhdl(level+1)
    end.join(", ")
    # Close the select.
    res << ")"
    # Return the resulting string.
    return res
end