📄 simos_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. * *//***************************************************************** * simos_interface.c - SimOS interface to the HP disk simulator. * Always runs on thread 0. * * $Author: bosch $ * $Date: 1998/02/10 00:36:50 $ *****************************************************************/#include "sim.h"#include "simtypes.h"#include "simos_interface.h"#include "diskdevice.h"#include "diskdevices.h"#include "modularize.h"#include "queue.h"#include "eventcallback.h"#include "hd.h"#include "cpu_interface.h"#include "heap.h"#include "simutil.h"#include "sim_error.h"#include "machine_params.h"Heap heap; /* the event heap */double diskTICSperMSEC;typedef struct DiskModelCallback{ EventCallbackHdr hdr; /* Event header of the callback */ int diskNum; int sector; int nsectors; int iswrite; dmaRoutine_t dmaRoutine; void *dmaArg; doneRoutine_t doneRoutine; int doneArg;} DiskModelCallback;DiskModelCallback *diskModelCallback;EventCallbackHdr *diskModelEhdr;#define BQSIZE 15 /* size of bus queue */ /* * DiskModelInit - Initialize the HP disk model. We allow the user to * specify the MAX number of disks being models and * how the time of the disk model should be scaled. * A scaling factor of 1.0 gives realistic timings. */voidDiskModelInit(int maxNumDisks, double scaling){ int diskNum; int *busOwner; NCQUEUE *busWaitq; if (scaling == 0) { CPUError("HD: Can't run HP disk at scaling of 0... use fixed model.\n"); } /* diskTICSperMSEC = (scaling*1000.0*1000.0)/(double)simConfigNsecPerInstr; */ SIMASSERT( CPU_CLOCK ); diskTICSperMSEC = (scaling * 1000.0 * CPU_CLOCK) ; InitTime(); /* initialize the global clock */ busOwner = (int *) MALLOC(sizeof(int),"busOwner"); *busOwner = BUS_FREE; busWaitq = MakeQueue_noncyc(BQSIZE, "bus queue"); for (diskNum = 0; diskNum < maxNumDisks; diskNum++) { DiskDeviceInit(diskNum, diskNum, busOwner, busWaitq, NULL); } /* Currently we model each disk as having its own SCSI bus. */ diskModelEhdr = (EventCallbackHdr *) ZMALLOC(sizeof(EventCallbackHdr),"DiskModelEHdr"); diskModelCallback = (DiskModelCallback *) ZMALLOC(sizeof(DiskModelCallback)*SIM_MAX_DISKS, "DiskModelCallback"); ASSERT( diskModelCallback );} /* * DiskModelRequest - Start the modeling of a DISK request. We allow the user * to provide routines to handle the data as it comes over * the SCSI bus (dmaRoutine) and the compleition response * (doneroutine). * Because we do not want to have to deal with shared memory in MP embra, * we run all of the disk model requests on CPU 0. The DMA module is shared * memory mapped. The final callback interrupts the CPU that requested the * transfer in the first place */static void DiskModelStartCallback(int cpuNum,EventCallbackHdr *hdr,void *arg){ TICS begintime = CPUVec.CycleCount(0); DiskModelCallback *cback = (DiskModelCallback *)hdr; /* * Advance the simulator's time to the current time and launch the request. */ WaitTime(begintime); DiskDeviceTransferStart(cback->diskNum, cback->sector, cback->nsectors, cback->iswrite, cback->dmaRoutine, cback->dmaArg, cback->doneRoutine, cback->doneArg); }voidDiskModelRequest(int machine, int diskNum, int sector, int nsectors, int iswrite, dmaRoutine_t dmaRoutine, doneRoutine_t doneRoutine, int doneArg){ DiskModelCallback *cback = diskModelCallback+diskNum; ASSERT( diskModelCallback ); /* get all of the parameter in the callback. Have it handled by CPU 0 of the machine */ cback->diskNum = diskNum; cback->sector = sector; cback->nsectors = nsectors; cback->iswrite = iswrite; cback->dmaRoutine = dmaRoutine; cback->doneRoutine = doneRoutine; cback->doneArg = doneArg; /* pass over message to CPU 0 of the machine */ EventDoCallback(FIRST_CPU(machine), DiskModelStartCallback, (EventCallbackHdr *)cback,0,0);}/* * The following code and data interfaces the event callback mechanism of * the disk model with the simos Eventcallback mod. This is done by * recording a EventCallback that corresponds to the ROOT of the callback * Heap maintained by the disk simulator. */static void RecordCallback(int cpuNum,EventCallbackHdr *ptr, void *arg);static TICS lastregtime; /* Time of registered callback */voidUpdateEventCallback(TICS tics){ TICS regtime = tics+1; if (!EventCallbackActive(diskModelEhdr)) { /* If we don't have a callback registers - set one. */ SimTime time = CPUVec.CycleCount(0); if (time >= regtime) { /* This can happen in Embra because the callbacks can be delayed. */ regtime = time+1; } EventDoCallback(FIRST_CPU(M_FROM_CPU(diskModelEhdr->cpuNum)), RecordCallback,diskModelEhdr, (void *) 0, regtime - time); lastregtime = regtime; } else { SimTime time = CPUVec.CycleCount(0); if (time >= regtime) { /* This can happen in Embra because the callbacks can be delayed. */ regtime = time+1; } if (regtime < lastregtime) { /* If we have one register's too far in the future - Update it. */ EventCallbackUpdate(diskModelEhdr,regtime); lastregtime = regtime; } else { /* Update wasn't to the root of the heap */ } }}static voidRecordCallback(int cpuNum,EventCallbackHdr *ptr, void *arg){ HeapKey Hpkey; HeapData Hpdat; TICS current_time = CPUVec.CycleCount(0); /* * Update the disk's simulated time to the current time and * re-register the top of the heap if needed. */ WaitTime(current_time); if (TopHeap(heap, &Hpdat, &Hpkey) != FALSE) { UpdateEventCallback(Hpkey); }}voidAdvanceTime(void){ TICS begintime = CPUVec.CycleCount(0); WaitTime(begintime); /* Update simulators time */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -