| #!/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 |
| """mdbook preprocessor that generates ISA tables for the OTBN. |
| |
| The preprocessor also handles `{{#otbn-insn-ref ... }}` links to the ISA Table. |
| """ |
| |
| import json |
| import sys |
| import re |
| from pathlib import Path |
| import tempfile |
| import subprocess |
| |
| from mdbook import utils as md_utils |
| |
| REPO_TOP = Path(__file__).resolve().parents[1] |
| |
| # We are looking to match on the following example strings |
| # {{#otbn-isa base }} |
| OTBN_ISA_BASE_PATTERN = re.compile(r'\{\{#otbn-isa\s+base\s*\}\}') |
| OTBN_ISA_BIGNUM_PATTERN = re.compile(r'\{\{#otbn-isa\s+bignum\s*\}\}') |
| |
| # {{#otbn-insn-ref insn }} |
| OTBN_INSNREF_PATTERN = re.compile(r'\{\{#otbn-insn-ref\s+?(.+?)\s*?\}\}') |
| |
| OTBN_SCRIPT = REPO_TOP / 'hw/ip/otbn/util/yaml_to_doc.py' |
| OTBN_CFG = REPO_TOP / 'hw/ip/otbn/data/insns.yml' |
| OTBN_IMPL = REPO_TOP / 'hw/ip/otbn/dv/otbnsim/sim/insn.py' |
| |
| |
| def main() -> None: |
| md_utils.supports_html_only() |
| |
| (base_content, bignum_content) = get_listings() |
| |
| # load both the context and the book from stdin |
| context, book = json.load(sys.stdin) |
| |
| isa_book_path = None |
| for chapter in md_utils.chapters(book["sections"]): |
| if chapter["source_path"] is None: |
| continue |
| |
| if OTBN_ISA_BASE_PATTERN.search(chapter["content"]) \ |
| and OTBN_ISA_BIGNUM_PATTERN.search(chapter["content"]): |
| |
| chapter["content"] = OTBN_ISA_BASE_PATTERN.sub(base_content, chapter["content"]) |
| chapter["content"] = OTBN_ISA_BIGNUM_PATTERN.sub(bignum_content, chapter["content"]) |
| |
| isa_book_path = chapter["source_path"] |
| break |
| |
| if isa_book_path is None: |
| sys.exit("No file was found with both {{#otbn-isa base}} and {{#otbn-isa bignum}}") |
| |
| def ref_to_link(m: re.Match): |
| instr = m.group(1) |
| ref = instr.replace(".", "").lower() |
| return '<a href="/{}#{}"><code>{}</code></a>)'.format(isa_book_path, ref, instr) |
| |
| for chapter in md_utils.chapters(book["sections"]): |
| chapter["content"] = \ |
| OTBN_INSNREF_PATTERN.sub( |
| ref_to_link, |
| chapter["content"], |
| ) |
| |
| # dump the book into stdout |
| print(json.dumps(book)) |
| |
| |
| def get_listings() -> (str, str): |
| """Use the otbn utility scripts to generate the ISA listings.""" |
| with tempfile.TemporaryDirectory() as tmpdir: |
| subprocess.run( |
| [str(OTBN_SCRIPT), str(OTBN_CFG), str(OTBN_IMPL), tmpdir], |
| check=True, |
| ) |
| tmpdir = Path(tmpdir) |
| with open(tmpdir / "base.md") as f: |
| base_content = f.read() |
| |
| with open(tmpdir / "bignum.md") as f: |
| bignum_content = f.read() |
| |
| return (base_content, bignum_content) |
| |
| |
| if __name__ == "__main__": |
| main() |