Class: HDLRuby::Low::Select

Inherits:
Operation show all
Defined in:
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.rb,
lib/HDLRuby/hruby_low2hdr.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

Describes a selection operation (generalization of the ternary operator).

NOTE: choice is using the value of +select+ as an index.

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!, #fix_scope_refnames!, #leftvalue?, #replace_names!, #rightvalue?, #set_type!, #signal2subs!, #statement, #to_c_expr

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#absolute_ref, #hierarchy, #no_parent!, #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)



5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
# File 'lib/HDLRuby/hruby_low.rb', line 5506

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



5501
5502
5503
# File 'lib/HDLRuby/hruby_low.rb', line 5501

def select
  @select
end

Instance Method Details

#add_choice(choice) ⇒ Object

Adds a +choice+.



5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
# File 'lib/HDLRuby/hruby_low.rb', line 5574

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)


152
153
154
155
# File 'lib/HDLRuby/hruby_low_with_bool.rb', line 152

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.



265
266
267
268
269
270
271
272
273
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 265

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

Extracts the expressions from the casts.



265
266
267
268
269
270
271
272
273
274
275
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 265

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 )
    self.set_select!(self.select.casts_without_expression!)
    self.map_choices! { |choice| choice.casts_without_expression! }
    return self
end

#cloneObject

Clones the select (deeply)



5647
5648
5649
5650
# File 'lib/HDLRuby/hruby_low.rb', line 5647

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

#delete_choice!(choice) ⇒ Object

Deletes a choice.



1537
1538
1539
1540
1541
1542
1543
1544
1545
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1537

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.



5589
5590
5591
5592
5593
5594
# File 'lib/HDLRuby/hruby_low.rb', line 5589

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

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
# File 'lib/HDLRuby/hruby_low.rb', line 5537

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 type.
    self.type.each_deep(&ruby_block)
    # Then apply on the select.
    self.select.each_deep(&ruby_block)
    # Then apply on the choices.
    self.each_choice do |choice|
        choice.each_deep(&ruby_block)
    end
end

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

Iterates over the expression children if any.



5602
5603
5604
5605
5606
5607
5608
# File 'lib/HDLRuby/hruby_low.rb', line 5602

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.



5613
5614
5615
5616
5617
5618
5619
5620
5621
# File 'lib/HDLRuby/hruby_low.rb', line 5613

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.



5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
# File 'lib/HDLRuby/hruby_low.rb', line 5626

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)


5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
# File 'lib/HDLRuby/hruby_low.rb', line 5553

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.



336
337
338
339
340
341
342
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 336

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



5597
5598
5599
# File 'lib/HDLRuby/hruby_low.rb', line 5597

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

#hashObject

Hash function.



5569
5570
5571
# File 'lib/HDLRuby/hruby_low.rb', line 5569

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

#immutable?Boolean

Tells if the expression is immutable (cannot be written.)

Returns:

  • (Boolean)


5526
5527
5528
5529
5530
5531
5532
# File 'lib/HDLRuby/hruby_low.rb', line 5526

def immutable?
    # Immutable if children are all immutable.
    return self.select.constant &&
      self.each_choice.reduce(true) do |r,c|
        r && c.immutable?
    end
end

#map_choices!(&ruby_block) ⇒ Object

Maps on the choices.



1528
1529
1530
1531
1532
1533
1534
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1528

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 Also known as: map_expressions!

Maps on the children.



1548
1549
1550
1551
1552
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1548

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.



1562
1563
1564
1565
1566
1567
1568
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
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1562

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.



1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1516

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

Generates the C text of the equivalent HDLRuby code.

+level+ is the hierachical level of the object.

def to_c(level = 0)

def to_c(res,level = 0) # Gather the possible selection choices. expressions = self.each_choice.to_a # Create the resulting string. # res = "( 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 " res << expressions.size.times.map do |i| "src#{i" end.join(",") res << ";\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 = #HDLRuby::Low::Select.selfself.selectself.select.to_c(level+2);\n" res << "sel = " self.select.to_c(res,level+2) res << ";\n" # Compute each choice expression. expressions.each_with_index do |expr,i| res << (" " * ((level+1)*3)) # res << "src#i = #HDLRuby::Low::Select.exprexpr.to_c(level+2);\n" res << "src#i = " expr.to_c(res,level+2) res << ";\n" end # Compute the resulting selection. res << (" " * ((level+1)*3)) res << "select_value(sel,dst,#HDLRuby::Low::Select.expressionsexpressions.size," # res << "#{ |i| "src#{i" }.join(",")}" 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; })" return res end Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object.



2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
# File 'lib/HDLRuby/hruby_low2c.rb', line 2665

def to_c(res,level = 0)
    # Save the value pool state.
    res << (" " * (level*3)) << "PV;\n"
    # Gather the possible selection choices.
    expressions = self.each_choice.to_a
    # Create the resulting string.
    # Compute the selection.
    self.select.to_c(res,level)
    # Compute each choice expression.
    expressions.each_with_index do |expr,i|
        expr.to_c(res,level)
    end
    # Compute the resulting selection.
    res << (" " * (level*3))
    res << "hselect(#{expressions.size});\n"
    # Restore the value pool state.
    res << (" " * (level*3)) << "RV;\n"
    return res
end

#to_hdr(level = 0) ⇒ Object

Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object.



629
630
631
632
633
634
635
636
637
638
639
640
641
642
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 629

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

#to_highObject

Creates a new high select expression.



472
473
474
475
476
# File 'lib/HDLRuby/hruby_low2high.rb', line 472

def to_high
    return HDLRuby::High::Select(self.type.to_high,self.operator,
                                 self.select.to_high,
                            self.each_choice.map { |ch| ch.to_high })
end

#to_verilogObject

Converts the system to Verilog code.



1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
# File 'lib/HDLRuby/hruby_verilog.rb', line 1627

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}"
    res = ""
    sels = self.select.to_verilog
    @choices[0..-2].each_with_index do |choice,i|
        res << "#{sels} == #{i} ? #{choice.to_verilog} : "
    end
    res << @choices[-1].to_verilog
    return res
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.



1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1390

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:

  • (Boolean)


5639
5640
5641
5642
5643
5644
# File 'lib/HDLRuby/hruby_low.rb', line 5639

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