1// ååäºå¹´ä¸çº¿ · 1985â2026 äºä»¶å¢å¾ · SVGï¼timeline66 ç 42 å¹´å£å¾çï¼ 2// å 个çªå£è²å¸¦å«åºï¼å½åçªå£èãå ¶ä½å¢¨ç°ï¼çªå¸¦æ ç¾ä¸ä¸äº¤éï¼ï¼äºä»¶çå¾è´ªå¿åå± 3// éå³°æå¸ï¼å±æ°å³å®å¾é«ï¼ï¼è¿æè½è½´ï¼éå LâR draw-inï¼æ¯åå¯ç¹ä¸é»ã 4// çå¾äºå®å ¨é¨å¯å¨ RPT.analog_matrix / tm_tables / archive é¡µä¸ V52 䏿¾å°å¯¹åºè¡ï¼ 5// æ æºè ï¼1987 TSMC åç«ã2016 cohort æç«å¹´ï¼æãå®ç¼ºå¿ç¼ãä¸ç»ã 6(() => { 7 const host = document.getElementById("timeline42-chart"); 8 if (!host) return; 9 const body = U.frame(host, { 10 title: "Forty-two years on one line", 11 sub: "shaded = the six windows · blue = current window · red = a break · click any plaque", 12 src: "Kimi Research", 13 }); 14 15 const P = U.PAL; 16 const MONO = U.FONTS.mono; 17 const SERIF = U.FONTS.serif; 18 const NS = "http://www.w3.org/2000/svg"; 19 const svgEl = (n, a) => { const e = document.createElementNS(NS, n); for (const k in a) e.setAttribute(k, a[k]); return e; }; 20 21 // kind: ink=åå²äºä»¶ï¼å¢¨è²ï¼/ brk=å´©ç·ä¸è¡ï¼è¯ä¹çº¢ï¼/ cur=å½å卿äºä»¶ï¼çµèï¼ 22 // drill æ°å¼+å£å¾+å¸¦æ¥æåºå¤ï¼å ¨é¨å¯¹åºå°æ°æ®è¡ 23 const PLAQUES = [ 24 { y: 1984, yr: "1983â84", name: "Xilinx and Altera founded", kind: "ink", 25 drill: { title: "1983â84 · Xilinx and Altera founded", 26 value: "Altera 1983-06 · Xilinx 1984-02", 27 sub: "Altera's first round $1.3M; Xilinx's $4.3M (Dataquest 1987 archive). Both independently chose not to build fabs â the fabless model starts here.", 28 source: "Kimi Research" } }, 29 { y: 1994, yr: "1994", name: "Xilinx takes the PLD crown", kind: "ink", 30 drill: { title: "1994 · the PLD crown changes hands", 31 value: "Xilinx takes the PLD crown (1994)", 32 sub: "Xilinx: 1990 IPO, FY1996 $560M. AMD's PLD unit lost the crown in 1994 and was sold to Vantis â Lattice in 1999.", 33 source: "Kimi Research" } }, 34 { y: 2000, yr: "2000", name: "Telecom bubble peaks", kind: "ink", 35 drill: { title: "2000 · telecom bubble peaks", 36 value: "Nasdaq peaks 2000-03; the order freeze arrives 9â12 months later", 37 sub: "Xilinx FY2001 10-K: 'Net revenue growth slowed substantially in the fourth quarter of fiscal 2001 due to decelerating bookings and order cancellations' â particularly in the telecommunications sector.", 38 source: "Company disclosure" } }, 39 { y: 2001, yr: "2001", name: "Industry â32% · duopoly â39%", kind: "brk", 40 drill: { title: "2001 · the clearing", 41 value: "Industry â32% · both duopolists â39%", 42 sub: "WSTS cut its full-year forecast to â32% (Oct 2001); double-ordering in the shortage became mountains of inventory in the downturn. The reference scale for this report's downside stress tests.", 43 source: "Company disclosure" } }, 44 { y: 2003, yr: "2003", name: "The $12 million-gate FPGA", kind: "ink", 45 drill: { title: "2003 · the $12 million-gate FPGA", 46 value: "Spartan-3: a million-gate FPGA priced under $12", 47 sub: "Two quarters after climbing out of the â32% trough, Xilinx's CEO declared an assault on the $23B ASIC/ASSP market â weaponizing the cost curve.", 48 source: "Company disclosure" } }, 49 { y: 2012, yr: "2012", name: "Microsoft wires 1,632 FPGA servers", kind: "ink", 50 drill: { title: "2012 · the invisible deployment", 51 value: "1,632 FPGA servers wired by end-2012", 52 sub: "Microsoft Project Catapult: each server = Xeon + PCIe daughter card (Stratix V). Not public at the time; disclosed at ISCA 2014 â per-server ranking throughput +95% at a fixed latency distribution.", 53 source: "Kimi Research" } }, 54 { y: 2015, yr: "2015", name: "Google deploys TPU v1", kind: "ink", 55 drill: { title: "2015 · Google deploys TPU v1", 56 value: "In production 2015 · disclosed 2016-05 · ISCA 2017", 57 sub: "65,536 8-bit MACs; 92 TOPS peak (INT8); 28MiB on-chip; vs Haswell/K80 avg 15â30x performance, 30â80x efficiency. Inference only.", 58 source: "Kimi Research" } }, 59 { y: 2016, yr: "2016", name: "Intel buys into AI", kind: "ink", 60 drill: { title: "2016 · Intel buys into AI", 61 value: "Nervana + Movidius · â$400M / undisclosed", 62 sub: "The 2015â18 acquisition chain: Altera $16.7B (2015), Nervana/Movidius (2016), Mobileye $15.3B (2017). Nervana was killed in 2019; Movidius kept at the edge.", 63 source: "Kimi Research" } }, 64 { y: 2020, yr: "2020", name: "AMD bids $35B for Xilinx", kind: "ink", 65 drill: { title: "2020 · the M&A supercycle", 66 value: "AMD bids $35B for Xilinx (all stock, 2020-10-27)", 67 sub: "China conditional approval 2022-01-27; completed 2022-02-14 at â$49B â the largest semiconductor deal in history. NVIDIA â Arm ($40B) was terminated the same week.", 68 source: "Kimi Research" } }, 69 { y: 2022, yr: "2022", name: "Oct 7: peak meets controls", kind: "brk", 70 drill: { title: "2022 · peak meets controls", 71 value: "BIS final rule 2022-10-07; 2022H2 PC â19.5% triggered the reversal", 72 sub: "A100/H100 effectively banned for China; equipment limits at 14/16nm FinFET, 18nm DRAM, 128-layer NAND; the 'US persons' clause introduced for the first time. The two markets now cycle separately.", 73 source: "Industry & official" } }, 74 { y: 2023, yr: "2023", name: "Generative AI ignites", kind: "cur", 75 drill: { title: "2023 · generative AI ignites", 76 value: "The inference window opens", 77 sub: "Demand trigger of the current window: generative-AI inference. By 2024-02 NVIDIA's CFO put â40% of the past year's data-center revenue on inference.", 78 source: "Company disclosure" } }, 79 { y: 2025, yr: "2025", name: "NVLink Fusion opens the platform", kind: "cur", 80 drill: { title: "2025 · NVLink Fusion opens the platform", 81 value: "Third-party XPUs onto NVLink scale-up (official, 2025-05-18)", 82 sub: "Third-party CPU/XPU onto NVLink, NVLink Switch, bridge chiplet/IP, mixed NVIDIA-GPU clusters. Launch partners: MediaTek, Marvell, Alchip, Astera Labs, Synopsys, Cadence; GUC on the ecosystem page.", 83 source: "Company disclosure" } }, 84 { y: 2026, yr: "2026", name: "Expansion confirmed · no peak yet", kind: "cur", dashed: true, 85 drill: { title: "2026 · expansion confirmed", 86 value: "No peak yet â NVIDIA data-center +92% (2026Q1)", 87 sub: "CoWoS capacity on the 70â120â200 kwpm track (2025A â 2026E â 2027E capacity); the constraint is moving forward to power and datacenter shells.", 88 source: "Kimi Research" } }, 89 ]; 90 91 // å 个çªå£ = analog_matrix ç 1985â2026 åè¡ï¼1960â84 è¡è¶ åº 42 å¹´å£å¾ï¼ä¸ç»ï¼ 92 const WINDOWS = [ 93 { id: "W1", y0: 1985, y1: 1995, name: "FPGA founding" }, 94 { id: "W2", y0: 1995, y1: 2003, name: "telecom bubble" }, 95 { id: "W3", y0: 2004, y1: 2012, name: "the quiet decade" }, 96 { id: "W4", y0: 2013, y1: 2018, name: "ignition" }, 97 { id: "W5", y0: 2019, y1: 2022, name: "first in-house wave" },
98 { id: "W6", y0: 2023, y1: 2026, name: "inference boom", cur: true }, 99 ]; 100 101 // ââ 尺寸 ââ 102 const PH = 46, TIER_GAP = 12, TIER_H = PH + TIER_GAP, TOP = 20, AXIS_GAP = 12; 103 const X0 = 1983.5, X1 = 2026.8, ML = 26, MR = 26, GAP = 10; 104 const COL = { ink: P.ink, brk: P.neg, cur: P.blue }; 105 106 const mc = document.createElement("canvas").getContext("2d"); 107 const nameW = s => { mc.font = "700 12px " + SERIF; return mc.measureText(s).width; }; 108 109 let played = false; // å ¥åºå¨ç»æ¯å¦å·²æå®ï¼resize/åä½åéåä¿æå®æå¸§ï¼ 110 111 function build(final) { 112 body.innerHTML = ""; 113 const W = Math.min(1120, Math.max(620, body.getBoundingClientRect().width || host.getBoundingClientRect().width - 20)); 114 const xOf = yr => ML + (yr - X0) / (X1 - X0) * (W - ML - MR); 115 116 // ââ è´ªå¿åå±ï¼æå¹´ä»½ååºï¼æ¾è¿ä¸å åçæä½å± ââ 117 const ps = PLAQUES.map((p, i) => ({ ...p, i, w: Math.max(96, Math.ceil(nameW(p.name)) + 20) })); 118 const tiers = []; // tiers[t] = è¯¥å±æå³å ç¨è¾¹ 119 ps.forEach(p => { 120 p.x = U.clamp(xOf(p.y) - p.w / 2, ML, W - MR - p.w); 121 let t = 0; 122 while (t < tiers.length && p.x < tiers[t] + GAP) t++; 123 p.tier = t; tiers[t] = p.x + p.w; 124 p.leadX = U.clamp(xOf(p.y), p.x + 12, p.x + p.w - 12); 125 }); 126 const nTiers = tiers.length; 127 const axisY = TOP + nTiers * TIER_H + AXIS_GAP; 128 const H = axisY + 66; 129 130 const svg = svgEl("svg", { width: "100%", height: H, viewBox: `0 0 ${W} ${H}`, 131 style: "display:block", "data-drill-keep": "1", class: "t42-svg" }); 132 body.appendChild(svg); 133 const yOf = t => TOP + (nTiers - 1 - t) * TIER_H; // å± 0 è´´è¿è½´ï¼å±æ°è¶é«è¶é ä¸ 134 135 const animated = []; // { start, dur, set(p) } 136 137 // ââ çªå£è²å¸¦ï¼è½´ä¸å段ï¼çªå¸¦æ ç¾ä¸ä¸äº¤éï¼ââ 138 const segY = axisY + 7, segH = 5; 139 WINDOWS.forEach((w, i) => { 140 const x0 = xOf(w.y0) + 1, x1 = xOf(Math.min(w.y1, X1)) - 1; 141 const seg = svgEl("rect", { x: x0, y: segY, height: segH, rx: 1, 142 fill: w.cur ? "rgba(34,81,255,.22)" : "rgba(133,149,166,.18)" }); 143 svg.appendChild(seg); 144 animated.push({ start: 0.05 + i * 0.05, dur: 0.45, set: p => { seg.setAttribute("width", Math.max(0, (x1 - x0) * p)); } }); 145 146 const lc = U.clamp((x0 + x1) / 2, ML + 34, W - MR - 34); 147 const row = i % 2; // ä¸ä¸äº¤é 148 const ty = axisY + (row ? 46 : 24); 149 const l1 = svgEl("text", { x: lc, y: ty, "text-anchor": "middle", 150 style: `font:9px ${MONO};fill:${w.cur ? P.blue : P.inkMd}` }); 151 l1.textContent = `${w.id} · ${w.y0}â${String(w.y1).slice(2)}`; 152 const l2 = svgEl("text", { x: lc, y: ty + 11, "text-anchor": "middle", 153 style: `font:8.5px ${MONO};fill:${w.cur ? P.blue : P.inkLo}` }); 154 l2.textContent = w.name; 155 [l1, l2].forEach(t => { svg.appendChild(t); animated.push({ start: 0.4 + i * 0.05, dur: 0.4, set: p => { t.setAttribute("opacity", p); } }); }); 156 }); 157 158 // ââ 年代å»åº¦ + æ·¡æ ¼çº¿ ââ 159 [1990, 2000, 2010, 2020].forEach(yr => { 160 const px = xOf(yr); 161 const gl = svgEl("line", { x1: px, y1: TOP - 6, x2: px, y2: axisY, stroke: P.lineLo, "stroke-width": 1 }); 162 svg.appendChild(gl); 163 const tk = svgEl("line", { x1: px, y1: axisY - 4, x2: px, y2: axisY + 4, stroke: P.inkLo, "stroke-width": 1 }); 164 const lb = svgEl("text", { x: px, y: axisY - 8, "text-anchor": "middle", 165 style: `font:9px ${MONO};fill:${P.inkLo}` }); 166 lb.textContent = yr; 167 svg.appendChild(tk); svg.appendChild(lb); 168 [gl, tk, lb].forEach(e => { e.setAttribute("opacity", 0); animated.push({ start: 0.25, dur: 0.5, set: p => { e.setAttribute("opacity", p); } }); }); 169 }); 170 171 // ââ 主轴ï¼LâR ç»åºï¼ââ 172 const ax = svgEl("line", { x1: xOf(X0), y1: axisY, y2: axisY, stroke: P.ink, "stroke-width": 1.2 }); 173 svg.appendChild(ax);
174 animated.push({ start: 0, dur: 0.7, set: p => { ax.setAttribute("x2", xOf(X0) + (xOf(X1) - xOf(X0)) * p); } }); 175 [xOf(X0), xOf(X1)].forEach(px => { 176 const e = svgEl("line", { x1: px, y1: axisY - 4, x2: px, y2: axisY + 4, stroke: P.ink, "stroke-width": 1.2 }); 177 svg.appendChild(e); e.setAttribute("opacity", 0); 178 animated.push({ start: 0.5, dur: 0.3, set: p => { e.setAttribute("opacity", p); } }); 179 }); 180 181 // è¿æå±å«åºï¼ç©¿çæ¶éäºçå¾ä¹åï¼ï¼è½è½´åç¹å±æ¬¡ä¹ï¼çå¾æä¸ 182 const leadLayer = svgEl("g", { class: "t42-leaders" }); 183 const dotLayer = svgEl("g", { class: "t42-dots" }); 184 svg.appendChild(leadLayer); svg.appendChild(dotLayer); 185 186 // ââ çå¾ï¼hairline æè¾¹ + mono å¹´ä»½çæ + ç²ä½å¢¨åäºä»¶å ââ 187 ps.forEach(p => { 188 const S = 0.55 + p.i * 0.11; // éåéå³°ï¼æå¹´ä»½ LâRï¼ 189 const c = COL[p.kind], py = yOf(p.tier); 190 const g = svgEl("g", { class: "t42-plaque", style: "cursor:pointer" }); 191 svg.appendChild(g); 192 193 // è¿æï¼è½è½´ï¼ 194 const lead = svgEl("line", { x1: p.leadX, x2: p.leadX, y1: py + PH, y2: py + PH, 195 stroke: p.kind === "brk" ? "rgba(194,47,78,.45)" : p.kind === "cur" ? "rgba(34,81,255,.45)" : "rgba(5,28,44,.3)", 196 "stroke-width": 1 }); 197 leadLayer.appendChild(lead); 198 animated.push({ start: S + 0.25, dur: 0.35, set: q => { 199 lead.setAttribute("y2", py + PH + (axisY - py - PH) * q); lead.setAttribute("opacity", q); 200 } }); 201 202 // è½è½´åç¹ï¼å½åçªå£å®å¿èï¼å ¶ä½ç©ºå¿ 203 const dot = svgEl("circle", { cx: p.leadX, cy: axisY, r: 0, 204 fill: p.kind === "cur" ? P.blue : P.paper, 205 stroke: p.kind === "cur" ? P.blue : p.kind === "brk" ? P.neg : P.inkMd, "stroke-width": 1.2 }); 206 dotLayer.appendChild(dot); 207 animated.push({ start: S + 0.55, dur: 0.2, set: q => { dot.setAttribute("r", 3 * q); } }); 208 209 // æ¡ï¼draw-inï¼æè¾¹æ²¿å¨é¿ç»åºï¼2026 宿ååèçº¿ï¼ 210 const rect = svgEl("rect", { x: p.x, y: py, width: p.w, height: PH, fill: P.paper, 211 stroke: c, "stroke-width": 1 }); 212 g.appendChild(rect); 213 const per = 2 * (p.w + PH); 214 rect.setAttribute("stroke-dasharray", per); 215 animated.push({ start: S, dur: 0.45, set: q => { 216 rect.setAttribute("stroke-dashoffset", per * (1 - q)); 217 if (q >= 1 && p.dashed) rect.setAttribute("stroke-dasharray", "4 3"); 218 } }); 219 220 const ey = svgEl("text", { x: p.x + 10, y: py + 15, style: `font:9px ${MONO};fill:${c};opacity:.8` }); 221 ey.textContent = p.yr; 222 const idx = svgEl("text", { x: p.x + p.w - 10, y: py + 15, "text-anchor": "end", 223 style: `font:8px ${MONO};fill:${P.inkLo}` }); 224 idx.textContent = String(p.i + 1).padStart(2, "0"); 225 const nm = svgEl("text", { x: p.x + 10, y: py + 34, style: `font:700 12px ${SERIF};fill:${c}` }); 226 nm.textContent = p.name; 227 [ey, idx, nm].forEach(t => { g.appendChild(t); t.setAttribute("opacity", 0); 228 animated.push({ start: S + 0.28, dur: 0.3, set: q => { t.setAttribute("opacity", q); } }); }); 229 230 // ââ ç¹å»ä¸é» ââ 231 g.addEventListener("click", e => { 232 U.showDrill({ title: p.drill.title, value: p.drill.value, sub: p.drill.sub, 233 source: p.drill.source, x: e.clientX, y: e.clientY }); 234 }); 235 }); 236 237 // ââ å ¥åºå¨ç»ï¼reduced-motion â ç´æ¥å®æå¸§ï¼ââ 238 if (final || matchMedia("(prefers-reduced-motion: reduce)").matches) { 239 animated.forEach(a => a.set(1)); 240 played = true; 241 return; 242 } 243 animated.forEach(a => a.set(0)); 244 let running = false, t0 = null; 245 const total = Math.max(...animated.map(a => a.start + a.dur)) + 0.05; 246 function tick(ts) { 247 if (t0 == null) t0 = ts; 248 const el = (ts - t0) / 1000; 249 animated.forEach(a => a.set(U.smooth(U.clamp((el - a.start) / a.dur, 0, 1)))); 250 if (el < total && running) requestAnimationFrame(tick); 251 else { running = false; played = true; animated.forEach(a => a.set(1)); } 252 } 253 function start() { if (running || played) return; running = true; t0 = null; requestAnimationFrame(tick); } 254 const io = new IntersectionObserver(es => { 255 if (!es[0].isIntersecting) return; 256 io.disconnect(); start(); 257 }, { threshold: 0.15 }); 258 io.observe(svg); 259 } 260 261 build(false); 262 // åä½å°±ä½åè¥çå¾å®½åº¦åäºåéæï¼ä¿æå®æå¸§ï¼ä¸éæå¨ç»ï¼ 263 if (document.fonts && document.fonts.ready) { 264 const before = PLAQUES.map(p => nameW(p.name)); 265 document.fonts.ready.then(() => { 266 const changed = PLAQUES.some((p, i) => Math.abs(nameW(p.name) - before[i]) > 2); 267 if (changed) build(true); 268 }); 269 } 270 let rt; 271 window.addEventListener("resize", () => { clearTimeout(rt); rt = setTimeout(() => build(true), 200); }); 272})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.