from m5.params import *
from m5.proxy import *
-from m5.objects.Device import BasicPioDevice
+from m5.objects.Device import PioDevice
from m5.objects.ClockDomain import DerivedClockDomain
-class X86LocalApic(BasicPioDevice):
+class X86LocalApic(PioDevice):
type = 'X86LocalApic'
cxx_class = 'X86ISA::Interrupts'
cxx_header = 'arch/x86/interrupts.hh'
int_latency = Param.Latency('1ns', \
"Latency for an interrupt to propagate through this device.")
- # pio_addr isn't used by the local APIC model since it's address is
- # calculated dynamically using the initial ID of the CPU it's attached to,
- # but it needs to be set to something to make the BasicPioDevice happy.
- pio_addr = 0x2000000000000000
+ pio_latency = Param.Latency('100ns', 'Programmed IO latency')
# The clock rate for the local APIC timer is supposed to be the "bus clock"
# which we assume is 1/16th the rate of the CPU clock. I don't think this
X86ISA::Interrupts::read(PacketPtr pkt)
{
Addr offset = pkt->getAddr() - pioAddr;
- //Make sure we're at least only accessing one register.
+ // Make sure we're at least only accessing one register.
if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
panic("Accessed more than one register at a time in the APIC!\n");
ApicRegIndex reg = decodeAddr(offset);
X86ISA::Interrupts::write(PacketPtr pkt)
{
Addr offset = pkt->getAddr() - pioAddr;
- //Make sure we're at least only accessing one register.
+ // Make sure we're at least only accessing one register.
if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
panic("Accessed more than one register at a time in the APIC!\n");
ApicRegIndex reg = decodeAddr(offset);
// int port that it inherited from IntDevice. Note IntDevice is
// not a SimObject itself.
//
- BasicPioDevice::init();
+ PioDevice::init();
IntDevice::init();
// the slave port has a range so inform the connected master
}
+AddrRangeList
+X86ISA::Interrupts::getAddrRanges() const
+{
+ assert(cpu);
+ AddrRangeList ranges;
+ ranges.push_back(RangeSize(pioAddr, PageBytes));
+ return ranges;
+}
+
+
AddrRangeList
X86ISA::Interrupts::getIntAddrRange() const
{
X86ISA::Interrupts::Interrupts(Params * p)
- : BasicPioDevice(p, PageBytes), IntDevice(this, p->int_latency),
+ : PioDevice(p), IntDevice(this, p->int_latency),
apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
pendingSmi(false), smiVector(0),
pendingNmi(false), nmiVector(0),
pendingStartup(false), startupVector(0),
startedUp(false), pendingUnmaskableInt(false),
pendingIPIs(0), cpu(NULL),
- intSlavePort(name() + ".int_slave", this, this)
+ intSlavePort(name() + ".int_slave", this, this),
+ pioDelay(p->pio_latency)
{
memset(regs, 0, sizeof(regs));
//Set the local apic DFR to the flat model.
ApicRegIndex decodeAddr(Addr paddr);
-class Interrupts : public BasicPioDevice, IntDevice
+class Interrupts : public PioDevice, IntDevice
{
protected:
// Storage for the APIC registers
// Port for receiving interrupts
IntSlavePort intSlavePort;
+ Tick pioDelay;
+ Addr pioAddr = MaxAddr;
+
public:
int getInitialApicId() { return initialApicId; }
return entry.periodic;
}
+ AddrRangeList getAddrRanges() const override;
AddrRangeList getIntAddrRange() const override;
Port &getPort(const std::string &if_name,
} else if (if_name == "int_slave") {
return intSlavePort;
}
- return BasicPioDevice::getPort(if_name, idx);
+ return PioDevice::getPort(if_name, idx);
}
/*