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_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

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



5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
# File 'lib/HDLRuby/hruby_low.rb', line 5167

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



5162
5163
5164
# File 'lib/HDLRuby/hruby_low.rb', line 5162

def select
  @select
end

Instance Method Details

#add_choice(choice) ⇒ Object

Adds a +choice+.



5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
# File 'lib/HDLRuby/hruby_low.rb', line 5235

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.



257
258
259
260
261
262
263
264
265
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 257

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.



259
260
261
262
263
264
265
266
267
268
269
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 259

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)



5308
5309
5310
5311
# File 'lib/HDLRuby/hruby_low.rb', line 5308

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

#delete_choice!(choice) ⇒ Object

Deletes a choice.



1576
1577
1578
1579
1580
1581
1582
1583
1584
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1576

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.



5250
5251
5252
5253
5254
5255
# File 'lib/HDLRuby/hruby_low.rb', line 5250

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.



5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
# File 'lib/HDLRuby/hruby_low.rb', line 5198

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.



5263
5264
5265
5266
5267
5268
5269
# File 'lib/HDLRuby/hruby_low.rb', line 5263

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.



5274
5275
5276
5277
5278
5279
5280
5281
5282
# File 'lib/HDLRuby/hruby_low.rb', line 5274

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.



5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
# File 'lib/HDLRuby/hruby_low.rb', line 5287

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)


5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
# File 'lib/HDLRuby/hruby_low.rb', line 5214

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.



312
313
314
315
316
317
318
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 312

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



5258
5259
5260
# File 'lib/HDLRuby/hruby_low.rb', line 5258

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

#hashObject

Hash function.



5230
5231
5232
# File 'lib/HDLRuby/hruby_low.rb', line 5230

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5187
5188
5189
5190
5191
5192
5193
# File 'lib/HDLRuby/hruby_low.rb', line 5187

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.



1567
1568
1569
1570
1571
1572
1573
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1567

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.



1587
1588
1589
1590
1591
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1587

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.



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
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1599

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.



1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1555

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.



2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
# File 'lib/HDLRuby/hruby_low2c.rb', line 2619

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.



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

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.



437
438
439
440
441
# File 'lib/HDLRuby/hruby_low2high.rb', line 437

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.



1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
# File 'lib/HDLRuby/hruby_verilog.rb', line 1525

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.



1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1361

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)


5300
5301
5302
5303
5304
5305
# File 'lib/HDLRuby/hruby_low.rb', line 5300

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