for (int i = 0; i < p.cores.size(); i++)
p.cores[i]->setCluster(this, i);
- sc_core::sc_attr_base *base;
-
- base = evs->get_attribute(Iris::Gem5CpuClusterAttributeName);
- auto *gem5_cluster_attr =
- dynamic_cast<sc_core::sc_attribute<CortexA76Cluster *> *>(base);
- panic_if(base && !gem5_cluster_attr,
- "The EVS gem5 CPU cluster attribute was not of type "
- "sc_attribute<FastModel::CortexA76Cluster *>.");
- if (gem5_cluster_attr)
- gem5_cluster_attr->value = this;
+ Iris::BaseCpuEvs *e = dynamic_cast<Iris::BaseCpuEvs *>(evs);
+ panic_if(!e, "EVS should be of type Iris::BaseCpuEvs");
+ e->setCluster(this);
set_evs_param("core.BROADCASTATOMIC", p.BROADCASTATOMIC);
set_evs_param("core.BROADCASTCACHEMAINT", p.BROADCASTCACHEMAINT);
template <class Types>
void
-ScxEvsCortexA76<Types>::clockChangeHandler()
+ScxEvsCortexA76<Types>::setClkPeriod(Tick clk_period)
{
- clockRateControl->set_mul_div(SimClock::Int::s, clockPeriod.value);
+ clockRateControl->set_mul_div(SimClock::Int::s, clk_period);
+}
+
+template <class Types>
+void
+ScxEvsCortexA76<Types>::setCluster(SimObject *cluster)
+{
+ gem5CpuCluster = dynamic_cast<CortexA76Cluster *>(cluster);
+ panic_if(!gem5CpuCluster, "Cluster should be of type CortexA76Cluster");
}
template <class Types>
ScxEvsCortexA76<Types>::ScxEvsCortexA76(
const sc_core::sc_module_name &mod_name, const Params &p) :
Base(mod_name), amba(Base::amba, p.name + ".amba", -1),
- clockChanged(Iris::ClockEventName.c_str()),
- clockPeriod(Iris::PeriodAttributeName.c_str()),
- gem5CpuCluster(Iris::Gem5CpuClusterAttributeName.c_str()),
- sendFunctional(Iris::SendFunctionalAttributeName.c_str()),
params(p)
{
for (int i = 0; i < CoreCount; i++) {
}
clockRateControl.bind(this->clock_rate_s);
-
- this->add_attribute(gem5CpuCluster);
- this->add_attribute(clockPeriod);
- SC_METHOD(clockChangeHandler);
- this->dont_initialize();
- this->sensitive << clockChanged;
-
- sendFunctional.value = [this](PacketPtr pkt) { sendFunc(pkt); };
- this->add_attribute(sendFunctional);
}
template <class Types>
{
Base::before_end_of_elaboration();
- auto *cluster = gem5CpuCluster.value;
-
- auto set_on_change = [cluster](
+ auto set_on_change = [this](
SignalReceiver &recv, ArmInterruptPinGen *gen, int num)
{
- auto *pin = gen->get(cluster->getCore(num)->getContext(0));
+ auto *pin = gen->get(gem5CpuCluster->getCore(num)->getContext(0));
auto handler = [pin](bool status)
{
status ? pin->raise() : pin->clear();
};
for (int i = 0; i < CoreCount; i++) {
- set_on_change(*cnthpirq[i], cluster->params().cnthpirq, i);
- set_on_change(*cnthvirq[i], cluster->params().cnthvirq, i);
- set_on_change(*cntpsirq[i], cluster->params().cntpsirq, i);
- set_on_change(*cntvirq[i], cluster->params().cntvirq, i);
- set_on_change(*commirq[i], cluster->params().commirq, i);
- set_on_change(*ctidbgirq[i], cluster->params().ctidbgirq, i);
- set_on_change(*pmuirq[i], cluster->params().pmuirq, i);
- set_on_change(*vcpumntirq[i], cluster->params().vcpumntirq, i);
- set_on_change(*cntpnsirq[i], cluster->params().cntpnsirq, i);
+ set_on_change(*cnthpirq[i], gem5CpuCluster->params().cnthpirq, i);
+ set_on_change(*cnthvirq[i], gem5CpuCluster->params().cnthvirq, i);
+ set_on_change(*cntpsirq[i], gem5CpuCluster->params().cntpsirq, i);
+ set_on_change(*cntvirq[i], gem5CpuCluster->params().cntvirq, i);
+ set_on_change(*commirq[i], gem5CpuCluster->params().commirq, i);
+ set_on_change(*ctidbgirq[i], gem5CpuCluster->params().ctidbgirq, i);
+ set_on_change(*pmuirq[i], gem5CpuCluster->params().pmuirq, i);
+ set_on_change(*vcpumntirq[i], gem5CpuCluster->params().vcpumntirq, i);
+ set_on_change(*cntpnsirq[i], gem5CpuCluster->params().cntpnsirq, i);
}
}
#include "arch/arm/fastmodel/amba_ports.hh"
#include "arch/arm/fastmodel/common/signal_receiver.hh"
+#include "arch/arm/fastmodel/iris/cpu.hh"
#include "arch/arm/fastmodel/protocol/exported_clock_rate_control.hh"
#include "mem/port_proxy.hh"
#include "params/FastModelScxEvsCortexA76x1.hh"
class CortexA76Cluster;
template <class Types>
-class ScxEvsCortexA76 : public Types::Base
+class ScxEvsCortexA76 : public Types::Base, public Iris::BaseCpuEvs
{
private:
static const int CoreCount = Types::CoreCount;
std::vector<std::unique_ptr<SignalReceiver>> vcpumntirq;
std::vector<std::unique_ptr<SignalReceiver>> cntpnsirq;
- sc_core::sc_event clockChanged;
- sc_core::sc_attribute<Tick> clockPeriod;
- sc_core::sc_attribute<CortexA76Cluster *> gem5CpuCluster;
- sc_core::sc_attribute<PortProxy::SendFunctionalFunc> sendFunctional;
-
- void sendFunc(PacketPtr pkt);
-
- void clockChangeHandler();
+ CortexA76Cluster *gem5CpuCluster;
const Params ¶ms;
Base::start_of_simulation();
}
void start_of_simulation() override {}
+
+ void sendFunc(PacketPtr pkt) override;
+
+ void setClkPeriod(Tick clk_period) override;
+
+ void setCluster(SimObject *cluster) override;
};
struct ScxEvsCortexA76x1Types
for (int i = 0; i < p.cores.size(); i++)
p.cores[i]->setCluster(this, i);
- sc_core::sc_attr_base *base;
-
- base = evs->get_attribute(Iris::Gem5CpuClusterAttributeName);
- auto *gem5_cluster_attr =
- dynamic_cast<sc_core::sc_attribute<CortexR52Cluster *> *>(base);
- panic_if(base && !gem5_cluster_attr,
- "The EVS gem5 CPU cluster attribute was not of type "
- "sc_attribute<FastModel::CortexR52Cluster *>.");
- if (gem5_cluster_attr)
- gem5_cluster_attr->value = this;
+ Iris::BaseCpuEvs *e = dynamic_cast<Iris::BaseCpuEvs *>(evs);
+ panic_if(!e, "EVS should be of type Iris::BaseCpuEvs");
+ e->setCluster(this);
set_evs_param("core.CLUSTER_ID", params().CLUSTER_ID);
set_evs_param("core.DBGROMADDR", params().DBGROMADDR);
#include "arch/arm/fastmodel/CortexR52/evs.hh"
+#include "arch/arm/fastmodel/CortexR52/cortex_r52.hh"
#include "arch/arm/fastmodel/iris/cpu.hh"
#include "base/logging.hh"
#include "sim/core.hh"
template <class Types>
void
-ScxEvsCortexR52<Types>::clockChangeHandler()
+ScxEvsCortexR52<Types>::setClkPeriod(Tick clk_period)
{
- clockRateControl->set_mul_div(SimClock::Int::s, clockPeriod.value);
+ clockRateControl->set_mul_div(SimClock::Int::s, clk_period);
+}
+
+template <class Types>
+void
+ScxEvsCortexR52<Types>::setCluster(SimObject *cluster)
+{
+ gem5CpuCluster = dynamic_cast<CortexR52Cluster *>(cluster);
+ panic_if(!gem5CpuCluster, "Cluster should be of type CortexR52Cluster");
}
template <class Types>
ScxEvsCortexR52<Types>::ScxEvsCortexR52(
const sc_core::sc_module_name &mod_name, const Params &p) :
Base(mod_name),
- clockChanged(Iris::ClockEventName.c_str()),
- clockPeriod(Iris::PeriodAttributeName.c_str()),
- gem5CpuCluster(Iris::Gem5CpuClusterAttributeName.c_str()),
- sendFunctional(Iris::SendFunctionalAttributeName.c_str()),
params(p)
{
for (int i = 0; i < CoreCount; i++)
clockRateControl.bind(this->clock_rate_s);
signalInterrupt.bind(this->signal_interrupt);
-
- this->add_attribute(gem5CpuCluster);
- this->add_attribute(clockPeriod);
- SC_METHOD(clockChangeHandler);
- this->dont_initialize();
- this->sensitive << clockChanged;
-
- sendFunctional.value = [this](PacketPtr pkt) { sendFunc(pkt); };
- this->add_attribute(sendFunctional);
}
template <class Types>
#include "arch/arm/fastmodel/amba_ports.hh"
#include "arch/arm/fastmodel/common/signal_receiver.hh"
+#include "arch/arm/fastmodel/iris/cpu.hh"
#include "arch/arm/fastmodel/protocol/exported_clock_rate_control.hh"
#include "arch/arm/fastmodel/protocol/signal_interrupt.hh"
#include "dev/intpin.hh"
class CortexR52Cluster;
template <class Types>
-class ScxEvsCortexR52 : public Types::Base
+class ScxEvsCortexR52 : public Types::Base, public Iris::BaseCpuEvs
{
private:
static const int CoreCount = Types::CoreCount;
std::vector<std::unique_ptr<ClstrInt>> spis;
- sc_core::sc_event clockChanged;
- sc_core::sc_attribute<Tick> clockPeriod;
- sc_core::sc_attribute<CortexR52Cluster *> gem5CpuCluster;
- sc_core::sc_attribute<PortProxy::SendFunctionalFunc> sendFunctional;
-
- void sendFunc(PacketPtr pkt);
-
- void clockChangeHandler();
+ CortexR52Cluster *gem5CpuCluster;
const Params ¶ms;
Base::start_of_simulation();
}
void start_of_simulation() override {}
+
+ void sendFunc(PacketPtr pkt) override;
+
+ void setClkPeriod(Tick clk_period) override;
+
+ void setCluster(SimObject *cluster) override;
};
struct ScxEvsCortexR52x1Types
BaseCPU::BaseCPU(const BaseCPUParams ¶ms, sc_core::sc_module *_evs) :
::BaseCPU::BaseCPU(params), evs(_evs),
- clockEvent(nullptr), periodAttribute(nullptr)
+ evs_base_cpu(dynamic_cast<Iris::BaseCpuEvs *>(_evs))
{
- sc_core::sc_attr_base *base;
-
- const auto &event_vec = evs->get_child_events();
- auto event_it = std::find_if(event_vec.begin(), event_vec.end(),
- [](const sc_core::sc_event *e) -> bool {
- return e->basename() == ClockEventName; });
- if (event_it != event_vec.end())
- clockEvent = *event_it;
-
- base = evs->get_attribute(PeriodAttributeName);
- periodAttribute = dynamic_cast<sc_core::sc_attribute<Tick> *>(base);
- panic_if(base && !periodAttribute,
- "The EVS clock period attribute is not of type "
- "sc_attribute<Tick>.");
-
- base = evs->get_attribute(SendFunctionalAttributeName);
- sendFunctional =
- dynamic_cast<sc_core::sc_attribute<PortProxy::SendFunctionalFunc> *>(
- base);
- panic_if(base && !sendFunctional,
- "The EVS send functional attribute is not of type "
- "sc_attribute<PortProxy::SendFunctionalFunc>.");
+ panic_if(!evs_base_cpu, "EVS should be of type BaseCpuEvs");
// Make sure fast model knows we're using debugging mechanisms to control
// the simulation, and it shouldn't shut down if simulation time stops
namespace Iris
{
-// The name of the event that should be notified when the CPU subsystem needs
-// to adjust it's clock.
-static const std::string ClockEventName = "gem5_clock_period_event";
-// The name of the attribute the subsystem should create which can be set to
-// the desired clock period, in gem5's Ticks.
-static const std::string PeriodAttributeName = "gem5_clock_period_attribute";
-// The name of the attribute the subsystem should create which will be set to
-// a pointer to its corresponding gem5 CPU.
-static const std::string Gem5CpuClusterAttributeName = "gem5_cpu_cluster";
-// The name of the attribute the subsystem should create to hold the
-// sendFunctional delegate for port proxies.
-static const std::string SendFunctionalAttributeName = "gem5_send_functional";
+// The base interface of the EVS used by gem5 BaseCPU below.
+class BaseCpuEvs
+{
+ public:
+ virtual void sendFunc(PacketPtr pkt) = 0;
+ virtual void setClkPeriod(Tick clk_period) = 0;
+ virtual void setCluster(SimObject *cluster) = 0;
+};
// This CPU class adds some mechanisms which help attach the gem5 and fast
// model CPUs to each other. It acts as a base class for the gem5 CPU, and
PortProxy::SendFunctionalFunc
getSendFunctional() override
{
- if (sendFunctional)
- return sendFunctional->value;
- return ::BaseCPU::getSendFunctional();
+ return [this] (PacketPtr pkt) { evs_base_cpu->sendFunc(pkt); };
}
protected:
sc_core::sc_module *evs;
-
- private:
- sc_core::sc_event *clockEvent;
- sc_core::sc_attribute<Tick> *periodAttribute;
- sc_core::sc_attribute<PortProxy::SendFunctionalFunc> *sendFunctional;
+ // Hold casted pointer to *evs.
+ Iris::BaseCpuEvs *evs_base_cpu;
protected:
void
clockPeriodUpdated() override
{
- if (!clockEvent || !periodAttribute) {
- warn("Unable to notify EVS of clock change, missing:");
- warn_if(!clockEvent, " Clock change event");
- warn_if(!periodAttribute, " Clock period attribute");
- return;
- }
-
- periodAttribute->value = clockPeriod();
- clockEvent->notify();
+ evs_base_cpu->setClkPeriod(clockPeriod());
}
void init() override;