blob: 5f38404a29c5594fa83fbb1556c65ab0d9cc61b2 [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4"""
5Generates the documentation for the register tool
6
7"""
Rupert Swarbrickc5b38152021-02-04 09:43:19 +00008from .access import SWACCESS_PERMITTED, HWACCESS_PERMITTED
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +00009from reggen import (validate,
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000010 ip_block, enum_entry, field,
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +000011 register, multi_register, window)
lowRISC Contributors802543a2019-08-31 12:12:56 +010012
13
14def genout(outfile, msg):
15 outfile.write(msg)
16
17
18doc_intro = """
19
Rupert Swarbrick11042032020-11-25 10:32:04 +000020<!-- Start of output generated by `regtool.py --doc` -->
lowRISC Contributors802543a2019-08-31 12:12:56 +010021
22The tables describe each key and the type of the value. The following
23types are used:
24
25Type | Description
26---- | -----------
27"""
28
29swaccess_intro = """
30
31Register fields are tagged using the swaccess key to describe the
32permitted access and side-effects. This key must have one of these
33values:
34
35"""
36
37hwaccess_intro = """
38
39Register fields are tagged using the hwaccess key to describe the
40permitted access from hardware logic and side-effects. This key must
41have one of these values:
42
43"""
44
45top_example = """
46The basic structure of a register definition file is thus:
47
48```hjson
49{
50 name: "GP",
51 regwidth: "32",
52 registers: [
53 // register definitions...
54 ]
55}
56
57```
58
59"""
60
61register_example = """
62
63The basic register definition group will follow this pattern:
64
65```hjson
66 { name: "REGA",
67 desc: "Description of register",
68 swaccess: "rw",
69 resval: "42",
70 fields: [
71 // bit field definitions...
72 ]
73 }
74```
75
76The name and brief description are required. If the swaccess key is
77provided it describes the access pattern that will be used by all
78bitfields in the register that do not override with their own swaccess
79key. This is a useful shortcut because in most cases a register will
80have the same access restrictions for all fields. The reset value of
81the register may also be provided here or in the individual fields. If
82it is provided in both places then they must match, if it is provided
83in neither place then the reset value defaults to zero for all except
84write-only fields when it defaults to x.
85
86"""
87
88field_example = """
89
90Field names should be relatively short because they will be used
91frequently (and need to fit in the register layout picture!) The field
92description is expected to be longer and will most likely make use of
Philipp Wagner14a3fee2019-11-21 10:07:02 +000093the Hjson ability to include multi-line strings. An example with three
lowRISC Contributors802543a2019-08-31 12:12:56 +010094fields:
95
96```hjson
97 fields: [
98 { bits: "15:0",
99 name: "RXS",
100 desc: '''
101 Last 16 oversampled values of RX. These are captured at 16x the baud
102 rate clock. This is a shift register with the most recent bit in
103 bit 0 and the oldest in bit 15. Only valid when ENRXS is set.
104 '''
105 }
106 { bits: "16",
107 name: "ENRXS",
108 desc: '''
109 If this bit is set the receive oversampled data is collected
110 in the RXS field.
111 '''
112 }
113 {bits: "20:19", name: "TXILVL",
114 desc: "Trigger level for TX interrupts",
115 resval: "2",
116 enum: [
117 { value: "0", name: "txlvl1", desc: "1 character" },
118 { value: "1", name: "txlvl4", desc: "4 characters" },
119 { value: "2", name: "txlvl8", desc: "8 characters" },
120 { value: "3", name: "txlvl16", desc: "16 characters" }
121 ]
122 }
123 ]
124```
125
126In all of these the swaccess parameter is inherited from the register
127level, and will be added so this key is always available to the
128backend. The RXS and ENRXS will default to zero reset value (unless
129something different is provided for the register) and will have the
130key added, but TXILVL expicitly sets its reset value as 2.
131
132The missing bits 17 and 18 will be treated as reserved by the tool, as
133will any bits between 21 and the maximum in the register.
134
135The TXILVL is an example using an enumeration to specify all valid
136values for the field. In this case all possible values are described,
137if the list is incomplete then the field is marked with the rsvdenum
138key so the backend can take appropriate action. (If the enum field is
139more than 7 bits then the checking is not done.)
140
141"""
142
143offset_intro = """
144
145"""
146
147multi_intro = """
148
149The multireg expands on the register required fields and will generate
150a list of the generated registers (that contain all required and
151generated keys for an actual register).
152
153"""
154
155window_intro = """
156
157A window defines an open region of the register space that can be used
158for things that are not registers (for example access to a buffer ram).
159
160"""
161
162regwen_intro = """
163
164Registers can protect themselves from software writes by using the
165register attribute regwen. When not an emptry string (the default
166value), regwen indicates that another register must be true in order
167to allow writes to this register. This is useful for the prevention
168of software modification. The register-enable register (call it
169REGWEN) must be one bit in width, and should default to 1 and be rw1c
170for preferred security control. This allows all writes to proceed
171until at some point software disables future modifications by clearing
172REGWEN. An error is reported if REGWEN does not exist, contains more
173than one bit, is not `rw1c` or does not default to 1. One REGWEN can
Scott Johnson3976f9f2020-05-20 13:54:40 -0700174protect multiple registers. The REGWEN register must precede those
175registers that refer to it in the .hjson register list. An example:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100176
177```hjson
178 { name: "REGWEN",
179 desc: "Register write enable for a bank of registers",
180 swaccess: "rw1c",
181 fields: [ { bits: "0", resval: "1" } ]
182 }
183 { name: "REGA",
184 swaccess: "rw",
185 regwen: "REGWEN",
186 ...
187 }
188 { name: "REGB",
189 swaccess: "rw",
190 regwen: "REGWEN",
191 ...
192 }
193```
194"""
195
196doc_tail = """
197
198(end of output generated by `regtool.py --doc`)
199
200"""
201
202
203def doc_tbl_head(outfile, use):
Eunchan Kim0bd75662020-04-24 10:21:18 -0700204 if use is not None:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100205 genout(outfile, "\nKey | Kind | Type | Description of Value\n")
206 genout(outfile, "--- | ---- | ---- | --------------------\n")
207 else:
208 genout(outfile, "\nKey | Description\n")
209 genout(outfile, "--- | -----------\n")
210
211
212def doc_tbl_line(outfile, key, use, desc):
Eunchan Kim0bd75662020-04-24 10:21:18 -0700213 if use is not None:
Rupert Swarbrickc02b52f2020-10-07 15:34:16 +0100214 desc_key, desc_txt = desc
215 val_type = (validate.val_types[desc_key][0]
216 if desc_key is not None else None)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100217 else:
Rupert Swarbrickc02b52f2020-10-07 15:34:16 +0100218 assert isinstance(desc, str)
219 val_type = None
220 desc_txt = desc
221
222 if val_type is not None:
Weicai Yang53b0d4d2020-11-30 15:28:33 -0800223 genout(
224 outfile, '{} | {} | {} | {}\n'.format(key, validate.key_use[use],
225 val_type, desc_txt))
Rupert Swarbrickc02b52f2020-10-07 15:34:16 +0100226 else:
227 genout(outfile, key + " | " + desc_txt + "\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100228
229
230def document(outfile):
231 genout(outfile, doc_intro)
232 for x in validate.val_types:
233 genout(
234 outfile,
235 validate.val_types[x][0] + " | " + validate.val_types[x][1] + "\n")
236
237 genout(outfile, swaccess_intro)
238 doc_tbl_head(outfile, None)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000239 for key, value in SWACCESS_PERMITTED.items():
240 doc_tbl_line(outfile, key, None, value[0])
lowRISC Contributors802543a2019-08-31 12:12:56 +0100241
242 genout(outfile, hwaccess_intro)
243 doc_tbl_head(outfile, None)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000244 for key, value in HWACCESS_PERMITTED.items():
245 doc_tbl_line(outfile, key, None, value[0])
lowRISC Contributors802543a2019-08-31 12:12:56 +0100246
Eunchan Kim0bd75662020-04-24 10:21:18 -0700247 genout(
248 outfile, "\n\nThe top level of the JSON is a group containing "
249 "the following keys:\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100250 doc_tbl_head(outfile, 1)
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +0000251 for k, v in ip_block.REQUIRED_FIELDS.items():
252 doc_tbl_line(outfile, k, 'r', v)
253 for k, v in ip_block.OPTIONAL_FIELDS.items():
254 doc_tbl_line(outfile, k, 'o', v)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100255 genout(outfile, top_example)
256
Pirmin Vogel1237a4e2020-06-23 09:07:28 +0200257 genout(
258 outfile, "\n\nThe list of registers includes register definition "
259 "groups containing the following keys:\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100260 doc_tbl_head(outfile, 1)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000261 for k, v in register.REQUIRED_FIELDS.items():
262 doc_tbl_line(outfile, k, 'r', v)
263 for k, v in register.OPTIONAL_FIELDS.items():
264 doc_tbl_line(outfile, k, 'o', v)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100265 genout(outfile, register_example)
266
Eunchan Kim0bd75662020-04-24 10:21:18 -0700267 genout(
268 outfile, "\n\nIn the fields list each field definition is a group "
Pirmin Vogel1237a4e2020-06-23 09:07:28 +0200269 "itself containing the following keys:\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100270 doc_tbl_head(outfile, 1)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000271 for k, v in field.REQUIRED_FIELDS.items():
272 doc_tbl_line(outfile, k, 'r', v)
273 for k, v in field.OPTIONAL_FIELDS.items():
274 doc_tbl_line(outfile, k, 'o', v)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100275 genout(outfile, field_example)
276
277 genout(outfile, "\n\nDefinitions in an enumeration group contain:\n")
278 doc_tbl_head(outfile, 1)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000279 for k, v in enum_entry.REQUIRED_FIELDS.items():
280 doc_tbl_line(outfile, k, 'r', v)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100281
282 genout(
Eunchan Kim0bd75662020-04-24 10:21:18 -0700283 outfile, "\n\nThe list of registers may include single entry groups "
284 "to control the offset, open a window or generate registers:\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100285 doc_tbl_head(outfile, 1)
286 for x in validate.list_optone:
287 doc_tbl_line(outfile, x, 'o', validate.list_optone[x])
288
289 genout(outfile, offset_intro)
290 genout(outfile, regwen_intro)
291
292 genout(outfile, window_intro)
293 doc_tbl_head(outfile, 1)
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000294 for k, v in window.REQUIRED_FIELDS.items():
295 doc_tbl_line(outfile, k, 'r', v)
296 for k, v in window.OPTIONAL_FIELDS.items():
297 doc_tbl_line(outfile, k, 'o', v)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100298
299 genout(outfile, multi_intro)
300 doc_tbl_head(outfile, 1)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000301 for k, v in multi_register.REQUIRED_FIELDS.items():
302 doc_tbl_line(outfile, k, 'r', v)
303 for k, v in multi_register.OPTIONAL_FIELDS.items():
304 doc_tbl_line(outfile, k, 'o', v)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100305
306 genout(outfile, doc_tail)