Class: HDLRuby::Low::Cast

Inherits:
Expression
  • Object
show all
Includes:
OneChildMutable
Defined in:
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_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 Cast class with functionality for extracting expressions from 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!, #leftvalue?, #map_nodes!, #replace_expressions!, #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, child) ⇒ Cast

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



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

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



4981
4982
4983
# File 'lib/HDLRuby/hruby_low.rb', line 4981

def child
  @child
end

Instance Method Details

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



198
199
200
201
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 198

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.



184
185
186
187
188
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
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 184

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)



5070
5071
5072
# File 'lib/HDLRuby/hruby_low.rb', line 5070

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.



5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
# File 'lib/HDLRuby/hruby_low.rb', line 5005

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.



5032
5033
5034
5035
5036
5037
# File 'lib/HDLRuby/hruby_low.rb', line 5032

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.



5042
5043
5044
5045
5046
5047
5048
5049
# File 'lib/HDLRuby/hruby_low.rb', line 5042

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.



5054
5055
5056
5057
5058
5059
5060
5061
# File 'lib/HDLRuby/hruby_low.rb', line 5054

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)


5017
5018
5019
5020
5021
5022
5023
5024
# File 'lib/HDLRuby/hruby_low.rb', line 5017

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.



241
242
243
244
245
246
247
248
249
250
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 241

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.



5027
5028
5029
# File 'lib/HDLRuby/hruby_low.rb', line 5027

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

#immutable?Boolean

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

Returns:

  • (Boolean)


4997
4998
4999
5000
# File 'lib/HDLRuby/hruby_low.rb', line 4997

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)



2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
# File 'lib/HDLRuby/hruby_low2c.rb', line 2332

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.



567
568
569
570
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 567

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.



402
403
404
# File 'lib/HDLRuby/hruby_low2high.rb', line 402

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.



1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
# File 'lib/HDLRuby/hruby_verilog.rb', line 1738

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
        if (sw>cw) then
            # Need to sign extend.
            return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," +
                "#{self.child.to_verilog}})"
        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.



1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1217

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

#use_name?(*names) ⇒ Boolean

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

Returns:

  • (Boolean)


5064
5065
5066
5067
# File 'lib/HDLRuby/hruby_low.rb', line 5064

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