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)



4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
# File 'lib/HDLRuby/hruby_low.rb', line 4636

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.



4632
4633
4634
# File 'lib/HDLRuby/hruby_low.rb', line 4632

def range
  @range
end

#refObject (readonly)

The accessed reference.



4629
4630
4631
# File 'lib/HDLRuby/hruby_low.rb', line 4629

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)



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

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.



4690
4691
4692
4693
4694
4695
4696
4697
# File 'lib/HDLRuby/hruby_low.rb', line 4690

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.



4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
# File 'lib/HDLRuby/hruby_low.rb', line 4702

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)


4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
# File 'lib/HDLRuby/hruby_low.rb', line 4665

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.



4677
4678
4679
# File 'lib/HDLRuby/hruby_low.rb', line 4677

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

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children.



1681
1682
1683
1684
1685
1686
1687
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1681

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.



4684
4685
4686
4687
# File 'lib/HDLRuby/hruby_low.rb', line 4684

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.



1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1695

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.



1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1664

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.



1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1652

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.



1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
# File 'lib/HDLRuby/hruby_low2c.rb', line 1901

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.



1948
1949
1950
1951
1952
# File 'lib/HDLRuby/hruby_low2c.rb', line 1948

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