Class: HDLRuby::Low::Cast

Inherits:
Expression show all
Includes:
OneChildMutable
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_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 cast.

Direct Known Subclasses

High::Cast

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 included from OneChildMutable

#map_nodes!, #replace_expressions!, #set_child!

Methods inherited from Expression

#boolean?, #break_types!, #extract_selects_to!, #fix_scope_refnames!, #leftvalue?, #map_nodes!, #replace_expressions!, #replace_names!, #rightvalue?, #set_type!, #signal2subs!, #statement, #to_c_expr, #to_viz_names

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#absolute_ref, #hierarchy, #no_parent!, #scope

Constructor Details

#initialize(type, child) ⇒ Cast

Creates a new cast of +child+ to +type+.



5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
# File 'lib/HDLRuby/hruby_low.rb', line 5180

def initialize(type,child)
    # Create the expression and set the type
    super(type)
    # Check and set the child.
    unless child.is_a?(Expression)
        raise AnyError,"Invalid class for an expression: #{child.class}"
    end
    @child = child
    # And set its parent.
    child.parent = self
end

Instance Attribute Details

#childObject (readonly)

The child



5177
5178
5179
# File 'lib/HDLRuby/hruby_low.rb', line 5177

def child
  @child
end

Instance Method Details

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



204
205
206
207
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 204

def boolean_in_assign2select
    # Recurse on the child.
    return Cast.new(self.type,self.child.boolean_in_assign2select)
end

#casts_without_expression!Object

Extracts the expressions from the casts.



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 189

def casts_without_expression!
    # Recurse on the child.
    nchild = self.child.casts_without_expression!
    nchild.parent = nil
    # Process the cast.
    unless (nchild.is_a?(Ref)) then
        # Need to extract the child.
        # Create signal holding the child.
        stmnt = self.statement
        if (stmnt.is_a?(Connection)) then
            # Specific case of connections: need to build
            # a new block.
            scop = stmnt.parent
            scop.delete_connection!(stmnt)
            stmnt = Transmit.new(stmnt.left.clone, stmnt.right.clone)
            blk = Block.new(:seq)
            scop.add_behavior(Behavior.new(blk))
            blk.add_statement(stmnt)
        else
            blk = stmnt.block
        end
        name = HDLRuby.uniq_name
        typ = nchild.type
        sig = blk.add_inner(SignalI.new(name,typ))
        # Add a statement assigning the child to the new signal.
        nref = RefName.new(typ,RefThis.new,name)
        nstmnt = Transmit.new(nref,nchild)
        idx = blk.each_statement.find_index(stmnt)
        blk.insert_statement!(idx,nstmnt)
        # Replace the child by a reference to the created
        # signal.
        nchild = nref.clone
    end
    return Cast.new(self.type,nchild)
end

#cloneObject

Clones the value (deeply)



5266
5267
5268
# File 'lib/HDLRuby/hruby_low.rb', line 5266

def clone
    return Cast.new(@type,@child.clone)
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
# File 'lib/HDLRuby/hruby_low.rb', line 5201

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 child.
    self.child.each_deep(&ruby_block)
end

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

Iterates over the expression children if any.



5228
5229
5230
5231
5232
5233
# File 'lib/HDLRuby/hruby_low.rb', line 5228

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 child.
    ruby_block.call(@child)
end

#each_node_deep(&ruby_block) ⇒ Object

Iterates over the nodes deeply if any.



5238
5239
5240
5241
5242
5243
5244
5245
# File 'lib/HDLRuby/hruby_low.rb', line 5238

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 child.
    @child.each_node_deep(&ruby_block)
end

#each_ref_deep(&ruby_block) ⇒ Object

Iterates over all the references encountered in the expression.

NOTE: do not iterate inside the references.



5250
5251
5252
5253
5254
5255
5256
5257
# File 'lib/HDLRuby/hruby_low.rb', line 5250

def each_ref_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_ref_deep) unless ruby_block
    # puts "each_ref_deep for Unary"
    # A ruby block?
    # Recurse on the child.
    @child.each_ref_deep(&ruby_block)
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


5213
5214
5215
5216
5217
5218
5219
5220
# File 'lib/HDLRuby/hruby_low.rb', line 5213

def eql?(obj)
    # General comparison.
    return false unless super(obj)
    # Specific comparison.
    return false unless obj.is_a?(Cast)
    return false unless @child.eql?(obj.child)
    return true
end

#explicit_types(type = nil) ⇒ Object

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



261
262
263
264
265
266
267
268
269
270
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 261

def explicit_types(type = nil)
    # Does the type match the cast?
    if type && !self.type.eql?(type) then
        # No, Recurse on the child tomatch the type.
        return self.child.explicit_types(type)
    else
        # No simply recurse on the child with the cast's type.
        return self.child.explicit_types(self.type)
    end
end

#hashObject

Hash function.



5223
5224
5225
# File 'lib/HDLRuby/hruby_low.rb', line 5223

def hash
    return [super,@child].hash
end

#immutable?Boolean

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

Returns:

  • (Boolean)


5193
5194
5195
5196
# File 'lib/HDLRuby/hruby_low.rb', line 5193

def immutable?
    # Immutable if the child is immutable.
    return child.immutable?
end

#to_c(res, level = 0) ⇒ Object

return res end Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c(level = 0)



2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
# File 'lib/HDLRuby/hruby_low2c.rb', line 2344

def to_c(res,level = 0)
    # Save the value pool state.
    res << (" " * (level*3)) << "PV;\n"
    # Generate the child.
    self.child.to_c(res,level)
    res << (" " * (level*3))
    # res << "d=cast(d,"
    res << "cast("
    self.type.to_c(res,level+1)
    res << ");\n"
    # Restore the value pool state.
    res << (" " * (level*3)) << "RV;\n"
    return res
end

#to_hdr(level = 0) ⇒ Object

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



582
583
584
585
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 582

def to_hdr(level = 0)
    return self.child.to_hdr(level) + 
        ".as(" + self.type.to_hdr(level) + ")"
end

#to_highObject

Creates a new high cast expression.



434
435
436
# File 'lib/HDLRuby/hruby_low2high.rb', line 434

def to_high
    return HDLRuby::High::Cast(self.type.to_high, self.child.to_high)
end

#to_verilogObject

Converts the system to Verilog code. NOTE: the cast is rounded up size bit-width cast is not supported by traditional verilog.



1858
1859
1860
1861
1862
1863
1864
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 1858

def to_verilog
    if self.child.is_a?(Value) then
        return self.child.to_verilog
    end
    # Get the type widths, used for computing extensions or truncations.
    cw = self.child.type.width
    sw = self.type.width
    if self.type.signed? then
        # Need to sign extend.
        if cw == 1 then
            return "$signed({#{sw}{#{self.child.to_verilog}}})"
        elsif (sw>cw) then
            # return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + "#{self.child.to_verilog}})"
            if self.child.is_a?(RefName) then
                return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + "#{self.child.to_verilog}})"
            else
                # No a pure signal, need to use a function for accessing.
                at = self.child.type.to_verilog
                rt = bit.to_verilog
                IndexersI.add(at,rt)
                return "$signed({{#{sw-cw}{#{IndexersI.indexer_name(at,rt)}(#{self.child.to_verilog},#{cw-1})}}," + "#{self.child.to_verilog}})"
            end
        elsif (sw<cw) then
            # Need to truncate
            # return "$signed(#{self.child.to_verilog}[#{sw-1}:0])"
            TruncersI.add((cw-1)..0,(sw-1)..0)
            return "$signed(#{TruncersI.truncer_name((cw-1)..0,(sw-1)..0)}(#{self.child.to_verilog}))"
        else
            # Only enforce signed.
            return "$signed(#{self.child.to_verilog})"
        end
    else
        if (sw>cw) then
            # Need to extend.
            return "$unsigned({{#{sw-cw}{1'b0}},#{self.child.to_verilog}})"
        elsif (sw<cw) then
            # Need to truncate
            # return "$unsigned(#{self.child.to_verilog}[#{sw-1}:0])"
            TruncersI.add((cw-1)..0,(sw-1)..0)
            return "$unsigned(#{TruncersI.truncer_name((cw-1)..0,(sw-1)..0)}(#{self.child.to_verilog}))"
        else
            # Only enforce signed.
            return "$unsigned(#{self.child.to_verilog})"
        end
    end
end

#to_vhdl(level = 0) ⇒ Object

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



1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1241

def to_vhdl(level = 0)
    if type.class == TypeVector then
        case type.base.name
        when :bit
            return "std_logic_vector(resize(unsigned(" + 
                self.child.to_vhdl(level) + ")," +
                (type.range.first-type.range.last+1).abs.to_s + "))"
        when :signed
            return "resize(signed(" + 
                self.child.to_vhdl(level) + ")," +
                (type.range.first-type.range.last+1).abs.to_s + ")"
        when :unsigned
            return "resize(unsigned(" + 
                self.child.to_vhdl(level) + ")," +
                (type.range.first-type.range.last+1).abs.to_s + ")"
        else
            raise "Intenal error: convertion to #{type.class} not supported yet for VHDL conversion."
        end
    elsif [:bit,:signed,:unsigned].include?(type.name) then
        # No conversion required.
        return self.child.to_vhdl(level)
    else
        raise "Intenal error: convertion to #{type.class} not supported yet for VHDL conversion."
    end
end

#to_viz_node(parent) ⇒ Object

Converts the value to a Viz flow node under +parent+.



4909
4910
4911
4912
4913
4914
# File 'lib/HDLRuby/hruby_viz.rb', line 4909

def to_viz_node(parent)
  node = HDLRuby::Viz::Node.new(:cast,parent,self.type.to_viz_name)
  # And generate the children.
  self.child.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)


5260
5261
5262
5263
# File 'lib/HDLRuby/hruby_low.rb', line 5260

def use_name?(*names)
    # Recurse on the child.
    return @child.use_name?(*names)
end