x86: Turn the local APIC Interrupts class into a SimObject.
authorGabe Black <gabeblack@google.com>
Wed, 11 Sep 2019 23:45:41 +0000 (16:45 -0700)
committerGabe Black <gabeblack@google.com>
Fri, 18 Oct 2019 21:50:26 +0000 (21:50 +0000)
It will no longer be a PioDevice or a ClockedObject, but will carry
forward the little bits and pieces of those classes that it was using.
Those are a PIO port for memory mapped register accesses, and a clock
domain parameter for setting the apic tick frequency.

This brings the x86 Interrupts class in line with the Interrupts of the
other ISAs so that they can inherit from a standard base class.

Change-Id: I6b25fa21911b39a756e0cf9408c5489a81d6ca56
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20829
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/x86/X86LocalApic.py
src/arch/x86/interrupts.cc
src/arch/x86/interrupts.hh

index 456409a62b92cfe9ccf7b163c965d4635f97f953..914f29766c3bcc1d4fdf53bb8df0c31d768c6745 100644 (file)
@@ -42,10 +42,10 @@ from m5.defines import buildEnv
 from m5.params import *
 from m5.proxy import *
 
-from m5.objects.Device import PioDevice
 from m5.objects.ClockDomain import DerivedClockDomain
+from m5.SimObject import SimObject
 
-class X86LocalApic(PioDevice):
+class X86LocalApic(SimObject):
     type = 'X86LocalApic'
     cxx_class = 'X86ISA::Interrupts'
     cxx_header = 'arch/x86/interrupts.hh'
@@ -53,6 +53,8 @@ class X86LocalApic(PioDevice):
     int_slave = SlavePort("Port for receiving interrupt messages")
     int_latency = Param.Latency('1ns', \
             "Latency for an interrupt to propagate through this device.")
+    pio = SlavePort("Programmed I/O port")
+    system = Param.System(Parent.any, "System this device is part of")
 
     pio_latency = Param.Latency('100ns', 'Programmed IO latency')
 
@@ -60,5 +62,6 @@ class X86LocalApic(PioDevice):
     # which we assume is 1/16th the rate of the CPU clock. I don't think this
     # is a hard rule, but seems to be true in practice. This can be overriden
     # in configs that use it.
-    clk_domain = DerivedClockDomain(
-            clk_domain=Parent.clk_domain, clk_divider=16)
+    clk_domain = Param.DerivedClockDomain(
+            DerivedClockDomain(clk_domain=Parent.clk_domain, clk_divider=16),
+            "The clock for the local APIC. Should not be modified.")
index 14bdc0fc72fa5c33bfc2e4f7e38c4601c0ad3214..d237366ab1a27cfc4eec3e1ca37cf8895e68a2d1 100644 (file)
@@ -290,16 +290,13 @@ X86ISA::Interrupts::setCPU(BaseCPU * newCPU)
 void
 X86ISA::Interrupts::init()
 {
-    //
-    // The local apic must register its address ranges on its pio
-    // port via the basicpiodevice(piodevice) init() function.
-    PioDevice::init();
-
-    // The slave port has a range, so inform the connected master.
-    intSlavePort.sendRangeChange();
-    // If the master port isn't connected, we can't send interrupts anywhere.
     panic_if(!intMasterPort.isConnected(),
             "Int port not connected to anything!");
+    panic_if(!pioPort.isConnected(),
+            "Pio port of %s not connected to anything!", name());
+
+    intSlavePort.sendRangeChange();
+    pioPort.sendRangeChange();
 }
 
 
@@ -599,7 +596,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
 
 
 X86ISA::Interrupts::Interrupts(Params * p)
-    : PioDevice(p),
+    : SimObject(p), sys(p->system), clockDomain(*p->clk_domain),
       apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
       pendingSmi(false), smiVector(0),
       pendingNmi(false), nmiVector(0),
@@ -610,7 +607,7 @@ X86ISA::Interrupts::Interrupts(Params * p)
       pendingIPIs(0), cpu(NULL),
       intSlavePort(name() + ".int_slave", this, this),
       intMasterPort(name() + ".int_master", this, this, p->int_latency),
-      pioDelay(p->pio_latency)
+      pioPort(this), pioDelay(p->pio_latency)
 {
     memset(regs, 0, sizeof(regs));
     //Set the local apic DFR to the flat model.
index 3d6ef1f8264e62fe349c752d9b2dcc25050ce78b..519d9f10ec98c715f72915330f2148c8aa3d795d 100644 (file)
@@ -72,9 +72,12 @@ namespace X86ISA {
 
 ApicRegIndex decodeAddr(Addr paddr);
 
-class Interrupts : public PioDevice
+class Interrupts : public SimObject
 {
   protected:
+    System *sys;
+    ClockDomain &clockDomain;
+
     // Storage for the APIC registers
     uint32_t regs[NUM_APIC_REGS];
 
@@ -165,6 +168,8 @@ class Interrupts : public PioDevice
         return bits(regs[base + (vector / 32)], vector % 32);
     }
 
+    Tick clockPeriod() const { return clockDomain.clockPeriod(); }
+
     void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
 
     BaseCPU *cpu;
@@ -175,6 +180,9 @@ class Interrupts : public PioDevice
     IntSlavePort<Interrupts> intSlavePort;
     IntMasterPort<Interrupts> intMasterPort;
 
+    // Port for memory mapped register accesses.
+    PioPort<Interrupts> pioPort;
+
     Tick pioDelay;
     Addr pioAddr = MaxAddr;
 
@@ -203,8 +211,8 @@ class Interrupts : public PioDevice
     /*
      * Functions to interact with the interrupt port.
      */
-    Tick read(PacketPtr pkt) override;
-    Tick write(PacketPtr pkt) override;
+    Tick read(PacketPtr pkt);
+    Tick write(PacketPtr pkt);
     Tick recvMessage(PacketPtr pkt);
     void completeIPI(PacketPtr pkt);
 
@@ -217,7 +225,7 @@ class Interrupts : public PioDevice
         return entry.periodic;
     }
 
-    AddrRangeList getAddrRanges() const override;
+    AddrRangeList getAddrRanges() const;
     AddrRangeList getIntAddrRange() const;
 
     Port &getPort(const std::string &if_name,
@@ -227,8 +235,10 @@ class Interrupts : public PioDevice
             return intMasterPort;
         } else if (if_name == "int_slave") {
             return intSlavePort;
+        } else if (if_name == "pio") {
+            return pioPort;
         }
-        return PioDevice::getPort(if_name, idx);
+        return SimObject::getPort(if_name, idx);
     }
 
     /*