summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2018-08-30 16:43:02 +0100
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2018-09-10 10:24:10 +0000
commit579443c64fd176ec2af4c7f38b3d37484ad21ffa (patch)
tree30fef6eda22a6ea0e7b334c59a6ca62e06e94850 /src
parent4c9ba9cd2925c83889c6388b4f5a15820bd9986b (diff)
downloadgem5-579443c64fd176ec2af4c7f38b3d37484ad21ffa.tar.xz
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>
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/pmu.cc2
-rw-r--r--src/dev/arm/Gic.py4
-rw-r--r--src/dev/arm/base_gic.cc72
-rw-r--r--src/dev/arm/base_gic.hh72
-rw-r--r--src/dev/arm/vio_mmio.cc3
5 files changed, 126 insertions, 27 deletions
diff --git a/src/arch/arm/pmu.cc b/src/arch/arm/pmu.cc
index 13b23c745..b569b6967 100644
--- a/src/arch/arm/pmu.cc
+++ b/src/arch/arm/pmu.cc
@@ -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");
diff --git a/src/dev/arm/Gic.py b/src/dev/arm/Gic.py
index 5f756639e..4cc661f0b 100644
--- a/src/dev/arm/Gic.py
+++ b/src/dev/arm/Gic.py
@@ -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'
diff --git a/src/dev/arm/base_gic.cc b/src/dev/arm/base_gic.cc
index 65754d018..864bad38f 100644
--- a/src/dev/arm/base_gic.cc
+++ b/src/dev/arm/base_gic.cc
@@ -70,12 +70,53 @@ BaseGic::params() const
return dynamic_cast<const Params *>(_params);
}
+ArmInterruptPinGen::ArmInterruptPinGen(const ArmInterruptPinParams *p)
+ : SimObject(p)
+{
+}
+
+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::ArmInterruptPin(const ArmInterruptPinParams *p)
- : SimObject(p),
- threadContext(nullptr),
- platform(dynamic_cast<RealView*>(p->platform)),
- intNum(p->num)
+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);
}
diff --git a/src/dev/arm/base_gic.hh b/src/dev/arm/base_gic.hh
index c5dfa3e82..f18539fe8 100644
--- a/src/dev/arm/base_gic.hh
+++ b/src/dev/arm/base_gic.hh
@@ -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 ArmInterruptPinGen : public SimObject
+{
+ public:
+ 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 ArmInterruptPin : public SimObject
+class ArmPPIGen : public ArmInterruptPinGen
{
public:
- ArmInterruptPin(const ArmInterruptPinParams *p);
+ 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
diff --git a/src/dev/arm/vio_mmio.cc b/src/dev/arm/vio_mmio.cc
index 1dcaf8cd9..9f7bf1333 100644
--- a/src/dev/arm/vio_mmio.cc
+++ b/src/dev/arm/vio_mmio.cc
@@ -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");