from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice
+from X86IntPin import X86IntSourcePin
class Cmos(BasicPioDevice):
type = 'Cmos'
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')
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'
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)
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')
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,
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)
from I8254 import I8254
from I8259 import I8259
from PcSpeaker import PcSpeaker
+from X86IntPin import X86IntLine
from m5.SimObject import SimObject
def x86IOAddress(port):
_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")
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
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")
X86ISA::Cmos::X86RTC::handleEvent()
{
assert(intPin);
- intPin->signalInterrupt();
+ intPin->raise();
+ //XXX This is a hack.
+ intPin->lower();
}
Tick
namespace X86ISA
{
-class IntPin;
+class IntSourcePin;
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)
{
}
#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();
entry.mask = 1;
for (int i = 0; i < TableSize; i++) {
redirTable[i] = entry;
+ pinStates[i] = false;
}
}
}
}
+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()
{
static const uint8_t APICVersion = 0x14;
RedirTableEntry redirTable[TableSize];
+ bool pinStates[TableSize];
public:
typedef I82094AAParams Params;
I82094AA(Params *p);
- void
- setExtIntPic(I8259 * pic)
- {
- extIntPic = pic;
- }
-
Tick read(PacketPtr pkt);
Tick write(PacketPtr pkt);
}
void signalInterrupt(int line);
+ void raiseInterruptPin(int number);
+ void lowerInterruptPin(int number);
};
}; // namespace X86ISA
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
namespace X86ISA
{
-class IntPin;
+class IntSourcePin;
class I8254 : public BasicPioDevice
{
X86Intel8254Timer pit;
- IntPin *intPin;
+ IntSourcePin *intPin;
void counterInterrupt(unsigned int num);
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;
}
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");
}
}
+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()
{
{
protected:
static const int NumLines = 8;
+ bool pinStates[NumLines];
Tick latency;
- IntPin *output;
+ IntSourcePin *output;
Enums::X86I8259CascadeMode mode;
I8259 * slave;
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();
};
#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);
}
#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 {
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)
{
}
};
-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
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);
}
};