Skip to content

Commit 847c115

Browse files
committed
refactor: 引入 OOO Completion Fabric 建模完成反压
将原先面向 CDB 队列的执行完成边界迁移为 CompletionEvent/CompletionFabric,作为后续结构约束模拟的统一落点。 第一版 fabric 只负责 completion 事件的带宽仲裁、队列保留和 fanout,WritebackStage 继续复用现有 RS wakeup、物理寄存器写回和 ROB complete 消费者。 执行完成路径现在在 completion bandwidth 用尽时保持 execution unit busy,并记录 completion_port_busy stall;memory inflight 回来时也会在下游 completion backpressure 下保留 entry,避免重复统计 miss latency。 补充 CompletionFabric、ExecuteStage backpressure、ExecuteMemoryInflight backpressure、Writeback/OooRecovery 迁移测试,并更新 CONTEXT、ADR 和 ARCHITECTURE。 验证:cmake --build build -j;ctest --test-dir build -R "CompletionFabric|ExecuteStage|WritebackStage|OooRecovery|ExecuteMemoryInflight|ExecuteMemoryOrder" --output-on-failure;ctest --test-dir build --output-on-failure(400/400)。
1 parent 14053aa commit 847c115

31 files changed

Lines changed: 511 additions & 132 deletions

ARCHITECTURE.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ flowchart LR
123123
```mermaid
124124
flowchart TD
125125
subgraph Execute["Execute path"]
126-
ES["ExecuteStage\n调度 / execution-unit ticking / complete to CDB"]
126+
ES["ExecuteStage\n调度 / execution-unit ticking / submit completion"]
127+
CF["CompletionFabric\ncompletion arbitration / backpressure / fanout"]
128+
WS["WritebackStage\nwakeup / PRF write / ROB complete"]
127129
ELC["ExecuteLoadCompletion\nready load 完成状态机"]
128130
ELH["ExecuteLoadHazard\nROB older store hazard replay"]
129131
ELA["ExecuteLoadAccess\nforwarding / memory read / D$ read / exception"]
@@ -147,6 +149,7 @@ flowchart TD
147149
REC["OooRecovery\nshared flush / younger cleanup / restart"]
148150
149151
ES --> ELC
152+
ES --> CF
150153
ELC --> ELH
151154
ELC --> ELA
152155
ELA --> ELV
@@ -157,6 +160,8 @@ flowchart TD
157160
ESA --> EMI
158161
ESA --> EMO
159162
ES --> ECR
163+
EMI --> CF
164+
CF --> WS
160165
ECR --> REC
161166
EMO --> REC
162167
@@ -181,8 +186,10 @@ flowchart TD
181186
优先看 `ExecuteStoreAccess`
182187
- 改 D$ hit/miss/blocking/outstanding/stall counter:
183188
优先看 `ExecuteDCacheAccess`
184-
- 改已发出的 load/store miss 如何等待和回到 CDB:
185-
优先看 `ExecuteMemoryInflight`
189+
- 改已发出的 load/store miss 如何等待并提交完成事件:
190+
优先看 `ExecuteMemoryInflight``CompletionFabric`
191+
- 改执行完成带宽、completion backpressure、写回 fanout:
192+
优先看 `CompletionFabric``ExecuteStage``WritebackStage`
186193
- 改 addr-unknown store speculation、Bad Addr-Unknown Pair、load-store violation recovery trigger:
187194
优先看 `ExecuteMemoryOrder`
188195
- 改执行阶段早恢复、branch/JALR younger cleanup、rename checkpoint restore:
@@ -221,7 +228,7 @@ flowchart TD
221228
- 一个性能实验需要替换或比较不同策略,现有模块没有合适落点。
222229

223230
不满足这些条件时,优先把逻辑留在现有模块或补文档导航。
224-
例如 ALU/FP/BRANCH 的简单 ticking、CDB enqueue 的统一收尾、dispatch loop 的基本形状,暂时保留在 `ExecuteStage` 更直观。
231+
例如 ALU/FP/BRANCH 的简单 ticking、Completion Fabric 之外的 dispatch loop 基本形状,暂时保留在 `ExecuteStage` 更直观。
225232

226233
### 性能探索入口索引
227234

CONTEXT.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ _Avoid_: syscall, normal memory-mapped device
4545
The CPU mode that models instruction flow through fetch, decode, issue, execute, writeback, and commit with speculative execution and in-order retirement.
4646
_Avoid_: OOO blob, pipeline code
4747

48+
**Structural Constraint Simulator**:
49+
The modeling role for the out-of-order CPU: capture the timing and resource constraints that explain performance behavior without attempting cycle-accurate RTL reproduction.
50+
_Avoid_: full RTL replica, teaching-only Tomasulo model, functional-only simulator
51+
52+
**Completion Fabric**:
53+
The out-of-order pipeline's result-completion boundary that arbitrates when executed work becomes visible to wakeup, physical-register writeback, and ROB completion.
54+
_Avoid_: treating the Common Data Bus as the long-term domain boundary
55+
56+
**Completion Backpressure**:
57+
The structural constraint where an execution unit that has produced a result must keep holding it when the Completion Fabric cannot accept another completion event in the current cycle.
58+
_Avoid_: silently buffering every completed result in an unbounded queue
59+
4860
**Stage Context**:
4961
A stage-specific adapter that exposes only the state and actions a pipeline stage needs for one execution step.
5062
_Avoid_: passing raw `CPUState` as the stage interface
@@ -124,6 +136,9 @@ _Avoid_: blacklist entry
124136
## Relationships
125137

126138
- An **Out-of-Order Pipeline** executes each stage through a **Stage Context**.
139+
- A **Structural Constraint Simulator** should model performance-visible resource contention while keeping implementation detail below full RTL fidelity.
140+
- A **Completion Fabric** replaces the Common Data Bus as the domain concept for execution-result completion; any CDB-like queue is only a legacy or migration detail.
141+
- **Completion Backpressure** keeps completed execution units occupied when completion bandwidth is exhausted.
127142
- The **Simulator** owns the run lifecycle and may create a **Reference Execution Context** when **DiffTest** is enabled for an out-of-order run.
128143
- A **Checkpoint Runner** drives the **Simulator** over an **Instruction Window** after importing a workload slice.
129144
- **Address Translation** delegates Sv39-specific page-table traversal to the **SV39 Page Walker** and is constrained by **Privilege State**.
@@ -153,5 +168,8 @@ _Avoid_: blacklist entry
153168
## Flagged Ambiguities
154169

155170
- Use **Execute Memory Order** for the decision and accounting around memory-order speculation. Use **OOO Recovery** for the shared pipeline cleanup rules.
171+
- Use **Structural Constraint Simulator** for the intended OOO modeling fidelity; do not describe this direction as full RTL reproduction or as a purely functional simulator.
172+
- Use **Completion Fabric** for the future result-completion boundary; use Common Data Bus only when referring to legacy implementation or migration work.
173+
- Use **Completion Backpressure** when completion bandwidth stalls a completed execution unit; do not model this as an always-available result queue.
156174
- Use **Address Translation** for the fetch/load/store translation boundary. Use **SV39 Page Walker** only for the Sv39 page-table walk inside that boundary.
157175
- Use **DiffTest** for commit-time reference comparison, not for ordinary unit tests or benchmark result checks.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Retire CDB as the OOO Completion Boundary
2+
3+
The out-of-order CPU will use **Completion Fabric** as the domain concept for execution-result completion instead of continuing to treat the Common Data Bus as the architecture boundary. Existing CDB-shaped code may remain during migration, but the design direction is to reduce or remove it because a single global bus hides performance-visible distinctions between wakeup, physical-register writeback, and ROB completion.
4+
5+
**Status**: accepted
6+
7+
**Considered Options**
8+
9+
- Keep CDB as the primary concept and add more limits around it.
10+
- Retire CDB as a domain concept and migrate toward a Completion Fabric with separate completion consumers.
11+
12+
**Consequences**
13+
14+
- New design docs and tests should describe completion behavior in terms of Completion Fabric rather than CDB.
15+
- Migration can be incremental; existing CDB queues do not need to disappear in the first patch.
16+
- The first implementation should focus on completion-event arbitration and fanout to existing wakeup, physical-register writeback, and ROB-completion consumers.
17+
- More realistic bypass, wakeup, and select networks are deferred until the Completion Fabric boundary is established.
18+
- The first implementation should model completion backpressure: a completed execution unit keeps holding its result when completion bandwidth is exhausted instead of placing every result into an unbounded queue.
19+
- IPC improvement is not an acceptance criterion for the first implementation. A lower IPC is acceptable when it follows from modeling a previously missing structural constraint more realistically.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include "cpu/ooo/ooo_types.h"
4+
5+
#include <cstddef>
6+
#include <queue>
7+
8+
namespace riscv {
9+
10+
class CompletionFabric {
11+
public:
12+
explicit CompletionFabric(size_t completion_width = OOOPipelineConfig::COMPLETION_WIDTH);
13+
14+
void beginCycle();
15+
bool trySubmit(const CompletionEvent& event);
16+
17+
bool empty() const { return ready_events_.empty(); }
18+
size_t size() const { return ready_events_.size(); }
19+
size_t completionWidth() const { return completion_width_; }
20+
size_t usedCompletionSlots() const { return accepted_this_cycle_; }
21+
size_t availableCompletionSlots() const;
22+
23+
CompletionEvent popReadyEvent();
24+
uint64_t clear();
25+
uint64_t flushYoungerThan(uint64_t instruction_id);
26+
27+
private:
28+
size_t completion_width_;
29+
size_t accepted_this_cycle_;
30+
std::queue<CompletionEvent> ready_events_;
31+
};
32+
33+
} // namespace riscv

include/cpu/ooo/cpu_state.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "common/types.h"
4+
#include "cpu/ooo/completion_fabric.h"
45
#include "core/memory.h"
56
#include "core/decoder.h"
67
#include "cpu/ooo/register_rename.h"
@@ -67,6 +68,7 @@ struct ExecutionUnit {
6768
uint64_t result;
6869
bool has_exception;
6970
std::string exception_msg;
71+
bool completion_pending;
7072
// 跳转指令相关字段
7173
uint64_t jump_target;
7274
bool is_jump;
@@ -147,6 +149,7 @@ inline void resetExecutionUnitState(ExecutionUnit& unit) {
147149
unit.result = 0;
148150
unit.has_exception = false;
149151
unit.exception_msg.clear();
152+
unit.completion_pending = false;
150153
unit.jump_target = 0;
151154
unit.is_jump = false;
152155
unit.load_address = 0;
@@ -253,7 +256,7 @@ struct CPUState {
253256

254257
// 流水线缓冲区
255258
std::queue<FetchedInstruction> fetch_buffer; // 取指缓冲区
256-
std::queue<CommonDataBusEntry> cdb_queue; // 通用数据总线队列
259+
CompletionFabric completion_fabric; // 执行完成事件仲裁与缓冲
257260

258261
// 核心组件(共享引用)
259262
std::shared_ptr<Memory> memory;

include/cpu/ooo/execute_memory_inflight.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace riscv {
88

99
class ExecuteMemoryInflight {
1010
public:
11-
using CompletionCallback = std::function<void(ExecutionUnit&, ExecutionUnitType)>;
11+
using CompletionCallback = std::function<bool(ExecutionUnit&, ExecutionUnitType)>;
1212

1313
static bool hasAny(const CPUState& state);
1414
static bool tryMove(ExecutionUnit& unit,

include/cpu/ooo/ooo_recovery.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class OooRecovery {
3939
struct Result {
4040
uint64_t flushed_rob_entries = 0;
4141
uint64_t fetch_buffer_dropped = 0;
42-
uint64_t flushed_cdb_entries = 0;
42+
uint64_t flushed_completion_events = 0;
4343
bool flushed_l1d_inflight = false;
4444
};
4545

@@ -49,7 +49,7 @@ class OooRecovery {
4949

5050
private:
5151
static void recordFlushCounters(CPUState& state, Reason reason, uint64_t flushed_rob_entries);
52-
static uint64_t flushYoungerCdbEntries(CPUState& state, uint64_t instruction_id);
52+
static uint64_t flushYoungerCompletionEvents(CPUState& state, uint64_t instruction_id);
5353
static bool flushYoungerExecutionUnits(CPUState& state, const YoungerThanRequest& request);
5454
static void restoreRenameCheckpointForSurvivingWork(CPUState& state,
5555
uint64_t instruction_id,

include/cpu/ooo/ooo_types.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ enum class ExecutionUnitType {
3838
class DynamicInst;
3939
using DynamicInstPtr = std::shared_ptr<DynamicInst>;
4040

41-
// 公共数据总线项 - 使用DynamicInst指针保持数据一致性
42-
struct CommonDataBusEntry {
41+
// 执行完成事件 - 使用DynamicInst指针保持数据一致性
42+
struct CompletionEvent {
4343
DynamicInstPtr instruction; // 直接使用DynamicInst指针作为数据源
4444
bool valid;
4545

46-
CommonDataBusEntry() : instruction(nullptr), valid(false) {}
47-
explicit CommonDataBusEntry(DynamicInstPtr inst) : instruction(inst), valid(true) {}
46+
CompletionEvent() : instruction(nullptr), valid(false) {}
47+
explicit CompletionEvent(DynamicInstPtr inst) : instruction(inst), valid(true) {}
4848
};
4949

5050
// 分支预测结果
@@ -75,6 +75,7 @@ struct OOOPipelineConfig {
7575
static constexpr size_t ISSUE_WIDTH = 4;
7676
static constexpr size_t DISPATCH_WIDTH = 4;
7777
static constexpr size_t WRITEBACK_WIDTH = 2;
78+
static constexpr size_t COMPLETION_WIDTH = WRITEBACK_WIDTH;
7879
static constexpr size_t COMMIT_WIDTH = 4;
7980
static constexpr size_t STORE_COMMIT_WIDTH = 1;
8081
static constexpr size_t RECOVERY_REDIRECT_LATENCY = 2;

include/cpu/ooo/perf_counter_defs.inc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ PERF_COUNTER_DEF(TOPDOWN_SLOTS_RESOURCE_BLOCKED, "cpu.topdown.slots.resource_blo
2020
PERF_COUNTER_DEF(TOPDOWN_SLOTS_NO_UNIT, "cpu.topdown.slots.no_unit", "Execute slots selected work but found no execution unit")
2121
PERF_COUNTER_DEF(TOPDOWN_SLOTS_AMO_WAIT, "cpu.topdown.slots.amo_wait", "Execute slots selected AMO work delayed by older store-like operations")
2222
PERF_COUNTER_DEF(TOPDOWN_SLOTS_OTHER, "cpu.topdown.slots.other", "Execute slots not classified by the slot topdown-lite categories")
23-
PERF_COUNTER_DEF(CDB_ENQUEUED, "cpu.execute.cdb_enqueued", "Execution results enqueued to CDB")
24-
PERF_COUNTER_DEF(WRITEBACKS, "cpu.writeback.count", "CDB entries consumed in writeback stage")
23+
PERF_COUNTER_DEF(COMPLETION_ACCEPTED, "cpu.completion.accepted", "Execution completion events accepted by the completion fabric")
24+
PERF_COUNTER_DEF(WRITEBACKS, "cpu.writeback.count", "Completion events consumed in writeback stage")
2525
PERF_COUNTER_DEF(COMMIT_SLOTS, "cpu.commit.slots", "Total commit stage slots available")
2626
PERF_COUNTER_DEF(COMMIT_UTILIZED_SLOTS, "cpu.commit.utilized_slots", "Commit slots that successfully retired an instruction")
2727
PERF_COUNTER_DEF(STALL_COMMIT_STORE_PORT_BUSY, "cpu.stall.commit_store_port_busy", "Commit stopped because store memory write ports were exhausted")
@@ -85,6 +85,7 @@ PERF_COUNTER_DEF(STALL_EXECUTE_DEPENDENCY_BLOCKED, "cpu.stall.execute_dependency
8585
PERF_COUNTER_DEF(STALL_EXECUTE_RESOURCE_BLOCKED, "cpu.stall.execute_resource_blocked", "Execute stalled because ready instructions wait for resources")
8686
PERF_COUNTER_DEF(STALL_EXECUTE_NO_UNIT, "cpu.stall.execute_no_unit", "Execute stage had ready instruction but no execution unit")
8787
PERF_COUNTER_DEF(STALL_EXECUTE_AMO_WAIT, "cpu.stall.execute_amo_wait", "AMO delayed by older uncommitted store-like operations")
88+
PERF_COUNTER_DEF(STALL_COMPLETION_PORT_BUSY, "cpu.stall.completion_port_busy", "Execution result held because completion fabric bandwidth was exhausted")
8889
PERF_COUNTER_DEF(STALL_MEMORY_REPLAY_PORT_BUSY, "cpu.stall.memory_replay_port_busy", "Memory inflight completion delayed because replay ports were exhausted")
8990

9091
PERF_COUNTER_DEF(LOAD_REPLAYS, "cpu.memory.load_replays", "Load instructions replayed due to memory ordering")

include/cpu/ooo/reservation_station.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ using ReservationStationEntry = DynamicInst;
1919
*
2020
* 功能:
2121
* 1. 管理等待执行的指令
22-
* 2. 监听公共数据总线(CDB),更新操作数状态
22+
* 2. 监听完成事件,更新操作数状态
2323
* 3. 选择准备好的指令发射到执行单元
2424
* 4. 支持不同类型的执行单元(ALU、分支、访存)
2525
*/
@@ -80,8 +80,8 @@ class ReservationStation {
8080
size_t limit,
8181
const std::function<bool(const DynamicInstPtr&)>& can_dispatch = {});
8282

83-
// 更新操作数(来自CDB
84-
void update_operands(const CommonDataBusEntry& cdb_entry, StoreBuffer* store_buffer);
83+
// 更新操作数(来自完成事件
84+
void update_operands(const CompletionEvent& completion_event, StoreBuffer* store_buffer);
8585

8686
// 释放保留站表项
8787
void release_entry(RSEntry rs_entry);

0 commit comments

Comments
 (0)