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, #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 = [])



5302
5303
5304
5305
5306
5307
5308
5309
# File 'lib/HDLRuby/hruby_low.rb', line 5302

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.



5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
# File 'lib/HDLRuby/hruby_low.rb', line 5356

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.



273
274
275
276
277
278
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 273

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)



5399
5400
5401
5402
# File 'lib/HDLRuby/hruby_low.rb', line 5399

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.



5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
# File 'lib/HDLRuby/hruby_low.rb', line 5322

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.



5372
5373
5374
5375
5376
5377
# File 'lib/HDLRuby/hruby_low.rb', line 5372

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.



5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
# File 'lib/HDLRuby/hruby_low.rb', line 5381

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)


5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
# File 'lib/HDLRuby/hruby_low.rb', line 5336

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.



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 326

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.



5351
5352
5353
# File 'lib/HDLRuby/hruby_low.rb', line 5351

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5312
5313
5314
5315
5316
5317
# File 'lib/HDLRuby/hruby_low.rb', line 5312

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.



2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
# File 'lib/HDLRuby/hruby_low2c.rb', line 2553

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



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



1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
# File 'lib/HDLRuby/hruby_verilog.rb', line 1780

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)



1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1387

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)


5393
5394
5395
5396
# File 'lib/HDLRuby/hruby_low.rb', line 5393

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