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



4697
4698
4699
# File 'lib/HDLRuby/hruby_low.rb', line 4697

def content
  @content
end

Instance Method Details

#<=>(value) ⇒ Object

Compare values.

NOTE: mainly used for being supported by ranges.



4774
4775
4776
4777
# File 'lib/HDLRuby/hruby_low.rb', line 4774

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)



4800
4801
4802
# File 'lib/HDLRuby/hruby_low.rb', line 4800

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.



4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
# File 'lib/HDLRuby/hruby_low.rb', line 4742

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)


4756
4757
4758
4759
4760
4761
4762
4763
# File 'lib/HDLRuby/hruby_low.rb', line 4756

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)


4785
4786
4787
# File 'lib/HDLRuby/hruby_low.rb', line 4785

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.



4766
4767
4768
# File 'lib/HDLRuby/hruby_low.rb', line 4766

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

#immutable?Boolean

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

Returns:

  • (Boolean)


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

def immutable?
    # Values are always immutable.
    true
end

#odd?Boolean

Tells if the value is odd.

Returns:

  • (Boolean)


4790
4791
4792
# File 'lib/HDLRuby/hruby_low.rb', line 4790

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.



2097
2098
2099
2100
2101
2102
2103
2104
# File 'lib/HDLRuby/hruby_low2c.rb', line 2097

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.



2108
2109
2110
2111
# File 'lib/HDLRuby/hruby_low2c.rb', line 2108

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)



2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
# File 'lib/HDLRuby/hruby_low2c.rb', line 2125

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

    # The header of the value generation.
    res << " " * level*3
    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 int data[] = { "
    #     res << str.scan(/.{1,#{Low2C.int_width}}/m).reverse.map do |sub|
    #         sub.to_i(2).to_s # + "ULL"
    #     end.join(",")
    #     res << ", 0" if (str.length <= 32)
    #     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

    # Declares the data.
    if self.content.is_a?(::Integer) then
        if self.type.width <= 64 then
            res << " " * (level+1)*3
            res << "Value value = make_value("
            self.type.to_c(res,level+1)
            res << ",1);\n"
            # res << " " * (level+1)*3
            # res << "value->numeric = 1;\n"
            res << " " * (level+1)*3
            res << "value->capacity = 0;\n"
            res << " " * (level+1)*3
            res << "value->data_str = NULL;\n"
            res << " " * (level+1)*3
            if self.content.bit_length <= 63 then
                res << "value->data_int = #{self.content}LLU;\n"
            else
                res << "value->data_int = "
                res << "#{self.content & 0xFFFFFFFFFFFF}LLU;\n"
            end
            # Close the value.
            res << " " * (level+1)*3
            res << "return value;\n"
            res << " " * level*3
            res << "}\n\n"
            # Return the result.
            return res
        else
            str = self.content.to_s(2)
            # if str[-1] == "-" then
            #     str[-1] = "1"
            # elsif str[-1] == "1" then
            #     str = "0" + str
            # end
            if self.content < 0 then
                str = (2**self.type.width + self.content).to_s(2)
                str = "1" * (self.type.width-str.length) + str
            else
                str = self.content.to_s(2)
                str = "0" * (self.type.width-str.length) + str
            end
            str.reverse!
        end
    else
        str = content.to_s.reverse
    end
    str = str.ljust(self.type.width,str[-1])
    res << " " * (level+1)*3
    res << "Value value = make_value("
    self.type.to_c(res,level+1)
    res << ",1);\n"
    res << " " * (level+1)*3
    res << "value->numeric = 0;\n"
    res << " " * (level+1)*3
    res << "value->capacity = #{str.length+1};"
    res << " " * (level+1)*3
    res << "value->data_str = calloc(value->capacity,sizeof(char));\n"
    res << " " * (level+1)*3
    res << "strcpy(value->data_str,\"#{str}\");\n"

    # Close the value.
    res << " " * (level+1)*3
    res << "return value;\n"
    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



2115
2116
2117
2118
# File 'lib/HDLRuby/hruby_low2c.rb', line 2115

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

#to_getrangeObject

How to use when simply obtaining the width



1576
1577
1578
# File 'lib/HDLRuby/hruby_verilog.rb', line 1576

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.



4795
4796
4797
# File 'lib/HDLRuby/hruby_low.rb', line 4795

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)



1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
# File 'lib/HDLRuby/hruby_verilog.rb', line 1543

def to_verilog(unknown = nil)
    # if self.type.base.name.to_s == "bit"
    # if self.type.unsigned? then
    #     # return "#{self.type.range.first + 1}'b#{self.content.to_verilog}"
    #     return "#{self.type.width}'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}"
    if self.content.is_a?(Numeric) then
        if self.content < 0 then
            # str = (2**self.type.width + self.content).to_s(2)
            str = self.content.to_s(2)
            str = "0" * (self.type.width-str.length+1) + str[1..-1]
            return "-#{self.type.width}'b#{str}"
        else
            str = self.content.to_s(2)
            str = "0" * (self.type.width-str.length) + str
            return "#{self.type.width}'b#{str}"
        end
        # return "#{self.type.width}'b#{str}"
    else
        str = self.content.to_verilog
        return "#{str.length}'b#{str}"
    end
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.



4780
4781
4782
# File 'lib/HDLRuby/hruby_low.rb', line 4780

def width
    return @type.width
end