X86: Rework interrupt pins to allow one to many connections.
This commit is contained in:
parent
64b663c607
commit
6a3f255a84
16 changed files with 209 additions and 70 deletions
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -36,7 +36,9 @@ void
|
|||
X86ISA::Cmos::X86RTC::handleEvent()
|
||||
{
|
||||
assert(intPin);
|
||||
intPin->signalInterrupt();
|
||||
intPin->raise();
|
||||
//XXX This is a hack.
|
||||
intPin->lower();
|
||||
}
|
||||
|
||||
Tick
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,13 @@ class IntDev
|
|||
}
|
||||
};
|
||||
|
||||
class IntPin : public SimObject
|
||||
class IntSinkPin : public SimObject
|
||||
{
|
||||
protected:
|
||||
IntDev * device;
|
||||
int line;
|
||||
|
||||
public:
|
||||
typedef X86IntPinParams Params;
|
||||
IntDev * device;
|
||||
int number;
|
||||
|
||||
IntDev *
|
||||
getDevice() const
|
||||
{
|
||||
return device;
|
||||
}
|
||||
typedef X86IntSinkPinParams Params;
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
|
@ -134,16 +141,73 @@ class IntPin : public SimObject
|
|||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
IntPin(Params *p) : SimObject(p),
|
||||
device(dynamic_cast<IntDev *>(p->device)), line(p->line)
|
||||
IntSinkPin(Params *p) : SimObject(p),
|
||||
device(dynamic_cast<IntDev *>(p->device)), number(p->number)
|
||||
{
|
||||
assert(device);
|
||||
}
|
||||
};
|
||||
|
||||
class IntSourcePin : public SimObject
|
||||
{
|
||||
protected:
|
||||
std::vector<IntSinkPin *> sinks;
|
||||
|
||||
public:
|
||||
typedef X86IntSourcePinParams Params;
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
void
|
||||
signalInterrupt()
|
||||
addSink(IntSinkPin *sink)
|
||||
{
|
||||
device->signalInterrupt(line);
|
||||
sinks.push_back(sink);
|
||||
}
|
||||
|
||||
void
|
||||
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)
|
||||
{
|
||||
source->addSink(sink);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue