⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 params.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************** * ParamAccess * ----------- * When reading a per-machine param, this function is called just * before reading from the dummy param. We copy the correct value * int the dummy and let the copy proceed. * When writing to a per-machine param, this function is called * just after the dummy param is written to. We copy this value * out to all the machines that are currently active. *****************************************************************/char *ParamAccess(ClientData clientData, Tcl_Interp *interp,            char *name1, char *name2, int flags){   char buf[64];   Tcl_HashEntry *entryPtr;   ParamStruct   *oneParam;   int count;   sprintf(buf, "%s(%s)", name1, name2);   if (!(entryPtr = Tcl_FindHashEntry(&entries, buf))) {      return "unknown parameter accessed";   }     oneParam = (ParamStruct *)Tcl_GetHashValue(entryPtr);   /* If we are reading the values */   if (flags & TCL_TRACE_READS) {      /* We don't want anyone changing variables after they have been          read, so we make them read-only after the first read. Note          that this only protects you in Tcl, not when referencing and          changing the linked variables in C. */      /* A per-machine parameter */      if (oneParam->bitField) {         int totalActive = 0, firstActive = MAX_MACHINES+1;         char *paramPtr;         for (count = 0; count < MAX_MACHINES; count++) {            if (machineParamVec[count]) {               totalActive++;               if (firstActive > count)                  firstActive = count;            }         }         /* If more than one machine is the read source, only allow if we've never modified             this param inside a machine block */         if (totalActive != 1) {            if (oneParam->modifiedPerMachine) {               CPUWarning("PARAM: Must specify machine num when reading %s (since previously set per-machine).\nPARAM: Use '[machine_val machine_num param_name]' to specify.\n",                          oneParam->name);               return "PARAM: ambiguous variable read";            } else               firstActive = 0;         }          if (!IS_INITIALIZED(*oneParam, firstActive)) {            CPUWarning("PARAM: Trying to read uninitialized variable %s (machine %d).\n",                       oneParam->name, firstActive);            return "PARAM: uninitialized variable";         }                  /* Set the value of the dummy */         if (oneParam->type == PARAM_INT) {	   paramPtr = tcl_itoa(*(int*)oneParam->accessFunc(firstActive, buf));         } else if (oneParam->type == PARAM_STRING) {	   paramPtr = SaveString(*((char **)oneParam->accessFunc(firstActive,								 buf)));         } else {          /* Type not currently handled here */            ASSERT (0);	    paramPtr = 0; /* compiler happy */         }         Tcl_SetVar2(interp, name1, name2, paramPtr, TCL_GLOBAL_ONLY);          SET_READONLY(*oneParam, firstActive);      } else {         if (machineScope == MACHINE_VAL) {            CPUWarning("PARAM: Can't use machine_val to read an all-machines param\n");            return "PARAM: incorrect variable read";         }         if (!oneParam->initialized) {            CPUWarning("PARAM: Trying to read uninitialized variable %s.\n",                       oneParam->name);            return "PARAM: uninitialized variable";         }         oneParam->readOnly = TRUE;      }         } else {#ifndef SIM_ALPHA      ASSERT(TclIniting);#endif      /* A per-machine parameter */      if (oneParam->bitField) {         char *paramVal = Tcl_GetVar2(interp, name1, name2, TCL_GLOBAL_ONLY);          for (count = 0; count < MAX_MACHINES; count++) {            if (machineParamVec[count]) {               if (IS_READONLY(*oneParam, count)) {                  CPUWarning("PARAM: Trying to write to %s (machine %d) after it has been read... ABORTING\n",                        oneParam->name, count);                  return "PARAM: writing to accessed var";               } else {                  SET_INITIALIZED(*oneParam, count);               }               /* Copy the value to this machine's param */               if (oneParam->type == PARAM_INT) {                  Tcl_GetInt(interp, paramVal,			     (int*)oneParam->accessFunc(count, buf));               } else if (oneParam->type == PARAM_STRING) {                  *((char **)oneParam->accessFunc(count, buf)) =		                                   SaveString(paramVal);               } else {                  /* Type not currently handled here */                  ASSERT (0);               }            }         }         /* If we modified this in a machine block, set modifiedPerMachine */         if (machineScope != MACHINE_TOP) {            oneParam->modifiedPerMachine = TRUE;         }      } else {         if (machineScope != MACHINE_TOP) {             CPUWarning("PARAM: Trying to modify an all-machines param %s per machine... ABORTING\n",                 oneParam->name);             return "PARAM: illegal modification";          }         if (oneParam->readOnly) {            CPUWarning("PARAM: Trying to write to %s after it has been read... ABORTING\n",                oneParam->name);            return "PARAM: illegal modification";         } else {            oneParam->initialized = TRUE;            if (!strcmp(name2, "CPU.Model")) {               return AccessCPUModel(interp);            }         }      }   }   return NULL;}/* * Calling this function for per-machine params would be a bad idea,  * since only the last accessed value would be returned. However, it * is never used on these params, so there is no problem. */intParamLookup(void *valptr, char *name, int type) {  char *ptr;  char *val = Tcl_GetVar2(TCLInterp, "PARAM", name, TCL_GLOBAL_ONLY);  if (val == NULL) {    return FALSE;  }  switch (type) {  case PARAM_STRING:    *((char **)valptr) = val;    return TRUE;  case PARAM_INT:    return (Tcl_GetInt(TCLInterp, val, (int *)valptr) == TCL_OK);  case PARAM_BOOLEAN:    return (Tcl_GetBoolean(TCLInterp, val, (int *)valptr) == TCL_OK);  case PARAM_DOUBLE:    return (Tcl_GetDouble(TCLInterp, val, (double *)valptr) == TCL_OK);  case PARAM_LL:#if defined(__alpha) || defined(i386)    *((int64 *)valptr) = strtol(val, &ptr, 0);#else    *((int64 *)valptr) = strtoll(val, &ptr, 0);#endif    return (ptr != val);  default:    break;  }      return FALSE;}/***************************************************************** * ParamGrabbed * * Almost all parameters return FALSE for this, so will require * initialization by the init.simos and follow-on scripts. * *****************************************************************/static intParamGrabbed(char* varName){   int i;   for (i=0; i<numgrabbed; i++) {      if (!strcmp(varName, grabbedParams[i]))          return TRUE;   }   return FALSE;}/***************************************************************** * ParamGrabbedAtStartup * * Called by simcpt.c to record its dirty deed.  Note that * this is called *before* tclinit so we can't rely on anything * from the tcl library. * NOTE: This specifies that the param has been grabbed for _all_ * machines, since when restoring from checkpoint, values must * have been set for all machines. *****************************************************************/voidParamGrabbedAtStartup(char* varName){   ASSERT(numgrabbed < MAXGRABBED);   grabbedParams[numgrabbed++] = varName;}/***************************************************************** * MachineSettingsComplete * * This procedure has two purposes: *   Ensure that all variables have had a default value assigned  *      to them  *   Compute the derived fields from the "specified" values *****************************************************************/voidMachineSettingsComplete(void){   int i, machNo, cpuCount, memoryCount;   int consoleCount, etherCount, clockCount;   bool badParamExists = FALSE;   Tcl_HashEntry *entryPtr;   ParamStruct *oneParam;   /*    * Find the value of PARAM(MACHINE.Count) so that we know how many machines    * to check for completion on.    */   if (!(entryPtr = Tcl_FindHashEntry(&entries, "PARAM(MACHINE.Count)"))) {      /* It should exist, so if not we will assert fail */      ASSERT(0);   }   oneParam = (ParamStruct *)Tcl_GetHashValue(entryPtr);   ASSERT(oneParam);   if (!oneParam->initialized) {      CPUWarning("PARAM: PARAM(MACHINE.Count) has not been initialized. Assuming 1 machine.\n");      oneParam->initialized = TRUE;      NUM_MACHINES = 1;   }   if (NUM_MACHINES < 1 || NUM_MACHINES > MAX_MACHINES) {      CPUWarning("Number of machines (%d) is out of legal range of %d to %d.\n",                 NUM_MACHINES, 1, MAX_MACHINES);      ASSERT(0);   }#ifndef SOLO   /*    * Ensure that if we have more than one machine, that each machine is just    * one cell. i.e If we have multiple machines, then each is just one cell,    * and if we have multiple cells, then we only have one machine.    */   inCellMode = 0;   if (NUM_MACHINES > 1) {      for (machNo = 0; machNo < NUM_MACHINES; machNo++) {         if (machines.machine[machNo].NumCells > 1) {            CPUWarning("Can't have a machine with more than one cell when using multiple machines");            ASSERT(0);         }      }   } else {      if (machines.machine[0].NumCells > 1) {         inCellMode = 1;         ASSERT(NUM_CONSOLES(0) == NUM_CELLS(0));         ASSERT(NUM_ETHER_CONTROLLERS(0) == NUM_CELLS(0));         ASSERT(NUM_CLOCKS(0) == NUM_CELLS(0));      }   }#endif   /*     * Check for any uninitialized parameters. I could also do this    * within the Tcl access functions, but then I would miss the case     * where C was accessing an uninitialized variable.    */   for (i=0; i< paramCount; i++) {      if (param[i].bitField) {         for (machNo = 0; machNo < NUM_MACHINES; machNo++) {              if (!IS_INITIALIZED(param[i], machNo)) {                 CPUWarning("PARAM: %s (machine %d) has not been initialized\n",                            param[i].name, machNo);                 badParamExists = TRUE;             }         }      } else {         if (!param[i].initialized) {            CPUWarning("PARAM %s has not been initialized\n",                       param[i].name);            badParamExists = TRUE;         }      }   }   if (badParamExists) {       ASSERT(0);   }   /*     * Compute all of the derived parameter fields     */   MAX_CPUS_PER_MACHINE = 0;   MAX_CONSOLES_PER_MACHINE = 0;   MAX_ETHER_CONTROLLERS_PER_MACHINE = 0;   MAX_CLOCKS_PER_MACHINE = 0;   /* Find the total number of CPUS for allocating mapping vector */   for (machNo = 0, cpuCount = 0; machNo < NUM_MACHINES; machNo++) {       cpuCount += NUM_CPUS(machNo);   }   /* Allocate memory for cpu to machine mapping array */   MachineFromCPU = (int*) calloc(SIM_MAXCPUS /* XXX cpuCount XXX */,				  sizeof(int));   for (machNo = 0, cpuCount = 0, memoryCount = 0, consoleCount = 0,            etherCount = 0, clockCount = 0 ;        machNo < NUM_MACHINES; machNo++) {       machines.machine[machNo].MemSize =           machines.machine[machNo].MemSizeSpecified*1024*1024;      FIRST_CPU(machNo) = cpuCount;      for (i = 0; i < NUM_CPUS(machNo); cpuCount++, i++) {          MachineFromCPU[cpuCount] = machNo;      }      LAST_CPU(machNo) = cpuCount-1;      if (NUM_CPUS(machNo) > MAX_CPUS_PER_MACHINE)         MAX_CPUS_PER_MACHINE = NUM_CPUS(machNo);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -