mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 04:36:09 +01:00
tweaking datasheet
This commit is contained in:
+65
-2
@@ -101,6 +101,69 @@ def prepare_table(name: str, table: dict) -> None:
|
||||
table["has_footnote"] = bool(table.get("footnote"))
|
||||
|
||||
|
||||
def load_config(path: Path) -> dict:
|
||||
"""Parse the content YAML, reporting syntax errors against the offending line."""
|
||||
text = path.read_text(encoding="utf-8")
|
||||
try:
|
||||
return yaml.safe_load(text)
|
||||
except yaml.YAMLError as error:
|
||||
mark = getattr(error, "problem_mark", None)
|
||||
detail = getattr(error, "problem", str(error))
|
||||
if mark is None:
|
||||
raise SystemExit(f"{path}: {detail}")
|
||||
line = (
|
||||
text.splitlines()[mark.line] if mark.line < len(text.splitlines()) else ""
|
||||
)
|
||||
raise SystemExit(
|
||||
f"{path}:{mark.line + 1}: {detail}\n"
|
||||
f" {line.strip()}\n"
|
||||
' hint: inside a "quoted" value, HTML quotes must be escaped as \\"'
|
||||
)
|
||||
|
||||
|
||||
def walk_strings(node, path: str = ""):
|
||||
"""Yield (dotted-path, text) for every string in the loaded config."""
|
||||
if isinstance(node, dict):
|
||||
for key, value in node.items():
|
||||
yield from walk_strings(value, f"{path}.{key}" if path else str(key))
|
||||
elif isinstance(node, list):
|
||||
for index, value in enumerate(node):
|
||||
yield from walk_strings(value, f"{path}[{index}]")
|
||||
elif isinstance(node, str):
|
||||
yield path, node
|
||||
|
||||
|
||||
def validate_markup(content: dict) -> None:
|
||||
"""Catch the two easy ways to write broken HTML in the config.
|
||||
|
||||
YAML only processes \\" as an escape inside "quoted" values. In a >- folded
|
||||
or plain value the backslash survives into the page and breaks the markup,
|
||||
so a loaded string should never still contain one.
|
||||
"""
|
||||
problems = []
|
||||
for path, text in walk_strings(content):
|
||||
if '\\"' in text:
|
||||
problems.append(
|
||||
f'{path}: contains a literal \\" — in a >- or plain value write '
|
||||
"the quote on its own, with no backslash"
|
||||
)
|
||||
for tag in ("b", "a", "span"):
|
||||
opened = len(re.findall(rf"<{tag}\b", text))
|
||||
closed = len(re.findall(rf"</{tag}>", text))
|
||||
if opened != closed:
|
||||
problems.append(
|
||||
f"{path}: {opened} <{tag}> but {closed} </{tag}> — unbalanced tag"
|
||||
)
|
||||
# An unterminated href swallows the rest of the tag, which still leaves
|
||||
# <a> and </a> balanced, so check the attribute closes its own quotes.
|
||||
if len(re.findall(r"href=", text)) != len(re.findall(r'href="[^"]*"', text)):
|
||||
problems.append(
|
||||
f'{path}: malformed link — href="..." is missing its closing quote'
|
||||
)
|
||||
if problems:
|
||||
raise SystemExit("\n".join(f"{p}" for p in problems))
|
||||
|
||||
|
||||
def as_data_uri_payload(path: Path) -> str:
|
||||
if not path.is_file():
|
||||
raise SystemExit(f"missing asset: {path}")
|
||||
@@ -223,8 +286,8 @@ def main() -> None:
|
||||
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)
|
||||
content = load_config(args.config)
|
||||
validate_markup(content)
|
||||
|
||||
for key in TABLE_KEYS:
|
||||
if key not in content:
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
:root {
|
||||
--navy: {{theme.navy}};
|
||||
--red: {{theme.red}};
|
||||
--tag-bg: {{theme.tag_bg}};
|
||||
--tag-fg: {{theme.tag_fg}};
|
||||
--ink: {{theme.ink}};
|
||||
--ink-mid: {{theme.ink_mid}};
|
||||
--ink-faint: {{theme.ink_faint}};
|
||||
@@ -88,8 +90,8 @@ body {
|
||||
|
||||
.bar__tag {
|
||||
margin-left: auto;
|
||||
background: var(--red);
|
||||
color: #fff;
|
||||
background: var(--tag-bg);
|
||||
color: var(--tag-fg);
|
||||
font-size: var(--t-fine);
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.16em;
|
||||
@@ -110,6 +112,10 @@ body {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* Page 2 opens straight onto a section heading, so it needs the top margin
|
||||
that page 1 gets from the hero's own padding. */
|
||||
.body--specs { padding-top: 5.5mm; }
|
||||
|
||||
.label {
|
||||
font-size: var(--t-micro);
|
||||
font-weight: 600;
|
||||
@@ -146,8 +152,7 @@ body {
|
||||
display: grid;
|
||||
grid-template-columns: 1.32fr 1fr;
|
||||
gap: 7mm;
|
||||
padding: 4.6mm 0 4.2mm;
|
||||
border-bottom: 2px solid var(--rule-hard);
|
||||
padding: 4.6mm 0 5.4mm;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
@@ -167,8 +172,6 @@ body {
|
||||
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; }
|
||||
@@ -187,17 +190,11 @@ body {
|
||||
.features {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
border-bottom: 2px solid var(--rule-hard);
|
||||
column-gap: 7mm;
|
||||
row-gap: 4.4mm;
|
||||
padding: 0 0 5.4mm;
|
||||
}
|
||||
|
||||
.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);
|
||||
@@ -256,8 +253,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
||||
|
||||
/* ---------- pricing / faq blocks ---------- */
|
||||
|
||||
.block { padding: 3.2mm 0; border-bottom: 2px solid var(--rule-hard); }
|
||||
.block:last-of-type { border-bottom: 0; }
|
||||
.block { padding: 0 0 5.4mm; }
|
||||
.block:last-of-type { padding-bottom: 0; }
|
||||
|
||||
.faq {
|
||||
display: grid;
|
||||
@@ -366,7 +363,7 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
|
||||
|
||||
<header class="bar">
|
||||
{{> logo}}
|
||||
<div class="bar__word">{{&doc.wordmark}}<span>{{&doc.wordmark_sub}}</span></div>
|
||||
<div class="bar__word">{{&doc.wordmark}}{{#doc.wordmark_sub}}<span>{{&doc.wordmark_sub}}</span>{{/doc.wordmark_sub}}</div>
|
||||
<div class="bar__tag">{{&doc.tag}}</div>
|
||||
<div class="bar__ref">{{&doc.ref}}</div>
|
||||
</header>
|
||||
@@ -378,7 +375,6 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
|
||||
<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}}">
|
||||
@@ -438,7 +434,7 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
|
||||
<div class="bar__title">{{&doc.page2_title}}</div>
|
||||
</header>
|
||||
|
||||
<div class="body">
|
||||
<div class="body body--specs">
|
||||
|
||||
<div class="block">
|
||||
{{#process}}{{> secthead}}{{> table}}{{> footnote}}{{/process}}
|
||||
|
||||
+33
-23
@@ -7,6 +7,10 @@
|
||||
# Notes for editing:
|
||||
# - Every text field is rendered as raw HTML, so <b>, <br> and <a href="...">
|
||||
# work anywhere. Write a literal ampersand as &.
|
||||
# - Inside a "quoted" value (the table rows), escape any double quote the HTML
|
||||
# needs as \" — an unescaped one ends the value and breaks the YAML:
|
||||
# "see <a href=\"https://example.com\">the docs</a>"
|
||||
# Values written as plain or >- folded text need no escaping.
|
||||
# - 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)
|
||||
@@ -20,8 +24,8 @@
|
||||
doc:
|
||||
title: Tiny Tapeout — Datasheet
|
||||
wordmark: Tiny Tapeout
|
||||
wordmark_sub: SHARED SILICON ASIC SHUTTLE
|
||||
tag: DATASHEET
|
||||
wordmark_sub: "" # strapline under the wordmark on page 1; blank to hide
|
||||
tag: PRODUCT DATASHEET
|
||||
ref: DOC TT-DS-2026 · REV A
|
||||
page2_title: Electrical & Mechanical Specifications
|
||||
|
||||
@@ -29,6 +33,11 @@ doc:
|
||||
theme:
|
||||
navy: "#040371" # header bars and table header rows
|
||||
red: "#ec3013" # accent: labels, rules, prices
|
||||
# DATASHEET tag in the header bar. Official Tiny Tapeout brand colours:
|
||||
# yellow #fef244 · cyan #3dfef7 · hot pink #f82381 · pink #fc9f9f · blue #040371
|
||||
# Set tag_fg to navy for the light colours, #ffffff for hot pink.
|
||||
tag_bg: "#fef244"
|
||||
tag_fg: "#040371"
|
||||
ink: "#141414" # body text
|
||||
ink_mid: "#55545f" # secondary text
|
||||
ink_faint: "#86858f" # captions, dashes
|
||||
@@ -48,10 +57,10 @@ assets:
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
hero:
|
||||
eyebrow: Shared multi-project chip · SKY130 / SG13G2 / GF180MCU
|
||||
eyebrow: Shared multi project chip · SKY130 / IHP 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.
|
||||
Tiny Tapeout makes it more accessible than ever to get 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
|
||||
@@ -66,7 +75,7 @@ features:
|
||||
- kicker: 02 · Languages
|
||||
title: HDL agnostic
|
||||
body: >-
|
||||
Any language that can produce Verilog RTL. Project templates and CI are
|
||||
Any language that can produce Verilog. Project templates and CI are
|
||||
supplied for Verilog, with community provided VHDL and Chisel.
|
||||
- kicker: 03 · I/O
|
||||
title: 26 pins, plus analog
|
||||
@@ -77,11 +86,11 @@ features:
|
||||
title: Three PDKs
|
||||
body: >-
|
||||
SkyWater SKY130, IHP sg13g2 and GlobalFoundries gf180mcu. Open-source PDKs
|
||||
running multiple times per year.
|
||||
running multiple times per year with no NDAs to sign.
|
||||
- kicker: 05 · Hardware
|
||||
title: Demoboard available
|
||||
body: >-
|
||||
An optional RP2350-based demoboard carries your packaged chip and selects
|
||||
An optional RP2350-based demoboard carries the packaged chip and selects
|
||||
any project on the die over USB.
|
||||
- kicker: 06 · Flexibility
|
||||
title: Bring your own flow
|
||||
@@ -104,12 +113,12 @@ pricing:
|
||||
"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.",
|
||||
"Optional add-on: packaged chip on an RP2350 powered demoboard.",
|
||||
"€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
|
||||
your design manufactured on the chip — on its own it does not get you a
|
||||
physical chip. To receive a physical chip, add the demoboard PCB. Confirm
|
||||
current figures at
|
||||
<b><a href="https://app.tinytapeout.com/calculator">app.tinytapeout.com/calculator</a></b>.
|
||||
|
||||
@@ -120,7 +129,7 @@ faq:
|
||||
- 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>.
|
||||
shipped. Check <a href="https://app.tinytapeout.com/chips">tinytapeout.com/chips</a> for the schedule.
|
||||
- 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.
|
||||
@@ -140,7 +149,7 @@ faq:
|
||||
- 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.
|
||||
submission is GDS + LEF, produced with any toolchain you like. For full terms see <a href="https://tinytapeout.com/terms">tinytapeout.com/terms</a>.
|
||||
|
||||
institutions:
|
||||
label: Taught and used at
|
||||
@@ -163,15 +172,14 @@ 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}
|
||||
- {label: PDK, width: "22%", style: name}
|
||||
- {label: Foundry, width: "26%"}
|
||||
- {label: Node, width: "22%", style: num}
|
||||
- {label: 1×1 tile area, style: mono}
|
||||
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"]
|
||||
- ["SKY130A", "SkyWater", "130 nm", "161.00 × 111.52 µm"]
|
||||
- ["ihp-sg13g2", "IHP", "130 nm BiCMOS", "202.08 × 154.98 µm"]
|
||||
- ["gf180mcuD", "GlobalFoundries", "180 nm", "346.64 × 160.72 µm"]
|
||||
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
|
||||
@@ -244,9 +252,11 @@ ordering:
|
||||
- {}
|
||||
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"]
|
||||
"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."]
|
||||
- ["Volume discount",
|
||||
"10% off orders over €10,000."]
|
||||
- ["Deliverable",
|
||||
"Silicon area only for remote or shared test, or area plus the demoboard kit: packaged chip, RP2350 demoboard and breakout board."]
|
||||
- ["Design tools",
|
||||
@@ -261,5 +271,5 @@ disclaimer:
|
||||
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.
|
||||
ordering. Full terms and conditions of sale are published at
|
||||
<a href="https://tinytapeout.com/terms">tinytapeout.com/terms</a>.
|
||||
|
||||
Reference in New Issue
Block a user