| // Copyright lowRISC contributors. | 
 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 | { | 
 |   name:               "otbn", | 
 |   human_name:         "OpenTitan Big Number Accelerator", | 
 |   one_line_desc:      "Programmable coprocessor for asymmetric cryptography with SCA and FI countermeasures", | 
 |   one_paragraph_desc: ''' | 
 |   OpenTitan Big Number Accelerator (OTBN) is a programmable coprocessor for asymmetric cryptographic algorithms such as RSA or elliptic curve cryptography (ECC). | 
 |   Such algorithms are dominated by wide integer arithmetic, which are executed on OTBN's 256-bit-wide data path. | 
 |   The data OTBN processes is often security sensitive, and OTBN is designed to reduce the attack surface by | 
 |   (1) keeping the instruction set and the processor design as simple as possible to aid verification, | 
 |   (2) minimizing control flow and clearly separating it from data flow, | 
 |   (3) limiting OTBN's instruction fetch and data memory accesses to separate, dedicated on-chip memories, | 
 |   (4) giving OTBN software direct access to cryptographically secure random numbers, | 
 |   and (5) implementing various hardware countermeasures to deter side-channel analysis (SCA) and fault injection (FI) attacks. | 
 |   ''' | 
 |   design_spec:        "../doc", | 
 |   dv_doc:             "../doc/dv", | 
 |   hw_checklist:       "../doc/checklist", | 
 |   sw_checklist:       "/sw/device/lib/dif/dif_otbn" | 
 |   revisions: [ | 
 |       { | 
 |           version:            "0.1", | 
 |           life_stage:         "L1", | 
 |           design_stage:       "D1", | 
 |           verification_stage: "V1", | 
 |           dif_stage:          "S1", | 
 |           commit_id:          "a46be154ebbcb7b0d5e310b5510a4ac700adc9df", | 
 |           notes:              "" | 
 |       }, | 
 |       { | 
 |           version:            "1.0", | 
 |           life_stage:         "L1", | 
 |           design_stage:       "D2S", | 
 |           verification_stage: "V2S", | 
 |           dif_stage:          "S2", | 
 |           commit_id:          "a6b908283fccba3f8b6b44052c6ad87276dc21e8", | 
 |           notes:              "" | 
 |       }, | 
 |   ] | 
 |   clocking: [ | 
 |     {clock: "clk_i", reset: "rst_ni", idle: "idle_o", primary: true}, | 
 |     {clock: "clk_edn_i", reset: "rst_edn_ni", idle: "idle_o"}, | 
 |     {clock: "clk_otp_i", reset: "rst_otp_ni", idle: "idle_otp_o"} | 
 |   ] | 
 |   bus_interfaces: [ | 
 |     { protocol: "tlul", direction: "device" } | 
 |   ], | 
 |   param_list: [ | 
 |     { name:    "Stub", | 
 |       type:    "bit", | 
 |       default: "0", | 
 |       desc:    "Stub out the core of Otbn logic" | 
 |       local:   "false", | 
 |       expose:  "true" | 
 |     }, | 
 |     { name:    "RegFile", | 
 |       type:    "otbn_pkg::regfile_e", | 
 |       default: "otbn_pkg::RegFileFF", | 
 |       desc:    "Selection of the register file implementation. See otbn_pkg.sv." | 
 |       local:   "false", | 
 |       expose:  "true" | 
 |     }, | 
 |     { name:    "RndCnstUrndPrngSeed", | 
 |       type:    "otbn_pkg::urnd_prng_seed_t", | 
 |       desc:    ''' | 
 |         Default seed of the PRNG used for URND. | 
 |       ''' | 
 |       randcount: "256", | 
 |       randtype:  "data" | 
 |     }, | 
 |     { name:    "SecMuteUrnd" | 
 |       type:    "bit" | 
 |       default: "0" | 
 |       desc: ''' | 
 |         If enabled (1), URND is advanced only when data is needed. | 
 |         Disabled (0) by default. | 
 |         Useful for SCA measurements only. | 
 |         ''' | 
 |       local:   "false" | 
 |       expose:  "true" | 
 |     } | 
 |     { name:    "SecSkipUrndReseedAtStart" | 
 |       type:    "bit" | 
 |       default: "0" | 
 |       desc: ''' | 
 |         If enabled (1), URND reseed is skipped at the start of an operation. | 
 |         Disabled (0) by default. | 
 |         Useful for SCA measurements only. | 
 |         ''' | 
 |       local:   "false" | 
 |       expose:  "true" | 
 |     } | 
 |     { name: "RndCnstOtbnKey", | 
 |       type: "otp_ctrl_pkg::otbn_key_t", | 
 |       desc: ''' | 
 |         Compile-time random reset value for IMem/DMem scrambling key. | 
 |       ''' | 
 |       randcount: "128", | 
 |       randtype: "data" | 
 |     }, | 
 |     { name: "RndCnstOtbnNonce", | 
 |       type: "otp_ctrl_pkg::otbn_nonce_t", | 
 |       desc: ''' | 
 |         Compile-time random reset value for IMem/DMem scrambling nonce. | 
 |       ''' | 
 |       randcount: "64", | 
 |       randtype: "data" | 
 |     }, | 
 |   ] | 
 |   interrupt_list: [ | 
 |     { name: "done" | 
 |       desc: "OTBN has completed the operation." | 
 |     } | 
 |   ] | 
 |   alert_list: [ | 
 |     { name: "fatal" | 
 |       desc: "A fatal error. Fatal alerts are non-recoverable and will be asserted until a hard reset." | 
 |     } | 
 |     { name: "recov" | 
 |       desc: "A recoverable error. Just sent once (as the processor stops)." | 
 |     } | 
 |   ] | 
 |  | 
 |   inter_signal_list: [ | 
 |     // Key request to OTP | 
 |     { struct:  "otbn_otp_key" | 
 |       type:    "req_rsp" | 
 |       name:    "otbn_otp_key" | 
 |       act:     "req" | 
 |       default: "'0" | 
 |       package: "otp_ctrl_pkg" | 
 |     }, | 
 |     // EDN interface for RND | 
 |     { struct:  "edn" | 
 |       type:    "req_rsp" | 
 |       name:    "edn_rnd" | 
 |       act:     "req" | 
 |       package: "edn_pkg" | 
 |     }, | 
 |  | 
 |     // EDN interface for URND | 
 |     { struct:  "edn" | 
 |       type:    "req_rsp" | 
 |       name:    "edn_urnd" | 
 |       act:     "req" | 
 |       package: "edn_pkg" | 
 |     }, | 
 |  | 
 |     // OTBN is not performing any operation and can be clock/power-gated. | 
 |     { name:    "idle", | 
 |       type:    "uni", | 
 |       struct:  "mubi4", | 
 |       width:   "1", | 
 |       act:     "req", | 
 |       package: "prim_mubi_pkg" | 
 |     }, | 
 |  | 
 |     // ram configuration | 
 |     { struct:  "ram_1p_cfg", | 
 |       package: "prim_ram_1p_pkg", | 
 |       type:    "uni", | 
 |       name:    "ram_cfg", | 
 |       act:     "rcv" | 
 |     }, | 
 |  | 
 |     // Lifecycle escalation | 
 |     { struct:  "lc_tx" | 
 |       type:    "uni" | 
 |       name:    "lc_escalate_en" | 
 |       act:     "rcv" | 
 |       default: "lc_ctrl_pkg::Off" | 
 |       package: "lc_ctrl_pkg" | 
 |     }, | 
 |  | 
 |     // Lifecycle RMA request and acknowledge | 
 |     { struct:  "lc_tx" | 
 |       type:    "uni" | 
 |       name:    "lc_rma_req" | 
 |       act:     "rcv" | 
 |       default: "lc_ctrl_pkg::Off" | 
 |       package: "lc_ctrl_pkg" | 
 |     }, | 
 |  | 
 |     { struct:  "lc_tx" | 
 |       type:    "uni" | 
 |       name:    "lc_rma_ack" | 
 |       act:     "req" | 
 |       default: "lc_ctrl_pkg::Off" | 
 |       package: "lc_ctrl_pkg" | 
 |     }, | 
 |  | 
 |     // Key sideload | 
 |     { struct:  "otbn_key_req" | 
 |       type:    "uni" | 
 |       name:    "keymgr_key" | 
 |       act:     "rcv" | 
 |       package: "keymgr_pkg" | 
 |     }, | 
 |   ], | 
 |   countermeasures: [ | 
 |     { name: "MEM.SCRAMBLE", | 
 |       desc: "Both the imem and dmem are scrambled by using prim_ram_1p_scr." | 
 |     } | 
 |     { name: "DATA.MEM.INTEGRITY", | 
 |       desc: ''' | 
 |         Dmem is protected with ECC integrity. | 
 |         This is carried through to OTBN's register file. | 
 |       ''' | 
 |     } | 
 |     { name: "INSTRUCTION.MEM.INTEGRITY", | 
 |       desc: ''' | 
 |         Imem is protected with ECC integrity. | 
 |         This is carried through into OTBN's execute stage. | 
 |       ''' | 
 |     } | 
 |     { name: "BUS.INTEGRITY", | 
 |       desc: "End-to-end bus integrity scheme." | 
 |     } | 
 |     { name: "CONTROLLER.FSM.GLOBAL_ESC", | 
 |       desc: "The controller FSM moves to a terminal error state upon global escalation." | 
 |     } | 
 |     { name: "CONTROLLER.FSM.LOCAL_ESC", | 
 |       desc: ''' | 
 |         The controller FSM moves to a terminal error state upon local escalation. | 
 |         Can be triggered by CONTROLLER.FSM.SPARSE, SCRAMBLE_CTRL.FSM.SPARSE, and START_STOP_CTRL.FSM.SPARSE. | 
 |       ''' | 
 |     } | 
 |     { name: "CONTROLLER.FSM.SPARSE", | 
 |       desc: "The controller FSM uses a sparse state encoding." | 
 |     } | 
 |     { name: "SCRAMBLE.KEY.SIDELOAD", | 
 |       desc: "The scrambling key is sideloaded from OTP and thus unreadable by SW." | 
 |     } | 
 |     { name: "SCRAMBLE_CTRL.FSM.LOCAL_ESC", | 
 |       desc: ''' | 
 |         The scramble control FSM moves to a terminal error state upon local escalation. | 
 |         Can be triggered by SCRAMBLE_CTRL.FSM.SPARSE. | 
 |       ''' | 
 |     } | 
 |     { name: "SCRAMBLE_CTRL.FSM.SPARSE", | 
 |       desc: "The scramble control FSM uses a sparse state encoding." | 
 |     } | 
 |     { name: "START_STOP_CTRL.FSM.GLOBAL_ESC", | 
 |       desc: "The start-stop control FSM moves to a terminal error state upon global escalation." | 
 |     } | 
 |     { name: "START_STOP_CTRL.FSM.LOCAL_ESC", | 
 |       desc: ''' | 
 |         The start-stop control FSM moves to a terminal error state upon local escalation. | 
 |         Can be triggered by START_STOP_CTRL.FSM.SPARSE. | 
 |       ''' | 
 |     } | 
 |     { name: "START_STOP_CTRL.FSM.SPARSE", | 
 |       desc: "The start-stop control FSM uses a sparse state encoding." | 
 |     } | 
 |     { name: "DATA_REG_SW.SCA", | 
 |       desc: "Blanking of bignum data paths when unused by the executing instruction." | 
 |     } | 
 |     { name: "CTRL.REDUN", | 
 |       desc: ''' | 
 |         Check pre-decoded control matches separately decoded control from main decoder. | 
 |         This includes control signals used for blanking, pushing/popping the call stack, controlling loop and branch/jump instructions, as well as the actual branch target. | 
 |       ''' | 
 |     } | 
 |     { name: "PC.CTRL_FLOW.REDUN", | 
 |       desc: ''' | 
 |         Check prefetch stage PC and execute stage PC match. | 
 |         The prefetch stage and execute stage store their PC's separately and have separate increment calculations. | 
 |       ''' | 
 |     } | 
 |     { name: "RND.BUS.CONSISTENCY", | 
 |       desc: "Comparison on successive bus values received over the EDN RND interface." | 
 |     } | 
 |     { name: "RND.RNG.DIGEST", | 
 |       desc: "Checking that the random numbers received over the EDN RND interface have not been generated from entropy that failed the FIPS health checks in the entropy source." | 
 |     } | 
 |     { name: "RF_BASE.DATA_REG_SW.INTEGRITY" | 
 |       desc: "Register file is protected with ECC integrity." | 
 |     } | 
 |     { name: "RF_BASE.DATA_REG_SW.GLITCH_DETECT" | 
 |       desc: ''' | 
 |         This countermeasure checks for spurious write-enable signals on the register file by monitoring the one-hot0 property of the individual write-enable strobes. | 
 |       ''' | 
 |     } | 
 |     { name: "STACK_WR_PTR.CTR.REDUN" | 
 |       desc: ''' | 
 |         The write pointer of the stack (used for calls and loops) is redundant. | 
 |         If the two instances of the counter mismatch, an error is emitted. | 
 |       ''' | 
 |     } | 
 |     { name: "RF_BIGNUM.DATA_REG_SW.INTEGRITY" | 
 |       desc: "Register file is protected with ECC integrity." | 
 |     } | 
 |     { name: "RF_BIGNUM.DATA_REG_SW.GLITCH_DETECT" | 
 |       desc: "This countermeasure checks for spurious write-enable signals on the register file by monitoring the one-hot0 property of the individual write-enable strobes." | 
 |     } | 
 |     { name: "LOOP_STACK.CTR.REDUN" | 
 |       desc: "The iteration counter of each entry in the loop step uses cross counts via prim_count." | 
 |     } | 
 |     { name: "LOOP_STACK.ADDR.INTEGRITY" | 
 |       desc: "Loop start and end address on the loop stack are protected with ECC integrity." | 
 |     } | 
 |     { name: "CALL_STACK.ADDR.INTEGRITY" | 
 |       desc: "Call stack entries are protected with ECC integrity." | 
 |     } | 
 |     { name: "START_STOP_CTRL.STATE.CONSISTENCY" | 
 |       desc: ''' | 
 |         The secure wipe handshake between otbn_controller and | 
 |         otbn_start_stop_control uses a level-based req/ack interface. At the | 
 |         otbn_controller end, there is a check for unexpected acks. In | 
 |         otbn_start_stop_control, there is a check for secure wipe requests when | 
 |         we aren't in a state that allows it, and also a check for if the | 
 |         request drops at an unexpected time. | 
 |       ''' | 
 |     } | 
 |     { name: "DATA.MEM.SEC_WIPE" | 
 |       desc: ''' | 
 |         Rotate the scrambling key, effectively wiping the dmem. | 
 |         Initiated on command, upon fatal errors and before RMA entry. | 
 |       ''' | 
 |     } | 
 |     { name: "INSTRUCTION.MEM.SEC_WIPE" | 
 |       desc: ''' | 
 |         Rotate the scrambling key, effectively wiping the imem. | 
 |         Initiated on command, upon fatal errors and before RMA entry. | 
 |       ''' | 
 |     } | 
 |     { name: "DATA_REG_SW.SEC_WIPE" | 
 |       desc: ''' | 
 |         Securely wipe programmer visible OTBN register (GPRs, WDRs, CSRs, WSRs) state with random data. | 
 |         Initiated after reset, at the end of any OTBN operation, upon recoverable and fatal errors, and before RMA entry. | 
 |       ''' | 
 |     } | 
 |     { name: "WRITE.MEM.INTEGRITY" | 
 |       desc: ''' | 
 |         A software visible checksum is calculated for all dmem and imem writes | 
 |       ''' | 
 |     } | 
 |     { name: "CTRL_FLOW.COUNT" | 
 |       desc: "A software visible count of instructions executed" | 
 |     } | 
 |     { name: "CTRL_FLOW.SCA" | 
 |       desc: ''' | 
 |         OTBN architecture does not have any data dependent timing behaviour | 
 |       ''' | 
 |     } | 
 |     { name: "DATA.MEM.SW_NOACCESS" | 
 |       desc: "A portion of DMEM is invisible to CPU software" | 
 |     } | 
 |     { name: "KEY.SIDELOAD" | 
 |       desc: "Keys can be sideloaded without exposing them to the CPU" | 
 |     } | 
 |     { name: "TLUL_FIFO.CTR.REDUN", | 
 |       desc: "The TL-UL response FIFO pointers are implemented with duplicate counters." | 
 |     } | 
 |   ] | 
 |  | 
 |   regwidth: "32" | 
 |   registers: [ | 
 |     // The magic values for EXECUTE, SEC_WIPE_DMEM and SEC_WIPE_IMEM in the CMD | 
 |     // register below were generated with the sparse-fsm-encode.py script: | 
 |     // | 
 |     //   util/design/sparse-fsm-encode.py -d 4 -m 3 -n 8 --avoid-zero -s 1 | 
 |     // | 
 |     // and have a hamming distance of at least 4 from one another and the zero | 
 |     // word. | 
 |     { name: "CMD" | 
 |       desc: ''' | 
 |         Command Register | 
 |  | 
 |         A command initiates an OTBN operation. While performing the operation, | 
 |         OTBN is busy; the !!STATUS register reflects that. | 
 |  | 
 |         All operations signal their completion by raising the done | 
 |         interrupt; alternatively, software may poll the !!STATUS register. | 
 |  | 
 |         Writes are ignored if OTBN is not idle. | 
 |         Unrecognized commands are ignored. | 
 |       ''', | 
 |       swaccess: "wo", | 
 |       hwaccess: "hro", | 
 |       hwext: "true", | 
 |       hwqe:  "true", | 
 |       fields: [ | 
 |         { bits: "7:0" | 
 |           name: "cmd" | 
 |           resval: 0, | 
 |           desc: ''' | 
 |             The operation to perform. | 
 |  | 
 |             <table> | 
 |               <thead> | 
 |                 <tr> | 
 |                   <th>Value</th> | 
 |                   <th>Name</th> | 
 |                   <th>Description</th> | 
 |                 </tr> | 
 |               </thead> | 
 |               <tbody> | 
 |                 <tr> | 
 |                   <td>0xd8</td> | 
 |                   <td>EXECUTE</td> | 
 |                   <td> | 
 |                     Starts the execution of the program stored in the | 
 |                     instruction memory, starting at address zero. | 
 |                   </td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0xc3</td> | 
 |                   <td>SEC_WIPE_DMEM</td> | 
 |                   <td>Securely removes all contents from the data memory.</td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0x1e</td> | 
 |                   <td>SEC_WIPE_IMEM</td> | 
 |                   <td> | 
 |                     Securely removes all contents from the instruction memory. | 
 |                   </td> | 
 |                 </tr> | 
 |               </tbody> | 
 |             </table> | 
 |           ''' | 
 |           tags: [ | 
 |             // Don't write this field in the automated CSR tests: it would | 
 |             // start an operation! | 
 |             "excl:CsrAllTests:CsrExclWrite" | 
 |           ] | 
 |         } | 
 |       ], | 
 |     } | 
 |     { name: "CTRL", | 
 |       desc: "Control Register", | 
 |       hwext: "true", | 
 |       swaccess: "rw", | 
 |       hwaccess: "hrw", | 
 |       hwqe:  "true", | 
 |       fields: [ | 
 |         { bits: "0", | 
 |           name: "software_errs_fatal", | 
 |           resval: 0, | 
 |           desc: ''' | 
 |             Controls the reaction to software errors. | 
 |  | 
 |             When set software errors produce fatal errors, rather than | 
 |             recoverable errors. | 
 |  | 
 |             Writes are ignored if OTBN is not idle. | 
 |           ''' | 
 |         } | 
 |       ], | 
 |       tags: [ | 
 |         // Don't write this register in the automated CSR tests, because those | 
 |         // tests are not aware whether OTBN is idle or not. If OTBN is not idle, | 
 |         // it ignores the write and the test would fail. | 
 |         "excl:CsrAllTests:CsrExclWrite" | 
 |       ] | 
 |     } | 
 |     { name: "STATUS", | 
 |       desc: "Status Register", | 
 |       swaccess: "ro", | 
 |       hwaccess: "hwo", | 
 |       fields: [ | 
 |         { bits: "7:0", | 
 |           name: "status", | 
 |           resval: "0x04", | 
 |           // Note: Keep the list of status codes in sync with status_e in | 
 |           // otbn_pkg.sv. | 
 |           desc: ''' | 
 |             Indicates the current operational state OTBN is in. | 
 |  | 
 |             All BUSY values represent an operation started by a write to the | 
 |             !!CMD register. | 
 |  | 
 |             <table> | 
 |               <thead> | 
 |                 <tr> | 
 |                   <th>Value</th> | 
 |                   <th>Name</th> | 
 |                   <th>Description</th> | 
 |                 </tr> | 
 |               </thead> | 
 |               <tbody> | 
 |                 <tr> | 
 |                   <td>0x00</td> | 
 |                   <td>IDLE</td> | 
 |                   <td>OTBN is idle: it is not performing any action.</td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0x01</td> | 
 |                   <td>BUSY_EXECUTE</td> | 
 |                   <td>OTBN is busy executing software.</td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0x02</td> | 
 |                   <td>BUSY_SEC_WIPE_DMEM</td> | 
 |                   <td>OTBN is busy securely wiping the data memory.</td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0x03</td> | 
 |                   <td>BUSY_SEC_WIPE_IMEM</td> | 
 |                   <td>OTBN is busy securely wiping the instruction memory.</td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0x04</td> | 
 |                   <td>BUSY_SEC_WIPE_INT</td> | 
 |                   <td>OTBN is busy securely wiping the internal state.</td> | 
 |                 </tr> | 
 |                 <tr> | 
 |                   <td>0xFF</td> | 
 |                   <td>LOCKED</td> | 
 |                   <td> | 
 |                     OTBN is locked as reaction to a fatal error, and must be | 
 |                     reset to unlock it again. See also the section | 
 |                     "Reaction to Fatal Errors". | 
 |                   </td> | 
 |                 </tr> | 
 |               </tbody> | 
 |             </table> | 
 |           ''' | 
 |           tags: [ | 
 |             // Exclude this field from the automated CSR tests. The register model does not know | 
 |             // OTBN automatically transitions from the reset state to `IDLE` as it completes the | 
 |             // initial secure wipe of the internal state. | 
 |             "excl:CsrAllTests:CsrExclAll" | 
 |           ] | 
 |         } | 
 |       ] | 
 |     } | 
 |     { name: "ERR_BITS", | 
 |       desc: ''' | 
 |         Operation Result Register | 
 |  | 
 |         Describes the errors detected during an operation. | 
 |  | 
 |         Refer to the "List of Errors" section for a detailed description of the | 
 |         errors. | 
 |  | 
 |         The host CPU can clear this register when OTBN is not running, | 
 |         by writing any value. Write attempts while OTBN is running are ignored. | 
 |       ''', | 
 |       swaccess: "rw", | 
 |       hwaccess: "hrw", | 
 |       hwext: "true", | 
 |       hwqe:  "true", | 
 |       tags: [ | 
 |         // Don't use this register in the automated CSR tests. Its behaviour is | 
 |         // "write any value to clear", which we don't model in those tests. | 
 |         "excl:CsrAllTests:CsrExclWrite" | 
 |       ], | 
 |       fields: [ | 
 |         // Software errors | 
 |         { bits: "0", | 
 |           name: "bad_data_addr" | 
 |           resval: 0, | 
 |           desc: "A `BAD_DATA_ADDR` error was observed." | 
 |         } | 
 |         { bits: "1", | 
 |           name: "bad_insn_addr" | 
 |           resval: 0, | 
 |           desc: "A `BAD_INSN_ADDR` error was observed." | 
 |         } | 
 |         { bits: "2", | 
 |           resval: 0, | 
 |           name: "call_stack" | 
 |           desc: "A `CALL_STACK` error was observed." | 
 |         } | 
 |         { bits: "3", | 
 |           resval: 0, | 
 |           name: "illegal_insn" | 
 |           desc: "An `ILLEGAL_INSN` error was observed." | 
 |         } | 
 |         { bits: "4", | 
 |           name: "loop" | 
 |           resval: 0, | 
 |           desc: "A `LOOP` error was observed." | 
 |         } | 
 |         { bits: "5", | 
 |           name: "key_invalid" | 
 |           resval: 0, | 
 |           desc: "A `KEY_INVALID` error was observed." | 
 |         } | 
 |  | 
 |         // Recoverable errors | 
 |         { bits: "6", | 
 |           name: "rnd_rep_chk_fail" | 
 |           resval: 0, | 
 |           desc: "An `RND_REP_CHK_FAIL` error was observed." | 
 |         } | 
 |         { bits: "7", | 
 |           name: "rnd_fips_chk_fail" | 
 |           resval: 0, | 
 |           desc: "An `RND_FIPS_CHK_FAIL` error was observed." | 
 |         } | 
 |  | 
 |         // Fatal errors. Keep in sync with list in FATAL_ALERT_CAUSE. | 
 |         { bits: "16", | 
 |           name: "imem_intg_violation" | 
 |           resval: 0, | 
 |           desc: "A `IMEM_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "17", | 
 |           name: "dmem_intg_violation" | 
 |           resval: 0, | 
 |           desc: "A `DMEM_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "18", | 
 |           name: "reg_intg_violation" | 
 |           resval: 0, | 
 |           desc: "A `REG_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "19", | 
 |           name: "bus_intg_violation" | 
 |           resval: 0, | 
 |           desc: "A `BUS_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "20", | 
 |           name: "bad_internal_state", | 
 |           resval: 0, | 
 |           desc: "A `BAD_INTERNAL_STATE` error was observed." | 
 |         } | 
 |         { bits: "21", | 
 |           name: "illegal_bus_access" | 
 |           resval: 0, | 
 |           desc: "An `ILLEGAL_BUS_ACCESS` error was observed." | 
 |         } | 
 |         { bits: "22", | 
 |           name: "lifecycle_escalation" | 
 |           resval: 0, | 
 |           desc: "A `LIFECYCLE_ESCALATION` error was observed." | 
 |         } | 
 |         { bits: "23", | 
 |           name: "fatal_software" | 
 |           resval: 0, | 
 |           desc: "A `FATAL_SOFTWARE` error was observed." | 
 |         } | 
 |       ] | 
 |     } | 
 |     { name: "FATAL_ALERT_CAUSE", | 
 |       desc: ''' | 
 |         Fatal Alert Cause Register | 
 |  | 
 |         Describes any errors that led to a fatal alert. | 
 |         A fatal error puts OTBN in locked state; the value of this register | 
 |         does not change until OTBN is reset. | 
 |  | 
 |         Refer to the "List of Errors" section for a detailed description of the | 
 |         errors. | 
 |       ''' | 
 |       swaccess: "ro", | 
 |       hwaccess: "hwo", | 
 |       fields: [ | 
 |         // Keep the list in sync with the fatal errors in ERR_BITS. | 
 |         { bits: "0", | 
 |           name: "imem_intg_violation", | 
 |           resval: 0, | 
 |           desc: "A `IMEM_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "1", | 
 |           name: "dmem_intg_violation", | 
 |           resval: 0, | 
 |           desc: "A `DMEM_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "2", | 
 |           name: "reg_intg_violation", | 
 |           resval: 0, | 
 |           desc: "A `REG_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "3", | 
 |           name: "bus_intg_violation", | 
 |           resval: 0, | 
 |           desc: "A `BUS_INTG_VIOLATION` error was observed." | 
 |         } | 
 |         { bits: "4", | 
 |           name: "bad_internal_state", | 
 |           resval: 0, | 
 |           desc: "A `BAD_INTERNAL_STATE` error was observed." | 
 |         } | 
 |         { bits: "5", | 
 |           name: "illegal_bus_access" | 
 |           resval: 0, | 
 |           desc: "A `ILLEGAL_BUS_ACCESS` error was observed." | 
 |         } | 
 |         { bits: "6", | 
 |           name: "lifecycle_escalation" | 
 |           resval: 0, | 
 |           desc: "A `LIFECYCLE_ESCALATION` error was observed." | 
 |         } | 
 |         { bits: "7", | 
 |           name: "fatal_software" | 
 |           resval: 0, | 
 |           desc: "A `FATAL_SOFTWARE` error was observed." | 
 |         } | 
 |       ] | 
 |     } | 
 |     { name: "INSN_CNT", | 
 |       desc: ''' | 
 |         Instruction Count Register | 
 |  | 
 |         Returns the number of instructions executed in the current or last | 
 |         operation. The counter saturates at 2^32-1 and is reset to 0 at the | 
 |         start of a new operation. | 
 |  | 
 |         Only the EXECUTE operation counts instructions; for all other operations | 
 |         this register remains at 0. Instructions triggering an error do not | 
 |         count towards the total. | 
 |  | 
 |         Always reads as 0 if OTBN is locked. | 
 |  | 
 |         The host CPU can clear this register when OTBN is not running, | 
 |         by writing any value. Write attempts while OTBN is running are ignored. | 
 |       ''', | 
 |       swaccess: "rw", | 
 |       hwaccess: "hrw", | 
 |       hwext: "true", | 
 |       hwqe:  "true", | 
 |       fields: [ | 
 |         { bits: "31:0", | 
 |           name: "insn_cnt", | 
 |           resval: 0, | 
 |           desc: ''' | 
 |             The number of executed instructions. | 
 |           ''' | 
 |           tags: [ | 
 |             // Don't write this field in the automated CSR tests. Like | 
 |             // ERR_BITS, its behaviour is "write any value to clear", which we | 
 |             // don't model in those tests. | 
 |             "excl:CsrAllTests:CsrExclWrite" | 
 |           ] | 
 |         } | 
 |       ] | 
 |     } | 
 |     { name: "LOAD_CHECKSUM", | 
 |       desc: ''' | 
 |         A 32-bit CRC checksum of data written to memory | 
 |  | 
 |         See the "Memory Load Integrity" section of the manual for full details. | 
 |       ''' | 
 |       hwext: "true", | 
 |       hwqe:  "true", | 
 |       swaccess: "rw", | 
 |       hwaccess: "hrw", | 
 |       fields: [ | 
 |         { bits: "31:0", | 
 |           name: "checksum", | 
 |           resval: 0, | 
 |           desc: "Checksum accumulator" | 
 |         } | 
 |       ] | 
 |       tags: [ | 
 |         // Don't read this field in any of the automated CSR tests (they | 
 |         // will predict the value wrongly because they don't know that it | 
 |         // updates on memory writes). | 
 |         "excl:CsrAllTests:CsrExclAll" | 
 |       ] | 
 |     } | 
 |  | 
 |     // Give IMEM and DMEM 16 KiB address space, each, to allow for easy expansion | 
 |     // of the actual IMEM and DMEM sizes without changing the address map. | 
 |     { skipto: "0x4000" } | 
 |  | 
 |     // Imem size (given as `items` below) must be a power of two. | 
 |     { window: { | 
 |         name: "IMEM", | 
 |         items: "1024", // 4 kB | 
 |         swaccess: "rw", | 
 |         data-intg-passthru: "true", | 
 |         byte-write: "false", | 
 |         desc: ''' | 
 |           Instruction Memory Access | 
 |  | 
 |           The instruction memory may only be accessed through this window | 
 |           while OTBN is idle. | 
 |  | 
 |           If OTBN is busy or locked, read accesses return 0 and write accesses | 
 |           are ignored. | 
 |           If OTBN is busy, any access additionally triggers an | 
 |           ILLEGAL_BUS_ACCESS fatal error. | 
 |         ''' | 
 |       } | 
 |     } | 
 |  | 
 |     { skipto: "0x8000" } | 
 |  | 
 |     // Dmem size (given as `items` below) must be a power of two. | 
 |     { window: { | 
 |         name: "DMEM", | 
 |         items: "768", // 3 kB visible over the bus (1 kB scratch) | 
 |         unusual: "true", // Needed to avoid an error because of the non-power-of-two size | 
 |         swaccess: "rw", | 
 |         data-intg-passthru: "true", | 
 |         byte-write: "false", | 
 |         desc: ''' | 
 |           Data Memory Access | 
 |  | 
 |           The data memory may only be accessed through this window while OTBN | 
 |           is idle. | 
 |  | 
 |           If OTBN is busy or locked, read accesses return 0 and write accesses | 
 |           are ignored. | 
 |           If OTBN is busy, any access additionally triggers an | 
 |           ILLEGAL_BUS_ACCESS fatal error. | 
 |  | 
 |           Note that DMEM is actually 4kiB in size, but only the first 3kiB of | 
 |           the memory is visible through this register interface. | 
 |         ''' | 
 |       } | 
 |     } | 
 |   ] | 
 | } |