from m5.params import *
from m5.proxy import *
-from m5.objects.Device import PioDevice
from m5.objects.ClockDomain import DerivedClockDomain
+from m5.SimObject import SimObject
-class X86LocalApic(PioDevice):
+class X86LocalApic(SimObject):
type = 'X86LocalApic'
cxx_class = 'X86ISA::Interrupts'
cxx_header = 'arch/x86/interrupts.hh'
int_slave = SlavePort("Port for receiving interrupt messages")
int_latency = Param.Latency('1ns', \
"Latency for an interrupt to propagate through this device.")
+ pio = SlavePort("Programmed I/O port")
+ system = Param.System(Parent.any, "System this device is part of")
pio_latency = Param.Latency('100ns', 'Programmed IO latency')
# which we assume is 1/16th the rate of the CPU clock. I don't think this
# is a hard rule, but seems to be true in practice. This can be overriden
# in configs that use it.
- clk_domain = DerivedClockDomain(
- clk_domain=Parent.clk_domain, clk_divider=16)
+ clk_domain = Param.DerivedClockDomain(
+ DerivedClockDomain(clk_domain=Parent.clk_domain, clk_divider=16),
+ "The clock for the local APIC. Should not be modified.")
void
X86ISA::Interrupts::init()
{
- //
- // The local apic must register its address ranges on its pio
- // port via the basicpiodevice(piodevice) init() function.
- PioDevice::init();
-
- // The slave port has a range, so inform the connected master.
- intSlavePort.sendRangeChange();
- // If the master port isn't connected, we can't send interrupts anywhere.
panic_if(!intMasterPort.isConnected(),
"Int port not connected to anything!");
+ panic_if(!pioPort.isConnected(),
+ "Pio port of %s not connected to anything!", name());
+
+ intSlavePort.sendRangeChange();
+ pioPort.sendRangeChange();
}
X86ISA::Interrupts::Interrupts(Params * p)
- : PioDevice(p),
+ : SimObject(p), sys(p->system), clockDomain(*p->clk_domain),
apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
pendingSmi(false), smiVector(0),
pendingNmi(false), nmiVector(0),
pendingIPIs(0), cpu(NULL),
intSlavePort(name() + ".int_slave", this, this),
intMasterPort(name() + ".int_master", this, this, p->int_latency),
- pioDelay(p->pio_latency)
+ pioPort(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 PioDevice
+class Interrupts : public SimObject
{
protected:
+ System *sys;
+ ClockDomain &clockDomain;
+
// Storage for the APIC registers
uint32_t regs[NUM_APIC_REGS];
return bits(regs[base + (vector / 32)], vector % 32);
}
+ Tick clockPeriod() const { return clockDomain.clockPeriod(); }
+
void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
BaseCPU *cpu;
IntSlavePort<Interrupts> intSlavePort;
IntMasterPort<Interrupts> intMasterPort;
+ // Port for memory mapped register accesses.
+ PioPort<Interrupts> pioPort;
+
Tick pioDelay;
Addr pioAddr = MaxAddr;
/*
* Functions to interact with the interrupt port.
*/
- Tick read(PacketPtr pkt) override;
- Tick write(PacketPtr pkt) override;
+ Tick read(PacketPtr pkt);
+ Tick write(PacketPtr pkt);
Tick recvMessage(PacketPtr pkt);
void completeIPI(PacketPtr pkt);
return entry.periodic;
}
- AddrRangeList getAddrRanges() const override;
+ AddrRangeList getAddrRanges() const;
AddrRangeList getIntAddrRange() const;
Port &getPort(const std::string &if_name,
return intMasterPort;
} else if (if_name == "int_slave") {
return intSlavePort;
+ } else if (if_name == "pio") {
+ return pioPort;
}
- return PioDevice::getPort(if_name, idx);
+ return SimObject::getPort(if_name, idx);
}
/*