arch-riscv: Add basic features toward rv32 support

Various changes to support rv32:
1. Add riscv_bits field into RiscvISA to switch rv_type
2. Add rv_type field into ExtMachInst
3. Split various constants into rv32/rv64 version
4. Fix mcause/mstatus/misa setting per rv_type
5. Split RiscvCPU into rv32/rv64
6. Fix how reset/branch create new pc so rv_type is preserved
7. Tag gdb-xml only for rv64

TODO:
Add rv32 gdb-xml
Add rv32 implementation into decoder

Currently there're three places where we store the rv_type information
(1) ISA (2) PCState (3) ExtMachInst. In theory, the ISA should be the
source of truth, and propagates information into PCState, then Inst.

However, there is an API on RiscvProcess that let users modify the
rv_type in PCState, so there's a chance to get inconsistent rv_type. We
should either modify the structure so such kind of usage is well
supported, or just prohibit people from setting a different rv_type.

Change-Id: If5685ae60f8d18f4f2e18137e235989e63156404
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/63091
Reviewed-by: Yu-hsin Wang <yuhsingw@google.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Roger Chang
2022-11-28 07:21:14 +00:00
parent da83764f94
commit 749c4779f4
21 changed files with 265 additions and 121 deletions

View File

@@ -23,6 +23,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import functools
from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU
from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU
from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU
@@ -41,6 +43,13 @@ class RiscvCPU:
ArchISA = RiscvISA
class Riscv32CPU:
ArchDecoder = RiscvDecoder
ArchMMU = RiscvMMU
ArchInterrupts = RiscvInterrupts
ArchISA = functools.partial(RiscvISA, riscv_type="RV32")
class RiscvAtomicSimpleCPU(BaseAtomicSimpleCPU, RiscvCPU):
mmu = RiscvMMU()
@@ -59,3 +68,23 @@ class RiscvO3CPU(BaseO3CPU, RiscvCPU):
class RiscvMinorCPU(BaseMinorCPU, RiscvCPU):
mmu = RiscvMMU()
class Riscv32AtomicSimpleCPU(BaseAtomicSimpleCPU, Riscv32CPU):
mmu = RiscvMMU()
class Riscv32NonCachingSimpleCPU(BaseNonCachingSimpleCPU, Riscv32CPU):
mmu = RiscvMMU()
class Riscv32TimingSimpleCPU(BaseTimingSimpleCPU, Riscv32CPU):
mmu = RiscvMMU()
class Riscv32O3CPU(BaseO3CPU, Riscv32CPU):
mmu = RiscvMMU()
class Riscv32MinorCPU(BaseMinorCPU, Riscv32CPU):
mmu = RiscvMMU()

View File

@@ -38,10 +38,15 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from m5.params import Enum
from m5.params import Param
from m5.objects.BaseISA import BaseISA
class RiscvType(Enum):
vals = ["RV32", "RV64"]
class RiscvISA(BaseISA):
type = "RiscvISA"
cxx_class = "gem5::RiscvISA::ISA"
@@ -50,3 +55,4 @@ class RiscvISA(BaseISA):
check_alignment = Param.Bool(
False, "whether to check memory access alignment"
)
riscv_type = Param.RiscvType("RV64", "RV32 or RV64")

View File

@@ -70,7 +70,8 @@ SimObject('RiscvFsWorkload.py', sim_objects=['RiscvBareMetal', 'RiscvLinux'],
tags='riscv isa')
SimObject('RiscvInterrupts.py', sim_objects=['RiscvInterrupts'],
tags='riscv isa')
SimObject('RiscvISA.py', sim_objects=['RiscvISA'], tags='riscv isa')
SimObject('RiscvISA.py', sim_objects=['RiscvISA'],
enums=['RiscvType'], tags='riscv isa')
SimObject('RiscvMMU.py', sim_objects=['RiscvMMU'], tags='riscv isa')
SimObject('RiscvSeWorkload.py', sim_objects=[
'RiscvSEWorkload', 'RiscvEmuLinux'], tags='riscv isa')

View File

@@ -111,6 +111,7 @@ Decoder::decode(PCStateBase &_next_pc)
next_pc.compressed(false);
}
emi.rv_type = static_cast<int>(next_pc.rvType());
return decode(emi, next_pc.instAddr());
}

View File

@@ -135,10 +135,9 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
}
// Set fault cause, privilege, and return PC
// Interrupt is indicated on the MSB of cause (bit 63 in RV64)
uint64_t _cause = _code;
if (isInterrupt()) {
_cause |= (1L << 63);
_cause |= CAUSE_INTERRUPT_MASKS[pc_state.rvType()];
}
tc->setMiscReg(cause, _cause);
tc->setMiscReg(epc, tc->pcState().instAddr());
@@ -177,8 +176,10 @@ Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
// Advance the PC to the implementation-defined reset vector
auto workload = dynamic_cast<Workload *>(tc->getSystemPtr()->workload);
PCState pc(workload->getEntry());
tc->pcState(pc);
std::unique_ptr<PCState> new_pc(dynamic_cast<PCState *>(
tc->getIsaPtr()->newPCState(workload->getEntry())));
panic_if(!new_pc, "Failed create new PCState from ISA pointer");
tc->pcState(*new_pc);
}
void

View File

@@ -43,7 +43,7 @@
Import('*')
GdbXml('riscv.xml', 'gdb_xml_riscv_target', tags='riscv isa')
GdbXml('riscv-64bit-cpu.xml', 'gdb_xml_riscv_cpu', tags='riscv isa')
GdbXml('riscv-64bit-fpu.xml', 'gdb_xml_riscv_fpu', tags='riscv isa')
GdbXml('riscv-64bit-csr.xml', 'gdb_xml_riscv_csr', tags='riscv isa')
GdbXml('riscv-64bit.xml', 'gdb_xml_riscv_64bit_target', tags='riscv isa')
GdbXml('riscv-64bit-cpu.xml', 'gdb_xml_riscv_64bit_cpu', tags='riscv isa')
GdbXml('riscv-64bit-fpu.xml', 'gdb_xml_riscv_64bit_fpu', tags='riscv isa')
GdbXml('riscv-64bit-csr.xml', 'gdb_xml_riscv_64bit_csr', tags='riscv isa')

View File

@@ -66,7 +66,7 @@ class ImmOp : public RiscvStaticInst
protected:
I imm;
ImmOp(const char *mnem, MachInst _machInst, OpClass __opClass)
ImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
: RiscvStaticInst(mnem, _machInst, __opClass), imm(0)
{}
};
@@ -93,7 +93,7 @@ class CSROp : public RiscvStaticInst
uint64_t uimm;
/// Constructor
CSROp(const char *mnem, MachInst _machInst, OpClass __opClass)
CSROp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
: RiscvStaticInst(mnem, _machInst, __opClass),
csr(FUNCT12), uimm(CSRIMM)
{

View File

@@ -53,7 +53,7 @@ namespace RiscvISA
class Unknown : public RiscvStaticInst
{
public:
Unknown(MachInst _machInst)
Unknown(ExtMachInst _machInst)
: RiscvStaticInst("unknown", _machInst, No_OpClass)
{}

View File

@@ -204,7 +204,7 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs);
} // anonymous namespace
ISA::ISA(const Params &p) :
BaseISA(p), checkAlignment(p.check_alignment)
BaseISA(p), rv_type(p.riscv_type), checkAlignment(p.check_alignment)
{
_regClasses.push_back(&intRegClass);
_regClasses.push_back(&floatRegClass);
@@ -243,12 +243,24 @@ void ISA::clear()
std::fill(miscRegFile.begin(), miscRegFile.end(), 0);
miscRegFile[MISCREG_PRV] = PRV_M;
miscRegFile[MISCREG_ISA] = (2ULL << MXL_OFFSET) | 0x14112D;
miscRegFile[MISCREG_VENDORID] = 0;
miscRegFile[MISCREG_ARCHID] = 0;
miscRegFile[MISCREG_IMPID] = 0;
miscRegFile[MISCREG_STATUS] = (2ULL << UXL_OFFSET) | (2ULL << SXL_OFFSET) |
(1ULL << FS_OFFSET);
// rv_type dependent init.
switch (rv_type) {
case RV32:
miscRegFile[MISCREG_ISA] = (1ULL << MXL_OFFSETS[RV32]) | 0x14112D;
miscRegFile[MISCREG_STATUS] = (1ULL << FS_OFFSET);
break;
case RV64:
miscRegFile[MISCREG_ISA] = (2ULL << MXL_OFFSETS[RV64]) | 0x14112D;
miscRegFile[MISCREG_STATUS] = (2ULL << UXL_OFFSET) |
(2ULL << SXL_OFFSET) |
(1ULL << FS_OFFSET);
break;
default:
panic("%s: Unknown rv_type: %d", name(), (int)rv_type);
}
miscRegFile[MISCREG_MCOUNTEREN] = 0x7;
miscRegFile[MISCREG_SCOUNTEREN] = 0x7;
// don't set it to zero; software may try to determine the supported
@@ -365,8 +377,18 @@ ISA::readMiscReg(RegIndex idx)
STATUS status = readMiscRegNoEffect(idx);
uint64_t sd_bit = \
(status.xs == 3) || (status.fs == 3) || (status.vs == 3);
// We assume RV64 here, updating the SD bit at index 63.
status.sd = sd_bit;
// For RV32, the SD bit is at index 31
// For RV64, the SD bit is at index 63.
switch (rv_type) {
case RV32:
status.rv32_sd = sd_bit;
break;
case RV64:
status.rv64_sd = sd_bit;
break;
default:
panic("%s: Unknown rv_type: %d", name(), (int)rv_type);
}
setMiscRegNoEffect(idx, status);
return readMiscRegNoEffect(idx);
@@ -506,10 +528,12 @@ ISA::setMiscReg(RegIndex idx, RegVal val)
break;
case MISCREG_STATUS:
{
// SXL and UXL are hard-wired to 64 bit
auto cur = readMiscRegNoEffect(idx);
val &= ~(STATUS_SXL_MASK | STATUS_UXL_MASK);
val |= cur & (STATUS_SXL_MASK | STATUS_UXL_MASK);
if (rv_type != RV32) {
// SXL and UXL are hard-wired to 64 bit
auto cur = readMiscRegNoEffect(idx);
val &= ~(STATUS_SXL_MASK | STATUS_UXL_MASK);
val |= cur & (STATUS_SXL_MASK | STATUS_UXL_MASK);
}
setMiscRegNoEffect(idx, val);
}
break;

View File

@@ -70,6 +70,7 @@ enum FPUStatus
class ISA : public BaseISA
{
protected:
RiscvType rv_type;
std::vector<RegVal> miscRegFile;
bool checkAlignment;
@@ -80,10 +81,10 @@ class ISA : public BaseISA
void clear() override;
PCStateBase *
PCStateBase*
newPCState(Addr new_inst_addr=0) const override
{
return new PCState(new_inst_addr);
return new PCState(new_inst_addr, rv_type);
}
public:
@@ -104,7 +105,7 @@ class ISA : public BaseISA
virtual const std::unordered_map<int, RegVal>&
getCSRMaskMap() const
{
return CSRMasks;
return CSRMasks[rv_type];
}
bool alignmentCheckEnabled() const { return checkAlignment; }
@@ -125,6 +126,8 @@ class ISA : public BaseISA
void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) override;
void globalClearExclusive() override;
RiscvType rvType() const { return rv_type; }
};
} // namespace RiscvISA

View File

@@ -32,6 +32,7 @@
//
// Bitfield definitions.
//
def bitfield RVTYPE rv_type;
def bitfield QUADRANT <1:0>;
def bitfield OPCODE <6:2>;

View File

@@ -39,7 +39,7 @@ def template BasicDeclare {{
public:
/// Constructor.
%(class_name)s(MachInst machInst);
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, trace::InstRecord *) const override;
using %(base_class)s::generateDisassembly;
};
@@ -47,7 +47,7 @@ def template BasicDeclare {{
// Basic instruction class constructor template.
def template BasicConstructor {{
%(class_name)s::%(class_name)s(MachInst machInst)
%(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(set_reg_idx_arr)s;

View File

@@ -125,7 +125,7 @@ def template CBasicDeclare {{
public:
/// Constructor.
%(class_name)s(MachInst machInst);
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, trace::InstRecord *) const override;
std::string generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const override;

View File

@@ -44,7 +44,7 @@ def template ImmDeclare {{
public:
/// Constructor.
%(class_name)s(MachInst machInst);
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, trace::InstRecord *) const override;
std::string generateDisassembly(Addr pc,
const loader::SymbolTable *symtab) const override;
@@ -52,7 +52,7 @@ def template ImmDeclare {{
}};
def template ImmConstructor {{
%(class_name)s::%(class_name)s(MachInst machInst)
%(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(set_reg_idx_arr)s;
@@ -168,7 +168,7 @@ def template BranchDeclare {{
public:
/// Constructor.
%(class_name)s(MachInst machInst);
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, trace::InstRecord *) const override;
std::string
@@ -198,7 +198,9 @@ def template BranchExecute {{
%(class_name)s::branchTarget(const PCStateBase &branch_pc) const
{
auto &rpc = branch_pc.as<RiscvISA::PCState>();
return std::make_unique<PCState>(rpc.pc() + imm);
std::unique_ptr<PCState> npc(dynamic_cast<PCState*>(rpc.clone()));
npc->set(rpc.pc() + imm);
return npc;
}
std::string
@@ -226,7 +228,7 @@ def template JumpDeclare {{
public:
/// Constructor.
%(class_name)s(MachInst machInst);
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, trace::InstRecord *) const override;
std::string
@@ -241,7 +243,7 @@ def template JumpDeclare {{
}};
def template JumpConstructor {{
%(class_name)s::%(class_name)s(MachInst machInst)
%(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(set_reg_idx_arr)s;

View File

@@ -43,21 +43,29 @@
#define __ARCH_RISCV_PCSTATE_HH__
#include "arch/generic/pcstate.hh"
#include "enums/RiscvType.hh"
namespace gem5
{
namespace RiscvISA
{
using RiscvType = enums::RiscvType;
constexpr enums::RiscvType RV32 = enums::RV32;
constexpr enums::RiscvType RV64 = enums::RV64;
class PCState : public GenericISA::UPCState<4>
{
private:
bool _compressed = false;
bool _rv32 = false;
RiscvType _rv_type = RV64;
public:
using GenericISA::UPCState<4>::UPCState;
PCState() = default;
PCState(const PCState &other) = default;
PCState(Addr addr, RiscvType rv_type) : UPCState(addr), _rv_type(rv_type)
{
}
PCStateBase *clone() const override { return new PCState(*this); }
@@ -67,14 +75,14 @@ class PCState : public GenericISA::UPCState<4>
Base::update(other);
auto &pcstate = other.as<PCState>();
_compressed = pcstate._compressed;
_rv32 = pcstate._rv32;
_rv_type = pcstate._rv_type;
}
void compressed(bool c) { _compressed = c; }
bool compressed() const { return _compressed; }
void rv32(bool val) { _rv32 = val; }
bool rv32() const { return _rv32; }
void rvType(RiscvType rv_type) { _rv_type = rv_type; }
RiscvType rvType() const { return _rv_type; }
bool
branching() const override

View File

@@ -115,7 +115,7 @@ RiscvProcess32::initState()
auto *tc = system->threads[ctx];
tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
PCState pc = tc->pcState().as<PCState>();
pc.rv32(true);
pc.rvType(RV32);
tc->pcState(pc);
}
}

View File

@@ -51,10 +51,12 @@
#include "arch/generic/vec_pred_reg.hh"
#include "arch/generic/vec_reg.hh"
#include "arch/riscv/types.hh"
#include "base/bitunion.hh"
#include "base/types.hh"
#include "cpu/reg_class.hh"
#include "debug/MiscRegs.hh"
#include "enums/RiscvType.hh"
namespace gem5
{
@@ -550,9 +552,10 @@ const std::unordered_map<int, CSRMetadata> CSRData = {
* the fields for higher privileges.
*/
BitUnion64(STATUS)
Bitfield<63> sd;
Bitfield<63> rv64_sd;
Bitfield<35, 34> sxl;
Bitfield<33, 32> uxl;
Bitfield<31> rv32_sd;
Bitfield<22> tsr;
Bitfield<21> tw;
Bitfield<20> tvm;
@@ -590,20 +593,34 @@ BitUnion64(INTERRUPT)
Bitfield<0> usi;
EndBitUnion(INTERRUPT)
const off_t MXL_OFFSET = (sizeof(uint64_t) * 8 - 2);
const off_t MXL_OFFSETS[enums::Num_RiscvType] = {
[RV32] = (sizeof(uint32_t) * 8 - 2),
[RV64] = (sizeof(uint64_t) * 8 - 2),
};
const off_t SXL_OFFSET = 34;
const off_t UXL_OFFSET = 32;
const off_t FS_OFFSET = 13;
const off_t FRM_OFFSET = 5;
const RegVal ISA_MXL_MASK = 3ULL << MXL_OFFSET;
const RegVal ISA_MXL_MASKS[enums::Num_RiscvType] = {
[RV32] = 3ULL << MXL_OFFSETS[RV32],
[RV64] = 3ULL << MXL_OFFSETS[RV64],
};
const RegVal ISA_EXT_MASK = mask(26);
const RegVal ISA_EXT_C_MASK = 1UL << ('c' - 'a');
const RegVal MISA_MASK = ISA_MXL_MASK | ISA_EXT_MASK;
const RegVal MISA_MASKS[enums::Num_RiscvType] = {
[RV32] = ISA_MXL_MASKS[RV32] | ISA_EXT_MASK,
[RV64] = ISA_MXL_MASKS[RV64] | ISA_EXT_MASK,
};
const RegVal STATUS_SD_MASK = 1ULL << ((sizeof(uint64_t) * 8) - 1);
const RegVal STATUS_SD_MASKS[enums::Num_RiscvType] = {
[RV32] = 1ULL << ((sizeof(uint32_t) * 8) - 1),
[RV64] = 1ULL << ((sizeof(uint64_t) * 8) - 1),
};
const RegVal STATUS_SXL_MASK = 3ULL << SXL_OFFSET;
const RegVal STATUS_UXL_MASK = 3ULL << UXL_OFFSET;
const RegVal STATUS_TSR_MASK = 1ULL << 22;
const RegVal STATUS_TW_MASK = 1ULL << 21;
const RegVal STATUS_TVM_MASK = 1ULL << 20;
@@ -621,26 +638,39 @@ const RegVal STATUS_UPIE_MASK = 1ULL << 4;
const RegVal STATUS_MIE_MASK = 1ULL << 3;
const RegVal STATUS_SIE_MASK = 1ULL << 1;
const RegVal STATUS_UIE_MASK = 1ULL << 0;
const RegVal MSTATUS_MASK = STATUS_SD_MASK | STATUS_SXL_MASK |
STATUS_UXL_MASK | STATUS_TSR_MASK |
STATUS_TW_MASK | STATUS_TVM_MASK |
STATUS_MXR_MASK | STATUS_SUM_MASK |
STATUS_MPRV_MASK | STATUS_XS_MASK |
STATUS_FS_MASK | STATUS_VS_MASK |
STATUS_MPP_MASK | STATUS_SPP_MASK |
STATUS_MPIE_MASK | STATUS_SPIE_MASK |
STATUS_UPIE_MASK | STATUS_MIE_MASK |
STATUS_SIE_MASK | STATUS_UIE_MASK;
const RegVal SSTATUS_MASK = STATUS_SD_MASK | STATUS_UXL_MASK |
STATUS_MXR_MASK | STATUS_SUM_MASK |
STATUS_XS_MASK | STATUS_FS_MASK |
STATUS_VS_MASK | STATUS_SPP_MASK |
STATUS_SPIE_MASK | STATUS_UPIE_MASK |
STATUS_SIE_MASK | STATUS_UIE_MASK;
const RegVal USTATUS_MASK = STATUS_SD_MASK | STATUS_MXR_MASK |
STATUS_SUM_MASK | STATUS_XS_MASK |
STATUS_FS_MASK | STATUS_VS_MASK |
STATUS_UPIE_MASK | STATUS_UIE_MASK;
const RegVal MSTATUS_MASKS[enums::Num_RiscvType] = {
[RV32] = STATUS_SD_MASKS[RV32] | STATUS_TSR_MASK | STATUS_TW_MASK |
STATUS_TVM_MASK | STATUS_MXR_MASK | STATUS_SUM_MASK |
STATUS_MPRV_MASK | STATUS_XS_MASK | STATUS_FS_MASK |
STATUS_VS_MASK | STATUS_MPP_MASK | STATUS_SPP_MASK |
STATUS_MPIE_MASK | STATUS_SPIE_MASK | STATUS_UPIE_MASK |
STATUS_MIE_MASK | STATUS_SIE_MASK | STATUS_UIE_MASK,
[RV64] = STATUS_SD_MASKS[RV64] | STATUS_SXL_MASK | STATUS_UXL_MASK |
STATUS_TSR_MASK | STATUS_TW_MASK | STATUS_TVM_MASK |
STATUS_MXR_MASK | STATUS_SUM_MASK | STATUS_MPRV_MASK |
STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK|
STATUS_MPP_MASK | STATUS_SPP_MASK | STATUS_MPIE_MASK |
STATUS_SPIE_MASK | STATUS_UPIE_MASK | STATUS_MIE_MASK |
STATUS_SIE_MASK | STATUS_UIE_MASK,
};
const RegVal SSTATUS_MASKS[enums::Num_RiscvType] = {
[RV32] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | STATUS_SUM_MASK |
STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK |
STATUS_SPP_MASK | STATUS_SPIE_MASK | STATUS_UPIE_MASK |
STATUS_SIE_MASK | STATUS_UIE_MASK,
[RV64] = STATUS_SD_MASKS[RV64] | STATUS_UXL_MASK | STATUS_MXR_MASK |
STATUS_SUM_MASK | STATUS_XS_MASK | STATUS_FS_MASK |
STATUS_VS_MASK | STATUS_SPP_MASK | STATUS_SPIE_MASK |
STATUS_UPIE_MASK | STATUS_SIE_MASK | STATUS_UIE_MASK,
};
const RegVal USTATUS_MASKS[enums::Num_RiscvType] = {
[RV32] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | STATUS_SUM_MASK |
STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK |
STATUS_UPIE_MASK | STATUS_UIE_MASK,
[RV64] = STATUS_SD_MASKS[RV64] | STATUS_MXR_MASK | STATUS_SUM_MASK |
STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK |
STATUS_UPIE_MASK | STATUS_UIE_MASK,
};
const RegVal MEI_MASK = 1ULL << 11;
const RegVal SEI_MASK = 1ULL << 9;
@@ -661,20 +691,38 @@ const RegVal UI_MASK = UEI_MASK | UTI_MASK | USI_MASK;
const RegVal FFLAGS_MASK = (1 << FRM_OFFSET) - 1;
const RegVal FRM_MASK = 0x7;
const std::unordered_map<int, RegVal> CSRMasks = {
{CSR_USTATUS, USTATUS_MASK},
{CSR_UIE, UI_MASK},
{CSR_UIP, UI_MASK},
{CSR_FFLAGS, FFLAGS_MASK},
{CSR_FRM, FRM_MASK},
{CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)},
{CSR_SSTATUS, SSTATUS_MASK},
{CSR_SIE, SI_MASK},
{CSR_SIP, SI_MASK},
{CSR_MSTATUS, MSTATUS_MASK},
{CSR_MISA, MISA_MASK},
{CSR_MIE, MI_MASK},
{CSR_MIP, MI_MASK}
const RegVal CAUSE_INTERRUPT_MASKS[enums::Num_RiscvType] = {
[RV32] = (1ULL << 31),
[RV64] = (1ULL << 63),
};
const std::unordered_map<int, RegVal> CSRMasks[enums::Num_RiscvType] = {
[RV32] = {{CSR_USTATUS, USTATUS_MASKS[RV32]},
{CSR_UIE, UI_MASK},
{CSR_UIP, UI_MASK},
{CSR_FFLAGS, FFLAGS_MASK},
{CSR_FRM, FRM_MASK},
{CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)},
{CSR_SSTATUS, SSTATUS_MASKS[RV32]},
{CSR_SIE, SI_MASK},
{CSR_SIP, SI_MASK},
{CSR_MSTATUS, MSTATUS_MASKS[RV32]},
{CSR_MISA, MISA_MASKS[RV32]},
{CSR_MIE, MI_MASK},
{CSR_MIP, MI_MASK}},
[RV64] = {{CSR_USTATUS, USTATUS_MASKS[RV64]},
{CSR_UIE, UI_MASK},
{CSR_UIP, UI_MASK},
{CSR_FFLAGS, FFLAGS_MASK},
{CSR_FRM, FRM_MASK},
{CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)},
{CSR_SSTATUS, SSTATUS_MASKS[RV64]},
{CSR_SIE, SI_MASK},
{CSR_SIP, SI_MASK},
{CSR_MSTATUS, MSTATUS_MASKS[RV64]},
{CSR_MISA, MISA_MASKS[RV64]},
{CSR_MIE, MI_MASK},
{CSR_MIP, MI_MASK}},
};
} // namespace RiscvISA

View File

@@ -135,10 +135,10 @@
#include <string>
#include "arch/riscv/gdb-xml/gdb_xml_riscv_cpu.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_csr.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_fpu.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_target.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_64bit_cpu.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_64bit_csr.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_64bit_fpu.hh"
#include "arch/riscv/gdb-xml/gdb_xml_riscv_64bit_target.hh"
#include "arch/riscv/mmu.hh"
#include "arch/riscv/pagetable_walker.hh"
#include "arch/riscv/regs/float.hh"
@@ -155,8 +155,16 @@ namespace gem5
using namespace RiscvISA;
static RiscvType
getRvType(ThreadContext* tc)
{
auto isa = dynamic_cast<ISA*>(tc->getIsaPtr());
panic_if(!isa, "Cannot derive rv_type from non-riscv isa");
return isa->rvType();
}
RemoteGDB::RemoteGDB(System *_system, int _port)
: BaseRemoteGDB(_system, _port), regCache(this)
: BaseRemoteGDB(_system, _port), regCache64(this)
{
}
@@ -186,9 +194,10 @@ RemoteGDB::acc(Addr va, size_t len)
}
void
RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
RemoteGDB::Riscv64GdbRegCache::getRegs(ThreadContext *context)
{
DPRINTF(GDBAcc, "getregs in remotegdb, size %lu\n", size());
auto& RVxCSRMasks = CSRMasks[RV64];
// General registers
for (int i = 0; i < int_reg::NumArchRegs; i++) {
@@ -200,11 +209,11 @@ RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
for (int i = 0; i < float_reg::NumRegs; i++)
r.fpu[i] = context->getReg(floatRegClass[i]);
r.fflags = context->readMiscRegNoEffect(
CSRData.at(CSR_FFLAGS).physIndex) & CSRMasks.at(CSR_FFLAGS);
CSRData.at(CSR_FFLAGS).physIndex) & RVxCSRMasks.at(CSR_FFLAGS);
r.frm = context->readMiscRegNoEffect(
CSRData.at(CSR_FRM).physIndex) & CSRMasks.at(CSR_FRM);
CSRData.at(CSR_FRM).physIndex) & RVxCSRMasks.at(CSR_FRM);
r.fcsr = context->readMiscRegNoEffect(
CSRData.at(CSR_FCSR).physIndex) & CSRMasks.at(CSR_FCSR);
CSRData.at(CSR_FCSR).physIndex) & RVxCSRMasks.at(CSR_FCSR);
// CSR registers
r.cycle = context->readMiscRegNoEffect(
@@ -214,9 +223,9 @@ RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
// U mode CSR
r.ustatus = context->readMiscRegNoEffect(
CSRData.at(CSR_USTATUS).physIndex) & CSRMasks.at(CSR_USTATUS);
CSRData.at(CSR_USTATUS).physIndex) & RVxCSRMasks.at(CSR_USTATUS);
r.uie = context->readMiscReg(
CSRData.at(CSR_UIE).physIndex) & CSRMasks.at(CSR_UIE);
CSRData.at(CSR_UIE).physIndex) & RVxCSRMasks.at(CSR_UIE);
r.utvec = context->readMiscRegNoEffect(
CSRData.at(CSR_UTVEC).physIndex);
r.uscratch = context->readMiscRegNoEffect(
@@ -228,17 +237,17 @@ RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
r.utval = context->readMiscRegNoEffect(
CSRData.at(CSR_UTVAL).physIndex);
r.uip = context->readMiscReg(
CSRData.at(CSR_UIP).physIndex) & CSRMasks.at(CSR_UIP);
CSRData.at(CSR_UIP).physIndex) & RVxCSRMasks.at(CSR_UIP);
// S mode CSR
r.sstatus = context->readMiscRegNoEffect(
CSRData.at(CSR_SSTATUS).physIndex) & CSRMasks.at(CSR_SSTATUS);
CSRData.at(CSR_SSTATUS).physIndex) & RVxCSRMasks.at(CSR_SSTATUS);
r.sedeleg = context->readMiscRegNoEffect(
CSRData.at(CSR_SEDELEG).physIndex);
r.sideleg = context->readMiscRegNoEffect(
CSRData.at(CSR_SIDELEG).physIndex);
r.sie = context->readMiscReg(
CSRData.at(CSR_SIE).physIndex) & CSRMasks.at(CSR_SIE);
CSRData.at(CSR_SIE).physIndex) & RVxCSRMasks.at(CSR_SIE);
r.stvec = context->readMiscRegNoEffect(
CSRData.at(CSR_STVEC).physIndex);
r.scounteren = context->readMiscRegNoEffect(
@@ -252,7 +261,7 @@ RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
r.stval = context->readMiscRegNoEffect(
CSRData.at(CSR_STVAL).physIndex);
r.sip = context->readMiscReg(
CSRData.at(CSR_SIP).physIndex) & CSRMasks.at(CSR_SIP);
CSRData.at(CSR_SIP).physIndex) & RVxCSRMasks.at(CSR_SIP);
r.satp = context->readMiscRegNoEffect(
CSRData.at(CSR_SATP).physIndex);
@@ -266,15 +275,15 @@ RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
r.mhartid = context->readMiscRegNoEffect(
CSRData.at(CSR_MHARTID).physIndex);
r.mstatus = context->readMiscRegNoEffect(
CSRData.at(CSR_MSTATUS).physIndex) & CSRMasks.at(CSR_MSTATUS);
CSRData.at(CSR_MSTATUS).physIndex) & RVxCSRMasks.at(CSR_MSTATUS);
r.misa = context->readMiscRegNoEffect(
CSRData.at(CSR_MISA).physIndex) & CSRMasks.at(CSR_MISA);
CSRData.at(CSR_MISA).physIndex) & RVxCSRMasks.at(CSR_MISA);
r.medeleg = context->readMiscRegNoEffect(
CSRData.at(CSR_MEDELEG).physIndex);
r.mideleg = context->readMiscRegNoEffect(
CSRData.at(CSR_MIDELEG).physIndex);
r.mie = context->readMiscReg(
CSRData.at(CSR_MIE).physIndex) & CSRMasks.at(CSR_MIE);
CSRData.at(CSR_MIE).physIndex) & RVxCSRMasks.at(CSR_MIE);
r.mtvec = context->readMiscRegNoEffect(
CSRData.at(CSR_MTVEC).physIndex);
r.mcounteren = context->readMiscRegNoEffect(
@@ -288,13 +297,13 @@ RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
r.mtval = context->readMiscRegNoEffect(
CSRData.at(CSR_MTVAL).physIndex);
r.mip = context->readMiscReg(
CSRData.at(CSR_MIP).physIndex) & CSRMasks.at(CSR_MIP);
CSRData.at(CSR_MIP).physIndex) & RVxCSRMasks.at(CSR_MIP);
// H mode CSR (to be implemented)
}
void
RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
RemoteGDB::Riscv64GdbRegCache::setRegs(ThreadContext *context) const
{
// NOTE: no error will be reported for attempting to set masked bits.
RegVal oldVal;
@@ -310,23 +319,25 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
for (int i = 0; i < float_reg::NumRegs; i++)
context->setReg(floatRegClass[i], r.fpu[i]);
auto& RVxCSRMasks = CSRMasks[RV64];
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_FFLAGS).physIndex);
mask = CSRMasks.at(CSR_FFLAGS);
mask = RVxCSRMasks.at(CSR_FFLAGS);
newVal = (oldVal & ~mask) | (r.fflags & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_FFLAGS).physIndex, newVal);
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_FRM).physIndex);
mask = CSRMasks.at(CSR_FRM);
mask = RVxCSRMasks.at(CSR_FRM);
newVal = (oldVal & ~mask) | (r.frm & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_FRM).physIndex, newVal);
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_FCSR).physIndex);
mask = CSRMasks.at(CSR_FCSR);
mask = RVxCSRMasks.at(CSR_FCSR);
newVal = (oldVal & ~mask) | (r.fcsr & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_FCSR).physIndex, newVal);
@@ -340,13 +351,13 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
// U mode CSR
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_USTATUS).physIndex);
mask = CSRMasks.at(CSR_USTATUS);
mask = RVxCSRMasks.at(CSR_USTATUS);
newVal = (oldVal & ~mask) | (r.ustatus & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_USTATUS).physIndex, newVal);
oldVal = context->readMiscReg(
CSRData.at(CSR_UIE).physIndex);
mask = CSRMasks.at(CSR_UIE);
mask = RVxCSRMasks.at(CSR_UIE);
newVal = (oldVal & ~mask) | (r.uie & mask);
context->setMiscReg(
CSRData.at(CSR_UIE).physIndex, newVal);
@@ -362,7 +373,7 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
CSRData.at(CSR_UTVAL).physIndex, r.utval);
oldVal = context->readMiscReg(
CSRData.at(CSR_UIP).physIndex);
mask = CSRMasks.at(CSR_UIP);
mask = RVxCSRMasks.at(CSR_UIP);
newVal = (oldVal & ~mask) | (r.uip & mask);
context->setMiscReg(
CSRData.at(CSR_UIP).physIndex, newVal);
@@ -370,7 +381,7 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
// S mode CSR
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_SSTATUS).physIndex);
mask = CSRMasks.at(CSR_SSTATUS);
mask = RVxCSRMasks.at(CSR_SSTATUS);
newVal = (oldVal & ~mask) | (r.sstatus & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_SSTATUS).physIndex, newVal);
@@ -380,7 +391,7 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
CSRData.at(CSR_SIDELEG).physIndex, r.sideleg);
oldVal = context->readMiscReg(
CSRData.at(CSR_SIE).physIndex);
mask = CSRMasks.at(CSR_SIE);
mask = RVxCSRMasks.at(CSR_SIE);
newVal = (oldVal & ~mask) | (r.sie & mask);
context->setMiscReg(
CSRData.at(CSR_SIE).physIndex, newVal);
@@ -398,7 +409,7 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
CSRData.at(CSR_STVAL).physIndex, r.stval);
oldVal = context->readMiscReg(
CSRData.at(CSR_SIP).physIndex);
mask = CSRMasks.at(CSR_SIP);
mask = RVxCSRMasks.at(CSR_SIP);
newVal = (oldVal & ~mask) | (r.sip & mask);
context->setMiscReg(
CSRData.at(CSR_SIP).physIndex, newVal);
@@ -416,13 +427,13 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
CSRData.at(CSR_MHARTID).physIndex, r.mhartid);
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_MSTATUS).physIndex);
mask = CSRMasks.at(CSR_MSTATUS);
mask = RVxCSRMasks.at(CSR_MSTATUS);
newVal = (oldVal & ~mask) | (r.mstatus & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_MSTATUS).physIndex, newVal);
oldVal = context->readMiscRegNoEffect(
CSRData.at(CSR_MISA).physIndex);
mask = CSRMasks.at(CSR_MISA);
mask = RVxCSRMasks.at(CSR_MISA);
newVal = (oldVal & ~mask) | (r.misa & mask);
context->setMiscRegNoEffect(
CSRData.at(CSR_MISA).physIndex, newVal);
@@ -432,7 +443,7 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
CSRData.at(CSR_MIDELEG).physIndex, r.mideleg);
oldVal = context->readMiscReg(
CSRData.at(CSR_MIE).physIndex);
mask = CSRMasks.at(CSR_MIE);
mask = RVxCSRMasks.at(CSR_MIE);
newVal = (oldVal & ~mask) | (r.mie & mask);
context->setMiscReg(
CSRData.at(CSR_MIE).physIndex, newVal);
@@ -450,7 +461,7 @@ RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
CSRData.at(CSR_MTVAL).physIndex, r.mtval);
oldVal = context->readMiscReg(
CSRData.at(CSR_MIP).physIndex);
mask = CSRMasks.at(CSR_MIP);
mask = RVxCSRMasks.at(CSR_MIP);
newVal = (oldVal & ~mask) | (r.mip & mask);
context->setMiscReg(
CSRData.at(CSR_MIP).physIndex, newVal);
@@ -473,11 +484,13 @@ RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output)
Blobs::s##_len) \
}
static const std::map<std::string, std::string> annexMap{
GDB_XML("target.xml", gdb_xml_riscv_target),
GDB_XML("riscv-64bit-cpu.xml", gdb_xml_riscv_cpu),
GDB_XML("riscv-64bit-fpu.xml", gdb_xml_riscv_fpu),
GDB_XML("riscv-64bit-csr.xml", gdb_xml_riscv_csr)};
GDB_XML("riscv-64bit.xml", gdb_xml_riscv_64bit_target),
GDB_XML("riscv-64bit-cpu.xml", gdb_xml_riscv_64bit_cpu),
GDB_XML("riscv-64bit-fpu.xml", gdb_xml_riscv_64bit_fpu),
GDB_XML("riscv-64bit-csr.xml", gdb_xml_riscv_64bit_csr)};
#undef GDB_XML
if (getRvType(context()) == RV32)
return false;
auto it = annexMap.find(annex);
if (it == annexMap.end())
return false;
@@ -488,7 +501,7 @@ RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output)
BaseGdbRegCache *
RemoteGDB::gdbRegs()
{
return &regCache;
return &regCache64;
}
} // namespace gem5

View File

@@ -58,7 +58,7 @@ class RemoteGDB : public BaseRemoteGDB
// A breakpoint will be 2 bytes if it is compressed and 4 if not
bool checkBpKind(size_t kind) override { return kind == 2 || kind == 4; }
class RiscvGdbRegCache : public BaseGdbRegCache
class Riscv64GdbRegCache : public BaseGdbRegCache
{
using BaseGdbRegCache::BaseGdbRegCache;
private:
@@ -142,7 +142,7 @@ class RemoteGDB : public BaseRemoteGDB
}
};
RiscvGdbRegCache regCache;
Riscv64GdbRegCache regCache64;
public:
RemoteGDB(System *_system, int _port);

View File

@@ -43,6 +43,7 @@
#define __ARCH_RISCV_TYPES_HH__
#include "arch/riscv/pcstate.hh"
#include "base/bitunion.hh"
namespace gem5
{
@@ -51,7 +52,13 @@ namespace RiscvISA
{
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
// This should be further extend someday when we start to support 64b+ inst.
// For now, we should be safe using the msbs to store extra information.
BitUnion64(ExtMachInst)
// Decoder state
Bitfield<63, 62> rv_type;
EndBitUnion(ExtMachInst)
} // namespace RiscvISA
} // namespace gem5