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.



5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
# File 'lib/idl/ast.rb', line 5689

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



5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
# File 'lib/idl/ast.rb', line 5764

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.archdef.possible_xlens.map{ |xlen| fd.width(symtab.archdef, xlen) }.max)
  elsif fd.base64_only?
    if symtab.archdef.possible_xlens.include?(64)
      Type.new(:bits, width: fd.width(symtab.archdef, 64))
    end
  elsif fd.base32_only?
    if symtab.archdef.possible_xlens.include?(32)
      Type.new(:bits, width: fd.width(symtab.archdef, 32))
    end
  else
    internal_error "unexpected field base"
  end
end

#calc_value(symtab) ⇒ Object



5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
# File 'lib/idl/ast.rb', line 5797

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.archdef)
end

#csr_def(symtab) ⇒ Object



5728
5729
5730
5731
5732
5733
5734
5735
5736
# File 'lib/idl/ast.rb', line 5728

def csr_def(symtab)
  archdef = symtab.archdef

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

#csr_name(symtab) ⇒ Object



5738
5739
5740
# File 'lib/idl/ast.rb', line 5738

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

#field_def(symtab) ⇒ Object



5742
5743
5744
# File 'lib/idl/ast.rb', line 5742

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

#field_name(symtab) ⇒ Object



5746
5747
5748
# File 'lib/idl/ast.rb', line 5746

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

#freeze_tree(symtab) ⇒ Object



5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
# File 'lib/idl/ast.rb', line 5700

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)
  @archdef = symtab.archdef # remember archdef, 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



5751
5752
5753
5754
5755
5756
5757
# File 'lib/idl/ast.rb', line 5751

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:



5760
5761
5762
# File 'lib/idl/ast.rb', line 5760

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:



5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
# File 'lib/idl/ast.rb', line 5715

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.archdef.mxlen == 32 && !field_def(symtab).defined_in_base32?
  type_error "CSR[#{csr_name(symtab)}].#{@field_name} is not defined in RV64" if symtab.archdef.mxlen == 64 && !field_def(symtab).defined_in_base64?
end

#value(symtab) ⇒ Object

Return the compile-time-known value of the node



5789
5790
5791
5792
5793
5794
5795
# File 'lib/idl/ast.rb', line 5789

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