Search
lxdream.org :: lxdream/src/sh4/pmm.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/pmm.c
changeset 841:808d64b05073
next929:fd8cb0c82f5f
author nkeynes
date Tue Sep 02 11:53:16 2008 +0000 (11 years ago)
permissions -rw-r--r--
last change Initial implementation of the performance counters, only working one for now
is raw clock cycles (0x23)
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/sh4/pmm.c Tue Sep 02 11:53:16 2008 +0000
1.3 @@ -0,0 +1,156 @@
1.4 +/**
1.5 + * $Id: pmm.c 833 2008-08-18 12:18:10Z nkeynes $
1.6 + *
1.7 + * PMM (performance counter) module
1.8 + *
1.9 + * Copyright (c) 2005 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include "sh4/sh4mmio.h"
1.23 +#include "sh4/sh4core.h"
1.24 +#include "clock.h"
1.25 +
1.26 +/*
1.27 + * Performance counter list from Paul Mundt's OProfile patch
1.28 + * Currently only 0x23 is actually supported, since it doesn't require any
1.29 + * actual instrumentation
1.30 + *
1.31 + * 0x01 Operand read access
1.32 + * 0x02 Operand write access
1.33 + * 0x03 UTLB miss
1.34 + * 0x04 Operand cache read miss
1.35 + * 0x05 Operand cache write miss
1.36 + * 0x06 Instruction fetch (w/ cache)
1.37 + * 0x07 Instruction TLB miss
1.38 + * 0x08 Instruction cache miss
1.39 + * 0x09 All operand accesses
1.40 + * 0x0a All instruction accesses
1.41 + * 0x0b OC RAM operand access
1.42 + * 0x0d On-chip I/O space access
1.43 + * 0x0e Operand access (r/w)
1.44 + * 0x0f Operand cache miss (r/w)
1.45 + * 0x10 Branch instruction
1.46 + * 0x11 Branch taken
1.47 + * 0x12 BSR/BSRF/JSR
1.48 + * 0x13 Instruction execution
1.49 + * 0x14 Instruction execution in parallel
1.50 + * 0x15 FPU Instruction execution
1.51 + * 0x16 Interrupt
1.52 + * 0x17 NMI
1.53 + * 0x18 trapa instruction execution
1.54 + * 0x19 UBCA match
1.55 + * 0x1a UBCB match
1.56 + * 0x21 Instruction cache fill
1.57 + * 0x22 Operand cache fill
1.58 + * 0x23 Elapsed time
1.59 + * 0x24 Pipeline freeze by I-cache miss
1.60 + * 0x25 Pipeline freeze by D-cache miss
1.61 + * 0x27 Pipeline freeze by branch instruction
1.62 + * 0x28 Pipeline freeze by CPU register
1.63 + * 0x29 Pipeline freeze by FPU
1.64 + */
1.65 +struct PMM_counter_struct {
1.66 + uint64_t count;
1.67 + uint32_t mode; /* if running only, otherwise 0 */
1.68 + uint32_t runfor;
1.69 +};
1.70 +
1.71 +static struct PMM_counter_struct PMM_counter[2] = {{0,0},{0,0}};
1.72 +
1.73 +void PMM_reset(void)
1.74 +{
1.75 + PMM_counter[0].count = 0;
1.76 + PMM_counter[0].mode = 0;
1.77 + PMM_counter[0].runfor = 0;
1.78 + PMM_counter[1].count = 0;
1.79 + PMM_counter[1].mode = 0;
1.80 + PMM_counter[1].runfor = 0;
1.81 +}
1.82 +
1.83 +void PMM_save_state( FILE *f ) {
1.84 + fwrite( &PMM_counter, sizeof(PMM_counter), 1, f );
1.85 +}
1.86 +
1.87 +int PMM_load_state( FILE *f )
1.88 +{
1.89 + fread( &PMM_counter, sizeof(PMM_counter), 1, f );
1.90 + return 0;
1.91 +}
1.92 +
1.93 +void PMM_count( int ctr, uint32_t runfor )
1.94 +{
1.95 + uint32_t delta = runfor - PMM_counter[ctr].runfor;
1.96 +
1.97 + switch( PMM_counter[ctr].mode ) {
1.98 + case 0x23:
1.99 + PMM_counter[ctr].count += (delta / (1000/SH4_BASE_RATE));
1.100 + break;
1.101 + default:
1.102 + break;
1.103 + }
1.104 +
1.105 + PMM_counter[ctr].runfor = runfor;
1.106 +}
1.107 +
1.108 +uint32_t PMM_run_slice( uint32_t nanosecs )
1.109 +{
1.110 + PMM_count( 0, nanosecs );
1.111 + PMM_count( 1, nanosecs );
1.112 + PMM_counter[0].runfor = 0;
1.113 + PMM_counter[1].runfor = 0;
1.114 + return nanosecs;
1.115 +}
1.116 +
1.117 +void PMM_write_control( int ctr, uint32_t val )
1.118 +{
1.119 + int is_running = ((val & PMCR_RUNNING) == PMCR_RUNNING);
1.120 +
1.121 + PMM_count(ctr, sh4r.slice_cycle);
1.122 + if( PMM_counter[ctr].mode == 0 && (val & PMCR_PMCLR) != 0 ) {
1.123 + PMM_counter[ctr].count = 0;
1.124 + }
1.125 + if( is_running ) {
1.126 + int mode = val & 0x3F;
1.127 + if( mode != PMM_counter[ctr].mode ) {
1.128 + /* Instrumentation setup goes here */
1.129 + PMM_counter[ctr].mode = mode;
1.130 + }
1.131 + } else if( PMM_counter[ctr].mode != 0 ) {
1.132 + /* Instrumentation removal goes here */
1.133 + PMM_counter[ctr].mode = 0;
1.134 + }
1.135 +}
1.136 +
1.137 +int32_t mmio_region_PMM_read( uint32_t reg )
1.138 +{
1.139 + switch( reg & 0x1F ) {
1.140 + case 0: return 0; /* not a register */
1.141 + case PMCTR1H:
1.142 + PMM_count(0, sh4r.slice_cycle);
1.143 + return ((uint32_t)(PMM_counter[0].count >> 32)) & 0x0000FFFF;
1.144 + case PMCTR1L:
1.145 + PMM_count(0, sh4r.slice_cycle);
1.146 + return (uint32_t)PMM_counter[0].count;
1.147 + case PMCTR2H:
1.148 + PMM_count(1, sh4r.slice_cycle);
1.149 + return ((uint32_t)(PMM_counter[1].count >> 32)) & 0x0000FFFF;
1.150 + default:
1.151 + PMM_count(1, sh4r.slice_cycle);
1.152 + return (uint32_t)PMM_counter[1].count;
1.153 + }
1.154 +}
1.155 +
1.156 +void mmio_region_PMM_write( uint32_t reg, uint32_t val )
1.157 +{
1.158 + /* Read-only */
1.159 +}
.