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

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#absolute_ref, #hierarchy, #no_parent!, #scope

Constructor Details

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

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



5662
5663
5664
5665
5666
5667
5668
5669
# File 'lib/HDLRuby/hruby_low.rb', line 5662

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.



5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
# File 'lib/HDLRuby/hruby_low.rb', line 5716

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)



5759
5760
5761
5762
# File 'lib/HDLRuby/hruby_low.rb', line 5759

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.



5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
# File 'lib/HDLRuby/hruby_low.rb', line 5682

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.



5732
5733
5734
5735
5736
5737
# File 'lib/HDLRuby/hruby_low.rb', line 5732

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.



5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
# File 'lib/HDLRuby/hruby_low.rb', line 5741

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)


5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
# File 'lib/HDLRuby/hruby_low.rb', line 5696

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.



5711
5712
5713
# File 'lib/HDLRuby/hruby_low.rb', line 5711

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5672
5673
5674
5675
5676
5677
# File 'lib/HDLRuby/hruby_low.rb', line 5672

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.



1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
# File 'lib/HDLRuby/hruby_verilog.rb', line 1943

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)


5753
5754
5755
5756
# File 'lib/HDLRuby/hruby_low.rb', line 5753

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