📄 flash_interface.c
字号:
void FlashliteInstallTimer(int cpuNum, unsigned int interval, unsigned int timeLeft){ FlashInstallTimer(cpuNum, interval, timeLeft);}static voidDownloadProtocolState(void){ int cpu, iec; /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * * NOTE: * More state needs to be downloaded here -- for now, we * only do the ibit table and the enable mask. * * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ for (cpu = 0; cpu < NUM_CPUS(0); cpu++) { for (iec = 0; iec < 64; iec++) { FlashSetIbitTableEntry(cpu, iec, SimMagic_GetIbitTableEntry(cpu, iec)); } FlashSetInterruptState(cpu, SimMagic_GetIECPending(cpu), SimMagic_GetIECTrans(cpu), SimMagic_GetIECEnable(cpu)); }}static voidDMADone(int nodeNum, void *token, int status){ ASSERT(status == 0); CacheCmdDone(nodeNum, (int)token, 0,0,status, NULL);}unsigned long longFlashAddrFromSimosAddr(unsigned int space, unsigned int addr){ static int totalMemPerProc = 0; FLASHAddress faddr; faddr.ll = 0; if (totalMemPerProc == 0) ParamLookup(&totalMemPerProc, "MEMSYS.FLASH.TotalMemPerProc", PARAM_INT); if (IS_DIRECT_MAP(addr)) { faddr.fa.node = addr >> bytesPerNode_shift; faddr.fa.space = space; faddr.fa.offset = addr & nodeOffsetMask; } else { faddr.fa.node = SimosAddrToMemnum(addr); faddr.fa.space = space; switch (addrMap) { case FIRST_TOUCH: case ROUND_ROBIN: faddr.fa.offset = addr; break; case HIVE: faddr.fa.offset = addr & nodeOffsetMask; break; case HIVE_ROUND_ROBIN: faddr.fa.offset = addr & nodeOffsetMask; break; default: CPUError("AddrMap %d not supported.\n", addrMap); } ASSERT(faddr.fa.offset >= directMapLimit); }/* CPUPrint("FFS: %d, 0x%08x => 0x%llx\n", space, addr, faddr.ll);*/ ASSERT(faddr.fa.offset < totalMemPerProc); return faddr.ll;}static unsigned intFlashAddrToSimosAddr(unsigned long long addr64){ FLASHAddress faddr; uint addr; int flashNodeForSimNode0, simNode, ncpusPerCell, cell, cpu; faddr.ll = addr64; if (IS_DIRECT_MAP(faddr.fa.offset)) { addr = (faddr.fa.node << bytesPerNode_shift) | faddr.fa.offset; } else if (faddr.fa.offset >= OSPC_RANGE_OFFSET(OFFSET_FIELD_SIZE)) { /* ASSUME that there's nothing useful above OSPC_RANGE_OFFSET */ addr = faddr.fa.offset - OSPC_RANGE_OFFSET(OFFSET_FIELD_SIZE) + OSPC_LOADDR_SIMOS; } else { switch (addrMap) { case FIRST_TOUCH: case ROUND_ROBIN: addr = faddr.fa.offset; break; case HIVE: addr = (faddr.fa.node << bytesPerNode_shift) | faddr.fa.offset; break; case HIVE_ROUND_ROBIN: ncpusPerCell = NUM_CPUS(0)/NUM_CELLS(0); cell = faddr.fa.node/ncpusPerCell; cpu = faddr.fa.node % ncpusPerCell; flashNodeForSimNode0 = (faddr.fa.offset/FLASH_PAGE_SIZE) % ncpusPerCell; simNode = cell * ncpusPerCell + (ncpusPerCell + cpu - flashNodeForSimNode0) % ncpusPerCell; addr = (simNode << bytesPerNode_shift) | faddr.fa.offset; break; default: CPUError("AddrMap %d not supported.\n", addrMap); addr = 0; /* Get rid of compiler warning */ } }/* CPUPrint("FTS: 0x%llx => 0x%08x\n", faddr, addr);*/ ASSERT(addr < MEM_SIZE(0)); return addr;}#endif/***************************************************************** * FlashliteCmd *****************************************************************/static ResultFlashliteCmd(int cpuNum, int cmd, PA addr, int transId, PA replacedPaddr, int writeback, byte *wbData) { int fcmd, flavor, len, way = 0; int former; int elimcmd, elimflavor; LL elimAddr, flashAddr; LL nextEvent; uint errorVec = 0; bool stall = TRUE;#ifndef SOLO if (cmd & MEMSYS_DMAFLAVOR) { int isRead = ((cmd & MEMSYS_CMDMASK) == MEMSYS_GET); uint pciAddress; int node, deviceId, hit; FLASHAddress faddr; deviceId = TRANSID2DMACHANNEL(transId); ASSERT(deviceId < 4); if (simosPageToNode[addr/FLASH_PAGE_SIZE] < 0) { simosPageToNode[addr/FLASH_PAGE_SIZE] = cpuNum; /* First touch */ } /* * Current we map flash address to node and office address and have * the DMA go through the PCI bus local to that node. We need to setup * the DMA mapping tables if we want to do this diffently. */ faddr.ll = FlashAddrFromAddr(0,addr); node = faddr.fa.node; pciAddress = 0x80000000 | faddr.fa.offset; /* * Push flashlite notion of time forward to that of the DMA. */ (void) FlashAdvanceTime(MipsyReadTime(cpuNum)); hit = FlashDMAReq(node, deviceId, isRead, pciAddress, wbData, writeback, (void *)transId, DMADone); nextEvent = FlashAdvanceTime(MipsyReadTime(cpuNum)); if (nextEvent != (LL)-1) { nextEvent += 1; if (callbackTime) { if (nextEvent < callbackTime) { EventCallbackUpdate(&callback, (SimTime) nextEvent); callbackTime = nextEvent; } } else { EventDoCallback(cpuNum,RunFlashlite, &callback, 0, nextEvent - MipsyReadTime(cpuNum)); callbackTime = nextEvent; } } return (hit ? SUCCESS : STALL); } #endif len = 0; switch (cmd & MEMSYS_CMDMASK) { case MEMSYS_GET: fcmd = PI_PROC_GET_REQ; if (cmd & MEMSYS_IFFLAVOR) { flavor = PI_GET_INSTRUCTION; } else if (cmd & MEMSYS_LLFLAVOR) { flavor = PI_GET_DATA_LL; } else { flavor = PI_GET_DATA; if (cmd & MEMSYS_PREFETCH) { flavor = PI_GET_DATA_PREFETCH; } } nodeState[cpuNum].stats.numGETs++; break; case MEMSYS_GETX: fcmd = PI_PROC_GETX_REQ; flavor = PI_GET_DATA; nodeState[cpuNum].stats.numGETXs++; if (cmd & MEMSYS_PREFETCH) { flavor = PI_GET_DATA_PREFETCH; } break; case MEMSYS_UPGRADE: fcmd = PI_PROC_UPGRADE_REQ; if (cmd & MEMSYS_SCFLAVOR) { flavor = PI_UPGRADE_SC; } else if (cmd & MEMSYS_PREFETCH) { flavor = PI_UPGRADE_PREFETCH; } else { flavor = PI_UPGRADE_NORMAL; } nodeState[cpuNum].stats.numUPGRADEs++; break; case MEMSYS_UNCWRITE: if (FlashUncachedWriteQueueFull(cpuNum)) { /* If flashlite can not accept this uncached write we * setup a callback to try again later. We will eventually * force the write into flashlite. */ if (!nodeState[cpuNum].retryCallback.active) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, (void *)0, 1); } return STALL; } stall = FALSE; fcmd = PI_PROC_UNC_WRITE_REQ; flavor = SW_SERVICES_FLAVOR; len = writeback; break; case MEMSYS_UNCWRITE_ACCELERATED: if (FlashUncachedWriteQueueFull(cpuNum)) { /* If flashlite can not accept this uncached write we * setup a callback to try again later. We will eventually * force the write into flashlite. */ if (!nodeState[cpuNum].retryCallback.active) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, (void *)0, 1); } return STALL; } stall = FALSE; fcmd = PI_PROC_UNC_PUT_SEQ_REQ; /* We don't actually know it's a _sequential_ accelerated, just that it's accelerated. */ flavor = SW_SERVICES_FLAVOR; len = writeback; break; case MEMSYS_UNCREAD: if (!nodeState[cpuNum].uncachedReadState.active) { FlashBreakGatherIfNecessary(cpuNum); /* DT: * Old test was !FlashGloballyPerformed(cpuNum), WRONG! There * was a window between the moment the fence count hits 0 and * the moment the last entry is removed from the SMHT. We were * falling off that window. */ if (!EmptySMHT(cpuNum) || !FlashGloballyPerformed(cpuNum)) { if (!nodeState[cpuNum].retryCallback.active) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, (void *)1, 1); } return STALL; } if (!FlashUncachedWriteQueueEmpty(cpuNum)) { if (!nodeState[cpuNum].retryCallback.active) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, (void *)1, 1); } return STALL; } } else { int size = writeback; if ((nodeState[cpuNum].uncachedReadState.addr == addr) && (nodeState[cpuNum].uncachedReadState.size == size)) { if (nodeState[cpuNum].uncachedReadState.done) { /* An uncached read has finished. Return it to the caller. */ bcopy(nodeState[cpuNum].uncachedReadState.data, wbData, size); nodeState[cpuNum].uncachedReadState.active = FALSE; return SUCCESS; } else { /* Still outstanding. Wakeup must have been spurious. */ return STALL; } } else { FlashBreakGatherIfNecessary(cpuNum); /* NOTE (DT) see comment above */ if (!EmptySMHT(cpuNum) || !FlashGloballyPerformed(cpuNum)) { if (!nodeState[cpuNum].retryCallback.active) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, (void *)1, 1); } return STALL; } if (!FlashUncachedWriteQueueEmpty(cpuNum)) { if (!nodeState[cpuNum].retryCallback.active) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, (void *)1, 1); } return STALL; } ASSERT(nodeState[cpuNum].uncachedReadState.done); } } /* A new request. Fill in buffer for tracking */ nodeState[cpuNum].uncachedReadState.active = TRUE; nodeState[cpuNum].uncachedReadState.addr = addr; nodeState[cpuNum].uncachedReadState.size = writeback; nodeState[cpuNum].uncachedReadState.done = FALSE; fcmd = PI_PROC_UNC_READ_REQ; flavor = SW_SERVICES_FLAVOR; len = writeback; break; case MEMSYS_SYNC: /* An accelerated write may be in progress. If we want to * sync, then terminate the gather and let the write proceed. */ FlashBreakGatherIfNecessary(cpuNum); /* SYNC is a special case that returns */ /* without calling flashlite, just */ /* querying its state */ if (!FlashGloballyPerformed(cpuNum)) { /* Must wait for flashlite */ return STALL; } return SUCCESS; default: assert(0); fcmd = 0; } elimAddr = 0; /* elimAddr.fa.space = 0; - For now only NORMAL address space */ if (replacedPaddr == MEMSYS_NOADDR) { elimcmd = 0; elimflavor = 0; } else {#ifndef SOLO if ((replacedPaddr == OSPC_LOADDR_SIMOS) || (replacedPaddr == OSPC_HIADDR_SIMOS) || (replacedPaddr == OSPC_VEC_REQ_ADDR_SIMOS) || (replacedPaddr == OSPC_VEC_REP_ADDR_SIMOS)) { FLASHAddress faddr; faddr.ll = 0; faddr.fa.node = cpuNum; faddr.fa.offset = OSPC_RANGE_OFFSET(OFFSET_FIELD_SIZE) + (replacedPaddr - OSPC_LOADDR_SIMOS); elimAddr = faddr.ll; } else { elimAddr = FlashAddrFromAddr(0,replacedPaddr); }#else#if 0 /* JH: This is the safe, default version that doesn't provide the lock hack. In case the lock code crashes for you badly, this is a saving grace you can use*/ elimAddr = FlashAddrFromAddr(0,replacedPaddr);#else if ( ((replacedPaddr)&soloPACompressOffsetMask) >= soloBarrierBase) { /* barrier space overloading currently supported in SOLO only */#ifdef DEBUG_PAGE_VERBOSE CPUPrint("Barrier address detected, mapping to space 2 addr %x offset %x\n", replacedPaddr, ((addr)&soloPACompressOffsetMask));#endif /* DEBUG_PAGE_VERBOSE */ elimAddr = FlashAddrFromAddr(2,replacedPaddr); elimAddr -= soloBarrierBase; /* This adjusts the phys addr so that it begins from zero in space 2*/ } else if (((replacedPaddr)&soloPACompressOffsetMask) >= soloLockBase) {/* Lock space overloading currently supported in SOLO only */#ifdef DEBUG_PAGE_VERBOSE CPUPrint("Lock address (replace) detected, mapping to space 1 addr %x offset %x\n", replacedPaddr, ((replacedPaddr)&soloPACompressOffsetMask));#endif elimAddr = FlashAddrFromAddr(1,replacedPaddr); elimAddr -= soloLockBase; /* This adjusts the phys addr so that it begins from zero in space 1*/ } else { elimAddr = FlashAddrFromAddr(0,replacedPaddr); }#endif#ifdef DEBUG_PAGE_VERBOSE CPUPrint("after decompression ELIM addr, pAddr = %llx\n",elimAddr);#endif /* DEBUG_PAGE_VERBOSE */#endif if (writeback) { elimcmd = PI_PROC_PUTX_REQ; elimflavor = 0; nodeState[cpuNum].stats.numWBs++; } else { elimcmd = PI_PROC_REPLACE_REQ; elimflavor = PI_REPLACE_SHARED; } if (transId < 0) { stall = FALSE; /* Must be from a cache flush, don't stall the processor */ } } /* Store request info in flashPending so that it can be checked while handling requests in FlashAdvanceTime */ flashPending.active = 1; flashPending.fcmd = fcmd; flashPending.flavor = flavor; flashPending.cpuNum = cpuNum; flashPending.addr = (addr & ~(SCACHE_LINE_SIZE - 1)); nextEvent = FlashAdvanceTime(MipsyReadTime(cpuNum)); /* Extract the fcmd/flavor from flashPending since it might have changed */ flashPending.active = 0; fcmd = flashPending.fcmd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -