Class: Idl::IntLiteralAst

Inherits:
AstNode
  • Object
show all
Includes:
Rvalue
Defined in:
lib/idl/ast.rb

Overview

represents an integer literal

Instance Method Summary collapse

Constructor Details

#initialize(input, interval) ⇒ IntLiteralAst

Returns a new instance of IntLiteralAst.



4298
4299
4300
4301
# File 'lib/idl/ast.rb', line 4298

def initialize(input, interval)
  super(input, interval, EMPTY_ARRAY)
  @types = [nil, nil]
end

Instance Method Details

#to_idlString

Return valid IDL representation of the node (and its subtree)

Returns:

  • (String)

    IDL code for the node



4483
# File 'lib/idl/ast.rb', line 4483

def to_idl = text_value

#type(symtab) ⇒ Type

Given a specific symbol table, return the type of this node.

Should not be called until #type_check is called with the same arguments

Parameters:

Returns:

  • (Type)

    The type of the node

Raises:



4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
# File 'lib/idl/ast.rb', line 4321

def type(symtab)
  cache_idx = symtab.mxlen >> 6 # 0 = 32, 1 = 64
  return @types[cache_idx] unless @types[cache_idx].nil?

  case text_value.delete("_")
  when /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
    # verilog-style literal
    width = ::Regexp.last_match(1)
    signed = ::Regexp.last_match(4)

    memoize = true
    if width.nil? || width == "XLEN"
      width = symtab.mxlen
      memoize = false
    end

    qualifiers = signed == "s" ? [:signed, :const] : [:const]
    t = Type.new(:bits, width: width.to_i, qualifiers:)
    @types[cache_idx] = t if memoize
    t
  when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/
    # C++-style literal
    signed = ::Regexp.last_match(3)

    qualifiers = signed == "s" ? [:signed, :const] : [:const]
    type = Type.new(:bits, width: width(symtab), qualifiers:)
    @types[cache_idx] = type
    type
  when /^([0-9]*)(s?)$/
    # basic decimal
    signed = ::Regexp.last_match(2)

    qualifiers = signed == "s" ? [:signed, :const] : [:const]
    type = Type.new(:bits, width: width(symtab), qualifiers:)
    @types[cache_idx] = type
    type
  else
    internal_error "Unhandled int value"
  end
end

#type_check(symtab) ⇒ void

This method returns an undefined value.

type check this node and all children

Calls to #type and/or #value may depend on type_check being called first with the same symtab. If not, those functions may raise an AstNode::InternalError

Parameters:

Raises:



4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
# File 'lib/idl/ast.rb', line 4304

def type_check(symtab)
  if text_value.delete("_") =~ /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
    # verilog-style literal
    width = ::Regexp.last_match(1)
    value_text = ::Regexp.last_match(6)

    if width.nil? || width == "XLEN"
      width = symtab.mxlen
      memoize = false
    end

    # ensure we actually have enough bits to represent the value
    type_error("#{value_text} cannot be represented in #{width} bits") if unsigned_value.bit_length > width.to_i
  end
end

#unsigned_valueInteger

Returns the unsigned value of this literal (i.e., treating it as unsigned even if the signed specifier is present).

Returns:

  • (Integer)

    the unsigned value of this literal (i.e., treating it as unsigned even if the signed specifier is present)



4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
# File 'lib/idl/ast.rb', line 4431

def unsigned_value
  # return @unsigned_value unless @unsigned_value.nil?

  case text_value.delete("_")
  when /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
    # verilog-style literal
    radix_id = ::Regexp.last_match(5)
    value = ::Regexp.last_match(6)

    radix_id = "d" if radix_id.empty?

    case radix_id
    when "b"
      value.to_i(2)
    when "o"
      value.to_i(8)
    when "d"
      value.to_i(10)
    when "h"
      value.to_i(16)
    end
  when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/
    # C++-style literal
    radix_id = ::Regexp.last_match(1)
    value = ::Regexp.last_match(2)

    radix_id = "o" if radix_id.empty?

    # @unsigned_value =
      case radix_id
      when "b"
        value.to_i(2)
      when "o"
        value.to_i(8)
      when "d"
        value.to_i(10)
      when "x"
        value.to_i(16)
      end

  when /^([0-9]*)(s?)$/
    # basic decimal
    value = ::Regexp.last_match(1)

    # @unsigned_value = value.to_i(10)
    value.to_i(10)
  else
    internal_error "Unhandled int value '#{text_value}'"
  end
end

#value(symtab) ⇒ Object

Return the compile-time-known value of the node



4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
# File 'lib/idl/ast.rb', line 4400

def value(symtab)
  # return @value unless @value.nil?

  if text_value.delete("_") =~ /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
    # verilog-style literal
    width = ::Regexp.last_match(1)
    signed = ::Regexp.last_match(4)

    memoize = true
    if width.nil? || width == "XLEN"
      width = symtab.mxlen
      memoize = false
    end

    v =
      if !signed.empty? && ((unsigned_value >> (width.to_i - 1)) == 1)
        -(2**width.to_i - unsigned_value)
      else
        unsigned_value
      end

    # @value = v if memoize
    v
  else
    # @value = unsigned_value
    unsigned_value
  end
end

#values(symtab) ⇒ Array<Integer>, ... Originally defined in module Rvalue

Return a complete list of possible compile-time-known values of the node, or raise a ValueError if the full list cannot be determined

For most AstNodes, this will just be a single-entry array

Parameters:

  • symtab (SymbolTable)

    The context for the evaulation

Returns:

  • (Array<Integer>)

    The complete list of compile-time-known values, when they are integral

  • (Array<Boolean>)

    The complete list of compile-time-known values, when they are booleans

  • (AstNode::ValueError)

    if the list of values is not knowable at compile time

#width(symtab) ⇒ Object



4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
# File 'lib/idl/ast.rb', line 4362

def width(symtab)
  # return @width unless @width.nil?

  text_value_no_underscores = text_value.delete("_")

  case text_value_no_underscores
  when /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
    # verilog-style literal
    width = ::Regexp.last_match(1)
    memoize = true
    if width.nil? || width == "XLEN"
      width = symtab.mxlen
      memoize = false
    end
    # @width = width if memoize
    width
  when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/
    signed = ::Regexp.last_match(3)

    width = signed == "s" ? value(symtab).bit_length + 1 : value(symtab).bit_length
    width = 1 if width.zero? # happens when the literal is '0'

    # @width = width
    width
  when /^([0-9]*)(s?)$/
    signed = ::Regexp.last_match(3)

    width = signed == "s" ? value(symtab).bit_length + 1 : value(symtab).bit_length
    width = 1 if width.zero? # happens when the literal is '0'

    # @width = width
    width
  else
    internal_error "No match on int literal"
  end
end