x86: Move APIC clock divider to Python
authorAndreas Hansson <andreas.hansson@arm.com>
Tue, 19 Feb 2013 10:56:06 +0000 (05:56 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Tue, 19 Feb 2013 10:56:06 +0000 (05:56 -0500)
This patch moves the 16x APIC clock divider to the Python code to
avoid the post-instantiation modifications to the clock. The x86 APIC
was the only object setting the clock after creation time and this
required some custom functionality and configuration. With this patch,
the clock multiplier is moved to the Python code and the objects are
instantiated with the appropriate clock.

src/arch/x86/interrupts.cc
src/arch/x86/interrupts.hh
src/arch/x86/utility.cc
src/cpu/BaseCPU.py
src/python/m5/params.py

index 8eae2d3901d95358923e99bca85178be58dd146a..c693e6bbdace00c5f0b3f795a2108e107731638c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -410,9 +410,8 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg)
       case APIC_CURRENT_COUNT:
         {
             if (apicTimerEvent.scheduled()) {
-                assert(clock);
                 // Compute how many m5 ticks happen per count.
-                uint64_t ticksPerCount = clock *
+                uint64_t ticksPerCount = clockPeriod() *
                     divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]);
                 // Compute how many m5 ticks are left.
                 uint64_t val = apicTimerEvent.when() - curTick();
@@ -587,19 +586,20 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
         break;
       case APIC_INITIAL_COUNT:
         {
-            assert(clock);
             newVal = bits(val, 31, 0);
             // Compute how many timer ticks we're being programmed for.
             uint64_t newCount = newVal *
                 (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
             // Schedule on the edge of the next tick plus the new count.
-            Tick offset = curTick() % clock;
+            Tick offset = curTick() % clockPeriod();
             if (offset) {
                 reschedule(apicTimerEvent,
-                        curTick() + (newCount + 1) * clock - offset, true);
+                           curTick() + (newCount + 1) *
+                           clockPeriod() - offset, true);
             } else {
                 reschedule(apicTimerEvent,
-                        curTick() + newCount * clock, true);
+                           curTick() + newCount *
+                           clockPeriod(), true);
             }
         }
         break;
@@ -629,8 +629,6 @@ X86ISA::Interrupts::Interrupts(Params * p) :
     pendingIPIs(0), cpu(NULL),
     intSlavePort(name() + ".int_slave", this, this, latency)
 {
-    // Override the default clock
-    clock = 0;
     pioSize = PageBytes;
     memset(regs, 0, sizeof(regs));
     //Set the local apic DFR to the flat model.
@@ -735,7 +733,6 @@ void
 X86ISA::Interrupts::serialize(std::ostream &os)
 {
     SERIALIZE_ARRAY(regs, NUM_APIC_REGS);
-    SERIALIZE_SCALAR(clock);
     SERIALIZE_SCALAR(pendingSmi);
     SERIALIZE_SCALAR(smiVector);
     SERIALIZE_SCALAR(pendingNmi);
@@ -761,7 +758,6 @@ void
 X86ISA::Interrupts::unserialize(Checkpoint *cp, const std::string &section)
 {
     UNSERIALIZE_ARRAY(regs, NUM_APIC_REGS);
-    UNSERIALIZE_SCALAR(clock);
     UNSERIALIZE_SCALAR(pendingSmi);
     UNSERIALIZE_SCALAR(smiVector);
     UNSERIALIZE_SCALAR(pendingNmi);
index 06094f0b1d0bee9582c847ed78b7ca3a8679c93d..4e6ef4324af1746fc7a8ed995523a88c43395a53 100644 (file)
@@ -201,12 +201,6 @@ class Interrupts : public BasicPioDevice, IntDev
 
     void setCPU(BaseCPU * newCPU);
 
-    void
-    setClock(Tick newClock)
-    {
-        clock = newClock;
-    }
-
     const Params *
     params() const
     {
index e56e96b998b72611ddcdccecb8a6673388ab9e68..ae6c37be629818939bc0bfdf5531f01cb94351c8 100644 (file)
@@ -174,10 +174,6 @@ void initCPU(ThreadContext *tc, int cpuId)
 
     interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);
 
-    // @todo: Control the relative frequency, in this case 16:1, of
-    // the clocks in the Python code
-    interrupts->setClock(tc->getCpuPtr()->clockPeriod() * 16);
-
     // TODO Set the SMRAM base address (SMBASE) to 0x00030000
 
     tc->setMiscReg(MISCREG_VM_CR, 0);
index 4fc2ebf1b95b71193d66649551f682fa6d3a96a6..5e1a0a96135b70c21aecc8d46f0f296f9335ae45 100644 (file)
@@ -221,8 +221,9 @@ class BaseCPU(MemObject):
         elif buildEnv['TARGET_ISA'] == 'alpha':
             self.interrupts = AlphaInterrupts()
         elif buildEnv['TARGET_ISA'] == 'x86':
-            _localApic = X86LocalApic(pio_addr=0x2000000000000000)
-            self.interrupts = _localApic
+            self.interrupts = X86LocalApic(clock = Parent.clock * 16,
+                                           pio_addr=0x2000000000000000)
+            _localApic = self.interrupts
         elif buildEnv['TARGET_ISA'] == 'mips':
             self.interrupts = MipsInterrupts()
         elif buildEnv['TARGET_ISA'] == 'arm':
index b9a205307480b921762c0b2b7ac4462b63391603..fdd22dac00ee5c23b0e8e59daf055ee2c6516584 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012-2013 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -1207,9 +1207,10 @@ class Frequency(TickParamValue):
     def ini_str(self):
         return '%d' % self.getValue()
 
-# A generic frequency and/or Latency value.  Value is stored as a latency,
-# but to avoid ambiguity this object does not support numeric ops (* or /).
-# An explicit conversion to a Latency or Frequency must be made first.
+# A generic frequency and/or Latency value. Value is stored as a
+# latency, and any manipulation using a multiplier thus scales the
+# clock period, i.e. a 2x multiplier doubles the clock period and thus
+# halves the clock frequency.
 class Clock(ParamValue):
     cxx_type = 'Tick'
 
@@ -1243,6 +1244,14 @@ class Clock(ParamValue):
             return Latency(self)
         raise AttributeError, "Frequency object has no attribute '%s'" % attr
 
+    def __mul__(self, other):
+        # Always treat the clock as a period when scaling
+        newobj = self.__class__(self)
+        newobj.value *= other
+        return newobj
+
+    __rmul__ = __mul__
+
     def getValue(self):
         return self.period.getValue()