OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [platform/] [realview/] [perfmon.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Platform specific perfmon initialization
3
 *
4
 * Copyright (C) 2010 B Labs Ltd.
5
 *
6
 * Author: Bahadir Balban
7
 */
8
#include <l4/platform/realview/irq.h>
9
#include <l4/lib/printk.h>
10
#include INC_PLAT(offsets.h)
11
#include INC_SUBARCH(perfmon.h)
12
#include INC_SUBARCH(mmu_ops.h)
13
 
14
/*
15
 * Current findings by these tests:
16
 *
17
 * Cpu cycle count and timer ticks are consistently showing 400Mhz
18
 * with a reference timer tick of 1Mhz. So cycle counts are fixed
19
 * with regard to the timer.
20
 *
21
 * Instruction execute count on the busy_loop however, is varying
22
 * between x1, x2 combinations when compared to timer and cycle
23
 * count values. This is happening by trivial changes in code such
24
 * as adding a function call. (Other variables are ruled out, e.g.
25
 * no concurrent memory accesses, caches are off)
26
 *
27
 * There may be two causes to this:
28
 * - Due to missing dmb/dsb/isb instructions.
29
 * - Due to BTC (busy_loop has one branch) which may describe
30
 * the doubling in IPC, since out of the 2 instructions in the
31
 * busy loop one is a branch.
32
 *
33
 * Disabling the BTC increased cycle counts per instruction
34
 * significantly, advising us not to expect any accuracy in counting
35
 * instructions in cycles. Hence instruction-based tests are
36
 * commented out. It is wise to only rely upon timer and cycle counts.
37
 */
38
 
39
#if 0
40
void busy_loop(int times);
41
 
42
void platform_test_loop_cycles()
43
{
44
        const int looptotal = 1000000;
45
        int cyccnt, loops = looptotal;
46
        int inst_per_loop = 2;
47
        int ipc_whole, ipc_decimal, temp;
48
 
49
        /* Test the basic cycle counter */
50
        perfmon_reset_start_cyccnt();
51
        isb();
52
 
53
        busy_loop(loops);
54
 
55
        /* Finish all earlier instructions */
56
        isb();
57
 
58
        cyccnt = perfmon_read_cyccnt();
59
 
60
        /* Finish reading cyccnt */
61
        isb();
62
 
63
        /*
64
         * Do some fixed point division
65
         *
66
         * The idea is to multiply by 10, divide by 10 and
67
         * get the remainder. Remainder becomes the decimal
68
         * part. The division result is the whole part.
69
         */
70
        temp = inst_per_loop * looptotal * 10 / (cyccnt * 64);
71
        ipc_whole = temp / 10;
72
        ipc_decimal = temp - ipc_whole * 10;
73
 
74
        printk("Perfmon: %d cycles/%d instructions\n",
75
               cyccnt * 64, inst_per_loop * looptotal);
76
        printk("Perfmon: %d.%d Inst/cycle\n",
77
               ipc_whole, ipc_decimal);
78
}
79
 
80
void platform_test_loop_ticks()
81
{
82
        /* Initialize the timer */
83
        unsigned long timer_base =
84
                PLATFORM_TIMER0_VBASE + SP804_TIMER1_OFFSET;
85
        volatile u32 reg = read(timer_base + SP804_CTRL);
86
 
87
        const int looptotal = 500000;
88
        int ticks, loops = looptotal;
89
        int inst_per_loop = 2;
90
        const int timer_load = 0xFFFFFFFF;
91
        int timer_read;
92
        int ipm_whole, ipm_decimal, temp;
93
 
94
        /* Make sure timer is disabled */
95
        write(0, timer_base + SP804_CTRL);
96
 
97
        /* Load the timer with a full value */
98
        write(timer_load, timer_base + SP804_LOAD);
99
 
100
        /* One shot, 32 bits, no irqs */
101
        reg = SP804_32BIT | SP804_ONESHOT | SP804_ENABLE;
102
 
103
        /* Start the timer */
104
        write(reg, timer_base + SP804_CTRL);
105
        dmb(); /* Make sure write occurs before looping */
106
 
107
        busy_loop(loops);
108
 
109
        timer_read = read(timer_base + SP804_VALUE);
110
 
111
        ticks = timer_load - timer_read;
112
 
113
        temp = (inst_per_loop * looptotal) * 10 / ticks;
114
        ipm_whole = temp / 10;
115
        ipm_decimal = temp - ipm_whole * 10;
116
 
117
        printk("Perfmon: %d ticks/%d instructions\n",
118
               ticks, inst_per_loop * looptotal);
119
 
120
        printk("Perfmon: %d%d instr/Mhz.\n",
121
               ipm_whole, ipm_decimal);
122
}
123
 
124
 
125
void platform_test_tick_cycles()
126
{
127
        /* Initialize the timer */
128
        unsigned long timer_base =
129
                PLATFORM_TIMER0_VBASE + SP804_TIMER1_OFFSET;
130
        volatile u32 reg = read(timer_base + SP804_CTRL);
131
        const int timer_load = 1000;
132
        int mhz_top, mhz_bot, temp;
133
        int cyccnt;
134
 
135
        /* Make sure timer is disabled */
136
        write(0, timer_base + SP804_CTRL);
137
 
138
        /* Load the timer with ticks value */
139
        write(timer_load, timer_base + SP804_LOAD);
140
 
141
        /* One shot, 32 bits, no irqs */
142
        reg = SP804_32BIT | SP804_ONESHOT | SP804_ENABLE;
143
 
144
        /* Start the timer */
145
        write(reg, timer_base + SP804_CTRL);
146
 
147
        /* Start counter */
148
        perfmon_reset_start_cyccnt();
149
 
150
        /* Wait until 0 */
151
        while (read(timer_base + SP804_VALUE) != 0)
152
                ;
153
 
154
        cyccnt = perfmon_read_cyccnt();
155
 
156
        /* Fixed-point accuracy on bottom digit */
157
        temp = cyccnt * 64 * 10 / timer_load;
158
        mhz_top = temp / 10;
159
        mhz_bot = temp - mhz_top * 10;
160
 
161
        //printk("Perfmon: %u cycles/%dMhz\n",
162
        //       cyccnt * 64, timer_load);
163
        printk("%s: %d.%d MHz CPU speed measured by timer REFCLK at 1MHz\n",
164
               __KERNELNAME__, mhz_top, mhz_bot);
165
}
166
 
167
#endif
168
 
169
void platform_test_tick_cycles()
170
{
171
        /* Initialize the timer */
172
        const int load_value = 1000;
173
        int mhz_top, mhz_bot, temp;
174
        unsigned long timer_base =
175
                timer_secondary_base(PLATFORM_TIMER0_VBASE);
176
        int cyccnt;
177
 
178
        /* Make sure timer is disabled */
179
        timer_stop(timer_base);
180
 
181
        /* Load the timer with ticks value */
182
        timer_load(load_value, timer_base);
183
 
184
        /* One shot, 32 bits, no irqs */
185
        timer_init_oneshot(timer_base);
186
 
187
        /* Start the timer */
188
        timer_start(timer_base);
189
 
190
        /* Start counter */
191
        perfmon_reset_start_cyccnt();
192
 
193
        /* Wait until 0 */
194
        while (timer_read(timer_base) != 0)
195
                ;
196
 
197
        cyccnt = perfmon_read_cyccnt();
198
 
199
        /* Fixed-point accuracy on bottom digit */
200
        temp = cyccnt * 64 * 10 / load_value;
201
        mhz_top = temp / 10;
202
        mhz_bot = temp - mhz_top * 10;
203
 
204
        //printk("Perfmon: %u cycles/%dMhz\n",
205
        //       cyccnt * 64, timer_load);
206
        printk("%s: %d.%d MHz CPU speed measured by timer REFCLK at 1MHz\n",
207
               __KERNELNAME__, mhz_top, mhz_bot);
208
}
209
 
210
void platform_test_cpucycles(void)
211
{
212
        /*
213
         * Variable results:
214
         *
215
         * platform_test_loop_cycles();
216
         * platform_test_loop_ticks();
217
         */
218
 
219
        /* Fixed result */
220
        platform_test_tick_cycles();
221
}
222
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.