From 4e3426624557b555c354035ee3961eab7554d81d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 4 Jun 2009 21:50:20 -0700 Subject: move: put predictor includes and cc files into the same place --HG-- rename : src/cpu/2bit_local_pred.cc => src/cpu/pred/2bit_local.cc rename : src/cpu/o3/2bit_local_pred.hh => src/cpu/pred/2bit_local.hh rename : src/cpu/btb.cc => src/cpu/pred/btb.cc rename : src/cpu/o3/btb.hh => src/cpu/pred/btb.hh rename : src/cpu/ras.cc => src/cpu/pred/ras.cc rename : src/cpu/o3/ras.hh => src/cpu/pred/ras.hh rename : src/cpu/tournament_pred.cc => src/cpu/pred/tournament.cc rename : src/cpu/o3/tournament_pred.hh => src/cpu/pred/tournament.hh --- src/cpu/pred/2bit_local.cc | 146 ++++++++++++++++++++++ src/cpu/pred/2bit_local.hh | 110 +++++++++++++++++ src/cpu/pred/SConscript | 38 ++++++ src/cpu/pred/btb.cc | 134 ++++++++++++++++++++ src/cpu/pred/btb.hh | 129 ++++++++++++++++++++ src/cpu/pred/ras.cc | 84 +++++++++++++ src/cpu/pred/ras.hh | 100 +++++++++++++++ src/cpu/pred/tournament.cc | 297 +++++++++++++++++++++++++++++++++++++++++++++ src/cpu/pred/tournament.hh | 221 +++++++++++++++++++++++++++++++++ 9 files changed, 1259 insertions(+) create mode 100644 src/cpu/pred/2bit_local.cc create mode 100644 src/cpu/pred/2bit_local.hh create mode 100644 src/cpu/pred/SConscript create mode 100644 src/cpu/pred/btb.cc create mode 100644 src/cpu/pred/btb.hh create mode 100644 src/cpu/pred/ras.cc create mode 100644 src/cpu/pred/ras.hh create mode 100644 src/cpu/pred/tournament.cc create mode 100644 src/cpu/pred/tournament.hh (limited to 'src/cpu/pred') diff --git a/src/cpu/pred/2bit_local.cc b/src/cpu/pred/2bit_local.cc new file mode 100644 index 000000000..65925fe79 --- /dev/null +++ b/src/cpu/pred/2bit_local.cc @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "base/intmath.hh" +#include "base/misc.hh" +#include "base/trace.hh" +#include "cpu/pred/2bit_local.hh" + +LocalBP::LocalBP(unsigned _localPredictorSize, + unsigned _localCtrBits, + unsigned _instShiftAmt) + : localPredictorSize(_localPredictorSize), + localCtrBits(_localCtrBits), + instShiftAmt(_instShiftAmt) +{ + if (!isPowerOf2(localPredictorSize)) { + fatal("Invalid local predictor size!\n"); + } + + localPredictorSets = localPredictorSize / localCtrBits; + + if (!isPowerOf2(localPredictorSets)) { + fatal("Invalid number of local predictor sets! Check localCtrBits.\n"); + } + + // Setup the index mask. + indexMask = localPredictorSets - 1; + + DPRINTF(Fetch, "Branch predictor: index mask: %#x\n", indexMask); + + // Setup the array of counters for the local predictor. + localCtrs.resize(localPredictorSets); + + for (int i = 0; i < localPredictorSets; ++i) + localCtrs[i].setBits(_localCtrBits); + + DPRINTF(Fetch, "Branch predictor: local predictor size: %i\n", + localPredictorSize); + + DPRINTF(Fetch, "Branch predictor: local counter bits: %i\n", localCtrBits); + + DPRINTF(Fetch, "Branch predictor: instruction shift amount: %i\n", + instShiftAmt); +} + +void +LocalBP::reset() +{ + for (int i = 0; i < localPredictorSets; ++i) { + localCtrs[i].reset(); + } +} + +bool +LocalBP::lookup(Addr &branch_addr, void * &bp_history) +{ + bool taken; + uint8_t counter_val; + unsigned local_predictor_idx = getLocalIndex(branch_addr); + + DPRINTF(Fetch, "Branch predictor: Looking up index %#x\n", + local_predictor_idx); + + counter_val = localCtrs[local_predictor_idx].read(); + + DPRINTF(Fetch, "Branch predictor: prediction is %i.\n", + (int)counter_val); + + taken = getPrediction(counter_val); + +#if 0 + // Speculative update. + if (taken) { + DPRINTF(Fetch, "Branch predictor: Branch updated as taken.\n"); + localCtrs[local_predictor_idx].increment(); + } else { + DPRINTF(Fetch, "Branch predictor: Branch updated as not taken.\n"); + localCtrs[local_predictor_idx].decrement(); + } +#endif + + return taken; +} + +void +LocalBP::update(Addr &branch_addr, bool taken, void *bp_history) +{ + assert(bp_history == NULL); + unsigned local_predictor_idx; + + // Update the local predictor. + local_predictor_idx = getLocalIndex(branch_addr); + + DPRINTF(Fetch, "Branch predictor: Looking up index %#x\n", + local_predictor_idx); + + if (taken) { + DPRINTF(Fetch, "Branch predictor: Branch updated as taken.\n"); + localCtrs[local_predictor_idx].increment(); + } else { + DPRINTF(Fetch, "Branch predictor: Branch updated as not taken.\n"); + localCtrs[local_predictor_idx].decrement(); + } +} + +inline +bool +LocalBP::getPrediction(uint8_t &count) +{ + // Get the MSB of the count + return (count >> (localCtrBits - 1)); +} + +inline +unsigned +LocalBP::getLocalIndex(Addr &branch_addr) +{ + return (branch_addr >> instShiftAmt) & indexMask; +} diff --git a/src/cpu/pred/2bit_local.hh b/src/cpu/pred/2bit_local.hh new file mode 100644 index 000000000..8b7bb8463 --- /dev/null +++ b/src/cpu/pred/2bit_local.hh @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_O3_2BIT_LOCAL_PRED_HH__ +#define __CPU_O3_2BIT_LOCAL_PRED_HH__ + +#include + +#include "base/types.hh" +#include "cpu/o3/sat_counter.hh" + +/** + * Implements a local predictor that uses the PC to index into a table of + * counters. Note that any time a pointer to the bp_history is given, it + * should be NULL using this predictor because it does not have any branch + * predictor state that needs to be recorded or updated; the update can be + * determined solely by the branch being taken or not taken. + */ +class LocalBP +{ + public: + /** + * Default branch predictor constructor. + * @param localPredictorSize Size of the local predictor. + * @param localCtrBits Number of bits per counter. + * @param instShiftAmt Offset amount for instructions to ignore alignment. + */ + LocalBP(unsigned localPredictorSize, unsigned localCtrBits, + unsigned instShiftAmt); + + /** + * Looks up the given address in the branch predictor and returns + * a true/false value as to whether it is taken. + * @param branch_addr The address of the branch to look up. + * @param bp_history Pointer to any bp history state. + * @return Whether or not the branch is taken. + */ + bool lookup(Addr &branch_addr, void * &bp_history); + + /** + * Updates the branch predictor with the actual result of a branch. + * @param branch_addr The address of the branch to update. + * @param taken Whether or not the branch was taken. + */ + void update(Addr &branch_addr, bool taken, void *bp_history); + + void squash(void *bp_history) + { assert(bp_history == NULL); } + + void reset(); + + private: + /** + * Returns the taken/not taken prediction given the value of the + * counter. + * @param count The value of the counter. + * @return The prediction based on the counter value. + */ + inline bool getPrediction(uint8_t &count); + + /** Calculates the local index based on the PC. */ + inline unsigned getLocalIndex(Addr &PC); + + /** Array of counters that make up the local predictor. */ + std::vector localCtrs; + + /** Size of the local predictor. */ + unsigned localPredictorSize; + + /** Number of sets. */ + unsigned localPredictorSets; + + /** Number of bits of the local predictor's counters. */ + unsigned localCtrBits; + + /** Number of bits to shift the PC when calculating index. */ + unsigned instShiftAmt; + + /** Mask to get index bits. */ + unsigned indexMask; +}; + +#endif // __CPU_O3_2BIT_LOCAL_PRED_HH__ diff --git a/src/cpu/pred/SConscript b/src/cpu/pred/SConscript new file mode 100644 index 000000000..ce1dab9e2 --- /dev/null +++ b/src/cpu/pred/SConscript @@ -0,0 +1,38 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt + +Import('*') + +if 'InOrderCPU' in env['CPU_MODELS'] or 'O3CPU' in env['CPU_MODELS']: + Source('2bit_local.cc') + Source('btb.cc') + Source('ras.cc') + Source('tournament.cc') + TraceFlag('FreeList') diff --git a/src/cpu/pred/btb.cc b/src/cpu/pred/btb.cc new file mode 100644 index 000000000..81676aceb --- /dev/null +++ b/src/cpu/pred/btb.cc @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "base/intmath.hh" +#include "base/trace.hh" +#include "cpu/pred/btb.hh" + +DefaultBTB::DefaultBTB(unsigned _numEntries, + unsigned _tagBits, + unsigned _instShiftAmt) + : numEntries(_numEntries), + tagBits(_tagBits), + instShiftAmt(_instShiftAmt) +{ + DPRINTF(Fetch, "BTB: Creating BTB object.\n"); + + if (!isPowerOf2(numEntries)) { + fatal("BTB entries is not a power of 2!"); + } + + btb.resize(numEntries); + + for (int i = 0; i < numEntries; ++i) { + btb[i].valid = false; + } + + idxMask = numEntries - 1; + + tagMask = (1 << tagBits) - 1; + + tagShiftAmt = instShiftAmt + floorLog2(numEntries); +} + +void +DefaultBTB::reset() +{ + for (int i = 0; i < numEntries; ++i) { + btb[i].valid = false; + } +} + +inline +unsigned +DefaultBTB::getIndex(const Addr &inst_PC) +{ + // Need to shift PC over by the word offset. + return (inst_PC >> instShiftAmt) & idxMask; +} + +inline +Addr +DefaultBTB::getTag(const Addr &inst_PC) +{ + return (inst_PC >> tagShiftAmt) & tagMask; +} + +bool +DefaultBTB::valid(const Addr &inst_PC, ThreadID tid) +{ + unsigned btb_idx = getIndex(inst_PC); + + Addr inst_tag = getTag(inst_PC); + + assert(btb_idx < numEntries); + + if (btb[btb_idx].valid + && inst_tag == btb[btb_idx].tag + && btb[btb_idx].tid == tid) { + return true; + } else { + return false; + } +} + +// @todo Create some sort of return struct that has both whether or not the +// address is valid, and also the address. For now will just use addr = 0 to +// represent invalid entry. +Addr +DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid) +{ + unsigned btb_idx = getIndex(inst_PC); + + Addr inst_tag = getTag(inst_PC); + + assert(btb_idx < numEntries); + + if (btb[btb_idx].valid + && inst_tag == btb[btb_idx].tag + && btb[btb_idx].tid == tid) { + return btb[btb_idx].target; + } else { + return 0; + } +} + +void +DefaultBTB::update(const Addr &inst_PC, const Addr &target, ThreadID tid) +{ + unsigned btb_idx = getIndex(inst_PC); + + assert(btb_idx < numEntries); + + btb[btb_idx].tid = tid; + btb[btb_idx].valid = true; + btb[btb_idx].target = target; + btb[btb_idx].tag = getTag(inst_PC); +} diff --git a/src/cpu/pred/btb.hh b/src/cpu/pred/btb.hh new file mode 100644 index 000000000..6557522e0 --- /dev/null +++ b/src/cpu/pred/btb.hh @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_O3_BTB_HH__ +#define __CPU_O3_BTB_HH__ + +#include "base/misc.hh" +#include "base/types.hh" + +class DefaultBTB +{ + private: + struct BTBEntry + { + BTBEntry() + : tag(0), target(0), valid(false) + { + } + + /** The entry's tag. */ + Addr tag; + + /** The entry's target. */ + Addr target; + + /** The entry's thread id. */ + ThreadID tid; + + /** Whether or not the entry is valid. */ + bool valid; + }; + + public: + /** Creates a BTB with the given number of entries, number of bits per + * tag, and instruction offset amount. + * @param numEntries Number of entries for the BTB. + * @param tagBits Number of bits for each tag in the BTB. + * @param instShiftAmt Offset amount for instructions to ignore alignment. + */ + DefaultBTB(unsigned numEntries, unsigned tagBits, + unsigned instShiftAmt); + + void reset(); + + /** Looks up an address in the BTB. Must call valid() first on the address. + * @param inst_PC The address of the branch to look up. + * @param tid The thread id. + * @return Returns the target of the branch. + */ + Addr lookup(const Addr &inst_PC, ThreadID tid); + + /** Checks if a branch is in the BTB. + * @param inst_PC The address of the branch to look up. + * @param tid The thread id. + * @return Whether or not the branch exists in the BTB. + */ + bool valid(const Addr &inst_PC, ThreadID tid); + + /** Updates the BTB with the target of a branch. + * @param inst_PC The address of the branch being updated. + * @param target_PC The target address of the branch. + * @param tid The thread id. + */ + void update(const Addr &inst_PC, const Addr &target_PC, + ThreadID tid); + + private: + /** Returns the index into the BTB, based on the branch's PC. + * @param inst_PC The branch to look up. + * @return Returns the index into the BTB. + */ + inline unsigned getIndex(const Addr &inst_PC); + + /** Returns the tag bits of a given address. + * @param inst_PC The branch's address. + * @return Returns the tag bits. + */ + inline Addr getTag(const Addr &inst_PC); + + /** The actual BTB. */ + std::vector btb; + + /** The number of entries in the BTB. */ + unsigned numEntries; + + /** The index mask. */ + unsigned idxMask; + + /** The number of tag bits per entry. */ + unsigned tagBits; + + /** The tag mask. */ + unsigned tagMask; + + /** Number of bits to shift PC when calculating index. */ + unsigned instShiftAmt; + + /** Number of bits to shift PC when calculating tag. */ + unsigned tagShiftAmt; +}; + +#endif // __CPU_O3_BTB_HH__ diff --git a/src/cpu/pred/ras.cc b/src/cpu/pred/ras.cc new file mode 100644 index 000000000..5af188749 --- /dev/null +++ b/src/cpu/pred/ras.cc @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "cpu/pred/ras.hh" + +void +ReturnAddrStack::init(unsigned _numEntries) +{ + numEntries = _numEntries; + usedEntries = 0; + tos = 0; + + addrStack.resize(numEntries); + + for (int i = 0; i < numEntries; ++i) + addrStack[i] = 0; +} + +void +ReturnAddrStack::reset() +{ + usedEntries = 0; + tos = 0; + for (int i = 0; i < numEntries; ++i) + addrStack[i] = 0; +} + +void +ReturnAddrStack::push(const Addr &return_addr) +{ + incrTos(); + + addrStack[tos] = return_addr; + + if (usedEntries != numEntries) { + ++usedEntries; + } +} + +void +ReturnAddrStack::pop() +{ + if (usedEntries > 0) { + --usedEntries; + } + + decrTos(); +} + +void +ReturnAddrStack::restore(unsigned top_entry_idx, + const Addr &restored_target) +{ + tos = top_entry_idx; + + addrStack[tos] = restored_target; +} diff --git a/src/cpu/pred/ras.hh b/src/cpu/pred/ras.hh new file mode 100644 index 000000000..a36faf79a --- /dev/null +++ b/src/cpu/pred/ras.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_O3_RAS_HH__ +#define __CPU_O3_RAS_HH__ + +#include + +#include "base/types.hh" + +/** Return address stack class, implements a simple RAS. */ +class ReturnAddrStack +{ + public: + /** Creates a return address stack, but init() must be called prior to + * use. + */ + ReturnAddrStack() {} + + /** Initializes RAS with a specified number of entries. + * @param numEntries Number of entries in the RAS. + */ + void init(unsigned numEntries); + + void reset(); + + /** Returns the top address on the RAS. */ + Addr top() + { return addrStack[tos]; } + + /** Returns the index of the top of the RAS. */ + unsigned topIdx() + { return tos; } + + /** Pushes an address onto the RAS. */ + void push(const Addr &return_addr); + + /** Pops the top address from the RAS. */ + void pop(); + + /** Changes index to the top of the RAS, and replaces the top address with + * a new target. + * @param top_entry_idx The index of the RAS that will now be the top. + * @param restored_target The new target address of the new top of the RAS. + */ + void restore(unsigned top_entry_idx, const Addr &restored_target); + + bool empty() { return usedEntries == 0; } + + bool full() { return usedEntries == numEntries; } + private: + /** Increments the top of stack index. */ + inline void incrTos() + { if (++tos == numEntries) tos = 0; } + + /** Decrements the top of stack index. */ + inline void decrTos() + { tos = (tos == 0 ? numEntries - 1 : tos - 1); } + + /** The RAS itself. */ + std::vector addrStack; + + /** The number of entries in the RAS. */ + unsigned numEntries; + + /** The number of used entries in the RAS. */ + unsigned usedEntries; + + /** The top of stack index. */ + unsigned tos; +}; + +#endif // __CPU_O3_RAS_HH__ diff --git a/src/cpu/pred/tournament.cc b/src/cpu/pred/tournament.cc new file mode 100644 index 000000000..223e45333 --- /dev/null +++ b/src/cpu/pred/tournament.cc @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "base/intmath.hh" +#include "cpu/pred/tournament.hh" + +TournamentBP::TournamentBP(unsigned _localPredictorSize, + unsigned _localCtrBits, + unsigned _localHistoryTableSize, + unsigned _localHistoryBits, + unsigned _globalPredictorSize, + unsigned _globalCtrBits, + unsigned _globalHistoryBits, + unsigned _choicePredictorSize, + unsigned _choiceCtrBits, + unsigned _instShiftAmt) + : localPredictorSize(_localPredictorSize), + localCtrBits(_localCtrBits), + localHistoryTableSize(_localHistoryTableSize), + localHistoryBits(_localHistoryBits), + globalPredictorSize(_globalPredictorSize), + globalCtrBits(_globalCtrBits), + globalHistoryBits(_globalHistoryBits), + choicePredictorSize(_globalPredictorSize), + choiceCtrBits(_choiceCtrBits), + instShiftAmt(_instShiftAmt) +{ + if (!isPowerOf2(localPredictorSize)) { + fatal("Invalid local predictor size!\n"); + } + + //Setup the array of counters for the local predictor + localCtrs.resize(localPredictorSize); + + for (int i = 0; i < localPredictorSize; ++i) + localCtrs[i].setBits(localCtrBits); + + localPredictorMask = floorPow2(localPredictorSize) - 1; + + if (!isPowerOf2(localHistoryTableSize)) { + fatal("Invalid local history table size!\n"); + } + + //Setup the history table for the local table + localHistoryTable.resize(localHistoryTableSize); + + for (int i = 0; i < localHistoryTableSize; ++i) + localHistoryTable[i] = 0; + + // Setup the local history mask + localHistoryMask = (1 << localHistoryBits) - 1; + + if (!isPowerOf2(globalPredictorSize)) { + fatal("Invalid global predictor size!\n"); + } + + //Setup the array of counters for the global predictor + globalCtrs.resize(globalPredictorSize); + + for (int i = 0; i < globalPredictorSize; ++i) + globalCtrs[i].setBits(globalCtrBits); + + //Clear the global history + globalHistory = 0; + // Setup the global history mask + globalHistoryMask = (1 << globalHistoryBits) - 1; + + if (!isPowerOf2(choicePredictorSize)) { + fatal("Invalid choice predictor size!\n"); + } + + //Setup the array of counters for the choice predictor + choiceCtrs.resize(choicePredictorSize); + + for (int i = 0; i < choicePredictorSize; ++i) + choiceCtrs[i].setBits(choiceCtrBits); + + // @todo: Allow for different thresholds between the predictors. + threshold = (1 << (localCtrBits - 1)) - 1; + threshold = threshold / 2; +} + +inline +unsigned +TournamentBP::calcLocHistIdx(Addr &branch_addr) +{ + // Get low order bits after removing instruction offset. + return (branch_addr >> instShiftAmt) & (localHistoryTableSize - 1); +} + +inline +void +TournamentBP::updateGlobalHistTaken() +{ + globalHistory = (globalHistory << 1) | 1; + globalHistory = globalHistory & globalHistoryMask; +} + +inline +void +TournamentBP::updateGlobalHistNotTaken() +{ + globalHistory = (globalHistory << 1); + globalHistory = globalHistory & globalHistoryMask; +} + +inline +void +TournamentBP::updateLocalHistTaken(unsigned local_history_idx) +{ + localHistoryTable[local_history_idx] = + (localHistoryTable[local_history_idx] << 1) | 1; +} + +inline +void +TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx) +{ + localHistoryTable[local_history_idx] = + (localHistoryTable[local_history_idx] << 1); +} + +bool +TournamentBP::lookup(Addr &branch_addr, void * &bp_history) +{ + bool local_prediction; + unsigned local_history_idx; + unsigned local_predictor_idx; + + bool global_prediction; + bool choice_prediction; + + //Lookup in the local predictor to get its branch prediction + local_history_idx = calcLocHistIdx(branch_addr); + local_predictor_idx = localHistoryTable[local_history_idx] + & localPredictorMask; + local_prediction = localCtrs[local_predictor_idx].read() > threshold; + + //Lookup in the global predictor to get its branch prediction + global_prediction = globalCtrs[globalHistory].read() > threshold; + + //Lookup in the choice predictor to see which one to use + choice_prediction = choiceCtrs[globalHistory].read() > threshold; + + // Create BPHistory and pass it back to be recorded. + BPHistory *history = new BPHistory; + history->globalHistory = globalHistory; + history->localPredTaken = local_prediction; + history->globalPredTaken = global_prediction; + history->globalUsed = choice_prediction; + bp_history = (void *)history; + + assert(globalHistory < globalPredictorSize && + local_history_idx < localHistoryTableSize && + local_predictor_idx < localPredictorSize); + + // Commented code is for doing speculative update of counters and + // all histories. + if (choice_prediction) { + if (global_prediction) { +// updateHistoriesTaken(local_history_idx); +// globalCtrs[globalHistory].increment(); +// localCtrs[local_history_idx].increment(); + updateGlobalHistTaken(); + return true; + } else { +// updateHistoriesNotTaken(local_history_idx); +// globalCtrs[globalHistory].decrement(); +// localCtrs[local_history_idx].decrement(); + updateGlobalHistNotTaken(); + return false; + } + } else { + if (local_prediction) { +// updateHistoriesTaken(local_history_idx); +// globalCtrs[globalHistory].increment(); +// localCtrs[local_history_idx].increment(); + updateGlobalHistTaken(); + return true; + } else { +// updateHistoriesNotTaken(local_history_idx); +// globalCtrs[globalHistory].decrement(); +// localCtrs[local_history_idx].decrement(); + updateGlobalHistNotTaken(); + return false; + } + } +} + +void +TournamentBP::uncondBr(void * &bp_history) +{ + // Create BPHistory and pass it back to be recorded. + BPHistory *history = new BPHistory; + history->globalHistory = globalHistory; + history->localPredTaken = true; + history->globalPredTaken = true; + bp_history = static_cast(history); + + updateGlobalHistTaken(); +} + +void +TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history) +{ + unsigned local_history_idx; + unsigned local_predictor_idx; + unsigned local_predictor_hist; + + // Get the local predictor's current prediction + local_history_idx = calcLocHistIdx(branch_addr); + local_predictor_hist = localHistoryTable[local_history_idx]; + local_predictor_idx = local_predictor_hist & localPredictorMask; + + // Update the choice predictor to tell it which one was correct if + // there was a prediction. + if (bp_history) { + BPHistory *history = static_cast(bp_history); + if (history->localPredTaken != history->globalPredTaken) { + // If the local prediction matches the actual outcome, + // decerement the counter. Otherwise increment the + // counter. + if (history->localPredTaken == taken) { + choiceCtrs[globalHistory].decrement(); + } else if (history->globalPredTaken == taken){ + choiceCtrs[globalHistory].increment(); + } + } + + // We're done with this history, now delete it. + delete history; + } + + assert(globalHistory < globalPredictorSize && + local_history_idx < localHistoryTableSize && + local_predictor_idx < localPredictorSize); + + // Update the counters and local history with the proper + // resolution of the branch. Global history is updated + // speculatively and restored upon squash() calls, so it does not + // need to be updated. + if (taken) { + localCtrs[local_predictor_idx].increment(); + globalCtrs[globalHistory].increment(); + + updateLocalHistTaken(local_history_idx); + } else { + localCtrs[local_predictor_idx].decrement(); + globalCtrs[globalHistory].decrement(); + + updateLocalHistNotTaken(local_history_idx); + } +} + +void +TournamentBP::squash(void *bp_history) +{ + BPHistory *history = static_cast(bp_history); + + // Restore global history to state prior to this branch. + globalHistory = history->globalHistory; + + // Delete this BPHistory now that we're done with it. + delete history; +} + +#ifdef DEBUG +int +TournamentBP::BPHistory::newCount = 0; +#endif diff --git a/src/cpu/pred/tournament.hh b/src/cpu/pred/tournament.hh new file mode 100644 index 000000000..96bd43ed6 --- /dev/null +++ b/src/cpu/pred/tournament.hh @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_O3_TOURNAMENT_PRED_HH__ +#define __CPU_O3_TOURNAMENT_PRED_HH__ + +#include + +#include "base/types.hh" +#include "cpu/o3/sat_counter.hh" + +/** + * Implements a tournament branch predictor, hopefully identical to the one + * used in the 21264. It has a local predictor, which uses a local history + * table to index into a table of counters, and a global predictor, which + * uses a global history to index into a table of counters. A choice + * predictor chooses between the two. Only the global history register + * is speculatively updated, the rest are updated upon branches committing + * or misspeculating. + */ +class TournamentBP +{ + public: + /** + * Default branch predictor constructor. + */ + TournamentBP(unsigned localPredictorSize, + unsigned localCtrBits, + unsigned localHistoryTableSize, + unsigned localHistoryBits, + unsigned globalPredictorSize, + unsigned globalHistoryBits, + unsigned globalCtrBits, + unsigned choicePredictorSize, + unsigned choiceCtrBits, + unsigned instShiftAmt); + + /** + * Looks up the given address in the branch predictor and returns + * a true/false value as to whether it is taken. Also creates a + * BPHistory object to store any state it will need on squash/update. + * @param branch_addr The address of the branch to look up. + * @param bp_history Pointer that will be set to the BPHistory object. + * @return Whether or not the branch is taken. + */ + bool lookup(Addr &branch_addr, void * &bp_history); + + /** + * Records that there was an unconditional branch, and modifies + * the bp history to point to an object that has the previous + * global history stored in it. + * @param bp_history Pointer that will be set to the BPHistory object. + */ + void uncondBr(void * &bp_history); + + /** + * Updates the branch predictor with the actual result of a branch. + * @param branch_addr The address of the branch to update. + * @param taken Whether or not the branch was taken. + * @param bp_history Pointer to the BPHistory object that was created + * when the branch was predicted. + */ + void update(Addr &branch_addr, bool taken, void *bp_history); + + /** + * Restores the global branch history on a squash. + * @param bp_history Pointer to the BPHistory object that has the + * previous global branch history in it. + */ + void squash(void *bp_history); + + /** Returns the global history. */ + inline unsigned readGlobalHist() { return globalHistory; } + + private: + /** + * Returns if the branch should be taken or not, given a counter + * value. + * @param count The counter value. + */ + inline bool getPrediction(uint8_t &count); + + /** + * Returns the local history index, given a branch address. + * @param branch_addr The branch's PC address. + */ + inline unsigned calcLocHistIdx(Addr &branch_addr); + + /** Updates global history as taken. */ + inline void updateGlobalHistTaken(); + + /** Updates global history as not taken. */ + inline void updateGlobalHistNotTaken(); + + /** + * Updates local histories as taken. + * @param local_history_idx The local history table entry that + * will be updated. + */ + inline void updateLocalHistTaken(unsigned local_history_idx); + + /** + * Updates local histories as not taken. + * @param local_history_idx The local history table entry that + * will be updated. + */ + inline void updateLocalHistNotTaken(unsigned local_history_idx); + + /** + * The branch history information that is created upon predicting + * a branch. It will be passed back upon updating and squashing, + * when the BP can use this information to update/restore its + * state properly. + */ + struct BPHistory { +#ifdef DEBUG + BPHistory() + { newCount++; } + ~BPHistory() + { newCount--; } + + static int newCount; +#endif + unsigned globalHistory; + bool localPredTaken; + bool globalPredTaken; + bool globalUsed; + }; + + /** Local counters. */ + std::vector localCtrs; + + /** Size of the local predictor. */ + unsigned localPredictorSize; + + /** Mask to get the proper index bits into the predictor. */ + unsigned localPredictorMask; + + /** Number of bits of the local predictor's counters. */ + unsigned localCtrBits; + + /** Array of local history table entries. */ + std::vector localHistoryTable; + + /** Size of the local history table. */ + unsigned localHistoryTableSize; + + /** Number of bits for each entry of the local history table. + * @todo Doesn't this come from the size of the local predictor? + */ + unsigned localHistoryBits; + + /** Mask to get the proper local history. */ + unsigned localHistoryMask; + + /** Array of counters that make up the global predictor. */ + std::vector globalCtrs; + + /** Size of the global predictor. */ + unsigned globalPredictorSize; + + /** Number of bits of the global predictor's counters. */ + unsigned globalCtrBits; + + /** Global history register. */ + unsigned globalHistory; + + /** Number of bits for the global history. */ + unsigned globalHistoryBits; + + /** Mask to get the proper global history. */ + unsigned globalHistoryMask; + + /** Array of counters that make up the choice predictor. */ + std::vector choiceCtrs; + + /** Size of the choice predictor (identical to the global predictor). */ + unsigned choicePredictorSize; + + /** Number of bits of the choice predictor's counters. */ + unsigned choiceCtrBits; + + /** Number of bits to shift the instruction over to get rid of the word + * offset. + */ + unsigned instShiftAmt; + + /** Threshold for the counter value; above the threshold is taken, + * equal to or below the threshold is not taken. + */ + unsigned threshold; +}; + +#endif // __CPU_O3_TOURNAMENT_PRED_HH__ -- cgit v1.2.3