URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [nog_patch_60/] [or1ksim/] [bpb/] [branch_predict.c] - Rev 3
Go to most recent revision | Compare with Previous | Blame | View Log
/* branch_predict.c -- branch prediction simulation Copyright (C) 1999 Damjan Lampret, lampret@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Branch prediction functions. At the moment this functions only simulate functionality of branch prediction and do not influence on fetche/decode/execute stages. They are here only to verify performance of various branch prediction configurations. */ #include <stdio.h> #include <string.h> #include <errno.h> #include <stdarg.h> #include "branch_predict.h" #include "abstract.h" #include "stats.h" /* Branch prediction buffer */ /* Length of BPB */ #define BPB_LEN 32 /* Number of BPB ways (1, 2, 3 etc.). */ #define BPB_WAYS 2 /* Number of prediction states (2, 4, 8 etc.). */ #define BPB_PSTATES 2 /* Number of usage states (2, 3, 4 etc.). */ #define BPB_USTATES 2 /* branch prediction buffer entry */ struct bpb_entry { struct { unsigned long addr; /* address of a branch insn */ int taken; /* taken == 1, not taken == 0 OR */ /* strongly taken == 3, taken == 2, not taken == 1, strongly not taken == 0 */ int lru; /* least recently == 0 */ } way[BPB_WAYS]; } bpb[BPB_LEN]; /* First check if branch is already in the cache and if it is: - increment BPB hit stats, - set 'lru' at this way to BPB_USTATES - 1 and decrement 'lru' of other ways unless they have reached 0, - increment correct/incorrect stats according to BPB 'taken' field and 'taken' variable, - increment or decrement BPB taken field according to 'taken' variable and if not: - increment BPB miss stats - find lru way and entry and replace old address with 'addr' and 'taken' field with (BPB_PSTATES/2 - 1) + 'taken' - set 'lru' with BPB_USTATES - 1 and decrement 'lru' of other ways unless they have reached 0 */ void bpb_update(unsigned long addr, int taken) { int entry, way = -1; int i; /* Calc entry. */ entry = addr % BPB_LEN; /* Scan all ways and try to find our addr. */ for (i = 0; i < BPB_WAYS; i++) if (bpb[entry].way[i].addr == addr) way = i; /* Did we find our cached branch? */ if (way >= 0) { /* Yes, we did. */ mstats.bpb.hit++; for (i = 0; i < BPB_WAYS; i++) if (bpb[entry].way[i].lru) bpb[entry].way[i].lru--; bpb[entry].way[way].lru = BPB_USTATES - 1; if (bpb[entry].way[way].taken / (BPB_PSTATES / 2) == taken) mstats.bpb.correct++; else mstats.bpb.incorrect++; if (taken && (bpb[entry].way[way].taken < BPB_PSTATES - 1)) bpb[entry].way[way].taken++; else if (!taken && (bpb[entry].way[way].taken)) bpb[entry].way[way].taken--; } else { /* No, we didn't. */ int minlru = BPB_USTATES - 1; int minway = 0; mstats.bpb.miss++; for (i = 0; i < BPB_WAYS; i++) if (bpb[entry].way[i].lru < minlru) minway = i; bpb[entry].way[minway].addr = addr; bpb[entry].way[minway].taken = (BPB_PSTATES / 2 - 1) + taken; for (i = 0; i < BPB_WAYS; i++) if (bpb[entry].way[i].lru) bpb[entry].way[i].lru--; bpb[entry].way[minway].lru = BPB_USTATES - 1; } } /* Branch target instruction cache */ /* Length of BTIC */ #define BTIC_LEN 32 /* Number of BTIC ways (1, 2, 3 etc.). */ #define BTIC_WAYS 2 /* Number of usage states (2, 3, 4 etc.). */ #define BTIC_USTATES 2 struct btic_entry { struct { unsigned long addr; /* cached target address of a branch */ int lru; /* least recently used */ char *insn; /* cached insn at target address (not used currently) */ } way[BTIC_WAYS]; } btic[BTIC_LEN]; /* First check if target addr is already in the cache and if it is: - increment BTIC hit stats, - set 'lru' at this way to BTIC_USTATES - 1 and decrement 'lru' of other ways unless they have reached 0, and if not: - increment BTIC miss stats - find lru way and entry and replace old address with 'addr' and 'insn' with NULL - set 'lru' with BTIC_USTATES - 1 and decrement 'lru' of other ways unless they have reached 0 */ void btic_update(unsigned long targetaddr) { int entry, way = -1; int i; /* Calc entry. */ entry = targetaddr % BTIC_LEN; /* Scan all ways and try to find our addr. */ for (i = 0; i < BTIC_WAYS; i++) if (btic[entry].way[i].addr == targetaddr) way = i; /* Did we find our cached branch? */ if (way >= 0) { /* Yes, we did. */ mstats.btic.hit++; for (i = 0; i < BTIC_WAYS; i++) if (btic[entry].way[i].lru) btic[entry].way[i].lru--; btic[entry].way[way].lru = BTIC_USTATES - 1; } else { /* No, we didn't. */ int minlru = BTIC_USTATES - 1; int minway = 0; mstats.btic.miss++; for (i = 0; i < BTIC_WAYS; i++) if (btic[entry].way[i].lru < minlru) minway = i; btic[entry].way[minway].addr = targetaddr; btic[entry].way[minway].insn = NULL; for (i = 0; i < BTIC_WAYS; i++) if (btic[entry].way[i].lru) btic[entry].way[i].lru--; btic[entry].way[minway].lru = BTIC_USTATES - 1; } }
Go to most recent revision | Compare with Previous | Blame | View Log