blob: 0f6480a6086f6236a38c5d6183a3dbc001880536 [file] [log] [blame]
Miles Dai7a881fc2022-09-09 16:20:55 -04001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
5"""Rules for generating OTP images.
6
Miles Dai8a010642022-10-11 13:34:29 -04007OTP image generation begins with producing one or more (H)JSON files that
8describe the OTP configuration. These files are then consumed by the OTP image
9generation tool to produce the OTP VMEM image file used to preload the OTP in
10FPGA synthesis or simulation.
11
12The JSON file generation is handled by the otp_json rule, which accepts a list
13of partitions. Due to Bazel's limited datatypes for rule attributes, a helper
14function (otp_partition) is used to serialize the representation of each
15partition to pass it into otp_json as a string.
16
17Usage example:
18otp_json(
19 name = "example_otp_json",
20 partitions = [
21 otp_partition(
22 name = "Partition0",
23 lock = True,
24 items = {
25 "ITEM_1": "abc",
26 "ITEM_2": "<random>",
27 }
28 ),
29 otp_partition(...),
30 ],
31)
32
33Note that the "items" dictionary for each partition should be expressed as
34{"key": "value"} mappings. This will be expanded by the otp_json rule into a
35list of dicts, each of the form {"name": key, "value": value}, which is the
36format expected by the image generation tool.
Miles Dai7a881fc2022-09-09 16:20:55 -040037"""
38
Timothy Trippelefafefb2022-11-04 14:32:38 -070039load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
Alexander Williams419f8462022-11-07 14:37:08 -080040load("//rules:host.bzl", "host_tools_transition")
Timothy Trippelefafefb2022-11-04 14:32:38 -070041
Dan McArdle8175ae02022-10-15 18:28:26 -040042def get_otp_images():
43 """Returns a list of (otp_name, img_target) tuples.
44
45 Each tuple corresponds to an OTP image defined in //hw/ip/otp_ctrl/data. The
46 otp_name is a short, unique suffix of the image target, e.g. "rma". The
47 img_target is the full path of the OTP image target.
48 """
49
50 img_targets = [
51 "//hw/ip/otp_ctrl/data:img_dev",
52 "//hw/ip/otp_ctrl/data:img_rma",
53 "//hw/ip/otp_ctrl/data:img_test_unlocked0",
54 "//hw/ip/otp_ctrl/data:img_prod",
Johnathan Van Whyc2caa252022-11-02 12:59:26 -070055 "//hw/ip/otp_ctrl/data:img_prod_end",
Dan McArdle8175ae02022-10-15 18:28:26 -040056 "//hw/ip/otp_ctrl/data:img_exec_disabled",
Chris Frantz57ad9502022-10-28 11:30:56 -070057 "//hw/ip/otp_ctrl/data:img_bootstrap_disabled",
Dan McArdle8175ae02022-10-15 18:28:26 -040058 ]
59
60 out = []
61 for img_target in img_targets:
62 [_, img_target_name] = img_target.rsplit(":")
63 otp_name = img_target_name.removeprefix("img_")
64 out.append((
65 otp_name,
66 img_target,
67 ))
68 return out
69
Miles Dai8a010642022-10-11 13:34:29 -040070def otp_partition(name, **kwargs):
71 partition = {
72 "name": name,
73 }
74 partition.update(kwargs)
75 return json.encode(partition)
76
Miles Dai7a881fc2022-09-09 16:20:55 -040077def _otp_json_impl(ctx):
Miles Dai7a881fc2022-09-09 16:20:55 -040078 otp = {}
Miles Dai8a010642022-10-11 13:34:29 -040079 if ctx.attr.seed != "":
80 otp["seed"] = ctx.attr.seed
81 otp["partitions"] = [json.decode(p) for p in ctx.attr.partitions]
Miles Dai7a881fc2022-09-09 16:20:55 -040082
83 # For every partition with an "items" dictionary, expand the dictionary of
84 # key:value pairs into a list of dicts, each of the form
85 # {
86 # "name": key,
87 # "value": value
88 # }
89 # This format is expected by the OTP image generation tool
90 for partition in otp["partitions"]:
91 if "items" in partition.keys():
92 items = partition["items"]
Miles Dai9f3e3692023-01-11 14:55:09 -050093 partition["items"] = [{"name": k, "value": v} for k, v in items.items()]
Miles Dai7a881fc2022-09-09 16:20:55 -040094
95 file = ctx.actions.declare_file("{}.json".format(ctx.attr.name))
96 ctx.actions.write(file, json.encode_indent(otp))
Miles Dai8a010642022-10-11 13:34:29 -040097 return [DefaultInfo(files = depset([file]))]
Miles Dai7a881fc2022-09-09 16:20:55 -040098
99otp_json = rule(
100 implementation = _otp_json_impl,
101 attrs = {
Miles Dai8a010642022-10-11 13:34:29 -0400102 "seed": attr.string(
103 doc = "Seed to be used for generation of partition randomized values. Can be overridden by the OTP image generation tool.",
104 ),
105 "partitions": attr.string_list(doc = "A list of serialized partitions from otp_partition."),
Miles Dai7a881fc2022-09-09 16:20:55 -0400106 },
107)
Miles Daif89fce82022-09-12 22:40:01 -0400108
Jon Flatleyb0e0bf82022-11-01 16:24:20 -0400109def _otp_alert_digest_impl(ctx):
110 file = ctx.actions.declare_file("{}.json".format(ctx.attr.name))
111
112 outputs = [file]
113
114 inputs = [
115 ctx.file._opentitantool,
116 ctx.file.otp_img,
117 ]
118
119 args = ctx.actions.args()
Alexander Williams419f8462022-11-07 14:37:08 -0800120 args.add_all(("--rcfile=", "otp", "alert-digest", ctx.file.otp_img))
Jon Flatleyb0e0bf82022-11-01 16:24:20 -0400121 args.add("--output", file)
122
123 ctx.actions.run(
124 outputs = outputs,
125 inputs = inputs,
126 arguments = [args],
127 executable = ctx.file._opentitantool.path,
128 )
129
130 return [DefaultInfo(files = depset([file]))]
131
132otp_alert_digest = rule(
133 implementation = _otp_alert_digest_impl,
134 attrs = {
135 "otp_img": attr.label(
136 allow_single_file = [".json", ".hjson"],
137 doc = "The OTP image file containing alert_handler values.",
138 ),
139 "_opentitantool": attr.label(
140 default = "//sw/host/opentitantool:opentitantool",
141 allow_single_file = True,
Alexander Williams419f8462022-11-07 14:37:08 -0800142 executable = True,
143 cfg = host_tools_transition,
144 ),
145 "_allowlist_function_transition": attr.label(
146 default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
Jon Flatleyb0e0bf82022-11-01 16:24:20 -0400147 ),
148 },
149)
150
Miles Daif89fce82022-09-12 22:40:01 -0400151def _otp_image(ctx):
152 output = ctx.actions.declare_file(ctx.attr.name + ".24.vmem")
153 args = ctx.actions.args()
Miles Dai8a010642022-10-11 13:34:29 -0400154 if not ctx.attr.verbose:
155 args.add("--quiet")
Miles Daif89fce82022-09-12 22:40:01 -0400156 args.add("--lc-state-def", ctx.file.lc_state_def)
157 args.add("--mmap-def", ctx.file.mmap_def)
Timothy Trippelefafefb2022-11-04 14:32:38 -0700158 if ctx.attr.img_seed:
159 args.add("--img-seed", ctx.attr.img_seed[BuildSettingInfo].value)
Michael Schaffnera67db352022-11-29 16:31:15 -0800160 if ctx.attr.lc_seed:
161 args.add("--lc-seed", ctx.attr.lc_seed[BuildSettingInfo].value)
Timothy Trippelefafefb2022-11-04 14:32:38 -0700162 if ctx.attr.otp_seed:
163 args.add("--otp-seed", ctx.attr.otp_seed[BuildSettingInfo].value)
Miles Daif89fce82022-09-12 22:40:01 -0400164 args.add("--img-cfg", ctx.file.src)
Miles Dai8a010642022-10-11 13:34:29 -0400165 args.add_all(ctx.files.overlays, before_each = "--add-cfg")
Miles Daif89fce82022-09-12 22:40:01 -0400166 args.add("--out", "{}/{}.BITWIDTH.vmem".format(output.dirname, ctx.attr.name))
167 ctx.actions.run(
168 outputs = [output],
169 inputs = [
170 ctx.file.src,
171 ctx.file.lc_state_def,
172 ctx.file.mmap_def,
Miles Dai8a010642022-10-11 13:34:29 -0400173 ] + ctx.files.overlays,
Miles Daif89fce82022-09-12 22:40:01 -0400174 arguments = [args],
175 executable = ctx.executable._tool,
176 )
177 return [DefaultInfo(files = depset([output]), runfiles = ctx.runfiles(files = [output]))]
178
179otp_image = rule(
180 implementation = _otp_image,
181 attrs = {
Miles Dai8a010642022-10-11 13:34:29 -0400182 "src": attr.label(
183 allow_single_file = [".json", ".hjson"],
184 doc = "Image configuration file in Hjson format.",
185 ),
186 "overlays": attr.label_list(
187 allow_files = [".json", ".hjson"],
188 doc = "Additional image configuration file(s) in Hjson format to override src. Overlays are applied in the order provided.",
189 ),
Miles Daif89fce82022-09-12 22:40:01 -0400190 "lc_state_def": attr.label(
191 allow_single_file = True,
192 default = "//hw/ip/lc_ctrl/data:lc_ctrl_state.hjson",
193 doc = "Life-cycle state definition file in Hjson format.",
194 ),
195 "mmap_def": attr.label(
196 allow_single_file = True,
197 default = "//hw/ip/otp_ctrl/data:otp_ctrl_mmap.hjson",
198 doc = "OTP Controller memory map file in Hjson format.",
199 ),
Timothy Trippelefafefb2022-11-04 14:32:38 -0700200 "img_seed": attr.label(
201 default = "//hw/ip/otp_ctrl/data:img_seed",
202 doc = "Configuration override seed used to randomize field values in an OTP image.",
203 ),
Michael Schaffnera67db352022-11-29 16:31:15 -0800204 "lc_seed": attr.label(
205 default = "//hw/ip/otp_ctrl/data:lc_seed",
206 doc = "Configuration override seed used to randomize LC netlist constants.",
207 ),
Timothy Trippelefafefb2022-11-04 14:32:38 -0700208 "otp_seed": attr.label(
209 default = "//hw/ip/otp_ctrl/data:otp_seed",
210 doc = "Configuration override seed used to randomize OTP netlist constants.",
211 ),
Miles Dai8a010642022-10-11 13:34:29 -0400212 "verbose": attr.bool(
213 default = False,
214 doc = "Display progress messages from image-generation tool.",
215 ),
Miles Daif89fce82022-09-12 22:40:01 -0400216 "_tool": attr.label(
217 default = "//util/design:gen-otp-img",
218 executable = True,
219 cfg = "exec",
220 ),
221 },
222)
Miles Daia0da3fc2022-11-08 15:43:58 -0500223
224# This is a set of overlays to generate a generic, standard OTP image.
225# Additional overlays can be applied on top to further customize the OTP.
226STD_OTP_OVERLAYS = [
227 "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg",
228 "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg",
229 "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg",
230 "//hw/ip/otp_ctrl/data:otp_json_hw_cfg",
231]