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

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

#scope

Constructor Details

#initialize(type, ref, range) ⇒ RefRange

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



4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
# File 'lib/HDLRuby/hruby_low.rb', line 4720

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.



4716
4717
4718
# File 'lib/HDLRuby/hruby_low.rb', line 4716

def range
  @range
end

#refObject (readonly)

The accessed reference.



4713
4714
4715
# File 'lib/HDLRuby/hruby_low.rb', line 4713

def ref
  @ref
end

Instance Method Details

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



286
287
288
289
290
291
292
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 286

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

#cloneObject

Clones the range references (deeply)



4805
4806
4807
4808
# File 'lib/HDLRuby/hruby_low.rb', line 4805

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

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

Iterates over the reference children if any.



4774
4775
4776
4777
4778
4779
4780
4781
# File 'lib/HDLRuby/hruby_low.rb', line 4774

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.



4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
# File 'lib/HDLRuby/hruby_low.rb', line 4786

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)


4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
# File 'lib/HDLRuby/hruby_low.rb', line 4749

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.



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 391

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)


105
106
107
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 105

def from_systemI?
    return self.ref.from_systemI?
end

#hashObject

Hash function.



4761
4762
4763
# File 'lib/HDLRuby/hruby_low.rb', line 4761

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

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children.



1769
1770
1771
1772
1773
1774
1775
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1769

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.



4768
4769
4770
4771
# File 'lib/HDLRuby/hruby_low.rb', line 4768

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.



1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1783

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

#set_range!(range) ⇒ Object

Sets the range.



1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1752

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.



1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1740

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(level = 0, left = false) ⇒ Object

Generates the C text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object and +left+ tells if it is a left value or not.



1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
# File 'lib/HDLRuby/hruby_low2c.rb', line 1923

def to_c(level = 0, left = false)
    # if left then
    #     res = "write_range(#{self.ref.to_c(level,left)},"
    # else
    #     res = "read_range(#{self.ref.to_c(level,left)},"
    # end
    # res << "read64(#{self.range.first.to_c(level)})," +
    #        "read64(#{self.range.last.to_c(level)})," +
    #        "#{self.type.base.to_c(level)})"
    # return res
    # Decide if it is a read or a write
    command = left ? "write" : "read"
    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"
    # Compute the range.
    res << (" " * ((level+1)*3))
    # res << "first = read64(#{self.range.first.to_c(level+2)});\n"
    res << "first = value2integer(#{self.range.first.to_c(level+2)});\n"
    res << (" " * ((level+1)*3))
    # res << "last = read64(#{self.range.last.to_c(level+2)});\n"
    res << "last = value2integer(#{self.range.last.to_c(level+2)});\n"
    # Make the access.
    res << (" " * ((level+1)*3))
    # res << "dst = #{command}_range(ref,first,last,#{self.ref.type.base.to_c(level)},dst);\n"
    # puts "will read_range for #{self.ref.name} with width=#{self.ref.type.width} with base width=#{self.ref.type.base.width} with range=#{self.ref.type.range} with range=#{self.range.first.content}..#{self.range.last.content}"
    res << "dst = #{command}_range(ref,first,last,#{self.type.base.to_c(level)},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; })"
end

#to_c_signal(level = 0) ⇒ Object

Generates the C text for reference as left value to a signal. +level+ is the hierarchical level of the object.



1970
1971
1972
1973
1974
# File 'lib/HDLRuby/hruby_low2c.rb', line 1970

def to_c_signal(level = 0)
    # return to_c(level,true)
    return "make_ref_rangeS(#{self.ref.to_c_signal(level)}," +
        "value2integer(#{self.range.first.to_c(level)}),value2integer(#{self.range.last.to_c(level)}))"
end

#to_high(level = 0) ⇒ Object

Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.



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

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

#to_verilog(unknown = false) ⇒ Object

Converts the system to Verilog code.



1362
1363
1364
# File 'lib/HDLRuby/hruby_verilog.rb', line 1362

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.



1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1437

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)


4798
4799
4800
4801
4802
# File 'lib/HDLRuby/hruby_low.rb', line 4798

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