arch,cpu: Remove the idea of a zero register.

This is now handled by using the InvalidRegClass.

Change-Id: If43d8f27cfebc249ec6600847bcfd98c9e94cf40
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49746
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-08-22 06:04:31 -07:00
parent caffb4e1ff
commit a40950a5c9
30 changed files with 42 additions and 131 deletions

View File

@@ -64,7 +64,6 @@ CheckerCPU::init()
CheckerCPU::CheckerCPU(const Params &p)
: BaseCPU(p, true),
zeroReg(params().isa[0]->regClasses().at(IntRegClass).zeroReg()),
systemPtr(NULL), icachePort(NULL), dcachePort(NULL),
tc(NULL), thread(NULL),
unverifiedReq(nullptr),

View File

@@ -87,8 +87,6 @@ class CheckerCPU : public BaseCPU, public ExecContext
/** id attached to all issued requests */
RequestorID requestorId;
const RegIndex zeroReg;
public:
void init() override;

View File

@@ -201,9 +201,6 @@ Checker<DynInstPtr>::verify(const DynInstPtr &completed_inst)
Fault fault = NoFault;
// maintain $r0 semantics
thread->setIntReg(zeroReg, 0);
// Check if any recent PC changes match up with anything we
// expect to happen. This is mostly to check if traps or
// PC-based events have occurred in both the checker and CPU.

View File

@@ -158,11 +158,7 @@ printRegName(std::ostream &os, const RegId& reg,
os << reg_class.regName(reg);
break;
case IntRegClass:
if (reg.index() == reg_class.zeroReg()) {
os << 'z';
} else {
os << 'r' << reg.index();
}
os << 'r' << reg.index();
break;
case CCRegClass:
os << 'c' << reg.index();

View File

@@ -87,7 +87,7 @@ class ExecContext : public gem5::ExecContext
ExecContext (
MinorCPU &cpu_,
SimpleThread &thread_, Execute &execute_,
MinorDynInstPtr inst_, RegIndex zeroReg) :
MinorDynInstPtr inst_) :
cpu(cpu_),
thread(thread_),
execute(execute_),

View File

@@ -70,8 +70,6 @@ Execute::Execute(const std::string &name_,
inp(inp_),
out(out_),
cpu(cpu_),
zeroReg(cpu.threads[0]->getIsaPtr()->regClasses().
at(IntRegClass).zeroReg()),
issueLimit(params.executeIssueLimit),
memoryIssueLimit(params.executeMemoryIssueLimit),
commitLimit(params.executeCommitLimit),
@@ -90,8 +88,7 @@ Execute::Execute(const std::string &name_,
params.executeLSQRequestsQueueSize,
params.executeLSQTransfersQueueSize,
params.executeLSQStoreBufferSize,
params.executeLSQMaxStoreBufferStoresPerCycle,
zeroReg),
params.executeLSQMaxStoreBufferStoresPerCycle),
executeInfo(params.numThreads,
ExecuteThreadInfo(params.executeCommitLimit)),
interruptPriority(0),
@@ -332,7 +329,7 @@ Execute::handleMemResponse(MinorDynInstPtr inst,
ThreadID thread_id = inst->id.threadId;
ThreadContext *thread = cpu.getContext(thread_id);
ExecContext context(cpu, *cpu.threads[thread_id], *this, inst, zeroReg);
ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
PacketPtr packet = response->packet;
@@ -467,8 +464,7 @@ Execute::executeMemRefInst(MinorDynInstPtr inst, BranchData &branch,
ThreadContext *thread = cpu.getContext(inst->id.threadId);
std::unique_ptr<PCStateBase> old_pc(thread->pcState().clone());
ExecContext context(cpu, *cpu.threads[inst->id.threadId],
*this, inst, zeroReg);
ExecContext context(cpu, *cpu.threads[inst->id.threadId], *this, inst);
DPRINTF(MinorExecute, "Initiating memRef inst: %s\n", *inst);
@@ -914,8 +910,7 @@ Execute::commitInst(MinorDynInstPtr inst, bool early_memory_issue,
panic("We should never hit the case where we try to commit from a "
"suspended thread as the streamSeqNum should not match");
} else if (inst->isFault()) {
ExecContext context(cpu, *cpu.threads[thread_id], *this,
inst, zeroReg);
ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
DPRINTF(MinorExecute, "Fault inst reached Execute: %s\n",
inst->fault->name());
@@ -976,8 +971,7 @@ Execute::commitInst(MinorDynInstPtr inst, bool early_memory_issue,
* backwards, so no other branches may evaluate this cycle*/
completed_inst = false;
} else {
ExecContext context(cpu, *cpu.threads[thread_id], *this,
inst, zeroReg);
ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
DPRINTF(MinorExecute, "Committing inst: %s\n", *inst);

View File

@@ -78,9 +78,6 @@ class Execute : public Named
/** Pointer back to the containing CPU */
MinorCPU &cpu;
/** Index of the zero integer register. */
const RegIndex zeroReg;
/** Number of instructions that can be issued per cycle */
unsigned int issueLimit;

View File

@@ -58,10 +58,9 @@ namespace minor
{
LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
RegIndex zero_reg, PacketDataPtr data_, uint64_t *res_) :
PacketDataPtr data_, uint64_t *res_) :
SenderState(),
port(port_),
zeroReg(zero_reg),
inst(inst_),
isLoad(isLoad_),
data(data_),
@@ -81,7 +80,7 @@ LSQ::LSQRequest::tryToSuppressFault()
{
SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
std::unique_ptr<PCStateBase> old_pc(thread.pcState().clone());
ExecContext context(port.cpu, thread, port.execute, inst, zeroReg);
ExecContext context(port.cpu, thread, port.execute, inst);
[[maybe_unused]] Fault fault = inst->translationFault;
// Give the instruction a chance to suppress a translation fault
@@ -104,7 +103,7 @@ LSQ::LSQRequest::completeDisabledMemAccess()
SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
std::unique_ptr<PCStateBase> old_pc(thread.pcState().clone());
ExecContext context(port.cpu, thread, port.execute, inst, zeroReg);
ExecContext context(port.cpu, thread, port.execute, inst);
context.setMemAccPredicate(false);
inst->staticInst->completeAcc(nullptr, &context, inst->traceData);
@@ -393,7 +392,7 @@ LSQ::SplitDataRequest::finish(const Fault &fault_, const RequestPtr &request_,
LSQ::SplitDataRequest::SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
bool isLoad_, PacketDataPtr data_, uint64_t *res_) :
LSQRequest(port_, inst_, isLoad_, port_.zeroReg, data_, res_),
LSQRequest(port_, inst_, isLoad_, data_, res_),
translationEvent([this]{ sendNextFragmentToTranslation(); },
"translationEvent"),
numFragments(0),
@@ -1132,7 +1131,7 @@ LSQ::tryToSendToTransfers(LSQRequestPtr request)
SimpleThread &thread = *cpu.threads[request->inst->id.threadId];
std::unique_ptr<PCStateBase> old_pc(thread.pcState().clone());
ExecContext context(cpu, thread, execute, request->inst, zeroReg);
ExecContext context(cpu, thread, execute, request->inst);
/* Handle LLSC requests and tests */
if (is_load) {
@@ -1406,12 +1405,10 @@ LSQ::LSQ(std::string name_, std::string dcache_port_name_,
unsigned int in_memory_system_limit, unsigned int line_width,
unsigned int requests_queue_size, unsigned int transfers_queue_size,
unsigned int store_buffer_size,
unsigned int store_buffer_cycle_store_limit,
RegIndex zero_reg) :
unsigned int store_buffer_cycle_store_limit) :
Named(name_),
cpu(cpu_),
execute(execute_),
zeroReg(zero_reg),
dcachePort(dcache_port_name_, *this, cpu_),
lastMemBarrier(cpu.numThreads, 0),
state(MemoryRunning),

View File

@@ -72,8 +72,6 @@ class LSQ : public Named
MinorCPU &cpu;
Execute &execute;
const RegIndex zeroReg;
protected:
/** State of memory access for head access. */
enum MemoryState
@@ -134,8 +132,6 @@ class LSQ : public Named
/** Owning port */
LSQ &port;
const RegIndex zeroReg;
/** Instruction which made this request */
MinorDynInstPtr inst;
@@ -208,8 +204,7 @@ class LSQ : public Named
public:
LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
RegIndex zero_reg, PacketDataPtr data_ = NULL,
uint64_t *res_ = NULL);
PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
virtual ~LSQRequest();
@@ -319,7 +314,7 @@ class LSQ : public Named
public:
SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
/* Say this is a load, not actually relevant */
LSQRequest(port_, inst_, true, port_.zeroReg, NULL, 0)
LSQRequest(port_, inst_, true, NULL, 0)
{ }
};
@@ -386,7 +381,7 @@ class LSQ : public Named
public:
SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
LSQRequest(port_, inst_, isLoad_, port_.zeroReg, data_, res_),
LSQRequest(port_, inst_, isLoad_, data_, res_),
packetInFlight(false),
packetSent(false)
{ }
@@ -656,8 +651,7 @@ class LSQ : public Named
unsigned int max_accesses_in_memory_system, unsigned int line_width,
unsigned int requests_queue_size, unsigned int transfers_queue_size,
unsigned int store_buffer_size,
unsigned int store_buffer_cycle_store_limit,
RegIndex zero_reg);
unsigned int store_buffer_cycle_store_limit);
virtual ~LSQ();

View File

@@ -55,13 +55,8 @@ Scoreboard::findIndex(const RegId& reg, Index &scoreboard_index)
switch (reg.classValue()) {
case IntRegClass:
if (reg.index() == zeroReg) {
/* Don't bother with the zero register */
ret = false;
} else {
scoreboard_index = reg.index();
ret = true;
}
scoreboard_index = reg.index();
ret = true;
break;
case FloatRegClass:
scoreboard_index = floatRegOffset + reg.index();

View File

@@ -82,8 +82,6 @@ class Scoreboard : public Named
* [NumIntRegs+NumCCRegs, NumFloatRegs+NumIntRegs+NumCCRegs-1] */
const unsigned numRegs;
const RegIndex zeroReg;
/** Type to use when indexing numResults */
typedef unsigned short int Index;
@@ -120,7 +118,6 @@ class Scoreboard : public Named
vecPredRegOffset(vecRegOffset +
reg_classes.at(VecElemClass).numRegs()),
numRegs(vecPredRegOffset + reg_classes.at(VecPredRegClass).numRegs()),
zeroReg(reg_classes.at(IntRegClass).zeroReg()),
numResults(numRegs, 0),
numUnpredictableResults(numRegs, 0),
fuIndices(numRegs, invalidFUIndex),

View File

@@ -98,8 +98,7 @@ CPU::CPU(const BaseO3CPUParams &params)
rob(this, params),
scoreboard(name() + ".scoreboard", regFile.totalNumPhysRegs(),
params.isa[0]->regClasses().at(IntRegClass).zeroReg()),
scoreboard(name() + ".scoreboard", regFile.totalNumPhysRegs()),
isa(numThreads, NULL),

View File

@@ -65,9 +65,6 @@ ElasticTrace::ElasticTrace(const ElasticTraceParams &params)
stats(this)
{
cpu = dynamic_cast<CPU *>(params.manager);
const BaseISA::RegClasses &regClasses =
cpu->getContext(0)->getIsaPtr()->regClasses();
zeroReg = regClasses.at(IntRegClass).zeroReg();
fatal_if(!cpu, "Manager of %s is not of type O3CPU and thus does not "\
"support dependency tracing.\n", name());
@@ -251,9 +248,7 @@ ElasticTrace::updateRegDep(const DynInstConstPtr& dyn_inst)
for (int src_idx = 0; src_idx < max_regs; src_idx++) {
const RegId& src_reg = dyn_inst->srcRegIdx(src_idx);
if (!src_reg.is(MiscRegClass) &&
!((src_reg.is(IntRegClass) && src_reg.index() == zeroReg) ||
src_reg.is(InvalidRegClass))) {
if (!src_reg.is(MiscRegClass) && !src_reg.is(InvalidRegClass)) {
// Get the physical register index of the i'th source register.
PhysRegIdPtr phys_src_reg = dyn_inst->renamedSrcIdx(src_idx);
DPRINTFR(ElasticTrace, "[sn:%lli] Check map for src reg"
@@ -284,9 +279,7 @@ ElasticTrace::updateRegDep(const DynInstConstPtr& dyn_inst)
// For data dependency tracking the register must be an int, float or
// CC register and not a Misc register.
const RegId& dest_reg = dyn_inst->destRegIdx(dest_idx);
if (!dest_reg.is(MiscRegClass) &&
!((dest_reg.is(IntRegClass) && dest_reg.index() == zeroReg) ||
dest_reg.is(InvalidRegClass))) {
if (!dest_reg.is(MiscRegClass) && !dest_reg.is(InvalidRegClass)) {
// Get the physical register index of the i'th destination
// register.
PhysRegIdPtr phys_dest_reg =

View File

@@ -190,8 +190,6 @@ class ElasticTrace : public ProbeListenerObject
*/
bool firstWin;
RegIndex zeroReg;
/**
* @defgroup InstExecInfo Struct for storing information before an
* instruction reaches the commit stage, e.g. execute timestamp.

View File

@@ -86,8 +86,6 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs,
intRegIds.emplace_back(IntRegClass, phys_reg, flat_reg_idx++);
}
zeroReg = RegId(IntRegClass, reg_classes.at(IntRegClass).zeroReg());
// The next batch of the registers are the floating-point physical
// registers; put them onto the floating-point free list.
for (phys_reg = 0; phys_reg < numPhysicalFloatRegs; phys_reg++) {

View File

@@ -76,7 +76,6 @@ class PhysRegFile
/** Integer register file. */
RegFile intRegFile;
std::vector<PhysRegId> intRegIds;
RegId zeroReg;
/** Floating point register file. */
RegFile floatRegFile;
@@ -255,8 +254,7 @@ class PhysRegFile
case InvalidRegClass:
break;
case IntRegClass:
if (phys_reg->index() != zeroReg.index())
intRegFile.reg(idx) = val;
intRegFile.reg(idx) = val;
DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n",
idx, val);
break;

View File

@@ -54,8 +54,7 @@ namespace gem5
namespace o3
{
SimpleRenameMap::SimpleRenameMap()
: freeList(NULL), zeroReg(IntRegClass, 0)
SimpleRenameMap::SimpleRenameMap() : freeList(NULL)
{
}
@@ -68,7 +67,6 @@ SimpleRenameMap::init(const RegClass &reg_class, SimpleFreeList *_freeList)
map.resize(reg_class.numRegs());
freeList = _freeList;
zeroReg = RegId(IntRegClass, reg_class.zeroReg());
}
SimpleRenameMap::RenameInfo
@@ -79,10 +77,7 @@ SimpleRenameMap::rename(const RegId& arch_reg)
// requested architected register.
PhysRegIdPtr prev_reg = map[arch_reg.index()];
if (arch_reg == zeroReg) {
assert(prev_reg->index() == zeroReg.index());
renamed_reg = prev_reg;
} else if (arch_reg.is(InvalidRegClass)) {
if (arch_reg.is(InvalidRegClass)) {
assert(prev_reg->is(InvalidRegClass));
renamed_reg = prev_reg;
} else if (prev_reg->getNumPinnedWrites() > 0) {

View File

@@ -85,15 +85,6 @@ class SimpleRenameMap
*/
SimpleFreeList *freeList;
/**
* The architectural index of the zero register. This register is
* mapped but read-only, so we ignore attempts to rename it via
* the rename() method. If there is no such register for this map
* table, it should be set to an invalid index so that it never
* matches.
*/
RegId zeroReg;
public:
SimpleRenameMap();

View File

@@ -35,9 +35,9 @@ namespace gem5
namespace o3
{
Scoreboard::Scoreboard(const std::string &_my_name, unsigned _numPhysicalRegs,
RegIndex zero_reg) :
_name(_my_name), zeroReg(zero_reg), regScoreBoard(_numPhysicalRegs, true),
Scoreboard::Scoreboard(const std::string &_my_name,
unsigned _numPhysicalRegs) :
_name(_my_name), regScoreBoard(_numPhysicalRegs, true),
numPhysRegs(_numPhysicalRegs)
{}

View File

@@ -58,9 +58,6 @@ class Scoreboard
* explicitly because Scoreboard is not a SimObject. */
const std::string _name;
/** Index of the zero integer register. */
const RegIndex zeroReg;
/** Scoreboard of physical integer registers, saying whether or not they
* are ready. */
std::vector<bool> regScoreBoard;
@@ -73,8 +70,7 @@ class Scoreboard
* @param _numPhysicalRegs Number of physical registers.
* @param _numMiscRegs Number of miscellaneous registers.
*/
Scoreboard(const std::string &_my_name, unsigned _numPhysicalRegs,
RegIndex _zero_reg);
Scoreboard(const std::string &_my_name, unsigned _numPhysicalRegs);
/** Destructor. */
~Scoreboard() {}
@@ -93,12 +89,7 @@ class Scoreboard
assert(phys_reg->flatIndex() < numPhysRegs);
bool ready = regScoreBoard[phys_reg->flatIndex()];
if (phys_reg->is(IntRegClass) && phys_reg->index() == zeroReg)
gem5_assert(ready);
return ready;
return regScoreBoard[phys_reg->flatIndex()];
}
/** Sets the register as ready. */
@@ -131,10 +122,6 @@ class Scoreboard
assert(phys_reg->flatIndex() < numPhysRegs);
// zero reg should never be marked unready
if (phys_reg->is(IntRegClass) && phys_reg->index() == zeroReg)
return;
regScoreBoard[phys_reg->flatIndex()] = false;
}

View File

@@ -82,7 +82,6 @@ class RegClass
{
private:
size_t _numRegs;
const RegIndex _zeroReg;
size_t _regBytes;
// This is how much to shift an index by to get an offset of a register in
// a register file from the register index, which would otherwise need to
@@ -95,20 +94,18 @@ class RegClass
public:
RegClass(size_t num_regs, const debug::Flag &debug_flag,
RegIndex new_zero=-1, size_t reg_bytes=sizeof(RegVal)) :
_numRegs(num_regs), _zeroReg(new_zero), _regBytes(reg_bytes),
size_t reg_bytes=sizeof(RegVal)) :
_numRegs(num_regs), _regBytes(reg_bytes),
_regShift(ceilLog2(reg_bytes)), debugFlag(debug_flag)
{}
RegClass(size_t num_regs, RegClassOps &new_ops,
const debug::Flag &debug_flag, RegIndex new_zero=-1,
size_t reg_bytes=sizeof(RegVal)) :
RegClass(num_regs, debug_flag, new_zero, reg_bytes)
const debug::Flag &debug_flag, size_t reg_bytes=sizeof(RegVal)) :
RegClass(num_regs, debug_flag, reg_bytes)
{
_ops = &new_ops;
}
size_t numRegs() const { return _numRegs; }
RegIndex zeroReg() const { return _zeroReg; }
size_t regBytes() const { return _regBytes; }
size_t regShift() const { return _regShift; }
const debug::Flag &debug() const { return debugFlag; }

View File

@@ -85,7 +85,6 @@ BaseSimpleCPU::BaseSimpleCPU(const BaseSimpleCPUParams &p)
: BaseCPU(p),
curThread(0),
branchPred(p.branchPred),
zeroReg(p.isa[0]->regClasses().at(IntRegClass).zeroReg()),
traceData(NULL),
_status(Idle)
{

View File

@@ -86,8 +86,6 @@ class BaseSimpleCPU : public BaseCPU
ThreadID curThread;
branch_prediction::BPredUnit *branchPred;
const RegIndex zeroReg;
void checkPcEventQueue();
void swapActiveThread();

View File

@@ -408,9 +408,6 @@ class SimpleThread : public ThreadState, public ThreadContext
auto &reg_file = regFiles[reg.classValue()];
const auto &reg_class = reg_file.regClass;
if (reg.index() == reg_class.zeroReg())
return;
DPRINTFV(reg_class.debug(), "Setting %s register %s (%d) to %#x.\n",
reg.className(), reg_class.regName(arch_reg), idx, val);
reg_file.reg(idx) = val;
@@ -427,9 +424,6 @@ class SimpleThread : public ThreadState, public ThreadContext
auto &reg_file = regFiles[reg.classValue()];
const auto &reg_class = reg_file.regClass;
if (reg.index() == reg_class.zeroReg())
return;
DPRINTFV(reg_class.debug(), "Setting %s register %d to %#x.\n",
reg.className(), idx, val);
reg_file.reg(idx) = val;