summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
authorNathan Binkert <binkertn@umich.edu>2005-11-21 23:43:15 -0500
committerNathan Binkert <binkertn@umich.edu>2005-11-21 23:43:15 -0500
commitf806a25c9edb3a9a9f5bc34b88340be6b24a2022 (patch)
tree054c4562aabde4aaf354f764dd88b029dbe3f858 /dev
parent50ee8c646128a9e08051843535076f12f6c6dfea (diff)
downloadgem5-f806a25c9edb3a9a9f5bc34b88340be6b24a2022.tar.xz
add support for delaying pio writes until the cache access occurs
dev/ns_gige.cc: add support for delaying pio writes until the cache access occurs the only write we delay are for CR_TXE and CR_RXE dev/sinic.cc: dev/sinic.hh: the txPioRequest and rxPioRequest things were more or less bogus add support for delaying pio writes until the cache access occurs dev/sinicreg.hh: Add delay_read and delay_write to the register information struct for now, we won't delay any reads, and we'll delay the writes that initiate DMAs python/m5/objects/Ethernet.py: add a parameter to delay pio writes until the timing access actually occurs. --HG-- extra : convert_revision : 79b18ea2812c2935d7d5ea6eff1f55265114d05d
Diffstat (limited to 'dev')
-rw-r--r--dev/ns_gige.cc61
-rw-r--r--dev/ns_gige.hh10
-rw-r--r--dev/sinic.cc111
-rw-r--r--dev/sinic.hh26
-rw-r--r--dev/sinicreg.hh48
5 files changed, 178 insertions, 78 deletions
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index c8ff04ec5..979bb6b7a 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -130,6 +130,7 @@ NSGigE::NSGigE(Params *p)
} else if (p->payload_bus)
panic("Must define a header bus if defining a payload bus");
+ pioDelayWrite = p->pio_delay_write && pioInterface;
intrDelay = p->intr_delay;
dmaReadDelay = p->dma_read_delay;
@@ -801,6 +802,13 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
+ if (pioDelayWrite) {
+ int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ if (cpu >= writeQueue.size())
+ writeQueue.resize(cpu + 1);
+ writeQueue[cpu].push_back(RegWriteData(daddr, *(uint32_t *)data));
+ }
+
if (req->size == sizeof(uint32_t)) {
uint32_t reg = *(uint32_t *)data;
uint16_t rfaddr;
@@ -813,20 +821,24 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
if (reg & CR_TXD) {
txEnable = false;
} else if (reg & CR_TXE) {
- txEnable = true;
+ if (!pioDelayWrite) {
+ txEnable = true;
- // the kernel is enabling the transmit machine
- if (txState == txIdle)
- txKick();
+ // the kernel is enabling the transmit machine
+ if (txState == txIdle)
+ txKick();
+ }
}
if (reg & CR_RXD) {
rxEnable = false;
} else if (reg & CR_RXE) {
- rxEnable = true;
+ if (!pioDelayWrite) {
+ rxEnable = true;
- if (rxState == rxIdle)
- rxKick();
+ if (rxState == rxIdle)
+ rxKick();
+ }
}
if (reg & CR_TXR)
@@ -2934,8 +2946,38 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
Tick
NSGigE::cacheAccess(MemReqPtr &req)
{
+ Addr daddr = req->paddr & 0xfff;
DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
- req->paddr, req->paddr - addr);
+ req->paddr, daddr);
+
+ if (!pioDelayWrite || !req->cmd.isWrite())
+ return curTick + pioLatency;
+
+ int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ std::list<RegWriteData> &wq = writeQueue[cpu];
+ if (wq.empty())
+ panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr);
+
+ const RegWriteData &data = wq.front();
+ if (data.daddr != daddr)
+ panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
+ cpu, data.daddr, daddr);
+
+ if (daddr == CR) {
+ if ((data.value & (CR_TXD | CR_TXE)) == CR_TXE) {
+ txEnable = true;
+ if (txState == txIdle)
+ txKick();
+ }
+
+ if ((data.value & (CR_RXD | CR_RXE)) == CR_RXE) {
+ rxEnable = true;
+ if (rxState == rxIdle)
+ rxKick();
+ }
+ }
+
+ wq.pop_front();
return curTick + pioLatency;
}
@@ -2995,6 +3037,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> dma_write_factor;
Param<bool> dma_no_allocate;
Param<Tick> pio_latency;
+ Param<bool> pio_delay_write;
Param<Tick> intr_delay;
Param<Tick> rx_delay;
@@ -3034,6 +3077,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"),
INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"),
+ INIT_PARAM(pio_delay_write, ""),
INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
INIT_PARAM(rx_delay, "Receive Delay"),
@@ -3077,6 +3121,7 @@ CREATE_SIM_OBJECT(NSGigE)
params->dma_write_factor = dma_write_factor;
params->dma_no_allocate = dma_no_allocate;
params->pio_latency = pio_latency;
+ params->pio_delay_write = pio_delay_write;
params->intr_delay = intr_delay;
params->rx_delay = rx_delay;
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 36fd6050a..7db833028 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -239,6 +239,15 @@ class NSGigE : public PciDev
uint32_t rxDescCnt;
DmaState rxDmaState;
+ struct RegWriteData {
+ Addr daddr;
+ uint32_t value;
+ RegWriteData(Addr da, uint32_t val) : daddr(da), value(val) {}
+ };
+
+ std::vector<std::list<RegWriteData> > writeQueue;
+ bool pioDelayWrite;
+
bool extstsEnable;
/** EEPROM State Machine */
@@ -376,6 +385,7 @@ class NSGigE : public PciDev
Tick tx_delay;
Tick rx_delay;
Tick pio_latency;
+ bool pio_delay_write;
bool dma_desc_free;
bool dma_data_free;
Tick dma_read_delay;
diff --git a/dev/sinic.cc b/dev/sinic.cc
index ef2350d11..e51518b0c 100644
--- a/dev/sinic.cc
+++ b/dev/sinic.cc
@@ -112,6 +112,8 @@ Device::Device(Params *p)
p->dma_no_allocate);
} else if (p->payload_bus)
panic("must define a header bus if defining a payload bus");
+
+ pioDelayWrite = p->pio_delay_write && pioInterface;
}
Device::~Device()
@@ -311,7 +313,14 @@ Device::writeConfig(int offset, int size, const uint8_t *data)
}
void
-Device::prepareRead()
+Device::prepareIO(int cpu)
+{
+ if (cpu >= writeQueue.size())
+ writeQueue.resize(cpu + 1);
+}
+
+void
+Device::prepareRead(int cpu)
{
using namespace Regs;
@@ -328,6 +337,12 @@ Device::prepareRead()
regs.TxWait = regs.TxDone;
}
+void
+Device::prepareWrite(int cpu)
+{
+ prepareIO(cpu);
+}
+
/**
* I/O read of device register
*/
@@ -350,6 +365,8 @@ Device::read(MemReqPtr &req, uint8_t *data)
Fault
Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
{
+ int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+
if (!regValid(daddr))
panic("invalid register: da=%#x pa=%#x va=%#x size=%d",
daddr, req->paddr, req->vaddr, req->size);
@@ -363,7 +380,7 @@ Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
info.name, daddr, req->paddr, req->vaddr, req->size);
- prepareRead();
+ prepareRead(cpu);
uint64_t value = 0;
if (req->size == 4) {
@@ -393,7 +410,7 @@ Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
* IPR read of device register
*/
Fault
-Device::iprRead(Addr daddr, uint64_t &result)
+Device::iprRead(Addr daddr, int cpu, uint64_t &result)
{
if (!regValid(daddr))
panic("invalid address: da=%#x", daddr);
@@ -404,7 +421,7 @@ Device::iprRead(Addr daddr, uint64_t &result)
DPRINTF(EthernetPIO, "read reg=%s da=%#x\n", info.name, daddr);
- prepareRead();
+ prepareRead(cpu);
if (info.size == 4)
result = regData32(daddr);
@@ -440,6 +457,8 @@ Device::write(MemReqPtr &req, const uint8_t *data)
Fault
Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
{
+ int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+
if (!regValid(daddr))
panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
daddr, req->paddr, req->vaddr, req->size);
@@ -459,6 +478,21 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
info.name, info.size == 4 ? reg32 : reg64, daddr, req->paddr,
req->vaddr, req->size);
+ if (pioDelayWrite)
+ writeQueue[cpu].push_back(RegWriteData(daddr, reg64));
+
+ if (!pioDelayWrite || !info.delay_write)
+ regWrite(daddr, cpu, data);
+
+ return No_Fault;
+}
+
+void
+Device::regWrite(Addr daddr, int cpu, const uint8_t *data)
+{
+ uint32_t reg32 = *(uint32_t *)data;
+ uint64_t reg64 = *(uint64_t *)data;
+
switch (daddr) {
case Regs::Config:
changeConfig(reg32);
@@ -502,8 +536,6 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
}
break;
}
-
- return No_Fault;
}
void
@@ -769,12 +801,6 @@ Device::rxKick()
next:
switch (rxState) {
case rxIdle:
- if (rxPioRequest) {
- DPRINTF(EthernetPIO, "rxIdle: PIO waiting responding at %d\n",
- curTick + pioLatency);
- pioInterface->respond(rxPioRequest, curTick);
- rxPioRequest = 0;
- }
goto exit;
case rxFifoBlock:
@@ -977,12 +1003,6 @@ Device::txKick()
next:
switch (txState) {
case txIdle:
- if (txPioRequest) {
- DPRINTF(EthernetPIO, "txIdle: PIO waiting responding at %d\n",
- curTick + pioLatency);
- pioInterface->respond(txPioRequest, curTick + pioLatency);
- txPioRequest = 0;
- }
goto exit;
case txFifoBlock:
@@ -1371,42 +1391,46 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
/*
* re-add addrRanges to bus bridges
*/
- if (pioInterface)
+ if (pioInterface) {
pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+ pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
+ }
}
Tick
Device::cacheAccess(MemReqPtr &req)
{
- //The mask is to give you only the offset into the device register file
- Addr daddr = req->paddr - addr;
+ Addr daddr;
+ int bar;
+ if (!getBAR(req->paddr, daddr, bar))
+ panic("address does not map to a BAR pa=%#x va=%#x size=%d",
+ req->paddr, req->vaddr, req->size);
- DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
- req->paddr, daddr);
+ DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n",
+ req->cmd.toString(), req->paddr, bar, daddr);
- Tick when = curTick + pioLatency;
+ if (!pioDelayWrite || !req->cmd.isWrite())
+ return curTick + pioLatency;
- switch (daddr) {
- case Regs::RxWait:
- if (rxState != rxIdle) {
- DPRINTF(EthernetPIO, "rxState=%s (not idle)... waiting\n",
- TxStateStrings[txState]);
- rxPioRequest = req;
- when = 0;
- }
- break;
+ if (bar == 0) {
+ int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ std::list<RegWriteData> &wq = writeQueue[cpu];
+ if (wq.empty())
+ panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr);
- case Regs::TxWait:
- if (txState != txIdle) {
- DPRINTF(EthernetPIO, "txState=%s (not idle)... waiting\n",
- TxStateStrings[txState]);
- txPioRequest = req;
- when = 0;
- }
- break;
+ const RegWriteData &data = wq.front();
+ if (data.daddr != daddr)
+ panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
+ cpu, data.daddr, daddr);
+
+ const Regs::Info &info = regInfo(data.daddr);
+ if (info.delay_write)
+ regWrite(daddr, cpu, (uint8_t *)&data.value);
+
+ wq.pop_front();
}
- return when;
+ return curTick + pioLatency;
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
@@ -1463,6 +1487,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
Param<Tick> dma_write_factor;
Param<bool> dma_no_allocate;
Param<Tick> pio_latency;
+ Param<bool> pio_delay_write;
Param<Tick> intr_delay;
Param<Tick> rx_delay;
@@ -1505,6 +1530,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"),
INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"),
+ INIT_PARAM(pio_delay_write, ""),
INIT_PARAM(intr_delay, "Interrupt Delay"),
INIT_PARAM(rx_delay, "Receive Delay"),
@@ -1551,6 +1577,7 @@ CREATE_SIM_OBJECT(Device)
params->dma_write_factor = dma_write_factor;
params->dma_no_allocate = dma_no_allocate;
params->pio_latency = pio_latency;
+ params->pio_delay_write = pio_delay_write;
params->intr_delay = intr_delay;
params->tx_delay = tx_delay;
diff --git a/dev/sinic.hh b/dev/sinic.hh
index b9089cd53..b3255b6c0 100644
--- a/dev/sinic.hh
+++ b/dev/sinic.hh
@@ -235,13 +235,6 @@ class Device : public Base
Tick dmaWriteFactor;
/**
- * PIO parameters
- */
- protected:
- MemReqPtr rxPioRequest;
- MemReqPtr txPioRequest;
-
-/**
* Interrupt management
*/
protected:
@@ -262,12 +255,26 @@ class Device : public Base
virtual Fault read(MemReqPtr &req, uint8_t *data);
virtual Fault write(MemReqPtr &req, const uint8_t *data);
- void prepareRead();
- Fault iprRead(Addr daddr, uint64_t &result);
+ void prepareIO(int cpu);
+ void prepareRead(int cpu);
+ void prepareWrite(int cpu);
+ Fault iprRead(Addr daddr, int cpu, uint64_t &result);
Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ void regWrite(Addr daddr, int cpu, const uint8_t *data);
Tick cacheAccess(MemReqPtr &req);
+ protected:
+ struct RegWriteData {
+ Addr daddr;
+ uint64_t value;
+ RegWriteData(Addr da, uint64_t val) : daddr(da), value(val) {}
+ };
+
+ std::vector<std::list<RegWriteData> > writeQueue;
+
+ bool pioDelayWrite;
+
/**
* Statistics
*/
@@ -323,6 +330,7 @@ class Device : public Base
Bus *header_bus;
Bus *payload_bus;
Tick pio_latency;
+ bool pio_delay_write;
PhysicalMemory *physmem;
IntrControl *intctrl;
bool rx_filter;
diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh
index 12f545255..30f5b3c95 100644
--- a/dev/sinicreg.hh
+++ b/dev/sinicreg.hh
@@ -140,6 +140,8 @@ struct Info
uint8_t size;
bool read;
bool write;
+ bool delay_read;
+ bool delay_write;
const char *name;
};
@@ -148,26 +150,34 @@ struct Info
inline const Regs::Info&
regInfo(Addr daddr)
{
+ static Regs::Info invalid = { 0, false, false, false, false, "invalid" };
static Regs::Info info [] = {
- { 4, true, true, "Config" },
- { 4, false, true, "Command" },
- { 4, true, true, "IntrStatus" },
- { 4, true, true, "IntrMask" },
- { 4, true, false, "RxMaxCopy" },
- { 4, true, false, "TxMaxCopy" },
- { 4, true, false, "RxMaxIntr" },
- { 0, false, false, "invalid" },
- { 4, true, false, "RxFifoSize" },
- { 4, true, false, "TxFifoSize" },
- { 4, true, false, "RxFifoMark" },
- { 4, true, false, "TxFifoMark" },
- { 8, true, true, "RxData" }, { 0, false, false, "invalid" },
- { 8, true, false, "RxDone" }, { 0, false, false, "invalid" },
- { 8, true, false, "RxWait" }, { 0, false, false, "invalid" },
- { 8, true, true, "TxData" }, { 0, false, false, "invalid" },
- { 8, true, false, "TxDone" }, { 0, false, false, "invalid" },
- { 8, true, false, "TxWait" }, { 0, false, false, "invalid" },
- { 8, true, false, "HwAddr" }, { 0, false, false, "invalid" }
+ { 4, true, true, false, false, "Config" },
+ { 4, false, true, false, false, "Command" },
+ { 4, true, true, false, false, "IntrStatus" },
+ { 4, true, true, false, false, "IntrMask" },
+ { 4, true, false, false, false, "RxMaxCopy" },
+ { 4, true, false, false, false, "TxMaxCopy" },
+ { 4, true, false, false, false, "RxMaxIntr" },
+ invalid,
+ { 4, true, false, false, false, "RxFifoSize" },
+ { 4, true, false, false, false, "TxFifoSize" },
+ { 4, true, false, false, false, "RxFifoMark" },
+ { 4, true, false, false, false, "TxFifoMark" },
+ { 8, true, true, false, true, "RxData" },
+ invalid,
+ { 8, true, false, false, false, "RxDone" },
+ invalid,
+ { 8, true, false, false, false, "RxWait" },
+ invalid,
+ { 8, true, true, false, true, "TxData" },
+ invalid,
+ { 8, true, false, false, false, "TxDone" },
+ invalid,
+ { 8, true, false, false, false, "TxWait" },
+ invalid,
+ { 8, true, false, false, false, "HwAddr" },
+ invalid,
};
return info[daddr / 4];