codex/dma-data-and-control-paths.py

dma-data-and-control-paths.py
"""Draw schematic DMA payload and control paths; no real hardware operations.

Tested with Python 3.14.4, Matplotlib 3.10.7.
Run from _media; the opaque matching PNG is written to the current directory.
"""

from pathlib import Path

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch, FancyBboxPatch


def main():
    plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 12})
    fig, ax = plt.subplots(figsize=(10, 6.5), dpi=110, facecolor="white")
    ax.set(xlim=(0, 12), ylim=(0, 8))
    ax.axis("off")
    ink, blue, orange = "#203040", "#155d8a", "#a84b12"

    def text(x, y, label, size=12, color=ink, weight="normal", background=False):
        ax.text(x, y, label, ha="center", va="center", fontsize=size,
                color=color, weight=weight, linespacing=1.4, zorder=6,
                bbox=dict(facecolor="white", edgecolor="none", pad=2)
                if background else None)

    def box(x, y, w, h, label, color=blue):
        ax.add_patch(FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.06",
                                   facecolor="#f5f8fb", edgecolor=color, linewidth=1.7))
        text(x + w / 2, y + h / 2, label, 13, color)

    def arrow(start, end, control=False, curve=0):
        ax.add_patch(FancyArrowPatch(start, end, arrowstyle="-|>",
                                   mutation_scale=19, linewidth=1.9 if control else 3.3,
                                   linestyle="--" if control else "-",
                                   color=orange if control else blue,
                                   connectionstyle=f"arc3,rad={curve}"))

    text(6, 7.65, "DMA: separate data movement from CPU control", 18, weight="bold")
    text(6, 7.15, "Toy receive operation: four bytes A, B, C, D", 12)
    box(4.3, 5.6, 3.4, 1.0, "CPU running driver code", orange)
    box(0.65, 2.9, 2.8, 1.0, "Device with\nDMA engine")
    box(4.55, 2.9, 2.9, 1.0, "Optional IOMMU\ntranslation / protection")
    box(8.55, 2.9, 2.8, 1.0, "Memory buffer\n[A] [B] [C] [D]")

    arrow((4.28, 6.05), (1.35, 3.98), True, 0.18)
    text(1.7, 5.9, "1. Setup:\naddress, length, direction", 11, orange, background=True)
    arrow((3.0, 3.98), (5.25, 5.55), True, 0.08)
    text(5.9, 4.7, "3. Completion\nnotification", 11, orange, background=True)
    arrow((7.72, 6.02), (10.5, 3.98), True, -0.12)
    text(10.4, 6.15, "CPU still coordinates\nbuffer ownership,\ncaches and mappings", 11, orange, background=True)

    arrow((3.55, 3.4), (4.45, 3.4))
    arrow((7.55, 3.4), (8.45, 3.4))
    text(6, 2.35, "2. Payload data: device → memory", 14, blue, "bold")
    text(6, 1.9, "No per-item CPU copy on this path; interconnect details omitted.", 11)
    text(6, 1.45, "Dashed orange = CPU setup / completion / coordination", 11, orange)
    text(6, 1.05, "Solid blue = payload transfer", 11, blue)
    text(6, 0.55, "Completion may use an interrupt or be polled. DMA is not an interrupt.", 11)
    fig.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99)
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"),
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()