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!, #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+.



4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
# File 'lib/HDLRuby/hruby_low.rb', line 4813

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



4810
4811
4812
# File 'lib/HDLRuby/hruby_low.rb', line 4810

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)



4899
4900
4901
# File 'lib/HDLRuby/hruby_low.rb', line 4899

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.



4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
# File 'lib/HDLRuby/hruby_low.rb', line 4834

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.



4861
4862
4863
4864
4865
4866
# File 'lib/HDLRuby/hruby_low.rb', line 4861

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.



4871
4872
4873
4874
4875
4876
4877
4878
# File 'lib/HDLRuby/hruby_low.rb', line 4871

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.



4883
4884
4885
4886
4887
4888
4889
4890
# File 'lib/HDLRuby/hruby_low.rb', line 4883

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)


4846
4847
4848
4849
4850
4851
4852
4853
# File 'lib/HDLRuby/hruby_low.rb', line 4846

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.



4856
4857
4858
# File 'lib/HDLRuby/hruby_low.rb', line 4856

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

#immutable?Boolean

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

Returns:

  • (Boolean)


4826
4827
4828
4829
# File 'lib/HDLRuby/hruby_low.rb', line 4826

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)



2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
# File 'lib/HDLRuby/hruby_low2c.rb', line 2300

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.



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

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)


4893
4894
4895
4896
# File 'lib/HDLRuby/hruby_low.rb', line 4893

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