# SKY130 Open MPW mask-layer renders

**Start at [masks.html](masks.html)** - every run against every mask layer, each cell
linking to that render's 40-die grid with the project, die size and shape count behind each
image. There is a page per shuttle run (`mpw-001.html` ...) and one inside every render
directory (`<run>_<mask>/<run>_<mask>.html`). They are plain HTML: no JavaScript, no server.

One directory per (shuttle run, mask layer): the drawn shapes that go on that photomask,
rendered from the tapeout layouts the 40 projects of that run submitted.

    <run>_<mask>/<run>_<mask>_reticle.png            all 40 dies, stitched at the manifest's
                                                     frame positions (A1..F7), 0.5 um/pixel
    <run>_<mask>_reticle_overview.png                the same, scaled to fit 4096 px
    <run>_<mask>_tile_XY.png                         one grid cell of the reticle, 42 of them
    <run>_<mask>_tiles.json                          where each tile belongs, and its checksum
    reconstruct_reticle.py                           rebuilds the reticle PNG from the tiles
    <run>_<mask>_slot-NNN_XY.png                     one die, 0.125 um/pixel, white = mask shapes
    <run>_<mask>_slot-NNN_XY.json                    that die's extent, shape count and source path
    job.json / result.json                           what was rendered and from where
    MD5SUMS / SHA1SUMS / SHA256SUMS                  checksums for that directory's own files

## The full-resolution reticles are 3.5 gigapixels

Every `_reticle.png` is 53432 x 65056 pixels. The files are small - a few MB for a sparse
mask layer - but the *dimensions* are the problem: decoding one needs around 3.5 GB of
memory however small the file is, and most image viewers refuse outright.

So each reticle is also published as **42 tiles**, a 7 x 6 grid of about 7576 x 10776 pixels
each, named by the frame position they cover (`_tile_A1.png` ... `_tile_F7.png`). The cuts
fall in the gaps between dies, never through one, so **every tile holds whole projects** -
tile `D3` is exactly the die in frame D3, with the surrounding scribe. Which project that is
is in `<run>_<mask>_tiles.json`, alongside each tile's position, size and SHA-256.

Two of the 42 cells hold no project: those are SkyWater's process test structures, which are
not in the tapeout manifest and so are not rendered. They are still published, just
unattributed.

### Putting the big image back together

`reconstruct_reticle.py` rebuilds the full-resolution PNG from the tiles, **byte for byte**:

    python3 reconstruct_reticle.py

It needs nothing but Python 3 itself - no pip install, no Pillow, no numpy. Run it in a
directory holding the tiles and the `_tiles.json` manifest and it finds them itself. It
checks every tile's SHA-256 as it reads it, and the finished file's SHA-256 against the
manifest.

This works because both the tiles and the full image are written with PNG's *Up* filter,
which predicts each pixel from the one above it and never looks left - so a row of tiles'
scanlines laid end to end *is* the full image's scanline. Rebuilding moves bytes; it does no
pixel arithmetic, which is why a pure-Python script can do it at a sensible speed.

If your Python's zlib compresses differently from the one that produced these files (some
distributions ship zlib-ng), the rebuilt file will have identical pixels but different bytes.
The script detects exactly that case and tells you so, rather than reporting a failure: it
verifies the uncompressed PNG data stream, which matches regardless.

## Checksums

Every directory carries `MD5SUMS`, `SHA1SUMS` and `SHA256SUMS` listing its own files, in the
format the standard tools read:

    sha256sum -c SHA256SUMS

They cover only that directory, never its subdirectories, so they stay valid for whatever
subset of the tree you actually downloaded.

## Provenance

Sources are the public shuttle repositories under
https://foss-eda-tools.googlesource.com/third_party/shuttle/sky130/ ; every slot's layout is
named by `repo_path` in the JSON, so any image here can be traced back to the tapeout it came
from. Layer numbers are SKY130 drawn layers; fab-derived masks (HVTPM, LVTNM, NCM, NTM, HVNTM)
are evaluated as a boolean expression over drawn layers, recorded as `expr`.

These are renders of *drawn* data, not photomask artwork: reticle pitch, 4x reduction, mirroring
and the frame features the fab adds are not modelled. Empty images are real results - several
masks are used by no project on a given shuttle.

Generated with sky130-mask-decoder. The custody field recording who holds a physical mask set is
omitted from the metadata published here.
