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:
@@ -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");
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user