New simulator for Fujitsu frv contributed by Red Hat.
[deliverable/binutils-gdb.git] / sim / frv / profile.c
1 /* frv simulator machine independent profiling code.
2
3 Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 Contributed by Red Hat
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 */
23 #define WANT_CPU
24 #define WANT_CPU_FRVBF
25
26 #include "sim-main.h"
27 #include "bfd.h"
28
29 #if WITH_PROFILE_MODEL_P
30
31 #include "profile.h"
32 #include "profile-fr400.h"
33 #include "profile-fr500.h"
34
35 static void
36 reset_gr_flags (SIM_CPU *cpu, INT gr)
37 {
38 SIM_DESC sd = CPU_STATE (cpu);
39 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
40 fr400_reset_gr_flags (cpu, gr);
41 /* Other machines have no gr flags right now. */
42 }
43
44 static void
45 reset_fr_flags (SIM_CPU *cpu, INT fr)
46 {
47 SIM_DESC sd = CPU_STATE (cpu);
48 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
49 fr400_reset_fr_flags (cpu, fr);
50 else if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
51 fr500_reset_fr_flags (cpu, fr);
52 }
53
54 static void
55 reset_acc_flags (SIM_CPU *cpu, INT acc)
56 {
57 SIM_DESC sd = CPU_STATE (cpu);
58 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
59 fr400_reset_acc_flags (cpu, acc);
60 /* Other machines have no acc flags right now. */
61 }
62
63 static void
64 reset_cc_flags (SIM_CPU *cpu, INT cc)
65 {
66 SIM_DESC sd = CPU_STATE (cpu);
67 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
68 fr500_reset_cc_flags (cpu, cc);
69 /* Other machines have no cc flags. */
70 }
71
72 void
73 set_use_is_gr_complex (SIM_CPU *cpu, INT gr)
74 {
75 if (gr != -1)
76 {
77 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
78 reset_gr_flags (cpu, gr);
79 ps->cur_gr_complex |= (((DI)1) << gr);
80 }
81 }
82
83 void
84 set_use_not_gr_complex (SIM_CPU *cpu, INT gr)
85 {
86 if (gr != -1)
87 {
88 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
89 ps->cur_gr_complex &= ~(((DI)1) << gr);
90 }
91 }
92
93 int
94 use_is_gr_complex (SIM_CPU *cpu, INT gr)
95 {
96 if (gr != -1)
97 {
98 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
99 return ps->cur_gr_complex & (((DI)1) << gr);
100 }
101 return 0;
102 }
103
104 /* Globals flag indicates whether this insn is being modeled. */
105 enum FRV_INSN_MODELING model_insn = FRV_INSN_NO_MODELING;
106
107 /* static buffer for the name of the currently most restrictive hazard. */
108 static char hazard_name[100] = "";
109
110 /* Print information about the wait applied to an entire VLIW insn. */
111 FRV_INSN_FETCH_BUFFER frv_insn_fetch_buffer[]
112 = {
113 {1, NO_REQNO}, {1, NO_REQNO} /* init with impossible address. */
114 };
115
116 enum cache_request
117 {
118 cache_load,
119 cache_invalidate,
120 cache_flush,
121 cache_preload,
122 cache_unlock
123 };
124
125 /* A queue of load requests from the data cache. Use to keep track of loads
126 which are still pending. */
127 /* TODO -- some of these are mutually exclusive and can use a union. */
128 typedef struct
129 {
130 FRV_CACHE *cache;
131 unsigned reqno;
132 SI address;
133 int length;
134 int is_signed;
135 int regnum;
136 int cycles;
137 int regtype;
138 int lock;
139 int all;
140 int slot;
141 int active;
142 enum cache_request request;
143 } CACHE_QUEUE_ELEMENT;
144
145 #define CACHE_QUEUE_SIZE 64 /* TODO -- make queue dynamic */
146 struct
147 {
148 unsigned reqno;
149 int ix;
150 CACHE_QUEUE_ELEMENT q[CACHE_QUEUE_SIZE];
151 } cache_queue = {0, 0};
152
153 /* Queue a request for a load from the cache. The load will be queued as
154 'inactive' and will be requested after the given number
155 of cycles have passed from the point the load is activated. */
156 void
157 request_cache_load (SIM_CPU *cpu, INT regnum, int regtype, int cycles)
158 {
159 CACHE_QUEUE_ELEMENT *q;
160 FRV_VLIW *vliw;
161 int slot;
162
163 /* For a conditional load which was not executed, CPU_LOAD_LENGTH will be
164 zero. */
165 if (CPU_LOAD_LENGTH (cpu) == 0)
166 return;
167
168 if (cache_queue.ix >= CACHE_QUEUE_SIZE)
169 abort (); /* TODO: Make the queue dynamic */
170
171 q = & cache_queue.q[cache_queue.ix];
172 ++cache_queue.ix;
173
174 q->reqno = cache_queue.reqno++;
175 q->request = cache_load;
176 q->cache = CPU_DATA_CACHE (cpu);
177 q->address = CPU_LOAD_ADDRESS (cpu);
178 q->length = CPU_LOAD_LENGTH (cpu);
179 q->is_signed = CPU_LOAD_SIGNED (cpu);
180 q->regnum = regnum;
181 q->regtype = regtype;
182 q->cycles = cycles;
183 q->active = 0;
184
185 vliw = CPU_VLIW (cpu);
186 slot = vliw->next_slot - 1;
187 q->slot = (*vliw->current_vliw)[slot];
188
189 CPU_LOAD_LENGTH (cpu) = 0;
190 }
191
192 /* Queue a request to flush the cache. The request will be queued as
193 'inactive' and will be requested after the given number
194 of cycles have passed from the point the request is activated. */
195 void
196 request_cache_flush (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
197 {
198 CACHE_QUEUE_ELEMENT *q;
199 FRV_VLIW *vliw;
200 int slot;
201
202 if (cache_queue.ix >= CACHE_QUEUE_SIZE)
203 abort (); /* TODO: Make the queue dynamic */
204
205 q = & cache_queue.q[cache_queue.ix];
206 ++cache_queue.ix;
207
208 q->reqno = cache_queue.reqno++;
209 q->request = cache_flush;
210 q->cache = cache;
211 q->address = CPU_LOAD_ADDRESS (cpu);
212 q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
213 q->cycles = cycles;
214 q->active = 0;
215
216 vliw = CPU_VLIW (cpu);
217 slot = vliw->next_slot - 1;
218 q->slot = (*vliw->current_vliw)[slot];
219 }
220
221 /* Queue a request to invalidate the cache. The request will be queued as
222 'inactive' and will be requested after the given number
223 of cycles have passed from the point the request is activated. */
224 void
225 request_cache_invalidate (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
226 {
227 CACHE_QUEUE_ELEMENT *q;
228 FRV_VLIW *vliw;
229 int slot;
230
231 if (cache_queue.ix >= CACHE_QUEUE_SIZE)
232 abort (); /* TODO: Make the queue dynamic */
233
234 q = & cache_queue.q[cache_queue.ix];
235 ++cache_queue.ix;
236
237 q->reqno = cache_queue.reqno++;
238 q->request = cache_invalidate;
239 q->cache = cache;
240 q->address = CPU_LOAD_ADDRESS (cpu);
241 q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
242 q->cycles = cycles;
243 q->active = 0;
244
245 vliw = CPU_VLIW (cpu);
246 slot = vliw->next_slot - 1;
247 q->slot = (*vliw->current_vliw)[slot];
248 }
249
250 /* Queue a request to preload the cache. The request will be queued as
251 'inactive' and will be requested after the given number
252 of cycles have passed from the point the request is activated. */
253 void
254 request_cache_preload (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
255 {
256 CACHE_QUEUE_ELEMENT *q;
257 FRV_VLIW *vliw;
258 int slot;
259
260 if (cache_queue.ix >= CACHE_QUEUE_SIZE)
261 abort (); /* TODO: Make the queue dynamic */
262
263 q = & cache_queue.q[cache_queue.ix];
264 ++cache_queue.ix;
265
266 q->reqno = cache_queue.reqno++;
267 q->request = cache_preload;
268 q->cache = cache;
269 q->address = CPU_LOAD_ADDRESS (cpu);
270 q->length = CPU_LOAD_LENGTH (cpu);
271 q->lock = CPU_LOAD_LOCK (cpu);
272 q->cycles = cycles;
273 q->active = 0;
274
275 vliw = CPU_VLIW (cpu);
276 slot = vliw->next_slot - 1;
277 q->slot = (*vliw->current_vliw)[slot];
278
279 CPU_LOAD_LENGTH (cpu) = 0;
280 }
281
282 /* Queue a request to unlock the cache. The request will be queued as
283 'inactive' and will be requested after the given number
284 of cycles have passed from the point the request is activated. */
285 void
286 request_cache_unlock (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
287 {
288 CACHE_QUEUE_ELEMENT *q;
289 FRV_VLIW *vliw;
290 int slot;
291
292 if (cache_queue.ix >= CACHE_QUEUE_SIZE)
293 abort (); /* TODO: Make the queue dynamic */
294
295 q = & cache_queue.q[cache_queue.ix];
296 ++cache_queue.ix;
297
298 q->reqno = cache_queue.reqno++;
299 q->request = cache_unlock;
300 q->cache = cache;
301 q->address = CPU_LOAD_ADDRESS (cpu);
302 q->cycles = cycles;
303 q->active = 0;
304
305 vliw = CPU_VLIW (cpu);
306 slot = vliw->next_slot - 1;
307 q->slot = (*vliw->current_vliw)[slot];
308 }
309
310 static void
311 submit_cache_request (CACHE_QUEUE_ELEMENT *q)
312 {
313 switch (q->request)
314 {
315 case cache_load:
316 frv_cache_request_load (q->cache, q->reqno, q->address, q->slot);
317 break;
318 case cache_flush:
319 frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
320 q->all, 1/*flush*/);
321 break;
322 case cache_invalidate:
323 frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
324 q->all, 0/*flush*/);
325 break;
326 case cache_preload:
327 frv_cache_request_preload (q->cache, q->address, q->slot,
328 q->length, q->lock);
329 break;
330 case cache_unlock:
331 frv_cache_request_unlock (q->cache, q->address, q->slot);
332 break;
333 default:
334 abort ();
335 }
336 }
337
338 /* Activate all inactive load requests. */
339 static void
340 activate_cache_requests (SIM_CPU *cpu)
341 {
342 int i;
343 for (i = 0; i < cache_queue.ix; ++i)
344 {
345 CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
346 if (! q->active)
347 {
348 q->active = 1;
349 /* Submit the request now if the cycle count is zero. */
350 if (q->cycles == 0)
351 submit_cache_request (q);
352 }
353 }
354 }
355
356 /* Check to see if a load is pending which affects the given register(s).
357 */
358 int
359 load_pending_for_register (SIM_CPU *cpu, int regnum, int words, int regtype)
360 {
361 int i;
362 for (i = 0; i < cache_queue.ix; ++i)
363 {
364 CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
365
366 /* Must be the same kind of register. */
367 if (! q->active || q->request != cache_load || q->regtype != regtype)
368 continue;
369
370 /* If the registers numbers are equal, then we have a match. */
371 if (q->regnum == regnum)
372 return 1; /* load pending */
373
374 /* Check for overlap of a load with a multi-word register. */
375 if (regnum < q->regnum)
376 {
377 if (regnum + words > q->regnum)
378 return 1;
379 }
380 /* Check for overlap of a multi-word load with the register. */
381 else
382 {
383 int data_words = (q->length + sizeof (SI) - 1) / sizeof (SI);
384 if (q->regnum + data_words > regnum)
385 return 1;
386 }
387 }
388
389 return 0; /* no load pending */
390 }
391
392 /* Check to see if a cache flush pending which affects the given address. */
393 static int
394 flush_pending_for_address (SIM_CPU *cpu, SI address)
395 {
396 int line_mask = ~(CPU_DATA_CACHE (cpu)->line_size - 1);
397 int i;
398 for (i = 0; i < cache_queue.ix; ++i)
399 {
400 CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
401
402 /* Must be the same kind of request and active. */
403 if (! q->active || q->request != cache_flush)
404 continue;
405
406 /* If the addresses are equal, then we have a match. */
407 if ((q->address & line_mask) == (address & line_mask))
408 return 1; /* flush pending */
409 }
410
411 return 0; /* no flush pending */
412 }
413
414 static void
415 remove_cache_queue_element (SIM_CPU *cpu, int i)
416 {
417 /* If we are removing the load of a FR register, then remember which one(s).
418 */
419 CACHE_QUEUE_ELEMENT q = cache_queue.q[i];
420
421 for (--cache_queue.ix; i < cache_queue.ix; ++i)
422 cache_queue.q[i] = cache_queue.q[i + 1];
423
424 /* If we removed a load of a FR register, check to see if any other loads
425 of that register is still queued. If not, then apply the queued post
426 processing time of that register to its latency. Also apply
427 1 extra cycle of latency to the register since it was a floating point
428 load. */
429 if (q.request == cache_load && q.regtype != REGTYPE_NONE)
430 {
431 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
432 int data_words = (q.length + sizeof (SI) - 1) / sizeof (SI);
433 int j;
434 for (j = 0; j < data_words; ++j)
435 {
436 int regnum = q.regnum + j;
437 if (! load_pending_for_register (cpu, regnum, 1, q.regtype))
438 {
439 if (q.regtype == REGTYPE_FR)
440 {
441 int *fr = ps->fr_busy;
442 fr[regnum] += 1 + ps->fr_ptime[regnum];
443 ps->fr_ptime[regnum] = 0;
444 }
445 }
446 }
447 }
448 }
449
450 /* Copy data from the cache buffer to the target register(s). */
451 static void
452 copy_load_data (SIM_CPU *current_cpu, FRV_CACHE *cache, int slot,
453 CACHE_QUEUE_ELEMENT *q)
454 {
455 switch (q->length)
456 {
457 case 1:
458 if (q->regtype == REGTYPE_FR)
459 {
460 if (q->is_signed)
461 {
462 QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
463 SET_H_FR (q->regnum, value);
464 }
465 else
466 {
467 UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
468 SET_H_FR (q->regnum, value);
469 }
470 }
471 else
472 {
473 if (q->is_signed)
474 {
475 QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
476 SET_H_GR (q->regnum, value);
477 }
478 else
479 {
480 UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
481 SET_H_GR (q->regnum, value);
482 }
483 }
484 break;
485 case 2:
486 if (q->regtype == REGTYPE_FR)
487 {
488 if (q->is_signed)
489 {
490 HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
491 SET_H_FR (q->regnum, value);
492 }
493 else
494 {
495 UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
496 SET_H_FR (q->regnum, value);
497 }
498 }
499 else
500 {
501 if (q->is_signed)
502 {
503 HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
504 SET_H_GR (q->regnum, value);
505 }
506 else
507 {
508 UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
509 SET_H_GR (q->regnum, value);
510 }
511 }
512 break;
513 case 4:
514 if (q->regtype == REGTYPE_FR)
515 {
516 SET_H_FR (q->regnum,
517 CACHE_RETURN_DATA (cache, slot, q->address, SF, 4));
518 }
519 else
520 {
521 SET_H_GR (q->regnum,
522 CACHE_RETURN_DATA (cache, slot, q->address, SI, 4));
523 }
524 break;
525 case 8:
526 if (q->regtype == REGTYPE_FR)
527 {
528 SET_H_FR_DOUBLE (q->regnum,
529 CACHE_RETURN_DATA (cache, slot, q->address, DF, 8));
530 }
531 else
532 {
533 SET_H_GR_DOUBLE (q->regnum,
534 CACHE_RETURN_DATA (cache, slot, q->address, DI, 8));
535 }
536 break;
537 case 16:
538 if (q->regtype == REGTYPE_FR)
539 frvbf_h_fr_quad_set_handler (current_cpu, q->regnum,
540 CACHE_RETURN_DATA_ADDRESS (cache, slot,
541 q->address,
542 16));
543 else
544 frvbf_h_gr_quad_set_handler (current_cpu, q->regnum,
545 CACHE_RETURN_DATA_ADDRESS (cache, slot,
546 q->address,
547 16));
548 break;
549 default:
550 abort ();
551 }
552 }
553
554 static int
555 request_complete (SIM_CPU *cpu, CACHE_QUEUE_ELEMENT *q)
556 {
557 FRV_CACHE* cache;
558 if (! q->active || q->cycles > 0)
559 return 0;
560
561 cache = CPU_DATA_CACHE (cpu);
562 switch (q->request)
563 {
564 case cache_load:
565 /* For loads, we must wait until the data is returned from the cache. */
566 if (frv_cache_data_in_buffer (cache, 0, q->address, q->reqno))
567 {
568 copy_load_data (cpu, cache, 0, q);
569 return 1;
570 }
571 if (frv_cache_data_in_buffer (cache, 1, q->address, q->reqno))
572 {
573 copy_load_data (cpu, cache, 1, q);
574 return 1;
575 }
576 break;
577
578 case cache_flush:
579 /* We must wait until the data is flushed. */
580 if (frv_cache_data_flushed (cache, 0, q->address, q->reqno))
581 return 1;
582 if (frv_cache_data_flushed (cache, 1, q->address, q->reqno))
583 return 1;
584 break;
585
586 default:
587 /* All other requests are complete once they've been made. */
588 return 1;
589 }
590
591 return 0;
592 }
593
594 /* Run the insn and data caches through the given number of cycles, taking
595 note of load requests which are fullfilled as a result. */
596 static void
597 run_caches (SIM_CPU *cpu, int cycles)
598 {
599 FRV_CACHE* data_cache = CPU_DATA_CACHE (cpu);
600 FRV_CACHE* insn_cache = CPU_INSN_CACHE (cpu);
601 int i;
602 /* For each cycle, run the caches, noting which requests have been fullfilled
603 and submitting new requests on their designated cycles. */
604 for (i = 0; i < cycles; ++i)
605 {
606 int j;
607 /* Run the caches through 1 cycle. */
608 frv_cache_run (data_cache, 1);
609 frv_cache_run (insn_cache, 1);
610
611 /* Note whether prefetched insn data has been loaded yet. */
612 for (j = LS; j < FRV_CACHE_PIPELINES; ++j)
613 {
614 if (frv_insn_fetch_buffer[j].reqno != NO_REQNO
615 && frv_cache_data_in_buffer (insn_cache, j,
616 frv_insn_fetch_buffer[j].address,
617 frv_insn_fetch_buffer[j].reqno))
618 frv_insn_fetch_buffer[j].reqno = NO_REQNO;
619 }
620
621 /* Check to see which requests have been satisfied and which should
622 be submitted now. */
623 for (j = 0; j < cache_queue.ix; ++j)
624 {
625 CACHE_QUEUE_ELEMENT *q = & cache_queue.q[j];
626 if (! q->active)
627 continue;
628
629 /* If a load has been satisfied, complete the operation and remove it
630 from the queue. */
631 if (request_complete (cpu, q))
632 {
633 remove_cache_queue_element (cpu, j);
634 --j;
635 continue;
636 }
637
638 /* Decrease the cycle count of each queued request.
639 Submit a request for each queued request whose cycle count has
640 become zero. */
641 --q->cycles;
642 if (q->cycles == 0)
643 submit_cache_request (q);
644 }
645 }
646 }
647
648 static void
649 apply_latency_adjustments (SIM_CPU *cpu)
650 {
651 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
652 int i;
653 /* update the latencies of the registers. */
654 int *fr = ps->fr_busy;
655 int *acc = ps->acc_busy;
656 for (i = 0; i < 64; ++i)
657 {
658 if (ps->fr_busy_adjust[i] > 0)
659 *fr -= ps->fr_busy_adjust[i]; /* OK if it goes negative. */
660 if (ps->acc_busy_adjust[i] > 0)
661 *acc -= ps->acc_busy_adjust[i]; /* OK if it goes negative. */
662 ++fr;
663 ++acc;
664 }
665 }
666
667 /* Account for the number of cycles which have just passed in the latency of
668 various system elements. Works for negative cycles too so that latency
669 can be extended in the case of insn fetch latency.
670 If negative or zero, then no adjustment is necessary. */
671 static void
672 update_latencies (SIM_CPU *cpu, int cycles)
673 {
674 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
675 int i;
676 /* update the latencies of the registers. */
677 int *fdiv;
678 int *fsqrt;
679 int *idiv;
680 int *ccr;
681 int *gr = ps->gr_busy;
682 int *fr = ps->fr_busy;
683 int *acc = ps->acc_busy;
684 /* This loop handles GR, FR and ACC registers. */
685 for (i = 0; i < 64; ++i)
686 {
687 if (*gr <= cycles)
688 {
689 *gr = 0;
690 reset_gr_flags (cpu, i);
691 }
692 else
693 *gr -= cycles;
694 /* If the busy drops to 0, then mark the register as
695 "not in use". */
696 if (*fr <= cycles)
697 {
698 int *fr_lat = ps->fr_latency + i;
699 *fr = 0;
700 ps->fr_busy_adjust[i] = 0;
701 /* Only clear flags if this register has no target latency. */
702 if (*fr_lat == 0)
703 reset_fr_flags (cpu, i);
704 }
705 else
706 *fr -= cycles;
707 /* If the busy drops to 0, then mark the register as
708 "not in use". */
709 if (*acc <= cycles)
710 {
711 int *acc_lat = ps->acc_latency + i;
712 *acc = 0;
713 ps->acc_busy_adjust[i] = 0;
714 /* Only clear flags if this register has no target latency. */
715 if (*acc_lat == 0)
716 reset_acc_flags (cpu, i);
717 }
718 else
719 *acc -= cycles;
720 ++gr;
721 ++fr;
722 ++acc;
723 }
724 /* This loop handles CCR registers. */
725 ccr = ps->ccr_busy;
726 for (i = 0; i < 8; ++i)
727 {
728 if (*ccr <= cycles)
729 {
730 *ccr = 0;
731 reset_cc_flags (cpu, i);
732 }
733 else
734 *ccr -= cycles;
735 ++ccr;
736 }
737 /* This loop handles resources. */
738 idiv = ps->idiv_busy;
739 fdiv = ps->fdiv_busy;
740 fsqrt = ps->fsqrt_busy;
741 for (i = 0; i < 2; ++i)
742 {
743 *idiv = (*idiv <= cycles) ? 0 : (*idiv - cycles);
744 *fdiv = (*fdiv <= cycles) ? 0 : (*fdiv - cycles);
745 *fsqrt = (*fsqrt <= cycles) ? 0 : (*fsqrt - cycles);
746 ++idiv;
747 ++fdiv;
748 ++fsqrt;
749 }
750 }
751
752 /* Print information about the wait for the given number of cycles. */
753 void
754 frv_model_trace_wait_cycles (SIM_CPU *cpu, int cycles, const char *hazard_name)
755 {
756 if (TRACE_INSN_P (cpu) && cycles > 0)
757 {
758 SIM_DESC sd = CPU_STATE (cpu);
759 trace_printf (sd, cpu, "**** %s wait %d cycles ***\n",
760 hazard_name, cycles);
761 }
762 }
763
764 void
765 trace_vliw_wait_cycles (SIM_CPU *cpu)
766 {
767 if (TRACE_INSN_P (cpu))
768 {
769 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
770 frv_model_trace_wait_cycles (cpu, ps->vliw_wait, hazard_name);
771 }
772 }
773
774 /* Wait for the given number of cycles. */
775 void
776 frv_model_advance_cycles (SIM_CPU *cpu, int cycles)
777 {
778 PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
779 update_latencies (cpu, cycles);
780 run_caches (cpu, cycles);
781 PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
782 }
783
784 void
785 handle_resource_wait (SIM_CPU *cpu)
786 {
787 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
788 if (ps->vliw_wait != 0)
789 frv_model_advance_cycles (cpu, ps->vliw_wait);
790 if (ps->vliw_load_stall > ps->vliw_wait)
791 ps->vliw_load_stall -= ps->vliw_wait;
792 else
793 ps->vliw_load_stall = 0;
794 }
795
796 /* Account for the number of cycles until these resources will be available
797 again. */
798 static void
799 update_target_latencies (SIM_CPU *cpu)
800 {
801 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
802 int i;
803 /* update the latencies of the registers. */
804 int *ccr_lat;
805 int *gr_lat = ps->gr_latency;
806 int *fr_lat = ps->fr_latency;
807 int *acc_lat = ps->acc_latency;
808 int *ccr;
809 int *gr = ps->gr_busy;
810 int *fr = ps->fr_busy;
811 int *acc = ps->acc_busy;
812 /* This loop handles GR, FR and ACC registers. */
813 for (i = 0; i < 64; ++i)
814 {
815 if (*gr_lat)
816 {
817 *gr = *gr_lat;
818 *gr_lat = 0;
819 }
820 if (*fr_lat)
821 {
822 *fr = *fr_lat;
823 *fr_lat = 0;
824 }
825 if (*acc_lat)
826 {
827 *acc = *acc_lat;
828 *acc_lat = 0;
829 }
830 ++gr; ++gr_lat;
831 ++fr; ++fr_lat;
832 ++acc; ++acc_lat;
833 }
834 /* This loop handles CCR registers. */
835 ccr = ps->ccr_busy;
836 ccr_lat = ps->ccr_latency;
837 for (i = 0; i < 8; ++i)
838 {
839 if (*ccr_lat)
840 {
841 *ccr = *ccr_lat;
842 *ccr_lat = 0;
843 }
844 ++ccr; ++ccr_lat;
845 }
846 }
847
848 /* Run the caches until all pending cache flushes are complete. */
849 static void
850 wait_for_flush (SIM_CPU *cpu)
851 {
852 SI address = CPU_LOAD_ADDRESS (cpu);
853 int wait = 0;
854 while (flush_pending_for_address (cpu, address))
855 {
856 frv_model_advance_cycles (cpu, 1);
857 ++wait;
858 }
859 if (TRACE_INSN_P (cpu) && wait)
860 {
861 sprintf (hazard_name, "Data cache flush address %p:", address);
862 frv_model_trace_wait_cycles (cpu, wait, hazard_name);
863 }
864 }
865
866 /* Initialize cycle counting for an insn.
867 FIRST_P is non-zero if this is the first insn in a set of parallel
868 insns. */
869 void
870 frvbf_model_insn_before (SIM_CPU *cpu, int first_p)
871 {
872 SIM_DESC sd = CPU_STATE (cpu);
873 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
874
875 ps->vliw_wait = 0;
876 ps->post_wait = 0;
877 memset (ps->fr_busy_adjust, 0, sizeof (ps->fr_busy_adjust));
878 memset (ps->acc_busy_adjust, 0, sizeof (ps->acc_busy_adjust));
879
880 if (first_p)
881 {
882 ps->vliw_insns++;
883 ps->vliw_cycles = 0;
884 ps->vliw_branch_taken = 0;
885 ps->vliw_load_stall = 0;
886 }
887
888 switch (STATE_ARCHITECTURE (sd)->mach)
889 {
890 case bfd_mach_fr400:
891 fr400_model_insn_before (cpu, first_p);
892 break;
893 case bfd_mach_fr500:
894 fr500_model_insn_before (cpu, first_p);
895 break;
896 default:
897 break;
898 }
899
900 if (first_p)
901 wait_for_flush (cpu);
902 }
903
904 /* Record the cycles computed for an insn.
905 LAST_P is non-zero if this is the last insn in a set of parallel insns,
906 and we update the total cycle count.
907 CYCLES is the cycle count of the insn. */
908
909 void
910 frvbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
911 {
912 PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
913 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
914 SIM_DESC sd = CPU_STATE (cpu);
915
916 PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
917
918 /* The number of cycles for a VLIW insn is the maximum number of cycles
919 used by any individual insn within it. */
920 if (cycles > ps->vliw_cycles)
921 ps->vliw_cycles = cycles;
922
923 if (last_p)
924 {
925 /* This is the last insn in a VLIW insn. */
926 struct frv_interrupt_timer *timer = & frv_interrupt_state.timer;
927
928 activate_cache_requests (cpu); /* before advancing cycles. */
929 apply_latency_adjustments (cpu); /* must go first. */
930 update_target_latencies (cpu); /* must go next. */
931 frv_model_advance_cycles (cpu, ps->vliw_cycles);
932
933 PROFILE_MODEL_LOAD_STALL_CYCLES (p) += ps->vliw_load_stall;
934
935 /* Check the interrupt timer. cycles contains the total cycle count. */
936 if (timer->enabled)
937 {
938 cycles = PROFILE_MODEL_TOTAL_CYCLES (p);
939 if (timer->current % timer->value
940 + (cycles - timer->current) >= timer->value)
941 frv_queue_external_interrupt (cpu, timer->interrupt);
942 timer->current = cycles;
943 }
944
945 ps->past_first_p = 0; /* Next one will be the first in a new VLIW. */
946 ps->branch_address = -1;
947 }
948 else
949 ps->past_first_p = 1;
950
951 switch (STATE_ARCHITECTURE (sd)->mach)
952 {
953 case bfd_mach_fr400:
954 fr400_model_insn_after (cpu, last_p, cycles);
955 break;
956 case bfd_mach_fr500:
957 fr500_model_insn_after (cpu, last_p, cycles);
958 break;
959 default:
960 break;
961 }
962 }
963
964 USI
965 frvbf_model_branch (SIM_CPU *current_cpu, PCADDR target, int hint)
966 {
967 /* Record the hint and branch address for use in profiling. */
968 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
969 ps->branch_hint = hint;
970 ps->branch_address = target;
971 }
972
973 /* Top up the latency of the given GR by the given number of cycles. */
974 void
975 update_GR_latency (SIM_CPU *cpu, INT out_GR, int cycles)
976 {
977 if (out_GR >= 0)
978 {
979 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
980 int *gr = ps->gr_latency;
981 if (gr[out_GR] < cycles)
982 gr[out_GR] = cycles;
983 }
984 }
985
986 void
987 decrease_GR_busy (SIM_CPU *cpu, INT in_GR, int cycles)
988 {
989 if (in_GR >= 0)
990 {
991 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
992 int *gr = ps->gr_busy;
993 gr[in_GR] -= cycles;
994 }
995 }
996
997 /* Top up the latency of the given double GR by the number of cycles. */
998 void
999 update_GRdouble_latency (SIM_CPU *cpu, INT out_GR, int cycles)
1000 {
1001 if (out_GR >= 0)
1002 {
1003 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1004 int *gr = ps->gr_latency;
1005 if (gr[out_GR] < cycles)
1006 gr[out_GR] = cycles;
1007 if (out_GR < 63 && gr[out_GR + 1] < cycles)
1008 gr[out_GR + 1] = cycles;
1009 }
1010 }
1011
1012 void
1013 update_GR_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
1014 {
1015 if (out_GR >= 0)
1016 {
1017 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1018 int *gr = ps->gr_latency;
1019
1020 /* The latency of the GR will be at least the number of cycles used
1021 by the insn. */
1022 if (gr[out_GR] < cycles)
1023 gr[out_GR] = cycles;
1024
1025 /* The latency will also depend on how long it takes to retrieve the
1026 data from the cache or memory. Assume that the load is issued
1027 after the last cycle of the insn. */
1028 request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
1029 }
1030 }
1031
1032 void
1033 update_GRdouble_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
1034 {
1035 if (out_GR >= 0)
1036 {
1037 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1038 int *gr = ps->gr_latency;
1039
1040 /* The latency of the GR will be at least the number of cycles used
1041 by the insn. */
1042 if (gr[out_GR] < cycles)
1043 gr[out_GR] = cycles;
1044 if (out_GR < 63 && gr[out_GR + 1] < cycles)
1045 gr[out_GR + 1] = cycles;
1046
1047 /* The latency will also depend on how long it takes to retrieve the
1048 data from the cache or memory. Assume that the load is issued
1049 after the last cycle of the insn. */
1050 request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
1051 }
1052 }
1053
1054 void
1055 update_GR_latency_for_swap (SIM_CPU *cpu, INT out_GR, int cycles)
1056 {
1057 update_GR_latency_for_load (cpu, out_GR, cycles);
1058 }
1059
1060 /* Top up the latency of the given FR by the given number of cycles. */
1061 void
1062 update_FR_latency (SIM_CPU *cpu, INT out_FR, int cycles)
1063 {
1064 if (out_FR >= 0)
1065 {
1066 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1067 int *fr = ps->fr_latency;
1068 if (fr[out_FR] < cycles)
1069 fr[out_FR] = cycles;
1070 }
1071 }
1072
1073 /* Top up the latency of the given double FR by the number of cycles. */
1074 void
1075 update_FRdouble_latency (SIM_CPU *cpu, INT out_FR, int cycles)
1076 {
1077 if (out_FR >= 0)
1078 {
1079 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1080 int *fr = ps->fr_latency;
1081 if (fr[out_FR] < cycles)
1082 fr[out_FR] = cycles;
1083 if (out_FR < 63 && fr[out_FR + 1] < cycles)
1084 fr[out_FR + 1] = cycles;
1085 }
1086 }
1087
1088 void
1089 update_FR_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
1090 {
1091 if (out_FR >= 0)
1092 {
1093 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1094 int *fr = ps->fr_latency;
1095
1096 /* The latency of the FR will be at least the number of cycles used
1097 by the insn. */
1098 if (fr[out_FR] < cycles)
1099 fr[out_FR] = cycles;
1100
1101 /* The latency will also depend on how long it takes to retrieve the
1102 data from the cache or memory. Assume that the load is issued
1103 after the last cycle of the insn. */
1104 request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
1105 }
1106 }
1107
1108 void
1109 update_FRdouble_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
1110 {
1111 if (out_FR >= 0)
1112 {
1113 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1114 int *fr = ps->fr_latency;
1115
1116 /* The latency of the FR will be at least the number of cycles used
1117 by the insn. */
1118 if (fr[out_FR] < cycles)
1119 fr[out_FR] = cycles;
1120 if (out_FR < 63 && fr[out_FR + 1] < cycles)
1121 fr[out_FR + 1] = cycles;
1122
1123 /* The latency will also depend on how long it takes to retrieve the
1124 data from the cache or memory. Assume that the load is issued
1125 after the last cycle of the insn. */
1126 request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
1127 }
1128 }
1129
1130 /* Top up the post-processing time of the given FR by the given number of
1131 cycles. */
1132 void
1133 update_ACC_ptime (SIM_CPU *cpu, INT out_ACC, int cycles)
1134 {
1135 if (out_ACC >= 0)
1136 {
1137 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1138 /* No load can be pending on this register. Apply the cycles
1139 directly to the latency of the register. */
1140 int *acc = ps->acc_latency;
1141 acc[out_ACC] += cycles;
1142 }
1143 }
1144
1145 void
1146 decrease_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
1147 {
1148 if (out_ACC >= 0)
1149 {
1150 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1151 int *acc = ps->acc_busy;
1152 acc[out_ACC] -= cycles;
1153 if (ps->acc_busy_adjust[out_ACC] >= 0
1154 && cycles > ps->acc_busy_adjust[out_ACC])
1155 ps->acc_busy_adjust[out_ACC] = cycles;
1156 }
1157 }
1158
1159 void
1160 decrease_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
1161 {
1162 if (out_FR >= 0)
1163 {
1164 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1165 int *fr = ps->fr_busy;
1166 fr[out_FR] -= cycles;
1167 if (ps->fr_busy_adjust[out_FR] >= 0
1168 && cycles > ps->fr_busy_adjust[out_FR])
1169 ps->fr_busy_adjust[out_FR] = cycles;
1170 }
1171 }
1172
1173 void
1174 increase_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
1175 {
1176 if (out_FR >= 0)
1177 {
1178 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1179 int *fr = ps->fr_busy;
1180 fr[out_FR] += cycles;
1181 }
1182 }
1183
1184 /* Top up the latency of the given ACC by the given number of cycles. */
1185 void
1186 update_ACC_latency (SIM_CPU *cpu, INT out_ACC, int cycles)
1187 {
1188 if (out_ACC >= 0)
1189 {
1190 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1191 int *acc = ps->acc_latency;
1192 if (acc[out_ACC] < cycles)
1193 acc[out_ACC] = cycles;
1194 }
1195 }
1196
1197 /* Top up the latency of the given CCR by the given number of cycles. */
1198 void
1199 update_CCR_latency (SIM_CPU *cpu, INT out_CCR, int cycles)
1200 {
1201 if (out_CCR >= 0)
1202 {
1203 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1204 int *ccr = ps->ccr_latency;
1205 if (ccr[out_CCR] < cycles)
1206 ccr[out_CCR] = cycles;
1207 }
1208 }
1209
1210 /* Top up the latency of the given integer division resource by the given
1211 number of cycles. */
1212 void
1213 update_idiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1214 {
1215 /* operate directly on the busy cycles since each resource can only
1216 be used once in a VLIW insn. */
1217 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1218 int *r = ps->idiv_busy;
1219 r[in_resource] = cycles;
1220 }
1221
1222 /* Set the latency of the given resource to the given number of cycles. */
1223 void
1224 update_fdiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1225 {
1226 /* operate directly on the busy cycles since each resource can only
1227 be used once in a VLIW insn. */
1228 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1229 int *r = ps->fdiv_busy;
1230 r[in_resource] = cycles;
1231 }
1232
1233 /* Set the latency of the given resource to the given number of cycles. */
1234 void
1235 update_fsqrt_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1236 {
1237 /* operate directly on the busy cycles since each resource can only
1238 be used once in a VLIW insn. */
1239 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1240 int *r = ps->fsqrt_busy;
1241 r[in_resource] = cycles;
1242 }
1243
1244 /* Set the branch penalty to the given number of cycles. */
1245 void
1246 update_branch_penalty (SIM_CPU *cpu, int cycles)
1247 {
1248 /* operate directly on the busy cycles since only one branch can occur
1249 in a VLIW insn. */
1250 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1251 ps->branch_penalty = cycles;
1252 }
1253
1254 /* Check the availability of the given GR register and update the number
1255 of cycles the current VLIW insn must wait until it is available. */
1256 void
1257 vliw_wait_for_GR (SIM_CPU *cpu, INT in_GR)
1258 {
1259 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1260 int *gr = ps->gr_busy;
1261 /* If the latency of the register is greater than the current wait
1262 then update the current wait. */
1263 if (in_GR >= 0 && gr[in_GR] > ps->vliw_wait)
1264 {
1265 if (TRACE_INSN_P (cpu))
1266 sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1267 ps->vliw_wait = gr[in_GR];
1268 }
1269 }
1270
1271 /* Check the availability of the given GR register and update the number
1272 of cycles the current VLIW insn must wait until it is available. */
1273 void
1274 vliw_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
1275 {
1276 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1277 int *gr = ps->gr_busy;
1278 /* If the latency of the register is greater than the current wait
1279 then update the current wait. */
1280 if (in_GR >= 0)
1281 {
1282 if (gr[in_GR] > ps->vliw_wait)
1283 {
1284 if (TRACE_INSN_P (cpu))
1285 sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1286 ps->vliw_wait = gr[in_GR];
1287 }
1288 if (in_GR < 63 && gr[in_GR + 1] > ps->vliw_wait)
1289 {
1290 if (TRACE_INSN_P (cpu))
1291 sprintf (hazard_name, "Data hazard for gr%d:", in_GR + 1);
1292 ps->vliw_wait = gr[in_GR + 1];
1293 }
1294 }
1295 }
1296
1297 /* Check the availability of the given FR register and update the number
1298 of cycles the current VLIW insn must wait until it is available. */
1299 void
1300 vliw_wait_for_FR (SIM_CPU *cpu, INT in_FR)
1301 {
1302 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1303 int *fr = ps->fr_busy;
1304 /* If the latency of the register is greater than the current wait
1305 then update the current wait. */
1306 if (in_FR >= 0 && fr[in_FR] > ps->vliw_wait)
1307 {
1308 if (TRACE_INSN_P (cpu))
1309 sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1310 ps->vliw_wait = fr[in_FR];
1311 }
1312 }
1313
1314 /* Check the availability of the given GR register and update the number
1315 of cycles the current VLIW insn must wait until it is available. */
1316 void
1317 vliw_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
1318 {
1319 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1320 int *fr = ps->fr_busy;
1321 /* If the latency of the register is greater than the current wait
1322 then update the current wait. */
1323 if (in_FR >= 0)
1324 {
1325 if (fr[in_FR] > ps->vliw_wait)
1326 {
1327 if (TRACE_INSN_P (cpu))
1328 sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1329 ps->vliw_wait = fr[in_FR];
1330 }
1331 if (in_FR < 63 && fr[in_FR + 1] > ps->vliw_wait)
1332 {
1333 if (TRACE_INSN_P (cpu))
1334 sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
1335 ps->vliw_wait = fr[in_FR + 1];
1336 }
1337 }
1338 }
1339
1340 /* Check the availability of the given CCR register and update the number
1341 of cycles the current VLIW insn must wait until it is available. */
1342 void
1343 vliw_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
1344 {
1345 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1346 int *ccr = ps->ccr_busy;
1347 /* If the latency of the register is greater than the current wait
1348 then update the current wait. */
1349 if (in_CCR >= 0 && ccr[in_CCR] > ps->vliw_wait)
1350 {
1351 if (TRACE_INSN_P (cpu))
1352 {
1353 if (in_CCR > 3)
1354 sprintf (hazard_name, "Data hazard for icc%d:", in_CCR-4);
1355 else
1356 sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
1357 }
1358 ps->vliw_wait = ccr[in_CCR];
1359 }
1360 }
1361
1362 /* Check the availability of the given ACC register and update the number
1363 of cycles the current VLIW insn must wait until it is available. */
1364 void
1365 vliw_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
1366 {
1367 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1368 int *acc = ps->acc_busy;
1369 /* If the latency of the register is greater than the current wait
1370 then update the current wait. */
1371 if (in_ACC >= 0 && acc[in_ACC] > ps->vliw_wait)
1372 {
1373 if (TRACE_INSN_P (cpu))
1374 sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
1375 ps->vliw_wait = acc[in_ACC];
1376 }
1377 }
1378
1379 /* Check the availability of the given integer division resource and update
1380 the number of cycles the current VLIW insn must wait until it is available.
1381 */
1382 void
1383 vliw_wait_for_idiv_resource (SIM_CPU *cpu, INT in_resource)
1384 {
1385 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1386 int *r = ps->idiv_busy;
1387 /* If the latency of the resource is greater than the current wait
1388 then update the current wait. */
1389 if (r[in_resource] > ps->vliw_wait)
1390 {
1391 if (TRACE_INSN_P (cpu))
1392 {
1393 sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
1394 }
1395 ps->vliw_wait = r[in_resource];
1396 }
1397 }
1398
1399 /* Check the availability of the given float division resource and update
1400 the number of cycles the current VLIW insn must wait until it is available.
1401 */
1402 void
1403 vliw_wait_for_fdiv_resource (SIM_CPU *cpu, INT in_resource)
1404 {
1405 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1406 int *r = ps->fdiv_busy;
1407 /* If the latency of the resource is greater than the current wait
1408 then update the current wait. */
1409 if (r[in_resource] > ps->vliw_wait)
1410 {
1411 if (TRACE_INSN_P (cpu))
1412 {
1413 sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
1414 }
1415 ps->vliw_wait = r[in_resource];
1416 }
1417 }
1418
1419 /* Check the availability of the given float square root resource and update
1420 the number of cycles the current VLIW insn must wait until it is available.
1421 */
1422 void
1423 vliw_wait_for_fsqrt_resource (SIM_CPU *cpu, INT in_resource)
1424 {
1425 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1426 int *r = ps->fsqrt_busy;
1427 /* If the latency of the resource is greater than the current wait
1428 then update the current wait. */
1429 if (r[in_resource] > ps->vliw_wait)
1430 {
1431 if (TRACE_INSN_P (cpu))
1432 {
1433 sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
1434 }
1435 ps->vliw_wait = r[in_resource];
1436 }
1437 }
1438
1439 /* Run the caches until all requests for the given register(s) are satisfied. */
1440 void
1441 load_wait_for_GR (SIM_CPU *cpu, INT in_GR)
1442 {
1443 if (in_GR >= 0)
1444 {
1445 int wait = 0;
1446 while (load_pending_for_register (cpu, in_GR, 1/*words*/, REGTYPE_NONE))
1447 {
1448 frv_model_advance_cycles (cpu, 1);
1449 ++wait;
1450 }
1451 if (wait)
1452 {
1453 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1454 ps->vliw_wait += wait;
1455 ps->vliw_load_stall += wait;
1456 if (TRACE_INSN_P (cpu))
1457 sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1458 }
1459 }
1460 }
1461
1462 void
1463 load_wait_for_FR (SIM_CPU *cpu, INT in_FR)
1464 {
1465 if (in_FR >= 0)
1466 {
1467 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1468 int *fr;
1469 int wait = 0;
1470 while (load_pending_for_register (cpu, in_FR, 1/*words*/, REGTYPE_FR))
1471 {
1472 frv_model_advance_cycles (cpu, 1);
1473 ++wait;
1474 }
1475 /* Post processing time may have been added to the register's
1476 latency after the loads were processed. Account for that too.
1477 */
1478 fr = ps->fr_busy;
1479 if (fr[in_FR])
1480 {
1481 wait += fr[in_FR];
1482 frv_model_advance_cycles (cpu, fr[in_FR]);
1483 }
1484 /* Update the vliw_wait with the number of cycles we waited for the
1485 load and any post-processing. */
1486 if (wait)
1487 {
1488 ps->vliw_wait += wait;
1489 ps->vliw_load_stall += wait;
1490 if (TRACE_INSN_P (cpu))
1491 sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1492 }
1493 }
1494 }
1495
1496 void
1497 load_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
1498 {
1499 if (in_GR >= 0)
1500 {
1501 int wait = 0;
1502 while (load_pending_for_register (cpu, in_GR, 2/*words*/, REGTYPE_NONE))
1503 {
1504 frv_model_advance_cycles (cpu, 1);
1505 ++wait;
1506 }
1507 if (wait)
1508 {
1509 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1510 ps->vliw_wait += wait;
1511 ps->vliw_load_stall += wait;
1512 if (TRACE_INSN_P (cpu))
1513 sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1514 }
1515 }
1516 }
1517
1518 void
1519 load_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
1520 {
1521 if (in_FR >= 0)
1522 {
1523 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1524 int *fr;
1525 int wait = 0;
1526 while (load_pending_for_register (cpu, in_FR, 2/*words*/, REGTYPE_FR))
1527 {
1528 frv_model_advance_cycles (cpu, 1);
1529 ++wait;
1530 }
1531 /* Post processing time may have been added to the registers'
1532 latencies after the loads were processed. Account for that too.
1533 */
1534 fr = ps->fr_busy;
1535 if (fr[in_FR])
1536 {
1537 wait += fr[in_FR];
1538 frv_model_advance_cycles (cpu, fr[in_FR]);
1539 }
1540 if (in_FR < 63)
1541 {
1542 if (fr[in_FR + 1])
1543 {
1544 wait += fr[in_FR + 1];
1545 frv_model_advance_cycles (cpu, fr[in_FR + 1]);
1546 }
1547 }
1548 /* Update the vliw_wait with the number of cycles we waited for the
1549 load and any post-processing. */
1550 if (wait)
1551 {
1552 ps->vliw_wait += wait;
1553 ps->vliw_load_stall += wait;
1554 if (TRACE_INSN_P (cpu))
1555 sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1556 }
1557 }
1558 }
1559
1560 void
1561 enforce_full_fr_latency (SIM_CPU *cpu, INT in_FR)
1562 {
1563 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1564 ps->fr_busy_adjust [in_FR] = -1;
1565 }
1566
1567 /* Calculate how long the post processing for a floating point insn must
1568 wait for resources to become available. */
1569 int
1570 post_wait_for_FR (SIM_CPU *cpu, INT in_FR)
1571 {
1572 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1573 int *fr = ps->fr_busy;
1574
1575 if (in_FR >= 0 && fr[in_FR] > ps->post_wait)
1576 {
1577 ps->post_wait = fr[in_FR];
1578 if (TRACE_INSN_P (cpu))
1579 sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1580 }
1581 }
1582
1583 /* Calculate how long the post processing for a floating point insn must
1584 wait for resources to become available. */
1585 int
1586 post_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
1587 {
1588 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1589 int *fr = ps->fr_busy;
1590
1591 if (in_FR >= 0)
1592 {
1593 if (fr[in_FR] > ps->post_wait)
1594 {
1595 ps->post_wait = fr[in_FR];
1596 if (TRACE_INSN_P (cpu))
1597 sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1598 }
1599 if (in_FR < 63 && fr[in_FR + 1] > ps->post_wait)
1600 {
1601 ps->post_wait = fr[in_FR + 1];
1602 if (TRACE_INSN_P (cpu))
1603 sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
1604 }
1605 }
1606 }
1607
1608 int
1609 post_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
1610 {
1611 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1612 int *acc = ps->acc_busy;
1613
1614 if (in_ACC >= 0 && acc[in_ACC] > ps->post_wait)
1615 {
1616 ps->post_wait = acc[in_ACC];
1617 if (TRACE_INSN_P (cpu))
1618 sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
1619 }
1620 }
1621
1622 int
1623 post_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
1624 {
1625 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1626 int *ccr = ps->ccr_busy;
1627
1628 if (in_CCR >= 0 && ccr[in_CCR] > ps->post_wait)
1629 {
1630 ps->post_wait = ccr[in_CCR];
1631 if (TRACE_INSN_P (cpu))
1632 {
1633 if (in_CCR > 3)
1634 sprintf (hazard_name, "Data hazard for icc%d:", in_CCR - 4);
1635 else
1636 sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
1637 }
1638 }
1639 }
1640
1641 int
1642 post_wait_for_fdiv (SIM_CPU *cpu, INT slot)
1643 {
1644 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1645 int *fdiv = ps->fdiv_busy;
1646
1647 /* Multiple floating point divisions in the same slot need only wait 1
1648 extra cycle. */
1649 if (fdiv[slot] > 0 && 1 > ps->post_wait)
1650 {
1651 ps->post_wait = 1;
1652 if (TRACE_INSN_P (cpu))
1653 {
1654 sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", slot);
1655 }
1656 }
1657 }
1658
1659 int
1660 post_wait_for_fsqrt (SIM_CPU *cpu, INT slot)
1661 {
1662 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1663 int *fsqrt = ps->fsqrt_busy;
1664
1665 /* Multiple floating point square roots in the same slot need only wait 1
1666 extra cycle. */
1667 if (fsqrt[slot] > 0 && 1 > ps->post_wait)
1668 {
1669 ps->post_wait = 1;
1670 if (TRACE_INSN_P (cpu))
1671 {
1672 sprintf (hazard_name, "Resource hazard for square root in slot F%d:", slot);
1673 }
1674 }
1675 }
1676
1677 /* Print cpu-specific profile information. */
1678 #define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
1679
1680 static void
1681 print_cache (SIM_CPU *cpu, FRV_CACHE *cache, const char *cache_name)
1682 {
1683 SIM_DESC sd = CPU_STATE (cpu);
1684
1685 if (cache != NULL)
1686 {
1687 char comma_buf[20];
1688 unsigned accesses;
1689
1690 sim_io_printf (sd, " %s Cache\n\n", cache_name);
1691 accesses = cache->statistics.accesses;
1692 sim_io_printf (sd, " Total accesses: %s\n", COMMAS (accesses));
1693 if (accesses != 0)
1694 {
1695 float rate;
1696 unsigned hits = cache->statistics.hits;
1697 sim_io_printf (sd, " Hits: %s\n", COMMAS (hits));
1698 rate = (float)hits / accesses;
1699 sim_io_printf (sd, " Hit rate: %.2f%%\n", rate * 100);
1700 }
1701 }
1702 else
1703 sim_io_printf (sd, " Model %s has no %s cache\n",
1704 MODEL_NAME (CPU_MODEL (cpu)), cache_name);
1705
1706 sim_io_printf (sd, "\n");
1707 }
1708
1709 static char *
1710 slot_names[] =
1711 {
1712 "none",
1713 "I0", "I1", "I01",
1714 "FM1", "FM1", "FM01",
1715 "B0", "B1", "B01",
1716 "C"
1717 };
1718
1719 static void
1720 print_parallel (SIM_CPU *cpu, int verbose)
1721 {
1722 SIM_DESC sd = CPU_STATE (cpu);
1723 PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
1724 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1725 unsigned total, vliw;
1726 char comma_buf[20];
1727 float average;
1728
1729 sim_io_printf (sd, "Model %s Parallelization\n\n",
1730 MODEL_NAME (CPU_MODEL (cpu)));
1731
1732 total = PROFILE_TOTAL_INSN_COUNT (p);
1733 sim_io_printf (sd, " Total instructions: %s\n", COMMAS (total));
1734 vliw = ps->vliw_insns;
1735 sim_io_printf (sd, " VLIW instructions: %s\n", COMMAS (vliw));
1736 average = (float)total / vliw;
1737 sim_io_printf (sd, " Average VLIW length: %.2f\n", average);
1738 average = (float)PROFILE_MODEL_TOTAL_CYCLES (p) / vliw;
1739 sim_io_printf (sd, " Cycles per VLIW instruction: %.2f\n", average);
1740 average = (float)total / PROFILE_MODEL_TOTAL_CYCLES (p);
1741 sim_io_printf (sd, " Instructions per cycle: %.2f\n", average);
1742
1743 if (verbose)
1744 {
1745 int i;
1746 int max_val = 0;
1747 int max_name_len = 0;
1748 for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
1749 {
1750 int len;
1751 if (INSNS_IN_SLOT (i) > max_val)
1752 max_val = INSNS_IN_SLOT (i);
1753 len = strlen (slot_names[i]);
1754 if (len > max_name_len)
1755 max_name_len = len;
1756 }
1757 if (max_val > 0)
1758 {
1759 sim_io_printf (sd, "\n");
1760 sim_io_printf (sd, " Instructions per slot:\n");
1761 sim_io_printf (sd, "\n");
1762 for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
1763 {
1764 if (INSNS_IN_SLOT (i) != 0)
1765 {
1766 sim_io_printf (sd, " %*s: %*s: ",
1767 max_name_len, slot_names[i],
1768 max_val < 10000 ? 5 : 10,
1769 COMMAS (INSNS_IN_SLOT (i)));
1770 sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
1771 INSNS_IN_SLOT (i),
1772 max_val);
1773 sim_io_printf (sd, "\n");
1774 }
1775 }
1776 } /* details to print */
1777 } /* verbose */
1778
1779 sim_io_printf (sd, "\n");
1780 }
1781
1782 void
1783 frv_profile_info (SIM_CPU *cpu, int verbose)
1784 {
1785 /* FIXME: Need to add smp support. */
1786 PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
1787
1788 #if WITH_PROFILE_PARALLEL_P
1789 if (PROFILE_FLAGS (p) [PROFILE_PARALLEL_IDX])
1790 print_parallel (cpu, verbose);
1791 #endif
1792
1793 #if WITH_PROFILE_CACHE_P
1794 if (PROFILE_FLAGS (p) [PROFILE_CACHE_IDX])
1795 {
1796 SIM_DESC sd = CPU_STATE (cpu);
1797 sim_io_printf (sd, "Model %s Cache Statistics\n\n",
1798 MODEL_NAME (CPU_MODEL (cpu)));
1799 print_cache (cpu, CPU_INSN_CACHE (cpu), "Instruction");
1800 print_cache (cpu, CPU_DATA_CACHE (cpu), "Data");
1801 }
1802 #endif /* WITH_PROFILE_CACHE_P */
1803 }
1804
1805 /* A hack to get registers referenced for profiling. */
1806 SI frv_ref_SI (SI ref) {return ref;}
1807 #endif /* WITH_PROFILE_MODEL_P */
This page took 0.204045 seconds and 4 git commands to generate.