Class: HDLRuby::Low::Concat

Inherits:
Expression
  • Object
show all
Includes:
MutableConcat
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_bool2select.rb,
lib/HDLRuby/hruby_low_casts_without_expression.rb

Overview

Extends the Concat class with functionality for converting booleans in assignments to select operators.

Direct Known Subclasses

High::Concat

Constant Summary

Constants included from Low2Symbol

Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable

Instance Attribute Summary

Attributes inherited from Expression

#type

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods included from MutableConcat

#replace_expressions!

Methods inherited from Expression

#boolean?, #break_types!, #each_ref_deep, #extract_selects_to!, #leftvalue?, #replace_expressions!, #replace_names!, #rightvalue?, #set_type!, #statement

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #scope

Constructor Details

#initialize(type, expressions = []) ⇒ Concat

Creates a new concatenation with +type+ of several +expressions+ together.
def initialize(expressions = [])



5057
5058
5059
5060
5061
5062
5063
# File 'lib/HDLRuby/hruby_low.rb', line 5057

def initialize(type,expressions = [])
    super(type)
    # Initialize the array of expressions that are concatenated.
    @expressions = []
    # Check and add the expressions.
    expressions.each { |expression| self.add_expression(expression) }
end

Instance Method Details

#add_expression(expression) ⇒ Object

Adds an +expression+ to concat.



5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
# File 'lib/HDLRuby/hruby_low.rb', line 5110

def add_expression(expression)
    # Check expression.
    unless expression.is_a?(Expression) then
        raise AnyError,
              "Invalid class for an expression: #{expression.class}"
    end
    # Add it.
    @expressions << expression
    # And set its parent.
    expression.parent = self
    expression
end

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



261
262
263
264
265
266
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 261

def boolean_in_assign2select
    # Recurse on the sub expressions.
    return Concat.new(self.type,self.each_expression.map do |expr|
        expr.boolean_in_assign2select
    end )
end

#casts_without_expression!Object

Extracts the expressions from the casts.



277
278
279
280
281
282
283
284
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 277

def casts_without_expression!
    # Recurse on the sub expressions.
    # return Concat.new(self.type,self.each_expression.map do |expr|
    #     expr.casts_without_expression
    # end )
    self.map_expressions! {|expr| expr.casts_without_expression! }
    return self
end

#cloneObject

Clones the concatenated expression (deeply)



5153
5154
5155
5156
# File 'lib/HDLRuby/hruby_low.rb', line 5153

def clone
    return Concat.new(@type,
                      @expressions.map {|expr| expr.clone } )
end

#delete_expression!(expression) ⇒ Object

Delete an expression.



1688
1689
1690
1691
1692
1693
1694
1695
1696
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1688

def delete_expression!(expression)
    if @expressions.include?(expression) then
        # The expression is present, delete it.
        @expressions.delete(expression)
        # And remove its parent.
        expression.parent = nil
    end
    expression
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
# File 'lib/HDLRuby/hruby_low.rb', line 5076

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 expressions.
    self.each_expression do |expr|
        expr.each_deep(&ruby_block)
    end
end

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

Iterates over the concatenated expressions.

Returns an enumerator if no ruby block is given.



5126
5127
5128
5129
5130
5131
# File 'lib/HDLRuby/hruby_low.rb', line 5126

def each_expression(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_expression) unless ruby_block
    # A ruby block? Apply it on each children.
    @expressions.each(&ruby_block)
end

#each_node_deep(&ruby_block) ⇒ Object

Iterates over the nodes deeply if any.



5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
# File 'lib/HDLRuby/hruby_low.rb', line 5135

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.
    self.each_expression do |expr|
        expr.each_node_deep(&ruby_block)
    end
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
# File 'lib/HDLRuby/hruby_low.rb', line 5090

def eql?(obj)
    # General comparison.
    return false unless super(obj)
    # Specific comparison.
    return false unless obj.is_a?(Concat)
    idx = 0
    obj.each_expression do |expression|
        return false unless @expressions[idx].eql?(expression)
        idx += 1
    end
    return false unless idx == @expressions.size
    return true
end

#explicit_types(type = nil) ⇒ Object

Explicit the types conversions in the concat where +type+ is the expected type of the condition if any.



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 307

def explicit_types(type = nil)
    # Is there a type to match?
    if type then
        # Yes, update the concat to the type.
        # Get the real type in case of typedef.
        type = type.def while type.is_a?(TypeDef)
        # Is it an array type?
        if type.is_a?(TypeVector) then
            # Yes, update the concat without subcasting.
            return Concat.new(type,self.each_expression.map do |expr|
                expr.explicit_types
            end)
        else
            # No, it should be a tuple.
            return Concat.new(type,
                              self.each_expression.map.with_index do
                |expr,i|
                expr.explicit_types(type.get_type(i))
            end)
        end
    else
        # No, recurse on the sub expressions.
        return Concat.new(self.type,
                          self.each_expression.map do |expr|
            expr.explicit_types
        end)
    end
end

#hashObject

Hash function.



5105
5106
5107
# File 'lib/HDLRuby/hruby_low.rb', line 5105

def hash
    return [super,@expressions].hash
end

#immutable?Boolean

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

Returns:

  • (Boolean)


5066
5067
5068
5069
5070
5071
# File 'lib/HDLRuby/hruby_low.rb', line 5066

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

#map_expressions!(&ruby_block) ⇒ Object Also known as: map_nodes!

Maps on the expression.



1677
1678
1679
1680
1681
1682
1683
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1677

def map_expressions!(&ruby_block)
    @expressions.map! do |expression|
        expression = ruby_block.call(expression)
        expression.parent = self unless expression.parent
        expression
    end
end

#to_c(res, level = 0) ⇒ Object

Generates the C text for the equivalent HDLRuby code.

+level+ is the hierachical level of the object.

def to_c(res,level = 0) # Gather the content to concat. expressions = self.each_expression.to_a # Create the resulting string. res << "( # Overrides the upper src0, src1, ..., and dst... # And allocates a new value for dst. 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 each sub expression. expressions.each_with_index do |expr,i| res << (" " * ((level+1)*3)) res << "src#i = " expr.to_c_expr(res,level+2) res << ";\n" end # Compute the direction. # Compute the resulting concatenation. res << (" " * ((level+1)*3)) res << "concat_value(#HDLRuby::Low::Concat.expressionsexpressions.size," res << "#== :little ? 1 : 0,dst," 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 for the equivalent HDLRuby code. +level+ is the hierachical level of the object.



2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
# File 'lib/HDLRuby/hruby_low2c.rb', line 2445

def to_c(res,level = 0)
    # Save the value pool state.
    res << (" " * (level*3)) << "SV;\n"
    # Gather the content to concat.
    expressions = self.each_expression.to_a
    # Compute each sub expression.
    expressions.each_with_index do |expr,i|
        expr.to_c(res,level+2)
    end
    # Compute the resulting concatenation.
    res << (" " * ((level+1)*3))
    res << "sconcat(#{expressions.size},"
    res << (self.type.direction == :little ? "1" : "0")
    res << ");\n"
    # Restore the value pool state.
    res << (" " * (level*3)) << "RV;\n"
    return res
end

#to_c_expr(res, level = 0) ⇒ Object

Generates the C text of expression for the equivalent HDLRuby code. +level+ is the hierachical level of the object.



2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
# File 'lib/HDLRuby/hruby_low2c.rb', line 2466

def to_c_expr(res,level = 0)
    # Gather the content to concat.
    expressions = self.each_expression.to_a
    # Create the resulting string.
    res << "({\n"
    # Overrides the upper src0, src1, ..., and dst...
    # And allocates a new value for dst.
    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 value pool state.
    res << (" " * (level*3)) << "SV;\n"
    # Compute each sub expression.
    expressions.each_with_index do |expr,i|
        res << (" " * ((level+1)*3))
        res << "src#{i} = "
        expr.to_c_expr(res,level+2)
        res << ";\n"
    end
    # Compute the direction.
    # Compute the resulting concatenation.
    res << (" " * ((level+1)*3))
    res << "concat_value(#{expressions.size},"
    res << "#{self.type.direction == :little ? 1 : 0},dst,"
    res << expressions.size.times.map { |i| "src#{i}" }.join(",")
    res << ");\n"
    # Save the value pool state.
    res << (" " * (level*3)) << "SV;\n"
    # Close the computation.
    res << (" " * (level*3))
    res << "dst; })"
    return res
end

#to_hdr(level = 0) ⇒ Object

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



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

def to_hdr(level = 0)
    # The resulting string.
    res = ""
    # Generate the header.
    res << "[ "
    # Generate the expressions.
    res << self.each_expression.map do |expression|
        expression.to_hdr(level+1)
    end.join(", ")
    # Close the select.
    res << " ]"
    # Return the resulting string.
    return res
end

#to_highObject

Creates a new high concat expression.



448
449
450
451
# File 'lib/HDLRuby/hruby_low2high.rb', line 448

def to_high
    return HDLRuby::High::Concat.new(self.type.to_high,
                        self.each_expression.map { |ex| ex.to_high })
end

#to_verilogObject



1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
# File 'lib/HDLRuby/hruby_verilog.rb', line 1765

def to_verilog    
    expression = self.each_expression.to_a

    result = "{"
    expression[0..-2].each do |expression|
        result << "#{expression.to_verilog},"
    end
    result << "#{expression.last.to_verilog}}"

    return result
end

#to_vhdl(level = 0, type = self.type) ⇒ Object

Generates the text of the equivalent HDLRuby::High code. +type+ is the expected type of the content. +level+ is the hierachical level of the object. def to_vhdl(type,level = 0)



1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1375

def to_vhdl(level = 0, type = self.type)
    raise "Invalid class for a type: #{type.class}" unless type.is_a?(Type) 
    # The resulting string.
    res = ""
    # Generate the header.
    # Generate the expressions.
    # Depends if it is an initialization or not.
    # if self.type.is_a?(TypeTuple) then
    if self.parent.is_a?(SignalC) then
        res << "( " << self.each_expression.map do |expression|
            Low2VHDL.to_type(type,expression)
        end.join(",\n#{" "*((level+1)*3)}") << " )"
    else
        # Compute the width of the concatenation.
        width = self.each_expression.reduce(0) do |sum,expr|
            sum += expr.type.width
        end
        # Generate the missing bits if any.
        width = type.width - width
        res << '"' + "0" * width + '" & ' if width > 0
        # Generate the concatenation.
        res << self.each_expression.map do |expression|
            # "(" + Low2VHDL.to_type(type,expression) + ")"
            "(" + expression.to_vhdl(level+1) + ")"
        end.join(" & ")
    end
    # 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)


5147
5148
5149
5150
# File 'lib/HDLRuby/hruby_low.rb', line 5147

def use_name?(*names)
    # Recurse on the expressions.
    return @expressions.any? { |expr| expr.use_name?(*names) }
end