From 579443c64fd176ec2af4c7f38b3d37484ad21ffa Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 30 Aug 2018 16:43:02 +0100 Subject: 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 Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/12401 Maintainer: Andreas Sandberg --- src/arch/arm/pmu.cc | 2 +- src/dev/arm/Gic.py | 4 ++- src/dev/arm/base_gic.cc | 72 ++++++++++++++++++++++++++++++++++++++----------- src/dev/arm/base_gic.hh | 72 +++++++++++++++++++++++++++++++++++++++++++------ src/dev/arm/vio_mmio.cc | 3 ++- 5 files changed, 126 insertions(+), 27 deletions(-) (limited to 'src') 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(_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(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(_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(_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 + #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 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"); -- cgit v1.2.3