| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| """ |
| Generate HTML documentation from Block |
| """ |
| |
| from typing import TextIO |
| |
| from .ip_block import IpBlock |
| from .html_helpers import render_td |
| from .signal import Signal |
| |
| |
| def genout(outfile: TextIO, msg: str) -> None: |
| outfile.write(msg) |
| |
| |
| def name_width(x: Signal) -> str: |
| if x.bits.width() == 1: |
| return x.name |
| |
| return '{}[{}:0]'.format(x.name, x.bits.msb) |
| |
| |
| def gen_kv(outfile: TextIO, key: str, value: str) -> None: |
| genout(outfile, |
| '<p><i>{}:</i> {}</p>\n'.format(key, value)) |
| |
| |
| def gen_cfg_html(cfgs: IpBlock, outfile: TextIO) -> None: |
| rnames = cfgs.get_rnames() |
| |
| ot_server = 'https://docs.opentitan.org' |
| comport_url = ot_server + '/doc/rm/comportability_specification' |
| genout(outfile, |
| '<p>Referring to the <a href="{url}">Comportable guideline for ' |
| 'peripheral device functionality</a>, the module ' |
| '<b><code>{mod_name}</code></b> has the following hardware ' |
| 'interfaces defined.</p>\n' |
| .format(url=comport_url, mod_name=cfgs.name)) |
| |
| # clocks |
| gen_kv(outfile, |
| 'Primary Clock', |
| '<b><code>{}</code></b>'.format(cfgs.clocking.primary.clock)) |
| other_clocks = cfgs.clocking.other_clocks() |
| if other_clocks: |
| other_clocks_str = ['<b><code>{}</code></b>'.format(clk) |
| for clk in other_clocks] |
| gen_kv(outfile, 'Other Clocks', ', '.join(other_clocks_str)) |
| else: |
| gen_kv(outfile, 'Other Clocks', '<i>none</i>') |
| |
| # bus interfaces |
| dev_ports = ['<b><code>{}</code></b>'.format(port) |
| for port in cfgs.bus_interfaces.get_port_names(False, True)] |
| assert dev_ports |
| gen_kv(outfile, 'Bus Device Interfaces (TL-UL)', ', '.join(dev_ports)) |
| |
| host_ports = ['<b><code>{}</code></b>'.format(port) |
| for port in cfgs.bus_interfaces.get_port_names(True, False)] |
| if host_ports: |
| gen_kv(outfile, 'Bus Host Interfaces (TL-UL)', ', '.join(host_ports)) |
| else: |
| gen_kv(outfile, 'Bus Host Interfaces (TL-UL)', '<i>none</i>') |
| |
| # IO |
| ios = ([('input', x) for x in cfgs.xputs[1]] + |
| [('output', x) for x in cfgs.xputs[2]] + |
| [('inout', x) for x in cfgs.xputs[0]]) |
| if ios: |
| genout(outfile, "<p><i>Peripheral Pins for Chip IO:</i></p>\n") |
| genout( |
| outfile, "<table class=\"cfgtable\"><tr>" + |
| "<th>Pin name</th><th>direction</th>" + |
| "<th>Description</th></tr>\n") |
| for direction, x in ios: |
| genout(outfile, |
| '<tr><td>{}</td><td>{}</td>{}</tr>' |
| .format(name_width(x), |
| direction, |
| render_td(x.desc, rnames, None))) |
| genout(outfile, "</table>\n") |
| else: |
| genout(outfile, "<p><i>Peripheral Pins for Chip IO: none</i></p>\n") |
| |
| if not cfgs.interrupts: |
| genout(outfile, "<p><i>Interrupts: none</i></p>\n") |
| else: |
| genout(outfile, "<p><i>Interrupts:</i></p>\n") |
| genout( |
| outfile, "<table class=\"cfgtable\"><tr><th>Interrupt Name</th>" + |
| "<th>Description</th></tr>\n") |
| for x in cfgs.interrupts: |
| genout(outfile, |
| '<tr><td>{}</td>{}</tr>' |
| .format(name_width(x), |
| render_td(x.desc, rnames, None))) |
| genout(outfile, "</table>\n") |
| |
| if not cfgs.alerts: |
| genout(outfile, "<p><i>Security Alerts: none</i></p>\n") |
| else: |
| genout(outfile, "<p><i>Security Alerts:</i></p>\n") |
| genout( |
| outfile, "<table class=\"cfgtable\"><tr><th>Alert Name</th>" + |
| "<th>Description</th></tr>\n") |
| for x in cfgs.alerts: |
| genout(outfile, |
| '<tr><td>{}</td>{}</tr>' |
| .format(x.name, |
| render_td(x.desc, rnames, None))) |
| genout(outfile, "</table>\n") |