e1084800ab
ADR-0024 (SIP-level TP launcher): rank = SIP abstraction, engine-routed install, mp.spawn parity, epoch barrier, ShardSpec structural coords. ADR-0025 (IPCQ direction addressing): address-based matching for meta arrival and credit return; fixes 2-rank bidirectional ring deadlock. ADR-0026 (DPPolicy intra-device only): remove sip/num_sips fields; ShardSpec uses structural (sip, cube, pe); pe_index property removed. ADR-0027 (Megatron-style TP API): ColumnParallelLinear / RowParallelLinear on top of ADR-0024 launcher. Backlog until 0024/0025/0026 land. ADR-0028 (DTensor support): stub / future work. ADR-0029 (Hierarchical all-reduce): 3-level reduce using all_pes mapper and multi_pe_sip_local validator from ADR-0024. Backlog. ADR-0030 (IPCQ PhysAddr integration): blocked on ADR-0031. ADR-0031 (PhysAddr PE-resource extension): stub; local_offset range-based partition approach; specific ranges TBD. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
258 lines
10 KiB
Markdown
258 lines
10 KiB
Markdown
# ADR-0031: PhysAddr PE-Resource Extension
|
|
|
|
## Status
|
|
|
|
Stub (Blocker for ADR-0030 — specific range allocations TBD)
|
|
|
|
## Context
|
|
|
|
### 목표
|
|
|
|
ADR-0001의 `PhysAddr` schema를 **PE 내부의 다양한 resource**를 체계적으로
|
|
표현할 수 있도록 확장한다. ADR-0030 (IPCQ PhysAddr integration) 및 향후의
|
|
PE-local resource 추가 (scratchpad, register file, status register, 등)의
|
|
기반을 제공한다.
|
|
|
|
### 현재 상태 (ADR-0001)
|
|
|
|
51-bit PhysAddr layout:
|
|
|
|
```
|
|
[50:47] rack_id (4)
|
|
[46:43] sip_id (4)
|
|
[42:38] sip_seg (5) # cube_id
|
|
[37:0] local_offset (38)
|
|
```
|
|
|
|
`local_offset` (38 bits) 내부:
|
|
|
|
- `[37]` selector: 1 = HBM window (128GB), 0 = PE resource window
|
|
- PE resource window는 `unit_type` (3 bits: PE | MCPU | SRAM) +
|
|
`pe_id` (4 bits) + `ext` (1 bit) + `sub_offset` (29 bits)
|
|
|
|
Factory API:
|
|
- `PhysAddr.hbm_addr(...)` — HBM generic
|
|
- `PhysAddr.pe_hbm_addr(...)` — PE-local HBM slice
|
|
- `PhysAddr.pe_tcm_addr(...)` — PE TCM (via `UnitType.PE` + `sub_offset`)
|
|
- `PhysAddr.cube_sram_addr(...)` — Cube-shared SRAM
|
|
|
|
### 풀어야 할 문제
|
|
|
|
1. **PE 내부 resource 구분의 명시적 체계 부재**: 현재 `local_offset` (38 bits)
|
|
이 평면 공간으로 취급되고, PE TCM / IPCQ ring / scratchpad / 향후 register
|
|
file 등이 관습적 offset 범위로만 구분됨. Schema 레벨에서 명확하지 않음.
|
|
2. **IPCQ 주소의 PhysAddr 표현 부재**: ADR-0030이 IPCQ ring buffer를 PhysAddr로
|
|
표현하려면 "이 주소가 IPCQ 영역"을 decode 가능해야 함. 현재는 불가.
|
|
3. **향후 PE resource 확장 경로**: register file, performance counter 등
|
|
추가 시 일관된 위치 할당 규칙 필요.
|
|
|
|
### 설계 방향 — local_offset을 PE 컴포넌트별 range로 분할
|
|
|
|
`local_offset` (38 bits = 256GB per PE segment)을 **PE 컴포넌트마다 고정
|
|
range**로 나누어 할당한다. 각 range는 해당 컴포넌트 전용 주소 공간이며,
|
|
`PhysAddr.decode()`가 주소가 어느 range에 속하는지 판별해 해당하는 `kind` /
|
|
`unit_type` / `sub_type` 필드를 채운다.
|
|
|
|
개념적 구조 (구체적 bit 할당은 **TBD**):
|
|
|
|
```
|
|
local_offset [37:0] (38 bits total)
|
|
├── HBM window [37] = 1 (기존 128GB)
|
|
├── PE component ranges [37] = 0
|
|
│ ├── TCM [range_1]
|
|
│ ├── IPCQ rings [range_2]
|
|
│ ├── Scratchpad [range_3]
|
|
│ ├── Register file [range_4]
|
|
│ ├── (reserved) ...
|
|
│ └── Sideband / status [range_N]
|
|
```
|
|
|
|
### 왜 range-based partition인가
|
|
|
|
- **Schema-level 명시성**: 주소 하나 보고 어느 컴포넌트의 자원인지 decode 가능.
|
|
"Routing consumes decoded domains" (ADR-0001 D5) 계약 충족.
|
|
- **Unit type enum 확장보다 유연**: 3-bit `UnitType` 공간을 고갈시키지 않고
|
|
세분화 가능. 미래 추가 컴포넌트도 빈 range 할당.
|
|
- **Allocator 통합 자연**: 각 PE-level allocator가 관리하는 하위 pool을
|
|
address range와 1:1 매칭 (e.g., `reserve_ipcq_tcm()` → IPCQ range 안에서만
|
|
할당).
|
|
- **Decode routing 단순**: `PhysAddr.decode(addr)`가 range table을 참조해
|
|
`kind` + sub-field를 채움. 기존 HBM selector bit 패턴의 일반화.
|
|
|
|
### 왜 지금 다루는가
|
|
|
|
- ADR-0030 (IPCQ PhysAddr 통합)이 이 확장에 **의존**. ADR-0030 단독 진행 시
|
|
`sub_offset` 공간을 불투명하게 재사용하게 되어 ADR-0001 계약 미충족.
|
|
- PE 내부 자원이 더 추가될 가능성 — 지금 구조를 정리해두면 일관된 확장 경로 확보.
|
|
|
|
---
|
|
|
|
## Decision (pending specific range allocation)
|
|
|
|
### D1. Range-based local_offset partition — approach
|
|
|
|
`local_offset`을 고정 byte range로 분할하고, 각 range를 PE 컴포넌트에 할당한다.
|
|
주소의 어느 range에 속하는가로 `kind` / component type을 결정.
|
|
|
|
```python
|
|
# src/kernbench/policy/address/phyaddr.py (conceptual, post-extension)
|
|
@dataclass(frozen=True)
|
|
class PeResourceRange:
|
|
name: str # e.g. "tcm", "ipcq", "scratchpad", "regfile"
|
|
start_offset: int # local_offset 내 시작
|
|
end_offset: int # exclusive
|
|
byte_size: int # end - start
|
|
|
|
PE_RESOURCE_MAP: tuple[PeResourceRange, ...] = (
|
|
# TBD — 구체적 range 할당은 사용자가 별도 업데이트
|
|
)
|
|
```
|
|
|
|
`PhysAddr.decode(addr)`의 PE resource 경로는:
|
|
|
|
```python
|
|
def decode_pe_resource(local_offset: int) -> dict:
|
|
for r in PE_RESOURCE_MAP:
|
|
if r.start_offset <= local_offset < r.end_offset:
|
|
return {
|
|
"kind": "pe_resource",
|
|
"component": r.name, # NEW: "tcm"/"ipcq"/...
|
|
"component_offset": local_offset - r.start_offset, # within range
|
|
}
|
|
raise PhysAddrError(f"local_offset {local_offset} not in any PE range")
|
|
```
|
|
|
|
### D2. Specific range allocations — **TBD**
|
|
|
|
> 사용자가 구체적 byte 할당을 별도로 정의한 뒤 본 ADR에 업데이트.
|
|
>
|
|
> 필요 정보:
|
|
> - 각 컴포넌트 (TCM, IPCQ, scratchpad, regfile, ...)의 이름 / byte size
|
|
> - `local_offset` 내 시작 offset (align 고려)
|
|
> - 현재 하드웨어 사양 / 시뮬레이션 요구 반영
|
|
|
|
이 섹션이 채워진 뒤 ADR status: **Stub → Proposed → Accepted** 승격.
|
|
|
|
### D3. Factory API — per-component 함수
|
|
|
|
기존 `PhysAddr.pe_tcm_addr(...)` 패턴을 일반화:
|
|
|
|
```python
|
|
# 기존 (이미 존재)
|
|
PhysAddr.pe_tcm_addr(rack_id, sip_id, cube_id, pe_id, tcm_offset)
|
|
|
|
# 신규 (ADR-0031 후 추가)
|
|
PhysAddr.pe_ipcq_addr(rack_id, sip_id, cube_id, pe_id, ipcq_offset)
|
|
PhysAddr.pe_scratchpad_addr(...)
|
|
PhysAddr.pe_regfile_addr(...)
|
|
# ...
|
|
```
|
|
|
|
각 factory는 해당 컴포넌트의 range 내에서 `component_offset`만 받아 최종
|
|
PhysAddr encoding. 호출자는 어느 range인지 몰라도 됨.
|
|
|
|
### D4. Backward compatibility
|
|
|
|
- 기존 `pe_tcm_addr()` signature / semantic 유지.
|
|
- 내부 인코딩만 신규 range table을 참조하도록 변경.
|
|
- 기존 `UnitType.PE` decoding 경로는 `PE_RESOURCE_MAP`에서 "tcm" range를
|
|
대응하도록 매핑 → 기존 코드 transparent.
|
|
- 기존 코드가 `PhysAddr.decode(addr).unit_type == UnitType.PE`를 체크하는
|
|
경우는 여전히 유효 (TCM 주소는 계속 PE unit_type).
|
|
|
|
---
|
|
|
|
## Open questions
|
|
|
|
### 🔴 Pending user input (ADR 승격 blocker)
|
|
|
|
- **D2의 specific range allocation**: 사용자가 구체적 byte 할당 테이블을
|
|
제공해야 Stub → Proposed 승격 가능. 필요 정보:
|
|
- 컴포넌트 목록 (TCM, IPCQ, scratchpad, regfile 등)
|
|
- 각 컴포넌트의 byte size / 시작 offset
|
|
- Alignment 요구사항 (4KB / page-aligned 등)
|
|
|
|
### 🟡 설계 세부 — range allocation 결정 과정에서 함께 결정
|
|
|
|
- **총 local_offset space 배분**: HBM window (bit 37 = 1, 128GB)을 유지할지,
|
|
아니면 PE resource space를 확장하기 위해 HBM window 축소할지.
|
|
- **Range padding / reserved space**: 미래 컴포넌트 추가를 위한 "reserved"
|
|
range 몇 개를 미리 확보할지.
|
|
- **Address alignment**: 각 range의 시작 offset이 특정 alignment (page /
|
|
cache line) 만족해야 하는지.
|
|
- **Diagnostic / debug 포맷**: `PhysAddr.decode()` 출력에서 component 이름 +
|
|
component_offset을 사람이 읽기 좋게 표시 (e.g., "IPCQ ring sip=0 cube=0 pe=3
|
|
offset=0x1234").
|
|
- **기존 `UnitType` enum의 role**: Range-based 접근 후에도 `unit_type` 필드
|
|
유지할지 (decode 결과에 `component` 추가), 또는 enum 대체할지.
|
|
|
|
### 🟢 ADR-0030 연동 질문
|
|
|
|
- **IPCQ range 내 direction/slot 표현**: PhysAddr는 `component_offset` 단위
|
|
까지만 표현. "direction=E, slot=2"는 IPCQ range 내 offset 계산으로 도출
|
|
(`direction_idx * slot_region_size + slot_idx * slot_size`) — 이 공식은
|
|
ADR-0030 scope에서 구체화.
|
|
- **Allocator pool 구조**: `PEMemAllocator`가 여러 range (TCM, IPCQ,
|
|
scratchpad)를 개별 pool로 관리할지, 단일 pool에서 kind별 reserved만 관리
|
|
할지. Range-based schema면 개별 pool이 자연스러움.
|
|
|
|
---
|
|
|
|
## Non-goals (this ADR)
|
|
|
|
- **51-bit 전체 layout 재작성**: 본 ADR은 `local_offset` (38 bits) 내부의
|
|
subdivision만 다룬다. Rack / SIP / cube segment 같은 상위 bit 구조는
|
|
불변.
|
|
- **`UnitType` enum 재설계**: range-based 접근으로 대체 가능하지만, 기존 enum
|
|
(PE / MCPU / SRAM)은 backward compat 위해 유지.
|
|
- **Dynamic range allocation**: runtime에 range 크기 바꾸는 기능 불필요. 모든
|
|
range는 컴파일 / 설정 시점에 고정.
|
|
- **Multi-process / multi-rack partitioning**: PE 내부 resource만 다룸.
|
|
|
|
---
|
|
|
|
## Action
|
|
|
|
### Phase 1 — User 입력: specific range allocation (**Blocker**)
|
|
- 사용자가 정의한 PE 컴포넌트별 byte range를 D2에 기입:
|
|
- `PE_RESOURCE_MAP` 테이블 내용 (name, start_offset, byte_size per 컴포넌트)
|
|
- 각 컴포넌트의 hardware spec 근거 note
|
|
|
|
### Phase 2 — ADR Stub → Proposed 승격
|
|
- D2 채워지면 status 변경.
|
|
- Open questions의 "🔴 Pending user input" 블록 제거.
|
|
- ADR-0001에 amendment note 초안 작성.
|
|
|
|
### Phase 3 — 구현
|
|
- `PhysAddr` range-based decode 구현.
|
|
- 신규 factory 함수 (`pe_ipcq_addr`, `pe_scratchpad_addr` 등 컴포넌트별)
|
|
추가.
|
|
- 기존 `pe_tcm_addr` 내부 인코딩만 신규 range table 참조하도록 수정
|
|
(signature 불변).
|
|
- 기존 코드 경로 회귀 확인.
|
|
|
|
### Phase 4 — ADR-0030 unblock
|
|
- ADR-0030 "Blocked" 상태 해제.
|
|
- Install_plan builder가 `pe_ipcq_addr(...)` 등 확장된 factory 호출하도록
|
|
수정.
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
- **ADR-0001** (PhysAddr layout): 본 ADR은 ADR-0001의 확장.
|
|
- **ADR-0023** (IPCQ protocol): IPCQ ring buffer의 주소 체계를 PhysAddr로
|
|
통합할 수 있게 하는 기반.
|
|
- **ADR-0030** (IPCQ PhysAddr integration): 본 ADR에 blocked.
|
|
|
|
---
|
|
|
|
## Affected files (future, after promotion to Proposed)
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `src/kernbench/policy/address/phyaddr.py` | Range table (`PE_RESOURCE_MAP`), range-based decode, 신규 component-specific factory들 (`pe_ipcq_addr` 등), 기존 `pe_tcm_addr` 내부 인코딩 갱신 |
|
|
| `src/kernbench/policy/address/allocator.py` | Range-aware pool 분리 (TCM pool / IPCQ pool / scratchpad pool 등 per-PE) |
|
|
| `docs/adr/ADR-0001-physaddr-layout.md` | Amendment note: range-based PE resource partition |
|
|
| `tests/test_phyaddr.py` | Range table 검증, 각 factory의 encode/decode round-trip, 기존 `pe_tcm_addr` 회귀 |
|