fastmodel: Move ARM but not CortexA76 specific bits to the IRIS TC.
Now that the IRIS thread context can be specific to ARM, some things which had been pushed to a different level of abstraction can be mvoed back. This will hopefully allow more code sharing in the future when other types of CPUs are supported. Change-Id: Ic3a5f0db53ebe93e18f7507ed71812bce27b6d01 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23788 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -40,8 +40,7 @@ CortexA76TC::CortexA76TC(
|
||||
::BaseCPU *cpu, int id, System *system, ::BaseTLB *dtb, ::BaseTLB *itb,
|
||||
iris::IrisConnectionInterface *iris_if,
|
||||
const std::string &iris_path) :
|
||||
ThreadContext(cpu, id, system, dtb, itb, iris_if, iris_path),
|
||||
vecRegs(TheISA::NumVecRegs), pcRscId(iris::IRIS_UINT64_MAX)
|
||||
ThreadContext(cpu, id, system, dtb, itb, iris_if, iris_path)
|
||||
{}
|
||||
|
||||
bool
|
||||
@@ -87,7 +86,6 @@ CortexA76TC::initFromIrisInstance(const ResourceMap &resources)
|
||||
ThreadContext::initFromIrisInstance(resources);
|
||||
|
||||
pcRscId = extractResourceId(resources, "PC");
|
||||
icountRscId = extractResourceId(resources, "icount");
|
||||
|
||||
extractResourceMap(miscRegIds, resources, miscRegIdxNameMap);
|
||||
|
||||
@@ -97,54 +95,6 @@ CortexA76TC::initFromIrisInstance(const ResourceMap &resources)
|
||||
extractResourceMap(vecRegIds, resources, vecRegIdxNameMap);
|
||||
}
|
||||
|
||||
TheISA::PCState
|
||||
CortexA76TC::pcState() const
|
||||
{
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
ArmISA::PCState pc;
|
||||
|
||||
pc.thumb(cpsr.t);
|
||||
pc.nextThumb(pc.thumb());
|
||||
pc.jazelle(cpsr.j);
|
||||
pc.nextJazelle(cpsr.j);
|
||||
pc.aarch64(!cpsr.width);
|
||||
pc.nextAArch64(!cpsr.width);
|
||||
pc.illegalExec(false);
|
||||
|
||||
iris::ResourceReadResult result;
|
||||
call().resource_read(_instId, result, pcRscId);
|
||||
Addr addr = result.data.at(0);
|
||||
if (cpsr.width && cpsr.t)
|
||||
addr = addr & ~0x1;
|
||||
pc.set(addr);
|
||||
|
||||
return pc;
|
||||
}
|
||||
void
|
||||
CortexA76TC::pcState(const TheISA::PCState &val)
|
||||
{
|
||||
Addr pc = val.pc();
|
||||
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
if (cpsr.width && cpsr.t)
|
||||
pc = pc | 0x1;
|
||||
|
||||
iris::ResourceWriteResult result;
|
||||
call().resource_write(_instId, result, pcRscId, pc);
|
||||
}
|
||||
|
||||
Addr
|
||||
CortexA76TC::instAddr() const
|
||||
{
|
||||
return pcState().instAddr();
|
||||
}
|
||||
|
||||
Addr
|
||||
CortexA76TC::nextInstAddr() const
|
||||
{
|
||||
return pcState().nextInstAddr();
|
||||
}
|
||||
|
||||
iris::MemorySpaceId
|
||||
CortexA76TC::getBpSpaceId(Addr pc) const
|
||||
{
|
||||
@@ -161,57 +111,6 @@ CortexA76TC::getBpSpaceId(Addr pc) const
|
||||
return bpSpaceId;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CortexA76TC::readIntReg(RegIndex reg_idx) const
|
||||
{
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
|
||||
iris::ResourceReadResult result;
|
||||
if (cpsr.width)
|
||||
call().resource_read(_instId, result, intReg32Ids.at(reg_idx));
|
||||
else
|
||||
call().resource_read(_instId, result, intReg64Ids.at(reg_idx));
|
||||
return result.data.at(0);
|
||||
}
|
||||
|
||||
void
|
||||
CortexA76TC::setIntReg(RegIndex reg_idx, uint64_t val)
|
||||
{
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
|
||||
iris::ResourceWriteResult result;
|
||||
if (cpsr.width)
|
||||
call().resource_write(_instId, result, intReg32Ids.at(reg_idx), val);
|
||||
else
|
||||
call().resource_write(_instId, result, intReg64Ids.at(reg_idx), val);
|
||||
}
|
||||
|
||||
const ArmISA::VecRegContainer &
|
||||
CortexA76TC::readVecReg(const RegId ®_id) const
|
||||
{
|
||||
const RegIndex idx = reg_id.index();
|
||||
// Ignore accesses to registers which aren't architected. gem5 defines a
|
||||
// few extra registers which it uses internally in the implementation of
|
||||
// some instructions.
|
||||
if (idx >= vecRegIds.size())
|
||||
return vecRegs.at(idx);
|
||||
ArmISA::VecRegContainer ® = vecRegs.at(idx);
|
||||
|
||||
iris::ResourceReadResult result;
|
||||
call().resource_read(_instId, result, vecRegIds.at(idx));
|
||||
size_t data_size = result.data.size() * (sizeof(*result.data.data()));
|
||||
size_t size = std::min(data_size, reg.SIZE);
|
||||
memcpy(reg.raw_ptr<void>(), (void *)result.data.data(), size);
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
const ArmISA::VecRegContainer &
|
||||
CortexA76TC::readVecRegFlat(RegIndex idx) const
|
||||
{
|
||||
return readVecReg(RegId(VecRegClass, idx));
|
||||
}
|
||||
|
||||
Iris::ThreadContext::IdxNameMap CortexA76TC::miscRegIdxNameMap({
|
||||
{ ArmISA::MISCREG_CPSR, "CPSR" },
|
||||
{ ArmISA::MISCREG_SPSR, "SPSR" },
|
||||
|
||||
@@ -46,10 +46,6 @@ class CortexA76TC : public Iris::ThreadContext
|
||||
static IdxNameMap vecRegIdxNameMap;
|
||||
static iris::MemorySpaceId bpSpaceId;
|
||||
|
||||
// Temporary holding places for the vector reg accessors to return.
|
||||
// These are not updated live, only when requested.
|
||||
mutable std::vector<ArmISA::VecRegContainer> vecRegs;
|
||||
|
||||
public:
|
||||
CortexA76TC(::BaseCPU *cpu, int id, System *system,
|
||||
::BaseTLB *dtb, ::BaseTLB *itb,
|
||||
@@ -60,30 +56,7 @@ class CortexA76TC : public Iris::ThreadContext
|
||||
|
||||
void initFromIrisInstance(const ResourceMap &resources) override;
|
||||
|
||||
TheISA::PCState pcState() const override;
|
||||
void pcState(const TheISA::PCState &val) override;
|
||||
Addr instAddr() const override;
|
||||
Addr nextInstAddr() const override;
|
||||
|
||||
iris::ResourceId pcRscId;
|
||||
iris::ResourceId icountRscId;
|
||||
|
||||
ResourceIds intReg32Ids;
|
||||
ResourceIds intReg64Ids;
|
||||
ResourceIds vecRegIds;
|
||||
|
||||
iris::MemorySpaceId getBpSpaceId(Addr pc) const override;
|
||||
|
||||
void setIntReg(RegIndex reg_idx, RegVal val) override;
|
||||
RegVal readIntReg(RegIndex reg_idx) const override;
|
||||
TheISA::ISA *
|
||||
getIsaPtr() override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
|
||||
const VecRegContainer &readVecReg(const RegId ®) const override;
|
||||
const VecRegContainer &readVecRegFlat(RegIndex idx) const override;
|
||||
};
|
||||
|
||||
} // namespace FastModel
|
||||
|
||||
@@ -244,7 +244,7 @@ ThreadContext::ThreadContext(
|
||||
BaseCPU *cpu, int id, System *system, ::BaseTLB *dtb, ::BaseTLB *itb,
|
||||
iris::IrisConnectionInterface *iris_if, const std::string &iris_path) :
|
||||
_cpu(cpu), _threadId(id), _system(system), _dtb(dtb), _itb(itb),
|
||||
_irisPath(iris_path), _instId(iris::IRIS_UINT64_MAX), _status(Active),
|
||||
_irisPath(iris_path), vecRegs(TheISA::NumVecRegs),
|
||||
comInstEventQueue("instruction-based event queue"),
|
||||
client(iris_if, "client." + iris_path)
|
||||
{
|
||||
@@ -431,6 +431,54 @@ ThreadContext::setStatus(Status new_status)
|
||||
_status = new_status;
|
||||
}
|
||||
|
||||
ArmISA::PCState
|
||||
ThreadContext::pcState() const
|
||||
{
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
ArmISA::PCState pc;
|
||||
|
||||
pc.thumb(cpsr.t);
|
||||
pc.nextThumb(pc.thumb());
|
||||
pc.jazelle(cpsr.j);
|
||||
pc.nextJazelle(cpsr.j);
|
||||
pc.aarch64(!cpsr.width);
|
||||
pc.nextAArch64(!cpsr.width);
|
||||
pc.illegalExec(false);
|
||||
|
||||
iris::ResourceReadResult result;
|
||||
call().resource_read(_instId, result, pcRscId);
|
||||
Addr addr = result.data.at(0);
|
||||
if (cpsr.width && cpsr.t)
|
||||
addr = addr & ~0x1;
|
||||
pc.set(addr);
|
||||
|
||||
return pc;
|
||||
}
|
||||
void
|
||||
ThreadContext::pcState(const ArmISA::PCState &val)
|
||||
{
|
||||
Addr pc = val.pc();
|
||||
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
if (cpsr.width && cpsr.t)
|
||||
pc = pc | 0x1;
|
||||
|
||||
iris::ResourceWriteResult result;
|
||||
call().resource_write(_instId, result, pcRscId, pc);
|
||||
}
|
||||
|
||||
Addr
|
||||
ThreadContext::instAddr() const
|
||||
{
|
||||
return pcState().instAddr();
|
||||
}
|
||||
|
||||
Addr
|
||||
ThreadContext::nextInstAddr() const
|
||||
{
|
||||
return pcState().nextInstAddr();
|
||||
}
|
||||
|
||||
RegVal
|
||||
ThreadContext::readMiscRegNoEffect(RegIndex misc_reg) const
|
||||
{
|
||||
@@ -449,16 +497,52 @@ ThreadContext::setMiscRegNoEffect(RegIndex misc_reg, const RegVal val)
|
||||
RegVal
|
||||
ThreadContext::readIntReg(RegIndex reg_idx) const
|
||||
{
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
|
||||
iris::ResourceReadResult result;
|
||||
call().resource_read(_instId, result, intRegIds.at(reg_idx));
|
||||
if (cpsr.width)
|
||||
call().resource_read(_instId, result, intReg32Ids.at(reg_idx));
|
||||
else
|
||||
call().resource_read(_instId, result, intReg64Ids.at(reg_idx));
|
||||
return result.data.at(0);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::setIntReg(RegIndex reg_idx, RegVal val)
|
||||
{
|
||||
ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
|
||||
iris::ResourceWriteResult result;
|
||||
call().resource_write(_instId, result, intRegIds.at(reg_idx), val);
|
||||
if (cpsr.width)
|
||||
call().resource_write(_instId, result, intReg32Ids.at(reg_idx), val);
|
||||
else
|
||||
call().resource_write(_instId, result, intReg64Ids.at(reg_idx), val);
|
||||
}
|
||||
|
||||
const ArmISA::VecRegContainer &
|
||||
ThreadContext::readVecReg(const RegId ®_id) const
|
||||
{
|
||||
const RegIndex idx = reg_id.index();
|
||||
// Ignore accesses to registers which aren't architected. gem5 defines a
|
||||
// few extra registers which it uses internally in the implementation of
|
||||
// some instructions.
|
||||
if (idx >= vecRegIds.size())
|
||||
return vecRegs.at(idx);
|
||||
ArmISA::VecRegContainer ® = vecRegs.at(idx);
|
||||
|
||||
iris::ResourceReadResult result;
|
||||
call().resource_read(_instId, result, vecRegIds.at(idx));
|
||||
size_t data_size = result.data.size() * (sizeof(*result.data.data()));
|
||||
size_t size = std::min(data_size, reg.SIZE);
|
||||
memcpy(reg.raw_ptr<void>(), (void *)result.data.data(), size);
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
const ArmISA::VecRegContainer &
|
||||
ThreadContext::readVecRegFlat(RegIndex idx) const
|
||||
{
|
||||
return readVecReg(RegId(VecRegClass, idx));
|
||||
}
|
||||
|
||||
} // namespace Iris
|
||||
|
||||
@@ -63,9 +63,13 @@ class ThreadContext : public ::ThreadContext
|
||||
::BaseTLB *_itb;
|
||||
|
||||
std::string _irisPath;
|
||||
iris::InstanceId _instId;
|
||||
iris::InstanceId _instId = iris::IRIS_UINT64_MAX;
|
||||
|
||||
Status _status;
|
||||
// Temporary holding places for the vector reg accessors to return.
|
||||
// These are not updated live, only when requested.
|
||||
mutable std::vector<ArmISA::VecRegContainer> vecRegs;
|
||||
|
||||
Status _status = Active;
|
||||
|
||||
virtual void initFromIrisInstance(const ResourceMap &resources);
|
||||
|
||||
@@ -76,7 +80,13 @@ class ThreadContext : public ::ThreadContext
|
||||
|
||||
|
||||
ResourceIds miscRegIds;
|
||||
ResourceIds intRegIds;
|
||||
ResourceIds intReg32Ids;
|
||||
ResourceIds intReg64Ids;
|
||||
|
||||
iris::ResourceId pcRscId = iris::IRIS_UINT64_MAX;
|
||||
iris::ResourceId icountRscId;
|
||||
|
||||
ResourceIds vecRegIds;
|
||||
|
||||
std::vector<iris::MemorySpaceInfo> memorySpaces;
|
||||
std::vector<iris::MemorySupportedAddressTranslationResult> translations;
|
||||
@@ -188,7 +198,7 @@ class ThreadContext : public ::ThreadContext
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
TheISA::Decoder *
|
||||
ArmISA::Decoder *
|
||||
getDecoderPtr() override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
@@ -196,6 +206,12 @@ class ThreadContext : public ::ThreadContext
|
||||
|
||||
System *getSystemPtr() override { return _cpu->system; }
|
||||
|
||||
ArmISA::ISA *
|
||||
getIsaPtr() override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
|
||||
Kernel::Statistics *
|
||||
getKernelStats() override
|
||||
{
|
||||
@@ -289,11 +305,7 @@ class ThreadContext : public ::ThreadContext
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
|
||||
const VecRegContainer &
|
||||
readVecReg(const RegId ®) const override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
const VecRegContainer &readVecReg(const RegId ®) const override;
|
||||
VecRegContainer &
|
||||
getWritableVecReg(const RegId ®) override
|
||||
{
|
||||
@@ -412,9 +424,14 @@ class ThreadContext : public ::ThreadContext
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
|
||||
void pcStateNoRecord(const TheISA::PCState &val) override { pcState(val); }
|
||||
void pcStateNoRecord(const ArmISA::PCState &val) override { pcState(val); }
|
||||
MicroPC microPC() const override { return 0; }
|
||||
|
||||
ArmISA::PCState pcState() const override;
|
||||
void pcState(const ArmISA::PCState &val) override;
|
||||
Addr instAddr() const override;
|
||||
Addr nextInstAddr() const override;
|
||||
|
||||
RegVal readMiscRegNoEffect(RegIndex misc_reg) const override;
|
||||
RegVal
|
||||
readMiscReg(RegIndex misc_reg) override
|
||||
@@ -496,11 +513,7 @@ class ThreadContext : public ::ThreadContext
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
|
||||
const VecRegContainer &
|
||||
readVecRegFlat(RegIndex idx) const override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
const VecRegContainer &readVecRegFlat(RegIndex idx) const override;
|
||||
VecRegContainer &
|
||||
getWritableVecRegFlat(RegIndex idx) override
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user