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