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)



5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
# File 'lib/HDLRuby/hruby_low.rb', line 5148

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



5143
5144
5145
# File 'lib/HDLRuby/hruby_low.rb', line 5143

def select
  @select
end

Instance Method Details

#add_choice(choice) ⇒ Object

Adds a +choice+.



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

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)



5289
5290
5291
5292
# File 'lib/HDLRuby/hruby_low.rb', line 5289

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.



5231
5232
5233
5234
5235
5236
# File 'lib/HDLRuby/hruby_low.rb', line 5231

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.



5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
# File 'lib/HDLRuby/hruby_low.rb', line 5179

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.



5244
5245
5246
5247
5248
5249
5250
# File 'lib/HDLRuby/hruby_low.rb', line 5244

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.



5255
5256
5257
5258
5259
5260
5261
5262
5263
# File 'lib/HDLRuby/hruby_low.rb', line 5255

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.



5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
# File 'lib/HDLRuby/hruby_low.rb', line 5268

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)


5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
# File 'lib/HDLRuby/hruby_low.rb', line 5195

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



5239
5240
5241
# File 'lib/HDLRuby/hruby_low.rb', line 5239

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

#hashObject

Hash function.



5211
5212
5213
# File 'lib/HDLRuby/hruby_low.rb', line 5211

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5168
5169
5170
5171
5172
5173
5174
# File 'lib/HDLRuby/hruby_low.rb', line 5168

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.



2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
# File 'lib/HDLRuby/hruby_low2c.rb', line 2484

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 << "select(#{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.



1523
1524
1525
1526
# File 'lib/HDLRuby/hruby_verilog.rb', line 1523

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.



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)


5281
5282
5283
5284
5285
5286
# File 'lib/HDLRuby/hruby_low.rb', line 5281

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