a13n
Build AI agents and run them on cloud.
Generate analog chip layout (GDS) from a netlist directly in the browser
AI summary · website content
Developer toolsJavaScript · PythonGitHub @gotzawalOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗아날로그 회로의 넷리스트(.sp)를 넣으면 칩 레이아웃(GDS)을 브라우저에서 만든다.
회로 읽기 · 배치 · 배선 · DRC/LVS 검사 · GDS 내보내기까지 이 탭 안에서 돌고, 산출물을 바로
받는다. 서버도 빌드도 없다 — 이 폴더를 정적 호스팅에 그대로 올리면 된다.
배치기·배선기의 소스와 검사, 예제를 만드는 도구는 symplace/ 에 있다 (아래 "소스" 절).
앞으로의 재구성과 예제 추가 계획은 PLAN.md.
# 새 저장소에 이 폴더 내용을 넣고
git init && git add . && git commit -m "analog layout generator"
git branch -M main
git remote add origin [email protected]:<사용자>/<저장소>.git
git push -u origin main
저장소 Settings → Pages → Source 를 Deploy from a branch, 브랜치 main,
폴더 / (root) 로 두면 몇 분 뒤 https://<사용자>.github.io/<저장소>/ 에서 뜬다.
.nojekyll 이 들어 있다 (Jekyll 처리를 건너뛰어 py/, _로 시작하는 파일도
그대로 서빙된다).
file:// 로는 안 된다 — ES 모듈과 워커가 막힌다. HTTP 로 띄워야 한다.
python3 -m http.server 8791
# http://127.0.0.1:8791
배치는 모듈 워커에서 돈다. 워커를 못 쓰는 브라우저(구형 사파리)에서는 같은 코드를 메인 스레드에서 돌린다 — 그동안 페이지가 멎지만 아무것도 안 나오지는 않는다.
data/*.json (앞단 출력: 회로의 소자 묶음과 템플릿),
data/*.leaves.json (리프 셀의 전체 도형 — 배선할 때만 받는다), netlists/*.sp (예제의 원본 회로).index.html 페이지
worker.mjs 배치를 워커에서 돌리는 얇은 껍데기
routeworker.mjs 배선을 워커에서 — src/route/pipeline.mjs + alignroute.wasm (파이썬 없음)
frontworker.mjs 앞단 — .sp 를 올릴 때만. Pyodide 안에서 ALIGN 앞단(py/front.py)을 그대로 돌린다
view.mjs 캔버스 — 확대/이동, 패널, 배선 레이어
edit.mjs 편집기 — 보기/편집 토글로 켜는 배치·배선 편집. index.html 이 필요할 때 동적으로 받는다 (못 받아도 보기·배치·배선은 된다)
src/job.mjs 배치 한 판 (워커에서도, 메인 스레드에서도 같은 코드가 돈다)
src/*.mjs 배치기 본체 (의존성 없는 ES 모듈)
src/gpu/runner.mjs 연속 단계(Adam)를 WebGPU 컴퓨트 셰이더로 — 있으면 쓰고, 없으면 CPU
src/edit/ 편집의 셈 — place.mjs (편집 키트로 문제 다시 짓기, 제약을 따르는 끌기, 위상 유지 정리, variant 다시),
wires.mjs (넷의 조각 그래프, 옮길 범위, 되펴기), compact.mjs (정돈),
draw.mjs (배선 그리기 — 층 짝, 트랙 스냅, 비아 쌓기, 최소 길이, 지우기, 연결 덩이·플라이라인, 그리는 동안의 규칙),
assist.mjs (보조 배선 — 트랙 격자 길찾기: 커서를 따라 긋고 핀에 붙기, 열린 곳 잇기)
src/route/ 배선 — ALIGN 배선 알고리즘의 이식: 입력·PnRDB(align/), Rust 배선기(alignroute.wasm),
도형 합성, DRC/LVS, GDS
src/schematic/ 회로도·묶음 보기 — SPICE 읽기(spice.mjs), .sp 와 앞단 출력에서 회로 만들기(circuit.mjs),
자동 배열(layout.mjs), 캔버스 그리기(draw.mjs)
data/*.json 예제의 앞단 출력 (미리 만들어둬 첫 화면이 빠르다), data/index.json 이 목록
data/*.leaves.json 예제의 리프 셀 전체 도형 — 배선할 때만 받는다
netlists/*.sp 예제의 원본 회로 (회로도 보기가 읽고, 회로 올리기에 그대로 넣어 볼 수도 있다)
py/ 앞단용 Pyodide 스택 (원본 약 39 MB, .sp 를 처음 올릴 때만 받는다)
symplace/ 소스·검사·도구 — Rust 배선기(alignroute/), node 검사, 예제 묶기(pack-example.mjs)
.sp 넷리스트) 예제를 고른다. 제목 아래 "개념 설명" 을 펼치면 이 도구가 하는 일이
적혀 있다.Routing 보기에 그려지고, 아래 내려받기 칸이 그 자리에서 채워진다.캔버스 옆과 아래의 카드(결과, 설계, Routing · GDS · DRC, 소자 variant, Primitives 블록 표, 하위 모듈)는 접혀 있는 것이 기본이다 — 제목을 클릭하면 펴진다. Placement·Routing 보기의 그림은 캔버스 좌우를 꽉 채우고 높이는 비율대로 따라간다 (창 높이의 1.4 배까지 — 그보다 세로로 긴 설계는 다 보이게 맞춘다).
그림은 흐름 순서대로 넷이다 — Schematic / Primitives / Placement / Routing. 휠로 확대, 끌어서 이동,
더블클릭으로 초기화. Routing 보기에서는 금속·비아·소자층·웰을 묶음으로 껐다 켤 수 있다.
stack 2, m=4). 그림 아래 표가 블록마다 종류·소자·variant 후보(2_primitives 의 크기)·제약을 적는다.Schematic·Primitives 모듈(src/schematic/)은 페이지가 따로, 필요할 때 받는다 — 못 받아도 예제 목록과
배치·배선은 그대로 돈다. 빌드가 없는 정적 사이트라 브라우저가 옛 모듈을 캐시에 쥔 채 새 index.html 만 받는 일이 있는데,
그때 페이지가 통째로 비지 않게 하려는 것이다 (test/stale.mjs 가 그 상황을 만들어 본다).
두 그림은 같은 배열기가 놓는다 (src/schematic/layout.mjs). 넷의 높이를 스프링으로 풀어(전원 위, 접지
아래, 트랜지스터마다 한 단) 세로를 정하고, 직렬로 이어진 소자를 한 열에 세운 뒤 열끼리의 친화도로
피들러 벡터를 구해 가로 순서를 정한다. 거울 쌍이 있으면 축 양쪽에 거울로 두고, 양쪽에 채널로 닿는
열(꼬리 전류원)은 축 위에 둔다. 회로도는 앞단의 묶음을 .sp 소자에 되맞춰 같은 대칭 배열을 쓴다.
앞단 출력만 올린 설계는 원문이 없어 회로도가 없고 묶음만 된다.
배선에는 리프 셀의 전체 도형이 든다. 예제는 data/<예제>.leaves.json 을 그때 받고
(6~219 KB), 올린 .sp 는 앞단이 같이 낸다. 파이썬은 안 뜬다 — 예제를 고르고 배치·배선하는
데는 Pyodide 를 받지 않는다.
편집 모드의 원칙은 셋이다. 편집은 제약을 따라 움직인다 — 거울 쌍의 한쪽을 끌면 짝이 거울로 따라오고, 축 위 블록은
축을 따라서만 미끄러진다. 배치기의 영공간 z = z0 + N theta 위에서 끌기 때문에 끄는 동안에도 대칭 잔차가 0 이다.
최적화는 사용자가 정한 위상 안에서만 한다 — 배치의 위상은 쌍마다의 왼/오/아래/위, 배선의 위상은 넷의 조각·비아·핀 접속이고,
최적화기는 좌표만 바꾼다. 편집이 없으면 아무것도 달라지지 않는다. 계획과 실측은 symplace/PLAN-edit.md.
Placement 편집. 블록을 클릭해 고르고 (Shift 로 여럿) 끌면 제약을 따라 움직인다. 축 핸들을 끌면 축이 움직이고, Alt 를
누른 채 블록을 끌면 그 대칭 그룹이 통째로 간다. 끄는 동안 겹친 쌍은 빨갛고, 원래 자리는 유령 상자로, 고른 블록의 넷은
플라이라인으로 보인다. 놓은 뒤 정리 (Enter) 를 누르면 편집 좌표에서 읽은 쌍 관계를 그대로 둔 채 겹침을 없애고 격자에
앉히며 압축한다 — 배치기의 legalize 그 자체라 수십 ms 다. 압축 슬라이더가 0 이면 손댄 것만 고치고, 배치기 기본 0.5 면
배치기가 냈을 배치로 돌아간다. Order 를 어긴 편집(순서 제약이 있는 블록의 자리 바꾸기)은 정리가 어느 쌍인지 알리며 거절한다.
| 키 | |
|---|---|
| 화살표 | 한 격자 (80 / 84) 씩, Shift 면 열 격자 |
| F / V | x / y 반전 (거울 그룹 단위) |
| L | 잠금 — 끌 때 그 자리에 둔다 |
| S | 고른 두 블록의 자리 바꾸기 |
| Enter | 정리 |
| Z / Y | 되돌리기 / 다시 실행 |
| Esc | 고르기 해제 |
카드의 variant 드롭다운으로 블록의 variant(같은 소자의 다른 종횡비)를 고르면 그 블록(거울 짝까지)의 variant 가 고정된다.
그 뒤 Placement 를 다시 실행해도 고정한 variant 는 그대로 두고 나머지를 배치기가 고른다. 고정을 풀면 다시 배치기가 고른다.
variant 다시 는 위상(쌍 관계)을 그대로 둔 채 고정하지 않은 블록의 variant 배정을 전수로 돌려 (128 개까지, 배치 워커에서)
log(면적) + w·log(HPWL) 로 줄 세우고 1 위를 적용한다 — high_speed_comparator 가 6080x11760 에서 6080x10584 로
(ALIGN 이 낸 bbox) 간다. 반전 다시 는 반전만 다시 고르고, 원래대로 는 배치기 결과로 되돌린다.
편집한 배치는 그 배치의 배선 결과를 지운다 (Routing 을 다시 실행한다). 내려받는 배치 JSON 이름에 -edited 가 붙고
안에 edited (편집 수) 와 fixedVariants 가 적힌다.
Routing 편집. 도형을 클릭하면 그 넷이 골라지고 나머지는 흐려진다. 그 넷의 조각(같은 트랙의 토막을 이은 것)을 클릭하면 옮길 수 있는 범위가 카드에 뜬다 — 핀 위 조각은 못 옮기고, 이웃 조각의 최소 길이와 끝단 간격, 같은 층의 다른 도형과의 간격, 비아 간격, 모듈 경계가 범위를 정한다. 끌거나 화살표로 옆 트랙에 옮기면 (층의 수직 방향으로만, 트랙에 스냅) 배선기 없이 도형 합성·DRC/LVS·GDS 를 다시 해 (10~20 ms) 카드가 배선기 결과 대비 오류 수를 보이고, 그 넷은 고정된다.
| 키 | |
|---|---|
| 화살표 | 한 트랙 |
| F | 이 넷 고정 / 해제 — 고정한 넷은 다시 배선할 때 그대로 둔다 (배선기 입력에 장애물로 심는다) |
| R | 이 넷만 다시 배선 — 나머지 넷은 지금 경로 그대로 고정 |
| C / Shift+C | 정돈 — 이 넷 / 전부. 위상(조각·비아·핀 접속)은 그대로, 조각을 범위 안에서 미끄러뜨려 길이를 줄인다. 오류가 늘면 되돌린다 |
| Z / Y | 되돌리기 / 다시 실행 |
| Esc | 조각, 다음에 넷 고르기 해제 |
카드에 고정 넷 빼고 다시 배선 과 원래 배선으로 가 더 있다. 배선기 결과는 대개 이미 최단이라 정돈은 "이미
짧습니다" 라 하고, 옮겨서 우회를 만든 뒤에 쓸모가 있다. 편집한 배선의 내려받기(GDS·배선 JSON)에는 -wires 가 붙는다.
배선 그리기 — Custom Compiler 의 routing assistant 처럼. Routing 보기에는 캔버스 바로 위에 도구 줄이 있다 — 고르기·배선, 보조·수동, 층 팔레트(M1~M5), 꺾는 층, 열린 곳 모두 잇기. 편집 전에도 보이고, 도구를 누르면 편집에 들어간다.
보조는 M1~M4 트랙 격자(세로 층 x 160, 가로 층 y 168 — 네 층이 한 격자에 맞는다) 위에서 긋는다. 넷을 누르는 순간 다른 넷·블록· 전원 도형으로 막힌 꼭짓점·변·비아 자리를 칠해 두고 (검사기가 보는 간격·끝단 간격·비아 간격, 같은 중심선에 폭이 다른 도형이 있는 트랙 — DIFFERENT WIDTH 는 떨어져 있어도 본다), 커서가 움직일 때마다 누른 자리에서 커서까지의 ㄱ자가 막힌 데를 지나는지 본다 (1 ms 미만). 막혔을 때 돌아갈 길은 누른 자리에서의 다익스트라 한 번으로 미리 찾아 둔다. 나온 경로는 수동과 같은 점 줄이라 최소 길이 늘이기와 재검사를 그대로 탄다.
고르기 도구에서 조각을 고르고 Delete 를 누르면 그 조각이 지워진다 (닿은 비아와 떠 버린 조각까지). 넷 줄의 배선 지우기 는 그 넷의 배선을 다 지운다 (rip-up) — 핀만 남고 플라이라인이 이을 곳을 보인다. 카드의 보기 줄에서 플라이라인과 오류 표식(검사기 오류가 난 자리 — 배선기 결과에 없던 것은 굵게)을 켜고 끄며, 열린 넷을 골라 볼 수 있다.
| 키 (그리기) | |
|---|---|
| 누르고 끌기 (보조) | 핀·배선을 누른 자리에서 끄는 대로 긋기 — 꺾으면 굽이, 붙을 곳 가까이면 붙고, 놓으면 끝 |
| 클릭 | 시작 · 여기까지 고정(보조) / 꺾기(수동) · 붙을 곳이면 잇고 끝 · 플라이라인 위면 그 열린 곳 잇기 |
| 더블클릭 / Enter | 끝 |
| Backspace / Z | 한 칸 무르기 (그리는 중) |
| Esc | 버리기, 한 번 더 누르면 고르기 도구로 |
| A | 보조 / 수동 |
| 1 ~ 5 | 그리기 층 M1 ~ M5 (보조는 먼저 쓸 층) |
| T | 꺾는 층 위 / 아래 |
| W | 그리기 / 고르기 |
| 빈 자리 끌기 | 이동 (그리는 중에도) |
test/edit-assist.mjs 가 넷마다 배선을 지우고, 핀을 누른 자리에서 여덟 쪽으로 끌어 보고, 플라이라인의 한 끝 핀을 눌러 다른
끝으로 끄는 것을 되풀이한다 — 기본 셋(telescopic, cascode, high_speed_comparator, single_to_differential_converter)에서 끌어 본
머리 464 개 가운데 384 개가 손이 간 대로 (처음 끈 쪽이 첫 토막) 가고 나머지는 막힌 데라 돌아가며, 넣어 본 72 개 전부 오류가
늘지 않는다. 29 넷 전부가 클릭 없이 핀에 붙어 이어지고 DRC/LVS 가 배선기 결과보다 늘지 않는다 (누를 때 격자를 짓고 한 번 찾는
데 가장 길어 26 ms, 커서를 따라가는 데 1 ms 미만). 배치 캐시가 있는 예제 27 개의 배선된 넷 130 개를 하나씩
지우고 모두 잇기로 다시 이어도 130 개 전부 이어지고 오류가 늘지 않으며, 길이는 배선기의 0.99 배다. test/edit-draw.mjs 는 수동
으로 배선기 경로대로 다시 그린다 — 기본 셋(telescopic, cascode, high_speed_comparator)에서 26 넷 전부가 배선기와 같은 도형, 같은
DRC/LVS 로 돌아온다. 페이지에서는 test/edit-page.mjs 가 둘 다 진짜 마우스·키로 한다.
한계: 편집은 최상위 모듈만이다 (하위 모듈은 블록으로 옮기고 뒤집고 variant 를 바꾼다). 전원 넷은 옮기거나 그릴 수 없다. 한 층 안에서 방향을 바꾸는 토막은 없다 — 꺾으면 층이 바뀐다. 보조 길찾기는 M1~M4 격자 안이다 — M5 는 트랙 피치가 달라 수동으로 그린다. 넷을 고정하고 다시 배선한 결과는 ALIGN 의 것과 같지 않다 — 편집이 없으면 같다.
.sp (또는 .cir) 파일 하나면 된다. 제약을 같이 주려면 <서브서킷>.const.json 을 함께
올린다 — 서브서킷마다 하나씩 여러 개여도 된다.
.sp 넷리스트
-> 앞단 1_topology + 2_primitives Pyodide 에서 0.7 ~ 9 s
-> 배치 variant·반전·영역·격자 JS 에서 3 ~ 60 s (WebGPU 가 있으면 시작점을 더 준다)
-> 배선 ALIGN 배선 알고리즘의 이식 JS + Rust wasm (전역·상세·전원 배선, 검사, GDS) 0.1 ~ 1 s
-> GDS + DRC/LVS
앞단 출력을 직접 올려도 된다 (그때는 배치까지만 된다 — 리프 전체 도형이 없어서다. "예제로 저장" 으로 받은 파일은 리프를 담고 있어 배선까지 된다).
1_topology/<top>.verilog.json 인스턴스 -> abstract 템플릿, fa_map, 제약
2_primitives/__primitives__.json concrete -> abstract, x_cells, y_cells
2_primitives/<concrete>.json bbox, terminals
{topology, primitives, templates} 로 묶은 JSON 한 파일도 받는다 (data/*.json 이 그 형식이다).
배치기가 다루는 제약은 SymmetricBlocks, Align, Order, AspectRatio, HorizontalDistance /
VerticalDistance / BlockDistance, GroupBlocks(앞단이 하위 모듈로 만든다) 다. 앞단·배선기 몫인
제약(PowerPorts, SymmetricNets, ConfigureCompiler 등)은 그대로 넘어가고, 어느 쪽도 아닌 것
(GroupCaps, GuardRing, Boundary 등)은 설계 표에 "배치기가 무시한 제약" 으로 보인다.
쓰기만 할 거면 예제로 만들 필요가 없다 — 회로 올리기에 .sp 를 던지면
그 자리에서 돈다. 예제는 "미리 올려둔 회로" 일 뿐이고, 목록은 data/index.json 에서 읽는다.
[ { "name": "my_ota", "label": "My OTA" }, ... ]
.sp 를 올린다. 앞단이 브라우저에서 한 번 돈다.<이름>.json 이 떨어진다 (리프 도형까지 든다).data/ 에 넣고 data/index.json 에 한 줄 더한다. 첫 화면을 가볍게 하려면
node symplace/web/placer/pack-example.mjs 로 data/<이름>.json 과 data/<이름>.leaves.json
둘로 나눈다 (앞단 출력 폴더를 받는다).지금 예제 12 개는 ALIGN-public 의 examples/ 에서 가져온 회로들이다: telescopic_ota,
current_mirror_ota, five_transistor_ota, cascode_current_mirror_ota, high_speed_comparator, buffer,
inverter_v1/v2/v3, common_source, block_spacing_bug, five_transistor_ota_high_frequency.
node symplace/web/placer/test/place.mjs 가 찍는 값이다. HPWL 은 핀 경계 사각형으로 잰다
(아래 "variant 선택"). 겹침은 전부 정확히 0, 대칭 잔차는 1e-12 이하, 격자 밖 블록 0 이다.
| 예제 | 블록 | variant 조합 | bbox | 채움 | HPWL | 시간 |
|---|---|---|---|---|---|---|
| telescopic_ota | 5 | 8 | 1440×11760 | 0.87 | 15916 | 4 s |
| current_mirror_ota | 5 | 2 | 8800×2352 | 1.00 | 18156 | 4 s |
| five_transistor_ota | 3 | 60 | 4160×5880 | 0.83 | 8028 | 5 s |
| cascode_current_mirror_ota | 11 (계층 2) | 16 | 6480×11760 | 0.86 | 75396 | 18 s |
| high_speed_comparator | 10 (계층 5) | 108 | 6080×11760 | 0.72 | 28364 | 44 s |
브라우저에 WebGPU 가 있으면 (Chrome/Edge, Firefox, Safari 26) 연속 단계(Adam 600 스텝)를
컴퓨트 셰이더로 돈다 (src/gpu/runner.mjs). 워크그룹 하나가 시작점 하나고, 한 스텝이
여섯 패스(centers, wire, overlap, spectrum, grad, adam)다. CPU 의 Objective.eval +
adam 과 같은 계산이다 — 좌표를 영역 긴 변으로 나눈 무차원 문제를 f32 로 풀고,
calibrate 가 lam·mu 를 기울기 비로 잡으므로 궤적이 같다. test/gpu.mjs 가 재는 값:
calibrate 한 번의 W·D·B·lam·mu 가 CPU(f64) 와 상대오차 1e-5~1e-7, 600 스텝 뒤 최선
점수가 소수 넷째 자리까지 같고, 40 스텝씩 끊어 돌린 것이 비트까지 같다.
GPU 일 때 예산의 뜻이 바뀐다. 총 시작점이 아니라 설정(variant 배정 x 영역)마다 "GPU 시작점/설정" 개다 (기본 32). CPU 의 시작점 96 은 설정당 1~4 개라 배정 하나의 점수가 표본 서너 개로 정해져 순위가 잡음 안에 있었다. legalize·반전·정확한 면적은 CPU(f64) 에 남는다. 어댑터가 없으면 CPU 로 조용히 떨어지고 화면에 CPU 라고 적는다.
GPU 가 없는 기계에서 헤드리스 Chromium 의 SwiftShader(소프트웨어)로 잰 값이라 절대 시간은 참고만: five_transistor 설정 180 x 8 = 1,440 시작점이 164 s 였다 (같은 조건의 CPU 는 시작점 180 개에 6.5 s). 실제 GPU 에서의 시간은 아직 재지 못했다.
"시작점" 은 총 시작점 수다. 설정(= variant 배정 x 영역 후보) 수가 하한이고, 남는 예산은 잘 되는 설정에 더 준다.
1 라운드 (너비) 설정마다 시작점 하나 — 모든 설정을 한 번은 본다
2 라운드 이후 (깊이) 점수 상위 설정에만 하나씩 더. 볼 설정 수를 라운드마다
반으로 줄이고, 하나까지 가면 다시 절반에서 시작한다
전에는 설정마다 floor(예산/설정수) 개 를 똑같이 흩뿌리고 끝이었다.
설정이 예산보다 많으면 그 몫이 1 로 깔려서 (1) 예산 설정이 아무 일도 안 하고
(2) 예산을 늘려도 깊이가 안 깊어졌다. variant 조합은 128 개까지 전수로 보고
(WebGPU 면 512), 그보다 많으면 추첨한다.
면적과 배선의 맞바꿈은 두 단계에 걸쳐 있고, 둘은 하는 일이 다르다.
| 무엇을 바꾸나 | 파라미터 | 슬라이더 | 기본 | |
|---|---|---|---|---|
| 연속 단계 | 어떤 해가 나오는가 | lamRatio | 배선 ↔ 퍼뜨리기, 1/4 ~ 4 | 1 |
| 선택 | 나온 해 중 무엇을 고르나 | hpwlWeight | 면적 ↔ 배선, 1/16 ~ 16 | 1 |
둘 다 로그 눈금이다. 저울은 비율이라 2 배와 1/2 배가 슬라이더에서 같은
거리여야 한다. 한 칸이 2^0.1 = 1.072 배고, 기본값이 눈금에 정확히 떨어진다.
hpwlWeight 인가점수가 log(면적) + w x log(HPWL) + 3 x 겹침 이다 (solver.mjs 의 scoreOf).
로그라 기준값이 없다 — 면적 10% 와 배선 10% 가 같은 값이고, 로그 눈금 슬라이더의 w 가
곧 "면적 1 대 배선 w" 로 읽힌다. 이 저울은 고를 때의 저울과 legalize 뒤의 저울이 같아야
한다. 다르면 legalize 할 상위 후보를 고르는 기준이 최종 기준과 어긋나 좋은 후보가 먼저 잘린다.
lamRatio 인가에너지는 E = W + lam x D + mu x B 다. 여기서 W 에 무게를 곱하는 것은
아무 효과가 없다 — calibrate 가 lam 과 mu 를 |grad W| 로 정규화하기
때문에 스케일이 그대로 상쇄된다.
lam = lamRatio * |grad W| / |grad D| mu = muRatio * |grad W| / |grad B|
즉 이 단계에서 저울을 실제로 움직이는 양은 하나뿐이다 — 밀도 기울기를 배선
기울기의 몇 배로 둘 것인가, 그게 lamRatio 다. 낮추면 넷이 더 세게 당겨
배선이 짧아지고 겹침이 많이 남는다. 높이면 퍼뜨려 겹침이 적게 남는다.
겹침은 legalize 가 어차피 0 으로 만드니, 이건 "얼마나 무른 유체로 둘 것인가" 다.
눈금은 결과가 아니라 겹침으로 읽어라. lamRatio 에 대한 연속 단계 겹침은
깨끗하게 단조롭다 (five_transistor_ota, 후보 중앙값):
lamRatio 0.25 0.5 1 2 4
연속 겹침 0.216 0.189 0.160 0.140 0.111
반면 최종 면적/HPWL 은 단조롭지 않다. 저울이 탐색을 옮기면 이기는 이산 variant가 바뀌고, 그 차이가 저울 차이보다 크기 때문이다. 그래서 화면에도 연속 단계 겹침 중앙값을 같이 띄운다 — 슬라이더가 실제로 무엇을 했는지 보는 눈금이다.
2_primitives 는 같은 소자를 여러 종횡비로 만들어 둔다 (X1_Y2 는 800x3528,
X2_Y1 은 1120x2352 — 트랜지스터도 파라미터도 같고 모양만 다르다).
어느 쪽을 쓰느냐는 연속 최적화로 못 정하는 이산 선택이고 배치를 크게 바꾼다.
다중 시작의 한 축으로 넣어 고른다. 여기서 중요한 것 셋.
X16_Y1 (핀이 폭 5,032 짜리 가로 막대) 이 블록 가운데 점 하나로 보여
길쭉한 variant 일수록 배선이 공짜로 보인다. 그래서 핀 경계 사각형의 min/max 로 잰다
(templateInfo 가 넷별 핀 반폭을 남기고, hpwl 과 연속 단계의 wirelength 가 x ± ex 로 잰다).
후보 점수는 거울 반전 뒤의 배선길이로 매긴다 — 반전 전 값으로 줄을 세우면 그 이득이 후보마다
다르게 붙어 순위가 흔들린다.legalize.mjs 의 refineDirections).SUB_VARIANTS)를 상위의 variant 로 올린다. 하위 모듈의
점수에는 종횡비가 없고, 상위가 어떻게 쓸지는 그 자리에서 판단할 수 없기 때문이다.legalize 가 INFEASIBLE 이면 그 후보는 버려진다. 계층 설계에서는 그게 대부분이었으므로 실패하면 여유 영역을 넓혀 다시 푼다 (1.6 → 3 → 6). 영역 제약은 넓히면 실행가능 집합이 커지기만 하고, 목적함수에 반둘레가 들어 있어 넓혀줘도 알아서 좁게 푼다.
자세한 설계 노트(variant·반전·영역·계층·legalize)는 symplace/web/placer/README.md.
배선기는 새로 짠 것이 아니라 ALIGN 의 배선 단계를 그대로 옮긴 것이다 (symplace/PLAN-route-align.md 에 옮긴 과정과 대조 방법이 있다).
| 단계 | 어디 |
|---|---|
| 입력 만들기, PnRDB, 배치 심기, 계층 부기 | src/route/align/ (JS) |
| 전역 배선 (RouteWork 4) | symplace/alignroute/src/gr (Rust + lp_solve C 소스) |
| 상세 배선 (RouteWork 5) | symplace/alignroute/src/dr (Rust) |
| 전원 격자·전원 배선 (RouteWork 2·3) | symplace/alignroute/src/pr (Rust) |
| 도형 합성·DRC/LVS·GDS | src/route/pipeline.mjs, compose.mjs, check.mjs, gds.mjs |
브라우저에서 telescopic_ota 0.22 s, high_speed_comparator 0.57 s 다. 검사기·도형 합성·GDS 쓰기는
고정 사례로 지킨다: 검사기 106 사례 (test/check.mjs), 격자 오류 문구 150 개 (test/compose.mjs),
GDS 바이트 2 사례 (test/gds.mjs).
lp_solve 는 C 소스 그대로 링크한다. 전역 배선의 ILP 는 최적해가 심하게 겹치고 lp_solve 는 대개
처음 찾은 정수해를 낸다 — 다른 풀이기로는 같은 배선이 안 나온다. clang wasm32-wasi 로 빌드해
Rust 에 정적으로 링크한다.
symplace/ 에 소스와 검사, 도구가 있다 — 자세한 것은 symplace/README.md.
symplace/alignroute/ Rust 배선기 — build.sh 가 src/route/alignroute.wasm 을 만든다 (lp_solve C 소스를 같이 빌드)
symplace/web/placer/test/ node 검사 — 심플렉스, 에너지 대조, 배치, legalize, 검사기·격자·GDS 고정 사례, 브라우저(WebGPU·페이지)
symplace/web/placer/fixtures/ 고정값 — 배치 문제의 정답 4 예제, 검사기 사례 106, 격자 문구 150, GDS 2
symplace/web/placer/pack-example.mjs 앞단 출력 폴더 -> data/ 의 예제 파일
symplace/web/placer/README.md 배치기 설계 노트 (variant·반전·영역·계층을 어떻게 고르는지, legalize)
symplace/scripts/ z3 빌드, route/node/ (페이지와 같은 배치·배선을 node 에서), place/ (분석), edit/ (편집 계획의 실측)
symplace/PLAN-route-align.md 배선기를 ALIGN 알고리즘 그대로 옮긴 계획과 대조 기록
symplace/PLAN-place-variants-gpu.md variant 선택 분석과 WebGPU 계획·결과
symplace/PLAN-edit.md 배치·배선 비주얼 편집과 토폴로지 유지 최적화 계획 (실측 포함)
배치기 본체(src/*.mjs)는 이 저장소 루트의 것 하나뿐이다. 사이트가 그대로
읽고, 검사도 그것을 읽는다 (symplace/web/placer/test/* 가 ../../../../src/
를 임포트한다). 검사가 읽는 예제도 사이트가 읽는 data/<예제>.json 그대로다. 사본을 두지 않는다.
node symplace/web/placer/test/place.mjs # 앞단 출력만으로 배치 (본 경로) — 겹침·대칭·Order·격자 검사
node symplace/web/placer/test/lp.mjs # 심플렉스 검증
node symplace/web/placer/test/parity.mjs # 에너지·기울기·영공간을 고정값과 대조
node symplace/web/placer/test/design.mjs # 앞단 출력에서 만든 문제 == 고정값의 문제
node symplace/web/placer/test/legalize.mjs # 겹침 0 / 대칭 잔차 / 면적
node symplace/web/placer/test/chunk.mjs # 끊어 돌린 Adam == 한 번에 돌린 Adam
node symplace/web/placer/test/variants.mjs # variant 배정 전수 — 배정이 결과를 가르는가
node symplace/web/placer/test/gpu.mjs # GPU runner == CPU (headless Chromium, WebGPU)
node symplace/web/placer/test/page.mjs high_speed_comparator gpu 96 32 # 페이지 통째로 (워커 + WebGPU)
node symplace/web/placer/test/leaves.mjs # 리프 도형 파일이 예제와 맞는가
node symplace/web/placer/test/check.mjs # JS DRC/LVS 검사기 == 고정 사례
node symplace/web/placer/test/compose.mjs # 배선 도형의 격자 검사 == 고정 사례
node symplace/web/placer/test/gds.mjs # GDS == 고정 사례 (바이트)
node symplace/web/placer/test/schematic.mjs # 회로도·묶음 배열 — 예제 전부에서 겹침 0, 선이 핀에 닿는가, 거울 쌍 대칭
node symplace/web/placer/test/views.mjs # 페이지의 회로도·묶음 보기 (headless Chromium) — 예제 전부 + 올리기
node symplace/web/placer/test/stale.mjs # 옛 모듈이 브라우저 캐시에 남은 채 새 판을 새로고침해도 예제 목록이 뜨는가
node symplace/web/placer/test/edit-place.mjs # 배치 편집 — 키트로 다시 지은 문제, 끌기의 성질, 편집 6 종의 정리, 반전·variant, 위상 유지 variant 다시
node symplace/web/placer/test/edit-wires.mjs # 배선 편집 — 편집 없는 재검사 == 배선 결과, 조각 그래프 되펴기, 범위 안 옮기기, 넷 고정 재배선
node symplace/web/placer/test/edit-compact.mjs # 정돈 — 위상 그대로, 길이·오류 안 늚, 범위 끝까지 밀었다 정돈하면 원래 길이
node symplace/web/placer/test/edit-draw.mjs # 배선 그리기 — 넷을 지우고 점을 찍어 다시 그리면 배선기와 같은 도형·검사, 지우기, 규칙 알림
node symplace/web/placer/test/edit-assist.mjs # 보조 배선 — 넷을 지우고 플라이라인을 따라 끌면 핀에 붙어 이어지고 오류가 안 늚, 모두 잇기
node symplace/web/placer/test/edit-page.mjs current_mirror_ota 48 # 페이지의 편집기 통째로 (headless Chromium)
node symplace/scripts/route/node/newroute.mjs all # 예제 전부를 배치하고 페이지와 같은 길로 배선 (DRC/LVS 를 찍는다)
페이지를 여는 데 드는 것: 없다. ES 모듈과 wasm 하나(src/route/alignroute.wasm, 1.3 MB)뿐이고,
글꼴도 시스템 것을 쓴다 — 외부 주소를 하나도 안 부른다. 예제를 고르고 배치·배선·GDS 까지 오프라인으로 된다.
| 무엇을 할 때 | 드는 것 |
|---|---|
.sp 를 올릴 때 (앞단) | Pyodide 0.27.8 을 jsDelivr CDN 에서, networkx·pydantic 1.10.13·python-gdsii 를 PyPI 에서 (합쳐 약 16 MB), 저장소의 libz3 (22 MB, py/z3) 와 ALIGN 앞단 소스 (0.2 MB, py/front). 첫 방문에만 받고 브라우저가 캐시한다 |
| node 검사 | node 22. 브라우저 검사(gpu.mjs, page.mjs)만 Playwright 전역 설치 |
| 배선기 빌드 | Rust (wasm32-wasip1), clang + wasi-libc, lp_solve 5.5.2.11 C 소스 (fetch-lpsolve.sh 가 받는다). crate 는 serde·serde_json 뿐 |
앞단의 Pyodide 스택이 남은 가장 큰 의존성이다 — ALIGN 앞단(회로 읽기·소자 묶기·템플릿 생성)을 JS 로 옮기면 없어진다. 그 계획은 PLAN.md.