2fb632dbda
branch prediction, and makes memory dependence work properly. SConscript: Added return address stack, tournament predictor. cpu/base_cpu.cc: Added debug break and print statements. cpu/base_dyn_inst.cc: cpu/base_dyn_inst.hh: Comment out possibly unneeded variables. cpu/beta_cpu/2bit_local_pred.cc: 2bit predictor no longer speculatively updates itself. cpu/beta_cpu/alpha_dyn_inst.hh: Comment formatting. cpu/beta_cpu/alpha_full_cpu.hh: Formatting cpu/beta_cpu/alpha_full_cpu_builder.cc: Added new parameters for branch predictors, and IQ parameters. cpu/beta_cpu/alpha_full_cpu_impl.hh: Register stats. cpu/beta_cpu/alpha_params.hh: Added parameters for IQ, branch predictors, and store sets. cpu/beta_cpu/bpred_unit.cc: Removed one class. cpu/beta_cpu/bpred_unit.hh: Add in RAS, stats. Changed branch predictor unit functionality so that it holds a history of past branches so it can update, and also hold a proper history of the RAS so it can be restored on branch mispredicts. cpu/beta_cpu/bpred_unit_impl.hh: Added in stats, history of branches, RAS. Now bpred unit actually modifies the instruction's predicted next PC. cpu/beta_cpu/btb.cc: Add in sanity checks. cpu/beta_cpu/comm.hh: Add in communication where needed, remove it where it's not. cpu/beta_cpu/commit.hh: cpu/beta_cpu/rename.hh: cpu/beta_cpu/rename_impl.hh: Add in stats. cpu/beta_cpu/commit_impl.hh: Stats, update what is sent back on branch mispredict. cpu/beta_cpu/cpu_policy.hh: Change the bpred unit being used. cpu/beta_cpu/decode.hh: cpu/beta_cpu/decode_impl.hh: Stats. cpu/beta_cpu/fetch.hh: Stats, change squash so it can handle squashes from decode differently than squashes from commit. cpu/beta_cpu/fetch_impl.hh: Add in stats. Change how a cache line is fetched. Update to work with caches. Also have separate functions for different behavior if squash is coming from decode vs commit. cpu/beta_cpu/free_list.hh: Remove some old comments. cpu/beta_cpu/full_cpu.cc: cpu/beta_cpu/full_cpu.hh: Added function to remove instructions from back of instruction list until a certain sequence number. cpu/beta_cpu/iew.hh: Stats, separate squashing behavior due to branches vs memory. cpu/beta_cpu/iew_impl.hh: Stats, separate squashing behavior for branches vs memory. cpu/beta_cpu/inst_queue.cc: Debug stuff cpu/beta_cpu/inst_queue.hh: Stats, change how mem dep unit works, debug stuff cpu/beta_cpu/inst_queue_impl.hh: Stats, change how mem dep unit works, debug stuff. Also add in parameters that used to be hardcoded. cpu/beta_cpu/mem_dep_unit.hh: cpu/beta_cpu/mem_dep_unit_impl.hh: Add in stats, change how memory dependence unit works. It now holds the memory instructions that are waiting for their memory dependences to resolve. It provides which instructions are ready directly to the IQ. cpu/beta_cpu/regfile.hh: Fix up sanity checks. cpu/beta_cpu/rename_map.cc: Fix loop variable type. cpu/beta_cpu/rob_impl.hh: Remove intermediate DynInstPtr cpu/beta_cpu/store_set.cc: Add in debugging statements. cpu/beta_cpu/store_set.hh: Reorder function arguments to match the rest of the calls. --HG-- extra : convert_revision : aabf9b1fecd1d743265dfc3b174d6159937c6f44
315 lines
10 KiB
C++
315 lines
10 KiB
C++
|
|
#include "cpu/beta_cpu/rename_map.hh"
|
|
|
|
// Todo: Consider making functions inline. Avoid having things that are
|
|
// using the zero register or misc registers from adding on the registers
|
|
// to the free list. Possibly remove the direct communication between
|
|
// this and the freelist. Considering making inline bool functions that
|
|
// determine if the register is a logical int, logical fp, physical int,
|
|
// physical fp, etc.
|
|
|
|
SimpleRenameMap::SimpleRenameMap(unsigned _numLogicalIntRegs,
|
|
unsigned _numPhysicalIntRegs,
|
|
unsigned _numLogicalFloatRegs,
|
|
unsigned _numPhysicalFloatRegs,
|
|
unsigned _numMiscRegs,
|
|
RegIndex _intZeroReg,
|
|
RegIndex _floatZeroReg)
|
|
: numLogicalIntRegs(_numLogicalIntRegs),
|
|
numPhysicalIntRegs(_numPhysicalIntRegs),
|
|
numLogicalFloatRegs(_numLogicalFloatRegs),
|
|
numPhysicalFloatRegs(_numPhysicalFloatRegs),
|
|
numMiscRegs(_numMiscRegs),
|
|
intZeroReg(_intZeroReg),
|
|
floatZeroReg(_floatZeroReg)
|
|
{
|
|
DPRINTF(Rename, "Rename: Creating rename map. Phys: %i / %i, Float: "
|
|
"%i / %i.\n", numLogicalIntRegs, numPhysicalIntRegs,
|
|
numLogicalFloatRegs, numPhysicalFloatRegs);
|
|
|
|
numLogicalRegs = numLogicalIntRegs + numLogicalFloatRegs;
|
|
|
|
numPhysicalRegs = numPhysicalIntRegs + numPhysicalFloatRegs;
|
|
|
|
//Create the rename maps, and their scoreboards.
|
|
intRenameMap = new RenameEntry[numLogicalIntRegs];
|
|
floatRenameMap = new RenameEntry[numLogicalRegs];
|
|
|
|
// Should combine this into one scoreboard.
|
|
intScoreboard.resize(numPhysicalIntRegs);
|
|
floatScoreboard.resize(numPhysicalRegs);
|
|
miscScoreboard.resize(numPhysicalRegs + numMiscRegs);
|
|
|
|
// Initialize the entries in the integer rename map to point to the
|
|
// physical registers of the same index, and consider each register
|
|
// ready until the first rename occurs.
|
|
for (RegIndex index = 0; index < numLogicalIntRegs; ++index)
|
|
{
|
|
intRenameMap[index].physical_reg = index;
|
|
intScoreboard[index] = 1;
|
|
}
|
|
|
|
// Initialize the rest of the physical registers (the ones that don't
|
|
// directly map to a logical register) as unready.
|
|
for (PhysRegIndex index = numLogicalIntRegs;
|
|
index < numPhysicalIntRegs;
|
|
++index)
|
|
{
|
|
intScoreboard[index] = 0;
|
|
}
|
|
|
|
int float_reg_idx = numPhysicalIntRegs;
|
|
|
|
// Initialize the entries in the floating point rename map to point to
|
|
// the physical registers of the same index, and consider each register
|
|
// ready until the first rename occurs.
|
|
// Although the index refers purely to architected registers, because
|
|
// the floating reg indices come after the integer reg indices, they
|
|
// may exceed the size of a normal RegIndex (short).
|
|
for (PhysRegIndex index = numLogicalIntRegs;
|
|
index < numLogicalRegs; ++index)
|
|
{
|
|
floatRenameMap[index].physical_reg = float_reg_idx++;
|
|
}
|
|
|
|
for (PhysRegIndex index = numPhysicalIntRegs;
|
|
index < numPhysicalIntRegs + numLogicalFloatRegs; ++index)
|
|
{
|
|
floatScoreboard[index] = 1;
|
|
}
|
|
|
|
// Initialize the rest of the physical registers (the ones that don't
|
|
// directly map to a logical register) as unready.
|
|
for (PhysRegIndex index = numPhysicalIntRegs + numLogicalFloatRegs;
|
|
index < numPhysicalRegs;
|
|
++index)
|
|
{
|
|
floatScoreboard[index] = 0;
|
|
}
|
|
|
|
// Initialize the entries in the misc register scoreboard to be ready.
|
|
for (PhysRegIndex index = numPhysicalRegs;
|
|
index < numPhysicalRegs + numMiscRegs; ++index)
|
|
{
|
|
miscScoreboard[index] = 1;
|
|
}
|
|
}
|
|
|
|
SimpleRenameMap::~SimpleRenameMap()
|
|
{
|
|
// Delete the rename maps as they were allocated with new.
|
|
delete [] intRenameMap;
|
|
delete [] floatRenameMap;
|
|
}
|
|
|
|
void
|
|
SimpleRenameMap::setFreeList(SimpleFreeList *fl_ptr)
|
|
{
|
|
//Setup the interface to the freelist.
|
|
freeList = fl_ptr;
|
|
}
|
|
|
|
|
|
// Don't allow this stage to fault; force that check to the rename stage.
|
|
// Simply ask to rename a logical register and get back a new physical
|
|
// register index.
|
|
SimpleRenameMap::RenameInfo
|
|
SimpleRenameMap::rename(RegIndex arch_reg)
|
|
{
|
|
PhysRegIndex renamed_reg;
|
|
PhysRegIndex prev_reg;
|
|
|
|
if (arch_reg < numLogicalIntRegs) {
|
|
|
|
// Record the current physical register that is renamed to the
|
|
// requested architected register.
|
|
prev_reg = intRenameMap[arch_reg].physical_reg;
|
|
|
|
// If it's not referencing the zero register, then mark the register
|
|
// as not ready.
|
|
if (arch_reg != intZeroReg) {
|
|
// Get a free physical register to rename to.
|
|
renamed_reg = freeList->getIntReg();
|
|
|
|
// Update the integer rename map.
|
|
intRenameMap[arch_reg].physical_reg = renamed_reg;
|
|
|
|
assert(renamed_reg >= 0 && renamed_reg < numPhysicalIntRegs);
|
|
|
|
// Mark register as not ready.
|
|
intScoreboard[renamed_reg] = false;
|
|
} else {
|
|
// Otherwise return the zero register so nothing bad happens.
|
|
renamed_reg = intZeroReg;
|
|
}
|
|
} else if (arch_reg < numLogicalRegs) {
|
|
// Subtract off the base offset for floating point registers.
|
|
// arch_reg = arch_reg - numLogicalIntRegs;
|
|
|
|
// Record the current physical register that is renamed to the
|
|
// requested architected register.
|
|
prev_reg = floatRenameMap[arch_reg].physical_reg;
|
|
|
|
// If it's not referencing the zero register, then mark the register
|
|
// as not ready.
|
|
if (arch_reg != floatZeroReg) {
|
|
// Get a free floating point register to rename to.
|
|
renamed_reg = freeList->getFloatReg();
|
|
|
|
// Update the floating point rename map.
|
|
floatRenameMap[arch_reg].physical_reg = renamed_reg;
|
|
|
|
assert(renamed_reg < numPhysicalRegs &&
|
|
renamed_reg >= numPhysicalIntRegs);
|
|
|
|
// Mark register as not ready.
|
|
floatScoreboard[renamed_reg] = false;
|
|
} else {
|
|
// Otherwise return the zero register so nothing bad happens.
|
|
renamed_reg = floatZeroReg;
|
|
}
|
|
} else {
|
|
// Subtract off the base offset for miscellaneous registers.
|
|
arch_reg = arch_reg - numLogicalRegs;
|
|
|
|
// No renaming happens to the misc. registers. They are simply the
|
|
// registers that come after all the physical registers; thus
|
|
// take the base architected register and add the physical registers
|
|
// to it.
|
|
renamed_reg = arch_reg + numPhysicalRegs;
|
|
|
|
// Set the previous register to the same register; mainly it must be
|
|
// known that the prev reg was outside the range of normal registers
|
|
// so the free list can avoid adding it.
|
|
prev_reg = renamed_reg;
|
|
|
|
assert(renamed_reg < numPhysicalRegs + numMiscRegs);
|
|
|
|
miscScoreboard[renamed_reg] = false;
|
|
}
|
|
|
|
return RenameInfo(renamed_reg, prev_reg);
|
|
}
|
|
|
|
//Perhaps give this a pair as a return value, of the physical register
|
|
//and whether or not it's ready.
|
|
PhysRegIndex
|
|
SimpleRenameMap::lookup(RegIndex arch_reg)
|
|
{
|
|
if (arch_reg < numLogicalIntRegs) {
|
|
return intRenameMap[arch_reg].physical_reg;
|
|
} else if (arch_reg < numLogicalRegs) {
|
|
// Subtract off the base FP offset.
|
|
// arch_reg = arch_reg - numLogicalIntRegs;
|
|
|
|
return floatRenameMap[arch_reg].physical_reg;
|
|
} else {
|
|
// Subtract off the misc registers offset.
|
|
arch_reg = arch_reg - numLogicalRegs;
|
|
|
|
// Misc. regs don't rename, so simply add the base arch reg to
|
|
// the number of physical registers.
|
|
return numPhysicalRegs + arch_reg;
|
|
}
|
|
}
|
|
|
|
bool
|
|
SimpleRenameMap::isReady(PhysRegIndex phys_reg)
|
|
{
|
|
if (phys_reg < numPhysicalIntRegs) {
|
|
return intScoreboard[phys_reg];
|
|
} else if (phys_reg < numPhysicalRegs) {
|
|
|
|
// Subtract off the base FP offset.
|
|
// phys_reg = phys_reg - numPhysicalIntRegs;
|
|
|
|
return floatScoreboard[phys_reg];
|
|
} else {
|
|
// Subtract off the misc registers offset.
|
|
// phys_reg = phys_reg - numPhysicalRegs;
|
|
|
|
return miscScoreboard[phys_reg];
|
|
}
|
|
}
|
|
|
|
// In this implementation the miscellaneous registers do not actually rename,
|
|
// so this function does not allow you to try to change their mappings.
|
|
void
|
|
SimpleRenameMap::setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg)
|
|
{
|
|
if (arch_reg < numLogicalIntRegs) {
|
|
DPRINTF(Rename, "Rename Map: Integer register %i being set to %i.\n",
|
|
(int)arch_reg, renamed_reg);
|
|
|
|
intRenameMap[arch_reg].physical_reg = renamed_reg;
|
|
} else {
|
|
assert(arch_reg < (numLogicalIntRegs + numLogicalFloatRegs));
|
|
|
|
DPRINTF(Rename, "Rename Map: Float register %i being set to %i.\n",
|
|
(int)arch_reg - numLogicalIntRegs, renamed_reg);
|
|
|
|
floatRenameMap[arch_reg].physical_reg = renamed_reg;
|
|
}
|
|
}
|
|
|
|
void
|
|
SimpleRenameMap::squash(vector<RegIndex> freed_regs,
|
|
vector<UnmapInfo> unmaps)
|
|
{
|
|
panic("Not sure this function should be called.");
|
|
|
|
// Not sure the rename map should be able to access the free list
|
|
// like this.
|
|
while (!freed_regs.empty()) {
|
|
RegIndex free_register = freed_regs.back();
|
|
|
|
if (free_register < numPhysicalIntRegs) {
|
|
freeList->addIntReg(free_register);
|
|
} else {
|
|
// Subtract off the base FP dependence tag.
|
|
free_register = free_register - numPhysicalIntRegs;
|
|
freeList->addFloatReg(free_register);
|
|
}
|
|
|
|
freed_regs.pop_back();
|
|
}
|
|
|
|
// Take unmap info and roll back the rename map.
|
|
}
|
|
|
|
void
|
|
SimpleRenameMap::markAsReady(PhysRegIndex ready_reg)
|
|
{
|
|
DPRINTF(Rename, "Rename map: Marking register %i as ready.\n",
|
|
(int)ready_reg);
|
|
|
|
if (ready_reg < numPhysicalIntRegs) {
|
|
assert(ready_reg >= 0);
|
|
|
|
intScoreboard[ready_reg] = 1;
|
|
} else if (ready_reg < numPhysicalRegs) {
|
|
|
|
// Subtract off the base FP offset.
|
|
// ready_reg = ready_reg - numPhysicalIntRegs;
|
|
|
|
floatScoreboard[ready_reg] = 1;
|
|
} else {
|
|
//Subtract off the misc registers offset.
|
|
// ready_reg = ready_reg - numPhysicalRegs;
|
|
|
|
miscScoreboard[ready_reg] = 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
SimpleRenameMap::numFreeEntries()
|
|
{
|
|
int free_int_regs = freeList->numFreeIntRegs();
|
|
int free_float_regs = freeList->numFreeFloatRegs();
|
|
|
|
if (free_int_regs < free_float_regs) {
|
|
return free_int_regs;
|
|
} else {
|
|
return free_float_regs;
|
|
}
|
|
}
|