📄 flash_interface.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//* -*-mode:c-*- DO NOT MOVE THIS COMMENT *//* $Id: flash_interface.c,v 1.91 1998/02/10 00:37:08 bosch Exp $ *//***************************************************************** * flash_interface.c * *****************************************************************/#include <stdio.h>#include <time.h>#include <assert.h>#include <stdlib.h>#include "cpu_interface.h"#include "mipsy.h"#include "pcache.h"#include "scache.h"#include "memstat.h"#include "memsys.h"#include "eventcallback.h"#include "cpu_interface.h"#include "cpu_state.h"#include "cp0.h"#include "memory.h"#include "string.h"#include "simutil.h"#include "tcl_init.h"#include "registry.h"#include "machine_defs.h"#include "params.h"#ifdef USE_FLASHLITE#define ERROR FLASHLITE_ERROR#define BIG_ENDIAN#include "simosinterface.h"#include "flash_interface.h"#include "mipsy_interface.h" #include "datafind.h"#ifdef SOLO#include "solo.h"#include "solo_page.h"#else#include "firewallhack.h"#include "simmagic.h"#include "firewall.h"#endif#endif#ifdef HWBCOPY#include "hw_bcopy.h"#endif/* for now just putting these here until there's a better place */#define OSPC_LOADDR_SIMOS (__MAGIC_OSPC_BASE + MAGIC_OSPC_LO_OFFS - K0BASE)#define OSPC_HIADDR_SIMOS (__MAGIC_OSPC_BASE + MAGIC_OSPC_HI_OFFS - K0BASE)#define OSPC_VEC_REQ_ADDR_SIMOS (__MAGIC_OSPC_BASE + MAGIC_OSPC_VEC_REQ_OFFS - K0BASE)#define OSPC_VEC_REP_ADDR_SIMOS (__MAGIC_OSPC_BASE + MAGIC_OSPC_VEC_REP_OFFS - K0BASE)#define OSPC_RANGE_OFFSET(_offset_field_bits) \ ((0x1LL << (_offset_field_bits)) - 0x4000)#define SWS_ZONENUM_BITS 4#define SWS_ZONENUM_OFFSET 24#define SWS_ZONE_FRAMALIAS (0<<SWS_ZONENUM_OFFSET)#define SWS_ZONE_FIREWALL (3<<SWS_ZONENUM_OFFSET)#define SWS_ZONE_FPROMALIAS (15<<SWS_ZONENUM_OFFSET)#define SW_SERVICES_FLAVOR PI_UNC_FLAVOR_A#define PIO_FLAVOR PI_UNC_FLAVOR_Ctypedef enum {PIO_BYTE, PIO_HALF, PIO_WORD, PIO_DWORD} PIOAccessSize;typedef enum {HIVE, FIRST_TOUCH, ROUND_ROBIN, HIVE_ROUND_ROBIN} AddrMapType;#ifdef USE_FLASHLITEstatic AddrMapType addrMap;#ifndef SOLO/* directMapLimit must be >= remap size AND must include any special addresses, which would normally include OSPC addrs, but they are handled separately because they need to be translated to non-coherent get space. Addresses that are less than directMapLimit don't go through Address Map conversion.*/static int directMapLimit;#define IS_DIRECT_MAP(addr) (((addr) & nodeOffsetMask) < directMapLimit)#endif#endif/* * Struct to hold information about a pending memory request -- * this is necessary because FlashAdvanceTime might change the state * of the cache, forcing the outgoing memory request to change. */struct FlashPending { int active; int fcmd; int flavor; int cpuNum; PA addr;} flashPending; /* * Unlike the other memory systems we have, the flashlite memory system * is currently a compile time option triggered by the USE_FLASHLITE * define. If this is not defined we provide stubs so simulator can * link without it. */#ifndef USE_FLASHLITE/***************************************************************** * FlashliteInit *****************************************************************/void FlashliteInit(void){ { extern int LinkSymbolToRetrieveFlashFaultInit; LinkSymbolToRetrieveFlashFaultInit = 1; } CPUError("FlashliteCmd called when compile with !USE_FLASHLITE\n"); return;}void FlashliteInstallTimer(int cpuNum, unsigned int interval, unsigned int timeLeft){}void FlashliteConfigDefaults(void){ }voidFlashliteRaiseSlot(int cpu, int slot){ CPUError("FlashliteRaisedIBit called and USE_FLASHLITE not defined\n");}voidFlashliteClearSlot(int cpu, int slot){ CPUError("FlashliteClearIBit called and USE_FLASHLITE not defined\n");}extern void InitMagicPromalias(char* addr, unsigned nbytes){ CPUError("InitMagicPromalias called and USE_FLASHLITE not defined\n");}extern intFlashliteWQFull(int cpu){ return 0;}#else /* is defined(USE_FLASHLITE) *//* * Since flashlite uses a thread model while SimOS uses a * calback back model we need to keep the two simulated clocks * in synch. This is done by registering a callback when * the next thread wakeup will occur in flashlite. */static LL callbackTime = 0; /* Time of next flashlite event to fire. */static EventCallbackHdr callback;extern bool mipsySyncWhenDone;static void RunFlashlite(int cpuNum, EventCallbackHdr *hdr, void *v);static Result FlashliteCmd(int cpuNum, int cmd, PA addr, int transId, PA replacedPaddr, int writeback, byte *wbData);static void FlashliteStatus(void);static void FlashliteDone(void);static void FlashliteDumpStats(void);static void RetryUncachedOp(int cpuNum, EventCallbackHdr *hdr, void *arg);static void ConvertNormalToCritWordFirst(LL *subBuffer, LL *alignedBuffer, unsigned startAddr);static void ConvertCritWordFirstToNormal(LL *subBuffer, LL *alignedBuffer, unsigned startAddr);static void GetUncachedAddr(int cpuNum, PA vAddr, unsigned long long *p_addr, int *p_flavor);static void SetConsistencyType(int cpuNum, enum ConsistencyType ctype);static void FlashliteDrain(void);#ifndef SOLOstatic void DownloadProtocolState(void);static void DownloadMiscbusState(void);static void DMADone(int nodeNum, void *token, int status);static void InitMagicPromalias(void);extern void MipsyTakeBusError(int cpunum, int isIRef, LL addr);static uint Uncached64To32Bit(unsigned long long addr64);extern void MipsyErrUncachedOp(int cpuNum, uint addr);extern void MipsyNakUncachedOp(int cpuNum);#elsevoidMipsyCacheError(int cpuNum, bool isAsync){ CPUError("Wow! How'd we get a MipsyCacheError with SoloMipsy?. (cpuNum %d, isAsync %u)\n", cpuNum, isAsync);}#endifbool flashliteRunning = FALSE;FILE *mipsy_cpulogF;LL cpu_start_mem[SIM_MAXCPUS];LL cpu_finish_mem[SIM_MAXCPUS];LL *cpu_start = cpu_start_mem;LL *cpu_finish = cpu_finish_mem;static int bytesPerNode_shift; /* supports backmap from FLASH * address to simos address in the * hive layout */static int nodeOffsetMask;/* * State kept on behalf of a flashlite node. */static struct nodeState { /* * In order to correctly handle uncached reads we maintain * the state of outstanding uncached reads in the following * buffer. Note this assumes we have only one outstanding * uncached read per node. */ struct { bool active; /* State structure is inuse */ PA addr; /* Address of uncached read */ int size; /* Size of uncached read */ bool done; /* Flashlite has returned data */ int status; /* 0 if no error, data valid. */ char data[8]; /* Data if returned */ } uncachedReadState; /* * Because of flow control problems we might have to stall an * uncached op. The following callback will unstall us * for a retry. */ EventCallbackHdr retryCallback; /* * Some stats for the node. */ struct FlashStats { long long numGETs; long long numGETXs; long long numUPGRADEs; long long numWBs; long long numNAKs; } stats;} nodeState[SIM_MAXCPUS];/* * In order to run SIMOS requires that all its addresses be remapped into * phyiscal addresses that are valid for flash. The SOLO V_to_P already * handles this remapping for solo. */#ifndef SOLO/* * Do the mappings between Simos and Flash addresses * This mapping currently assumes fewer than 128 CPUs */static signed char *simosPageToNode;#define SimosAddrToMemnum(_addr) \ (simosPageToNode[(_addr)/FLASH_PAGE_SIZE])static int nodeaddrMask;static void InitSimosMemoryMap(void);static unsigned int FlashAddrToSimosAddr(unsigned long long faddr);#define FlashAddrFromAddr(_a,_b) FlashAddrFromSimosAddr((_a),(_b))#define FlashAddrToAddr(_a) FlashAddrToSimosAddr((_a))#endif#ifdef SOLO#define FlashAddrFromAddr(_a,_b) FlashAddrFromSoloAddr((_a),(_b))#define FlashAddrToAddr(_a) FlashAddrToSoloAddr((_a))#endifunsigned FlashAddrCompress(unsigned long long flashAddr){ return((unsigned)(FlashAddrToAddr(flashAddr)));}/***************************************************************** * MemsysInit *****************************************************************/void FlashliteInit(void){ int i; /* * You wouldn't get very far without upgrades or the wrong * cache line size but the error messages generated by * flashlite make it difficult to figure this out so we * explictly check here. */ if (NUM_MACHINES > 1) { CPUError("Flashlite won't run with multiple machines.\n"); } if ((NUM_CPUS(0) == 1) && !UPGRADES_ON_UP) { CPUError("Flashlite won't run without upgrades.\n"); } if (SCACHE_LINE_SIZE != (WORDS_IN_CACHELINE*8)) { CPUError("Flashlite requires SCacheLineSize of 128.\n"); } memsysVec.type = FLASHLITE; memsysVec.NoMemoryDelay = 0; memsysVec.MemsysCmd = FlashliteCmd; memsysVec.MemsysDumpStats = FlashliteDumpStats; memsysVec.MemsysDone = FlashliteDone; memsysVec.MemsysStatus = FlashliteStatus; memsysVec.MemsysDrain = FlashliteDrain; bzero((char *)nodeState, sizeof(nodeState)); callbackTime = 0; mipsy_cpulogF = cpulogF; FlashInitSim(); flashliteRunning = TRUE; mipsySyncWhenDone = TRUE;#ifndef SOLO InitMagicPromalias(); /* run flash forward a bunch of cycles in order to get past its * protocol initialization. This is important so we don't give it * cache misses while it is booting, plus it allows us to update * the firewall, NI registers, etc. from a checkpoint without * worrying about that state being smashed by protocol initialization. */#ifdef notdef { int cycleoffset; ParamLookup(&cycleoffset, "MEMSYS.FLASH.FlashSimosCycleOffset", PARAM_INT); if (cycleoffset == 0) { CPUWarning("\rWARNING: No value specified for FlashSimosCycleOffset\n"); CPUWarning("\rWARNING: Data restored from checkpoint may be overwritten by protocol boot\n"); } else { CPUWarning("\rRunning flashlite forward by %d simos cycles to exec protocol boot\n", cycleoffset); FlashSimosCycleOffset(cycleoffset); FlashAdvanceTime(0); CPUWarning("\rProtocol boot timeout complete, starting SimOS\n"); } }#endif { int cycleoffset; CPUWarning("\rRunning flashlite forward to exec protocol boot\n"); cycleoffset = FlashAdvanceThroughMAGICBoot(); FlashSimosCycleOffset(cycleoffset); CPUWarning("\rProtocol boot complete at cycle %d, starting SimOS\n", cycleoffset); } /* Initialize the address remap and fake firewall * support for flashlite. */ /* Order is important -- JKB */ DownloadMiscbusState(); DownloadProtocolState(); InitSimosMemoryMap(); FlashFlushChangesToVerilogMem(); for (i = 0; i < NUM_CPUS(0); i++) { cpu_start[i] = MipsyReadTime(cpuNum); }#endif { extern int LinkSymbolToRetrieveFlashFaultInit; LinkSymbolToRetrieveFlashFaultInit = 1; }}#ifndef SOLOstatic voidDownloadMiscbusState(void){ /* initialize workermask and workermatch for each cpu * This is a bit of a hack since the OS doesn't set these up * yet -- when we add that functionality we'll have mask/match * values in the checkpoint directly. * * xxx Also: set firewall shift. This is a hack, since we don't * checkpoint this value and the OS cannot be expected to set it * when resuming from a checkpoint. The firewall shift is the number * of positions the node number must be shifted right to get the cell * number, i.e. log2(CPUs/cell). */ { int cpuspercell, i; int numcells = NUM_CELLS(0); int wmask; if (numcells == 0) numcells = 1; cpuspercell = NUM_CPUS(0) / numcells; wmask = ~(cpuspercell - 1); for (i=0; i<NUM_CPUS(0); i++) { FlashSetWorker(i, wmask, i & wmask); FlashSetFWShift(i, GetLog2(cpuspercell)); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -