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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [or1ksim/] [bpb/] [branch-predict.c] - Blame information for rev 178

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* branch-predict.c -- branch prediction simulation
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
/* Branch prediction functions.  At the moment this functions only simulate
27
   functionality of branch prediction and do not influence on
28
   fetche/decode/execute stages.  They are here only to verify performance of
29
   various branch prediction configurations. */
30
 
31
 
32
/* Autoconf and/or portability configuration */
33
#include "config.h"
34
#include "port.h"
35
 
36
/* System includes */
37
#include <stdio.h>
38
#include <errno.h>
39
#include <stdarg.h>
40
 
41
/* Package includes */
42
#include "sim-config.h"
43
#include "arch.h"
44
#include "stats.h"
45
 
46
/* Branch prediction buffer */
47
 
48
/* Length of BPB */
49
#define BPB_LEN 64
50
 
51
/* Number of BPB ways (1, 2, 3 etc.). */
52
#define BPB_WAYS 1
53
 
54
/* Number of prediction states (2, 4, 8 etc.). */
55
#define BPB_PSTATES 2
56
 
57
/* Number of usage states (2, 3, 4 etc.). */
58
#define BPB_USTATES 2
59
 
60
/* branch prediction buffer entry */
61
struct bpb_entry
62
{
63
  struct
64
  {
65
    oraddr_t addr;              /* address of a branch insn */
66
    int taken;                  /* taken == 1, not taken == 0  OR */
67
    /* strongly taken == 3, taken == 2,
68
       not taken == 1, strongly not taken == 0 */
69
    int lru;                    /* least recently == 0 */
70
  } way[BPB_WAYS];
71
} bpb[BPB_LEN];
72
 
73
void
74
bpb_info ()
75
{
76
  if (!config.bpb.enabled)
77
    {
78
      PRINTF ("BPB not simulated. Check -bpb option.\n");
79
      return;
80
    }
81
 
82
  PRINTF ("BPB %d bytes: ",
83
          BPB_LEN * BPB_WAYS * (BPB_PSTATES + BPB_USTATES) / 8);
84
  PRINTF ("%d ways, %d sets, %d bits/prediction\n", BPB_WAYS, BPB_LEN,
85
          BPB_PSTATES + BPB_USTATES);
86
}
87
 
88
/* First check if branch is already in the cache and if it is:
89
    - increment BPB hit stats,
90
    - set 'lru' at this way to BPB_USTATES - 1 and
91
      decrement 'lru' of other ways unless they have reached 0,
92
    - increment correct/incorrect stats according to BPB 'taken' field
93
      and 'taken' variable,
94
    - increment or decrement BPB taken field according to 'taken' variable
95
   and if not:
96
    - increment BPB miss stats
97
    - find lru way and entry and replace old address with 'addr' and
98
      'taken' field with (BPB_PSTATES/2 - 1) + 'taken'
99
    - set 'lru' with BPB_USTATES - 1 and decrement 'lru' of other
100
      ways unless they have reached 0
101
*/
102
 
103
void
104
bpb_update (oraddr_t addr, int taken)
105
{
106
  int entry, way = -1;
107
  int i;
108
 
109
  /* BPB simulation enabled/disabled. */
110
  if (!config.bpb.enabled)
111
    return;
112
 
113
  /* Calc entry. */
114
  entry = addr % BPB_LEN;
115
 
116
  /* Scan all ways and try to find our addr. */
117
  for (i = 0; i < BPB_WAYS; i++)
118
    if (bpb[entry].way[i].addr == addr)
119
      way = i;
120
 
121
  /* Did we find our cached branch? */
122
  if (way >= 0)
123
    {                           /* Yes, we did. */
124
      or1k_mstats.bpb.hit++;
125
 
126
      for (i = 0; i < BPB_WAYS; i++)
127
        if (bpb[entry].way[i].lru)
128
          bpb[entry].way[i].lru--;
129
      bpb[entry].way[way].lru = BPB_USTATES - 1;
130
 
131
      if (bpb[entry].way[way].taken / (BPB_PSTATES / 2) == taken)
132
        or1k_mstats.bpb.correct++;
133
      else
134
        or1k_mstats.bpb.incorrect++;
135
 
136
      if (taken && (bpb[entry].way[way].taken < BPB_PSTATES - 1))
137
        bpb[entry].way[way].taken++;
138
      else if (!taken && (bpb[entry].way[way].taken))
139
        bpb[entry].way[way].taken--;
140
    }
141
  else
142
    {                           /* No, we didn't. */
143
      int minlru = BPB_USTATES - 1;
144
      int minway = 0;
145
 
146
      or1k_mstats.bpb.miss++;
147
 
148
      for (i = 0; i < BPB_WAYS; i++)
149
        if (bpb[entry].way[i].lru < minlru)
150
          minway = i;
151
 
152
      bpb[entry].way[minway].addr = addr;
153
      bpb[entry].way[minway].taken = (BPB_PSTATES / 2 - 1) + taken;
154
      for (i = 0; i < BPB_WAYS; i++)
155
        if (bpb[entry].way[i].lru)
156
          bpb[entry].way[i].lru--;
157
      bpb[entry].way[minway].lru = BPB_USTATES - 1;
158
    }
159
}
160
 
161
/* Branch target instruction cache */
162
 
163
/* Length of BTIC */
164
#define BTIC_LEN 128
165
 
166
/* Number of BTIC ways (1, 2, 3 etc.). */
167
#define BTIC_WAYS 2
168
 
169
/* Number of usage states (2, 3, 4 etc.). */
170
#define BTIC_USTATES 2
171
 
172
/* Target block size in bytes. */
173
#define BTIC_BLOCKSIZE 4
174
 
175
struct btic_entry
176
{
177
  struct
178
  {
179
    oraddr_t addr;              /* cached target address of a branch */
180
    int lru;                    /* least recently used */
181
    char *insn;                 /* cached insn at target address (not used currently) */
182
  } way[BTIC_WAYS];
183
} btic[BTIC_LEN];
184
 
185
void
186
btic_info ()
187
{
188
  if (!config.bpb.btic)
189
    {
190
      PRINTF ("BTIC not simulated. Check --btic option.\n");
191
      return;
192
    }
193
 
194
  PRINTF ("BTIC %d bytes: ",
195
          BTIC_LEN * BTIC_WAYS * (BTIC_USTATES + BTIC_BLOCKSIZE * 8) / 8);
196
  PRINTF ("%d ways, %d sets, %d bits/target\n", BTIC_WAYS, BTIC_LEN,
197
          BTIC_USTATES + BTIC_BLOCKSIZE * 8);
198
}
199
 
200
/* First check if target addr is already in the cache and if it is:
201
    - increment BTIC hit stats,
202
    - set 'lru' at this way to BTIC_USTATES - 1 and
203
      decrement 'lru' of other ways unless they have reached 0,
204
   and if not:
205
    - increment BTIC miss stats
206
    - find lru way and entry and replace old address with 'addr' and
207
      'insn' with NULL
208
    - set 'lru' with BTIC_USTATES - 1 and decrement 'lru' of other
209
      ways unless they have reached 0
210
*/
211
 
212
void
213
btic_update (oraddr_t targetaddr)
214
{
215
  int entry, way = -1;
216
  int i;
217
 
218
  /* BTIC simulation enabled/disabled. */
219
  if (!config.bpb.btic)
220
    return;
221
 
222
  /* Calc entry. */
223
  entry = targetaddr % BTIC_LEN;
224
 
225
  /* Scan all ways and try to find our addr. */
226
  for (i = 0; i < BTIC_WAYS; i++)
227
    if (btic[entry].way[i].addr == targetaddr)
228
      way = i;
229
 
230
  /* Did we find our cached branch? */
231
  if (way >= 0)
232
    {                           /* Yes, we did. */
233
      or1k_mstats.btic.hit++;
234
 
235
      for (i = 0; i < BTIC_WAYS; i++)
236
        if (btic[entry].way[i].lru)
237
          btic[entry].way[i].lru--;
238
      btic[entry].way[way].lru = BTIC_USTATES - 1;
239
    }
240
  else
241
    {                           /* No, we didn't. */
242
      int minlru = BTIC_USTATES - 1;
243
      int minway = 0;
244
 
245
      or1k_mstats.btic.miss++;
246
 
247
      for (i = 0; i < BTIC_WAYS; i++)
248
        if (btic[entry].way[i].lru < minlru)
249
          minway = i;
250
 
251
      btic[entry].way[minway].addr = targetaddr;
252
      btic[entry].way[minway].insn = NULL;
253
      for (i = 0; i < BTIC_WAYS; i++)
254
        if (btic[entry].way[i].lru)
255
          btic[entry].way[i].lru--;
256
      btic[entry].way[minway].lru = BTIC_USTATES - 1;
257
    }
258
}
259
 
260
/*----------------------------------------------------[ BPB configuration ]---*/
261
static void
262
bpb_enabled (union param_val val, void *dat)
263
{
264
  config.bpb.enabled = val.int_val;
265
}
266
 
267
static void
268
bpb_btic (union param_val val, void *dat)
269
{
270
  config.bpb.btic = val.int_val;
271
}
272
 
273
static void
274
bpb_sbp_bnf_fwd (union param_val val, void *dat)
275
{
276
  config.bpb.sbp_bnf_fwd = val.int_val;
277
}
278
 
279
static void
280
bpb_sbp_bf_fwd (union param_val val, void *dat)
281
{
282
  config.bpb.sbp_bf_fwd = val.int_val;
283
}
284
 
285
static void
286
bpb_missdelay (union param_val val, void *dat)
287
{
288
  config.bpb.missdelay = val.int_val;
289
}
290
 
291
static void
292
bpb_hitdelay (union param_val val, void *dat)
293
{
294
  config.bpb.hitdelay = val.int_val;
295
}
296
 
297
void
298
reg_bpb_sec ()
299
{
300
  struct config_section *sec = reg_config_sec ("bpb", NULL, NULL);
301
 
302
  reg_config_param (sec, "enabled", paramt_int, bpb_enabled);
303
  reg_config_param (sec, "btic", paramt_int, bpb_btic);
304
  reg_config_param (sec, "sbp_bnf_fwd", paramt_int, bpb_sbp_bnf_fwd);
305
  reg_config_param (sec, "sbp_bf_fwd", paramt_int, bpb_sbp_bf_fwd);
306
  reg_config_param (sec, "missdelay", paramt_int, bpb_missdelay);
307
  reg_config_param (sec, "hitdelay", paramt_int, bpb_hitdelay);
308
}

powered by: WebSVN 2.1.0

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