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

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

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



5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
# File 'lib/HDLRuby/hruby_low.rb', line 5338

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



5333
5334
5335
# File 'lib/HDLRuby/hruby_low.rb', line 5333

def select
  @select
end

Instance Method Details

#add_choice(choice) ⇒ Object

Adds a +choice+.



5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
# File 'lib/HDLRuby/hruby_low.rb', line 5406

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)



5479
5480
5481
5482
# File 'lib/HDLRuby/hruby_low.rb', line 5479

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.



5421
5422
5423
5424
5425
5426
# File 'lib/HDLRuby/hruby_low.rb', line 5421

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.



5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
# File 'lib/HDLRuby/hruby_low.rb', line 5369

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.



5434
5435
5436
5437
5438
5439
5440
# File 'lib/HDLRuby/hruby_low.rb', line 5434

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.



5445
5446
5447
5448
5449
5450
5451
5452
5453
# File 'lib/HDLRuby/hruby_low.rb', line 5445

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.



5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
# File 'lib/HDLRuby/hruby_low.rb', line 5458

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)


5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
# File 'lib/HDLRuby/hruby_low.rb', line 5385

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



5429
5430
5431
# File 'lib/HDLRuby/hruby_low.rb', line 5429

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

#hashObject

Hash function.



5401
5402
5403
# File 'lib/HDLRuby/hruby_low.rb', line 5401

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5358
5359
5360
5361
5362
5363
5364
# File 'lib/HDLRuby/hruby_low.rb', line 5358

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.



1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
# File 'lib/HDLRuby/hruby_verilog.rb', line 1544

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)


5471
5472
5473
5474
5475
5476
# File 'lib/HDLRuby/hruby_low.rb', line 5471

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