Melissa Jost has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/53039 )
Change subject: dev: Modify LupIO-TMR for SMP support
......................................................................
dev: Modify LupIO-TMR for SMP support
Added a new LupioTimer struct, as well as a timer event function for
SMP support.
Change-Id: Idbcc549dfa3c5f8d5342d7e2250337a7482a1ac0
---
M src/dev/lupio/lupio_tmr.cc
M src/dev/lupio/lupio_tmr.hh
2 files changed, 94 insertions(+), 56 deletions(-)
diff --git a/src/dev/lupio/lupio_tmr.cc b/src/dev/lupio/lupio_tmr.cc
index 731db18..6a69af0 100644
--- a/src/dev/lupio/lupio_tmr.cc
+++ b/src/dev/lupio/lupio_tmr.cc
@@ -34,11 +34,11 @@
#include "params/LupioTMR.hh"
// Specific fields for CTRL
-#define LUPIO_TMR_IE 0x1
-#define LUPIO_TMR_PD 0x2
+#define LUPIO_TMR_IRQE 0x1
+#define LUPIO_TMR_PRDC 0x2
// Specific fields for STAT
-#define LUPIO_TMR_EX 0x1
+#define LUPIO_TMR_EXPD 0x1
namespace gem5
{
@@ -49,26 +49,37 @@
BasicPioDevice(params, params.pio_size),
system(params.system),
nThread(params.num_threads),
- tmrEvent([this]{ lupioTMRCallback(); }, name()),
intType(params.int_type)
{
+ timers.resize(nThread);
+
+ for (int cpu = 0; cpu < nThread; cpu++) {
+ timers[cpu].tmrEvent = new EventFunctionWrapper(
+ [=]{
+ lupioTMRCallback(cpu);
+ }, name()+"done"
+ );
+ }
+
DPRINTF(LupioTMR, "LupioTMR initalized\n");
}
-void
-LupioTMR::updateIRQ(int level)
+LupioTMR::~LupioTMR()
{
- if (nThread > 1) {
- panic("This device currently does not offer SMP support\n");
+ for (int cpu = 0; cpu < nThread; cpu++) {
+ delete timers[cpu].tmrEvent;
}
+}
- auto tc = system->threads[0];
+void
+LupioTMR::updateIRQ(int level, int cpu)
+{
+ auto tc = system->threads[cpu];
// post an interrupt
if (level) {
tc->getCpuPtr()->postInterrupt(tc->threadId(), intType, 0);
- }
- // clear the interrupt
- else {
+ } else {
+ // clear the interrupt
tc->getCpuPtr()->clearInterrupt(tc->threadId(), intType, 0);
}
}
@@ -80,52 +91,61 @@
}
void
-LupioTMR::lupioTMRSet()
+LupioTMR::lupioTMRSet(int cpu)
{
- startTime = curTick();
- if (!tmrEvent.scheduled()) {
- schedule(tmrEvent, (reload * sim_clock::as_int::ns) + curTick());
+ // Start the timer
+ timers[cpu].startTime = curTick();
+
+ // Schedule the timer to fire at the number of ticks stored
+ // in the reload register from the current tick
+ if (!timers[cpu].tmrEvent->scheduled()) {
+ // Convert the reload value to ticks from nanoseconds
+ schedule(*(timers[cpu].tmrEvent),
+ (timers[cpu].reload * sim_clock::as_int::ns) + curTick());
}
}
void
-LupioTMR::lupioTMRCallback()
+LupioTMR::lupioTMRCallback(int cpu)
{
// Signal expiration
- expired = true;
- if (ie) {
- updateIRQ(1);
+ timers[cpu].expired = true;
+ if (timers[cpu].ie) {
+ updateIRQ(1, cpu);
}
// If periodic timer, reload
- if (pd && reload) {
- lupioTMRSet();
+ if (timers[cpu].pd && timers[cpu].reload) {
+ lupioTMRSet(cpu);
}
}
uint64_t
LupioTMR::lupioTMRRead(uint8_t addr, int size)
{
- uint64_t r = 0;
-
- switch (addr >> 2) {
+ uint32_t r = 0;
+
+ size_t cpu = addr >> LUPIO_TMR_MAX;
+ size_t reg = (addr >> 2) & (LUPIO_TMR_MAX - 1);
+
+ switch (reg) {
case LUPIO_TMR_TIME:
r = lupioTMRCurrentTime();
DPRINTF(LupioTMR, "Read LUPIO_TMR_TME: %d\n", r);
break;
case LUPIO_TMR_LOAD:
- r = reload;
+ r = timers[cpu].reload;
DPRINTF(LupioTMR, "Read LUPIO_TMR_LOAD: %d\n", r);
break;
case LUPIO_TMR_STAT:
- if (expired) {
- r |= LUPIO_TMR_EX;
+ if (timers[cpu].expired) {
+ r |= LUPIO_TMR_EXPD;
}
// Acknowledge expiration
- expired = false;
+ timers[cpu].expired = false;
DPRINTF(LupioTMR, "Read LUPIO_TMR_STAT: %d\n", r);
- updateIRQ(0);
+ updateIRQ(0, cpu);
break;
default:
@@ -141,26 +161,31 @@
{
uint32_t val = val64;
- switch (addr >> 2) {
+ size_t cpu = addr >> LUPIO_TMR_MAX;
+ size_t reg = (addr >> 2) & (LUPIO_TMR_MAX - 1);
+
+ switch (reg) {
case LUPIO_TMR_LOAD:
- reload = val;
- DPRINTF(LupioTMR, "Write LUPIO_TMR_LOAD: %d\n", reload);
+ timers[cpu].reload = val;
+ DPRINTF(LupioTMR, "Write LUPIO_TMR_LOAD: %d\n",
+ timers[cpu].reload);
break;
case LUPIO_TMR_CTRL:
- ie = val & LUPIO_TMR_IE;
- pd = val & LUPIO_TMR_PD;
+ timers[cpu].ie = val & LUPIO_TMR_IRQE;
+ timers[cpu].pd = val & LUPIO_TMR_PRDC;
DPRINTF(LupioTMR, "Write LUPIO_TMR_CTRL\n");
// Stop current timer if any
- if (curTick() < startTime + (reload * sim_clock::as_int::ns)
- && tmrEvent.scheduled()) {
- deschedule(tmrEvent);
+ if (curTick() < timers[cpu].startTime +
+ (timers[cpu].reload * sim_clock::as_int::ns) &&
+ (timers[cpu].tmrEvent)->scheduled()) {
+ deschedule(*(timers[cpu].tmrEvent));
}
// If reload isn't 0, start a new one
- if (reload) {
- lupioTMRSet();
+ if (timers[cpu].reload) {
+ lupioTMRSet(cpu);
}
break;
@@ -179,7 +204,7 @@
DPRINTF(LupioTMR,
"Read request - addr: %#x, size: %#x\n", tmr_addr, pkt->getSize());
- uint64_t read_val = lupioTMRRead(pic_addr, pkt->getSize());
+ uint64_t read_val = lupioTMRRead(tmr_addr, pkt->getSize());
DPRINTF(LupioTMR, "Packet Read: %#x\n", read_val);
pkt->setUintX(read_val, byteOrder);
pkt->makeResponse();
@@ -195,7 +220,7 @@
DPRINTF(LupioTMR, "Write register %#x value %#x\n", tmr_addr,
pkt->getUintX(byteOrder));
- lupioTMRWrite(pic_addr, pkt->getUintX(byteOrder), pkt->getSize());
+ lupioTMRWrite(tmr_addr, pkt->getUintX(byteOrder), pkt->getSize());
DPRINTF(LupioTMR, "Packet Write Value: %d\n",
pkt->getUintX(byteOrder));
pkt->makeResponse();
diff --git a/src/dev/lupio/lupio_tmr.hh b/src/dev/lupio/lupio_tmr.hh
index c5a88f6..b0a2387 100644
--- a/src/dev/lupio/lupio_tmr.hh
+++ b/src/dev/lupio/lupio_tmr.hh
@@ -49,10 +49,8 @@
const ByteOrder byteOrder = ByteOrder::little;
System *system;
int nThread;
- EventFunctionWrapper tmrEvent;
int intType;
-
- Tick startTime = 0;
+ int nCPUs = 0;
// Register map
enum
@@ -66,15 +64,17 @@
LUPIO_TMR_MAX,
};
- // Timer registers
- uint64_t reload = 0;
+ struct LupioTimer
+ {
+ Event *tmrEvent = nullptr;
+ uint64_t reload = 0;
+ bool ie = false; // Control
+ bool pd = false;
+ bool expired = false; // Status
+ Tick startTime = 0;
+ };
- // Control
- bool ie = false;
- bool pd = false;
-
- // Status
- bool expired = false;
+ std::vector<LupioTimer> timers;
/**
* Function to return data pertaining to the timer, such as the
simulated
@@ -93,20 +93,21 @@
/**
* Schedule the next timer event
*/
- void lupioTMRSet();
+ void lupioTMRSet(int cpu);
/**
* Process the timer's event
*/
- void lupioTMRCallback();
+ void lupioTMRCallback(int cpu);
/**
* Post or clear timer interrupts
*/
- void updateIRQ(int level);
+ void updateIRQ(int level, int cpu);
public:
PARAMS(LupioTMR);
LupioTMR(const Params ¶ms);
+ ~LupioTMR();
/**
* Implement BasicPioDevice virtual functions
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/53039
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Idbcc549dfa3c5f8d5342d7e2250337a7482a1ac0
Gerrit-Change-Number: 53039
Gerrit-PatchSet: 1
Gerrit-Owner: Melissa Jost <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s