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

Subversion Repositories or1k

[/] [or1k/] [tags/] [or1k-1_0/] [or1ksim/] [bpb/] [branch_predict.c] - Diff between revs 249 and 1765

Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

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