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

Overview

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

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)



4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
# File 'lib/HDLRuby/hruby_low.rb', line 4277

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).



4272
4273
4274
# File 'lib/HDLRuby/hruby_low.rb', line 4272

def select
  @select
end

Instance Method Details

#add_choice(choice) ⇒ Object

Adds a +choice+.



4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
# File 'lib/HDLRuby/hruby_low.rb', line 4318

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:



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

#casts_without_expressionObject

Extracts the expressions from the casts.



239
240
241
242
243
244
245
246
247
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 239

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

#cloneObject

Clones the select (deeply)



4391
4392
4393
4394
# File 'lib/HDLRuby/hruby_low.rb', line 4391

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

#delete_choice!(choice) ⇒ Object

Deletes a choice.



1494
1495
1496
1497
1498
1499
1500
1501
1502
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1494

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.



4333
4334
4335
4336
4337
4338
# File 'lib/HDLRuby/hruby_low.rb', line 4333

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.



4346
4347
4348
4349
4350
4351
4352
# File 'lib/HDLRuby/hruby_low.rb', line 4346

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.



4357
4358
4359
4360
4361
4362
4363
4364
4365
# File 'lib/HDLRuby/hruby_low.rb', line 4357

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.



4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
# File 'lib/HDLRuby/hruby_low.rb', line 4370

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:



4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
# File 'lib/HDLRuby/hruby_low.rb', line 4297

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+.



4341
4342
4343
# File 'lib/HDLRuby/hruby_low.rb', line 4341

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

#hashObject

Hash function.



4313
4314
4315
# File 'lib/HDLRuby/hruby_low.rb', line 4313

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

#map_choices!(&ruby_block) ⇒ Object

Maps on the choices.



1485
1486
1487
1488
1489
1490
1491
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1485

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.



1505
1506
1507
1508
1509
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1505

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.



1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1517

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.



1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1473

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.



1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
# File 'lib/HDLRuby/hruby_low2c.rb', line 1736

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.



1464
1465
1466
1467
# File 'lib/HDLRuby/hruby_verilog.rb', line 1464

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

#use_name?(*names) ⇒ Boolean

Tell if the expression includes a signal whose name is one of +names+.

Returns:



4383
4384
4385
4386
4387
4388
# File 'lib/HDLRuby/hruby_low.rb', line 4383

def use_name?(*names)
    # Recurse on the select.
    return true if @select.use_name?(*names)
    # Recurse on the choices.
    return @choices.any? { |choice| choice.use_name?(*names) }
end