{
  "$schema": "/usr/share/sail-riscv/sail_riscv_config_schema.json",
  "base": {
    "xlen": 32,
    // Whether the base ISA is E, in which case accessing
    // x16-31 is reserved and in this implementation will
    // raise an illegal instruction exception.
    "E": false,
    "writable_misa": false,
    "writable_fiom": true,
    // The top 29 bits in this value control whether the corresponding
    // HPM counters (hpmcounter31 .. hpmcounter3) are supported
    // (i.e. are not read-only zero). A set bit specifies that the
    // corresponding counter is supported. The lowest 3 bits
    // (writable_hpm_counters[2 .. 0]) are ignored.
    "writable_hpm_counters": {
      "len": 32,
      "value": "0xFFFF_FFFF"
    },
    // The bits in this value control whether the corresponding bits
    // of the `scounteren` CSR that control access to HPM counters,
    // and `cycle`, `time` and `instret` registers, are read-only
    // zero. A set bit specifies that the corresponding bit of
    // `scounteren` is writable, otherwise the bit is read-only zero.
    // If Sscounterenw is supported the top 29 bits must be a superset of
    // the top 29 bits of `writable_hpm_counters`.
    "scounteren_writable_bits": {
      "len": 32,
      "value": "0xFFFF_FFFF"
    },
    // The bits in this value control whether the corresponding bits
    // of the `mcounteren` CSR that control access to HPM counters,
    // and `cycle`, `time` and `instret` registers at lower privilege
    // modes, are read-only zero. A set bit specifies that the
    // corresponding bit of `mcounteren` is writable, otherwise the
    // bit is read-only zero.
    "mcounteren_writable_bits": {
      "len": 32,
      "value": "0xFFFF_FFFF"
    },
    // `mtvec.{direct,vectored}.supported` indicates whether the
    // corresponding mode is supported for `mtvec`.  At least one mode
    // should be supported.  If both modes are supported, the mode on
    // reset is unspecified.
    // The `mtvec.{direct,vectored}.base_alignment` parameters control the alignment
    // of the trap vector base for each mode.  The alignment is
    // specified as the power of 2 of the desired byte alignment, and
    // can range from a minimum of 2 upto a maximum of 24. If
    // unaligned values are written to these CSRs, the lowest bits
    // will be zeroed to respect the specified alignment.
    "mtvec": {
      "direct": {
        "supported": true,
        "base_alignment": 2
      },
      "vectored": {
        "supported": false,
        "base_alignment": 6
      }
    },
    // Similar to `mtvec` above. If `S` mode is not supported, these
    // values need to be present and legal but are ignored.
    "stvec": {
      // The spec requires `base_alignment` for `stvec.direct` to be 2
      // (i.e. 4-byte alignment), hence there is no configuration
      // parameter for it.
      "direct": {
        "supported": true
      },
      "vectored": {
        "supported": false,
        "base_alignment": 2
      }
    },
    "medeleg": {
      "delegatable_bits": {
        "len": 64,
        "value": "0x0000_0000_0008_b3FE"
      }
    },
    "mideleg": {
      "delegatable_bits": {
        "len": "xlen",
        "value": "0x0000_2222"
      }
    },
    // These settings control whether the specified exceptions
    // cause information to be written into the appropriate
    // `xtval` registers.
    "xtval_nonzero": {
      "illegal_instruction": true,
      "software_breakpoint": true,
      "hardware_breakpoint": true,
      "load_address_misaligned": true,
      "load_access_fault": true,
      "load_page_fault": true,
      "samo_address_misaligned": true,
      "samo_access_fault": true,
      "samo_page_fault": true,
      "fetch_address_misaligned": true,
      "fetch_access_fault": true,
      "fetch_page_fault": true,
      "software_check": true,
      "reserved_exceptions": false
    },
    "reserved_behavior": {
      // The configuration option determines how to handle the reserved behavior `amocas_odd_registers`.
      // "AMOCAS_Fatal"  – raise a Sail exception, stopping execution.
      // "AMOCAS_Illegal" – treat it as an illegal instruction.
      "amocas_odd_register": "AMOCAS_Illegal",
      // The configuration option determines how to handle execution of a floating-point
      // instruction with DYN (dynamic) rounding mode when `fcsr.FRM` contains a
      // reserved value (0b101, 0b110, 0b111).
      // This does not affect the execution of floating-point instructions that have a
      // reserved rounding mode statically encoded in the instruction.
      // "Fcsr_RM_Fatal"  – raise a Sail exception, stopping execution.
      // "Fcsr_RM_Illegal" – treat it as an illegal instruction.
      "fcsr_rm": "Fcsr_RM_Illegal",
      // The configuration option determines how to handle the reserved behavior `pmpcfg_with_R0W1`.
      // "PMP_Fatal"  – raise a Sail exception, stopping execution.
      // "PMP_ClearPermissions" – convert a PMP entry with R=0, W=1 to R=0, W=0, X=0.
      "pmpcfg_write_only": "PMP_ClearPermissions",
      // The configuration option determines how to handle the reserved behavior `xenvcfg.CBIE` with 0b10.
      // "Xenvcfg_Fatal"  – raise a Sail exception, stopping execution.
      // "Xenvcfg_ClearPermissions" – convert CBIE with 0b10 to 0b00.
      "xenvcfg_cbie": "Xenvcfg_ClearPermissions",
      // The configuration option determines how to handle the reserved behavior `xtvec[Mode] >= 2`.
      // "Xtvec_Fatal"  – raise a Sail exception, stopping execution.
      // "Xtvec_Ignore" – use old Mode of xtvec.
      "xtvec_mode": "Xtvec_Ignore",
      // The configuration option determines how to handle the reserved behavior: Odd-numbered registers for RV32Zdinx.
      // "Zdinx_Fatal"  – raise a Sail exception, stopping execution.
      // "Zdinx_Illegal" – treat it as an illegal instruction.
      "rv32zdinx_odd_register": "Zdinx_Illegal"
    },
    "mstatus": {
      // The legal values for the FS and VS fields in this CSR are
      // specified by the two fields below.  Their values can be one
      // of:
      // - "ExtContext_FourState" allows all values {Off, Initial, Clean, Dirty}.
      // - "ExtContext_TwoState" allows {Off, Dirty}, and writes of Initial and Clean get written as Dirty.
      // - "ExtContext_Off" allows only {Off}.  This makes the field read-only zero.
      "fs_legal_states": "ExtContext_FourState",
      "vs_legal_states": "ExtContext_Off"
    },
    "privileged_isa_version": "Privileged_ISA_1_13"
  },
  "memory": {
    "physaddr_bits": 32,
    "pmp": {
      "grain": 10,
      // This specifies the number of PMP entries present.
      // The value must be one of 0, 16, or 64.
      "count": 16,
      // This specifies the number of usable PMP entries.
      // Entries higher than this are read-only-zero.
      // The value must be less than or equal to `count`.
      "usable_count": 16,
      "tor_supported": true,
      "na4_supported": false,
      "napot_supported": true
    },
    // These settings control global support for misaligned access so they are
    // checked before address translation. `misaligned_fault` in
    // `regions` is checked after address translation.
    "misaligned": {
      // `exceptions` specifies the treatment of misaligned accesses
      // before address translation.  If a fault is specified for an access,
      // it will have a higher priority than memory-protection faults arising from
      // that access if it were allowed to proceed.
      "exceptions": {
        // A misaligned scalar or vector load/store can either proceed
        // without a fault (use `{"None" : null}`), or raise an access fault
        // (use `{"Some": "AccessFault"}`) or a misaligned exception
        // (use `{"Some": "AlignmentException"}`).
        // This option controls scalar loads/stores.
        "load_store": {
          "Some": "AlignmentException"
        },
        // A misaligned vector load/store can be configured
        // independently of the scalar case above, but uses the same
        // option values.
        "vector": {
          "Some": "AlignmentException"
        },
        // A misaligned LR/SC currently always faults, and this field can specify
        // whether it generates an access fault (use `"AccessFault"`)
        // or a misaligned exception (use `"AlignmentException"`).
        "lrsc": "AlignmentException",
        // Similarly, a misaligned AMO currently always faults, and this field
        // can specify either `"AccessFault"` or `"AlignmentException"`.
        "amo": {
          "Some": "AlignmentException"
        }
      },
      // If a misaligned access was specified to have no fault in `exceptions` above, the
      // fields below specify how it is handled.
      //
      // Memory accesses that span multiple naturally aligned
      // 2^allowed_within_exp sized regions will be split into multiple
      // memory operations. 0 means all misaligned accesses will be split.
      // The maximum value is 12 (one page).
      "default_allowed_within_exp": 0,
      // If the access gets split due to `allowed_within_exp` then the size
      // of the operations will be one byte if `byte_by_byte` is set, otherwise
      // they will be the maximum size possible based on the alignment. For
      // example a 4-byte access to address 0x2 will use two 2-byte operations.
      "byte_by_byte": false,
      // If multiple memory operations are needed, this controls whether they
      // are done in increasing or decreasing address order. This is architecturally
      // observable because some store operations may succeed, and even for
      // loads the resulting `xtval` may depend on this setting.
      "order_decreasing": false
    },
    // Address to write DTB to (if provided). This must be in a suitable memory
    // region (see `memory.regions`).
    "dtb_address": {
      "len": 64,
      "value": "0x1000"
    },
    // The locations and sizes of memory regions and their PMAs.  These regions
    // are required to be aligned to 4K (page) boundaries.  To specify
    // the `misaligned` PMA attribute for a region, see the comments for
    // `memory.misaligned.exceptions` above.
    "regions": [
      // ROM
      {
        "base": {
          "len": 64,
          "value": "0x1000"
        },
        "size": {
          "len": 64,
          "value": "0x1000"
        },
        "attributes": {
          "mem_type": "IOMemory",
          "cacheable": true,
          "coherent": false,
          "executable": false,
          "readable": true,
          "writable": false,
          "read_idempotent": true,
          "write_idempotent": true,
          "misaligned_exceptions": {
            "load_store": {
              "None": null
            },
            "vector": {
              "None": null
            },
            "amo": "AccessFault"
          },
          "misaligned_atomicity_granule_size_exp": 0,
          "vector_misaligned_atomicity_granule_size_exp": 0,
          "atomic_support": "AMONone",
          "reservability": "RsrvNone",
          "supports_cbo_zero": false,
          "supports_pte_read": false,
          "supports_pte_write": false
        },
        "include_in_device_tree": false
      },
      // MMIO
      {
        "base": {
          "len": 64,
          "value": "0x2000000"
        },
        "size": {
          "len": 64,
          "value": "0x10000000"
        },
        "attributes": {
          "mem_type": "IOMemory",
          "cacheable": false,
          "coherent": true,
          "executable": false,
          "readable": true,
          "writable": true,
          "read_idempotent": false,
          "write_idempotent": false,
          "misaligned_exceptions": {
            "load_store": {
              "Some": "AlignmentException"
            },
            "vector": {
              "Some": "AlignmentException"
            },
            "amo": "AccessFault"
          },
          "misaligned_atomicity_granule_size_exp": 0,
          "vector_misaligned_atomicity_granule_size_exp": 0,
          "atomic_support": "AMONone",
          "reservability": "RsrvNone",
          "supports_cbo_zero": false,
          "supports_pte_read": false,
          "supports_pte_write": false
        },
        "include_in_device_tree": false
      },
      // RAM
      {
        "base": {
          "len": 64,
          "value": "0x80000000"
        },
        "size": {
          "len": 64,
          "value": "0x80000000"
        },
        "attributes": {
          "mem_type": "MainMemory",
          "cacheable": true,
          "coherent": true,
          "executable": true,
          "readable": true,
          "writable": true,
          "read_idempotent": true,
          "write_idempotent": true,
          "misaligned_exceptions": {
            "load_store": {
              "None": null
            },
            "vector": {
              "None": null
            },
            "amo": "AccessFault"
          },
          "misaligned_atomicity_granule_size_exp": 0,
          "vector_misaligned_atomicity_granule_size_exp": 0,
          "atomic_support": "AMOArithmetic",
          "reservability": "RsrvEventual",
          "supports_cbo_zero": true,
          "supports_pte_read": true,
          "supports_pte_write": true
        },
        "include_in_device_tree": true
      }
    ]
  },
  "platform": {
    "vendorid": 1538,
    "archid": 36,
    "impid": 256,
    "hartid": 0,
    // Cache block size, specified as a power of 2.
    "cache_block_size_exp": 6,
    "reservation": {
      // This specifies both the size and alignment of the reservation set, specified as a power of 2.
      // It must be at least 2 on RV32 and 3 on RV64 to support Zalrsc.  It must not be more than
      // 6 for Za64rs and 7 for Za128rs.  In all cases, it must be less than or equal to 12.
      "reservation_set_size_exp": 2,
      // Some implementations (e.g. Spike) require the Store-Conditional to provide the same
      // address as the matching Load-Reserve in order to succeed, regardless of the
      // configured reservation set size.  This controls whether such an exact address
      // match is required for a Store-Conditional to succeed.
      "require_exact_reservation_addr": true,
      // Some implementations (e.g. SiFive U74) also invalidate the
      // reservation on stores from the same hart.  If this is set to `true`, the
      // model invalidates the reservation if a store from the same hart lies within
      // the reservation set.
      "invalidate_on_same_hart_store": true
    },
    "clint": {
      // Whether the platform contains a CLINT.
      "supported": true,
      // If supported, this must be in a suitable IO memory region (see `memory.regions`).
      // Otherwise, these values can be left as 0.
      "base": 33554432,
      "size": 786432
    },
    // Very simple MMIO device to generate interrupts for testing
    // purposes. See docs/SimpleInterruptGenerator.md for details.
    "simple_interrupt_generator": {
      // Whether the platform contains this device.
      "supported": true,
      // If supported, this must be in a suitable IO memory region (see `memory.regions`)
      // and 4-byte aligned. The size is always 0x20.  If not supported, this can be left
      // as 0.
      "base": 201326592
    },
    "clock_frequency": 1000000000,
    "instructions_per_tick": 2,
    "wfi_is_nop": false,
    // WFI is optionally available to User mode.  Note that even if
    // `wfi_is_nop` is set to `true` above, it will still not be
    // available to User mode unless `wfi_available_to_user_mode` is
    // also `true`.
    "wfi_available_to_user_mode": true,
    // The maximum increment in the time CSR before a wait instruction
    // (e.g. WFI, WRS.NTO, WRS.STO) that is not a NOP expires its
    // wait. It is not possible to wait indefinitely.
    //
    // If WFI or WRS.STO (Short TimeOut) exceed this limit in
    // non-machine privilege with mstatus[TW] set, an illegal
    // instruction is raised. Otherwise they retire successfully.
    //
    // Note: it is also legal for these instructions to spuriously
    // retire successfully at any point, but there is currently no
    // configuration option for this behaviour.
    "max_time_to_wait": 200
  },
  "extensions": {
    "M": {
      "supported": true
    },
    "A": {
      "supported": true
    },
    "F": {
      "supported": true,
      "fflags_dirty_policy": "Fflags_Dirty_Instruction"
    },
    "D": {
      "supported": true
    },
    "V": {
      // `support_level` must be one of the below strings:
      // . "Disabled" for no vector extension support
      // . "Integer" for Zve*x support
      // . "Float_single" for Zve*f support
      // . "Float_double" for Zve*d support
      // . "Full" for the full V extension
      // Note that `support_level` requires compatible
      // values for `vlen_exp` and `elen_exp` below.
      // For e.g. Zve32x and Zve32f require `elen_exp` >= 5,
      // Zve64x, Zve64f, and Zve64d require `elen_exp` >= 6,
      // and V requires `elen_exp` >= 6 and `vlen_exp` >= 7.
      "support_level": "Disabled",
      // `vlen_exp` and `elen_exp` should be between 3 and 16,
      // inclusive.  If `support_level` is `"Disabled"`, then these
      // should be left as 3 (or any other legal value).
      "vlen_exp": 3,
      "elen_exp": 3,
      "reserved_behavior": {
        // This determines how to handle attempts by vsetvli, vsetivli,
        // and vsetvl to set an unsupported or reserved vtype.
        // "IllegalVtype_SetVill" - set vtype.vill, set vl to zero, clear vstart, and write rd.
        // "IllegalVtype_Illegal" - treat it as an illegal instruction.
        // "IllegalVtype_Fatal"   - raise a Sail exception, stopping execution.
        "illegal_vtype": "IllegalVtype_SetVill",
        // This determines how to handle an out-of-bounds vstart (vstart >= VLMAX), which the
        // vector spec marks reserved and recommends, but does not require, trapping.
        // "Vstart_Illegal" - raise an illegal instruction exception.
        // "Vstart_Ignore"  - treat as a no-op, the instruction writes nothing.
        "vstart_out_of_bounds": "Vstart_Illegal"
      },
      "vl_use_ceil": false,
      // The maximum index EEW for indexed vector addressing mode, as
      // a power of 2.  This must be at least 3 but must not exceed
      // the supported ELEN.
      "max_index_eew_exp": 3,
      "vstart": {
        // The vector specification permits implementations to raise an
        // illegal instruction exception when `vstart` is non-zero for
        // instructions that cannot produce such a `vstart` value through
        // normal execution.
        "zero_required": {
          // Whether vector arithmetic instructions raise an illegal instruction
          // exception when `vstart` is non-zero. This also governs instructions
          // from the Zvbb, Zvbc, Zvabd, Zvfbfmin, and Zvfbfwma extensions.
          "arith": true,
          // Whether the vector scalar move instructions (vmv.x.s, vmv.s.x,
          // vfmv.f.s and vfmv.s.f) raise an illegal instruction exception when
          // `vstart` is non-zero.
          "scalar_move": true
        }
      }
    },
    "B": {
      "supported": true
    },
    "S": {
      "supported": true
    },
    "U": {
      "supported": true
    },
    "Zibi": {
      "supported": false
    },
    // This extension just asserts that the cache block size is 64 bytes.
    // If you enable this you also need to ensure `platform.cache_block_size_exp`
    // is 6, otherwise you will get a config validation error.
    "Zic64b": {
      "supported": false
    },
    "Zicbom": {
      "supported": false
    },
    "Zicbop": {
      "supported": false
    },
    "Zicboz": {
      "supported": false
    },
    "Ziccamoa": {
      "supported": false
    },
    "Ziccamoc": {
      "supported": false
    },
    "Ziccif": {
      "supported": false
    },
    "Zicclsm": {
      "supported": false
    },
    "Ziccrse": {
      "supported": false
    },
    "Zicfilp": {
      "supported": false
    },
    "Zicfiss": {
      "supported": false
    },
    "Zicond": {
      "supported": false
    },
    "Zicntr": {
      "supported": true
    },
    "Zicsr": {
      "supported": true
    },
    "Zifencei": {
      "supported": true
    },
    "Zihintntl": {
      "supported": false
    },
    "Zihintpause": {
      "supported": false
    },
    "Zihpm": {
      "supported": true
    },
    "Zimop": {
      "supported": false
    },
    "Zmmul": {
      "supported": true
    },
    "Zaamo": {
      "supported": true
    },
    "Zabha": {
      "supported": false
    },
    "Zacas": {
      "supported": false
    },
    "Zalrsc": {
      "supported": true
    },
    "Zama16b": {
      "supported": false
    },
    "Zawrs": {
      "supported": false,
      // Whether `WRS.NTO` and `WRS.STO` behave as NOPS.  If they do
      // not, see above note for `platform.max_time_to_wait`.  If
      // Zawrs is not supported, these `is_nop` fields need to be
      // present but their boolean values are ignored.
      "nto": {
        "is_nop": false
      },
      "sto": {
        "is_nop": false
      }
    },
    "Zfa": {
      "supported": false
    },
    "Zfbfmin": {
      "supported": false
    },
    "Zfh": {
      "supported": false
    },
    "Zfhmin": {
      "supported": false
    },
    "Zfinx": {
      "supported": false
    },
    "Zdinx": {
      "supported": false
    },
    "Zca": {
      "supported": true
    },
    "Zcf": {
      "supported": true
    },
    "Zcd": {
      "supported": true
    },
    "Zcb": {
      "supported": false
    },
    "Zcmop": {
      "supported": false
    },
    "Zba": {
      "supported": true
    },
    "Zbb": {
      "supported": true
    },
    "Zbs": {
      "supported": true
    },
    "Zbc": {
      "supported": true
    },
    "Zbkb": {
      "supported": true
    },
    "Zbkc": {
      "supported": true
    },
    "Zbkx": {
      "supported": true
    },
    "Zknd": {
      "supported": true
    },
    "Zkne": {
      "supported": true
    },
    "Zknh": {
      "supported": true
    },
    "Zkr": {
      "supported": false,
      // If Zkr is not supported, these fields need to be present but
      // their boolean values are ignored.
      "sseed_reset_value": false,
      "useed_reset_value": false,
      "sseed_read_only_zero": false,
      "useed_read_only_zero": false
    },
    "Zksed": {
      "supported": true
    },
    "Zksh": {
      "supported": true
    },
    "Zkt": {
      "supported": false
    },
    "Zhinx": {
      "supported": false
    },
    "Zhinxmin": {
      "supported": false
    },
    "Zvabd": {
      "supported": false
    },
    "Zvfbfmin": {
      "supported": false
    },
    "Zvfbfwma": {
      "supported": false
    },
    "Zvfh": {
      "supported": false
    },
    "Zvfhmin": {
      "supported": false
    },
    "Zvbb": {
      "supported": false
    },
    "Zvbc": {
      "supported": false
    },
    "Zvkb": {
      "supported": false
    },
    "Zvkg": {
      "supported": false
    },
    "Zvkned": {
      "supported": false
    },
    "Zvknha": {
      "supported": false
    },
    "Zvknhb": {
      "supported": false
    },
    "Zvksed": {
      "supported": false
    },
    "Zvksh": {
      "supported": false
    },
    "Zvkt": {
      "supported": false
    },
    "Ssccptr": {
      "supported": false
    },
    "Sscofpmf": {
      "supported": true
    },
    "Sscounterenw": {
      "supported": true
    },
    "Sstc": {
      "supported": false
    },
    // Enabling Sstvala requires that the exceptions specified in the extension
    // have their appropriate settings under `base.xtval_nonzero`.
    "Sstvala": {
      "supported": true
    },
    "Svade": {
      "supported": true
    },
    "Svadu": {
      "supported": false
    },
    "Svinval": {
      "supported": false
    },
    "Svrsw60t59b": {
      "supported": false
    },
    "Svnapot": {
      "supported": false
    },
    "Ssnpm": {
      "supported": false,
      "supported_pmlen_7": true,
      "supported_pmlen_16": true
    },
    "Smnpm": {
      "supported": false,
      "supported_pmlen_7": true,
      "supported_pmlen_16": true
    },
    "Smmpm": {
      "supported": false,
      "supported_pmlen_7": true,
      "supported_pmlen_16": true
    },
    "Smcntrpmf": {
      "supported": true
    },
    "Svbare": {
      "supported": true,
      "sfence_vma_illegal_if_svbare_only": true
    },
    "Sv32": {
      "supported": true
    },
    "Sv39": {
      "supported": false
    },
    "Sv48": {
      "supported": false
    },
    "Sv57": {
      "supported": false
    },
    "Stateen": {
      "Smstateen": {
        "supported": false
      },
      "Ssstateen": {
        "supported": false
      },
      "C_readonly_zero": true,
      "SE0_readonly_zero": false
    },
    "Ssqosid": {
      "supported": false,
      // These lengths should be between 1 and 12, inclusive.
      // If Ssqosid is not supported, this should be left as 1
      // (or any other legal value).
      "rcid_length": 12,
      "mcid_length": 12
    },
    "Svpbmt": {
      "supported": false
    },
    "Svvptc": {
      "supported": false
    }
  }
}
