summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-01-31 23:33:54 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-01-31 23:33:54 -0800
commit6a3f255a84d93f3e621319fd81f355416e385c8c (patch)
treee6dd2386d3989fdd3169d66a14c1a057463ca323
parent64b663c6071ecd58eff6dacd38ee351038259427 (diff)
downloadgem5-6a3f255a84d93f3e621319fd81f355416e385c8c.tar.xz
X86: Rework interrupt pins to allow one to many connections.
-rw-r--r--src/dev/x86/Cmos.py4
-rw-r--r--src/dev/x86/I82094AA.py5
-rw-r--r--src/dev/x86/I8254.py4
-rw-r--r--src/dev/x86/I8259.py8
-rw-r--r--src/dev/x86/SouthBridge.py21
-rw-r--r--src/dev/x86/X86IntPin.py24
-rw-r--r--src/dev/x86/cmos.cc4
-rw-r--r--src/dev/x86/cmos.hh6
-rw-r--r--src/dev/x86/i82094aa.cc20
-rw-r--r--src/dev/x86/i82094aa.hh9
-rw-r--r--src/dev/x86/i8254.cc7
-rw-r--r--src/dev/x86/i8254.hh4
-rw-r--r--src/dev/x86/i8259.cc38
-rw-r--r--src/dev/x86/i8259.hh11
-rw-r--r--src/dev/x86/intdev.cc18
-rw-r--r--src/dev/x86/intdev.hh92
16 files changed, 207 insertions, 68 deletions
diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py
index a9910f70d..0a92145e2 100644
--- a/src/dev/x86/Cmos.py
+++ b/src/dev/x86/Cmos.py
@@ -29,6 +29,7 @@
from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice
+from X86IntPin import X86IntSourcePin
class Cmos(BasicPioDevice):
type = 'Cmos'
@@ -36,4 +37,5 @@ class Cmos(BasicPioDevice):
time = Param.Time('01/01/2009',
"System time to use ('Now' for actual time)")
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
- int_pin = Param.X86IntPin('Pin to signal RTC alarm interrupts to')
+ int_pin = Param.X86IntSourcePin(X86IntSourcePin(),
+ 'Pin to signal RTC alarm interrupts to')
diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py
index b4ad96a9f..5ca58614d 100644
--- a/src/dev/x86/I82094AA.py
+++ b/src/dev/x86/I82094AA.py
@@ -29,7 +29,7 @@
from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice
-from X86IntPin import X86IntPin
+from X86IntPin import X86IntSinkPin
class I82094AA(BasicPioDevice):
type = 'I82094AA'
@@ -37,6 +37,7 @@ class I82094AA(BasicPioDevice):
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
pio_addr = Param.Addr("Device address")
int_port = Port("Port for sending and receiving interrupt messages")
+ external_int_pic = Param.I8259("External PIC, if any")
def pin(self, line):
- return X86IntPin(device=self, line=line)
+ return X86IntSinkPin(device=self, number=line)
diff --git a/src/dev/x86/I8254.py b/src/dev/x86/I8254.py
index d67d04e86..f468717cc 100644
--- a/src/dev/x86/I8254.py
+++ b/src/dev/x86/I8254.py
@@ -29,9 +29,11 @@
from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice
+from X86IntPin import X86IntSourcePin
class I8254(BasicPioDevice):
type = 'I8254'
cxx_class = 'X86ISA::I8254'
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
- int_pin = Param.X86IntPin('Pin to signal timer interrupts to')
+ int_pin = Param.X86IntSourcePin(X86IntSourcePin(),
+ 'Pin to signal timer interrupts to')
diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py
index d241b092a..e0128d032 100644
--- a/src/dev/x86/I8259.py
+++ b/src/dev/x86/I8259.py
@@ -29,7 +29,7 @@
from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice
-from X86IntPin import X86IntPin
+from X86IntPin import X86IntSourcePin, X86IntSinkPin
class X86I8259CascadeMode(Enum):
map = {'I8259Master' : 0,
@@ -41,8 +41,10 @@ class I8259(BasicPioDevice):
type = 'I8259'
cxx_class='X86ISA::I8259'
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
- output = Param.X86IntPin('The pin this I8259 drives')
+ output = Param.X86IntSourcePin(X86IntSourcePin(),
+ 'The pin this I8259 drives')
mode = Param.X86I8259CascadeMode('How this I8259 is cascaded')
+ slave = Param.I8259('Slave I8259, if any')
def pin(self, line):
- return X86IntPin(device=self, line=line)
+ return X86IntSinkPin(device=self, number=line)
diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py
index bbe3ad102..ba9aaf2b4 100644
--- a/src/dev/x86/SouthBridge.py
+++ b/src/dev/x86/SouthBridge.py
@@ -34,6 +34,7 @@ from I8237 import I8237
from I8254 import I8254
from I8259 import I8259
from PcSpeaker import PcSpeaker
+from X86IntPin import X86IntLine
from m5.SimObject import SimObject
def x86IOAddress(port):
@@ -52,6 +53,9 @@ class SouthBridge(SimObject):
_pit = I8254(pio_addr=x86IOAddress(0x40))
_speaker = PcSpeaker(pio_addr=x86IOAddress(0x61))
_io_apic = I82094AA(pio_addr=0xFEC00000)
+ # This is to make sure the interrupt lines are instantiated. Don't use
+ # it for anything directly.
+ int_lines = VectorParam.X86IntLine([], "Interrupt lines")
pic1 = Param.I8259(_pic1, "Master PIC")
pic2 = Param.I8259(_pic2, "Slave PIC")
@@ -61,13 +65,20 @@ class SouthBridge(SimObject):
speaker = Param.PcSpeaker(_speaker, "PC speaker")
io_apic = Param.I82094AA(_io_apic, "I/O APIC")
+ def connectPins(self, source, sink):
+ self.int_lines.append(X86IntLine(source=source, sink=sink))
+
def attachIO(self, bus):
- # Make internal connections
- self.pic1.output = self.io_apic.pin(0)
- self.pic2.output = self.pic1.pin(2)
- self.cmos.int_pin = self.pic2.pin(0)
- self.pit.int_pin = self.pic1.pin(0)
+ # Route interupt signals
+ self.connectPins(self.pic1.output, self.io_apic.pin(0))
+ self.connectPins(self.pic2.output, self.pic1.pin(2))
+ self.connectPins(self.cmos.int_pin, self.pic2.pin(0))
+ self.connectPins(self.pit.int_pin, self.pic1.pin(0))
+ self.connectPins(self.pit.int_pin, self.io_apic.pin(2))
+ # Tell the devices about each other
+ self.pic1.slave = self.pic2
self.speaker.i8254 = self.pit
+ self.io_apic.external_int_pic = self.pic1
# Connect to the bus
self.cmos.pio = bus.port
self.dma1.pio = bus.port
diff --git a/src/dev/x86/X86IntPin.py b/src/dev/x86/X86IntPin.py
index 372b4ab66..35e274624 100644
--- a/src/dev/x86/X86IntPin.py
+++ b/src/dev/x86/X86IntPin.py
@@ -29,9 +29,23 @@
from m5.params import *
from m5.SimObject import SimObject
-class X86IntPin(SimObject):
- type = 'X86IntPin'
- cxx_class = 'X86ISA::IntPin'
+# A generic pin to drive an interrupt signal generated by a device.
+class X86IntSourcePin(SimObject):
+ type = 'X86IntSourcePin'
+ cxx_class = 'X86ISA::IntSourcePin'
- line = Param.Int("Interrupt line for this pin")
- device = Param.SimObject("Device which handles interrupts")
+# A generic pin to receive an interrupt signal generated by another device.
+class X86IntSinkPin(SimObject):
+ type = 'X86IntSinkPin'
+ cxx_class = 'X86ISA::IntSinkPin'
+
+ device = Param.SimObject("Device this pin belongs to")
+ number = Param.Int("The pin number on the device")
+
+# An interrupt line which is driven by a source pin and drives a sink pin.
+class X86IntLine(SimObject):
+ type = 'X86IntLine'
+ cxx_class = 'X86ISA::IntLine'
+
+ source = Param.X86IntSourcePin("Pin driving this line")
+ sink = Param.X86IntSinkPin("Pin driven by this line")
diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc
index c88592870..6bdc78a4b 100644
--- a/src/dev/x86/cmos.cc
+++ b/src/dev/x86/cmos.cc
@@ -36,7 +36,9 @@ void
X86ISA::Cmos::X86RTC::handleEvent()
{
assert(intPin);
- intPin->signalInterrupt();
+ intPin->raise();
+ //XXX This is a hack.
+ intPin->lower();
}
Tick
diff --git a/src/dev/x86/cmos.hh b/src/dev/x86/cmos.hh
index 45fb9e8f2..76276dbc1 100644
--- a/src/dev/x86/cmos.hh
+++ b/src/dev/x86/cmos.hh
@@ -38,7 +38,7 @@
namespace X86ISA
{
-class IntPin;
+class IntSourcePin;
class Cmos : public BasicPioDevice
{
@@ -57,10 +57,10 @@ class Cmos : public BasicPioDevice
class X86RTC : public MC146818
{
protected:
- IntPin * intPin;
+ IntSourcePin * intPin;
public:
X86RTC(EventManager *em, const std::string &n, const struct tm time,
- bool bcd, Tick frequency, IntPin * _intPin) :
+ bool bcd, Tick frequency, IntSourcePin * _intPin) :
MC146818(em, n, time, bcd, frequency), intPin(_intPin)
{
}
diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc
index a229fffc3..03944c190 100644
--- a/src/dev/x86/i82094aa.cc
+++ b/src/dev/x86/i82094aa.cc
@@ -36,7 +36,8 @@
#include "sim/system.hh"
X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
- latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL)
+ latency(p->pio_latency), pioAddr(p->pio_addr),
+ extIntPic(p->external_int_pic)
{
// This assumes there's only one I/O APIC in the system
id = sys->numContexts();
@@ -47,6 +48,7 @@ X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
entry.mask = 1;
for (int i = 0; i < TableSize; i++) {
redirTable[i] = entry;
+ pinStates[i] = false;
}
}
@@ -209,6 +211,22 @@ X86ISA::I82094AA::signalInterrupt(int line)
}
}
+void
+X86ISA::I82094AA::raiseInterruptPin(int number)
+{
+ assert(number < TableSize);
+ if (!pinStates[number])
+ signalInterrupt(number);
+ pinStates[number] = true;
+}
+
+void
+X86ISA::I82094AA::lowerInterruptPin(int number)
+{
+ assert(number < TableSize);
+ pinStates[number] = false;
+}
+
X86ISA::I82094AA *
I82094AAParams::create()
{
diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh
index 6a8873d45..b11e2bcb1 100644
--- a/src/dev/x86/i82094aa.hh
+++ b/src/dev/x86/i82094aa.hh
@@ -77,6 +77,7 @@ class I82094AA : public PioDevice, public IntDev
static const uint8_t APICVersion = 0x14;
RedirTableEntry redirTable[TableSize];
+ bool pinStates[TableSize];
public:
typedef I82094AAParams Params;
@@ -89,12 +90,6 @@ class I82094AA : public PioDevice, public IntDev
I82094AA(Params *p);
- void
- setExtIntPic(I8259 * pic)
- {
- extIntPic = pic;
- }
-
Tick read(PacketPtr pkt);
Tick write(PacketPtr pkt);
@@ -123,6 +118,8 @@ class I82094AA : public PioDevice, public IntDev
}
void signalInterrupt(int line);
+ void raiseInterruptPin(int number);
+ void lowerInterruptPin(int number);
};
}; // namespace X86ISA
diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc
index ac3847cd6..4f37eebad 100644
--- a/src/dev/x86/i8254.cc
+++ b/src/dev/x86/i8254.cc
@@ -37,8 +37,11 @@ void
X86ISA::I8254::counterInterrupt(unsigned int num)
{
DPRINTF(I8254, "Interrupt from counter %d.\n", num);
- if (num == 0)
- intPin->signalInterrupt();
+ if (num == 0) {
+ intPin->raise();
+ //XXX This is a hack.
+ intPin->lower();
+ }
}
Tick
diff --git a/src/dev/x86/i8254.hh b/src/dev/x86/i8254.hh
index e6860b2c4..7de20dfd4 100644
--- a/src/dev/x86/i8254.hh
+++ b/src/dev/x86/i8254.hh
@@ -38,7 +38,7 @@
namespace X86ISA
{
-class IntPin;
+class IntSourcePin;
class I8254 : public BasicPioDevice
{
@@ -64,7 +64,7 @@ class I8254 : public BasicPioDevice
X86Intel8254Timer pit;
- IntPin *intPin;
+ IntSourcePin *intPin;
void counterInterrupt(unsigned int num);
diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc
index b3d3a5aa2..b7c8bb08a 100644
--- a/src/dev/x86/i8259.cc
+++ b/src/dev/x86/i8259.cc
@@ -36,20 +36,12 @@
X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this),
latency(p->pio_latency), output(p->output),
- mode(p->mode), slave(NULL),
+ mode(p->mode), slave(p->slave),
IRR(0), ISR(0), IMR(0),
readIRR(true), initControlWord(0), autoEOI(false)
{
- if (output) {
- I8259 * master;
- master = dynamic_cast<I8259 *>(output->getDevice());
- if (master)
- master->setSlave(this);
- I82094AA * ioApic;
- ioApic = dynamic_cast<I82094AA *>(output->getDevice());
- if (ioApic)
- ioApic->setExtIntPic(this);
- }
+ for (int i = 0; i < NumLines; i++)
+ pinStates[i] = false;
pioSize = 2;
}
@@ -237,7 +229,9 @@ X86ISA::I8259::requestInterrupt(int line)
if (bits(ISR, 7, line) == 0) {
if (output) {
DPRINTF(I8259, "Propogating interrupt.\n");
- output->signalInterrupt();
+ output->raise();
+ //XXX This is a hack.
+ output->lower();
} else {
warn("Received interrupt but didn't have "
"anyone to tell about it.\n");
@@ -260,6 +254,26 @@ X86ISA::I8259::signalInterrupt(int line)
}
}
+void
+X86ISA::I8259::raiseInterruptPin(int number)
+{
+ if (number >= NumLines)
+ fatal("Line number %d doesn't exist. The max is %d.\n",
+ number, NumLines - 1);
+ if (!pinStates[number])
+ signalInterrupt(number);
+ pinStates[number] = true;
+}
+
+void
+X86ISA::I8259::lowerInterruptPin(int number)
+{
+ if (number >= NumLines)
+ fatal("Line number %d doesn't exist. The max is %d.\n",
+ number, NumLines - 1);
+ pinStates[number] = false;
+}
+
int
X86ISA::I8259::getVector()
{
diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh
index 5a2cf72e8..dfb56646a 100644
--- a/src/dev/x86/i8259.hh
+++ b/src/dev/x86/i8259.hh
@@ -45,9 +45,10 @@ class I8259 : public BasicPioDevice, public IntDev
{
protected:
static const int NumLines = 8;
+ bool pinStates[NumLines];
Tick latency;
- IntPin *output;
+ IntSourcePin *output;
Enums::X86I8259CascadeMode mode;
I8259 * slave;
@@ -90,16 +91,12 @@ class I8259 : public BasicPioDevice, public IntDev
I8259(Params * p);
- void
- setSlave(I8259 * _slave)
- {
- slave = _slave;
- }
-
Tick read(PacketPtr pkt);
Tick write(PacketPtr pkt);
void signalInterrupt(int line);
+ void raiseInterruptPin(int number);
+ void lowerInterruptPin(int number);
int getVector();
};
diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc
index 463b3c9fe..e386687a9 100644
--- a/src/dev/x86/intdev.cc
+++ b/src/dev/x86/intdev.cc
@@ -30,8 +30,20 @@
#include "dev/x86/intdev.hh"
-X86ISA::IntPin *
-X86IntPinParams::create()
+X86ISA::IntSourcePin *
+X86IntSourcePinParams::create()
{
- return new X86ISA::IntPin(this);
+ return new X86ISA::IntSourcePin(this);
+}
+
+X86ISA::IntSinkPin *
+X86IntSinkPinParams::create()
+{
+ return new X86ISA::IntSinkPin(this);
+}
+
+X86ISA::IntLine *
+X86IntLineParams::create()
+{
+ return new X86ISA::IntLine(this);
}
diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh
index ba9a073a4..ca8e7eea5 100644
--- a/src/dev/x86/intdev.hh
+++ b/src/dev/x86/intdev.hh
@@ -38,7 +38,9 @@
#include "mem/mem_object.hh"
#include "mem/mport.hh"
#include "sim/sim_object.hh"
-#include "params/X86IntPin.hh"
+#include "params/X86IntSourcePin.hh"
+#include "params/X86IntSinkPin.hh"
+#include "params/X86IntLine.hh"
namespace X86ISA {
@@ -99,6 +101,18 @@ class IntDev
panic("signalInterrupt not implemented.\n");
}
+ virtual void
+ raiseInterruptPin(int number)
+ {
+ panic("raiseInterruptPin not implemented.\n");
+ }
+
+ virtual void
+ lowerInterruptPin(int number)
+ {
+ panic("lowerInterruptPin not implemented.\n");
+ }
+
virtual Tick
recvMessage(PacketPtr pkt)
{
@@ -113,20 +127,34 @@ class IntDev
}
};
-class IntPin : public SimObject
+class IntSinkPin : public SimObject
{
- protected:
+ public:
IntDev * device;
- int line;
+ int number;
- public:
- typedef X86IntPinParams Params;
+ typedef X86IntSinkPinParams Params;
+
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
- IntDev *
- getDevice() const
+ IntSinkPin(Params *p) : SimObject(p),
+ device(dynamic_cast<IntDev *>(p->device)), number(p->number)
{
- return device;
+ assert(device);
}
+};
+
+class IntSourcePin : public SimObject
+{
+ protected:
+ std::vector<IntSinkPin *> sinks;
+
+ public:
+ typedef X86IntSourcePinParams Params;
const Params *
params() const
@@ -134,16 +162,52 @@ class IntPin : public SimObject
return dynamic_cast<const Params *>(_params);
}
- IntPin(Params *p) : SimObject(p),
- device(dynamic_cast<IntDev *>(p->device)), line(p->line)
+ void
+ addSink(IntSinkPin *sink)
{
- assert(device);
+ sinks.push_back(sink);
}
void
- signalInterrupt()
+ raise()
+ {
+ for (int i = 0; i < sinks.size(); i++) {
+ const IntSinkPin &pin = *sinks[i];
+ pin.device->raiseInterruptPin(pin.number);
+ }
+ }
+
+ void
+ lower()
+ {
+ for (int i = 0; i < sinks.size(); i++) {
+ const IntSinkPin &pin = *sinks[i];
+ pin.device->lowerInterruptPin(pin.number);
+ }
+ }
+
+ IntSourcePin(Params *p) : SimObject(p)
+ {}
+};
+
+class IntLine : public SimObject
+{
+ protected:
+ IntSourcePin *source;
+ IntSinkPin *sink;
+
+ public:
+ typedef X86IntLineParams Params;
+
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
+
+ IntLine(Params *p) : SimObject(p), source(p->source), sink(p->sink)
{
- device->signalInterrupt(line);
+ source->addSink(sink);
}
};