front-cpu 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +475 -0
- package/README.zh-CN.md +474 -0
- package/dist/Pipeline.d.ts +119 -0
- package/dist/Pipeline.d.ts.map +1 -0
- package/dist/Pipeline.js +373 -0
- package/dist/Pipeline.js.map +1 -0
- package/dist/debug.d.ts +3 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +12 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +49 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +8 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/isa/index.d.ts +20 -0
- package/dist/isa/index.d.ts.map +1 -0
- package/dist/isa/index.js +26 -0
- package/dist/isa/index.js.map +1 -0
- package/dist/isa/types.d.ts +144 -0
- package/dist/isa/types.d.ts.map +1 -0
- package/dist/isa/types.js +10 -0
- package/dist/isa/types.js.map +1 -0
- package/dist/logging/CPUConsole.d.ts +105 -0
- package/dist/logging/CPUConsole.d.ts.map +1 -0
- package/dist/logging/CPUConsole.js +471 -0
- package/dist/logging/CPUConsole.js.map +1 -0
- package/dist/logging/CPUDebugger.d.ts +91 -0
- package/dist/logging/CPUDebugger.d.ts.map +1 -0
- package/dist/logging/CPUDebugger.js +166 -0
- package/dist/logging/CPUDebugger.js.map +1 -0
- package/dist/logging/CPUEventCollector.d.ts +90 -0
- package/dist/logging/CPUEventCollector.d.ts.map +1 -0
- package/dist/logging/CPUEventCollector.js +353 -0
- package/dist/logging/CPUEventCollector.js.map +1 -0
- package/dist/logging/CPULogger.d.ts +150 -0
- package/dist/logging/CPULogger.d.ts.map +1 -0
- package/dist/logging/CPULogger.js +336 -0
- package/dist/logging/CPULogger.js.map +1 -0
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +16 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/runtime.d.ts +37 -0
- package/dist/logging/runtime.d.ts.map +1 -0
- package/dist/logging/runtime.js +42 -0
- package/dist/logging/runtime.js.map +1 -0
- package/dist/logging/stack-parser.d.ts +22 -0
- package/dist/logging/stack-parser.d.ts.map +1 -0
- package/dist/logging/stack-parser.js +144 -0
- package/dist/logging/stack-parser.js.map +1 -0
- package/dist/logging/types.d.ts +73 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +47 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/scheduling/ResourceStrategyRegistry.d.ts +61 -0
- package/dist/scheduling/ResourceStrategyRegistry.d.ts.map +1 -0
- package/dist/scheduling/ResourceStrategyRegistry.js +109 -0
- package/dist/scheduling/ResourceStrategyRegistry.js.map +1 -0
- package/dist/scheduling/index.d.ts +6 -0
- package/dist/scheduling/index.d.ts.map +1 -0
- package/dist/scheduling/index.js +5 -0
- package/dist/scheduling/index.js.map +1 -0
- package/dist/scheduling/types.d.ts +44 -0
- package/dist/scheduling/types.d.ts.map +1 -0
- package/dist/scheduling/types.js +5 -0
- package/dist/scheduling/types.js.map +1 -0
- package/dist/stages/EX.d.ts +17 -0
- package/dist/stages/EX.d.ts.map +1 -0
- package/dist/stages/EX.js +95 -0
- package/dist/stages/EX.js.map +1 -0
- package/dist/stages/IF.d.ts +41 -0
- package/dist/stages/IF.d.ts.map +1 -0
- package/dist/stages/IF.js +83 -0
- package/dist/stages/IF.js.map +1 -0
- package/dist/stages/RES.d.ts +17 -0
- package/dist/stages/RES.d.ts.map +1 -0
- package/dist/stages/RES.js +37 -0
- package/dist/stages/RES.js.map +1 -0
- package/dist/stages/SCH.d.ts +77 -0
- package/dist/stages/SCH.d.ts.map +1 -0
- package/dist/stages/SCH.js +270 -0
- package/dist/stages/SCH.js.map +1 -0
- package/dist/stages/WB.d.ts +19 -0
- package/dist/stages/WB.d.ts.map +1 -0
- package/dist/stages/WB.js +102 -0
- package/dist/stages/WB.js.map +1 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/InstructionCancellation.d.ts +31 -0
- package/dist/utils/InstructionCancellation.d.ts.map +1 -0
- package/dist/utils/InstructionCancellation.js +53 -0
- package/dist/utils/InstructionCancellation.js.map +1 -0
- package/dist/utils/abortable.d.ts +30 -0
- package/dist/utils/abortable.d.ts.map +1 -0
- package/dist/utils/abortable.js +76 -0
- package/dist/utils/abortable.js.map +1 -0
- package/dist/utils/request.d.ts +27 -0
- package/dist/utils/request.d.ts.map +1 -0
- package/dist/utils/request.js +96 -0
- package/dist/utils/request.js.map +1 -0
- package/package.json +74 -0
- package/src/Pipeline.ts +475 -0
- package/src/debug.ts +15 -0
- package/src/index.ts +67 -0
- package/src/interfaces.ts +53 -0
- package/src/isa/index.ts +34 -0
- package/src/isa/types.ts +178 -0
- package/src/logging/CPUConsole.md +843 -0
- package/src/logging/CPUConsole.ts +631 -0
- package/src/logging/CPUDebugger.ts +235 -0
- package/src/logging/CPUEventCollector.ts +418 -0
- package/src/logging/CPULogger.ts +435 -0
- package/src/logging/CPU_LOGGING_DESIGN.md +1319 -0
- package/src/logging/USAGE_GUIDE.md +505 -0
- package/src/logging/index.ts +21 -0
- package/src/logging/runtime.ts +96 -0
- package/src/logging/stack-parser.ts +168 -0
- package/src/logging/types.ts +101 -0
- package/src/scheduling/ResourceStrategyRegistry.ts +124 -0
- package/src/scheduling/index.ts +13 -0
- package/src/scheduling/types.ts +47 -0
- package/src/stages/EX.ts +121 -0
- package/src/stages/IF.ts +103 -0
- package/src/stages/RES.ts +46 -0
- package/src/stages/SCH.ts +331 -0
- package/src/stages/WB.ts +127 -0
- package/src/types.ts +118 -0
- package/src/utils/InstructionCancellation.ts +73 -0
- package/src/utils/abortable.ts +89 -0
- package/src/utils/request.ts +125 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RES阶段:Response(响应处理)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { QueuedInstruction } from '../types'
|
|
6
|
+
import { InstructionStatus } from '../types'
|
|
7
|
+
import { isInstructionCancelled } from '../utils/InstructionCancellation'
|
|
8
|
+
|
|
9
|
+
export class ResponseStage {
|
|
10
|
+
/**
|
|
11
|
+
* 处理网络响应
|
|
12
|
+
*
|
|
13
|
+
* @returns success: 是否成功, shouldRetry: 是否需要重试, discarded: 是否被丢弃
|
|
14
|
+
*/
|
|
15
|
+
processResponse(
|
|
16
|
+
instruction: QueuedInstruction,
|
|
17
|
+
error?: Error
|
|
18
|
+
): { success: boolean; shouldRetry: boolean; discarded?: boolean } {
|
|
19
|
+
// 标记RES阶段时间戳
|
|
20
|
+
instruction.timestamps.RES = Date.now()
|
|
21
|
+
|
|
22
|
+
// 🔥 检查指令是否已被取消(可能在 SCH 或 EX 阶段被取消)
|
|
23
|
+
if (isInstructionCancelled(instruction)) {
|
|
24
|
+
// 保持 CANCELLED 状态,不要改为 FAILED
|
|
25
|
+
// instruction.status 已经是 CANCELLED
|
|
26
|
+
|
|
27
|
+
// 返回 discarded 标志
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
shouldRetry: false,
|
|
31
|
+
discarded: true
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (error) {
|
|
36
|
+
// 失败处理(简化版:不实现重试)
|
|
37
|
+
instruction.status = InstructionStatus.FAILED
|
|
38
|
+
instruction.error = error
|
|
39
|
+
return { success: false, shouldRetry: false }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 成功
|
|
43
|
+
instruction.status = InstructionStatus.RESPONDED
|
|
44
|
+
return { success: true, shouldRetry: false }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SCH阶段:Scheduler(指令调度器)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { QueuedInstruction } from '../types'
|
|
6
|
+
import { InstructionStatus } from '../types'
|
|
7
|
+
import { getISA } from '../isa'
|
|
8
|
+
import type { ResourceAccessMode, SchedulingStrategy } from '../isa/types'
|
|
9
|
+
import { resourceStrategyRegistry } from '../scheduling/ResourceStrategyRegistry'
|
|
10
|
+
import { cancelInstruction } from '../utils/InstructionCancellation'
|
|
11
|
+
|
|
12
|
+
export class SchedulerStage {
|
|
13
|
+
private pendingQueue: QueuedInstruction[] = []
|
|
14
|
+
private activeInstructions: Map<string, QueuedInstruction> = new Map()
|
|
15
|
+
// 资源 -> 调度策略映射
|
|
16
|
+
private resourceStrategies: Map<string, SchedulingStrategy> = new Map()
|
|
17
|
+
// 资源 -> 读写锁状态
|
|
18
|
+
private resourceLocks: Map<string, ResourceLockState> = new Map()
|
|
19
|
+
private maxConcurrency: number
|
|
20
|
+
|
|
21
|
+
constructor(maxConcurrency: number = 10) {
|
|
22
|
+
this.maxConcurrency = maxConcurrency
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 调度循环(tick)
|
|
27
|
+
*/
|
|
28
|
+
tick(): void {
|
|
29
|
+
// 🔥 边检查边发射,避免批量检查导致的竞态条件
|
|
30
|
+
// 每发射一个指令,资源状态立即更新,下一个指令检查时会看到最新状态
|
|
31
|
+
|
|
32
|
+
let issued = true
|
|
33
|
+
while (issued) {
|
|
34
|
+
issued = false
|
|
35
|
+
|
|
36
|
+
for (const instruction of this.pendingQueue) {
|
|
37
|
+
if (this.canIssue(instruction)) {
|
|
38
|
+
this.issue(instruction)
|
|
39
|
+
issued = true
|
|
40
|
+
break // 跳出for循环,重新检查pending队列
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 如果这轮没有发射任何指令,说明所有指令都被阻塞了,退出
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 添加指令到调度队列
|
|
50
|
+
*/
|
|
51
|
+
addInstruction(instruction: QueuedInstruction): void {
|
|
52
|
+
this.pendingQueue.push(instruction)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 判断指令是否可以发射
|
|
57
|
+
*/
|
|
58
|
+
private canIssue(instruction: QueuedInstruction): boolean {
|
|
59
|
+
// 检查并发数限制
|
|
60
|
+
if (this.activeInstructions.size >= this.maxConcurrency) {
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 检查资源冲突(根据调度策略)
|
|
65
|
+
if (this.hasResourceConflict(instruction)) {
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return true
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 获取指令的调度策略
|
|
74
|
+
*/
|
|
75
|
+
private getInstructionStrategy(instruction: QueuedInstruction): SchedulingStrategy {
|
|
76
|
+
const ISA = getISA()
|
|
77
|
+
const isa = ISA[instruction.type]
|
|
78
|
+
const instructionStrategy = isa?.meta.schedulingStrategy
|
|
79
|
+
const resourceAccesses = this.getResourceAccesses(instruction)
|
|
80
|
+
|
|
81
|
+
// 如果有多个资源,使用第一个资源的策略
|
|
82
|
+
const primaryResourceId = resourceAccesses[0]?.id
|
|
83
|
+
if (!primaryResourceId) {
|
|
84
|
+
return 'serial' // 默认
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return resourceStrategyRegistry.getStrategy(primaryResourceId, instructionStrategy)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 发射指令
|
|
92
|
+
*/
|
|
93
|
+
private issue(instruction: QueuedInstruction): void {
|
|
94
|
+
// 从pending队列移除
|
|
95
|
+
const index = this.pendingQueue.indexOf(instruction)
|
|
96
|
+
if (index !== -1) {
|
|
97
|
+
this.pendingQueue.splice(index, 1)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 标记为issued
|
|
101
|
+
instruction.status = InstructionStatus.ISSUED
|
|
102
|
+
instruction.timestamps.SCH = Date.now()
|
|
103
|
+
|
|
104
|
+
// 加入active列表
|
|
105
|
+
this.activeInstructions.set(instruction.id, instruction)
|
|
106
|
+
|
|
107
|
+
// 记录资源的活跃指令
|
|
108
|
+
const resourceAccesses = this.getResourceAccesses(instruction)
|
|
109
|
+
const strategy = this.getInstructionStrategy(instruction)
|
|
110
|
+
|
|
111
|
+
for (const resourceAccess of resourceAccesses) {
|
|
112
|
+
// 记录策略
|
|
113
|
+
this.resourceStrategies.set(resourceAccess.id, strategy)
|
|
114
|
+
|
|
115
|
+
// 记录读写锁
|
|
116
|
+
const lockState = this.getOrCreateResourceLock(resourceAccess.id)
|
|
117
|
+
if (resourceAccess.mode === 'read') {
|
|
118
|
+
lockState.readers.add(instruction.id)
|
|
119
|
+
} else {
|
|
120
|
+
lockState.writers.add(instruction.id)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 检测资源冲突(根据调度策略)
|
|
127
|
+
*/
|
|
128
|
+
private hasResourceConflict(instruction: QueuedInstruction): boolean {
|
|
129
|
+
const resourceAccesses = this.getResourceAccesses(instruction)
|
|
130
|
+
const strategy = this.getInstructionStrategy(instruction)
|
|
131
|
+
|
|
132
|
+
for (const resourceAccess of resourceAccesses) {
|
|
133
|
+
const lockState = this.resourceLocks.get(resourceAccess.id)
|
|
134
|
+
const hasActive =
|
|
135
|
+
!!lockState && (lockState.readers.size > 0 || lockState.writers.size > 0)
|
|
136
|
+
|
|
137
|
+
// out-of-order: 允许并发,不冲突
|
|
138
|
+
if (strategy === 'out-of-order') {
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// latest: 不冲突,但会取消旧指令(保留最新)
|
|
143
|
+
if (strategy === 'latest' && hasActive) {
|
|
144
|
+
this.cancelOldInstructions(resourceAccess.id, instruction.id)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// serial: 如果有活跃指令,则冲突(串行执行)
|
|
148
|
+
if (strategy === 'serial' && hasActive) {
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// read-write: 读共享、写互斥
|
|
153
|
+
if (strategy === 'read-write' && lockState) {
|
|
154
|
+
if (resourceAccess.mode === 'read') {
|
|
155
|
+
if (lockState.writers.size > 0) {
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
if (lockState.writers.size > 0 || lockState.readers.size > 0) {
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return false
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 取消旧指令(latest 策略)
|
|
171
|
+
*/
|
|
172
|
+
private cancelOldInstructions(resourceId: string, newInstructionId: string): void {
|
|
173
|
+
const lockState = this.resourceLocks.get(resourceId)
|
|
174
|
+
if (!lockState) return
|
|
175
|
+
|
|
176
|
+
const activeInstructionIds = new Set<string>([
|
|
177
|
+
...lockState.readers,
|
|
178
|
+
...lockState.writers,
|
|
179
|
+
])
|
|
180
|
+
|
|
181
|
+
for (const oldInstructionId of activeInstructionIds) {
|
|
182
|
+
const oldInstruction = this.activeInstructions.get(oldInstructionId)
|
|
183
|
+
if (oldInstruction && oldInstructionId !== newInstructionId) {
|
|
184
|
+
// 使用统一的取消机制
|
|
185
|
+
cancelInstruction(
|
|
186
|
+
oldInstruction,
|
|
187
|
+
`Cancelled by latest strategy: new instruction ${newInstructionId}`,
|
|
188
|
+
'SCH'
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 从payload中提取资源访问列表(读/写)
|
|
196
|
+
*/
|
|
197
|
+
private getResourceAccesses(instruction: QueuedInstruction): NormalizedResourceAccess[] {
|
|
198
|
+
const ISA = getISA()
|
|
199
|
+
const isa = ISA[instruction.type]
|
|
200
|
+
if (!isa) {
|
|
201
|
+
return []
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const rawAccesses = isa.meta.resourceIdentifier(instruction.payload)
|
|
205
|
+
const merged = new Map<string, ResourceAccessMode>()
|
|
206
|
+
|
|
207
|
+
for (const rawAccess of rawAccesses) {
|
|
208
|
+
const normalized =
|
|
209
|
+
typeof rawAccess === 'string'
|
|
210
|
+
? { id: rawAccess, mode: 'write' as ResourceAccessMode }
|
|
211
|
+
: {
|
|
212
|
+
id: rawAccess.id,
|
|
213
|
+
mode: (rawAccess.mode ?? 'write') as ResourceAccessMode,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const existing = merged.get(normalized.id)
|
|
217
|
+
if (!existing) {
|
|
218
|
+
merged.set(normalized.id, normalized.mode)
|
|
219
|
+
continue
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (existing === 'read' && normalized.mode === 'write') {
|
|
223
|
+
merged.set(normalized.id, 'write')
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return Array.from(merged, ([id, mode]) => ({ id, mode }))
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 获取或创建资源读写锁
|
|
232
|
+
*/
|
|
233
|
+
private getOrCreateResourceLock(resourceId: string): ResourceLockState {
|
|
234
|
+
let lockState = this.resourceLocks.get(resourceId)
|
|
235
|
+
if (!lockState) {
|
|
236
|
+
lockState = {
|
|
237
|
+
readers: new Set<string>(),
|
|
238
|
+
writers: new Set<string>(),
|
|
239
|
+
}
|
|
240
|
+
this.resourceLocks.set(resourceId, lockState)
|
|
241
|
+
}
|
|
242
|
+
return lockState
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 释放指令占用的资源
|
|
247
|
+
*/
|
|
248
|
+
releaseInstruction(instructionId: string): void {
|
|
249
|
+
const instruction = this.activeInstructions.get(instructionId)
|
|
250
|
+
if (!instruction) return
|
|
251
|
+
|
|
252
|
+
// 释放资源的活跃指令记录
|
|
253
|
+
const resourceAccesses = this.getResourceAccesses(instruction)
|
|
254
|
+
for (const resourceAccess of resourceAccesses) {
|
|
255
|
+
const lockState = this.resourceLocks.get(resourceAccess.id)
|
|
256
|
+
if (!lockState) {
|
|
257
|
+
continue
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (resourceAccess.mode === 'read') {
|
|
261
|
+
lockState.readers.delete(instructionId)
|
|
262
|
+
} else {
|
|
263
|
+
lockState.writers.delete(instructionId)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// 如果该资源没有活跃指令了,清理记录
|
|
267
|
+
if (lockState.readers.size === 0 && lockState.writers.size === 0) {
|
|
268
|
+
this.resourceLocks.delete(resourceAccess.id)
|
|
269
|
+
this.resourceStrategies.delete(resourceAccess.id)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 从active列表移除
|
|
274
|
+
this.activeInstructions.delete(instructionId)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* 获取pending队列(用于调试)
|
|
279
|
+
*/
|
|
280
|
+
getPendingQueue(): QueuedInstruction[] {
|
|
281
|
+
return [...this.pendingQueue]
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 获取正在执行的指令列表(用于调试)
|
|
286
|
+
*/
|
|
287
|
+
getActiveInstructions(): QueuedInstruction[] {
|
|
288
|
+
return Array.from(this.activeInstructions.values())
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 获取pending队列大小
|
|
293
|
+
*/
|
|
294
|
+
getPendingQueueSize(): number {
|
|
295
|
+
return this.pendingQueue.length
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* 获取活跃指令数量
|
|
300
|
+
*/
|
|
301
|
+
getActiveCount(): number {
|
|
302
|
+
return this.activeInstructions.size
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* 获取所有待处理指令
|
|
307
|
+
*/
|
|
308
|
+
getPendingInstructions(): QueuedInstruction[] {
|
|
309
|
+
return [...this.pendingQueue]
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* 清空调度器
|
|
314
|
+
*/
|
|
315
|
+
clear(): void {
|
|
316
|
+
this.pendingQueue = []
|
|
317
|
+
this.activeInstructions.clear()
|
|
318
|
+
this.resourceStrategies.clear()
|
|
319
|
+
this.resourceLocks.clear()
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
interface ResourceLockState {
|
|
324
|
+
readers: Set<string>
|
|
325
|
+
writers: Set<string>
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
interface NormalizedResourceAccess {
|
|
329
|
+
id: string
|
|
330
|
+
mode: ResourceAccessMode
|
|
331
|
+
}
|
package/src/stages/WB.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WB阶段:Write Back(写回)
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* 1. 调用 commit 函数(成功时)
|
|
6
|
+
* 2. 回滚乐观更新(失败时)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { QueuedInstruction } from '../types'
|
|
10
|
+
import { InstructionStatus } from '../types'
|
|
11
|
+
import { getISA } from '../isa'
|
|
12
|
+
import { cpuEventCollector, cpuConsole } from '../logging/runtime'
|
|
13
|
+
|
|
14
|
+
export class WriteBackStage {
|
|
15
|
+
/**
|
|
16
|
+
* 回滚乐观更新
|
|
17
|
+
*/
|
|
18
|
+
private rollbackOptimisticUpdate(instruction: QueuedInstruction): void {
|
|
19
|
+
const ISA = getISA()
|
|
20
|
+
const definition = ISA[instruction.type]
|
|
21
|
+
|
|
22
|
+
if (instruction.optimisticSnapshot && definition?.optimistic?.rollback) {
|
|
23
|
+
// 记录回滚操作
|
|
24
|
+
if (!instruction.writeBackExecution) {
|
|
25
|
+
instruction.writeBackExecution = { hasCommit: false, rollbackExecuted: true }
|
|
26
|
+
}
|
|
27
|
+
instruction.writeBackExecution.rollbackExecuted = true
|
|
28
|
+
instruction.writeBackExecution.rollbackSnapshot = instruction.optimisticSnapshot
|
|
29
|
+
|
|
30
|
+
// 🎯 记录乐观更新回滚事件
|
|
31
|
+
cpuEventCollector.onOptimisticRolledBack(
|
|
32
|
+
instruction.id,
|
|
33
|
+
instruction.type,
|
|
34
|
+
instruction.context.correlationId,
|
|
35
|
+
instruction.optimisticSnapshot,
|
|
36
|
+
'指令执行失败',
|
|
37
|
+
instruction.error
|
|
38
|
+
)
|
|
39
|
+
cpuConsole.onOptimisticRolledBack(instruction, '指令执行失败')
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
definition.optimistic.rollback(instruction.optimisticSnapshot)
|
|
43
|
+
} catch (rollbackError) {
|
|
44
|
+
instruction.writeBackExecution.rollbackError =
|
|
45
|
+
rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError))
|
|
46
|
+
console.error('❌ [CPU] 乐观更新回滚失败:', {
|
|
47
|
+
instructionId: instruction.id,
|
|
48
|
+
type: instruction.type,
|
|
49
|
+
error: rollbackError,
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 写回/完成指令
|
|
57
|
+
*/
|
|
58
|
+
async writeBack(instruction: QueuedInstruction, success: boolean): Promise<void> {
|
|
59
|
+
// 标记WB阶段
|
|
60
|
+
instruction.timestamps.WB = Date.now()
|
|
61
|
+
|
|
62
|
+
const ISA = getISA()
|
|
63
|
+
const definition = ISA[instruction.type]
|
|
64
|
+
|
|
65
|
+
// 初始化WB执行记录
|
|
66
|
+
instruction.writeBackExecution = {
|
|
67
|
+
hasCommit: !!(definition && definition.commit),
|
|
68
|
+
rollbackExecuted: false,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 🔥 如果指令已被取消,只回滚不提交
|
|
72
|
+
if (instruction.cancelled) {
|
|
73
|
+
this.rollbackOptimisticUpdate(instruction)
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (success) {
|
|
78
|
+
// ==================== 成功路径 ====================
|
|
79
|
+
|
|
80
|
+
// 🔥 调用 commit 函数(如果存在)
|
|
81
|
+
if (definition && definition.commit) {
|
|
82
|
+
// 记录commit调用参数
|
|
83
|
+
instruction.writeBackExecution.commitArgs = {
|
|
84
|
+
result: instruction.result,
|
|
85
|
+
payload: instruction.payload,
|
|
86
|
+
context: instruction.context,
|
|
87
|
+
optimisticSnapshot: instruction.optimisticSnapshot,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
await definition.commit(
|
|
92
|
+
instruction.result,
|
|
93
|
+
instruction.payload,
|
|
94
|
+
instruction.context,
|
|
95
|
+
instruction.optimisticSnapshot // 🔥 传递乐观更新快照
|
|
96
|
+
)
|
|
97
|
+
instruction.writeBackExecution.commitSuccess = true
|
|
98
|
+
} catch (error) {
|
|
99
|
+
instruction.writeBackExecution.commitSuccess = false
|
|
100
|
+
instruction.writeBackExecution.commitError =
|
|
101
|
+
error instanceof Error ? error : new Error(String(error))
|
|
102
|
+
|
|
103
|
+
// commit失败 → 回滚乐观更新
|
|
104
|
+
this.rollbackOptimisticUpdate(instruction)
|
|
105
|
+
|
|
106
|
+
// 设置为失败状态
|
|
107
|
+
instruction.status = InstructionStatus.FAILED
|
|
108
|
+
instruction.error = instruction.writeBackExecution.commitError
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 成功场景
|
|
114
|
+
instruction.status = InstructionStatus.COMMITTED
|
|
115
|
+
} else {
|
|
116
|
+
// ==================== 失败路径 ====================
|
|
117
|
+
|
|
118
|
+
// 🔥 回滚乐观更新
|
|
119
|
+
this.rollbackOptimisticUpdate(instruction)
|
|
120
|
+
|
|
121
|
+
// 设置失败状态(如果不是已取消)
|
|
122
|
+
if (instruction.status !== InstructionStatus.CANCELLED) {
|
|
123
|
+
instruction.status = InstructionStatus.FAILED
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CPU流水线核心类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CallSource } from './logging/types'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 流水线阶段
|
|
9
|
+
*/
|
|
10
|
+
export const PipelineStage = {
|
|
11
|
+
IF: 'IF', // Instruction Fetch
|
|
12
|
+
SCH: 'SCH', // Scheduler
|
|
13
|
+
EX: 'EX', // Execute
|
|
14
|
+
RES: 'RES', // Response
|
|
15
|
+
WB: 'WB', // Write Back
|
|
16
|
+
} as const
|
|
17
|
+
|
|
18
|
+
export type PipelineStage = (typeof PipelineStage)[keyof typeof PipelineStage]
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 指令状态
|
|
22
|
+
*/
|
|
23
|
+
export const InstructionStatus = {
|
|
24
|
+
PENDING: 'pending', // 在IF缓冲区等待调度
|
|
25
|
+
ISSUED: 'issued', // 已发射到EX阶段
|
|
26
|
+
EXECUTING: 'executing', // 正在执行
|
|
27
|
+
RESPONDED: 'responded', // 已收到响应
|
|
28
|
+
COMMITTED: 'committed', // 已提交完成
|
|
29
|
+
FAILED: 'failed', // 执行失败
|
|
30
|
+
CANCELLED: 'cancelled', // 被取消/丢弃(可能在任何阶段)
|
|
31
|
+
} as const
|
|
32
|
+
|
|
33
|
+
export type InstructionStatus = (typeof InstructionStatus)[keyof typeof InstructionStatus]
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 指令执行上下文
|
|
37
|
+
*/
|
|
38
|
+
export interface InstructionContext {
|
|
39
|
+
/** 指令唯一ID */
|
|
40
|
+
instructionId: string
|
|
41
|
+
/** 关联ID(用于SSE去重等) */
|
|
42
|
+
correlationId: string
|
|
43
|
+
/** 时间戳 */
|
|
44
|
+
timestamp: number
|
|
45
|
+
/** 来源 */
|
|
46
|
+
source: 'user' | 'system' | 'test'
|
|
47
|
+
/** 重试次数 */
|
|
48
|
+
retryCount: number
|
|
49
|
+
/** 调用源(哪个文件哪一行发起的指令) */
|
|
50
|
+
callSource?: CallSource
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* WB阶段执行信息
|
|
55
|
+
*/
|
|
56
|
+
export interface WriteBackExecution {
|
|
57
|
+
/** 是否有commit函数 */
|
|
58
|
+
hasCommit: boolean
|
|
59
|
+
/** commit函数调用参数 */
|
|
60
|
+
commitArgs?: {
|
|
61
|
+
result: any
|
|
62
|
+
payload: any
|
|
63
|
+
context: InstructionContext
|
|
64
|
+
optimisticSnapshot?: any
|
|
65
|
+
}
|
|
66
|
+
/** commit执行结果 */
|
|
67
|
+
commitSuccess?: boolean
|
|
68
|
+
/** commit错误信息 */
|
|
69
|
+
commitError?: Error
|
|
70
|
+
/** 是否执行了回滚 */
|
|
71
|
+
rollbackExecuted?: boolean
|
|
72
|
+
/** 回滚快照 */
|
|
73
|
+
rollbackSnapshot?: any
|
|
74
|
+
/** 回滚错误 */
|
|
75
|
+
rollbackError?: Error
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 队列中的指令
|
|
80
|
+
*/
|
|
81
|
+
export interface QueuedInstruction<TPayload = any> {
|
|
82
|
+
/** 指令ID */
|
|
83
|
+
id: string
|
|
84
|
+
/** 指令类型 */
|
|
85
|
+
type: string
|
|
86
|
+
/** 指令负载 */
|
|
87
|
+
payload: TPayload
|
|
88
|
+
/** 执行上下文 */
|
|
89
|
+
context: InstructionContext
|
|
90
|
+
/** 当前状态 */
|
|
91
|
+
status: InstructionStatus
|
|
92
|
+
/** 各阶段时间戳 */
|
|
93
|
+
timestamps: {
|
|
94
|
+
IF?: number
|
|
95
|
+
SCH?: number
|
|
96
|
+
EX?: number
|
|
97
|
+
RES?: number
|
|
98
|
+
WB?: number
|
|
99
|
+
}
|
|
100
|
+
/** 执行结果 */
|
|
101
|
+
result?: any
|
|
102
|
+
/** 错误信息 */
|
|
103
|
+
error?: Error
|
|
104
|
+
/** 乐观更新快照(用于回滚) */
|
|
105
|
+
optimisticSnapshot?: any
|
|
106
|
+
/** WB阶段执行详情 */
|
|
107
|
+
writeBackExecution?: WriteBackExecution
|
|
108
|
+
/** 是否已取消(用于 switchMap 策略) */
|
|
109
|
+
cancelled?: boolean
|
|
110
|
+
/** 取消原因 */
|
|
111
|
+
cancelReason?: string
|
|
112
|
+
/** 取消发生的阶段 */
|
|
113
|
+
cancelledAt?: 'SCH' | 'EX' | 'RES'
|
|
114
|
+
/** 用于取消网络请求 */
|
|
115
|
+
abortController?: AbortController
|
|
116
|
+
/** 指令标签 */
|
|
117
|
+
tags?: string[]
|
|
118
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 指令取消管理器
|
|
3
|
+
*
|
|
4
|
+
* 提供统一的指令取消机制,可以在任何阶段取消指令
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { QueuedInstruction } from '../types'
|
|
8
|
+
import { InstructionStatus } from '../types'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 取消指令
|
|
12
|
+
*
|
|
13
|
+
* @param instruction 要取消的指令
|
|
14
|
+
* @param reason 取消原因
|
|
15
|
+
* @param stage 取消发生的阶段
|
|
16
|
+
*/
|
|
17
|
+
export function cancelInstruction(
|
|
18
|
+
instruction: QueuedInstruction,
|
|
19
|
+
reason: string,
|
|
20
|
+
stage: 'SCH' | 'EX' | 'RES'
|
|
21
|
+
): void {
|
|
22
|
+
// 标记为已取消
|
|
23
|
+
instruction.cancelled = true
|
|
24
|
+
instruction.cancelReason = reason
|
|
25
|
+
instruction.cancelledAt = stage
|
|
26
|
+
instruction.status = InstructionStatus.CANCELLED
|
|
27
|
+
|
|
28
|
+
// 设置错误信息
|
|
29
|
+
instruction.error = new Error(`[${stage}] ${reason}`)
|
|
30
|
+
|
|
31
|
+
// 🔥 实际取消网络请求
|
|
32
|
+
if (instruction.abortController && !instruction.abortController.signal.aborted) {
|
|
33
|
+
instruction.abortController.abort(instruction.cancelReason)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 检查指令是否已被取消
|
|
39
|
+
*/
|
|
40
|
+
export function isInstructionCancelled(instruction: QueuedInstruction): boolean {
|
|
41
|
+
return instruction.cancelled === true || instruction.status === InstructionStatus.CANCELLED
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 获取取消信息(用于日志)
|
|
46
|
+
*/
|
|
47
|
+
export function getCancellationInfo(instruction: QueuedInstruction): {
|
|
48
|
+
cancelled: boolean
|
|
49
|
+
reason?: string
|
|
50
|
+
stage?: string
|
|
51
|
+
} {
|
|
52
|
+
return {
|
|
53
|
+
cancelled: isInstructionCancelled(instruction),
|
|
54
|
+
reason: instruction.cancelReason,
|
|
55
|
+
stage: instruction.cancelledAt,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 批量取消指令(用于 switchMap 等场景)
|
|
61
|
+
*/
|
|
62
|
+
export function cancelInstructions(
|
|
63
|
+
instructions: QueuedInstruction[],
|
|
64
|
+
reason: string,
|
|
65
|
+
stage: 'SCH' | 'EX' | 'RES'
|
|
66
|
+
): void {
|
|
67
|
+
for (const instruction of instructions) {
|
|
68
|
+
if (!isInstructionCancelled(instruction)) {
|
|
69
|
+
cancelInstruction(instruction, reason, stage)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|