[topgen] Update LPG logic to account for per-clock group assignments
Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/hw/ip/alert_handler/data/alert_handler.hjson b/hw/ip/alert_handler/data/alert_handler.hjson
index ac07069..34ac2e3 100644
--- a/hw/ip/alert_handler/data/alert_handler.hjson
+++ b/hw/ip/alert_handler/data/alert_handler.hjson
@@ -63,7 +63,9 @@
'''
type: "logic [NAlerts-1:0][NLpgWidth-1:0]",
default: '''
-'0
+ {
+ 1'b0
+ }
''',
local: "true"
},
@@ -85,7 +87,11 @@
defines whether the protocol is synchronous (0) or asynchronous (1).
'''
type: "logic [NAlerts-1:0]",
- default: "'0",
+ default: '''
+ {
+ '0
+ }
+ '''
local: "true"
},
{ name: "N_CLASSES",
diff --git a/hw/ip/alert_handler/data/alert_handler.hjson.tpl b/hw/ip/alert_handler/data/alert_handler.hjson.tpl
index 9a6b35c..493a95c 100644
--- a/hw/ip/alert_handler/data/alert_handler.hjson.tpl
+++ b/hw/ip/alert_handler/data/alert_handler.hjson.tpl
@@ -67,7 +67,15 @@
'''
type: "logic [NAlerts-1:0][NLpgWidth-1:0]",
default: '''
-${lpg_map}
+% if lpg_map:
+ {
+ % for l in list(reversed(lpg_map)):
+ ${l}${"" if loop.last else ","}
+ % endfor
+ }
+% else:
+ '0
+% endif
''',
local: "true"
},
@@ -89,7 +97,17 @@
defines whether the protocol is synchronous (0) or asynchronous (1).
'''
type: "logic [NAlerts-1:0]",
- default: "${async_on}",
+ default: '''
+% if async_on:
+ {
+ % for a in list(reversed(async_on)):
+ ${a}${"" if loop.last else ","}
+ % endfor
+ }
+% else:
+ '0
+% endif
+ '''
local: "true"
},
{ name: "N_CLASSES",
diff --git a/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv b/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv
index 200ffaf..edc6a4e 100644
--- a/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv
+++ b/hw/ip/alert_handler/rtl/alert_handler_reg_pkg.sv
@@ -10,10 +10,14 @@
parameter int NAlerts = 4;
parameter int NLpg = 1;
parameter int NLpgWidth = 1;
- parameter logic [NAlerts-1:0][NLpgWidth-1:0] LpgMap = '0;
+ 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 logic [NAlerts-1:0] AsyncOn = {
+ '0
+};
parameter int N_CLASSES = 4;
parameter int N_ESC_SEV = 4;
parameter int N_PHASES = 4;
diff --git a/hw/ip/alert_handler/util/reg_alert_handler.py b/hw/ip/alert_handler/util/reg_alert_handler.py
index a24cddd..f97d91b 100755
--- a/hw/ip/alert_handler/util/reg_alert_handler.py
+++ b/hw/ip/alert_handler/util/reg_alert_handler.py
@@ -31,19 +31,11 @@
type=int,
default=16,
help='Width of accumulator')
- parser.add_argument('--async_on',
- type=str,
- default="'0",
- help="""Enables asynchronous signalling between specific
- alert RX/TX pairs""")
- parser.add_argument('--n_lpg',
- type=int,
- default=1,
- help='Number of LPGs')
- parser.add_argument('--lpg_map',
- type=str,
- default="'0",
- help="""Encodes the alert to LPG mapping""")
+
+ # can currently not be overridden with this script
+ n_lpg = 1
+ lpg_map = ["1'b0"]
+ async_on = ["'0"]
args = parser.parse_args()
@@ -55,9 +47,9 @@
reg_tpl.render(n_alerts=args.n_alerts,
esc_cnt_dw=args.esc_cnt_dw,
accu_cnt_dw=args.accu_cnt_dw,
- async_on=args.async_on,
- n_lpg=args.n_lpg,
- lpg_map=args.lpg_map,
+ async_on=async_on,
+ n_lpg=n_lpg,
+ lpg_map=lpg_map,
n_classes=4)) # leave this constant for now
print(out.getvalue())
diff --git a/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson b/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson
index b4719fa..23e6789 100644
--- a/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson
+++ b/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson
@@ -71,64 +71,66 @@
'''
type: "logic [NAlerts-1:0][NLpgWidth-1:0]",
default: '''
-{5'd19,
-5'd19,
-5'd19,
-5'd19,
-5'd19,
-5'd19,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd18,
-5'd18,
-5'd18,
-5'd18,
-5'd18,
-5'd18,
-5'd17,
-5'd16,
-5'd16,
-5'd16,
-5'd11,
-5'd15,
-5'd15,
-5'd14,
-5'd13,
-5'd13,
-5'd12,
-5'd11,
-5'd10,
-5'd10,
-5'd10,
-5'd10,
-5'd9,
-5'd9,
-5'd9,
-5'd9,
-5'd9,
-5'd9,
-5'd8,
-5'd7,
-5'd0,
-5'd6,
-5'd5,
-5'd4,
-5'd3,
-5'd2,
-5'd1,
-5'd0,
-5'd0,
-5'd0,
-5'd0,
-5'd0}
+ {
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd17,
+ 5'd16,
+ 5'd16,
+ 5'd16,
+ 5'd11,
+ 5'd15,
+ 5'd15,
+ 5'd14,
+ 5'd13,
+ 5'd13,
+ 5'd12,
+ 5'd11,
+ 5'd10,
+ 5'd10,
+ 5'd10,
+ 5'd10,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd8,
+ 5'd7,
+ 5'd0,
+ 5'd6,
+ 5'd5,
+ 5'd4,
+ 5'd3,
+ 5'd2,
+ 5'd1,
+ 5'd0,
+ 5'd0,
+ 5'd0,
+ 5'd0,
+ 5'd0
+ }
''',
local: "true"
},
@@ -150,7 +152,68 @@
defines whether the protocol is synchronous (0) or asynchronous (1).
'''
type: "logic [NAlerts-1:0]",
- default: "58'h3ffffffffffffff",
+ default: '''
+ {
+ 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
+ }
+ '''
local: "true"
},
{ name: "N_CLASSES",
diff --git a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv b/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv
index 151974d..cd83f75 100644
--- a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv
+++ b/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv
@@ -10,67 +10,128 @@
parameter int NAlerts = 58;
parameter int NLpg = 20;
parameter int NLpgWidth = 5;
- parameter logic [NAlerts-1:0][NLpgWidth-1:0] LpgMap = {5'd19,
-5'd19,
-5'd19,
-5'd19,
-5'd19,
-5'd19,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd17,
-5'd18,
-5'd18,
-5'd18,
-5'd18,
-5'd18,
-5'd18,
-5'd17,
-5'd16,
-5'd16,
-5'd16,
-5'd11,
-5'd15,
-5'd15,
-5'd14,
-5'd13,
-5'd13,
-5'd12,
-5'd11,
-5'd10,
-5'd10,
-5'd10,
-5'd10,
-5'd9,
-5'd9,
-5'd9,
-5'd9,
-5'd9,
-5'd9,
-5'd8,
-5'd7,
-5'd0,
-5'd6,
-5'd5,
-5'd4,
-5'd3,
-5'd2,
-5'd1,
-5'd0,
-5'd0,
-5'd0,
-5'd0,
-5'd0};
+ parameter logic [NAlerts-1:0][NLpgWidth-1:0] LpgMap = {
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd19,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd17,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd18,
+ 5'd17,
+ 5'd16,
+ 5'd16,
+ 5'd16,
+ 5'd11,
+ 5'd15,
+ 5'd15,
+ 5'd14,
+ 5'd13,
+ 5'd13,
+ 5'd12,
+ 5'd11,
+ 5'd10,
+ 5'd10,
+ 5'd10,
+ 5'd10,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd9,
+ 5'd8,
+ 5'd7,
+ 5'd0,
+ 5'd6,
+ 5'd5,
+ 5'd4,
+ 5'd3,
+ 5'd2,
+ 5'd1,
+ 5'd0,
+ 5'd0,
+ 5'd0,
+ 5'd0,
+ 5'd0
+};
parameter int EscCntDw = 32;
parameter int AccuCntDw = 16;
- parameter logic [NAlerts-1:0] AsyncOn = 58'h3ffffffffffffff;
+ parameter logic [NAlerts-1:0] AsyncOn = {
+ 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
+};
parameter int N_CLASSES = 4;
parameter int N_ESC_SEV = 4;
parameter int N_PHASES = 4;
diff --git a/util/topgen.py b/util/topgen.py
index ebabb61..e2cabd3 100755
--- a/util/topgen.py
+++ b/util/topgen.py
@@ -137,12 +137,12 @@
# default values
esc_cnt_dw = 32
accu_cnt_dw = 16
- async_on = "'0"
+ async_on = []
# leave this constant
n_classes = 4
# low power groups
n_lpg = 1
- lpg_map = "'0"
+ lpg_map = []
topname = top["name"]
@@ -150,8 +150,9 @@
n_alerts = sum([x["width"] if "width" in x else 1 for x in top["alert"]])
n_lpg = len(top['alert_lpgs'])
n_lpg_width = n_lpg.bit_length()
- # format used to print out LPG map indices in binary format
- lpg_idx_format = str(n_lpg_width) + "'d{:d},\n"
+ # format used to print out indices in binary format
+ async_on_format = "1'b{:01b}"
+ lpg_idx_format = str(n_lpg_width) + "'d{:d}"
# Double check that all these values are greated than 0
if esc_cnt_dw < 1:
@@ -167,15 +168,12 @@
n_alerts = 1
log.warning("no alerts are defined in the system")
else:
- async_on = ""
- lpg_map = ""
+ async_on = []
+ lpg_map = []
for alert in top['alert']:
for k in range(alert['width']):
- async_on = str(alert['async']) + async_on
- lpg_map = lpg_idx_format.format(alert['lpg_idx']) + lpg_map
- # convert to hexstring to shorten line length
- async_on = ("%d'h" % n_alerts) + hex(int(async_on, 2))[2:]
- lpg_map = '{' + lpg_map[:-2] + '}'
+ 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)
diff --git a/util/topgen/merge.py b/util/topgen/merge.py
index 56336d6..b28f5c9 100644
--- a/util/topgen/merge.py
+++ b/util/topgen/merge.py
@@ -8,7 +8,7 @@
from collections import OrderedDict
from copy import deepcopy
from math import ceil, log2
-from typing import Dict, List
+from typing import Dict, List, Union, Tuple
from topgen import c, lib
from .clocks import Clocks
@@ -521,6 +521,26 @@
return None
+def _get_clock_group_name(clk: Union[str, OrderedDict], default_ep_grp) -> Tuple[str, str]:
+ """Return the clock group of a particular clock connection
+
+ Checks whether there is a specific clock group associated with this
+ connection and returns its name. If not, this returns the default clock
+ group of the clock end point.
+ """
+ # If the value of a particular connection is a dict,
+ # there are additional attributes to explore
+ if isinstance(clk, str):
+ group_name = default_ep_grp
+ src_name = clk
+ else:
+ assert isinstance(clk, Dict)
+ group_name = clk.get('group', default_ep_grp)
+ src_name = clk['clock']
+
+ return group_name, src_name
+
+
def extract_clocks(top: OrderedDict):
'''Add clock exports to top and connections to endpoints
@@ -559,15 +579,7 @@
for port, clk in ep['clock_srcs'].items():
- # If the value of a particular connection is a dict,
- # there are additional attributes to explore
- if isinstance(clk, str):
- group_name = ep_grp
- src_name = clk
- else:
- assert isinstance(clk, Dict)
- group_name = clk.get('group', ep_grp)
- src_name = clk['clock']
+ group_name, src_name = _get_clock_group_name(clk, ep_grp)
group = clocks.groups[group_name]
@@ -767,7 +779,8 @@
top['alert_lpgs'] = []
for module in top["module"]:
# the alert senders are attached to the primary clock of this block,
- # so let's start by getting that primary clock.
+ # so let's start by getting that primary clock port of an IP (we need
+ # that to look up the clock connection at the top-level).
block = name_to_block[module['type']]
block_clock = block.get_primary_clock()
primary_reset = module['reset_connections'][block_clock.reset]
@@ -776,7 +789,13 @@
# 1) the clock group of the primary clock
# 2) the primary reset name
# 3) the domain of the primary reset
- clock_group = module['clock_group']
+ #
+ # 1) need to figure out whether the primary clock has a
+ # specific clock group assignment or not
+ clk = module['clock_srcs'][block_clock.clock]
+ clock_group, _ = _get_clock_group_name(clk, module['clock_group'])
+
+ # 2-3) get reset info
reset_name = primary_reset['name']
reset_domain = primary_reset['domain']
diff --git a/util/topgen/resets.py b/util/topgen/resets.py
index 1dd1e8f..85d22eb 100644
--- a/util/topgen/resets.py
+++ b/util/topgen/resets.py
@@ -155,7 +155,6 @@
return path
-
def get_lpg_path(self, name: str, domain: Optional[str]) -> str:
'''Get path to lpg indication signals'''
@@ -164,7 +163,7 @@
raise ValueError(f'Reset {name} is not a reset exported from rstmgr')
if reset.rst_type == 'ext':
- raise ValueError(f'External reset cannot be associated with an LPG')
+ raise ValueError(f'External reset {name} cannot be associated with an LPG')
path = reset.lpg_path
if domain:
@@ -172,7 +171,6 @@
return path
-
def get_unused_resets(self, domains: list) -> Dict[str, str]:
'''Get unused resets'''