dev-arm: Factory SimObject for generating ArmInterruptPin

With this patch the python ArmInterruptPin SimObject matches to the
C++ ArmInterruptPinGen. The latter is in charge of generating
the ArmInterruptPin (which is not a SimObject anymore).
This is meant to ease the generation of ArmInterruptPins: by
not being SimObjects we are not forced to instantiate them
in the configuration script; we can generate them dynamically
instead throughout simulation.

Change-Id: I917d73a26168447221f5993c8ae975ee3771e3bf
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/12401
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
Giacomo Travaglini
2018-08-30 16:43:02 +01:00
parent 4c9ba9cd29
commit 579443c64f
5 changed files with 126 additions and 27 deletions

View File

@@ -67,7 +67,7 @@ PMU::PMU(const ArmPMUParams *p)
cycleCounterEventId(p->cycleEventId),
swIncrementEvent(nullptr),
reg_pmcr_conf(0),
interrupt(p->interrupt)
interrupt(p->interrupt->get())
{
DPRINTF(PMUVerbose, "Initializing the PMU.\n");

View File

@@ -52,6 +52,7 @@ class BaseGic(PioDevice):
class ArmInterruptPin(SimObject):
type = 'ArmInterruptPin'
cxx_header = "dev/arm/base_gic.hh"
cxx_class = "ArmInterruptPinGen"
abstract = True
platform = Param.Platform(Parent.any, "Platform with interrupt controller")
@@ -60,11 +61,12 @@ class ArmInterruptPin(SimObject):
class ArmSPI(ArmInterruptPin):
type = 'ArmSPI'
cxx_header = "dev/arm/base_gic.hh"
cxx_class = "ArmSPIGen"
class ArmPPI(ArmInterruptPin):
type = 'ArmPPI'
cxx_header = "dev/arm/base_gic.hh"
cxx_class = "ArmPPIGen"
class Pl390(BaseGic):
type = 'Pl390'

View File

@@ -70,12 +70,53 @@ BaseGic::params() const
return dynamic_cast<const Params *>(_params);
}
ArmInterruptPinGen::ArmInterruptPinGen(const ArmInterruptPinParams *p)
: SimObject(p)
{
}
ArmInterruptPin::ArmInterruptPin(const ArmInterruptPinParams *p)
: SimObject(p),
threadContext(nullptr),
platform(dynamic_cast<RealView*>(p->platform)),
intNum(p->num)
ArmSPIGen::ArmSPIGen(const ArmSPIParams *p)
: ArmInterruptPinGen(p), pin(new ArmSPI(p->platform, p->num))
{
}
ArmInterruptPin*
ArmSPIGen::get(ThreadContext* tc)
{
return pin;
}
ArmPPIGen::ArmPPIGen(const ArmPPIParams *p)
: ArmInterruptPinGen(p)
{
}
ArmInterruptPin*
ArmPPIGen::get(ThreadContext* tc)
{
panic_if(!tc, "Invalid Thread Context\n");
ContextID cid = tc->contextId();
auto pin_it = pins.find(cid);
if (pin_it != pins.end()) {
// PPI Pin Already generated
return pin_it->second;
} else {
// Generate PPI Pin
auto p = static_cast<const ArmPPIParams *>(_params);
ArmPPI *pin = new ArmPPI(p->platform, tc, p->num);
pins.insert({cid, pin});
return pin;
}
}
ArmInterruptPin::ArmInterruptPin(
Platform *_platform, ThreadContext *tc, uint32_t int_num)
: threadContext(tc), platform(dynamic_cast<RealView*>(_platform)),
intNum(int_num)
{
fatal_if(!platform, "Interrupt not connected to a RealView platform");
}
@@ -97,10 +138,9 @@ ArmInterruptPin::targetContext() const
return threadContext->contextId();
}
ArmSPI::ArmSPI(const ArmSPIParams *p)
: ArmInterruptPin(p)
ArmSPI::ArmSPI(
Platform *_platform, uint32_t int_num)
: ArmInterruptPin(_platform, nullptr, int_num)
{
}
@@ -116,8 +156,9 @@ ArmSPI::clear()
platform->gic->clearInt(intNum);
}
ArmPPI::ArmPPI(const ArmPPIParams *p)
: ArmInterruptPin(p)
ArmPPI::ArmPPI(
Platform *_platform, ThreadContext *tc, uint32_t int_num)
: ArmInterruptPin(_platform, tc, int_num)
{
}
@@ -133,15 +174,14 @@ ArmPPI::clear()
platform->gic->clearPPInt(intNum, targetContext());
}
ArmSPI *
ArmSPIGen *
ArmSPIParams::create()
{
return new ArmSPI(this);
return new ArmSPIGen(this);
}
ArmPPI *
ArmPPIGen *
ArmPPIParams::create()
{
return new ArmPPI(this);
return new ArmPPIGen(this);
}

View File

@@ -44,11 +44,16 @@
#ifndef __DEV_ARM_BASE_GIC_H__
#define __DEV_ARM_BASE_GIC_H__
#include <unordered_map>
#include "dev/io_device.hh"
class Platform;
class RealView;
class ThreadContext;
class ArmInterruptPin;
class ArmSPI;
class ArmPPI;
struct ArmInterruptPinParams;
struct ArmPPIParams;
@@ -111,12 +116,59 @@ class BaseGicRegisters
};
/**
* Generic representation of an Arm interrupt pin.
* This SimObject is instantiated in the python world and
* serves as an ArmInterruptPin generator. In this way it
* is possible to instantiate a single generator per component
* during configuration, and to dynamically spawn ArmInterruptPins.
* See ArmPPIGen for more info on how this is used.
*/
class ArmInterruptPin : public SimObject
class ArmInterruptPinGen : public SimObject
{
public:
ArmInterruptPin(const ArmInterruptPinParams *p);
ArmInterruptPinGen(const ArmInterruptPinParams *p);
virtual ArmInterruptPin* get(ThreadContext *tc = nullptr) = 0;
};
/**
* Shared Peripheral Interrupt Generator
* It is capable of generating one interrupt only: it maintains a pointer
* to it and returns it every time it is asked for it (via the get metod)
*/
class ArmSPIGen : public ArmInterruptPinGen
{
public:
ArmSPIGen(const ArmSPIParams *p);
ArmInterruptPin* get(ThreadContext *tc = nullptr) override;
protected:
ArmSPI* pin;
};
/**
* Private Peripheral Interrupt Generator
* Since PPIs are banked in the GIC, this class is capable of generating
* more than one interrupt (one per ContextID).
*/
class ArmPPIGen : public ArmInterruptPinGen
{
public:
ArmPPIGen(const ArmPPIParams *p);
ArmInterruptPin* get(ThreadContext* tc = nullptr) override;
protected:
std::unordered_map<ContextID, ArmPPI*> pins;
};
/**
* Generic representation of an Arm interrupt pin.
*/
class ArmInterruptPin
{
friend class ArmInterruptPinGen;
protected:
ArmInterruptPin(Platform *platform, ThreadContext *tc,
uint32_t int_num);
public: /* Public interface */
/**
@@ -153,27 +205,31 @@ class ArmInterruptPin : public SimObject
/** Arm platform to use for interrupt generation */
RealView *const platform;
/** Interrupt number to generate */
const uint32_t intNum;
};
class ArmSPI : public ArmInterruptPin
{
public:
ArmSPI(const ArmSPIParams *p);
friend class ArmSPIGen;
private:
ArmSPI(Platform *platform, uint32_t int_num);
public:
void raise() override;
void clear() override;
};
class ArmPPI : public ArmInterruptPin
{
public:
ArmPPI(const ArmPPIParams *p);
friend class ArmPPIGen;
private:
ArmPPI(Platform *platform, ThreadContext *tc, uint32_t int_num);
public:
void raise() override;
void clear() override;
};
#endif

View File

@@ -48,7 +48,8 @@ MmioVirtIO::MmioVirtIO(const MmioVirtIOParams *params)
: BasicPioDevice(params, params->pio_size),
hostFeaturesSelect(0), guestFeaturesSelect(0), pageSize(0),
interruptStatus(0),
callbackKick(this), vio(*params->vio), interrupt(params->interrupt)
callbackKick(this), vio(*params->vio),
interrupt(params->interrupt->get())
{
fatal_if(!interrupt, "No MMIO VirtIO interrupt specified\n");