-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.cc
523 lines (441 loc) · 22.9 KB
/
router.cc
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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
/*
* router.cc
*
* Created on: 2016年7月30日
* Author: Vincent
*
* Function:
* 路由器:输入缓存,虚通道,虚通道仲裁(Round Robin),交叉开关仲裁(Round Robin),交叉开关传输
* 数据包:Flit形式,Flit长度可调(根据Head Flit决定)
*/
#include "router.h"
Router::Router(){
selfMsgAlloc=nullptr;
}
Router::~Router(){
cancelAndDelete(selfMsgAlloc);
}
void Router::initialize()
{
//对Buffer进行初始化
for(int i = 0; i < PortNum; i++) {
SAInputWinVcid[i] = -1;
SAOutputWin[i] = -1;
for(int j = 0; j < VC; j++) {
for(int k = 0; k < OutBufferDepth; k++) {
OutputBuffer[i][j][k] = nullptr;
}
RCInputVCState[i][j] = -1;
BufferConnectCredit[i][j] = BufferDepth;
VAOutputVCState[i][j] = -1;
VAOutputVCStatePre[i][j] = -1;
VAInputVCState[i][j] = false;
//InputVCFlitCount[i][j] = 0;
for(int k = 0; k < BufferDepth; k++){
InputBuffer[i][j][k] = nullptr;
}
}
}
//对selfMsg进行初始化
selfMsgAlloc = new cMessage("selfMsgAlloc");
scheduleAt(Sim_Start_Time, selfMsgAlloc);
RouterPower = 0;
flitReceived = 0;
t_start_h = t_end_h = t_max_h = t_start_r = t_end_r = t_max_r = 0;
t_handleMessage = 0;
t_router = 0;
t_totalTime = clock();
}
void Router::handleMessage(cMessage *msg)
{
t_start_h = clock();
if (msg->isSelfMessage()) {
//****************仲裁定时****************************
if(msg == selfMsgAlloc){//自消息为仲裁定时消息
scheduleAt(simTime()+CLK_CYCLE, selfMsgAlloc);
//Step 2. Routing Logic
//计算每个packet的输出端口及输出vcid
for(int i = 0; i < PortNum; i++) {
for(int j = 0; j < VC; j++) {
DataPkt* current_pkt = InputBuffer[i][j][0];
//InputBuffer队头的Pkt还没有经过Routing Computing,-1代表还没RC过
if(current_pkt != nullptr && current_pkt->getIsHead() == true && RCInputVCState[i][j] == -1) { //数据包有可能阻塞在队头
RCInputVCState[i][j] = getPortAndVCID(current_pkt);
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 2. Routing Computation >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), INPORT: "<<i<<
", INPORT VCID: "<<j<<", Routing Result: OUTPORT: "<<RCInputVCState[i][j]/VC<<
", OUTPUT VCID: "<<RCInputVCState[i][j]%VC<<", Msg: { "<<InputBuffer[i][j][0]<<" }\n";
}
}
}
}
//开始对部分模块进行计时
t_start_r = clock();
//Step 3. Virtual Channel Allocation
//每一个输出端口的每一个virtual channel要对每个输入端口的每个virtual channel进行仲裁,只有一个胜利
//外循环,对每个output virtual channel进行循环
for(int i = 0; i < PortNum; i++) {
for(int j = 0; j < VC; j++) {
//内循环,对每个input virtual channel进行判断
//注意:加了OutputBuffer后,tail flit数据送到outputBuffer后一定要释放VAOutputVCState,输出虚通道状态寄存器要释放
if(VAOutputVCState[i][j] >= 0) continue; //若输出端口vc已被分配,则跳过下面循环
bool flag = false;
int port_vc = VAOutputVCStatePre[i][j] + 1;
int count = 0, total = PortNum * VC;
for(; count < total && flag == false; count++, port_vc++) {
int m = (port_vc / VC) % PortNum;
int n = port_vc % VC;
if(RCInputVCState[m][n] == i * VC + j) {//该输入虚通道里面的数据一定是head flit, 否则上面if语句会跳过
if(VAInputVCState[m][n] == true) {
EV << "Error: Step 3. VC Allocation >> ROUTER: " << getIndex()<<"("<<swpid2swlid(getIndex()) << "), VAInputVCState != false" << endl;
}
VAInputVCState[m][n] = true; //该虚通道仲裁胜利
VAOutputVCStatePre[i][j] = m * VC + n;
VAOutputVCState[i][j] = m * VC + n;
flag = true;
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 3. VC Allocation >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), WIN INPORT: "<<m<<
", WIN INPORT VCID: "<<n<<", OUTPORT: "<<i<<
", OUTPORT VCID: "<<j<<", Win Msg: { "<<InputBuffer[m][n][0]<<" }\n";
}
}
}
}
}
//Step 4. Switch Arbitration
//在VAInputVCState中为true的输入vc中做选择,而且其对应的输出端口的vc的buffer必须为空,能够容纳它
//4.1. 输入端口仲裁
for(int i = 0; i < PortNum; i++) {
int last_vcid = SAInputWinVcid[i] + 1;
bool flag = false;
for(int j = 0; j < VC && flag == false; j++, last_vcid++) {
int cur_vcid = last_vcid % VC; //Round Robin
//必须保证输入虚通道在虚通道仲裁中胜利(即输出虚通道为此输入虚通道保留)
//此外还需要保证输入buffer有数据,可能head flit传输胜利,但是body flit还没过来
if(VAInputVCState[i][cur_vcid] == true && InputBuffer[i][cur_vcid][0] != nullptr) { //之前写成InputBuffer[i][cur_vcid] != nullptr,查了3天,泪崩,需要判断输入buffer是否有数据,可能堵在前一跳路由器
int port = RCInputVCState[i][cur_vcid] / VC;
int out_vcid = RCInputVCState[i][cur_vcid] % VC;
if(OutputBuffer[port][out_vcid][OutBufferDepth-1] == nullptr) { //判断输出buffer有空间
SAInputWinVcid[i] = cur_vcid;
flag = true;
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 4.1 Switch Allocation, Input Port Stage >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), INPORT: "<<i<<
", WIN VCID: "<<cur_vcid<<
", Win Msg: { "<<InputBuffer[i][cur_vcid][0]<<" }\n";
}
}
}
}
if(flag == false) {
SAInputWinVcid[i] = -1; //没有合适的虚通道
}
}
//4.2. 输出端口仲裁
for(int i = 0; i < PortNum; i++) {
//内循环,对每一个输入端口判断是否请求该输出端口
int last_inport = SAOutputWin[i] + 1; //Round Robin
bool flag = false;
for(int j = 0; j < PortNum && flag == false; j++, last_inport++) {
int cur_inport = last_inport % PortNum;
//SAInputWinVcid[cur_inport] != -1保证输入有数据,输出有buffer
if(SAInputWinVcid[cur_inport] != -1) {
int inport_vcid = SAInputWinVcid[cur_inport];
int out_port = RCInputVCState[cur_inport][inport_vcid] / VC;
if(out_port == i) {
SAOutputWin[i] = cur_inport;
flag = true;
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 4.2 Switch Allocation, Output Port Stage >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), OUTPORT: "<<i<<
", WIN INPORT: "<<cur_inport<<" }\n";
}
}
}
}
if(flag == false) {
SAOutputWin[i] = -1; //仲裁失败
}
}
//Step 5. Switch Traversal
//交叉开关传输,传输完数据后必须把相关的状态reset,传输完的标志是把输入buffer中的tail flit传输到输出buffer中
//pkt从输入buffer到输出buffer需要改变pkt中的vcid,改为下一跳路由器输入buffer的vcid(和这一跳路由器输出的vcid相同)
for(int i = 0; i < PortNum; i++) {
if(SAOutputWin[i] == -1) continue;
int inport = SAOutputWin[i];
int inport_vcid = SAInputWinVcid[inport];
int output_vcid = RCInputVCState[inport][inport_vcid] % VC;
DataPkt* current_pkt = InputBuffer[inport][inport_vcid][0];
//有可能body flit还没传输过来,导致current_pkt == nullptr
//可能有bug
if(current_pkt == nullptr) {
EV << "Error in Step 5. Switch Traversal in Router " << getIndex() << ", current_pkt is null" << endl;
continue;
}
//修改VCID
current_pkt->setVc_id(output_vcid);
//对输入缓存进行shift
for(int j = 0; j < BufferDepth - 1; j++){
InputBuffer[inport][inport_vcid][j] = InputBuffer[inport][inport_vcid][j+1];
}
InputBuffer[inport][inport_vcid][BufferDepth-1] = nullptr;
//将数据放到输出buffer
if(OutputBuffer[i][output_vcid][OutBufferDepth-1] != nullptr) {
EV << "Error in Step 5. Switch Traversal in Router, OutputBuffer != nullptr " << getIndex() << ", current_pkt is null" << endl;
}
OutputBuffer[i][output_vcid][OutBufferDepth-1] = current_pkt;
//每转发input buffer里面的一个flit,就产生一个流控信号,通知上游router,进行increment credit操作
//先将bufferInfoMsg放入Queue中,由于和Data Pkt共用一个信道,容易发生阻塞,需要队列保存数据
int from_port = getNextRouterPort(inport);
BufferInfoMsg* bufferInfoMsg = new BufferInfoMsg("bufferInfoMsg");
bufferInfoMsg->setFrom_port(from_port);
bufferInfoMsg->setVcid(inport_vcid);
bufTxQueue[inport].insert(bufferInfoMsg);
//判断是否为tail flit,如果是,则重置寄存器状态
if(current_pkt->getIsTail() == true) {
RCInputVCState[inport][inport_vcid] = -1;
VAInputVCState[inport][inport_vcid] = false;
if(Verbose >= VERBOSE_DETAIL_DEBUG_MESSAGES) {
EV << "In Router: " << getIndex() << "(" << swpid2swlid(getIndex()) << "), VCA Input: Inport: "
<< inport << ", vcid: " << inport_vcid << ", is released" << endl;
}
}
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 5. Switch Traversal >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), OUTPORT: "<<i<<
", OUTPORT VCID: "<<output_vcid<<", INPORT: "<<inport<<
", INPORT VCID: "<<inport_vcid<<", InputBuffer: { "<< current_pkt << " }" << '\n';
}
}
//结束部分模块的计时
t_end_r = clock();
if (simTime().dbl() > RecordStartTime) {
if(t_end_r - t_start_r > t_max_r) {
t_max_r = t_end_r - t_start_r;
}
t_router += t_end_r - t_start_r;
}
//Step 6. Forward Data Message
//发送数据,需要检查信道是否空闲以及
for(int i = 0; i < PortNum; i++) {
if(channelAvailTime(i) <= simTime()) {
bool flag = false;
for(int j = 0; j < VC && flag == false; j++) {
if(OutputBuffer[i][j][0] != nullptr && BufferConnectCredit[i][j] != 0) {
flag = true;
DataPkt* forward_msg = OutputBuffer[i][j][0];
//对流控信息寄存器进行操作
OutputBuffer[i][j][0] = nullptr;
if(!connectToProcessor(i)) { //与路由器相连
BufferConnectCredit[i][j]--;
}
//判断是否为tail
//注意,outputBuffer的入口位置有空闲的时候,就需要重置寄存器状态,这样就可以进行下一轮的虚通道仲裁
// if(forward_msg->getIsTail() == true) {
// VAOutputVCState[i][j] = -1;
// if(Verbose >= VERBOSE_DETAIL_DEBUG_MESSAGES) {
// EV << "In Router: " << getIndex() << "(" << swpid2swlid(getIndex()) << "), VCA Output: Output: "
// << i << ", vcid: " << j << ", is released" << endl;
// }
// }
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 6. Forward Message >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), OUTPORT: "<<i<<
", OUTPORT VCID: "<<j<<", Forward Pkt: { " <<forward_msg<<" }" <<'\n';
}
//发送pkt数据
forwardMessage(forward_msg, i);
}
}
}
}
//Step 7. Forward bufferInfoMsg Message
for(int i = 0; i < PortNum; i++) {
if(bufTxQueue[i].isEmpty() || channelAvailTime(i) > simTime()) continue;
BufferInfoMsg* bufferInfoMsg = (BufferInfoMsg*) bufTxQueue[i].front();
bufTxQueue[i].pop(); //注意,先pop再发送
//发送bufferInfoMsg
forwardBufferInfoMsg(bufferInfoMsg, i);
}
//Step 8. Shift OutputBuffer
for(int i = 0; i < PortNum; i++) {
for(int j = 0; j < VC; j++) {
for(int k = 0; k < OutBufferDepth; k++) {
if(OutputBuffer[i][j][k] != nullptr && k > 0 && OutputBuffer[i][j][k-1] == nullptr) {
if (k == OutBufferDepth - 1 && OutputBuffer[i][j][k]->getIsTail() == true) {
VAOutputVCState[i][j] = -1;
if(Verbose >= VERBOSE_DETAIL_DEBUG_MESSAGES) {
EV << "In Router: " << getIndex() << "(" << swpid2swlid(getIndex()) << "), VCA Output: Output: "
<< i << ", vcid: " << j << ", is released" << endl;
}
}
OutputBuffer[i][j][k-1] = OutputBuffer[i][j][k];
OutputBuffer[i][j][k] = nullptr;
}
}
}
}
} // end of selfMsgAlloc
} // end of selfMsg
else{ //非自消息,即收到其他路由器的消息
//*************************收到其他端口buffer更新消息************************
if(strcmp("bufferInfoMsg", msg->getName()) == 0){
//收到的消息为buffer状态消息,更新BufferConnectCredit[PortNum][VC]
BufferInfoMsg* bufferInfoMsg = check_and_cast<BufferInfoMsg*>(msg);
int from_port = bufferInfoMsg->getFrom_port();
int vcid = bufferInfoMsg->getVcid();
BufferConnectCredit[from_port][vcid]++;
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Receiving bufferInfoMsg >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), INPORT: "<<from_port<<
", Received MSG: { "<<bufferInfoMsg<<" }\n";
EV<<"BufferConnectCredit["<<from_port<<"]["<<vcid<<"]="<<BufferConnectCredit[from_port][vcid]<<"\n";
}
delete bufferInfoMsg;
}else{
//**********************收到其他端口的DataPkt数据消息*******************
DataPkt *datapkt = check_and_cast<DataPkt*>(msg);
if (simTime().dbl() > RecordStartTime) {
flitReceived += 1;
}
//Step 1. Input Buffer
//决定放到哪个input port的virtual channel
int input_port = datapkt->getFrom_router_port();
int vc_id = datapkt->getVc_id();
//由于有流控机制的存在,上一跳路由器向该路由器发送FatTreePkt时,buffer一定有容量来保存数据
for(int i = 0; i < BufferDepth; i++){
if(InputBuffer[input_port][vc_id][i] == nullptr){
InputBuffer[input_port][vc_id][i] = datapkt;
break;
}
}
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV<<"Step 1. Input Buffer >> ROUTER: "<<getIndex()<<"("<<swpid2swlid(getIndex())<<"), INPORT: "<<input_port<<
", VCID: "<<vc_id<<", Received MSG: { "<<datapkt<<" }\n";
}
}//end of DataPkt
} // end of Not self msg
t_end_h = clock();
if (simTime().dbl() > RecordStartTime) {
if(t_end_h - t_start_h > t_max_h) {
t_max_h = t_end_h - t_start_h;
}
t_handleMessage += t_end_h - t_start_h;
}
}
//调用...计算路由端口
void Router::forwardMessage(DataPkt *msg, int out_port_id)
{
// Increment hop count.
msg->setHopCount(msg->getHopCount()+1);
//int k=calRoutePort(msg);//计算发出msg的端口号
int k = out_port_id;
char str1[20]="port_";
char str2[20];
sprintf(str2, "%d", k);
strcat(str1,str2);
strcat(str1,"$o");
//EV<<"k="<<k<<" str1="<<str1<<" str2="<<str2<<"\n";
msg->setFrom_router_port(getNextRouterPort(k));//设置接受该msg的Router的port端口号
send(msg,str1);
int cur_swpid=getIndex();//当前路由器的id
int cur_swlid=swpid2swlid(cur_swpid);
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV << "Forwarding message { " << msg << " } from router "<<cur_swpid<<"("<<cur_swlid<<")"<< " through port "<<k<<"\n";
}
}
void Router::forwardBufferInfoMsg(BufferInfoMsg *msg, int out_port_id){
int k = out_port_id;
char str1[20]="port_";
char str2[20];
sprintf(str2, "%d", k);
strcat(str1,str2);
strcat(str1,"$o");
//EV<<"k="<<k<<" str1="<<str1<<" str2="<<str2<<"\n";
msg->setFrom_port(getNextRouterPort(k));//设置接受该msg的Router的port端口号
send(msg,str1);
int cur_swpid=getIndex();//当前路由器的id
int cur_swlid=swpid2swlid(cur_swpid);
if (Verbose >= VERBOSE_DEBUG_MESSAGES) {
EV << "Forwarding BufferInfoMsg { " << msg << " } from router "<<cur_swpid<<"("<<cur_swlid<<")"<< " through port "<<k<<"\n";
}
}
int Router::getPortAndVCID(DataPkt* msg) {
int port = calRoutePort(msg);
int best_vcid = 0;
for(int i = 0; i < VC; i++){
if(BufferConnectCredit[port][i] > BufferConnectCredit[port][best_vcid]){
best_vcid = i;
}
}
//return value port * VC + vcid
return port * VC + best_vcid;
}
int Router::getNextRouterAvailVCID(int port_num){
int vc_id = intuniform(0,VC-1); //随机分配一个通道,以此vc开始循环判断是否有空的vc,增加随机分布,防止每次都从0开始
for(int i=0;i<VC;i++){
int vcid_tmp = (vc_id + i)%VC;
if(BufferConnectCredit[port_num][vcid_tmp] != 0){
return vcid_tmp;
}
}
return -1;
}
simtime_t Router::channelAvailTime(int port_num) {
int k = port_num;
char str1[20] = "port_";
char str2[20];
sprintf(str2, "%d", k);
strcat(str1, str2);
strcat(str1, "$o");
cChannel* txChannel = gate(str1)->getTransmissionChannel();
simtime_t txFinishTime = txChannel->getTransmissionFinishTime();
return txFinishTime;
}
double Router::getRouterPower() {
double timeCount = simTime().dbl() - Sim_Start_Time;
double clockCount = timeCount / CLK_CYCLE; //时钟周期数
double TR = flitReceived / (PortNum * clockCount);
//recordScalar("TR", );
//instances
int XBAR_insts = PortNum * PortNum * FlitWidth;
int SWVC_insts = 9 * ((pow(PortNum,2) * VC * VC) + pow(PortNum,2) + (PortNum * VC) - PortNum);
int INBUF_insts = 180 * PortNum * VC + 2 * PortNum * VC * BufferDepth * FlitWidth + 2* PortNum *
PortNum * VC * BufferDepth + 3 * PortNum * VC * BufferDepth + 5 * PortNum * PortNum
* BufferDepth + PortNum * PortNum + PortNum * FlitWidth + 15 * PortNum;
int OUTBUF_insts = 25 * PortNum + 80 * PortNum * VC;
int CLKCTRL_insts = 0.02 * (SWVC_insts + INBUF_insts + OUTBUF_insts);
//leakage power
double XBAR_leakage_power = MUX2_leak_nW * XBAR_insts;
double SWVC_leakage_power = ((6*NOR_leak_nW + 2*INV_leak_nW + DFF_leak_nW)/9)* SWVC_insts;
double INBUF_leakage_power = ((AOI_leak_nW + DFF_leak_nW)/2) * INBUF_insts;
double OUTBUF_leakage_power = ((AOI_leak_nW + DFF_leak_nW)/2) * OUTBUF_insts;
double CLKCTRL_leakage_power = ((AOI_leak_nW + INV_leak_nW)/2) * CLKCTRL_insts;
//internal power
double XBAR_internal_power = MUX2_int_J * TR * XBAR_insts;
double SWVC_internal_power = (6*NOR_int_J + 2*INV_int_J + DFF_int_J) * TR * SWVC_insts;
double INBUF_internal_power = (AOI_int_J + DFF_int_J) * .5 * (INBUF_insts * TR + .05 * INBUF_insts);
double OUTBUF_internal_power = (AOI_int_J + DFF_int_J) * .5 * (OUTBUF_insts * TR + .05 * OUTBUF_insts);
double CLKCTRL_internal_power = (AOI_int_J + INV_int_J) * CLKCTRL_insts * TR;
//switching power
double XBAR_switching_power = 0.5 * 1.4 * MUX2_load_pF * VDD * VDD * TR * FREQ;
double SWVC_switching_power = 0.5 *1.4 * (NOR_load_pF + INV_load_pF + DFF_load_pF) * VDD * VDD * FREQ * SWVC_insts * TR;
double INBUF_switching_power = 0.5 *1.4 * VDD * VDD * FREQ * .5 * (INBUF_insts * TR * AOI_load_pF + .05 * INBUF_insts * DFF_load_pF);
double OUTBUF_switching_power = 0.5 *1.4 * VDD * VDD * FREQ * .5 * (OUTBUF_insts * TR * AOI_load_pF + .05 * OUTBUF_insts * DFF_load_pF);
double CLKCTRL_switching_power = .5 * 1.4 *(INV_load_pF + AOI_load_pF) * VDD * VDD * FREQ * CLKCTRL_insts * TR;
double p_leakage = 1e-6 * (XBAR_leakage_power + SWVC_leakage_power + INBUF_leakage_power + OUTBUF_leakage_power + CLKCTRL_leakage_power);
double p_internal = XBAR_internal_power + SWVC_internal_power + INBUF_internal_power + OUTBUF_internal_power + CLKCTRL_internal_power;
double p_switching = 1e-9 * (XBAR_switching_power + SWVC_switching_power + INBUF_switching_power + OUTBUF_switching_power + CLKCTRL_switching_power);
double p_total = p_leakage + p_internal + p_switching;
return p_total;
}
void Router::finish()
{
// This function is called by OMNeT++ at the end of the simulation.
double routerPower = getRouterPower();
EV <<"Router power: " << routerPower <<endl;
recordScalar("routerPower", routerPower);
if(getIndex() == 0) {
t_totalTime = clock() - t_totalTime;
recordScalar("realTotalTime", t_totalTime * 1.0 / CLOCKS_PER_SEC); // 单位是s
}
recordScalar("realTotalHandleMessageTime", t_handleMessage * 1.0 / CLOCKS_PER_SEC);
recordScalar("realRouterTime", t_router * 1.0 / CLOCKS_PER_SEC);
recordScalar("realMaxHandleMessagetime", t_max_h * 1.0 / CLOCKS_PER_SEC);
recordScalar("realMaxRouterTime", t_max_r * 1.0 / CLOCKS_PER_SEC);
}