Class: HDLRuby::Low::RefRange

Inherits:
Ref show all
Defined in:
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_viz.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

Describes a range reference.

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!, #fix_scope_refnames!, #leftvalue?, #replace_names!, #rightvalue?, #set_type!, #signal2subs!, #statement, #to_c_expr

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#absolute_ref, #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)



6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
# File 'lib/HDLRuby/hruby_low.rb', line 6062

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
    # Clears the parent of first and last that is automatically added
    # by Ruby when creating a range.
    first.no_parent! if first.is_a?(Hparent)
    last.no_parent! if last.is_a?(Hparent)
    # And set their parents.
    first.parent = last.parent = self
end

Instance Attribute Details

#rangeObject (readonly)

The access range.



6058
6059
6060
# File 'lib/HDLRuby/hruby_low.rb', line 6058

def range
  @range
end

#refObject (readonly)

The accessed reference.



6055
6056
6057
# File 'lib/HDLRuby/hruby_low.rb', line 6055

def ref
  @ref
end

Instance Method Details

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



324
325
326
327
328
329
330
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 324

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.



333
334
335
336
337
338
339
340
341
342
343
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 333

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)



6178
6179
6180
6181
# File 'lib/HDLRuby/hruby_low.rb', line 6178

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.



6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
# File 'lib/HDLRuby/hruby_low.rb', line 6100

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.



6147
6148
6149
6150
6151
6152
6153
6154
# File 'lib/HDLRuby/hruby_low.rb', line 6147

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.



6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
# File 'lib/HDLRuby/hruby_low.rb', line 6159

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)


6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
# File 'lib/HDLRuby/hruby_low.rb', line 6122

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.



454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 454

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)


161
162
163
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 161

def from_systemI?
    return self.ref.from_systemI?
end

#hashObject

Hash function.



6134
6135
6136
# File 'lib/HDLRuby/hruby_low.rb', line 6134

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

#immutable?Boolean

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

Returns:

  • (Boolean)


6092
6093
6094
6095
# File 'lib/HDLRuby/hruby_low.rb', line 6092

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.



1812
1813
1814
1815
1816
1817
1818
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1812

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.



6141
6142
6143
6144
# File 'lib/HDLRuby/hruby_low.rb', line 6141

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.



1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1828

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.



168
169
170
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 168

def resolve
    return self.ref.resolve
end

#set_range!(range) ⇒ Object

Sets the range.



1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1795

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.



1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1783

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



3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
# File 'lib/HDLRuby/hruby_low2c.rb', line 3028

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)



3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
# File 'lib/HDLRuby/hruby_low2c.rb', line 3069

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.



718
719
720
721
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 718

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.



523
524
525
526
527
# File 'lib/HDLRuby/hruby_low2high.rb', line 523

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.



1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
# File 'lib/HDLRuby/hruby_verilog.rb', line 1579

def to_verilog(unknown = false)
    if self.ref.is_a?(RefName) then
        return "#{self.ref.to_verilog}[#{self.range.first.to_getrange}:#{self.range.last.to_getrange}]"
    else
        # No a pure signal, need to use a function for accessing.
        # sr = self.range.first.to_i..self.range.last.to_i
        # cr = (self.type.width-1)..0
        sr = (self.range.first.to_i+1)*self.ref.type.base.width-1..
            self.range.last.to_i*self.ref.type.base.width
        cr = (self.ref.type.width-1)..0
        TruncersI.add(cr,sr)
        return "#{TruncersI.truncer_name(cr,sr)}(#{self.ref.to_verilog})"
    end
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.



1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1507

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

#to_viz_namesObject

Get the port names for visualization from the expression.



4978
4979
4980
4981
# File 'lib/HDLRuby/hruby_viz.rb', line 4978

def to_viz_names
  return self.ref.to_viz_names +
    self.range.first.to_viz_names + self.range.last.to_viz_names
end

#to_viz_node(parent) ⇒ Object

Converts the index reference to a Viz flow node under +parent+.



4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
# File 'lib/HDLRuby/hruby_viz.rb', line 4984

def to_viz_node(parent)
  # Create the viz node.
  node = HDLRuby::Viz::Node.new(:[],parent)
  # Generate the base.
  self.ref.to_viz_node(node)
  # Generate the range.
  self.range.first.to_viz_node(node)
  self.range.last.to_viz_node(node)
  return node
end

#use_name?(*names) ⇒ Boolean

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

Returns:

  • (Boolean)


6171
6172
6173
6174
6175
# File 'lib/HDLRuby/hruby_low.rb', line 6171

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