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 &params);
+    ~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

Reply via email to