diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson index 0ae7bca1182bbc..15d9f9a63af6df 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/templates/toplevel.sv.tpl b/hw/top_earlgrey/templates/toplevel.sv.tpl index 4fedee0fbd48dd..52e5f8871c597e 100644 --- a/hw/top_earlgrey/templates/toplevel.sv.tpl +++ b/hw/top_earlgrey/templates/toplevel.sv.tpl @@ -128,6 +128,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, @@ -605,6 +613,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 3e90b6c9ee40c9..8fef200841543f 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, @@ -996,6 +1012,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 080806d1805c57..0542809a787e5a 100644 --- a/util/topgen/lib.py +++ b/util/topgen/lib.py @@ -1034,7 +1034,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 @@ -1044,11 +1049,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)) @@ -1063,6 +1069,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 de342e870f1397..23d400467fdb13 100644 --- a/util/topgen/templates/toplevel_pkg.sv.tpl +++ b/util/topgen/templates/toplevel_pkg.sv.tpl @@ -63,6 +63,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 {