Class: HDLRuby::Low::Value

Inherits:
Expression
  • Object
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_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 Value class with functionality for extracting expressions from cast.

Direct Known Subclasses

High::Value

Constant Summary collapse

@@made_values =
Set.new

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_node, #each_node_deep, #each_ref_deep, #extract_selects_to!, #leftvalue?, #map_nodes!, #replace_expressions!, #replace_names!, #rightvalue?, #set_type!, #statement, #use_name?

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #scope

Constructor Details

#initialize(type, content) ⇒ Value

Creates a new value typed +type+ and containing +content+.



329
330
331
332
333
334
335
336
337
338
339
# File 'lib/HDLRuby/hruby_db.rb', line 329

def initialize(type,content)
    # Ensures type is from Low::Type
    type = Type.get(type)
    # # Ensures the content is valid for low-level hardware.
    # unless content.is_a?(Numeric) or 
    #        content.is_a?(HDLRuby::BitString) then
    #     raise "Invalid type for a value content: #{content.class}."
    # end # NOW CHECKED BY BASE
    # Initialize the value structure.
    super(type,content)
end

Instance Attribute Details

#contentObject (readonly)

The content of the value.



4650
4651
4652
# File 'lib/HDLRuby/hruby_low.rb', line 4650

def content
  @content
end

Instance Method Details

#<=>(value) ⇒ Object

Compare values.

NOTE: mainly used for being supported by ranges.



4714
4715
4716
4717
# File 'lib/HDLRuby/hruby_low.rb', line 4714

def <=>(value)
    value = value.content if value.respond_to?(:content)
    return self.content <=> value
end

#boolean_in_assign2selectObject

Converts booleans in assignments to select operators.



187
188
189
190
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 187

def boolean_in_assign2select
    # Simple clones.
    return self.clone
end

#casts_without_expression!Object

Extracts the expressions from the casts.



172
173
174
175
176
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 172

def casts_without_expression!
    # # Simple clones.
    # return self.clone
    return self
end

#cloneObject

Clones the value (deeply)



4740
4741
4742
# File 'lib/HDLRuby/hruby_low.rb', line 4740

def clone
    return Value.new(@type,@content)
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
# File 'lib/HDLRuby/hruby_low.rb', line 4682

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 content if possible.
    if self.content.respond_to?(:each_deep) then
        self.content.each_deep(&ruby_block)
    end
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


4696
4697
4698
4699
4700
4701
4702
4703
# File 'lib/HDLRuby/hruby_low.rb', line 4696

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

#even?Boolean

Tells if the value is even.

Returns:

  • (Boolean)


4725
4726
4727
# File 'lib/HDLRuby/hruby_low.rb', line 4725

def even?
    return @content.even?
end

#explicit_types(type = nil) ⇒ Object

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



224
225
226
227
228
229
230
231
232
233
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 224

def explicit_types(type = nil)
    # Does the type match the value?
    if type && !self.type.eql?(type) then
        # No, update the type of the value.
        return Value.new(type,self.content)
    else
        # yes, return the value as is.
        return self.clone
    end
end

#hashObject

Hash function.



4706
4707
4708
# File 'lib/HDLRuby/hruby_low.rb', line 4706

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

#immutable?Boolean

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

Returns:

  • (Boolean)


4674
4675
4676
4677
# File 'lib/HDLRuby/hruby_low.rb', line 4674

def immutable?
    # Values are always immutable.
    true
end

#odd?Boolean

Tells if the value is odd.

Returns:

  • (Boolean)


4730
4731
4732
# File 'lib/HDLRuby/hruby_low.rb', line 4730

def odd?
    return @content.odd?
end

#set_content!(content) ⇒ Object

Sets the content.



1379
1380
1381
1382
1383
1384
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1379

def set_content!(content)
    unless content.is_a?(Numeric) or content.is_a?(HDLRuby::BitString)
        content = HDLRuby::BitString.new(content.to_s)
    end
    @content = content 
end

#to_arithObject

Generate the text of the equivalent VHDL is case of arithmetic expression.



1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1155

def to_arith
    case self.content
    when HDLRuby::BitString
        if self.content.specified? then
            sign = self.type.signed? && self.content.to_s[-1] == "0" ?
                -1 : 1
            return (sign * self.content.to_s.to_i(2)).to_s
        else
            return self.content.to_s.upcase
        end
    else
        # NOTE: in VHDL, "z" and "x" must be upcase.
        return self.content.to_s.upcase
    end
end

#to_c(res, level = 0) ⇒ Object

Generates the C text for an access to the value. +level+ is the hierachical level of the object.



2013
2014
2015
2016
2017
2018
2019
2020
# File 'lib/HDLRuby/hruby_low2c.rb', line 2013

def to_c(res,level = 0)
    # res << Low2C.make_name(self) << "()"
    # return res
    res << (" " * (level*3))
    # res << "d=" << Low2C.make_name(self) << "();\n"
    res << "push(" << Low2C.make_name(self) << "());\n"
    return res
end

#to_c_expr(res, level = 0) ⇒ Object

Generates the C text for an expression access to the value. +level+ is the hierachical level of the object.



2024
2025
2026
2027
# File 'lib/HDLRuby/hruby_low2c.rb', line 2024

def to_c_expr(res,level = 0)
    res << Low2C.make_name(self) << "()"
    return res
end

#to_c_make(res, level = 0) ⇒ Object

Generates the text of the equivalent c. +level+ is the hierachical level of the object. def to_c_make(level = 0)



2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
# File 'lib/HDLRuby/hruby_low2c.rb', line 2043

def to_c_make(res,level = 0)
    # Check is the value maker is already present.
    maker = Low2C.make_name(self);
    # return "" if @@made_values.include?(maker)
    return res if @@made_values.include?(maker)
    @@made_values.add(maker)

    # The resulting string.
    # res = ""

    # The header of the value generation.
    res << " " * level*3
    # res << "Value " << Low2C.make_name(self) << "() {\n"
    res << "Value " << maker << "() {\n"

    # Declares the data.
    # Create the bit string.
    # str = self.content.is_a?(BitString) ?
    #     self.content.to_s : self.content.to_s(2).rjust(32,"0")
    if self.content.is_a?(BitString) then
        str = self.content.is_a?(BitString) ?
            self.content.to_s : self.content.to_s(2).rjust(32,"0")
    else
        # sign = self.content>=0 ? "0" : "1"
        # str = self.content.abs.to_s(2).rjust(width,sign).upcase
        if self.content >= 0 then
            str = self.content.to_s(2).rjust(width,"0").upcase
        else
            # Compute the extension to the next multiple
            # of int_width
            ext_width = (((width-1) / Low2C.int_width)+1)*Low2C.int_width
            # Convert the string.
            str = (2**ext_width+self.content).to_s(2).upcase
        end
        # puts "content=#{self.content} str=#{str}"
    end
    # Is it a fully defined number?
    # NOTE: bignum values are not supported by the simulation engine
    #       yet, therefore numeric values are limited to 64 max.
    if str =~ /^[01]+$/ && str.length <= 64 then
        # Yes, generate a numeral value.
        res << " " * (level+1)*3
        # res << "static unsigned long long data[] = { "
        res << "static unsigned int data[] = { "
        res << str.scan(/.{1,#{Low2C.int_width}}/m).reverse.map do |sub|
            sub.to_i(2).to_s # + "ULL"
        end.join(",")
        res << " };\n"
        # Create the value.
        res << " " * (level+1)*3
        # puts "str=#{str} type width=#{self.type.width} signed? #{type.signed?}"
        # res << "return make_set_value(#{self.type.to_c(level+1)},1," +
        #        "data);\n" 
        res << "return make_set_value("
        self.type.to_c(res,level+1)
        res << ",1,data);\n" 
    else
        # No, generate a bit string value.
        res << " " * (level+1)*3
        # res << "static unsigned char data[] = \"#{str}\";\n"
        res << "static unsigned char data[] = \"#{str.reverse}\";\n"
        # Create the value.
        res << " " * (level+1)*3
        # res << "return make_set_value(#{self.type.to_c(level+1)},0," +
        #        "data);\n" 
        res << "return make_set_value("
        self.type.to_c(res,level+1)
        res << ",0,data);\n" 
    end

    # Close the value.
    res << " " * level*3
    res << "}\n\n"
    # Return the result.
    return res
end

#to_ch(res) ⇒ Object

Generates the content of the h file. def to_ch



2031
2032
2033
2034
2035
2036
# File 'lib/HDLRuby/hruby_low2c.rb', line 2031

def to_ch(res)
    # res = ""
    # return "extern Value #{Low2C.make_name(self)}();"
    res << "extern Value " << Low2C.make_name(self) << "();"
    return res
end

#to_getrangeObject

How to use when simply obtaining the width



1542
1543
1544
# File 'lib/HDLRuby/hruby_verilog.rb', line 1542

def to_getrange
    return "#{self.content.to_verilog}"
end

#to_hdr(level = 0) ⇒ Object

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



553
554
555
556
557
558
559
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 553

def to_hdr(level = 0)
    if self.content.is_a?(HDLRuby::BitString) then
        return "_#{self.content}"
    else
        return self.content.to_s
    end
end

#to_highObject

Creates a new high value expression.



384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/HDLRuby/hruby_low2high.rb', line 384

def to_high
    # Is there a content?
    if (self.content) then
        # Yes, use it for creating the new value.
        return HDLRuby::High::Value.new(self.type.to_high,
                                        self.content.to_high)
    else
        # puts "Self.type.name=#{self.type.name}"
        # No (this should be a void value).
        return HDLRuby::High::Value.new(self.type.to_high,nil)
    end
end

#to_iObject

Converts to integer.



4735
4736
4737
# File 'lib/HDLRuby/hruby_low.rb', line 4735

def to_i
    return @content.to_i
end

#to_verilog(unknown = nil) ⇒ Object

Converts the system to Verilog code. If it is bit, it is b, and if it is int, it is represented by d. (Example: 4'b0000, 32'd1)



1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
# File 'lib/HDLRuby/hruby_verilog.rb', line 1527

def to_verilog(unknown = nil)
    if self.type.base.name.to_s == "bit"
        return "#{self.type.range.first + 1}'b#{self.content.to_verilog}"
    elsif self.type.name.to_s == "integer"
        str = self.content.to_verilog
        if str[0] == "-" then
            # Negative value.
            return "-#{self.type.range.first + 1}'d#{str[1..-1]}"
        else
            return "#{self.type.range.first + 1}'d#{str}"
        end
    end
    return "#{self.type.range.first + 1}'b#{self.content.to_verilog}"
end

#to_vhdl(level = 0, std_logic = false, width = nil) ⇒ Object

Generates the text of the equivalent VHDL with +width+ bits. +level+ is the hierachical level of the object.



1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1174

def to_vhdl(level = 0, std_logic = false, width = nil)
    raise "Invalid std_logic argument: #{std_logic}." unless std_logic == true || std_logic == false
    if self.type.boolean? then
        # Boolean case
        if self.content.is_a?(HDLRuby::BitString)
            return self.zero? ? "false" : "true"
        else
            return self.to_i == 0 ? "false" : "true"
        end
    end
    # Other cases
    # Maybe the value is used as a range or an index.
    if self.parent.is_a?(RefIndex) or self.parent.is_a?(RefRange) then
        # Yes, convert to a simple integer.
        return self.to_i.to_s.upcase
    end
    # No, generates as a bit string.
    width = self.type.width unless width
    # puts "self.type=#{self.type} width=#{width}"
    case self.content
    # when Numeric
    #     return self.content.to_s
    when HDLRuby::BitString
        # Compute the extension: in case of signed type, the extension
        # is the last bit. Otherwise it is 0 unless the last bit
        # is not defined (Z or X).
        sign = self.type.signed? ? self.content.to_s[-1] : 
            /[01]/ =~ self.content[-1] ? "0" : self.content[-1]
        return '"' + self.content.to_s.rjust(width,sign).upcase + '"'
    else
        # sign = self.type.signed? ? (self.content>=0 ? "0" : "1") : "0"
        sign = self.content>=0 ? "0" : "1"
        return '"' + self.content.abs.to_s(2).rjust(width,sign).upcase + '"'
    end
end

#widthObject

Gets the bit width of the value.



4720
4721
4722
# File 'lib/HDLRuby/hruby_low.rb', line 4720

def width
    return @type.width
end