From 4b5c0389d6d705ca34719b9c7c340883915d227b Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Sun, 26 Oct 2025 23:07:24 +0000 Subject: [PATCH 1/3] Add doctest infrastructure and fix failing test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 & 2 of doctest improvements: - Fix import path in chipflow-toml-guide.rst doctest (_parse_config_file from config.parser) - Add doctest_global_setup in conf.py with common imports for test examples - Existing doctest now passes The global setup imports common modules (Amaranth, ChipFlow signatures) so that doctests can focus on demonstrating API usage without repetitive imports. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/chipflow-toml-guide.rst | 2 +- docs/conf.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/chipflow-toml-guide.rst b/docs/chipflow-toml-guide.rst index 34113210..3ccec959 100644 --- a/docs/chipflow-toml-guide.rst +++ b/docs/chipflow-toml-guide.rst @@ -14,7 +14,7 @@ Let's start with a typical example: # Assert that example-chipflow.toml matches the current config schema. If # this test fails, then its likely that the content in this file will need # to be updated. - from chipflow_lib.config import _parse_config_file + from chipflow_lib.config.parser import _parse_config_file _parse_config_file("docs/example-chipflow.toml") ``[chipflow]`` table diff --git a/docs/conf.py b/docs/conf.py index cf8ee255..65350965 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -108,6 +108,20 @@ ("Members", "params_style"), # `amaranth.lib.wiring` signature members ] +# Doctest configuration +doctest_global_setup = """ +from pathlib import Path +from amaranth import Module +from amaranth.lib import wiring +from amaranth.lib.wiring import In, Out, connect, flipped +from amaranth_soc import csr, wishbone +from chipflow_lib.platforms import ( + UARTSignature, GPIOSignature, SPISignature, I2CSignature, + QSPIFlashSignature, JTAGSignature, + IOTripPoint, Sky130DriveMode, + SoftwareDriverSignature, attach_data, SoftwareBuild +) +""" rst_prolog = """ .. role:: py(code) From 6fcdec9bba00e9ac0ba0ce5532d677a11b62c54b Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Sun, 26 Oct 2025 23:08:55 +0000 Subject: [PATCH 2/3] Convert strategic examples to testable doctests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3 of doctest improvements: - Convert complete MySoC examples to testcode blocks with assertions - Two examples converted: using-pin-signatures.rst and architecture.rst - Examples now validate that classes can be instantiated correctly - All doctests pass (3 tests total) Strategy: Convert only complete, self-contained examples that use documented public APIs. Keep illustrative fragments as code-block for readability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/architecture.rst | 13 +++++++------ docs/using-pin-signatures.rst | 12 ++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/architecture.rst b/docs/architecture.rst index 458f0564..2bce1689 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -58,13 +58,9 @@ Design Flow in Detail You write your design in Python using Amaranth HDL and ChipFlow signatures: -.. code-block:: python - - from chipflow_lib.platforms import UARTSignature, GPIOSignature - from amaranth import Module - from amaranth.lib.wiring import Component, Out +.. testcode:: - class MySoC(Component): + class MySoC(wiring.Component): def __init__(self): super().__init__({ "uart": Out(UARTSignature()), @@ -76,6 +72,11 @@ You write your design in Python using Amaranth HDL and ChipFlow signatures: # Your design logic here return m + # Verify the design can be instantiated + design = MySoC() + assert hasattr(design, 'uart') + assert hasattr(design, 'gpio') + 2. Signatures Add Metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/using-pin-signatures.rst b/docs/using-pin-signatures.rst index 939b959e..42de28dd 100644 --- a/docs/using-pin-signatures.rst +++ b/docs/using-pin-signatures.rst @@ -34,11 +34,9 @@ Using Pin Signatures in Your Top-Level Design Pin signatures are used when defining your top-level component's interface: -.. code-block:: python - - from amaranth.lib.wiring import Out - from chipflow_lib.platforms import UARTSignature, GPIOSignature, QSPIFlashSignature +.. testcode:: + # Define a simple SoC with external interfaces class MySoC(wiring.Component): def __init__(self): super().__init__({ @@ -47,6 +45,12 @@ Pin signatures are used when defining your top-level component's interface: "flash": Out(QSPIFlashSignature()), }) + # Verify the component can be instantiated + soc = MySoC() + assert hasattr(soc, 'uart') + assert hasattr(soc, 'gpio') + assert hasattr(soc, 'flash') + These signatures tell ChipFlow: - How to connect your design to the physical pins of your chip From 5401eee0a81744f76cbff1730d263180b7cbc64c Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Sun, 26 Oct 2025 23:09:54 +0000 Subject: [PATCH 3/3] Document doctest strategy with comprehensive comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 4 of doctest improvements: - Add detailed comments in conf.py explaining testing philosophy - Clarify when to use testcode vs code-block - Document the selective testing approach for maintainability - Provide guidance for future contributors The strategy balances automatic validation with documentation readability, testing complete examples while keeping fragments illustrative. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/conf.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 65350965..792bff01 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -109,6 +109,28 @@ ] # Doctest configuration +# +# Strategy: Selective testing with infrastructure +# ------------------------------------------------ +# We use Sphinx doctest extension to validate code examples in our documentation. +# The approach balances completeness with maintainability: +# +# 1. Complete, runnable examples use `.. testcode::` and are validated automatically +# 2. Illustrative code fragments remain as `.. code-block::` for readability +# 3. Global setup (below) provides common imports to reduce boilerplate +# +# When to convert an example to testcode: +# - Complete class definitions that can be instantiated +# - Signature usage examples showing public API +# - Self-contained examples using only documented public APIs +# +# When to keep as code-block: +# - Incomplete fragments (e.g., just showing part of __init__) +# - Examples requiring external dependencies (chipflow_digital_ip) +# - Pseudo-code or conceptual illustrations +# +# Run tests with: pdm test-docs + doctest_global_setup = """ from pathlib import Path from amaranth import Module