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.



4446
4447
4448
# File 'lib/HDLRuby/hruby_low.rb', line 4446

def content
  @content
end

Instance Method Details

#<=>(value) ⇒ Object

Compare values.

NOTE: mainly used for being supported by ranges.



4510
4511
4512
4513
# File 'lib/HDLRuby/hruby_low.rb', line 4510

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.



175
176
177
178
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 175

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)



4536
4537
4538
# File 'lib/HDLRuby/hruby_low.rb', line 4536

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.



4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
# File 'lib/HDLRuby/hruby_low.rb', line 4478

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)


4492
4493
4494
4495
4496
4497
4498
4499
# File 'lib/HDLRuby/hruby_low.rb', line 4492

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)


4521
4522
4523
# File 'lib/HDLRuby/hruby_low.rb', line 4521

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.



205
206
207
208
209
210
211
212
213
214
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 205

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.



4502
4503
4504
# File 'lib/HDLRuby/hruby_low.rb', line 4502

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

#immutable?Boolean

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

Returns:

  • (Boolean)


4470
4471
4472
4473
# File 'lib/HDLRuby/hruby_low.rb', line 4470

def immutable?
    # Values are always immutable.
    true
end

#odd?Boolean

Tells if the value is odd.

Returns:

  • (Boolean)


4526
4527
4528
# File 'lib/HDLRuby/hruby_low.rb', line 4526

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.



1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1143

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.



1904
1905
1906
1907
1908
1909
1910
1911
# File 'lib/HDLRuby/hruby_low2c.rb', line 1904

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.



1915
1916
1917
1918
# File 'lib/HDLRuby/hruby_low2c.rb', line 1915

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)



1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
# File 'lib/HDLRuby/hruby_low2c.rb', line 1934

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



1922
1923
1924
1925
1926
1927
# File 'lib/HDLRuby/hruby_low2c.rb', line 1922

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



1534
1535
1536
# File 'lib/HDLRuby/hruby_verilog.rb', line 1534

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.



4531
4532
4533
# File 'lib/HDLRuby/hruby_low.rb', line 4531

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)



1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
# File 'lib/HDLRuby/hruby_verilog.rb', line 1519

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.



1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1162

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.



4516
4517
4518
# File 'lib/HDLRuby/hruby_low.rb', line 4516

def width
    return @type.width
end