diff --git a/doc/rm/comportability_specification/index.md b/doc/rm/comportability_specification/index.md index 1f78b4a655ab0..7ec054ab88e5c 100644 --- a/doc/rm/comportability_specification/index.md +++ b/doc/rm/comportability_specification/index.md @@ -231,7 +231,7 @@ See the section on [Interrupt Handling](#interrupt-handling) below, which define ### Alerts -Each peripheral has the option of designating output signals as security critical alerts destined for the hardware [alert handler module]({{< relref "/hw/ip/alert_handler/doc" >}}). +Each peripheral has the option of designating output signals as security critical alerts destined for the hardware [alert handler module]({{< relref "/hw/top_earlgrey/ip_autogen/alert_handler/doc" >}}). These are differential signals (to avoid single point of failure) sent to the alert handler for it to send to the processor for first-line defense handling, or hardware security response if the processor does not act. The peripheral lists its collection of alerts with the `alert_list` attribute in the configuration file. For each alert in the full system, a corresponding set of signals will be generated in the alert handler to carry out this communication between alert sender and handler. @@ -454,7 +454,7 @@ Specification of this control is defined in the rv_plic documentation of the cor Alerts are another critical and common implementation to standardize for all peripherals. Unlike interrupts, there is no software component to alerts at the peripheral, though there is at the hardware alert handler. -See that [specification]({{< relref "/hw/ip/alert_handler/doc" >}}) for full details. +See that [specification]({{< relref "/hw/top_earlgrey/ip_autogen/alert_handler/doc" >}}) for full details. A general description of the handling of alerts at the hardware level is given here. ### Alerts per Module @@ -530,7 +530,7 @@ Cause registers for recoverable alerts must either be clearable by SW, or the HW Cause registers for fatal alerts must not be clearable in any way and must hence be read-only. The `prim_alert_sender` converts the event into a differentially encoded signal pair to be routed to the hardware alert handler, as dictated by the details in the -[alert handler specification]({{< relref "/hw/ip/alert_handler/doc" >}}). +[alert handler specification]({{< relref "/hw/top_earlgrey/ip_autogen/alert_handler/doc" >}}). The alert handler module is automatically generated to have enough alert ports to represent each alert declared in the different included peripheral IP configuration files. ## Inter Signal Handling diff --git a/doc/rm/register_tool/index.md b/doc/rm/register_tool/index.md index df5ea18272533..a9de3ad2eb72a 100644 --- a/doc/rm/register_tool/index.md +++ b/doc/rm/register_tool/index.md @@ -618,7 +618,7 @@ The following aspects need to be considered when integrating shadow registers in It is thus **highly recommended** to use non-permissive reset values and use software for configuring more permissive values. - Error hook-ups: - - Storage errors signaled to the hardware in `err_storage` are fatal, and should be hooked up directly into the [alert system]({{< relref "hw/ip/alert_handler/doc" >}}). + - Storage errors signaled to the hardware in `err_storage` are fatal, and should be hooked up directly into the [alert system]({{< relref "hw/top_earlgrey/ip_autogen/alert_handler/doc" >}}). - Update errors signaled to the hardware in `err_update` may be software errors and do not affect the current committed value; thus they can be considered informational bugs that are collected into error status or interrupts, and optionally alerts. They do not generate error responses on the TL-UL system bus interface. @@ -675,7 +675,7 @@ The following features are currently not implemented but might be added in the f Depending on the design, the reset propagation **may** be multi-cycle, and thus it is possible for the shadow register and committed register to not be reset at the same time when resets are asserted. This may manifest as an issue if the reset skews are **not** balanced, and may cause register outputs to change on the opposite sides of a clock edge for the receiving domain. It is thus important to ensure the skews of the committed and shadow reset lines to be roughly balanced and/or downstream logic to correctly ignore errors when this happens. - Note that a module may need to be reset during operation of the system, i.e., when the [alert system]({{< relref "hw/ip/alert_handler/doc" >}}) is running. + Note that a module may need to be reset during operation of the system, i.e., when the [alert system]({{< relref "hw/top_earlgrey/ip_autogen/alert_handler/doc" >}}) is running. Software-controllable resets should be avoided. If a single reset bit drives both normal and shadow resets, then the problem is simply moved to a different place. diff --git a/doc/security/_index.md b/doc/security/_index.md index ca15cd314576c..8bcdf18421434 100644 --- a/doc/security/_index.md +++ b/doc/security/_index.md @@ -106,7 +106,7 @@ alert policy assignments to handle alerts completely in hardware depending on the assigned severity. [aes]: {{< relref "hw/ip/aes/doc" >}} -[alert_handler]: {{< relref "hw/ip/alert_handler/doc" >}} +[alert_handler]: {{< relref "hw/top_earlgrey/ip_autogen/alert_handler/doc" >}} [comportable_ip]: {{< relref "doc/rm/comportability_specification" >}} [csrng]: {{< relref "hw/ip/csrng/doc" >}} [entropy_source]: {{< relref "hw/ip/entropy_src/doc" >}} diff --git a/hw/Makefile b/hw/Makefile index cf9942c11001e..f7b0194360472 100644 --- a/hw/Makefile +++ b/hw/Makefile @@ -11,7 +11,6 @@ REG_OUTPUT_SW_DIR ?= ${REG_OUTPUT_DIR}/sw IPS ?= aes \ adc_ctrl \ - alert_handler \ aon_timer \ clkmgr \ entropy_src \ diff --git a/hw/dv/sv/alert_esc_agent/README.md b/hw/dv/sv/alert_esc_agent/README.md index 243f5eb524db6..ae0b4a65a767a 100644 --- a/hw/dv/sv/alert_esc_agent/README.md +++ b/hw/dv/sv/alert_esc_agent/README.md @@ -7,7 +7,7 @@ ALERT_ESC UVM Agent is extended from DV library agent classes. This agent implements both alert(alert_rx, alert_tx) and escalation (esc_rx, esc_tx) interface protocols, and can be configured to behave in both host and device modes. For design documentation, please refer to [alert_handler -spec]({{< relref "hw/ip/alert_handler/doc/_index.md" >}}). +spec]({{< relref "hw/top_earlgrey/ip_autogen/alert_handler/doc/_index.md" >}}). ### Alert Agent diff --git a/hw/ip/alert_handler/alert_handler_reg.core b/hw/ip/alert_handler/alert_handler_reg.core deleted file mode 100644 index 9f79e666eda77..0000000000000 --- a/hw/ip/alert_handler/alert_handler_reg.core +++ /dev/null @@ -1,23 +0,0 @@ -CAPI=2: -# Copyright lowRISC contributors. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:ip:alert_handler_reg:0.1" -description: "Auto-generated alert handler register sources with default parameters." -filesets: - files_rtl: - depend: - - lowrisc:tlul:headers - - lowrisc:prim:subreg - - "fileset_top ? (lowrisc:systems:alert_handler_reg)" - - "fileset_topgen ? (lowrisc:systems:topgen-reg-only)" - files: - - "fileset_ip ? (rtl/alert_handler_reg_pkg.sv)" - - "fileset_ip ? (rtl/alert_handler_reg_top.sv)" - file_type: systemVerilogSource - - -targets: - default: &default_target - filesets: - - files_rtl diff --git a/hw/ip/alert_handler/data/alert_handler.hjson b/hw/ip/alert_handler/data/alert_handler.hjson deleted file mode 100644 index a0e6622cc8c4b..0000000000000 --- a/hw/ip/alert_handler/data/alert_handler.hjson +++ /dev/null @@ -1,1717 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -# ALERT_HANDLER register template -# -# Parameter (given by Python tool) -# - n_alerts: Number of alert sources -# - esc_cnt_dw: Width of escalation counter -# - accu_cnt_dw: Width of accumulator -# - async_on: Enables asynchronous sygnalling between specific alert RX/TX pairs -# - n_classes: Number of supported classes (leave this at 4 at the moment) -# - n_lpg: Number of low-power groups (LPGs) -# - lpg_map: Defines a mapping from alerts to LPGs. - -{ - name: "ALERT_HANDLER", - clocking: [ - {clock: "clk_i", reset: "rst_ni", primary: true}, - {clock: "clk_edn_i", reset: "rst_edn_ni"} - ] - bus_interfaces: [ - { protocol: "tlul", direction: "device" } - ], - regwidth: "32", - hier_path: "u_reg_wrap" - param_list: [ - // Random netlist constants - { name: "RndCnstLfsrSeed", - desc: "Compile-time random bits for initial LFSR seed", - type: "alert_pkg::lfsr_seed_t" - randcount: "32", - randtype: "data", // randomize randcount databits - } - { name: "RndCnstLfsrPerm", - desc: "Compile-time random permutation for LFSR output", - type: "alert_pkg::lfsr_perm_t" - randcount: "32", - randtype: "perm", // random permutation for randcount elements - } - // Normal parameters - { name: "NAlerts", - desc: "Number of alert channels.", - type: "int", - default: "4", - local: "true" - }, - { name: "NLpg", - desc: "Number of LPGs.", - type: "int", - default: "1", - local: "true" - }, - { name: "NLpgWidth", - desc: "Width of LPG ID.", - type: "int", - default: "1", - local: "true" - }, - { name: "LpgMap", - desc: ''' - Defines a mapping from alerts to LPGs. - ''' - type: "logic [NAlerts-1:0][NLpgWidth-1:0]", - default: ''' - { - 1'b0 - } - ''', - local: "true" - }, - { name: "EscCntDw", - desc: "Width of the escalation timer.", - type: "int", - default: "32", - local: "true" - }, - { name: "AccuCntDw", - desc: "Width of the accumulation counter.", - type: "int", - default: "16", - local: "true" - }, - { name: "AsyncOn", - desc: ''' - Each bit of this parameter corresponds to an escalation channel and - defines whether the protocol is synchronous (0) or asynchronous (1). - ''' - type: "logic [NAlerts-1:0]", - default: ''' - { - '0 - } - ''' - local: "true" - }, - { name: "N_CLASSES", - desc: "Number of classes", - type: "int", - default: "4", - local: "true" - }, - { name: "N_ESC_SEV", - desc: "Number of escalation severities", - type: "int", - default: "4", - local: "true" - }, - { name: "N_PHASES", - desc: "Number of escalation phases", - type: "int", - default: "4", - local: "true" - }, - { name: "N_LOC_ALERT", - desc: "Number of local alerts", - type: "int", - default: "7", - local: "true" - }, - { name: "PING_CNT_DW", - desc: "Width of ping counter", - type: "int", - default: "16", - local: "true" - }, - { name: "PHASE_DW", - desc: "Width of phase ID", - type: "int", - default: "2", - local: "true" - }, - { name: "CLASS_DW", - desc: "Width of class ID", - type: "int", - default: "2", - local: "true" - }, - { name: "LOCAL_ALERT_ID_ALERT_PINGFAIL", - desc: "Local alert ID for alert ping failure.", - type: "int", - default: "0", - local: "true" - }, - { name: "LOCAL_ALERT_ID_ESC_PINGFAIL", - desc: "Local alert ID for escalation ping failure.", - type: "int", - default: "1", - local: "true" - }, - { name: "LOCAL_ALERT_ID_ALERT_INTEGFAIL", - desc: "Local alert ID for alert integrity failure.", - type: "int", - default: "2", - local: "true" - }, - { name: "LOCAL_ALERT_ID_ESC_INTEGFAIL", - desc: "Local alert ID for escalation integrity failure.", - type: "int", - default: "3", - local: "true" - }, - { name: "LOCAL_ALERT_ID_BUS_INTEGFAIL", - desc: "Local alert ID for bus integrity failure.", - type: "int", - default: "4", - local: "true" - }, - { name: "LOCAL_ALERT_ID_SHADOW_REG_UPDATE_ERROR", - desc: "Local alert ID for shadow register update error.", - type: "int", - default: "5", - local: "true" - }, - { name: "LOCAL_ALERT_ID_SHADOW_REG_STORAGE_ERROR", - desc: "Local alert ID for shadow register storage error.", - type: "int", - default: "6", - local: "true" - }, - { name: "LOCAL_ALERT_ID_LAST", - desc: "Last local alert ID.", - type: "int", - default: "6", - local: "true" - }, - ], - - inter_signal_list: [ - { struct: "alert_crashdump", - type: "uni", - name: "crashdump", - act: "req", - package: "alert_pkg" - }, - { struct: "edn" - type: "req_rsp" - name: "edn" - act: "req" - width: "1" - package: "edn_pkg" - }, - { struct: "esc_rx" - type: "uni" - name: "esc_rx" - act: "rcv" - width: "4", // N_ESC_SEV - package: "prim_esc_pkg" - }, - { struct: "esc_tx" - type: "uni" - name: "esc_tx" - act: "req" - width: "4", // N_ESC_SEV - package: "prim_esc_pkg" - }, - ] -# interrupt registers for the classes - interrupt_list: [ - { name: "classa", - desc: ''' - Interrupt state bit of Class A. Set by HW in case an alert within this class triggered. Defaults true, write one to clear. - ''', - }, - { name: "classb", - desc: ''' - Interrupt state bit of Class B. Set by HW in case an alert within this class triggered. Defaults true, write one to clear. - ''', - }, - { name: "classc", - desc: ''' - Interrupt state bit of Class C. Set by HW in case an alert within this class triggered. Defaults true, write one to clear. - ''', - }, - { name: "classd", - desc: ''' - Interrupt state bit of Class D. Set by HW in case an alert within this class triggered. Defaults true, write one to clear. - ''', - }, - ], - - registers: [ -# register lock for ping timeout counter - { name: "PING_TIMER_REGWEN", - desc: ''' - Register write enable for !!PING_TIMEOUT_CYC_SHADOWED and !!PING_TIMER_EN_SHADOWED. - ''', - swaccess: "rw0c", - hwaccess: "none", - fields: [ - { - bits: "0", - desc: ''' - When true, the !!PING_TIMEOUT_CYC_SHADOWED and !!PING_TIMER_EN_SHADOWED registers can be modified. - When false, they become read-only. Defaults true, write one to clear. - This should be cleared once the alert handler has been configured and the ping - timer mechanism has been kicked off. - ''' - resval: 1, - }, - ] - }, - { name: "PING_TIMEOUT_CYC_SHADOWED", - desc: ''' - Ping timeout cycle count. - ''' - shadowed: "true", - swaccess: "rw", - hwaccess: "hro", - regwen: "PING_TIMER_REGWEN", - fields: [ - { - bits: "PING_CNT_DW-1:0", - resval: 256, - desc: ''' - Timeout value in cycles. - If an alert receiver or an escalation sender does not respond to a ping within this timeout window, a pingfail alert will be raised. - It is recommended to set this value to the equivalent of 256 cycles of the slowest alert sender clock domain in the system (or greater). - ''' - } - ] - } - { name: "PING_TIMER_EN_SHADOWED", - desc: ''' - Ping timer enable. - ''' - shadowed: "true", - swaccess: "rw1s", - hwaccess: "hro", - regwen: "PING_TIMER_REGWEN", - fields: [ - { - bits: "0", - resval: 0, - desc: ''' - Setting this to 1 enables the ping timer mechanism. - This bit cannot be cleared to 0 once it has been set to 1. - - Note that the alert pinging mechanism will only ping alerts that have been enabled and locked. - ''' - } - ] - } -# all alerts - { multireg: { name: "ALERT_REGWEN", - desc: "Register write enable for alert enable bits.", - count: "NAlerts", - compact: "false", - swaccess: "rw0c", - hwaccess: "hro", - hwqe: "false", - cname: "alert", - fields: [ - { bits: "0", - name: "EN", - desc: ''' - Alert configuration write enable bit. - If this is cleared to 0, the corresponding !!ALERT_EN_SHADOWED0 - and !!ALERT_CLASS bits are not writable anymore. - - Note that the alert pinging mechanism will only ping alerts that have been enabled and locked. - ''', - resval: "1", - } - ] - } - }, - { multireg: { name: "ALERT_EN_SHADOWED", - desc: '''Enable register for alerts. - ''', - count: "NAlerts", - shadowed: "true", - swaccess: "rw", - hwaccess: "hro", - regwen: "ALERT_REGWEN", - regwen_multi: "true", - cname: "alert", - tags: [// Enable `alert_en` might cause top-level escalators to trigger - // unexpected reset - "excl:CsrAllTests:CsrExclWrite"] - fields: [ - { bits: "0", - name: "EN_A", - resval: 0 - desc: ''' - Alert enable bit. - - Note that the alert pinging mechanism will only ping alerts that have been enabled and locked. - ''' - } - ] - } - }, - { multireg: { name: "ALERT_CLASS_SHADOWED", - desc: '''Class assignment of alerts. - ''', - count: "NAlerts", - shadowed: "true", - swaccess: "rw", - hwaccess: "hro", - regwen: "ALERT_REGWEN", - regwen_multi: "true", - cname: "alert", - fields: [ - { - bits: "CLASS_DW-1:0", - name: "CLASS_A", - resval: 0 - desc: "Classification ", - enum: [ - { value: "0", name: "ClassA", desc: "" }, - { value: "1", name: "ClassB", desc: "" }, - { value: "2", name: "ClassC", desc: "" }, - { value: "3", name: "ClassD", desc: "" }, - ] - } - ] - } - }, - { multireg: { - name: "ALERT_CAUSE", - desc: "Alert Cause Register", - count: "NAlerts", - compact: "false", - cname: "ALERT", - swaccess: "rw1c", - hwaccess: "hrw", - fields: [ - { bits: "0", name: "A", desc: "Cause bit ", resval: 0} - ], - tags: [// The value of this register is determined by triggering different kinds of alerts - // Cannot be auto-predicted so excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - } - }, -# local alerts - { multireg: { name: "LOC_ALERT_REGWEN", - desc: "Register write enable for alert enable bits.", - count: "N_LOC_ALERT", - compact: "false", - swaccess: "rw0c", - hwaccess: "none", - cname: "LOC_ALERT", - fields: [ - { bits: "0", - name: "EN", - desc: ''' - Alert configuration write enable bit. - If this is cleared to 0, the corresponding !!LOC_ALERT_EN_SHADOWED0 - and !!LOC_ALERT_CLASS_SHADOWED0 bits are not writable anymore. - - Note that the alert pinging mechanism will only ping alerts that have been enabled and locked. - ''', - resval: "1", - } - ] - } - }, - { multireg: { name: "LOC_ALERT_EN_SHADOWED", - desc: - ''' - Enable register for the local alerts - "alert pingfail" (0), "escalation pingfail" (1), - "alert integfail" (2), "escalation integfail" (3), - "bus integrity failure" (4), "shadow reg update error" (5) - and "shadow reg storage error" (6). - ''', - count: "N_LOC_ALERT", - shadowed: "true", - swaccess: "rw", - hwaccess: "hro", - regwen: "LOC_ALERT_REGWEN", - regwen_multi: "true", - cname: "LOC_ALERT", - fields: [ - { bits: "0", - name: "EN_LA", - resval: 0 - desc: ''' - Alert enable bit. - - Note that the alert pinging mechanism will only ping alerts that have been enabled and locked. - ''' - } - ] - } - }, - { multireg: { name: "LOC_ALERT_CLASS_SHADOWED", - desc: ''' - Class assignment of the local alerts - "alert pingfail" (0), "escalation pingfail" (1), - "alert integfail" (2), "escalation integfail" (3), - "bus integrity failure" (4), "shadow reg update error" (5) - and "shadow reg storage error" (6). - ''', - count: "N_LOC_ALERT", - shadowed: "true", - swaccess: "rw", - hwaccess: "hro", - regwen: "LOC_ALERT_REGWEN", - regwen_multi: "true", - cname: "LOC_ALERT", - fields: [ - { - bits: "CLASS_DW-1:0", - name: "CLASS_LA", - resval: 0 - desc: "Classification ", - enum: [ - { value: "0", name: "ClassA", desc: "" }, - { value: "1", name: "ClassB", desc: "" }, - { value: "2", name: "ClassC", desc: "" }, - { value: "3", name: "ClassD", desc: "" }, - ] - } - ] - } - }, - { multireg: { - name: "LOC_ALERT_CAUSE", - desc: '''Alert Cause Register for the local alerts - "alert pingfail" (0), "escalation pingfail" (1), - "alert integfail" (2), "escalation integfail" (3), - "bus integrity failure" (4), "shadow reg update error" (5) - and "shadow reg storage error" (6). - ''', - count: "N_LOC_ALERT", - compact: "false", - cname: "LOC_ALERT", - swaccess: "rw1c", - hwaccess: "hrw", - tags: [// Top level CSR automation test, CPU clock is disabled, so escalation response will - // not send back to alert handler. This will set loc_alert_cause and could not predict - // automatically. - // TODO: remove the exclusion after set up top-level esc_receiver_driver - "excl:CsrNonInitTests:CsrExclCheck"], - fields: [ - { bits: "0", name: "LA", desc: "Cause bit ", resval: 0} - ] - } - }, -# classes - - { name: "CLASSA_REGWEN", - desc: ''' - Lock bit for Class A configuration. - ''' - swaccess: "rw0c", - hwaccess: "none", - fields: [ - { bits: "0", - desc: ''' - Class configuration enable bit. - If this is cleared to 0, the corresponding class configuration - registers cannot be written anymore. - ''', - resval: 1, - } - ] - }, - { name: "CLASSA_CTRL_SHADOWED", - desc: "Escalation control register for alert Class A. Can not be modified if !!CLASSA_REGWEN is false." - swaccess: "rw", - hwaccess: "hro", - regwen: "CLASSA_REGWEN", - shadowed: "true", - fields: [ - { bits: "0", - name: "EN", - desc: ''' - Enable escalation mechanisms (accumulation and - interrupt timeout) for Class A. Note that interrupts can fire - regardless of whether the escalation mechanisms are enabled for - this class or not. - ''', - } - { bits: "1", - name: "LOCK", - desc: ''' - Enable automatic locking of escalation counter for class A. - If true, there is no way to stop the escalation protocol for class A - once it has been triggered. - ''' - } - { bits: "2", - name: "EN_E0", - resval: 1, - desc: "Enable escalation signal 0 for Class A", - } - { bits: "3", - name: "EN_E1", - resval: 1, - desc: "Enable escalation signal 1 for Class A", - } - { bits: "4", - name: "EN_E2", - resval: 1, - desc: "Enable escalation signal 2 for Class A", - } - { bits: "5", - name: "EN_E3", - resval: 1, - desc: "Enable escalation signal 3 for Class A", - } - { bits: "7:6", - name: "MAP_E0", - resval: 0, - desc: "Determines in which escalation phase escalation signal 0 shall be asserted.", - } - { bits: "9:8", - name: "MAP_E1", - resval: 1, - desc: "Determines in which escalation phase escalation signal 1 shall be asserted.", - } - { bits: "11:10", - name: "MAP_E2", - resval: 2, - desc: "Determines in which escalation phase escalation signal 2 shall be asserted.", - } - { bits: "13:12", - name: "MAP_E3", - resval: 3, - desc: "Determines in which escalation phase escalation signal 3 shall be asserted.", - } - ] - }, - { name: "CLASSA_CLR_REGWEN", - desc: ''' - Clear enable for escalation protocol of Class A alerts. - ''' - swaccess: "rw0c", - hwaccess: "hwo", - fields: [ - { bits: "0", - desc: '''Register defaults to true, can only be cleared. This register is set - to false by the hardware if the escalation protocol has been triggered and the bit - !!CLASSA_CTRL_SHADOWED.LOCK is true. - ''', - resval: 1, - } - ], - tags: [// The value of this register is set to false only by hardware, - // under the condition that escalation is triggered and the corresponding lock bit is true - // Cannot not be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSA_CLR_SHADOWED", - desc: ''' - Clear for escalation protocol of Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - hwqe: "true", - shadowed: "true", - regwen: "CLASSA_CLR_REGWEN", - fields: [ - { bits: "0", - desc: '''Writing 1 to this register clears the accumulator and aborts escalation - (if it has been triggered). This clear is disabled if !!CLASSA_CLR_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSA_ACCUM_CNT", - desc: ''' - Current accumulation value for alert Class A. Software can clear this register - with a write to !!CLASSA_CLR_SHADOWED register unless !!CLASSA_CLR_REGWEN is false. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "AccuCntDw-1:0" } - ], - tags: [// The value of this register is determined by how many alerts have been triggered - // Cannot be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSA_ACCUM_THRESH_SHADOWED", - desc: ''' - Accumulation threshold value for alert Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - fields: [ - { bits: "AccuCntDw-1:0", - desc: '''Once the accumulation value register is equal to the threshold escalation will - be triggered on the next alert occurrence within this class A begins. Note that this - register can not be modified if !!CLASSA_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSA_TIMEOUT_CYC_SHADOWED", - desc: ''' - Interrupt timeout in cycles. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''If the interrupt corresponding to this class is not - handled within the specified amount of cycles, escalation will be triggered. - Set to a positive value to enable the interrupt timeout for Class A. The timeout is set to zero - by default, which disables this feature. Note that this register can not be modified if - !!CLASSA_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSA_CRASHDUMP_TRIGGER_SHADOWED", - desc: ''' - Crashdump trigger configuration for Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - resval: "0", - fields: [ - { bits: "PHASE_DW-1:0", - desc: ''' - Determine in which escalation phase to capture the crashdump containing all alert cause CSRs and escalation - timer states. It is recommended to capture the crashdump upon entering the first escalation phase - that activates a countermeasure with many side-effects (e.g. life cycle state scrapping) in order - to prevent spurious alert events from masking the original alert causes. - Note that this register can not be modified if !!CLASSA_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSA_PHASE0_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 0 for Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSA_REGWEN is false.''' - } - ] - } - { name: "CLASSA_PHASE1_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 1 for Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSA_REGWEN is false.''' - } - ] - } - { name: "CLASSA_PHASE2_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 2 for Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSA_REGWEN is false.''' - } - ] - } - { name: "CLASSA_PHASE3_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 3 for Class A. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSA_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSA_REGWEN is false.''' - } - ] - } - { name: "CLASSA_ESC_CNT", - desc: ''' - Escalation counter in cycles for Class A. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''Returns the current timeout or escalation count (depending on !!CLASSA_STATE). - This register can not be directly cleared. However, SW can indirectly clear as follows. - - If the class is in the Timeout state, the timeout can be aborted by clearing the - corresponding interrupt bit. - - If this class is in any of the escalation phases (e.g. Phase0), escalation protocol can be - aborted by writing to !!CLASSA_CLR_SHADOWED. Note however that has no effect if !!CLASSA_REGWEN - is set to false (either by SW or by HW via the !!CLASSA_CTRL_SHADOWED.LOCK feature). - ''' - } - ], - tags: [// The value of this register is determined by counting how many cycles the escalation phase has lasted - // Cannot be auto-predicted so excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSA_STATE", - desc: ''' - Current escalation state of Class A. See also !!CLASSA_ESC_CNT. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "2:0", - enum: [ - { value: "0b000", name: "Idle", desc: "No timeout or escalation triggered." }, - { value: "0b001", name: "Timeout", desc: "IRQ timeout counter is active." }, - { value: "0b010", name: "FsmError", desc: "Terminal error state if FSM has been glitched." }, - { value: "0b011", name: "Terminal", desc: "Terminal state after escalation protocol." }, - { value: "0b100", name: "Phase0", desc: "Escalation Phase0 is active." }, - { value: "0b101", name: "Phase1", desc: "Escalation Phase1 is active." }, - { value: "0b110", name: "Phase2", desc: "Escalation Phase2 is active." }, - { value: "0b111", name: "Phase3", desc: "Escalation Phase3 is active." } - ] - } - ], - tags: [// The current escalation state cannot be auto-predicted - // so this register is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - - { name: "CLASSB_REGWEN", - desc: ''' - Lock bit for Class B configuration. - ''' - swaccess: "rw0c", - hwaccess: "none", - fields: [ - { bits: "0", - desc: ''' - Class configuration enable bit. - If this is cleared to 0, the corresponding class configuration - registers cannot be written anymore. - ''', - resval: 1, - } - ] - }, - { name: "CLASSB_CTRL_SHADOWED", - desc: "Escalation control register for alert Class B. Can not be modified if !!CLASSB_REGWEN is false." - swaccess: "rw", - hwaccess: "hro", - regwen: "CLASSB_REGWEN", - shadowed: "true", - fields: [ - { bits: "0", - name: "EN", - desc: ''' - Enable escalation mechanisms (accumulation and - interrupt timeout) for Class B. Note that interrupts can fire - regardless of whether the escalation mechanisms are enabled for - this class or not. - ''', - } - { bits: "1", - name: "LOCK", - desc: ''' - Enable automatic locking of escalation counter for class B. - If true, there is no way to stop the escalation protocol for class B - once it has been triggered. - ''' - } - { bits: "2", - name: "EN_E0", - resval: 1, - desc: "Enable escalation signal 0 for Class B", - } - { bits: "3", - name: "EN_E1", - resval: 1, - desc: "Enable escalation signal 1 for Class B", - } - { bits: "4", - name: "EN_E2", - resval: 1, - desc: "Enable escalation signal 2 for Class B", - } - { bits: "5", - name: "EN_E3", - resval: 1, - desc: "Enable escalation signal 3 for Class B", - } - { bits: "7:6", - name: "MAP_E0", - resval: 0, - desc: "Determines in which escalation phase escalation signal 0 shall be asserted.", - } - { bits: "9:8", - name: "MAP_E1", - resval: 1, - desc: "Determines in which escalation phase escalation signal 1 shall be asserted.", - } - { bits: "11:10", - name: "MAP_E2", - resval: 2, - desc: "Determines in which escalation phase escalation signal 2 shall be asserted.", - } - { bits: "13:12", - name: "MAP_E3", - resval: 3, - desc: "Determines in which escalation phase escalation signal 3 shall be asserted.", - } - ] - }, - { name: "CLASSB_CLR_REGWEN", - desc: ''' - Clear enable for escalation protocol of Class B alerts. - ''' - swaccess: "rw0c", - hwaccess: "hwo", - fields: [ - { bits: "0", - desc: '''Register defaults to true, can only be cleared. This register is set - to false by the hardware if the escalation protocol has been triggered and the bit - !!CLASSB_CTRL_SHADOWED.LOCK is true. - ''', - resval: 1, - } - ], - tags: [// The value of this register is set to false only by hardware, - // under the condition that escalation is triggered and the corresponding lock bit is true - // Cannot not be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSB_CLR_SHADOWED", - desc: ''' - Clear for escalation protocol of Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - hwqe: "true", - shadowed: "true", - regwen: "CLASSB_CLR_REGWEN", - fields: [ - { bits: "0", - desc: '''Writing 1 to this register clears the accumulator and aborts escalation - (if it has been triggered). This clear is disabled if !!CLASSB_CLR_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSB_ACCUM_CNT", - desc: ''' - Current accumulation value for alert Class B. Software can clear this register - with a write to !!CLASSB_CLR_SHADOWED register unless !!CLASSB_CLR_REGWEN is false. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "AccuCntDw-1:0" } - ], - tags: [// The value of this register is determined by how many alerts have been triggered - // Cannot be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSB_ACCUM_THRESH_SHADOWED", - desc: ''' - Accumulation threshold value for alert Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - fields: [ - { bits: "AccuCntDw-1:0", - desc: '''Once the accumulation value register is equal to the threshold escalation will - be triggered on the next alert occurrence within this class B begins. Note that this - register can not be modified if !!CLASSB_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSB_TIMEOUT_CYC_SHADOWED", - desc: ''' - Interrupt timeout in cycles. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''If the interrupt corresponding to this class is not - handled within the specified amount of cycles, escalation will be triggered. - Set to a positive value to enable the interrupt timeout for Class B. The timeout is set to zero - by default, which disables this feature. Note that this register can not be modified if - !!CLASSB_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSB_CRASHDUMP_TRIGGER_SHADOWED", - desc: ''' - Crashdump trigger configuration for Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - resval: "0", - fields: [ - { bits: "PHASE_DW-1:0", - desc: ''' - Determine in which escalation phase to capture the crashdump containing all alert cause CSRs and escalation - timer states. It is recommended to capture the crashdump upon entering the first escalation phase - that activates a countermeasure with many side-effects (e.g. life cycle state scrapping) in order - to prevent spurious alert events from masking the original alert causes. - Note that this register can not be modified if !!CLASSB_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSB_PHASE0_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 0 for Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSB_REGWEN is false.''' - } - ] - } - { name: "CLASSB_PHASE1_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 1 for Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSB_REGWEN is false.''' - } - ] - } - { name: "CLASSB_PHASE2_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 2 for Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSB_REGWEN is false.''' - } - ] - } - { name: "CLASSB_PHASE3_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 3 for Class B. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSB_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSB_REGWEN is false.''' - } - ] - } - { name: "CLASSB_ESC_CNT", - desc: ''' - Escalation counter in cycles for Class B. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''Returns the current timeout or escalation count (depending on !!CLASSB_STATE). - This register can not be directly cleared. However, SW can indirectly clear as follows. - - If the class is in the Timeout state, the timeout can be aborted by clearing the - corresponding interrupt bit. - - If this class is in any of the escalation phases (e.g. Phase0), escalation protocol can be - aborted by writing to !!CLASSB_CLR_SHADOWED. Note however that has no effect if !!CLASSB_REGWEN - is set to false (either by SW or by HW via the !!CLASSB_CTRL_SHADOWED.LOCK feature). - ''' - } - ], - tags: [// The value of this register is determined by counting how many cycles the escalation phase has lasted - // Cannot be auto-predicted so excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSB_STATE", - desc: ''' - Current escalation state of Class B. See also !!CLASSB_ESC_CNT. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "2:0", - enum: [ - { value: "0b000", name: "Idle", desc: "No timeout or escalation triggered." }, - { value: "0b001", name: "Timeout", desc: "IRQ timeout counter is active." }, - { value: "0b010", name: "FsmError", desc: "Terminal error state if FSM has been glitched." }, - { value: "0b011", name: "Terminal", desc: "Terminal state after escalation protocol." }, - { value: "0b100", name: "Phase0", desc: "Escalation Phase0 is active." }, - { value: "0b101", name: "Phase1", desc: "Escalation Phase1 is active." }, - { value: "0b110", name: "Phase2", desc: "Escalation Phase2 is active." }, - { value: "0b111", name: "Phase3", desc: "Escalation Phase3 is active." } - ] - } - ], - tags: [// The current escalation state cannot be auto-predicted - // so this register is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - - { name: "CLASSC_REGWEN", - desc: ''' - Lock bit for Class C configuration. - ''' - swaccess: "rw0c", - hwaccess: "none", - fields: [ - { bits: "0", - desc: ''' - Class configuration enable bit. - If this is cleared to 0, the corresponding class configuration - registers cannot be written anymore. - ''', - resval: 1, - } - ] - }, - { name: "CLASSC_CTRL_SHADOWED", - desc: "Escalation control register for alert Class C. Can not be modified if !!CLASSC_REGWEN is false." - swaccess: "rw", - hwaccess: "hro", - regwen: "CLASSC_REGWEN", - shadowed: "true", - fields: [ - { bits: "0", - name: "EN", - desc: ''' - Enable escalation mechanisms (accumulation and - interrupt timeout) for Class C. Note that interrupts can fire - regardless of whether the escalation mechanisms are enabled for - this class or not. - ''', - } - { bits: "1", - name: "LOCK", - desc: ''' - Enable automatic locking of escalation counter for class C. - If true, there is no way to stop the escalation protocol for class C - once it has been triggered. - ''' - } - { bits: "2", - name: "EN_E0", - resval: 1, - desc: "Enable escalation signal 0 for Class C", - } - { bits: "3", - name: "EN_E1", - resval: 1, - desc: "Enable escalation signal 1 for Class C", - } - { bits: "4", - name: "EN_E2", - resval: 1, - desc: "Enable escalation signal 2 for Class C", - } - { bits: "5", - name: "EN_E3", - resval: 1, - desc: "Enable escalation signal 3 for Class C", - } - { bits: "7:6", - name: "MAP_E0", - resval: 0, - desc: "Determines in which escalation phase escalation signal 0 shall be asserted.", - } - { bits: "9:8", - name: "MAP_E1", - resval: 1, - desc: "Determines in which escalation phase escalation signal 1 shall be asserted.", - } - { bits: "11:10", - name: "MAP_E2", - resval: 2, - desc: "Determines in which escalation phase escalation signal 2 shall be asserted.", - } - { bits: "13:12", - name: "MAP_E3", - resval: 3, - desc: "Determines in which escalation phase escalation signal 3 shall be asserted.", - } - ] - }, - { name: "CLASSC_CLR_REGWEN", - desc: ''' - Clear enable for escalation protocol of Class C alerts. - ''' - swaccess: "rw0c", - hwaccess: "hwo", - fields: [ - { bits: "0", - desc: '''Register defaults to true, can only be cleared. This register is set - to false by the hardware if the escalation protocol has been triggered and the bit - !!CLASSC_CTRL_SHADOWED.LOCK is true. - ''', - resval: 1, - } - ], - tags: [// The value of this register is set to false only by hardware, - // under the condition that escalation is triggered and the corresponding lock bit is true - // Cannot not be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSC_CLR_SHADOWED", - desc: ''' - Clear for escalation protocol of Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - hwqe: "true", - shadowed: "true", - regwen: "CLASSC_CLR_REGWEN", - fields: [ - { bits: "0", - desc: '''Writing 1 to this register clears the accumulator and aborts escalation - (if it has been triggered). This clear is disabled if !!CLASSC_CLR_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSC_ACCUM_CNT", - desc: ''' - Current accumulation value for alert Class C. Software can clear this register - with a write to !!CLASSC_CLR_SHADOWED register unless !!CLASSC_CLR_REGWEN is false. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "AccuCntDw-1:0" } - ], - tags: [// The value of this register is determined by how many alerts have been triggered - // Cannot be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSC_ACCUM_THRESH_SHADOWED", - desc: ''' - Accumulation threshold value for alert Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - fields: [ - { bits: "AccuCntDw-1:0", - desc: '''Once the accumulation value register is equal to the threshold escalation will - be triggered on the next alert occurrence within this class C begins. Note that this - register can not be modified if !!CLASSC_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSC_TIMEOUT_CYC_SHADOWED", - desc: ''' - Interrupt timeout in cycles. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''If the interrupt corresponding to this class is not - handled within the specified amount of cycles, escalation will be triggered. - Set to a positive value to enable the interrupt timeout for Class C. The timeout is set to zero - by default, which disables this feature. Note that this register can not be modified if - !!CLASSC_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSC_CRASHDUMP_TRIGGER_SHADOWED", - desc: ''' - Crashdump trigger configuration for Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - resval: "0", - fields: [ - { bits: "PHASE_DW-1:0", - desc: ''' - Determine in which escalation phase to capture the crashdump containing all alert cause CSRs and escalation - timer states. It is recommended to capture the crashdump upon entering the first escalation phase - that activates a countermeasure with many side-effects (e.g. life cycle state scrapping) in order - to prevent spurious alert events from masking the original alert causes. - Note that this register can not be modified if !!CLASSC_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSC_PHASE0_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 0 for Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSC_REGWEN is false.''' - } - ] - } - { name: "CLASSC_PHASE1_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 1 for Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSC_REGWEN is false.''' - } - ] - } - { name: "CLASSC_PHASE2_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 2 for Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSC_REGWEN is false.''' - } - ] - } - { name: "CLASSC_PHASE3_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 3 for Class C. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSC_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSC_REGWEN is false.''' - } - ] - } - { name: "CLASSC_ESC_CNT", - desc: ''' - Escalation counter in cycles for Class C. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''Returns the current timeout or escalation count (depending on !!CLASSC_STATE). - This register can not be directly cleared. However, SW can indirectly clear as follows. - - If the class is in the Timeout state, the timeout can be aborted by clearing the - corresponding interrupt bit. - - If this class is in any of the escalation phases (e.g. Phase0), escalation protocol can be - aborted by writing to !!CLASSC_CLR_SHADOWED. Note however that has no effect if !!CLASSC_REGWEN - is set to false (either by SW or by HW via the !!CLASSC_CTRL_SHADOWED.LOCK feature). - ''' - } - ], - tags: [// The value of this register is determined by counting how many cycles the escalation phase has lasted - // Cannot be auto-predicted so excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSC_STATE", - desc: ''' - Current escalation state of Class C. See also !!CLASSC_ESC_CNT. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "2:0", - enum: [ - { value: "0b000", name: "Idle", desc: "No timeout or escalation triggered." }, - { value: "0b001", name: "Timeout", desc: "IRQ timeout counter is active." }, - { value: "0b010", name: "FsmError", desc: "Terminal error state if FSM has been glitched." }, - { value: "0b011", name: "Terminal", desc: "Terminal state after escalation protocol." }, - { value: "0b100", name: "Phase0", desc: "Escalation Phase0 is active." }, - { value: "0b101", name: "Phase1", desc: "Escalation Phase1 is active." }, - { value: "0b110", name: "Phase2", desc: "Escalation Phase2 is active." }, - { value: "0b111", name: "Phase3", desc: "Escalation Phase3 is active." } - ] - } - ], - tags: [// The current escalation state cannot be auto-predicted - // so this register is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - - { name: "CLASSD_REGWEN", - desc: ''' - Lock bit for Class D configuration. - ''' - swaccess: "rw0c", - hwaccess: "none", - fields: [ - { bits: "0", - desc: ''' - Class configuration enable bit. - If this is cleared to 0, the corresponding class configuration - registers cannot be written anymore. - ''', - resval: 1, - } - ] - }, - { name: "CLASSD_CTRL_SHADOWED", - desc: "Escalation control register for alert Class D. Can not be modified if !!CLASSD_REGWEN is false." - swaccess: "rw", - hwaccess: "hro", - regwen: "CLASSD_REGWEN", - shadowed: "true", - fields: [ - { bits: "0", - name: "EN", - desc: ''' - Enable escalation mechanisms (accumulation and - interrupt timeout) for Class D. Note that interrupts can fire - regardless of whether the escalation mechanisms are enabled for - this class or not. - ''', - } - { bits: "1", - name: "LOCK", - desc: ''' - Enable automatic locking of escalation counter for class D. - If true, there is no way to stop the escalation protocol for class D - once it has been triggered. - ''' - } - { bits: "2", - name: "EN_E0", - resval: 1, - desc: "Enable escalation signal 0 for Class D", - } - { bits: "3", - name: "EN_E1", - resval: 1, - desc: "Enable escalation signal 1 for Class D", - } - { bits: "4", - name: "EN_E2", - resval: 1, - desc: "Enable escalation signal 2 for Class D", - } - { bits: "5", - name: "EN_E3", - resval: 1, - desc: "Enable escalation signal 3 for Class D", - } - { bits: "7:6", - name: "MAP_E0", - resval: 0, - desc: "Determines in which escalation phase escalation signal 0 shall be asserted.", - } - { bits: "9:8", - name: "MAP_E1", - resval: 1, - desc: "Determines in which escalation phase escalation signal 1 shall be asserted.", - } - { bits: "11:10", - name: "MAP_E2", - resval: 2, - desc: "Determines in which escalation phase escalation signal 2 shall be asserted.", - } - { bits: "13:12", - name: "MAP_E3", - resval: 3, - desc: "Determines in which escalation phase escalation signal 3 shall be asserted.", - } - ] - }, - { name: "CLASSD_CLR_REGWEN", - desc: ''' - Clear enable for escalation protocol of Class D alerts. - ''' - swaccess: "rw0c", - hwaccess: "hwo", - fields: [ - { bits: "0", - desc: '''Register defaults to true, can only be cleared. This register is set - to false by the hardware if the escalation protocol has been triggered and the bit - !!CLASSD_CTRL_SHADOWED.LOCK is true. - ''', - resval: 1, - } - ], - tags: [// The value of this register is set to false only by hardware, - // under the condition that escalation is triggered and the corresponding lock bit is true - // Cannot not be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSD_CLR_SHADOWED", - desc: ''' - Clear for escalation protocol of Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - hwqe: "true", - shadowed: "true", - regwen: "CLASSD_CLR_REGWEN", - fields: [ - { bits: "0", - desc: '''Writing 1 to this register clears the accumulator and aborts escalation - (if it has been triggered). This clear is disabled if !!CLASSD_CLR_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSD_ACCUM_CNT", - desc: ''' - Current accumulation value for alert Class D. Software can clear this register - with a write to !!CLASSD_CLR_SHADOWED register unless !!CLASSD_CLR_REGWEN is false. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "AccuCntDw-1:0" } - ], - tags: [// The value of this register is determined by how many alerts have been triggered - // Cannot be auto-predicted so it is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSD_ACCUM_THRESH_SHADOWED", - desc: ''' - Accumulation threshold value for alert Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - fields: [ - { bits: "AccuCntDw-1:0", - desc: '''Once the accumulation value register is equal to the threshold escalation will - be triggered on the next alert occurrence within this class D begins. Note that this - register can not be modified if !!CLASSD_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSD_TIMEOUT_CYC_SHADOWED", - desc: ''' - Interrupt timeout in cycles. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''If the interrupt corresponding to this class is not - handled within the specified amount of cycles, escalation will be triggered. - Set to a positive value to enable the interrupt timeout for Class D. The timeout is set to zero - by default, which disables this feature. Note that this register can not be modified if - !!CLASSD_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSD_CRASHDUMP_TRIGGER_SHADOWED", - desc: ''' - Crashdump trigger configuration for Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - resval: "0", - fields: [ - { bits: "PHASE_DW-1:0", - desc: ''' - Determine in which escalation phase to capture the crashdump containing all alert cause CSRs and escalation - timer states. It is recommended to capture the crashdump upon entering the first escalation phase - that activates a countermeasure with many side-effects (e.g. life cycle state scrapping) in order - to prevent spurious alert events from masking the original alert causes. - Note that this register can not be modified if !!CLASSD_REGWEN is false. - ''' - } - ] - }, - { name: "CLASSD_PHASE0_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 0 for Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSD_REGWEN is false.''' - } - ] - } - { name: "CLASSD_PHASE1_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 1 for Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSD_REGWEN is false.''' - } - ] - } - { name: "CLASSD_PHASE2_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 2 for Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSD_REGWEN is false.''' - } - ] - } - { name: "CLASSD_PHASE3_CYC_SHADOWED", - desc: ''' - Duration of escalation phase 3 for Class D. - ''' - swaccess: "rw", - hwaccess: "hro", - shadowed: "true", - regwen: "CLASSD_REGWEN", - fields: [ - { bits: "EscCntDw-1:0" , - desc: '''Escalation phase duration in cycles. Note that this register can not be - modified if !!CLASSD_REGWEN is false.''' - } - ] - } - { name: "CLASSD_ESC_CNT", - desc: ''' - Escalation counter in cycles for Class D. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "EscCntDw-1:0", - desc: '''Returns the current timeout or escalation count (depending on !!CLASSD_STATE). - This register can not be directly cleared. However, SW can indirectly clear as follows. - - If the class is in the Timeout state, the timeout can be aborted by clearing the - corresponding interrupt bit. - - If this class is in any of the escalation phases (e.g. Phase0), escalation protocol can be - aborted by writing to !!CLASSD_CLR_SHADOWED. Note however that has no effect if !!CLASSD_REGWEN - is set to false (either by SW or by HW via the !!CLASSD_CTRL_SHADOWED.LOCK feature). - ''' - } - ], - tags: [// The value of this register is determined by counting how many cycles the escalation phase has lasted - // Cannot be auto-predicted so excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - { name: "CLASSD_STATE", - desc: ''' - Current escalation state of Class D. See also !!CLASSD_ESC_CNT. - ''' - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "2:0", - enum: [ - { value: "0b000", name: "Idle", desc: "No timeout or escalation triggered." }, - { value: "0b001", name: "Timeout", desc: "IRQ timeout counter is active." }, - { value: "0b010", name: "FsmError", desc: "Terminal error state if FSM has been glitched." }, - { value: "0b011", name: "Terminal", desc: "Terminal state after escalation protocol." }, - { value: "0b100", name: "Phase0", desc: "Escalation Phase0 is active." }, - { value: "0b101", name: "Phase1", desc: "Escalation Phase1 is active." }, - { value: "0b110", name: "Phase2", desc: "Escalation Phase2 is active." }, - { value: "0b111", name: "Phase3", desc: "Escalation Phase3 is active." } - ] - } - ], - tags: [// The current escalation state cannot be auto-predicted - // so this register is excluded from read check - "excl:CsrNonInitTests:CsrExclWriteCheck"] - }, - ], -} - diff --git a/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv b/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv deleted file mode 100644 index edc6a4e20f3a7..0000000000000 --- a/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv +++ /dev/null @@ -1,1078 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure - -package alert_handler_reg_pkg; - - // Param list - parameter int NAlerts = 4; - parameter int NLpg = 1; - parameter int NLpgWidth = 1; - parameter logic [NAlerts-1:0][NLpgWidth-1:0] LpgMap = { - 1'b0 -}; - parameter int EscCntDw = 32; - parameter int AccuCntDw = 16; - parameter logic [NAlerts-1:0] AsyncOn = { - '0 -}; - parameter int N_CLASSES = 4; - parameter int N_ESC_SEV = 4; - parameter int N_PHASES = 4; - parameter int N_LOC_ALERT = 7; - parameter int PING_CNT_DW = 16; - parameter int PHASE_DW = 2; - parameter int CLASS_DW = 2; - parameter int LOCAL_ALERT_ID_ALERT_PINGFAIL = 0; - parameter int LOCAL_ALERT_ID_ESC_PINGFAIL = 1; - parameter int LOCAL_ALERT_ID_ALERT_INTEGFAIL = 2; - parameter int LOCAL_ALERT_ID_ESC_INTEGFAIL = 3; - parameter int LOCAL_ALERT_ID_BUS_INTEGFAIL = 4; - parameter int LOCAL_ALERT_ID_SHADOW_REG_UPDATE_ERROR = 5; - parameter int LOCAL_ALERT_ID_SHADOW_REG_STORAGE_ERROR = 6; - parameter int LOCAL_ALERT_ID_LAST = 6; - - // Address widths within the block - parameter int BlockAw = 9; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - struct packed { - logic q; - } classa; - struct packed { - logic q; - } classb; - struct packed { - logic q; - } classc; - struct packed { - logic q; - } classd; - } alert_handler_reg2hw_intr_state_reg_t; - - typedef struct packed { - struct packed { - logic q; - } classa; - struct packed { - logic q; - } classb; - struct packed { - logic q; - } classc; - struct packed { - logic q; - } classd; - } alert_handler_reg2hw_intr_enable_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic qe; - } classa; - struct packed { - logic q; - logic qe; - } classb; - struct packed { - logic q; - logic qe; - } classc; - struct packed { - logic q; - logic qe; - } classd; - } alert_handler_reg2hw_intr_test_reg_t; - - typedef struct packed { - logic [15:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_ping_timeout_cyc_shadowed_reg_t; - - typedef struct packed { - logic q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_ping_timer_en_shadowed_reg_t; - - typedef struct packed { - logic q; - } alert_handler_reg2hw_alert_regwen_mreg_t; - - typedef struct packed { - logic q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_alert_en_shadowed_mreg_t; - - typedef struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_alert_class_shadowed_mreg_t; - - typedef struct packed { - logic q; - } alert_handler_reg2hw_alert_cause_mreg_t; - - typedef struct packed { - logic q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_loc_alert_en_shadowed_mreg_t; - - typedef struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_loc_alert_class_shadowed_mreg_t; - - typedef struct packed { - logic q; - } alert_handler_reg2hw_loc_alert_cause_mreg_t; - - typedef struct packed { - struct packed { - logic q; - logic err_update; - logic err_storage; - } en; - struct packed { - logic q; - logic err_update; - logic err_storage; - } lock; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e0; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e1; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e2; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e3; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e0; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e1; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e2; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e3; - } alert_handler_reg2hw_classa_ctrl_shadowed_reg_t; - - typedef struct packed { - logic q; - logic qe; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_clr_shadowed_reg_t; - - typedef struct packed { - logic [15:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_accum_thresh_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_timeout_cyc_shadowed_reg_t; - - typedef struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_crashdump_trigger_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_phase0_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_phase1_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_phase2_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classa_phase3_cyc_shadowed_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic err_update; - logic err_storage; - } en; - struct packed { - logic q; - logic err_update; - logic err_storage; - } lock; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e0; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e1; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e2; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e3; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e0; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e1; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e2; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e3; - } alert_handler_reg2hw_classb_ctrl_shadowed_reg_t; - - typedef struct packed { - logic q; - logic qe; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_clr_shadowed_reg_t; - - typedef struct packed { - logic [15:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_accum_thresh_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_timeout_cyc_shadowed_reg_t; - - typedef struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_crashdump_trigger_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_phase0_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_phase1_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_phase2_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classb_phase3_cyc_shadowed_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic err_update; - logic err_storage; - } en; - struct packed { - logic q; - logic err_update; - logic err_storage; - } lock; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e0; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e1; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e2; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e3; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e0; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e1; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e2; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e3; - } alert_handler_reg2hw_classc_ctrl_shadowed_reg_t; - - typedef struct packed { - logic q; - logic qe; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_clr_shadowed_reg_t; - - typedef struct packed { - logic [15:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_accum_thresh_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_timeout_cyc_shadowed_reg_t; - - typedef struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_crashdump_trigger_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_phase0_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_phase1_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_phase2_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classc_phase3_cyc_shadowed_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic err_update; - logic err_storage; - } en; - struct packed { - logic q; - logic err_update; - logic err_storage; - } lock; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e0; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e1; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e2; - struct packed { - logic q; - logic err_update; - logic err_storage; - } en_e3; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e0; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e1; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e2; - struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } map_e3; - } alert_handler_reg2hw_classd_ctrl_shadowed_reg_t; - - typedef struct packed { - logic q; - logic qe; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_clr_shadowed_reg_t; - - typedef struct packed { - logic [15:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_accum_thresh_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_timeout_cyc_shadowed_reg_t; - - typedef struct packed { - logic [1:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_crashdump_trigger_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_phase0_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_phase1_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_phase2_cyc_shadowed_reg_t; - - typedef struct packed { - logic [31:0] q; - logic err_update; - logic err_storage; - } alert_handler_reg2hw_classd_phase3_cyc_shadowed_reg_t; - - typedef struct packed { - struct packed { - logic d; - logic de; - } classa; - struct packed { - logic d; - logic de; - } classb; - struct packed { - logic d; - logic de; - } classc; - struct packed { - logic d; - logic de; - } classd; - } alert_handler_hw2reg_intr_state_reg_t; - - typedef struct packed { - logic d; - logic de; - } alert_handler_hw2reg_alert_cause_mreg_t; - - typedef struct packed { - logic d; - logic de; - } alert_handler_hw2reg_loc_alert_cause_mreg_t; - - typedef struct packed { - logic d; - logic de; - } alert_handler_hw2reg_classa_clr_regwen_reg_t; - - typedef struct packed { - logic [15:0] d; - } alert_handler_hw2reg_classa_accum_cnt_reg_t; - - typedef struct packed { - logic [31:0] d; - } alert_handler_hw2reg_classa_esc_cnt_reg_t; - - typedef struct packed { - logic [2:0] d; - } alert_handler_hw2reg_classa_state_reg_t; - - typedef struct packed { - logic d; - logic de; - } alert_handler_hw2reg_classb_clr_regwen_reg_t; - - typedef struct packed { - logic [15:0] d; - } alert_handler_hw2reg_classb_accum_cnt_reg_t; - - typedef struct packed { - logic [31:0] d; - } alert_handler_hw2reg_classb_esc_cnt_reg_t; - - typedef struct packed { - logic [2:0] d; - } alert_handler_hw2reg_classb_state_reg_t; - - typedef struct packed { - logic d; - logic de; - } alert_handler_hw2reg_classc_clr_regwen_reg_t; - - typedef struct packed { - logic [15:0] d; - } alert_handler_hw2reg_classc_accum_cnt_reg_t; - - typedef struct packed { - logic [31:0] d; - } alert_handler_hw2reg_classc_esc_cnt_reg_t; - - typedef struct packed { - logic [2:0] d; - } alert_handler_hw2reg_classc_state_reg_t; - - typedef struct packed { - logic d; - logic de; - } alert_handler_hw2reg_classd_clr_regwen_reg_t; - - typedef struct packed { - logic [15:0] d; - } alert_handler_hw2reg_classd_accum_cnt_reg_t; - - typedef struct packed { - logic [31:0] d; - } alert_handler_hw2reg_classd_esc_cnt_reg_t; - - typedef struct packed { - logic [2:0] d; - } alert_handler_hw2reg_classd_state_reg_t; - - // Register -> HW type - typedef struct packed { - alert_handler_reg2hw_intr_state_reg_t intr_state; // [856:853] - alert_handler_reg2hw_intr_enable_reg_t intr_enable; // [852:849] - alert_handler_reg2hw_intr_test_reg_t intr_test; // [848:841] - alert_handler_reg2hw_ping_timeout_cyc_shadowed_reg_t ping_timeout_cyc_shadowed; // [840:825] - alert_handler_reg2hw_ping_timer_en_shadowed_reg_t ping_timer_en_shadowed; // [824:824] - alert_handler_reg2hw_alert_regwen_mreg_t [3:0] alert_regwen; // [823:820] - alert_handler_reg2hw_alert_en_shadowed_mreg_t [3:0] alert_en_shadowed; // [819:816] - alert_handler_reg2hw_alert_class_shadowed_mreg_t [3:0] alert_class_shadowed; // [815:808] - alert_handler_reg2hw_alert_cause_mreg_t [3:0] alert_cause; // [807:804] - alert_handler_reg2hw_loc_alert_en_shadowed_mreg_t [6:0] loc_alert_en_shadowed; // [803:797] - alert_handler_reg2hw_loc_alert_class_shadowed_mreg_t [6:0] - loc_alert_class_shadowed; // [796:783] - alert_handler_reg2hw_loc_alert_cause_mreg_t [6:0] loc_alert_cause; // [782:776] - alert_handler_reg2hw_classa_ctrl_shadowed_reg_t classa_ctrl_shadowed; // [775:762] - alert_handler_reg2hw_classa_clr_shadowed_reg_t classa_clr_shadowed; // [761:760] - alert_handler_reg2hw_classa_accum_thresh_shadowed_reg_t - classa_accum_thresh_shadowed; // [759:744] - alert_handler_reg2hw_classa_timeout_cyc_shadowed_reg_t classa_timeout_cyc_shadowed; // [743:712] - alert_handler_reg2hw_classa_crashdump_trigger_shadowed_reg_t - classa_crashdump_trigger_shadowed; // [711:710] - alert_handler_reg2hw_classa_phase0_cyc_shadowed_reg_t classa_phase0_cyc_shadowed; // [709:678] - alert_handler_reg2hw_classa_phase1_cyc_shadowed_reg_t classa_phase1_cyc_shadowed; // [677:646] - alert_handler_reg2hw_classa_phase2_cyc_shadowed_reg_t classa_phase2_cyc_shadowed; // [645:614] - alert_handler_reg2hw_classa_phase3_cyc_shadowed_reg_t classa_phase3_cyc_shadowed; // [613:582] - alert_handler_reg2hw_classb_ctrl_shadowed_reg_t classb_ctrl_shadowed; // [581:568] - alert_handler_reg2hw_classb_clr_shadowed_reg_t classb_clr_shadowed; // [567:566] - alert_handler_reg2hw_classb_accum_thresh_shadowed_reg_t - classb_accum_thresh_shadowed; // [565:550] - alert_handler_reg2hw_classb_timeout_cyc_shadowed_reg_t classb_timeout_cyc_shadowed; // [549:518] - alert_handler_reg2hw_classb_crashdump_trigger_shadowed_reg_t - classb_crashdump_trigger_shadowed; // [517:516] - alert_handler_reg2hw_classb_phase0_cyc_shadowed_reg_t classb_phase0_cyc_shadowed; // [515:484] - alert_handler_reg2hw_classb_phase1_cyc_shadowed_reg_t classb_phase1_cyc_shadowed; // [483:452] - alert_handler_reg2hw_classb_phase2_cyc_shadowed_reg_t classb_phase2_cyc_shadowed; // [451:420] - alert_handler_reg2hw_classb_phase3_cyc_shadowed_reg_t classb_phase3_cyc_shadowed; // [419:388] - alert_handler_reg2hw_classc_ctrl_shadowed_reg_t classc_ctrl_shadowed; // [387:374] - alert_handler_reg2hw_classc_clr_shadowed_reg_t classc_clr_shadowed; // [373:372] - alert_handler_reg2hw_classc_accum_thresh_shadowed_reg_t - classc_accum_thresh_shadowed; // [371:356] - alert_handler_reg2hw_classc_timeout_cyc_shadowed_reg_t classc_timeout_cyc_shadowed; // [355:324] - alert_handler_reg2hw_classc_crashdump_trigger_shadowed_reg_t - classc_crashdump_trigger_shadowed; // [323:322] - alert_handler_reg2hw_classc_phase0_cyc_shadowed_reg_t classc_phase0_cyc_shadowed; // [321:290] - alert_handler_reg2hw_classc_phase1_cyc_shadowed_reg_t classc_phase1_cyc_shadowed; // [289:258] - alert_handler_reg2hw_classc_phase2_cyc_shadowed_reg_t classc_phase2_cyc_shadowed; // [257:226] - alert_handler_reg2hw_classc_phase3_cyc_shadowed_reg_t classc_phase3_cyc_shadowed; // [225:194] - alert_handler_reg2hw_classd_ctrl_shadowed_reg_t classd_ctrl_shadowed; // [193:180] - alert_handler_reg2hw_classd_clr_shadowed_reg_t classd_clr_shadowed; // [179:178] - alert_handler_reg2hw_classd_accum_thresh_shadowed_reg_t - classd_accum_thresh_shadowed; // [177:162] - alert_handler_reg2hw_classd_timeout_cyc_shadowed_reg_t classd_timeout_cyc_shadowed; // [161:130] - alert_handler_reg2hw_classd_crashdump_trigger_shadowed_reg_t - classd_crashdump_trigger_shadowed; // [129:128] - alert_handler_reg2hw_classd_phase0_cyc_shadowed_reg_t classd_phase0_cyc_shadowed; // [127:96] - alert_handler_reg2hw_classd_phase1_cyc_shadowed_reg_t classd_phase1_cyc_shadowed; // [95:64] - alert_handler_reg2hw_classd_phase2_cyc_shadowed_reg_t classd_phase2_cyc_shadowed; // [63:32] - alert_handler_reg2hw_classd_phase3_cyc_shadowed_reg_t classd_phase3_cyc_shadowed; // [31:0] - } alert_handler_reg2hw_t; - - // HW -> register type - typedef struct packed { - alert_handler_hw2reg_intr_state_reg_t intr_state; // [241:234] - alert_handler_hw2reg_alert_cause_mreg_t [3:0] alert_cause; // [233:226] - alert_handler_hw2reg_loc_alert_cause_mreg_t [6:0] loc_alert_cause; // [225:212] - alert_handler_hw2reg_classa_clr_regwen_reg_t classa_clr_regwen; // [211:210] - alert_handler_hw2reg_classa_accum_cnt_reg_t classa_accum_cnt; // [209:194] - alert_handler_hw2reg_classa_esc_cnt_reg_t classa_esc_cnt; // [193:162] - alert_handler_hw2reg_classa_state_reg_t classa_state; // [161:159] - alert_handler_hw2reg_classb_clr_regwen_reg_t classb_clr_regwen; // [158:157] - alert_handler_hw2reg_classb_accum_cnt_reg_t classb_accum_cnt; // [156:141] - alert_handler_hw2reg_classb_esc_cnt_reg_t classb_esc_cnt; // [140:109] - alert_handler_hw2reg_classb_state_reg_t classb_state; // [108:106] - alert_handler_hw2reg_classc_clr_regwen_reg_t classc_clr_regwen; // [105:104] - alert_handler_hw2reg_classc_accum_cnt_reg_t classc_accum_cnt; // [103:88] - alert_handler_hw2reg_classc_esc_cnt_reg_t classc_esc_cnt; // [87:56] - alert_handler_hw2reg_classc_state_reg_t classc_state; // [55:53] - alert_handler_hw2reg_classd_clr_regwen_reg_t classd_clr_regwen; // [52:51] - alert_handler_hw2reg_classd_accum_cnt_reg_t classd_accum_cnt; // [50:35] - alert_handler_hw2reg_classd_esc_cnt_reg_t classd_esc_cnt; // [34:3] - alert_handler_hw2reg_classd_state_reg_t classd_state; // [2:0] - } alert_handler_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] ALERT_HANDLER_INTR_STATE_OFFSET = 9'h 0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_INTR_ENABLE_OFFSET = 9'h 4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_INTR_TEST_OFFSET = 9'h 8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_PING_TIMER_REGWEN_OFFSET = 9'h c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_OFFSET = 9'h 10; - parameter logic [BlockAw-1:0] ALERT_HANDLER_PING_TIMER_EN_SHADOWED_OFFSET = 9'h 14; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_REGWEN_0_OFFSET = 9'h 18; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_REGWEN_1_OFFSET = 9'h 1c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_REGWEN_2_OFFSET = 9'h 20; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_REGWEN_3_OFFSET = 9'h 24; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_EN_SHADOWED_0_OFFSET = 9'h 28; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_EN_SHADOWED_1_OFFSET = 9'h 2c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_EN_SHADOWED_2_OFFSET = 9'h 30; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_EN_SHADOWED_3_OFFSET = 9'h 34; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CLASS_SHADOWED_0_OFFSET = 9'h 38; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CLASS_SHADOWED_1_OFFSET = 9'h 3c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CLASS_SHADOWED_2_OFFSET = 9'h 40; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CLASS_SHADOWED_3_OFFSET = 9'h 44; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CAUSE_0_OFFSET = 9'h 48; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CAUSE_1_OFFSET = 9'h 4c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CAUSE_2_OFFSET = 9'h 50; - parameter logic [BlockAw-1:0] ALERT_HANDLER_ALERT_CAUSE_3_OFFSET = 9'h 54; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_0_OFFSET = 9'h 58; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_1_OFFSET = 9'h 5c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_2_OFFSET = 9'h 60; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_3_OFFSET = 9'h 64; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_4_OFFSET = 9'h 68; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_5_OFFSET = 9'h 6c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_REGWEN_6_OFFSET = 9'h 70; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0_OFFSET = 9'h 74; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1_OFFSET = 9'h 78; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2_OFFSET = 9'h 7c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_3_OFFSET = 9'h 80; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_4_OFFSET = 9'h 84; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_5_OFFSET = 9'h 88; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_6_OFFSET = 9'h 8c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_OFFSET = 9'h 90; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1_OFFSET = 9'h 94; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2_OFFSET = 9'h 98; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_3_OFFSET = 9'h 9c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_4_OFFSET = 9'h a0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_5_OFFSET = 9'h a4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_6_OFFSET = 9'h a8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_0_OFFSET = 9'h ac; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_1_OFFSET = 9'h b0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_2_OFFSET = 9'h b4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_3_OFFSET = 9'h b8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_4_OFFSET = 9'h bc; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_5_OFFSET = 9'h c0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_LOC_ALERT_CAUSE_6_OFFSET = 9'h c4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_REGWEN_OFFSET = 9'h c8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_CTRL_SHADOWED_OFFSET = 9'h cc; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_CLR_REGWEN_OFFSET = 9'h d0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_CLR_SHADOWED_OFFSET = 9'h d4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_ACCUM_CNT_OFFSET = 9'h d8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_ACCUM_THRESH_SHADOWED_OFFSET = 9'h dc; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_TIMEOUT_CYC_SHADOWED_OFFSET = 9'h e0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_CRASHDUMP_TRIGGER_SHADOWED_OFFSET = 9'h e4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_PHASE0_CYC_SHADOWED_OFFSET = 9'h e8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_PHASE1_CYC_SHADOWED_OFFSET = 9'h ec; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_PHASE2_CYC_SHADOWED_OFFSET = 9'h f0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_PHASE3_CYC_SHADOWED_OFFSET = 9'h f4; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_ESC_CNT_OFFSET = 9'h f8; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSA_STATE_OFFSET = 9'h fc; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_REGWEN_OFFSET = 9'h 100; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_CTRL_SHADOWED_OFFSET = 9'h 104; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_CLR_REGWEN_OFFSET = 9'h 108; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_CLR_SHADOWED_OFFSET = 9'h 10c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_ACCUM_CNT_OFFSET = 9'h 110; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_ACCUM_THRESH_SHADOWED_OFFSET = 9'h 114; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_TIMEOUT_CYC_SHADOWED_OFFSET = 9'h 118; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_CRASHDUMP_TRIGGER_SHADOWED_OFFSET = 9'h 11c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_PHASE0_CYC_SHADOWED_OFFSET = 9'h 120; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_PHASE1_CYC_SHADOWED_OFFSET = 9'h 124; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_PHASE2_CYC_SHADOWED_OFFSET = 9'h 128; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_PHASE3_CYC_SHADOWED_OFFSET = 9'h 12c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_ESC_CNT_OFFSET = 9'h 130; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSB_STATE_OFFSET = 9'h 134; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_REGWEN_OFFSET = 9'h 138; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_CTRL_SHADOWED_OFFSET = 9'h 13c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_CLR_REGWEN_OFFSET = 9'h 140; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_CLR_SHADOWED_OFFSET = 9'h 144; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_ACCUM_CNT_OFFSET = 9'h 148; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_ACCUM_THRESH_SHADOWED_OFFSET = 9'h 14c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_TIMEOUT_CYC_SHADOWED_OFFSET = 9'h 150; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_CRASHDUMP_TRIGGER_SHADOWED_OFFSET = 9'h 154; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_PHASE0_CYC_SHADOWED_OFFSET = 9'h 158; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_PHASE1_CYC_SHADOWED_OFFSET = 9'h 15c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_PHASE2_CYC_SHADOWED_OFFSET = 9'h 160; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_PHASE3_CYC_SHADOWED_OFFSET = 9'h 164; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_ESC_CNT_OFFSET = 9'h 168; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSC_STATE_OFFSET = 9'h 16c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_REGWEN_OFFSET = 9'h 170; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_CTRL_SHADOWED_OFFSET = 9'h 174; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_CLR_REGWEN_OFFSET = 9'h 178; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_CLR_SHADOWED_OFFSET = 9'h 17c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_ACCUM_CNT_OFFSET = 9'h 180; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_ACCUM_THRESH_SHADOWED_OFFSET = 9'h 184; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_TIMEOUT_CYC_SHADOWED_OFFSET = 9'h 188; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_CRASHDUMP_TRIGGER_SHADOWED_OFFSET = 9'h 18c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_PHASE0_CYC_SHADOWED_OFFSET = 9'h 190; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_PHASE1_CYC_SHADOWED_OFFSET = 9'h 194; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_PHASE2_CYC_SHADOWED_OFFSET = 9'h 198; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_PHASE3_CYC_SHADOWED_OFFSET = 9'h 19c; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_ESC_CNT_OFFSET = 9'h 1a0; - parameter logic [BlockAw-1:0] ALERT_HANDLER_CLASSD_STATE_OFFSET = 9'h 1a4; - - // Reset values for hwext registers and their fields - parameter logic [3:0] ALERT_HANDLER_INTR_TEST_RESVAL = 4'h 0; - parameter logic [0:0] ALERT_HANDLER_INTR_TEST_CLASSA_RESVAL = 1'h 0; - parameter logic [0:0] ALERT_HANDLER_INTR_TEST_CLASSB_RESVAL = 1'h 0; - parameter logic [0:0] ALERT_HANDLER_INTR_TEST_CLASSC_RESVAL = 1'h 0; - parameter logic [0:0] ALERT_HANDLER_INTR_TEST_CLASSD_RESVAL = 1'h 0; - parameter logic [15:0] ALERT_HANDLER_CLASSA_ACCUM_CNT_RESVAL = 16'h 0; - parameter logic [31:0] ALERT_HANDLER_CLASSA_ESC_CNT_RESVAL = 32'h 0; - parameter logic [2:0] ALERT_HANDLER_CLASSA_STATE_RESVAL = 3'h 0; - parameter logic [15:0] ALERT_HANDLER_CLASSB_ACCUM_CNT_RESVAL = 16'h 0; - parameter logic [31:0] ALERT_HANDLER_CLASSB_ESC_CNT_RESVAL = 32'h 0; - parameter logic [2:0] ALERT_HANDLER_CLASSB_STATE_RESVAL = 3'h 0; - parameter logic [15:0] ALERT_HANDLER_CLASSC_ACCUM_CNT_RESVAL = 16'h 0; - parameter logic [31:0] ALERT_HANDLER_CLASSC_ESC_CNT_RESVAL = 32'h 0; - parameter logic [2:0] ALERT_HANDLER_CLASSC_STATE_RESVAL = 3'h 0; - parameter logic [15:0] ALERT_HANDLER_CLASSD_ACCUM_CNT_RESVAL = 16'h 0; - parameter logic [31:0] ALERT_HANDLER_CLASSD_ESC_CNT_RESVAL = 32'h 0; - parameter logic [2:0] ALERT_HANDLER_CLASSD_STATE_RESVAL = 3'h 0; - - // Register index - typedef enum int { - ALERT_HANDLER_INTR_STATE, - ALERT_HANDLER_INTR_ENABLE, - ALERT_HANDLER_INTR_TEST, - ALERT_HANDLER_PING_TIMER_REGWEN, - ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED, - ALERT_HANDLER_PING_TIMER_EN_SHADOWED, - ALERT_HANDLER_ALERT_REGWEN_0, - ALERT_HANDLER_ALERT_REGWEN_1, - ALERT_HANDLER_ALERT_REGWEN_2, - ALERT_HANDLER_ALERT_REGWEN_3, - ALERT_HANDLER_ALERT_EN_SHADOWED_0, - ALERT_HANDLER_ALERT_EN_SHADOWED_1, - ALERT_HANDLER_ALERT_EN_SHADOWED_2, - ALERT_HANDLER_ALERT_EN_SHADOWED_3, - ALERT_HANDLER_ALERT_CLASS_SHADOWED_0, - ALERT_HANDLER_ALERT_CLASS_SHADOWED_1, - ALERT_HANDLER_ALERT_CLASS_SHADOWED_2, - ALERT_HANDLER_ALERT_CLASS_SHADOWED_3, - ALERT_HANDLER_ALERT_CAUSE_0, - ALERT_HANDLER_ALERT_CAUSE_1, - ALERT_HANDLER_ALERT_CAUSE_2, - ALERT_HANDLER_ALERT_CAUSE_3, - ALERT_HANDLER_LOC_ALERT_REGWEN_0, - ALERT_HANDLER_LOC_ALERT_REGWEN_1, - ALERT_HANDLER_LOC_ALERT_REGWEN_2, - ALERT_HANDLER_LOC_ALERT_REGWEN_3, - ALERT_HANDLER_LOC_ALERT_REGWEN_4, - ALERT_HANDLER_LOC_ALERT_REGWEN_5, - ALERT_HANDLER_LOC_ALERT_REGWEN_6, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_3, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_4, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_5, - ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_6, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_3, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_4, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_5, - ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_6, - ALERT_HANDLER_LOC_ALERT_CAUSE_0, - ALERT_HANDLER_LOC_ALERT_CAUSE_1, - ALERT_HANDLER_LOC_ALERT_CAUSE_2, - ALERT_HANDLER_LOC_ALERT_CAUSE_3, - ALERT_HANDLER_LOC_ALERT_CAUSE_4, - ALERT_HANDLER_LOC_ALERT_CAUSE_5, - ALERT_HANDLER_LOC_ALERT_CAUSE_6, - ALERT_HANDLER_CLASSA_REGWEN, - ALERT_HANDLER_CLASSA_CTRL_SHADOWED, - ALERT_HANDLER_CLASSA_CLR_REGWEN, - ALERT_HANDLER_CLASSA_CLR_SHADOWED, - ALERT_HANDLER_CLASSA_ACCUM_CNT, - ALERT_HANDLER_CLASSA_ACCUM_THRESH_SHADOWED, - ALERT_HANDLER_CLASSA_TIMEOUT_CYC_SHADOWED, - ALERT_HANDLER_CLASSA_CRASHDUMP_TRIGGER_SHADOWED, - ALERT_HANDLER_CLASSA_PHASE0_CYC_SHADOWED, - ALERT_HANDLER_CLASSA_PHASE1_CYC_SHADOWED, - ALERT_HANDLER_CLASSA_PHASE2_CYC_SHADOWED, - ALERT_HANDLER_CLASSA_PHASE3_CYC_SHADOWED, - ALERT_HANDLER_CLASSA_ESC_CNT, - ALERT_HANDLER_CLASSA_STATE, - ALERT_HANDLER_CLASSB_REGWEN, - ALERT_HANDLER_CLASSB_CTRL_SHADOWED, - ALERT_HANDLER_CLASSB_CLR_REGWEN, - ALERT_HANDLER_CLASSB_CLR_SHADOWED, - ALERT_HANDLER_CLASSB_ACCUM_CNT, - ALERT_HANDLER_CLASSB_ACCUM_THRESH_SHADOWED, - ALERT_HANDLER_CLASSB_TIMEOUT_CYC_SHADOWED, - ALERT_HANDLER_CLASSB_CRASHDUMP_TRIGGER_SHADOWED, - ALERT_HANDLER_CLASSB_PHASE0_CYC_SHADOWED, - ALERT_HANDLER_CLASSB_PHASE1_CYC_SHADOWED, - ALERT_HANDLER_CLASSB_PHASE2_CYC_SHADOWED, - ALERT_HANDLER_CLASSB_PHASE3_CYC_SHADOWED, - ALERT_HANDLER_CLASSB_ESC_CNT, - ALERT_HANDLER_CLASSB_STATE, - ALERT_HANDLER_CLASSC_REGWEN, - ALERT_HANDLER_CLASSC_CTRL_SHADOWED, - ALERT_HANDLER_CLASSC_CLR_REGWEN, - ALERT_HANDLER_CLASSC_CLR_SHADOWED, - ALERT_HANDLER_CLASSC_ACCUM_CNT, - ALERT_HANDLER_CLASSC_ACCUM_THRESH_SHADOWED, - ALERT_HANDLER_CLASSC_TIMEOUT_CYC_SHADOWED, - ALERT_HANDLER_CLASSC_CRASHDUMP_TRIGGER_SHADOWED, - ALERT_HANDLER_CLASSC_PHASE0_CYC_SHADOWED, - ALERT_HANDLER_CLASSC_PHASE1_CYC_SHADOWED, - ALERT_HANDLER_CLASSC_PHASE2_CYC_SHADOWED, - ALERT_HANDLER_CLASSC_PHASE3_CYC_SHADOWED, - ALERT_HANDLER_CLASSC_ESC_CNT, - ALERT_HANDLER_CLASSC_STATE, - ALERT_HANDLER_CLASSD_REGWEN, - ALERT_HANDLER_CLASSD_CTRL_SHADOWED, - ALERT_HANDLER_CLASSD_CLR_REGWEN, - ALERT_HANDLER_CLASSD_CLR_SHADOWED, - ALERT_HANDLER_CLASSD_ACCUM_CNT, - ALERT_HANDLER_CLASSD_ACCUM_THRESH_SHADOWED, - ALERT_HANDLER_CLASSD_TIMEOUT_CYC_SHADOWED, - ALERT_HANDLER_CLASSD_CRASHDUMP_TRIGGER_SHADOWED, - ALERT_HANDLER_CLASSD_PHASE0_CYC_SHADOWED, - ALERT_HANDLER_CLASSD_PHASE1_CYC_SHADOWED, - ALERT_HANDLER_CLASSD_PHASE2_CYC_SHADOWED, - ALERT_HANDLER_CLASSD_PHASE3_CYC_SHADOWED, - ALERT_HANDLER_CLASSD_ESC_CNT, - ALERT_HANDLER_CLASSD_STATE - } alert_handler_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] ALERT_HANDLER_PERMIT [106] = '{ - 4'b 0001, // index[ 0] ALERT_HANDLER_INTR_STATE - 4'b 0001, // index[ 1] ALERT_HANDLER_INTR_ENABLE - 4'b 0001, // index[ 2] ALERT_HANDLER_INTR_TEST - 4'b 0001, // index[ 3] ALERT_HANDLER_PING_TIMER_REGWEN - 4'b 0011, // index[ 4] ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED - 4'b 0001, // index[ 5] ALERT_HANDLER_PING_TIMER_EN_SHADOWED - 4'b 0001, // index[ 6] ALERT_HANDLER_ALERT_REGWEN_0 - 4'b 0001, // index[ 7] ALERT_HANDLER_ALERT_REGWEN_1 - 4'b 0001, // index[ 8] ALERT_HANDLER_ALERT_REGWEN_2 - 4'b 0001, // index[ 9] ALERT_HANDLER_ALERT_REGWEN_3 - 4'b 0001, // index[ 10] ALERT_HANDLER_ALERT_EN_SHADOWED_0 - 4'b 0001, // index[ 11] ALERT_HANDLER_ALERT_EN_SHADOWED_1 - 4'b 0001, // index[ 12] ALERT_HANDLER_ALERT_EN_SHADOWED_2 - 4'b 0001, // index[ 13] ALERT_HANDLER_ALERT_EN_SHADOWED_3 - 4'b 0001, // index[ 14] ALERT_HANDLER_ALERT_CLASS_SHADOWED_0 - 4'b 0001, // index[ 15] ALERT_HANDLER_ALERT_CLASS_SHADOWED_1 - 4'b 0001, // index[ 16] ALERT_HANDLER_ALERT_CLASS_SHADOWED_2 - 4'b 0001, // index[ 17] ALERT_HANDLER_ALERT_CLASS_SHADOWED_3 - 4'b 0001, // index[ 18] ALERT_HANDLER_ALERT_CAUSE_0 - 4'b 0001, // index[ 19] ALERT_HANDLER_ALERT_CAUSE_1 - 4'b 0001, // index[ 20] ALERT_HANDLER_ALERT_CAUSE_2 - 4'b 0001, // index[ 21] ALERT_HANDLER_ALERT_CAUSE_3 - 4'b 0001, // index[ 22] ALERT_HANDLER_LOC_ALERT_REGWEN_0 - 4'b 0001, // index[ 23] ALERT_HANDLER_LOC_ALERT_REGWEN_1 - 4'b 0001, // index[ 24] ALERT_HANDLER_LOC_ALERT_REGWEN_2 - 4'b 0001, // index[ 25] ALERT_HANDLER_LOC_ALERT_REGWEN_3 - 4'b 0001, // index[ 26] ALERT_HANDLER_LOC_ALERT_REGWEN_4 - 4'b 0001, // index[ 27] ALERT_HANDLER_LOC_ALERT_REGWEN_5 - 4'b 0001, // index[ 28] ALERT_HANDLER_LOC_ALERT_REGWEN_6 - 4'b 0001, // index[ 29] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0 - 4'b 0001, // index[ 30] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1 - 4'b 0001, // index[ 31] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2 - 4'b 0001, // index[ 32] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_3 - 4'b 0001, // index[ 33] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_4 - 4'b 0001, // index[ 34] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_5 - 4'b 0001, // index[ 35] ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_6 - 4'b 0001, // index[ 36] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0 - 4'b 0001, // index[ 37] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1 - 4'b 0001, // index[ 38] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2 - 4'b 0001, // index[ 39] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_3 - 4'b 0001, // index[ 40] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_4 - 4'b 0001, // index[ 41] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_5 - 4'b 0001, // index[ 42] ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_6 - 4'b 0001, // index[ 43] ALERT_HANDLER_LOC_ALERT_CAUSE_0 - 4'b 0001, // index[ 44] ALERT_HANDLER_LOC_ALERT_CAUSE_1 - 4'b 0001, // index[ 45] ALERT_HANDLER_LOC_ALERT_CAUSE_2 - 4'b 0001, // index[ 46] ALERT_HANDLER_LOC_ALERT_CAUSE_3 - 4'b 0001, // index[ 47] ALERT_HANDLER_LOC_ALERT_CAUSE_4 - 4'b 0001, // index[ 48] ALERT_HANDLER_LOC_ALERT_CAUSE_5 - 4'b 0001, // index[ 49] ALERT_HANDLER_LOC_ALERT_CAUSE_6 - 4'b 0001, // index[ 50] ALERT_HANDLER_CLASSA_REGWEN - 4'b 0011, // index[ 51] ALERT_HANDLER_CLASSA_CTRL_SHADOWED - 4'b 0001, // index[ 52] ALERT_HANDLER_CLASSA_CLR_REGWEN - 4'b 0001, // index[ 53] ALERT_HANDLER_CLASSA_CLR_SHADOWED - 4'b 0011, // index[ 54] ALERT_HANDLER_CLASSA_ACCUM_CNT - 4'b 0011, // index[ 55] ALERT_HANDLER_CLASSA_ACCUM_THRESH_SHADOWED - 4'b 1111, // index[ 56] ALERT_HANDLER_CLASSA_TIMEOUT_CYC_SHADOWED - 4'b 0001, // index[ 57] ALERT_HANDLER_CLASSA_CRASHDUMP_TRIGGER_SHADOWED - 4'b 1111, // index[ 58] ALERT_HANDLER_CLASSA_PHASE0_CYC_SHADOWED - 4'b 1111, // index[ 59] ALERT_HANDLER_CLASSA_PHASE1_CYC_SHADOWED - 4'b 1111, // index[ 60] ALERT_HANDLER_CLASSA_PHASE2_CYC_SHADOWED - 4'b 1111, // index[ 61] ALERT_HANDLER_CLASSA_PHASE3_CYC_SHADOWED - 4'b 1111, // index[ 62] ALERT_HANDLER_CLASSA_ESC_CNT - 4'b 0001, // index[ 63] ALERT_HANDLER_CLASSA_STATE - 4'b 0001, // index[ 64] ALERT_HANDLER_CLASSB_REGWEN - 4'b 0011, // index[ 65] ALERT_HANDLER_CLASSB_CTRL_SHADOWED - 4'b 0001, // index[ 66] ALERT_HANDLER_CLASSB_CLR_REGWEN - 4'b 0001, // index[ 67] ALERT_HANDLER_CLASSB_CLR_SHADOWED - 4'b 0011, // index[ 68] ALERT_HANDLER_CLASSB_ACCUM_CNT - 4'b 0011, // index[ 69] ALERT_HANDLER_CLASSB_ACCUM_THRESH_SHADOWED - 4'b 1111, // index[ 70] ALERT_HANDLER_CLASSB_TIMEOUT_CYC_SHADOWED - 4'b 0001, // index[ 71] ALERT_HANDLER_CLASSB_CRASHDUMP_TRIGGER_SHADOWED - 4'b 1111, // index[ 72] ALERT_HANDLER_CLASSB_PHASE0_CYC_SHADOWED - 4'b 1111, // index[ 73] ALERT_HANDLER_CLASSB_PHASE1_CYC_SHADOWED - 4'b 1111, // index[ 74] ALERT_HANDLER_CLASSB_PHASE2_CYC_SHADOWED - 4'b 1111, // index[ 75] ALERT_HANDLER_CLASSB_PHASE3_CYC_SHADOWED - 4'b 1111, // index[ 76] ALERT_HANDLER_CLASSB_ESC_CNT - 4'b 0001, // index[ 77] ALERT_HANDLER_CLASSB_STATE - 4'b 0001, // index[ 78] ALERT_HANDLER_CLASSC_REGWEN - 4'b 0011, // index[ 79] ALERT_HANDLER_CLASSC_CTRL_SHADOWED - 4'b 0001, // index[ 80] ALERT_HANDLER_CLASSC_CLR_REGWEN - 4'b 0001, // index[ 81] ALERT_HANDLER_CLASSC_CLR_SHADOWED - 4'b 0011, // index[ 82] ALERT_HANDLER_CLASSC_ACCUM_CNT - 4'b 0011, // index[ 83] ALERT_HANDLER_CLASSC_ACCUM_THRESH_SHADOWED - 4'b 1111, // index[ 84] ALERT_HANDLER_CLASSC_TIMEOUT_CYC_SHADOWED - 4'b 0001, // index[ 85] ALERT_HANDLER_CLASSC_CRASHDUMP_TRIGGER_SHADOWED - 4'b 1111, // index[ 86] ALERT_HANDLER_CLASSC_PHASE0_CYC_SHADOWED - 4'b 1111, // index[ 87] ALERT_HANDLER_CLASSC_PHASE1_CYC_SHADOWED - 4'b 1111, // index[ 88] ALERT_HANDLER_CLASSC_PHASE2_CYC_SHADOWED - 4'b 1111, // index[ 89] ALERT_HANDLER_CLASSC_PHASE3_CYC_SHADOWED - 4'b 1111, // index[ 90] ALERT_HANDLER_CLASSC_ESC_CNT - 4'b 0001, // index[ 91] ALERT_HANDLER_CLASSC_STATE - 4'b 0001, // index[ 92] ALERT_HANDLER_CLASSD_REGWEN - 4'b 0011, // index[ 93] ALERT_HANDLER_CLASSD_CTRL_SHADOWED - 4'b 0001, // index[ 94] ALERT_HANDLER_CLASSD_CLR_REGWEN - 4'b 0001, // index[ 95] ALERT_HANDLER_CLASSD_CLR_SHADOWED - 4'b 0011, // index[ 96] ALERT_HANDLER_CLASSD_ACCUM_CNT - 4'b 0011, // index[ 97] ALERT_HANDLER_CLASSD_ACCUM_THRESH_SHADOWED - 4'b 1111, // index[ 98] ALERT_HANDLER_CLASSD_TIMEOUT_CYC_SHADOWED - 4'b 0001, // index[ 99] ALERT_HANDLER_CLASSD_CRASHDUMP_TRIGGER_SHADOWED - 4'b 1111, // index[100] ALERT_HANDLER_CLASSD_PHASE0_CYC_SHADOWED - 4'b 1111, // index[101] ALERT_HANDLER_CLASSD_PHASE1_CYC_SHADOWED - 4'b 1111, // index[102] ALERT_HANDLER_CLASSD_PHASE2_CYC_SHADOWED - 4'b 1111, // index[103] ALERT_HANDLER_CLASSD_PHASE3_CYC_SHADOWED - 4'b 1111, // index[104] ALERT_HANDLER_CLASSD_ESC_CNT - 4'b 0001 // index[105] ALERT_HANDLER_CLASSD_STATE - }; - -endpackage - diff --git a/hw/ip/alert_handler/rtl/alert_handler_reg_top.sv b/hw/ip/alert_handler/rtl/alert_handler_reg_top.sv deleted file mode 100644 index 6f5a36c0fbded..0000000000000 --- a/hw/ip/alert_handler/rtl/alert_handler_reg_top.sv +++ /dev/null @@ -1,6103 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - -`include "prim_assert.sv" - -module alert_handler_reg_top ( - input clk_i, - input rst_ni, - input rst_shadowed_ni, - input tlul_pkg::tl_h2d_t tl_i, - output tlul_pkg::tl_d2h_t tl_o, - // To HW - output alert_handler_reg_pkg::alert_handler_reg2hw_t reg2hw, // Write - input alert_handler_reg_pkg::alert_handler_hw2reg_t hw2reg, // Read - - // Integrity check errors - output logic intg_err_o, - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import alert_handler_reg_pkg::* ; - - localparam int AW = 9; - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [AW-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - logic reg_busy; - - tlul_pkg::tl_h2d_t tl_reg_h2d; - tlul_pkg::tl_d2h_t tl_reg_d2h; - - - // incoming payload check - logic intg_err; - tlul_cmd_intg_chk u_chk ( - .tl_i(tl_i), - .err_o(intg_err) - ); - - logic intg_err_q; - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - intg_err_q <= '0; - end else if (intg_err) begin - intg_err_q <= 1'b1; - end - end - - // integrity error output is permanent and should be used for alert generation - // register errors are transactional - assign intg_err_o = intg_err_q | intg_err; - - // outgoing integrity generation - tlul_pkg::tl_d2h_t tl_o_pre; - tlul_rsp_intg_gen #( - .EnableRspIntgGen(1), - .EnableDataIntgGen(1) - ) u_rsp_intg_gen ( - .tl_i(tl_o_pre), - .tl_o(tl_o) - ); - - assign tl_reg_h2d = tl_i; - assign tl_o_pre = tl_reg_d2h; - - tlul_adapter_reg #( - .RegAw(AW), - .RegDw(DW), - .EnableDataIntgGen(0) - ) u_reg_if ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - .tl_i (tl_reg_h2d), - .tl_o (tl_reg_d2h), - - .we_o (reg_we), - .re_o (reg_re), - .addr_o (reg_addr), - .wdata_o (reg_wdata), - .be_o (reg_be), - .busy_i (reg_busy), - .rdata_i (reg_rdata), - .error_i (reg_error) - ); - - // cdc oversampling signals - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err | intg_err; - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic intr_state_we; - logic intr_state_classa_qs; - logic intr_state_classa_wd; - logic intr_state_classb_qs; - logic intr_state_classb_wd; - logic intr_state_classc_qs; - logic intr_state_classc_wd; - logic intr_state_classd_qs; - logic intr_state_classd_wd; - logic intr_enable_we; - logic intr_enable_classa_qs; - logic intr_enable_classa_wd; - logic intr_enable_classb_qs; - logic intr_enable_classb_wd; - logic intr_enable_classc_qs; - logic intr_enable_classc_wd; - logic intr_enable_classd_qs; - logic intr_enable_classd_wd; - logic intr_test_we; - logic intr_test_classa_wd; - logic intr_test_classb_wd; - logic intr_test_classc_wd; - logic intr_test_classd_wd; - logic ping_timer_regwen_we; - logic ping_timer_regwen_qs; - logic ping_timer_regwen_wd; - logic ping_timeout_cyc_shadowed_re; - logic ping_timeout_cyc_shadowed_we; - logic [15:0] ping_timeout_cyc_shadowed_qs; - logic [15:0] ping_timeout_cyc_shadowed_wd; - logic ping_timer_en_shadowed_re; - logic ping_timer_en_shadowed_we; - logic ping_timer_en_shadowed_qs; - logic ping_timer_en_shadowed_wd; - logic alert_regwen_0_we; - logic alert_regwen_0_qs; - logic alert_regwen_0_wd; - logic alert_regwen_1_we; - logic alert_regwen_1_qs; - logic alert_regwen_1_wd; - logic alert_regwen_2_we; - logic alert_regwen_2_qs; - logic alert_regwen_2_wd; - logic alert_regwen_3_we; - logic alert_regwen_3_qs; - logic alert_regwen_3_wd; - logic alert_en_shadowed_0_re; - logic alert_en_shadowed_0_we; - logic alert_en_shadowed_0_qs; - logic alert_en_shadowed_0_wd; - logic alert_en_shadowed_1_re; - logic alert_en_shadowed_1_we; - logic alert_en_shadowed_1_qs; - logic alert_en_shadowed_1_wd; - logic alert_en_shadowed_2_re; - logic alert_en_shadowed_2_we; - logic alert_en_shadowed_2_qs; - logic alert_en_shadowed_2_wd; - logic alert_en_shadowed_3_re; - logic alert_en_shadowed_3_we; - logic alert_en_shadowed_3_qs; - logic alert_en_shadowed_3_wd; - logic alert_class_shadowed_0_re; - logic alert_class_shadowed_0_we; - logic [1:0] alert_class_shadowed_0_qs; - logic [1:0] alert_class_shadowed_0_wd; - logic alert_class_shadowed_1_re; - logic alert_class_shadowed_1_we; - logic [1:0] alert_class_shadowed_1_qs; - logic [1:0] alert_class_shadowed_1_wd; - logic alert_class_shadowed_2_re; - logic alert_class_shadowed_2_we; - logic [1:0] alert_class_shadowed_2_qs; - logic [1:0] alert_class_shadowed_2_wd; - logic alert_class_shadowed_3_re; - logic alert_class_shadowed_3_we; - logic [1:0] alert_class_shadowed_3_qs; - logic [1:0] alert_class_shadowed_3_wd; - logic alert_cause_0_we; - logic alert_cause_0_qs; - logic alert_cause_0_wd; - logic alert_cause_1_we; - logic alert_cause_1_qs; - logic alert_cause_1_wd; - logic alert_cause_2_we; - logic alert_cause_2_qs; - logic alert_cause_2_wd; - logic alert_cause_3_we; - logic alert_cause_3_qs; - logic alert_cause_3_wd; - logic loc_alert_regwen_0_we; - logic loc_alert_regwen_0_qs; - logic loc_alert_regwen_0_wd; - logic loc_alert_regwen_1_we; - logic loc_alert_regwen_1_qs; - logic loc_alert_regwen_1_wd; - logic loc_alert_regwen_2_we; - logic loc_alert_regwen_2_qs; - logic loc_alert_regwen_2_wd; - logic loc_alert_regwen_3_we; - logic loc_alert_regwen_3_qs; - logic loc_alert_regwen_3_wd; - logic loc_alert_regwen_4_we; - logic loc_alert_regwen_4_qs; - logic loc_alert_regwen_4_wd; - logic loc_alert_regwen_5_we; - logic loc_alert_regwen_5_qs; - logic loc_alert_regwen_5_wd; - logic loc_alert_regwen_6_we; - logic loc_alert_regwen_6_qs; - logic loc_alert_regwen_6_wd; - logic loc_alert_en_shadowed_0_re; - logic loc_alert_en_shadowed_0_we; - logic loc_alert_en_shadowed_0_qs; - logic loc_alert_en_shadowed_0_wd; - logic loc_alert_en_shadowed_1_re; - logic loc_alert_en_shadowed_1_we; - logic loc_alert_en_shadowed_1_qs; - logic loc_alert_en_shadowed_1_wd; - logic loc_alert_en_shadowed_2_re; - logic loc_alert_en_shadowed_2_we; - logic loc_alert_en_shadowed_2_qs; - logic loc_alert_en_shadowed_2_wd; - logic loc_alert_en_shadowed_3_re; - logic loc_alert_en_shadowed_3_we; - logic loc_alert_en_shadowed_3_qs; - logic loc_alert_en_shadowed_3_wd; - logic loc_alert_en_shadowed_4_re; - logic loc_alert_en_shadowed_4_we; - logic loc_alert_en_shadowed_4_qs; - logic loc_alert_en_shadowed_4_wd; - logic loc_alert_en_shadowed_5_re; - logic loc_alert_en_shadowed_5_we; - logic loc_alert_en_shadowed_5_qs; - logic loc_alert_en_shadowed_5_wd; - logic loc_alert_en_shadowed_6_re; - logic loc_alert_en_shadowed_6_we; - logic loc_alert_en_shadowed_6_qs; - logic loc_alert_en_shadowed_6_wd; - logic loc_alert_class_shadowed_0_re; - logic loc_alert_class_shadowed_0_we; - logic [1:0] loc_alert_class_shadowed_0_qs; - logic [1:0] loc_alert_class_shadowed_0_wd; - logic loc_alert_class_shadowed_1_re; - logic loc_alert_class_shadowed_1_we; - logic [1:0] loc_alert_class_shadowed_1_qs; - logic [1:0] loc_alert_class_shadowed_1_wd; - logic loc_alert_class_shadowed_2_re; - logic loc_alert_class_shadowed_2_we; - logic [1:0] loc_alert_class_shadowed_2_qs; - logic [1:0] loc_alert_class_shadowed_2_wd; - logic loc_alert_class_shadowed_3_re; - logic loc_alert_class_shadowed_3_we; - logic [1:0] loc_alert_class_shadowed_3_qs; - logic [1:0] loc_alert_class_shadowed_3_wd; - logic loc_alert_class_shadowed_4_re; - logic loc_alert_class_shadowed_4_we; - logic [1:0] loc_alert_class_shadowed_4_qs; - logic [1:0] loc_alert_class_shadowed_4_wd; - logic loc_alert_class_shadowed_5_re; - logic loc_alert_class_shadowed_5_we; - logic [1:0] loc_alert_class_shadowed_5_qs; - logic [1:0] loc_alert_class_shadowed_5_wd; - logic loc_alert_class_shadowed_6_re; - logic loc_alert_class_shadowed_6_we; - logic [1:0] loc_alert_class_shadowed_6_qs; - logic [1:0] loc_alert_class_shadowed_6_wd; - logic loc_alert_cause_0_we; - logic loc_alert_cause_0_qs; - logic loc_alert_cause_0_wd; - logic loc_alert_cause_1_we; - logic loc_alert_cause_1_qs; - logic loc_alert_cause_1_wd; - logic loc_alert_cause_2_we; - logic loc_alert_cause_2_qs; - logic loc_alert_cause_2_wd; - logic loc_alert_cause_3_we; - logic loc_alert_cause_3_qs; - logic loc_alert_cause_3_wd; - logic loc_alert_cause_4_we; - logic loc_alert_cause_4_qs; - logic loc_alert_cause_4_wd; - logic loc_alert_cause_5_we; - logic loc_alert_cause_5_qs; - logic loc_alert_cause_5_wd; - logic loc_alert_cause_6_we; - logic loc_alert_cause_6_qs; - logic loc_alert_cause_6_wd; - logic classa_regwen_we; - logic classa_regwen_qs; - logic classa_regwen_wd; - logic classa_ctrl_shadowed_re; - logic classa_ctrl_shadowed_we; - logic classa_ctrl_shadowed_en_qs; - logic classa_ctrl_shadowed_en_wd; - logic classa_ctrl_shadowed_lock_qs; - logic classa_ctrl_shadowed_lock_wd; - logic classa_ctrl_shadowed_en_e0_qs; - logic classa_ctrl_shadowed_en_e0_wd; - logic classa_ctrl_shadowed_en_e1_qs; - logic classa_ctrl_shadowed_en_e1_wd; - logic classa_ctrl_shadowed_en_e2_qs; - logic classa_ctrl_shadowed_en_e2_wd; - logic classa_ctrl_shadowed_en_e3_qs; - logic classa_ctrl_shadowed_en_e3_wd; - logic [1:0] classa_ctrl_shadowed_map_e0_qs; - logic [1:0] classa_ctrl_shadowed_map_e0_wd; - logic [1:0] classa_ctrl_shadowed_map_e1_qs; - logic [1:0] classa_ctrl_shadowed_map_e1_wd; - logic [1:0] classa_ctrl_shadowed_map_e2_qs; - logic [1:0] classa_ctrl_shadowed_map_e2_wd; - logic [1:0] classa_ctrl_shadowed_map_e3_qs; - logic [1:0] classa_ctrl_shadowed_map_e3_wd; - logic classa_clr_regwen_we; - logic classa_clr_regwen_qs; - logic classa_clr_regwen_wd; - logic classa_clr_shadowed_re; - logic classa_clr_shadowed_we; - logic classa_clr_shadowed_qs; - logic classa_clr_shadowed_wd; - logic classa_accum_cnt_re; - logic [15:0] classa_accum_cnt_qs; - logic classa_accum_thresh_shadowed_re; - logic classa_accum_thresh_shadowed_we; - logic [15:0] classa_accum_thresh_shadowed_qs; - logic [15:0] classa_accum_thresh_shadowed_wd; - logic classa_timeout_cyc_shadowed_re; - logic classa_timeout_cyc_shadowed_we; - logic [31:0] classa_timeout_cyc_shadowed_qs; - logic [31:0] classa_timeout_cyc_shadowed_wd; - logic classa_crashdump_trigger_shadowed_re; - logic classa_crashdump_trigger_shadowed_we; - logic [1:0] classa_crashdump_trigger_shadowed_qs; - logic [1:0] classa_crashdump_trigger_shadowed_wd; - logic classa_phase0_cyc_shadowed_re; - logic classa_phase0_cyc_shadowed_we; - logic [31:0] classa_phase0_cyc_shadowed_qs; - logic [31:0] classa_phase0_cyc_shadowed_wd; - logic classa_phase1_cyc_shadowed_re; - logic classa_phase1_cyc_shadowed_we; - logic [31:0] classa_phase1_cyc_shadowed_qs; - logic [31:0] classa_phase1_cyc_shadowed_wd; - logic classa_phase2_cyc_shadowed_re; - logic classa_phase2_cyc_shadowed_we; - logic [31:0] classa_phase2_cyc_shadowed_qs; - logic [31:0] classa_phase2_cyc_shadowed_wd; - logic classa_phase3_cyc_shadowed_re; - logic classa_phase3_cyc_shadowed_we; - logic [31:0] classa_phase3_cyc_shadowed_qs; - logic [31:0] classa_phase3_cyc_shadowed_wd; - logic classa_esc_cnt_re; - logic [31:0] classa_esc_cnt_qs; - logic classa_state_re; - logic [2:0] classa_state_qs; - logic classb_regwen_we; - logic classb_regwen_qs; - logic classb_regwen_wd; - logic classb_ctrl_shadowed_re; - logic classb_ctrl_shadowed_we; - logic classb_ctrl_shadowed_en_qs; - logic classb_ctrl_shadowed_en_wd; - logic classb_ctrl_shadowed_lock_qs; - logic classb_ctrl_shadowed_lock_wd; - logic classb_ctrl_shadowed_en_e0_qs; - logic classb_ctrl_shadowed_en_e0_wd; - logic classb_ctrl_shadowed_en_e1_qs; - logic classb_ctrl_shadowed_en_e1_wd; - logic classb_ctrl_shadowed_en_e2_qs; - logic classb_ctrl_shadowed_en_e2_wd; - logic classb_ctrl_shadowed_en_e3_qs; - logic classb_ctrl_shadowed_en_e3_wd; - logic [1:0] classb_ctrl_shadowed_map_e0_qs; - logic [1:0] classb_ctrl_shadowed_map_e0_wd; - logic [1:0] classb_ctrl_shadowed_map_e1_qs; - logic [1:0] classb_ctrl_shadowed_map_e1_wd; - logic [1:0] classb_ctrl_shadowed_map_e2_qs; - logic [1:0] classb_ctrl_shadowed_map_e2_wd; - logic [1:0] classb_ctrl_shadowed_map_e3_qs; - logic [1:0] classb_ctrl_shadowed_map_e3_wd; - logic classb_clr_regwen_we; - logic classb_clr_regwen_qs; - logic classb_clr_regwen_wd; - logic classb_clr_shadowed_re; - logic classb_clr_shadowed_we; - logic classb_clr_shadowed_qs; - logic classb_clr_shadowed_wd; - logic classb_accum_cnt_re; - logic [15:0] classb_accum_cnt_qs; - logic classb_accum_thresh_shadowed_re; - logic classb_accum_thresh_shadowed_we; - logic [15:0] classb_accum_thresh_shadowed_qs; - logic [15:0] classb_accum_thresh_shadowed_wd; - logic classb_timeout_cyc_shadowed_re; - logic classb_timeout_cyc_shadowed_we; - logic [31:0] classb_timeout_cyc_shadowed_qs; - logic [31:0] classb_timeout_cyc_shadowed_wd; - logic classb_crashdump_trigger_shadowed_re; - logic classb_crashdump_trigger_shadowed_we; - logic [1:0] classb_crashdump_trigger_shadowed_qs; - logic [1:0] classb_crashdump_trigger_shadowed_wd; - logic classb_phase0_cyc_shadowed_re; - logic classb_phase0_cyc_shadowed_we; - logic [31:0] classb_phase0_cyc_shadowed_qs; - logic [31:0] classb_phase0_cyc_shadowed_wd; - logic classb_phase1_cyc_shadowed_re; - logic classb_phase1_cyc_shadowed_we; - logic [31:0] classb_phase1_cyc_shadowed_qs; - logic [31:0] classb_phase1_cyc_shadowed_wd; - logic classb_phase2_cyc_shadowed_re; - logic classb_phase2_cyc_shadowed_we; - logic [31:0] classb_phase2_cyc_shadowed_qs; - logic [31:0] classb_phase2_cyc_shadowed_wd; - logic classb_phase3_cyc_shadowed_re; - logic classb_phase3_cyc_shadowed_we; - logic [31:0] classb_phase3_cyc_shadowed_qs; - logic [31:0] classb_phase3_cyc_shadowed_wd; - logic classb_esc_cnt_re; - logic [31:0] classb_esc_cnt_qs; - logic classb_state_re; - logic [2:0] classb_state_qs; - logic classc_regwen_we; - logic classc_regwen_qs; - logic classc_regwen_wd; - logic classc_ctrl_shadowed_re; - logic classc_ctrl_shadowed_we; - logic classc_ctrl_shadowed_en_qs; - logic classc_ctrl_shadowed_en_wd; - logic classc_ctrl_shadowed_lock_qs; - logic classc_ctrl_shadowed_lock_wd; - logic classc_ctrl_shadowed_en_e0_qs; - logic classc_ctrl_shadowed_en_e0_wd; - logic classc_ctrl_shadowed_en_e1_qs; - logic classc_ctrl_shadowed_en_e1_wd; - logic classc_ctrl_shadowed_en_e2_qs; - logic classc_ctrl_shadowed_en_e2_wd; - logic classc_ctrl_shadowed_en_e3_qs; - logic classc_ctrl_shadowed_en_e3_wd; - logic [1:0] classc_ctrl_shadowed_map_e0_qs; - logic [1:0] classc_ctrl_shadowed_map_e0_wd; - logic [1:0] classc_ctrl_shadowed_map_e1_qs; - logic [1:0] classc_ctrl_shadowed_map_e1_wd; - logic [1:0] classc_ctrl_shadowed_map_e2_qs; - logic [1:0] classc_ctrl_shadowed_map_e2_wd; - logic [1:0] classc_ctrl_shadowed_map_e3_qs; - logic [1:0] classc_ctrl_shadowed_map_e3_wd; - logic classc_clr_regwen_we; - logic classc_clr_regwen_qs; - logic classc_clr_regwen_wd; - logic classc_clr_shadowed_re; - logic classc_clr_shadowed_we; - logic classc_clr_shadowed_qs; - logic classc_clr_shadowed_wd; - logic classc_accum_cnt_re; - logic [15:0] classc_accum_cnt_qs; - logic classc_accum_thresh_shadowed_re; - logic classc_accum_thresh_shadowed_we; - logic [15:0] classc_accum_thresh_shadowed_qs; - logic [15:0] classc_accum_thresh_shadowed_wd; - logic classc_timeout_cyc_shadowed_re; - logic classc_timeout_cyc_shadowed_we; - logic [31:0] classc_timeout_cyc_shadowed_qs; - logic [31:0] classc_timeout_cyc_shadowed_wd; - logic classc_crashdump_trigger_shadowed_re; - logic classc_crashdump_trigger_shadowed_we; - logic [1:0] classc_crashdump_trigger_shadowed_qs; - logic [1:0] classc_crashdump_trigger_shadowed_wd; - logic classc_phase0_cyc_shadowed_re; - logic classc_phase0_cyc_shadowed_we; - logic [31:0] classc_phase0_cyc_shadowed_qs; - logic [31:0] classc_phase0_cyc_shadowed_wd; - logic classc_phase1_cyc_shadowed_re; - logic classc_phase1_cyc_shadowed_we; - logic [31:0] classc_phase1_cyc_shadowed_qs; - logic [31:0] classc_phase1_cyc_shadowed_wd; - logic classc_phase2_cyc_shadowed_re; - logic classc_phase2_cyc_shadowed_we; - logic [31:0] classc_phase2_cyc_shadowed_qs; - logic [31:0] classc_phase2_cyc_shadowed_wd; - logic classc_phase3_cyc_shadowed_re; - logic classc_phase3_cyc_shadowed_we; - logic [31:0] classc_phase3_cyc_shadowed_qs; - logic [31:0] classc_phase3_cyc_shadowed_wd; - logic classc_esc_cnt_re; - logic [31:0] classc_esc_cnt_qs; - logic classc_state_re; - logic [2:0] classc_state_qs; - logic classd_regwen_we; - logic classd_regwen_qs; - logic classd_regwen_wd; - logic classd_ctrl_shadowed_re; - logic classd_ctrl_shadowed_we; - logic classd_ctrl_shadowed_en_qs; - logic classd_ctrl_shadowed_en_wd; - logic classd_ctrl_shadowed_lock_qs; - logic classd_ctrl_shadowed_lock_wd; - logic classd_ctrl_shadowed_en_e0_qs; - logic classd_ctrl_shadowed_en_e0_wd; - logic classd_ctrl_shadowed_en_e1_qs; - logic classd_ctrl_shadowed_en_e1_wd; - logic classd_ctrl_shadowed_en_e2_qs; - logic classd_ctrl_shadowed_en_e2_wd; - logic classd_ctrl_shadowed_en_e3_qs; - logic classd_ctrl_shadowed_en_e3_wd; - logic [1:0] classd_ctrl_shadowed_map_e0_qs; - logic [1:0] classd_ctrl_shadowed_map_e0_wd; - logic [1:0] classd_ctrl_shadowed_map_e1_qs; - logic [1:0] classd_ctrl_shadowed_map_e1_wd; - logic [1:0] classd_ctrl_shadowed_map_e2_qs; - logic [1:0] classd_ctrl_shadowed_map_e2_wd; - logic [1:0] classd_ctrl_shadowed_map_e3_qs; - logic [1:0] classd_ctrl_shadowed_map_e3_wd; - logic classd_clr_regwen_we; - logic classd_clr_regwen_qs; - logic classd_clr_regwen_wd; - logic classd_clr_shadowed_re; - logic classd_clr_shadowed_we; - logic classd_clr_shadowed_qs; - logic classd_clr_shadowed_wd; - logic classd_accum_cnt_re; - logic [15:0] classd_accum_cnt_qs; - logic classd_accum_thresh_shadowed_re; - logic classd_accum_thresh_shadowed_we; - logic [15:0] classd_accum_thresh_shadowed_qs; - logic [15:0] classd_accum_thresh_shadowed_wd; - logic classd_timeout_cyc_shadowed_re; - logic classd_timeout_cyc_shadowed_we; - logic [31:0] classd_timeout_cyc_shadowed_qs; - logic [31:0] classd_timeout_cyc_shadowed_wd; - logic classd_crashdump_trigger_shadowed_re; - logic classd_crashdump_trigger_shadowed_we; - logic [1:0] classd_crashdump_trigger_shadowed_qs; - logic [1:0] classd_crashdump_trigger_shadowed_wd; - logic classd_phase0_cyc_shadowed_re; - logic classd_phase0_cyc_shadowed_we; - logic [31:0] classd_phase0_cyc_shadowed_qs; - logic [31:0] classd_phase0_cyc_shadowed_wd; - logic classd_phase1_cyc_shadowed_re; - logic classd_phase1_cyc_shadowed_we; - logic [31:0] classd_phase1_cyc_shadowed_qs; - logic [31:0] classd_phase1_cyc_shadowed_wd; - logic classd_phase2_cyc_shadowed_re; - logic classd_phase2_cyc_shadowed_we; - logic [31:0] classd_phase2_cyc_shadowed_qs; - logic [31:0] classd_phase2_cyc_shadowed_wd; - logic classd_phase3_cyc_shadowed_re; - logic classd_phase3_cyc_shadowed_we; - logic [31:0] classd_phase3_cyc_shadowed_qs; - logic [31:0] classd_phase3_cyc_shadowed_wd; - logic classd_esc_cnt_re; - logic [31:0] classd_esc_cnt_qs; - logic classd_state_re; - logic [2:0] classd_state_qs; - - // Register instances - // R[intr_state]: V(False) - // F[classa]: 0:0 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_intr_state_classa ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_state_we), - .wd (intr_state_classa_wd), - - // from internal hardware - .de (hw2reg.intr_state.classa.de), - .d (hw2reg.intr_state.classa.d), - - // to internal hardware - .qe (), - .q (reg2hw.intr_state.classa.q), - - // to register interface (read) - .qs (intr_state_classa_qs) - ); - - // F[classb]: 1:1 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_intr_state_classb ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_state_we), - .wd (intr_state_classb_wd), - - // from internal hardware - .de (hw2reg.intr_state.classb.de), - .d (hw2reg.intr_state.classb.d), - - // to internal hardware - .qe (), - .q (reg2hw.intr_state.classb.q), - - // to register interface (read) - .qs (intr_state_classb_qs) - ); - - // F[classc]: 2:2 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_intr_state_classc ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_state_we), - .wd (intr_state_classc_wd), - - // from internal hardware - .de (hw2reg.intr_state.classc.de), - .d (hw2reg.intr_state.classc.d), - - // to internal hardware - .qe (), - .q (reg2hw.intr_state.classc.q), - - // to register interface (read) - .qs (intr_state_classc_qs) - ); - - // F[classd]: 3:3 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_intr_state_classd ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_state_we), - .wd (intr_state_classd_wd), - - // from internal hardware - .de (hw2reg.intr_state.classd.de), - .d (hw2reg.intr_state.classd.d), - - // to internal hardware - .qe (), - .q (reg2hw.intr_state.classd.q), - - // to register interface (read) - .qs (intr_state_classd_qs) - ); - - - // R[intr_enable]: V(False) - // F[classa]: 0:0 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_intr_enable_classa ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_enable_we), - .wd (intr_enable_classa_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.intr_enable.classa.q), - - // to register interface (read) - .qs (intr_enable_classa_qs) - ); - - // F[classb]: 1:1 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_intr_enable_classb ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_enable_we), - .wd (intr_enable_classb_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.intr_enable.classb.q), - - // to register interface (read) - .qs (intr_enable_classb_qs) - ); - - // F[classc]: 2:2 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_intr_enable_classc ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_enable_we), - .wd (intr_enable_classc_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.intr_enable.classc.q), - - // to register interface (read) - .qs (intr_enable_classc_qs) - ); - - // F[classd]: 3:3 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_intr_enable_classd ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (intr_enable_we), - .wd (intr_enable_classd_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.intr_enable.classd.q), - - // to register interface (read) - .qs (intr_enable_classd_qs) - ); - - - // R[intr_test]: V(True) - // F[classa]: 0:0 - prim_subreg_ext #( - .DW (1) - ) u_intr_test_classa ( - .re (1'b0), - .we (intr_test_we), - .wd (intr_test_classa_wd), - .d ('0), - .qre (), - .qe (reg2hw.intr_test.classa.qe), - .q (reg2hw.intr_test.classa.q), - .qs () - ); - - // F[classb]: 1:1 - prim_subreg_ext #( - .DW (1) - ) u_intr_test_classb ( - .re (1'b0), - .we (intr_test_we), - .wd (intr_test_classb_wd), - .d ('0), - .qre (), - .qe (reg2hw.intr_test.classb.qe), - .q (reg2hw.intr_test.classb.q), - .qs () - ); - - // F[classc]: 2:2 - prim_subreg_ext #( - .DW (1) - ) u_intr_test_classc ( - .re (1'b0), - .we (intr_test_we), - .wd (intr_test_classc_wd), - .d ('0), - .qre (), - .qe (reg2hw.intr_test.classc.qe), - .q (reg2hw.intr_test.classc.q), - .qs () - ); - - // F[classd]: 3:3 - prim_subreg_ext #( - .DW (1) - ) u_intr_test_classd ( - .re (1'b0), - .we (intr_test_we), - .wd (intr_test_classd_wd), - .d ('0), - .qre (), - .qe (reg2hw.intr_test.classd.qe), - .q (reg2hw.intr_test.classd.q), - .qs () - ); - - - // R[ping_timer_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_ping_timer_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (ping_timer_regwen_we), - .wd (ping_timer_regwen_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (ping_timer_regwen_qs) - ); - - - // R[ping_timeout_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (16), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (16'h100) - ) u_ping_timeout_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (ping_timeout_cyc_shadowed_re), - .we (ping_timeout_cyc_shadowed_we & ping_timer_regwen_qs), - .wd (ping_timeout_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.ping_timeout_cyc_shadowed.q), - - // to register interface (read) - .qs (ping_timeout_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.ping_timeout_cyc_shadowed.err_update), - .err_storage (reg2hw.ping_timeout_cyc_shadowed.err_storage) - ); - - - // R[ping_timer_en_shadowed]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1S), - .RESVAL (1'h0) - ) u_ping_timer_en_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (ping_timer_en_shadowed_re), - .we (ping_timer_en_shadowed_we & ping_timer_regwen_qs), - .wd (ping_timer_en_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.ping_timer_en_shadowed.q), - - // to register interface (read) - .qs (ping_timer_en_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.ping_timer_en_shadowed.err_update), - .err_storage (reg2hw.ping_timer_en_shadowed.err_storage) - ); - - - // Subregister 0 of Multireg alert_regwen - // R[alert_regwen_0]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_alert_regwen_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_regwen_0_we), - .wd (alert_regwen_0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_regwen[0].q), - - // to register interface (read) - .qs (alert_regwen_0_qs) - ); - - - // Subregister 1 of Multireg alert_regwen - // R[alert_regwen_1]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_alert_regwen_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_regwen_1_we), - .wd (alert_regwen_1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_regwen[1].q), - - // to register interface (read) - .qs (alert_regwen_1_qs) - ); - - - // Subregister 2 of Multireg alert_regwen - // R[alert_regwen_2]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_alert_regwen_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_regwen_2_we), - .wd (alert_regwen_2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_regwen[2].q), - - // to register interface (read) - .qs (alert_regwen_2_qs) - ); - - - // Subregister 3 of Multireg alert_regwen - // R[alert_regwen_3]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_alert_regwen_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_regwen_3_we), - .wd (alert_regwen_3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_regwen[3].q), - - // to register interface (read) - .qs (alert_regwen_3_qs) - ); - - - // Subregister 0 of Multireg alert_en_shadowed - // R[alert_en_shadowed_0]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_alert_en_shadowed_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_en_shadowed_0_re), - .we (alert_en_shadowed_0_we & alert_regwen_0_qs), - .wd (alert_en_shadowed_0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_en_shadowed[0].q), - - // to register interface (read) - .qs (alert_en_shadowed_0_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_en_shadowed[0].err_update), - .err_storage (reg2hw.alert_en_shadowed[0].err_storage) - ); - - - // Subregister 1 of Multireg alert_en_shadowed - // R[alert_en_shadowed_1]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_alert_en_shadowed_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_en_shadowed_1_re), - .we (alert_en_shadowed_1_we & alert_regwen_1_qs), - .wd (alert_en_shadowed_1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_en_shadowed[1].q), - - // to register interface (read) - .qs (alert_en_shadowed_1_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_en_shadowed[1].err_update), - .err_storage (reg2hw.alert_en_shadowed[1].err_storage) - ); - - - // Subregister 2 of Multireg alert_en_shadowed - // R[alert_en_shadowed_2]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_alert_en_shadowed_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_en_shadowed_2_re), - .we (alert_en_shadowed_2_we & alert_regwen_2_qs), - .wd (alert_en_shadowed_2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_en_shadowed[2].q), - - // to register interface (read) - .qs (alert_en_shadowed_2_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_en_shadowed[2].err_update), - .err_storage (reg2hw.alert_en_shadowed[2].err_storage) - ); - - - // Subregister 3 of Multireg alert_en_shadowed - // R[alert_en_shadowed_3]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_alert_en_shadowed_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_en_shadowed_3_re), - .we (alert_en_shadowed_3_we & alert_regwen_3_qs), - .wd (alert_en_shadowed_3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_en_shadowed[3].q), - - // to register interface (read) - .qs (alert_en_shadowed_3_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_en_shadowed[3].err_update), - .err_storage (reg2hw.alert_en_shadowed[3].err_storage) - ); - - - // Subregister 0 of Multireg alert_class_shadowed - // R[alert_class_shadowed_0]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_alert_class_shadowed_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_class_shadowed_0_re), - .we (alert_class_shadowed_0_we & alert_regwen_0_qs), - .wd (alert_class_shadowed_0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_class_shadowed[0].q), - - // to register interface (read) - .qs (alert_class_shadowed_0_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_class_shadowed[0].err_update), - .err_storage (reg2hw.alert_class_shadowed[0].err_storage) - ); - - - // Subregister 1 of Multireg alert_class_shadowed - // R[alert_class_shadowed_1]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_alert_class_shadowed_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_class_shadowed_1_re), - .we (alert_class_shadowed_1_we & alert_regwen_1_qs), - .wd (alert_class_shadowed_1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_class_shadowed[1].q), - - // to register interface (read) - .qs (alert_class_shadowed_1_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_class_shadowed[1].err_update), - .err_storage (reg2hw.alert_class_shadowed[1].err_storage) - ); - - - // Subregister 2 of Multireg alert_class_shadowed - // R[alert_class_shadowed_2]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_alert_class_shadowed_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_class_shadowed_2_re), - .we (alert_class_shadowed_2_we & alert_regwen_2_qs), - .wd (alert_class_shadowed_2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_class_shadowed[2].q), - - // to register interface (read) - .qs (alert_class_shadowed_2_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_class_shadowed[2].err_update), - .err_storage (reg2hw.alert_class_shadowed[2].err_storage) - ); - - - // Subregister 3 of Multireg alert_class_shadowed - // R[alert_class_shadowed_3]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_alert_class_shadowed_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (alert_class_shadowed_3_re), - .we (alert_class_shadowed_3_we & alert_regwen_3_qs), - .wd (alert_class_shadowed_3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.alert_class_shadowed[3].q), - - // to register interface (read) - .qs (alert_class_shadowed_3_qs), - - // Shadow register error conditions - .err_update (reg2hw.alert_class_shadowed[3].err_update), - .err_storage (reg2hw.alert_class_shadowed[3].err_storage) - ); - - - // Subregister 0 of Multireg alert_cause - // R[alert_cause_0]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_alert_cause_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_cause_0_we), - .wd (alert_cause_0_wd), - - // from internal hardware - .de (hw2reg.alert_cause[0].de), - .d (hw2reg.alert_cause[0].d), - - // to internal hardware - .qe (), - .q (reg2hw.alert_cause[0].q), - - // to register interface (read) - .qs (alert_cause_0_qs) - ); - - - // Subregister 1 of Multireg alert_cause - // R[alert_cause_1]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_alert_cause_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_cause_1_we), - .wd (alert_cause_1_wd), - - // from internal hardware - .de (hw2reg.alert_cause[1].de), - .d (hw2reg.alert_cause[1].d), - - // to internal hardware - .qe (), - .q (reg2hw.alert_cause[1].q), - - // to register interface (read) - .qs (alert_cause_1_qs) - ); - - - // Subregister 2 of Multireg alert_cause - // R[alert_cause_2]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_alert_cause_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_cause_2_we), - .wd (alert_cause_2_wd), - - // from internal hardware - .de (hw2reg.alert_cause[2].de), - .d (hw2reg.alert_cause[2].d), - - // to internal hardware - .qe (), - .q (reg2hw.alert_cause[2].q), - - // to register interface (read) - .qs (alert_cause_2_qs) - ); - - - // Subregister 3 of Multireg alert_cause - // R[alert_cause_3]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_alert_cause_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (alert_cause_3_we), - .wd (alert_cause_3_wd), - - // from internal hardware - .de (hw2reg.alert_cause[3].de), - .d (hw2reg.alert_cause[3].d), - - // to internal hardware - .qe (), - .q (reg2hw.alert_cause[3].q), - - // to register interface (read) - .qs (alert_cause_3_qs) - ); - - - // Subregister 0 of Multireg loc_alert_regwen - // R[loc_alert_regwen_0]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_0_we), - .wd (loc_alert_regwen_0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_0_qs) - ); - - - // Subregister 1 of Multireg loc_alert_regwen - // R[loc_alert_regwen_1]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_1_we), - .wd (loc_alert_regwen_1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_1_qs) - ); - - - // Subregister 2 of Multireg loc_alert_regwen - // R[loc_alert_regwen_2]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_2_we), - .wd (loc_alert_regwen_2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_2_qs) - ); - - - // Subregister 3 of Multireg loc_alert_regwen - // R[loc_alert_regwen_3]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_3_we), - .wd (loc_alert_regwen_3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_3_qs) - ); - - - // Subregister 4 of Multireg loc_alert_regwen - // R[loc_alert_regwen_4]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_4 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_4_we), - .wd (loc_alert_regwen_4_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_4_qs) - ); - - - // Subregister 5 of Multireg loc_alert_regwen - // R[loc_alert_regwen_5]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_5 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_5_we), - .wd (loc_alert_regwen_5_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_5_qs) - ); - - - // Subregister 6 of Multireg loc_alert_regwen - // R[loc_alert_regwen_6]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_loc_alert_regwen_6 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_regwen_6_we), - .wd (loc_alert_regwen_6_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (loc_alert_regwen_6_qs) - ); - - - // Subregister 0 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_0]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_0_re), - .we (loc_alert_en_shadowed_0_we & loc_alert_regwen_0_qs), - .wd (loc_alert_en_shadowed_0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[0].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_0_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[0].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[0].err_storage) - ); - - - // Subregister 1 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_1]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_1_re), - .we (loc_alert_en_shadowed_1_we & loc_alert_regwen_1_qs), - .wd (loc_alert_en_shadowed_1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[1].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_1_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[1].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[1].err_storage) - ); - - - // Subregister 2 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_2]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_2_re), - .we (loc_alert_en_shadowed_2_we & loc_alert_regwen_2_qs), - .wd (loc_alert_en_shadowed_2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[2].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_2_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[2].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[2].err_storage) - ); - - - // Subregister 3 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_3]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_3_re), - .we (loc_alert_en_shadowed_3_we & loc_alert_regwen_3_qs), - .wd (loc_alert_en_shadowed_3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[3].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_3_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[3].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[3].err_storage) - ); - - - // Subregister 4 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_4]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_4 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_4_re), - .we (loc_alert_en_shadowed_4_we & loc_alert_regwen_4_qs), - .wd (loc_alert_en_shadowed_4_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[4].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_4_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[4].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[4].err_storage) - ); - - - // Subregister 5 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_5]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_5 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_5_re), - .we (loc_alert_en_shadowed_5_we & loc_alert_regwen_5_qs), - .wd (loc_alert_en_shadowed_5_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[5].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_5_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[5].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[5].err_storage) - ); - - - // Subregister 6 of Multireg loc_alert_en_shadowed - // R[loc_alert_en_shadowed_6]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_loc_alert_en_shadowed_6 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_en_shadowed_6_re), - .we (loc_alert_en_shadowed_6_we & loc_alert_regwen_6_qs), - .wd (loc_alert_en_shadowed_6_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_en_shadowed[6].q), - - // to register interface (read) - .qs (loc_alert_en_shadowed_6_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_en_shadowed[6].err_update), - .err_storage (reg2hw.loc_alert_en_shadowed[6].err_storage) - ); - - - // Subregister 0 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_0]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_0_re), - .we (loc_alert_class_shadowed_0_we & loc_alert_regwen_0_qs), - .wd (loc_alert_class_shadowed_0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[0].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_0_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[0].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[0].err_storage) - ); - - - // Subregister 1 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_1]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_1_re), - .we (loc_alert_class_shadowed_1_we & loc_alert_regwen_1_qs), - .wd (loc_alert_class_shadowed_1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[1].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_1_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[1].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[1].err_storage) - ); - - - // Subregister 2 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_2]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_2_re), - .we (loc_alert_class_shadowed_2_we & loc_alert_regwen_2_qs), - .wd (loc_alert_class_shadowed_2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[2].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_2_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[2].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[2].err_storage) - ); - - - // Subregister 3 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_3]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_3_re), - .we (loc_alert_class_shadowed_3_we & loc_alert_regwen_3_qs), - .wd (loc_alert_class_shadowed_3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[3].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_3_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[3].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[3].err_storage) - ); - - - // Subregister 4 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_4]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_4 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_4_re), - .we (loc_alert_class_shadowed_4_we & loc_alert_regwen_4_qs), - .wd (loc_alert_class_shadowed_4_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[4].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_4_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[4].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[4].err_storage) - ); - - - // Subregister 5 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_5]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_5 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_5_re), - .we (loc_alert_class_shadowed_5_we & loc_alert_regwen_5_qs), - .wd (loc_alert_class_shadowed_5_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[5].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_5_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[5].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[5].err_storage) - ); - - - // Subregister 6 of Multireg loc_alert_class_shadowed - // R[loc_alert_class_shadowed_6]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_loc_alert_class_shadowed_6 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (loc_alert_class_shadowed_6_re), - .we (loc_alert_class_shadowed_6_we & loc_alert_regwen_6_qs), - .wd (loc_alert_class_shadowed_6_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_class_shadowed[6].q), - - // to register interface (read) - .qs (loc_alert_class_shadowed_6_qs), - - // Shadow register error conditions - .err_update (reg2hw.loc_alert_class_shadowed[6].err_update), - .err_storage (reg2hw.loc_alert_class_shadowed[6].err_storage) - ); - - - // Subregister 0 of Multireg loc_alert_cause - // R[loc_alert_cause_0]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_0_we), - .wd (loc_alert_cause_0_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[0].de), - .d (hw2reg.loc_alert_cause[0].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[0].q), - - // to register interface (read) - .qs (loc_alert_cause_0_qs) - ); - - - // Subregister 1 of Multireg loc_alert_cause - // R[loc_alert_cause_1]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_1_we), - .wd (loc_alert_cause_1_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[1].de), - .d (hw2reg.loc_alert_cause[1].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[1].q), - - // to register interface (read) - .qs (loc_alert_cause_1_qs) - ); - - - // Subregister 2 of Multireg loc_alert_cause - // R[loc_alert_cause_2]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_2_we), - .wd (loc_alert_cause_2_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[2].de), - .d (hw2reg.loc_alert_cause[2].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[2].q), - - // to register interface (read) - .qs (loc_alert_cause_2_qs) - ); - - - // Subregister 3 of Multireg loc_alert_cause - // R[loc_alert_cause_3]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_3_we), - .wd (loc_alert_cause_3_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[3].de), - .d (hw2reg.loc_alert_cause[3].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[3].q), - - // to register interface (read) - .qs (loc_alert_cause_3_qs) - ); - - - // Subregister 4 of Multireg loc_alert_cause - // R[loc_alert_cause_4]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_4 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_4_we), - .wd (loc_alert_cause_4_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[4].de), - .d (hw2reg.loc_alert_cause[4].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[4].q), - - // to register interface (read) - .qs (loc_alert_cause_4_qs) - ); - - - // Subregister 5 of Multireg loc_alert_cause - // R[loc_alert_cause_5]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_5 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_5_we), - .wd (loc_alert_cause_5_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[5].de), - .d (hw2reg.loc_alert_cause[5].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[5].q), - - // to register interface (read) - .qs (loc_alert_cause_5_qs) - ); - - - // Subregister 6 of Multireg loc_alert_cause - // R[loc_alert_cause_6]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW1C), - .RESVAL (1'h0) - ) u_loc_alert_cause_6 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (loc_alert_cause_6_we), - .wd (loc_alert_cause_6_wd), - - // from internal hardware - .de (hw2reg.loc_alert_cause[6].de), - .d (hw2reg.loc_alert_cause[6].d), - - // to internal hardware - .qe (), - .q (reg2hw.loc_alert_cause[6].q), - - // to register interface (read) - .qs (loc_alert_cause_6_qs) - ); - - - // R[classa_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classa_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classa_regwen_we), - .wd (classa_regwen_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classa_regwen_qs) - ); - - - // R[classa_ctrl_shadowed]: V(False) - // F[en]: 0:0 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classa_ctrl_shadowed_en ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_en_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.en.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_en_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.en.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.en.err_storage) - ); - - // F[lock]: 1:1 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classa_ctrl_shadowed_lock ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_lock_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.lock.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_lock_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.lock.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.lock.err_storage) - ); - - // F[en_e0]: 2:2 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classa_ctrl_shadowed_en_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_en_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.en_e0.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_en_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.en_e0.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.en_e0.err_storage) - ); - - // F[en_e1]: 3:3 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classa_ctrl_shadowed_en_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_en_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.en_e1.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_en_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.en_e1.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.en_e1.err_storage) - ); - - // F[en_e2]: 4:4 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classa_ctrl_shadowed_en_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_en_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.en_e2.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_en_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.en_e2.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.en_e2.err_storage) - ); - - // F[en_e3]: 5:5 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classa_ctrl_shadowed_en_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_en_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.en_e3.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_en_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.en_e3.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.en_e3.err_storage) - ); - - // F[map_e0]: 7:6 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classa_ctrl_shadowed_map_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_map_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.map_e0.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_map_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.map_e0.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.map_e0.err_storage) - ); - - // F[map_e1]: 9:8 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h1) - ) u_classa_ctrl_shadowed_map_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_map_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.map_e1.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_map_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.map_e1.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.map_e1.err_storage) - ); - - // F[map_e2]: 11:10 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h2) - ) u_classa_ctrl_shadowed_map_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_map_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.map_e2.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_map_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.map_e2.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.map_e2.err_storage) - ); - - // F[map_e3]: 13:12 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h3) - ) u_classa_ctrl_shadowed_map_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_ctrl_shadowed_re), - .we (classa_ctrl_shadowed_we & classa_regwen_qs), - .wd (classa_ctrl_shadowed_map_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_ctrl_shadowed.map_e3.q), - - // to register interface (read) - .qs (classa_ctrl_shadowed_map_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_ctrl_shadowed.map_e3.err_update), - .err_storage (reg2hw.classa_ctrl_shadowed.map_e3.err_storage) - ); - - - // R[classa_clr_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classa_clr_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classa_clr_regwen_we), - .wd (classa_clr_regwen_wd), - - // from internal hardware - .de (hw2reg.classa_clr_regwen.de), - .d (hw2reg.classa_clr_regwen.d), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classa_clr_regwen_qs) - ); - - - // R[classa_clr_shadowed]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classa_clr_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_clr_shadowed_re), - .we (classa_clr_shadowed_we & classa_clr_regwen_qs), - .wd (classa_clr_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (reg2hw.classa_clr_shadowed.qe), - .q (reg2hw.classa_clr_shadowed.q), - - // to register interface (read) - .qs (classa_clr_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_clr_shadowed.err_update), - .err_storage (reg2hw.classa_clr_shadowed.err_storage) - ); - - - // R[classa_accum_cnt]: V(True) - prim_subreg_ext #( - .DW (16) - ) u_classa_accum_cnt ( - .re (classa_accum_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classa_accum_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classa_accum_cnt_qs) - ); - - - // R[classa_accum_thresh_shadowed]: V(False) - prim_subreg_shadow #( - .DW (16), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (16'h0) - ) u_classa_accum_thresh_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_accum_thresh_shadowed_re), - .we (classa_accum_thresh_shadowed_we & classa_regwen_qs), - .wd (classa_accum_thresh_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_accum_thresh_shadowed.q), - - // to register interface (read) - .qs (classa_accum_thresh_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_accum_thresh_shadowed.err_update), - .err_storage (reg2hw.classa_accum_thresh_shadowed.err_storage) - ); - - - // R[classa_timeout_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classa_timeout_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_timeout_cyc_shadowed_re), - .we (classa_timeout_cyc_shadowed_we & classa_regwen_qs), - .wd (classa_timeout_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_timeout_cyc_shadowed.q), - - // to register interface (read) - .qs (classa_timeout_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_timeout_cyc_shadowed.err_update), - .err_storage (reg2hw.classa_timeout_cyc_shadowed.err_storage) - ); - - - // R[classa_crashdump_trigger_shadowed]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classa_crashdump_trigger_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_crashdump_trigger_shadowed_re), - .we (classa_crashdump_trigger_shadowed_we & classa_regwen_qs), - .wd (classa_crashdump_trigger_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_crashdump_trigger_shadowed.q), - - // to register interface (read) - .qs (classa_crashdump_trigger_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_crashdump_trigger_shadowed.err_update), - .err_storage (reg2hw.classa_crashdump_trigger_shadowed.err_storage) - ); - - - // R[classa_phase0_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classa_phase0_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_phase0_cyc_shadowed_re), - .we (classa_phase0_cyc_shadowed_we & classa_regwen_qs), - .wd (classa_phase0_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_phase0_cyc_shadowed.q), - - // to register interface (read) - .qs (classa_phase0_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_phase0_cyc_shadowed.err_update), - .err_storage (reg2hw.classa_phase0_cyc_shadowed.err_storage) - ); - - - // R[classa_phase1_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classa_phase1_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_phase1_cyc_shadowed_re), - .we (classa_phase1_cyc_shadowed_we & classa_regwen_qs), - .wd (classa_phase1_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_phase1_cyc_shadowed.q), - - // to register interface (read) - .qs (classa_phase1_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_phase1_cyc_shadowed.err_update), - .err_storage (reg2hw.classa_phase1_cyc_shadowed.err_storage) - ); - - - // R[classa_phase2_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classa_phase2_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_phase2_cyc_shadowed_re), - .we (classa_phase2_cyc_shadowed_we & classa_regwen_qs), - .wd (classa_phase2_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_phase2_cyc_shadowed.q), - - // to register interface (read) - .qs (classa_phase2_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_phase2_cyc_shadowed.err_update), - .err_storage (reg2hw.classa_phase2_cyc_shadowed.err_storage) - ); - - - // R[classa_phase3_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classa_phase3_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classa_phase3_cyc_shadowed_re), - .we (classa_phase3_cyc_shadowed_we & classa_regwen_qs), - .wd (classa_phase3_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classa_phase3_cyc_shadowed.q), - - // to register interface (read) - .qs (classa_phase3_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classa_phase3_cyc_shadowed.err_update), - .err_storage (reg2hw.classa_phase3_cyc_shadowed.err_storage) - ); - - - // R[classa_esc_cnt]: V(True) - prim_subreg_ext #( - .DW (32) - ) u_classa_esc_cnt ( - .re (classa_esc_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classa_esc_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classa_esc_cnt_qs) - ); - - - // R[classa_state]: V(True) - prim_subreg_ext #( - .DW (3) - ) u_classa_state ( - .re (classa_state_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classa_state.d), - .qre (), - .qe (), - .q (), - .qs (classa_state_qs) - ); - - - // R[classb_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classb_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classb_regwen_we), - .wd (classb_regwen_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classb_regwen_qs) - ); - - - // R[classb_ctrl_shadowed]: V(False) - // F[en]: 0:0 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classb_ctrl_shadowed_en ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_en_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.en.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_en_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.en.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.en.err_storage) - ); - - // F[lock]: 1:1 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classb_ctrl_shadowed_lock ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_lock_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.lock.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_lock_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.lock.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.lock.err_storage) - ); - - // F[en_e0]: 2:2 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classb_ctrl_shadowed_en_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_en_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.en_e0.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_en_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.en_e0.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.en_e0.err_storage) - ); - - // F[en_e1]: 3:3 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classb_ctrl_shadowed_en_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_en_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.en_e1.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_en_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.en_e1.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.en_e1.err_storage) - ); - - // F[en_e2]: 4:4 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classb_ctrl_shadowed_en_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_en_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.en_e2.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_en_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.en_e2.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.en_e2.err_storage) - ); - - // F[en_e3]: 5:5 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classb_ctrl_shadowed_en_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_en_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.en_e3.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_en_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.en_e3.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.en_e3.err_storage) - ); - - // F[map_e0]: 7:6 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classb_ctrl_shadowed_map_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_map_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.map_e0.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_map_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.map_e0.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.map_e0.err_storage) - ); - - // F[map_e1]: 9:8 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h1) - ) u_classb_ctrl_shadowed_map_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_map_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.map_e1.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_map_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.map_e1.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.map_e1.err_storage) - ); - - // F[map_e2]: 11:10 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h2) - ) u_classb_ctrl_shadowed_map_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_map_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.map_e2.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_map_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.map_e2.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.map_e2.err_storage) - ); - - // F[map_e3]: 13:12 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h3) - ) u_classb_ctrl_shadowed_map_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_ctrl_shadowed_re), - .we (classb_ctrl_shadowed_we & classb_regwen_qs), - .wd (classb_ctrl_shadowed_map_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_ctrl_shadowed.map_e3.q), - - // to register interface (read) - .qs (classb_ctrl_shadowed_map_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_ctrl_shadowed.map_e3.err_update), - .err_storage (reg2hw.classb_ctrl_shadowed.map_e3.err_storage) - ); - - - // R[classb_clr_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classb_clr_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classb_clr_regwen_we), - .wd (classb_clr_regwen_wd), - - // from internal hardware - .de (hw2reg.classb_clr_regwen.de), - .d (hw2reg.classb_clr_regwen.d), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classb_clr_regwen_qs) - ); - - - // R[classb_clr_shadowed]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classb_clr_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_clr_shadowed_re), - .we (classb_clr_shadowed_we & classb_clr_regwen_qs), - .wd (classb_clr_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (reg2hw.classb_clr_shadowed.qe), - .q (reg2hw.classb_clr_shadowed.q), - - // to register interface (read) - .qs (classb_clr_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_clr_shadowed.err_update), - .err_storage (reg2hw.classb_clr_shadowed.err_storage) - ); - - - // R[classb_accum_cnt]: V(True) - prim_subreg_ext #( - .DW (16) - ) u_classb_accum_cnt ( - .re (classb_accum_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classb_accum_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classb_accum_cnt_qs) - ); - - - // R[classb_accum_thresh_shadowed]: V(False) - prim_subreg_shadow #( - .DW (16), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (16'h0) - ) u_classb_accum_thresh_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_accum_thresh_shadowed_re), - .we (classb_accum_thresh_shadowed_we & classb_regwen_qs), - .wd (classb_accum_thresh_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_accum_thresh_shadowed.q), - - // to register interface (read) - .qs (classb_accum_thresh_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_accum_thresh_shadowed.err_update), - .err_storage (reg2hw.classb_accum_thresh_shadowed.err_storage) - ); - - - // R[classb_timeout_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classb_timeout_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_timeout_cyc_shadowed_re), - .we (classb_timeout_cyc_shadowed_we & classb_regwen_qs), - .wd (classb_timeout_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_timeout_cyc_shadowed.q), - - // to register interface (read) - .qs (classb_timeout_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_timeout_cyc_shadowed.err_update), - .err_storage (reg2hw.classb_timeout_cyc_shadowed.err_storage) - ); - - - // R[classb_crashdump_trigger_shadowed]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classb_crashdump_trigger_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_crashdump_trigger_shadowed_re), - .we (classb_crashdump_trigger_shadowed_we & classb_regwen_qs), - .wd (classb_crashdump_trigger_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_crashdump_trigger_shadowed.q), - - // to register interface (read) - .qs (classb_crashdump_trigger_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_crashdump_trigger_shadowed.err_update), - .err_storage (reg2hw.classb_crashdump_trigger_shadowed.err_storage) - ); - - - // R[classb_phase0_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classb_phase0_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_phase0_cyc_shadowed_re), - .we (classb_phase0_cyc_shadowed_we & classb_regwen_qs), - .wd (classb_phase0_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_phase0_cyc_shadowed.q), - - // to register interface (read) - .qs (classb_phase0_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_phase0_cyc_shadowed.err_update), - .err_storage (reg2hw.classb_phase0_cyc_shadowed.err_storage) - ); - - - // R[classb_phase1_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classb_phase1_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_phase1_cyc_shadowed_re), - .we (classb_phase1_cyc_shadowed_we & classb_regwen_qs), - .wd (classb_phase1_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_phase1_cyc_shadowed.q), - - // to register interface (read) - .qs (classb_phase1_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_phase1_cyc_shadowed.err_update), - .err_storage (reg2hw.classb_phase1_cyc_shadowed.err_storage) - ); - - - // R[classb_phase2_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classb_phase2_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_phase2_cyc_shadowed_re), - .we (classb_phase2_cyc_shadowed_we & classb_regwen_qs), - .wd (classb_phase2_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_phase2_cyc_shadowed.q), - - // to register interface (read) - .qs (classb_phase2_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_phase2_cyc_shadowed.err_update), - .err_storage (reg2hw.classb_phase2_cyc_shadowed.err_storage) - ); - - - // R[classb_phase3_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classb_phase3_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classb_phase3_cyc_shadowed_re), - .we (classb_phase3_cyc_shadowed_we & classb_regwen_qs), - .wd (classb_phase3_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classb_phase3_cyc_shadowed.q), - - // to register interface (read) - .qs (classb_phase3_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classb_phase3_cyc_shadowed.err_update), - .err_storage (reg2hw.classb_phase3_cyc_shadowed.err_storage) - ); - - - // R[classb_esc_cnt]: V(True) - prim_subreg_ext #( - .DW (32) - ) u_classb_esc_cnt ( - .re (classb_esc_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classb_esc_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classb_esc_cnt_qs) - ); - - - // R[classb_state]: V(True) - prim_subreg_ext #( - .DW (3) - ) u_classb_state ( - .re (classb_state_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classb_state.d), - .qre (), - .qe (), - .q (), - .qs (classb_state_qs) - ); - - - // R[classc_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classc_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classc_regwen_we), - .wd (classc_regwen_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classc_regwen_qs) - ); - - - // R[classc_ctrl_shadowed]: V(False) - // F[en]: 0:0 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classc_ctrl_shadowed_en ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_en_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.en.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_en_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.en.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.en.err_storage) - ); - - // F[lock]: 1:1 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classc_ctrl_shadowed_lock ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_lock_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.lock.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_lock_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.lock.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.lock.err_storage) - ); - - // F[en_e0]: 2:2 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classc_ctrl_shadowed_en_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_en_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.en_e0.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_en_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.en_e0.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.en_e0.err_storage) - ); - - // F[en_e1]: 3:3 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classc_ctrl_shadowed_en_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_en_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.en_e1.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_en_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.en_e1.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.en_e1.err_storage) - ); - - // F[en_e2]: 4:4 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classc_ctrl_shadowed_en_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_en_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.en_e2.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_en_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.en_e2.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.en_e2.err_storage) - ); - - // F[en_e3]: 5:5 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classc_ctrl_shadowed_en_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_en_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.en_e3.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_en_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.en_e3.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.en_e3.err_storage) - ); - - // F[map_e0]: 7:6 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classc_ctrl_shadowed_map_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_map_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.map_e0.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_map_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.map_e0.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.map_e0.err_storage) - ); - - // F[map_e1]: 9:8 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h1) - ) u_classc_ctrl_shadowed_map_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_map_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.map_e1.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_map_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.map_e1.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.map_e1.err_storage) - ); - - // F[map_e2]: 11:10 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h2) - ) u_classc_ctrl_shadowed_map_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_map_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.map_e2.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_map_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.map_e2.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.map_e2.err_storage) - ); - - // F[map_e3]: 13:12 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h3) - ) u_classc_ctrl_shadowed_map_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_ctrl_shadowed_re), - .we (classc_ctrl_shadowed_we & classc_regwen_qs), - .wd (classc_ctrl_shadowed_map_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_ctrl_shadowed.map_e3.q), - - // to register interface (read) - .qs (classc_ctrl_shadowed_map_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_ctrl_shadowed.map_e3.err_update), - .err_storage (reg2hw.classc_ctrl_shadowed.map_e3.err_storage) - ); - - - // R[classc_clr_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classc_clr_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classc_clr_regwen_we), - .wd (classc_clr_regwen_wd), - - // from internal hardware - .de (hw2reg.classc_clr_regwen.de), - .d (hw2reg.classc_clr_regwen.d), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classc_clr_regwen_qs) - ); - - - // R[classc_clr_shadowed]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classc_clr_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_clr_shadowed_re), - .we (classc_clr_shadowed_we & classc_clr_regwen_qs), - .wd (classc_clr_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (reg2hw.classc_clr_shadowed.qe), - .q (reg2hw.classc_clr_shadowed.q), - - // to register interface (read) - .qs (classc_clr_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_clr_shadowed.err_update), - .err_storage (reg2hw.classc_clr_shadowed.err_storage) - ); - - - // R[classc_accum_cnt]: V(True) - prim_subreg_ext #( - .DW (16) - ) u_classc_accum_cnt ( - .re (classc_accum_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classc_accum_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classc_accum_cnt_qs) - ); - - - // R[classc_accum_thresh_shadowed]: V(False) - prim_subreg_shadow #( - .DW (16), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (16'h0) - ) u_classc_accum_thresh_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_accum_thresh_shadowed_re), - .we (classc_accum_thresh_shadowed_we & classc_regwen_qs), - .wd (classc_accum_thresh_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_accum_thresh_shadowed.q), - - // to register interface (read) - .qs (classc_accum_thresh_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_accum_thresh_shadowed.err_update), - .err_storage (reg2hw.classc_accum_thresh_shadowed.err_storage) - ); - - - // R[classc_timeout_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classc_timeout_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_timeout_cyc_shadowed_re), - .we (classc_timeout_cyc_shadowed_we & classc_regwen_qs), - .wd (classc_timeout_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_timeout_cyc_shadowed.q), - - // to register interface (read) - .qs (classc_timeout_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_timeout_cyc_shadowed.err_update), - .err_storage (reg2hw.classc_timeout_cyc_shadowed.err_storage) - ); - - - // R[classc_crashdump_trigger_shadowed]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classc_crashdump_trigger_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_crashdump_trigger_shadowed_re), - .we (classc_crashdump_trigger_shadowed_we & classc_regwen_qs), - .wd (classc_crashdump_trigger_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_crashdump_trigger_shadowed.q), - - // to register interface (read) - .qs (classc_crashdump_trigger_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_crashdump_trigger_shadowed.err_update), - .err_storage (reg2hw.classc_crashdump_trigger_shadowed.err_storage) - ); - - - // R[classc_phase0_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classc_phase0_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_phase0_cyc_shadowed_re), - .we (classc_phase0_cyc_shadowed_we & classc_regwen_qs), - .wd (classc_phase0_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_phase0_cyc_shadowed.q), - - // to register interface (read) - .qs (classc_phase0_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_phase0_cyc_shadowed.err_update), - .err_storage (reg2hw.classc_phase0_cyc_shadowed.err_storage) - ); - - - // R[classc_phase1_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classc_phase1_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_phase1_cyc_shadowed_re), - .we (classc_phase1_cyc_shadowed_we & classc_regwen_qs), - .wd (classc_phase1_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_phase1_cyc_shadowed.q), - - // to register interface (read) - .qs (classc_phase1_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_phase1_cyc_shadowed.err_update), - .err_storage (reg2hw.classc_phase1_cyc_shadowed.err_storage) - ); - - - // R[classc_phase2_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classc_phase2_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_phase2_cyc_shadowed_re), - .we (classc_phase2_cyc_shadowed_we & classc_regwen_qs), - .wd (classc_phase2_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_phase2_cyc_shadowed.q), - - // to register interface (read) - .qs (classc_phase2_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_phase2_cyc_shadowed.err_update), - .err_storage (reg2hw.classc_phase2_cyc_shadowed.err_storage) - ); - - - // R[classc_phase3_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classc_phase3_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classc_phase3_cyc_shadowed_re), - .we (classc_phase3_cyc_shadowed_we & classc_regwen_qs), - .wd (classc_phase3_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classc_phase3_cyc_shadowed.q), - - // to register interface (read) - .qs (classc_phase3_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classc_phase3_cyc_shadowed.err_update), - .err_storage (reg2hw.classc_phase3_cyc_shadowed.err_storage) - ); - - - // R[classc_esc_cnt]: V(True) - prim_subreg_ext #( - .DW (32) - ) u_classc_esc_cnt ( - .re (classc_esc_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classc_esc_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classc_esc_cnt_qs) - ); - - - // R[classc_state]: V(True) - prim_subreg_ext #( - .DW (3) - ) u_classc_state ( - .re (classc_state_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classc_state.d), - .qre (), - .qe (), - .q (), - .qs (classc_state_qs) - ); - - - // R[classd_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classd_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classd_regwen_we), - .wd (classd_regwen_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classd_regwen_qs) - ); - - - // R[classd_ctrl_shadowed]: V(False) - // F[en]: 0:0 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classd_ctrl_shadowed_en ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_en_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.en.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_en_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.en.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.en.err_storage) - ); - - // F[lock]: 1:1 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classd_ctrl_shadowed_lock ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_lock_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.lock.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_lock_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.lock.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.lock.err_storage) - ); - - // F[en_e0]: 2:2 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classd_ctrl_shadowed_en_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_en_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.en_e0.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_en_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.en_e0.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.en_e0.err_storage) - ); - - // F[en_e1]: 3:3 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classd_ctrl_shadowed_en_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_en_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.en_e1.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_en_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.en_e1.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.en_e1.err_storage) - ); - - // F[en_e2]: 4:4 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classd_ctrl_shadowed_en_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_en_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.en_e2.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_en_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.en_e2.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.en_e2.err_storage) - ); - - // F[en_e3]: 5:5 - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h1) - ) u_classd_ctrl_shadowed_en_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_en_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.en_e3.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_en_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.en_e3.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.en_e3.err_storage) - ); - - // F[map_e0]: 7:6 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classd_ctrl_shadowed_map_e0 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_map_e0_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.map_e0.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_map_e0_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.map_e0.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.map_e0.err_storage) - ); - - // F[map_e1]: 9:8 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h1) - ) u_classd_ctrl_shadowed_map_e1 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_map_e1_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.map_e1.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_map_e1_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.map_e1.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.map_e1.err_storage) - ); - - // F[map_e2]: 11:10 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h2) - ) u_classd_ctrl_shadowed_map_e2 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_map_e2_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.map_e2.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_map_e2_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.map_e2.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.map_e2.err_storage) - ); - - // F[map_e3]: 13:12 - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h3) - ) u_classd_ctrl_shadowed_map_e3 ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_ctrl_shadowed_re), - .we (classd_ctrl_shadowed_we & classd_regwen_qs), - .wd (classd_ctrl_shadowed_map_e3_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_ctrl_shadowed.map_e3.q), - - // to register interface (read) - .qs (classd_ctrl_shadowed_map_e3_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_ctrl_shadowed.map_e3.err_update), - .err_storage (reg2hw.classd_ctrl_shadowed.map_e3.err_storage) - ); - - - // R[classd_clr_regwen]: V(False) - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) - ) u_classd_clr_regwen ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (classd_clr_regwen_we), - .wd (classd_clr_regwen_wd), - - // from internal hardware - .de (hw2reg.classd_clr_regwen.de), - .d (hw2reg.classd_clr_regwen.d), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (classd_clr_regwen_qs) - ); - - - // R[classd_clr_shadowed]: V(False) - prim_subreg_shadow #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_classd_clr_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_clr_shadowed_re), - .we (classd_clr_shadowed_we & classd_clr_regwen_qs), - .wd (classd_clr_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (reg2hw.classd_clr_shadowed.qe), - .q (reg2hw.classd_clr_shadowed.q), - - // to register interface (read) - .qs (classd_clr_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_clr_shadowed.err_update), - .err_storage (reg2hw.classd_clr_shadowed.err_storage) - ); - - - // R[classd_accum_cnt]: V(True) - prim_subreg_ext #( - .DW (16) - ) u_classd_accum_cnt ( - .re (classd_accum_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classd_accum_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classd_accum_cnt_qs) - ); - - - // R[classd_accum_thresh_shadowed]: V(False) - prim_subreg_shadow #( - .DW (16), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (16'h0) - ) u_classd_accum_thresh_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_accum_thresh_shadowed_re), - .we (classd_accum_thresh_shadowed_we & classd_regwen_qs), - .wd (classd_accum_thresh_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_accum_thresh_shadowed.q), - - // to register interface (read) - .qs (classd_accum_thresh_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_accum_thresh_shadowed.err_update), - .err_storage (reg2hw.classd_accum_thresh_shadowed.err_storage) - ); - - - // R[classd_timeout_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classd_timeout_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_timeout_cyc_shadowed_re), - .we (classd_timeout_cyc_shadowed_we & classd_regwen_qs), - .wd (classd_timeout_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_timeout_cyc_shadowed.q), - - // to register interface (read) - .qs (classd_timeout_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_timeout_cyc_shadowed.err_update), - .err_storage (reg2hw.classd_timeout_cyc_shadowed.err_storage) - ); - - - // R[classd_crashdump_trigger_shadowed]: V(False) - prim_subreg_shadow #( - .DW (2), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (2'h0) - ) u_classd_crashdump_trigger_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_crashdump_trigger_shadowed_re), - .we (classd_crashdump_trigger_shadowed_we & classd_regwen_qs), - .wd (classd_crashdump_trigger_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_crashdump_trigger_shadowed.q), - - // to register interface (read) - .qs (classd_crashdump_trigger_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_crashdump_trigger_shadowed.err_update), - .err_storage (reg2hw.classd_crashdump_trigger_shadowed.err_storage) - ); - - - // R[classd_phase0_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classd_phase0_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_phase0_cyc_shadowed_re), - .we (classd_phase0_cyc_shadowed_we & classd_regwen_qs), - .wd (classd_phase0_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_phase0_cyc_shadowed.q), - - // to register interface (read) - .qs (classd_phase0_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_phase0_cyc_shadowed.err_update), - .err_storage (reg2hw.classd_phase0_cyc_shadowed.err_storage) - ); - - - // R[classd_phase1_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classd_phase1_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_phase1_cyc_shadowed_re), - .we (classd_phase1_cyc_shadowed_we & classd_regwen_qs), - .wd (classd_phase1_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_phase1_cyc_shadowed.q), - - // to register interface (read) - .qs (classd_phase1_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_phase1_cyc_shadowed.err_update), - .err_storage (reg2hw.classd_phase1_cyc_shadowed.err_storage) - ); - - - // R[classd_phase2_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classd_phase2_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_phase2_cyc_shadowed_re), - .we (classd_phase2_cyc_shadowed_we & classd_regwen_qs), - .wd (classd_phase2_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_phase2_cyc_shadowed.q), - - // to register interface (read) - .qs (classd_phase2_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_phase2_cyc_shadowed.err_update), - .err_storage (reg2hw.classd_phase2_cyc_shadowed.err_storage) - ); - - - // R[classd_phase3_cyc_shadowed]: V(False) - prim_subreg_shadow #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0) - ) u_classd_phase3_cyc_shadowed ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .rst_shadowed_ni (rst_shadowed_ni), - - // from register interface - .re (classd_phase3_cyc_shadowed_re), - .we (classd_phase3_cyc_shadowed_we & classd_regwen_qs), - .wd (classd_phase3_cyc_shadowed_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.classd_phase3_cyc_shadowed.q), - - // to register interface (read) - .qs (classd_phase3_cyc_shadowed_qs), - - // Shadow register error conditions - .err_update (reg2hw.classd_phase3_cyc_shadowed.err_update), - .err_storage (reg2hw.classd_phase3_cyc_shadowed.err_storage) - ); - - - // R[classd_esc_cnt]: V(True) - prim_subreg_ext #( - .DW (32) - ) u_classd_esc_cnt ( - .re (classd_esc_cnt_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classd_esc_cnt.d), - .qre (), - .qe (), - .q (), - .qs (classd_esc_cnt_qs) - ); - - - // R[classd_state]: V(True) - prim_subreg_ext #( - .DW (3) - ) u_classd_state ( - .re (classd_state_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.classd_state.d), - .qre (), - .qe (), - .q (), - .qs (classd_state_qs) - ); - - - - logic [105:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[ 0] = (reg_addr == ALERT_HANDLER_INTR_STATE_OFFSET); - addr_hit[ 1] = (reg_addr == ALERT_HANDLER_INTR_ENABLE_OFFSET); - addr_hit[ 2] = (reg_addr == ALERT_HANDLER_INTR_TEST_OFFSET); - addr_hit[ 3] = (reg_addr == ALERT_HANDLER_PING_TIMER_REGWEN_OFFSET); - addr_hit[ 4] = (reg_addr == ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_OFFSET); - addr_hit[ 5] = (reg_addr == ALERT_HANDLER_PING_TIMER_EN_SHADOWED_OFFSET); - addr_hit[ 6] = (reg_addr == ALERT_HANDLER_ALERT_REGWEN_0_OFFSET); - addr_hit[ 7] = (reg_addr == ALERT_HANDLER_ALERT_REGWEN_1_OFFSET); - addr_hit[ 8] = (reg_addr == ALERT_HANDLER_ALERT_REGWEN_2_OFFSET); - addr_hit[ 9] = (reg_addr == ALERT_HANDLER_ALERT_REGWEN_3_OFFSET); - addr_hit[ 10] = (reg_addr == ALERT_HANDLER_ALERT_EN_SHADOWED_0_OFFSET); - addr_hit[ 11] = (reg_addr == ALERT_HANDLER_ALERT_EN_SHADOWED_1_OFFSET); - addr_hit[ 12] = (reg_addr == ALERT_HANDLER_ALERT_EN_SHADOWED_2_OFFSET); - addr_hit[ 13] = (reg_addr == ALERT_HANDLER_ALERT_EN_SHADOWED_3_OFFSET); - addr_hit[ 14] = (reg_addr == ALERT_HANDLER_ALERT_CLASS_SHADOWED_0_OFFSET); - addr_hit[ 15] = (reg_addr == ALERT_HANDLER_ALERT_CLASS_SHADOWED_1_OFFSET); - addr_hit[ 16] = (reg_addr == ALERT_HANDLER_ALERT_CLASS_SHADOWED_2_OFFSET); - addr_hit[ 17] = (reg_addr == ALERT_HANDLER_ALERT_CLASS_SHADOWED_3_OFFSET); - addr_hit[ 18] = (reg_addr == ALERT_HANDLER_ALERT_CAUSE_0_OFFSET); - addr_hit[ 19] = (reg_addr == ALERT_HANDLER_ALERT_CAUSE_1_OFFSET); - addr_hit[ 20] = (reg_addr == ALERT_HANDLER_ALERT_CAUSE_2_OFFSET); - addr_hit[ 21] = (reg_addr == ALERT_HANDLER_ALERT_CAUSE_3_OFFSET); - addr_hit[ 22] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_0_OFFSET); - addr_hit[ 23] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_1_OFFSET); - addr_hit[ 24] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_2_OFFSET); - addr_hit[ 25] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_3_OFFSET); - addr_hit[ 26] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_4_OFFSET); - addr_hit[ 27] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_5_OFFSET); - addr_hit[ 28] = (reg_addr == ALERT_HANDLER_LOC_ALERT_REGWEN_6_OFFSET); - addr_hit[ 29] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0_OFFSET); - addr_hit[ 30] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1_OFFSET); - addr_hit[ 31] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2_OFFSET); - addr_hit[ 32] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_3_OFFSET); - addr_hit[ 33] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_4_OFFSET); - addr_hit[ 34] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_5_OFFSET); - addr_hit[ 35] = (reg_addr == ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_6_OFFSET); - addr_hit[ 36] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_OFFSET); - addr_hit[ 37] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1_OFFSET); - addr_hit[ 38] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2_OFFSET); - addr_hit[ 39] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_3_OFFSET); - addr_hit[ 40] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_4_OFFSET); - addr_hit[ 41] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_5_OFFSET); - addr_hit[ 42] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_6_OFFSET); - addr_hit[ 43] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_0_OFFSET); - addr_hit[ 44] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_1_OFFSET); - addr_hit[ 45] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_2_OFFSET); - addr_hit[ 46] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_3_OFFSET); - addr_hit[ 47] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_4_OFFSET); - addr_hit[ 48] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_5_OFFSET); - addr_hit[ 49] = (reg_addr == ALERT_HANDLER_LOC_ALERT_CAUSE_6_OFFSET); - addr_hit[ 50] = (reg_addr == ALERT_HANDLER_CLASSA_REGWEN_OFFSET); - addr_hit[ 51] = (reg_addr == ALERT_HANDLER_CLASSA_CTRL_SHADOWED_OFFSET); - addr_hit[ 52] = (reg_addr == ALERT_HANDLER_CLASSA_CLR_REGWEN_OFFSET); - addr_hit[ 53] = (reg_addr == ALERT_HANDLER_CLASSA_CLR_SHADOWED_OFFSET); - addr_hit[ 54] = (reg_addr == ALERT_HANDLER_CLASSA_ACCUM_CNT_OFFSET); - addr_hit[ 55] = (reg_addr == ALERT_HANDLER_CLASSA_ACCUM_THRESH_SHADOWED_OFFSET); - addr_hit[ 56] = (reg_addr == ALERT_HANDLER_CLASSA_TIMEOUT_CYC_SHADOWED_OFFSET); - addr_hit[ 57] = (reg_addr == ALERT_HANDLER_CLASSA_CRASHDUMP_TRIGGER_SHADOWED_OFFSET); - addr_hit[ 58] = (reg_addr == ALERT_HANDLER_CLASSA_PHASE0_CYC_SHADOWED_OFFSET); - addr_hit[ 59] = (reg_addr == ALERT_HANDLER_CLASSA_PHASE1_CYC_SHADOWED_OFFSET); - addr_hit[ 60] = (reg_addr == ALERT_HANDLER_CLASSA_PHASE2_CYC_SHADOWED_OFFSET); - addr_hit[ 61] = (reg_addr == ALERT_HANDLER_CLASSA_PHASE3_CYC_SHADOWED_OFFSET); - addr_hit[ 62] = (reg_addr == ALERT_HANDLER_CLASSA_ESC_CNT_OFFSET); - addr_hit[ 63] = (reg_addr == ALERT_HANDLER_CLASSA_STATE_OFFSET); - addr_hit[ 64] = (reg_addr == ALERT_HANDLER_CLASSB_REGWEN_OFFSET); - addr_hit[ 65] = (reg_addr == ALERT_HANDLER_CLASSB_CTRL_SHADOWED_OFFSET); - addr_hit[ 66] = (reg_addr == ALERT_HANDLER_CLASSB_CLR_REGWEN_OFFSET); - addr_hit[ 67] = (reg_addr == ALERT_HANDLER_CLASSB_CLR_SHADOWED_OFFSET); - addr_hit[ 68] = (reg_addr == ALERT_HANDLER_CLASSB_ACCUM_CNT_OFFSET); - addr_hit[ 69] = (reg_addr == ALERT_HANDLER_CLASSB_ACCUM_THRESH_SHADOWED_OFFSET); - addr_hit[ 70] = (reg_addr == ALERT_HANDLER_CLASSB_TIMEOUT_CYC_SHADOWED_OFFSET); - addr_hit[ 71] = (reg_addr == ALERT_HANDLER_CLASSB_CRASHDUMP_TRIGGER_SHADOWED_OFFSET); - addr_hit[ 72] = (reg_addr == ALERT_HANDLER_CLASSB_PHASE0_CYC_SHADOWED_OFFSET); - addr_hit[ 73] = (reg_addr == ALERT_HANDLER_CLASSB_PHASE1_CYC_SHADOWED_OFFSET); - addr_hit[ 74] = (reg_addr == ALERT_HANDLER_CLASSB_PHASE2_CYC_SHADOWED_OFFSET); - addr_hit[ 75] = (reg_addr == ALERT_HANDLER_CLASSB_PHASE3_CYC_SHADOWED_OFFSET); - addr_hit[ 76] = (reg_addr == ALERT_HANDLER_CLASSB_ESC_CNT_OFFSET); - addr_hit[ 77] = (reg_addr == ALERT_HANDLER_CLASSB_STATE_OFFSET); - addr_hit[ 78] = (reg_addr == ALERT_HANDLER_CLASSC_REGWEN_OFFSET); - addr_hit[ 79] = (reg_addr == ALERT_HANDLER_CLASSC_CTRL_SHADOWED_OFFSET); - addr_hit[ 80] = (reg_addr == ALERT_HANDLER_CLASSC_CLR_REGWEN_OFFSET); - addr_hit[ 81] = (reg_addr == ALERT_HANDLER_CLASSC_CLR_SHADOWED_OFFSET); - addr_hit[ 82] = (reg_addr == ALERT_HANDLER_CLASSC_ACCUM_CNT_OFFSET); - addr_hit[ 83] = (reg_addr == ALERT_HANDLER_CLASSC_ACCUM_THRESH_SHADOWED_OFFSET); - addr_hit[ 84] = (reg_addr == ALERT_HANDLER_CLASSC_TIMEOUT_CYC_SHADOWED_OFFSET); - addr_hit[ 85] = (reg_addr == ALERT_HANDLER_CLASSC_CRASHDUMP_TRIGGER_SHADOWED_OFFSET); - addr_hit[ 86] = (reg_addr == ALERT_HANDLER_CLASSC_PHASE0_CYC_SHADOWED_OFFSET); - addr_hit[ 87] = (reg_addr == ALERT_HANDLER_CLASSC_PHASE1_CYC_SHADOWED_OFFSET); - addr_hit[ 88] = (reg_addr == ALERT_HANDLER_CLASSC_PHASE2_CYC_SHADOWED_OFFSET); - addr_hit[ 89] = (reg_addr == ALERT_HANDLER_CLASSC_PHASE3_CYC_SHADOWED_OFFSET); - addr_hit[ 90] = (reg_addr == ALERT_HANDLER_CLASSC_ESC_CNT_OFFSET); - addr_hit[ 91] = (reg_addr == ALERT_HANDLER_CLASSC_STATE_OFFSET); - addr_hit[ 92] = (reg_addr == ALERT_HANDLER_CLASSD_REGWEN_OFFSET); - addr_hit[ 93] = (reg_addr == ALERT_HANDLER_CLASSD_CTRL_SHADOWED_OFFSET); - addr_hit[ 94] = (reg_addr == ALERT_HANDLER_CLASSD_CLR_REGWEN_OFFSET); - addr_hit[ 95] = (reg_addr == ALERT_HANDLER_CLASSD_CLR_SHADOWED_OFFSET); - addr_hit[ 96] = (reg_addr == ALERT_HANDLER_CLASSD_ACCUM_CNT_OFFSET); - addr_hit[ 97] = (reg_addr == ALERT_HANDLER_CLASSD_ACCUM_THRESH_SHADOWED_OFFSET); - addr_hit[ 98] = (reg_addr == ALERT_HANDLER_CLASSD_TIMEOUT_CYC_SHADOWED_OFFSET); - addr_hit[ 99] = (reg_addr == ALERT_HANDLER_CLASSD_CRASHDUMP_TRIGGER_SHADOWED_OFFSET); - addr_hit[100] = (reg_addr == ALERT_HANDLER_CLASSD_PHASE0_CYC_SHADOWED_OFFSET); - addr_hit[101] = (reg_addr == ALERT_HANDLER_CLASSD_PHASE1_CYC_SHADOWED_OFFSET); - addr_hit[102] = (reg_addr == ALERT_HANDLER_CLASSD_PHASE2_CYC_SHADOWED_OFFSET); - addr_hit[103] = (reg_addr == ALERT_HANDLER_CLASSD_PHASE3_CYC_SHADOWED_OFFSET); - addr_hit[104] = (reg_addr == ALERT_HANDLER_CLASSD_ESC_CNT_OFFSET); - addr_hit[105] = (reg_addr == ALERT_HANDLER_CLASSD_STATE_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[ 0] & (|(ALERT_HANDLER_PERMIT[ 0] & ~reg_be))) | - (addr_hit[ 1] & (|(ALERT_HANDLER_PERMIT[ 1] & ~reg_be))) | - (addr_hit[ 2] & (|(ALERT_HANDLER_PERMIT[ 2] & ~reg_be))) | - (addr_hit[ 3] & (|(ALERT_HANDLER_PERMIT[ 3] & ~reg_be))) | - (addr_hit[ 4] & (|(ALERT_HANDLER_PERMIT[ 4] & ~reg_be))) | - (addr_hit[ 5] & (|(ALERT_HANDLER_PERMIT[ 5] & ~reg_be))) | - (addr_hit[ 6] & (|(ALERT_HANDLER_PERMIT[ 6] & ~reg_be))) | - (addr_hit[ 7] & (|(ALERT_HANDLER_PERMIT[ 7] & ~reg_be))) | - (addr_hit[ 8] & (|(ALERT_HANDLER_PERMIT[ 8] & ~reg_be))) | - (addr_hit[ 9] & (|(ALERT_HANDLER_PERMIT[ 9] & ~reg_be))) | - (addr_hit[ 10] & (|(ALERT_HANDLER_PERMIT[ 10] & ~reg_be))) | - (addr_hit[ 11] & (|(ALERT_HANDLER_PERMIT[ 11] & ~reg_be))) | - (addr_hit[ 12] & (|(ALERT_HANDLER_PERMIT[ 12] & ~reg_be))) | - (addr_hit[ 13] & (|(ALERT_HANDLER_PERMIT[ 13] & ~reg_be))) | - (addr_hit[ 14] & (|(ALERT_HANDLER_PERMIT[ 14] & ~reg_be))) | - (addr_hit[ 15] & (|(ALERT_HANDLER_PERMIT[ 15] & ~reg_be))) | - (addr_hit[ 16] & (|(ALERT_HANDLER_PERMIT[ 16] & ~reg_be))) | - (addr_hit[ 17] & (|(ALERT_HANDLER_PERMIT[ 17] & ~reg_be))) | - (addr_hit[ 18] & (|(ALERT_HANDLER_PERMIT[ 18] & ~reg_be))) | - (addr_hit[ 19] & (|(ALERT_HANDLER_PERMIT[ 19] & ~reg_be))) | - (addr_hit[ 20] & (|(ALERT_HANDLER_PERMIT[ 20] & ~reg_be))) | - (addr_hit[ 21] & (|(ALERT_HANDLER_PERMIT[ 21] & ~reg_be))) | - (addr_hit[ 22] & (|(ALERT_HANDLER_PERMIT[ 22] & ~reg_be))) | - (addr_hit[ 23] & (|(ALERT_HANDLER_PERMIT[ 23] & ~reg_be))) | - (addr_hit[ 24] & (|(ALERT_HANDLER_PERMIT[ 24] & ~reg_be))) | - (addr_hit[ 25] & (|(ALERT_HANDLER_PERMIT[ 25] & ~reg_be))) | - (addr_hit[ 26] & (|(ALERT_HANDLER_PERMIT[ 26] & ~reg_be))) | - (addr_hit[ 27] & (|(ALERT_HANDLER_PERMIT[ 27] & ~reg_be))) | - (addr_hit[ 28] & (|(ALERT_HANDLER_PERMIT[ 28] & ~reg_be))) | - (addr_hit[ 29] & (|(ALERT_HANDLER_PERMIT[ 29] & ~reg_be))) | - (addr_hit[ 30] & (|(ALERT_HANDLER_PERMIT[ 30] & ~reg_be))) | - (addr_hit[ 31] & (|(ALERT_HANDLER_PERMIT[ 31] & ~reg_be))) | - (addr_hit[ 32] & (|(ALERT_HANDLER_PERMIT[ 32] & ~reg_be))) | - (addr_hit[ 33] & (|(ALERT_HANDLER_PERMIT[ 33] & ~reg_be))) | - (addr_hit[ 34] & (|(ALERT_HANDLER_PERMIT[ 34] & ~reg_be))) | - (addr_hit[ 35] & (|(ALERT_HANDLER_PERMIT[ 35] & ~reg_be))) | - (addr_hit[ 36] & (|(ALERT_HANDLER_PERMIT[ 36] & ~reg_be))) | - (addr_hit[ 37] & (|(ALERT_HANDLER_PERMIT[ 37] & ~reg_be))) | - (addr_hit[ 38] & (|(ALERT_HANDLER_PERMIT[ 38] & ~reg_be))) | - (addr_hit[ 39] & (|(ALERT_HANDLER_PERMIT[ 39] & ~reg_be))) | - (addr_hit[ 40] & (|(ALERT_HANDLER_PERMIT[ 40] & ~reg_be))) | - (addr_hit[ 41] & (|(ALERT_HANDLER_PERMIT[ 41] & ~reg_be))) | - (addr_hit[ 42] & (|(ALERT_HANDLER_PERMIT[ 42] & ~reg_be))) | - (addr_hit[ 43] & (|(ALERT_HANDLER_PERMIT[ 43] & ~reg_be))) | - (addr_hit[ 44] & (|(ALERT_HANDLER_PERMIT[ 44] & ~reg_be))) | - (addr_hit[ 45] & (|(ALERT_HANDLER_PERMIT[ 45] & ~reg_be))) | - (addr_hit[ 46] & (|(ALERT_HANDLER_PERMIT[ 46] & ~reg_be))) | - (addr_hit[ 47] & (|(ALERT_HANDLER_PERMIT[ 47] & ~reg_be))) | - (addr_hit[ 48] & (|(ALERT_HANDLER_PERMIT[ 48] & ~reg_be))) | - (addr_hit[ 49] & (|(ALERT_HANDLER_PERMIT[ 49] & ~reg_be))) | - (addr_hit[ 50] & (|(ALERT_HANDLER_PERMIT[ 50] & ~reg_be))) | - (addr_hit[ 51] & (|(ALERT_HANDLER_PERMIT[ 51] & ~reg_be))) | - (addr_hit[ 52] & (|(ALERT_HANDLER_PERMIT[ 52] & ~reg_be))) | - (addr_hit[ 53] & (|(ALERT_HANDLER_PERMIT[ 53] & ~reg_be))) | - (addr_hit[ 54] & (|(ALERT_HANDLER_PERMIT[ 54] & ~reg_be))) | - (addr_hit[ 55] & (|(ALERT_HANDLER_PERMIT[ 55] & ~reg_be))) | - (addr_hit[ 56] & (|(ALERT_HANDLER_PERMIT[ 56] & ~reg_be))) | - (addr_hit[ 57] & (|(ALERT_HANDLER_PERMIT[ 57] & ~reg_be))) | - (addr_hit[ 58] & (|(ALERT_HANDLER_PERMIT[ 58] & ~reg_be))) | - (addr_hit[ 59] & (|(ALERT_HANDLER_PERMIT[ 59] & ~reg_be))) | - (addr_hit[ 60] & (|(ALERT_HANDLER_PERMIT[ 60] & ~reg_be))) | - (addr_hit[ 61] & (|(ALERT_HANDLER_PERMIT[ 61] & ~reg_be))) | - (addr_hit[ 62] & (|(ALERT_HANDLER_PERMIT[ 62] & ~reg_be))) | - (addr_hit[ 63] & (|(ALERT_HANDLER_PERMIT[ 63] & ~reg_be))) | - (addr_hit[ 64] & (|(ALERT_HANDLER_PERMIT[ 64] & ~reg_be))) | - (addr_hit[ 65] & (|(ALERT_HANDLER_PERMIT[ 65] & ~reg_be))) | - (addr_hit[ 66] & (|(ALERT_HANDLER_PERMIT[ 66] & ~reg_be))) | - (addr_hit[ 67] & (|(ALERT_HANDLER_PERMIT[ 67] & ~reg_be))) | - (addr_hit[ 68] & (|(ALERT_HANDLER_PERMIT[ 68] & ~reg_be))) | - (addr_hit[ 69] & (|(ALERT_HANDLER_PERMIT[ 69] & ~reg_be))) | - (addr_hit[ 70] & (|(ALERT_HANDLER_PERMIT[ 70] & ~reg_be))) | - (addr_hit[ 71] & (|(ALERT_HANDLER_PERMIT[ 71] & ~reg_be))) | - (addr_hit[ 72] & (|(ALERT_HANDLER_PERMIT[ 72] & ~reg_be))) | - (addr_hit[ 73] & (|(ALERT_HANDLER_PERMIT[ 73] & ~reg_be))) | - (addr_hit[ 74] & (|(ALERT_HANDLER_PERMIT[ 74] & ~reg_be))) | - (addr_hit[ 75] & (|(ALERT_HANDLER_PERMIT[ 75] & ~reg_be))) | - (addr_hit[ 76] & (|(ALERT_HANDLER_PERMIT[ 76] & ~reg_be))) | - (addr_hit[ 77] & (|(ALERT_HANDLER_PERMIT[ 77] & ~reg_be))) | - (addr_hit[ 78] & (|(ALERT_HANDLER_PERMIT[ 78] & ~reg_be))) | - (addr_hit[ 79] & (|(ALERT_HANDLER_PERMIT[ 79] & ~reg_be))) | - (addr_hit[ 80] & (|(ALERT_HANDLER_PERMIT[ 80] & ~reg_be))) | - (addr_hit[ 81] & (|(ALERT_HANDLER_PERMIT[ 81] & ~reg_be))) | - (addr_hit[ 82] & (|(ALERT_HANDLER_PERMIT[ 82] & ~reg_be))) | - (addr_hit[ 83] & (|(ALERT_HANDLER_PERMIT[ 83] & ~reg_be))) | - (addr_hit[ 84] & (|(ALERT_HANDLER_PERMIT[ 84] & ~reg_be))) | - (addr_hit[ 85] & (|(ALERT_HANDLER_PERMIT[ 85] & ~reg_be))) | - (addr_hit[ 86] & (|(ALERT_HANDLER_PERMIT[ 86] & ~reg_be))) | - (addr_hit[ 87] & (|(ALERT_HANDLER_PERMIT[ 87] & ~reg_be))) | - (addr_hit[ 88] & (|(ALERT_HANDLER_PERMIT[ 88] & ~reg_be))) | - (addr_hit[ 89] & (|(ALERT_HANDLER_PERMIT[ 89] & ~reg_be))) | - (addr_hit[ 90] & (|(ALERT_HANDLER_PERMIT[ 90] & ~reg_be))) | - (addr_hit[ 91] & (|(ALERT_HANDLER_PERMIT[ 91] & ~reg_be))) | - (addr_hit[ 92] & (|(ALERT_HANDLER_PERMIT[ 92] & ~reg_be))) | - (addr_hit[ 93] & (|(ALERT_HANDLER_PERMIT[ 93] & ~reg_be))) | - (addr_hit[ 94] & (|(ALERT_HANDLER_PERMIT[ 94] & ~reg_be))) | - (addr_hit[ 95] & (|(ALERT_HANDLER_PERMIT[ 95] & ~reg_be))) | - (addr_hit[ 96] & (|(ALERT_HANDLER_PERMIT[ 96] & ~reg_be))) | - (addr_hit[ 97] & (|(ALERT_HANDLER_PERMIT[ 97] & ~reg_be))) | - (addr_hit[ 98] & (|(ALERT_HANDLER_PERMIT[ 98] & ~reg_be))) | - (addr_hit[ 99] & (|(ALERT_HANDLER_PERMIT[ 99] & ~reg_be))) | - (addr_hit[100] & (|(ALERT_HANDLER_PERMIT[100] & ~reg_be))) | - (addr_hit[101] & (|(ALERT_HANDLER_PERMIT[101] & ~reg_be))) | - (addr_hit[102] & (|(ALERT_HANDLER_PERMIT[102] & ~reg_be))) | - (addr_hit[103] & (|(ALERT_HANDLER_PERMIT[103] & ~reg_be))) | - (addr_hit[104] & (|(ALERT_HANDLER_PERMIT[104] & ~reg_be))) | - (addr_hit[105] & (|(ALERT_HANDLER_PERMIT[105] & ~reg_be))))); - end - assign intr_state_we = addr_hit[0] & reg_we & !reg_error; - - assign intr_state_classa_wd = reg_wdata[0]; - - assign intr_state_classb_wd = reg_wdata[1]; - - assign intr_state_classc_wd = reg_wdata[2]; - - assign intr_state_classd_wd = reg_wdata[3]; - assign intr_enable_we = addr_hit[1] & reg_we & !reg_error; - - assign intr_enable_classa_wd = reg_wdata[0]; - - assign intr_enable_classb_wd = reg_wdata[1]; - - assign intr_enable_classc_wd = reg_wdata[2]; - - assign intr_enable_classd_wd = reg_wdata[3]; - assign intr_test_we = addr_hit[2] & reg_we & !reg_error; - - assign intr_test_classa_wd = reg_wdata[0]; - - assign intr_test_classb_wd = reg_wdata[1]; - - assign intr_test_classc_wd = reg_wdata[2]; - - assign intr_test_classd_wd = reg_wdata[3]; - assign ping_timer_regwen_we = addr_hit[3] & reg_we & !reg_error; - - assign ping_timer_regwen_wd = reg_wdata[0]; - assign ping_timeout_cyc_shadowed_re = addr_hit[4] & reg_re & !reg_error; - assign ping_timeout_cyc_shadowed_we = addr_hit[4] & reg_we & !reg_error; - - assign ping_timeout_cyc_shadowed_wd = reg_wdata[15:0]; - assign ping_timer_en_shadowed_re = addr_hit[5] & reg_re & !reg_error; - assign ping_timer_en_shadowed_we = addr_hit[5] & reg_we & !reg_error; - - assign ping_timer_en_shadowed_wd = reg_wdata[0]; - assign alert_regwen_0_we = addr_hit[6] & reg_we & !reg_error; - - assign alert_regwen_0_wd = reg_wdata[0]; - assign alert_regwen_1_we = addr_hit[7] & reg_we & !reg_error; - - assign alert_regwen_1_wd = reg_wdata[0]; - assign alert_regwen_2_we = addr_hit[8] & reg_we & !reg_error; - - assign alert_regwen_2_wd = reg_wdata[0]; - assign alert_regwen_3_we = addr_hit[9] & reg_we & !reg_error; - - assign alert_regwen_3_wd = reg_wdata[0]; - assign alert_en_shadowed_0_re = addr_hit[10] & reg_re & !reg_error; - assign alert_en_shadowed_0_we = addr_hit[10] & reg_we & !reg_error; - - assign alert_en_shadowed_0_wd = reg_wdata[0]; - assign alert_en_shadowed_1_re = addr_hit[11] & reg_re & !reg_error; - assign alert_en_shadowed_1_we = addr_hit[11] & reg_we & !reg_error; - - assign alert_en_shadowed_1_wd = reg_wdata[0]; - assign alert_en_shadowed_2_re = addr_hit[12] & reg_re & !reg_error; - assign alert_en_shadowed_2_we = addr_hit[12] & reg_we & !reg_error; - - assign alert_en_shadowed_2_wd = reg_wdata[0]; - assign alert_en_shadowed_3_re = addr_hit[13] & reg_re & !reg_error; - assign alert_en_shadowed_3_we = addr_hit[13] & reg_we & !reg_error; - - assign alert_en_shadowed_3_wd = reg_wdata[0]; - assign alert_class_shadowed_0_re = addr_hit[14] & reg_re & !reg_error; - assign alert_class_shadowed_0_we = addr_hit[14] & reg_we & !reg_error; - - assign alert_class_shadowed_0_wd = reg_wdata[1:0]; - assign alert_class_shadowed_1_re = addr_hit[15] & reg_re & !reg_error; - assign alert_class_shadowed_1_we = addr_hit[15] & reg_we & !reg_error; - - assign alert_class_shadowed_1_wd = reg_wdata[1:0]; - assign alert_class_shadowed_2_re = addr_hit[16] & reg_re & !reg_error; - assign alert_class_shadowed_2_we = addr_hit[16] & reg_we & !reg_error; - - assign alert_class_shadowed_2_wd = reg_wdata[1:0]; - assign alert_class_shadowed_3_re = addr_hit[17] & reg_re & !reg_error; - assign alert_class_shadowed_3_we = addr_hit[17] & reg_we & !reg_error; - - assign alert_class_shadowed_3_wd = reg_wdata[1:0]; - assign alert_cause_0_we = addr_hit[18] & reg_we & !reg_error; - - assign alert_cause_0_wd = reg_wdata[0]; - assign alert_cause_1_we = addr_hit[19] & reg_we & !reg_error; - - assign alert_cause_1_wd = reg_wdata[0]; - assign alert_cause_2_we = addr_hit[20] & reg_we & !reg_error; - - assign alert_cause_2_wd = reg_wdata[0]; - assign alert_cause_3_we = addr_hit[21] & reg_we & !reg_error; - - assign alert_cause_3_wd = reg_wdata[0]; - assign loc_alert_regwen_0_we = addr_hit[22] & reg_we & !reg_error; - - assign loc_alert_regwen_0_wd = reg_wdata[0]; - assign loc_alert_regwen_1_we = addr_hit[23] & reg_we & !reg_error; - - assign loc_alert_regwen_1_wd = reg_wdata[0]; - assign loc_alert_regwen_2_we = addr_hit[24] & reg_we & !reg_error; - - assign loc_alert_regwen_2_wd = reg_wdata[0]; - assign loc_alert_regwen_3_we = addr_hit[25] & reg_we & !reg_error; - - assign loc_alert_regwen_3_wd = reg_wdata[0]; - assign loc_alert_regwen_4_we = addr_hit[26] & reg_we & !reg_error; - - assign loc_alert_regwen_4_wd = reg_wdata[0]; - assign loc_alert_regwen_5_we = addr_hit[27] & reg_we & !reg_error; - - assign loc_alert_regwen_5_wd = reg_wdata[0]; - assign loc_alert_regwen_6_we = addr_hit[28] & reg_we & !reg_error; - - assign loc_alert_regwen_6_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_0_re = addr_hit[29] & reg_re & !reg_error; - assign loc_alert_en_shadowed_0_we = addr_hit[29] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_0_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_1_re = addr_hit[30] & reg_re & !reg_error; - assign loc_alert_en_shadowed_1_we = addr_hit[30] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_1_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_2_re = addr_hit[31] & reg_re & !reg_error; - assign loc_alert_en_shadowed_2_we = addr_hit[31] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_2_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_3_re = addr_hit[32] & reg_re & !reg_error; - assign loc_alert_en_shadowed_3_we = addr_hit[32] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_3_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_4_re = addr_hit[33] & reg_re & !reg_error; - assign loc_alert_en_shadowed_4_we = addr_hit[33] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_4_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_5_re = addr_hit[34] & reg_re & !reg_error; - assign loc_alert_en_shadowed_5_we = addr_hit[34] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_5_wd = reg_wdata[0]; - assign loc_alert_en_shadowed_6_re = addr_hit[35] & reg_re & !reg_error; - assign loc_alert_en_shadowed_6_we = addr_hit[35] & reg_we & !reg_error; - - assign loc_alert_en_shadowed_6_wd = reg_wdata[0]; - assign loc_alert_class_shadowed_0_re = addr_hit[36] & reg_re & !reg_error; - assign loc_alert_class_shadowed_0_we = addr_hit[36] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_0_wd = reg_wdata[1:0]; - assign loc_alert_class_shadowed_1_re = addr_hit[37] & reg_re & !reg_error; - assign loc_alert_class_shadowed_1_we = addr_hit[37] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_1_wd = reg_wdata[1:0]; - assign loc_alert_class_shadowed_2_re = addr_hit[38] & reg_re & !reg_error; - assign loc_alert_class_shadowed_2_we = addr_hit[38] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_2_wd = reg_wdata[1:0]; - assign loc_alert_class_shadowed_3_re = addr_hit[39] & reg_re & !reg_error; - assign loc_alert_class_shadowed_3_we = addr_hit[39] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_3_wd = reg_wdata[1:0]; - assign loc_alert_class_shadowed_4_re = addr_hit[40] & reg_re & !reg_error; - assign loc_alert_class_shadowed_4_we = addr_hit[40] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_4_wd = reg_wdata[1:0]; - assign loc_alert_class_shadowed_5_re = addr_hit[41] & reg_re & !reg_error; - assign loc_alert_class_shadowed_5_we = addr_hit[41] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_5_wd = reg_wdata[1:0]; - assign loc_alert_class_shadowed_6_re = addr_hit[42] & reg_re & !reg_error; - assign loc_alert_class_shadowed_6_we = addr_hit[42] & reg_we & !reg_error; - - assign loc_alert_class_shadowed_6_wd = reg_wdata[1:0]; - assign loc_alert_cause_0_we = addr_hit[43] & reg_we & !reg_error; - - assign loc_alert_cause_0_wd = reg_wdata[0]; - assign loc_alert_cause_1_we = addr_hit[44] & reg_we & !reg_error; - - assign loc_alert_cause_1_wd = reg_wdata[0]; - assign loc_alert_cause_2_we = addr_hit[45] & reg_we & !reg_error; - - assign loc_alert_cause_2_wd = reg_wdata[0]; - assign loc_alert_cause_3_we = addr_hit[46] & reg_we & !reg_error; - - assign loc_alert_cause_3_wd = reg_wdata[0]; - assign loc_alert_cause_4_we = addr_hit[47] & reg_we & !reg_error; - - assign loc_alert_cause_4_wd = reg_wdata[0]; - assign loc_alert_cause_5_we = addr_hit[48] & reg_we & !reg_error; - - assign loc_alert_cause_5_wd = reg_wdata[0]; - assign loc_alert_cause_6_we = addr_hit[49] & reg_we & !reg_error; - - assign loc_alert_cause_6_wd = reg_wdata[0]; - assign classa_regwen_we = addr_hit[50] & reg_we & !reg_error; - - assign classa_regwen_wd = reg_wdata[0]; - assign classa_ctrl_shadowed_re = addr_hit[51] & reg_re & !reg_error; - assign classa_ctrl_shadowed_we = addr_hit[51] & reg_we & !reg_error; - - assign classa_ctrl_shadowed_en_wd = reg_wdata[0]; - - assign classa_ctrl_shadowed_lock_wd = reg_wdata[1]; - - assign classa_ctrl_shadowed_en_e0_wd = reg_wdata[2]; - - assign classa_ctrl_shadowed_en_e1_wd = reg_wdata[3]; - - assign classa_ctrl_shadowed_en_e2_wd = reg_wdata[4]; - - assign classa_ctrl_shadowed_en_e3_wd = reg_wdata[5]; - - assign classa_ctrl_shadowed_map_e0_wd = reg_wdata[7:6]; - - assign classa_ctrl_shadowed_map_e1_wd = reg_wdata[9:8]; - - assign classa_ctrl_shadowed_map_e2_wd = reg_wdata[11:10]; - - assign classa_ctrl_shadowed_map_e3_wd = reg_wdata[13:12]; - assign classa_clr_regwen_we = addr_hit[52] & reg_we & !reg_error; - - assign classa_clr_regwen_wd = reg_wdata[0]; - assign classa_clr_shadowed_re = addr_hit[53] & reg_re & !reg_error; - assign classa_clr_shadowed_we = addr_hit[53] & reg_we & !reg_error; - - assign classa_clr_shadowed_wd = reg_wdata[0]; - assign classa_accum_cnt_re = addr_hit[54] & reg_re & !reg_error; - assign classa_accum_thresh_shadowed_re = addr_hit[55] & reg_re & !reg_error; - assign classa_accum_thresh_shadowed_we = addr_hit[55] & reg_we & !reg_error; - - assign classa_accum_thresh_shadowed_wd = reg_wdata[15:0]; - assign classa_timeout_cyc_shadowed_re = addr_hit[56] & reg_re & !reg_error; - assign classa_timeout_cyc_shadowed_we = addr_hit[56] & reg_we & !reg_error; - - assign classa_timeout_cyc_shadowed_wd = reg_wdata[31:0]; - assign classa_crashdump_trigger_shadowed_re = addr_hit[57] & reg_re & !reg_error; - assign classa_crashdump_trigger_shadowed_we = addr_hit[57] & reg_we & !reg_error; - - assign classa_crashdump_trigger_shadowed_wd = reg_wdata[1:0]; - assign classa_phase0_cyc_shadowed_re = addr_hit[58] & reg_re & !reg_error; - assign classa_phase0_cyc_shadowed_we = addr_hit[58] & reg_we & !reg_error; - - assign classa_phase0_cyc_shadowed_wd = reg_wdata[31:0]; - assign classa_phase1_cyc_shadowed_re = addr_hit[59] & reg_re & !reg_error; - assign classa_phase1_cyc_shadowed_we = addr_hit[59] & reg_we & !reg_error; - - assign classa_phase1_cyc_shadowed_wd = reg_wdata[31:0]; - assign classa_phase2_cyc_shadowed_re = addr_hit[60] & reg_re & !reg_error; - assign classa_phase2_cyc_shadowed_we = addr_hit[60] & reg_we & !reg_error; - - assign classa_phase2_cyc_shadowed_wd = reg_wdata[31:0]; - assign classa_phase3_cyc_shadowed_re = addr_hit[61] & reg_re & !reg_error; - assign classa_phase3_cyc_shadowed_we = addr_hit[61] & reg_we & !reg_error; - - assign classa_phase3_cyc_shadowed_wd = reg_wdata[31:0]; - assign classa_esc_cnt_re = addr_hit[62] & reg_re & !reg_error; - assign classa_state_re = addr_hit[63] & reg_re & !reg_error; - assign classb_regwen_we = addr_hit[64] & reg_we & !reg_error; - - assign classb_regwen_wd = reg_wdata[0]; - assign classb_ctrl_shadowed_re = addr_hit[65] & reg_re & !reg_error; - assign classb_ctrl_shadowed_we = addr_hit[65] & reg_we & !reg_error; - - assign classb_ctrl_shadowed_en_wd = reg_wdata[0]; - - assign classb_ctrl_shadowed_lock_wd = reg_wdata[1]; - - assign classb_ctrl_shadowed_en_e0_wd = reg_wdata[2]; - - assign classb_ctrl_shadowed_en_e1_wd = reg_wdata[3]; - - assign classb_ctrl_shadowed_en_e2_wd = reg_wdata[4]; - - assign classb_ctrl_shadowed_en_e3_wd = reg_wdata[5]; - - assign classb_ctrl_shadowed_map_e0_wd = reg_wdata[7:6]; - - assign classb_ctrl_shadowed_map_e1_wd = reg_wdata[9:8]; - - assign classb_ctrl_shadowed_map_e2_wd = reg_wdata[11:10]; - - assign classb_ctrl_shadowed_map_e3_wd = reg_wdata[13:12]; - assign classb_clr_regwen_we = addr_hit[66] & reg_we & !reg_error; - - assign classb_clr_regwen_wd = reg_wdata[0]; - assign classb_clr_shadowed_re = addr_hit[67] & reg_re & !reg_error; - assign classb_clr_shadowed_we = addr_hit[67] & reg_we & !reg_error; - - assign classb_clr_shadowed_wd = reg_wdata[0]; - assign classb_accum_cnt_re = addr_hit[68] & reg_re & !reg_error; - assign classb_accum_thresh_shadowed_re = addr_hit[69] & reg_re & !reg_error; - assign classb_accum_thresh_shadowed_we = addr_hit[69] & reg_we & !reg_error; - - assign classb_accum_thresh_shadowed_wd = reg_wdata[15:0]; - assign classb_timeout_cyc_shadowed_re = addr_hit[70] & reg_re & !reg_error; - assign classb_timeout_cyc_shadowed_we = addr_hit[70] & reg_we & !reg_error; - - assign classb_timeout_cyc_shadowed_wd = reg_wdata[31:0]; - assign classb_crashdump_trigger_shadowed_re = addr_hit[71] & reg_re & !reg_error; - assign classb_crashdump_trigger_shadowed_we = addr_hit[71] & reg_we & !reg_error; - - assign classb_crashdump_trigger_shadowed_wd = reg_wdata[1:0]; - assign classb_phase0_cyc_shadowed_re = addr_hit[72] & reg_re & !reg_error; - assign classb_phase0_cyc_shadowed_we = addr_hit[72] & reg_we & !reg_error; - - assign classb_phase0_cyc_shadowed_wd = reg_wdata[31:0]; - assign classb_phase1_cyc_shadowed_re = addr_hit[73] & reg_re & !reg_error; - assign classb_phase1_cyc_shadowed_we = addr_hit[73] & reg_we & !reg_error; - - assign classb_phase1_cyc_shadowed_wd = reg_wdata[31:0]; - assign classb_phase2_cyc_shadowed_re = addr_hit[74] & reg_re & !reg_error; - assign classb_phase2_cyc_shadowed_we = addr_hit[74] & reg_we & !reg_error; - - assign classb_phase2_cyc_shadowed_wd = reg_wdata[31:0]; - assign classb_phase3_cyc_shadowed_re = addr_hit[75] & reg_re & !reg_error; - assign classb_phase3_cyc_shadowed_we = addr_hit[75] & reg_we & !reg_error; - - assign classb_phase3_cyc_shadowed_wd = reg_wdata[31:0]; - assign classb_esc_cnt_re = addr_hit[76] & reg_re & !reg_error; - assign classb_state_re = addr_hit[77] & reg_re & !reg_error; - assign classc_regwen_we = addr_hit[78] & reg_we & !reg_error; - - assign classc_regwen_wd = reg_wdata[0]; - assign classc_ctrl_shadowed_re = addr_hit[79] & reg_re & !reg_error; - assign classc_ctrl_shadowed_we = addr_hit[79] & reg_we & !reg_error; - - assign classc_ctrl_shadowed_en_wd = reg_wdata[0]; - - assign classc_ctrl_shadowed_lock_wd = reg_wdata[1]; - - assign classc_ctrl_shadowed_en_e0_wd = reg_wdata[2]; - - assign classc_ctrl_shadowed_en_e1_wd = reg_wdata[3]; - - assign classc_ctrl_shadowed_en_e2_wd = reg_wdata[4]; - - assign classc_ctrl_shadowed_en_e3_wd = reg_wdata[5]; - - assign classc_ctrl_shadowed_map_e0_wd = reg_wdata[7:6]; - - assign classc_ctrl_shadowed_map_e1_wd = reg_wdata[9:8]; - - assign classc_ctrl_shadowed_map_e2_wd = reg_wdata[11:10]; - - assign classc_ctrl_shadowed_map_e3_wd = reg_wdata[13:12]; - assign classc_clr_regwen_we = addr_hit[80] & reg_we & !reg_error; - - assign classc_clr_regwen_wd = reg_wdata[0]; - assign classc_clr_shadowed_re = addr_hit[81] & reg_re & !reg_error; - assign classc_clr_shadowed_we = addr_hit[81] & reg_we & !reg_error; - - assign classc_clr_shadowed_wd = reg_wdata[0]; - assign classc_accum_cnt_re = addr_hit[82] & reg_re & !reg_error; - assign classc_accum_thresh_shadowed_re = addr_hit[83] & reg_re & !reg_error; - assign classc_accum_thresh_shadowed_we = addr_hit[83] & reg_we & !reg_error; - - assign classc_accum_thresh_shadowed_wd = reg_wdata[15:0]; - assign classc_timeout_cyc_shadowed_re = addr_hit[84] & reg_re & !reg_error; - assign classc_timeout_cyc_shadowed_we = addr_hit[84] & reg_we & !reg_error; - - assign classc_timeout_cyc_shadowed_wd = reg_wdata[31:0]; - assign classc_crashdump_trigger_shadowed_re = addr_hit[85] & reg_re & !reg_error; - assign classc_crashdump_trigger_shadowed_we = addr_hit[85] & reg_we & !reg_error; - - assign classc_crashdump_trigger_shadowed_wd = reg_wdata[1:0]; - assign classc_phase0_cyc_shadowed_re = addr_hit[86] & reg_re & !reg_error; - assign classc_phase0_cyc_shadowed_we = addr_hit[86] & reg_we & !reg_error; - - assign classc_phase0_cyc_shadowed_wd = reg_wdata[31:0]; - assign classc_phase1_cyc_shadowed_re = addr_hit[87] & reg_re & !reg_error; - assign classc_phase1_cyc_shadowed_we = addr_hit[87] & reg_we & !reg_error; - - assign classc_phase1_cyc_shadowed_wd = reg_wdata[31:0]; - assign classc_phase2_cyc_shadowed_re = addr_hit[88] & reg_re & !reg_error; - assign classc_phase2_cyc_shadowed_we = addr_hit[88] & reg_we & !reg_error; - - assign classc_phase2_cyc_shadowed_wd = reg_wdata[31:0]; - assign classc_phase3_cyc_shadowed_re = addr_hit[89] & reg_re & !reg_error; - assign classc_phase3_cyc_shadowed_we = addr_hit[89] & reg_we & !reg_error; - - assign classc_phase3_cyc_shadowed_wd = reg_wdata[31:0]; - assign classc_esc_cnt_re = addr_hit[90] & reg_re & !reg_error; - assign classc_state_re = addr_hit[91] & reg_re & !reg_error; - assign classd_regwen_we = addr_hit[92] & reg_we & !reg_error; - - assign classd_regwen_wd = reg_wdata[0]; - assign classd_ctrl_shadowed_re = addr_hit[93] & reg_re & !reg_error; - assign classd_ctrl_shadowed_we = addr_hit[93] & reg_we & !reg_error; - - assign classd_ctrl_shadowed_en_wd = reg_wdata[0]; - - assign classd_ctrl_shadowed_lock_wd = reg_wdata[1]; - - assign classd_ctrl_shadowed_en_e0_wd = reg_wdata[2]; - - assign classd_ctrl_shadowed_en_e1_wd = reg_wdata[3]; - - assign classd_ctrl_shadowed_en_e2_wd = reg_wdata[4]; - - assign classd_ctrl_shadowed_en_e3_wd = reg_wdata[5]; - - assign classd_ctrl_shadowed_map_e0_wd = reg_wdata[7:6]; - - assign classd_ctrl_shadowed_map_e1_wd = reg_wdata[9:8]; - - assign classd_ctrl_shadowed_map_e2_wd = reg_wdata[11:10]; - - assign classd_ctrl_shadowed_map_e3_wd = reg_wdata[13:12]; - assign classd_clr_regwen_we = addr_hit[94] & reg_we & !reg_error; - - assign classd_clr_regwen_wd = reg_wdata[0]; - assign classd_clr_shadowed_re = addr_hit[95] & reg_re & !reg_error; - assign classd_clr_shadowed_we = addr_hit[95] & reg_we & !reg_error; - - assign classd_clr_shadowed_wd = reg_wdata[0]; - assign classd_accum_cnt_re = addr_hit[96] & reg_re & !reg_error; - assign classd_accum_thresh_shadowed_re = addr_hit[97] & reg_re & !reg_error; - assign classd_accum_thresh_shadowed_we = addr_hit[97] & reg_we & !reg_error; - - assign classd_accum_thresh_shadowed_wd = reg_wdata[15:0]; - assign classd_timeout_cyc_shadowed_re = addr_hit[98] & reg_re & !reg_error; - assign classd_timeout_cyc_shadowed_we = addr_hit[98] & reg_we & !reg_error; - - assign classd_timeout_cyc_shadowed_wd = reg_wdata[31:0]; - assign classd_crashdump_trigger_shadowed_re = addr_hit[99] & reg_re & !reg_error; - assign classd_crashdump_trigger_shadowed_we = addr_hit[99] & reg_we & !reg_error; - - assign classd_crashdump_trigger_shadowed_wd = reg_wdata[1:0]; - assign classd_phase0_cyc_shadowed_re = addr_hit[100] & reg_re & !reg_error; - assign classd_phase0_cyc_shadowed_we = addr_hit[100] & reg_we & !reg_error; - - assign classd_phase0_cyc_shadowed_wd = reg_wdata[31:0]; - assign classd_phase1_cyc_shadowed_re = addr_hit[101] & reg_re & !reg_error; - assign classd_phase1_cyc_shadowed_we = addr_hit[101] & reg_we & !reg_error; - - assign classd_phase1_cyc_shadowed_wd = reg_wdata[31:0]; - assign classd_phase2_cyc_shadowed_re = addr_hit[102] & reg_re & !reg_error; - assign classd_phase2_cyc_shadowed_we = addr_hit[102] & reg_we & !reg_error; - - assign classd_phase2_cyc_shadowed_wd = reg_wdata[31:0]; - assign classd_phase3_cyc_shadowed_re = addr_hit[103] & reg_re & !reg_error; - assign classd_phase3_cyc_shadowed_we = addr_hit[103] & reg_we & !reg_error; - - assign classd_phase3_cyc_shadowed_wd = reg_wdata[31:0]; - assign classd_esc_cnt_re = addr_hit[104] & reg_re & !reg_error; - assign classd_state_re = addr_hit[105] & reg_re & !reg_error; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = intr_state_classa_qs; - reg_rdata_next[1] = intr_state_classb_qs; - reg_rdata_next[2] = intr_state_classc_qs; - reg_rdata_next[3] = intr_state_classd_qs; - end - - addr_hit[1]: begin - reg_rdata_next[0] = intr_enable_classa_qs; - reg_rdata_next[1] = intr_enable_classb_qs; - reg_rdata_next[2] = intr_enable_classc_qs; - reg_rdata_next[3] = intr_enable_classd_qs; - end - - addr_hit[2]: begin - reg_rdata_next[0] = '0; - reg_rdata_next[1] = '0; - reg_rdata_next[2] = '0; - reg_rdata_next[3] = '0; - end - - addr_hit[3]: begin - reg_rdata_next[0] = ping_timer_regwen_qs; - end - - addr_hit[4]: begin - reg_rdata_next[15:0] = ping_timeout_cyc_shadowed_qs; - end - - addr_hit[5]: begin - reg_rdata_next[0] = ping_timer_en_shadowed_qs; - end - - addr_hit[6]: begin - reg_rdata_next[0] = alert_regwen_0_qs; - end - - addr_hit[7]: begin - reg_rdata_next[0] = alert_regwen_1_qs; - end - - addr_hit[8]: begin - reg_rdata_next[0] = alert_regwen_2_qs; - end - - addr_hit[9]: begin - reg_rdata_next[0] = alert_regwen_3_qs; - end - - addr_hit[10]: begin - reg_rdata_next[0] = alert_en_shadowed_0_qs; - end - - addr_hit[11]: begin - reg_rdata_next[0] = alert_en_shadowed_1_qs; - end - - addr_hit[12]: begin - reg_rdata_next[0] = alert_en_shadowed_2_qs; - end - - addr_hit[13]: begin - reg_rdata_next[0] = alert_en_shadowed_3_qs; - end - - addr_hit[14]: begin - reg_rdata_next[1:0] = alert_class_shadowed_0_qs; - end - - addr_hit[15]: begin - reg_rdata_next[1:0] = alert_class_shadowed_1_qs; - end - - addr_hit[16]: begin - reg_rdata_next[1:0] = alert_class_shadowed_2_qs; - end - - addr_hit[17]: begin - reg_rdata_next[1:0] = alert_class_shadowed_3_qs; - end - - addr_hit[18]: begin - reg_rdata_next[0] = alert_cause_0_qs; - end - - addr_hit[19]: begin - reg_rdata_next[0] = alert_cause_1_qs; - end - - addr_hit[20]: begin - reg_rdata_next[0] = alert_cause_2_qs; - end - - addr_hit[21]: begin - reg_rdata_next[0] = alert_cause_3_qs; - end - - addr_hit[22]: begin - reg_rdata_next[0] = loc_alert_regwen_0_qs; - end - - addr_hit[23]: begin - reg_rdata_next[0] = loc_alert_regwen_1_qs; - end - - addr_hit[24]: begin - reg_rdata_next[0] = loc_alert_regwen_2_qs; - end - - addr_hit[25]: begin - reg_rdata_next[0] = loc_alert_regwen_3_qs; - end - - addr_hit[26]: begin - reg_rdata_next[0] = loc_alert_regwen_4_qs; - end - - addr_hit[27]: begin - reg_rdata_next[0] = loc_alert_regwen_5_qs; - end - - addr_hit[28]: begin - reg_rdata_next[0] = loc_alert_regwen_6_qs; - end - - addr_hit[29]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_0_qs; - end - - addr_hit[30]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_1_qs; - end - - addr_hit[31]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_2_qs; - end - - addr_hit[32]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_3_qs; - end - - addr_hit[33]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_4_qs; - end - - addr_hit[34]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_5_qs; - end - - addr_hit[35]: begin - reg_rdata_next[0] = loc_alert_en_shadowed_6_qs; - end - - addr_hit[36]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_0_qs; - end - - addr_hit[37]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_1_qs; - end - - addr_hit[38]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_2_qs; - end - - addr_hit[39]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_3_qs; - end - - addr_hit[40]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_4_qs; - end - - addr_hit[41]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_5_qs; - end - - addr_hit[42]: begin - reg_rdata_next[1:0] = loc_alert_class_shadowed_6_qs; - end - - addr_hit[43]: begin - reg_rdata_next[0] = loc_alert_cause_0_qs; - end - - addr_hit[44]: begin - reg_rdata_next[0] = loc_alert_cause_1_qs; - end - - addr_hit[45]: begin - reg_rdata_next[0] = loc_alert_cause_2_qs; - end - - addr_hit[46]: begin - reg_rdata_next[0] = loc_alert_cause_3_qs; - end - - addr_hit[47]: begin - reg_rdata_next[0] = loc_alert_cause_4_qs; - end - - addr_hit[48]: begin - reg_rdata_next[0] = loc_alert_cause_5_qs; - end - - addr_hit[49]: begin - reg_rdata_next[0] = loc_alert_cause_6_qs; - end - - addr_hit[50]: begin - reg_rdata_next[0] = classa_regwen_qs; - end - - addr_hit[51]: begin - reg_rdata_next[0] = classa_ctrl_shadowed_en_qs; - reg_rdata_next[1] = classa_ctrl_shadowed_lock_qs; - reg_rdata_next[2] = classa_ctrl_shadowed_en_e0_qs; - reg_rdata_next[3] = classa_ctrl_shadowed_en_e1_qs; - reg_rdata_next[4] = classa_ctrl_shadowed_en_e2_qs; - reg_rdata_next[5] = classa_ctrl_shadowed_en_e3_qs; - reg_rdata_next[7:6] = classa_ctrl_shadowed_map_e0_qs; - reg_rdata_next[9:8] = classa_ctrl_shadowed_map_e1_qs; - reg_rdata_next[11:10] = classa_ctrl_shadowed_map_e2_qs; - reg_rdata_next[13:12] = classa_ctrl_shadowed_map_e3_qs; - end - - addr_hit[52]: begin - reg_rdata_next[0] = classa_clr_regwen_qs; - end - - addr_hit[53]: begin - reg_rdata_next[0] = classa_clr_shadowed_qs; - end - - addr_hit[54]: begin - reg_rdata_next[15:0] = classa_accum_cnt_qs; - end - - addr_hit[55]: begin - reg_rdata_next[15:0] = classa_accum_thresh_shadowed_qs; - end - - addr_hit[56]: begin - reg_rdata_next[31:0] = classa_timeout_cyc_shadowed_qs; - end - - addr_hit[57]: begin - reg_rdata_next[1:0] = classa_crashdump_trigger_shadowed_qs; - end - - addr_hit[58]: begin - reg_rdata_next[31:0] = classa_phase0_cyc_shadowed_qs; - end - - addr_hit[59]: begin - reg_rdata_next[31:0] = classa_phase1_cyc_shadowed_qs; - end - - addr_hit[60]: begin - reg_rdata_next[31:0] = classa_phase2_cyc_shadowed_qs; - end - - addr_hit[61]: begin - reg_rdata_next[31:0] = classa_phase3_cyc_shadowed_qs; - end - - addr_hit[62]: begin - reg_rdata_next[31:0] = classa_esc_cnt_qs; - end - - addr_hit[63]: begin - reg_rdata_next[2:0] = classa_state_qs; - end - - addr_hit[64]: begin - reg_rdata_next[0] = classb_regwen_qs; - end - - addr_hit[65]: begin - reg_rdata_next[0] = classb_ctrl_shadowed_en_qs; - reg_rdata_next[1] = classb_ctrl_shadowed_lock_qs; - reg_rdata_next[2] = classb_ctrl_shadowed_en_e0_qs; - reg_rdata_next[3] = classb_ctrl_shadowed_en_e1_qs; - reg_rdata_next[4] = classb_ctrl_shadowed_en_e2_qs; - reg_rdata_next[5] = classb_ctrl_shadowed_en_e3_qs; - reg_rdata_next[7:6] = classb_ctrl_shadowed_map_e0_qs; - reg_rdata_next[9:8] = classb_ctrl_shadowed_map_e1_qs; - reg_rdata_next[11:10] = classb_ctrl_shadowed_map_e2_qs; - reg_rdata_next[13:12] = classb_ctrl_shadowed_map_e3_qs; - end - - addr_hit[66]: begin - reg_rdata_next[0] = classb_clr_regwen_qs; - end - - addr_hit[67]: begin - reg_rdata_next[0] = classb_clr_shadowed_qs; - end - - addr_hit[68]: begin - reg_rdata_next[15:0] = classb_accum_cnt_qs; - end - - addr_hit[69]: begin - reg_rdata_next[15:0] = classb_accum_thresh_shadowed_qs; - end - - addr_hit[70]: begin - reg_rdata_next[31:0] = classb_timeout_cyc_shadowed_qs; - end - - addr_hit[71]: begin - reg_rdata_next[1:0] = classb_crashdump_trigger_shadowed_qs; - end - - addr_hit[72]: begin - reg_rdata_next[31:0] = classb_phase0_cyc_shadowed_qs; - end - - addr_hit[73]: begin - reg_rdata_next[31:0] = classb_phase1_cyc_shadowed_qs; - end - - addr_hit[74]: begin - reg_rdata_next[31:0] = classb_phase2_cyc_shadowed_qs; - end - - addr_hit[75]: begin - reg_rdata_next[31:0] = classb_phase3_cyc_shadowed_qs; - end - - addr_hit[76]: begin - reg_rdata_next[31:0] = classb_esc_cnt_qs; - end - - addr_hit[77]: begin - reg_rdata_next[2:0] = classb_state_qs; - end - - addr_hit[78]: begin - reg_rdata_next[0] = classc_regwen_qs; - end - - addr_hit[79]: begin - reg_rdata_next[0] = classc_ctrl_shadowed_en_qs; - reg_rdata_next[1] = classc_ctrl_shadowed_lock_qs; - reg_rdata_next[2] = classc_ctrl_shadowed_en_e0_qs; - reg_rdata_next[3] = classc_ctrl_shadowed_en_e1_qs; - reg_rdata_next[4] = classc_ctrl_shadowed_en_e2_qs; - reg_rdata_next[5] = classc_ctrl_shadowed_en_e3_qs; - reg_rdata_next[7:6] = classc_ctrl_shadowed_map_e0_qs; - reg_rdata_next[9:8] = classc_ctrl_shadowed_map_e1_qs; - reg_rdata_next[11:10] = classc_ctrl_shadowed_map_e2_qs; - reg_rdata_next[13:12] = classc_ctrl_shadowed_map_e3_qs; - end - - addr_hit[80]: begin - reg_rdata_next[0] = classc_clr_regwen_qs; - end - - addr_hit[81]: begin - reg_rdata_next[0] = classc_clr_shadowed_qs; - end - - addr_hit[82]: begin - reg_rdata_next[15:0] = classc_accum_cnt_qs; - end - - addr_hit[83]: begin - reg_rdata_next[15:0] = classc_accum_thresh_shadowed_qs; - end - - addr_hit[84]: begin - reg_rdata_next[31:0] = classc_timeout_cyc_shadowed_qs; - end - - addr_hit[85]: begin - reg_rdata_next[1:0] = classc_crashdump_trigger_shadowed_qs; - end - - addr_hit[86]: begin - reg_rdata_next[31:0] = classc_phase0_cyc_shadowed_qs; - end - - addr_hit[87]: begin - reg_rdata_next[31:0] = classc_phase1_cyc_shadowed_qs; - end - - addr_hit[88]: begin - reg_rdata_next[31:0] = classc_phase2_cyc_shadowed_qs; - end - - addr_hit[89]: begin - reg_rdata_next[31:0] = classc_phase3_cyc_shadowed_qs; - end - - addr_hit[90]: begin - reg_rdata_next[31:0] = classc_esc_cnt_qs; - end - - addr_hit[91]: begin - reg_rdata_next[2:0] = classc_state_qs; - end - - addr_hit[92]: begin - reg_rdata_next[0] = classd_regwen_qs; - end - - addr_hit[93]: begin - reg_rdata_next[0] = classd_ctrl_shadowed_en_qs; - reg_rdata_next[1] = classd_ctrl_shadowed_lock_qs; - reg_rdata_next[2] = classd_ctrl_shadowed_en_e0_qs; - reg_rdata_next[3] = classd_ctrl_shadowed_en_e1_qs; - reg_rdata_next[4] = classd_ctrl_shadowed_en_e2_qs; - reg_rdata_next[5] = classd_ctrl_shadowed_en_e3_qs; - reg_rdata_next[7:6] = classd_ctrl_shadowed_map_e0_qs; - reg_rdata_next[9:8] = classd_ctrl_shadowed_map_e1_qs; - reg_rdata_next[11:10] = classd_ctrl_shadowed_map_e2_qs; - reg_rdata_next[13:12] = classd_ctrl_shadowed_map_e3_qs; - end - - addr_hit[94]: begin - reg_rdata_next[0] = classd_clr_regwen_qs; - end - - addr_hit[95]: begin - reg_rdata_next[0] = classd_clr_shadowed_qs; - end - - addr_hit[96]: begin - reg_rdata_next[15:0] = classd_accum_cnt_qs; - end - - addr_hit[97]: begin - reg_rdata_next[15:0] = classd_accum_thresh_shadowed_qs; - end - - addr_hit[98]: begin - reg_rdata_next[31:0] = classd_timeout_cyc_shadowed_qs; - end - - addr_hit[99]: begin - reg_rdata_next[1:0] = classd_crashdump_trigger_shadowed_qs; - end - - addr_hit[100]: begin - reg_rdata_next[31:0] = classd_phase0_cyc_shadowed_qs; - end - - addr_hit[101]: begin - reg_rdata_next[31:0] = classd_phase1_cyc_shadowed_qs; - end - - addr_hit[102]: begin - reg_rdata_next[31:0] = classd_phase2_cyc_shadowed_qs; - end - - addr_hit[103]: begin - reg_rdata_next[31:0] = classd_phase3_cyc_shadowed_qs; - end - - addr_hit[104]: begin - reg_rdata_next[31:0] = classd_esc_cnt_qs; - end - - addr_hit[105]: begin - reg_rdata_next[2:0] = classd_state_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // shadow busy - logic shadow_busy; - logic rst_done; - logic shadow_rst_done; - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rst_done <= '0; - end else begin - rst_done <= 1'b1; - end - end - - always_ff @(posedge clk_i or negedge rst_shadowed_ni) begin - if (!rst_shadowed_ni) begin - shadow_rst_done <= '0; - end else begin - shadow_rst_done <= 1'b1; - end - end - - // both shadow and normal resets have been released - assign shadow_busy = ~(rst_done & shadow_rst_done); - - // register busy - logic reg_busy_sel; - assign reg_busy = reg_busy_sel | shadow_busy; - always_comb begin - reg_busy_sel = '0; - unique case (1'b1) - default: begin - reg_busy_sel = '0; - end - endcase - end - - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni) - `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni) - - `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o_pre.d_valid, clk_i, !rst_ni) - - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni) - - // this is formulated as an assumption such that the FPV testbenches do disprove this - // property by mistake - //`ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.chk_en == tlul_pkg::CheckDis) - -endmodule diff --git a/hw/ip/alert_handler/util/reg_alert_handler.py b/hw/ip/alert_handler/util/reg_alert_handler.py deleted file mode 100755 index f97d91b64007c..0000000000000 --- a/hw/ip/alert_handler/util/reg_alert_handler.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python3 -# Copyright lowRISC contributors. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 -r"""Convert mako template to Hjson register description -""" -import argparse -import sys -from io import StringIO - -from mako.template import Template - - -def main(): - parser = argparse.ArgumentParser(prog="reg_alert_handler") - parser.add_argument('input', - nargs='?', - metavar='file', - type=argparse.FileType('r'), - default=sys.stdin, - help='input template file') - parser.add_argument('--n_alerts', - type=int, - default=4, - help='Number of alert sources') - parser.add_argument('--esc_cnt_dw', - type=int, - default=32, - help='Width of escalation counter') - parser.add_argument('--accu_cnt_dw', - type=int, - default=16, - help='Width of accumulator') - - # can currently not be overridden with this script - n_lpg = 1 - lpg_map = ["1'b0"] - async_on = ["'0"] - - args = parser.parse_args() - - # Determine output: if stdin then stdout if not then ?? - out = StringIO() - - reg_tpl = Template(args.input.read()) - out.write( - reg_tpl.render(n_alerts=args.n_alerts, - esc_cnt_dw=args.esc_cnt_dw, - accu_cnt_dw=args.accu_cnt_dw, - async_on=async_on, - n_lpg=n_lpg, - lpg_map=lpg_map, - n_classes=4)) # leave this constant for now - - print(out.getvalue()) - - out.close() - - -if __name__ == "__main__": - main() diff --git a/hw/ip/lc_ctrl/doc/_index.md b/hw/ip/lc_ctrl/doc/_index.md index d528f408962aa..9fb1a355e7188 100644 --- a/hw/ip/lc_ctrl/doc/_index.md +++ b/hw/ip/lc_ctrl/doc/_index.md @@ -25,7 +25,7 @@ The life cycle controller provides the following features: - A CSR and a JTAG interface for initiating life cycle transitions. - Dedicated concurrent decoding of the redundant life cycle state and broadcasting of redundantly encoded life cycle qualification signals (e.g., to enable DFT features or the main processor). - A token hashing and matching mechanism to guard important life cycle transitions. -- An escalation receiver for the alert subsystem, which allows to invalidate the life cycle state as part of an escalation sequence (see also [alert handler subsystem]({{< relref "hw/ip/alert_handler/doc" >}})). +- An escalation receiver for the alert subsystem, which allows to invalidate the life cycle state as part of an escalation sequence (see also alert handler subsystem). ## Prelude - Why Not Software? @@ -123,7 +123,7 @@ This general policy places a time-bound on how quickly life cycle states can cha ## Security Escalation -The life cycle controller contains two escalation paths that are connected to [escalation severities 1 and 2 of the alert handler]({{< relref "hw/ip/alert_handler/doc/_index.md#escalation-signaling" >}}). +The life cycle controller contains two escalation paths that are connected to escalation severities 1 and 2 of the alert handler. The two escalation paths are redundant, and both trigger the same mechanism. Upon assertion of any of the two escalation actions, the life cycle state is **TEMPORARILY** altered. @@ -131,7 +131,7 @@ I.e. when this escalation path is triggered, the life cycle state is transitione This causes [all decoded outputs]({{< relref "#life-cycle-decoded-outputs-and-controls" >}}) to be disabled until the next power cycle. In addition to that, the life cycle controller asserts the ESCALATE_EN life cycle signal which is distributed to all IPs in the design that expose an escalation action (like moving FSMs into terminal error states or clearing sensitive registers). -Whether to escalate to the life cycle controller or not is a software decision, please see the [alert handler]({{< relref "hw/ip/alert_handler/doc/_index.md" >}}) for more details. +Whether to escalate to the life cycle controller or not is a software decision, please see the alert handler for more details. ## Life Cycle Decoded Outputs and Controls @@ -484,7 +484,7 @@ Note that the two additional life cycle control signals `lc_flash_rma_req_o` and The life cycle controller contains a JTAG TAP that can be used to access the same CSR space that is accessible via TL-UL. In order to write to the CSRs, a [hardware mutex]({{< relref "#hardware-mutex" >}}) has to be claimed. -The life cycle controller also contains two escalation receivers that are connected to escalation severity 1 and 2 of the [alert handler module]({{< relref "hw/ip/alert_handler/doc" >}}). +The life cycle controller also contains two escalation receivers that are connected to escalation severity 1 and 2 of the alert handler module. The actions that are triggered by these escalation receivers are explained in the [escalation handling section]({{< relref "#escalation-handling" >}}) below. ### System Integration @@ -565,7 +565,7 @@ Note that an initiated life cycle transition request always ends in `PostTransSt #### Escalation Handling -The life cycle controller contains two escalation channels that are connected to the [alert handler]({{< relref "hw/ip/alert_handler/doc" >}}). +The life cycle controller contains two escalation channels that are connected to the alert handler. When the first channel `esc_wipe_secrets` is asserted, the life cycle controller permanently asserts the `lc_escalate_en` life cycle signal. That signal is routed to various security modules in OpenTitan and triggers local wiping and invalidation features. @@ -670,4 +670,3 @@ It is expected that the JTAG TAP interface is used to access the life cycle tran ## Register Table {{< incGenFromIpDesc "../data/lc_ctrl.hjson" "registers" >}} - diff --git a/hw/ip/lc_ctrl/lc_ctrl.core b/hw/ip/lc_ctrl/lc_ctrl.core index 64b8e9d77c747..478a0e180e33d 100644 --- a/hw/ip/lc_ctrl/lc_ctrl.core +++ b/hw/ip/lc_ctrl/lc_ctrl.core @@ -20,7 +20,7 @@ filesets: - lowrisc:ip:otp_ctrl_pkg - lowrisc:ip:kmac_pkg - lowrisc:ip:rv_dm - - lowrisc:ip:alert_handler_reg + - lowrisc:ip_interfaces:alert_handler_reg files: - rtl/lc_ctrl_reg_top.sv - rtl/lc_ctrl_state_decode.sv diff --git a/hw/ip/pwrmgr/pwrmgr.core b/hw/ip/pwrmgr/pwrmgr.core index 4b9fdcfee3c6c..0f24740f10e54 100644 --- a/hw/ip/pwrmgr/pwrmgr.core +++ b/hw/ip/pwrmgr/pwrmgr.core @@ -15,7 +15,7 @@ filesets: - lowrisc:ip:rom_ctrl_pkg - lowrisc:ip:lc_ctrl_pkg - lowrisc:ip:pwrmgr_pkg - - lowrisc:ip:alert_handler_reg + - lowrisc:ip_interfaces:alert_handler_reg files: - rtl/pwrmgr.sv - rtl/pwrmgr_cdc.sv diff --git a/hw/ip/rstmgr/doc/_index.md b/hw/ip/rstmgr/doc/_index.md index 2281d40d28536..37e793d7e0426 100644 --- a/hw/ip/rstmgr/doc/_index.md +++ b/hw/ip/rstmgr/doc/_index.md @@ -109,7 +109,7 @@ This separation is required because the non-volatile controllers (OTP / Lifecycl If these modules are reset along with the rest of the system, the TAP and related debug functions would also be reset. By keeping these reset trees separate, we allow the state of the test domain functions to persist while functionally resetting the rest of the core domain. -Additionally, modules such as [alert handler]({{< relref "hw/ip/alert_handler/doc" >}}) and [aon timers]() (which contain the watchdog function) are also kept on the `rst_lc_n` tree. +Additionally, modules such as alert handler and [aon timers]() (which contain the watchdog function) are also kept on the `rst_lc_n` tree. This ensures that an erroneously requested system reset through `rst_sys_n` cannot silence the alert mechanism or prevent the system from triggering a watchdog mechanism. The reset topology also contains additional properties: diff --git a/hw/ip/rstmgr/rstmgr_pkg.core b/hw/ip/rstmgr/rstmgr_pkg.core index 189859a401f8d..2bafee693b1f2 100644 --- a/hw/ip/rstmgr/rstmgr_pkg.core +++ b/hw/ip/rstmgr/rstmgr_pkg.core @@ -10,7 +10,7 @@ filesets: depend: - lowrisc:ip:pwrmgr_pkg - lowrisc:ip:rstmgr_reg - - lowrisc:ip:alert_handler_reg + - lowrisc:ip_interfaces:alert_handler_reg - lowrisc:ip:alert_handler_component - lowrisc:ibex:ibex_pkg - "fileset_top ? (lowrisc:systems:rstmgr_pkg)" diff --git a/hw/ip/rv_core_ibex/rv_core_ibex.core b/hw/ip/rv_core_ibex/rv_core_ibex.core index e48add5811968..ec4903e8bf0a9 100644 --- a/hw/ip/rv_core_ibex/rv_core_ibex.core +++ b/hw/ip/rv_core_ibex/rv_core_ibex.core @@ -15,7 +15,7 @@ filesets: - lowrisc:tlul:adapter_host - lowrisc:ip:lc_ctrl_pkg - lowrisc:prim:lc_sync - - lowrisc:ip:alert_handler_reg + - lowrisc:ip_interfaces:alert_handler_reg - lowrisc:ip:pwrmgr_pkg files: diff --git a/hw/ip_templates/alert_handler/alert_handler.core.tpl b/hw/ip_templates/alert_handler/alert_handler.core.tpl new file mode 100644 index 0000000000000..46454477a66cc --- /dev/null +++ b/hw/ip_templates/alert_handler/alert_handler.core.tpl @@ -0,0 +1,38 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: ${instance_vlnv("lowrisc:ip:alert_handler:0.1")} +description: "Alert Handler" +virtual: + - lowrisc:ip_interfaces:alert_handler + +filesets: + files_rtl: + depend: + - lowrisc:ip:alert_handler_component + - ${instance_vlnv("lowrisc:ip_interfaces:alert_handler_reg:0.1")} + file_type: systemVerilogSource + +parameters: + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + +targets: + default: &default_target + filesets: + - files_rtl + toplevel: alert_handler + + lint: + <<: *default_target + default_tool: verilator + parameters: + - SYNTHESIS=true + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" diff --git a/hw/ip/alert_handler/alert_handler_component.core b/hw/ip_templates/alert_handler/alert_handler_component.core similarity index 96% rename from hw/ip/alert_handler/alert_handler_component.core rename to hw/ip_templates/alert_handler/alert_handler_component.core index 913221307e542..e543eb0374173 100644 --- a/hw/ip/alert_handler/alert_handler_component.core +++ b/hw/ip_templates/alert_handler/alert_handler_component.core @@ -15,7 +15,7 @@ filesets: - lowrisc:prim:edn_req - lowrisc:prim:buf - lowrisc:prim:mubi - - "fileset_topgen ? (lowrisc:systems:topgen-reg-only)" + - lowrisc:ip_interfaces:alert_handler_reg files: - rtl/alert_pkg.sv - rtl/alert_handler_reg_wrap.sv diff --git a/hw/ip_templates/alert_handler/alert_handler_reg.core.tpl b/hw/ip_templates/alert_handler/alert_handler_reg.core.tpl new file mode 100644 index 0000000000000..922ff9e0c22f8 --- /dev/null +++ b/hw/ip_templates/alert_handler/alert_handler_reg.core.tpl @@ -0,0 +1,27 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: ${instance_vlnv("lowrisc:ip:alert_handler_reg:0.1")} +description: "Auto-generated alert handler register sources" +virtual: + # TODO: Check if the generated files actually maintain a stable public API. + - "lowrisc:ip_interfaces:alert_handler_reg" + +filesets: + files_rtl: + depend: + - lowrisc:tlul:headers + - lowrisc:prim:subreg + - lowrisc:ip:tlul + - lowrisc:prim:subreg + files: + - rtl/alert_handler_reg_pkg.sv + - rtl/alert_handler_reg_top.sv + file_type: systemVerilogSource + + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/ip/alert_handler/data/alert_handler.hjson.tpl b/hw/ip_templates/alert_handler/data/alert_handler.hjson.tpl similarity index 100% rename from hw/ip/alert_handler/data/alert_handler.hjson.tpl rename to hw/ip_templates/alert_handler/data/alert_handler.hjson.tpl diff --git a/hw/ip/alert_handler/data/alert_handler.prj.hjson b/hw/ip_templates/alert_handler/data/alert_handler.prj.hjson similarity index 100% rename from hw/ip/alert_handler/data/alert_handler.prj.hjson rename to hw/ip_templates/alert_handler/data/alert_handler.prj.hjson diff --git a/hw/ip_templates/alert_handler/data/alert_handler.tpldesc.hjson b/hw/ip_templates/alert_handler/data/alert_handler.tpldesc.hjson new file mode 100644 index 0000000000000..7c604a81ca72c --- /dev/null +++ b/hw/ip_templates/alert_handler/data/alert_handler.tpldesc.hjson @@ -0,0 +1,49 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ + "template_param_list": [ + { + "name": "n_alerts", + "desc": "Number of alert sources", + "type": "int", + "default": 4 + }, + { + "name": "esc_cnt_dw", + "desc": "Width of escalation counter", + "type": "int", + "default": 32 + }, + { + "name": "accu_cnt_dw", + "desc": "Width of accumulator" + "type": "int" + "default": 16 + }, + { + "name": "async_on", + "desc": "Enables asynchronous sygnalling between specific alert RX/TX pairs" + "type": "object" + "default": [] + }, + { + "name": "n_classes", + "desc": "Number of supported classes (leave this at 4 at the moment)" + "type": "int" + "default": 4 + }, + { + "name": "n_lpg", + "desc": "Number of LPGs" + "type": "int" + "default": 1 + }, + { + "name": "lpg_map", + "desc": "Encodes the alert to LPG mapping" + "type": "object" + "default": [] + }, + ], +} diff --git a/hw/ip/alert_handler/data/alert_handler_testplan.hjson b/hw/ip_templates/alert_handler/data/alert_handler_testplan.hjson similarity index 100% rename from hw/ip/alert_handler/data/alert_handler_testplan.hjson rename to hw/ip_templates/alert_handler/data/alert_handler_testplan.hjson diff --git a/hw/ip/alert_handler/doc/_index.md b/hw/ip_templates/alert_handler/doc/_index.md similarity index 98% rename from hw/ip/alert_handler/doc/_index.md rename to hw/ip_templates/alert_handler/doc/_index.md index 350881dfc2586..5d568180d4c39 100644 --- a/hw/ip/alert_handler/doc/_index.md +++ b/hw/ip_templates/alert_handler/doc/_index.md @@ -113,7 +113,7 @@ Parameter | Default (Max) | Description ### Signals -{{< incGenFromIpDesc "/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson" "hwcfg" >}} +{{< incGenFromIpDesc "../data/alert_handler.hjson" "hwcfg" >}} The table below lists other alert handler module signals. The number of alert instances is parametric and hence alert and ping diff pairs are grouped together in packed arrays. @@ -952,18 +952,7 @@ However, alert accumulation will not be triggered by this testing mechanism. ## Register Table -The register description below matches the instance in the [Earl Grey top level design]({{< relref "hw/top_earlgrey/doc" >}}). - -A similar register description can be generated with the `reg_alert_handler.py` script. -The reason for having yet another script for register generation is that the alert handler is configurable for the number of alert sources (similar to the rv_plic design). - -In order to generate the register file for four alert sources, from `hw/ip/alert_handler/doc`: - -```console -$ ./reg_alert_handler.py alert_handler.hjson.tpl -n 4 > alert_handler.hjson -``` - -{{< incGenFromIpDesc "/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson" "registers" >}} +{{< incGenFromIpDesc "../data/alert_handler.hjson" "registers" >}} # Additional Notes diff --git a/hw/ip/alert_handler/doc/alert_handler_alert_rxtx.svg b/hw/ip_templates/alert_handler/doc/alert_handler_alert_rxtx.svg similarity index 100% rename from hw/ip/alert_handler/doc/alert_handler_alert_rxtx.svg rename to hw/ip_templates/alert_handler/doc/alert_handler_alert_rxtx.svg diff --git a/hw/ip/alert_handler/doc/alert_handler_block_diagram.svg b/hw/ip_templates/alert_handler/doc/alert_handler_block_diagram.svg similarity index 100% rename from hw/ip/alert_handler/doc/alert_handler_block_diagram.svg rename to hw/ip_templates/alert_handler/doc/alert_handler_block_diagram.svg diff --git a/hw/ip/alert_handler/doc/alert_handler_escalation_rxtx.svg b/hw/ip_templates/alert_handler/doc/alert_handler_escalation_rxtx.svg similarity index 100% rename from hw/ip/alert_handler/doc/alert_handler_escalation_rxtx.svg rename to hw/ip_templates/alert_handler/doc/alert_handler_escalation_rxtx.svg diff --git a/hw/ip/alert_handler/doc/checklist.md b/hw/ip_templates/alert_handler/doc/checklist.md similarity index 100% rename from hw/ip/alert_handler/doc/checklist.md rename to hw/ip_templates/alert_handler/doc/checklist.md diff --git a/hw/ip/alert_handler/doc/dv/index.md b/hw/ip_templates/alert_handler/doc/dv/index.md similarity index 100% rename from hw/ip/alert_handler/doc/dv/index.md rename to hw/ip_templates/alert_handler/doc/dv/index.md diff --git a/hw/ip/alert_handler/doc/dv/tb.svg b/hw/ip_templates/alert_handler/doc/dv/tb.svg similarity index 100% rename from hw/ip/alert_handler/doc/dv/tb.svg rename to hw/ip_templates/alert_handler/doc/dv/tb.svg diff --git a/hw/ip/alert_handler/dv/alert_handler_generic_sim.core b/hw/ip_templates/alert_handler/dv/alert_handler_sim.core.tpl similarity index 78% rename from hw/ip/alert_handler/dv/alert_handler_generic_sim.core rename to hw/ip_templates/alert_handler/dv/alert_handler_sim.core.tpl index 34502d352e588..af5d900dbbe99 100644 --- a/hw/ip/alert_handler/dv/alert_handler_generic_sim.core +++ b/hw/ip_templates/alert_handler/dv/alert_handler_sim.core.tpl @@ -2,18 +2,18 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:dv:alert_handler_generic_sim:0.1" +name: ${instance_vlnv("lowrisc:dv:alert_handler_sim:0.1")} description: "ALERT_HANDLER DV sim target" filesets: files_rtl: depend: - - lowrisc:ip:alert_handler:0.1 + - ${instance_vlnv("lowrisc:ip:alert_handler:0.1")} file_type: systemVerilogSource files_dv: depend: - lowrisc:dv:alert_handler_tb - - lowrisc:dv:alert_handler_sva + - ${instance_vlnv("lowrisc:dv:alert_handler_sva:0.1")} file_type: systemVerilogSource generate: diff --git a/hw/ip/alert_handler/dv/alert_handler_generic_sim_cfg.hjson b/hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl similarity index 92% rename from hw/ip/alert_handler/dv/alert_handler_generic_sim_cfg.hjson rename to hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl index 364ef9690d5ed..7dafab8e9f143 100644 --- a/hw/ip/alert_handler/dv/alert_handler_generic_sim_cfg.hjson +++ b/hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl @@ -15,10 +15,10 @@ tool: vcs // Fusesoc core file used for building the file list. - fusesoc_core: lowrisc:dv:alert_handler_generic_sim:0.1 + fusesoc_core: ${instance_vlnv("lowrisc:dv:alert_handler_sim:0.1")} // Testplan hjson file. - testplan: "{proj_root}/hw/ip/alert_handler/data/alert_handler_testplan.hjson" + testplan: "{self_dir}/../data/alert_handler_testplan.hjson" // Import additional common sim cfg files. import_cfgs: [// Project wide common sim cfg file @@ -37,7 +37,7 @@ reseed: 50 // Add ALERT_HANDLER specific exclusion files. - vcs_cov_excl_files: ["{proj_root}/hw/ip/alert_handler/dv/cov/alert_handler_cov_excl.el"] + vcs_cov_excl_files: ["{self_dir}/cov/alert_handler_cov_excl.el"] // Default UVM test and seq class name. uvm_test: alert_handler_base_test diff --git a/hw/ip/alert_handler/dv/cov/alert_handler_cov_excl.el b/hw/ip_templates/alert_handler/dv/cov/alert_handler_cov_excl.el similarity index 100% rename from hw/ip/alert_handler/dv/cov/alert_handler_cov_excl.el rename to hw/ip_templates/alert_handler/dv/cov/alert_handler_cov_excl.el diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env.core b/hw/ip_templates/alert_handler/dv/env/alert_handler_env.core similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_env.core rename to hw/ip_templates/alert_handler/dv/env/alert_handler_env.core diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_env.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_env.sv rename to hw/ip_templates/alert_handler/dv/env/alert_handler_env.sv diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_env_cfg.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv rename to hw/ip_templates/alert_handler/dv/env/alert_handler_env_cfg.sv diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env_cov.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_env_cov.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_env_cov.sv rename to hw/ip_templates/alert_handler/dv/env/alert_handler_env_cov.sv diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env_pkg.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_env_pkg.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_env_pkg.sv rename to hw/ip_templates/alert_handler/dv/env/alert_handler_env_pkg.sv diff --git a/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_scoreboard.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv rename to hw/ip_templates/alert_handler/dv/env/alert_handler_scoreboard.sv diff --git a/hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_virtual_sequencer.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv rename to hw/ip_templates/alert_handler/dv/env/alert_handler_virtual_sequencer.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv similarity index 100% rename from hw/ip/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv rename to hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv diff --git a/hw/ip/alert_handler/dv/sva/alert_handler_bind.sv b/hw/ip_templates/alert_handler/dv/sva/alert_handler_bind.sv similarity index 100% rename from hw/ip/alert_handler/dv/sva/alert_handler_bind.sv rename to hw/ip_templates/alert_handler/dv/sva/alert_handler_bind.sv diff --git a/hw/top_earlgrey/ip/alert_handler/dv/sva/alert_handler_sva.core b/hw/ip_templates/alert_handler/dv/sva/alert_handler_sva.core.tpl similarity index 62% rename from hw/top_earlgrey/ip/alert_handler/dv/sva/alert_handler_sva.core rename to hw/ip_templates/alert_handler/dv/sva/alert_handler_sva.core.tpl index cd3b33a4ee913..2e14283f072d7 100644 --- a/hw/top_earlgrey/ip/alert_handler/dv/sva/alert_handler_sva.core +++ b/hw/ip_templates/alert_handler/dv/sva/alert_handler_sva.core.tpl @@ -2,7 +2,7 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:top_earlgrey:alert_handler_sva:0.1" +name: ${instance_vlnv("lowrisc:dv:alert_handler_sva:0.1")} description: "ALERT_HANDLER assertion modules and bind file." filesets: files_dv: @@ -13,16 +13,26 @@ filesets: - alert_handler_bind.sv file_type: systemVerilogSource -# TODO: This only caters to top_earlgrey chip specific assertions. + files_formal: + depend: + - ${instance_vlnv("lowrisc:ip:alert_handler:0.1")} + generate: csr_assert_gen: generator: csr_assert_gen parameters: - spec: ../../data/autogen/alert_handler.hjson + spec: ../../data/alert_handler.hjson targets: - default: + default: &default_target filesets: - files_dv generate: - csr_assert_gen + + formal: + <<: *default_target + filesets: + - files_formal + - files_dv + toplevel: alert_handler diff --git a/hw/ip/alert_handler/dv/tb/alert_handler_tb.core b/hw/ip_templates/alert_handler/dv/tb/alert_handler_tb.core similarity index 100% rename from hw/ip/alert_handler/dv/tb/alert_handler_tb.core rename to hw/ip_templates/alert_handler/dv/tb/alert_handler_tb.core diff --git a/hw/ip/alert_handler/dv/tb/tb.sv b/hw/ip_templates/alert_handler/dv/tb/tb.sv similarity index 100% rename from hw/ip/alert_handler/dv/tb/tb.sv rename to hw/ip_templates/alert_handler/dv/tb/tb.sv diff --git a/hw/ip/alert_handler/dv/tests/alert_handler_base_test.sv b/hw/ip_templates/alert_handler/dv/tests/alert_handler_base_test.sv similarity index 100% rename from hw/ip/alert_handler/dv/tests/alert_handler_base_test.sv rename to hw/ip_templates/alert_handler/dv/tests/alert_handler_base_test.sv diff --git a/hw/ip/alert_handler/dv/tests/alert_handler_test.core b/hw/ip_templates/alert_handler/dv/tests/alert_handler_test.core similarity index 100% rename from hw/ip/alert_handler/dv/tests/alert_handler_test.core rename to hw/ip_templates/alert_handler/dv/tests/alert_handler_test.core diff --git a/hw/ip/alert_handler/dv/tests/alert_handler_test_pkg.sv b/hw/ip_templates/alert_handler/dv/tests/alert_handler_test_pkg.sv similarity index 100% rename from hw/ip/alert_handler/dv/tests/alert_handler_test_pkg.sv rename to hw/ip_templates/alert_handler/dv/tests/alert_handler_test_pkg.sv diff --git a/hw/ip_templates/alert_handler/fpv/alert_handler_esc_timer_fpv.core.tpl b/hw/ip_templates/alert_handler/fpv/alert_handler_esc_timer_fpv.core.tpl new file mode 100644 index 0000000000000..067b24db71881 --- /dev/null +++ b/hw/ip_templates/alert_handler/fpv/alert_handler_esc_timer_fpv.core.tpl @@ -0,0 +1,25 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: ${instance_vlnv("lowrisc:fpv:alert_handler_esc_timer_fpv:0.1")} +description: "alert_handler_esc_timer FPV target" +filesets: + files_fpv: + depend: + - lowrisc:prim:all + - ${instance_vlnv("lowrisc:ip:alert_handler")} + files: + - vip/alert_handler_esc_timer_assert_fpv.sv + - tb/alert_handler_esc_timer_bind_fpv.sv + - tb/alert_handler_esc_timer_fpv.sv + file_type: systemVerilogSource + +targets: + default: + # note, this setting is just used + # to generate a file list for jg + default_tool: icarus + filesets: + - files_fpv + toplevel: alert_handler_esc_timer_fpv diff --git a/hw/ip_templates/alert_handler/fpv/alert_handler_ping_timer_fpv.core.tpl b/hw/ip_templates/alert_handler/fpv/alert_handler_ping_timer_fpv.core.tpl new file mode 100644 index 0000000000000..3461ca75f1929 --- /dev/null +++ b/hw/ip_templates/alert_handler/fpv/alert_handler_ping_timer_fpv.core.tpl @@ -0,0 +1,25 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: ${instance_vlnv("lowrisc:fpv:alert_handler_ping_timer_fpv:0.1")} +description: "ALERT_HANDLER FPV target" +filesets: + files_fpv: + depend: + - lowrisc:prim:all + - ${instance_vlnv("lowrisc:ip:alert_handler")} + files: + - vip/alert_handler_ping_timer_assert_fpv.sv + - tb/alert_handler_ping_timer_bind_fpv.sv + - tb/alert_handler_ping_timer_fpv.sv + file_type: systemVerilogSource + +targets: + default: + # note, this setting is just used + # to generate a file list for jg + default_tool: icarus + filesets: + - files_fpv + toplevel: alert_handler_ping_timer_fpv diff --git a/hw/ip/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv b/hw/ip_templates/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv similarity index 100% rename from hw/ip/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv rename to hw/ip_templates/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv diff --git a/hw/ip/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv b/hw/ip_templates/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv similarity index 100% rename from hw/ip/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv rename to hw/ip_templates/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv diff --git a/hw/ip/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv b/hw/ip_templates/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv similarity index 100% rename from hw/ip/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv rename to hw/ip_templates/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv diff --git a/hw/ip/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv b/hw/ip_templates/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv similarity index 100% rename from hw/ip/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv rename to hw/ip_templates/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv diff --git a/hw/ip/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv b/hw/ip_templates/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv similarity index 100% rename from hw/ip/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv rename to hw/ip_templates/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv diff --git a/hw/ip/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv b/hw/ip_templates/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv similarity index 100% rename from hw/ip/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv rename to hw/ip_templates/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv diff --git a/hw/ip/alert_handler/lint/alert_handler.vlt b/hw/ip_templates/alert_handler/lint/alert_handler.vlt similarity index 100% rename from hw/ip/alert_handler/lint/alert_handler.vlt rename to hw/ip_templates/alert_handler/lint/alert_handler.vlt diff --git a/hw/ip/alert_handler/lint/alert_handler.waiver b/hw/ip_templates/alert_handler/lint/alert_handler.waiver similarity index 100% rename from hw/ip/alert_handler/lint/alert_handler.waiver rename to hw/ip_templates/alert_handler/lint/alert_handler.waiver diff --git a/hw/ip/alert_handler/rtl/alert_handler.sv b/hw/ip_templates/alert_handler/rtl/alert_handler.sv similarity index 98% rename from hw/ip/alert_handler/rtl/alert_handler.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler.sv index 8295b027239d9..5b3ffc5b4af39 100644 --- a/hw/ip/alert_handler/rtl/alert_handler.sv +++ b/hw/ip_templates/alert_handler/rtl/alert_handler.sv @@ -2,11 +2,7 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // -// Alert handler top. -// -// Note that the alert_pkg, the regfile and alert_handler_reg_wrap -// have to be generated using the reg_alert_handler.py script. -// +// Alert handler top `include "prim_assert.sv" diff --git a/hw/ip/alert_handler/rtl/alert_handler_accu.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_accu.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_handler_accu.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler_accu.sv diff --git a/hw/ip/alert_handler/rtl/alert_handler_class.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_class.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_handler_class.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler_class.sv diff --git a/hw/ip/alert_handler/rtl/alert_handler_esc_timer.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_esc_timer.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_handler_esc_timer.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler_esc_timer.sv diff --git a/hw/ip_templates/alert_handler/rtl/alert_handler_lp_ctrl.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_lp_ctrl.sv new file mode 100644 index 0000000000000..fc4f0a77f29b5 --- /dev/null +++ b/hw/ip_templates/alert_handler/rtl/alert_handler_lp_ctrl.sv @@ -0,0 +1,80 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module gathers and synchronizes the clock gating and reset indication signals for all +// low-power groups (LPGs), synchronizes them to the alert handler clock domain. +// The clock gating and reset indication signals are then logically OR'ed to produce one multibit +// value for each LPG. The LPG multibit values are then mapped to the alert channels using +// the AlertLpgMap parameter, and each multibit output value is buffered independently. +// + +`include "prim_assert.sv" + +module alert_handler_lp_ctrl import alert_pkg::*; ( + input clk_i, + input rst_ni, + // Low power clk and rst indication signals. + input lc_ctrl_pkg::lc_tx_t [NLpg-1:0] lpg_cg_en_i, + input lc_ctrl_pkg::lc_tx_t [NLpg-1:0] lpg_rst_en_i, + // Init requests going to the individual alert channels. + output lc_ctrl_pkg::lc_tx_t [NAlerts-1:0] alert_init_trig_o +); + + /////////////////////////////////////////////////// + // Aggregate multibit indication signals per LPG // + /////////////////////////////////////////////////// + + lc_ctrl_pkg::lc_tx_t [NLpg-1:0] lpg_init_trig; + for (genvar k = 0; k < NLpg; k++) begin : gen_lpgs + + lc_ctrl_pkg::lc_tx_t [0:0] lpg_cg_en; + prim_lc_sync #( + .ResetValueIsOn(1) + ) u_prim_lc_sync_cg_en ( + .clk_i, + .rst_ni, + .lc_en_i(lpg_cg_en_i[k]), + .lc_en_o(lpg_cg_en) + ); + lc_ctrl_pkg::lc_tx_t [0:0] lpg_rst_en; + prim_lc_sync #( + .ResetValueIsOn(1) + ) u_prim_lc_sync_rst_en ( + .clk_i, + .rst_ni, + .lc_en_i(lpg_rst_en_i[k]), + .lc_en_o(lpg_rst_en) + ); + + // Perform a logical OR operation of the multibit life cycle signals. + // I.e., if any of the incoming multibit signals is On, the output will also be On. + // Otherwise, the output may have any value other than On. + prim_lc_combine #( + .ActiveLow(0), // Active Value is "On" + .CombineMode(0) // Combo mode is "OR" + ) u_prim_lc_combine ( + .lc_en_a_i(lpg_cg_en[0]), + .lc_en_b_i(lpg_rst_en[0]), + .lc_en_o (lpg_init_trig[k]) + ); + end + + ////////////////////////////////// + // LPG to Alert Channel Mapping // + ////////////////////////////////// + + // select the correct lpg for the alert channel at index j and buffer the multibit signal for each + // alert channel. + for (genvar j=0; j < NAlerts; j++) begin : gen_alert_map + prim_lc_sync #( + .AsyncOn(0) // no sync flops + ) u_prim_lc_sync_lpg_en ( + .clk_i, + .rst_ni, + .lc_en_i(lpg_init_trig[LpgMap[j]]), + .lc_en_o({alert_init_trig_o[j]}) + ); + end + +endmodule : alert_handler_lp_ctrl diff --git a/hw/ip/alert_handler/rtl/alert_handler_lpg_ctrl.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_lpg_ctrl.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_handler_lpg_ctrl.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler_lpg_ctrl.sv diff --git a/hw/ip/alert_handler/rtl/alert_handler_ping_timer.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_ping_timer.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_handler_ping_timer.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler_ping_timer.sv diff --git a/hw/ip/alert_handler/rtl/alert_handler_reg_wrap.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_reg_wrap.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_handler_reg_wrap.sv rename to hw/ip_templates/alert_handler/rtl/alert_handler_reg_wrap.sv diff --git a/hw/ip/alert_handler/rtl/alert_pkg.sv b/hw/ip_templates/alert_handler/rtl/alert_pkg.sv similarity index 100% rename from hw/ip/alert_handler/rtl/alert_pkg.sv rename to hw/ip_templates/alert_handler/rtl/alert_pkg.sv diff --git a/hw/top_earlgrey/doc/_index.md b/hw/top_earlgrey/doc/_index.md index b24667333f4a0..a43a8154e63ee 100644 --- a/hw/top_earlgrey/doc/_index.md +++ b/hw/top_earlgrey/doc/_index.md @@ -375,7 +375,7 @@ This ensures that the underlying concern is guaranteed to be addressed if the pr Each peripheral has an option to present a list of individual alerts, representing individual threats that require handling. These alerts are sent in a particular encoding method to the alert handler module, itself a peripheral on the system bus. -See the details of the [alert handler specification]({{< relref "hw/ip/alert_handler/doc" >}}) for more information. +See the details of the alert handler specification for more information. At this time, the alert handler module is not wired into the top level. diff --git a/hw/top_earlgrey/dv/top_earlgrey_sim_cfgs.hjson b/hw/top_earlgrey/dv/top_earlgrey_sim_cfgs.hjson index 69a18fa1a8cfc..9d7dc17ed0c7e 100644 --- a/hw/top_earlgrey/dv/top_earlgrey_sim_cfgs.hjson +++ b/hw/top_earlgrey/dv/top_earlgrey_sim_cfgs.hjson @@ -50,7 +50,7 @@ "{proj_root}/hw/ip/uart/dv/uart_sim_cfg.hjson", "{proj_root}/hw/ip/usbdev/dv/usbdev_sim_cfg.hjson", // Top level IPs. - "{proj_root}/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim_cfg.hjson", + "{proj_root}/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson", "{proj_root}/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_main_sim_cfg.hjson", "{proj_root}/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_peri_sim_cfg.hjson", // Top level. diff --git a/hw/top_earlgrey/formal/top_earlgrey_fpv_cfgs.hjson b/hw/top_earlgrey/formal/top_earlgrey_fpv_cfgs.hjson index 32c305cbfc44e..964621e69ebc8 100644 --- a/hw/top_earlgrey/formal/top_earlgrey_fpv_cfgs.hjson +++ b/hw/top_earlgrey/formal/top_earlgrey_fpv_cfgs.hjson @@ -204,9 +204,9 @@ } { name: alert_handler - fusesoc_core: lowrisc:dv:alert_handler_sva + fusesoc_core: lowrisc:opentitan:top_earlgrey_alert_handler_sva import_cfgs: ["{proj_root}/hw/formal/tools/dvsim/common_fpv_cfg.hjson"] - rel_path: "hw/ip/alert_handler/{sub_flow}/{tool}" + rel_path: "hw/top_earlgrey/ip_autogen/alert_handler/{sub_flow}/{tool}" cov: false } { diff --git a/hw/top_earlgrey/ip/alert_handler/BUILD b/hw/top_earlgrey/ip/alert_handler/BUILD deleted file mode 100644 index 9f9e5f5367a15..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/BUILD +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright lowRISC contributors. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 diff --git a/hw/top_earlgrey/ip/alert_handler/alert_handler_reg.core b/hw/top_earlgrey/ip/alert_handler/alert_handler_reg.core deleted file mode 100644 index 2402d0ca457d3..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/alert_handler_reg.core +++ /dev/null @@ -1,21 +0,0 @@ -CAPI=2: -# Copyright lowRISC contributors. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:systems:alert_handler_reg:0.1" -description: "Auto-generated alert handler register sources for top_earlgrey chip." -filesets: - files_rtl: - depend: - - lowrisc:tlul:headers - - files: - - rtl/autogen/alert_handler_reg_pkg.sv - - rtl/autogen/alert_handler_reg_top.sv - file_type: systemVerilogSource - - -targets: - default: &default_target - filesets: - - files_rtl diff --git a/hw/top_earlgrey/ip/alert_handler/data/BUILD b/hw/top_earlgrey/ip/alert_handler/data/BUILD deleted file mode 100644 index 9f9e5f5367a15..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/data/BUILD +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright lowRISC contributors. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 diff --git a/hw/top_earlgrey/ip/alert_handler/data/autogen/BUILD b/hw/top_earlgrey/ip/alert_handler/data/autogen/BUILD deleted file mode 100644 index 7d512997ee534..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/data/autogen/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright lowRISC contributors. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 - -package(default_visibility = ["//visibility:public"]) - -load("//rules:autogen.bzl", "autogen_hjson_header") - -autogen_hjson_header( - name = "alert_handler_regs", - srcs = [ - "alert_handler.hjson", - ], -) diff --git a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv b/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv deleted file mode 100644 index 58548c9557917..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------// -// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND: -// util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson --alert-handler-only -o hw/top_earlgrey/ - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -parameter uint NUM_ALERTS = 29; -parameter bit [NUM_ALERTS-1:0] ASYNC_ON = 29'b11100111111100001100000001111; diff --git a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim_cfg.hjson b/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim_cfg.hjson deleted file mode 100644 index 8302ac5bc1e9c..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim_cfg.hjson +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -{ - // Import additional common sim cfg files. - import_cfgs: ["{proj_root}/hw/ip/alert_handler/dv/alert_handler_generic_sim_cfg.hjson"] - - overrides: [ - { - name: fusesoc_core - value: lowrisc:dv:alert_handler_sim:0.1 - } - { - name: design_level - value: "top" - } - ] -} diff --git a/hw/top_earlgrey/ip/alert_handler/dv/sva/alert_handler_bind.sv b/hw/top_earlgrey/ip/alert_handler/dv/sva/alert_handler_bind.sv deleted file mode 120000 index 933d1eae0a9d8..0000000000000 --- a/hw/top_earlgrey/ip/alert_handler/dv/sva/alert_handler_bind.sv +++ /dev/null @@ -1 +0,0 @@ -../../../../../ip/alert_handler/dv/sva/alert_handler_bind.sv \ No newline at end of file diff --git a/hw/top_earlgrey/ip/rstmgr/system_rstmgr_pkg.core b/hw/top_earlgrey/ip/rstmgr/system_rstmgr_pkg.core index 0c06946c9c6ad..aaf4e9d5e052d 100644 --- a/hw/top_earlgrey/ip/rstmgr/system_rstmgr_pkg.core +++ b/hw/top_earlgrey/ip/rstmgr/system_rstmgr_pkg.core @@ -10,7 +10,7 @@ filesets: depend: - lowrisc:ip:pwrmgr_pkg - lowrisc:ip:rstmgr_reg - - lowrisc:ip:alert_handler_reg + - lowrisc:ip_interfaces:alert_handler_reg - lowrisc:ip:alert_handler_component files: - rtl/autogen/rstmgr_pkg.sv diff --git a/hw/ip/alert_handler/alert_handler.core b/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler.core similarity index 75% rename from hw/ip/alert_handler/alert_handler.core rename to hw/top_earlgrey/ip_autogen/alert_handler/alert_handler.core index 34270e576ddca..a2eb62d9beeaf 100644 --- a/hw/ip/alert_handler/alert_handler.core +++ b/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler.core @@ -2,14 +2,17 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:ip:alert_handler:0.1" +name: lowrisc:opentitan:top_earlgrey_alert_handler:0.1 description: "Alert Handler" +virtual: + - lowrisc:ip_interfaces:alert_handler filesets: files_rtl: depend: - - lowrisc:ip:alert_handler_reg - lowrisc:ip:alert_handler_component + - lowrisc:opentitan:top_earlgrey_alert_handler_reg:0.1 + file_type: systemVerilogSource parameters: SYNTHESIS: diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler_component.core b/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler_component.core new file mode 100644 index 0000000000000..e543eb0374173 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler_component.core @@ -0,0 +1,61 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:ip:alert_handler_component:0.1" +description: "Alert Handler component without the CSRs" + +filesets: + files_rtl: + depend: + - lowrisc:ip:tlul + - lowrisc:prim:all + - lowrisc:prim:esc + - lowrisc:prim:lfsr + - lowrisc:prim:edn_req + - lowrisc:prim:buf + - lowrisc:prim:mubi + - lowrisc:ip_interfaces:alert_handler_reg + files: + - rtl/alert_pkg.sv + - rtl/alert_handler_reg_wrap.sv + - rtl/alert_handler_lpg_ctrl.sv + - rtl/alert_handler_class.sv + - rtl/alert_handler_ping_timer.sv + - rtl/alert_handler_esc_timer.sv + - rtl/alert_handler_accu.sv + - rtl/alert_handler.sv + file_type: systemVerilogSource + + files_verilator_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + files: + - lint/alert_handler.vlt + file_type: vlt + + files_ascentlint_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + files: + - lint/alert_handler.waiver + file_type: waiver + + files_veriblelint_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_verilator_waiver) + - tool_ascentlint ? (files_ascentlint_waiver) + - tool_veriblelint ? (files_veriblelint_waiver) + - files_rtl diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler_reg.core b/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler_reg.core new file mode 100644 index 0000000000000..e7be9e36f4678 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/alert_handler_reg.core @@ -0,0 +1,27 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: lowrisc:opentitan:top_earlgrey_alert_handler_reg:0.1 +description: "Auto-generated alert handler register sources" +virtual: + # TODO: Check if the generated files actually maintain a stable public API. + - "lowrisc:ip_interfaces:alert_handler_reg" + +filesets: + files_rtl: + depend: + - lowrisc:tlul:headers + - lowrisc:prim:subreg + - lowrisc:ip:tlul + - lowrisc:prim:subreg + files: + - rtl/alert_handler_reg_pkg.sv + - rtl/alert_handler_reg_top.sv + file_type: systemVerilogSource + + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.hjson similarity index 99% rename from hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson rename to hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.hjson index 859f2e525499c..cea96c4d66030 100644 --- a/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson +++ b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.hjson @@ -1,11 +1,3 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------// -// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND: -// util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson --alert-handler-only -o hw/top_earlgrey/ - // Copyright lowRISC contributors. // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.prj.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.prj.hjson new file mode 100644 index 0000000000000..80e59fda9cb5e --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.prj.hjson @@ -0,0 +1,17 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +{ + name: "alert_handler", + design_spec: "../doc", + dv_doc: "../doc/dv", + hw_checklist: "../doc/checklist", + sw_checklist: "/sw/device/lib/dif/dif_alert_handler" + version: "0.5", + life_stage: "L1", + design_stage: "D1", + verification_stage: "V1", + dif_stage: "S0", + notes: "Use both FPV and DV to perform block level verification.", +} diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson new file mode 100644 index 0000000000000..3b61b193d6acf --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson @@ -0,0 +1,108 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ + name: "alert_handler" + import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson", + "hw/dv/tools/dvsim/testplans/intr_test_testplan.hjson", + "hw/dv/tools/dvsim/testplans/enable_reg_testplan.hjson", + "hw/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", + "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", + "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson"] + testpoints: [ + { + name: smoke + desc: ''' + - Alert_handler smoke test with one class configured that escalates through all + phases after one alert has been triggered + - Check interrupt pins, alert cause CSR values, escalation pings, and crashdump_o + output values + - Support both synchronous and asynchronous settings + ''' + milestone: V1 + tests: ["alert_handler_smoke"] + } + { + name: esc_accum + desc: ''' + Based on the smoke test, this test will focus on testing the escalation accumulation + feature. So all the escalations in the test will be triggered by alert accumulation. + ''' + milestone: V2 + tests: ["alert_handler_esc_alert_accum"] + } + { + name: esc_timeout + desc: ''' + Based on the smoke test, this test will focus on testing the escalation timeout + feature. So all the escalations in the test will be triggered by interrupt timeout. + ''' + milestone: V2 + tests: ["alert_handler_esc_intr_timeout"] + } + { + name: entropy + desc: ''' + Based on the smoke test, this test enables ping testing, and check if the ping feature + correctly pings all devices within certain period of time. + ''' + milestone: V2 + tests: ["alert_handler_entropy"] + } + { + name: sig_int_fail + desc: ''' + This test will randomly inject differential pair failures on alert tx/rx pairs and the + escalator tx/rx pairs. Then check if integrity failure alert is triggered and + escalated. + ''' + milestone: V2 + tests: ["alert_handler_sig_int_fail"] + } + { + name: clk_skew + desc: ''' + This test will randomly inject clock skew within the differential pairs. Then check no + alert is raised. + ''' + milestone: V2 + tests: ["alert_handler_smoke"] + } + { + name: random_alerts + desc: "Input random alerts and randomly write phase cycles." + milestone: V2 + tests: ["alert_handler_random_alerts"] + } + { + name: random_classes + desc: "Based on random_alerts test, this test will also randomly enable interrupt classes." + milestone: V2 + tests: ["alert_handler_random_classes"] + } + { + name: ping_timeout + desc: ''' + Based on entropy test, this test request alert_sender and esc_receiver drivers to + randomly create ping requests timeout stimulus. + + Checks: + - Verify interrupt pin and states. + - Verify alert and local alert causes. + - Verify escalation states and counts. + ''' + milestone: V2 + tests: ["alert_handler_ping_timeout"] + } + { + name: stress_all + desc: ''' + Combine above sequences in one test to run sequentially with the following exclusions: + - CSR sequences: scoreboard disabled + - Ping_corner_cases sequence: included reset in the sequence + ''' + milestone: V2 + tests: ["alert_handler_stress_all"] + } + ] +} diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/data/top_earlgrey_alert_handler.ipconfig.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/data/top_earlgrey_alert_handler.ipconfig.hjson new file mode 100644 index 0000000000000..8810bf1a8c042 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/data/top_earlgrey_alert_handler.ipconfig.hjson @@ -0,0 +1,136 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ + instance_name: top_earlgrey_alert_handler + param_values: + { + n_alerts: 58 + esc_cnt_dw: 32 + accu_cnt_dw: 16 + async_on: + [ + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + 1'b1 + ] + n_classes: 4 + n_lpg: 20 + lpg_map: + [ + 5'd0 + 5'd0 + 5'd0 + 5'd0 + 5'd0 + 5'd1 + 5'd2 + 5'd3 + 5'd4 + 5'd5 + 5'd6 + 5'd0 + 5'd7 + 5'd8 + 5'd9 + 5'd9 + 5'd9 + 5'd9 + 5'd9 + 5'd9 + 5'd10 + 5'd10 + 5'd10 + 5'd10 + 5'd11 + 5'd12 + 5'd13 + 5'd13 + 5'd14 + 5'd15 + 5'd15 + 5'd11 + 5'd16 + 5'd16 + 5'd16 + 5'd17 + 5'd18 + 5'd18 + 5'd18 + 5'd18 + 5'd18 + 5'd18 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd17 + 5'd19 + 5'd19 + 5'd19 + 5'd19 + 5'd19 + 5'd19 + ] + } +} diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/_index.md b/hw/top_earlgrey/ip_autogen/alert_handler/doc/_index.md new file mode 100644 index 0000000000000..5d568180d4c39 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/_index.md @@ -0,0 +1,975 @@ +--- +title: "Alert Handler Technical Specification" +--- + + +# Overview + +This document specifies the functionality of the alert handler mechanism. +The alert handler is a module that is a peripheral on the chip interconnect bus, and thus follows the [Comportability Specification]({{< relref "doc/rm/comportability_specification" >}}). +It gathers alerts - defined as interrupt-type signals from other peripherals that are designated as potential security threats - throughout the design, and converts them to interrupts that the processor can handle. +If the processor does not handle them, the alert handler mechanism provides hardware responses to handle the threat. + + +## Features + +- Differentially-signaled, asynchronous alert inputs from `NAlerts` peripheral sources, where `NAlerts` is a function of the requirements of the peripherals. + +- Ping testing of alert sources: + - responder module requests periodic alert response from each source to ensure proper wiring. + - reset-asserted and clock-gated information is used to temporarily pause the ping mechanism on alert channels that are in a low-power state. + +- Register locking on all configuration registers. + - Once locked, can not be modified by software until next system reset. + +- Register-based assignment of alert to alert-class. + - Four classes, can be individually disabled. + - Each class generates one interrupt. + - Disambiguation history for software to determine which alert caused the class interrupt. + - Each class has configurable response time for escalation. + - Disable allows for ignoring alerts, should only be used in cases when alerts are faulty. + Undesirable access is enforced by locking the register state after initial configuration. + +- Register-based escalation controls. + - Number of alerts in class before escalation. + - Timeout for unhandled alert IRQs can also trigger escalation. + - Configurable escalation enables for 4 escalation signals. + - Could map to NMI, wipe secrets signal, lower privilege, chip reset, etc. + - Escalation signals differentially-signaled with heartbeat, will trigger response if differential or heartbeat failure at destination. + - Configurable time in cycles between each escalation level. + +- Two locally sourced hardware alerts. + - Differential signaling from a source has failed. + - Ping response from a source has failed. + + +## Description + +The alert handler module manages incoming alerts from throughout the system, classifies them, sends interrupts, and escalates interrupts to hardware responses if the processor does not respond to any interrupts. +The intention is for this module to be a stand-in for security responses in the case where the processor can not handle the security alerts. + +It is first notable that all security alerts are rare events. +Module and top level designers should only designate events as alerts if they are expected to never happen, and if they have potential security consequences. +Examples are parity errors (which might indicate an attack), illegal actions on cryptography or security modules, physical sensors of environmental modification (e.g. voltage, temperature), etc. +Alerts will be routed through this module and initially converted to interrupts for the processor to handle. +The expectation is that the secure operating system has a protocol for handling any such alert interrupt in software. +The operating system should respond, then clear the interrupt. +Since these are possible security attacks, the response is not always obvious, but the response is beyond the scope of this document. + +This module is designed to help the full chip respond to security threats in the case where the processor is not trusted: either it has been attacked, or is not responding. +It does this by escalating alerts beyond a processor interrupt. +It provides four such escalation signals that can be routed to chip functions for attack responses. +This could include such functions as wiping secret chip material, power down, reset, etc. +It is beyond the scope of this document to specify what those escalation responses are at the chip level. + +To ease software management of alerts, classification is provided whereby each alert can be classified into one of four classes. +How the classification is done by software is beyond the scope of this document, but it is suggested that alerts of a similar profile (risk of occurring, level of security concern, frequency of false trigger, etc) are classed together. +For each class a counter of alerts is kept, clearable by software. +If that counter exceeds a programmable maximum value, then the escalation protocol for that class begins. + +The details for alert signaling, classification, and escalation are all given in the Theory of Operations section. + + +# Theory of Operations + +## Block Diagram + +The figure below shows a block diagram of the alert handler module, as well as a few examples of alert senders in other peripheral modules. +In this diagram, there are seven sources of alerts: three sources from external modules (two from `periph0` and one from `periph1`), and four local sources (`alert_ping_fail`, `alert_sig_int`, `esc_ping_fail`, `esc_sig_int`). +The local sources represent alerts that are created by this module itself. See the later section on special local alerts. + +![Alert Handler Block Diagram](alert_handler_block_diagram.svg) + +Also shown are internal modules for classification, interrupt generation, accumulation, escalation, ping generation and alert-channel low-power control. +These are described later in the document. +Note that the differential alert sender and receiver blocks used for alert signaling support both _asynchronous_ and _synchronous_ clocking schemes, and hence peripherals able to raise alerts may be placed in clock domains different from that of the alert handler (Jittered clock domains are also supported in the asynchronous clocking scheme). +Proper care must however be taken when formulating the timing constraints for the diff pairs, and when determining clock-dependent parameters (such as the ping timeout) of the design. +On the escalation sender / receiver side, the differential signaling blocks employ a fully synchronous clocking scheme throughout. + +## Hardware Interfaces + +### Parameters + +The following table lists the main parameters used throughout the alert handler design. +Note that the alert handler is generated based on the system configuration, and hence these parameters are placed into a package as "localparams". +The parameterization rules are explained in more detail in the architectural description. + +Localparam | Default (Max) | Top Earlgrey | Description +---------------|-----------------------|--------------|--------------- +`NAlerts` | 8 (248) | see RTL | Number of alert instances. Maximum number bounded by LFSR implementation that generates ping timing. +`NLpg` | 1 | see RTL | Number of unique low-power groups as determined by topgen. +`LpgMap` | {0} | see RTL | Array mapping each alert to a unique low-power group as determined by topgen. +`EscCntWidth` | 32 (32) | 32 | Width of the escalation counters in bit. +`AccuCntWidth` | 16 (32) | 16 | Width of the alert accumulation counters in bit. +`AsyncOn` | '0 (2^`NAlerts`-1) | see RTL | This is a bit array specifying whether a certain alert sender / receiver pair goes across an asynchronous boundary or not. + +The next table lists free parameters in the `prim_alert_sender` and +`prim_alert receiver` submodules. + +Parameter | Default (Max) | Description +---------------|------------------|--------------- +`AsyncOn` | `1'b0` (`1'b1`) | 0: Synchronous, 1: Asynchronous, determines whether additional synchronizer flops and logic need to be instantiated. + + +### Signals + +{{< incGenFromIpDesc "../data/alert_handler.hjson" "hwcfg" >}} + +The table below lists other alert handler module signals. +The number of alert instances is parametric and hence alert and ping diff pairs are grouped together in packed arrays. +The diff pair signals are indexed with the corresponding alert instance ``. + +Signal | Direction | Type | Description +-------------------------|------------------|---------------- |--------------- +`edn_o` | `output` | `otp_edn_req_t` | Entropy request to the entropy distribution network for LFSR reseeding and ephemeral key derivation. +`edn_i` | `input` | `otp_edn_rsp_t` | Entropy acknowledgment to the entropy distribution network for LFSR reseeding and ephemeral key derivation. +`alert_tx_i[]` | `input` | packed `alert_tx_t` array | Incoming alert or ping response(s), differentially encoded. Index range: `[NAlerts-1:0]` +`alert_rx_o[]` | `output` | packed `alert_rx_t` array | Outgoing alert acknowledgment and ping requests, differentially encoded. Index range: `[NAlerts-1:0]` +`esc_tx_o[]` | `output` | packed `esc_tx_t` array | Escalation or ping request, differentially encoded. Index corresponds to severity level, and ranges from 0 to 3. +`esc_rx_i[]` | `input` | packed `esc_rx_t` array | Escalation ping response, differentially encoded. Index corresponds to severity level, and ranges from 0 to 3. +`lpg_cg_en_i[]` | `input` | packed `mubi4_t` array | Incoming clock gated indication from clock manager. Index range: `[NLpg-1:0]` +`lpg_rst_en_i[]` | `output` | packed `mubi4_t` array | Incoming reset asserted indication from reset manager. Index range: `[NLpg-1:0]` +`crashdump_o` | `output` | packed `struct` | This is a collection of alert handler state registers that can be latched by hardware debugging circuitry, if needed. + +#### Entropy Network Connections + +The LFSR ping timer needs to be periodically reseeded. +Therefore, the alert handler is connected to the entropy distribution network via the `edn_i/o` signals. + +#### Alert Channels + +For each alert, there is a pair of input and two pairs of output signals. +These signals are connected to a differential sender module within the source, and a differential receiver module within the alert handler. +Both of these modules are described in more detail in the following section. +These signal pairs carry differentially encoded messages that enable two types of signaling: a native alert and a ping/response test of the alert mechanism. +The latter is to ensure that all alert senders are always active and have not been the target of an attack. + +#### Escalation Channels + +For each escalation action in the system, there is a pair of input and a pair of output signals, encapsulated in the `esc_rx_t` and `esc_tx_t` types. +These signals are connected to a differential sender module within the alert handler, and a differential receiver module within the module that performs a particular escalation action (for example the reset manager or life cycle controllers). +The signal pairs carry differentially encoded messages that enable two types of signaling: a native escalation and a ping/response test of the escalation mechanism. +The latter is to ensure that all escalation receivers are always active and have not been the target of an attack. + +#### Low-power Indication Signals + +The `lpg_cg_en_i` and `lpg_rst_en_i` are two arrays with multibit indication signals from the [clock]({{< relref "hw/ip/clkmgr/doc/" >}}) and [reset managers]({{< relref "hw/ip/rstmgr/doc" >}}). +These indication signals convey whether a specific group of alert senders are either clock gated or in reset. +As explained in [more detail below]({{< relref "#low-power-management-of-alert-channels" >}}), this information is used to temporarily halt the ping timer mechanism on channels that are in a low-power state in order to prevent false positives. + +#### Crashdump Output + +The `crashdump_o` struct outputs a snapshot of CSRs and alert handler state bits that can be read by hardware debugging circuitry: + +```systemverilog + typedef struct packed { + // alerts + logic [NAlerts-1:0] alert_cause; // alert cause bits + logic [6:0] loc_alert_cause; // local alert cause bits + // class state + logic [3:0][15:0] class_accum_cnt; // current accumulator value + logic [3:0][31:0] class_esc_cnt; // current escalation counter value + cstate_e [3:0] class_esc_state; // current escalation protocol state + } alert_crashdump_t; +``` + +This can be useful for extracting more information about possible failures or bugs without having to use the tile-link bus interface (which may become unresponsive under certain circumstances). +It is recommended for the top level to store this information in an always-on location. + +Note that the crashdump state is continuously output via `crashdump_o` until the latching trigger condition is true for the first time (see {{< regref CLASSA_CRASHDUMP_TRIGGER_SHADOWED >}}). +After that, the `crashdump_o` is held constant and the alert handler has to be reset in order to re-arm the crashdump latching mechanism. +This is done so that it is possible to capture the true alert cause before spurious alert events start to pop up due to escalation countermeasures with excessive side effects (like life cycle scrapping for example). + +## Design Details + +This section gives the full design details of the alert handler module and its submodules. + + +### Alert Definition + +Alerts are defined as events that have security implications, and should be handled by the main processor, or escalated to other hardware modules to take action. +Each peripheral has the option to define one or more alert signals. +Those peripherals should instantiate one module (`prim_alert_sender`) to convert the event associated with that alert into a signal to the alert handler module. +The alert handler instantiates one receiver module (`prim_alert_receiver`) per alert, then handles the classification, accumulation, and escalation of the received signal. +The differential signaling submodules may either use a synchronous or asynchronous clocking scheme, since the message type to be transferred is a single discrete event. + + +### Differential Alert Signaling + +Each alert sender is connected to the corresponding alert receiver via the 3 differential pairs `alert_tx_i/o.alert_p/n`, `alert_rx_i/o.ack_p/n` and `alert_rx_i/o.ping_p/n`, as illustrated below: + +![Alert Handler Alert RXTX](alert_handler_alert_rxtx.svg) + +Alerts are encoded differentially and signaled using a full handshake on the `alert_tx_i/o.alert_p/n` and `alert_rx_i/o.ack_p/n` wires. +The use of a full handshake protocol allows this mechanism to be used with an asynchronous clocking strategy, where peripherals may reside in a different clock domain than the alert handler. +The full handshake guarantees that alert messages are correctly back-pressured and no alert is "lost" at the asynchronous boundary due to (possibly variable) clock ratios greater or less than 1.0. +The "native alert message" will be repeated on the output wires as long as the alert event is still true within the peripheral. + +The wave pattern below illustrates differential full handshake mechanism. + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p...............' }, + { name: 'alert_req_i', wave: '01.|..|..|...|..' }, + { name: 'alert_ack_o', wave: '0..|..|..|10.|..' }, + { name: 'alert_tx_o/i.alert_p', wave: '01.|..|0.|..1|..' , node: '.a.....c....e'}, + { name: 'alert_tx_o/i.alert_n', wave: '10.|..|1.|..0|..' }, + { name: 'alert_rx_i/o.ack_p', wave: '0..|1.|..|0..|1.' , node: '....b.....d..'}, + { name: 'alert_rx_i/o.ack_n', wave: '1..|0.|..|1..|0.' }, + { name: 'alert_o', wave: '0..|10|..|...|10' }, + ], + edge: [ + 'a~>b Phase 0/1', + 'b~>c Phase 1/2', + 'c~>d Phase 2/3', + 'd~>e 2 Pause Cycles', + ], + head: { + text: 'Alert signaling and repeat pattern', + }, + foot: { + text: 'Native alert at time 1 with 4-phase handshake; repeated alert at time 12;', + tick: 0, + } +} +{{< /wavejson >}} + +The handshake pattern is repeated as long as the alert is true. +The sender will wait for 2 cycles between handshakes. + +Note that the alert is immediately propagated to `alert_o` once the initial level change on `alert_tx_i.alert_p/n` has been received and synchronized to the local clock on the receiver side. +This ensures that the first occurrence of an alert is always propagated - even if the handshake lines have been manipulated to emulate backpressure. +(In such a scenario, all subsequent alerts would be back-pressured and eventually the ping testing mechanism described in the next subsection would detect that the wires have been tampered with.) + +The alert sender and receiver modules can either be used synchronously or asynchronously. +The signaling protocol remains the same in both cases, but the additional synchronizer flops at the diff pair inputs may be omitted, which results in lower signaling latency. + +### Ping Testing + +In order to ensure that the event sending modules have not been compromised, the alert receiver module `prim_alert_receiver` will "ping" or line-test the senders periodically every few microseconds. +Pings timing is randomized so their appearance can not be predicted. + + +The ping timing is generated by a central LFSR-based timer within the alert handler that randomly asserts the `ping_req_i` signal of a particular `prim_alert_receiver` module. +Once `ping_req_i` is asserted, the receiver module encodes the ping message as a level change on the differential `alert_rx_o.ping_p/n` output, and waits until the sender responds with a full handshake on the `alert_tx_i.alert_p/n` and `alert_rx_o.ack_p/n` lines. +Once that handshake is complete, the `ping_ok_o` signal is asserted. +The LFSR timer has a programmable ping timeout, after which it will automatically assert a "pingfail" alert. +That timeout is a function of the clock ratios present in the system, and has to be programmed accordingly at system startup (as explained later in the LFSR timer subsection). + +The following wave diagram illustrates a correct ping sequence, viewed from the receiver side: + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p..............' }, + { name: 'ping_req_i', wave: '01.|..|..|..|.0' }, + { name: 'ping_ok_o', wave: '0..|..|..|..|10' , node: '.............e'}, + { name: 'alert_rx_o.ping_p', wave: '01.|..|..|..|..' , node: '.a'}, + { name: 'alert_rx_o.ping_n', wave: '10.|..|..|..|..' , node: '.b'}, + { name: 'alert_tx_i.alert_p', wave: '0..|1.|..|0.|..' , node: '....c'}, + { name: 'alert_tx_i.alert_n', wave: '1..|0.|..|1.|..' }, + { name: 'alert_rx_o.ack_p', wave: '0..|..|1.|..|0.' , node: '.............d'}, + { name: 'alert_rx_o.ack_n', wave: '1..|..|0.|..|1.' }, + ], + edge: [ + 'a-b', + 'b~>c ping response', + 'd->e response complete', + ], + head: { + text: 'Ping testing', + }, + foot: { + text: 'Level change at time 1 triggers a full handshake (ping response) at time 4', + tick: 0, + } +} +{{< /wavejson >}} + +In the unlikely case that a ping request collides with a native alert at the sender side, the native alert is held back until the ping handshake has been completed. +This slightly delays the transmission of a native alert, but the alert will eventually be signaled. +Further, if an alert is sent out right before a ping requests comes in at the sender side, the receiver will treat the alert as a ping response. +However, the "true" ping response will be returned right after the alert handshake completed, and thus the alert will eventually be signaled with a slight delay. + +Note that in both collision cases mentioned, the delay will be in the order of the handshake length, plus the constant amount of pause cycles between handshakes (2 sender cycles). + + +### Monitoring of Signal Integrity Issues + +All differential pairs are monitored for signal integrity issues, and if an encoding failure is detected, the receiver module asserts a signal integrity alert via `integ_fail_o`. In particular, this covers the following failure cases: + +1. The `alert_tx_i.alert_p/n` pair is not correctly encoded on the receiver side. +This can be directly flagged as an integrity failure on the receiver side. + +2. The `alert_rx_i.ping_p/n` or the `alert_rx_i.ack_p/n` pairs are not correctly encoded on the sender side. +This is signaled to the receiver by setting the `alert_tx_o.alert_p/n` wires to the same value, and that value will be continuously toggled. +This implicitly triggers a signal integrity alert on the receiver side. + +Some of these failure patterns are illustrated in the wave diagram below: + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p..............' }, + { name: 'alert_tx_o.alert_p', wave: '0.1...|0..10101' , node: '..a.......d'}, + { name: 'alert_tx_o.alert_n', wave: '1.....|....0101' }, + { name: 'alert_rx_i.ack_p', wave: '0.....|.1......' , node: '........c'}, + { name: 'alert_rx_i.ack_n', wave: '1.....|........' }, + { name: 'integ_fail_o', wave: '0...1.|0....1..' , node: '....b.......e'}, + ], + edge: [ + 'a~>b sigint issue detected', + 'c~>d', + 'd~>e indirect sigint issue detected', + ], + head: { + text: 'Detection of Signal Integrity Issues', + }, + foot: { + text: 'signal integrity issues occur at times 2 and 8; synchronizer latency is 2 cycles.', + tick: 0, + } +} +{{< /wavejson >}} + +Note that if signal integrity failures occur during ping or alert handshaking, it is possible that the protocol state-machines lock up and the alert sender and receiver modules become unresponsive. However, the above mechanisms ensure that this will always trigger either a signal integrity alert or eventually a "pingfail" alert. + +### Skew on Asynchronous Differential Pairs + +Note that there is likely a (small) skew present within each differential pair of the signaling mechanism above. Since these pairs cross clock domain boundaries, it may thus happen that a level change appears in staggered manner after resynchronization, as illustrated below: + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p...........' }, + { name: 'diff_p', wave: '0.1.|.0.|..1' , node: '......a....d' }, + { name: 'diff_n', wave: '1.0.|..1|.0.' , node: '.......b..c.' }, + ], + edge: [ + 'a-~>b skew', + 'c-~>d skew' + ], + head: { + text: 'Skewed diff pair', + }, + foot: { + text: 'Correctly sampled diff pair at time 2; staggered samples at time 6-7 and 10-11', + tick: 0, + } +} +{{< /wavejson >}} + +This behavior is permissible, but needs to be accounted for in the protocol logic. +Further, the skew within the differential pair should be constrained to be smaller than the shortest clock period in the system. +This ensures that the staggered level changes appear at most 1 cycle apart from each other. + + +### LFSR Timer + +The `ping_req_i` inputs of all signaling modules (`prim_alert_receiver`, `prim_esc_sender`) instantiated within the alert handler are connected to a central ping timer that alternatingly pings either an alert line or an escalation line after waiting for a pseudo-random amount of clock cycles. +Further, this ping timer also randomly selects a particular alert line to be pinged (escalation senders are always pinged in-order due to the [ping monitoring mechanism]({{< relref "#monitoring-of-pings-at-the-escalation-receiver-side" >}}) on the escalation side). +That should make it more difficult to predict the next ping occurrence based on past observations. + +The ping timer is implemented using an [LFSR-based PRNG of Galois type]({{< relref "hw/ip/prim/doc/prim_lfsr.md" >}}). +This ping timer is reseeded with fresh entropy from EDN roughly every 500k cycles which corresponds to around 16 ping operations on average. +The LFSR is 32bits wide, but only 24bits of its state are actually being used to generate the random timer count and select the alert line to be pinged. +I.e., the 32bits first go through a fixed permutation function, and then bits `[23:16]` are used to determine which alert line to ping. +The random cycle count is created by OR'ing bits `[15:0]` with the constant `3'b100` as follows: + +``` +cycle_cnt = permuted[15:0] | 3'b100; +``` + +This constant DC offset introduces a minimum ping spacing of 4 cycles (1 cycle + margin) to ensure that the handshake protocols of the sender/receiver pairs work. + +After selecting one of the peripherals to ping, the LFSR timer waits until either the corresponding `*_ping_ok[]` signal is asserted, or until the programmable ping timeout value is reached. +In both cases, the LFSR timer proceeds with the next ping, but in the second case it will additionally raise a "pingfail" alert. +The ping enable signal remains asserted during the time where the LFSR counter waits. + +The timeout value is a function of the ratios between the alert handler clock and peripheral clocks present in the system, and can be programmed at startup time via the register {{< regref "PING_TIMEOUT_CYC_SHADOWED" >}}. + +Note that the ping timer directly flags a "pingfail" alert if a spurious "ping ok" message comes in that has not been requested. + + +As described in the programmers guide below, the ping timer has to be enabled explicitly. +Only alerts that have been *enabled and locked* will be pinged in order to avoid spurious alerts. +Escalation channels are always enabled, and hence will always be pinged once this mechanism has been turned on. + +In addition to the ping timer mechanism described above, the escalation receivers contain monitoring counters that monitor the liveness of the alert handler (described in more detail in [this section]({{< relref "#monitoring-of-pings-at-the-escalation-receiver-side" >}})). +This mechanism requires that the maximum wait time between escalation receiver pings is bounded. +To that end, escalation senders are pinged in-order every second ping operation (i.e., the wait time is randomized, but the selection of the escalation line is not). + +### Alert Receiving + +The alert handler module contains one alert receiver module (`prim_alert_receiver`) per sending module. +This receiver module has three outputs based upon the signaling of the input alert. +Primary is the signal of a received native alert, shown in the top-level diagram as `alert_triggered[]`. +Also generated are two other outputs, one that signals a differential encoding error (`alert_integ_fail[]`), and one that signals the receipt of a ping response (`alert_ping_ok[]`). +Each "triggered" alert received is sent into the classification block for individual configuration. +All of the `integ_fail` signals are OR'ed together to create one alert for classification. +The ping responses are fed to the LFSR timer, which determines whether a ping has correctly completed within the timeout window or not. + + +### Alert Classification and Interrupts + +Each of the incoming and local alert signals can be classified generically to one of four classes, or disabled for no classification at all. +These are the classes A, B, C, and D. +There is no pre-determined definition of a class, that is left to software. +But for guidance, software can consider that some alert types are similar to others; some alert types are more "noisy" than others (i.e. when triggered they stay on for long periods of time); some are more critical than others, etc. + +For each alert class (A-D), an interrupt is generally sent. +Like all other peripheral interrupts, there is a triad of registers: enable, status, test. +Thus like all other interrupts, software should handle the source of the interrupt (in this case, the original alert), then clear the state. +Since the interrupt class is disassociated with the original alert (due to the classification process), software can access cause registers to determine which alerts have fired since the last clearing. +Since alerts are expected to be rare (if ever) events, the complexity of dealing with multiple interrupts per class firing during the same time period should not be of concern. See the programming section on interrupt clearing. + +Each of the four interrupts can optionally trigger a timeout counter that triggers escalation if the interrupt is not handled and cleared within a certain time frame. +This feature is explained in more detail in the next subsection about escalation mechanisms. + +Note that an interrupt always fires once an alert has been registered in the corresponding class. +Interrupts are not dependent on escalation mechanisms like alert accumulation or timeout as described in the next subsection. + + +### Escalation Mechanisms + +There are two mechanisms per class that can trigger the corresponding escalation +protocol: + +1. The first consists of an accumulation counter that counts the amount of alert occurrences within a particular class. + An alert classified to class A indicates that on every received alert trigger, the accumulation counter for class A is incremented. + Note: since alerts are expected to be rare or never occur, the module does not attempt to count every alert per cycle, but rather all triggers per class are ORd before sending to the accumulation counter as an increment signal. + Once the threshold has been reached, the next occurrence triggers the escalation escalation protocol for this particular class. + The counter is a saturation counter, meaning that it will not wrap around once it hits the maximum representable count. + This mechanism has two associated CSRs: + + - Accumulation max value. + This is the total number (sum of all alerts classified in this group) of alerts required to enter escalation phase (see below). + Example register is {{< regref "CLASSA_ACCUM_THRESH_SHADOWED" >}}. + - Current accumulation register. + This clearable register indicates how many alerts have been accumulated to date. + Software should clear before it reaches the accumulation setting to avoid escalation. + Example register is {{< regref "CLASSA_ACCUM_CNT" >}}. + +2. The second way is an interrupt timeout counter which triggers escalation if an alert interrupt is not handled within the programmable timeout window. + Once the counter hits the timeout threshold, the escalation protocol is triggered. + The corresponding CSRs are: + + - Interrupt timeout value in cycles {{< regref "CLASSA_TIMEOUT_CYC_SHADOWED" >}}. + The interrupt timeout is disabled if this is set to 0 (default). + - The current interrupt timeout value can be read via {{< regref "CLASSA_ESC_CNT" >}} if {{< regref "CLASSA_STATE" >}} is in the `Timeout` state. + Software should clear the corresponding interrupt state bit {{< regref "INTR_STATE.CLASSA" >}} before the timeout expires to avoid escalation. + +Technically, the interrupt timeout feature (2. above) is implemented using the same counter used to time the escalation phases. +This is possible since escalation phases or interrupt timeout periods are non-overlapping (escalation always takes precedence should it be triggered). + + +### Programmable Escalation Protocol + +There are four output escalation signals, 0, 1, 2, and 3. +There is no predetermined definition of an escalation signal, that is left to the top-level integration. +Examples could be processor Non Maskable Interrupt (NMI), privilege lowering, secret wiping, chip reset, etc. +Typically the assumption is that escalation level 0 is the first to trigger, followed by 1, 2, and then 3, emulating a "fuse" that is lit that can't be stopped once the first triggers (this is however not a requirement). +See register section for discussion of counter clearing and register locking to determine the finality of accumulation +triggers. + +Each class can be programmed with its own escalation protocol. +If one of the two mechanisms described above fires, a timer for that particular class is started. +The timer can be programmed with up to 4 delays (e.g., {{< regref "CLASSA_PHASE0_CYC" >}}), each representing a distinct escalation phase (0 - 3). +Each of the four escalation severity outputs (0 - 3) are by default configured to be asserted during the corresponding phase, e.g., severity 0 in phase 0, severity 1 in phase 1, etc. +However, this mapping can be freely reassigned by modifying the corresponding enable/phase mappings (e.g., {{< regref "CLASSA_CTRL_SHADOWED.E0_MAP" >}} for enable bit 0 of class A). +This mapping will be locked in together with the alert enable configuration after initial configuration. + +SW can stop a triggered escalation protocol by clearing the corresponding escalation counter (e.g., {{< regref "CLASSA_ESC_CNT" >}}). +Protection of this clearing is up to software, see the register control section that follows for {{< regref "CLASSA_CTRL_SHADOWED.LOCK" >}}. + +It should be noted that each of the escalation phases have a duration of at least 1 clock cycle, even if the cycle count of a particular phase has been +set to 0. + +The next waveform shows the gathering of alerts of one class until eventually the escalation protocol is engaged. +In this diagram, two different alerts are shown for class A, and the gathering and escalation configuration values are shown. + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p...................' }, + { name: 'CLASSA_ACCUM_THRESH_SHADOWED', wave: '2...................', data: ['15'] }, + { name: 'CLASSA_PHASE0_CYC_SHADOWED', wave: '2...................', data: ['1e3 cycles'] }, + { name: 'CLASSA_PHASE1_CYC_SHADOWED', wave: '2...................', data: ['1e4 cycles'] }, + { name: 'CLASSA_PHASE2_CYC_SHADOWED', wave: '2...................', data: ['1e5 cycles'] }, + { name: 'CLASSA_PHASE3_CYC_SHADOWED', wave: '2...................', data: ['1e6 cycles'] }, + { name: 'alert_triggered[0]', wave: '010|.10.............' }, + { name: 'alert_triggered[1]', wave: '0..|10..............' }, + { name: 'CLASSA_ACCUM_CNT', wave: '33.|33..............', data: ['0', '1','15','16'] }, + { name: 'irq_o[0]', wave: '01.|................' }, + { name: 'CLASSA_STATE', wave: '3..|.3|3.|3..|3..|3.', data: ['Idle', ' Phase0','Phase1','Phase2','Phase3','Terminal'] }, + { name: 'CLASSA_ESC_CNT', wave: '3..|.3|33|333|333|3.', data: ['0','1','1','2','1','2','3','1','2','3','0'] }, + { name: 'esc_tx_o.esc_p[0]', wave: '0..|.1|.0...........', node: '.....a..b' }, + { name: 'esc_tx_o.esc_n[0]', wave: '1..|.0|.1...........' }, + { name: 'esc_tx_o.esc_p[1]', wave: '0..|..|1.|.0........', node: '.......c...d' }, + { name: 'esc_tx_o.esc_n[1]', wave: '1..|..|0.|.1........' }, + { name: 'esc_tx_o.esc_p[2]', wave: '0..|.....|1..|.0....', node: '..........e....f' }, + { name: 'esc_tx_o.esc_n[2]', wave: '1..|.....|0..|.1....' }, + { name: 'esc_tx_o.esc_p[3]', wave: '0..|.........|1..|.0', node: '..............g....h' }, + { name: 'esc_tx_o.esc_n[3]', wave: '1..|.........|0..|.1' }, + ], + edge: [ + 'a->b 1e3 + 1 cycles', + 'c->d 1e4 + 1 cycles', + 'e->f 1e5 + 1 cycles', + 'g->h 1e6 + 1 cycles', + ], + head: { + text: 'Alert class gathering and escalation triggers (fully synchronous case)', + }, + foot: { + text: 'alert class A gathers 16 alerts, triggers first escalation, followed by three more', + tick: 0, + } +} +{{< /wavejson >}} + +In this diagram, the first alert triggers an interrupt to class A. +The assumption is that the processor is wedged or taken over, in which case it does not handle the interrupt. +Once enough interrupts gather (16 in this case), the first escalation phase is entered, followed by three more (each phase has its own programmable length). +Note that the accumulator threshold is set to 15 in order to trigger on the 16th occurrence. +If escalation shall be triggered on the first occurrence within an alert class, the accumulation threshold shall be set to 0. +Also note that it takes one cycle to activate escalation and enter phase 0. + +The next wave shows a case where an interrupt remains unhandled and hence the interrupt timeout counter triggers escalation. + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p.....................' }, + { name: 'CLASSA_TIMEOUT_CYC_SHADOWED', wave: '2.....................', data: ['1e4 cycles'] }, + { name: 'alert_triggered[0]', wave: '010.|.................' }, + { name: 'irq_o[0]', wave: '01..|.................', node: '.a..|.b' }, + { name: 'CLASSA_ESC_STATE', wave: '33..|.3|3.|3..|3...|3.', data: ['Idle', 'Timeout',' Phase0','Phase1','Phase2','Phase3','Terminal'] }, + { name: 'CLASSA_ESC_CNT', wave: '3333|33|33|333|3333|3.', data: ['0', '1','2','3','1e4','1','1','2','1','2','3','1','2','3','4','0'] }, + { name: 'esc_tx_o.esc_p[0]', wave: '0...|.1|.0............' }, + { name: 'esc_tx_o.esc_n[0]', wave: '1...|.0|.1............' }, + { name: 'esc_tx_o.esc_p[1]', wave: '0...|..|1.|.0.........' }, + { name: 'esc_tx_o.esc_n[1]', wave: '1...|..|0.|.1.........' }, + { name: 'esc_tx_o.esc_p[2]', wave: '0...|.....|1..|.0.....' }, + { name: 'esc_tx_o.esc_n[2]', wave: '1...|.....|0..|.1.....' }, + { name: 'esc_tx_o.esc_p[3]', wave: '0...|.........|1...|.0' }, + { name: 'esc_tx_o.esc_n[3]', wave: '1...|.........|0...|.1' }, + ], + edge: [ + 'a->b 1e4 cycles', + ], + head: { + text: 'Escalation due to an interrupt timeout (fully synchronous case)', + }, + foot: { + text: 'alert class A triggers an interrupt and the timeout counter, which eventually triggers escalation after 1e4 cycles.', + tick: 0, + } +} +{{< /wavejson >}} + +It should be noted here that the differential escalation signaling protocol distinguishes 'true' escalation conditions from mere pings by encoding them as pulses that are N + 1 cycles long. +This is reflected in the two wave diagrams above. +Refer to the subsequent section on escalation signaling for more details. + +### Escalation Signaling + +For each of the four escalation severities, the alert handler instantiates a `prim_esc_sender` module and each of the four escalation countermeasures instantiates an `prim_esc_receiver` module. +The signaling mechanism has similarities with the alert signaling mechanism - but it is a fully synchronous protocol. +Hence, it must be ensured at the top-level that all escalation sender and receiver modules are using the same clock and reset +signals. + +As illustrated in the following block diagram, a sender-receiver pair is connected with two differential lines, one going from sender to receiver and the other going from receiver to sender. + +![Alert Handler Escalation RXTX](alert_handler_escalation_rxtx.svg) + +Upon receiving an escalation enable pulse of width N > 0 at the `esc_req_i` input, the escalation sender encodes that signal as a differential pulse of width N+1 on `esc_tx.esc_p/n`. +The receiver decodes that message and asserts the `esc_req_o` output after one cycle of delay. +Further, it acknowledges the receipt of that message by continuously toggling the `esc_rx.resp_p/n` signals as long as the escalation signal is asserted. +Any failure to respond correctly will trigger a `integ_fail_o` alert, as illustrated below: + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p..................' }, + { name: 'ping_req_i', wave: '0........|.........' }, + { name: 'ping_ok_o', wave: '0........|.........' }, + { name: 'integ_fail_o', wave: '0........|..1010...' , node: '............b.d' }, + { name: 'ping_fail_o', wave: '0........|.........' }, + { name: 'esc_req_i', wave: '01....0..|.1....0..' }, + { name: 'esc_rx_i/o.resp_p', wave: '0.101010.|.........', node: '............a.c' }, + { name: 'esc_rx_i/o.resp_n', wave: '1.010101.|.........' }, + { name: 'esc_tx_o/i.esc_p', wave: '01.....0.|.1.....0.' }, + { name: 'esc_tx_o/i.esc_n', wave: '10.....1.|.0.....1.' }, + { name: 'esc_req_o', wave: '0.1....0.|..?....0.'}, + ], + edge: [ + 'a~>b missing response', + 'c~>d', + ], + head: { + text: 'Escalation signaling and response', + }, + foot: { + text: 'escalation enable pulse shown at input sender at time 1 and 11; missing response and repeated integfail at time 12 and 14', + tick: 0, + } +} +{{< /wavejson >}} + +Further, any differential signal mismatch on both the `esc_tx_i.esc_p/n` and `esc_rx_i.resp_p/n` lines will trigger an `integ_fail_o` alert. +Mismatches on `esc_rx_i.resp_p/n` can be directly detected at the sender. +Mismatches on the `esc_tx_i.esc_p/n` line will be signaled back to the sender by setting both the positive and negative response wires to the same value - and that value is being toggled each cycle. +This implicitly triggers a signal integrity alert on the sender side. +In addition to that, a signal integrity error on the `esc_tx_i.esc_p/n` lines will lead to assertion of the `esc_req_o` output, since it cannot be guaranteed that the back signalling mechanism always works when the sender / receiver pair is being tampered with. + +This back-signaling mechanism can be leveraged to fast-track escalation and use another countermeasure in case it is detected that a particular escalation signaling path has been tampered with. + +Some signal integrity failure cases are illustrated in the wave diagram below: + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p...........' }, + { name: 'ping_req_i', wave: '0....|......' }, + { name: 'ping_ok_o', wave: '0....|......' }, + { name: 'integ_fail_o', wave: '0.1.0|.1....' , node: '..b....e' }, + { name: 'esc_req_i', wave: '0....|......' }, + { name: 'esc_rx_i.resp_p', wave: '0.1.0|..1010', node: '..a..' }, + { name: 'esc_rx_i.resp_n', wave: '1....|.01010', node: '.......d' }, + { name: 'esc_tx_i.esc_p', wave: '0....|1.....', node: '......c..' }, + { name: 'esc_tx_i.esc_n', wave: '1....|......' }, + { name: 'esc_req_o', wave: '0....|1.....'}, + ], + edge: [ + 'a~>b', + 'c->d', + 'd->e', + ], + head: { + text: 'possible signal integrity failure cases', + }, + foot: { + text: 'direct signal integrity failure at time 2; indirect failure at time 6', + tick: 0, + } +} +{{< /wavejson >}} + + +### Ping Testing of the Escalation Signals + + +Similarly to the alert signaling scheme, the escalation signaling lines can be pinged / line tested in order to test whether the escalation receiver has been tampered with. +This is achieved by asserting `ping_req_i` at the escalation sender module. +A ping request is encoded as a single cycle pulse on the `esc_tx_o.esc_p/n` outputs. +Hence, the receiver module will not decode this single cycle pulse as an escalation enable message, but it will respond to it with a "1010" pattern on the `esc_rx_i.resp_p/n` lines. +The escalation sender module will assert `ping_ok_o` if that pattern is received correctly after one cycle of latency. +Otherwise, the escalation sender will first assert `integ_fail_o` later, after the programmable ping timeout is reached, the LFSR timer will raise a "pingfail" alert. +The `integ_fail_o` triggers in this case since "no ping response" and "wrong ping response" are ambiguous in this setting, and it has been decided to not suppress integrity failures when expecting a ping response. + +This mechanism is illustrated below from the viewpoint of the sender module. + +{{< wavejson >}} +{ + signal: [ + { name: 'clk_i', wave: 'p..............' }, + { name: 'ping_req_i', wave: '01....0|.1.....' , node: '.a'}, + { name: 'ping_ok_o', wave: '0....10|.......' , node: '.....e....g'}, + { name: 'integ_fail_o', wave: '0......|..10101' }, + { name: 'esc_req_i', wave: '0......|.......' }, + { name: 'esc_rx_i.resp_p', wave: '0.1010.|.......' , node: '..c..d....f'}, + { name: 'esc_rx_i.resp_n', wave: '1.0101.|.......' }, + { name: 'esc_tx_o.esc_p', wave: '010....|.10....' , node: '.b'}, + { name: 'esc_tx_o.esc_n', wave: '101....|.01....' }, + ], + edge: [ + 'a->b', + 'b->c', + 'd->e correct response', + 'f->g missing response', + ], + head: { + text: 'ping testing of escalation lines', + }, + foot: { + text: 'ping trig at sender input at time 1 and 9; correct response at time 5; missing response at time 10', + tick: 0, + } +} +{{< /wavejson >}} + +Note that the escalation signal always takes precedence, and the `ping_req_i` will just be acknowledged with `ping_ok_o` in case `esc_req_i` is already asserted. +An ongoing ping sequence will be aborted immediately. + +Another thing to note is that the ping and escalation response sequences have to start _exactly_ one cycle after either a ping or escalation event has been signaled. +Otherwise the escalation sender will assert `integ_fail_o` immediately. + +### Monitoring of Pings at the Escalation Receiver Side + +Escalation receivers contain a mechanism to monitor the liveness of the alert handler itself. +In particular, the receivers passively monitor the ping requests sent out by the alert handler using a timeout counter. +If ping requests are absent for too long, the corresponding escalation action will be automatically asserted until reset. + +The monitoring mechanism builds on top of the following properties of the alert handler system: +1. the ping mechanism can only be enabled, but not disabled. +This allows us to start the timeout counter once the first ping request arrives at a particular escalation receiver. + +2. the escalation receivers are in the same clock/reset domain as the alert handler. +This ensures that we are seeing the same clock frequency, and the mechanism is properly reset together with the alert handler logic. + +3. the maximum cycle count between subsequent pings on the same escalation line is bounded, even though the wait counts are randomized. +This allows us to compute a safe and fixed timeout threshold based on design constants. + + +### Low-power Management of Alert Channels + +Due to the various clock and reset domains in the OpenTitan system, the alert handler ping mechanism needs to have additional logic to deal with alert senders that are either held in reset, or that are clock gated. +This is needed to ensure that no false alarms are produced by the ping mechanism when an alert channel (sender / receiver pair) does not respond due to the sender being either in reset or clock gated. + +Since the FSMs associated with an alert channel may end up in an inconsistent state when the sender is reset or gated while an asynchronous event handshake is in progress, this logic also needs to be able to re-initialize affected alert channels whenever the channels comes back from reset / clock gated state. + +#### Assumptions + +The following diagram shows a typical arrangement of alert sender (TX) and receiver (RX) pairs. + +![Alert Handler Low-Power Overview](alert_handler_lp_overview.svg) + +It is assumed that: + +1. The alert handler clock domain cannot be gated by SW. + This means that this clock domain is only ever disabled as part of the power-down sequence of the corresponding power domain. +2. The alert senders are in general located within different clock and reset domains than the alert receivers within the alert handler, and thus use the asynchronous event handshake mode. +3. Some alert senders may be located in an always-on (AON) power domain, within different clock and reset groups than the alert handler. +4. The alert handler may be located in an non-AON power domain, and may thus undergo a reset cycle where it cannot be guaranteed that all alert senders are reset as well (i.e., some alert senders may retain their state). + +Further, we assume that we can get the following side-band information from the clock and reset managers in the system: + +- All relevant reset signals pertaining to alert sender domains +- All relevant clock enable signals pertaining to alert sender domains + +#### Scenarios + +With the assumptions above, the following two problematic scenarios can occur. + +##### Alert Handler in Reset + +It may happen that the alert handler is reset while some alert senders (e.g. those located in the AON domain) are not. +In general, if the associated alert channels are idle during an alert handler reset cycle, no problems arise.  + +However, if an alert channel is reset while it is handling a ping request or an alert event, the sender / receiver FSMs may end up in an inconsistent state upon deassertion of the alert handler reset. +This can either lead to spurious alert or ping events, or a completely locked up alert channel which will be flagged eventually by the ping mechanism. + +##### Alert Sender in Reset or Clock-gated + +If any of the alert senders is either put into reset or its clock is disabled while the alert handler is operational, the ping mechanism inside the alert handler will eventually report a ping failure because of missing ping responses from the affected alert channel(s). + +Further, if the alert sender is reset while the corresponding alert channel is handling a ping request or an alert event, the sender / receiver FSMs may end up in an inconsistent state after reset deassertion. + +#### Employed Solution + +As elaborated before, the side effects of resetting / clock gating either the alert handler or any of the alert senders are inconsistent FSM states, leading to locked up alert channels, or spurious alert or ping events. +To address these issues, we have to: + +1. make sure spurious events (alert and ping_ok outputs of the alert receivers) are suppressed if an alert channel is clock gated or in reset, +2. provide a mechanism for resetting an alert channel to an operational state once the associated clock is re-enabled, or the associated reset is released, +3. trigger this reset mechanism on all alert channels whenever the alert handler itself has been reset. + +To attain this, the idea is to make use of side-band information available from the clock and reset managers to detect whether an alert channel (or a group of alert channels with the same clock and reset on the sender side) has to be put into a low-power state. +In the following we will refer to such a clock / reset domain grouping as a low-power group (LPG). + +The mechanism is illustrated below for a single LPG (in practice, this logic is replicated for each LPG that is identified in the system): + +![Alert Handler LPG Ctrl](alert_handler_lpg_ctrl.svg) + +The clock gating enable (`lpg_cg_en`) and reset enable (`lpg_rst_en`) indications are routed as multibit signals to the alert handler, where they are synchronized to the alert handler clock and logically combined using an OR function to form a combined low-power indication signal that is multibit encoded. + +This multibit indication signal is then routed to all alert receivers, where it is used to trigger re-initialization of each alert channel, and bypass the ping requests from the ping mechanism. + +To that end, two extra *init states* are added to the alert receiver FSMs to perform this in-band reset, as indicated in the state diagram below: + +![Alert Handler Receiver FSM](alert_handler_receiver_fsm.svg) + +Whenever the `init_trig` multibit signal of an LPG is asserted, all corresponding sender FSMs are moved into the `InitReq` state. +In that state, the alert receivers immediately acknowledge ping requests from the ping mechanism, and ignore alert events from the sender side. +In addition to that, the receivers intentionally place a signal integrity error onto the `ping_p` / `ping_n`, `ack_p` / `ack_n` lines going from receivers to the senders. +This causes the senders to 1) move into the signal integrity error state, and 2) respond by placing a signal integrity error onto the `alert_p` / `alert_n` lines, which serves as an initialization "acknowledge" signal in this case. +Since the sender FSMs fall back into the `Idle` state once the signal integrity error disappears, this procedure essentially implements an in-band reset mechanism with an acknowledgement handshake that can be used to determine whether the reset has been successful. + +#### Implementation Aspects + +##### Ping Mechanism Bypass + +Note that the ping bypass mechanism is to be implemented in a way that pings are only ack'ed immediately if 1) the FSM is in the `InitReq` state, and 2) the `init_trig` signal is still asserted. + +This allows to subject the initialization process of each alert channel to the ping mechanism for channels that are recovering from a reset or clock gated cycle on the sender side. +I.e., alert channels that get stuck during the initialization process can be detected by the ping mechanism since ping requests are not immediately ack'ed anymore once `init_trig` is deasserted. + +##### FSM Encoding + +Since there are many alert channels in the design, the receiver and sender FSMs themselves are not sparsely encoded. +Instead, we rely on the ping mechanism to detect alert channels that are in a bad state. +The specific implementation of the ping bypass mentioned in the previous subsection ensures that the ping mechanism can also be used to monitor the initialization sequence of alert channels. + +##### Latency / Skew Considerations + +Due to asynchronous transitions and different path latencies in the system, a change in reset or clock gating state will experience a different latency through the alert channels than through the indication signals (`rst_n` and `clk_en`) that are connected to the low-power control logic. + +It is consequently possible for a group of alert senders to already be in reset or clock gated state, while the corresponding LPG logic does not yet know about this state change - and vice versa. + +In practice, this means that ping requests may be pending for several cycles until the LPG logic detects a reset or clock-gated condition and disables the corresponding alert channel(s). +Fortunately, such delay can be tolerated by setting the ping timeout to a sufficiently large value (see {{< regref "CLASSA_TIMEOUT_CYC_SHADOWED" >}}). + +As for alert events, this latency difference should not pose a problem. +Alert events may get stuck in the alert sender due to a reset or clock-gated condition - but this is to be expected. + +##### Integration Considerations + +Note that due to the aforementioned latency tolerance built into the ping timer, it is permissible to connect **any** reset or clock enable indication signal from the relevant clock group to the LPG logic. +I.e., the only requirement is that the indication signals are logically related to the resets and clocks routed to the alert senders, and that the skew between reset / clock state changes and the indication signals is bounded. + +The topgen script is extended so that it can identify all LPGs and the associated alert channels. +This information is then used to parameterize the alert handler design, and make the necessary top-level connections from the reset and clock management controllers to the alert handler. + +### Hardening Against Glitch Attacks + +In addition to the differential alert and escalation signalling scheme, the internal state machines and counters are hardened against glitch attacks as described bellow: + +1. Ping Timer: + - The FSM is sparsely encoded. + - The LFSR and the counter are duplicated. + - If the FSM or counter are glitched into an invalid state, all internal ping fail alerts will be permanently asserted. + +2. Escalation Timers: + - The escalation timer FSMs are sparsely encoded. + - The escalation timer counters are duplicated. + - The escalation accumulators are duplicated. + - If one of these FSMs, counters or accumulators are glitched into an invalid state, all escalation actions will be triggered and the affected FSM goes into a terminal `FsmError` state. + +3. CSRs: + - Critical configuration CSRs are shadowed. + - The shadow CSRs can trigger additional internal alerts for CSR storage and update failures. + These internal alerts are fed back into the alert classifier in the same manner as the ping and integrity failure alerts. + +4. LPGs: + - Clock-gated and reset-asserted indication signals that are routed from clock and reset managers to the alert handler are encoded with multibit signals. + +# Programmers Guide + + +## Power-up and Reset Considerations + +False alerts during power-up and reset are not possible since the alerts are disabled by default, and need to be configured and locked in by the firmware. +The ping timer won't start until initial configuration is over and the registers are locked in. + +The low-power state management of alert channels is handled entirely by hardware and hence this is transparent to software. +Note however that the LPGs inherit the security properties of the associated clock groups and resets. +This means that the low-power state of certain alerts can be controlled by SW by means of clock gating or block reset. +For example, certain crypto blocks are located in a transactional clock group which can be clock gated by SW - and this also affects the associated alerts of these crypto blocks. +See [clock]({{< relref "hw/ip/clkmgr/doc/" >}}) and [reset managers]({{< relref "hw/ip/rstmgr/doc" >}}) for more detail. + + +## Initialization + +To initialize the block, software running at a high privilege levels (early in the security settings process) should do the following: + +1. For each alert and each local alert: + + - Determine if alert is enabled (should only be false if alert is known to be faulty). + Set {{< regref "ALERT_EN.EN_A0" >}} and {{< regref "LOC_ALERT_EN.EN_LA0" >}} accordingly. + + - Determine which class (A..D) the alert is associated with. + Set {{< regref "ALERT_CLASS.CLASS_A" >}} and {{< regref "LOC_ALERT_CLASS.CLASS_LA" >}} accordingly. + + - Optionally lock each alert configuration by writing 0 to {{< regref "ALERT_EN_REGWEN.EN0" >}} or {{< regref "LOC_ALERT_EN_REGWEN.EN0" >}}. + Note however that only **locked and enabled** alerts are going to be pinged using the ping mechanism. + This ensures that spurious ping failures cannot occur when previously enabled alerts are being disabled again (before locking). + + +2. Set the ping timeout value {{< regref "PING_TIMEOUT_CYC_SHADOWED" >}}. + This value is dependent on the clock ratios present in the system. + +3. For each class (A..D): + + - Determine whether to enable escalation mechanisms (accumulation / interrupt timeout) for this particular class. Set {{< regref "CLASSA_CTRL_SHADOWED.EN" >}} accordingly. + + - Determine if this class of alerts allows clearing of escalation once it has begun. + Set {{< regref "CLASSA_CTRL_SHADOWED.LOCK" >}} to true if clearing should be disabled. + If true, once escalation protocol begins, it can not be stopped, the assumption being that it ends in a chip reset else it will be rendered useless thenceforth. + + - Determine the number of alerts required to be accumulated before escalation protocol kicks in. Set {{< regref "CLASSA_ACCUM_THRESH" >}} accordingly. + + - Determine whether the interrupt associated with that class needs a timeout. + If yes, set {{< regref "CLASSA_TIMEOUT_CYC_SHADOWED" >}} to an appropriate value greater than zero (zero corresponds to an infinite timeout and disables the mechanism). + + - For each escalation phase (0..3): + - Determine length of each escalation phase by setting {{< regref "CLASSA_PHASE0_CYC" >}} accordingly + + - For each escalation signal (0..3): + - Determine whether to enable the escalation signal, and set the {{< regref "CLASSA_CTRL_SHADOWED.E0_EN" >}} bit accordingly (default is enabled). + Note that setting all of the `E*_EN` bits to 0 within a class has the same effect of disabling the entire class by setting {{< regref "CLASSA_CTRL_SHADOWED.EN" >}} to zero. + - Determine the phase -> escalation mapping of this class and program it via the {{< regref "CLASSA_CTRL_SHADOWED.E0_MAP" >}} values if it needs to be changed from the default mapping (0->0, 1->1, 2->2, 3->3). + + - Optionally lock the class configuration by writing 0 to {{< regref "CLASSA_CTRL_SHADOWED.REGWEN" >}}. + +4. After initial configuration at startup, enable the ping timer mechanism by writing 1 to {{< regref "PING_TIMER_EN" >}}. +It is also recommended to lock the ping timer configuration by clearing {{< regref "PING_TIMER_REGWEN" >}}. +Note that only **locked and enabled** alerts are going to be pinged using the ping mechanism. +This ensures that spurious ping failures cannot occur when previously enabled alerts are being disabled again (before locking). + +## Interrupt Handling + +For every alert that is enabled, an interrupt will be triggered on class A, B, C, or D. +To handle an interrupt of a particular class, software should execute the following steps: + +1. If needed, check the escalation state of this class by reading {{< regref "CLASSA_STATE" >}}. + This reveals whether escalation protocol has been triggered and in which escalation phase the class is. + In case interrupt timeouts are enabled the class will be in timeout state unless escalation has already been triggered. + The current interrupt or escalation cycle counter can be read via {{< regref "CLASSA_ESC_CNT" >}}. + +2. Since the interrupt does not indicate which alert triggered, SW must read the cause registers {{< regref "LOC_ALERT_CAUSE" >}} and {{< regref "ALERT_CAUSE" >}} etc. + The cause bits of all alerts are concatenated and chunked into 32bit words. + Hence the register file contains as many cause words as needed to cover all alerts present in the system. + Each cause register contains a sticky bit that is set by the incoming alert, and is clearable with a write by software. + This should only be cleared after software has cleared the event trigger, if applicable. + It is possible that the event requires no clearing (e.g. a parity error), or can't be cleared (a breach in the metal mesh protecting the chip). + + Note that in the rare case when multiple events are triggered at or about the same time, all events should be cleared before proceeding. + +3. After the event is cleared (if needed or possible), software should handle the interrupt as follows: + + - Resetting the accumulation register for the class by writing {{< regref "CLASSA_CLR" >}}. + This also aborts the escalation protocol if it has been triggered. + If for some reason it is desired to never allow the accumulator or escalation to be cleared, software can initialize the {{< regref "CLASSA_CLR_REGWEN" >}} register to zero. + If {{< regref "CLASSA_CLR_REGWEN" >}} is already false when an alert interrupt is detected (either due to software control or hardware trigger via {{< regref "CLASSA_CTRL_SHADOWED.LOCK" >}}), then the accumulation counter can not be cleared and this step has no effect. + + - After the accumulation counter is reset (if applicable), software should clear the class A interrupt state bit {{< regref "INTR_STATE.CLASSA" >}}. + Clearing the class A interrupt state bit also clears and stops the interrupt timeout counter (if enabled). + +Note that testing interrupts by writing to the interrupt test registers does also trigger the internal interrupt timeout (if enabled), since the interrupt state is used as enable signal for the timer. +However, alert accumulation will not be triggered by this testing mechanism. + +## Register Table + +{{< incGenFromIpDesc "../data/alert_handler.hjson" "registers" >}} + + +# Additional Notes + +## Timing Constraints + +The skew within all differential signal pairs must be constrained to be smaller than the period of the fastest clock operating the alert handler receivers. +The maximum propagation delay of differential pair should also be constrained (although it may be longer than the clock periods involved). + + +## Fast-track Alerts + +Note that it is possible to program a certain class to provide a fast-track response for critical alerts by setting its accumulation trigger value to 1, and configuring the escalation protocol such that the appropriate escalation measure is triggered within escalation phase 0. +This results in a minimal escalation latency of 4 clock cycles from alert sender input to escalation receiver output in the case where all involved signaling modules are completely synchronous with the alert handler. +In case the alert sender is asynchronous w.r.t. to the alert handler, the actual latency depends on the clock periods involved. +Assuming both clocks have the same frequency alert propagation takes at least 6-8 clock alert handler clock cycles. + +For alerts that mandate an asynchronous response (i.e. without requiring a clock to be active), it is highly recommended to build a separate network at the top-level. +That network should OR' the critical sources together and route the asynchronous alert signal directly to the highest severity countermeasure device. +Examples for alert conditions of this sort would be attacks on the secure clock. diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_alert_rxtx.svg b/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_alert_rxtx.svg new file mode 100644 index 0000000000000..d851d503f36b3 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_alert_rxtx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_block_diagram.svg b/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_block_diagram.svg new file mode 100644 index 0000000000000..1976ea10fb97e --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_block_diagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_escalation_rxtx.svg b/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_escalation_rxtx.svg new file mode 100644 index 0000000000000..9012f2c0d2934 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/alert_handler_escalation_rxtx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/checklist.md b/hw/top_earlgrey/ip_autogen/alert_handler/doc/checklist.md new file mode 100644 index 0000000000000..512c7ad207eeb --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/checklist.md @@ -0,0 +1,241 @@ +--- +title: "Alert Handler Checklist" +--- + +This checklist is for [Hardware Stage]({{< relref "/doc/project/development_stages.md" >}}) transitions for the [Alert Handler peripheral.]({{< relref "./" >}}) +All checklist items refer to the content in the [Checklist.]({{< relref "/doc/project/checklist.md" >}}) + +## Design Checklist + +### D1 + +Type | Item | Resolution | Note/Collaterals +--------------|----------------------- |-------------|------------------ +Documentation | [SPEC_COMPLETE][] | Done | [Alert Handler spec]({{< relref "./" >}}) +Documentation | [CSR_DEFINED][] | Done | +RTL | [CLKRST_CONNECTED][] | Done | +RTL | [IP_TOP][] | Done | +RTL | [IP_INSTANTIABLE][] | Done | +RTL | [PHYSICAL_MACROS_DEFINED_80][] | Done | +RTL | [FUNC_IMPLEMENTED][] | Done | +RTL | [ASSERT_KNOWN_ADDED][] | Done | +Code Quality | [LINT_SETUP][] | Done | + +[SPEC_COMPLETE]: {{}} +[CSR_DEFINED]: {{}} +[CLKRST_CONNECTED]: {{}} +[IP_TOP]: {{}} +[IP_INSTANTIABLE]: {{}} +[PHYSICAL_MACROS_DEFINED_80]: {{}} +[FUNC_IMPLEMENTED]: {{}} +[ASSERT_KNOWN_ADDED]: {{}} +[LINT_SETUP]: {{}} + +### D2 + +Type | Item | Resolution | Note/Collaterals +--------------|-------------------------|-------------|------------------ +Documentation | [NEW_FEATURES][] | Not Started | +Documentation | [BLOCK_DIAGRAM][] | Done | +Documentation | [DOC_INTERFACE][] | Done | +Documentation | [MISSING_FUNC][] | Not Started | +Documentation | [FEATURE_FROZEN][] | Not Started | +RTL | [FEATURE_COMPLETE][] | Not Started | +RTL | [AREA_CHECK][] | Not Started | +RTL | [PORT_FROZEN][] | Not Started | +RTL | [ARCHITECTURE_FROZEN][] | Not Started | +RTL | [REVIEW_TODO][] | Not Started | +RTL | [STYLE_X][] | Not Started | +Code Quality | [LINT_PASS][] | Done | +Code Quality | [CDC_SETUP][] | Done | +Code Quality | [FPGA_TIMING][] | Not Started | +Code Quality | [CDC_SYNCMACRO][] | Done | +Security | [SEC_CM_DOCUMENTED][] | Not Started | +Security | [SEC_RND_CNST][] | Not Started | + +[NEW_FEATURES]: {{}} +[BLOCK_DIAGRAM]: {{}} +[DOC_INTERFACE]: {{}} +[MISSING_FUNC]: {{}} +[FEATURE_FROZEN]: {{}} +[FEATURE_COMPLETE]: {{}} +[AREA_CHECK]: {{}} +[PORT_FROZEN]: {{}} +[ARCHITECTURE_FROZEN]: {{}} +[REVIEW_TODO]: {{}} +[STYLE_X]: {{}} +[LINT_PASS]: {{}} +[CDC_SETUP]: {{}} +[FPGA_TIMING]: {{}} +[CDC_SYNCMACRO]: {{}} +[SEC_CM_DOCUMENTED]: {{}} +[SEC_RND_CNST]: {{}} + +### D3 + + Type | Item | Resolution | Note/Collaterals +--------------|-------------------------|-------------|------------------ +Documentation | [NEW_FEATURES_D3][] | Not Started | +RTL | [TODO_COMPLETE][] | Not Started | +Code Quality | [LINT_COMPLETE][] | Not Started | +Code Quality | [CDC_COMPLETE][] | Not Started | +Review | [REVIEW_RTL][] | Not Started | +Review | [REVIEW_DELETED_FF][] | Not Started | +Review | [REVIEW_SW_CSR][] | Not Started | +Review | [REVIEW_SW_FATAL_ERR][] | Not Started | +Review | [REVIEW_SW_CHANGE][] | Not Started | +Review | [REVIEW_SW_ERRATA][] | Not Started | +Security | [SEC_CM_IMPLEMENTED][] | Not Started | +Security | [SEC_NON_RESET_FLOPS][] | Not Started | +Security | [SEC_SHADOW_REGS][] | Not Started | +Review | Reviewer(s) | Not Started | +Review | Signoff date | Not Started | + +[NEW_FEATURES_D3]: {{}} +[TODO_COMPLETE]: {{}} +[LINT_COMPLETE]: {{}} +[CDC_COMPLETE]: {{}} +[REVIEW_RTL]: {{}} +[REVIEW_DBG]: {{}} +[REVIEW_DELETED_FF]: {{}} +[REVIEW_SW_CSR]: {{}} +[REVIEW_SW_FATAL_ERR]: {{}} +[REVIEW_SW_CHANGE]: {{}} +[REVIEW_SW_ERRATA]: {{}} +[SEC_CM_IMPLEMENTED]: {{}} +[SEC_NON_RESET_FLOPS]: {{}} +[SEC_SHADOW_REGS]: {{}} + +## Verification Checklist + +### V1 + + Type | Item | Resolution | Note/Collaterals +--------------|---------------------------------------|-------------|------------------ +Documentation | [DV_DOC_DRAFT_COMPLETED][] | In Progress | +Documentation | [TESTPLAN_COMPLETED][] | In Progress | +Testbench | [TB_TOP_CREATED][] | Done | +Testbench | [PRELIMINARY_ASSERTION_CHECKS_ADDED][]| Done | +Testbench | [SIM_TB_ENV_CREATED][] | Done | +Testbench | [SIM_RAL_MODEL_GEN_AUTOMATED][] | Done | +Testbench | [CSR_CHECK_GEN_AUTOMATED][] | waived | Revisit later. Tool setup in progress. +Testbench | [TB_GEN_AUTOMATED][] | N/A | +Tests | [SIM_SMOKE_TEST_PASSING][] | Done | +Tests | [SIM_CSR_MEM_TEST_SUITE_PASSING][] | Done | +Tests | [FPV_MAIN_ASSERTIONS_PROVEN][] | Not Started | +Tool Setup | [SIM_ALT_TOOL_SETUP][] | N/A | +Regression | [SIM_SMOKE_REGRESSION_SETUP][] | Done | +Regression | [SIM_NIGHTLY_REGRESSION_SETUP][] | Not Started | +Regression | [FPV_REGRESSION_SETUP][] | Not Started | +Coverage | [SIM_COVERAGE_MODEL_ADDED][] | Not Started | +Code Quality | [TB_LINT_SETUP][] | Done | +Integration | [PRE_VERIFIED_SUB_MODULES_V1][] | N/A | +Review | [DESIGN_SPEC_REVIEWED][] | Not Started | +Review | [TESTPLAN_REVIEWED][] | Not Started | +Review | [STD_TEST_CATEGORIES_PLANNED][] | Not Started | Exception (?) +Review | [V2_CHECKLIST_SCOPED][] | Not Started | + +[DV_DOC_DRAFT_COMPLETED]: {{}} +[TESTPLAN_COMPLETED]: {{}} +[TB_TOP_CREATED]: {{}} +[PRELIMINARY_ASSERTION_CHECKS_ADDED]: {{}} +[SIM_TB_ENV_CREATED]: {{}} +[SIM_RAL_MODEL_GEN_AUTOMATED]: {{}} +[CSR_CHECK_GEN_AUTOMATED]: {{}} +[TB_GEN_AUTOMATED]: {{}} +[SIM_SMOKE_TEST_PASSING]: {{}} +[SIM_CSR_MEM_TEST_SUITE_PASSING]: {{}} +[FPV_MAIN_ASSERTIONS_PROVEN]: {{}} +[SIM_ALT_TOOL_SETUP]: {{}} +[SIM_SMOKE_REGRESSION_SETUP]: {{}} +[SIM_NIGHTLY_REGRESSION_SETUP]: {{}} +[FPV_REGRESSION_SETUP]: {{}} +[SIM_COVERAGE_MODEL_ADDED]: {{}} +[TB_LINT_SETUP]: {{}} +[PRE_VERIFIED_SUB_MODULES_V1]: {{}} +[DESIGN_SPEC_REVIEWED]: {{}} +[TESTPLAN_REVIEWED]: {{}} +[STD_TEST_CATEGORIES_PLANNED]: {{}} +[V2_CHECKLIST_SCOPED]: {{}} + +### V2 + + Type | Item | Resolution | Note/Collaterals +--------------|-----------------------------------------|-------------|------------------ +Documentation | [DESIGN_DELTAS_CAPTURED_V2][] | Not Started | +Documentation | [DV_DOC_COMPLETED][] | Not Started | +Testbench | [FUNCTIONAL_COVERAGE_IMPLEMENTED][] | Not Started | +Testbench | [ALL_INTERFACES_EXERCISED][] | Not Started | +Testbench | [ALL_ASSERTION_CHECKS_ADDED][] | Not Started | +Testbench | [SIM_TB_ENV_COMPLETED][] | Not Started | +Tests | [SIM_ALL_TESTS_PASSING][] | Not Started | +Tests | [FPV_ALL_ASSERTIONS_WRITTEN][] | Not Started | +Tests | [FPV_ALL_ASSUMPTIONS_REVIEWED][] | Not Started | +Tests | [SIM_FW_SIMULATED][] | Not Started | +Regression | [SIM_NIGHTLY_REGRESSION_V2][] | Not Started | +Coverage | [SIM_CODE_COVERAGE_V2][] | Not Started | +Coverage | [SIM_FUNCTIONAL_COVERAGE_V2][] | Not Started | +Coverage | [FPV_CODE_COVERAGE_V2][] | Not Started | +Coverage | [FPV_COI_COVERAGE_V2][] | Not Started | +Code Quality | [TB_LINT_PASS][] | Not Started | +Integration | [PRE_VERIFIED_SUB_MODULES_V2][] | Not Started | +Issues | [NO_HIGH_PRIORITY_ISSUES_PENDING][] | Not Started | +Issues | [ALL_LOW_PRIORITY_ISSUES_ROOT_CAUSED][] | Not Started | +Review | [DV_DOC_TESTPLAN_REVIEWED][] | Not Started | +Review | [V3_CHECKLIST_SCOPED][] | Not Started | + +[DESIGN_DELTAS_CAPTURED_V2]: {{}} +[DV_DOC_COMPLETED]: {{}} +[FUNCTIONAL_COVERAGE_IMPLEMENTED]: {{}} +[ALL_INTERFACES_EXERCISED]: {{}} +[ALL_ASSERTION_CHECKS_ADDED]: {{}} +[SIM_TB_ENV_COMPLETED]: {{}} +[SIM_ALL_TESTS_PASSING]: {{}} +[FPV_ALL_ASSERTIONS_WRITTEN]: {{}} +[FPV_ALL_ASSUMPTIONS_REVIEWED]: {{}} +[SIM_FW_SIMULATED]: {{}} +[SIM_NIGHTLY_REGRESSION_V2]: {{}} +[SIM_CODE_COVERAGE_V2]: {{}} +[SIM_FUNCTIONAL_COVERAGE_V2]: {{}} +[FPV_CODE_COVERAGE_V2]: {{}} +[FPV_COI_COVERAGE_V2]: {{}} +[TB_LINT_PASS]: {{}} +[PRE_VERIFIED_SUB_MODULES_V2]: {{}} +[NO_HIGH_PRIORITY_ISSUES_PENDING]: {{}} +[ALL_LOW_PRIORITY_ISSUES_ROOT_CAUSED]:{{}} +[DV_DOC_TESTPLAN_REVIEWED]: {{}} +[V3_CHECKLIST_SCOPED]: {{}} + +### V3 + + Type | Item | Resolution | Note/Collaterals +--------------|-----------------------------------|-------------|------------------ +Documentation | [DESIGN_DELTAS_CAPTURED_V3][] | Not Started | +Tests | [X_PROP_ANALYSIS_COMPLETED][] | Not Started | +Tests | [FPV_ASSERTIONS_PROVEN_AT_V3][] | Not Started | +Regression | [SIM_NIGHTLY_REGRESSION_AT_V3][] | Not Started | +Coverage | [SIM_CODE_COVERAGE_AT_100][] | Not Started | +Coverage | [SIM_FUNCTIONAL_COVERAGE_AT_100][]| Not Started | +Coverage | [FPV_CODE_COVERAGE_AT_100][] | Not Started | +Coverage | [FPV_COI_COVERAGE_AT_100][] | Not Started | +Code Quality | [ALL_TODOS_RESOLVED][] | Not Started | +Code Quality | [NO_TOOL_WARNINGS_THROWN][] | Not Started | +Code Quality | [TB_LINT_COMPLETE][] | Not Started | +Integration | [PRE_VERIFIED_SUB_MODULES_V3][] | Not Started | +Issues | [NO_ISSUES_PENDING][] | Not Started | +Review | Reviewer(s) | Not Started | +Review | Signoff date | Not Started | + +[DESIGN_DELTAS_CAPTURED_V3]: {{}} +[X_PROP_ANALYSIS_COMPLETED]: {{}} +[FPV_ASSERTIONS_PROVEN_AT_V3]: {{}} +[SIM_NIGHTLY_REGRESSION_AT_V3]: {{}} +[SIM_CODE_COVERAGE_AT_100]: {{}} +[SIM_FUNCTIONAL_COVERAGE_AT_100]:{{}} +[FPV_CODE_COVERAGE_AT_100]: {{}} +[FPV_COI_COVERAGE_AT_100]: {{}} +[ALL_TODOS_RESOLVED]: {{}} +[NO_TOOL_WARNINGS_THROWN]: {{}} +[TB_LINT_COMPLETE]: {{}} +[PRE_VERIFIED_SUB_MODULES_V3]: {{}} +[NO_ISSUES_PENDING]: {{}} diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/dv/index.md b/hw/top_earlgrey/ip_autogen/alert_handler/doc/dv/index.md new file mode 100644 index 0000000000000..976d01fab2598 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/dv/index.md @@ -0,0 +1,115 @@ +--- +title: "ALERT_HANDLER DV document" +--- + +## Goals +* **DV** + * Verify all ALERT_HANDLER IP features by running dynamic simulations with a SV/UVM based testbench + * Develop and run all tests based on the [testplan](#testplan) below towards closing code and functional coverage on the IP and all of its sub-modules +* **FPV** + * Verify TileLink device protocol compliance with an SVA based testbench + * Verify transmitter and receiver pairs for alert and escalator + * Partially verify ping_timer + +## Current status +* [Design & verification stage]({{< relref "hw" >}}) + * [HW development stages]({{< relref "doc/project/development_stages" >}}) +* [Simulation results](https://reports.opentitan.org/hw/ip/alert_handler/dv/latest/results.html) + +## Design features +For detailed information on ALERT_HANDLER design features, please see the [ALERT_HANDLER HWIP technical specification]({{< relref ".." >}}). + +## Testbench architecture +ALERT_HANDLER testbench has been constructed based on the [CIP testbench architecture]({{< relref "hw/dv/sv/cip_lib/doc" >}}). + +### Block diagram +![Block diagram](tb.svg) + +### Top level testbench +Top level testbench is located at `hw/ip/alert_handler/dv/tb/tb.sv`. It instantiates the ALERT_HANDLER DUT module `hw/ip/alert_handler/rtl/alert_handler.sv`. +In addition, it instantiates the following interfaces, connects them to the DUT and sets their handle into `uvm_config_db`: +* [Clock and reset interface]({{< relref "hw/dv/sv/common_ifs" >}}) +* [TileLink host interface]({{< relref "hw/dv/sv/tl_agent/README.md" >}}) +* ALERT_HANDLER IOs +* Interrupts ([`pins_if`]({{< relref "hw/dv/sv/common_ifs" >}})) +* Devmode ([`pins_if`]({{< relref "hw/dv/sv/common_ifs" >}})) + +The alert_handler testbench environment can be reused in chip level testing. + +### Common DV utility components +The following utilities provide generic helper tasks and functions to perform activities that are common across the project: +* [dv_utils_pkg]({{< relref "hw/dv/sv/dv_utils/README.md" >}}) +* [csr_utils_pkg]({{< relref "hw/dv/sv/csr_utils/README.md" >}}) + +### Global types & methods +All common types and methods defined at the package level can be found in +`alert_handler_env_pkg`. Some of them in use are: +```systemverilog + parameter uint NUM_MAX_ESC_SEV = 8; +``` + +### TL_agent +ALERT_HANDLER testbench instantiates (already handled in CIP base env) [tl_agent]({{< relref "hw/dv/sv/tl_agent/README.md" >}}) +which provides the ability to drive and independently monitor random traffic via +TL host interface into ALERT_HANDLER device. + +### ALERT_HANDLER Agent +[ALERT_HANDLER agent]:link WIP is used to drive and monitor transmitter and +receiver pairs for the alerts and escalators. + +### UVM RAL Model +The ALERT_HANDLER RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) `fusesoc` generator script automatically when the simulation is at the build stage. + +It can be created manually by invoking [`regtool`]({{< relref "util/reggen/README.md" >}}): + +### Stimulus strategy +#### Test sequences +All test sequences reside in `hw/ip/alert_handler/dv/env/seq_lib`. +The `alert_handler_base_vseq` virtual sequence is extended from `cip_base_vseq` and serves as a starting point. +All test sequences are extended from `alert_handler_base_vseq`. +It provides commonly used handles, variables, functions and tasks that the test sequences can simple use / call. +Some of the most commonly used tasks / functions are as follows: +* drive_alert: Drive alert_tx signal pairs through `alert_esc_if` interface +* read_ecs_status: Readout registers that reflect escalation status, including `classa/b/c/d_accum_cnt`, `classa/b/c/d_esc_cnt`, and `classa/b/c/d_state` + +#### Functional coverage +To ensure high quality constrained random stimulus, it is necessary to develop a functional coverage model. +The following covergroups have been developed to prove that the test intent has been adequately met: +* accum_cnt_cg: Cover number of alerts triggered under the same class +* esc_sig_length_cg: Cover signal length of each escalation pairs + +### Self-checking strategy +#### Scoreboard +The `alert_handler_scoreboard` is primarily used for end to end checking. +It creates the following analysis ports to retrieve the data monitored by corresponding interface agents: +* tl_a_chan_fifo: tl address channel +* tl_d_chan_fifo: tl data channel +* alert_fifo: An array of `alert_fifo` that connects to corresponding alert_monitors +* esc_fifo: An array of `esc_fifo` that connects to corresponding esc_monitors + +Alert_handler scoreboard monitors all valid CSR registers, alert handshakes, and escalation handshakes. +To ensure certain alert, interrupt, or escalation signals are triggered at the expected time, the alert_handler scoreboard implemented a few counters: +* intr_cnter_per_class[NUM_ALERT_HANDLER_CLASSES]: Count number of clock cycles that the interrupt bit stays high. + If the stored number is larger than the `timeout_cyc` registers, the corresponding escalation is expected to be triggered +* accum_cnter_per_class[NUM_ALERT_HANDLER_CLASSES]: Count number of alerts triggered under the same class. + If the stored number is larger than the `accum_threshold` registers, the corresponding escalation is expected to be triggered +* esc_cnter_per_signal[NUM_ESC_SIGNALS]: Count number of clock cycles that each escalation signal stays high. + Compare the counter against `phase_cyc` registers + +The alert_handler scoreboard is parameterized to support different number of classes, alert pairs, and escalation pairs. + +#### Assertions +* TLUL assertions: The `tb/alert_handler_bind.sv` binds the `tlul_assert` [assertions]({{< relref "hw/ip/tlul/doc/TlulProtocolChecker.md" >}}) to the IP to ensure TileLink interface protocol compliance. +* Unknown checks on DUT outputs: The RTL has assertions to ensure all outputs are initialized to known values after coming out of reset. + +## Building and running tests +We are using our in-house developed [regression tool]({{< relref "hw/dv/tools/README.md" >}}) for building and running our tests and regressions. +Please take a look at the link for detailed information on the usage, capabilities, features and known issues. +Here's how to run a smoke test: +```console +$ $REPO_TOP/util/dvsim/dvsim.py $REPO_TOP/hw/$CHIP/ip/alert_handler/dv/alert_handler_sim_cfg.hjson -i alert_handler_smoke +``` +In this run command, $CHIP can be top_earlgrey, etc. + +## Testplan +{{< incGenFromIpDesc "../../data/alert_handler_testplan.hjson" "testplan" >}} diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/doc/dv/tb.svg b/hw/top_earlgrey/ip_autogen/alert_handler/doc/dv/tb.svg new file mode 100644 index 0000000000000..4e2e670fe2138 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/doc/dv/tb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim.core b/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim.core similarity index 73% rename from hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim.core rename to hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim.core index 6cf71489dc0f2..e65adf32bafb4 100644 --- a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_sim.core +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim.core @@ -2,18 +2,18 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:dv:alert_handler_sim:0.1" +name: lowrisc:opentitan:top_earlgrey_alert_handler_sim:0.1 description: "ALERT_HANDLER DV sim target" filesets: files_rtl: depend: - - lowrisc:ip:alert_handler + - lowrisc:opentitan:top_earlgrey_alert_handler:0.1 file_type: systemVerilogSource files_dv: depend: - lowrisc:dv:alert_handler_tb - - lowrisc:top_earlgrey:alert_handler_sva + - lowrisc:opentitan:top_earlgrey_alert_handler_sva:0.1 file_type: systemVerilogSource generate: @@ -21,7 +21,7 @@ generate: generator: ralgen parameters: name: alert_handler - ip_hjson: ../data/autogen/alert_handler.hjson + ip_hjson: ../data/alert_handler.hjson targets: sim: &sim_target diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson new file mode 100644 index 0000000000000..d9932c8afdf0f --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson @@ -0,0 +1,106 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ + // Name of the sim cfg - typically same as the name of the DUT. + name: alert_handler + + // Top level dut name (sv module). + dut: alert_handler + + // Top level testbench name (sv module). + tb: tb + + // Simulator used to sign off this block + tool: vcs + + // Fusesoc core file used for building the file list. + fusesoc_core: lowrisc:opentitan:top_earlgrey_alert_handler_sim:0.1 + + // Testplan hjson file. + testplan: "{self_dir}/../data/alert_handler_testplan.hjson" + + // Import additional common sim cfg files. + import_cfgs: [// Project wide common sim cfg file + "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", + // Common CIP test lists + "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/intr_test.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson"] + + // Add additional tops for simulation. + sim_tops: ["alert_handler_bind"] + + // Default iterations for all tests - each test entry can override this. + reseed: 50 + + // Add ALERT_HANDLER specific exclusion files. + vcs_cov_excl_files: ["{self_dir}/cov/alert_handler_cov_excl.el"] + + // Default UVM test and seq class name. + uvm_test: alert_handler_base_test + uvm_test_seq: alert_handler_base_vseq + + // List of test specifications. + tests: [ + { + name: alert_handler_smoke + uvm_test_seq: alert_handler_smoke_vseq + } + + { + name: alert_handler_random_alerts + uvm_test_seq: alert_handler_random_alerts_vseq + } + + { + name: alert_handler_random_classes + uvm_test_seq: alert_handler_random_classes_vseq + } + + { + name: alert_handler_esc_intr_timeout + uvm_test_seq: alert_handler_esc_intr_timeout_vseq + } + + { + name: alert_handler_esc_alert_accum + uvm_test_seq: alert_handler_esc_alert_accum_vseq + } + + { + name: alert_handler_sig_int_fail + uvm_test_seq: alert_handler_sig_int_fail_vseq + } + + { + name: alert_handler_entropy + uvm_test_seq: alert_handler_entropy_vseq + run_opts: ["+test_timeout_ns=10_000_000_000"] + } + + { + name: alert_handler_ping_timeout + uvm_test_seq: alert_handler_ping_timeout_vseq + } + + { + name: alert_handler_stress_all + run_opts: ["+test_timeout_ns=15_000_000_000"] + } + + { + name: alert_handler_stress_all_with_rand_reset + } + ] + + // List of regressions. + regressions: [ + { + name: smoke + tests: ["alert_handler_smoke"] + } + ] +} diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/cov/alert_handler_cov_excl.el b/hw/top_earlgrey/ip_autogen/alert_handler/dv/cov/alert_handler_cov_excl.el new file mode 100644 index 0000000000000..d2a563c208366 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/cov/alert_handler_cov_excl.el @@ -0,0 +1,21 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +//================================================== +// This file contains the Excluded objects +// Generated By User: chencindy +// Format Version: 2 +// Date: Fri Oct 9 15:24:56 2020 +// ExclMode: default +//================================================== +CHECKSUM: "1270015083 3167692650" +INSTANCE: tb.dut +ANNOTATION: "[LOW_RISK] To reduce the simulation time, the max escalation cycle length is set to 1000." +Toggle crashdump_o.class_esc_cnt [0][31:10] "logic [3:0][31:0]crashdump_o.class_esc_cnt" +ANNOTATION: "[LOW_RISK] To reduce the simulation time, the max escalation cycle length is set to 1000." +Toggle crashdump_o.class_esc_cnt [3][31:10] "logic [3:0][31:0]crashdump_o.class_esc_cnt" +ANNOTATION: "[LOW_RISK] To reduce the simulation time, the max escalation cycle length is set to 1000." +Toggle crashdump_o.class_esc_cnt [2][31:10] "logic [3:0][31:0]crashdump_o.class_esc_cnt" +ANNOTATION: "[LOW_RISK] To reduce the simulation time, the max escalation cycle length is set to 1000." +Toggle crashdump_o.class_esc_cnt [1][31:10] "logic [3:0][31:0]crashdump_o.class_esc_cnt" diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core new file mode 100644 index 0000000000000..c29d53c1f648b --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core @@ -0,0 +1,36 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:alert_handler_env:0.1" +description: "ALERT_HANDLER DV UVM environment" +filesets: + files_dv: + depend: + - lowrisc:dv:ralgen + - lowrisc:dv:cip_lib + files: + - alert_handler_env_pkg.sv + - alert_handler_env_cfg.sv: {is_include_file: true} + - alert_handler_env_cov.sv: {is_include_file: true} + - alert_handler_virtual_sequencer.sv: {is_include_file: true} + - alert_handler_scoreboard.sv: {is_include_file: true} + - alert_handler_env.sv: {is_include_file: true} + - seq_lib/alert_handler_vseq_list.sv: {is_include_file: true} + - seq_lib/alert_handler_base_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_common_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_smoke_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_random_alerts_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_random_classes_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_esc_intr_timeout_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_esc_alert_accum_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_sig_int_fail_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_entropy_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_ping_timeout_vseq.sv: {is_include_file: true} + - seq_lib/alert_handler_stress_all_vseq.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.sv new file mode 100644 index 0000000000000..b8e6f625bd83a --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.sv @@ -0,0 +1,73 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class alert_handler_env extends cip_base_env #( + .CFG_T (alert_handler_env_cfg), + .COV_T (alert_handler_env_cov), + .VIRTUAL_SEQUENCER_T(alert_handler_virtual_sequencer), + .SCOREBOARD_T (alert_handler_scoreboard) + ); + `uvm_component_utils(alert_handler_env) + + `uvm_component_new + + alert_esc_agent alert_host_agent[]; + alert_esc_agent esc_device_agent[]; + + function void build_phase(uvm_phase phase); + super.build_phase(phase); + // build alert agents + alert_host_agent = new[NUM_ALERTS]; + virtual_sequencer.alert_host_seqr_h = new[NUM_ALERTS]; + foreach (alert_host_agent[i]) begin + alert_host_agent[i] = alert_esc_agent::type_id::create( + $sformatf("alert_host_agent[%0d]", i), this); + uvm_config_db#(alert_esc_agent_cfg)::set(this, + $sformatf("alert_host_agent[%0d]", i), "cfg", cfg.alert_host_cfg[i]); + cfg.alert_host_cfg[i].en_cov = cfg.en_cov; + cfg.alert_host_cfg[i].clk_freq_mhz = int'(cfg.clk_freq_mhz); + end + // build escalator agents + esc_device_agent = new[NUM_ESCS]; + virtual_sequencer.esc_device_seqr_h = new[NUM_ESCS]; + foreach (esc_device_agent[i]) begin + esc_device_agent[i] = alert_esc_agent::type_id::create( + $sformatf("esc_device_agent[%0d]", i), this); + uvm_config_db#(alert_esc_agent_cfg)::set(this, + $sformatf("esc_device_agent[%0d]", i), "cfg", cfg.esc_device_cfg[i]); + cfg.esc_device_cfg[i].en_cov = cfg.en_cov; + end + // get vifs + if (!uvm_config_db#(crashdump_vif)::get(this, "", "crashdump_vif", cfg.crashdump_vif)) begin + `uvm_fatal(get_full_name(), "failed to get crashdump_vif from uvm_config_db") + end + endfunction + + function void connect_phase(uvm_phase phase); + super.connect_phase(phase); + if (cfg.en_scb) begin + foreach (alert_host_agent[i]) begin + alert_host_agent[i].monitor.alert_esc_port.connect( + scoreboard.alert_fifo[i].analysis_export); + end + foreach (esc_device_agent[i]) begin + esc_device_agent[i].monitor.alert_esc_port.connect( + scoreboard.esc_fifo[i].analysis_export); + end + end + if (cfg.is_active) begin + foreach (alert_host_agent[i]) begin + if (cfg.alert_host_cfg[i].is_active) begin + virtual_sequencer.alert_host_seqr_h[i] = alert_host_agent[i].sequencer; + end + end + end + foreach (esc_device_agent[i]) begin + if (cfg.esc_device_cfg[i].is_active) begin + virtual_sequencer.esc_device_seqr_h[i] = esc_device_agent[i].sequencer; + end + end + endfunction + +endclass diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_cfg.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_cfg.sv new file mode 100644 index 0000000000000..59f8ce3923306 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_cfg.sv @@ -0,0 +1,58 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class alert_handler_env_cfg extends cip_base_env_cfg #(.RAL_T(alert_handler_reg_block)); + + // ext component cfgs + esc_en_vif esc_en_vif; + crashdump_vif crashdump_vif; + rand alert_esc_agent_cfg alert_host_cfg[]; + rand alert_esc_agent_cfg esc_device_cfg[]; + + `uvm_object_utils_begin(alert_handler_env_cfg) + `uvm_field_array_object(alert_host_cfg, UVM_DEFAULT) + `uvm_field_array_object(esc_device_cfg, UVM_DEFAULT) + `uvm_object_utils_end + + `uvm_object_new + + virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1); + has_edn = 1; + super.initialize(csr_base_addr); + shadow_update_err_status_fields[ral.loc_alert_cause[LocalShadowRegUpdateErr].la] = 1; + shadow_storage_err_status_fields[ral.loc_alert_cause[LocalShadowRegStorageErr].la] = 1; + + // set num_interrupts & num_alerts + begin + uvm_reg rg = ral.get_reg_by_name("intr_state"); + if (rg != null) begin + num_interrupts = ral.intr_state.get_n_used_bits(); + end + end + + alert_host_cfg = new[NUM_ALERTS]; + esc_device_cfg = new[NUM_ESCS]; + foreach (alert_host_cfg[i]) begin + alert_host_cfg[i] = + alert_esc_agent_cfg::type_id::create($sformatf("alert_host_cfg[%0d]", i)); + alert_host_cfg[i].if_mode = dv_utils_pkg::Host; + alert_host_cfg[i].is_async = ASYNC_ON[i]; + end + foreach (esc_device_cfg[i]) begin + esc_device_cfg[i] = + alert_esc_agent_cfg::type_id::create($sformatf("esc_device_cfg[%0d]", i)); + esc_device_cfg[i].if_mode = dv_utils_pkg::Device; + esc_device_cfg[i].is_alert = 0; + end + // only support 1 outstanding TL items in tlul_adapter + m_tl_agent_cfg.max_outstanding_req = 1; + endfunction + + // Override shadow register naming checks. The alert handler does not expose any alert signals, + // hence no alerts are defined in Hjson. + virtual function void check_shadow_reg_alerts(); + // Nothing to check. + endfunction + +endclass diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_cov.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_cov.sv new file mode 100644 index 0000000000000..a7eb4dfa7c777 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_cov.sv @@ -0,0 +1,41 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class alert_handler_env_cov extends cip_base_env_cov #(.CFG_T(alert_handler_env_cfg)); + `uvm_component_utils(alert_handler_env_cov) + + // the base class provides the following handles for use: + // alert_handler_env_cfg: cfg + + // covergroups + covergroup accum_cnt_cg with function sample (int class_i, int cnt); + class_index_cp: coverpoint class_i { + bins class_index[NUM_ALERT_CLASSES] = {[0:NUM_ALERT_CLASSES-1]}; + } + accum_cnt_cp: coverpoint cnt { + bins accum_cnt[20] = {[0:'hffff]}; + bins saturate_cnt = {'hffff}; + } + class_cnt_cross: cross class_index_cp, accum_cnt_cp; + endgroup : accum_cnt_cg + + covergroup esc_sig_length_cg with function sample (int sig_index, int sig_len); + esc_sig_index: coverpoint sig_index { + bins index[NUM_ESC_SIGNALS] = {[0:NUM_ESC_SIGNALS-1]}; + } + esc_sig_len: coverpoint sig_len { + bins len_2 = {2}; + bins lens_less_than_1000[20] = {[3:1000]}; + } + len_per_esc_sig: cross esc_sig_index, esc_sig_len; + endgroup : esc_sig_length_cg + + function new(string name, uvm_component parent); + super.new(name, parent); + // instantiate all covergroups here + accum_cnt_cg = new(); + esc_sig_length_cg = new(); + endfunction : new + +endclass diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_pkg.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_pkg.sv new file mode 100644 index 0000000000000..08fec39cdb0d9 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env_pkg.sv @@ -0,0 +1,96 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package alert_handler_env_pkg; + // dep packages + import uvm_pkg::*; + import top_pkg::*; + import dv_utils_pkg::*; + import csr_utils_pkg::*; + import tl_agent_pkg::*; + import alert_esc_agent_pkg::*; + import dv_base_reg_pkg::*; + import cip_base_pkg::*; + import alert_handler_ral_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + // parameters + parameter uint NUM_ALERTS = alert_handler_reg_pkg::NAlerts; + parameter uint NUM_ESCS = 4; + parameter uint NUM_MAX_ESC_SEV = 8; + parameter uint NUM_ESC_SIGNALS = 4; + parameter uint NUM_ALERT_CLASSES = 4; + parameter uint NUM_ESC_PHASES = 4; + parameter uint NUM_ALERT_CLASS_MSB = $clog2(NUM_ALERT_CLASSES) - 1; + parameter uint MIN_CYCLE_PER_PHASE = 2; + parameter uint NUM_LOCAL_ALERTS = 7; + parameter bit [NUM_ALERTS-1:0] ASYNC_ON = alert_handler_reg_pkg::AsyncOn; + // ignore esc signal cycle count after ping occurs - as ping response might ended up adding one + // extra cycle to the calculated cnt, or even combine two signals into one. + parameter uint IGNORE_CNT_CHECK_NS = 100_000_000; + // set the max ping timeout cycle to constrain the simulation run time + parameter uint MAX_PING_TIMEOUT_CYCLE = 300; + + parameter uint NUM_CRASHDUMP = NUM_ALERT_CLASSES * (alert_handler_reg_pkg::AccuCntDw + + alert_handler_reg_pkg::EscCntDw + 3) + + NUM_ALERTS + NUM_LOCAL_ALERTS; + // types + typedef enum { + EscPhase0, + EscPhase1, + EscPhase2, + EscPhase3 + } esc_phase_e; + + typedef enum { + AlertClassCtrlEn, + AlertClassCtrlLock, + AlertClassCtrlEnE0, + AlertClassCtrlEnE1, + AlertClassCtrlEnE2, + AlertClassCtrlEnE3, + AlertClassCtrlMapE0, + AlertClassCtrlMapE1, + AlertClassCtrlMapE2, + AlertClassCtrlMapE3 + } alert_class_ctrl_e; + + typedef enum { + EscStateIdle = 'b000, + EscStateTimeout = 'b001, + EscStateTerminal = 'b011, + EscStatePhase0 = 'b100, + EscStatePhase1 = 'b101, + EscStatePhase2 = 'b110, + EscStatePhase3 = 'b111 + } esc_state_e; + + typedef enum { + LocalAlertPingFail, + LocalEscPingFail, + LocalAlertIntFail, + LocalEscIntFail, + LocalBusIntgFail, + LocalShadowRegUpdateErr, + LocalShadowRegStorageErr + } local_alert_type_e; + + // forward declare classes to allow typedefs below + typedef virtual pins_if #(NUM_MAX_ESC_SEV) esc_en_vif; + typedef virtual pins_if #(NUM_CRASHDUMP) crashdump_vif; + + // functions + + // package sources + `include "alert_handler_env_cfg.sv" + `include "alert_handler_env_cov.sv" + `include "alert_handler_virtual_sequencer.sv" + `include "alert_handler_scoreboard.sv" + `include "alert_handler_env.sv" + `include "alert_handler_vseq_list.sv" + +endpackage diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_scoreboard.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_scoreboard.sv new file mode 100644 index 0000000000000..f2e51bc869ff4 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_scoreboard.sv @@ -0,0 +1,562 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`define ASSIGN_CLASS_PHASE_REGS(index, i) \ + reg_esc_phase_cycs_per_class_q[``index``] = \ + {ral.class``i``_phase0_cyc_shadowed, ral.class``i``_phase1_cyc_shadowed, \ + ral.class``i``_phase2_cyc_shadowed, ral.class``i``_phase3_cyc_shadowed}; + +class alert_handler_scoreboard extends cip_base_scoreboard #( + .CFG_T(alert_handler_env_cfg), + .RAL_T(alert_handler_reg_block), + .COV_T(alert_handler_env_cov) + ); + `uvm_component_utils(alert_handler_scoreboard) + + // esc_phase_cyc_per_class_q: each class has four phase cycles, stores each cycle length + // --- class --- phase0_cyc --- phase1_cyc --- phase2_cyc --- phase3_cyc --- + // --- A -classa_phase0_cyc - classa_phase1_cyc - classa_phase2_cyc - classa_phase3_cyc -- + // --- B -classb_phase0_cyc - classb_phase1_cyc - classb_phase2_cyc - classb_phase3_cyc -- + // --- C -classc_phase0_cyc - classc_phase1_cyc - classc_phase2_cyc - classc_phase3_cyc -- + // --- D -classd_phase0_cyc - classd_phase1_cyc - classd_phase2_cyc - classd_phase3_cyc -- + dv_base_reg reg_esc_phase_cycs_per_class_q[NUM_ALERT_CLASSES][$]; + + uvm_reg_field intr_state_fields[$]; + uvm_reg_field intr_state_field; + // once escalation triggers, no alerts can trigger another escalation in the same class + // until the class esc is cleared + bit [NUM_ALERT_CLASSES-1:0] under_esc_classes; + bit [NUM_ALERT_CLASSES-1:0] under_intr_classes; + bit [NUM_ALERT_CLASSES-1:0] clr_esc_under_intr; + int intr_cnter_per_class [NUM_ALERT_CLASSES]; + int accum_cnter_per_class [NUM_ALERT_CLASSES]; + esc_state_e state_per_class [NUM_ALERT_CLASSES]; + int esc_signal_release [NUM_ESC_SIGNALS]; + int esc_sig_class [NUM_ESC_SIGNALS]; // one class can increment one esc signal at a time + // For different alert classify in the same class and trigger at the same cycle, design only + // count once. So record the alert triggered timing here + realtime last_triggered_alert_per_class[NUM_ALERT_CLASSES]; + + string class_name[] = {"a", "b", "c", "d"}; + bit [TL_DW-1:0] intr_state_val; + // TLM agent fifos + uvm_tlm_analysis_fifo #(alert_esc_seq_item) alert_fifo[NUM_ALERTS]; + uvm_tlm_analysis_fifo #(alert_esc_seq_item) esc_fifo[NUM_ESCS]; + + `uvm_component_new + + function void build_phase(uvm_phase phase); + super.build_phase(phase); + ral.intr_state.get_fields(intr_state_fields); + `ASSIGN_CLASS_PHASE_REGS(0, a) + `ASSIGN_CLASS_PHASE_REGS(1, b) + `ASSIGN_CLASS_PHASE_REGS(2, c) + `ASSIGN_CLASS_PHASE_REGS(3, d) + + foreach (alert_fifo[i]) alert_fifo[i] = new($sformatf("alert_fifo[%0d]", i), this); + foreach (esc_fifo[i]) esc_fifo[i] = new($sformatf("esc_fifo[%0d]" , i), this); + endfunction + + function void connect_phase(uvm_phase phase); + super.connect_phase(phase); + endfunction + + task run_phase(uvm_phase phase); + super.run_phase(phase); + fork + process_alert_fifo(); + process_esc_fifo(); + check_intr_timeout_trigger_esc(); + esc_phase_signal_cnter(); + release_esc_signal(); + join_none + endtask + + virtual task process_alert_fifo(); + foreach (alert_fifo[i]) begin + automatic int index = i; + fork + forever begin + bit alert_en, loc_alert_en; + alert_esc_seq_item act_item; + alert_fifo[index].get(act_item); + alert_en = ral.alert_en_shadowed[index].get_mirrored_value(); + if (alert_en) begin + // alert detected + if (act_item.alert_esc_type == AlertEscSigTrans && !act_item.ping_timeout && + act_item.alert_handshake_sta == AlertReceived) begin + process_alert_sig(index, 0); + // alert integrity fail + end else if (act_item.alert_esc_type == AlertEscIntFail) begin + loc_alert_en = ral.loc_alert_en_shadowed[LocalAlertIntFail].get_mirrored_value(); + if (loc_alert_en) process_alert_sig(index, 1, LocalAlertIntFail); + end else if (act_item.alert_esc_type == AlertEscPingTrans && + act_item.ping_timeout) begin + loc_alert_en = ral.loc_alert_en_shadowed[LocalAlertPingFail].get_mirrored_value(); + if (loc_alert_en) begin + process_alert_sig(index, 1, LocalAlertPingFail); + `uvm_info(`gfn, $sformatf("alert %0d ping timeout, timeout_cyc reg is %0d", + index, ral.ping_timeout_cyc_shadowed.get_mirrored_value()), UVM_LOW); + end + end + end + end + join_none + end + endtask : process_alert_fifo + + virtual task process_esc_fifo(); + foreach (esc_fifo[i]) begin + automatic int index = i; + fork + forever begin + alert_esc_seq_item act_item; + esc_fifo[index].get(act_item); + // escalation triggered, check signal length + if (act_item.alert_esc_type == AlertEscSigTrans && + act_item.esc_handshake_sta == EscRespComplete) begin + check_esc_signal(act_item.sig_cycle_cnt, index); + // escalation integrity fail + end else if (act_item.alert_esc_type == AlertEscIntFail || + (act_item.esc_handshake_sta == EscIntFail && !act_item.ping_timeout)) begin + bit loc_alert_en = ral.loc_alert_en_shadowed[LocalEscIntFail].get_mirrored_value(); + if (loc_alert_en) process_alert_sig(index, 1, LocalEscIntFail); + // escalation ping timeout + end else if (act_item.alert_esc_type == AlertEscPingTrans && act_item.ping_timeout) begin + bit loc_alert_en = ral.loc_alert_en_shadowed[LocalEscPingFail].get_mirrored_value(); + if (loc_alert_en) begin + process_alert_sig(index, 1, LocalEscPingFail); + `uvm_info(`gfn, $sformatf("esc %0d ping timeout, timeout_cyc reg is %0d", + index, ral.ping_timeout_cyc_shadowed.get_mirrored_value()), UVM_LOW); + end + end + end + join_none + end + endtask : process_esc_fifo + + // this task process alert signal by checking if intergrity fail, then classify it to the + // mapping classes, then check if escalation is triggered by accumulation + // this task delayed to a negedge clk to avoid updating and checking regs at the same time + virtual task process_alert_sig(int alert_i, bit is_int_err, + local_alert_type_e local_alert_type = LocalAlertIntFail); + fork + begin + cfg.clk_rst_vif.wait_n_clks(1); + if (!under_reset) begin + bit [TL_DW-1:0] intr_en, class_ctrl; + bit [NUM_ALERT_CLASS_MSB:0] class_i; + if (!is_int_err) begin + class_i = `gmv(ral.alert_class_shadowed[alert_i]); + void'(ral.alert_cause[alert_i].predict(1)); + end else begin + class_i = `gmv(ral.loc_alert_class_shadowed[int'(local_alert_type)]); + void'(ral.loc_alert_cause[int'(local_alert_type)].predict(1)); + end + + intr_state_field = intr_state_fields[class_i]; + void'(intr_state_field.predict(.value(1), .kind(UVM_PREDICT_READ))); + intr_en = ral.intr_enable.get_mirrored_value(); + + // calculate escalation + class_ctrl = get_class_ctrl(class_i); + `uvm_info(`gfn, $sformatf("class %0d is triggered, class ctrl=%0h, under_esc=%0b", + class_i, class_ctrl, under_esc_classes[class_i]), UVM_DEBUG) + // if class escalation is enabled, add alert to accumulation count + if (class_ctrl[AlertClassCtrlEn] && + (class_ctrl[AlertClassCtrlEnE3:AlertClassCtrlEnE0] > 0)) begin + alert_accum_cal(class_i); + end + + // according to issue #841, interrupt will have one clock cycle delay + cfg.clk_rst_vif.wait_n_clks(1); + if (!under_reset) begin + `DV_CHECK_CASE_EQ(cfg.intr_vif.pins[class_i], intr_en[class_i], + $sformatf("Interrupt class_%s, is_local_err %0b, local_alert_type %s", + class_name[class_i],is_int_err, local_alert_type)); + if (!under_intr_classes[class_i] && intr_en[class_i]) under_intr_classes[class_i] = 1; + end + end + end + join_none + endtask + + // calculate alert accumulation count per class, if accumulation exceeds the threshold, + // and if current class is not under escalation, then predict escalation + // note: if more than one alerts triggered on the same clk cycle, only accumulates one + virtual function void alert_accum_cal(int class_i); + bit [TL_DW-1:0] accum_thresh = get_class_accum_thresh(class_i); + realtime curr_time = $realtime(); + if (curr_time != last_triggered_alert_per_class[class_i] && !cfg.under_reset) begin + last_triggered_alert_per_class[class_i] = curr_time; + // avoid accum_cnt saturate + if (accum_cnter_per_class[class_i] < 'hffff) begin + accum_cnter_per_class[class_i] += 1; + if (accum_cnter_per_class[class_i] > accum_thresh && !under_esc_classes[class_i]) begin + predict_esc(class_i); + end + end + end + `uvm_info(`gfn, + $sformatf("alert_accum: class=%0d, alert_cnt=%0d, thresh=%0d, under_esc=%0b", + class_i, accum_cnter_per_class[class_i], accum_thresh, + under_esc_classes[class_i]), UVM_DEBUG) + endfunction + + // if clren register is disabled, predict escalation signals by setting the corresponding + // under_esc_classes bit based on class_ctrl's lock bit + virtual function void predict_esc(int class_i); + bit [TL_DW-1:0] class_ctrl = get_class_ctrl(class_i); + if (class_ctrl[AlertClassCtrlLock]) begin + uvm_reg clren_rg; + clren_rg = ral.get_reg_by_name($sformatf("class%s_clr_regwen", class_name[class_i])); + `DV_CHECK_NE_FATAL(clren_rg, null) + void'(clren_rg.predict(0)); + end + under_esc_classes[class_i] = 1; + endfunction + + // check if escalation signal's duration length is correct + virtual function void check_esc_signal(int cycle_cnt, int esc_sig_i); + int class_a = `gmv(ral.classa_ctrl_shadowed); + int class_b = `gmv(ral.classb_ctrl_shadowed); + int class_c = `gmv(ral.classc_ctrl_shadowed); + int class_d = `gmv(ral.classd_ctrl_shadowed); + int sig_index = AlertClassCtrlEnE0+esc_sig_i; + bit [NUM_ALERT_CLASSES-1:0] select_class = {class_d[sig_index], class_c[sig_index], + class_b[sig_index], class_a[sig_index]}; + + + // Only compare the escalation signal length if exactly one class is assigned to this signal. + // Otherwise scb cannot predict the accurate cycle length if multiple classes are merged. + if ($countones(select_class) == 1) begin + int exp_cycle, phase, class_i; + // Find the class that triggers the escalation, and find which phase the escalation signal is + // reflecting. + for (class_i = 0; class_i < NUM_ALERT_CLASSES; class_i++) begin + if (select_class[class_i] == 1) begin + phase = `gmv(ral.get_reg_by_name($sformatf("class%0s_ctrl_shadowed", + class_name[class_i]))); + break; + end + end + phase = phase[(AlertClassCtrlMapE0 + esc_sig_i * 2) +: 2]; + exp_cycle = `gmv(ral.get_reg_by_name($sformatf("class%0s_phase%0d_cyc_shadowed", + class_name[class_i], phase))) + 1; + // Minimal phase length is 2 cycles. + exp_cycle = exp_cycle < 2 ? 2 : exp_cycle; + `uvm_info(`gfn, $sformatf("esc_signal_%0d, esc phase %0d, esc class %0d", + esc_sig_i, phase, class_i), UVM_HIGH); + + // If the escalation signal is interrupted by reset or esc_clear, we expect the signal length + // to be shorter than the phase_cycle_length. + if (cfg.under_reset || under_esc_classes[class_i] == 0) begin + `DV_CHECK_LE(cycle_cnt, exp_cycle) + end else begin + `DV_CHECK_EQ(cycle_cnt, exp_cycle) + end + if (cfg.en_cov) cov.esc_sig_length_cg.sample(esc_sig_i, cycle_cnt); + end + esc_sig_class[esc_sig_i] = 0; + endfunction + + virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name); + uvm_reg csr; + bit do_read_check = 1'b1; + bit write = item.is_write(); + uvm_reg_addr_t csr_addr = {item.a_addr[TL_AW-1:2], 2'b00}; + + // if access was to a valid csr, get the csr handle + if (csr_addr inside {cfg.ral_models[ral_name].csr_addrs}) begin + csr = ral.default_map.get_reg_by_offset(csr_addr); + `DV_CHECK_NE_FATAL(csr, null) + end + if (csr == null) begin + // we hit an oob addr - expect error response and return + `DV_CHECK_EQ(item.d_error, 1'b1) + return; + end + + if (channel == AddrChannel) begin + // if incoming access is a write to a valid csr, then make updates right away + if (write) begin + void'(csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask))); + // process the csr req + // for write, update local variable and fifo at address phase + case (csr.get_name()) + // add individual case item for each csr + "intr_test": begin + bit [TL_DW-1:0] intr_state_exp = item.a_data | ral.intr_state.get_mirrored_value(); + if (cfg.en_cov) begin + bit [TL_DW-1:0] intr_en = ral.intr_enable.get_mirrored_value(); + for (int i = 0; i < NUM_ALERT_CLASSES; i++) begin + cov.intr_test_cg.sample(i, item.a_data[i], intr_en[i], intr_state_exp[i]); + end + end + void'(ral.intr_state.predict(.value(intr_state_exp), .kind(UVM_PREDICT_DIRECT))); + end + // disable intr_enable or clear intr_state will clear the interrupt timeout cnter + "intr_state": begin + fork + begin + // after interrupt is set, it needs one clock cycle to update the value and stop + // the intr_timeout counter + cfg.clk_rst_vif.wait_clks(1); + if (!cfg.under_reset) begin + foreach (under_intr_classes[i]) begin + if (item.a_data[i]) begin + under_intr_classes[i] = 0; + clr_esc_under_intr[i] = 0; + if (!under_esc_classes[i]) state_per_class[i] = EscStateIdle; + end + end + void'(csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), + .be(item.a_mask))); + end + end + join_none + end + "intr_enable": begin + foreach (under_intr_classes[i]) begin + if (item.a_data[i] == 0) under_intr_classes[i] = 0; + end + end + "classa_clr_shadowed": begin + if (ral.classa_clr_regwen.get_mirrored_value()) clr_reset_esc_class(0); + end + "classb_clr_shadowed": begin + if (ral.classb_clr_regwen.get_mirrored_value()) clr_reset_esc_class(1); + end + "classc_clr_shadowed": begin + if (ral.classc_clr_regwen.get_mirrored_value()) clr_reset_esc_class(2); + end + "classd_clr_shadowed": begin + if (ral.classd_clr_regwen.get_mirrored_value()) clr_reset_esc_class(3); + end + default: begin + // TODO: align all names with shadow post_fix and re-enable this check. + //`uvm_fatal(`gfn, $sformatf("invalid csr: %0s", csr.get_full_name())) + end + endcase + end + end + + // process the csr req + // for read, update predication at address phase and compare at data phase + + if (!write) begin + // On reads, if do_read_check, is set, then check mirrored_value against item.d_data + if (channel == DataChannel) begin + if (cfg.en_cov) begin + if (csr.get_name() == "intr_state") begin + bit [TL_DW-1:0] intr_en = ral.intr_enable.get_mirrored_value(); + for (int i = 0; i < NUM_ALERT_CLASSES; i++) begin + cov.intr_cg.sample(i, intr_en[i], item.d_data[i]); + cov.intr_pins_cg.sample(i, cfg.intr_vif.pins[i]); + end + end else begin + for (int i = 0; i < NUM_ALERT_CLASSES; i++) begin + if (csr.get_name() == $sformatf("class%s_accum_cnt", class_name[i])) begin + cov.accum_cnt_cg.sample(i, item.d_data); + end + end + end + end + if (csr.get_name == "intr_state") begin + `DV_CHECK_EQ(intr_state_val, item.d_data, $sformatf("reg name: %0s", "intr_state")) + do_read_check = 0; + end + if (do_read_check) begin + `DV_CHECK_EQ(csr.get_mirrored_value(), item.d_data, + $sformatf("reg name: %0s", csr.get_full_name())) + end + void'(csr.predict(.value(item.d_data), .kind(UVM_PREDICT_READ))); + end else begin + // predict in address phase to avoid the register's value changed during the read + for (int i = 0; i < NUM_ALERT_CLASSES; i++) begin + if (csr.get_name() == $sformatf("class%s_esc_cnt", class_name[i])) begin + void'(csr.predict(.value(intr_cnter_per_class[i]), .kind(UVM_PREDICT_READ))); + end else if (csr.get_name() == $sformatf("class%s_accum_cnt", class_name[i])) begin + void'(csr.predict(.value(accum_cnter_per_class[i]), .kind(UVM_PREDICT_READ))); + end else if (csr.get_name() == $sformatf("class%s_state", class_name[i])) begin + void'(csr.predict(.value(state_per_class[i]), .kind(UVM_PREDICT_READ))); + end + end + if (csr.get_name() == "intr_state") intr_state_val = csr.get_mirrored_value(); + end + end + endtask + + // a counter to count how long each interrupt pins stay high until it is being reset + // if counter exceeds threshold, call predict_esc() function to calculate related esc + virtual task check_intr_timeout_trigger_esc(); + for (int i = 0; i < NUM_ALERT_CLASSES; i++) begin + fork + automatic int class_i = i; + begin : intr_sig_counter + forever @(under_intr_classes[class_i] && !under_esc_classes[class_i]) begin + fork + begin + bit [TL_DW-1:0] timeout_cyc, class_ctrl; + // if escalation cleared but interrupt not cleared, wait one more clk cycle for the + // FSM to reset to Idle, then start to count + if (clr_esc_under_intr[class_i]) cfg.clk_rst_vif.wait_n_clks(1); + clr_esc_under_intr[class_i] = 0; + // wait a clk for esc signal to go high + cfg.clk_rst_vif.wait_n_clks(1); + class_ctrl = get_class_ctrl(class_i); + if (class_ctrl[AlertClassCtrlEn] && + class_ctrl[AlertClassCtrlEnE3:AlertClassCtrlEnE0] > 0) begin + intr_cnter_per_class[class_i] = 1; + timeout_cyc = get_class_timeout_cyc(class_i); + if (timeout_cyc > 0) begin + state_per_class[class_i] = EscStateTimeout; + while (under_intr_classes[class_i]) begin + @(cfg.clk_rst_vif.cbn); + if (intr_cnter_per_class[class_i] >= timeout_cyc) predict_esc(class_i); + intr_cnter_per_class[class_i] += 1; + end + end + intr_cnter_per_class[class_i] = 0; + end + end + begin + wait(under_esc_classes[class_i]); + end + join_any + disable fork; + end // end forever + end + join_none + end + endtask + + // two counters for phases cycle length and esc signals cycle length + // phase cycle cnter: "intr_cnter_per_class" is used to check "esc_cnt" registers + virtual task esc_phase_signal_cnter(); + for (int i = 0; i < NUM_ALERT_CLASSES; i++) begin + fork + automatic int class_i = i; + begin : esc_phases_counter + forever @(!cfg.under_reset && under_esc_classes[class_i]) begin + fork + begin : inc_esc_cnt + for (int phase_i = 0; phase_i < NUM_ESC_PHASES; phase_i++) begin + int phase_thresh = `gmv(reg_esc_phase_cycs_per_class_q[class_i][phase_i]); + bit[TL_DW-1:0] class_ctrl = get_class_ctrl(class_i); + int enabled_sig_q[$]; + for (int sig_i = 0; sig_i < NUM_ESC_SIGNALS; sig_i++) begin + if (class_ctrl[sig_i*2+7 -: 2] == phase_i && class_ctrl[sig_i+2]) begin + enabled_sig_q.push_back(sig_i); + end + end + if (under_esc_classes[class_i]) begin + intr_cnter_per_class[class_i] = 1; + state_per_class[class_i] = esc_state_e'(phase_i + int'(EscStatePhase0)); + cfg.clk_rst_vif.wait_n_clks(1); + while (under_esc_classes[class_i] && + intr_cnter_per_class[class_i] < phase_thresh) begin + intr_cnter_per_class[class_i]++; + cfg.clk_rst_vif.wait_n_clks(1); + end + foreach (enabled_sig_q[i]) begin + int index = enabled_sig_q[i]; + if (esc_sig_class[index] == (class_i + 1)) esc_signal_release[index] = 1; + end + end + end // end four phases + intr_cnter_per_class[class_i] = 0; + if (under_esc_classes[class_i]) state_per_class[class_i] = EscStateTerminal; + end + begin + wait(cfg.under_reset || !under_esc_classes[class_i]); + if (!under_esc_classes[class_i]) begin + // wait 1 clk cycles until esc_signal_release is set + cfg.clk_rst_vif.wait_clks(1); + end + end + join_any + disable fork; + intr_cnter_per_class[class_i] = 0; + end // end forever + end + join_none + end + endtask + + // release escalation signal after one clock cycle, to ensure happens at the end of the clock + // cycle, waited 1 clks here + virtual task release_esc_signal(); + for (int i = 0; i < NUM_ESC_SIGNALS; i++) begin + fork + automatic int sig_i = i; + forever @ (esc_signal_release[sig_i]) begin + cfg.clk_rst_vif.wait_clks(1); + esc_sig_class[sig_i] = 0; + esc_signal_release[sig_i] = 0; + end + join_none + end + endtask + + virtual function void reset(string kind = "HARD"); + super.reset(kind); + under_intr_classes = '{default:0}; + intr_cnter_per_class = '{default:0}; + under_esc_classes = '{default:0}; + esc_sig_class = '{default:0}; + accum_cnter_per_class = '{default:0}; + state_per_class = '{default:EscStateIdle}; + clr_esc_under_intr = 0; + last_triggered_alert_per_class = '{default:$realtime}; + endfunction + + // clear accumulative counters, and escalation counters if they are under escalation + // interrupt timeout counters cannot be cleared by this + task clr_reset_esc_class(int class_i); + fork + begin + cfg.clk_rst_vif.wait_clks(1); + if (under_intr_classes[class_i]) clr_esc_under_intr[class_i] = 1; + if (under_esc_classes [class_i]) intr_cnter_per_class[class_i] = 0; + under_esc_classes[class_i] = 0; + cfg.clk_rst_vif.wait_n_clks(1); + last_triggered_alert_per_class[class_i] = $realtime; + accum_cnter_per_class[class_i] = 0; + if (state_per_class[class_i] != EscStateTimeout) state_per_class[class_i] = EscStateIdle; + end + join_none + endtask + + function void check_phase(uvm_phase phase); + super.check_phase(phase); + endfunction + + // get class_ctrl register mirrored value by class + function bit [TL_DW-1:0] get_class_ctrl(int class_i); + uvm_reg class_ctrl_rg; + class_ctrl_rg = ral.get_reg_by_name($sformatf("class%s_ctrl_shadowed", class_name[class_i])); + `DV_CHECK_NE_FATAL(class_ctrl_rg, null) + return class_ctrl_rg.get_mirrored_value(); + endfunction + + // get class_accum_thresh register mirrored value by class + function bit [TL_DW-1:0] get_class_accum_thresh(int class_i); + uvm_reg class_thresh_rg; + class_thresh_rg = ral.get_reg_by_name($sformatf("class%s_accum_thresh_shadowed", + class_name[class_i])); + `DV_CHECK_NE_FATAL(class_thresh_rg, null) + return class_thresh_rg.get_mirrored_value(); + endfunction + + // get class_timeout_cyc register mirrored value by class + function bit [TL_DW-1:0] get_class_timeout_cyc(int class_i); + dv_base_reg class_timeout_rg = + ral.get_dv_base_reg_by_name($sformatf("class%s_timeout_cyc_shadowed", + class_name[class_i])); + return class_timeout_rg.get_mirrored_value(); + endfunction +endclass + +`undef ASSIGN_CLASS_PHASE_REGS diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_virtual_sequencer.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_virtual_sequencer.sv new file mode 100644 index 0000000000000..af0fa9f5425f0 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_virtual_sequencer.sv @@ -0,0 +1,16 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class alert_handler_virtual_sequencer extends cip_base_virtual_sequencer #( + .CFG_T(alert_handler_env_cfg), + .COV_T(alert_handler_env_cov) + ); + alert_esc_sequencer alert_host_seqr_h[]; + alert_esc_sequencer esc_device_seqr_h[]; + + `uvm_component_utils(alert_handler_virtual_sequencer) + + `uvm_component_new + +endclass diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv new file mode 100644 index 0000000000000..5d86ed9d7d7b6 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv @@ -0,0 +1,316 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`define RAND_AND_WR_CLASS_PHASES_CYCLE(i) \ + `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.class``i``_phase0_cyc_shadowed, \ + class``i``_phase0_cyc_shadowed.value inside {[0: max_phase_cyc]};); \ + `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.class``i``_phase1_cyc_shadowed, \ + class``i``_phase1_cyc_shadowed.value inside {[0: max_phase_cyc]};); \ + `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.class``i``_phase2_cyc_shadowed, \ + class``i``_phase2_cyc_shadowed.value inside {[0: max_phase_cyc]};); \ + `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.class``i``_phase3_cyc_shadowed, \ + class``i``_phase3_cyc_shadowed.value inside {[0: max_phase_cyc]};); \ + csr_update(ral.class``i``_phase0_cyc_shadowed); \ + csr_update(ral.class``i``_phase1_cyc_shadowed); \ + csr_update(ral.class``i``_phase2_cyc_shadowed); \ + csr_update(ral.class``i``_phase3_cyc_shadowed); + +`define RAND_WRITE_CLASS_CTRL(i, lock_bit) \ + `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.class``i``_ctrl_shadowed, lock.value == lock_bit;) \ + csr_wr(.ptr(ral.class``i``_ctrl_shadowed), .value(ral.class``i``_ctrl_shadowed.get())); + +class alert_handler_base_vseq extends cip_base_vseq #( + .CFG_T (alert_handler_env_cfg), + .RAL_T (alert_handler_reg_block), + .COV_T (alert_handler_env_cov), + .VIRTUAL_SEQUENCER_T (alert_handler_virtual_sequencer) + ); + `uvm_object_utils(alert_handler_base_vseq) + + // various knobs to enable certain routines + bit do_alert_handler_init = 1'b0; + bit config_locked = 1'b0; + + `uvm_object_new + + virtual task dut_init(string reset_kind = "HARD"); + super.dut_init(); + if (do_alert_handler_init) alert_handler_init(); + config_locked = 0; + endtask + + virtual task dut_shutdown(); + // nothing special yet + endtask + + // setup basic alert_handler features + // alert_class default 0 -> all alert will trigger interrupt classA + virtual task alert_handler_init(bit [NUM_ALERT_CLASSES-1:0] intr_en = '1, + bit [NUM_ALERTS-1:0] alert_en = '1, + bit [NUM_ALERT_CLASSES-1:0][TL_DW-1:0] alert_class = 'h0, + bit [NUM_LOCAL_ALERTS-1:0] loc_alert_en = '1, + bit [NUM_ALERT_CLASSES-1:0][TL_DW-1:0] loc_alert_class = 'h0); + csr_wr(.ptr(ral.intr_enable), .value(intr_en)); + foreach (alert_en[i]) csr_wr(.ptr(ral.alert_en_shadowed[i]), + .value(alert_en[i])); + foreach (alert_class[i]) csr_wr(.ptr(ral.alert_class_shadowed[i]), + .value(alert_class[i])); + foreach (loc_alert_en[i]) csr_wr(.ptr(ral.loc_alert_en_shadowed[i]), + .value(loc_alert_en[i])); + foreach (loc_alert_class[i]) csr_wr(.ptr(ral.loc_alert_class_shadowed[i]), + .value(loc_alert_class[i])); + endtask + + virtual task alert_handler_rand_wr_class_ctrl(bit [NUM_ALERT_CLASSES-1:0] lock_bit); + bit [NUM_ALERT_CLASSES-1:0] class_en = $urandom(); + if (class_en[0]) `RAND_WRITE_CLASS_CTRL(a, lock_bit[0]) + if (class_en[1]) `RAND_WRITE_CLASS_CTRL(b, lock_bit[1]) + if (class_en[2]) `RAND_WRITE_CLASS_CTRL(c, lock_bit[2]) + if (class_en[3]) `RAND_WRITE_CLASS_CTRL(d, lock_bit[3]) + endtask + + virtual task alert_handler_wr_regwen_regs(bit [NUM_ALERT_CLASSES-1:0] regwen); + if (!regwen[0]) csr_wr(.ptr(ral.classa_clr_regwen), .value($urandom_range(0, 1))); + if (!regwen[1]) csr_wr(.ptr(ral.classb_clr_regwen), .value($urandom_range(0, 1))); + if (!regwen[2]) csr_wr(.ptr(ral.classc_clr_regwen), .value($urandom_range(0, 1))); + if (!regwen[3]) csr_wr(.ptr(ral.classd_clr_regwen), .value($urandom_range(0, 1))); + endtask + + // If do_lock_config is set, write value 1 to ping_timer_en register. + // If not set, this task has 50% of chance to write value 1 to ping_timer_en register. + virtual task lock_config(bit do_lock_config); + if (do_lock_config || $urandom_range(0, 1)) begin + csr_wr(.ptr(ral.ping_timer_en_shadowed), .value(do_lock_config)); + end + endtask + + virtual task drive_alert(bit[NUM_ALERTS-1:0] alert_trigger, bit[NUM_ALERTS-1:0] alert_int_err); + fork + begin : isolation_fork + foreach (alert_trigger[i]) begin + if (alert_trigger[i]) begin + automatic int index = i; + fork + begin + alert_sender_seq alert_seq; + `uvm_create_on(alert_seq, p_sequencer.alert_host_seqr_h[index]); + `DV_CHECK_RANDOMIZE_WITH_FATAL(alert_seq, int_err == alert_int_err[index];) + `uvm_send(alert_seq) + end + join_none + end + end + wait fork; + end + join + endtask + + // This sequence will drive standalone esc_resp_p/n without esc_p/n + virtual task drive_esc_rsp(bit [NUM_ESCS-1:0] esc_int_errs); + fork + begin : isolation_fork + foreach (cfg.esc_device_cfg[i]) begin + automatic int index = i; + if (esc_int_errs[index]) begin + fork + begin + esc_receiver_esc_rsp_seq esc_seq = + esc_receiver_esc_rsp_seq::type_id::create("esc_seq"); + `DV_CHECK_RANDOMIZE_WITH_FATAL(esc_seq, int_err == 1; standalone_int_err == 1; + ping_timeout == 0;) + esc_seq.start(p_sequencer.esc_device_seqr_h[index]); + end + join_none + end + end + wait fork; + end + join + endtask + + // alert_handler scb will compare the read value with expected value + // Not using "clear_all_interrupts" function in cip_base_vseq because of the signal interity + // error: after clearing intr_state, intr_state might come back to 1 in the next cycle. + virtual task check_alert_interrupts(); + bit [TL_DW-1:0] intr; + csr_rd(.ptr(ral.intr_state), .value(intr)); + csr_wr(.ptr(ral.intr_state), .value('1)); + endtask + + virtual task clear_esc(); + csr_wr(.ptr(ral.classa_clr_shadowed), .value(1)); + csr_wr(.ptr(ral.classb_clr_shadowed), .value(1)); + csr_wr(.ptr(ral.classc_clr_shadowed), .value(1)); + csr_wr(.ptr(ral.classd_clr_shadowed), .value(1)); + endtask + + // checking for csr_rd is done in scb + virtual task read_alert_cause(); + bit [TL_DW-1:0] alert_cause; + foreach (ral.alert_cause[i]) begin + if ($urandom_range(0, 1)) begin + csr_rd(.ptr(ral.alert_cause[i]), .value(alert_cause)); + end + end + foreach (ral.loc_alert_cause[i]) begin + if ($urandom_range(0, 1)) begin + csr_rd(.ptr(ral.loc_alert_cause[i]), .value(alert_cause)); + end + end + endtask + + virtual task read_esc_status(); + bit [TL_DW-1:0] csr_val; + csr_rd(.ptr(ral.classa_accum_cnt), .value(csr_val)); + csr_rd(.ptr(ral.classb_accum_cnt), .value(csr_val)); + csr_rd(.ptr(ral.classc_accum_cnt), .value(csr_val)); + csr_rd(.ptr(ral.classd_accum_cnt), .value(csr_val)); + + csr_rd(.ptr(ral.classa_state), .value(csr_val)); + csr_rd(.ptr(ral.classb_state), .value(csr_val)); + csr_rd(.ptr(ral.classc_state), .value(csr_val)); + csr_rd(.ptr(ral.classd_state), .value(csr_val)); + + csr_rd(.ptr(ral.classa_esc_cnt), .value(csr_val)); + csr_rd(.ptr(ral.classb_esc_cnt), .value(csr_val)); + csr_rd(.ptr(ral.classc_esc_cnt), .value(csr_val)); + csr_rd(.ptr(ral.classd_esc_cnt), .value(csr_val)); + endtask + + virtual task wait_alert_handshake_done(); + cfg.clk_rst_vif.wait_clks(2); + foreach (cfg.alert_host_cfg[i]) cfg.alert_host_cfg[i].vif.wait_ack_complete(); + endtask + + virtual function bit check_esc_done(bit[TL_DW-1:0] vals[$]); + foreach (vals[i]) begin + esc_state_e val = esc_state_e'(vals[i]); + if (val inside {EscStatePhase0, EscStatePhase1, EscStatePhase2, EscStatePhase3}) return 0; + end + return 1; + endfunction + + virtual task wait_esc_handshake_done(); + bit [TL_DW-1:0] csr_vals[4]; + do begin + csr_rd(.ptr(ral.classa_state), .value(csr_vals[0])); + csr_rd(.ptr(ral.classb_state), .value(csr_vals[1])); + csr_rd(.ptr(ral.classc_state), .value(csr_vals[2])); + csr_rd(.ptr(ral.classd_state), .value(csr_vals[3])); + end while (!check_esc_done(csr_vals)); + // check if there is any esc ping + foreach (cfg.esc_device_cfg[i]) cfg.esc_device_cfg[i].vif.wait_esc_complete(); + endtask + + // This task wait until any alert or esc protocol received a ping from LFSR. + // This task will also return the protocol index: + // alert index starts from 1; esc index stats from NUM_ALERTS + virtual task wait_alert_esc_ping(ref int ping_index); + int ping_i; + fork + begin : isolation_fork + foreach (cfg.alert_host_cfg[i]) begin + automatic int index = i; + fork + begin + cfg.alert_host_cfg[index].vif.wait_alert_ping(); + ping_i = index + 1; + end + join_none + end + foreach (cfg.esc_device_cfg[i]) begin + automatic int index = i; + fork + begin + cfg.esc_device_cfg[index].vif.wait_esc_ping(); + ping_i = index + NUM_ALERTS + 1; + end + join_none + end + wait (ping_i > 0); + disable fork; + ping_index = ping_i; + end + join + endtask + + virtual task alert_handler_crashdump_phases(bit [1:0] classa_phase = $urandom(), + bit [1:0] classb_phase = $urandom(), + bit [1:0] classc_phase = $urandom(), + bit [1:0] classd_phase = $urandom()); + csr_wr(.ptr(ral.classa_crashdump_trigger_shadowed), .value(classa_phase)); + csr_wr(.ptr(ral.classb_crashdump_trigger_shadowed), .value(classb_phase)); + csr_wr(.ptr(ral.classc_crashdump_trigger_shadowed), .value(classc_phase)); + csr_wr(.ptr(ral.classd_crashdump_trigger_shadowed), .value(classd_phase)); + endtask + + virtual task wr_phases_cycle(int max_phase_cyc); + `RAND_AND_WR_CLASS_PHASES_CYCLE(a); + `RAND_AND_WR_CLASS_PHASES_CYCLE(b); + `RAND_AND_WR_CLASS_PHASES_CYCLE(c); + `RAND_AND_WR_CLASS_PHASES_CYCLE(d); + endtask + + virtual task wr_intr_timeout_cycle(bit[TL_DW-1:0] intr_timeout_cyc[NUM_ALERT_CLASSES]); + csr_wr(.ptr(ral.classa_timeout_cyc_shadowed), .value(intr_timeout_cyc[0])); + csr_wr(.ptr(ral.classb_timeout_cyc_shadowed), .value(intr_timeout_cyc[1])); + csr_wr(.ptr(ral.classc_timeout_cyc_shadowed), .value(intr_timeout_cyc[2])); + csr_wr(.ptr(ral.classd_timeout_cyc_shadowed), .value(intr_timeout_cyc[3])); + endtask + + virtual task wr_class_accum_threshold(bit[TL_DW-1:0] accum_thresh[NUM_ALERT_CLASSES]); + csr_wr(.ptr(ral.classa_accum_thresh_shadowed), .value(accum_thresh[0])); + csr_wr(.ptr(ral.classb_accum_thresh_shadowed), .value(accum_thresh[1])); + csr_wr(.ptr(ral.classc_accum_thresh_shadowed), .value(accum_thresh[2])); + csr_wr(.ptr(ral.classd_accum_thresh_shadowed), .value(accum_thresh[3])); + endtask + + virtual task wr_ping_timeout_cycle(bit[TL_DW-1:0] timeout_val); + csr_wr(.ptr(ral.ping_timeout_cyc_shadowed), .value(timeout_val)); + if (`gmv(ral.ping_timer_regwen)) begin + if (timeout_val == 0) timeout_val = 1; + foreach (cfg.alert_host_cfg[i]) cfg.alert_host_cfg[i].ping_timeout_cycle = timeout_val; + foreach (cfg.esc_device_cfg[i]) cfg.esc_device_cfg[i].ping_timeout_cycle = timeout_val; + end + endtask + + // This sequence will automatically response to all escalation ping and esc responses + virtual task run_esc_rsp_seq_nonblocking(bit [NUM_ESCS-1:0] esc_int_errs = '0, + bit [NUM_ESCS-1:0] ping_timeout_errs = '0); + foreach (cfg.esc_device_cfg[i]) begin + automatic int index = i; + fork + forever begin + bit esc_int_err = esc_int_errs[index] ? $urandom_range(0, 1) : 0; + bit ping_timeout_err = ping_timeout_errs[index] ? $urandom_range(0, 1) : 0; + esc_receiver_esc_rsp_seq esc_seq = + esc_receiver_esc_rsp_seq::type_id::create("esc_seq"); + `DV_CHECK_RANDOMIZE_WITH_FATAL(esc_seq, int_err == esc_int_err; standalone_int_err == 0; + ping_timeout == ping_timeout_err;) + esc_seq.start(p_sequencer.esc_device_seqr_h[index]); + end + join_none + end + endtask + + // This task will response to all alert_ping + virtual task run_alert_ping_rsp_seq_nonblocking(bit [NUM_ALERTS-1:0] alert_int_err); + foreach (cfg.alert_host_cfg[i]) begin + automatic int index = i; + fork + forever begin + bit alert_timeout = alert_int_err[index] ? $urandom_range(0, 1) : 0; + alert_sender_ping_rsp_seq ping_seq = + alert_sender_ping_rsp_seq::type_id::create("ping_seq"); + `DV_CHECK_RANDOMIZE_WITH_FATAL(ping_seq, int_err == 0; ping_timeout == alert_timeout;) + ping_seq.start(p_sequencer.alert_host_seqr_h[index]); + end + join_none + end + endtask : run_alert_ping_rsp_seq_nonblocking + +endclass : alert_handler_base_vseq + +`undef RAND_AND_WR_CLASS_PHASES_CYCLE +`undef RAND_WRITE_CLASS_CTRL diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv new file mode 100644 index 0000000000000..248a1a0c77ff0 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv @@ -0,0 +1,59 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class alert_handler_common_vseq extends alert_handler_base_vseq; + `uvm_object_utils(alert_handler_common_vseq) + + constraint num_trans_c { + num_trans inside {[1:2]}; + } + + `uvm_object_new + + virtual task body(); + // run alert/esc ping response sequences without error or timeout to prevent triggering local + // alert failure + run_alert_ping_rsp_seq_nonblocking(0); + run_esc_rsp_seq_nonblocking(0); + run_common_vseq_wrapper(num_trans); + endtask : body + + // Override the task to check corresponding CSR status is updated correctly. + virtual task check_tl_intg_error_response(); + bit exp_val = `gmv(ral.loc_alert_en_shadowed[LocalBusIntgFail]); + csr_rd_check(.ptr(ral.loc_alert_cause[LocalBusIntgFail]), .compare_value(exp_val)); + endtask + + // If the common sequence is tl integrity error sequence, we override this task to disable local + // alert for tl_intg_err and lock this register. Because tl_intg_err can trigger local alert and + // eventually triggers escalation. Then the auto predications for escalation related registers + // such as `class_clr` and `clr_regwen` registers are not correct. + virtual task run_csr_vseq(string csr_test_type = "", + int num_test_csrs = 0, + bit do_rand_wr_and_reset = 1); + if (common_seq_type == "tl_intg_err") begin + csr_wr(.ptr(ral.loc_alert_regwen[LocalBusIntgFail]), .value(0), .predict(1)); + end + super.run_csr_vseq(csr_test_type, num_test_csrs, do_rand_wr_and_reset); + endtask + + virtual function void predict_shadow_reg_status(bit predict_update_err = 0, + bit predict_storage_err = 0); + if (predict_update_err) begin + foreach (cfg.shadow_update_err_status_fields[status_field]) begin + if (`gmv(ral.loc_alert_en_shadowed[LocalShadowRegUpdateErr])) begin + void'(status_field.predict(cfg.shadow_update_err_status_fields[status_field])); + end + end + end + if (predict_storage_err) begin + foreach (cfg.shadow_storage_err_status_fields[status_field]) begin + if (`gmv(ral.loc_alert_en_shadowed[LocalShadowRegStorageErr])) begin + void'(status_field.predict(cfg.shadow_storage_err_status_fields[status_field])); + end + end + end + endfunction + +endclass diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv new file mode 100644 index 0000000000000..6392bcb468794 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_entropy_vseq.sv @@ -0,0 +1,40 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence enable entropy by writing 1 to the lock_regen register. + +class alert_handler_entropy_vseq extends alert_handler_smoke_vseq; + `uvm_object_utils(alert_handler_entropy_vseq) + + `uvm_object_new + + // large number of num_trans to make sure covers all alerts and escalation pings + constraint num_trans_c { + num_trans inside {[400:1000]}; + } + + // increase the possibility to enable more alerts, because alert_handler only sends ping on + // enabled alerts + constraint enable_one_alert_c { + alert_en dist {'1 :/ 9, [0:('1-1)] :/ 1}; + } + + constraint sig_int_c { + esc_int_err == 0; + } + + constraint lock_bit_c { + do_lock_config == 1; + } + + constraint esc_accum_thresh_c { + foreach (accum_thresh[i]) {accum_thresh[i] dist {[0:1] :/ 5, [2:10] :/ 5};} + } + + function void pre_randomize(); + this.enable_classa_only_c.constraint_mode(0); + verbosity = UVM_HIGH; + endfunction + +endclass : alert_handler_entropy_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv new file mode 100644 index 0000000000000..12a61f71507e4 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_esc_alert_accum_vseq.sv @@ -0,0 +1,29 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence triggers escalation by accumulating alerts in the same class. +// difference from smoke test, this sequence set the threshold to larger numbers. + +class alert_handler_esc_alert_accum_vseq extends alert_handler_smoke_vseq; + `uvm_object_utils(alert_handler_esc_alert_accum_vseq) + + `uvm_object_new + + constraint disable_clr_esc_c { + do_clr_esc == 0; + } + + constraint enable_alert_accum_esc_only_c { + do_esc_intr_timeout == 0; // disable interrupt timeout triggered escalation + } + + constraint num_trans_c { + num_trans inside {[1:100]}; + } + + constraint esc_accum_thresh_c { + foreach (accum_thresh[i]) {accum_thresh[i] inside {[0:100]};} + } + +endclass : alert_handler_esc_alert_accum_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv new file mode 100644 index 0000000000000..555340dece52b --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_esc_intr_timeout_vseq.sv @@ -0,0 +1,17 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence triggers escalation by the interrupt timeout + +class alert_handler_esc_intr_timeout_vseq extends alert_handler_smoke_vseq; + `uvm_object_utils(alert_handler_esc_intr_timeout_vseq) + + `uvm_object_new + + constraint esc_due_to_intr_timeout_only_c { + foreach (accum_thresh[i]) {accum_thresh[i] > 1;} // prevent alert accumulation triggers esc + do_esc_intr_timeout == 1; + } + +endclass : alert_handler_esc_intr_timeout_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv new file mode 100644 index 0000000000000..c83a1313545bc --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_ping_timeout_vseq.sv @@ -0,0 +1,69 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence test corner cases for alert or escalation pings: +// 1). ping integrity fail or timeout +// 2). ping interrupted by a reset signal +// 3). escalation ping interrupted by real escalation signal (this could happen because escalation +// ping and real escalation share the same esc_p/n signals) + +class alert_handler_ping_timeout_vseq extends alert_handler_entropy_vseq; + `uvm_object_utils(alert_handler_ping_timeout_vseq) + + `uvm_object_new + + constraint num_trans_c { + num_trans inside {[1:10]}; + } + + constraint alert_trigger_c { + alert_trigger == 0; + } + + constraint intr_en_c { + intr_en == '1; + } + + constraint sig_int_c { + alert_int_err == 0; + esc_int_err == 0; + esc_standalone_int_err == 0; + } + + constraint loc_alert_en_c { + local_alert_en[LocalEscPingFail:LocalAlertPingFail] > 0; + } + + constraint ping_fail_c { + alert_ping_timeout == '1; + esc_ping_timeout == '1; + } + + constraint ping_timeout_cyc_c { + ping_timeout_cyc inside {[1:MAX_PING_TIMEOUT_CYCLE]}; + } + + // disable interrupt timeout + constraint esc_intr_timeout_c { + foreach (intr_timeout_cyc[i]) {intr_timeout_cyc[i] == 0;} + } + + function void pre_randomize(); + this.enable_classa_only_c.constraint_mode(0); + endfunction + + // In this sequence, because we disable all external alerts, so to ensure local alerts are + // triggerd, we wait for interrupt pins to fire then wait for alert and escalation handshake + // to finish. + virtual task wait_alert_esc_done(); + wait (cfg.intr_vif.pins[NUM_ALERT_CLASSES-1:0]); + // Wait two clock cycles to avoid building a cycle-accurate scb. + cfg.clk_rst_vif.wait_clks(2); + `uvm_info(`gfn, $sformatf("Interrupt pin = %0h", cfg.intr_vif.pins[NUM_ALERT_CLASSES-1:0]), + UVM_LOW) + check_alert_interrupts(); + super.wait_alert_esc_done(); + endtask + +endclass : alert_handler_ping_timeout_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv new file mode 100644 index 0000000000000..2e1286545fc92 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_random_alerts_vseq.sv @@ -0,0 +1,20 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence enable random alert inputs, and rand wr phase cycles + +class alert_handler_random_alerts_vseq extends alert_handler_smoke_vseq; + `uvm_object_utils(alert_handler_random_alerts_vseq) + + `uvm_object_new + + constraint esc_accum_thresh_c { + foreach (accum_thresh[i]) {accum_thresh[i] dist {[0:1] :/ 5, [2:5] :/ 5};} + } + + function void pre_randomize(); + this.enable_one_alert_c.constraint_mode(0); + endfunction + +endclass : alert_handler_random_alerts_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv new file mode 100644 index 0000000000000..8f58bf92febda --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_random_classes_vseq.sv @@ -0,0 +1,17 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence enable random classes, and rand wr phase cycles + +class alert_handler_random_classes_vseq extends alert_handler_random_alerts_vseq; + `uvm_object_utils(alert_handler_random_classes_vseq) + + `uvm_object_new + + function void pre_randomize(); + super.pre_randomize(); + this.enable_classa_only_c.constraint_mode(0); + endfunction + +endclass : alert_handler_random_classes_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv new file mode 100644 index 0000000000000..71c71013271c6 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_sig_int_fail_vseq.sv @@ -0,0 +1,26 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// this sequence enable signal intergrity fail. + +class alert_handler_sig_int_fail_vseq extends alert_handler_smoke_vseq; + `uvm_object_utils(alert_handler_sig_int_fail_vseq) + + `uvm_object_new + + constraint sig_int_c { + esc_int_err == 0; + esc_standalone_int_err == 0; + } + + constraint esc_accum_thresh_c { + foreach (accum_thresh[i]) {accum_thresh[i] dist {[0:1] :/ 5, [2:10] :/ 5};} + } + + function void pre_randomize(); + this.enable_one_alert_c.constraint_mode(0); + this.enable_classa_only_c.constraint_mode(0); + endfunction + +endclass : alert_handler_sig_int_fail_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv new file mode 100644 index 0000000000000..2ff03b9a0e44b --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_smoke_vseq.sv @@ -0,0 +1,189 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// basic smoke test vseq +class alert_handler_smoke_vseq extends alert_handler_base_vseq; + `uvm_object_utils(alert_handler_smoke_vseq) + + `uvm_object_new + + rand bit [NUM_ALERT_CLASSES-1:0] intr_en; + rand bit [NUM_ALERT_CLASSES-1:0] clr_en; + rand bit [NUM_ALERT_CLASSES-1:0] lock_bit_en; + rand bit [NUM_ALERTS-1:0] alert_trigger; + rand bit [NUM_ALERTS-1:0] alert_int_err; + rand bit [NUM_ALERTS-1:0] alert_en; + rand bit [NUM_ALERTS-1:0] alert_ping_timeout; + rand bit [NUM_ALERT_CLASSES-1:0][NUM_ALERTS-1:0] alert_class_map; + rand bit [NUM_LOCAL_ALERTS-1:0] local_alert_en; + rand bit [NUM_ALERT_CLASSES-1:0][NUM_LOCAL_ALERTS-1:0] local_alert_class_map; + rand bit [NUM_ESCS-1:0] esc_int_err; + rand bit [NUM_ESCS-1:0] esc_standalone_int_err; + rand bit [NUM_ESCS-1:0] esc_ping_timeout; + + rand bit do_clr_esc; + rand bit do_wr_phases_cyc; + rand bit do_esc_intr_timeout; + rand bit do_lock_config; + rand bit [TL_DW-1:0] ping_timeout_cyc; + rand bit [TL_DW-1:0] max_phase_cyc; + rand bit [TL_DW-1:0] intr_timeout_cyc [NUM_ALERT_CLASSES]; + rand bit [TL_DW-1:0] accum_thresh [NUM_ALERT_CLASSES]; + + int max_wait_phases_cyc = MIN_CYCLE_PER_PHASE * NUM_ESC_PHASES; + int max_intr_timeout_cyc; + + uvm_verbosity verbosity = UVM_LOW; + + constraint lock_bit_c { + do_lock_config dist {1 := 1, 0 := 49}; + } + + constraint clr_and_lock_en_c { + clr_en dist {[0:'b1110] :/ 4, '1 :/ 6}; + lock_bit_en dist {0 :/ 6, [1:'b1111] :/ 4}; + } + + constraint enable_one_alert_c { + $onehot(alert_en); + } + + constraint max_phase_cyc_c { + max_phase_cyc inside {[0:1_000]}; + } + + // Set min to 120 cycles to avoid alert ping timeout due to random delay. + // The max delay after ping request is 10 cycles plus 2 cycles async delay. + // Also the alert_sender and alert_handlers are in different clock domains, with a max 10 times + // difference in clock frequency. + constraint ping_timeout_cyc_c { + ping_timeout_cyc inside {[120:MAX_PING_TIMEOUT_CYCLE]}; + } + + constraint enable_classa_only_c { + alert_class_map == 0; // all the alerts assign to classa + local_alert_class_map == 0; // all local alerts assign to classa + } + + // constraint to trigger escalation + constraint esc_accum_thresh_c { + foreach (accum_thresh[i]) {soft accum_thresh[i] inside {[0:1]};} + } + + constraint esc_intr_timeout_c { + foreach (intr_timeout_cyc[i]) {intr_timeout_cyc[i] inside {[1:1_000]};} + } + + constraint sig_int_c { + alert_int_err == 0; + esc_int_err == 0; + esc_standalone_int_err == 0; + } + + constraint ping_fail_c { + alert_ping_timeout == 0; + esc_ping_timeout == 0; + } + + task body(); + fork + begin : isolation_fork + trigger_non_blocking_seqs(); + run_smoke_seq(); + disable fork; // disable non-blocking seqs for stress_all tests + end // end fork + join + endtask : body + + virtual task trigger_non_blocking_seqs(); + `DV_CHECK_MEMBER_RANDOMIZE_FATAL(esc_int_err) + `DV_CHECK_MEMBER_RANDOMIZE_FATAL(alert_ping_timeout) + `DV_CHECK_MEMBER_RANDOMIZE_FATAL(esc_ping_timeout) + run_esc_rsp_seq_nonblocking(esc_int_err, esc_ping_timeout); + run_alert_ping_rsp_seq_nonblocking(alert_ping_timeout); + endtask + + virtual task run_smoke_seq(); + `uvm_info(`gfn, $sformatf("num_trans=%0d", num_trans), UVM_LOW) + for (int i = 1; i <= num_trans; i++) begin + `DV_CHECK_RANDOMIZE_FATAL(this) + + `uvm_info(`gfn, + $sformatf("start seq %0d/%0d: intr_en=%0b, alert=%0b, alert_en=%0b, loc_alert_en=%0b", + i, num_trans, intr_en, alert_trigger, alert_en, local_alert_en), verbosity) + + // write initial settings (enable and mapping csrs) + alert_handler_init(.intr_en(intr_en), + .alert_en(alert_en), + .alert_class(alert_class_map), + .loc_alert_en(local_alert_en), + .loc_alert_class(local_alert_class_map)); + + // write class_ctrl and clren_reg + alert_handler_rand_wr_class_ctrl(lock_bit_en); + alert_handler_wr_regwen_regs(clr_en); + + // randomize crashdump triggered phases + alert_handler_crashdump_phases(); + + // randomly write phase cycle registers + // always set phase_cycle for the first iteration, in order to pass stress_all test + if (do_wr_phases_cyc || i == 1) wr_phases_cycle(max_phase_cyc); + + // randomly write interrupt timeout resigers and accumulative threshold registers + if (do_esc_intr_timeout) wr_intr_timeout_cycle(intr_timeout_cyc); + wr_class_accum_threshold(accum_thresh); + wr_ping_timeout_cycle(ping_timeout_cyc); + + // when all configuration registers are set, write lock register + lock_config(do_lock_config); + + // if config is not locked, update max_intr_timeout and max_wait_phases cycles + if (!config_locked) begin + bit [TL_DW-1:0] max_intr_timeout_cyc; + bit [TL_DW-1:0] max_q[$] = intr_timeout_cyc.max(); + max_intr_timeout_cyc = max_q[0]; + max_wait_phases_cyc = max2(max_wait_phases_cyc, max_phase_cyc * NUM_ESC_PHASES); + if (do_lock_config) config_locked = 1; + end + + // drive esc standalone responses and alerts + if (esc_standalone_int_err) drive_esc_rsp(esc_standalone_int_err); + drive_alert(alert_trigger, alert_int_err); + + if (do_esc_intr_timeout) begin + cfg.clk_rst_vif.wait_clks(max_intr_timeout_cyc); + // this task checks three sets of registers related to alert/esc status: + // alert_accum_cnt, esc_cnt, class_state + read_esc_status(); + end + // only check interrupt when no esc_int_err, otherwise clear interrupt might happen the + // same cycle as interrupt triggered by esc_int_err + if ((esc_int_err == 0) && (esc_ping_timeout == 0)) check_alert_interrupts(); + + // if ping timeout enabled, wait for ping timeout done before checking escalation phases + if ((esc_int_err | alert_ping_timeout) > 0) begin + cfg.clk_rst_vif.wait_clks(MAX_PING_TIMEOUT_CYCLE); + end + + // wait escalation done, and random interrupt with clear_esc + wait_alert_esc_done(); + + read_alert_cause(); + read_esc_status(); + if (do_clr_esc) clear_esc(); + check_alert_interrupts(); + end + endtask + + virtual task wait_alert_esc_done(); + wait_alert_handshake_done(); + if ($urandom_range(0, 1) && (esc_int_err == 0)) begin + cfg.clk_rst_vif.wait_clks($urandom_range(0, max_wait_phases_cyc)); + clear_esc(); + end + wait_esc_handshake_done(); + endtask + +endclass : alert_handler_smoke_vseq diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv new file mode 100644 index 0000000000000..f962108359454 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_stress_all_vseq.sv @@ -0,0 +1,56 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// combine all alert_handler seqs (except below seqs) in one seq to run sequentially +// 1. csr seq, which requires scb to be disabled +class alert_handler_stress_all_vseq extends alert_handler_base_vseq; + `uvm_object_utils(alert_handler_stress_all_vseq) + + `uvm_object_new + + task body(); + bit entropy_test_flag; // this flag ensures entropy test only runs once due to its long runtime + string seq_names[] = {"alert_handler_smoke_vseq", + "alert_handler_random_alerts_vseq", + "alert_handler_random_classes_vseq", + "alert_handler_esc_intr_timeout_vseq", + "alert_handler_esc_alert_accum_vseq", + "alert_handler_sig_int_fail_vseq", + "alert_handler_entropy_vseq"}; + for (int i = 1; i <= num_trans; i++) begin + uvm_sequence seq; + alert_handler_base_vseq alert_vseq; + uint seq_idx = entropy_test_flag ? $urandom_range(0, seq_names.size - 2) : + $urandom_range(0, seq_names.size - 1); + if (seq_names[seq_idx] == "alert_handler_entropy_vseq") entropy_test_flag = 1; + + seq = create_seq_by_name(seq_names[seq_idx]); + `downcast(alert_vseq, seq) + + // if upper seq disables do_apply_reset for this seq, then can't issue reset + // as upper seq may drive reset + if (do_apply_reset) begin + alert_vseq.do_apply_reset = $urandom_range(0, 1); + // config_locked will be set unless reset is issued + alert_vseq.config_locked = alert_vseq.do_apply_reset ? 0 : config_locked; + end else begin + alert_vseq.do_apply_reset = 0; + alert_vseq.config_locked = config_locked; + end + + alert_vseq.set_sequencer(p_sequencer); + `DV_CHECK_RANDOMIZE_FATAL(alert_vseq) + if (seq_names[seq_idx] == "alert_common_vseq") begin + alert_handler_common_vseq common_vseq; + `downcast(common_vseq, alert_vseq); + common_vseq.common_seq_type = "intr_test"; + end + + alert_vseq.start(p_sequencer); + config_locked = alert_vseq.config_locked; + end + endtask : body + +endclass + diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv new file mode 100644 index 0000000000000..14b176fab25d1 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv @@ -0,0 +1,15 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "alert_handler_base_vseq.sv" +`include "alert_handler_smoke_vseq.sv" +`include "alert_handler_common_vseq.sv" +`include "alert_handler_random_alerts_vseq.sv" +`include "alert_handler_random_classes_vseq.sv" +`include "alert_handler_esc_intr_timeout_vseq.sv" +`include "alert_handler_esc_alert_accum_vseq.sv" +`include "alert_handler_sig_int_fail_vseq.sv" +`include "alert_handler_entropy_vseq.sv" +`include "alert_handler_ping_timeout_vseq.sv" +`include "alert_handler_stress_all_vseq.sv" diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/sva/alert_handler_bind.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/sva/alert_handler_bind.sv new file mode 100644 index 0000000000000..f084fad4d5854 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/sva/alert_handler_bind.sv @@ -0,0 +1,23 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module alert_handler_bind; + + bind alert_handler tlul_assert #( + .EndpointType("Device") + ) tlul_assert_device ( + .clk_i, + .rst_ni, + .h2d (tl_i), + .d2h (tl_o) + ); + + bind alert_handler alert_handler_csr_assert_fpv alert_handler_csr_assert ( + .clk_i, + .rst_ni, + .h2d (tl_i), + .d2h (tl_o) + ); + +endmodule diff --git a/hw/ip/alert_handler/dv/sva/alert_handler_sva.core b/hw/top_earlgrey/ip_autogen/alert_handler/dv/sva/alert_handler_sva.core similarity index 86% rename from hw/ip/alert_handler/dv/sva/alert_handler_sva.core rename to hw/top_earlgrey/ip_autogen/alert_handler/dv/sva/alert_handler_sva.core index f5be6aa13cd0f..73c5d1a45699d 100644 --- a/hw/ip/alert_handler/dv/sva/alert_handler_sva.core +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/sva/alert_handler_sva.core @@ -2,7 +2,7 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:dv:alert_handler_sva:0.1" +name: lowrisc:opentitan:top_earlgrey_alert_handler_sva:0.1 description: "ALERT_HANDLER assertion modules and bind file." filesets: files_dv: @@ -15,7 +15,7 @@ filesets: files_formal: depend: - - lowrisc:ip:alert_handler + - lowrisc:opentitan:top_earlgrey_alert_handler:0.1 generate: csr_assert_gen: diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/tb/alert_handler_tb.core b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tb/alert_handler_tb.core new file mode 100644 index 0000000000000..edd71ffe0b406 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tb/alert_handler_tb.core @@ -0,0 +1,18 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:alert_handler_tb:0.1" +description: "ALERT_HANDLER UVM TB environment" +filesets: + files_dv: + depend: + - lowrisc:dv:alert_handler_test:0.1 + files: + - tb.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/tb/tb.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tb/tb.sv new file mode 100644 index 0000000000000..4deefb0f7d9b8 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tb/tb.sv @@ -0,0 +1,107 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module tb; + // dep packages + import uvm_pkg::*; + import dv_utils_pkg::*; + import alert_handler_env_pkg::*; + import alert_handler_test_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + wire clk, rst_n; + wire devmode; + wire [NUM_MAX_INTERRUPTS-1:0] interrupts; + wire [NUM_MAX_ESC_SEV-1:0] esc_en; + wire [NUM_CRASHDUMP-1:0] crashdump; + + // interfaces + clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n)); + pins_if #(NUM_MAX_INTERRUPTS) intr_if(interrupts); + pins_if #(NUM_CRASHDUMP) crashdump_if(crashdump); + pins_if #(1) devmode_if(devmode); + tl_if tl_if(.clk(clk), .rst_n(rst_n)); + alert_esc_if esc_device_if [NUM_ESCS](.clk(clk), .rst_n(rst_n)); + alert_esc_if alert_host_if [NUM_ALERTS](.clk(clk), .rst_n(rst_n)); + alert_esc_probe_if probe_if[NUM_ESCS](.clk(clk), .rst_n(rst_n)); + + // dut signals + prim_alert_pkg::alert_rx_t [NUM_ALERTS-1:0] alert_rx; + prim_alert_pkg::alert_tx_t [NUM_ALERTS-1:0] alert_tx; + + prim_esc_pkg::esc_rx_t [NUM_ESCS-1:0] esc_rx; + prim_esc_pkg::esc_tx_t [NUM_ESCS-1:0] esc_tx; + + for (genvar k = 0; k < NUM_ALERTS; k++) begin : gen_alert_if + assign alert_tx[k].alert_p = alert_host_if[k].alert_tx.alert_p; + assign alert_tx[k].alert_n = alert_host_if[k].alert_tx.alert_n; + assign alert_host_if[k].alert_rx.ack_p = alert_rx[k].ack_p; + assign alert_host_if[k].alert_rx.ack_n = alert_rx[k].ack_n; + assign alert_host_if[k].alert_rx.ping_p = alert_rx[k].ping_p; + assign alert_host_if[k].alert_rx.ping_n = alert_rx[k].ping_n; + initial begin + uvm_config_db#(virtual alert_esc_if)::set(null, $sformatf("*.env.alert_host_agent[%0d]", k), + "vif", alert_host_if[k]); + end + end + + for (genvar k = 0; k < NUM_ESCS; k++) begin : gen_esc_if + assign esc_rx[k].resp_p = esc_device_if[k].esc_rx.resp_p; + assign esc_rx[k].resp_n = esc_device_if[k].esc_rx.resp_n; + assign esc_device_if[k].esc_tx.esc_p = esc_tx[k].esc_p; + assign esc_device_if[k].esc_tx.esc_n = esc_tx[k].esc_n; + // TODO: add assertions to check the probed signal + assign probe_if[k].esc_en = dut.esc_sig_req[k]; + initial begin + uvm_config_db#(virtual alert_esc_if)::set(null, $sformatf("*.env.esc_device_agent[%0d]", k), + "vif", esc_device_if[k]); + uvm_config_db#(virtual alert_esc_probe_if)::set(null, + $sformatf("*.env.esc_device_agent[%0d]", k), "probe_vif", probe_if[k]); + end + end + + // edn_clk, edn_rst_n and edn_if are defined and driven in below macro + `DV_EDN_IF_CONNECT + + // main dut + alert_handler dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .rst_shadowed_ni ( rst_n ), + .clk_edn_i ( edn_clk ), + .rst_edn_ni ( edn_rst_n ), + .tl_i ( tl_if.h2d ), + .tl_o ( tl_if.d2h ), + .intr_classa_o ( interrupts[0] ), + .intr_classb_o ( interrupts[1] ), + .intr_classc_o ( interrupts[2] ), + .intr_classd_o ( interrupts[3] ), + // TODO: need to exercise LPGs + .lpg_cg_en_i ( {alert_pkg::NLpg{prim_mubi_pkg::MuBi4False}} ), + .lpg_rst_en_i ( {alert_pkg::NLpg{prim_mubi_pkg::MuBi4False}} ), + .crashdump_o ( crashdump ), + .edn_o ( edn_if.req ), + .edn_i ( {edn_if.ack, edn_if.d_data} ), + .alert_rx_o ( alert_rx ), + .alert_tx_i ( alert_tx ), + .esc_rx_i ( esc_rx ), + .esc_tx_o ( esc_tx ) + ); + + initial begin + // drive clk and rst_n from clk_if + clk_rst_if.set_active(); + uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "clk_rst_vif", clk_rst_if); + uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if); + uvm_config_db#(crashdump_vif)::set(null, "*.env", "crashdump_vif", crashdump_if); + uvm_config_db#(devmode_vif)::set(null, "*.env", "devmode_vif", devmode_if); + uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if); + $timeformat(-12, 0, " ps", 12); + run_test(); + end + +endmodule diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_base_test.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_base_test.sv new file mode 100644 index 0000000000000..ff8d256e332b8 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_base_test.sv @@ -0,0 +1,21 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class alert_handler_base_test extends cip_base_test #( + .ENV_T(alert_handler_env), + .CFG_T(alert_handler_env_cfg) + ); + + `uvm_component_utils(alert_handler_base_test) + `uvm_component_new + + // the base class dv_base_test creates the following instances: + // alert_handler_env_cfg: cfg + // alert_handler_env: env + + // the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in + // the run_phase; as such, nothing more needs to be done + +endclass : alert_handler_base_test + diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_test.core b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_test.core new file mode 100644 index 0000000000000..06a3f50fbc03e --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_test.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:alert_handler_test:0.1" +description: "ALERT_HANDLER DV UVM test" +filesets: + files_dv: + depend: + - lowrisc:dv:alert_handler_env + files: + - alert_handler_test_pkg.sv + - alert_handler_base_test.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_test_pkg.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_test_pkg.sv new file mode 100644 index 0000000000000..c3f6d76042363 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/tests/alert_handler_test_pkg.sv @@ -0,0 +1,22 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package alert_handler_test_pkg; + // dep packages + import uvm_pkg::*; + import cip_base_pkg::*; + import alert_handler_env_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + // local types + + // functions + + // package sources + `include "alert_handler_base_test.sv" + +endpackage diff --git a/hw/ip/alert_handler/fpv/alert_handler_esc_timer_fpv.core b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/alert_handler_esc_timer_fpv.core similarity index 62% rename from hw/ip/alert_handler/fpv/alert_handler_esc_timer_fpv.core rename to hw/top_earlgrey/ip_autogen/alert_handler/fpv/alert_handler_esc_timer_fpv.core index be2b40c9f9332..abe18e88da387 100644 --- a/hw/ip/alert_handler/fpv/alert_handler_esc_timer_fpv.core +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/alert_handler_esc_timer_fpv.core @@ -2,15 +2,13 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:fpv:alert_handler_esc_timer_fpv:0.1" +name: lowrisc:opentitan:top_earlgrey_alert_handler_esc_timer_fpv:0.1 description: "alert_handler_esc_timer FPV target" filesets: - files_formal: + files_fpv: depend: - lowrisc:prim:all - # note: this is an example config which may differ - # from a particular top-level config - - lowrisc:ip:alert_handler + - lowrisc:opentitan:top_earlgrey_alert_handler files: - vip/alert_handler_esc_timer_assert_fpv.sv - tb/alert_handler_esc_timer_bind_fpv.sv @@ -18,14 +16,10 @@ filesets: file_type: systemVerilogSource targets: - default: &default_target + default: # note, this setting is just used # to generate a file list for jg default_tool: icarus filesets: - - files_formal - toplevel: - - alert_handler_esc_timer_fpv - - formal: - <<: *default_target + - files_fpv + toplevel: alert_handler_esc_timer_fpv diff --git a/hw/ip/alert_handler/fpv/alert_handler_ping_timer_fpv.core b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/alert_handler_ping_timer_fpv.core similarity index 62% rename from hw/ip/alert_handler/fpv/alert_handler_ping_timer_fpv.core rename to hw/top_earlgrey/ip_autogen/alert_handler/fpv/alert_handler_ping_timer_fpv.core index db5d846778991..8f7765dcd34b7 100644 --- a/hw/ip/alert_handler/fpv/alert_handler_ping_timer_fpv.core +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/alert_handler_ping_timer_fpv.core @@ -2,15 +2,13 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:fpv:alert_handler_ping_timer_fpv:0.1" +name: lowrisc:opentitan:top_earlgrey_alert_handler_ping_timer_fpv:0.1 description: "ALERT_HANDLER FPV target" filesets: - files_formal: + files_fpv: depend: - lowrisc:prim:all - # note: this is an example config which may differ - # from a particular top-level config - - lowrisc:ip:alert_handler + - lowrisc:opentitan:top_earlgrey_alert_handler files: - vip/alert_handler_ping_timer_assert_fpv.sv - tb/alert_handler_ping_timer_bind_fpv.sv @@ -18,14 +16,10 @@ filesets: file_type: systemVerilogSource targets: - default: &default_target + default: # note, this setting is just used # to generate a file list for jg default_tool: icarus filesets: - - files_formal - toplevel: - - alert_handler_ping_timer_fpv - - formal: - <<: *default_target + - files_fpv + toplevel: alert_handler_ping_timer_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv new file mode 100644 index 0000000000000..883785557c666 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_esc_timer_bind_fpv.sv @@ -0,0 +1,31 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// + +module alert_handler_esc_timer_bind_fpv; + + + bind alert_handler_esc_timer + alert_handler_esc_timer_assert_fpv i_alert_handler_esc_timer_assert_fpv ( + .clk_i, + .rst_ni, + .en_i, + .clr_i, + .accu_trig_i, + .accu_fail_i, + .timeout_en_i, + .timeout_cyc_i, + .esc_en_i, + .esc_map_i, + .phase_cyc_i, + .crashdump_phase_i, + .latch_crashdump_o, + .esc_trig_o, + .esc_cnt_o, + .esc_sig_req_o, + .esc_state_o + ); + + +endmodule : alert_handler_esc_timer_bind_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv new file mode 100644 index 0000000000000..f1847e51bfeb7 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_esc_timer_fpv.sv @@ -0,0 +1,49 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Testbench module for alert_handler_esc_timer. +// Intended to be used with a formal tool. + +module alert_handler_esc_timer_fpv import alert_pkg::*; ( + input clk_i, + input rst_ni, + input en_i, + input clr_i, + input accu_trig_i, + input accu_fail_i, + input timeout_en_i, + input [EscCntDw-1:0] timeout_cyc_i, + input [N_ESC_SEV-1:0] esc_en_i, + input [N_ESC_SEV-1:0][PHASE_DW-1:0] esc_map_i, + input [N_PHASES-1:0][EscCntDw-1:0] phase_cyc_i, + input [PHASE_DW-1:0] crashdump_phase_i, + output logic latch_crashdump_o, + output logic esc_trig_o, + output logic[EscCntDw-1:0] esc_cnt_o, + output logic[N_ESC_SEV-1:0] esc_sig_req_o, + output cstate_e esc_state_o +); + + alert_handler_esc_timer i_alert_handler_esc_timer ( + .clk_i, + .rst_ni, + .en_i, + .clr_i, + .accu_trig_i, + .accu_fail_i, + .timeout_en_i, + .timeout_cyc_i, + .esc_en_i, + .esc_map_i, + .phase_cyc_i, + .crashdump_phase_i, + .latch_crashdump_o, + .esc_trig_o, + .esc_cnt_o, + .esc_sig_req_o, + .esc_state_o + ); + + +endmodule : alert_handler_esc_timer_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv new file mode 100644 index 0000000000000..78ecf332f3c1d --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_ping_timer_bind_fpv.sv @@ -0,0 +1,29 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// + +module alert_handler_ping_timer_bind_fpv; + + + bind alert_handler_ping_timer + alert_handler_ping_timer_assert_fpv i_alert_handler_ping_timer_assert_fpv ( + .clk_i, + .rst_ni, + .edn_req_o, + .edn_ack_i, + .edn_data_i, + .en_i, + .alert_ping_en_i, + .ping_timeout_cyc_i, + .wait_cyc_mask_i, + .alert_ping_req_o, + .esc_ping_req_o, + .alert_ping_ok_i, + .esc_ping_ok_i, + .alert_ping_fail_o, + .esc_ping_fail_o + ); + + +endmodule : alert_handler_ping_timer_bind_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv new file mode 100644 index 0000000000000..ca18a84573c4e --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/tb/alert_handler_ping_timer_fpv.sv @@ -0,0 +1,48 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Testbench module for ping timer in alert handler. Intended to use with +// a formal tool. + +module alert_handler_ping_timer_fpv import alert_pkg::*; ( + input clk_i, + input rst_ni, + output logic edn_req_o, + input edn_ack_i, + input [LfsrWidth-1:0] edn_data_i, + input en_i, + input [NAlerts-1:0] alert_ping_en_i, + input [PING_CNT_DW-1:0] ping_timeout_cyc_i, + input [PING_CNT_DW-1:0] wait_cyc_mask_i, + output logic [NAlerts-1:0] alert_ping_req_o, + output logic [N_ESC_SEV-1:0] esc_ping_req_o, + input [NAlerts-1:0] alert_ping_ok_i, + input [N_ESC_SEV-1:0] esc_ping_ok_i, + output logic alert_ping_fail_o, + output logic esc_ping_fail_o +); + + alert_handler_ping_timer #( + // disable max length check in FPV, otherwise this + // will not converge within acceptable compute time + .MaxLenSVA ( 1'b0 ) + ) i_alert_handler_ping_timer ( + .clk_i , + .rst_ni , + .edn_req_o , + .edn_ack_i , + .edn_data_i , + .en_i , + .alert_ping_en_i , + .ping_timeout_cyc_i, + .wait_cyc_mask_i , + .alert_ping_req_o , + .esc_ping_req_o , + .alert_ping_ok_i , + .esc_ping_ok_i , + .alert_ping_fail_o , + .esc_ping_fail_o + ); + +endmodule : alert_handler_ping_timer_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv new file mode 100644 index 0000000000000..f41b44178cc3b --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/vip/alert_handler_esc_timer_assert_fpv.sv @@ -0,0 +1,149 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Assertions for alert_handler_esc_timer. +// Intended to be used with a formal tool. + +`include "prim_assert.sv" + +module alert_handler_esc_timer_assert_fpv import alert_pkg::*; ( + input clk_i, + input rst_ni, + input en_i, + input clr_i, + input accu_trig_i, + input accu_fail_i, + input timeout_en_i, + input [EscCntDw-1:0] timeout_cyc_i, + input [N_ESC_SEV-1:0] esc_en_i, + input [N_ESC_SEV-1:0][PHASE_DW-1:0] esc_map_i, + input [N_PHASES-1:0][EscCntDw-1:0] phase_cyc_i, + input [PHASE_DW-1:0] crashdump_phase_i, + input logic latch_crashdump_o, + input logic esc_trig_o, + input logic[EscCntDw-1:0] esc_cnt_o, + input logic[N_ESC_SEV-1:0] esc_sig_req_o, + input cstate_e esc_state_o +); + + /////////////////////////////// + // Declarations & Parameters // + /////////////////////////////// + + // constrain the state-spaces + localparam int unsigned MAX_TIMEOUT_CYCLES = 10; + localparam int unsigned MAX_PHASE_CYCLES = 10; + + // symbolic vars for phase map check + logic [1:0] esc_sel; + logic [1:0] phase_sel; + localparam cstate_e Phases [4] = {Phase0, Phase1, Phase2, Phase3}; + + // set regs + logic esc_has_triggered_q; + + + ///////////////// + // Assumptions // + ///////////////// + + `ASSUME(TimeoutCycles_M, timeout_cyc_i < MAX_TIMEOUT_CYCLES) + `ASSUME(TimeoutCyclesConst_M, ##1 $stable(timeout_cyc_i)) + + `ASSUME(PhaseCycles_M, phase_cyc_i < MAX_PHASE_CYCLES) + `ASSUME(PhaseCyclesConst_M, ##1 $stable(phase_cyc_i)) + + `ASSUME(CrashdumpPhaseConst_M, ##1 $stable(crashdump_phase_i)) + + `ASSUME(EscSelConst_M, ##1 $stable(esc_sel)) + `ASSUME(PhaseSelConst_M, ##1 $stable(phase_sel)) + + //////////////////////// + // Forward Assertions // + //////////////////////// + + // if the class is not enabled and we are in IDLE state, + // neither of the two escalation mechanisms shall fire + `ASSERT(ClassDisabledNoEscTrig_A, esc_state_o == Idle && !en_i |-> !esc_trig_o) + `ASSERT(ClassDisabledNoEsc_A, esc_state_o == Idle && !en_i |-> !esc_sig_req_o) + `ASSERT(EscDisabledNoEsc_A, !esc_en_i[esc_sel] && esc_state_o != FsmError |-> + !esc_sig_req_o[esc_sel]) + + // if timeout counter is enabled due to a pending interrupt, check escalation + // assume accumulation trigger is not asserted during this sequence + `ASSERT(TimeoutEscTrig_A, esc_state_o == Idle ##1 en_i && $rose(timeout_en_i) && + (timeout_cyc_i > 0) ##1 timeout_en_i [*MAX_TIMEOUT_CYCLES] |=> esc_has_triggered_q, + clk_i, !rst_ni || accu_trig_i || clr_i || accu_fail_i) + + // check whether an accum trig leads to escalation if enabled + `ASSERT(AccumEscTrig_A, ##1 en_i && accu_trig_i && esc_state_o inside {Idle, Timeout} |=> + esc_has_triggered_q, clk_i, !rst_ni || clr_i || accu_fail_i) + + // check escalation cnt and state out + parameter logic [alert_handler_esc_timer.StateWidth-1:0] StateEncodings [8] = '{ + alert_handler_esc_timer.IdleSt, + alert_handler_esc_timer.TimeoutSt, + alert_handler_esc_timer.FsmErrorSt, + alert_handler_esc_timer.TerminalSt, + alert_handler_esc_timer.Phase0St, + alert_handler_esc_timer.Phase1St, + alert_handler_esc_timer.Phase2St, + alert_handler_esc_timer.Phase3St + }; + `ASSERT(EscStateOut_A, alert_handler_esc_timer.state_q == StateEncodings[esc_state_o]) + `ASSERT(EscCntOut_A, alert_handler_esc_timer.cnt_q[0] == esc_cnt_o) + + // check clr input + // we cannot use clr to exit from the timeout state + `ASSERT(ClrCheck_A, clr_i && !(esc_state_o inside {Idle, Timeout, FsmError}) && !accu_fail_i |=> + esc_state_o == Idle) + + // check escalation map + `ASSERT(PhaseEscMap_A, esc_state_o == Phases[phase_sel] && esc_map_i[esc_sel] == phase_sel && + esc_en_i[esc_sel] |-> esc_sig_req_o[esc_sel]) + + // check terminal state is reached eventually if triggered and not cleared + `ASSERT(TerminalState_A, esc_trig_o |-> strong(##[1:$] esc_state_o == Terminal), + clk_i, !rst_ni || clr_i || accu_fail_i) + + // check that the crashdump capture trigger is asserted correctly + `ASSERT(CrashdumpTrigger_A, + ##1 $changed(esc_state_o) && + esc_state_o == cstate_e'(4 + crashdump_phase_i) + <-> + $past(latch_crashdump_o), esc_state_o == FsmError) + + ///////////////////////// + // Backward Assertions // + ///////////////////////// + + // escalation can only be triggered when in Idle or Timeout state. Trigger mechanisms are either + // the accumulation trigger or a timeout trigger + `ASSERT(EscTrigBkwd_A, esc_trig_o |-> esc_state_o inside {Idle, Timeout} && accu_trig_i || + esc_state_o == Timeout && esc_cnt_o >= timeout_cyc_i) + `ASSERT(NoEscTrigBkwd_A, !esc_trig_o |-> !(esc_state_o inside {Idle, Timeout}) || + !en_i || !accu_trig_i || !timeout_en_i || clr_i) + + // escalation signals can only be asserted in the escalation phase states, or + // if we are in the terminal FsmError state + `ASSERT(EscBkwd_A, esc_sig_req_o[esc_sel] |-> esc_en_i[esc_sel] && + esc_has_triggered_q || esc_state_o == FsmError) + `ASSERT(NoEscBkwd_A, !esc_sig_req_o[esc_sel] |-> !esc_en_i[esc_sel] || + esc_state_o != Phases[esc_map_i[esc_sel]] && esc_state_o != FsmError, + clk_i, !rst_ni || clr_i) + + ////////////////////// + // Helper Processes // + ////////////////////// + + // set registers + always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs + if (!rst_ni) begin + esc_has_triggered_q <= 1'b0; + end else begin + esc_has_triggered_q <= esc_has_triggered_q & ~clr_i | esc_trig_o; + end + end + +endmodule : alert_handler_esc_timer_assert_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv new file mode 100644 index 0000000000000..9bb7de4d04c55 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/fpv/vip/alert_handler_ping_timer_assert_fpv.sv @@ -0,0 +1,132 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Assertions for ping timer in alert handler. Intended to use with +// a formal tool. + +`include "prim_assert.sv" + +module alert_handler_ping_timer_assert_fpv import alert_pkg::*; ( + input clk_i, + input rst_ni, + input edn_req_o, + input edn_ack_i, + input [LfsrWidth-1:0] edn_data_i, + input en_i, + input [NAlerts-1:0] alert_ping_en_i, + input [PING_CNT_DW-1:0] ping_timeout_cyc_i, + input [PING_CNT_DW-1:0] wait_cyc_mask_i, + input [NAlerts-1:0] alert_ping_req_o, + input [N_ESC_SEV-1:0] esc_ping_req_o, + input [NAlerts-1:0] alert_ping_ok_i, + input [N_ESC_SEV-1:0] esc_ping_ok_i, + input alert_ping_fail_o, + input esc_ping_fail_o +); + + localparam int unsigned PingEnDw = N_ESC_SEV + NAlerts; + logic [PingEnDw-1:0] ping_en_vector, ping_en_mask, ping_ok_vector; + + assign ping_en_vector = {esc_ping_req_o, alert_ping_req_o}; + assign ping_en_mask = {N_ESC_SEV'('1), alert_ping_en_i}; + assign ping_ok_vector = {esc_ping_ok_i, alert_ping_ok_i}; + + ///////////////// + // Assumptions // + ///////////////// + + localparam int MaxWaitCntDw = 3; + + // symbolic variables. we want to assess all valid indices + logic [$clog2(PingEnDw)-1:0] ping_en_sel; + logic [$clog2(N_ESC_SEV)-1:0] esc_idx; + `ASSUME_FPV(PingEnSelRange_M, ping_en_sel < PingEnDw) + `ASSUME_FPV(PingEnSelStable_M, ##1 $stable(ping_en_sel)) + `ASSUME_FPV(EscIdxRange_M, esc_idx < N_ESC_SEV) + `ASSUME_FPV(EscIdxStable_M, ##1 $stable(esc_idx)) + // assume that the alert enable configuration is locked once en_i is high + // this is ensured by the CSR regfile on the outside + `ASSUME_FPV(ConfigLocked0_M, en_i |-> $stable(alert_ping_en_i)) + `ASSUME_FPV(ConfigLocked1_M, en_i |-> $stable(ping_timeout_cyc_i)) + // enable stays high forever, once it has been asserted + `ASSUME(ConfigLocked2_M, en_i |=> en_i) + // reduce state space by reducing length of wait period + `ASSUME_FPV(WaitPeriod0_M, wait_cyc_mask_i == {MaxWaitCntDw{1'b1}}) + `ASSUME_FPV(WaitPeriod1_M, ping_timeout_cyc_i <= {MaxWaitCntDw{1'b1}}) + + //////////////////////// + // Forward Assertions // + //////////////////////// + + // no pings on disabled alerts + `ASSERT(DisabledNoAlertPings_A, ((~alert_ping_en_i) & alert_ping_req_o) == 0) + // no pings when not enabled + `ASSERT(NoPingsWhenDisabled0_A, !en_i |-> !alert_ping_req_o) + `ASSERT(NoPingsWhenDisabled1_A, !en_i |-> !esc_ping_req_o) + `ASSERT(NoPingsWhenDisabled2_A, en_i && !ping_en_mask[ping_en_sel] |-> + !ping_en_vector[ping_en_sel]) + + // spurious pings (i.e. pings that where not requested) + // on alert channels + `ASSERT(SpuriousPingsDetected0_A, en_i && !ping_en_vector[ping_en_sel] && + ping_ok_vector[ping_en_sel] && ping_en_sel < NAlerts |-> + alert_ping_fail_o) + // on escalation channels + `ASSERT(SpuriousPingsDetected1_A, en_i && !ping_en_vector[ping_en_sel] && + ping_ok_vector[ping_en_sel] && ping_en_sel >= NAlerts |-> + esc_ping_fail_o) + // response must be one hot + `ASSERT(SpuriousPingsDetected2_A, en_i && !$onehot0(ping_ok_vector) |-> + esc_ping_fail_o || alert_ping_fail_o) + + // ensure that the number of cycles between pings on a specific escalation channel + // are within bounds. we try to prove this property with a margin of 2x here, whereas + // the ping receivers actually work with a margin of 4x to stay on the safe side. + localparam int MarginFactor = 2; + localparam int NumWaitCounts = 2; + localparam int NumTimeoutCounts = 2; + localparam int PingPeriodBound = MarginFactor * // margin to apply + N_ESC_SEV * // number of escalation channels to ping + (NumWaitCounts + // 1 alert and 1 esc wait count + NumTimeoutCounts) * // 1 alert and 1 esc timeout count + 2**MaxWaitCntDw; // maximum counter value + + `ASSERT(EscalationPingPeriodWithinBounds_A, + $rose(esc_ping_req_o[esc_idx]) + |-> + ##[1 : PingPeriodBound] + $rose(esc_ping_req_o[esc_idx])) + + ///////////////////////// + // Backward Assertions // + ///////////////////////// + + // no pings when not enabled + `ASSERT(NoPingsWhenDisabledBkwd0_A, alert_ping_req_o |-> en_i) + `ASSERT(NoPingsWhenDisabledBkwd1_A, esc_ping_req_o |-> en_i) + + // spurious pings (i.e. pings that where not requested) + // on alert channels + `ASSERT(SpuriousPingsDetectedBkwd0_A, !alert_ping_fail_o |-> + !en_i || ping_en_vector[ping_en_sel] || + !ping_ok_vector[ping_en_sel] || ping_en_sel >= NAlerts) + // on escalation channels + `ASSERT(SpuriousPingsDetectedBkwd1_A, !esc_ping_fail_o |-> + !en_i || ping_en_vector[ping_en_sel] || + !ping_ok_vector[ping_en_sel] || ping_en_sel < NAlerts) + // response must be one hot + `ASSERT(SpuriousPingsDetectedBkwd2_A, !esc_ping_fail_o && !alert_ping_fail_o |-> + !en_i || $onehot0(ping_ok_vector)) + + ////////////////////////////////////////////////////////// + // Currently not Tested in FPV due to large state space // + ////////////////////////////////////////////////////////// + + // 1) if an alert is enabled, it should be pinged eventually + // when entropy input is disabled + // 2) ping ok within timeout -> ok + // 3) ping ok after timeout -> alert + // 4) no ping response -> alert + +endmodule : alert_handler_ping_timer_assert_fpv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/lint/alert_handler.vlt b/hw/top_earlgrey/ip_autogen/alert_handler/lint/alert_handler.vlt new file mode 100644 index 0000000000000..0e2406e9fbc5d --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/lint/alert_handler.vlt @@ -0,0 +1,12 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`verilator_config + +// Tell the Verilator scheduler to split up hw2reg_wrap into separate fields +// when scheduling processes. This structure is used (among other things) to +// communicate between alert_handler_accu and alert_handler_esc_timer instances +// and tracking it as one big blob causes spurious apparent circular +// dependencies. +split_var -module "alert_handler" -var "hw2reg_wrap" diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/lint/alert_handler.waiver b/hw/top_earlgrey/ip_autogen/alert_handler/lint/alert_handler.waiver new file mode 100644 index 0000000000000..457e1585b9643 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/lint/alert_handler.waiver @@ -0,0 +1,44 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# waiver file for alert handler + +waive -rules ENUM_RANGE -location {alert_handler_esc_timer.sv} -regexp {state_q} \ + -comment "State is used to index timeout cycle counts" + +waive -rules NOT_READ -location {alert_handler_ping_timer.sv} -regexp {perm_state} \ + -comment "Upper bits of permuted array are not read" + +waive -rules HIER_NET_NOT_READ -location {alert_handler_ping_timer.sv} -regexp {perm_state} \ + -comment "Upper bits of permuted array are not read" + +waive -rules HIER_NET_NOT_READ -location {alert_handler.sv} -regexp {[Nn]et 'tl_[io]\.[ad]_(address|param|user)} \ + -comment "Register interface doesn't use upper address and param, user filed" + +waive -rules INSIDE_OP_CONTEXT -location {prim_esc_sender.sv} -regexp {inside} \ + -comment "Inside operator is used within SVA" + +waive -rules CASE_INC -location {alert_handler_esc_timer.sv} -regexp {'b010} \ + -comment "Not all case tags are required." + +waive -rules CASE_INC -location {alert_handler_ping_timer.sv} -regexp {'b11} \ + -comment "Not all case tags are required." + +waive -rules CASE_INC -location {prim_esc_sender.sv} -regexp {'b111} \ + -comment "Not all case tags are required." + +waive -rules ONE_BIT_VEC -location {prim_lfsr.sv} -regexp {InDw - 1:0} \ + -comment "Data input may be one bit wide." + +waive -rules VAR_INDEX -location {alert_handler_esc_timer.sv} -regexp {phase_cyc_i\[phase_idx\]} \ + -comment "This indexing expression is correct." + +waive -rules VAR_INDEX -location {alert_handler_ping_timer.sv} -regexp {enable_mask\[id_to_ping\]} \ + -comment "This indexing expression is correct." + +waive -rules CLOCK_USE -location {alert_handler_lpg_ctrl.sv} -msg {'clk_i' is connected to 'prim_lc_sync' port 'clk_i', and used as} \ + -comment "This clock connection is only used for assertions internal to the prim module." + +waive -rules RESET_USE -location {alert_handler_lpg_ctrl.sv} -msg {'rst_ni' is connected to 'prim_lc_sync' port 'rst_ni', and used as} \ + -comment "This reset connection is only used for assertions internal to the prim module." diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv new file mode 100644 index 0000000000000..5b3ffc5b4af39 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv @@ -0,0 +1,282 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Alert handler top + +`include "prim_assert.sv" + +module alert_handler + import alert_pkg::*; + import prim_alert_pkg::*; + import prim_esc_pkg::*; +#( + // Compile time random constants, to be overriden by topgen. + parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, + parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault +) ( + input clk_i, + input rst_ni, + input rst_shadowed_ni, + input clk_edn_i, + input rst_edn_ni, + // Bus Interface (device) + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, + // Interrupt Requests + output logic intr_classa_o, + output logic intr_classb_o, + output logic intr_classc_o, + output logic intr_classd_o, + // Clock gating and reset info from rstmgr and clkmgr + input prim_mubi_pkg::mubi4_t [NLpg-1:0] lpg_cg_en_i, + input prim_mubi_pkg::mubi4_t [NLpg-1:0] lpg_rst_en_i, + // State information for HW crashdump + output alert_crashdump_t crashdump_o, + // Entropy Input + output edn_pkg::edn_req_t edn_o, + input edn_pkg::edn_rsp_t edn_i, + // Alert Sources + input alert_tx_t [NAlerts-1:0] alert_tx_i, + output alert_rx_t [NAlerts-1:0] alert_rx_o, + // Escalation outputs + input esc_rx_t [N_ESC_SEV-1:0] esc_rx_i, + output esc_tx_t [N_ESC_SEV-1:0] esc_tx_o +); + + ////////////////////////////////// + // Regfile Breakout and Mapping // + ////////////////////////////////// + + logic [N_CLASSES-1:0] latch_crashdump; + logic [N_LOC_ALERT-1:0] loc_alert_trig; + logic [N_CLASSES-1:0] irq; + hw2reg_wrap_t hw2reg_wrap; + reg2hw_wrap_t reg2hw_wrap; + + assign {intr_classd_o, + intr_classc_o, + intr_classb_o, + intr_classa_o} = irq; + + alert_handler_reg_wrap u_reg_wrap ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .tl_i, + .tl_o, + .irq_o ( irq ), + .latch_crashdump_i ( |latch_crashdump ), + .crashdump_o, + .hw2reg_wrap, + .reg2hw_wrap, + .fatal_integ_alert_o(loc_alert_trig[4]) + ); + + assign loc_alert_trig[5] = reg2hw_wrap.shadowed_err_update; + assign loc_alert_trig[6] = reg2hw_wrap.shadowed_err_storage; + + //////////////// + // Ping Timer // + //////////////// + + logic [NAlerts-1:0] alert_ping_req; + logic [NAlerts-1:0] alert_ping_ok; + logic [N_ESC_SEV-1:0] esc_ping_req; + logic [N_ESC_SEV-1:0] esc_ping_ok; + + logic edn_req, edn_ack; + logic [LfsrWidth-1:0] edn_data; + + prim_edn_req #( + .OutWidth(LfsrWidth) + ) u_edn_req ( + // Alert handler side + .clk_i, + .rst_ni, + .req_chk_i ( 1'b1 ), + .req_i ( edn_req ), + .ack_o ( edn_ack ), + .data_o ( edn_data ), + .fips_o ( ), + // EDN side + .clk_edn_i, + .rst_edn_ni, + .edn_o ( edn_o ), + .edn_i ( edn_i ) + ); + + alert_handler_ping_timer #( + .RndCnstLfsrSeed(RndCnstLfsrSeed), + .RndCnstLfsrPerm(RndCnstLfsrPerm) + ) u_ping_timer ( + .clk_i, + .rst_ni, + .edn_req_o ( edn_req ), + .edn_ack_i ( edn_ack ), + .edn_data_i ( edn_data ), + .en_i ( reg2hw_wrap.ping_enable ), + .alert_ping_en_i ( reg2hw_wrap.alert_ping_en ), + .ping_timeout_cyc_i ( reg2hw_wrap.ping_timeout_cyc ), + // set this to the maximum width in the design. + // can be overridden in DV and FPV to shorten the wait periods. + .wait_cyc_mask_i ( {PING_CNT_DW{1'b1}} ), + .alert_ping_req_o ( alert_ping_req ), + .esc_ping_req_o ( esc_ping_req ), + .alert_ping_ok_i ( alert_ping_ok ), + .esc_ping_ok_i ( esc_ping_ok ), + .alert_ping_fail_o ( loc_alert_trig[0] ), + .esc_ping_fail_o ( loc_alert_trig[1] ) + ); + + ///////////////////////////// + // Low-power group control // + ///////////////////////////// + + prim_mubi_pkg::mubi4_t [NAlerts-1:0] alert_init_trig; + alert_handler_lpg_ctrl u_alert_handler_lpg_ctrl ( + .clk_i, + .rst_ni, + .lpg_cg_en_i, + .lpg_rst_en_i, + .alert_init_trig_o ( alert_init_trig ) + ); + + ///////////////////// + // Alert Receivers // + ///////////////////// + + logic [NAlerts-1:0] alert_integfail; + logic [NAlerts-1:0] alert_trig; + + // Target interrupt notification + for (genvar k = 0 ; k < NAlerts ; k++) begin : gen_alerts + prim_alert_receiver #( + .AsyncOn(AsyncOn[k]) + ) u_alert_receiver ( + .clk_i, + .rst_ni, + .init_trig_i ( alert_init_trig[k] ), + .ping_req_i ( alert_ping_req[k] ), + .ping_ok_o ( alert_ping_ok[k] ), + .integ_fail_o ( alert_integfail[k] ), + .alert_o ( alert_trig[k] ), + .alert_rx_o ( alert_rx_o[k] ), + .alert_tx_i ( alert_tx_i[k] ) + ); + end + + assign loc_alert_trig[2] = |(reg2hw_wrap.alert_en & alert_integfail); + + /////////////////////////////////////// + // Set alert cause bits and classify // + /////////////////////////////////////// + + alert_handler_class u_class ( + .alert_trig_i ( alert_trig ), + .loc_alert_trig_i ( loc_alert_trig ), + .alert_en_i ( reg2hw_wrap.alert_en ), + .loc_alert_en_i ( reg2hw_wrap.loc_alert_en ), + .alert_class_i ( reg2hw_wrap.alert_class ), + .loc_alert_class_i ( reg2hw_wrap.loc_alert_class ), + .alert_cause_o ( hw2reg_wrap.alert_cause ), + .loc_alert_cause_o ( hw2reg_wrap.loc_alert_cause ), + .class_trig_o ( hw2reg_wrap.class_trig ) + ); + + //////////////////////////////////// + // Escalation Handling of Classes // + //////////////////////////////////// + + logic [N_CLASSES-1:0][N_ESC_SEV-1:0] class_esc_sig_req; + + for (genvar k = 0; k < N_CLASSES; k++) begin : gen_classes + logic class_accu_fail, class_accu_trig; + alert_handler_accu u_accu ( + .clk_i, + .rst_ni, + .class_en_i ( reg2hw_wrap.class_en[k] ), + .clr_i ( reg2hw_wrap.class_clr[k] ), + .class_trig_i ( hw2reg_wrap.class_trig[k] ), + .thresh_i ( reg2hw_wrap.class_accum_thresh[k] ), + .accu_cnt_o ( hw2reg_wrap.class_accum_cnt[k] ), + .accu_trig_o ( class_accu_trig ), + .accu_fail_o ( class_accu_fail ) + ); + + alert_handler_esc_timer u_esc_timer ( + .clk_i, + .rst_ni, + .en_i ( reg2hw_wrap.class_en[k] ), + // this clear does not apply to interrupts + .clr_i ( reg2hw_wrap.class_clr[k] ), + // an interrupt enables the timeout + .timeout_en_i ( irq[k] ), + .accu_trig_i ( class_accu_trig ), + .accu_fail_i ( class_accu_fail ), + .timeout_cyc_i ( reg2hw_wrap.class_timeout_cyc[k] ), + .esc_en_i ( reg2hw_wrap.class_esc_en[k] ), + .esc_map_i ( reg2hw_wrap.class_esc_map[k] ), + .phase_cyc_i ( reg2hw_wrap.class_phase_cyc[k] ), + .crashdump_phase_i ( reg2hw_wrap.class_crashdump_phase[k] ), + .latch_crashdump_o ( latch_crashdump[k] ), + .esc_trig_o ( hw2reg_wrap.class_esc_trig[k] ), + .esc_cnt_o ( hw2reg_wrap.class_esc_cnt[k] ), + .esc_state_o ( hw2reg_wrap.class_esc_state[k] ), + .esc_sig_req_o ( class_esc_sig_req[k] ) + ); + end + + //////////////////////// + // Escalation Senders // + //////////////////////// + + logic [N_ESC_SEV-1:0] esc_sig_req; + logic [N_ESC_SEV-1:0] esc_integfail; + logic [N_ESC_SEV-1:0][N_CLASSES-1:0] esc_sig_req_trsp; + + for (genvar k = 0; k < N_ESC_SEV; k++) begin : gen_esc_sev + for (genvar j = 0; j < N_CLASSES; j++) begin : gen_transp + assign esc_sig_req_trsp[k][j] = class_esc_sig_req[j][k]; + end + + assign esc_sig_req[k] = |esc_sig_req_trsp[k]; + + prim_esc_sender u_esc_sender ( + .clk_i, + .rst_ni, + .ping_req_i ( esc_ping_req[k] ), + .ping_ok_o ( esc_ping_ok[k] ), + .integ_fail_o ( esc_integfail[k] ), + .esc_req_i ( esc_sig_req[k] ), + .esc_rx_i ( esc_rx_i[k] ), + .esc_tx_o ( esc_tx_o[k] ) + ); + end + + assign loc_alert_trig[3] = |esc_integfail; + + //////////////// + // Assertions // + //////////////// + + // check whether all outputs have a good known state after reset + `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid) + `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready) + `ASSERT_KNOWN(IrqAKnownO_A, intr_classa_o) + `ASSERT_KNOWN(IrqBKnownO_A, intr_classb_o) + `ASSERT_KNOWN(IrqCKnownO_A, intr_classc_o) + `ASSERT_KNOWN(IrqDKnownO_A, intr_classd_o) + `ASSERT_KNOWN(CrashdumpKnownO_A, crashdump_o) + `ASSERT_KNOWN(AckPKnownO_A, alert_rx_o) + `ASSERT_KNOWN(EscPKnownO_A, esc_tx_o) + `ASSERT_KNOWN(EdnKnownO_A, edn_o) + + // this restriction is due to specifics in the ping selection mechanism + `ASSERT_INIT(CheckNAlerts, NAlerts < (256 - N_CLASSES)) + `ASSERT_INIT(CheckEscCntDw, EscCntDw <= 32) + `ASSERT_INIT(CheckAccuCntDw, AccuCntDw <= 32) + `ASSERT_INIT(CheckNClasses, N_CLASSES <= 8) + `ASSERT_INIT(CheckNEscSev, N_ESC_SEV <= 8) + +endmodule diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_accu.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_accu.sv new file mode 100644 index 0000000000000..8e599f77970eb --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_accu.sv @@ -0,0 +1,79 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module accumulates incoming alert triggers. Once the current accumulator +// value is greater or equal the accumulator threshold, the next occurence of +// class_trig_i will trigger escalation. +// +// Note that the accumulator is implemented using a saturation counter which +// does not wrap around. +// + +`include "prim_assert.sv" + +module alert_handler_accu import alert_pkg::*; ( + input clk_i, + input rst_ni, + input class_en_i, // class enable + input clr_i, // clear the accumulator + input class_trig_i, // increments the accu + input [AccuCntDw-1:0] thresh_i, // escalation trigger threshold + output logic [AccuCntDw-1:0] accu_cnt_o, // output of current accu value + output logic accu_trig_o, // escalation trigger output + output logic accu_fail_o // asserted if the tandem accu counters are not equal +); + + logic trig_gated_unbuf; + assign trig_gated_unbuf = class_trig_i & class_en_i; + + // We employ two redundant counters to guard against FI attacks. + // If any of the two is glitched and the two counter states do not agree, + // the check_fail_o signal is asserted which will move the corresponding escalation + // FSM into a terminal error state where all escalation actions will be permanently asserted. + logic [1:0][AccuCntDw-1:0] accu_q; + for (genvar k = 0; k < 2; k++) begin : gen_double_accu + + logic trig_gated_buf, clr_buf; + logic [AccuCntDw-1:0] accu_d; + + // These size_only buffers are instantiated in order to prevent + // optimization / merging of the two counters. + prim_buf u_prim_buf_clr ( + .in_i(clr_i), + .out_o(clr_buf) + ); + + prim_buf u_prim_buf_trig ( + .in_i(trig_gated_unbuf), + .out_o(trig_gated_buf) + ); + + assign accu_d = (clr_buf) ? '0 : // clear + (trig_gated_buf && !(&accu_q[k])) ? accu_q[k] + 1'b1 : // saturate counter + accu_q[k]; + + prim_flop #( + .Width(AccuCntDw) + ) u_prim_flop ( + .clk_i, + .rst_ni, + .d_i(accu_d), + .q_o(accu_q[k]) + ); + end + + assign accu_cnt_o = accu_q[0]; + assign accu_trig_o = (accu_q[0] >= thresh_i) & trig_gated_unbuf; + assign accu_fail_o = accu_q[0] != accu_q[1]; + + //////////////// + // Assertions // + //////////////// + + `ASSERT(DisabledNoTrigFwd_A, !class_en_i |-> !accu_trig_o) + `ASSERT(DisabledNoTrigBkwd_A, accu_trig_o |-> class_en_i) + `ASSERT(CheckFailFwd_A, accu_q[0] != accu_q[1] |-> accu_fail_o) + `ASSERT(CheckFailBkwd_A, accu_fail_o |-> accu_q[0] != accu_q[1]) + +endmodule : alert_handler_accu diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_class.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_class.sv new file mode 100644 index 0000000000000..79af26bb6317e --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_class.sv @@ -0,0 +1,49 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module gates the alert triggers with their enable bits, and correctly bins +// the enabled alerts into the class that they have been assigned to. The module +// produces the alert cause and class trigger signals. +// + +module alert_handler_class import alert_pkg::*; ( + input [NAlerts-1:0] alert_trig_i, // alert trigger + input [N_LOC_ALERT-1:0] loc_alert_trig_i, // alert trigger + input [NAlerts-1:0] alert_en_i, // alert enable + input [N_LOC_ALERT-1:0] loc_alert_en_i, // alert enable + input [NAlerts-1:0] [CLASS_DW-1:0] alert_class_i, // class assignment + input [N_LOC_ALERT-1:0][CLASS_DW-1:0] loc_alert_class_i, // class assignment + + output logic [NAlerts-1:0] alert_cause_o, // alert cause + output logic [N_LOC_ALERT-1:0] loc_alert_cause_o, // alert cause + output logic [N_CLASSES-1:0] class_trig_o // class triggered +); + + // assign alert cause + assign alert_cause_o = alert_en_i & alert_trig_i; + assign loc_alert_cause_o = loc_alert_en_i & loc_alert_trig_i; + + // classification mapping + logic [N_CLASSES-1:0][NAlerts-1:0] class_masks; + logic [N_CLASSES-1:0][N_LOC_ALERT-1:0] loc_class_masks; + + // this is basically an address to onehot0 decoder + always_comb begin : p_class_mask + class_masks = '0; + loc_class_masks = '0; + for (int unsigned kk = 0; kk < NAlerts; kk++) begin + class_masks[alert_class_i[kk]][kk] = 1'b1; + end + for (int unsigned kk = 0; kk < N_LOC_ALERT; kk++) begin + loc_class_masks[loc_alert_class_i[kk]][kk] = 1'b1; + end + end + + // mask and OR reduction, followed by class enable gating + for (genvar k = 0; k < N_CLASSES; k++) begin : gen_classifier + assign class_trig_o[k] = (|{ alert_cause_o & class_masks[k], + loc_alert_cause_o & loc_class_masks[k] }); + end + +endmodule : alert_handler_class diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv new file mode 100644 index 0000000000000..cb7a51b88c23b --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv @@ -0,0 +1,433 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module implements the escalation timer, which times the four escalation +// phases. There are two mechanisms that can trigger the escalation protocol: +// +// 1) via accum_trigger_i, which will be asserted once the accumulator value +// exceeds a programmable amount of alert occurences. +// +// 2) via an interrupt timeout, if this is enabled. If this functionality is +// enabled, the internal escalation counter is reused to check whether the +// interrupt times out. If it does time out, the outcome is the same as if +// accum_trigger_i where asserted. +// +// Note that escalation always takes precedence over the interrupt timeout. +// + +`include "prim_assert.sv" + +module alert_handler_esc_timer import alert_pkg::*; ( + input clk_i, + input rst_ni, + input en_i, // enables timeout/escalation + input clr_i, // aborts escalation + input accu_trig_i, // this triggers escalation + input accu_fail_i, // this moves the FSM into a terminal error state + input timeout_en_i, // enables timeout + input [EscCntDw-1:0] timeout_cyc_i, // interrupt timeout. 0 = disabled + input [N_ESC_SEV-1:0] esc_en_i, // escalation signal enables + input [N_ESC_SEV-1:0] + [PHASE_DW-1:0] esc_map_i, // escalation signal / phase map + input [N_PHASES-1:0] + [EscCntDw-1:0] phase_cyc_i, // cycle counts of individual phases + input [PHASE_DW-1:0] crashdump_phase_i, // determines when to assert latch_crashdump_o + output logic latch_crashdump_o, // asserted when entering escalation + output logic esc_trig_o, // asserted if escalation triggers + output logic [EscCntDw-1:0] esc_cnt_o, // current timeout / escalation count + output logic [N_ESC_SEV-1:0] esc_sig_req_o, // escalation signal outputs + // current state output + // 000: idle, 001: irq timeout counting 100: phase0, 101: phase1, 110: phase2, 111: phase3 + output cstate_e esc_state_o +); + + //////////////////// + // Tandem Counter // + //////////////////// + + logic cnt_en, cnt_clr, cnt_ge; + logic [1:0][EscCntDw-1:0] cnt_q; + + // We employ two redundant counters to guard against FI attacks. + // If any of the two is glitched and the two counter states do not agree, + // the FSM below is moved into a terminal error state and escalation actions + // are permanently asserted. + for (genvar k = 0; k < 2; k++) begin : gen_double_cnt + + logic cnt_en_buf, cnt_clr_buf; + + // These size_only buffers are instantiated in order to prevent + // optimization / merging of the two counters. + prim_buf u_prim_buf_clr ( + .in_i(cnt_clr), + .out_o(cnt_clr_buf) + ); + + prim_buf u_prim_buf_en ( + .in_i(cnt_en), + .out_o(cnt_en_buf) + ); + + // escalation counter, used for all phases and the timeout + logic [EscCntDw-1:0] cnt_d; + assign cnt_d = (cnt_clr_buf && cnt_en_buf) ? EscCntDw'(1'b1) : + (cnt_clr_buf) ? '0 : + (cnt_en_buf) ? cnt_q[k] + 1'b1 : cnt_q[k]; + + prim_flop #( + .Width(EscCntDw) + ) u_prim_flop ( + .clk_i, + .rst_ni, + .d_i(cnt_d), + .q_o(cnt_q[k]) + ); + end + + // threshold test, the thresholds are muxed further below + // depending on the current state + logic [EscCntDw-1:0] thresh; + assign cnt_ge = (cnt_q[0] >= thresh); + + // current counter output + assign esc_cnt_o = cnt_q[0]; + + // consistency check + logic cnt_check_fail; + assign cnt_check_fail = cnt_q[0] != cnt_q[1]; + + ////////////// + // Main FSM // + ////////////// + + logic [N_PHASES-1:0] phase_oh; + + // Encoding generated with: + // $ ./util/design/sparse-fsm-encode.py -d 5 -m 8 -n 10 \ + // -s 784905746 --language=sv + // + // Hamming distance histogram: + // + // 0: -- + // 1: -- + // 2: -- + // 3: -- + // 4: -- + // 5: |||||||||||||||||||| (42.86%) + // 6: |||||||||||||||||||| (42.86%) + // 7: |||||| (14.29%) + // 8: -- + // 9: -- + // 10: -- + // + // Minimum Hamming distance: 5 + // Maximum Hamming distance: 7 + // Minimum Hamming weight: 2 + // Maximum Hamming weight: 7 + // + localparam int StateWidth = 10; + typedef enum logic [StateWidth-1:0] { + IdleSt = 10'b1101000111, + TimeoutSt = 10'b0010011110, + Phase0St = 10'b1111011001, + Phase1St = 10'b0001110100, + Phase2St = 10'b1110110010, + Phase3St = 10'b0010000001, + TerminalSt = 10'b0101101010, + FsmErrorSt = 10'b1000101101 + } state_e; + + logic fsm_error; + state_e state_d, state_q; + + always_comb begin : p_fsm + // default + state_d = state_q; + esc_state_o = Idle; + cnt_en = 1'b0; + cnt_clr = 1'b0; + esc_trig_o = 1'b0; + phase_oh = '0; + thresh = timeout_cyc_i; + fsm_error = 1'b0; + latch_crashdump_o = 1'b0; + + unique case (state_q) + // wait for an escalation trigger or an alert trigger + // the latter will trigger an interrupt timeout + IdleSt: begin + cnt_clr = 1'b1; + esc_state_o = Idle; + + if (accu_trig_i && en_i && !clr_i) begin + state_d = Phase0St; + cnt_en = 1'b1; + esc_trig_o = 1'b1; + // the counter is zero in this state. so if the + // timeout count is zero (==disabled), cnt_ge will be true. + end else if (timeout_en_i && !cnt_ge && en_i) begin + cnt_en = 1'b1; + state_d = TimeoutSt; + end + end + // we are in interrupt timeout state + // in case an escalation comes in, we immediately have to + // switch over to the first escalation phase. + // in case the interrupt timeout hits it's cycle count, we + // also enter escalation phase0. + // ongoing timeouts can always be cleared. + TimeoutSt: begin + esc_state_o = Timeout; + + if ((accu_trig_i && en_i && !clr_i) || (cnt_ge && timeout_en_i)) begin + state_d = Phase0St; + cnt_en = 1'b1; + cnt_clr = 1'b1; + esc_trig_o = 1'b1; + // the timeout enable is connected to the irq state + // if that is cleared, stop the timeout counter + end else if (timeout_en_i) begin + cnt_en = 1'b1; + end else begin + state_d = IdleSt; + cnt_clr = 1'b1; + end + end + // note: autolocking the clear signal is done in the regfile + Phase0St: begin + cnt_en = 1'b1; + phase_oh[0] = 1'b1; + thresh = phase_cyc_i[0]; + esc_state_o = Phase0; + latch_crashdump_o = (crashdump_phase_i == 2'b00); + + if (clr_i) begin + state_d = IdleSt; + cnt_clr = 1'b1; + cnt_en = 1'b0; + end else if (cnt_ge) begin + state_d = Phase1St; + cnt_clr = 1'b1; + cnt_en = 1'b1; + end + end + Phase1St: begin + cnt_en = 1'b1; + phase_oh[1] = 1'b1; + thresh = phase_cyc_i[1]; + esc_state_o = Phase1; + latch_crashdump_o = (crashdump_phase_i == 2'b01); + + if (clr_i) begin + state_d = IdleSt; + cnt_clr = 1'b1; + cnt_en = 1'b0; + end else if (cnt_ge) begin + state_d = Phase2St; + cnt_clr = 1'b1; + cnt_en = 1'b1; + end + end + Phase2St: begin + cnt_en = 1'b1; + phase_oh[2] = 1'b1; + thresh = phase_cyc_i[2]; + esc_state_o = Phase2; + latch_crashdump_o = (crashdump_phase_i == 2'b10); + + + if (clr_i) begin + state_d = IdleSt; + cnt_clr = 1'b1; + cnt_en = 1'b0; + end else if (cnt_ge) begin + state_d = Phase3St; + cnt_clr = 1'b1; + end + end + Phase3St: begin + cnt_en = 1'b1; + phase_oh[3] = 1'b1; + thresh = phase_cyc_i[3]; + esc_state_o = Phase3; + latch_crashdump_o = (crashdump_phase_i == 2'b11); + + if (clr_i) begin + state_d = IdleSt; + cnt_clr = 1'b1; + cnt_en = 1'b0; + end else if (cnt_ge) begin + state_d = TerminalSt; + cnt_clr = 1'b1; + cnt_en = 1'b0; + end + end + // final, terminal state after escalation. + // if clr is locked down, only a system reset + // will get us out of this state + TerminalSt: begin + cnt_clr = 1'b1; + esc_state_o = Terminal; + if (clr_i) begin + state_d = IdleSt; + end + end + // error state, only reached if the FSM has been + // glitched. in this state, we trigger all escalation + // actions at once. + FsmErrorSt: begin + esc_state_o = FsmError; + fsm_error = 1'b1; + end + // catch glitches. + default: begin + state_d = FsmErrorSt; + esc_state_o = FsmError; + end + endcase + + // if any of the duplicate counter pairs has an inconsistent state + // we move into the terminal FSM error state. + if (accu_fail_i || cnt_check_fail) begin + state_d = FsmErrorSt; + end + end + + logic [N_ESC_SEV-1:0][N_PHASES-1:0] esc_map_oh; + for (genvar k = 0; k < N_ESC_SEV; k++) begin : gen_phase_map + // generate configuration mask for escalation enable signals + assign esc_map_oh[k] = N_ESC_SEV'(esc_en_i[k]) << esc_map_i[k]; + // mask reduce current phase state vector + assign esc_sig_req_o[k] = |(esc_map_oh[k] & phase_oh) | fsm_error; + end + + /////////////////// + // FSM Registers // + /////////////////// + + // This primitive is used to place a size-only constraint on the + // flops in order to prevent FSM state encoding optimizations. + logic [StateWidth-1:0] state_raw_q; + assign state_q = state_e'(state_raw_q); + prim_flop #( + .Width(StateWidth), + .ResetValue(StateWidth'(IdleSt)) + ) u_state_regs ( + .clk_i, + .rst_ni, + .d_i ( state_d ), + .q_o ( state_raw_q ) + ); + + //////////////// + // Assertions // + //////////////// + + // a clear should always bring us back to idle + `ASSERT(CheckClr_A, + !accu_fail_i && + clr_i && + !(state_q inside {IdleSt, TimeoutSt, FsmErrorSt}) + |=> + state_q == IdleSt) + // if currently in idle and not enabled, must remain here + `ASSERT(CheckEn_A, + !accu_fail_i && + state_q == IdleSt && + !en_i + |=> + state_q == IdleSt) + // Check if accumulation trigger correctly captured + `ASSERT(CheckAccumTrig0_A, + !accu_fail_i && + accu_trig_i && + state_q == IdleSt && + en_i && + !clr_i + |=> + state_q == Phase0St) + `ASSERT(CheckAccumTrig1_A, + !accu_fail_i && + accu_trig_i && + state_q == TimeoutSt && + en_i && + !clr_i + |=> + state_q == Phase0St) + // Check if timeout correctly captured + `ASSERT(CheckTimeout0_A, + !accu_fail_i && + state_q == IdleSt && + timeout_en_i && + en_i && + timeout_cyc_i != 0 && + !accu_trig_i + |=> + state_q == TimeoutSt) + `ASSERT(CheckTimeoutSt1_A, + !accu_fail_i && + state_q == TimeoutSt && + timeout_en_i && + cnt_q[0] < timeout_cyc_i && + !accu_trig_i + |=> + state_q == TimeoutSt) + `ASSERT(CheckTimeoutSt2_A, + !accu_fail_i && + state_q == TimeoutSt && + !timeout_en_i && + !accu_trig_i + |=> + state_q == IdleSt) + // Check if timeout correctly triggers escalation + `ASSERT(CheckTimeoutStTrig_A, + !accu_fail_i && + state_q == TimeoutSt && + timeout_en_i && + cnt_q[0] == timeout_cyc_i + |=> + state_q == Phase0St) + // Check whether escalation phases are correctly switched + `ASSERT(CheckPhase0_A, + !accu_fail_i && + state_q == Phase0St && + !clr_i && + cnt_q[0] >= phase_cyc_i[0] + |=> + state_q == Phase1St) + `ASSERT(CheckPhase1_A, + !accu_fail_i && + state_q == Phase1St && + !clr_i && + cnt_q[0] >= phase_cyc_i[1] + |=> + state_q == Phase2St) + `ASSERT(CheckPhase2_A, + !accu_fail_i && + state_q == Phase2St && + !clr_i && + cnt_q[0] >= phase_cyc_i[2] + |=> + state_q == Phase3St) + `ASSERT(CheckPhase3_A, + !accu_fail_i && + state_q == Phase3St && + !clr_i && + cnt_q[0] >= phase_cyc_i[3] + |=> + state_q == TerminalSt) + `ASSERT(AccuFailToFsmError_A, + accu_fail_i + |=> + state_q == FsmErrorSt) + `ASSERT(ErrorStIsTerminal_A, + state_q == FsmErrorSt + |=> + state_q == FsmErrorSt) + `ASSERT(ErrorStAllEscAsserted_A, + state_q == FsmErrorSt + |-> + esc_sig_req_o == '1) + +endmodule : alert_handler_esc_timer diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_lp_ctrl.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_lp_ctrl.sv new file mode 100644 index 0000000000000..fc4f0a77f29b5 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_lp_ctrl.sv @@ -0,0 +1,80 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module gathers and synchronizes the clock gating and reset indication signals for all +// low-power groups (LPGs), synchronizes them to the alert handler clock domain. +// The clock gating and reset indication signals are then logically OR'ed to produce one multibit +// value for each LPG. The LPG multibit values are then mapped to the alert channels using +// the AlertLpgMap parameter, and each multibit output value is buffered independently. +// + +`include "prim_assert.sv" + +module alert_handler_lp_ctrl import alert_pkg::*; ( + input clk_i, + input rst_ni, + // Low power clk and rst indication signals. + input lc_ctrl_pkg::lc_tx_t [NLpg-1:0] lpg_cg_en_i, + input lc_ctrl_pkg::lc_tx_t [NLpg-1:0] lpg_rst_en_i, + // Init requests going to the individual alert channels. + output lc_ctrl_pkg::lc_tx_t [NAlerts-1:0] alert_init_trig_o +); + + /////////////////////////////////////////////////// + // Aggregate multibit indication signals per LPG // + /////////////////////////////////////////////////// + + lc_ctrl_pkg::lc_tx_t [NLpg-1:0] lpg_init_trig; + for (genvar k = 0; k < NLpg; k++) begin : gen_lpgs + + lc_ctrl_pkg::lc_tx_t [0:0] lpg_cg_en; + prim_lc_sync #( + .ResetValueIsOn(1) + ) u_prim_lc_sync_cg_en ( + .clk_i, + .rst_ni, + .lc_en_i(lpg_cg_en_i[k]), + .lc_en_o(lpg_cg_en) + ); + lc_ctrl_pkg::lc_tx_t [0:0] lpg_rst_en; + prim_lc_sync #( + .ResetValueIsOn(1) + ) u_prim_lc_sync_rst_en ( + .clk_i, + .rst_ni, + .lc_en_i(lpg_rst_en_i[k]), + .lc_en_o(lpg_rst_en) + ); + + // Perform a logical OR operation of the multibit life cycle signals. + // I.e., if any of the incoming multibit signals is On, the output will also be On. + // Otherwise, the output may have any value other than On. + prim_lc_combine #( + .ActiveLow(0), // Active Value is "On" + .CombineMode(0) // Combo mode is "OR" + ) u_prim_lc_combine ( + .lc_en_a_i(lpg_cg_en[0]), + .lc_en_b_i(lpg_rst_en[0]), + .lc_en_o (lpg_init_trig[k]) + ); + end + + ////////////////////////////////// + // LPG to Alert Channel Mapping // + ////////////////////////////////// + + // select the correct lpg for the alert channel at index j and buffer the multibit signal for each + // alert channel. + for (genvar j=0; j < NAlerts; j++) begin : gen_alert_map + prim_lc_sync #( + .AsyncOn(0) // no sync flops + ) u_prim_lc_sync_lpg_en ( + .clk_i, + .rst_ni, + .lc_en_i(lpg_init_trig[LpgMap[j]]), + .lc_en_o({alert_init_trig_o[j]}) + ); + end + +endmodule : alert_handler_lp_ctrl diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_lpg_ctrl.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_lpg_ctrl.sv new file mode 100644 index 0000000000000..159451b6a56b1 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_lpg_ctrl.sv @@ -0,0 +1,74 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module gathers and synchronizes the clock gating and reset indication signals for all +// low-power groups (LPGs), synchronizes them to the alert handler clock domain. The clock gating +// and reset indication signals are then logically OR'ed to produce one multibit value for each +// LPG. The LPG multibit values are then mapped to the alert channels using the LpgMap parameter, +// and each multibit output value is buffered independently. +// + +`include "prim_assert.sv" + +module alert_handler_lpg_ctrl import alert_pkg::*; ( + input clk_i, + input rst_ni, + // Low power clk and rst indication signals. + input prim_mubi_pkg::mubi4_t [NLpg-1:0] lpg_cg_en_i, + input prim_mubi_pkg::mubi4_t [NLpg-1:0] lpg_rst_en_i, + // Init requests going to the individual alert channels. + output prim_mubi_pkg::mubi4_t [NAlerts-1:0] alert_init_trig_o +); + + import prim_mubi_pkg::mubi4_t; + import prim_mubi_pkg::mubi4_or_hi; + import prim_mubi_pkg::MuBi4True; + + /////////////////////////////////////////////////// + // Aggregate multibit indication signals per LPG // + /////////////////////////////////////////////////// + + mubi4_t [NLpg-1:0] synced_lpg_cg_en, synced_lpg_rst_en, lpg_init_trig; + for (genvar k = 0; k < NLpg; k++) begin : gen_lpgs + prim_mubi4_sync #( + .ResetValue(MuBi4True) + ) u_prim_mubi4_sync_cg_en ( + .clk_i, + .rst_ni, + .mubi_i(lpg_cg_en_i[k]), + .mubi_o(synced_lpg_cg_en[k:k]) + ); + prim_mubi4_sync #( + .ResetValue(MuBi4True) + ) u_prim_mubi4_sync_rst_en ( + .clk_i, + .rst_ni, + .mubi_i(lpg_rst_en_i[k]), + .mubi_o(synced_lpg_rst_en[k:k]) + ); + + // Perform a logical OR operation of the multibit life cycle signals. + // I.e., if any of the incoming multibit signals is On, the output will also be On. + // Otherwise, the output may have any value other than On. + assign lpg_init_trig[k] = mubi4_or_hi(synced_lpg_cg_en[k], synced_lpg_rst_en[k]); + end + + ////////////////////////////////// + // LPG to Alert Channel Mapping // + ////////////////////////////////// + + // select the correct lpg for the alert channel at index j and buffer the multibit signal for each + // alert channel. + for (genvar j=0; j < NAlerts; j++) begin : gen_alert_map + prim_mubi4_sync #( + .AsyncOn(0) // no sync flops + ) u_prim_mubi4_sync_lpg_en ( + .clk_i, + .rst_ni, + .mubi_i(lpg_init_trig[LpgMap[j]]), + .mubi_o({alert_init_trig_o[j]}) + ); + end + +endmodule : alert_handler_lpg_ctrl diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv new file mode 100644 index 0000000000000..ee7b757e5b110 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv @@ -0,0 +1,417 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module implements the ping mechanism. Once enabled, this module uses an +// LFSR-based PRNG to +// +// a) determine the next peripheral index to be pinged (can be an alert receiver or an +// escalation sender). it it is detected that this particular peripheral is disabled, +// another index will be drawn from the PRNG. +// +// b) determine the amount of pause cycles to wait before pinging the peripheral selected in a). +// +// Once the ping timer waited for the amount of pause cycles determined in b), it asserts +// the ping enable signal of the peripheral determined in a). If that peripheral does +// not respond within the ping timeout window, an internal alert will be raised. +// +// Further, if a spurious ping_ok signal is detected (i.e., a ping ok that has not been +// requested), the ping timer will also raise an internal alert. +// + +`include "prim_assert.sv" + +module alert_handler_ping_timer import alert_pkg::*; #( + // Compile time random constants, to be overriden by topgen. + parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, + parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, + // Enable this for DV, disable this for long LFSRs in FPV + parameter bit MaxLenSVA = 1'b1, + // Can be disabled in cases where entropy + // inputs are unused in order to not distort coverage + // (the SVA will be unreachable in such cases) + parameter bit LockupSVA = 1'b1 +) ( + input clk_i, + input rst_ni, + output logic edn_req_o, // request to EDN + input edn_ack_i, // ack from EDN + input [LfsrWidth-1:0] edn_data_i, // from EDN + input en_i, // enable ping testing + input [NAlerts-1:0] alert_ping_en_i, // determines which alerts to ping + input [PING_CNT_DW-1:0] ping_timeout_cyc_i, // timeout in cycles + input [PING_CNT_DW-1:0] wait_cyc_mask_i, // mask to shorten the counters in DV / FPV + output logic [NAlerts-1:0] alert_ping_req_o, // request to alert receivers + output logic [N_ESC_SEV-1:0] esc_ping_req_o, // enable to esc senders + input [NAlerts-1:0] alert_ping_ok_i, // response from alert receivers + input [N_ESC_SEV-1:0] esc_ping_ok_i, // response from esc senders + output logic alert_ping_fail_o, // any of the alert receivers failed + output logic esc_ping_fail_o // any of the esc senders failed +); + + localparam int unsigned IdDw = $clog2(NAlerts); + + // Entropy reseeding is triggered every time this counter expires. + // The expected wait time between pings is 2**(PING_CNT_DW-1) on average. + // We do not need to reseed the LFSR very often, and the constant below is chosen + // such that on average the LFSR is reseeded every 16th ping. + localparam int unsigned ReseedLfsrExtraBits = 3; + localparam int unsigned ReseedLfsrWidth = PING_CNT_DW + ReseedLfsrExtraBits; + + //////////////////// + // Reseed counter // + //////////////////// + + logic reseed_en; + logic [ReseedLfsrWidth-1:0] reseed_timer_d, reseed_timer_q; + + assign reseed_timer_d = (reseed_timer_q > '0) ? reseed_timer_q - 1'b1 : + (reseed_en) ? {wait_cyc_mask_i, + {ReseedLfsrExtraBits{1'b1}}} : '0; + assign edn_req_o = (reseed_timer_q == '0); + assign reseed_en = edn_req_o & edn_ack_i; + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs + if (!rst_ni) begin + reseed_timer_q <= '0; + end else begin + reseed_timer_q <= reseed_timer_d; + end + end + + /////////////////////////// + // Tandem LFSR Instances // + /////////////////////////// + + logic lfsr_en, lfsr_en_unbuf; + logic [LfsrWidth-1:0] entropy_unbuf; + logic [1:0][LfsrWidth-1:0] lfsr_state; + + assign lfsr_en_unbuf = reseed_en | lfsr_en; + assign entropy_unbuf = (reseed_en) ? edn_data_i[LfsrWidth-1:0] : '0; + + // We employ two redundant LFSRs to guard against FI attacks. + // If any of the two is glitched and the two LFSR states do not agree, + // the FSM below is moved into a terminal error state and all ping alerts + // are permanently asserted. + for (genvar k = 0; k < 2; k++) begin : gen_double_lfsr + // Instantiate size_only buffers to prevent + // optimization / merging of redundant logic. + logic lfsr_en_buf; + logic [LfsrWidth-1:0] entropy_buf, lfsr_state_unbuf; + prim_buf #( + .Width(LfsrWidth) + ) u_prim_buf_entropy ( + .in_i(entropy_unbuf), + .out_o(entropy_buf) + ); + + prim_buf u_prim_buf_lfsr_en ( + .in_i(lfsr_en_unbuf), + .out_o(lfsr_en_buf) + ); + + prim_buf #( + .Width(LfsrWidth) + ) u_prim_buf_state ( + .in_i(lfsr_state_unbuf), + .out_o(lfsr_state[k]) + ); + + prim_lfsr #( + .LfsrDw ( LfsrWidth ), + .EntropyDw ( LfsrWidth ), + .StateOutDw ( LfsrWidth ), + .DefaultSeed ( RndCnstLfsrSeed ), + .StatePermEn ( 1'b1 ), + .StatePerm ( RndCnstLfsrPerm ), + .MaxLenSVA ( MaxLenSVA ), + .LockupSVA ( LockupSVA ), + .ExtSeedSVA ( 1'b0 ) // ext seed is unused + ) u_prim_lfsr ( + .clk_i, + .rst_ni, + .seed_en_i ( 1'b0 ), + .seed_i ( '0 ), + .lfsr_en_i ( lfsr_en_buf ), + .entropy_i ( entropy_buf ), + .state_o ( lfsr_state_unbuf ) + ); + end + + logic [IdDw-1:0] id_to_ping; + assign id_to_ping = lfsr_state[0][PING_CNT_DW +: IdDw]; + + // align the enable mask with powers of two for the indexing operation below. + logic [2**IdDw-1:0] enable_mask; + assign enable_mask = (2**IdDw)'(alert_ping_en_i); + + // check if the randomly drawn alert ID is actually valid and the alert is enabled + logic id_vld; + assign id_vld = enable_mask[id_to_ping]; + + ////////////////////////////////// + // Escalation Counter Instances // + ////////////////////////////////// + + // As opposed to the alert ID, the escalation sender ID to be pinged is not drawn at random. + // Rather, we cycle through the escalation senders one by one in a deterministic fashion. + // This allows us to provide guarantees needed for the ping timeout / auto escalation feature + // implemented at the escalation receiver side. + // + // In particular, with N_ESC_SEV escalation senders in the design, we can guarantee + // that each escalation channel will be pinged at least once every + // + // N_ESC_SEV x (NUM_WAIT_COUNT + NUM_TIMEOUT_COUNT) x 2**PING_CNT_DW + // + // cycles - independently of the reseeding operation. + // + // - N_ESC_SEV: # escalation channels to ping. + // - NUM_WAIT_COUNT: # wait counts between subsequent escalation channel pings. + // - NUM_TIMEOUT_COUNT: # timeout counts between subsequent escalation channel pings. + // - 2**PING_CNT_DW: # maximum counter value. + // + // This guarantee is used inside the escalation receivers to monitor the pings sent out by the + // alert handler. I.e., once the alert handler has started to send out pings, each escalation + // receiver employs a timeout window within which it expects the next ping to arrive. If + // escalation pings cease to arrive at an escalation receiver for any reason, this will + // automatically trigger the associated escalation countermeasure. + // + // In order to have enough margin, the escalation receiver timeout counters use a threshold that + // is 4x higher than the value calculated above. With N_ESC_SEV = 4, PING_CNT_DW = 16 and + // NUM_WAIT_COUNT = NUM_TIMEOUT_COUNT = 2 this amounts to a 22bit timeout threshold. + + logic esc_cnt_en; + logic [1:0][PING_CNT_DW-1:0] esc_cnt_q; + + // We employ two redundant counters to guard against FI attacks. + // If any of the two is glitched and the two counter states do not agree, + // the FSM below is moved into a terminal error state and all ping alerts + // are permanently asserted. + for (genvar k = 0; k < 2; k++) begin : gen_double_esc_cnt + + logic [PING_CNT_DW-1:0] esc_cnt_d; + assign esc_cnt_d = (esc_cnt_q[k] >= PING_CNT_DW'(N_ESC_SEV-1)) ? '0 : (esc_cnt_q[k] + 1'b1); + + prim_flop_en #( + .Width(PING_CNT_DW) + ) u_prim_flop_en ( + .clk_i, + .rst_ni, + .en_i ( esc_cnt_en ), + .d_i ( esc_cnt_d ), + .q_o ( esc_cnt_q[k] ) + ); + end + + ///////////////////////////// + // Timer Counter Instances // + ///////////////////////////// + + logic [1:0][PING_CNT_DW-1:0] cnt_q; + logic wait_cnt_load, timeout_cnt_load, timer_expired; + assign timer_expired = (cnt_q[0] == '0); + assign lfsr_en = wait_cnt_load || timeout_cnt_load; + + // We employ two redundant counters to guard against FI attacks. + // If any of the two is glitched and the two counter states do not agree, + // the FSM below is moved into a terminal error state and all ping alerts + // are permanently asserted. + for (genvar k = 0; k < 2; k++) begin : gen_double_cnt + + // the constant offset ensures a minimum cycle spacing between pings. + logic [PING_CNT_DW-1:0] wait_cyc; + assign wait_cyc = (lfsr_state[k][PING_CNT_DW-1:0] | PING_CNT_DW'(3'b100)); + + // note that the masks are used for DV/FPV only in order to reduce the state space. + logic [PING_CNT_DW-1:0] cnt_d; + assign cnt_d = (wait_cnt_load) ? (wait_cyc & wait_cyc_mask_i) : + (timeout_cnt_load) ? (ping_timeout_cyc_i) : + (cnt_q[k] > '0) ? cnt_q[k] - 1'b1 : '0; + + prim_flop #( + .Width(PING_CNT_DW) + ) u_prim_flop ( + .clk_i, + .rst_ni, + .d_i ( cnt_d ), + .q_o ( cnt_q[k] ) + ); + end + + //////////////////////////// + // Ping and Timeout Logic // + //////////////////////////// + + logic alert_ping_en, esc_ping_en; + logic spurious_alert_ping, spurious_esc_ping; + + // generate ping enable vector + assign alert_ping_req_o = NAlerts'(alert_ping_en) << id_to_ping; + assign esc_ping_req_o = N_ESC_SEV'(esc_ping_en) << esc_cnt_q[0]; + + // under normal operation, these signals should never be asserted. + // we place hand instantiated buffers here such that these signals are not + // optimized away during synthesis (these buffers will receive a keep or size_only + // attribute in our Vivado and DC synthesis flows). + prim_buf u_prim_buf_spurious_alert_ping ( + .in_i(|(alert_ping_ok_i & ~alert_ping_req_o)), + .out_o(spurious_alert_ping) + ); + prim_buf u_prim_buf_spurious_esc_ping ( + .in_i(|(esc_ping_ok_i & ~esc_ping_req_o)), + .out_o(spurious_esc_ping) + ); + + // Encoding generated with: + // $ ./util/design/sparse-fsm-encode.py -d 5 -m 6 -n 9 \ + // -s 728582219 --language=sv + // + // Hamming distance histogram: + // + // 0: -- + // 1: -- + // 2: -- + // 3: -- + // 4: -- + // 5: |||||||||||||||||||| (60.00%) + // 6: ||||||||||||| (40.00%) + // 7: -- + // 8: -- + // 9: -- + // + // Minimum Hamming distance: 5 + // Maximum Hamming distance: 6 + // Minimum Hamming weight: 2 + // Maximum Hamming weight: 6 + // + localparam int StateWidth = 9; + typedef enum logic [StateWidth-1:0] { + InitSt = 9'b000101100, + AlertWaitSt = 9'b011001011, + AlertPingSt = 9'b110000000, + EscWaitSt = 9'b101110001, + EscPingSt = 9'b011110110, + FsmErrorSt = 9'b100011111 + } state_e; + + state_e state_d, state_q; + + always_comb begin : p_fsm + // default + state_d = state_q; + wait_cnt_load = 1'b0; + timeout_cnt_load = 1'b0; + esc_cnt_en = 1'b0; + alert_ping_en = 1'b0; + esc_ping_en = 1'b0; + // this captures spurious ping responses + alert_ping_fail_o = spurious_alert_ping; + esc_ping_fail_o = spurious_esc_ping; + + unique case (state_q) + // wait until activated + // we never return to this state + // once activated! + InitSt: begin + if (en_i) begin + state_d = AlertWaitSt; + wait_cnt_load = 1'b1; + end + end + // wait for random amount of cycles + AlertWaitSt: begin + if (timer_expired) begin + state_d = AlertPingSt; + timeout_cnt_load = 1'b1; + end + end + // send out an alert ping request and wait for a ping + // response or a ping timeout (whatever comes first). + // if the alert ID is not valid, we drop the request and + // proceed to the next ping. + AlertPingSt: begin + alert_ping_en = id_vld; + if (timer_expired || |(alert_ping_ok_i & alert_ping_req_o) || !id_vld) begin + state_d = EscWaitSt; + wait_cnt_load = 1'b1; + if (timer_expired) begin + alert_ping_fail_o = 1'b1; + end + end + end + // wait for random amount of cycles + EscWaitSt: begin + if (timer_expired) begin + state_d = EscPingSt; + timeout_cnt_load = 1'b1; + end + end + // send out an escalation ping request and wait for a ping + // response or a ping timeout (whatever comes first) + EscPingSt: begin + esc_ping_en = 1'b1; + if (timer_expired || |(esc_ping_ok_i & esc_ping_req_o)) begin + state_d = AlertWaitSt; + wait_cnt_load = 1'b1; + esc_cnt_en = 1'b1; + if (timer_expired) begin + esc_ping_fail_o = 1'b1; + end + end + end + // terminal FSM error state. + // if we for some reason end up in this state (e.g. malicious glitching) + // we are going to assert both ping fails continuously + FsmErrorSt: begin + alert_ping_fail_o = 1'b1; + esc_ping_fail_o = 1'b1; + end + default: begin + state_d = FsmErrorSt; + end + endcase + + // if the two LFSR or counter states do not agree, + // we move into the terminal state. + if (lfsr_state[0] != lfsr_state[1] || + cnt_q[0] != cnt_q[1] || + esc_cnt_q[0] != esc_cnt_q[1]) begin + state_d = FsmErrorSt; + end + end + + /////////////////// + // FSM Registers // + /////////////////// + + // This primitive is used to place a size-only constraint on the + // flops in order to prevent FSM state encoding optimizations. + logic [StateWidth-1:0] state_raw_q; + assign state_q = state_e'(state_raw_q); + + prim_flop #( + .Width(StateWidth), + .ResetValue(StateWidth'(InitSt)) + ) u_state_regs ( + .clk_i, + .rst_ni, + .d_i ( state_d ), + .q_o ( state_raw_q ) + ); + + //////////////// + // Assertions // + //////////////// + + // make sure the ID width is within bounds. + `ASSERT_INIT(MaxIdDw_A, IdDw <= (LfsrWidth - PING_CNT_DW)) + + // only one module is pinged at a time. + `ASSERT(PingOH0_A, $onehot0({alert_ping_req_o, esc_ping_req_o})) + + // we should never get into the ping state without knowing which module to ping. + `ASSERT(AlertPingOH_A, alert_ping_en |-> $onehot(alert_ping_req_o)) + `ASSERT(EscPingOH_A, esc_ping_en |-> $onehot(esc_ping_req_o)) + +endmodule : alert_handler_ping_timer diff --git a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_pkg.sv similarity index 100% rename from hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv rename to hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_pkg.sv diff --git a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_top.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_top.sv similarity index 100% rename from hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_top.sv rename to hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_top.sv diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_wrap.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_wrap.sv new file mode 100644 index 0000000000000..517695e01a0b2 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_reg_wrap.sv @@ -0,0 +1,574 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Breakout / remapping wrapper for register file. + +module alert_handler_reg_wrap import alert_pkg::*; ( + input clk_i, + input rst_ni, + input rst_shadowed_ni, + // Bus Interface (device) + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, + // interrupt + output logic [N_CLASSES-1:0] irq_o, + // State information for HW crashdump + input latch_crashdump_i, + output alert_crashdump_t crashdump_o, + // hw2reg + input hw2reg_wrap_t hw2reg_wrap, + // reg2hw + output reg2hw_wrap_t reg2hw_wrap, + // bus integrity alert + output logic fatal_integ_alert_o +); + + + ////////////////// + // reg instance // + ////////////////// + + logic [N_CLASSES-1:0] class_autolock_en; + alert_handler_reg_pkg::alert_handler_reg2hw_t reg2hw; + alert_handler_reg_pkg::alert_handler_hw2reg_t hw2reg; + + alert_handler_reg_top u_reg ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .tl_i, + .tl_o, + .reg2hw, + .hw2reg, + .intg_err_o(fatal_integ_alert_o), + .devmode_i(1'b1) + ); + + //////////////// + // interrupts // + //////////////// + + prim_intr_hw #( + .Width(1) + ) u_irq_classa ( + .clk_i, + .rst_ni, + .event_intr_i ( hw2reg_wrap.class_trig[0] ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.classa.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.classa.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.classa.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.classa.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.classa.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.classa.d ), + .intr_o ( irq_o[0] ) + ); + + prim_intr_hw #( + .Width(1) + ) u_irq_classb ( + .clk_i, + .rst_ni, + .event_intr_i ( hw2reg_wrap.class_trig[1] ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.classb.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.classb.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.classb.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.classb.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.classb.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.classb.d ), + .intr_o ( irq_o[1] ) + ); + + prim_intr_hw #( + .Width(1) + ) u_irq_classc ( + .clk_i, + .rst_ni, + .event_intr_i ( hw2reg_wrap.class_trig[2] ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.classc.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.classc.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.classc.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.classc.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.classc.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.classc.d ), + .intr_o ( irq_o[2] ) + ); + + prim_intr_hw #( + .Width(1) + ) u_irq_classd ( + .clk_i, + .rst_ni, + .event_intr_i ( hw2reg_wrap.class_trig[3] ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.classd.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.classd.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.classd.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.classd.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.classd.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.classd.d ), + .intr_o ( irq_o[3] ) + ); + + ///////////////////// + // hw2reg mappings // + ///////////////////// + + // if an alert is enabled and it fires, + // we have to set the corresponding cause bit + for (genvar k = 0; k < NAlerts; k++) begin : gen_alert_cause + assign hw2reg.alert_cause[k].d = 1'b1; + assign hw2reg.alert_cause[k].de = reg2hw.alert_cause[k].q | + hw2reg_wrap.alert_cause[k]; + end + + // if a local alert is enabled and it fires, + // we have to set the corresponding cause bit + for (genvar k = 0; k < N_LOC_ALERT; k++) begin : gen_loc_alert_cause + assign hw2reg.loc_alert_cause[k].d = 1'b1; + assign hw2reg.loc_alert_cause[k].de = reg2hw.loc_alert_cause[k].q | + hw2reg_wrap.loc_alert_cause[k]; + end + + // ping timeout in cycles + // autolock can clear these regs automatically upon entering escalation + // note: the class must be activated for this to occur + assign { hw2reg.classd_clr_regwen.d, + hw2reg.classc_clr_regwen.d, + hw2reg.classb_clr_regwen.d, + hw2reg.classa_clr_regwen.d } = '0; + + assign { hw2reg.classd_clr_regwen.de, + hw2reg.classc_clr_regwen.de, + hw2reg.classb_clr_regwen.de, + hw2reg.classa_clr_regwen.de } = hw2reg_wrap.class_esc_trig & + class_autolock_en & + reg2hw_wrap.class_en; + + // current accumulator counts + assign { hw2reg.classd_accum_cnt.d, + hw2reg.classc_accum_cnt.d, + hw2reg.classb_accum_cnt.d, + hw2reg.classa_accum_cnt.d } = hw2reg_wrap.class_accum_cnt; + + // current accumulator counts + assign { hw2reg.classd_esc_cnt.d, + hw2reg.classc_esc_cnt.d, + hw2reg.classb_esc_cnt.d, + hw2reg.classa_esc_cnt.d } = hw2reg_wrap.class_esc_cnt; + + // current accumulator counts + assign { hw2reg.classd_state.d, + hw2reg.classc_state.d, + hw2reg.classb_state.d, + hw2reg.classa_state.d } = hw2reg_wrap.class_esc_state; + + ///////////////////// + // reg2hw mappings // + ///////////////////// + + // config register lock + assign reg2hw_wrap.ping_enable = reg2hw.ping_timer_en_shadowed.q; + + // alert enable and class assignments + for (genvar k = 0; k < NAlerts; k++) begin : gen_alert_en_class + // we only ping enabled alerts that are locked + assign reg2hw_wrap.alert_ping_en[k] = reg2hw.alert_en_shadowed[k].q & + reg2hw.alert_regwen[k].q; + assign reg2hw_wrap.alert_en[k] = reg2hw.alert_en_shadowed[k].q; + assign reg2hw_wrap.alert_class[k] = reg2hw.alert_class_shadowed[k].q; + end + + // local alert enable and class assignments + for (genvar k = 0; k < N_LOC_ALERT; k++) begin : gen_loc_alert_en_class + assign reg2hw_wrap.loc_alert_en[k] = reg2hw.loc_alert_en_shadowed[k].q; + assign reg2hw_wrap.loc_alert_class[k] = reg2hw.loc_alert_class_shadowed[k].q; + end + + assign reg2hw_wrap.ping_timeout_cyc = reg2hw.ping_timeout_cyc_shadowed.q; + + // class enable + // we require that at least one of the enable signals is + // set for a class to be enabled + assign reg2hw_wrap.class_en = { + reg2hw.classd_ctrl_shadowed.en.q & ( reg2hw.classd_ctrl_shadowed.en_e3.q | + reg2hw.classd_ctrl_shadowed.en_e2.q | + reg2hw.classd_ctrl_shadowed.en_e1.q | + reg2hw.classd_ctrl_shadowed.en_e0.q ), + // + reg2hw.classc_ctrl_shadowed.en.q & ( reg2hw.classc_ctrl_shadowed.en_e3.q | + reg2hw.classc_ctrl_shadowed.en_e2.q | + reg2hw.classc_ctrl_shadowed.en_e1.q | + reg2hw.classc_ctrl_shadowed.en_e0.q ), + // + reg2hw.classb_ctrl_shadowed.en.q & ( reg2hw.classb_ctrl_shadowed.en_e3.q | + reg2hw.classb_ctrl_shadowed.en_e2.q | + reg2hw.classb_ctrl_shadowed.en_e1.q | + reg2hw.classb_ctrl_shadowed.en_e0.q ), + // + reg2hw.classa_ctrl_shadowed.en.q & ( reg2hw.classa_ctrl_shadowed.en_e3.q | + reg2hw.classa_ctrl_shadowed.en_e2.q | + reg2hw.classa_ctrl_shadowed.en_e1.q | + reg2hw.classa_ctrl_shadowed.en_e0.q ) + }; + + + // autolock enable + assign class_autolock_en = { reg2hw.classd_ctrl_shadowed.lock.q, + reg2hw.classc_ctrl_shadowed.lock.q, + reg2hw.classb_ctrl_shadowed.lock.q, + reg2hw.classa_ctrl_shadowed.lock.q }; + + // escalation signal enable + assign reg2hw_wrap.class_esc_en = { reg2hw.classd_ctrl_shadowed.en_e3.q, + reg2hw.classd_ctrl_shadowed.en_e2.q, + reg2hw.classd_ctrl_shadowed.en_e1.q, + reg2hw.classd_ctrl_shadowed.en_e0.q, + // + reg2hw.classc_ctrl_shadowed.en_e3.q, + reg2hw.classc_ctrl_shadowed.en_e2.q, + reg2hw.classc_ctrl_shadowed.en_e1.q, + reg2hw.classc_ctrl_shadowed.en_e0.q, + // + reg2hw.classb_ctrl_shadowed.en_e3.q, + reg2hw.classb_ctrl_shadowed.en_e2.q, + reg2hw.classb_ctrl_shadowed.en_e1.q, + reg2hw.classb_ctrl_shadowed.en_e0.q, + // + reg2hw.classa_ctrl_shadowed.en_e3.q, + reg2hw.classa_ctrl_shadowed.en_e2.q, + reg2hw.classa_ctrl_shadowed.en_e1.q, + reg2hw.classa_ctrl_shadowed.en_e0.q }; + + + // escalation phase to escalation signal mapping + assign reg2hw_wrap.class_esc_map = { reg2hw.classd_ctrl_shadowed.map_e3.q, + reg2hw.classd_ctrl_shadowed.map_e2.q, + reg2hw.classd_ctrl_shadowed.map_e1.q, + reg2hw.classd_ctrl_shadowed.map_e0.q, + // + reg2hw.classc_ctrl_shadowed.map_e3.q, + reg2hw.classc_ctrl_shadowed.map_e2.q, + reg2hw.classc_ctrl_shadowed.map_e1.q, + reg2hw.classc_ctrl_shadowed.map_e0.q, + // + reg2hw.classb_ctrl_shadowed.map_e3.q, + reg2hw.classb_ctrl_shadowed.map_e2.q, + reg2hw.classb_ctrl_shadowed.map_e1.q, + reg2hw.classb_ctrl_shadowed.map_e0.q, + // + reg2hw.classa_ctrl_shadowed.map_e3.q, + reg2hw.classa_ctrl_shadowed.map_e2.q, + reg2hw.classa_ctrl_shadowed.map_e1.q, + reg2hw.classa_ctrl_shadowed.map_e0.q }; + + // Determines in which phase to latch the crashdump. + assign reg2hw_wrap.class_crashdump_phase = { reg2hw.classd_crashdump_trigger_shadowed.q, + reg2hw.classc_crashdump_trigger_shadowed.q, + reg2hw.classb_crashdump_trigger_shadowed.q, + reg2hw.classa_crashdump_trigger_shadowed.q }; + + // writing 1b1 to a class clr register clears the accumulator and + // escalation state if autolock is not asserted + assign reg2hw_wrap.class_clr = { reg2hw.classd_clr_shadowed.q & reg2hw.classd_clr_shadowed.qe, + reg2hw.classc_clr_shadowed.q & reg2hw.classc_clr_shadowed.qe, + reg2hw.classb_clr_shadowed.q & reg2hw.classb_clr_shadowed.qe, + reg2hw.classa_clr_shadowed.q & reg2hw.classa_clr_shadowed.qe }; + + + // accumulator thresholds + assign reg2hw_wrap.class_accum_thresh = { reg2hw.classd_accum_thresh_shadowed.q, + reg2hw.classc_accum_thresh_shadowed.q, + reg2hw.classb_accum_thresh_shadowed.q, + reg2hw.classa_accum_thresh_shadowed.q }; + + // interrupt timeout lengths + assign reg2hw_wrap.class_timeout_cyc = { reg2hw.classd_timeout_cyc_shadowed.q, + reg2hw.classc_timeout_cyc_shadowed.q, + reg2hw.classb_timeout_cyc_shadowed.q, + reg2hw.classa_timeout_cyc_shadowed.q }; + // escalation phase lengths + assign reg2hw_wrap.class_phase_cyc = { reg2hw.classd_phase3_cyc_shadowed.q, + reg2hw.classd_phase2_cyc_shadowed.q, + reg2hw.classd_phase1_cyc_shadowed.q, + reg2hw.classd_phase0_cyc_shadowed.q, + // + reg2hw.classc_phase3_cyc_shadowed.q, + reg2hw.classc_phase2_cyc_shadowed.q, + reg2hw.classc_phase1_cyc_shadowed.q, + reg2hw.classc_phase0_cyc_shadowed.q, + // + reg2hw.classb_phase3_cyc_shadowed.q, + reg2hw.classb_phase2_cyc_shadowed.q, + reg2hw.classb_phase1_cyc_shadowed.q, + reg2hw.classb_phase0_cyc_shadowed.q, + // + reg2hw.classa_phase3_cyc_shadowed.q, + reg2hw.classa_phase2_cyc_shadowed.q, + reg2hw.classa_phase1_cyc_shadowed.q, + reg2hw.classa_phase0_cyc_shadowed.q}; + + ////////////////////// + // crashdump output // + ////////////////////// + + logic crashump_latched_q; + alert_crashdump_t crashdump_d, crashdump_q; + + // alert cause output + for (genvar k = 0; k < NAlerts; k++) begin : gen_alert_cause_dump + assign crashdump_d.alert_cause[k] = reg2hw.alert_cause[k].q; + end + + // local alert cause register output + for (genvar k = 0; k < N_LOC_ALERT; k++) begin : gen_loc_alert_cause_dump + assign crashdump_d.loc_alert_cause[k] = reg2hw.loc_alert_cause[k].q; + end + + assign crashdump_d.class_accum_cnt = hw2reg_wrap.class_accum_cnt; + assign crashdump_d.class_esc_cnt = hw2reg_wrap.class_esc_cnt; + assign crashdump_d.class_esc_state = hw2reg_wrap.class_esc_state; + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_crashdump + if (!rst_ni) begin + crashump_latched_q <= 1'b0; + crashdump_q <= '0; + end else begin + // We latch the crashdump upon triggering any of the escalation protocols. The reason for this + // is that during escalation, certain alert senders may start to trigger due to FSMs being + // moved into escalation mode - thereby masking the actual alert reasons exposed in the cause + // registers. Note that the alert handler only captures the crashdump once upon first + // assertion of this signal, and needs to be reset to re-arm the crashdump latching + // mechanism. + if (latch_crashdump_i && !crashump_latched_q) begin + crashump_latched_q <= 1'b1; + crashdump_q <= crashdump_d; + end + end + end + + // As long as the crashdump has not been latched yet, we output the current alert handler state. + // Once it has been latched, we switch to the latched snapshot. + assign crashdump_o = (crashump_latched_q) ? crashdump_q : crashdump_d; + + ///////////////////////////// + // aggregate shadow errors // + ///////////////////////////// + + always_comb begin : p_gather_shadow_errs + reg2hw_wrap.shadowed_err_update = 1'b0; + reg2hw_wrap.shadowed_err_storage = 1'b0; + reg2hw_wrap.shadowed_err_update |= reg2hw.ping_timer_en_shadowed.err_update; + reg2hw_wrap.shadowed_err_storage |= reg2hw.ping_timer_en_shadowed.err_storage; + + for (int k = 0; k < NAlerts; k++) begin + reg2hw_wrap.shadowed_err_update |= |{ + reg2hw.alert_en_shadowed[k].err_update, + reg2hw.alert_class_shadowed[k].err_update + }; + reg2hw_wrap.shadowed_err_storage |= |{ + reg2hw.alert_en_shadowed[k].err_storage, + reg2hw.alert_class_shadowed[k].err_storage + }; + end + + for (int k = 0; k < N_LOC_ALERT; k++) begin + reg2hw_wrap.shadowed_err_update |= |{ + reg2hw.loc_alert_en_shadowed[k].err_update, + reg2hw.loc_alert_class_shadowed[k].err_update + }; + reg2hw_wrap.shadowed_err_storage |= |{ + reg2hw.loc_alert_en_shadowed[k].err_storage, + reg2hw.loc_alert_class_shadowed[k].err_storage + }; + end + + reg2hw_wrap.shadowed_err_update |= |{ + reg2hw.ping_timeout_cyc_shadowed.err_update, + + reg2hw.classa_ctrl_shadowed.en.err_update, + reg2hw.classb_ctrl_shadowed.en.err_update, + reg2hw.classc_ctrl_shadowed.en.err_update, + reg2hw.classd_ctrl_shadowed.en.err_update, + + reg2hw.classa_ctrl_shadowed.lock.err_update, + reg2hw.classb_ctrl_shadowed.lock.err_update, + reg2hw.classc_ctrl_shadowed.lock.err_update, + reg2hw.classd_ctrl_shadowed.lock.err_update, + + reg2hw.classa_ctrl_shadowed.en_e0.err_update, + reg2hw.classa_ctrl_shadowed.en_e1.err_update, + reg2hw.classa_ctrl_shadowed.en_e2.err_update, + reg2hw.classa_ctrl_shadowed.en_e3.err_update, + + reg2hw.classb_ctrl_shadowed.en_e0.err_update, + reg2hw.classb_ctrl_shadowed.en_e1.err_update, + reg2hw.classb_ctrl_shadowed.en_e2.err_update, + reg2hw.classb_ctrl_shadowed.en_e3.err_update, + + reg2hw.classc_ctrl_shadowed.en_e0.err_update, + reg2hw.classc_ctrl_shadowed.en_e1.err_update, + reg2hw.classc_ctrl_shadowed.en_e2.err_update, + reg2hw.classc_ctrl_shadowed.en_e3.err_update, + + reg2hw.classd_ctrl_shadowed.en_e0.err_update, + reg2hw.classd_ctrl_shadowed.en_e1.err_update, + reg2hw.classd_ctrl_shadowed.en_e2.err_update, + reg2hw.classd_ctrl_shadowed.en_e3.err_update, + + reg2hw.classa_ctrl_shadowed.map_e0.err_update, + reg2hw.classa_ctrl_shadowed.map_e1.err_update, + reg2hw.classa_ctrl_shadowed.map_e2.err_update, + reg2hw.classa_ctrl_shadowed.map_e3.err_update, + + reg2hw.classb_ctrl_shadowed.map_e0.err_update, + reg2hw.classb_ctrl_shadowed.map_e1.err_update, + reg2hw.classb_ctrl_shadowed.map_e2.err_update, + reg2hw.classb_ctrl_shadowed.map_e3.err_update, + + reg2hw.classc_ctrl_shadowed.map_e0.err_update, + reg2hw.classc_ctrl_shadowed.map_e1.err_update, + reg2hw.classc_ctrl_shadowed.map_e2.err_update, + reg2hw.classc_ctrl_shadowed.map_e3.err_update, + + reg2hw.classd_ctrl_shadowed.map_e0.err_update, + reg2hw.classd_ctrl_shadowed.map_e1.err_update, + reg2hw.classd_ctrl_shadowed.map_e2.err_update, + reg2hw.classd_ctrl_shadowed.map_e3.err_update, + + reg2hw.classa_accum_thresh_shadowed.err_update, + reg2hw.classb_accum_thresh_shadowed.err_update, + reg2hw.classc_accum_thresh_shadowed.err_update, + reg2hw.classd_accum_thresh_shadowed.err_update, + + reg2hw.classa_timeout_cyc_shadowed.err_update, + reg2hw.classb_timeout_cyc_shadowed.err_update, + reg2hw.classc_timeout_cyc_shadowed.err_update, + reg2hw.classd_timeout_cyc_shadowed.err_update, + + reg2hw.classa_phase0_cyc_shadowed.err_update, + reg2hw.classa_phase1_cyc_shadowed.err_update, + reg2hw.classa_phase2_cyc_shadowed.err_update, + reg2hw.classa_phase3_cyc_shadowed.err_update, + + reg2hw.classb_phase0_cyc_shadowed.err_update, + reg2hw.classb_phase1_cyc_shadowed.err_update, + reg2hw.classb_phase2_cyc_shadowed.err_update, + reg2hw.classb_phase3_cyc_shadowed.err_update, + + reg2hw.classc_phase0_cyc_shadowed.err_update, + reg2hw.classc_phase1_cyc_shadowed.err_update, + reg2hw.classc_phase2_cyc_shadowed.err_update, + reg2hw.classc_phase3_cyc_shadowed.err_update, + + reg2hw.classd_phase0_cyc_shadowed.err_update, + reg2hw.classd_phase1_cyc_shadowed.err_update, + reg2hw.classd_phase2_cyc_shadowed.err_update, + reg2hw.classd_phase3_cyc_shadowed.err_update, + + reg2hw.classa_crashdump_trigger_shadowed.err_update, + reg2hw.classb_crashdump_trigger_shadowed.err_update, + reg2hw.classc_crashdump_trigger_shadowed.err_update, + reg2hw.classd_crashdump_trigger_shadowed.err_update, + + reg2hw.classa_clr_shadowed.err_update, + reg2hw.classb_clr_shadowed.err_update, + reg2hw.classc_clr_shadowed.err_update, + reg2hw.classd_clr_shadowed.err_update + }; + + reg2hw_wrap.shadowed_err_storage |= |{ + reg2hw.ping_timeout_cyc_shadowed.err_storage, + + reg2hw.classa_ctrl_shadowed.en.err_storage, + reg2hw.classb_ctrl_shadowed.en.err_storage, + reg2hw.classc_ctrl_shadowed.en.err_storage, + reg2hw.classd_ctrl_shadowed.en.err_storage, + + reg2hw.classa_ctrl_shadowed.lock.err_storage, + reg2hw.classb_ctrl_shadowed.lock.err_storage, + reg2hw.classc_ctrl_shadowed.lock.err_storage, + reg2hw.classd_ctrl_shadowed.lock.err_storage, + + reg2hw.classa_ctrl_shadowed.en_e0.err_storage, + reg2hw.classa_ctrl_shadowed.en_e1.err_storage, + reg2hw.classa_ctrl_shadowed.en_e2.err_storage, + reg2hw.classa_ctrl_shadowed.en_e3.err_storage, + + reg2hw.classb_ctrl_shadowed.en_e0.err_storage, + reg2hw.classb_ctrl_shadowed.en_e1.err_storage, + reg2hw.classb_ctrl_shadowed.en_e2.err_storage, + reg2hw.classb_ctrl_shadowed.en_e3.err_storage, + + reg2hw.classc_ctrl_shadowed.en_e0.err_storage, + reg2hw.classc_ctrl_shadowed.en_e1.err_storage, + reg2hw.classc_ctrl_shadowed.en_e2.err_storage, + reg2hw.classc_ctrl_shadowed.en_e3.err_storage, + + reg2hw.classd_ctrl_shadowed.en_e0.err_storage, + reg2hw.classd_ctrl_shadowed.en_e1.err_storage, + reg2hw.classd_ctrl_shadowed.en_e2.err_storage, + reg2hw.classd_ctrl_shadowed.en_e3.err_storage, + + reg2hw.classa_ctrl_shadowed.map_e0.err_storage, + reg2hw.classa_ctrl_shadowed.map_e1.err_storage, + reg2hw.classa_ctrl_shadowed.map_e2.err_storage, + reg2hw.classa_ctrl_shadowed.map_e3.err_storage, + + reg2hw.classb_ctrl_shadowed.map_e0.err_storage, + reg2hw.classb_ctrl_shadowed.map_e1.err_storage, + reg2hw.classb_ctrl_shadowed.map_e2.err_storage, + reg2hw.classb_ctrl_shadowed.map_e3.err_storage, + + reg2hw.classc_ctrl_shadowed.map_e0.err_storage, + reg2hw.classc_ctrl_shadowed.map_e1.err_storage, + reg2hw.classc_ctrl_shadowed.map_e2.err_storage, + reg2hw.classc_ctrl_shadowed.map_e3.err_storage, + + reg2hw.classd_ctrl_shadowed.map_e0.err_storage, + reg2hw.classd_ctrl_shadowed.map_e1.err_storage, + reg2hw.classd_ctrl_shadowed.map_e2.err_storage, + reg2hw.classd_ctrl_shadowed.map_e3.err_storage, + + reg2hw.classa_accum_thresh_shadowed.err_storage, + reg2hw.classb_accum_thresh_shadowed.err_storage, + reg2hw.classc_accum_thresh_shadowed.err_storage, + reg2hw.classd_accum_thresh_shadowed.err_storage, + + reg2hw.classa_timeout_cyc_shadowed.err_storage, + reg2hw.classb_timeout_cyc_shadowed.err_storage, + reg2hw.classc_timeout_cyc_shadowed.err_storage, + reg2hw.classd_timeout_cyc_shadowed.err_storage, + + reg2hw.classa_phase0_cyc_shadowed.err_storage, + reg2hw.classa_phase1_cyc_shadowed.err_storage, + reg2hw.classa_phase2_cyc_shadowed.err_storage, + reg2hw.classa_phase3_cyc_shadowed.err_storage, + + reg2hw.classb_phase0_cyc_shadowed.err_storage, + reg2hw.classb_phase1_cyc_shadowed.err_storage, + reg2hw.classb_phase2_cyc_shadowed.err_storage, + reg2hw.classb_phase3_cyc_shadowed.err_storage, + + reg2hw.classc_phase0_cyc_shadowed.err_storage, + reg2hw.classc_phase1_cyc_shadowed.err_storage, + reg2hw.classc_phase2_cyc_shadowed.err_storage, + reg2hw.classc_phase3_cyc_shadowed.err_storage, + + reg2hw.classd_phase0_cyc_shadowed.err_storage, + reg2hw.classd_phase1_cyc_shadowed.err_storage, + reg2hw.classd_phase2_cyc_shadowed.err_storage, + reg2hw.classd_phase3_cyc_shadowed.err_storage, + + reg2hw.classa_crashdump_trigger_shadowed.err_storage, + reg2hw.classb_crashdump_trigger_shadowed.err_storage, + reg2hw.classc_crashdump_trigger_shadowed.err_storage, + reg2hw.classd_crashdump_trigger_shadowed.err_storage, + + reg2hw.classa_clr_shadowed.err_storage, + reg2hw.classb_clr_shadowed.err_storage, + reg2hw.classc_clr_shadowed.err_storage, + reg2hw.classd_clr_shadowed.err_storage + }; + end + +endmodule : alert_handler_reg_wrap diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_pkg.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_pkg.sv new file mode 100644 index 0000000000000..5773fc1fd1b4d --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_pkg.sv @@ -0,0 +1,103 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// + +package alert_pkg; + + // these localparams are generated based on the system top-level configuration + localparam int unsigned NAlerts = alert_handler_reg_pkg::NAlerts; // maximum 252 + localparam int unsigned EscCntDw = alert_handler_reg_pkg::EscCntDw; // maximum 32 + localparam int unsigned AccuCntDw = alert_handler_reg_pkg::AccuCntDw; // maximum 32 + localparam int unsigned NLpg = alert_handler_reg_pkg::NLpg; + localparam int unsigned NLpgWidth = alert_handler_reg_pkg::NLpgWidth; + localparam logic [NAlerts-1:0][NLpgWidth-1:0] LpgMap = alert_handler_reg_pkg::LpgMap; + // enable async transitions for specific RX/TX pairs + localparam bit [NAlerts-1:0] AsyncOn = alert_handler_reg_pkg::AsyncOn; + + // common constants, do not change + localparam int unsigned N_CLASSES = alert_handler_reg_pkg::N_CLASSES; + localparam int unsigned N_ESC_SEV = alert_handler_reg_pkg::N_ESC_SEV; + localparam int unsigned N_PHASES = alert_handler_reg_pkg::N_PHASES; + localparam int unsigned N_LOC_ALERT = alert_handler_reg_pkg::N_LOC_ALERT; + + localparam int unsigned PING_CNT_DW = alert_handler_reg_pkg::PING_CNT_DW; + localparam int unsigned PHASE_DW = alert_handler_reg_pkg::PHASE_DW; + localparam int unsigned CLASS_DW = alert_handler_reg_pkg::CLASS_DW; + + // do not change the phase encoding + typedef enum logic [2:0] {Idle = 3'b000, Timeout = 3'b001, Terminal = 3'b011, + Phase0 = 3'b100, Phase1 = 3'b101, Phase2 = 3'b110, + Phase3 = 3'b111, FsmError = 3'b010} cstate_e; + + // These LFSR parameters have been generated with + // $ util/design/gen-lfsr-seed.py --width 32 --seed 2700182644 + localparam int LfsrWidth = 32; + typedef logic [LfsrWidth-1:0] lfsr_seed_t; + typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t; + localparam lfsr_seed_t RndCnstLfsrSeedDefault = 32'he96064e5; + localparam lfsr_perm_t RndCnstLfsrPermDefault = + 160'hebd1e5d4a1cee5afdb866a9c7a0278b899020d31; + + // struct containing the current alert handler state + // can be used to gather crashdump information in HW + typedef struct packed { + // alerts + logic [NAlerts-1:0] alert_cause; // alert cause bits + logic [N_LOC_ALERT-1:0] loc_alert_cause; // local alert cause bits + // class state + logic [N_CLASSES-1:0][AccuCntDw-1:0] class_accum_cnt; // current accumulator value + logic [N_CLASSES-1:0][EscCntDw-1:0] class_esc_cnt; // current escalation counter value + cstate_e [N_CLASSES-1:0] class_esc_state; // current escalation protocol state + } alert_crashdump_t; + + // Default for dangling connection + parameter alert_crashdump_t ALERT_CRASHDUMP_DEFAULT = '{ + alert_cause: '0, + loc_alert_cause: '0, + class_accum_cnt: '0, + class_esc_cnt: '0, + class_esc_state: '0 + }; + + // breakout wrapper structs + typedef struct packed { + // alerts + logic [NAlerts-1:0] alert_cause; // alert cause bits + logic [N_LOC_ALERT-1:0] loc_alert_cause; // local alert cause bits + // class state + logic [N_CLASSES-1:0] class_trig; // class trigger + logic [N_CLASSES-1:0] class_esc_trig; // escalation trigger + logic [N_CLASSES-1:0][AccuCntDw-1:0] class_accum_cnt; // current accumulator value + logic [N_CLASSES-1:0][EscCntDw-1:0] class_esc_cnt; // current escalation counter value + cstate_e [N_CLASSES-1:0] class_esc_state; // current escalation protocol state + } hw2reg_wrap_t; + + typedef struct packed { + // aggregated shadow reg errors (trigger internal alerts) + logic shadowed_err_update; + logic shadowed_err_storage; + // ping config + logic ping_enable; // ping timer enable + logic [PING_CNT_DW-1:0] ping_timeout_cyc; // ping timeout config + logic [NAlerts-1:0] alert_ping_en; // ping enable for alerts + // alert config + logic [N_LOC_ALERT-1:0] loc_alert_en; // alert enable + logic [N_LOC_ALERT-1:0][CLASS_DW-1:0] loc_alert_class; // alert class config + logic [NAlerts-1:0] alert_en; // alert enable + logic [NAlerts-1:0][CLASS_DW-1:0] alert_class; // alert class config + // class config + logic [N_CLASSES-1:0] class_en; // enables esc mechanisms + logic [N_CLASSES-1:0] class_clr; // clears esc/accu + logic [N_CLASSES-1:0][AccuCntDw-1:0] class_accum_thresh; // accum esc threshold + logic [N_CLASSES-1:0][EscCntDw-1:0] class_timeout_cyc; // interrupt timeout + logic [N_CLASSES-1:0][N_PHASES-1:0][EscCntDw-1:0] class_phase_cyc; // length of phases 0..3 + logic [N_CLASSES-1:0][N_ESC_SEV-1:0] class_esc_en; // esc signal enables + logic [N_CLASSES-1:0][N_ESC_SEV-1:0][PHASE_DW-1:0] class_esc_map; // esc signal/phase map + // determines when to latch the crashdump output. + logic [N_CLASSES-1:0][PHASE_DW-1:0] class_crashdump_phase; + } reg2hw_wrap_t; + +endpackage : alert_pkg + + diff --git a/hw/top_earlgrey/lint/top_earlgrey_dv_lint_cfgs.hjson b/hw/top_earlgrey/lint/top_earlgrey_dv_lint_cfgs.hjson index 1e09019f63f6c..329d93c522462 100644 --- a/hw/top_earlgrey/lint/top_earlgrey_dv_lint_cfgs.hjson +++ b/hw/top_earlgrey/lint/top_earlgrey_dv_lint_cfgs.hjson @@ -24,9 +24,9 @@ rel_path: "hw/ip/aes/dv/lint/{tool}" }, { name: alert_handler - fusesoc_core: lowrisc:dv:alert_handler_sim + fusesoc_core: lowrisc:opentitan:top_earlgrey_alert_handler_sim import_cfgs: ["{proj_root}/hw/lint/tools/dvsim/common_lint_cfg.hjson"] - rel_path: "hw/top_earlgrey/ip/alert_handler/dv/lint/{tool}" + rel_path: "hw/top_earlgrey/ip_autogen/alert_handler/dv/lint/{tool}" }, { name: aon_timer fusesoc_core: lowrisc:dv:aon_timer_sim diff --git a/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson b/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson index 7bd191d9627f2..30d2df27afc0b 100644 --- a/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson +++ b/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson @@ -24,9 +24,9 @@ rel_path: "hw/ip/aes/lint/{tool}" }, { name: alert_handler - fusesoc_core: lowrisc:ip:alert_handler + fusesoc_core: lowrisc:opentitan:top_earlgrey_alert_handler import_cfgs: ["{proj_root}/hw/lint/tools/dvsim/common_lint_cfg.hjson"] - rel_path: "hw/ip/alert_handler/lint/{tool}" + rel_path: "hw/top_earlgrey/ip_autogen/alert_handler/lint/{tool}" overrides: [ { name: design_level diff --git a/hw/top_earlgrey/top_earlgrey.core b/hw/top_earlgrey/top_earlgrey.core index 1f37869987728..1e59866671779 100644 --- a/hw/top_earlgrey/top_earlgrey.core +++ b/hw/top_earlgrey/top_earlgrey.core @@ -8,7 +8,7 @@ filesets: files_rtl_generic: depend: - lowrisc:ip:uart:0.1 - - lowrisc:ip:alert_handler + - lowrisc:opentitan:top_earlgrey_alert_handler - lowrisc:ip:gpio - lowrisc:ip:rv_core_ibex - lowrisc:ip:rv_dm diff --git a/meson.build b/meson.build index 8943a7d91ba3f..4cd6fe2514a13 100644 --- a/meson.build +++ b/meson.build @@ -211,7 +211,7 @@ gen_hw_hdr = generator( # TODO: Considering moving these into hw/ip directories. TOPNAME='top_earlgrey' hw_ip_aes_reg_h = gen_hw_hdr.process('hw/ip/aes/data/aes.hjson') -hw_ip_alert_handler_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/alert_handler/data/autogen/alert_handler.hjson') +hw_ip_alert_handler_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip_autogen/alert_handler/data/alert_handler.hjson') hw_ip_aon_timer_reg_h = gen_hw_hdr.process('hw/ip/aon_timer/data/aon_timer.hjson') hw_ip_clkmgr_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/clkmgr/data/autogen/clkmgr.hjson') hw_ip_entropy_src_reg_h = gen_hw_hdr.process('hw/ip/entropy_src/data/entropy_src.hjson') diff --git a/sw/device/lib/dif/dif_alert_handler.md b/sw/device/lib/dif/dif_alert_handler.md index 3360f1daeddc7..9564640fde21a 100644 --- a/sw/device/lib/dif/dif_alert_handler.md +++ b/sw/device/lib/dif/dif_alert_handler.md @@ -2,7 +2,7 @@ title: "Alert handler DIF Checklist" --- -This checklist is for [Development Stage]({{< relref "/doc/project/development_stages.md" >}}) transitions for the [Alert Handler DIF]({{< relref "hw/ip/alert_handler/doc" >}}). +This checklist is for [Development Stage]({{< relref "/doc/project/development_stages.md" >}}) transitions for the [Alert Handler DIF]({{< relref "hw/top_earlgrey/ip_autogen/alert_handler/doc" >}}). All checklist items refer to the content in the [Checklist]({{< relref "/doc/project/checklist.md" >}}). ## DIF Checklist diff --git a/topgen-reg-only.core b/topgen-reg-only.core index 5481562112a8b..ec86fcfd087f2 100644 --- a/topgen-reg-only.core +++ b/topgen-reg-only.core @@ -8,7 +8,6 @@ description: "Top-level generator tool." filesets: rtl: depend: - - lowrisc:ip:alert_handler_reggen - lowrisc:ip:clkmgr_reggen - lowrisc:ip:flash_ctrl_reggen - lowrisc:ip:pinmux_reggen diff --git a/util/build_docs.py b/util/build_docs.py index 14bc75e1363cc..007a4036a5e91 100755 --- a/util/build_docs.py +++ b/util/build_docs.py @@ -55,7 +55,7 @@ "hardware_definitions": [ "hw/ip/aes/data/aes.hjson", "hw/ip/aon_timer/data/aon_timer.hjson", - "hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson", + "hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.hjson", "hw/ip/entropy_src/data/entropy_src.hjson", "hw/ip/csrng/data/csrng.hjson", "hw/ip/adc_ctrl/data/adc_ctrl.hjson", @@ -103,7 +103,7 @@ # Pre-generate testplan fragments from these files. "testplan_definitions": [ "hw/ip/aes/data/aes_testplan.hjson", - "hw/ip/alert_handler/data/alert_handler_testplan.hjson", + "hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson", "hw/ip/aon_timer/data/aon_timer_testplan.hjson", "hw/ip/clkmgr/data/clkmgr_testplan.hjson", "hw/ip/entropy_src/data/entropy_src_testplan.hjson", diff --git a/util/make_new_dif.py b/util/make_new_dif.py index 60895a96d1490..ca3137ec540f9 100755 --- a/util/make_new_dif.py +++ b/util/make_new_dif.py @@ -46,6 +46,7 @@ IPS_USING_IPGEN = [ 'rv_plic', + 'alert_handler', ] # Subset of IPs for which some portion of the DIFs have been auto-generated. # NOTE: This exists while autogenerated DIF code is checked into the repository diff --git a/util/topgen-fusesoc.py b/util/topgen-fusesoc.py index 684c451d49134..84e966a4353c6 100755 --- a/util/topgen-fusesoc.py +++ b/util/topgen-fusesoc.py @@ -72,7 +72,6 @@ def main(): # example, flash_ctrl depends on topgen but also on pwrmgr_pkg which depends on # pwrmgr_reg_pkg generated by topgen. reg_top_suffix = { - 'alert_handler': '', 'clkmgr': '', 'flash_ctrl': '_core', 'pinmux': '', @@ -81,8 +80,7 @@ def main(): } # reg-only - for ip in ['alert_handler', 'clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr', - 'rstmgr']: + for ip in ['clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr', 'rstmgr']: core_filepath = os.path.abspath(os.path.join(files_out, 'generated-%s.core' % ip)) name = 'lowrisc:ip:%s_reggen' % ip, files = ['ip/%s/rtl/autogen/%s_reg_pkg.sv' % (ip, ip), diff --git a/util/topgen.py b/util/topgen.py index 7350428928c17..0c870713eece3 100755 --- a/util/topgen.py +++ b/util/topgen.py @@ -61,6 +61,7 @@ # TODO: Remove once all IP templates use ipgen. IPS_USING_IPGEN = [ 'rv_plic', + 'alert_handler', ] @@ -170,6 +171,8 @@ def generate_xbars(top, out_path): def generate_alert_handler(top, out_path): + topname = top["name"] + # default values esc_cnt_dw = 32 accu_cnt_dw = 16 @@ -180,7 +183,6 @@ def generate_alert_handler(top, out_path): n_lpg = 1 lpg_map = [] - topname = top["name"] # Count number of alerts and LPGs n_alerts = sum([x["width"] if "width" in x else 1 for x in top["alert"]]) @@ -211,56 +213,17 @@ def generate_alert_handler(top, out_path): async_on.append(async_on_format.format(int(alert['async']))) lpg_map.append(lpg_idx_format.format(int(alert['lpg_idx']))) - log.info("alert handler parameterization:") - log.info("NAlerts = %d" % n_alerts) - log.info("EscCntDw = %d" % esc_cnt_dw) - log.info("AccuCntDw = %d" % accu_cnt_dw) - log.info("AsyncOn = %s" % async_on) - log.info("NLpg = %s" % n_lpg) - log.info("LpgMap = %s" % lpg_map) - - # Define target path - rtl_path = out_path / 'ip/alert_handler/rtl/autogen' - rtl_path.mkdir(parents=True, exist_ok=True) - doc_path = out_path / 'ip/alert_handler/data/autogen' - doc_path.mkdir(parents=True, exist_ok=True) - - # Generating IP top module script is not generalized yet. - # So, topgen reads template files from alert_handler directory directly. - tpl_path = Path(__file__).resolve().parent / '../hw/ip/alert_handler/data' - hjson_tpl_path = tpl_path / 'alert_handler.hjson.tpl' - - # Generate Register Package and RTLs - out = StringIO() - with hjson_tpl_path.open(mode='r', encoding='UTF-8') as fin: - hjson_tpl = Template(fin.read()) - try: - out = hjson_tpl.render(n_alerts=n_alerts, - esc_cnt_dw=esc_cnt_dw, - accu_cnt_dw=accu_cnt_dw, - async_on=async_on, - n_classes=n_classes, - n_lpg=n_lpg, - lpg_map=lpg_map) - except: # noqa: E722 - log.error(exceptions.text_error_template().render()) - log.info("alert_handler hjson: %s" % out) - - if out == "": - log.error("Cannot generate alert_handler config file") - return - - hjson_gen_path = doc_path / "alert_handler.hjson" - gencmd = ( - "// util/topgen.py -t hw/top_{topname}/data/top_{topname}.hjson --alert-handler-only " - "-o hw/top_{topname}/\n\n".format(topname=topname)) - with hjson_gen_path.open(mode='w', encoding='UTF-8') as fout: - fout.write(genhdr + gencmd + out) - - # Generate register RTLs (currently using shell execute) - # TODO: More secure way to gneerate RTL - gen_rtl.gen_rtl(IpBlock.from_text(out, [], str(hjson_gen_path)), - str(rtl_path)) + params = { + 'n_alerts': n_alerts, + 'esc_cnt_dw': esc_cnt_dw, + 'accu_cnt_dw': accu_cnt_dw, + 'async_on': async_on, + 'n_classes': n_classes, + 'n_lpg': n_lpg, + 'lpg_map': lpg_map, + } + + ipgen_render('alert_handler', topname, params, out_path) def generate_plic(top, out_path):