blob: 7425967de3b85ecb491af49c197418bddea27ec7 [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"""
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +00005Generate HTML documentation from IpBlock
lowRISC Contributors802543a2019-08-31 12:12:56 +01006"""
7
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +00008from typing import Set, TextIO
lowRISC Contributors802543a2019-08-31 12:12:56 +01009
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +000010from .ip_block import IpBlock
11from .html_helpers import expand_paras, render_td
Rupert Swarbrickc5b38152021-02-04 09:43:19 +000012from .multi_register import MultiRegister
13from .register import Register
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +000014from .window import Window
Rupert Swarbrickc5b38152021-02-04 09:43:19 +000015
lowRISC Contributors802543a2019-08-31 12:12:56 +010016
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +000017def genout(outfile: TextIO, msg: str) -> None:
lowRISC Contributors802543a2019-08-31 12:12:56 +010018 outfile.write(msg)
19
20
lowRISC Contributors802543a2019-08-31 12:12:56 +010021# Generation of HTML table with register bit-field summary picture
22# Max 16-bit wide on one line
23
24
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +000025def gen_tbl_row(outfile: TextIO, msb: int, width: int, close: bool) -> None:
lowRISC Contributors802543a2019-08-31 12:12:56 +010026 if (close):
27 genout(outfile, "</tr>\n")
28 genout(outfile, "<tr>")
29 for x in range(msb, msb - width, -1):
30 genout(outfile, "<td class=\"bitnum\">" + str(x) + "</td>")
31
32 genout(outfile, "</tr><tr>")
33
34
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +000035def gen_html_reg_pic(outfile: TextIO, reg: Register, width: int) -> None:
lowRISC Contributors802543a2019-08-31 12:12:56 +010036
37 if (width > 32):
38 bsize = 3
39 nextbit = 63
40 hdrbits = 16
41 nextline = 48
42 elif (width > 16):
43 bsize = 3
44 nextbit = 31
45 hdrbits = 16
46 nextline = 16
47 elif (width > 8):
48 bsize = 3
49 nextbit = 15
50 nextline = 0
51 hdrbits = 16
52 else:
53 bsize = 12
54 nextbit = 7
55 nextline = 0
56 hdrbits = 8
57
58 genout(outfile, "<table class=\"regpic\">")
59 gen_tbl_row(outfile, nextbit, hdrbits, False)
60
Rupert Swarbrickc5b38152021-02-04 09:43:19 +000061 for field in reversed(reg.fields):
62 fieldlsb = field.bits.lsb
63 fieldwidth = field.bits.width()
64 fieldmsb = field.bits.msb
65 fname = field.name
lowRISC Contributors802543a2019-08-31 12:12:56 +010066
67 while nextbit > fieldmsb:
68 if (nextbit >= nextline) and (fieldmsb < nextline):
69 spans = nextbit - (nextline - 1)
70 else:
71 spans = nextbit - fieldmsb
72 genout(
73 outfile, "<td class=\"unused\" colspan=" + str(spans) +
74 ">&nbsp;</td>\n")
75 if (nextbit >= nextline) and (fieldmsb < nextline):
76 nextbit = nextline - 1
77 gen_tbl_row(outfile, nextbit, hdrbits, True)
78 nextline = nextline - 16
79 else:
80 nextbit = fieldmsb
81
82 while (fieldmsb >= nextline) and (fieldlsb < nextline):
83 spans = fieldmsb - (nextline - 1)
84 genout(
85 outfile, "<td class=\"fname\" colspan=" + str(spans) + ">" +
86 fname + "...</td>\n")
Rupert Swarbrickc5b38152021-02-04 09:43:19 +000087 fname = "..." + field.name
lowRISC Contributors802543a2019-08-31 12:12:56 +010088 fieldwidth = fieldwidth - spans
89 fieldmsb = nextline - 1
90 nextline = nextline - 16
91 gen_tbl_row(outfile, fieldmsb, hdrbits, True)
92
93 namelen = len(fname)
Eunchan Kim0bd75662020-04-24 10:21:18 -070094 if namelen == 0 or fname == ' ':
95 fname = "&nbsp;"
lowRISC Contributors802543a2019-08-31 12:12:56 +010096 if (namelen > bsize * fieldwidth):
97 usestyle = (" style=\"font-size:" + str(
98 (bsize * 100 * fieldwidth) / namelen) + "%\"")
99 else:
100 usestyle = ""
101
102 genout(
103 outfile, "<td class=\"fname\" colspan=" + str(fieldwidth) +
104 usestyle + ">" + fname + "</td>\n")
105
106 if (fieldlsb == nextline) and nextline > 0:
107 gen_tbl_row(outfile, nextline - 1, hdrbits, True)
108 nextline = nextline - 16
109
110 nextbit = fieldlsb - 1
111 while (nextbit > 0):
112 spans = nextbit - (nextline - 1)
113 genout(outfile,
114 "<td class=\"unused\" colspan=" + str(spans) + ">&nbsp;</td>\n")
115 nextbit = nextline - 1
116 if (nextline > 0):
117 gen_tbl_row(outfile, nextline - 1, hdrbits, True)
118 nextline = nextline - 16
119
120 genout(outfile, "</tr></table>")
121
122
123# Generation of HTML table with header, register picture and details
124
125
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +0000126def gen_html_register(outfile: TextIO,
127 reg: Register,
128 comp: str,
129 width: int,
130 rnames: Set[str]) -> None:
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000131 rname = reg.name
132 offset = reg.offset
Rupert Swarbricke3f9d6f2021-02-05 12:40:04 +0000133 regwen_div = ''
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000134 if reg.regwen is not None:
Rupert Swarbricke3f9d6f2021-02-05 12:40:04 +0000135 regwen_div = (' <div>Register enable = {}</div>\n'
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000136 .format(reg.regwen))
Rupert Swarbricke3f9d6f2021-02-05 12:40:04 +0000137
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000138 desc_paras = expand_paras(reg.desc, rnames)
Rupert Swarbrick94926ae2021-02-05 13:12:58 +0000139 desc_head = desc_paras[0]
140 desc_body = desc_paras[1:]
141
Rupert Swarbricke3f9d6f2021-02-05 12:40:04 +0000142 genout(outfile,
143 '<table class="regdef" id="Reg_{lrname}">\n'
144 ' <tr>\n'
145 ' <th class="regdef" colspan=5>\n'
146 ' <div>{comp}.{rname} @ {off:#x}</div>\n'
147 ' <div>{desc}</div>\n'
148 ' <div>Reset default = {resval:#x}, mask {mask:#x}</div>\n'
149 '{wen}'
150 ' </th>\n'
151 ' </tr>\n'
152 .format(lrname=rname.lower(),
153 comp=comp,
154 rname=rname,
155 off=offset,
Rupert Swarbrick94926ae2021-02-05 13:12:58 +0000156 desc=desc_head,
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000157 resval=reg.resval,
158 mask=reg.resmask,
Rupert Swarbricke3f9d6f2021-02-05 12:40:04 +0000159 wen=regwen_div))
Rupert Swarbrick94926ae2021-02-05 13:12:58 +0000160 if desc_body:
161 genout(outfile,
Rupert Swarbrick11880032021-02-19 12:27:00 +0000162 '<tr><td colspan=5>{}</td></tr>'
163 .format(''.join(desc_body)))
Rupert Swarbrick94926ae2021-02-05 13:12:58 +0000164
lowRISC Contributors802543a2019-08-31 12:12:56 +0100165 genout(outfile, "<tr><td colspan=5>")
166 gen_html_reg_pic(outfile, reg, width)
167 genout(outfile, "</td></tr>\n")
168
169 genout(outfile, "<tr><th width=5%>Bits</th>")
170 genout(outfile, "<th width=5%>Type</th>")
171 genout(outfile, "<th width=5%>Reset</th>")
172 genout(outfile, "<th>Name</th>")
173 genout(outfile, "<th>Description</th></tr>")
174 nextbit = 0
175 fcount = 0
lowRISC Contributors802543a2019-08-31 12:12:56 +0100176
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000177 for field in reg.fields:
178 fcount += 1
179 fname = field.name
180
181 fieldlsb = field.bits.lsb
182 if fieldlsb > nextbit:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100183 genout(outfile, "<tr><td class=\"regbits\">")
184 if (nextbit == (fieldlsb - 1)):
185 genout(outfile, str(nextbit))
186 else:
187 genout(outfile, str(fieldlsb - 1) + ":" + str(nextbit))
188 genout(outfile,
189 "</td><td></td><td></td><td></td><td>Reserved</td></tr>")
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000190 genout(outfile, "<tr><td class=\"regbits\">" + field.bits.as_str() + "</td>")
191 genout(outfile, "<td class=\"regperm\">" + field.swaccess.key + "</td>")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100192 genout(
Garret Kelly6f840152019-11-22 14:38:38 -0500193 outfile, "<td class=\"regrv\">" +
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000194 ('x' if field.resval is None else hex(field.resval)) +
Garret Kelly6f840152019-11-22 14:38:38 -0500195 "</td>")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100196 genout(outfile, "<td class=\"regfn\">" + fname + "</td>")
Rupert Swarbrick11880032021-02-19 12:27:00 +0000197
198 # Collect up any description and enum table
199 desc_parts = []
200
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000201 if field.desc is not None:
Rupert Swarbrick11880032021-02-19 12:27:00 +0000202 desc_parts += expand_paras(field.desc, rnames)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100203
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000204 if field.enum is not None:
Rupert Swarbrick11880032021-02-19 12:27:00 +0000205 desc_parts.append('<table>')
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000206 for enum in field.enum:
Rupert Swarbrick11880032021-02-19 12:27:00 +0000207 enum_desc_paras = expand_paras(enum.desc, rnames)
208 desc_parts.append('<tr>'
209 '<td>{val}</td>'
210 '<td>{name}</td>'
211 '<td>{desc}</td>'
212 '</tr>\n'
213 .format(val=enum.value,
214 name=enum.name,
215 desc=''.join(enum_desc_paras)))
216 desc_parts.append('</table>')
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000217 if field.has_incomplete_enum():
Rupert Swarbrick11880032021-02-19 12:27:00 +0000218 desc_parts.append("<p>Other values are reserved.</p>")
219
220 genout(outfile,
221 '<td class="regde">{}</td>'.format(''.join(desc_parts)))
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000222 nextbit = fieldlsb + field.bits.width()
lowRISC Contributors802543a2019-08-31 12:12:56 +0100223
Tobias Wölfel0435a832021-01-18 09:43:00 +0100224 genout(outfile, "</table>\n<br>\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100225
lowRISC Contributors802543a2019-08-31 12:12:56 +0100226
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +0000227def gen_html_window(outfile: TextIO,
228 win: Window,
229 comp: str,
230 regwidth: int,
231 rnames: Set[str]) -> None:
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000232 wname = win.name or '(unnamed window)'
233 offset = win.offset
234 genout(outfile,
235 '<table class="regdef" id="Reg_{lwname}">\n'
236 ' <tr>\n'
237 ' <th class="regdef">\n'
238 ' <div>{comp}.{wname} @ + {off:#x}</div>\n'
239 ' <div>{items} item {swaccess} window</div>\n'
240 ' <div>Byte writes are {byte_writes}supported</div>\n'
241 ' </th>\n'
242 ' </tr>\n'
243 .format(comp=comp,
244 wname=wname,
245 lwname=wname.lower(),
246 off=offset,
247 items=win.items,
248 swaccess=win.swaccess.key,
249 byte_writes=('' if win.byte_write else '<i>not</i> ')))
lowRISC Contributors802543a2019-08-31 12:12:56 +0100250 genout(outfile, '<tr><td><table class="regpic">')
251 genout(outfile, '<tr><td width="10%"></td>')
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000252 wid = win.validbits
lowRISC Contributors802543a2019-08-31 12:12:56 +0100253
254 for x in range(regwidth - 1, -1, -1):
255 if x == regwidth - 1 or x == wid - 1 or x == 0:
256 genout(outfile, '<td class="bitnum">' + str(x) + '</td>')
257 else:
258 genout(outfile, '<td class="bitnum"></td>')
259 genout(outfile, '</tr>')
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000260 tblmax = win.items - 1
lowRISC Contributors802543a2019-08-31 12:12:56 +0100261 for x in [0, 1, 2, tblmax - 1, tblmax]:
262 if x == 2:
263 genout(
264 outfile, '<tr><td>&nbsp;</td><td align=center colspan=' +
265 str(regwidth) + '>...</td></tr>')
266 else:
267 genout(
268 outfile, '<tr><td class="regbits">+' +
269 hex(offset + x * (regwidth // 8)) + '</td>')
270 if wid < regwidth:
271 genout(
272 outfile, '<td class="unused" colspan=' +
273 str(regwidth - wid) + '>&nbsp;</td>\n')
274 genout(
275 outfile,
276 '<td class="fname" colspan=' + str(wid) + '>&nbsp;</td>\n')
277 else:
278 genout(
279 outfile, '<td class="fname" colspan=' + str(regwidth) +
280 '>&nbsp;</td>\n')
281 genout(outfile, '</tr>')
282 genout(outfile, '</td></tr></table>')
Rupert Swarbrick94926ae2021-02-05 13:12:58 +0000283 genout(outfile,
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000284 '<tr>{}</tr>'.format(render_td(win.desc, rnames, 'regde')))
Tobias Wölfel0435a832021-01-18 09:43:00 +0100285 genout(outfile, "</table>\n<br>\n")
lowRISC Contributors802543a2019-08-31 12:12:56 +0100286
287
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +0000288def gen_html(block: IpBlock, outfile: TextIO) -> int:
289 rnames = set(block.regs.name_to_offset.keys())
lowRISC Contributors802543a2019-08-31 12:12:56 +0100290
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +0000291 for x in block.regs.entries:
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000292 if isinstance(x, Register):
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +0000293 gen_html_register(outfile, x, block.name, block.regwidth, rnames)
Rupert Swarbrickc5b38152021-02-04 09:43:19 +0000294 continue
295 if isinstance(x, MultiRegister):
296 for reg in x.regs:
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +0000297 gen_html_register(outfile, reg, block.name, block.regwidth,
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +0000298 rnames)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100299 continue
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000300 if isinstance(x, Window):
Rupert Swarbrickf5fb61f2021-03-03 12:20:55 +0000301 gen_html_window(outfile, x, block.name, block.regwidth, rnames)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100302 continue
303
Rupert Swarbrick6880e212021-02-10 16:10:00 +0000304 return 0