Class: HDLRuby::Low::RefRange

Inherits:
Ref 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_resolve.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 RefRange class with functionality for converting booleans in assignments to select operators.

Direct Known Subclasses

High::RefRange

Constant Summary

Constants included from Low2Symbol

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

Instance Attribute Summary collapse

Attributes inherited from Expression

#type

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods inherited from Expression

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

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #scope

Constructor Details

#initialize(type, ref, range) ⇒ RefRange

Create a new range reference with +type+ accessing +ref+ at +range+. def initialize(ref,range)



5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
# File 'lib/HDLRuby/hruby_low.rb', line 5455

def initialize(type,ref,range)
    super(type)
    # Check and set the refered object.
    # unless ref.is_a?(Ref) then
    unless ref.is_a?(Expression) then
        raise AnyError, "Invalid class for a reference: #{ref.class}."
    end
    @ref = ref
    # And set its parent.
    ref.parent = self
    # Check and set the range.
    first = range.first
    unless first.is_a?(Expression) then
        raise AnyError,
              "Invalid class for a range first: #{first.class}."
    end
    last = range.last
    unless last.is_a?(Expression) then
        raise AnyError, "Invalid class for a range last: #{last.class}."
    end
    @range = first..last
    # And set their parents.
    first.parent = last.parent = self
end

Instance Attribute Details

#rangeObject (readonly)

The access range.



5451
5452
5453
# File 'lib/HDLRuby/hruby_low.rb', line 5451

def range
  @range
end

#refObject (readonly)

The accessed reference.



5448
5449
5450
# File 'lib/HDLRuby/hruby_low.rb', line 5448

def ref
  @ref
end

Instance Method Details

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



300
301
302
303
304
305
306
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 300

def boolean_in_assign2select
    # Recurse on the sub references.
    return RefRange.new(self.type,
                        self.ref.boolean_in_assign2select,
                        self.range.first.boolean_in_assign2select ..
                        self.range.last.boolean_in_assign2select)
end

#casts_without_expression!Object

Extracts the expressions from the casts.



323
324
325
326
327
328
329
330
331
332
333
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 323

def casts_without_expression!
    # Recurse on the sub references.
    # return RefRange.new(self.type,
    #                     self.ref.casts_without_expression,
    #                     self.range.first.casts_without_expression ..
    #                     self.range.last.casts_without_expression)
    self.set_ref!(self.ref.casts_without_expression!)
    self.set_range!(self.range.first.casts_without_expression! ..
                    self.range.last.casts_without_expression!)
    return self
end

#cloneObject

Clones the range references (deeply)



5567
5568
5569
5570
# File 'lib/HDLRuby/hruby_low.rb', line 5567

def clone
    return RefRange.new(@type, @ref.clone,
                        (@range.first.clone)..(@range.last.clone) )
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
# File 'lib/HDLRuby/hruby_low.rb', line 5489

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 reference.
    self.ref.each_deep(&ruby_block)
    # Then apply on the range if possible.
    if self.range.first.respond_to?(:each_deep) then
        self.range.first.each_deep(&ruby_block)
    end
    if self.range.last.respond_to?(:each_deep) then
        self.range.last.each_deep(&ruby_block)
    end
end

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

Iterates over the reference children if any.



5536
5537
5538
5539
5540
5541
5542
5543
# File 'lib/HDLRuby/hruby_low.rb', line 5536

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 ranfe and the ref.
    ruby_block.call(@range.first)
    ruby_block.call(@range.last)
    ruby_block.call(@ref)
end

#each_node_deep(&ruby_block) ⇒ Object

Iterates over the nodes deeply if any.



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

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.
    @range.first.each_node_deep(&ruby_block)
    @range.last.each_node_deep(&ruby_block)
    @ref.each_node_deep(&ruby_block)
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

NOTE: ranges are assumed to be flattened (a range of range is a range of same level).

Returns:

  • (Boolean)


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

def eql?(obj)
    # General comparison.
    return false unless super(obj)
    # Specific comparison.
    return false unless obj.is_a?(RefRange)
    return false unless @range.first.eql?(obj.range.first)
    return false unless @range.last.eql?(obj.range.last)
    return false unless @ref.eql?(obj.ref)
    return true
end

#explicit_types(type = nil) ⇒ Object

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



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 405

def explicit_types(type = nil)
    # Is there a type to match ?
    if type then
        # Regenerate the reference and cast it.
        return Cast.new(type,
                    RefRange.new(self.type,self.ref.explicit_types,
                            self.range.first.explicit_types ..
                            self.range.last.explicit_types))
    else
        # No, recurse with the type of the current range ref.
        return RefRange.new(self.type,
                            self.ref.explicit_types,
                            self.range.first.explicit_types ..
                            self.range.last.explicit_types)
    end
end

#from_systemI?Boolean

Tells if it is a reference to a systemI signal.

Returns:

  • (Boolean)


126
127
128
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 126

def from_systemI?
    return self.ref.from_systemI?
end

#hashObject

Hash function.



5523
5524
5525
# File 'lib/HDLRuby/hruby_low.rb', line 5523

def hash
    return [super,@range,@ref].hash
end

#immutable?Boolean

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

Returns:

  • (Boolean)


5481
5482
5483
5484
# File 'lib/HDLRuby/hruby_low.rb', line 5481

def immutable?
    # Immutable if the ref is immutable.
    return self.ref.immutable?
end

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children.



1851
1852
1853
1854
1855
1856
1857
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1851

def map_nodes!(&ruby_block)
    @range = ruby_block.call(@range.first)..ruby_block.call(@range.last)
    @range.first.parent = self unless @range.first.parent
    @range.last.parent = self unless @range.last.parent
    @ref   = ruby_block.call(@ref)
    @ref.parent = self unless @ref.parent
end

#path_each(&ruby_block) ⇒ Object

Iterates over the names of the path indicated by the reference.

Returns an enumerator if no ruby block is given.



5530
5531
5532
5533
# File 'lib/HDLRuby/hruby_low.rb', line 5530

def path_each(&ruby_block)
    # Recurse on the base reference.
    return ref.path_each(&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.



1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1865

def replace_expressions!(node2rep)
    # First recurse on the ref.
    res = self.ref.replace_expressions!(node2rep)
    # And and the range.
    res = self.range.first.replace_expressions!(node2rep)
    res = self.range.last.replace_expressions!(node2rep)
    
    # Is there a replacement to on the ref?
    rep = node2rep[self.ref]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = self.ref
        # node.set_parent!(nil)
        self.set_ref!(rep)
        # And register the replacement.
        res[node] = rep
    end
    # Is there a replacement to on the range first?
    range = self.range
    rep = node2rep[range.first]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = range.first
        # node.set_parent!(nil)
        range.first = rep
        # And register the replacement.
        res[node] = rep
    end
    rep = node2rep[range.last]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = range.last
        # node.set_parent!(nil)
        range.last = rep
        # And register the replacement.
        res[node] = rep
    end
    self.set_range!(range)
    return res
end

#resolveObject

Resolves the name of the reference (if any) and return the corresponding object. NOTE: return nil if could not resolve.



133
134
135
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 133

def resolve
    return self.ref.resolve
end

#set_range!(range) ⇒ Object

Sets the range.



1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1834

def set_range!(range)
    # Check and set the range.
    first = range.first
    unless first.is_a?(Expression) then
        raise AnyError,
              "Invalid class for a range first: #{first.class}."
    end
    last = range.last
    unless last.is_a?(Expression) then
        raise AnyError, "Invalid class for a range last: #{last.class}."
    end
    @range = first..last
    # And set their parents.
    first.parent = last.parent = self
end

#set_ref!(ref) ⇒ Object

Sets the base reference.



1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1822

def set_ref!(ref)
    # Check and set the refered object.
    # unless ref.is_a?(Ref) then
    unless ref.is_a?(Expression) then
        raise AnyError, "Invalid class for a reference: #{ref.class}."
    end
    @ref = ref
    # And set its parent.
    ref.parent = self
end

#to_c(res, level = 0, left = false) ⇒ Object

Generates the C text of the equivalent HDLRuby code.

+level+ is the hierachical level of the object and

+left+ tells if it is a left value or not.

def to_c(level = 0, left = false)

def to_c(res,level = 0, left = false) # Decide if it is a read or a write command = left ? "write" : "read" # res = "( res << "({\n" # Overrides the upper ref and dst... # And allocates a new value for dst. res << (" " * ((level+1)*3)) res << "Value ref,dst = get_value();\n" res << (" " * ((level+1)*3)) res << "unsigned long long first,last;\n" # Save the state of the value pool. res << (" " * ((level+1)*3)) res << "unsigned int pool_state = get_value_pos();\n" # Compute the reference. res << (" " * ((level+1)*3)) # res << "ref = #{self.ref.to_c(level+2);\n" res << "ref = " self.ref.to_c(res,level+2) res << ";\n" # Compute the range. res << (" " * ((level+1)*3)) # res << "first = value2integer(#HDLRuby::Low::RefRange.selfself.rangeself.range.firstself.range.first.to_c(level+2));\n" res << "first = value2integer(" self.range.first.to_c(res,level+2) res << ");\n" res << (" " * ((level+1)*3)) # res << "last = value2integer(#HDLRuby::Low::RefRange.selfself.rangeself.range.lastself.range.last.to_c(level+2));\n" res << "last = value2integer(" self.range.last.to_c(res,level+2) res << ");\n" # Make the access. res << (" " * ((level+1)*3)) # puts "#command_range with first=#HDLRuby::Low::RefRange.selfself.rangeself.range.first and last=#HDLRuby::Low::RefRange.selfself.rangeself.range.last" # res << "dst = #command_range(ref,first,last,#HDLRuby::Low::RefRange.selfself.typeself.type.baseself.type.base.to_c(level),dst);\n" res << "dst = #command_range(ref,first,last," self.type.base.to_c(res,level) res << ",dst);\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



2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
# File 'lib/HDLRuby/hruby_low2c.rb', line 2719

def to_c(res,level = 0, left = false)
    # Save the value pool state.
    res << (" " * (level*3)) << "SV;\n"
    # Compute the reference.
    self.ref.to_c(res,level)
    # res << (" " * (level*3))
    # Compute the range.
    self.range.first.to_c(res,level)
    self.range.last.to_c(res,level)
    # Make the access.
    res << (" " * (level*3))
    if left then
        res << "swriteR("
    else
        res << "sreadR("
    end
    self.type.base.to_c(res,level)
    res << ");\n"
    # Restore the value pool state.
    res << (" " * (level*3)) << "RV;\n"
    return res
end

#to_c_signal(res, level = 0) ⇒ Object

Generates the C text for reference as left value to a signal.

+level+ is the hierarchical level of the object.

def to_c_signal(level = 0)

def to_c_signal(res,level = 0) # return "make_ref_rangeS(#HDLRuby::Low::RefRange.selfself.refself.ref.to_c_signal(level)," + # "value2integer(#HDLRuby::Low::RefRange.selfself.rangeself.range.firstself.range.first.to_c(level)),value2integer(#HDLRuby::Low::RefRange.selfself.rangeself.range.lastself.range.last.to_c(level)))" res << "make_ref_rangeS(" self.ref.to_c_signal(res,level) res << ",value2integer(" self.range.first.to_c(res,level) res << "),value2integer(" self.range.last.to_c(res,level) res << "))" return res end Generates the C text for reference as left value to a signal. +level+ is the hierarchical level of the object. def to_c_signal(level = 0)



2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
# File 'lib/HDLRuby/hruby_low2c.rb', line 2760

def to_c_signal(res,level = 0)
    res << "make_ref_rangeS("
    self.ref.to_c_signal(res,level)
    res << ","
    self.type.base.to_c(res,level)
    res << ",value2integer(({\n"
    self.range.first.to_c(res,level)
    res << " " * ((level+1)*3)
    res << "pop();})"
    res << "),value2integer(({\n"
    self.range.last.to_c(res,level)
    res << " " * ((level+1)*3)
    res << "pop();})"
    res << "))"
    return res
end

#to_hdr(level = 0) ⇒ Object

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



695
696
697
698
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 695

def to_hdr(level = 0)
    return self.ref.to_hdr(level) +
        "[(#{self.range.first.to_hdr(level)})..(#{self.range.last.to_hdr(level)})]"
end

#to_highObject

Creates a new high range reference.



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

def to_high
    return HDLRuby::High::RefRange.new(self.type.to_high,
                                       self.ref.to_high,
                    self.range.first.to_high..self.range.last.to_high)
end

#to_verilog(unknown = false) ⇒ Object

Converts the system to Verilog code.



1475
1476
1477
# File 'lib/HDLRuby/hruby_verilog.rb', line 1475

def to_verilog(unknown = false)
    return "#{self.ref.to_verilog}[#{self.range.first.to_getrange}:#{self.range.last.to_getrange}]"
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. +std_logic+ tells if std_logic computation is to be done.



1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1462

def to_vhdl(level = 0, std_logic = false)
    # Generates the direction.
    first = self.range.first
    first = first.content if first.is_a?(Value)
    last = self.range.last
    last = last.content if last.is_a?(Value)
    direction = first >= last ?  "downto " : " to "
    # Generate the reference.
    # Forced std_logic case.
    if std_logic then
        if first == last then
            # No range, single bit access for forcing std_logic.
            return self.ref.to_vhdl(level) +
                "(#{self.range.first.to_vhdl(level)})"
        else
            return self.ref.to_vhdl(level) +
                "((#{self.range.first.to_vhdl(level)}) " +
                direction + "(#{self.range.last.to_vhdl(level)}))(0)"
        end
    else
        return self.ref.to_vhdl(level) +
            "((#{self.range.first.to_vhdl(level)}) " +
            direction + "(#{self.range.last.to_vhdl(level)}))"
    end
end

#use_name?(*names) ⇒ Boolean

Tell if the expression includes a signal whose name is one of +names+.

Returns:

  • (Boolean)


5560
5561
5562
5563
5564
# File 'lib/HDLRuby/hruby_low.rb', line 5560

def use_name?(*names)
    # Recurse on the range and the reference.
    return @range.first.use_name?(names) ||
           @range.last.use_name?(names)  || @ref.use_name?(*names)
end