L1

L1 单元详细设计

把 [[Pipe]] 第 6 节 §193 的 L1 抽象展开到 RTL 起手前。每条 cacheline = 一条 data pipe 实例。L1 是被动单元:无命令队列、无 FSM、无数据搬运能力;本体 = bank 化 SRAM + count 阵列 + 控制接口。所有 count 更新由外部 master 经控制总线推 COUNT_DELTA,L1 自身不发起任何控制总线请求。

1. 顶层参数

参数 含义 默认 限制
N_CL cacheline 总数(= data pipe 容量) 256 2 的幂
CL_BYTES 每条 cacheline 字节数(物理固定 256 2 的幂
N_BANK SRAM bank 数 8 2 的幂,整除 N_CL
N_MASTER NoC slave 端口数 4
N_SYNC sync counter 数 16
N_PEND_WAIT 全单元未决 pwait 数 16 cacheline + sync 共用
COUNT_W count 寄存器位宽 32
HANDLE_W pipe handle 位宽 16 = unit_addr(8) + pipe_id(8)
ADDR_W 系统地址位宽 48
NOC_W NoC 数据 beat 位宽 512 每 cacheline 占 CL_BYTES*8/NOC_W beat

容量 = N_CL × CL_BYTES 字节。物理 cacheline 大小固定 —— palloc 不接受可变 size 参数;上层若需大块容器,分配多条相邻 cacheline 用作一组。

2. 顶层框图

                  ┌──────────────────── L1 单元 ────────────────┐
ctrl_s  ────────►│  ctrl 解码 + 路由 ──┬──► CL Pool Mgr        │
ctrl_s  ◄────────│                      ├──► Sync Pool          │
                 │                      ├──► count 阵列(分 bank)│
                 │                      └──► pending wait CAM   │
                 │                                                │
noc_s[0]◄─┐      │  ┌─────── crossbar ─┐    ┌─ Bank[0] SRAM ──┐ │
noc_s[0]─►┤      │  │ N_MASTER×N_BANK  ├──► │ Bank[1] SRAM    │ │
   ...    ├──────►  │  仲裁 + routing   │    │ ...             │ │
noc_s[M-1]◄┘      │  └──────────────────┘    │ Bank[N_BANK-1]  │ │
                 │                            └────────────────┘ │
                 └─────────────────────────────────────────────────┘

子模块:

  1. CL Pool Manager:data pipe 的 alloc/free + bitmap
  2. Count 阵列:每条 cacheline 一个 count,按 bank 分块
  3. Bank SRAM × N_BANK:cacheline 数据存储
  4. Crossbar:N_MASTER × N_BANK 路 master → bank 仲裁
  5. Sync Pool:N_SYNC 个独立 sync counter
  6. Pending Wait CAM:未决 pwait 表,共用于 cacheline + sync count
  7. Ctrl 解码 + 路由:单 slave 接收口

3. 顶层端口

3.1 控制端口 ctrl_s_*

完全复用 [[DMA]] §3.1 的从端定义。L1 不实例化 ctrl_m(无主端,无主动发起)。

3.2 数据端口 noc_s_[N_MASTER]

每个端口是 NoC slave,AXI4-lite 风格:

信号 方向 位宽 说明
req_valid in 1
req_ready out 1
req_addr in ADDR_W 物理字节地址
req_op in 1 0=read, 1=write
req_len in log2(CL_BYTES/NOC_W*8)+1 beats - 1;硬件约束:burst 不跨 cacheline
req_id in MASTER_ID_W = 6 master 内的 transaction id
wr_data in NOC_W 写数据
wr_strb in NOC_W/8 byte enable
wr_last in 1
rd_data out NOC_W
rd_id out MASTER_ID_W
rd_last out 1

约束:

4. 地址映射

4.1 物理地址 ↔ pipe_id

L1 占系统地址空间一段连续区域,基址 L1_BASE

byte_addr = L1_BASE | (cl_id << log2(CL_BYTES)) | offset

cl_id  = byte_addr[log2(CL_BYTES) +: log2(N_CL)]   // 也即 data pipe 的 pipe_id 低位
offset = byte_addr[0 +: log2(CL_BYTES)]

软件经 PALLOC 拿到的 handle = {unit_addr, type=data, cl_id},使用时按上式还原成 byte_addr 配进 master 的命令。Master 与 L1 之间的 NoC 端口只传 byte_addr,不传 pipe_id —— pipe_id 由 L1 自己从地址解出。

4.2 bank 映射
bank_id    = cl_id[0 +: log2(N_BANK)]                  // 低位选 bank
cl_in_bank = cl_id[log2(N_BANK) +: log2(N_CL/N_BANK)]   // 高位选 bank 内行

连续 cl_id 自然分布到不同 bank,降低线性扫描场景的 bank 冲突。

5. 控制总线协议子集

复用 [[DMA]] §5 的 opcode 表。L1 仅处理:

op 行为
PALLOC(type=data, _) → cl_id handle 见 §6
PALLOC(type=sync, _) → sync_id handle 见 §9
PFREE(handle) 见 §6 / §9
PREAD(handle) → count 直接读 count 阵列
PWAIT(handle, threshold) 见 §10
PSET_COUNT(handle, value) 直接写 count 阵列
COUNT_DELTA(handle, delta) 见 §7
COUNT_QUERY(handle, threshold) 立即比较,回 ack(命中/未命中)
PSIGNAL(handle, delta) 仅对 sync pipe,等价于 COUNT_DELTA

非法 op、handle 类型错配等不报错,行为未定义(特性 6)。

6. CL Pool 管理器

6.1 存储
存储 形式 容量
cl_alloc_bitmap FF N_CL bit
cl_valid_flag FF N_CL bit(PALLOC 后 1,PFREE 后 0)

cacheline 大小固定,无需 per-line metadata。

6.2 alloc / free
PALLOC(type=data) →
  free_id = priority_encoder(~cl_alloc_bitmap)
  cl_alloc_bitmap[free_id] ← 1
  cl_valid_flag[free_id] ← 1
  count_cl[free_id] ← 0        // 通过 count 阵列写端口
  resp ← {unit_addr, type=data, free_id}    // HANDLE_W

PFREE(handle) →
  cl_alloc_bitmap[handle.id] ← 0
  cl_valid_flag[handle.id] ← 0
  // count 不主动复位,下次 alloc 时清

延迟:1 cycle(N_CL = 256 时优先编码器 8 级,单 cycle 容易达到)。

7. Count 阵列

7.1 存储与分块

count 阵列与 bank SRAM 共用 cl_id 的 bank 映射

count_bank[N_BANK]:
  每个 bank:(N_CL/N_BANK) × COUNT_W 寄存器组

每 bank 独立读写端口。每 bank 可同 cycle 处理 1 读 + 1 写(互不冲突);本 bank 多读 / 多写 round-robin。

为什么按 cl_id bank 分块(与 SRAM 一致):连续 cacheline 的 count 更新分散到不同 bank,匹配 master 通常的访问 locality。

7.2 写端竞争

可能的 count 写来源:

  1. PALLOC 复位
  2. PSET_COUNT
  3. COUNT_DELTA(多路并发,来自任何外部 master)

每 bank 单写端口,上一级 round-robin 仲裁器选一个胜者;其他 backpressure 到 ctrl_s_req_ready。

7.3 与 SRAM 写完成的关系

完全解耦

L1 不在数据端口上推断"写完成 → count++"。这一语义由发起方在自己的执行 FSM 内排序保证(见 [[DMA]] §7.3:状态机先 WRITE 完成才进 NOTIFY;[[算力单元]] §7.3 同理)。

后果:若 master 提前发 COUNT_DELTA(在数据写到 SRAM 之前),L1 不能阻止;这是软件 / master 内部 RTL 的责任,不是 L1 的检查项。

8. Bank SRAM 阵列

8.1 Bank 组织
N_BANK 个 SRAM macro:
  每个:(N_CL/N_BANK) × CL_BYTES bytes
  端口:1R/1W 或 1RW(工艺选)
  数据位宽:NOC_W
  地址位宽:log2((N_CL/N_BANK) × CL_BYTES / (NOC_W/8))

CL_BYTES = 256,NOC_W = 512 时每 cacheline 占 4 beat。

8.2 Master ↔ Bank crossbar

N_MASTER × N_BANK 全连接 crossbar。

仲裁粒度:beat(不是 burst)。每 cycle 每 bank 接受一个 master 的一拍访问;冲突 round-robin。这避免某个 master 长 burst 占满 bank 期间其他 master 完全 starve。

实现:

回程 read data:每 bank 一个回路 fifo(深度 = max-outstanding-per-master),按 master_id route 回;master 端按 req_id 重排。

8.3 同 bank R/W 冲突
8.4 跨 cacheline burst 拒绝

L1 不支持单 burst 跨 cacheline。req_len + offset 跨界时,行为未定义 —— master 必须自己拆 burst。

9. Sync Pipe Pool

结构同 [[DMA]] §8。N_SYNC 个独立 counter,独立 alloc bitmap,与 cl_alloc_bitmap 不共享 ID 空间(落地 A,但 sync handle 的 type 字段区分)。

每 counter 单 cycle 读写。psignal / pset_count / pread / pwait 接口同 DMA。

10. Pending Wait CAM

结构同 [[DMA]] §8.2。

容量 N_PEND_WAIT,每项 {valid, target_handle, threshold, resp_tag}

比较广播:每 cycle 任何 count 更新事件(count_cl 或 sync_count)送入 CAM 比较口;命中条目发响应 + invalidate。

多 bank 的 count 同 cycle 都可能更新 —— CAM 比较口可以并发承接多个事件(每 bank 一个事件,单 cycle 内 N_BANK + 1 路广播)。或者把 CAM 比较端口分块:每 bank 一个独立 wait 子表。后者更省面积,前者更简单。推荐:单一 CAM,多端口同 cycle 接受 N_BANK 个更新事件。

11. 复位与启动

信号 / 状态 复位值
cl_alloc_bitmap / sync_alloc_bitmap 全 0
cl_valid_flag 全 0
count_cl[] / sync_count[] 0
Bank SRAM 内容 不复位(undefined)
pending wait CAM 全 invalid
crossbar 仲裁 round-robin pointer 0

SRAM 内容不复位的影响:未 PALLOC 的 cacheline 读出是垃圾,软件不应访问;count 已复位为 0,PWAIT 不会被未初始化数据误触发。

12. 调试可观测点

信号 宽度 用途
dbg_cl_alloc_count log2(N_CL)+1 已分配 cacheline 数
dbg_sync_alloc_count log2(N_SYNC)+1 已分配 sync 数
dbg_bank_busy N_BANK bank 当 cycle 是否被访问
dbg_bank_conflict N_BANK bank 当 cycle 是否被多 master 竞争
dbg_master_stall N_MASTER master 当 cycle 是否被 backpressure
dbg_pend_wait_occ log2(N_PEND_WAIT)+1 未决 wait 数
dbg_count_cl[N_CL] N_CL × COUNT_W 全部 cl count(性能区可裁掉)

13. 待规格化参数

  1. N_CL / CL_BYTES / N_BANK / N_MASTER 的实际值
  2. Bank SRAM 端口配置(1RW vs 1R/1W vs 2R/1W)
  3. Crossbar 是否带 QoS(不同 master 优先级)
  4. Pending Wait CAM 是统一表还是按 bank 分块
  5. 是否例化 ECC / parity 保护(特性 6 不要求,但产品级可加)

14. 关联回 Pipe 抽象

抽象层概念 本文档落点
data pipe 契约(输入序列 = 写、输出序列 = 读、count + credit) §4 地址=handle + §7 count + §8 SRAM
sync pipe 契约 §9
落地 A(每单元独立 ID) §6 + §9 各自 bitmap
落地 B(控制/数据总线分开) §3.1 vs §3.2 物理分离
落地 D(sync 独立) §9 与 §7 不共用任何状态
特性 2(粒度顺应硬件) cacheline = pipe 粒度,自然映射
特性 6(硬件零检查) §5.4 + §7.3 不强制 master 顺序
特性 7(参数创建即不可变) §6 cacheline 大小固定,alloc 后参数定
特性 8(三类 pipe) data 在 §6-§8,sync 在 §9,无 engine

Revision #1
Created 2026-05-13 13:49:42 UTC by Colin
Updated 2026-05-13 13:49:42 UTC by Colin