Class: HDLRuby::Low::Value

Inherits:
Expression show all
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

Describes a value.

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



4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
# File 'lib/HDLRuby/hruby_low.rb', line 4864

def initialize(type,content)
    super(type)
    if content.nil? then
        # Handle the nil content case.
        unless type.eql?(Void) then
            raise AnyError, "A value with nil content must have the Void type."
        end
        @content = content
    elsif content.is_a?(FalseClass) then
        @content = 0
    elsif content.is_a?(TrueClass) then
        @content = 1
    else
        # Checks and set the content: Ruby Numeric and HDLRuby
        # BitString are supported. Strings or equivalent are
        # converted to BitString.
        unless content.is_a?(Numeric) or
                content.is_a?(HDLRuby::BitString)
            # content = HDLRuby::BitString.new(content.to_s)
            content = content.to_s
            if self.type.unsigned? && content[0] != "0" then
                # content = "0" + content.rjust(self.type.width,content[0])
                if content[0] == "1" then
                    # Do not extend the 1, but 0 instead.
                    content = "0" + content.rjust(self.type.width,"0")
                else
                    # But extend the other.
                    content = "0" + content.rjust(self.type.width,content[0])
                end
            end
            content = HDLRuby::BitString.new(content)
        end
        @content = content 
        if (@content.is_a?(Numeric) && self.type.unsigned?) then
            # Adjust the bits for unsigned.
            @content = @content & (2**self.type.width-1)
        end
    end
end

Instance Attribute Details

#contentObject (readonly)

The content of the value.



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

def content
  @content
end

Instance Method Details

#<=>(value) ⇒ Object

Compare values.

NOTE: mainly used for being supported by ranges.



4945
4946
4947
4948
# File 'lib/HDLRuby/hruby_low.rb', line 4945

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.



192
193
194
195
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 192

def boolean_in_assign2select
    # Simple clones.
    return self.clone
end

#casts_without_expression!Object

Extracts the expressions from the casts.



176
177
178
179
180
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 176

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

#cloneObject

Clones the value (deeply)



4971
4972
4973
# File 'lib/HDLRuby/hruby_low.rb', line 4971

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.



4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
# File 'lib/HDLRuby/hruby_low.rb', line 4913

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)


4927
4928
4929
4930
4931
4932
4933
4934
# File 'lib/HDLRuby/hruby_low.rb', line 4927

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)


4956
4957
4958
# File 'lib/HDLRuby/hruby_low.rb', line 4956

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.



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

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.



4937
4938
4939
# File 'lib/HDLRuby/hruby_low.rb', line 4937

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

#immutable?Boolean

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

Returns:

  • (Boolean)


4905
4906
4907
4908
# File 'lib/HDLRuby/hruby_low.rb', line 4905

def immutable?
    # Values are always immutable.
    true
end

#odd?Boolean

Tells if the value is odd.

Returns:

  • (Boolean)


4961
4962
4963
# File 'lib/HDLRuby/hruby_low.rb', line 4961

def odd?
    return @content.odd?
end

#set_content!(content) ⇒ Object

Sets the content.



1344
1345
1346
1347
1348
1349
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1344

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.



1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1179

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.



2141
2142
2143
2144
2145
2146
2147
2148
# File 'lib/HDLRuby/hruby_low2c.rb', line 2141

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.



2152
2153
2154
2155
# File 'lib/HDLRuby/hruby_low2c.rb', line 2152

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)



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
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
# File 'lib/HDLRuby/hruby_low2c.rb', line 2169

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 & 0xFFFF_FFFF_FFFF_FFFF}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



2159
2160
2161
2162
# File 'lib/HDLRuby/hruby_low2c.rb', line 2159

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

#to_getrangeObject

How to use when simply obtaining the width



1596
1597
1598
# File 'lib/HDLRuby/hruby_verilog.rb', line 1596

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.



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

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.



415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/HDLRuby/hruby_low2high.rb', line 415

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.



4966
4967
4968
# File 'lib/HDLRuby/hruby_low.rb', line 4966

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)



1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
# File 'lib/HDLRuby/hruby_verilog.rb', line 1563

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.



1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1198

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.



4951
4952
4953
# File 'lib/HDLRuby/hruby_low.rb', line 4951

def width
    return @type.width
end