概述

本文档介绍如何在UVM验证环境中正确实现monitor采集DUT输出,以及如何通过分类型backpressure机制控制数据包流。核心特性是数据包级反压控制,确保数据包传输的完整性和可靠性。


第一部分:基础设计原则

核心原则

  • 只采样,不驱动 - Monitor绝不能影响DUT行为
  • 使用正确的信号方向 - input采样,output驱动
  • 时序同步 - 使用clocking block确保时序正确
  • 分类型精细控制 - 根据数据包类型实现独立流控
  • 数据包完整性 - 正确处理SOP/EOP边界和错误信号
  • 智能头部解析 - 从高128字节头部提取类型和长度信息
  • 数据包级反压 - backpressure只在完整数据包边界生效,避免中途中断

🎯 数据包级反压核心优势

  1. 传输完整性: 数据包传输过程中不被反压打断
  2. 边界对齐: 严格保持SOP/EOP边界完整性
  3. 状态一致: 避免传输状态机错乱
  4. 性能提升: DUT能完整处理数据包,减少重传开销

第二部分:Interface与Transaction设计

1. 优化的Interface定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
interface my_interface(input clk, input rst_n);
// === DUT输出信号(Monitor采样)- 2048位数据包格式 ===
logic [2047:0] data_out; // 2048位数据 (256字节)
logic sop_out; // 数据包开始标志
logic eop_out; // 数据包结束标志
logic vld_out; // 数据有效标志
logic err_out; // 错误标志

// === 分类型反压信号 - 数据包级控制 ===
logic type0_backpressure; // 控制数据类型0的数据包流
logic type1_backpressure; // 控制数据类型1的数据包流
logic type2_backpressure; // 控制数据类型2的数据包流

// === DUT输入信号(Driver驱动)- 2048位数据包格式 ===
logic [2047:0] data_in; // 2048位数据 (256字节)
logic sop_in; // 数据包开始标志
logic eop_in; // 数据包结束标志
logic vld_in; // 数据有效标志
logic err_in; // 错误标志
logic rdy_in; // DUT准备接收信号(可选)

// === Monitor clocking block - 严格只读 ===
clocking mon_cb @(posedge clk);
input data_out, sop_out, eop_out, vld_out, err_out;
input type0_backpressure, type1_backpressure, type2_backpressure;
endclocking

// === Driver clocking block - 输出+读取反压 ===
clocking drv_cb @(posedge clk);
output data_in, sop_in, eop_in, vld_in, err_in;
input type0_backpressure, type1_backpressure, type2_backpressure, rdy_in;
endclocking

// === Modport定义 - 严格访问控制 ===
modport monitor(clocking mon_cb, input clk, rst_n);
modport driver(clocking drv_cb, input clk, rst_n);

// === 便利函数 - 获取反压状态数组 ===
function bit [2:0] get_backpressure_status();
return {type2_backpressure, type1_backpressure, type0_backpressure};
endfunction

// === 便利函数 - 检查特定类型反压 ===
function bit is_type_backpressure_active(int data_type);
case (data_type)
0: return type0_backpressure;
1: return type1_backpressure;
2: return type2_backpressure;
default: return 1'b1; // 未知类型默认阻塞
endcase
endfunction
endinterface

2. 增强的Transaction类定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// === 反压事务类型定义 ===
typedef enum bit [1:0] {
BP_TYPE0 = 2'b00, // 类型0反压
BP_TYPE1 = 2'b01, // 类型1反压
BP_TYPE2 = 2'b10 // 类型2反压
} bp_type_e;

// === 分类型反压事务 ===
class typed_backpressure_transaction extends uvm_sequence_item;
bp_type_e bp_type; // 反压类型
bit [1:0] affected_data_type; // 受影响的数据类型
bit backpressure_active; // 反压是否激活
realtime start_time; // 反压开始时间
realtime end_time; // 反压结束时间
int duration_ns; // 反压持续时间(ns)
bit packet_interrupted; // 是否中断了数据包传输

`uvm_object_utils_begin(typed_backpressure_transaction)
`uvm_field_enum(bp_type_e, bp_type, UVM_ALL_ON)
`uvm_field_int(affected_data_type, UVM_ALL_ON)
`uvm_field_int(backpressure_active, UVM_ALL_ON)
`uvm_field_int(duration_ns, UVM_ALL_ON)
`uvm_field_int(packet_interrupted, UVM_ALL_ON)
`uvm_object_utils_end

function new(string name = "typed_backpressure_transaction");
super.new(name);
start_time = $realtime;
packet_interrupted = 0;
endfunction
endclass

// 数据包事务 - 支持2048位宽和头部/payload分离
class my_transaction extends uvm_sequence_item;
rand bit [2047:0] data; // 完整2048位数据
rand bit sop; // 数据包开始
rand bit eop; // 数据包结束
bit vld; // 数据有效
bit err; // 错误标志
realtime timestamp;
int packet_id; // 数据包ID

// 头部相关字段(仅SOP周期有效)
rand bit [1023:0] header; // 高128字节头部 (data[2047:1024])
rand bit [1:0] data_type; // 从头部提取的数据类型
rand int payload_length; // 从头部提取的payload长度(字节)

// payload相关字段
rand bit [1023:0] sop_payload; // SOP周期的payload部分 (data[1023:0])
rand bit [2047:0] pure_payload; // 非SOP周期的纯payload数据

// 约束条件
constraint c_data_type { data_type inside {0, 1, 2}; }
constraint c_payload_length {
payload_length >= 0;
payload_length <= 65535; // 最大payload长度
}
constraint c_sop_eop {
sop == 1 || eop == 1; // 必须有一个有效周期
}

// 数据组装约束
constraint c_data_assembly {
if (sop) {
// SOP周期:高128字节是头部,低128字节是payload
data[2047:1024] == header[1023:0]; // 头部信息
data[1023:0] == sop_payload[1023:0]; // SOP的payload部分
// 从头部提取信息
data_type == extract_type_from_header(header);
payload_length == extract_length_from_header(header);
} else {
// 非SOP周期:全部256字节是payload
data == pure_payload;
}
}

`uvm_object_utils_begin(my_transaction)
`uvm_field_int(data, UVM_ALL_ON)
`uvm_field_int(sop, UVM_ALL_ON)
`uvm_field_int(eop, UVM_ALL_ON)
`uvm_field_int(vld, UVM_ALL_ON)
`uvm_field_int(err, UVM_ALL_ON)
`uvm_field_int(data_type, UVM_ALL_ON)
`uvm_field_int(packet_id, UVM_ALL_ON)
`uvm_field_int(payload_length, UVM_ALL_ON)
`uvm_object_utils_end

function new(string name = "my_transaction");
super.new(name);
timestamp = $realtime;
packet_id = -1;
payload_length = 0;
data_type = 0;
endfunction

// 辅助函数:获取头部信息
virtual function bit [1023:0] get_header();
return sop ? data[2047:1024] : 1024'h0;
endfunction

// 辅助函数:获取当前beat的payload
virtual function bit [1023:0] get_beat_payload();
return sop ? data[1023:0] : data[2047:1024]; // SOP周期取低128字节,非SOP取高128字节
endfunction

// 辅助函数:从头部提取数据类型
virtual function bit [1:0] extract_type_from_header(bit [1023:0] hdr);
return hdr[1:0]; // 假设类型在头部最低2位
endfunction

// 辅助函数:从头部提取payload长度
virtual function int extract_length_from_header(bit [1023:0] hdr);
return int'(hdr[31:2]); // 假设长度在头部bit[31:2]
endfunction

// 辅助函数:提取payload长度(从实际数据)
virtual function int get_payload_length_from_header();
bit [1023:0] hdr = get_header();
return extract_length_from_header(hdr);
endfunction

// 辅助函数:提取数据类型(从实际数据)
virtual function bit [1:0] get_data_type_from_header();
bit [1023:0] hdr = get_header();
return extract_type_from_header(hdr);
endfunction

// 辅助函数:计算当前beat的有效payload字节数
virtual function int get_valid_payload_bytes(int remaining_len);
if (sop) begin
// SOP周期:最多128字节payload
return (remaining_len > 128) ? 128 : remaining_len;
end else begin
// 非SOP周期:最多256字节payload
return (remaining_len > 256) ? 256 : remaining_len;
end
endfunction

// === 增强的辅助函数 ===

// 验证头部完整性
virtual function bit validate_header();
if (!sop) return 1; // 非SOP周期不需要验证头部

bit [1023:0] hdr = get_header();
bit [1:0] extracted_type = extract_type_from_header(hdr);
int extracted_length = extract_length_from_header(hdr);

// 验证类型合法性
if (extracted_type > 2) begin
`uvm_warning("HEADER_VALIDATION",
$sformatf("Invalid data type %0d in header", extracted_type))
return 0;
end

// 验证长度合理性
if (extracted_length < 0 || extracted_length > 65535) begin
`uvm_warning("HEADER_VALIDATION",
$sformatf("Invalid payload length %0d in header", extracted_length))
return 0;
end

return 1;
endfunction

// 计算预期的beat数量
virtual function int calculate_expected_beats();
if (payload_length <= 128) return 1; // 只需SOP beat
return 1 + ((payload_length - 128) + 255) / 256; // SOP + 后续beats
endfunction
endclass

// 数据包级别的事务(完整数据包)
class packet_transaction extends uvm_sequence_item;
rand bit [1:0] data_type;
bit has_error;
realtime start_time;
realtime end_time;
int packet_id;
int beat_count; // 数据包包含的beat数
int total_payload_length; // 实际payload总长度
int expected_payload_length; // 头部声明的payload长度
my_transaction beats[$]; // 组成数据包的所有beat

// 头部信息
bit [127:0] packet_header; // 从SOP提取的头部

// payload数据
bit [1023:0] payload_data[$]; // 重组的payload数据

`uvm_object_utils_begin(packet_transaction)
`uvm_field_int(data_type, UVM_ALL_ON)
`uvm_field_int(has_error, UVM_ALL_ON)
`uvm_field_int(packet_id, UVM_ALL_ON)
`uvm_field_int(beat_count, UVM_ALL_ON)
`uvm_field_int(total_payload_length, UVM_ALL_ON)
`uvm_field_int(expected_payload_length, UVM_ALL_ON)
`uvm_field_queue_object(beats, UVM_ALL_ON)
`uvm_object_utils_end

function new(string name = "packet_transaction");
super.new(name);
packet_id = -1;
beat_count = 0;
has_error = 0;
total_payload_length = 0;
expected_payload_length = 0;
endfunction

// 检查payload长度一致性
virtual function bit check_payload_length();
return (total_payload_length == expected_payload_length);
endfunction
endclass

第三部分:Monitor实现

2048位数据感知的Monitor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
class my_monitor extends uvm_monitor;
`uvm_component_utils(my_monitor)

virtual my_interface.monitor vif;

// Analysis Ports
uvm_analysis_port #(my_transaction) beat_ap;
uvm_analysis_port #(packet_transaction) packet_ap;
uvm_analysis_port #(typed_backpressure_transaction) typed_bp_ap;

// 数据包重组相关
packet_transaction current_packet;
int packet_id_counter = 0;
bit packet_in_progress = 0;

// 分类型反压状态跟踪 - 增强为数据包级
bit [2:0] previous_bp_states = 3'b000;
realtime bp_start_times[3];
int bp_counts[3] = '{0, 0, 0};
int bp_interrupted_packets[3] = '{0, 0, 0}; // 被反压中断的数据包计数

function new(string name, uvm_component parent);
super.new(name, parent);
beat_ap = new("beat_ap", this);
packet_ap = new("packet_ap", this);
typed_bp_ap = new("typed_bp_ap", this);
endfunction

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual my_interface)::get(this, "", "vif", vif))
`uvm_fatal(get_type_name(), "Virtual interface not found!")
endfunction

virtual task run_phase(uvm_phase phase);
wait(vif.rst_n);

fork
collect_data_transactions();
monitor_typed_backpressure();
report_statistics();
join_none
endtask

// 采集数据事务 - 支持2048位数据包格式
virtual task collect_data_transactions();
my_transaction tr;
forever begin
@(vif.mon_cb iff vif.mon_cb.vld_out); // 等待有效数据

tr = my_transaction::type_id::create("tr");
tr.data = vif.mon_cb.data_out;
tr.sop = vif.mon_cb.sop_out;
tr.eop = vif.mon_cb.eop_out;
tr.vld = vif.mon_cb.vld_out;
tr.err = vif.mon_cb.err_out;

// 如果是SOP周期,从头部提取类型和长度信息
if (tr.sop) begin
tr.data_type = tr.get_data_type_from_header();
tr.payload_length = tr.get_payload_length_from_header();
end

// 发送Beat级别事务
beat_ap.write(tr);

// 处理数据包重组
handle_packet_assembly(tr);

`uvm_info(get_type_name(),
$sformatf("Collected beat: sop=%0b, eop=%0b, type=%0d, len=%0d, data=0x%0h",
tr.sop, tr.eop, tr.data_type, tr.payload_length, tr.data[63:0]), UVM_HIGH)
end
endtask

// 数据包重组处理
virtual task handle_packet_assembly(my_transaction beat);
if (beat.sop) begin
// 数据包开始
if (packet_in_progress) begin
`uvm_warning(get_type_name(), "New packet started before previous packet ended")
// 强制结束当前数据包
finalize_current_packet(1); // 标记为错误
end

start_new_packet(beat);
end

if (packet_in_progress) begin
// 添加beat到当前数据包
current_packet.beats.push_back(beat);
current_packet.beat_count++;
beat.packet_id = current_packet.packet_id;

if (beat.err) begin
current_packet.has_error = 1;
end
end

if (beat.eop) begin
// 数据包结束
if (!packet_in_progress) begin
`uvm_warning(get_type_name(), "EOP received without SOP")
end else begin
finalize_current_packet(0);
end
end
endtask

// 开始新数据包 - 提取头部信息
virtual function void start_new_packet(my_transaction first_beat);
current_packet = packet_transaction::type_id::create("current_packet");
current_packet.packet_id = packet_id_counter++;
current_packet.start_time = $realtime;

// 从SOP周期提取头部信息
if (first_beat.sop) begin
current_packet.packet_header = first_beat.get_header();
current_packet.data_type = first_beat.get_data_type_from_header();
current_packet.expected_payload_length = first_beat.get_payload_length_from_header();

`uvm_info(get_type_name(),
$sformatf("Started packet %0d, type=%0d, expected_payload=%0d bytes",
current_packet.packet_id, current_packet.data_type,
current_packet.expected_payload_length), UVM_MEDIUM)
end

packet_in_progress = 1;
endfunction

// 完成当前数据包 - 验证payload长度
virtual function void finalize_current_packet(bit force_error = 0);
if (current_packet != null) begin
current_packet.end_time = $realtime;
if (force_error) current_packet.has_error = 1;

// 计算实际payload总长度
calculate_total_payload_length();

// 检查payload长度一致性
if (!current_packet.check_payload_length()) begin
`uvm_warning(get_type_name(),
$sformatf("Payload length mismatch in packet %0d: expected=%0d, actual=%0d",
current_packet.packet_id, current_packet.expected_payload_length,
current_packet.total_payload_length))
current_packet.has_error = 1;
end

// 发送完整数据包
packet_ap.write(current_packet);

`uvm_info(get_type_name(),
$sformatf("Completed packet %0d: %0d beats, payload %0d/%0d bytes, %s",
current_packet.packet_id, current_packet.beat_count,
current_packet.total_payload_length, current_packet.expected_payload_length,
current_packet.has_error ? "WITH ERROR" : "OK"), UVM_MEDIUM)
end

packet_in_progress = 0;
current_packet = null;
endfunction

// 计算总payload长度 - 基于2048位数据宽度
virtual function void calculate_total_payload_length();
int total_bytes = 0;
int remaining_payload = current_packet.expected_payload_length;

foreach (current_packet.beats[i]) begin
my_transaction beat = current_packet.beats[i];
int this_beat_payload;

if (beat.sop) begin
// SOP周期:只有低128字节是payload
this_beat_payload = (remaining_payload > 128) ? 128 : remaining_payload;
end else begin
// 非SOP周期:全部256字节是payload
this_beat_payload = (remaining_payload > 256) ? 256 : remaining_payload;
end

total_bytes += this_beat_payload;
remaining_payload -= this_beat_payload;
end

current_packet.total_payload_length = total_bytes;
endfunction

// 监控分类型反压信号 - 增强数据包级监控
virtual task monitor_typed_backpressure();
bit [2:0] current_bp_states;
typed_backpressure_transaction bp_tr;

forever begin
@(vif.mon_cb);

current_bp_states = {vif.mon_cb.c_backpressure,
vif.mon_cb.b_backpressure,
vif.mon_cb.a_backpressure};

// 检查每种反压信号的变化
for (int i = 0; i < 3; i++) begin
if (current_bp_states[i] !== previous_bp_states[i]) begin
bp_tr = typed_backpressure_transaction::type_id::create("bp_tr");

case (i)
0: begin
bp_tr.bp_type = typed_backpressure_transaction::TYPE_A;
bp_tr.affected_data_type = 0;
end
1: begin
bp_tr.bp_type = typed_backpressure_transaction::TYPE_B;
bp_tr.affected_data_type = 1;
end
2: begin
bp_tr.bp_type = typed_backpressure_transaction::TYPE_C;
bp_tr.affected_data_type = 2;
end
endcase

bp_tr.backpressure_active = current_bp_states[i];

if (current_bp_states[i]) begin
// 反压激活
bp_start_times[i] = $realtime;
bp_counts[i]++;

// 检查是否会影响正在传输的数据包
if (packet_in_progress && current_packet != null &&
current_packet.data_type == i) begin
`uvm_warning("BP_PACKET_IMPACT",
$sformatf("Type %s backpressure activated during packet %0d transmission",
bp_tr.bp_type.name(), current_packet.packet_id))
bp_interrupted_packets[i]++;
end

`uvm_info("TYPED_BP_MON",
$sformatf("Type %s backpressure ACTIVATED (affects data type %0d) - Packet-level control",
bp_tr.bp_type.name(), bp_tr.affected_data_type), UVM_MEDIUM)
end else begin
// 反压释放
bp_tr.duration_ns = int'(($realtime - bp_start_times[i]) / 1ns);
`uvm_info("TYPED_BP_MON",
$sformatf("Type %s backpressure RELEASED (duration: %0d ns)",
bp_tr.bp_type.name(), bp_tr.duration_ns), UVM_MEDIUM)
end

typed_bp_ap.write(bp_tr);
end
end

previous_bp_states = current_bp_states;
end
endtask

// 统计报告 - 增强数据包级统计
virtual task report_statistics();
forever begin
#10us;
`uvm_info("BP_STATS",
$sformatf("BP Events - A:%0d, B:%0d, C:%0d | Interrupted Packets - A:%0d, B:%0d, C:%0d",
bp_counts[0], bp_counts[1], bp_counts[2],
bp_interrupted_packets[0], bp_interrupted_packets[1], bp_interrupted_packets[2]), UVM_LOW)
end
endtask
endclass

第四部分:优化的智能Driver设计

数据包级反压控制的Driver - 完整优化版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)

virtual my_interface.driver vif;

// === 分类型反压控制状态 - 优化版本 ===
typedef struct {
bit active; // 当前是否激活
bit pending; // 是否等待生效
int wait_cycles; // 等待周期数
int transactions; // 已传输事务数
int blocked_count; // 被阻塞事务数
realtime last_active_time; // 最后激活时间
} bp_status_t;

bp_status_t bp_status[3]; // 三种类型的反压状态
int max_bp_wait = 1000;

// === 数据包传输状态管理 - 优化版本 ===
typedef struct {
bit in_progress; // 是否正在传输
bit [1:0] packet_type; // 当前数据包类型
int beat_count; // 当前beat计数
int expected_beats; // 预期beat总数
realtime start_time; // 传输开始时间
int packet_id; // 数据包ID
} packet_tx_status_t;

packet_tx_status_t current_tx;
int packet_id_counter = 0;

function new(string name, uvm_component parent);
super.new(name, parent);
// 初始化反压状态
for (int i = 0; i < 3; i++) begin
bp_status[i] = '{default: 0};
end
current_tx = '{default: 0};
endfunction

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual my_interface)::get(this, "", "vif", vif))
`uvm_fatal(get_type_name(), "Virtual interface not found!")
uvm_config_db#(int)::get(this, "", "max_bp_wait", max_bp_wait);
endfunction

virtual task run_phase(uvm_phase phase);
wait(vif.rst_n);
reset_signals();

fork
drive_transactions();
monitor_typed_backpressure_driver();
manage_packet_level_backpressure();
join_none
endtask

virtual task reset_signals();
vif.drv_cb.data_in <= '0;
vif.drv_cb.sop_in <= '0;
vif.drv_cb.eop_in <= '0;
vif.drv_cb.vld_in <= '0;
vif.drv_cb.err_in <= '0;
endtask

virtual task drive_transactions();
my_transaction tr;
forever begin
seq_item_port.get_next_item(tr);

// 验证事务有效性
if (!validate_transaction(tr)) begin
`uvm_error(get_type_name(), "Invalid transaction received")
seq_item_port.item_done();
continue;
end

// 从SOP周期的头部获取数据类型
bit [1:0] data_type = tr.sop ? tr.get_data_type_from_header() : current_tx.packet_type;

// === 数据包级反压检查逻辑 ===
if (tr.sop) begin
// 新数据包开始 - 检查反压和传输状态
if (can_start_new_packet(data_type)) begin
start_new_packet_transmission(tr, data_type);
drive_packet_beat(tr);
update_transmission_stats(data_type, 1);
end else begin
// 数据包被阻塞
handle_blocked_packet(tr, data_type);
continue; // 重新尝试此事务
end
end else begin
// 数据包续传 - 不检查反压,确保传输完整性
if (!current_tx.in_progress) begin
`uvm_error(get_type_name(),
"Non-SOP beat received without active packet transmission")
seq_item_port.item_done();
continue;
end

drive_packet_beat(tr);
current_tx.beat_count++;

// 检查EOP
if (tr.eop) begin
complete_packet_transmission();
end
end

seq_item_port.item_done();
end
endtask

// === 验证事务有效性 ===
virtual function bit validate_transaction(my_transaction tr);
// 验证SOP/EOP逻辑
if (tr.sop && current_tx.in_progress) begin
`uvm_warning(get_type_name(),
"SOP received while packet transmission in progress - forcing completion")
force_complete_current_transmission();
end

// 验证头部(如果是SOP)
if (tr.sop && !tr.validate_header()) begin
return 0;
end

return 1;
endfunction

// === 检查是否可以开始新数据包 ===
virtual function bit can_start_new_packet(int data_type);
// 检查传输状态
if (current_tx.in_progress) begin
`uvm_error(get_type_name(),
"Cannot start new packet - transmission already in progress");
return 0;
end

// 检查该类型的反压状态
if (bp_status[data_type].active) begin
`uvm_info(get_type_name(),
$sformatf("New packet blocked - type %0d backpressure active", data_type),
UVM_MEDIUM);
return 0;
end

return 1;
endfunction

// === 开始新数据包传输 ===
virtual function void start_new_packet_transmission(my_transaction tr, int data_type);
current_tx.in_progress = 1;
current_tx.packet_type = data_type;
current_tx.beat_count = 1;
current_tx.expected_beats = tr.calculate_expected_beats();
current_tx.start_time = $realtime;
current_tx.packet_id = packet_id_counter++;

// 向Sequencer报告数据包开始传输
m_sequencer.notify_packet_start(data_type);

// 更新Driver状态到Sequencer
my_sequencer::driver_status_t status;
status.transmission_active = 1;
status.current_type = data_type;
status.beat_count = 1;
status.start_time = $realtime;
m_sequencer.update_driver_status(status);

`uvm_info(get_type_name(),
$sformatf("Started packet %0d transmission: type=%0d, expected_beats=%0d, payload_len=%0d",
current_tx.packet_id, data_type, current_tx.expected_beats, tr.payload_length),
UVM_MEDIUM)
endfunction

// === 完成数据包传输 ===
virtual function void complete_packet_transmission();
realtime duration = $realtime - current_tx.start_time;

`uvm_info(get_type_name(),
$sformatf("Completed packet %0d: type=%0d, %0d/%0d beats, duration=%.1f ns",
current_tx.packet_id, current_tx.packet_type,
current_tx.beat_count, current_tx.expected_beats, duration / 1ns),
UVM_MEDIUM)

// 验证beat数量
if (current_tx.beat_count != current_tx.expected_beats) begin
`uvm_warning(get_type_name(),
$sformatf("Beat count mismatch: expected %0d, actual %0d",
current_tx.expected_beats, current_tx.beat_count))
end

// 重置传输状态
current_tx.in_progress = 0;

// 应用等待生效的反压
apply_pending_backpressures();
endfunction

// === 处理被阻塞的数据包 ===
virtual function void handle_blocked_packet(my_transaction tr, int data_type);
bp_status[data_type].blocked_count++;

`uvm_info(get_type_name(),
$sformatf("Packet blocked: type=%0d (total blocked: %0d)",
data_type, bp_status[data_type].blocked_count), UVM_MEDIUM)

// 将事务放回队列等待重试
seq_item_port.put_response(tr);
endfunction

// === 应用等待生效的反压 ===
virtual function void apply_pending_backpressures();
for (int i = 0; i < 3; i++) begin
if (bp_status[i].pending) begin
bp_status[i].active = 1;
bp_status[i].pending = 0;
bp_status[i].last_active_time = $realtime;

`uvm_info(get_type_name(),
$sformatf("Applied pending backpressure for type %0d", i), UVM_MEDIUM)
end
end
endfunction

// === 监控分类型反压信号 - 完全优化版本 ===
virtual task monitor_typed_backpressure_driver();
bit [2:0] current_signals, previous_signals = 3'b000;

forever begin
@(vif.drv_cb);
current_signals = vif.get_backpressure_status();

// 检查每种反压信号的变化
for (int i = 0; i < 3; i++) begin
if (current_signals[i] !== previous_signals[i]) begin
handle_backpressure_change(i, current_signals[i]);
end
end

previous_signals = current_signals;
end
endtask

// === 处理反压状态变化 ===
virtual function void handle_backpressure_change(int type_idx, bit new_state);
if (new_state) begin
// 反压激活
if (current_tx.in_progress && current_tx.packet_type == type_idx) begin
// 正在传输该类型数据包,标记为待生效
bp_status[type_idx].pending = 1;
`uvm_info(get_type_name(),
$sformatf("Type %0d backpressure PENDING (packet %0d in transmission)",
type_idx, current_tx.packet_id), UVM_MEDIUM)
end else begin
// 立即生效
bp_status[type_idx].active = 1;
bp_status[type_idx].last_active_time = $realtime;
`uvm_info(get_type_name(),
$sformatf("Type %0d backpressure ACTIVATED immediately", type_idx), UVM_MEDIUM)
end
end else begin
// 反压释放
bp_status[type_idx].active = 0;
bp_status[type_idx].pending = 0;
`uvm_info(get_type_name(),
$sformatf("Type %0d backpressure RELEASED", type_idx), UVM_MEDIUM)
end
endfunction

// === 更新传输统计 ===
virtual function void update_transmission_stats(int data_type, bit success);
if (success) begin
bp_status[data_type].transactions++;
end
endfunction

// === 强制完成当前传输(错误恢复) ===
virtual function void force_complete_current_transmission();
if (current_tx.in_progress) begin
`uvm_warning(get_type_name(),
$sformatf("Force completing packet %0d transmission", current_tx.packet_id))
current_tx.in_progress = 0;
apply_pending_backpressures();
end
endfunction

virtual function void report_phase(uvm_phase phase);
`uvm_info(get_type_name(),
"=== Enhanced Driver Statistics by Data Type ===", UVM_LOW)

for (int i = 0; i < 3; i++) begin
real block_rate = (bp_status[i].transactions > 0) ?
real'(bp_status[i].blocked_count) * 100.0 /
(bp_status[i].transactions + bp_status[i].blocked_count) : 0.0;

`uvm_info(get_type_name(),
$sformatf("Type %0d: %0d sent, %0d blocked (%.1f%%), %0d BP wait cycles",
i, bp_status[i].transactions, bp_status[i].blocked_count,
block_rate, bp_status[i].wait_cycles), UVM_LOW)
end

`uvm_info(get_type_name(),
"=== Packet-Level Backpressure Benefits ===", UVM_LOW)
`uvm_info(get_type_name(),
"✓ Zero packet fragmentation - complete transmission guaranteed", UVM_LOW)
`uvm_info(get_type_name(),
"✓ Perfect SOP/EOP alignment - no boundary corruption", UVM_LOW)
`uvm_info(get_type_name(),
"✓ Optimal DUT performance - full packet processing", UVM_LOW)
`uvm_info(get_type_name(),
"✓ Minimal retransmission overhead - smart pending mechanism", UVM_LOW)
endfunction
endclass

第五部分:数据包序列生成

2048位头部感知的序列生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 精确payload长度的序列 - 支持2048位数据宽度
class exact_payload_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(exact_payload_sequence)

rand bit [1:0] packet_type;
rand int exact_payload_bytes;

constraint c_packet_type { packet_type inside {0, 1, 2}; }
constraint c_payload_bytes { exact_payload_bytes inside {[50:4000]}; } // 更大范围

function new(string name = "exact_payload_sequence");
super.new(name);
endfunction

virtual task body();
my_transaction tr;
int remaining_bytes = exact_payload_bytes;
int beat_count = 0;

// 计算需要的beat数
int total_beats = 1; // 至少需要SOP beat
if (exact_payload_bytes > 128) begin
// 需要额外的非SOP beat
total_beats += ((exact_payload_bytes - 128) + 255) / 256; // 向上取整
end

while (remaining_bytes > 0) begin
tr = my_transaction::type_id::create($sformatf("beat_%0d", beat_count));
start_item(tr);

if (beat_count == 0) begin
// SOP周期:构造头部和部分payload
bit [1023:0] constructed_header = 1024'h0;
constructed_header[1:0] = packet_type; // 设置类型
constructed_header[31:2] = exact_payload_bytes; // 设置长度

assert(tr.randomize() with {
sop == 1;
eop == (remaining_bytes <= 128);
header == constructed_header;
data_type == packet_type;
payload_length == exact_payload_bytes;
});

remaining_bytes -= (remaining_bytes > 128) ? 128 : remaining_bytes;
end else begin
// 后续周期:纯payload
int this_beat_payload = (remaining_bytes > 256) ? 256 : remaining_bytes;
assert(tr.randomize() with {
sop == 0;
eop == (remaining_bytes <= 256);
data_type == packet_type;
});
remaining_bytes -= this_beat_payload;
end

finish_item(tr);
beat_count++;
end

`uvm_info(get_type_name(),
$sformatf("Generated exact payload packet: type=%0d, %0d bytes, %0d beats",
packet_type, exact_payload_bytes, beat_count), UVM_LOW)
endtask
endclass

// 大payload数据包序列
class large_payload_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(large_payload_sequence)

rand bit [1:0] packet_type;
rand int large_payload_bytes;

constraint c_packet_type { packet_type inside {0, 1, 2}; }
constraint c_payload_bytes {
large_payload_bytes inside {[1000:10000]}; // 1KB-10KB大包
}

function new(string name = "large_payload_sequence");
super.new(name);
endfunction

virtual task body();
my_transaction tr;
int remaining_bytes = large_payload_bytes;
int beat_count = 0;

while (remaining_bytes > 0) begin
tr = my_transaction::type_id::create($sformatf("large_beat_%0d", beat_count));
start_item(tr);

if (beat_count == 0) begin
// SOP周期
bit [1023:0] large_header = 1024'h0;
large_header[1:0] = packet_type;
large_header[31:2] = large_payload_bytes;
// 可以在头部添加更多信息,如时间戳、序列号等
large_header[63:32] = $urandom(); // 随机时间戳

assert(tr.randomize() with {
sop == 1;
eop == (remaining_bytes <= 128);
header == large_header;
data_type == packet_type;
payload_length == large_payload_bytes;
});

remaining_bytes -= (remaining_bytes > 128) ? 128 : remaining_bytes;
end else begin
// 非SOP周期
assert(tr.randomize() with {
sop == 0;
eop == (remaining_bytes <= 256);
data_type == packet_type;
});

int this_beat_payload = (remaining_bytes > 256) ? 256 : remaining_bytes;
remaining_bytes -= this_beat_payload;
end

finish_item(tr);
beat_count++;
end

`uvm_info(get_type_name(),
$sformatf("Generated large payload packet: type=%0d, %0d bytes, %0d beats",
packet_type, large_payload_bytes, beat_count), UVM_LOW)
endtask
endclass

第六部分:UVM验证环境架构图与流程图

📊 UVM验证环境分层架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
┌─────────────────────────────────────────────────────────────────────────────────┐
│ UVM验证环境分层架构 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ TEST LAYER (测试层) ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ ┃ │
│ ┃ │ Light Traffic │ │ Medium Traffic │ │ Heavy Traffic │ │ Stress Test │ ┃ │
│ ┃ │ Test │ │ Test │ │ Test │ │ │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ • 轻载场景 │ │ • 中载场景 │ │ • 重载场景 │ │ • 极限测试 │ ┃ │
│ ┃ │ • 基础功能 │ │ • 混合流量 │ │ • 高频反压 │ │ • 错误注入 │ ┃ │
│ ┃ │ • 反压验证 │ │ • 负载均衡 │ │ • 性能验证 │ │ • 边界条件 │ ┃ │
│ ┃ └─────────────────┘ └─────────────────┘ └─────────────────┘ └──────────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ ENVIRONMENT LAYER (环境层) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────────────────┐ ┌─────────────────────────────┐ ┃ │
│ ┃ │ Data Agent │ │ Backpressure Agent │ ┃ │
│ ┃ │ ┌─────────────────────────┐ │ │ ┌─────────────────────────┐ │ ┃ │
│ ┃ │ │ Monitor │ │ │ │ BP Controller │ │ ┃ │
│ ┃ │ │ • Beat采集 │ │ │ │ • 随机反压 │ │ ┃ │
│ ┃ │ │ • Packet重组 │ │ │ │ • 周期反压 │ │ ┃ │
│ ┃ │ │ • 反压状态监控 │ │ │ │ • 突发反压 │ │ ┃ │
│ ┃ │ │ • 统计分析 │ │ │ │ • 自适应控制 │ │ ┃ │
│ ┃ │ └─────────────────────────┘ │ │ └─────────────────────────┘ │ ┃ │
│ ┃ │ │ └─────────────────────────────┘ ┃ │
│ ┃ │ ┌─────────────────────────┐ │ ┃ │
│ ┃ │ │ Sequencer │◄┼──────────────┐ ┃ │
│ ┃ │ │ • 反压状态桥梁 │ │ │ ┃ │
│ ┃ │ │ • 性能统计管理 │ │ │ ┃ │
│ ┃ │ │ • Driver状态跟踪 │ │ │ ┃ │
│ ┃ │ │ • 负载均衡算法 │ │ │ ┃ │
│ ┃ │ └─────────────────────────┘ │ │ ┃ │
│ ┃ │ ▲ │ │ ┃ │
│ ┃ │ ┌─────────┴─────────┐ │ │ ┃ │
│ ┃ │ │ Driver │ │ │ ┃ │
│ ┃ │ │ • 数据包级反压 │ │ │ ┃ │
│ ┃ │ │ • SOP/EOP对齐 │ │ │ ┃ │
│ ┃ │ │ • Pending机制 │ │ │ ┃ │
│ ┃ │ │ • 状态反馈 │ │ │ ┃ │
│ ┃ │ └───────────────────┘ │ │ ┃ │
│ ┃ └─────────────────────────────┘ │ ┃ │
│ ┃ │ ┃ │
│ ┃ ┌─────────────────────────────────────────────┼─────────────────────────┐ ┃ │
│ ┃ │ Scoreboard & Checker │ │ ┃ │
│ ┃ │ • 数据完整性检查 │ │ ┃ │
│ ┃ │ • 反压行为验证 │ │ ┃ │
│ ┃ │ • 性能指标统计 │ │ ┃ │
│ ┃ │ • 错误检测报告 │ │ ┃ │
│ ┃ └─────────────────────────────────────────────┘ │ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ INTERFACE LAYER (接口层) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────────────────┐ ┌─────────────────────────────────────┐ ┃ │
│ ┃ │ 2048位数据接口 │ │ 反压控制接口 │ ┃ │
│ ┃ │ ┌─────────────────────────┐ │ │ ┌─────────────────────────────────┐ │ ┃ │
│ ┃ │ │ data[2047:0] │ │ │ │ type0_backpressure │ │ ┃ │
│ ┃ │ │ sop/eop │ │ │ │ type1_backpressure │ │ ┃ │
│ ┃ │ │ vld/err │ │ │ │ type2_backpressure │ │ ┃ │
│ ┃ │ │ ───────────────────────│ │ │ │ ───────────────────────────────│ │ ┃ │
│ ┃ │ │ • 256字节宽度 │ │ │ │ • 分类型独立控制 │ │ ┃ │
│ ┃ │ │ • SOP:头部+Payload │ │ │ │ • 数据包级生效 │ │ ┃ │
│ ┃ │ │ • 非SOP:纯Payload │ │ │ │ • Pending延迟机制 │ │ ┃ │
│ ┃ │ └─────────────────────────┘ │ │ └─────────────────────────────────┘ │ ┃ │
│ ┃ └─────────────────────────────┘ └─────────────────────────────────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ DUT LAYER (设计层) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐ ┃ │
│ ┃ │ Ingress │────▶│ Packet Engine │────▶│ Egress │ ┃ │
│ ┃ │ │ │ │ │ │ ┃ │
│ ┃ │ • Header │ │ • 类型识别处理 │ │ • 输出缓冲控制 │ ┃ │
│ ┃ │ Parsing │ │ • Payload处理 │ │ • 反压信号生成 │ ┃ │
│ ┃ │ • Type │ │ • 错误检测 │ │ • SOP/EOP生成 │ ┃ │
│ ┃ │ Extract │ │ • 流量控制 │ │ • Valid信号控制 │ ┃ │
│ ┃ │ • Length │ │ • 性能监控 │ │ • 错误传播 │ ┃ │
│ ┃ │ Validate │ │ │ │ • 基于类型的流控制 │ ┃ │
│ ┃ └─────────────┘ └─────────────────┘ └─────────────────────────────┘ ┃ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘

🔄 Sequence控制激励产生流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Sequence激励控制核心流程 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ START │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ SEQUENCE CONTROL CENTER ┃ │
│ ┃ (激励控制中心) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────┐ ┃ │
│ ┃ │ 系统状态分析 │ │ 智能决策引擎 │ │ 激励策略执行 │ │ 性能优化 │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌──────┐ │ ┃ │
│ ┃ │ │反压状态[3:0]│ │ │ │ 保守模式 │ │ │ │数据包生成 │ │ │ │自适应│ │ ┃ │
│ ┃ │ │ type0: ● │ │ │ │ • 低风险 │ │ │ │• Type0小包 │ │ │ │速率 │ │ ┃ │
│ ┃ │ │ type1: ○ │ │ │ │ • 稳定优先 │ │ │ │• Type1中包 │ │ │ │调整 │ │ ┃ │
│ ┃ │ │ type2: ● │ │ │ └─────────────┘ │ │ │• Type2大包 │ │ │ └──────┘ │ ┃ │
│ ┃ │ └─────────────┘ │ │ ┌─────────────┐ │ │ └─────────────┘ │ │ │ ┃ │
│ ┃ │ ┌─────────────┐ │ │ │ 平衡模式 │ │ │ ┌─────────────┐ │ │ ┌──────┐ │ ┃ │
│ ┃ │ │吞吐率统计 │ │ │ │ • 负载均衡 │ │ │ │时序控制 │ │ │ │负载 │ │ ┃ │
│ ┃ │ │Type0: 45pps │ │ │ │ • 性能优化 │ │ │ │• 发送间隔 │ │ │ │均衡 │ │ ┃ │
│ ┃ │ │Type1: 32pps │ │ │ └─────────────┘ │ │ │• 优先级 │ │ │ └──────┘ │ ┃ │
│ ┃ │ │Type2: 28pps │ │ │ ┌─────────────┐ │ │ └─────────────┘ │ │ │ ┃ │
│ ┃ │ └─────────────┘ │ │ │ 激进模式 │ │ │ ┌─────────────┐ │ │ │ ┃ │
│ ┃ │ ┌─────────────┐ │ │ │ • 高吞吐量 │ │ │ │错误处理 │ │ │ │ ┃ │
│ ┃ │ │队列状态 │ │ │ │ • 压力测试 │ │ │ │• 重试机制 │ │ │ │ ┃ │
│ ┃ │ │Pending[3] │ │ │ └─────────────┘ │ │ │• 降级策略 │ │ │ │ ┃ │
│ ┃ │ │[5, 3, 8] │ │ │ │ │ └─────────────┘ │ │ │ ┃ │
│ ┃ │ └─────────────┘ └─────────────────┘ └─────────────────┘ └──────────┘ ┃ │
│ ┃ └─────────────────┘ ┃ │
│ ┃ │ │ │ ┃ │
│ ┃ ▼ ▼ ▼ ┃ │
│ ┃ ┌─────────────────────────────────────────────────────────────────────┐ ┃ │
│ ┃ │ 决策输出与控制命令 │ ┃ │
│ ┃ │ • 选择发送类型: Type1 (负载最轻) │ ┃ │
│ ┃ │ • 数据包大小: 1024 bytes │ ┃ │
│ ┃ │ • 发送时机: 立即发送 │ ┃ │
│ ┃ │ • 优先级: 中等 │ ┃ │
│ ┃ │ • 控制命令: start_item() → 子sequence调用 → finish_item() │ ┃ │
│ ┃ └─────────────────────────────────────────────────────────────────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ▼ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ SEQUENCER BRIDGE ┃ │
│ ┃ (状态桥梁) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────┐ ┃ │
│ ┃ │ 反压状态跟踪 │ │ 性能统计管理 │ │ Driver状态管理 │ │ 通信接口 │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ • BP信号监控 │ │ • 实时吞吐率 │ │ • 传输状态跟踪 │ │ • Mon→Seq │ ┃ │
│ ┃ │ • 状态变化通知 │ │ • 延迟统计 │ │ • 完成/阻塞报告 │ │ • Drv→Seq │ ┃ │
│ ┃ │ • 历史记录维护 │ │ • 负载均衡计算 │ │ • 错误状态反馈 │ │ • Seq→Drv │ ┃ │
│ ┃ │ • 趋势分析 │ │ • 性能告警 │ │ • 资源使用统计 │ │ • 状态同步│ ┃ │
│ ┃ └─────────────────┘ └─────────────────┘ └─────────────────┘ └──────────┘ ┃ │
│ ┃ ▲ ▲ ▲ ▲ ┃ │
│ ┃ │ │ │ │ ┃ │
│ ┃ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┃ │
│ ┃ │ Monitor │ │Performance│ │ Driver │ │ Control │ ┃ │
│ ┃ │ Feedback │ │ Metrics │ │ Feedback │ │ Interface │ ┃ │
│ ┃ └───────────┘ └───────────┘ └───────────┘ └───────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ▼ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ DRIVER RESPONSE ┃ │
│ ┃ (响应执行) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────┐ ┃ │
│ ┃ │ 事务接收处理 │ │ 数据包级反压控制│ │ 信号驱动执行 │ │ 状态反馈 │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ • get_next_item │ │ • SOP反压检查 │ │ • 接口信号驱动 │ │ • 完成通知│ ┃ │
│ ┃ │ • 事务验证 │ │ • 传输中不中断 │ │ • 时序控制 │ │ • 阻塞报告│ ┃ │
│ ┃ │ • 类型解析 │ │ • EOP后应用BP │ │ • clk edge同步 │ │ • 错误上报│ ┃ │
│ ┃ │ • 有效性检查 │ │ • Pending机制 │ │ • valid控制 │ │ • 统计更新│ ┃ │
│ ┃ └─────────────────┘ └─────────────────┘ └─────────────────┘ └──────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ INTERFACE │ │
│ │ ┌─────────────────────────┐ ┌─────────────────────────────────────┐ │ │
│ │ │ Data Signals │ │ Backpressure Signals │ │ │
│ │ │ data[2047:0] sop eop │◄────▶│ type0_backpressure type1_backpressure type2_backpressure │ │ │
│ │ │ vld err ready │ │ (由DUT产生,影响Sequence决策) │ │ │
│ │ └─────────────────────────┘ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ DUT │ │
│ │ ┌───────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐ │ │
│ │ │ Ingress │ │ Packet Engine │ │ Egress │ │ │
│ │ │ • Header解析 │ │ • 类型识别处理 │ │ • 输出缓冲控制 │ │ │
│ │ │ • 数据验证 │ │ • Payload处理 │ │ • 反压信号生成 │ │ │
│ │ │ • 流量控制 │ │ • 错误检测 │ │ • SOP/EOP生成 │ │ │
│ │ └───────────────┘ └─────────────────┘ └─────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘

⚙️ 数据包级反压控制机制详图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 数据包级反压控制时序图 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 时间线: ──────────────────────────────────────────────────────────────────────▶ │
│ │
│ Sequence ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ 激励控制 │Pkt-A│ │Pkt-B│ │Pkt-C│ │Pkt-D│ │Pkt-E│ │
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ │
│ Sequencer ┌─────────────────────────────────────────────────────────────────┐ │
│ 状态管理 │ BP Status: [0,1,0] → [1,1,0] → [1,1,0] → [0,1,0] → [0,0,0] │ │
│ │ Queue Len: [2,5,3] → [1,6,3] → [0,7,3] → [0,6,2] → [1,5,2] │ │
│ │ Decision: Send-A Block-B Block-C Send-D Send-E │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ │
│ Driver ┌─SOP─┐ ┌─Wait─┐ ┌─Wait─┐ ┌─SOP─┐ ┌─SOP─┐ │
│ 响应执行 │beat1│ │ ing │ │ ing │ │beat1│ │beat1│ │
│ ┌┴beat2┴┐ │ │ │ │ ┌┴beat2┴┐ ┌┴beat2┴┐ │
│ │ beat3 │ │ │ │ │ │ beat3 │ │ EOP │ │
│ └──EOP──┘ └──────┘ └──────┘ └──EOP──┘ └──────┘ │
│ │
│ 反压信号 type0_bp: ────────┬─────────────────────────┬───────────── │
│ (来自DUT) │ ████████████████████ │ │
│ └─────────────────────────┘ │
│ type1_bp: ─────────────┬───────────────────────────────────── │
│ │ ████████████████████████████████ │
│ └───────────────────────────────────── │
│ type2_bp: ───────────────────────────────────────────────────── │
│ │
│ 关键机制说明: │
│ 🔹 SOP检查: 只在数据包开始时检查反压状态 │
│ 🔹 传输保护: 数据包传输过程中绝不中断 │
│ 🔹 Pending应用: 反压在当前数据包EOP后才生效 │
│ 🔹 智能重试: 被阻塞的数据包自动重新调度 │
│ │
│ 数据包完整性保证: │
│ ✅ Pkt-A: Type0, 正常传输 (SOP→...→EOP) │
│ ❌ Pkt-B: Type1, 被反压阻塞,等待重试 │
│ ❌ Pkt-C: Type1, 仍被阻塞,继续等待 │
│ ✅ Pkt-D: Type0, 反压解除后正常传输 │
│ ✅ Pkt-E: Type2, 所有反压解除,正常传输 │
└─────────────────────────────────────────────────────────────────────────────────┘

🎯 Sequence决策算法流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Sequence智能决策算法 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ 激励请求到达 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ SEQUENCE CONTROL CENTER ┃ │
│ ┃ (激励控制中心) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────┐ ┃ │
│ ┃ │ 系统状态分析 │ │ 智能决策引擎 │ │ 激励策略执行 │ │ 性能优化 │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌──────┐ │ ┃ │
│ ┃ │ │反压状态[3:0]│ │ │ │ 保守模式 │ │ │ │数据包生成 │ │ │ │自适应│ │ ┃ │
│ ┃ │ │ type0: ● │ │ │ │ • 低风险 │ │ │ │• Type0小包 │ │ │ │速率 │ │ ┃ │
│ ┃ │ │ type1: ○ │ │ │ │ • 稳定优先 │ │ │ │• Type1中包 │ │ │ │调整 │ │ ┃ │
│ ┃ │ │ type2: ● │ │ │ └─────────────┘ │ │ │• Type2大包 │ │ │ └──────┘ │ ┃ │
│ ┃ │ └─────────────┘ │ │ ┌─────────────┐ │ │ └─────────────┘ │ │ │ ┃ │
│ ┃ │ ┌─────────────┐ │ │ │ 平衡模式 │ │ │ ┌─────────────┐ │ │ ┌──────┐ │ ┃ │
│ ┃ │ │吞吐率统计 │ │ │ │ • 负载均衡 │ │ │ │时序控制 │ │ │ │负载 │ │ ┃ │
│ ┃ │ │Type0: 45pps │ │ │ │ • 性能优化 │ │ │ │• 发送间隔 │ │ │ │均衡 │ │ ┃ │
│ ┃ │ │Type1: 32pps │ │ │ └─────────────┘ │ │ │• 优先级 │ │ │ └──────┘ │ ┃ │
│ ┃ │ │Type2: 28pps │ │ │ ┌─────────────┐ │ │ └─────────────┘ │ │ │ ┃ │
│ ┃ │ └─────────────┘ │ │ │ 激进模式 │ │ │ ┌─────────────┐ │ │ │ ┃ │
│ ┃ │ ┌─────────────┐ │ │ │ • 高吞吐量 │ │ │ │错误处理 │ │ │ │ ┃ │
│ ┃ │ │队列状态 │ │ │ │ • 压力测试 │ │ │ │• 重试机制 │ │ │ │ ┃ │
│ ┃ │ │Pending[3] │ │ │ └─────────────┘ │ │ │• 降级策略 │ │ │ │ ┃ │
│ ┃ │ │[5, 3, 8] │ │ │ │ │ └─────────────┘ │ │ │ ┃ │
│ ┃ │ └─────────────┘ └─────────────────┘ └─────────────────┘ └──────────┘ ┃ │
│ ┃ └─────────────────┘ ┃ │
│ ┃ │ │ │ ┃ │
│ ┃ ▼ ▼ ▼ ┃ │
│ ┃ ┌─────────────────────────────────────────────────────────────────────┐ ┃ │
│ ┃ │ 决策输出与控制命令 │ ┃ │
│ ┃ │ • 选择发送类型: Type1 (负载最轻) │ ┃ │
│ ┃ │ • 数据包大小: 1024 bytes │ ┃ │
│ ┃ │ • 发送时机: 立即发送 │ ┃ │
│ ┃ │ • 优先级: 中等 │ ┃ │
│ ┃ │ • 控制命令: start_item() → 子sequence调用 → finish_item() │ ┃ │
│ ┃ └─────────────────────────────────────────────────────────────────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ▼ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ SEQUENCER BRIDGE ┃ │
│ ┃ (状态桥梁) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────┐ ┃ │
│ ┃ │ 反压状态跟踪 │ │ 性能统计管理 │ │ Driver状态管理 │ │ 通信接口 │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ • BP信号监控 │ │ • 实时吞吐率 │ │ • 传输状态跟踪 │ │ • Mon→Seq │ ┃ │
│ ┃ │ • 状态变化通知 │ │ • 延迟统计 │ │ • 完成/阻塞报告 │ │ • Drv→Seq │ ┃ │
│ ┃ │ • 历史记录维护 │ │ • 负载均衡计算 │ │ • 错误状态反馈 │ │ • Seq→Drv │ ┃ │
│ ┃ │ • 趋势分析 │ │ • 性能告警 │ │ • 资源使用统计 │ │ • 状态同步│ ┃ │
│ ┃ └─────────────────┘ └─────────────────┘ └─────────────────┘ └──────────┘ ┃ │
│ ┃ ▲ ▲ ▲ ▲ ┃ │
│ ┃ │ │ │ │ ┃ │
│ ┃ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┃ │
│ ┃ │ Monitor │ │Performance│ │ Driver │ │ Control │ ┃ │
│ ┃ │ Feedback │ │ Metrics │ │ Feedback │ │ Interface │ ┃ │
│ ┃ └───────────┘ └───────────┘ └───────────┘ └───────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │ │
│ ▼ │
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ ┃ DRIVER RESPONSE ┃ │
│ ┃ (响应执行) ┃ │
│ ┃ ┃ │
│ ┃ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────┐ ┃ │
│ ┃ │ 事务接收处理 │ │ 数据包级反压控制│ │ 信号驱动执行 │ │ 状态反馈 │ ┃ │
│ ┃ │ │ │ │ │ │ │ │ ┃ │
│ ┃ │ • get_next_item │ │ • SOP反压检查 │ │ • 接口信号驱动 │ │ • 完成通知│ ┃ │
│ ┃ │ • 事务验证 │ │ • 传输中不中断 │ │ • 时序控制 │ │ • 阻塞报告│ ┃ │
│ ┃ │ • 类型解析 │ │ • EOP后应用BP │ │ • clk edge同步 │ │ • 错误上报│ ┃ │
│ ┃ │ • 有效性检查 │ │ • Pending机制 │ │ • valid控制 │ │ • 统计更新│ ┃ │
│ ┃ └─────────────────┘ └─────────────────┘ └─────────────────┘ └──────────┘ ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ INTERFACE │ │
│ │ ┌─────────────────────────┐ ┌─────────────────────────────────────┐ │ │
│ │ │ Data Signals │ │ Backpressure Signals │ │ │
│ │ │ data[2047:0] sop eop │◄────▶│ type0_backpressure type1_backpressure type2_backpressure │ │ │
│ │ │ vld err ready │ │ (由DUT产生,影响Sequence决策) │ │ │
│ │ └─────────────────────────┘ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ DUT │ │
│ │ ┌───────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐ │ │
│ │ │ Ingress │ │ Packet Engine │ │ Egress │ │ │
│ │ │ • Header解析 │ │ • 类型识别处理 │ │ • 输出缓冲控制 │ │ │
│ │ │ • 数据验证 │ │ • Payload处理 │ │ • 反压信号生成 │ │ │
│ │ │ • 流量控制 │ │ • 错误检测 │ │ • SOP/EOP生成 │ │ │
│ │ └───────────────┘ └─────────────────┘ └─────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘