[doc] Created dashboard pre-processor
Signed-off-by: Hugo McNally <hugo.mcnally@gmail.com>
Co-authored-by: Harry Callahan <hcallahan@lowrisc.org>
diff --git a/book.toml b/book.toml
index ede0c0f..2e102a3 100644
--- a/book.toml
+++ b/book.toml
@@ -45,6 +45,9 @@
[preprocessor.otbn]
command = "./util/mdbook_otbn.py"
+[preprocessor.dashboard]
+command = "./util/mdbook_dashboard.py"
+
[preprocessor.doxygen]
command = "./util/mdbook_doxygen.py"
out-dir = "docs/"
diff --git a/hw/README.md b/hw/README.md
index a5336f2..58a0851 100644
--- a/hw/README.md
+++ b/hw/README.md
@@ -26,7 +26,7 @@
## Comportable IPs
-{{< dashboard "comportable" >}}
+{{#dashboard comportable }}
## Processor cores
@@ -50,7 +50,7 @@
### Earl Grey-specific comportable IPs
-{{< dashboard "top_earlgrey" >}}
+{{#dashboard top_earlgrey }}
## Hardware documentation overview
diff --git a/util/mdbook_dashboard.py b/util/mdbook_dashboard.py
new file mode 100755
index 0000000..6fa54f4
--- /dev/null
+++ b/util/mdbook_dashboard.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+import json
+import sys
+import io
+import re
+from pathlib import Path
+
+import dashboard.gen_dashboard_entry as dashboard
+from mdbook import utils as md_utils
+
+# We are looking to match on the following example strings
+# {{#dashboard comportable }}
+DASHBOARD_PATTERN = re.compile(r'\{\{#dashboard\s+?(.+?)\s*\}\}')
+IP_CFG_PATTERN = re.compile(r'.+/data/(?!.+(_testplan|example)).+\.hjson')
+REPO_TOP = Path(__file__).resolve().parents[1]
+
+# FIXME: It would be nice if this isn't hard coded.
+DASHBOARDS = {
+ 'comportable': [
+ "hw/ip/aes/data/aes.hjson",
+ "hw/ip/aon_timer/data/aon_timer.hjson",
+ "hw/ip/entropy_src/data/entropy_src.hjson",
+ "hw/ip/csrng/data/csrng.hjson",
+ "hw/ip/adc_ctrl/data/adc_ctrl.hjson",
+ "hw/ip/edn/data/edn.hjson",
+ "hw/ip/flash_ctrl/data/flash_ctrl.hjson",
+ "hw/ip/gpio/data/gpio.hjson",
+ "hw/ip/hmac/data/hmac.hjson",
+ "hw/ip/i2c/data/i2c.hjson",
+ "hw/ip/keymgr/data/keymgr.hjson",
+ "hw/ip/kmac/data/kmac.hjson",
+ "hw/ip/lc_ctrl/data/lc_ctrl.hjson",
+ "hw/ip/otbn/data/otbn.hjson",
+ "hw/ip/otp_ctrl/data/otp_ctrl.hjson",
+ "hw/ip/pattgen/data/pattgen.hjson",
+ "hw/ip/pwm/data/pwm.hjson",
+ "hw/ip/rom_ctrl/data/rom_ctrl.hjson",
+ "hw/ip/rv_dm/data/rv_dm.hjson",
+ "hw/ip/rv_core_ibex/data/rv_core_ibex.hjson",
+ "hw/ip/rv_timer/data/rv_timer.hjson",
+ "hw/ip/spi_host/data/spi_host.hjson",
+ "hw/ip/spi_device/data/spi_device.hjson",
+ "hw/ip/sram_ctrl/data/sram_ctrl.hjson",
+ "hw/ip/sysrst_ctrl/data/sysrst_ctrl.hjson",
+ "hw/ip/uart/data/uart.hjson",
+ "hw/ip/usbdev/data/usbdev.hjson",
+ ],
+ 'top_earlgrey': [
+ "hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler.hjson",
+ "hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson",
+ "hw/top_earlgrey/ip/clkmgr/data/autogen/clkmgr.hjson",
+ "hw/top_earlgrey/ip/pwrmgr/data/autogen/pwrmgr.hjson",
+ "hw/top_earlgrey/ip/rstmgr/data/autogen/rstmgr.hjson",
+ "hw/top_earlgrey/ip/sensor_ctrl/data/sensor_ctrl.hjson",
+ "hw/top_earlgrey/ip_autogen/rv_plic/data/rv_plic.hjson",
+ ],
+}
+
+DASHBOARD_TEMPLATE = """
+<table class="hw-project-dashboard">
+ <thead>
+ <tr>
+ <th>Design Spec</th>
+ <th>DV Document</th>
+ <th><a href="/doc/project_governance/development_stages.html#versioning">Spec Version</a></th>
+ <th colspan="4">
+ <a href="/doc/project_governance/development_stages.html#life-stages">
+ Development Stage
+ </a>
+ </th>
+ <th>Notes</th>
+ </tr>
+ </thead>
+ <tbody>
+{}
+ </tbody>
+</table>
+"""
+
+
+def main() -> None:
+ md_utils.supports_html_only()
+
+ # Generate the dashboards
+ # gen_dashboards()
+
+ # load both the context and the book from stdin
+ context, book = json.load(sys.stdin)
+
+ for chapter in md_utils.chapters(book["sections"]):
+ # Add in the generated dashboard html
+ chapter['content'] = DASHBOARD_PATTERN.sub(
+ replace_with_dashboard,
+ chapter['content'])
+
+ # dump the book into stdout
+ print(json.dumps(book))
+
+
+def replace_with_dashboard(m: re.Match) -> str:
+ name = m.group(1)
+
+ try:
+ cfg_files = DASHBOARDS[name]
+ except KeyError:
+ sys.exit("A dashboard with name {}, {{#dashboard {} }}, doesn't exist".format(name, name))
+
+ buffer = io.StringIO()
+ for cfg_file in sorted(cfg_files):
+ dashboard.gen_dashboard_html(REPO_TOP / cfg_file, buffer)
+
+ return DASHBOARD_TEMPLATE.format(buffer.getvalue())
+
+
+if __name__ == "__main__":
+ main()