arch-riscv: enable rudimentary fs simulation

These changes enable a simple binary to be simulated in full system mode.
Additionally, a new fault was implemented.
It is executed once the CPU is initialized.
This fault clears all interrupts and sets the pc to a reset vector.

Change-Id: I50cfac91a61ba39a6ef3d38caca8794073887c88
Reviewed-on: https://gem5-review.googlesource.com/9061
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Robert
2018-03-13 14:29:00 +01:00
committed by Robert Scheffel
parent 98cbcbb54f
commit 5de8ca9550
12 changed files with 322 additions and 32 deletions

View File

@@ -28,10 +28,23 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Alec Roelke
# Robert Scheffel
from m5.params import *
from System import System
class RiscvSystem(System):
type = 'RiscvSystem'
cxx_header = 'arch/riscv/system.hh'
bare_metal = Param.Bool(False, "Using Bare Metal Application?")
reset_vect = Param.Addr(0x0, 'Reset vector')
load_addr_mask = 0xFFFFFFFFFFFFFFFF
class BareMetalRiscvSystem(RiscvSystem):
type = 'BareMetalRiscvSystem'
cxx_header = 'arch/riscv/bare_metal/system.hh'
bootloader = Param.String("File, that contains the bootloader code")
bare_metal = True

View File

@@ -57,10 +57,13 @@ if env['TARGET_ISA'] == 'riscv':
Source('stacktrace.cc')
Source('tlb.cc')
Source('system.cc')
Source('utility.cc')
Source('linux/process.cc')
Source('linux/linux.cc')
Source('bare_metal/system.cc')
SimObject('RiscvInterrupts.py')
SimObject('RiscvISA.py')
SimObject('RiscvTLB.py')

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 TU Dresden
* 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: Robert Scheffel
*/
#include "arch/riscv/bare_metal/system.hh"
#include "base/loader/object_file.hh"
BareMetalRiscvSystem::BareMetalRiscvSystem(Params *p)
: RiscvSystem(p),
bootloader(createObjectFile(p->bootloader))
{
if (bootloader == NULL) {
fatal("Could not load bootloader file %s", p->bootloader);
}
_resetVect = bootloader->entryPoint();
}
BareMetalRiscvSystem::~BareMetalRiscvSystem()
{
delete bootloader;
}
void
BareMetalRiscvSystem::initState()
{
// Call the initialisation of the super class
RiscvSystem::initState();
// load program sections into memory
if (!bootloader->loadSections(physProxy)) {
warn("could not load sections to memory");
}
}
BareMetalRiscvSystem *
BareMetalRiscvSystemParams::create()
{
return new BareMetalRiscvSystem(this);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2018 TU Dresden
* 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: Robert Scheffel
*/
#ifndef __ARCH_RISCV_BARE_METAL_SYSTEM_HH__
#define __ARCH_RISCV_BARE_METAL_SYSTEM_HH__
#include "arch/riscv/system.hh"
#include "params/BareMetalRiscvSystem.hh"
class BareMetalRiscvSystem : public RiscvSystem
{
protected:
ObjectFile* bootloader;
public:
typedef BareMetalRiscvSystemParams Params;
BareMetalRiscvSystem(Params *p);
~BareMetalRiscvSystem();
// initialize the system
virtual void initState();
};
#endif // __ARCH_RISCV_BARE_METAL_SYSTEM_HH__

View File

@@ -1,6 +1,7 @@
/*
* Copyright (c) 2016 RISC-V Foundation
* Copyright (c) 2016 The University of Virginia
* Copyright (c) 2018 TU Dresden
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,10 +28,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Alec Roelke
* Robert Scheffel
*/
#include "arch/riscv/faults.hh"
#include "arch/riscv/system.hh"
#include "arch/riscv/utility.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "sim/debug.hh"
#include "sim/full_system.hh"
@@ -56,6 +60,18 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
}
}
void Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (FullSystem) {
tc->getCpuPtr()->clearInterrupts(tc->threadId());
tc->clearArchRegs();
}
// Advance the PC to the implementation-defined reset vector
PCState pc = static_cast<RiscvSystem *>(tc->getSystemPtr())->resetVect();
tc->pcState(pc);
}
void
UnknownInstFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
{

View File

@@ -1,6 +1,7 @@
/*
* Copyright (c) 2016 RISC-V Foundation
* Copyright (c) 2016 The University of Virginia
* Copyright (c) 2018 TU Dresden
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Alec Roelke
* Robert Scheffel
*/
#ifndef __ARCH_RISCV_FAULTS_HH__
@@ -104,6 +106,27 @@ class RiscvFault : public FaultBase
invoke(ThreadContext *tc, const StaticInstPtr &inst);
};
class Reset : public FaultBase
{
public:
Reset()
: _name("reset")
{}
FaultName
name() const override
{
return _name;
}
void
invoke(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr) override;
private:
const FaultName _name;
};
class UnknownInstFault : public RiscvFault
{

View File

@@ -32,6 +32,7 @@
#define __ARCH_RISCV_INTERRUPT_HH__
#include "base/logging.hh"
#include "cpu/thread_context.hh"
#include "params/RiscvInterrupts.hh"
#include "sim/sim_object.hh"
@@ -78,13 +79,23 @@ class Interrupts : public SimObject
void
clearAll()
{
panic("Interrupts::clearAll not implemented.\n");
warn_once("Interrupts::clearAll not implemented.\n");
}
bool
checkInterrupts(ThreadContext *tc) const
{
panic("Interrupts::checkInterrupts not implemented.\n");
warn_once("Interrupts::checkInterrupts just rudimentary implemented");
/**
* read the machine interrupt register in order to check if interrupts
* are pending
* should be sufficient for now, as interrupts
* are not implemented at all
*/
if (tc->readMiscReg(MISCREG_IP))
return true;
return false;
}
Fault

View File

@@ -29,6 +29,7 @@
* Authors: Ali Saidi
* Nathan Binkert
* Jaidev Patwardhan
* Robert Scheffel
*/
#include "arch/riscv/system.hh"
@@ -44,7 +45,10 @@
using namespace LittleEndianGuest;
RiscvSystem::RiscvSystem(Params *p) : System(p)
RiscvSystem::RiscvSystem(Params *p)
: System(p),
_isBareMetal(p->bare_metal),
_resetVect(p->reset_vect)
{
}

View File

@@ -29,6 +29,7 @@
* Authors: Ali Saidi
* Nathan Binkert
* Jaidev Patwardhan
* Robert Scheffel
*/
#ifndef __ARCH_RISCV_SYSTEM_HH__
@@ -47,11 +48,23 @@
class RiscvSystem : public System
{
protected:
// checker for bare metal application
bool _isBareMetal;
// entry point for simulation
Addr _resetVect;
public:
typedef RiscvSystemParams Params;
RiscvSystem(Params *p);
~RiscvSystem();
// return reset vector
Addr resetVect() const { return _resetVect; }
// return bare metal checker
bool isBareMetal() const { return _isBareMetal; }
virtual bool breakpoint();
public:

View File

@@ -41,6 +41,7 @@
#include "arch/riscv/faults.hh"
#include "arch/riscv/pagetable.hh"
#include "arch/riscv/pra_constants.hh"
#include "arch/riscv/system.hh"
#include "arch/riscv/utility.hh"
#include "base/inifile.hh"
#include "base/str.hh"
@@ -285,42 +286,82 @@ TLB::regStats()
Fault
TLB::translateInst(const RequestPtr &req, ThreadContext *tc)
{
if (FullSystem)
panic("translateInst not implemented in RISC-V.\n");
if (FullSystem) {
/**
* check if we simulate a bare metal system
* if so, we have no tlb, phys addr == virt addr
*/
if (static_cast<RiscvSystem *>(tc->getSystemPtr())->isBareMetal())
req->setFlags(Request::PHYSICAL);
Process * p = tc->getProcessPtr();
if (req->getFlags() & Request::PHYSICAL) {
/**
* we simply set the virtual address to physical address
*/
req->setPaddr(req->getVaddr());
return checkCacheability(req);
} else {
/**
* as we currently support bare metal only, we throw a panic,
* if it is not a bare metal system
*/
panic("translateInst not implemented in RISC-V.\n");
}
} else {
Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req);
if (fault != NoFault)
return fault;
Fault fault = p->pTable->translate(req);
if (fault != NoFault)
return fault;
return NoFault;
return NoFault;
}
}
Fault
TLB::translateData(const RequestPtr &req, ThreadContext *tc, bool write)
{
if (FullSystem)
panic("translateData not implemented in RISC-V.\n");
if (FullSystem) {
/**
* check if we simulate a bare metal system
* if so, we have no tlb, phys addr == virt addr
*/
if (static_cast<RiscvSystem *>(tc->getSystemPtr())->isBareMetal())
req->setFlags(Request::PHYSICAL);
// In the O3 CPU model, sometimes a memory access will be speculatively
// executed along a branch that will end up not being taken where the
// address is invalid. In that case, return a fault rather than trying
// to translate it (which will cause a panic). Since RISC-V allows
// unaligned memory accesses, this should only happen if the request's
// length is long enough to wrap around from the end of the memory to the
// start.
assert(req->getSize() > 0);
if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
return make_shared<GenericPageTableFault>(req->getVaddr());
if (req->getFlags() & Request::PHYSICAL) {
/**
* we simply set the virtual address to physical address
*/
req->setPaddr(req->getVaddr());
return checkCacheability(req);
} else {
/**
* as we currently support bare metal only, we throw a panic,
* if it is not a bare metal system
*/
panic("translateData not implemented in RISC-V.\n");
}
} else {
// In the O3 CPU model, sometimes a memory access will be speculatively
// executed along a branch that will end up not being taken where the
// address is invalid. In that case, return a fault rather than trying
// to translate it (which will cause a panic). Since RISC-V allows
// unaligned memory accesses, this should only happen if the request's
// length is long enough to wrap around from the end of the memory to
// the start.
assert(req->getSize() > 0);
if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
return make_shared<GenericPageTableFault>(req->getVaddr());
Process * p = tc->getProcessPtr();
Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req);
if (fault != NoFault)
return fault;
Fault fault = p->pTable->translate(req);
if (fault != NoFault)
return fault;
return NoFault;
return NoFault;
}
}
Fault

44
src/arch/riscv/utility.cc Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018 TU Dresden
* 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: Robert Scheffel
*/
#include "arch/riscv/utility.hh"
#include "arch/riscv/faults.hh"
namespace RiscvISA
{
void initCPU(ThreadContext *tc, int cpuId)
{
static Fault reset = std::make_shared<Reset>();
reset->invoke(tc);
}
}

View File

@@ -1,6 +1,7 @@
/*
* Copyright (c) 2013 ARM Limited
* Copyright (c) 2014-2015 Sven Karlsson
* Copyright (c) 2018 TU Dresden
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -41,6 +42,7 @@
* Authors: Andreas Hansson
* Sven Karlsson
* Alec Roelke
* Robert Scheffel
*/
#ifndef __ARCH_RISCV_UTILITY_HH__
@@ -117,6 +119,7 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
inline void startupCPU(ThreadContext *tc, int cpuId)
{
tc->activate();
}
inline void
@@ -183,11 +186,10 @@ getExecutingAsid(ThreadContext *tc)
return 0;
}
inline void
initCPU(ThreadContext *, int cpuId)
{
panic("initCPU not implemented for Riscv.\n");
}
/**
* init Cpu function
*/
void initCPU(ThreadContext *tc, int cpuId);
} // namespace RiscvISA