blob: 53c65804d419f8ae0bec3c4415a4924491478551 [file] [log] [blame]
Michael Schaffner426ed202021-08-02 17:44:42 -07001#!/usr/bin/env python3
2# Copyright lowRISC contributors.
3# Licensed under the Apache License, Version 2.0, see LICENSE for details.
4# SPDX-License-Identifier: Apache-2.0
5r"""Top Module Documentation Generator
6"""
7import os
8from tabulate import tabulate
9
10TABLE_HEADER = '''<!--
11DO NOT EDIT THIS FILE DIRECTLY.
12It has been generated with the following command:
13'''
14
15
16def set_md_table_font_size(row, size):
17 """Wrap each row element with HTML tags and specify font size"""
18 for k, elem in enumerate(row):
19 row[k] = '<p style="font-size:' + str(size) + '">' + elem + '</p>'
20 return row
21
22
23def create_pinout_table(top, c_helper, target):
24 """Create the pinout table for a specific target and extract some stats"""
25 header = [
26 "Pad Name", "Type", "Bank", "Connection", "Special Function",
27 "Pinmux Insel Constant / Muxed Output Index", "Description"
28 ]
29 table_rows = [set_md_table_font_size(header, "smaller")]
30 colalign = ("center", ) * len(header)
31
32 # Pad stats
33 stats = {}
34 stats['muxed'] = 0
35 stats['direct'] = 0
36 stats['manual'] = 0
37
38 # get all pads for this target
39 pads = top['pinout']['pads'] + target['pinout']['add_pads']
Michael Schaffner51055db2021-11-04 13:07:54 -070040 remove_ports = target['pinout']['remove_ports']
Michael Schaffner426ed202021-08-02 17:44:42 -070041 remove_pads = target['pinout']['remove_pads']
42 special_signals = target['pinmux']['special_signals']
43
44 # map pad names to special function signals
45 special_pads = {}
46 for sig in special_signals:
47 special_pads.update({sig['pad']: {'name': sig['name'],
48 'desc': sig['desc']}})
49
50 i = 2 # insel enum starts at 2
51 j = 0 # mio_out enum starts at 0
52 for pad in pads:
53 # get the corresponding insel constant and MIO output index
54 if pad['connection'] == 'muxed':
55 name, _, _ = c_helper.pinmux_insel.constants[i]
56 insel = name.as_c_enum()
57 name, _, _ = c_helper.pinmux_mio_out.constants[j]
58 mio_out = name.as_c_enum()
59 i += 1
60 j += 1
61 else:
62 insel = "-"
63 mio_out = "-"
Michael Schaffner51055db2021-11-04 13:07:54 -070064 # check whether this pad/port needs to be dropped
65 if pad['name'] in remove_ports:
66 continue
Michael Schaffner426ed202021-08-02 17:44:42 -070067 if pad['name'] in remove_pads:
68 continue
69 # gather some stats
70 stats[pad['connection']] += 1
71 # annotate special functions
72 if pad['name'] in special_pads:
73 special_func = special_pads[pad['name']]['name']
74 desc = pad['desc'] + " / " + special_pads[pad['name']]['desc']
75 else:
76 special_func = "-"
77 desc = pad['desc']
78 row = [
79 pad['name'],
80 pad['type'],
81 pad['bank'],
82 pad['connection'],
83 special_func,
84 insel + ' / ' + mio_out,
85 desc
86 ]
87 table_rows.append(set_md_table_font_size(row, "smaller"))
88
89 ret_str = tabulate(table_rows,
90 headers="firstrow",
91 tablefmt="pipe",
92 colalign=colalign)
93
94 return ret_str, stats
95
96
97def create_pinmux_table(top, c_helper):
98 """Create the pinmux connectivity table"""
99 header = [
100 "Module / Signal", "Connection", "Pad",
101 "Pinmux Outsel Constant / Peripheral Input Index", "Description"
102 ]
103 table_rows = [set_md_table_font_size(header, "smaller")]
104 colalign = ("center", ) * len(header)
105
106 i = 3 # outsel enum starts at 3
107 j = 0 # periph_input enum starts at 0
108 for sig in top['pinmux']['ios']:
109 port = sig['name']
110 if sig['width'] > 1:
111 port += '[' + str(sig['idx']) + ']'
112 pad = sig['pad'] if sig['pad'] else '-'
113 # get the corresponding insel constant
114 if sig['connection'] == 'muxed' and sig['type'] in ['inout', 'output']:
115 name, _, _ = c_helper.pinmux_outsel.constants[i]
116 outsel = name.as_c_enum()
117 i += 1
118 else:
119 outsel = "-"
120 # get the corresponding peripheral input index
121 if sig['connection'] == 'muxed' and sig['type'] in ['inout', 'input']:
122 name, _, _ = c_helper.pinmux_peripheral_in.constants[j]
123 periph_in = name.as_c_enum()
124 j += 1
125 else:
126 periph_in = "-"
127 row = [
128 port,
129 sig['connection'],
130 pad,
131 outsel + " / " + periph_in,
132 sig['desc']
133 ]
134 table_rows.append(set_md_table_font_size(row, "smaller"))
135
136 return tabulate(table_rows,
137 headers="firstrow",
138 tablefmt="pipe",
139 colalign=colalign)
140
141
142def gen_pinmux_docs(top, c_helper, out_path):
143 """Generate target summary table and linked subtables"""
144
145 pinmux_path = out_path / '../ip/pinmux/doc'
146 doc_path = out_path / 'ip/pinmux/doc/autogen'
147 doc_path.mkdir(parents=True, exist_ok=True)
148
149 # this is used to create relative hyperlinks from the summary table to
150 # the individual target tables.
151 relpath_prefix = os.path.relpath(doc_path.resolve(), pinmux_path.resolve())
152
153 topname = top['name']
154 gencmd = ("util/topgen.py -t hw/top_{topname}/data/top_{topname}.hjson "
155 "-o hw/top_{topname}/\n\n".format(topname=topname))
156
157 header = [
158 "Target Name", "#IO Banks", "#Muxed Pads", "#Direct Pads",
159 "#Manual Pads", "#Total Pads", "Pinout / Pinmux Tables"
160 ]
161 table_rows = [header]
162 colalign = ("center", ) * len(header)
163
164 for target in top['targets']:
165
166 # create pinout/pinmux tables for this target
167 pinout_table = '---\n'
168 pinout_table += 'title: ' + target['name'].upper()
169 pinout_table += ' Target Pinout and Pinmux Connectivity\n'
170 pinout_table += '---\n'
171 pinout_table += TABLE_HEADER + gencmd + "-->\n\n"
172 pinout_table += '## Pinout Table\n\n'
173 table_str, stats = create_pinout_table(top, c_helper, target)
174 pinout_table += table_str + '\n'
175 pinout_table += '## Pinmux Connectivity\n\n'
176 pinout_table += create_pinmux_table(top, c_helper)
Michael Schaffnera35f7682022-05-12 14:18:15 -0700177 pinout_table += "\n"
Michael Schaffner426ed202021-08-02 17:44:42 -0700178
179 pinout_table_path = doc_path / ("pinout_" + target['name'] + ".md")
180 with open(pinout_table_path, 'w') as outfile:
181 outfile.write(pinout_table)
182
183 # gather some statistics
184 num_banks = len(top['pinout']['banks'])
185 # create summary table entry
186 pinout_table_relpath = relpath_prefix + "/pinout_" + target['name'] + "/index.html"
187 row = [
188 target['name'].upper(),
189 num_banks,
190 stats['muxed'],
191 stats['direct'],
192 stats['manual'],
193 stats['muxed'] + stats['direct'] + stats['manual'],
194 "[Pinout Table](" + str(pinout_table_relpath) + ")"
195 ]
196 table_rows.append(row)
197
198 summary_table = tabulate(table_rows,
199 headers="firstrow",
200 tablefmt="pipe",
201 colalign=colalign)
Michael Schaffner1d12d022022-04-29 12:14:13 -0700202 summary_table = TABLE_HEADER + gencmd + "-->\n\n" + summary_table + "\n"
Michael Schaffner426ed202021-08-02 17:44:42 -0700203
204 target_table_path = doc_path / "targets.md"
205 with open(target_table_path, 'w') as target_outfile:
206 target_outfile.write(summary_table)
207
208
209def gen_top_docs(top, c_helper, out_path):
210 # create pinout / pinmux specific tables for all targets
211 gen_pinmux_docs(top, c_helper, out_path)