From c6757dbeb46abd3cbc63f61b67732b44f272f622 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 18 Nov 2024 14:50:55 +0100 Subject: [PATCH] [topgen] Support for incoming alerts Signed-off-by: Robert Schilling --- .../data/autogen/top_earlgrey.gen.hjson | 1 + hw/top_earlgrey/rtl/autogen/top_earlgrey.sv | 2 ++ hw/top_earlgrey/templates/toplevel.sv.tpl | 22 +++++++++++++ util/topgen.py | 32 ++++++++++++++++++- util/topgen/lib.py | 20 ++++++++++-- util/topgen/templates/toplevel_pkg.sv.tpl | 8 +++++ util/topgen/validate.py | 1 + 7 files changed, 82 insertions(+), 4 deletions(-) diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson index a3d6521edfb6fc..5fc2c9dc79f6ff 100644 --- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson +++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson @@ -14280,6 +14280,7 @@ } } ] + incoming_alert: {} exported_clks: {} wakeups: [ diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv index 333febfbc05e9e..2e23e02ec0f404 100644 --- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv +++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv @@ -2705,6 +2705,8 @@ module top_earlgrey import top_earlgrey_pkg::*; #( .rst_esc_ni (rstmgr_aon_resets.rst_lc_io_div4_n[rstmgr_pkg::Domain0Sel]), .rst_otp_ni (rstmgr_aon_resets.rst_lc_io_div4_n[rstmgr_pkg::Domain0Sel]) ); + + // interrupt assignments assign intr_vector = { intr_edn1_edn_fatal_err, // IDs [185 +: 1] diff --git a/hw/top_earlgrey/templates/toplevel.sv.tpl b/hw/top_earlgrey/templates/toplevel.sv.tpl index b6e1d8ad9a8cae..939e08cd02d0fb 100644 --- a/hw/top_earlgrey/templates/toplevel.sv.tpl +++ b/hw/top_earlgrey/templates/toplevel.sv.tpl @@ -129,6 +129,14 @@ module top_${top["name"]} import top_${top["name"]}_pkg::*; #( output prim_mubi_pkg::mubi4_t [top_${top["name"]}_pkg::NOutgoingLpgs${alert_group.capitalize()}-1:0] outgoing_lpg_cg_en_${alert_group}_o, output prim_mubi_pkg::mubi4_t [top_${top["name"]}_pkg::NOutgoingLpgs${alert_group.capitalize()}-1:0] outgoing_lpg_rst_en_${alert_group}_o, % endfor + % for alert_group in top['incoming_alert'].keys(): + + // Incoming alerts for group ${alert_group} + input prim_alert_pkg::alert_tx_t [top_${top["name"]}_pkg::NIncomingAlerts${alert_group.capitalize()}-1:0] incoming_alert_${alert_group}_tx_i, + output prim_alert_pkg::alert_rx_t [top_${top["name"]}_pkg::NIncomingAlerts${alert_group.capitalize()}-1:0] incoming_alert_${alert_group}_rx_o, + input prim_mubi_pkg::mubi4_t [top_${top["name"]}_pkg::NIncomingLpgs${alert_group.capitalize()}-1:0] incoming_lpg_cg_en_${alert_group}_i, + input prim_mubi_pkg::mubi4_t [top_${top["name"]}_pkg::NIncomingLpgs${alert_group.capitalize()}-1:0] incoming_lpg_rst_en_${alert_group}_i, + % endfor // All clocks forwarded to ast output clkmgr_pkg::clkmgr_out_t clks_ast_o, @@ -620,6 +628,20 @@ endif % endfor ); % endfor + +% for alert_group, alerts in top['incoming_alert'].items(): +<% +w = len(alerts) +slice = str(alert_idx+w-1) + ":" + str(alert_idx) +%> + // Alert mapping to the alert handler for alert group ${alert_group} + % for alert in alerts: + // [${alert_idx}]: ${alert['name']}<% alert_idx += 1 %> + % endfor + assign alerts_tx[${slice}] = incoming_alert_${alert_group}_tx_i; + assign incoming_alert_${alert_group}_rx_o = alerts_rx[${slice}]; +% endfor + // interrupt assignments <% base = interrupt_num %>\ assign intr_vector = { diff --git a/util/topgen.py b/util/topgen.py index a9c902ef739bc6..dc8f08f5710a74 100755 --- a/util/topgen.py +++ b/util/topgen.py @@ -176,6 +176,14 @@ def generate_alert_handler(top: Dict[str, object], out_path: Path) -> None: # Count number of alerts and LPGs n_alerts = sum([x["width"] if "width" in x else 1 for x in top["alert"]]) n_lpg = len(top["alert_lpgs"]) + n_lpg_incoming_offset = n_lpg + + # Add incoming alerts and their LPGs + for alerts in top['incoming_alert'].values(): + n_alerts += len(alerts) + # Number of LPGs is maximum index + 1 + n_lpg += max(alert['lpg_idx'] for alert in alerts) + 1 + n_lpg_width = n_lpg.bit_length() # format used to print out indices in binary format async_on_format = "1'b{:01b}" @@ -198,10 +206,18 @@ def generate_alert_handler(top: Dict[str, object], out_path: Path) -> None: async_on = [] lpg_map = [] for alert in top["alert"]: - for k in range(alert["width"]): + for _ in range(alert["width"]): async_on.append(async_on_format.format(int(alert["async"]))) lpg_map.append(lpg_idx_format.format(int(alert["lpg_idx"]))) + lpg_prev_offset = n_lpg_incoming_offset + for alerts in top['incoming_alert'].values(): + for alert in alerts: + for _ in range(alert["width"]): + async_on.append(async_on_format.format(int(alert["async"]))) + lpg_map.append(lpg_idx_format.format(lpg_prev_offset + int(alert["lpg_idx"]))) + lpg_prev_offset += max(alert['lpg_idx'] for alert in alerts) + 1 + params = { "n_alerts": n_alerts, "esc_cnt_dw": esc_cnt_dw, @@ -1015,6 +1031,20 @@ def main(): topcfg = hjson.load(ftop, use_decimal=True, object_pairs_hook=OrderedDict) + + # Read external alert mappings for all available alert handlers if defined and inject + # that to the alert handler's module definition. + if 'incoming_alert' not in topcfg: + topcfg['incoming_alert'] = {} + + for m in topcfg['module']: + if m['type'] == 'alert_handler': + for alert_mappings_path in m.get('incoming_alert', []): + with open(Path(args.topcfg).parent / alert_mappings_path, "r") as falert: + + mapping = hjson.load(falert) + for alert_group, alerts in mapping.items(): + topcfg['incoming_alert'][alert_group] = alerts except ValueError: raise SystemExit(sys.exc_info()[1]) diff --git a/util/topgen/lib.py b/util/topgen/lib.py index 8f87400afe0466..4cecdd88a8ce5d 100644 --- a/util/topgen/lib.py +++ b/util/topgen/lib.py @@ -1042,7 +1042,12 @@ def _init_alert_mapping(self): # module name to the full name object used for the enum constant. source_name_map = {} - for name in self.top["alert_module"]: + # Uniquify the incoming alert module list + incoming_module_names = [] + for incoming_alerts in self.top['incoming_alert'].values(): + incoming_module_names.extend({alert['module_name'] for alert in incoming_alerts}) + + for name in self.top["alert_module"] + incoming_module_names: source_name = sources.add_constant(Name.from_snake_case(name), docstring=name) source_name_map[name] = source_name @@ -1052,11 +1057,12 @@ def _init_alert_mapping(self): else: sources.add_last_constant("Final Alert peripheral") - self.device_alerts = defaultdict(list) - for alert in self.top["alert"]: + def add_alert(alert, name_prefix=None): 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)]) + if name_prefix: + name = name_prefix + name irq_id = alerts.add_constant(name, docstring="{} {}".format( alert["name"], i)) @@ -1071,6 +1077,14 @@ def _init_alert_mapping(self): alert_mapping.add_entry(alert_id, source_name) self.device_alerts[alert["module_name"]].append(alert["name"]) + self.device_alerts = defaultdict(list) + for alert in self.top["alert"]: + add_alert(alert) + + for alert_group, incoming_alerts in self.top['incoming_alert'].items(): + for alert in incoming_alerts: + add_alert(alert, Name(f'incoming_{alert_group}')) + if isinstance(alerts, RustEnum): alerts.add_number_of_variants("The number of Alert ID.") else: diff --git a/util/topgen/templates/toplevel_pkg.sv.tpl b/util/topgen/templates/toplevel_pkg.sv.tpl index bb0e5896ba673d..23502b211b7257 100644 --- a/util/topgen/templates/toplevel_pkg.sv.tpl +++ b/util/topgen/templates/toplevel_pkg.sv.tpl @@ -83,6 +83,14 @@ package top_${top["name"]}_pkg; ${lib.Name.from_snake_case("top_" + top["name"] + "_outgoing_alert_" + alert_group + "_id_count").as_camel_case()} } ${"outgoing_alert_" + alert_group + "_id_e"}; % endfor +% for alert_group, alerts in top["incoming_alert"].items(): + + // Number of ${alert_group} incoming alerts + parameter int unsigned NIncomingAlerts${alert_group.capitalize()} = ${len(alerts)}; + + // Number of LPGs for incoming alert group ${alert_group} + parameter int unsigned NOutgoingLpgs${alert_group.capitalize()} = ${max(alert['lpg_idx'] for alert in alerts) + 1}; +% endfor // Enumeration of alert modules typedef enum int unsigned { diff --git a/util/topgen/validate.py b/util/topgen/validate.py index b8c06b8d86ea38..6546ae734895d1 100644 --- a/util/topgen/validate.py +++ b/util/topgen/validate.py @@ -63,6 +63,7 @@ 'datawidth': ['pn', "default data width"], 'exported_clks': ['g', 'clock signal routing rules'], 'host': ['g', 'list of host-only components in the system'], + 'incoming_alert': ['g', 'Parsed incoming alerts (generated)'], 'inter_module': ['g', 'define the signal connections between the modules'], 'interrupt': ['lnw', 'interrupts (generated)'], 'interrupt_module': ['l', 'list of the modules that connects to rv_plic'],