fastmodel: Add a gem5Cpu attribute to the CortexA76x1.
This attribute is to let the fast model EVS CPU find and talk to the gem5 CPU in case it needs a pointer to one of its ThreadContexts for instance. Also move the code that finds the clock period attribute/event to the constructor. gem5 guarantees that the EVS is constructed before its pointer is passed to the iris CPU wrapper, and so the EVS will have had a chance to install those controls if it's going to. Change-Id: I389ef0ba0f9d528140f40444baa5091a9ec338cd Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21045 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -59,7 +59,8 @@ CortexA76x1::CortexA76x1(const sc_core::sc_module_name &mod_name,
|
||||
vcpumntirqWrapper(vcpumntirq, params.name + ".vcpumntirq", -1),
|
||||
cntpnsirqWrapper(cntpnsirq, params.name + ".cntpnsirq", -1),
|
||||
clockChanged(Iris::ClockEventName.c_str()),
|
||||
clockPeriod(Iris::PeriodAttributeName.c_str())
|
||||
clockPeriod(Iris::PeriodAttributeName.c_str()),
|
||||
gem5Cpu(Iris::Gem5CpuAttributeName.c_str())
|
||||
{
|
||||
clockRateControl.bind(clock_rate_s);
|
||||
|
||||
@@ -195,6 +196,7 @@ CortexA76x1::CortexA76x1(const sc_core::sc_module_name &mod_name,
|
||||
set_parameter("core.cpu0.vfp-enable_at_reset",
|
||||
params.cpu0_vfp_enable_at_reset);
|
||||
|
||||
add_attribute(gem5Cpu);
|
||||
add_attribute(clockPeriod);
|
||||
SC_METHOD(clockChangeHandler);
|
||||
dont_initialize();
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include "systemc/ext/core/sc_module.hh"
|
||||
#include "systemc/sc_port_wrapper.hh"
|
||||
|
||||
class BaseCPU;
|
||||
|
||||
// This macro is to get the type IF of a sc_export<IF> variable x. It relies on
|
||||
// the fact that the "operator->()" function returns the "IF*" type and
|
||||
// std::decay to remove cv-qualifiers and reference.
|
||||
@@ -76,6 +78,7 @@ class CortexA76x1 : public scx_evs_CortexA76x1
|
||||
|
||||
sc_core::sc_event clockChanged;
|
||||
sc_core::sc_attribute<Tick> clockPeriod;
|
||||
sc_core::sc_attribute<::BaseCPU *> gem5Cpu;
|
||||
|
||||
void clockChangeHandler();
|
||||
|
||||
|
||||
@@ -34,6 +34,35 @@
|
||||
namespace Iris
|
||||
{
|
||||
|
||||
BaseCPU::BaseCPU(BaseCPUParams *params, sc_core::sc_module *_evs) :
|
||||
::BaseCPU::BaseCPU(params), evs(_evs),
|
||||
clockEvent(nullptr), periodAttribute(nullptr)
|
||||
{
|
||||
sc_core::sc_attr_base *base;
|
||||
|
||||
base = evs->get_attribute(Gem5CpuAttributeName);
|
||||
auto *gem5_cpu_attr =
|
||||
dynamic_cast<sc_core::sc_attribute<::BaseCPU *> *>(base);
|
||||
panic_if(base && !gem5_cpu_attr,
|
||||
"The EVS gem5 CPU attribute was not of type "
|
||||
"sc_attribute<::BaesCPU *>.");
|
||||
if (gem5_cpu_attr)
|
||||
gem5_cpu_attr->value = this;
|
||||
|
||||
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>.");
|
||||
}
|
||||
|
||||
BaseCPU::~BaseCPU()
|
||||
{
|
||||
for (auto &tc: threadContexts)
|
||||
|
||||
@@ -46,6 +46,9 @@ 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 Gem5CpuAttributeName = "gem5_cpu";
|
||||
|
||||
// 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
|
||||
@@ -54,10 +57,7 @@ static const std::string PeriodAttributeName = "gem5_clock_period_attribute";
|
||||
class BaseCPU : public ::BaseCPU
|
||||
{
|
||||
public:
|
||||
BaseCPU(BaseCPUParams *params, sc_core::sc_module *_evs) :
|
||||
::BaseCPU::BaseCPU(params), evs(_evs),
|
||||
clockEvent(nullptr), periodAttribute(nullptr)
|
||||
{}
|
||||
BaseCPU(BaseCPUParams *params, sc_core::sc_module *_evs);
|
||||
virtual ~BaseCPU();
|
||||
|
||||
Port &
|
||||
@@ -90,34 +90,11 @@ class BaseCPU : public ::BaseCPU
|
||||
sc_core::sc_event *clockEvent;
|
||||
sc_core::sc_attribute<Tick> *periodAttribute;
|
||||
|
||||
bool
|
||||
findClockControls()
|
||||
{
|
||||
if (!clockEvent) {
|
||||
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;
|
||||
}
|
||||
if (!periodAttribute) {
|
||||
sc_core::sc_attr_base *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>.");
|
||||
}
|
||||
return clockEvent && periodAttribute;
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
clockPeriodUpdated() override
|
||||
{
|
||||
if (!findClockControls()) {
|
||||
if (!clockEvent || !periodAttribute) {
|
||||
warn("Unable to notify EVS of clock change, missing:");
|
||||
warn_if(!clockEvent, " Clock change event");
|
||||
warn_if(!periodAttribute, " Clock period attribute");
|
||||
|
||||
Reference in New Issue
Block a user