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!, #signal2subs!, #statement, #to_c_expr

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #no_parent!, #scope

Constructor Details

#initialize(type, ref, range) ⇒ RefRange

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



5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
# File 'lib/HDLRuby/hruby_low.rb', line 5892

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.



5888
5889
5890
# File 'lib/HDLRuby/hruby_low.rb', line 5888

def range
  @range
end

#refObject (readonly)

The accessed reference.



5885
5886
5887
# File 'lib/HDLRuby/hruby_low.rb', line 5885

def ref
  @ref
end

Instance Method Details

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



312
313
314
315
316
317
318
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 312

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)



6004
6005
6006
6007
# File 'lib/HDLRuby/hruby_low.rb', line 6004

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.



5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
# File 'lib/HDLRuby/hruby_low.rb', line 5926

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.



5973
5974
5975
5976
5977
5978
5979
5980
# File 'lib/HDLRuby/hruby_low.rb', line 5973

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.



5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
# File 'lib/HDLRuby/hruby_low.rb', line 5985

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)


5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
# File 'lib/HDLRuby/hruby_low.rb', line 5948

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.



425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 425

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)


165
166
167
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 165

def from_systemI?
    return self.ref.from_systemI?
end

#hashObject

Hash function.



5960
5961
5962
# File 'lib/HDLRuby/hruby_low.rb', line 5960

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

#immutable?Boolean

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

Returns:

  • (Boolean)


5918
5919
5920
5921
# File 'lib/HDLRuby/hruby_low.rb', line 5918

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

#map_nodes!(&ruby_block) ⇒ Object Also known as: map_expressions!

Maps on the children.



1872
1873
1874
1875
1876
1877
1878
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1872

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.



5967
5968
5969
5970
# File 'lib/HDLRuby/hruby_low.rb', line 5967

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.



1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
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
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1888

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.



172
173
174
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 172

def resolve
    return self.ref.resolve
end

#set_range!(range) ⇒ Object

Sets the range.



1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1855

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.



1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1843

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



3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
# File 'lib/HDLRuby/hruby_low2c.rb', line 3014

def to_c(res,level = 0, left = false)
    # Save the value pool state.
    res << (" " * (level*3)) << "PV;\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)



3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
# File 'lib/HDLRuby/hruby_low2c.rb', line 3055

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.



1492
1493
1494
# File 'lib/HDLRuby/hruby_verilog.rb', line 1492

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.



1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1475

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)


5997
5998
5999
6000
6001
# File 'lib/HDLRuby/hruby_low.rb', line 5997

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