📄 flash_interface.c
字号:
flavor = flashPending.flavor; if ((fcmd == PI_PROC_UNC_READ_REQ) || (fcmd == PI_PROC_UNC_WRITE_REQ) || (fcmd == PI_PROC_UNC_PUT_SEQ_REQ)) { GetUncachedAddr(cpuNum, addr, &flashAddr, &flavor); } else {#ifndef SOLO /* Change fcmd to NC_GET for OSPC and map it to correct address */ uint lineStartAddr = addr & ~(SCACHE_LINE_SIZE - 1); if ((lineStartAddr == OSPC_LOADDR_SIMOS) || (lineStartAddr == OSPC_HIADDR_SIMOS) || (lineStartAddr == OSPC_VEC_REQ_ADDR_SIMOS) || (lineStartAddr == OSPC_VEC_REP_ADDR_SIMOS)) { FLASHAddress faddr; ASSERT(fcmd == PI_PROC_GET_REQ); fcmd = PI_PROC_NC_GET_REQ; faddr.ll = 0; faddr.fa.node = cpuNum; faddr.fa.offset = OSPC_RANGE_OFFSET(OFFSET_FIELD_SIZE) + (addr - OSPC_LOADDR_SIMOS); flashAddr = faddr.ll; } else { if (simosPageToNode[addr/FLASH_PAGE_SIZE] < 0) { simosPageToNode[addr/FLASH_PAGE_SIZE] = cpuNum; /* First touch */ } flashAddr = FlashAddrFromAddr(0,addr); }#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*/ flashAddr = FlashAddrFromAddr(0,addr);#else if ( ((addr)&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", addr, ((addr)&soloPACompressOffsetMask));#endif /* DEBUG_PAGE_VERBOSE */ flashAddr = FlashAddrFromAddr(2,addr); flashAddr -= soloBarrierBase; /* This adjusts the phys addr so that it begins from zero in space 1*/ } else if ( ((addr)&soloPACompressOffsetMask) >= soloLockBase) { /* lock space overloading currently supported in SOLO only */#ifdef DEBUG_PAGE_VERBOSE CPUPrint("Lock address detected, mapping to space 1 addr %x offset %x\n",addr, ((addr)&soloPACompressOffsetMask));#endif /* DEBUG_PAGE_VERBOSE */ flashAddr = FlashAddrFromAddr(1,addr); flashAddr -= soloLockBase; /* This adjusts the phys addr so that it begins from zero in space 1*/ } else { flashAddr = FlashAddrFromAddr(0,addr); }#endif#ifdef DEBUG_PAGE_VERBOSE CPUPrint("after decompression cmd addr, pAddr = %llx\n",flashAddr);#endif /* DEBUG_PAGE_VERBOSE */#endif }/* CPUPrint("Mapping Mipsy: %8.8x to Flash: %16.16llx\n", addr, flashAddr); */ /* Grab way from the SMHT */ if (transId >= 0) { way = SCACHE[GET_SCACHE_NUM(cpuNum)].SMHT[transId].scacheLRU; } former = SCACHE[GET_SCACHE_NUM(cpuNum)].SMHT[transId].formerState; nextEvent = FlashCmdToMagic(cpuNum, transId, FLASH_CMD_FORM(fcmd, flavor, way, len, former), flashAddr, FLASH_CMD_FORM(elimcmd, elimflavor, way, 0, 0), elimAddr, wbData, errorVec); assert(nextEvent >= MipsyReadTime(numNum)); assert(nextEvent <= 0x7FFFFFFFFFFFFFFFLL); 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; } } if (stall) { return STALL; } else { return SUCCESS; }}static voidRetryUncachedOp(int cpuNum, EventCallbackHdr *hdr, void *arg){ int isRead = (int) arg; if (isRead) { /* * If writeQueue is still not empty try again later otherwise * we allow the processor to retry. */ if (!FlashUncachedWriteQueueEmpty(cpuNum)) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, arg, 1); return; } } else { /* * If writeQueue is still full try again later otherwise * we allow the processor to retry. */ if (FlashUncachedWriteQueueFull(cpuNum)) { EventDoCallback(cpuNum,RetryUncachedOp, &nodeState[cpuNum].retryCallback, arg, 1); return; } } MipsyReissueUncachedOp(cpuNum);}voidDumpCacheLine(char *data,int length){ unsigned long *ld = (unsigned long *)data; int i; for (i=0; i< (length/sizeof(long)); i+=4) { CPUPrint("%8.8x %8.8x %8.8x %8.8x ",ld[i],ld[i+1], ld[i+2],ld[i+3]); if ((i+4)%8 == 0) { CPUPrint("\n"); } }}static voidRunFlashlite(int cpuNum, EventCallbackHdr *hdr, void *v){ LL nextEvent; nextEvent = FlashAdvanceTime(MipsyReadTime(cpuNum)); if (nextEvent == (LL)-1) { callbackTime = 0; return; } assert(nextEvent >= MipsyReadTime(cpuNum)); assert(nextEvent <= 0x7FFFFFFFFFFFFFFFLL); callbackTime = nextEvent+1; EventDoCallback(cpuNum, RunFlashlite, &callback, 0, callbackTime - MipsyReadTime(0));}voidSimosCmdToSimos(int cpunum, int transId, int cmd, LL addr, int *cacheState, byte *data, uint errorVec){ PA address; int wasDirty; LL lclData[WORDS_IN_CACHELINE]; int remoteResult; /* used to break stall into local vs. remote */ FLASHAddress faddr; /* set REMOTE_HOME if this addr's is not local */ faddr.ll = addr; remoteResult = (cpunum != faddr.fa.node) ? MEMSYS_RESULT_REMOTE_HOME : 0;#ifndef SOLO if (cmd == PI_DP_UNC_READ_RPLY || cmd == PI_DP_UNC_ERR_RPLY || cmd == PI_DP_UNC_NAK_RPLY) address = Uncached64To32Bit(addr); else {#endif#ifdef SOLO if (faddr.fa.space == 1) { /* Convert to lock range */ faddr.fa.space = 0; faddr.fa.offset = faddr.fa.offset + soloLockBase; /* Offset to start of lock VA range */ addr = faddr.ll;#ifdef DEBUG_PAGE_VERBOSE CPUPrint("Lock address detected, mapping upwards for (FA) %16.16llx\n", addr);#endif /* DEBUG_PAGE_VERBOSE */ } if (faddr.fa.space == 2) { /* Convert to lock range */ faddr.fa.space = 0; faddr.fa.offset = faddr.fa.offset + soloBarrierBase; /* Offset to start of lock VA range */ addr = faddr.ll;#ifdef DEBUG_PAGE_VERBOSE CPUPrint("Barrier address detected, mapping upwards for (FA) %16.16llx\n", addr);#endif /* DEBUG_PAGE_VERBOSE */ }#endif /* SOLO */ address = FlashAddrToAddr(addr);#ifndef SOLO }#endif#ifdef DEBUG_PAGE_VERBOSE CPUPrint("After FAtoA: mipsy addr = %x\n",address);#endif /* DEBUG_PAGE_VERBOSE *//* CPUPrint("Mapping Flash: %16.16llx to Mipsy: %8.8x\n", addr, address); */#ifndef SOLO if (errorVec && /* looks like an ECC... */ /* ... but check whether this is an unc read -- only bit 0 matters */ !(cmd == PI_DP_UNC_READ_RPLY && (errorVec & 0x1) == 0)) { if (cmd == PI_DP_UNC_READ_RPLY) { /* BUS ERROR the uncached ref */ MipsyTakeBusError(cpunum, 0, address); } else { /* Asynchronous */ MipsyCacheError(cpunum, 1); } /* Transaction should be allowed to complete. At 3:30am we think it's safe to allow the CPU to continue. return; */ } #endif switch (cmd) { case PI_DP_ERR_RPLY: /* bus error that goes through caches */ CacheCmdDone(cpunum, transId, 0, MEMSYS_STATUS_ERROR, remoteResult | MEMSYS_RESULT_MEMORY, data); break; case PI_DP_NAK_RPLY: CacheCmdDone(cpunum, transId, 0, MEMSYS_STATUS_NAK, remoteResult | MEMSYS_RESULT_MEMORY, data); nodeState[cpunum].stats.numNAKs++;#ifdef DEBUG CPUPrint("FLNAK: cpu %d count %lld\n", cpunum, nodeState[cpunum].stats.numNAKs);#endif break; case PI_DP_PUT_RPLY: if (data) { ConvertCritWordFirstToNormal((LL *)data, lclData, (unsigned)(addr & (SCACHE_LINE_SIZE-1))); data = (byte *)lclData; } CacheCmdDone(cpunum, transId, MEMSYS_SHARED, MEMSYS_STATUS_SUCCESS, remoteResult | MEMSYS_RESULT_MEMORY, data); break; case PI_DP_PUTX_RPLY: case PI_DP_ACK_RPLY: if (data) { ConvertCritWordFirstToNormal((LL *)data, lclData, (unsigned)(addr & (SCACHE_LINE_SIZE-1))); data = (byte *)lclData; } CacheCmdDone(cpunum, transId, MEMSYS_EXCLUSIVE, MEMSYS_STATUS_SUCCESS, remoteResult | MEMSYS_RESULT_MEMORY, data); break; case PI_DP_GET_REQ: if (CacheWriteback(cpunum, address, SCACHE_LINE_SIZE, (byte *)lclData)) { *cacheState = DIRTYEX; } else { *cacheState = SHARED; } ConvertNormalToCritWordFirst((LL*)data, lclData, (unsigned)(address & (SCACHE_LINE_SIZE-1))); break; case PI_DP_UNC_NAK_RPLY: if (!nodeState[cpunum].uncachedReadState.active) { CPUError("PI_DP_UNC_NAK_RPLY without active uncached read\n"); } nodeState[cpunum].uncachedReadState.active = FALSE;#ifndef SOLO MipsyNakUncachedOp(cpunum);#endif break; case PI_DP_UNC_ERR_RPLY: if (!nodeState[cpunum].uncachedReadState.active) { CPUError("PI_DP_UNC_ERR_RPLY without active uncached read\n"); } /* xxx isIRef? */#ifndef SOLO MipsyErrUncachedOp(cpunum, nodeState[cpunum].uncachedReadState.addr);#endif break; case PI_DP_UNC_READ_RPLY: if (!nodeState[cpunum].uncachedReadState.active) { CPUError("PI_DP_UNC_READ_RPLY without active uncached read\n"); } bcopy(data, nodeState[cpunum].uncachedReadState.data, nodeState[cpunum].uncachedReadState.size); nodeState[cpunum].uncachedReadState.done = TRUE; MipsyReissueUncachedOp(cpunum); break; case PI_DP_GETX_REQ: if (CacheExtract(cpunum, address, SCACHE_LINE_SIZE, &wasDirty, (char *)lclData)) { if (wasDirty) *cacheState = DIRTYEX; else *cacheState = SHARED; } else { *cacheState = INVAL; } ConvertNormalToCritWordFirst((LL *)data, lclData, (unsigned)(address & (SCACHE_LINE_SIZE-1))); break; case PI_DP_INVAL_REQ: if (CacheInvalidate(cpunum, address, SCACHE_LINE_SIZE, 0, &wasDirty)) { if (wasDirty) *cacheState = DIRTYEX; else *cacheState = SHARED; } else { *cacheState = INVAL; } /* Check for a pending upgrade request to the same line, change it into a GETX if found. */ if (flashPending.active && (flashPending.cpuNum == cpunum) && (flashPending.addr == (address & ~(SCACHE_LINE_SIZE - 1))) && (flashPending.fcmd == PI_PROC_UPGRADE_REQ)) { CPUPrint("MIPSY %lld: UPGRADE changing to GETX on cpu %d addr 0x%x\n", (uint64)CPUVec.CycleCount(cpunum),cpunum,flashPending.addr); flashPending.fcmd = PI_PROC_GETX_REQ; if (flashPending.flavor == PI_UPGRADE_SC) { flashPending.flavor = PI_GET_DATA; } } break; default: printf("Unknown command from MAGIC 0x%x for address %#llx\n", cmd, faddr.ll); }}voidFlashliteStatus(void){ FlashliteDumpStats();}#ifdef notdefstatic char *FlashliteStatus(int cpuNum){ static struct FlashStats oldStats[SIM_MAXCPUS]; static char buf[256]; sprintf(buf, "%lld/%lld/%lld", (nodeState[cpuNum].stats.numGETs - oldStats[cpuNum].numGETs) + (nodeState[cpuNum].stats.numGETXs - oldStats[cpuNum].numGETXs), (nodeState[cpuNum].stats.numWBs - oldStats[cpuNum].numWBs), (nodeState[cpuNum].stats.numNAKs - oldStats[cpuNum].numNAKs)); oldStats[cpuNum] = nodeState[cpuNum].stats; return buf;}#endifstatic void FlashliteDone(void){#ifndef SOLO int i; for (i = 0; i < NUM_CPUS(0); i++) { cpu_finish[i] = MipsyReadTime(0); }#endif FlashEnd();}#define FLASHLITE_DUMPEVERY -1static voidFlashliteDumpStats(void){ static int numCalls = 0; if(++numCalls == FLASHLITE_DUMPEVERY) { FlashDumpStats(); numCalls = 0; }}void FlashliteResetStats(void){ FlashResetStats();}void FlashliteStartCPU(int cpuNum){ cpu_start[cpuNum] = MipsyReadTime(cpuNum);}void FlashliteStopCPU(int cpuNum){ cpu_finish[cpuNum] = MipsyReadTime(cpuNum);}/* * The flash memory system deals with data in critical word first format * as we keep things in normal order. Here are two function for convert * data between the formats.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -