Class: HDLRuby::Low::Concat

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

Overview

Describes a concatenation expression.

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!, #signal2subs!, #statement, #to_c_expr

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #no_parent!, #scope

Constructor Details

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

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



5492
5493
5494
5495
5496
5497
5498
5499
# File 'lib/HDLRuby/hruby_low.rb', line 5492

def initialize(type,expressions = [])
    super(type)
    # puts "Building concat=#{self} with direction=#{type.direction}\n"
    # 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.



5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
# File 'lib/HDLRuby/hruby_low.rb', line 5546

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.



282
283
284
285
286
287
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 282

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.



284
285
286
287
288
289
290
291
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 284

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)



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

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

#delete_expression!(expression) ⇒ Object

Delete an expression.



1650
1651
1652
1653
1654
1655
1656
1657
1658
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1650

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.



5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
# File 'lib/HDLRuby/hruby_low.rb', line 5512

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.



5562
5563
5564
5565
5566
5567
# File 'lib/HDLRuby/hruby_low.rb', line 5562

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.



5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
# File 'lib/HDLRuby/hruby_low.rb', line 5571

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)


5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
# File 'lib/HDLRuby/hruby_low.rb', line 5526

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.



351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 351

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.



5541
5542
5543
# File 'lib/HDLRuby/hruby_low.rb', line 5541

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5502
5503
5504
5505
5506
5507
# File 'lib/HDLRuby/hruby_low.rb', line 5502

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.



1639
1640
1641
1642
1643
1644
1645
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1639

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.



2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
# File 'lib/HDLRuby/hruby_low2c.rb', line 2734

def to_c(res,level = 0)
    # puts "to_c fo concat=#{self} with type=#{self.type} and direction=#{self.type.direction}"
    # Save the value pool state.
    res << (" " * (level*3)) << "PV;\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))
    # puts "self.type=#{self.type} self.type.direction=#{self.type.direction}\n"
    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_hdr(level = 0) ⇒ Object

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



651
652
653
654
655
656
657
658
659
660
661
662
663
664
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 651

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.



484
485
486
487
# File 'lib/HDLRuby/hruby_low2high.rb', line 484

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

#to_verilogObject

Enhances Concat with generation of verilog code.



1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
# File 'lib/HDLRuby/hruby_verilog.rb', line 1840

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)



1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1417

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)


5583
5584
5585
5586
# File 'lib/HDLRuby/hruby_low.rb', line 5583

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