1 |
48 |
alirezamon |
#ifndef NETRACE_LIB_H
|
2 |
|
|
#define NETRACE_LIB_H
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
#include "netrace-1.0/queue.h"
|
6 |
|
|
#include "netrace-1.0/netrace.h"
|
7 |
|
|
#include "netrace-1.0/queue.c"
|
8 |
|
|
#include "netrace-1.0/netrace.c"
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
extern int reset,clk;
|
12 |
|
|
extern char simulation_done;
|
13 |
|
|
extern void connect_clk_reset_start_all(void);
|
14 |
|
|
extern void sim_eval_all (void);
|
15 |
|
|
extern void topology_connect_all_nodes (void);
|
16 |
|
|
extern Vpck_inj *pck_inj[NE];
|
17 |
|
|
extern unsigned int count_en;
|
18 |
|
|
extern unsigned long int main_time; // Current simulation time
|
19 |
|
|
extern int verbosity;
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
#define L2_LATENCY 8
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
int ignore_dependencies = 0;
|
28 |
|
|
int start_region = 0;
|
29 |
|
|
int reader_throttling = 0;
|
30 |
|
|
unsigned long long int nt_cycle=0;
|
31 |
|
|
unsigned long long int nt_start_cycle=0;
|
32 |
|
|
|
33 |
|
|
nt_header_t* header;
|
34 |
|
|
queue_t** waiting;
|
35 |
|
|
queue_t** inject;
|
36 |
|
|
queue_t** traverse;
|
37 |
|
|
nt_packet_t* trace_packet = NULL;
|
38 |
|
|
nt_packet_t* packet = NULL;
|
39 |
|
|
int nt_packets_left = 0;
|
40 |
|
|
|
41 |
|
|
|
42 |
|
|
int netrace_to_pronoc_map [64];
|
43 |
|
|
int pronoc_to_netrace_map [NE];
|
44 |
|
|
int pck_injct_in_pck_wr[NE];
|
45 |
|
|
|
46 |
|
|
unsigned int nt_total_rd_pck=0; // from trace file
|
47 |
|
|
unsigned int read_done=0;
|
48 |
|
|
|
49 |
|
|
typedef struct queue_node queue_node_t;
|
50 |
|
|
struct queue_node {
|
51 |
|
|
nt_packet_t* packet;
|
52 |
|
|
unsigned long long int cycle;
|
53 |
|
|
};
|
54 |
|
|
|
55 |
|
|
|
56 |
|
|
unsigned long long int calc_packet_timing( nt_packet_t* packet ) {
|
57 |
|
|
|
58 |
|
|
int n_hops = abs( packet->src - packet->dst );
|
59 |
|
|
if( n_hops <= 0 ) n_hops = 1;
|
60 |
|
|
return 3*n_hops;
|
61 |
|
|
}
|
62 |
|
|
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
void netrace_init( char * tracefile){
|
66 |
|
|
int i=0;
|
67 |
|
|
nt_open_trfile( tracefile );
|
68 |
|
|
if( ignore_dependencies ) {
|
69 |
|
|
nt_disable_dependencies();
|
70 |
|
|
printf("\tDependencies is turned off in tracking cleared packets list\n");
|
71 |
|
|
}
|
72 |
|
|
if( reader_throttling ) {
|
73 |
|
|
printf("\treader throttling is enabled\n");
|
74 |
|
|
}
|
75 |
|
|
nt_print_trheader();
|
76 |
|
|
header = nt_get_trheader();
|
77 |
|
|
nt_seek_region( &header->regions[start_region] );
|
78 |
|
|
for(i = 0; i < start_region; i++ ) {
|
79 |
|
|
nt_cycle += header->regions[i].num_cycles;
|
80 |
|
|
}
|
81 |
|
|
if(nt_cycle){
|
82 |
|
|
printf("\tThe simulation start at region %u and %llu cycle\n",start_region,nt_cycle);
|
83 |
|
|
nt_start_cycle=nt_cycle;
|
84 |
|
|
}
|
85 |
|
|
|
86 |
|
|
waiting = (queue_t**) malloc( header->num_nodes * sizeof(queue_t*) );
|
87 |
|
|
inject = (queue_t**) malloc( header->num_nodes * sizeof(queue_t*) );
|
88 |
|
|
traverse = (queue_t**) malloc( header->num_nodes * sizeof(queue_t*) );
|
89 |
|
|
if( (waiting == NULL) || (inject == NULL) || (traverse == NULL) ) {
|
90 |
|
|
printf( "ERROR: malloc fail queues\n" );
|
91 |
|
|
exit(0);
|
92 |
|
|
}
|
93 |
|
|
for( i = 0; i < header->num_nodes; ++i ) {
|
94 |
|
|
waiting[i] = queue_new();
|
95 |
|
|
inject[i] = queue_new();
|
96 |
|
|
traverse[i] = queue_new();
|
97 |
|
|
}
|
98 |
|
|
|
99 |
|
|
if( !reader_throttling ) {
|
100 |
|
|
trace_packet = nt_read_packet();
|
101 |
|
|
} else if( !ignore_dependencies ) {
|
102 |
|
|
nt_init_self_throttling();
|
103 |
|
|
}
|
104 |
|
|
|
105 |
|
|
MIN_PACKET_SIZE = (8*8)/Fpay;
|
106 |
|
|
MAX_PACKET_SIZE = (64*8)/Fpay;
|
107 |
|
|
AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size
|
108 |
|
|
int p=(MAX_PACKET_SIZE-MIN_PACKET_SIZE)+1;
|
109 |
|
|
rsv_size_array = (unsigned int*) calloc ( p , sizeof(int));
|
110 |
|
|
if (rsv_size_array==NULL){
|
111 |
|
|
fprintf(stderr,"ERROR: cannot allocate (%d x int) memory for rsv_size_array. \n",p);
|
112 |
|
|
exit(1);
|
113 |
|
|
}
|
114 |
|
|
|
115 |
|
|
|
116 |
|
|
if(verbosity==1) printf("\e[?25l"); //To hide the cursor:
|
117 |
|
|
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
|
121 |
|
|
|
122 |
|
|
|
123 |
|
|
void netrace_eval(unsigned int eval_num){
|
124 |
|
|
int i;
|
125 |
|
|
|
126 |
|
|
if((reset==1) || (count_en==0)) return;
|
127 |
|
|
|
128 |
|
|
if((( nt_cycle > header->num_cycles) || (read_done==1 )) && nt_packets_left==0 ) simulation_done=1;
|
129 |
|
|
|
130 |
|
|
// Reset packets remaining check
|
131 |
|
|
nt_packets_left = 0;
|
132 |
|
|
|
133 |
|
|
// Get packets for this cycle
|
134 |
|
|
if((end_sim_pck_num == 0 ) || (end_sim_pck_num > nt_total_rd_pck )){
|
135 |
|
|
if( reader_throttling ) {
|
136 |
|
|
nt_packet_list_t* list;
|
137 |
|
|
for( list = nt_get_cleared_packets_list(); list != NULL; list = list->next ) {
|
138 |
|
|
if( list->node_packet != NULL ) {
|
139 |
|
|
trace_packet = list->node_packet;
|
140 |
|
|
queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) );
|
141 |
|
|
new_node->packet = trace_packet;
|
142 |
|
|
new_node->cycle = (trace_packet->cycle > nt_cycle) ? trace_packet->cycle : nt_cycle;
|
143 |
|
|
queue_push( inject[trace_packet->src], new_node, new_node->cycle );
|
144 |
|
|
nt_total_rd_pck++;
|
145 |
|
|
} else {
|
146 |
|
|
printf( "ERROR: Malformed packet list" );
|
147 |
|
|
exit(-1);
|
148 |
|
|
}
|
149 |
|
|
}
|
150 |
|
|
nt_empty_cleared_packets_list();
|
151 |
|
|
} else {
|
152 |
|
|
while( (trace_packet != NULL) && (trace_packet->cycle == nt_cycle) ) {
|
153 |
|
|
// Place in appropriate queue
|
154 |
|
|
queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) );
|
155 |
|
|
new_node->packet = trace_packet;
|
156 |
|
|
new_node->cycle = (trace_packet->cycle > nt_cycle) ? trace_packet->cycle : nt_cycle;
|
157 |
|
|
if( ignore_dependencies || nt_dependencies_cleared( trace_packet ) ) {
|
158 |
|
|
// Add to inject queue
|
159 |
|
|
queue_push( inject[trace_packet->src], new_node, new_node->cycle );
|
160 |
|
|
nt_total_rd_pck++;
|
161 |
|
|
} else {
|
162 |
|
|
// Add to waiting queue
|
163 |
|
|
queue_push( waiting[trace_packet->src], new_node, new_node->cycle );
|
164 |
|
|
nt_total_rd_pck++;
|
165 |
|
|
}
|
166 |
|
|
// Get another packet from trace
|
167 |
|
|
trace_packet = nt_read_packet();
|
168 |
|
|
}
|
169 |
|
|
if( (trace_packet != NULL) && (trace_packet->cycle < nt_cycle) ) {
|
170 |
|
|
// Error check: Crash and burn
|
171 |
|
|
printf( "ERROR: Invalid trace_packet cycle time: %llu, current cycle: %llu\n", trace_packet->cycle, nt_cycle );
|
172 |
|
|
exit(-1);
|
173 |
|
|
}
|
174 |
|
|
}
|
175 |
|
|
}else {//if ~end_sim_pck_num
|
176 |
|
|
read_done=1;
|
177 |
|
|
}
|
178 |
|
|
|
179 |
|
|
if(eval_num<netrace_speed_up-1) {
|
180 |
|
|
nt_cycle++;
|
181 |
|
|
nt_packets_left=1;
|
182 |
|
|
return;
|
183 |
|
|
}
|
184 |
|
|
|
185 |
|
|
|
186 |
|
|
// Inject where possible (max one per node)
|
187 |
|
|
for( i = 0; i < header->num_nodes; ++i ) {
|
188 |
|
|
nt_packets_left |= !queue_empty( inject[i] );
|
189 |
|
|
//TODO define RRA if multiple netrace sources are mapped to one node. only one can sent packt at each cycle
|
190 |
|
|
int pronoc_src = netrace_to_pronoc_map[i];
|
191 |
|
|
//TODO define sent vc policy
|
192 |
|
|
int sent_vc = 0;
|
193 |
|
|
|
194 |
|
|
if(pck_inj[pronoc_src]->pck_injct_in_pck_wr){
|
195 |
|
|
//the wr_pck should be asserted only for single cycle
|
196 |
|
|
pck_inj[pronoc_src]->pck_injct_in_pck_wr = 0;
|
197 |
|
|
continue;
|
198 |
|
|
}
|
199 |
|
|
|
200 |
|
|
pck_inj[pronoc_src]->pck_injct_in_pck_wr = 0;
|
201 |
|
|
if((pck_inj[pronoc_src]->pck_injct_out_ready & (0x1<<sent_vc)) == 0){
|
202 |
|
|
//This pck injector is not ready yet
|
203 |
|
|
continue;
|
204 |
|
|
}
|
205 |
|
|
|
206 |
|
|
queue_node_t* temp_node = (queue_node_t*) queue_peek_front( inject[i] );
|
207 |
|
|
if( temp_node != NULL ) {
|
208 |
|
|
packet = temp_node->packet;
|
209 |
|
|
if( (packet != NULL) && (temp_node->cycle <= nt_cycle) ) {
|
210 |
|
|
|
211 |
|
|
if(verbosity>1) {
|
212 |
|
|
printf( "Inject: %llu ", nt_cycle );
|
213 |
|
|
nt_print_packet( packet );
|
214 |
|
|
}
|
215 |
|
|
temp_node = (queue_node_t*) queue_pop_front( inject[i] );
|
216 |
|
|
temp_node->cycle = nt_cycle;//injection time
|
217 |
|
|
queue_push( traverse[packet->dst], temp_node, temp_node->cycle );
|
218 |
|
|
long int ptr_addr = reinterpret_cast<long int> (temp_node);
|
219 |
|
|
int flit_num = (nt_get_packet_size(packet)* 8) / Fpay;
|
220 |
|
|
if(flit_num< pck_inj[pronoc_src]->min_pck_size) flit_num = pck_inj[pronoc_src]->min_pck_size;
|
221 |
|
|
int pronoc_dst = netrace_to_pronoc_map[packet->dst];
|
222 |
|
|
if(IS_SELF_LOOP_EN ==0){
|
223 |
|
|
if(packet->dst == pronoc_src ){
|
224 |
|
|
fprintf(stderr,"ERROR: ProNoC is not configured with self-loop enable and Netrace aims to inject\n a "
|
225 |
|
|
"packet with identical source and destination address. Enable the SELF_LOOP parameter\n"
|
226 |
|
|
"in ProNoC and rebuild the simulation model\n");
|
227 |
|
|
exit(1);
|
228 |
|
|
}
|
229 |
|
|
}
|
230 |
|
|
unsigned int sent_class =0;
|
231 |
|
|
pck_inj[pronoc_src]->pck_injct_in_data = ptr_addr;
|
232 |
|
|
pck_inj[pronoc_src]->pck_injct_in_size = flit_num;
|
233 |
|
|
pck_inj[pronoc_src]->pck_injct_in_endp_addr = endp_addr_encoder(pronoc_dst);
|
234 |
|
|
pck_inj[pronoc_src]->pck_injct_in_class_num = sent_class;
|
235 |
|
|
pck_inj[pronoc_src]->pck_injct_in_init_weight = 1;
|
236 |
|
|
pck_inj[pronoc_src]->pck_injct_in_vc = 0x1<<sent_vc;
|
237 |
|
|
pck_inj[pronoc_src]->pck_injct_in_pck_wr = 1;
|
238 |
|
|
total_sent_pck_num++;
|
239 |
|
|
|
240 |
|
|
#if (C>1)
|
241 |
|
|
sent_stat[pronoc_src][sent_class].pck_num ++;
|
242 |
|
|
sent_stat[pronoc_src][sent_class].flit_num +=flit_num;
|
243 |
|
|
#else
|
244 |
|
|
sent_stat[pronoc_src].pck_num ++;
|
245 |
|
|
sent_stat[pronoc_src].flit_num +=flit_num;
|
246 |
|
|
#endif
|
247 |
|
|
}
|
248 |
|
|
}
|
249 |
|
|
}
|
250 |
|
|
|
251 |
|
|
/*
|
252 |
|
|
// Step all network components, Eject where possible
|
253 |
|
|
for( i = 0; i < header->num_nodes; ++i ) {
|
254 |
|
|
nt_packets_left |= !queue_empty( traverse[i] );
|
255 |
|
|
queue_node_t* temp_node = (queue_node_t*) queue_peek_front( traverse[i] );
|
256 |
|
|
if( temp_node != NULL ) {
|
257 |
|
|
packet = temp_node->packet;
|
258 |
|
|
if( (packet != NULL) && (temp_node->cycle <= nt_cycle) ) {
|
259 |
|
|
printf( "Eject: %llu ", nt_cycle );
|
260 |
|
|
nt_print_packet( packet );
|
261 |
|
|
nt_clear_dependencies_free_packet( packet );
|
262 |
|
|
temp_node = (queue_node_t*) queue_pop_front( traverse[i] );
|
263 |
|
|
free( temp_node );
|
264 |
|
|
}
|
265 |
|
|
}
|
266 |
|
|
}
|
267 |
|
|
*/
|
268 |
|
|
|
269 |
|
|
// Step all network components, Eject where possible
|
270 |
|
|
for( i = 0; i < NE; ++i ) {
|
271 |
|
|
nt_packets_left |= !queue_empty( traverse[i] );
|
272 |
|
|
//check which pck injector got a packet
|
273 |
|
|
if(pck_inj[i]->pck_injct_out_pck_wr==0) continue;
|
274 |
|
|
//we have got a packet
|
275 |
|
|
//printf( "data=%lx\n",pck_inj[i]->pck_injct_out_data);
|
276 |
|
|
|
277 |
|
|
queue_node_t* temp_node = (queue_node_t*) pck_inj[i]->pck_injct_out_data;
|
278 |
|
|
if( temp_node != NULL ) {
|
279 |
|
|
packet = temp_node->packet;
|
280 |
|
|
if( packet != NULL){
|
281 |
|
|
if(verbosity>1) {
|
282 |
|
|
printf( "Eject: %llu ", nt_cycle );
|
283 |
|
|
nt_print_packet( packet );
|
284 |
|
|
}
|
285 |
|
|
// remove from traverse
|
286 |
|
|
nt_clear_dependencies_free_packet( packet );
|
287 |
|
|
queue_remove( traverse[i], temp_node );
|
288 |
|
|
unsigned long long int clk_num_h2t= (nt_cycle - temp_node->cycle)/netrace_speed_up;
|
289 |
|
|
unsigned int clk_num_h2h= clk_num_h2t - pck_inj[i]->pck_injct_out_h2t_delay;
|
290 |
|
|
/*
|
291 |
|
|
printf("clk_num_h2t (%llu) h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay);
|
292 |
|
|
if(clk_num_h2t < pck_inj[i]->pck_injct_out_h2t_delay){
|
293 |
|
|
fprintf(stderr, "ERROR:clk_num_h2t (%llu) is smaller than injector h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay);
|
294 |
|
|
exit(1);
|
295 |
|
|
}
|
296 |
|
|
*/
|
297 |
|
|
update_statistic_at_ejection (
|
298 |
|
|
i,// core_num
|
299 |
|
|
clk_num_h2h, // clk_num_h2h,
|
300 |
|
|
(unsigned int) clk_num_h2t, // clk_num_h2t,
|
301 |
|
|
pck_inj[i]->pck_injct_out_distance, // distance,
|
302 |
|
|
pck_inj[i]->pck_injct_out_class_num,// class_num,
|
303 |
|
|
packet->src// unsigned int src
|
304 |
|
|
);
|
305 |
|
|
#if(C>1)
|
306 |
|
|
rsvd_stat[i][pck_inj[i]->pck_injct_out_class_num].flit_num +=pck_inj[i]->pck_injct_out_size;
|
307 |
|
|
#else
|
308 |
|
|
rsvd_stat[i].flit_num+=pck_inj[i]->pck_injct_out_size;
|
309 |
|
|
#endif
|
310 |
|
|
free( temp_node );
|
311 |
|
|
|
312 |
|
|
}
|
313 |
|
|
}
|
314 |
|
|
}
|
315 |
|
|
// Check for cleared dependences... or not
|
316 |
|
|
if( !reader_throttling ) {
|
317 |
|
|
for( i = 0; i < header->num_nodes; ++i ) {
|
318 |
|
|
nt_packets_left |= !queue_empty( waiting[i] );
|
319 |
|
|
node_t* temp = waiting[i]->head;
|
320 |
|
|
while( temp != NULL ) {
|
321 |
|
|
queue_node_t* temp_node = (queue_node_t*) temp->elem;
|
322 |
|
|
packet = temp_node->packet;
|
323 |
|
|
temp = temp->next;
|
324 |
|
|
if( nt_dependencies_cleared( packet ) ) {
|
325 |
|
|
// remove from waiting
|
326 |
|
|
queue_remove( waiting[i], temp_node );
|
327 |
|
|
// add to inject
|
328 |
|
|
queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) );
|
329 |
|
|
new_node->packet = packet;
|
330 |
|
|
new_node->cycle = nt_cycle + L2_LATENCY;
|
331 |
|
|
queue_push( inject[i], new_node, new_node->cycle );
|
332 |
|
|
free( temp_node );
|
333 |
|
|
}
|
334 |
|
|
}
|
335 |
|
|
}
|
336 |
|
|
}
|
337 |
|
|
nt_cycle++;
|
338 |
|
|
}
|
339 |
|
|
|
340 |
|
|
|
341 |
|
|
void netrace_posedge_event(){
|
342 |
|
|
unsigned int i;
|
343 |
|
|
clk = 1; // Toggle clock
|
344 |
|
|
for(i=0;i<netrace_speed_up; i++) netrace_eval(i);
|
345 |
|
|
connect_clk_reset_start_all();
|
346 |
|
|
sim_eval_all();
|
347 |
|
|
//print total sent packet each 1024 clock cycles
|
348 |
|
|
if(verbosity==1) if(nt_cycle&0x3FF) printf("\rTotal sent packet: %9d", total_sent_pck_num);
|
349 |
|
|
}
|
350 |
|
|
|
351 |
|
|
|
352 |
|
|
void netrace_clk_negedge_event( ){
|
353 |
|
|
int i;
|
354 |
|
|
clk = 0;
|
355 |
|
|
topology_connect_all_nodes ();
|
356 |
|
|
connect_clk_reset_start_all();
|
357 |
|
|
sim_eval_all();
|
358 |
|
|
|
359 |
|
|
}
|
360 |
|
|
|
361 |
|
|
|
362 |
|
|
|
363 |
|
|
|
364 |
|
|
void netrace_final_report(){
|
365 |
|
|
int i;
|
366 |
|
|
unsigned int worst_sent=0, worst_rsv=0;
|
367 |
|
|
unsigned long long int total_clock = (nt_cycle-nt_start_cycle);
|
368 |
|
|
unsigned long long int pronoc_total_clock = total_clock/netrace_speed_up;
|
369 |
|
|
|
370 |
|
|
if(verbosity==1) printf("\e[?25h");//To re-enable the cursor:
|
371 |
|
|
printf("\nNetrace simulation results-------------------\n"
|
372 |
|
|
"\tNetrace end clock cycles: %llu\n"
|
373 |
|
|
"\tNetrace duration clock cycles: %llu\n"
|
374 |
|
|
"\tProNoC duration clock cycles: %llu\n"
|
375 |
|
|
,nt_cycle,total_clock,pronoc_total_clock);
|
376 |
|
|
|
377 |
|
|
|
378 |
|
|
|
379 |
|
|
print_statistic_new (pronoc_total_clock);
|
380 |
|
|
/*
|
381 |
|
|
printf("\t total , %u , %u, %u, %u \n",total_sent_pck_num, total_rsv_pck_num,total_sent_flit_number,total_rsv_flit_number);
|
382 |
|
|
printf("\nper node\n");
|
383 |
|
|
for(i=0;i<NE;i++){
|
384 |
|
|
printf("\t %u , %u , %u , %u , %u \n", i,sent_core_total_pck_num[i],rsvd_core_total_pck_num[i], sent_core_total_flit_num[i],rsv_core_total_flit_num[i]
|
385 |
|
|
sent_core_worst_delay[i], rsvd_core_worst_delay[i]
|
386 |
|
|
|
387 |
|
|
);
|
388 |
|
|
}
|
389 |
|
|
*/
|
390 |
|
|
}
|
391 |
|
|
|
392 |
|
|
|
393 |
|
|
|
394 |
|
|
#endif
|