Search
lxdream.org :: lxdream/src/sh4/pmm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/pmm.c
changeset 929:fd8cb0c82f5f
prev841:808d64b05073
next975:007bf7eb944f
author nkeynes
date Tue Jan 13 11:56:28 2009 +0000 (11 years ago)
permissions -rw-r--r--
last change Merge lxdream-mem branch back to trunk
view annotate diff log raw
     1 /**
     2  * $Id: pmm.c 833 2008-08-18 12:18:10Z nkeynes $
     3  * 
     4  * PMM (performance counter) module
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 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  */
    19 #include "sh4/sh4mmio.h"
    20 #include "sh4/sh4core.h"
    21 #include "clock.h"
    23 /*
    24  * Performance counter list from Paul Mundt's OProfile patch
    25  * Currently only 0x23 is actually supported, since it doesn't require any
    26  * actual instrumentation
    27  * 
    28  *     0x01            Operand read access
    29  *     0x02            Operand write access
    30  *     0x03            UTLB miss
    31  *     0x04            Operand cache read miss
    32  *     0x05            Operand cache write miss
    33  *     0x06            Instruction fetch (w/ cache)
    34  *     0x07            Instruction TLB miss
    35  *     0x08            Instruction cache miss
    36  *     0x09            All operand accesses
    37  *     0x0a            All instruction accesses
    38  *     0x0b            OC RAM operand access
    39  *     0x0d            On-chip I/O space access
    40  *     0x0e            Operand access (r/w)
    41  *     0x0f            Operand cache miss (r/w)
    42  *     0x10            Branch instruction
    43  *     0x11            Branch taken
    44  *     0x12            BSR/BSRF/JSR
    45  *     0x13            Instruction execution
    46  *     0x14            Instruction execution in parallel
    47  *     0x15            FPU Instruction execution
    48  *     0x16            Interrupt
    49  *     0x17            NMI
    50  *     0x18            trapa instruction execution
    51  *     0x19            UBCA match
    52  *     0x1a            UBCB match
    53  *     0x21            Instruction cache fill
    54  *     0x22            Operand cache fill
    55  *     0x23            Elapsed time
    56  *     0x24            Pipeline freeze by I-cache miss
    57  *     0x25            Pipeline freeze by D-cache miss
    58  *     0x27            Pipeline freeze by branch instruction
    59  *     0x28            Pipeline freeze by CPU register
    60  *     0x29            Pipeline freeze by FPU
    61  */
    62 struct PMM_counter_struct {
    63     uint64_t count;
    64     uint32_t mode; /* if running only, otherwise 0 */
    65     uint32_t runfor;
    66 };
    68 static struct PMM_counter_struct PMM_counter[2] = {{0,0},{0,0}};
    70 void PMM_reset(void)
    71 {
    72     PMM_counter[0].count = 0;
    73     PMM_counter[0].mode = 0;
    74     PMM_counter[0].runfor = 0;
    75     PMM_counter[1].count = 0;
    76     PMM_counter[1].mode = 0;
    77     PMM_counter[1].runfor = 0;
    78 }
    80 void PMM_save_state( FILE *f ) {
    81     fwrite( &PMM_counter, sizeof(PMM_counter), 1, f );
    82 }
    84 int PMM_load_state( FILE *f ) 
    85 {
    86     fread( &PMM_counter, sizeof(PMM_counter), 1, f );
    87     return 0;
    88 }
    90 void PMM_count( int ctr, uint32_t runfor )
    91 {
    92     uint32_t delta = runfor - PMM_counter[ctr].runfor;
    94     switch( PMM_counter[ctr].mode ) {
    95     case 0x23:
    96         PMM_counter[ctr].count += (delta / (1000/SH4_BASE_RATE)); 
    97         break;
    98     default:
    99         break;
   100     }
   102     PMM_counter[ctr].runfor = runfor;
   103 }
   105 uint32_t PMM_run_slice( uint32_t nanosecs )
   106 {
   107     PMM_count( 0, nanosecs );
   108     PMM_count( 1, nanosecs );
   109     PMM_counter[0].runfor = 0;
   110     PMM_counter[1].runfor = 0;
   111     return nanosecs;
   112 }
   114 void PMM_write_control( int ctr, uint32_t val )
   115 {
   116     int is_running = ((val & PMCR_RUNNING) == PMCR_RUNNING);
   118     PMM_count(ctr, sh4r.slice_cycle);
   119     if( PMM_counter[ctr].mode == 0 && (val & PMCR_PMCLR) != 0 ) {
   120         PMM_counter[ctr].count = 0;
   121     }
   122     if( is_running ) {
   123         int mode = val & 0x3F;
   124         if( mode != PMM_counter[ctr].mode ) {
   125             /* Instrumentation setup goes here */
   126             PMM_counter[ctr].mode = mode;
   127         }
   128     } else if( PMM_counter[ctr].mode != 0 ) {
   129         /* Instrumentation removal goes here */
   130         PMM_counter[ctr].mode = 0;
   131     }
   132 }
   134 MMIO_REGION_READ_FN( PMM, reg )
   135 {   
   136     switch( reg & 0x1F ) {
   137     case 0: return 0; /* not a register */
   138     case PMCTR1H: 
   139         PMM_count(0, sh4r.slice_cycle);
   140         return ((uint32_t)(PMM_counter[0].count >> 32)) & 0x0000FFFF;
   141     case PMCTR1L: 
   142         PMM_count(0, sh4r.slice_cycle);
   143         return (uint32_t)PMM_counter[0].count;
   144     case PMCTR2H: 
   145         PMM_count(1, sh4r.slice_cycle);
   146         return ((uint32_t)(PMM_counter[1].count >> 32)) & 0x0000FFFF;
   147     default: 
   148         PMM_count(1, sh4r.slice_cycle);
   149         return (uint32_t)PMM_counter[1].count;
   150     }
   151 }
   153 MMIO_REGION_WRITE_FN( PMM, reg, val )
   154 {
   155     /* Read-only */
   156 }
.