[topgen] Generate Software Definitions for Alert Handler
Signed-off-by: Sam Elliott <selliott@lowrisc.org>
diff --git a/hw/top_earlgrey/data/top_earlgrey.c.tpl b/hw/top_earlgrey/data/top_earlgrey.c.tpl
index a20f4e4..4cfbabe 100644
--- a/hw/top_earlgrey/data/top_earlgrey.c.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.c.tpl
@@ -11,3 +11,11 @@
* `${helper.plic_sources.name.as_c_type()}`.
*/
${helper.plic_mapping.render_definition()}
+
+/**
+ * Alert Handler Alert Source to Peripheral Map
+ *
+ * This array is a mapping from `${helper.alert_alerts.name.as_c_type()}` to
+ * `${helper.alert_sources.name.as_c_type()}`.
+ */
+${helper.alert_mapping.render_definition()}
diff --git a/hw/top_earlgrey/data/top_earlgrey.h.tpl b/hw/top_earlgrey/data/top_earlgrey.h.tpl
index 8985179..47e7a5d 100644
--- a/hw/top_earlgrey/data/top_earlgrey.h.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.h.tpl
@@ -116,6 +116,30 @@
*/
${helper.plic_targets.render()}
+/**
+ * Alert Handler Source Peripheral.
+ *
+ * Enumeration used to determine which peripheral asserted the corresponding
+ * alert.
+ */
+${helper.alert_sources.render()}
+
+/**
+ * Alert Handler Alert Source.
+ *
+ * Enumeration of all Alert Handler Alert Sources. The alert sources belonging to
+ * the same peripheral are guaranteed to be consecutive.
+ */
+${helper.alert_alerts.render()}
+
+/**
+ * Alert Handler Alert Source to Peripheral Map
+ *
+ * This array is a mapping from `${helper.alert_alerts.name.as_c_type()}` to
+ * `${helper.alert_sources.name.as_c_type()}`.
+ */
+${helper.alert_mapping.render_declaration()}
+
// Header Extern Guard
#ifdef __cplusplus
} // extern "C"
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.c b/hw/top_earlgrey/sw/autogen/top_earlgrey.c
index ebaa89a..9b2ad78 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.c
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.c
@@ -96,3 +96,26 @@
[kTopEarlgreyPlicIrqIdOtbnErr] = kTopEarlgreyPlicPeripheralOtbn,
};
+
+/**
+ * Alert Handler Alert Source to Peripheral Map
+ *
+ * This array is a mapping from `top_earlgrey_alert_id_t` to
+ * `top_earlgrey_alert_peripheral_t`.
+ */
+const top_earlgrey_alert_peripheral_t
+ top_earlgrey_alert_for_peripheral[12] = {
+ [kTopEarlgreyAlertIdAesCtrlErr] = kTopEarlgreyAlertPeripheralAes,
+ [kTopEarlgreyAlertIdHmacMsgPushShaDisabled] = kTopEarlgreyAlertPeripheralHmac,
+ [kTopEarlgreyAlertIdOtbnImemUncorrectable] = kTopEarlgreyAlertPeripheralOtbn,
+ [kTopEarlgreyAlertIdOtbnDmemUncorrectable] = kTopEarlgreyAlertPeripheralOtbn,
+ [kTopEarlgreyAlertIdOtbnRegUncorrectable] = kTopEarlgreyAlertPeripheralOtbn,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts0] = kTopEarlgreyAlertPeripheralSensorCtrl,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts1] = kTopEarlgreyAlertPeripheralSensorCtrl,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts2] = kTopEarlgreyAlertPeripheralSensorCtrl,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts3] = kTopEarlgreyAlertPeripheralSensorCtrl,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts4] = kTopEarlgreyAlertPeripheralSensorCtrl,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts5] = kTopEarlgreyAlertPeripheralSensorCtrl,
+ [kTopEarlgreyAlertIdSensorCtrlAstAlerts6] = kTopEarlgreyAlertPeripheralSensorCtrl,
+};
+
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.h b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
index 143fbd2..db39d92 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.h
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
@@ -590,6 +590,51 @@
kTopEarlgreyPlicTargetLast = 0, /**< \internal Final PLIC target */
} top_earlgrey_plic_target_t;
+/**
+ * Alert Handler Source Peripheral.
+ *
+ * Enumeration used to determine which peripheral asserted the corresponding
+ * alert.
+ */
+typedef enum top_earlgrey_alert_peripheral {
+ kTopEarlgreyAlertPeripheralAes = 0, /**< aes */
+ kTopEarlgreyAlertPeripheralHmac = 1, /**< hmac */
+ kTopEarlgreyAlertPeripheralOtbn = 2, /**< otbn */
+ kTopEarlgreyAlertPeripheralSensorCtrl = 3, /**< sensor_ctrl */
+ kTopEarlgreyAlertPeripheralLast = 3, /**< \internal Final Alert peripheral */
+} top_earlgrey_alert_peripheral_t;
+
+/**
+ * Alert Handler Alert Source.
+ *
+ * Enumeration of all Alert Handler Alert Sources. The alert sources belonging to
+ * the same peripheral are guaranteed to be consecutive.
+ */
+typedef enum top_earlgrey_alert_id {
+ kTopEarlgreyAlertIdAesCtrlErr = 0, /**< aes_ctrl_err */
+ kTopEarlgreyAlertIdHmacMsgPushShaDisabled = 1, /**< hmac_msg_push_sha_disabled */
+ kTopEarlgreyAlertIdOtbnImemUncorrectable = 2, /**< otbn_imem_uncorrectable */
+ kTopEarlgreyAlertIdOtbnDmemUncorrectable = 3, /**< otbn_dmem_uncorrectable */
+ kTopEarlgreyAlertIdOtbnRegUncorrectable = 4, /**< otbn_reg_uncorrectable */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts0 = 5, /**< sensor_ctrl_ast_alerts 0 */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts1 = 6, /**< sensor_ctrl_ast_alerts 1 */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts2 = 7, /**< sensor_ctrl_ast_alerts 2 */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts3 = 8, /**< sensor_ctrl_ast_alerts 3 */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts4 = 9, /**< sensor_ctrl_ast_alerts 4 */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts5 = 10, /**< sensor_ctrl_ast_alerts 5 */
+ kTopEarlgreyAlertIdSensorCtrlAstAlerts6 = 11, /**< sensor_ctrl_ast_alerts 6 */
+ kTopEarlgreyAlertIdLast = 11, /**< \internal The Last Valid Alert ID. */
+} top_earlgrey_alert_id_t;
+
+/**
+ * Alert Handler Alert Source to Peripheral Map
+ *
+ * This array is a mapping from `top_earlgrey_alert_id_t` to
+ * `top_earlgrey_alert_peripheral_t`.
+ */
+extern const top_earlgrey_alert_peripheral_t
+ top_earlgrey_alert_for_peripheral[12];
+
// Header Extern Guard
#ifdef __cplusplus
} // extern "C"
diff --git a/util/topgen/c.py b/util/topgen/c.py
index f62eb9f..17ce546 100644
--- a/util/topgen/c.py
+++ b/util/topgen/c.py
@@ -4,7 +4,6 @@
"""This contains a class which is used to help generate `top_{name}.h` and
`top_{name}.h`.
"""
-
from collections import OrderedDict
from mako.template import Template
@@ -137,6 +136,19 @@
self._init_plic_targets()
self._init_plic_mapping()
+ self._init_alert_mapping()
+
+ def modules(self):
+ return [(m["name"],
+ MemoryRegion(self._top_name + Name.from_snake_case(m["name"]),
+ m["base_addr"], m["size"]))
+ for m in self.top["module"]]
+
+ def memories(self):
+ return [(m["name"],
+ MemoryRegion(self._top_name + Name.from_snake_case(m["name"]),
+ m["base_addr"], m["size"]))
+ for m in self.top["memory"]]
def _init_plic_targets(self):
enum = CEnum(self._top_name + Name(["plic", "target"]))
@@ -153,10 +165,11 @@
"""We eventually want to generate a mapping from interrupt id to the
source peripheral.
- In order to do so, we generate two enums, and store the generated names
- in a dictionary that represents the mapping.
+ In order to do so, we generate two enums (one for interrupts, one for
+ sources), and store the generated names in a dictionary that represents
+ the mapping.
- Plic Interrupt ID 0 corresponds to no interrupt, and so no peripheral,
+ PLIC Interrupt ID 0 corresponds to no interrupt, and so no peripheral,
so we encode that in the enum as "unknown".
The interrupts have to be added in order, with "none" first, to ensure
@@ -211,14 +224,55 @@
self.plic_interrupts = interrupts
self.plic_mapping = plic_mapping
- def modules(self):
- return [(m["name"],
- MemoryRegion(self._top_name + Name.from_snake_case(m["name"]),
- m["base_addr"], m["size"]))
- for m in self.top["module"]]
+ def _init_alert_mapping(self):
+ """We eventually want to generate a mapping from alert id to the source
+ peripheral.
- def memories(self):
- return [(m["name"],
- MemoryRegion(self._top_name + Name.from_snake_case(m["name"]),
- m["base_addr"], m["size"]))
- for m in self.top["memory"]]
+ In order to do so, we generate two enums (one for alerts, one for
+ sources), and store the generated names in a dictionary that represents
+ the mapping.
+
+ Alert Handler has no concept of "no alert", unlike the PLIC.
+
+ The alerts have to be added in order, to ensure that they get the
+ correct mapping to their alert id, which is used for addressing the
+ right registers and bits.
+ """
+ sources = CEnum(self._top_name + Name(["alert", "peripheral"]))
+ alerts = CEnum(self._top_name + Name(["alert", "id"]))
+ alert_mapping = CArrayMapping(
+ self._top_name + Name(["alert", "for", "peripheral"]),
+ sources.name)
+
+ # When we generate the `alerts` enum, the only info we have about the
+ # source is the module name. We'll use `source_name_map` to map a short
+ # module name to the full name object used for the enum constant.
+ source_name_map = {}
+
+ for name in self.top["alert_module"]:
+ source_name = sources.add_constant(Name.from_snake_case(name),
+ docstring=name)
+ source_name_map[name] = source_name
+
+ sources.add_last_constant("Final Alert peripheral")
+
+ for alert in self.top["alert"]:
+ if "width" in alert and int(alert["width"]) != 1:
+ for i in range(int(alert["width"])):
+ name = Name.from_snake_case(
+ alert["name"]) + Name([str(i)])
+ irq_id = alerts.add_constant(name, docstring="{} {}".format(
+ alert["name"], i))
+ source_name = source_name_map[alert["module_name"]]
+ alert_mapping.add_entry(irq_id, source_name)
+ else:
+ name = Name.from_snake_case(alert["name"])
+ alert_id = alerts.add_constant(name, docstring=alert["name"])
+ source_name = source_name_map[alert["module_name"]]
+ alert_mapping.add_entry(alert_id, source_name)
+
+ alerts.add_last_constant("The Last Valid Alert ID.")
+
+ self.alert_sources = sources
+ self.alert_alerts = alerts
+ self.alert_mapping = alert_mapping