fastmodel: create base class for EVS CPU
Previously we use attribute and event for communication between gem5 SimObject to systemC fastmodel sc_module. Creating a base class allows us to perform casting once and get all the interface required. Also, instead of warning on attribute not found, we should make simulator panic if the sc_module does not provide the interface we need. Change-Id: I91e1036cb792d556dfc4010e7a0f138b1519b079 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40277 Reviewed-by: Gabe Black <gabe.black@gmail.com> Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -104,16 +104,9 @@ CortexA76Cluster::CortexA76Cluster(const Params &p) :
|
||||
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);
|
||||
|
||||
@@ -39,19 +39,23 @@ namespace FastModel
|
||||
|
||||
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++) {
|
||||
@@ -82,15 +86,6 @@ ScxEvsCortexA76<Types>::ScxEvsCortexA76(
|
||||
}
|
||||
|
||||
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>
|
||||
@@ -109,12 +104,10 @@ ScxEvsCortexA76<Types>::before_end_of_elaboration()
|
||||
{
|
||||
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();
|
||||
@@ -123,15 +116,15 @@ ScxEvsCortexA76<Types>::before_end_of_elaboration()
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#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"
|
||||
@@ -52,7 +53,7 @@ namespace FastModel
|
||||
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;
|
||||
@@ -81,14 +82,7 @@ class ScxEvsCortexA76 : public Types::Base
|
||||
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;
|
||||
|
||||
@@ -106,6 +100,12 @@ class ScxEvsCortexA76 : public Types::Base
|
||||
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
|
||||
|
||||
@@ -99,16 +99,9 @@ CortexR52Cluster::CortexR52Cluster(const Params &p) :
|
||||
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);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#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"
|
||||
@@ -37,9 +38,17 @@ namespace FastModel
|
||||
|
||||
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>
|
||||
@@ -61,10 +70,6 @@ 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++)
|
||||
@@ -77,15 +82,6 @@ ScxEvsCortexR52<Types>::ScxEvsCortexR52(
|
||||
|
||||
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>
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#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"
|
||||
@@ -54,7 +55,7 @@ namespace FastModel
|
||||
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;
|
||||
@@ -105,14 +106,7 @@ class ScxEvsCortexR52 : public Types::Base
|
||||
|
||||
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;
|
||||
|
||||
@@ -141,6 +135,12 @@ class ScxEvsCortexR52 : public Types::Base
|
||||
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
|
||||
|
||||
@@ -36,30 +36,9 @@ namespace Iris
|
||||
|
||||
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
|
||||
|
||||
@@ -38,18 +38,14 @@
|
||||
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
|
||||
@@ -87,32 +83,19 @@ class BaseCPU : public ::BaseCPU
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user