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:
Earl Ou
2021-02-01 09:41:33 +08:00
parent 7bb456f024
commit 16c1986fe2
8 changed files with 70 additions and 133 deletions

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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 &params;
@@ -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

View File

@@ -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);

View File

@@ -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>

View File

@@ -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 &params;
@@ -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

View File

@@ -36,30 +36,9 @@ namespace Iris
BaseCPU::BaseCPU(const BaseCPUParams &params, 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

View File

@@ -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;