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