Class: Idl::CsrFieldReadExpressionAst

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

Instance Method Summary collapse

Constructor Details

#initialize(input, interval, idx, field_name) ⇒ CsrFieldReadExpressionAst

Returns a new instance of CsrFieldReadExpressionAst.



5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
# File 'lib/idl/ast.rb', line 5724

def initialize(input, interval, idx, field_name)
  if idx.is_a?(AstNode)
    super(input, interval, [idx])
  else
    super(input, interval, EMPTY_ARRAY)
  end

  @idx = idx
  @field_name = field_name
end

Instance Method Details

#calc_type(symtab) ⇒ Object



5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
# File 'lib/idl/ast.rb', line 5799

def calc_type(symtab)
  fd = field_def(symtab)
  if fd.nil?
    if @idx.is_a?(IntLiteralAst)
      internal_error "Could not find CSR[#{@idx.to_idl}].#{@field_name}"
    else
      internal_error "Could not find CSR[#{@idx}].#{@field_name}"
    end
  end
  if fd.defined_in_all_bases?
    Type.new(:bits, width: symtab.cfg_arch.possible_xlens.map{ |xlen| fd.width(symtab.cfg_arch, xlen) }.max)
  elsif fd.base64_only?
    if symtab.cfg_arch.possible_xlens.include?(64)
      Type.new(:bits, width: fd.width(symtab.cfg_arch, 64))
    end
  elsif fd.base32_only?
    if symtab.cfg_arch.possible_xlens.include?(32)
      Type.new(:bits, width: fd.width(symtab.cfg_arch, 32))
    end
  else
    internal_error "unexpected field base"
  end
end

#calc_value(symtab) ⇒ Object



5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
# File 'lib/idl/ast.rb', line 5832

def calc_value(symtab)
  # field isn't implemented, so it must be zero
  return 0 if field_def(symtab).nil?

  unless field_def(symtab).type(symtab) == "RO"
    value_error "'#{csr_name(symtab)}.#{field_name(symtab)}' is not RO"
  end

  field_def(symtab).reset_value(symtab.cfg_arch)
end

#csr_def(symtab) ⇒ Object



5763
5764
5765
5766
5767
5768
5769
5770
5771
# File 'lib/idl/ast.rb', line 5763

def csr_def(symtab)
  cfg_arch = symtab.cfg_arch

  if @idx.is_a?(IntLiteralAst)
    cfg_arch.csrs.find { |c| c.address == @idx.value(symtab) }
  else
    cfg_arch.csr(@idx)
  end
end

#csr_name(symtab) ⇒ Object



5773
5774
5775
# File 'lib/idl/ast.rb', line 5773

def csr_name(symtab)
  csr_def(symtab).name
end

#field_def(symtab) ⇒ Object



5777
5778
5779
# File 'lib/idl/ast.rb', line 5777

def field_def(symtab)
  csr_def(symtab).fields.find { |f| f.name == @field_name }
end

#field_name(symtab) ⇒ Object



5781
5782
5783
# File 'lib/idl/ast.rb', line 5781

def field_name(symtab)
  field_def(symtab).name
end

#freeze_tree(symtab) ⇒ Object



5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
# File 'lib/idl/ast.rb', line 5735

def freeze_tree(symtab)
  return if frozen?

  value_result = value_try do
    @value = calc_value(symtab)
  end
  value_else(value_result) do
    @value = nil
  end
  @type = calc_type(symtab)
  @cfg_arch = symtab.cfg_arch # remember cfg_arch, used in gen_adoc pass
  freeze
end

#to_idlString

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

Returns:

  • (String)

    IDL code for the node



5786
5787
5788
5789
5790
5791
5792
# File 'lib/idl/ast.rb', line 5786

def to_idl
  if @idx.is_a?(IntLiteralAst)
    "CSR[#{@idx.to_idl}].#{@field_name}"
  else
    "CSR[#{@idx}].#{@field_name}"
  end
end

#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:



5795
5796
5797
# File 'lib/idl/ast.rb', line 5795

def type(symtab)
  @type
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:



5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
# File 'lib/idl/ast.rb', line 5750

def type_check(symtab)
  if @idx.is_a?(IntLiteralAst)
    type_error "No CSR at address #{@idx.text_value}" if csr_def(symtab).nil?
  else
    # idx is a csr name
    csr_name = @idx
    type_error "No CSR named #{csr_name}" if csr_def(symtab).nil?
  end
  type_error "CSR[#{csr_name(symtab)}] has no field named #{@field_name}" if field_def(symtab).nil?
  type_error "CSR[#{csr_name(symtab)}].#{@field_name} is not defined in RV32" if symtab.cfg_arch.mxlen == 32 && !field_def(symtab).defined_in_base32?
  type_error "CSR[#{csr_name(symtab)}].#{@field_name} is not defined in RV64" if symtab.cfg_arch.mxlen == 64 && !field_def(symtab).defined_in_base64?
end

#value(symtab) ⇒ Object

Return the compile-time-known value of the node



5824
5825
5826
5827
5828
5829
5830
# File 'lib/idl/ast.rb', line 5824

def value(symtab)
  if @value.nil?
    value_error "'#{csr_name(symtab)}.#{field_name(symtab)}' is not RO"
  else
    @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 evaluation

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