mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 12:46:08 +01:00
product datasheet in progress
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
# Build outputs — regenerate with build.py
|
||||||
|
tt-datasheet.html
|
||||||
|
tt-datasheet.pdf
|
||||||
|
.tt-datasheet.chrome.html
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2020 The Archivo Project Authors (https://github.com/Omnibus-Type/Archivo)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Datasheet assets
|
||||||
|
|
||||||
|
Both files are embedded as data URIs by `build.py`, so the generated HTML is
|
||||||
|
self-contained. Swap either one by dropping in a replacement and updating the
|
||||||
|
`assets:` block in `datasheet.yaml`.
|
||||||
|
|
||||||
|
| File | Source | Licence |
|
||||||
|
| ---- | ------ | ------- |
|
||||||
|
| `archivo.woff2` | [Archivo](https://github.com/Omnibus-Type/Archivo) via Google Fonts, latin subset, variable weight 100–900 | SIL Open Font License 1.1 — see `OFL.txt` |
|
||||||
|
| `demoboard.jpg` | Tiny Tapeout ETR demoboard quickstart guide, downscaled to 1000px | © 2024 Pat Deegan, psychogenic.com — **not** covered by this repo's Apache-2.0 licence |
|
||||||
|
|
||||||
|
The demoboard photo is credited in the datasheet caption. Confirm redistribution
|
||||||
|
is agreed with the copyright holder before publishing the datasheet externally.
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
@@ -0,0 +1,257 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Build the two-page Tiny Tapeout product datasheet.
|
||||||
|
|
||||||
|
All copy, numbers and colours live in datasheet.yaml. This script renders them
|
||||||
|
through datasheet.html.mustache, inlining the font and photo as data URIs so the
|
||||||
|
result is a single self-contained file that prints to two A4 pages.
|
||||||
|
|
||||||
|
python3 docs/product/build.py # write tt-datasheet.html
|
||||||
|
python3 docs/product/build.py --pdf # also render tt-datasheet.pdf
|
||||||
|
|
||||||
|
The sheets are a fixed 297mm tall with overflow hidden, so copy that grows too
|
||||||
|
long is silently clipped rather than spilling onto a third page. Every build
|
||||||
|
therefore measures the rendered sheets in headless Chrome and fails if anything
|
||||||
|
overflows. Pass --no-check to skip that (or set CHROME if it isn't found).
|
||||||
|
|
||||||
|
Requires chevron and pyyaml, both already pinned in requirements.txt.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import base64
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import chevron
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
HERE = Path(__file__).parent
|
||||||
|
|
||||||
|
# `style` tokens in datasheet.yaml -> CSS classes in the template.
|
||||||
|
STYLE_CLASSES = {
|
||||||
|
"name": "t-name",
|
||||||
|
"mono": "t-mono",
|
||||||
|
"num": "t-num",
|
||||||
|
"price": "t-price",
|
||||||
|
"dim": "t-dim",
|
||||||
|
"center": "t-center",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tables are rendered through partials/table.mustache and need preparing first.
|
||||||
|
TABLE_KEYS = ["pricing", "process", "ratings", "gpio", "analog", "ordering"]
|
||||||
|
|
||||||
|
EM_DASH = "—"
|
||||||
|
|
||||||
|
CHROME_CANDIDATES = [
|
||||||
|
os.environ.get("CHROME"),
|
||||||
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
||||||
|
"google-chrome",
|
||||||
|
"chromium",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def cell_classes(style: str, value: str) -> str:
|
||||||
|
"""Map a column's style tokens to CSS classes for one cell."""
|
||||||
|
classes = []
|
||||||
|
for token in style.split():
|
||||||
|
try:
|
||||||
|
classes.append(STYLE_CLASSES[token])
|
||||||
|
except KeyError:
|
||||||
|
raise SystemExit(
|
||||||
|
f"unknown style '{token}' — expected one of {', '.join(STYLE_CLASSES)}"
|
||||||
|
)
|
||||||
|
# A lone em dash means "not applicable"; grey it out wherever it appears.
|
||||||
|
if value.strip() == EM_DASH and "t-dim" not in classes:
|
||||||
|
classes.append("t-dim")
|
||||||
|
return " ".join(classes)
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_table(name: str, table: dict) -> None:
|
||||||
|
"""Expand a table's columns and rows into what the template expects."""
|
||||||
|
columns = table.get("columns") or []
|
||||||
|
for column in columns:
|
||||||
|
width = column.get("width")
|
||||||
|
column["width_attr"] = f' style="width:{width}"' if width else ""
|
||||||
|
column.setdefault("label", "")
|
||||||
|
|
||||||
|
styles = [column.get("style", "") for column in columns]
|
||||||
|
|
||||||
|
rows = []
|
||||||
|
for index, row in enumerate(table.get("rows") or [], start=1):
|
||||||
|
if len(row) != len(columns):
|
||||||
|
raise SystemExit(
|
||||||
|
f"{name}: row {index} has {len(row)} cells "
|
||||||
|
f"but there are {len(columns)} columns"
|
||||||
|
)
|
||||||
|
rows.append(
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{"v": value, "cls": cell_classes(style, value)}
|
||||||
|
for style, value in zip(styles, row)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
table["rows"] = rows
|
||||||
|
table["has_note"] = bool(table.get("note"))
|
||||||
|
table["has_footnote"] = bool(table.get("footnote"))
|
||||||
|
|
||||||
|
|
||||||
|
def as_data_uri_payload(path: Path) -> str:
|
||||||
|
if not path.is_file():
|
||||||
|
raise SystemExit(f"missing asset: {path}")
|
||||||
|
return base64.b64encode(path.read_bytes()).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def find_chrome() -> str:
|
||||||
|
for candidate in CHROME_CANDIDATES:
|
||||||
|
if candidate and (Path(candidate).is_file() or shutil.which(candidate)):
|
||||||
|
return candidate
|
||||||
|
raise SystemExit(
|
||||||
|
"could not find Chrome — set the CHROME environment variable to its path"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
MEASURE_SCRIPT = """
|
||||||
|
<div id="fit-report">pending</div>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("load", () => setTimeout(() => {
|
||||||
|
const mm = 25.4 / 96;
|
||||||
|
const report = [...document.querySelectorAll(".sheet")].map((sheet, i) => {
|
||||||
|
const body = sheet.querySelector(".body");
|
||||||
|
return [i + 1, ((body.scrollHeight - body.clientHeight) * mm).toFixed(1)].join(":");
|
||||||
|
});
|
||||||
|
document.getElementById("fit-report").textContent = report.join(",");
|
||||||
|
}, 500));
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def run_chrome(*flags: str, page: Path) -> bytes:
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
find_chrome(),
|
||||||
|
"--headless",
|
||||||
|
"--disable-gpu",
|
||||||
|
"--no-sandbox",
|
||||||
|
*flags,
|
||||||
|
page.resolve().as_uri(),
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
return result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def as_document(html_path: Path, extra: str = "") -> Path:
|
||||||
|
"""Chrome needs a complete document; the published artifact is wrapped for us."""
|
||||||
|
wrapped = html_path.with_name("." + html_path.stem + ".chrome.html")
|
||||||
|
wrapped.write_text(
|
||||||
|
"<!doctype html><html><head><meta charset='utf-8'>"
|
||||||
|
"<style>*{margin:0;padding:0}</style></head><body>"
|
||||||
|
+ html_path.read_text(encoding="utf-8")
|
||||||
|
+ extra
|
||||||
|
+ "</body></html>",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
|
def check_fit(html_path: Path) -> bool:
|
||||||
|
"""Measure each sheet in Chrome; report how far any of them overflows."""
|
||||||
|
page = as_document(html_path, MEASURE_SCRIPT)
|
||||||
|
try:
|
||||||
|
dom = run_chrome("--virtual-time-budget=5000", "--dump-dom", page=page)
|
||||||
|
finally:
|
||||||
|
page.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
found = re.search(rb'<div id="fit-report">([^<]*)</div>', dom)
|
||||||
|
if not found or found.group(1) == b"pending":
|
||||||
|
logging.warning("could not measure sheet fit — skipping check")
|
||||||
|
return True
|
||||||
|
|
||||||
|
overflowed = False
|
||||||
|
for entry in found.group(1).decode().split(","):
|
||||||
|
sheet, overflow = entry.split(":")
|
||||||
|
if float(overflow) > 0:
|
||||||
|
overflowed = True
|
||||||
|
logging.error(
|
||||||
|
f"page {sheet} overflows by {overflow}mm — content past the bottom "
|
||||||
|
"of the sheet is CLIPPED, not moved to another page"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logging.info(f"page {sheet} fits")
|
||||||
|
if overflowed:
|
||||||
|
logging.error("trim copy in datasheet.yaml, or shorten a table")
|
||||||
|
return not overflowed
|
||||||
|
|
||||||
|
|
||||||
|
def render_pdf(html_path: Path, pdf_path: Path) -> None:
|
||||||
|
page = as_document(html_path)
|
||||||
|
try:
|
||||||
|
run_chrome("--no-pdf-header-footer", f"--print-to-pdf={pdf_path}", page=page)
|
||||||
|
finally:
|
||||||
|
page.unlink(missing_ok=True)
|
||||||
|
pages = len(re.findall(rb"/Type\s*/Page[^s]", pdf_path.read_bytes()))
|
||||||
|
logging.info(f"wrote {pdf_path} ({pages} pages)")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument(
|
||||||
|
"--config", default=HERE / "datasheet.yaml", type=Path, help="content YAML"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--out", default=HERE / "tt-datasheet.html", type=Path, help="output HTML"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--pdf", action="store_true", help="also render a PDF next to the HTML"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-check",
|
||||||
|
dest="check",
|
||||||
|
action="store_false",
|
||||||
|
help="skip the headless-Chrome overflow check",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO, format="%(levelname)-8s %(message)s", stream=sys.stdout
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(args.config, encoding="utf-8") as fh:
|
||||||
|
content = yaml.safe_load(fh)
|
||||||
|
|
||||||
|
for key in TABLE_KEYS:
|
||||||
|
if key not in content:
|
||||||
|
raise SystemExit(f"{args.config}: missing '{key}' section")
|
||||||
|
prepare_table(key, content[key])
|
||||||
|
|
||||||
|
assets = HERE / "assets"
|
||||||
|
content["font_b64"] = as_data_uri_payload(assets / content["assets"]["font"])
|
||||||
|
content["photo_b64"] = as_data_uri_payload(assets / content["assets"]["photo"])
|
||||||
|
|
||||||
|
with open(HERE / "datasheet.html.mustache", encoding="utf-8") as fh:
|
||||||
|
rendered = chevron.render(
|
||||||
|
fh.read(),
|
||||||
|
content,
|
||||||
|
partials_path=str(HERE / "partials"),
|
||||||
|
partials_ext="mustache",
|
||||||
|
)
|
||||||
|
|
||||||
|
args.out.write_text(rendered, encoding="utf-8")
|
||||||
|
logging.info(f"wrote {args.out} ({len(rendered) / 1024:.0f} KB)")
|
||||||
|
|
||||||
|
if args.pdf:
|
||||||
|
render_pdf(args.out, args.out.with_suffix(".pdf"))
|
||||||
|
|
||||||
|
if args.check and not check_fit(args.out):
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,486 @@
|
|||||||
|
<title>{{&doc.title}}</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: "Archivo";
|
||||||
|
src: url(data:font/woff2;base64,{{&font_b64}}) format("woff2");
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--navy: {{theme.navy}};
|
||||||
|
--red: {{theme.red}};
|
||||||
|
--ink: {{theme.ink}};
|
||||||
|
--ink-mid: {{theme.ink_mid}};
|
||||||
|
--ink-faint: {{theme.ink_faint}};
|
||||||
|
--ground: {{theme.ground}};
|
||||||
|
--rule: {{theme.rule}};
|
||||||
|
--rule-hard: {{theme.rule_hard}};
|
||||||
|
--paper: #ffffff;
|
||||||
|
--chrome: #d8d7dd;
|
||||||
|
|
||||||
|
--t-micro: 6.2pt;
|
||||||
|
--t-fine: 7.1pt;
|
||||||
|
--t-body: {{theme.body_size}};
|
||||||
|
--t-lead: 9.6pt;
|
||||||
|
--t-sub: 13pt;
|
||||||
|
--t-h2: 15pt;
|
||||||
|
--t-h1: {{theme.heading_size}};
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) { :root { --chrome: #17171c; } }
|
||||||
|
:root[data-theme="dark"] { --chrome: #17171c; }
|
||||||
|
:root[data-theme="light"] { --chrome: #d8d7dd; }
|
||||||
|
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: var(--chrome);
|
||||||
|
font-family: "Archivo", "Helvetica Neue", Arial, sans-serif;
|
||||||
|
color: var(--ink);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deck {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8mm;
|
||||||
|
padding: 8mm 4mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet {
|
||||||
|
width: 210mm;
|
||||||
|
height: 297mm;
|
||||||
|
background: var(--paper);
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- masthead ---------- */
|
||||||
|
|
||||||
|
.bar {
|
||||||
|
background: var(--navy);
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5mm;
|
||||||
|
padding: 4.2mm 12mm;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar__logo { width: 11mm; height: 11mm; flex: none; display: block; }
|
||||||
|
|
||||||
|
.bar__word {
|
||||||
|
font-size: var(--t-sub);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar__word span { display: block; font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.14em; color: #9a99d6; margin-top: 1.1mm; }
|
||||||
|
|
||||||
|
.bar__tag {
|
||||||
|
margin-left: auto;
|
||||||
|
background: var(--red);
|
||||||
|
color: #fff;
|
||||||
|
font-size: var(--t-fine);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.16em;
|
||||||
|
padding: 1.4mm 3mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar__ref { font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.1em; color: #9a99d6; font-variant-numeric: tabular-nums; }
|
||||||
|
|
||||||
|
.bar--p2 .bar__title { margin-left: auto; font-size: var(--t-fine); font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; }
|
||||||
|
|
||||||
|
/* ---------- shared structure ---------- */
|
||||||
|
|
||||||
|
.body {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: 0 12mm;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: var(--t-micro);
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.16em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--red);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label--dim { color: var(--ink-faint); }
|
||||||
|
|
||||||
|
.secthead {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 3mm;
|
||||||
|
border-bottom: 2px solid var(--rule-hard);
|
||||||
|
padding-bottom: 1.1mm;
|
||||||
|
margin-bottom: 2.1mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secthead h2 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--t-h2);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.015em;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secthead .note { margin-left: auto; font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.06em; color: var(--ink-faint); }
|
||||||
|
|
||||||
|
/* ---------- hero ---------- */
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.32fr 1fr;
|
||||||
|
gap: 7mm;
|
||||||
|
padding: 4.6mm 0 4.2mm;
|
||||||
|
border-bottom: 2px solid var(--rule-hard);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
margin: 2.2mm 0 0;
|
||||||
|
font-size: var(--t-h1);
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 0.97;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
margin: 3mm 0 0;
|
||||||
|
font-size: var(--t-lead);
|
||||||
|
line-height: 1.4;
|
||||||
|
color: var(--ink);
|
||||||
|
max-width: 62ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .rule { height: 2px; background: var(--red); width: 22mm; margin-top: 3.2mm; }
|
||||||
|
|
||||||
|
.hero figure { margin: 0; display: flex; flex-direction: column; }
|
||||||
|
|
||||||
|
.hero img { width: 100%; height: 44mm; object-fit: cover; display: block; }
|
||||||
|
|
||||||
|
.hero figcaption {
|
||||||
|
font-size: var(--t-micro);
|
||||||
|
color: var(--ink-faint);
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
margin-top: 1.4mm;
|
||||||
|
border-top: 1px solid var(--rule);
|
||||||
|
padding-top: 1.2mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- feature grid ---------- */
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
border-bottom: 2px solid var(--rule-hard);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature {
|
||||||
|
padding: 2.8mm 4mm 2.9mm 0;
|
||||||
|
border-right: 1px solid var(--rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature:nth-child(3n) { border-right: 0; padding-right: 0; }
|
||||||
|
.feature:nth-child(n + 4) { border-top: 1px solid var(--rule); }
|
||||||
|
|
||||||
|
.feature h3 {
|
||||||
|
margin: 1.6mm 0 1.4mm;
|
||||||
|
font-size: var(--t-body);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.005em;
|
||||||
|
line-height: 1.12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature p { margin: 0; font-size: var(--t-fine); line-height: 1.36; color: var(--ink-mid); }
|
||||||
|
|
||||||
|
/* ---------- tables ---------- */
|
||||||
|
|
||||||
|
table { width: 100%; border-collapse: collapse; }
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: var(--navy);
|
||||||
|
color: #fff;
|
||||||
|
font-size: var(--t-micro);
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.13em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: left;
|
||||||
|
padding: 1.35mm 2.4mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
font-size: var(--t-fine);
|
||||||
|
line-height: 1.3;
|
||||||
|
padding: 1.35mm 2.4mm;
|
||||||
|
border-bottom: 1px solid var(--rule);
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:last-child td { border-bottom: 0; }
|
||||||
|
|
||||||
|
.t-num { font-variant-numeric: tabular-nums; }
|
||||||
|
.t-name { font-weight: 600; white-space: nowrap; }
|
||||||
|
.t-mono { font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; white-space: nowrap; }
|
||||||
|
.t-price { font-weight: 700; color: var(--red); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
||||||
|
.t-dim { color: var(--ink-faint); }
|
||||||
|
.t-center { text-align: center; }
|
||||||
|
.t-sub { color: var(--ink-faint); font-weight: 500; }
|
||||||
|
|
||||||
|
.zebra tbody tr:nth-child(odd) td { background: var(--ground); }
|
||||||
|
|
||||||
|
.tnote {
|
||||||
|
font-size: var(--t-micro);
|
||||||
|
line-height: 1.4;
|
||||||
|
color: var(--ink-mid);
|
||||||
|
border-left: 2px solid var(--red);
|
||||||
|
padding: 0 0 0 2.6mm;
|
||||||
|
margin-top: 1.9mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tnote b { color: var(--ink); font-weight: 700; }
|
||||||
|
|
||||||
|
/* ---------- pricing / faq blocks ---------- */
|
||||||
|
|
||||||
|
.block { padding: 3.2mm 0; border-bottom: 2px solid var(--rule-hard); }
|
||||||
|
.block:last-of-type { border-bottom: 0; }
|
||||||
|
|
||||||
|
.faq {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
column-gap: 8mm;
|
||||||
|
row-gap: 2.6mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq > div { border-top: 1px solid var(--rule); padding-top: 1.8mm; }
|
||||||
|
|
||||||
|
.faq h3 {
|
||||||
|
margin: 0 0 1.2mm;
|
||||||
|
font-size: var(--t-body);
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.15;
|
||||||
|
letter-spacing: -0.005em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq p { margin: 0; font-size: var(--t-fine); line-height: 1.36; color: var(--ink-mid); }
|
||||||
|
|
||||||
|
/* ---------- page 2 two-column band ---------- */
|
||||||
|
|
||||||
|
.band { display: grid; grid-template-columns: 1.05fr 1fr; gap: 8mm; }
|
||||||
|
|
||||||
|
.band__col { display: flex; flex-direction: column; min-width: 0; }
|
||||||
|
|
||||||
|
.linkline {
|
||||||
|
font-size: var(--t-micro);
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--ink-faint);
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 1.4mm;
|
||||||
|
border-top: 1px solid var(--rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkline b { color: var(--red); font-weight: 700; }
|
||||||
|
|
||||||
|
a { color: inherit; text-decoration: none; }
|
||||||
|
a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
|
||||||
|
@media screen { .tnote a, .note a { text-decoration: underline; text-underline-offset: 1.5px; } }
|
||||||
|
|
||||||
|
/* ---------- footers ---------- */
|
||||||
|
|
||||||
|
.foot {
|
||||||
|
flex: none;
|
||||||
|
padding: 3.4mm 12mm 5mm;
|
||||||
|
border-top: 2px solid var(--rule-hard);
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 6mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foot__body { flex: 1 1 auto; min-width: 0; }
|
||||||
|
|
||||||
|
.orgs {
|
||||||
|
margin-top: 1.8mm;
|
||||||
|
font-size: var(--t-fine);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--ink);
|
||||||
|
column-count: 2;
|
||||||
|
column-gap: 8mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orgs span { display: block; white-space: nowrap; }
|
||||||
|
.orgs span::before { content: "▪"; color: var(--red); margin-right: 1.6mm; font-size: 0.8em; }
|
||||||
|
|
||||||
|
.disclaimer { margin-top: 1.8mm; font-size: var(--t-micro); line-height: 1.45; color: var(--ink-mid); max-width: 150mm; }
|
||||||
|
|
||||||
|
.pageno {
|
||||||
|
flex: none;
|
||||||
|
font-size: var(--t-h2);
|
||||||
|
font-weight: 700;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
line-height: 0.9;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageno span { display: block; font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.14em; color: var(--ink-faint); margin-bottom: 1mm; }
|
||||||
|
|
||||||
|
/* ---------- print ---------- */
|
||||||
|
|
||||||
|
@page { size: A4; margin: 0; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body { background: #fff; }
|
||||||
|
.deck { display: block; gap: 0; padding: 0; }
|
||||||
|
.sheet { break-after: page; page-break-after: always; box-shadow: none; }
|
||||||
|
.sheet:last-child { break-after: auto; page-break-after: auto; }
|
||||||
|
th, .bar, .bar__tag, .zebra tbody tr:nth-child(odd) td {
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen {
|
||||||
|
.sheet { border: 1px solid var(--rule); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="deck">
|
||||||
|
|
||||||
|
<!-- ========================= PAGE 1 ========================= -->
|
||||||
|
<section class="sheet">
|
||||||
|
|
||||||
|
<header class="bar">
|
||||||
|
{{> logo}}
|
||||||
|
<div class="bar__word">{{&doc.wordmark}}<span>{{&doc.wordmark_sub}}</span></div>
|
||||||
|
<div class="bar__tag">{{&doc.tag}}</div>
|
||||||
|
<div class="bar__ref">{{&doc.ref}}</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="body">
|
||||||
|
|
||||||
|
<div class="hero">
|
||||||
|
<div>
|
||||||
|
<div class="label">{{&hero.eyebrow}}</div>
|
||||||
|
<h1>{{&hero.heading}}</h1>
|
||||||
|
<p>{{&hero.body}}</p>
|
||||||
|
<div class="rule"></div>
|
||||||
|
</div>
|
||||||
|
<figure>
|
||||||
|
<img src="data:image/jpeg;base64,{{&photo_b64}}" alt="{{hero.photo_alt}}">
|
||||||
|
<figcaption>{{&hero.photo_caption}}</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="features">
|
||||||
|
{{#features}}
|
||||||
|
<div class="feature">
|
||||||
|
<div class="label label--dim">{{&kicker}}</div>
|
||||||
|
<h3>{{&title}}</h3>
|
||||||
|
<p>{{&body}}</p>
|
||||||
|
</div>
|
||||||
|
{{/features}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
{{#pricing}}{{> secthead}}{{> table}}{{> footnote}}{{/pricing}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
{{#faq}}
|
||||||
|
{{> secthead}}
|
||||||
|
<div class="faq">
|
||||||
|
{{#items}}
|
||||||
|
<div>
|
||||||
|
<h3>{{&q}}</h3>
|
||||||
|
<p>{{&a}}</p>
|
||||||
|
</div>
|
||||||
|
{{/items}}
|
||||||
|
</div>
|
||||||
|
{{/faq}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="foot">
|
||||||
|
<div class="foot__body">
|
||||||
|
<div class="label label--dim">{{&institutions.label}}</div>
|
||||||
|
<div class="orgs">
|
||||||
|
{{#institutions.items}}<span>{{&.}}</span>
|
||||||
|
{{/institutions.items}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pageno"><span>PAGE</span>01</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ========================= PAGE 2 ========================= -->
|
||||||
|
<section class="sheet">
|
||||||
|
|
||||||
|
<header class="bar bar--p2">
|
||||||
|
{{> logo}}
|
||||||
|
<div class="bar__word">{{&doc.wordmark}}<span>{{&doc.ref}}</span></div>
|
||||||
|
<div class="bar__title">{{&doc.page2_title}}</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="body">
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
{{#process}}{{> secthead}}{{> table}}{{> footnote}}{{/process}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
{{#ratings}}{{> secthead}}{{> table}}{{> footnote}}{{/ratings}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
<div class="band">
|
||||||
|
<div class="band__col">
|
||||||
|
{{#gpio}}
|
||||||
|
{{> secthead}}
|
||||||
|
{{> table}}
|
||||||
|
<div class="linkline">{{&linkline}}</div>
|
||||||
|
{{/gpio}}
|
||||||
|
</div>
|
||||||
|
<div class="band__col">
|
||||||
|
{{#analog}}
|
||||||
|
{{> secthead}}
|
||||||
|
{{> table}}
|
||||||
|
<div class="linkline">{{&linkline}}</div>
|
||||||
|
{{/analog}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
{{#ordering}}{{> secthead}}{{> table}}{{> footnote}}{{/ordering}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="foot">
|
||||||
|
<div class="foot__body">
|
||||||
|
<div class="label label--dim">{{&disclaimer.label}}</div>
|
||||||
|
<p class="disclaimer">{{&disclaimer.body}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="pageno"><span>PAGE</span>02</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Tiny Tapeout product datasheet — all copy, numbers and colours.
|
||||||
|
#
|
||||||
|
# Edit this file, then rebuild:
|
||||||
|
# python3 docs/product/build.py
|
||||||
|
#
|
||||||
|
# Notes for editing:
|
||||||
|
# - Every text field is rendered as raw HTML, so <b>, <br> and <a href="...">
|
||||||
|
# work anywhere. Write a literal ampersand as &.
|
||||||
|
# - Table `style` tokens set cell formatting, space separated:
|
||||||
|
# name bold, no wrapping (first column of most tables)
|
||||||
|
# mono bold + tabular figures (dimensions, values, signal names)
|
||||||
|
# num tabular figures (aligned digits)
|
||||||
|
# price bold red + no wrapping (pricing column)
|
||||||
|
# dim greyed out (em dashes, secondary text)
|
||||||
|
# center centre aligned
|
||||||
|
# - Table rows must have the same number of cells as there are columns.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
doc:
|
||||||
|
title: Tiny Tapeout — Datasheet
|
||||||
|
wordmark: Tiny Tapeout
|
||||||
|
wordmark_sub: SHARED SILICON ASIC SHUTTLE
|
||||||
|
tag: DATASHEET
|
||||||
|
ref: DOC TT-DS-2026 · REV A
|
||||||
|
page2_title: Electrical & Mechanical Specifications
|
||||||
|
|
||||||
|
# Colours and the two page-level type sizes. Everything else scales from these.
|
||||||
|
theme:
|
||||||
|
navy: "#040371" # header bars and table header rows
|
||||||
|
red: "#ec3013" # accent: labels, rules, prices
|
||||||
|
ink: "#141414" # body text
|
||||||
|
ink_mid: "#55545f" # secondary text
|
||||||
|
ink_faint: "#86858f" # captions, dashes
|
||||||
|
ground: "#f2f1f4" # zebra stripe on tables
|
||||||
|
rule: "#c9c8d0" # thin rules
|
||||||
|
rule_hard: "#141414" # 2px section rules
|
||||||
|
heading_size: 30pt # page 1 headline
|
||||||
|
body_size: 8.3pt # feature and FAQ body text
|
||||||
|
|
||||||
|
assets:
|
||||||
|
# Relative to docs/product/assets/. Swap either file and rebuild.
|
||||||
|
photo: demoboard.jpg
|
||||||
|
font: archivo.woff2
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# PAGE 1
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
hero:
|
||||||
|
eyebrow: Shared multi-project chip · SKY130 / SG13G2 / GF180MCU
|
||||||
|
heading: From idea to chip design in minutes
|
||||||
|
body: >-
|
||||||
|
Tiny Tapeout makes it more accessible than ever to get your designs manufactured on a real chip.
|
||||||
|
Submit from a
|
||||||
|
GitHub repository and we handle integration, tapeout, packaging and delivery.
|
||||||
|
photo_alt: Tiny Tapeout ETR demoboard with a QFN-64 packaged ASIC on a breakout board
|
||||||
|
photo_caption: Demoboard with QFN-64 packaged die on breakout carrier.
|
||||||
|
|
||||||
|
features:
|
||||||
|
- kicker: 01 · Toolchain
|
||||||
|
title: Local tool install optional
|
||||||
|
body: >-
|
||||||
|
The whole flow can run in GitHub Actions. Push your repository and your design
|
||||||
|
is hardened in the cloud — nothing to install, no licences to buy.
|
||||||
|
- kicker: 02 · Languages
|
||||||
|
title: HDL agnostic
|
||||||
|
body: >-
|
||||||
|
Any language that can produce Verilog RTL. Project templates and CI are
|
||||||
|
supplied for Verilog, with community provided VHDL and Chisel.
|
||||||
|
- kicker: 03 · I/O
|
||||||
|
title: 26 pins, plus analog
|
||||||
|
body: >-
|
||||||
|
Clock, reset, 8 dedicated inputs, 8 dedicated outputs and 8 bidirectional
|
||||||
|
pins — plus up to 6 analog pins where the process allows.
|
||||||
|
- kicker: 04 · Process
|
||||||
|
title: Three PDKs
|
||||||
|
body: >-
|
||||||
|
SkyWater SKY130, IHP sg13g2 and GlobalFoundries gf180mcu. Open-source PDKs
|
||||||
|
running multiple times per year.
|
||||||
|
- kicker: 05 · Hardware
|
||||||
|
title: Demoboard available
|
||||||
|
body: >-
|
||||||
|
An optional RP2350-based demoboard carries your packaged chip and selects
|
||||||
|
any project on the die over USB.
|
||||||
|
- kicker: 06 · Flexibility
|
||||||
|
title: Bring your own flow
|
||||||
|
body: >-
|
||||||
|
Harden with the supplied open-source LibreLane flow, or use your own tools
|
||||||
|
entirely — the minimum submission is GDS + LEF.
|
||||||
|
|
||||||
|
pricing:
|
||||||
|
heading: Pricing
|
||||||
|
note: INDICATIVE FROM-PRICES · EUR
|
||||||
|
columns:
|
||||||
|
- {label: Item, width: "27%", style: name}
|
||||||
|
- {label: What it buys you}
|
||||||
|
- {label: From, width: "26%", style: price}
|
||||||
|
rows:
|
||||||
|
- ["1 tile",
|
||||||
|
"Roughly 1,000 standard cells of silicon area. Physical dimensions vary by PDK — see page 2.",
|
||||||
|
"€70"]
|
||||||
|
- ["Analog pin",
|
||||||
|
"Multiplexed analog pad access for mixed signal designs. Minimum project size of 2 tiles applies.",
|
||||||
|
"€100 <span class=\"t-sub\">/ pin</span>"]
|
||||||
|
- ["Demoboard PCB",
|
||||||
|
"Optional add-on: your packaged chip, an RP2350 demoboard and a breakout board.",
|
||||||
|
"€100 <span class=\"t-sub\">first 80 boards for individuals are subsidised</span><br>€300 <span class=\"t-sub\">academic & industry</span>"]
|
||||||
|
footnote: >-
|
||||||
|
<b>Silicon area and the demoboard are billed separately.</b> Buying area gets
|
||||||
|
your design manufactured on the wafer — on its own it does not get you a
|
||||||
|
physical chip. To hold your chip in your hand, add the demoboard PCB. Confirm
|
||||||
|
current figures at
|
||||||
|
<b><a href="https://app.tinytapeout.com/calculator">app.tinytapeout.com/calculator</a></b>.
|
||||||
|
|
||||||
|
faq:
|
||||||
|
heading: Frequently asked Questions
|
||||||
|
note: FULL FAQ AT TINYTAPEOUT.COM/FAQ
|
||||||
|
items:
|
||||||
|
- q: How long until I get my chip?
|
||||||
|
a: >-
|
||||||
|
Fabrication takes 6–9 months, then boards are assembled, tested and
|
||||||
|
shipped. Check <a href="https://app.tinytapeout.com/chips">tinytapeout.com/chips</a> for the schedule.</b>.
|
||||||
|
- q: Do I need chip design experience?
|
||||||
|
a: >-
|
||||||
|
No. Getting started documentation on the website and help on the Discord community helps beginners get started.
|
||||||
|
Thousands of past projects are public to learn from.
|
||||||
|
- q: What do I actually receive?
|
||||||
|
a: >-
|
||||||
|
Area alone gets your design onto the wafer. Add the demoboard to receive a
|
||||||
|
packaged chip, an RP2350 demoboard and a breakout board. Bare chips are not available separately.
|
||||||
|
- q: Which processes can I use?
|
||||||
|
a: >-
|
||||||
|
SkyWater SKY130 (130 nm), IHP sg13g2 (130 nm BiCMOS) and GlobalFoundries
|
||||||
|
gf180mcu (180 nm), each on its own shuttle schedule.
|
||||||
|
- q: Is it only open to individuals?
|
||||||
|
a: >-
|
||||||
|
No. Universities, schools and companies run group submissions, and dozens
|
||||||
|
of institutions already teach with Tiny Tapeout.
|
||||||
|
- q: What are the licence terms?
|
||||||
|
a: >-
|
||||||
|
Every design is published publicly under Apache-2.0. The minimum
|
||||||
|
submission is GDS + LEF, produced with any toolchain you like.
|
||||||
|
|
||||||
|
institutions:
|
||||||
|
label: Taught and used at
|
||||||
|
items:
|
||||||
|
- Carnegie Mellon University
|
||||||
|
- New York University
|
||||||
|
- UC Santa Cruz
|
||||||
|
- UC San Diego
|
||||||
|
- San Jose State University
|
||||||
|
- Oklahoma State University
|
||||||
|
- Technical University of Denmark
|
||||||
|
- Linköping University
|
||||||
|
- Graz University of Technology
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# PAGE 2
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
process:
|
||||||
|
heading: Process & fabrication
|
||||||
|
note: TILE DIMENSIONS PER PDK
|
||||||
|
columns:
|
||||||
|
- {label: PDK, width: "19%", style: name}
|
||||||
|
- {label: Foundry, width: "21%"}
|
||||||
|
- {label: Node, width: "17%", style: num}
|
||||||
|
- {label: 1×1 tile area, width: "25%", style: mono}
|
||||||
|
- {label: Package}
|
||||||
|
rows:
|
||||||
|
- ["SKY130A", "SkyWater", "130 nm", "161.00 × 111.52 µm", "QFN-64"]
|
||||||
|
- ["ihp-sg13g2", "IHP", "130 nm BiCMOS", "202.08 × 154.98 µm", "QFN-64"]
|
||||||
|
- ["gf180mcuD", "GlobalFoundries", "180 nm", "346.64 × 160.72 µm", "QFN-64"]
|
||||||
|
footnote: >-
|
||||||
|
One tile holds approximately <b>1,000 standard cells</b>. Larger designs are
|
||||||
|
built from multi-tile blocks from 1×2 up to 8×4; the available sizes differ
|
||||||
|
per PDK. Analog projects require a minimum height of 2 tiles.
|
||||||
|
|
||||||
|
ratings:
|
||||||
|
heading: Absolute maximum ratings
|
||||||
|
note: DIGITAL I/O
|
||||||
|
columns:
|
||||||
|
- {label: Parameter, width: "40%", style: name}
|
||||||
|
- {label: Min, width: "13%", style: num}
|
||||||
|
- {label: Typ, width: "13%", style: num}
|
||||||
|
- {label: Max, width: "13%", style: num}
|
||||||
|
- {label: Unit}
|
||||||
|
rows:
|
||||||
|
- ["I/O supply voltage", "1.71", "3.30", "5.50", "V"]
|
||||||
|
- ["Input frequency", "—", "—", "66", "MHz"]
|
||||||
|
- ["Output toggle frequency", "—", "—", "33", "MHz"]
|
||||||
|
- ["Output drive strength, source/sink", "—", "4", "—", "mA"]
|
||||||
|
- ["Demoboard clock generator", "1", "—", "66.5 M", "Hz"]
|
||||||
|
- ["Pad-to-tile round-trip latency", "—", "—", "20", "ns"]
|
||||||
|
- ["Clock insertion delay, pad to logic", "—", "—", "10", "ns"]
|
||||||
|
- ["Pin-to-pin latency variance", "—", "—", "2", "ns"]
|
||||||
|
footnote: >-
|
||||||
|
Characterised on <b>SKY130A</b> using the <b>sky130_ef_io_gpiov2_pad</b> cell;
|
||||||
|
ratings differ per PDK. Inputs are <b>not 5 V tolerant</b> despite the supply
|
||||||
|
range. Full per-process figures at
|
||||||
|
<b><a href="https://tinytapeout.com/specs/">tinytapeout.com/specs</a></b>.
|
||||||
|
|
||||||
|
gpio:
|
||||||
|
heading: GPIO pin map
|
||||||
|
columns:
|
||||||
|
- {label: Signal, width: "34%", style: mono}
|
||||||
|
- {label: Width, width: "14%", style: num center}
|
||||||
|
- {label: Direction, width: "22%"}
|
||||||
|
- {label: Function}
|
||||||
|
rows:
|
||||||
|
- ["clk", "1", "Input", "Clock"]
|
||||||
|
- ["rst_n", "1", "Input", "Reset, active low"]
|
||||||
|
- ["ui_in[7:0]", "8", "Input", "General purpose"]
|
||||||
|
- ["uo_out[7:0]", "8", "Output", "General purpose"]
|
||||||
|
- ["uio[7:0]", "8", "Bidirectional", "Per-pin direction control"]
|
||||||
|
linkline: >-
|
||||||
|
26 I/O PINS TOTAL ·
|
||||||
|
<b><a href="https://tinytapeout.com/specs/gpio/">TINYTAPEOUT.COM/SPECS/GPIO</a></b>
|
||||||
|
|
||||||
|
analog:
|
||||||
|
heading: Analog I/O
|
||||||
|
note: OPTIONAL
|
||||||
|
columns:
|
||||||
|
- {label: Parameter, style: name}
|
||||||
|
- {label: Value, width: "34%", style: mono}
|
||||||
|
rows:
|
||||||
|
- ["Analog pins, maximum", "6 · ua[0:5]"]
|
||||||
|
- ["Series resistance, pad to project", "< 500 Ω"]
|
||||||
|
- ["Parasitic capacitance", "< 5 pF"]
|
||||||
|
- ["Current per pin, maximum", "4 mA"]
|
||||||
|
- ["VDPWR digital supply", "1.8 V"]
|
||||||
|
- ["VAPWR analog supply", "3.3 V"]
|
||||||
|
linkline: >-
|
||||||
|
ALLOCATED IN ORDER ·
|
||||||
|
<b><a href="https://tinytapeout.com/specs/analog/">TINYTAPEOUT.COM/SPECS/ANALOG</a></b>
|
||||||
|
|
||||||
|
ordering:
|
||||||
|
heading: Ordering information
|
||||||
|
note: APP.TINYTAPEOUT.COM/CALCULATOR
|
||||||
|
headless: true # no header row on this table
|
||||||
|
columns:
|
||||||
|
- {width: "27%", style: name}
|
||||||
|
- {}
|
||||||
|
rows:
|
||||||
|
- ["Shuttle cadence",
|
||||||
|
"Several shuttles per year across the three processes. Check <a href="https://app.tinytapeout.com/chips">tinytapeout.com/chips</a> for the schedule"]
|
||||||
|
- ["Lead time",
|
||||||
|
"6–9 months in fabrication, then assembly, test and fulfilment."]
|
||||||
|
- ["Deliverable",
|
||||||
|
"Silicon area only for remote or shared test, or area plus the demoboard kit: packaged chip, RP2350 demoboard and breakout board."]
|
||||||
|
- ["Design tools",
|
||||||
|
"Supplied open-source LibreLane flow running in GitHub Actions, or any toolchain of your own."]
|
||||||
|
- ["Minimum submission",
|
||||||
|
"GDS + LEF in a public repository, licensed Apache-2.0."]
|
||||||
|
|
||||||
|
disclaimer:
|
||||||
|
label: Disclaimer
|
||||||
|
body: >-
|
||||||
|
Specifications are indicative and subject to change between shuttles.
|
||||||
|
Electrical characteristics are quoted for the SKY130A process unless stated
|
||||||
|
otherwise — consult tinytapeout.com/specs for the process you intend to use.
|
||||||
|
Pricing is indicative; confirm current figures with the calculator before
|
||||||
|
ordering. Tiny Tapeout devices are educational and prototyping parts, and are
|
||||||
|
not qualified for safety-critical, medical or automotive use.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{{#has_footnote}}<p class="tnote">{{&footnote}}</p>{{/has_footnote}}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<svg class="bar__logo" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Tiny Tapeout logo">
|
||||||
|
<g transform="matrix(0.75075075,0,0,0.7513148,-156.00601,-72.426747)" fill="#ffffff">
|
||||||
|
<path d="m 341,96.4 c -44.5,0 -83.9,21.9 -108.1,55.5 -7.9,11 -14.2,23.2 -18.5,36.4 h 21.6 52.1 v 90.1 h 39.3 v -24.3 h 22.7 v 87.8 c -3,0.3 -6.1,0.4 -9.2,0.4 -62.2,0 -112.8,-50.6 -112.8,-112.8 0,-10.3 1.4,-20.2 4,-29.6 h -21 c -2.2,9.5 -3.3,19.4 -3.3,29.6 0,73.4 59.7,133.1 133.1,133.1 3.1,0 6.1,-0.1 9.2,-0.3 1.7,-0.1 3.4,-0.3 5.1,-0.5 0.1,0 0.3,0 0.4,0 11.8,-1.3 23.1,-4.1 33.8,-8.3 v 0 c 0,0 0,0 0,0 V 254.1 H 428 V 217.7 H 327.5 V 188.2 H 366 V 151.8 H 259.3 c 20.5,-21.6 49.6,-35.1 81.7,-35.1 62.2,0 112.8,50.6 112.8,112.8 0,40.1 -21,75.4 -52.6,95.4 v 23.4 c 43.3,-22 73,-67 73,-118.8 C 474.1,156.1 414.4,96.4 341,96.4 Z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 859 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<div class="secthead">
|
||||||
|
<h2>{{&heading}}</h2>
|
||||||
|
{{#has_note}}<div class="note">{{¬e}}</div>{{/has_note}}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<table class="zebra">
|
||||||
|
<colgroup>{{#columns}}<col{{&width_attr}}>{{/columns}}</colgroup>
|
||||||
|
{{^headless}}
|
||||||
|
<thead><tr>{{#columns}}<th>{{&label}}</th>{{/columns}}</tr></thead>
|
||||||
|
{{/headless}}
|
||||||
|
<tbody>
|
||||||
|
{{#rows}}
|
||||||
|
<tr>{{#cells}}<td class="{{cls}}">{{&v}}</td>{{/cells}}</tr>
|
||||||
|
{{/rows}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
Reference in New Issue
Block a user