]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/frv/profile.c
New simulator for Fujitsu frv contributed by Red Hat.
[thirdparty/binutils-gdb.git] / sim / frv / profile.c
CommitLineData
b34f6357
DB
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
6This file is part of the GNU simulators.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License along
19with this program; if not, write to the Free Software Foundation, Inc.,
2059 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
35static void
36reset_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
44static void
45reset_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
54static void
55reset_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
63static void
64reset_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
72void
73set_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
83void
84set_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
93int
94use_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. */
105enum FRV_INSN_MODELING model_insn = FRV_INSN_NO_MODELING;
106
107/* static buffer for the name of the currently most restrictive hazard. */
108static char hazard_name[100] = "";
109
110/* Print information about the wait applied to an entire VLIW insn. */
111FRV_INSN_FETCH_BUFFER frv_insn_fetch_buffer[]
112= {
113 {1, NO_REQNO}, {1, NO_REQNO} /* init with impossible address. */
114};
115
116enum 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. */
128typedef 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 */
146struct
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. */
156void
157request_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. */
195void
196request_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. */
224void
225request_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. */
253void
254request_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. */
285void
286request_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
310static void
311submit_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. */
339static void
340activate_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 */
358int
359load_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. */
393static int
394flush_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
414static void
415remove_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). */
451static void
452copy_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
554static int
555request_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. */
596static void
597run_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
648static void
649apply_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. */
671static void
672update_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. */
753void
754frv_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
764void
765trace_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. */
775void
776frv_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
784void
785handle_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. */
798static void
799update_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. */
849static void
850wait_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. */
869void
870frvbf_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
909void
910frvbf_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
964USI
965frvbf_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. */
974void
975update_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
986void
987decrease_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. */
998void
999update_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
1012void
1013update_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
1032void
1033update_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
1054void
1055update_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. */
1061void
1062update_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. */
1074void
1075update_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
1088void
1089update_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
1108void
1109update_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. */
1132void
1133update_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
1145void
1146decrease_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
1159void
1160decrease_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
1173void
1174increase_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. */
1185void
1186update_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. */
1198void
1199update_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. */
1212void
1213update_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. */
1223void
1224update_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. */
1234void
1235update_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. */
1245void
1246update_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. */
1256void
1257vliw_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. */
1273void
1274vliw_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. */
1299void
1300vliw_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. */
1316void
1317vliw_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. */
1342void
1343vliw_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. */
1364void
1365vliw_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*/
1382void
1383vliw_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*/
1402void
1403vliw_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*/
1422void
1423vliw_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. */
1440void
1441load_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
1462void
1463load_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
1496void
1497load_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
1518void
1519load_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
1560void
1561enforce_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. */
1569int
1570post_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. */
1585int
1586post_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
1608int
1609post_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
1622int
1623post_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
1641int
1642post_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
1659int
1660post_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
1680static void
1681print_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
1709static char *
1710slot_names[] =
1711{
1712 "none",
1713 "I0", "I1", "I01",
1714 "FM1", "FM1", "FM01",
1715 "B0", "B1", "B01",
1716 "C"
1717};
1718
1719static void
1720print_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
1782void
1783frv_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. */
1806SI frv_ref_SI (SI ref) {return ref;}
1807#endif /* WITH_PROFILE_MODEL_P */