Skip to content

Commit 0db15f3

Browse files
[racl,raclgen,topgen] Deduplicate RACL templates
Signed-off-by: David Schrammel <davidschrammel@rivosinc.com>
1 parent bc24f2d commit 0db15f3

File tree

10 files changed

+129
-162
lines changed

10 files changed

+129
-162
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<%doc>
2+
// Copyright lowRISC contributors (OpenTitan project).
3+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
4+
// SPDX-License-Identifier: Apache-2.0
5+
</%doc>\
6+
<%page args="m, top"/>\
7+
% if 'racl_mappings' in m:
8+
.EnableRacl(1'b1),
9+
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
10+
% for if_name, mappings in m['racl_mappings'].items():
11+
<%
12+
register_mapping = mappings.get('register_mapping', {})
13+
window_mapping = mappings.get('window_mapping', {})
14+
range_mapping = mappings.get('range_mapping', [])
15+
racl_group = mappings.get('racl_group')
16+
group_suffix = f"_{racl_group.upper()}" if racl_group and racl_group != "Null" else ""
17+
if_suffix = f"_{if_name.upper()}" if if_name else ""
18+
if_suffix2 = f"{if_name.title()}" if if_name else ""
19+
policy_sel_name = f"RACL_POLICY_SEL_{m['name'].upper()}{group_suffix}{if_suffix}"
20+
%>\
21+
% if len(register_mapping) > 0:
22+
.RaclPolicySelVec${if_suffix2}(top_racl_pkg::${policy_sel_name}),
23+
% endif
24+
% for window_name, policy_idx in window_mapping.items():
25+
.RaclPolicySelWin${if_suffix2}${window_name.replace("_","").title()}(top_racl_pkg::${policy_sel_name}_WIN_${window_name.upper()}),
26+
% endfor
27+
% if len(range_mapping) > 0:
28+
.RaclPolicySelRanges${if_suffix2}Num(top_racl_pkg::${policy_sel_name}_NUM_RANGES),
29+
.RaclPolicySelRanges${if_suffix2}(top_racl_pkg::${policy_sel_name}_RANGES),
30+
% endif
31+
% endfor
32+
% endif
33+
% if m.get('template_type') == 'racl_ctrl':
34+
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
35+
% endif

hw/top_darjeeling/templates/toplevel.sv.tpl

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -485,39 +485,7 @@ max_intrwidth = (max(len(x.name) for x in block.interrupts)
485485
%>\
486486
% if m["param_list"] or block.alerts:
487487
${m["type"]} #(
488-
<%doc>
489-
Note: The RACL parameters must be generated identically across multiple files.
490-
Thus, this template needs to be manually synced between the following files:
491-
util/raclgen.py
492-
util/topgen/templates/toplevel_racl_pkg.sv.tpl
493-
hw/top_darjeeling/templates/toplevel.sv.tpl
494-
hw/top_earlgrey/templates/toplevel.sv.tpl
495-
hw/top_englishbreakfast/templates/toplevel.sv.tpl
496-
</%doc>\
497-
% if 'racl_mappings' in m:
498-
.EnableRacl(1'b1),
499-
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
500-
% for if_name in m['racl_mappings'].keys():
501-
<%
502-
register_mapping = m['racl_mappings'][if_name]['register_mapping']
503-
window_mapping = m['racl_mappings'][if_name]['window_mapping']
504-
racl_group = m['racl_mappings'][if_name]['racl_group']
505-
group_suffix = f"_{racl_group.upper()}" if racl_group and racl_group != "Null" else ""
506-
if_suffix = f"_{if_name.upper()}" if if_name else ""
507-
if_suffix2 = f"{if_name.title()}" if if_name else ""
508-
policy_sel_name = f"RACL_POLICY_SEL_{m['name'].upper()}{group_suffix}{if_suffix}"
509-
%>\
510-
% if len(register_mapping) > 0:
511-
.RaclPolicySelVec${if_suffix2}(top_racl_pkg::${policy_sel_name}),
512-
% endif
513-
% for window_name, policy_idx in window_mapping.items():
514-
.RaclPolicySelWin${if_suffix2}${window_name.replace("_","").title()}(top_racl_pkg::${policy_sel_name}_WIN_${window_name.upper()}),
515-
% endfor
516-
% endfor
517-
% endif
518-
% if m.get('template_type') == 'racl_ctrl':
519-
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
520-
% endif
488+
<%include file="racl.sv.tpl" args="m=m,top=top"/>\
521489
% if block.alerts:
522490
<%
523491
w = len(block.alerts)

hw/top_earlgrey/templates/racl.sv.tpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../top_darjeeling/templates/racl.sv.tpl

hw/top_earlgrey/templates/toplevel.sv.tpl

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -502,39 +502,7 @@ max_intrwidth = (max(len(x.name) for x in block.interrupts)
502502
%>\
503503
% if m["param_list"] or block.alerts:
504504
${m["type"]} #(
505-
<%doc>
506-
Note: The RACL parameters must be generated identically across multiple files.
507-
Thus, this template needs to be manually synced between the following files:
508-
util/raclgen.py
509-
util/topgen/templates/toplevel_racl_pkg.sv.tpl
510-
hw/top_darjeeling/templates/toplevel.sv.tpl
511-
hw/top_earlgrey/templates/toplevel.sv.tpl
512-
hw/top_englishbreakfast/templates/toplevel.sv.tpl
513-
</%doc>\
514-
% if 'racl_mappings' in m:
515-
.EnableRacl(1'b1),
516-
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
517-
% for if_name in m['racl_mappings'].keys():
518-
<%
519-
register_mapping = m['racl_mappings'][if_name]['register_mapping']
520-
window_mapping = m['racl_mappings'][if_name]['window_mapping']
521-
racl_group = m['racl_mappings'][if_name]['racl_group']
522-
group_suffix = f"_{racl_group.upper()}" if racl_group and racl_group != "Null" else ""
523-
if_suffix = f"_{if_name.upper()}" if if_name else ""
524-
if_suffix2 = f"{if_name.title()}" if if_name else ""
525-
policy_sel_name = f"RACL_POLICY_SEL_{m['name'].upper()}{group_suffix}{if_suffix}"
526-
%>\
527-
% if len(register_mapping) > 0:
528-
.RaclPolicySelVec${if_suffix2}(top_racl_pkg::${policy_sel_name}),
529-
% endif
530-
% for window_name, policy_idx in window_mapping.items():
531-
.RaclPolicySelWin${if_suffix2}${window_name.replace("_","").title()}(top_racl_pkg::${policy_sel_name}_WIN_${window_name.upper()}),
532-
% endfor
533-
% endfor
534-
% endif
535-
% if m.get('template_type') == 'racl_ctrl':
536-
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
537-
% endif
505+
<%include file="racl.sv.tpl" args="m=m,top=top"/>\
538506
% if block.alerts:
539507
<%
540508
w = len(block.alerts)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../top_darjeeling/templates/racl.sv.tpl

util/raclgen.py

Lines changed: 15 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
def main():
1717
parser = argparse.ArgumentParser()
1818

19+
parser.add_argument('--template',
20+
'-t',
21+
default='util/topgen/templates/toplevel_racl_pkg_parameters.sv.tpl',
22+
help='Path to template file.')
23+
1924
parser.add_argument('--racl-config',
2025
'-r',
2126
required=True,
@@ -50,60 +55,18 @@ def main():
5055
raise SystemExit(
5156
f'Failed to parse RACL config "{args.racl_config}". Error: {err}')
5257

53-
parsed_register_mapping, parsed_window_mapping, racl_group, policy_names = parse_racl_mapping(
58+
register_mapping, window_mapping, racl_group, policy_names = parse_racl_mapping(
5459
parsed_racl_config, args.mapping, args.if_name, ip_block)
5560

56-
template = """\
57-
<%doc>
58-
Note: The RACL parameters must be generated identically across multiple files.
59-
Thus, this template needs to be manually synced between the following files:
60-
util/raclgen.py
61-
util/topgen/templates/toplevel_racl_pkg.sv.tpl
62-
hw/top_darjeeling/templates/toplevel.sv.tpl
63-
hw/top_earlgrey/templates/toplevel.sv.tpl
64-
hw/top_englishbreakfast/templates/toplevel.sv.tpl
65-
</%doc>\
66-
<% import math %>\
67-
<% policy_idx_len = math.ceil(math.log10(max(1,len(policy_names)+1))) %>\
68-
<% group_suffix = f"_{racl_group.upper()}" if racl_group and racl_group != "Null" else "" %>\
69-
<% if_suffix = f"_{if_name.upper()}" if if_name else "" %>\
70-
<% reg_name_len = max( (len(name) for name in register_mapping.keys()), default=0 ) %>\
71-
<% window_name_len = max( (len(name) for name in window_mapping.keys()), default=0 ) %>\
72-
/**
73-
* Policy selection vector for ${module_name}
74-
* TLUL interface name: ${if_name}
75-
* RACL group: ${racl_group}
76-
% if len(register_mapping) > 0:
77-
* Register to policy mapping:
78-
% for reg_name, policy_idx in register_mapping.items():
79-
* ${f"{reg_name}:".ljust(reg_name_len+1)} ${policy_names[policy_idx]} \
80-
(Idx ${f"{policy_idx}".rjust(policy_idx_len)})
81-
% endfor
82-
% endif
83-
% if len(window_mapping) > 0:
84-
* Window to policy mapping:
85-
% for window_name, policy_idx in window_mapping.items():
86-
* ${f"{window_name}:".ljust(window_name_len+1)} ${policy_names[policy_idx]} \
87-
(Idx ${f"{policy_idx}".rjust(policy_idx_len)})
88-
% endfor
89-
% endif
90-
*/
91-
<% policy_sel_name = f"RACL_POLICY_SEL_{module_name.upper()}{group_suffix}{if_suffix}" %>\
92-
<% policy_sel_value = "'{" + ", ".join(map(str, reversed(register_mapping.values()))) + "};" %>\
93-
parameter racl_policy_sel_t ${policy_sel_name} [${len(register_mapping)}] = ${policy_sel_value}
94-
% for window_name, policy_idx in window_mapping.items():
95-
parameter racl_policy_sel_t ${policy_sel_name}_WIN_${window_name.upper()} = ${policy_idx};
96-
% endfor
97-
"""
98-
99-
print(
100-
Template(template).render(m=ip_block,
101-
if_name=args.if_name,
102-
register_mapping=parsed_register_mapping,
103-
window_mapping=parsed_window_mapping,
104-
policy_names=policy_names,
105-
module_name=ip_block.name,
106-
racl_group=racl_group).rstrip())
61+
print(Template(filename=args.template).render(
62+
register_mapping=register_mapping,
63+
window_mapping=window_mapping,
64+
range_mapping=[], # FIXME include range changes from #26094
65+
policy_names=policy_names,
66+
racl_group=racl_group,
67+
module_name=ip_block.name,
68+
if_name=args.if_name
69+
).rstrip())
10770

10871

10972
if __name__ == '__main__':

util/raclgen/lib.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import hjson
1111
from reggen.ip_block import IpBlock
1212
from reggen.validate import check_keys
13+
from mako.template import Template
1314

1415
# Required fields for the RACL hjson
1516
racl_required = {

util/topgen.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from design.lib.OtpMemMap import OtpMemMap
2323
from mako import exceptions
2424
from mako.template import Template
25+
from mako.lookup import TemplateLookup
2526
from raclgen.lib import DEFAULT_RACL_CONFIG, parse_racl_config, parse_racl_mapping
2627
from reggen import access, gen_rtl, gen_sec_cm_testplan, window
2728
from reggen.countermeasure import CounterMeasure
@@ -95,7 +96,7 @@ def ipgen_render(template_name: str, topname: str, params: Dict[str, object],
9596

9697
def generate_top(top: Dict[str, object], name_to_block: Dict[str, IpBlock],
9798
tpl_filename: str, **kwargs: Dict[str, object]) -> None:
98-
top_tpl = Template(filename=tpl_filename)
99+
top_tpl = Template(filename=tpl_filename, lookup=TemplateLookup(["/"]))
99100

100101
try:
101102
return top_tpl.render(top=top, name_to_block=name_to_block, **kwargs)

util/topgen/templates/toplevel_racl_pkg.sv.tpl

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,7 @@ package top_racl_pkg;
118118
% endfor
119119
% endfor
120120

121-
<%doc>
122-
Note: The RACL parameters must be generated identically across multiple files.
123-
Thus, this template needs to be manually synced between the following files:
124-
util/raclgen.py
125-
util/topgen/templates/toplevel_racl_pkg.sv.tpl
126-
hw/top_darjeeling/templates/toplevel.sv.tpl
127-
hw/top_earlgrey/templates/toplevel.sv.tpl
128-
hw/top_englishbreakfast/templates/toplevel.sv.tpl
129-
</%doc>\
121+
<% import raclgen.lib as raclgen %>\
130122
<% import math %>\
131123
% if 'racl' in topcfg:
132124
<% policy_names = [policy['name'] for policy in topcfg['racl']['policies'][racl_group]] %>\
@@ -145,40 +137,19 @@ package top_racl_pkg;
145137
% endif
146138
% for m in topcfg['module']:
147139
% if 'racl_mappings' in m:
148-
% for if_name in m['racl_mappings'].keys():
149-
<% register_mapping = m['racl_mappings'][if_name]['register_mapping'] %>\
150-
<% window_mapping = m['racl_mappings'][if_name]['window_mapping'] %>\
151-
<% racl_group = m['racl_mappings'][if_name]['racl_group'] %>\
152-
<% group_suffix = f"_{racl_group.upper()}" if racl_group and racl_group != "Null" else "" %>\
153-
<% if_suffix = f"_{if_name.upper()}" if if_name else "" %>\
154-
<% reg_name_len = max( (len(name) for name in register_mapping.keys()), default=0 ) %>\
155-
<% window_name_len = max( (len(name) for name in window_mapping.keys()), default=0 ) %>\
156-
/**
157-
* Policy selection vector for ${m["name"]}
158-
* TLUL interface name: ${if_name}
159-
* RACL group: ${racl_group}
160-
% if len(register_mapping) > 0:
161-
* Register to policy mapping:
162-
% for reg_name, policy_idx in register_mapping.items():
163-
* ${f"{reg_name}:".ljust(reg_name_len+1)} ${policy_names[policy_idx]} (Idx ${f"{policy_idx}".rjust(policy_idx_len)})
164-
% endfor
165-
% endif
166-
% if len(window_mapping) > 0:
167-
* Window to policy mapping:
168-
% for window_name, policy_idx in window_mapping.items():
169-
* ${f"{window_name}:".ljust(window_name_len+1)} ${policy_names[policy_idx]} (Idx ${f"{policy_idx}".rjust(policy_idx_len)})
170-
% endfor
171-
% endif
172-
*/
173-
<% policy_sel_name = f"RACL_POLICY_SEL_{m['name'].upper()}{group_suffix}{if_suffix}" %>\
174-
<% policy_sel_value = ", ".join(map(str, reversed(register_mapping.values())))%>\
175-
<% policy_sel_value = "\n ".join(textwrap.wrap(policy_sel_value, 94))%>\
176-
parameter racl_policy_sel_t ${policy_sel_name} [${len(register_mapping)}] = '{
177-
${policy_sel_value}
178-
};
179-
% for window_name, policy_idx in window_mapping.items():
180-
parameter racl_policy_sel_t ${policy_sel_name}_WIN_${window_name.upper()} = ${policy_idx};
181-
% endfor
140+
% for if_name, mappings in m['racl_mappings'].items():
141+
<%
142+
racl_tpl_args = {
143+
"register_mapping" : mappings.get('register_mapping', {}),
144+
"window_mapping" : mappings.get('window_mapping', {}),
145+
"range_mapping" : mappings.get('range_mapping', []),
146+
"policy_names" : policy_names,
147+
"racl_group" : mappings['racl_group'],
148+
"module_name" : m['name'],
149+
"if_name" : if_name
150+
}
151+
%>\
152+
<%include file="toplevel_racl_pkg_parameters.sv.tpl" args="**racl_tpl_args"/>\
182153

183154
% endfor
184155
% endif
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<%doc>
2+
// Copyright lowRISC contributors (OpenTitan project).
3+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
4+
// SPDX-License-Identifier: Apache-2.0
5+
</%doc>\
6+
<%page args="register_mapping, window_mapping, range_mapping, policy_names, racl_group, module_name, if_name"/>\
7+
<% import textwrap %>\
8+
<% import math %>\
9+
<% policy_idx_len = math.ceil(math.log10(max(1,len(policy_names)+1))) %>\
10+
<% group_suffix = f"_{racl_group.upper()}" if racl_group and racl_group != "Null" else "" %>\
11+
<% if_suffix = f"_{if_name.upper()}" if if_name else "" %>\
12+
<% reg_name_len = max( (len(name) for name in register_mapping.keys()), default=0 ) %>\
13+
<% window_name_len = max( (len(name) for name in window_mapping.keys()), default=0 ) %>\
14+
<% policy_sel_name = f"RACL_POLICY_SEL_{module_name.upper()}{group_suffix}{if_suffix}" %>\
15+
/**
16+
* Policy selection vector for ${module_name}
17+
* TLUL interface name: ${if_name}
18+
* RACL group: ${racl_group}
19+
% if len(register_mapping) > 0:
20+
* Register to policy mapping:
21+
% for reg_name, policy_idx in register_mapping.items():
22+
* ${f"{reg_name}:".ljust(reg_name_len+1)} ${policy_names[policy_idx]} \
23+
(Idx ${f"{policy_idx}".rjust(policy_idx_len)})
24+
% endfor
25+
% endif
26+
% if len(window_mapping) > 0:
27+
* Window to policy mapping:
28+
% for window_name, policy_idx in window_mapping.items():
29+
* ${f"{window_name}:".ljust(window_name_len+1)} ${policy_names[policy_idx]} \
30+
(Idx ${f"{policy_idx}".rjust(policy_idx_len)})
31+
% endfor
32+
% endif
33+
% if len(range_mapping) > 0:
34+
* Range to policy mapping:
35+
% for range in range_mapping:
36+
* ${f"0x{range['base']:08x}"} -- ${f"0x{(range['base']+range['size']):08x}"} \
37+
policy: ${policy_names[range['policy']]} (Idx ${f"{range['policy']}".rjust(policy_idx_len)})
38+
% endfor
39+
% endif
40+
*/
41+
% if len(register_mapping) > 0:
42+
<% policy_sel_value = ", ".join(map(str, reversed(register_mapping.values())))%>\
43+
<% policy_sel_value = "\n ".join(textwrap.wrap(policy_sel_value, 94))%>\
44+
parameter racl_policy_sel_t ${policy_sel_name} [${len(register_mapping)}] = '{
45+
${policy_sel_value}
46+
};
47+
% endif
48+
% for window_name, policy_idx in window_mapping.items():
49+
parameter racl_policy_sel_t ${policy_sel_name}_WIN_${window_name.upper()} = ${policy_idx};
50+
% endfor
51+
% if len(range_mapping) > 0:
52+
parameter racl_policy_sel_t ${policy_sel_name}_NUM_RANGES = ${len(range_mapping)};
53+
<% fmt_range = "'{{base:'h{base:x},mask:'h{mask:x},policy:{policy}}}" %>\
54+
<% value = ",\n".join(map(fmt_range.format_map, range_mapping)) %>\
55+
parameter racl_range_t ${policy_sel_name}_RANGES [${len(range_mapping)}] = '{
56+
${value}
57+
};
58+
% endif

0 commit comments

Comments
 (0)