📄 clock.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. * */ /**************************************************************** * clock.c * * $Author: bosch $ * $Date: 1998/02/10 00:30:15 $ *****************************************************************/#include <stdio.h>#include <string.h>#include "simmisc.h"#include "checkpoint.h"#include "simmagic.h"#include "sips.h"#include "eventcallback.h"#include "simutil.h"#include "embra.h"#include "cp0.h"#include "clock.h"#include "main_run.h"#include "mem_control.h"#include "stats.h"#include "callout.h"#include "translator.h"#include "debug.h"#include "driver.h"#include "hw_events.h"#include "embra_interface.h"/* ********************************************************************** * All of the clock shared state is in shared memory. All of the callbacks * must be in shared memory, event non IPI as the callbacks themselves are * queued. * **********************************************************************/#define MAX_INTERRUPT_CALLBACKS (16*SIM_MAXCPUS)typedef struct ClockSharedState { EventCallbackHdr interrupts[MAX_INTERRUPT_CALLBACKS]; int rotor; int lock; EventCallbackHdr pcSampling[SIM_MAXCPUS]; EventCallbackHdr periodicCallback[SIM_MAXCPUS]; EventCallbackHdr periodicAnnotationCallback; EventCallbackHdr statCallback[SIM_MAXCPUS]; EventCallbackHdr bootCallback; EventCallbackHdr exitCallback;} ClockSharedState;extern K0A non_excepting_tv( int cpuNum, VA va );static ClockSharedState *clockState;/* Local Data */static int pc_sample_interval = 256;int callout_interval = 0;/* Local Functions */static void InitPeriodicCallbacks(int cpu);static void StatCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static void PeriodicCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static void PeriodicAnnotationCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static void BootCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static SimTime next_PCSample;static void InitPeriodicCallbacks(int cpu){ ASSERT (cpu==0); if (embra.stats) { EventDoCallback(cpu,StatCallback, &clockState->statCallback[cpu],0, embra.statInterval); } EventDoCallback(cpu,PeriodicCallback, &clockState->periodicCallback[cpu],0, embra.miscCheckInterval); if (cpu == 0) { EventDoCallback(0,PeriodicAnnotationCallback, &clockState->periodicAnnotationCallback,0, embra.periodicAnnInterval); }}void EmbraClosePeriodicCallbacks(void){ int cpu = 0; if (EventCallbackActive(&clockState->statCallback[cpu])) { EventCallbackRemove(&clockState->statCallback[cpu]); } if (EventCallbackActive(&clockState->periodicCallback[cpu])) { EventCallbackRemove(&clockState->periodicCallback[cpu]); } if (EventCallbackActive(&clockState->periodicAnnotationCallback)) { EventCallbackRemove(&clockState->periodicAnnotationCallback); }}voidEmbra_Clock_Init(int cpuNum){ /* * allow fast check from assembly */ callout_interval = embra.timeQuantum; if( embra.MPinUP ) { int i; EMP[TOTAL_CPUS].eventQueueTimePtr = SingleEventQueueCalltimeAddr; for( i = 0; i <= TOTAL_CPUS; i++) { EMP[i].timeQuantum = embra.timeQuantum; EMP[i].cycleCountdown = EMP[i].timeQuantum; } InitPeriodicCallbacks(0); } else { ASSERT (!cpuNum); ASSERT( TOTAL_CPUS ==1); EMP[0].eventQueueTimePtr = SingleEventQueueCalltimeAddr; EMP[0].timeQuantum = embra.timeQuantum; EMP[cpuNum].cycleCountdown = embra.timeQuantum; InitPeriodicCallbacks(cpuNum); }}intUpdate_And_Check_Interrupts( int cpuNum , VA targetPC){ /*CPUWarning("CPU %d Update and Check HW 0x%x\n ", cpuNum, EMP[cpuNum].intrBitsPtr[0] ); */ /* Update and check for interrupts */ EMP[cpuNum].CP0[C0_CAUSE] = (EMP[cpuNum].CP0[C0_CAUSE] & ~CAUSE_EXTINTBITS) | ((EMP[cpuNum].intrBitsPtr[0] << CAUSE_IPSHIFT) & CAUSE_EXTINTBITS); if (((EMP[cpuNum].CP0[C0_CAUSE] & EMP[cpuNum].CP0[C0_SR]) & SR_IMASK) && (EMP[cpuNum].CP0[C0_SR] & SR_IEC) && !((EMP[cpuNum].CP0[C0_SR] & (SR_EXL|SR_ERL)))) { /* Processors generally take excpetions in between instructions */ /* so when we are stalled for a cache miss (or whatever), delay */ /* excpetion (interrupt) detection */ if( !EMP[cpuNum].stalled ) { if (targetPC) { ASSERT (!IN_BD(targetPC)); ASSERT (IS_KSEG0(targetPC) || IS_KUSEG(targetPC)); /* * now is the time to field the post-pc annotation, * since we are skipping the instruction by smashing * the PC. */ ASSERT (cpuNum==curEmp->myNum); AnnExec(AnnFMLookup(CLEAR_BD(EMP[cpuNum].PC),ANNFM_PC_TYPE)); EMP[cpuNum].PC = targetPC; } Em_EXCEPTION(cpuNum,EXC_INT,0); EmbraSideEffect(); return 1; } } return 0;}void EmIntrBitsChanged(int cpuNum){ Update_And_Check_Interrupts(cpuNum,0);}/* Do Interrupt Now (only takes exception if interrupt is enabled) */static void EmbraInterruptCallback(int cpuNum, EventCallbackHdr *hdr, void *arg){ IEC intrtoset = (IEC) (int) arg; /* keep compiler quiet by casting thru int */ SIM_DEBUG(('i',"DEV %d %lld Send 0x%x ", cpuNum, EmbraCpuCycleCount(cpuNum), intrtoset)); RaiseIBit(cpuNum, intrtoset); SIM_DEBUG(('i', "Ibits 0x%x\n", EMP[cpuNum].intrBitsPtr[0])); Update_And_Check_Interrupts( cpuNum,0 );}/* Do deliver SIPS Now */static void EmbraDeliverSIPSCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){ sim_sips_deliver(cpuNum, (int)arg /* chan */); Update_And_Check_Interrupts( cpuNum ,0);}/* Do Interrupt Now (only takes exception if interrupt is enabled) */static void BootCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){ int cpu; for( cpu = 1; cpu < TOTAL_CPUS; cpu++ ) { uint launchAddr = (uint)sim_misc.launchAddr[cpu]; if( launchAddr ) { /* XXX - non-backdoor address is launch, backdoor address is call */ if( IS_BACKDOOR(launchAddr) ) { int64 result; /* Do call */ result = ((int64 (*)(int,int,int,int))launchAddr) ( sim_misc.launchArg[cpu][0], sim_misc.launchArg[cpu][1], sim_misc.launchArg[cpu][2], sim_misc.launchArg[cpu][3] ); if( result == SLAVELOOP_CONTINUE ) { /* signal init function done */ sim_misc.launchAddr[cpu] = 0; /* clear so will be 0 if not set up on next call */ sim_misc.launchArg[cpu][0] = 0; sim_misc.launchArg[cpu][1] = 0; sim_misc.launchArg[cpu][2] = 0; sim_misc.launchArg[cpu][3] = 0; CPUPut("Slave %d returning to launch wait\n",cpu ); } } else { /* Add everybody in & let mem_control handle launch */ int i; for( i = 0; i <= TOTAL_CPUS; i++ ) { EMP[i].next = &EMP[(i+1)%(TOTAL_CPUS+1)]; } /* for */ /* Don't reinstall callback */ return; } } } EventDoCallback(cpuNum,BootCallback,hdr,0,embra.timeQuantum);}void Embra_Send_Interrupt( int cpuNum, IEC intrtoset, SimTime delay ){ int count = 0; EventCallbackHdr *event; if( delay == 0 ) { /* SIMLOCK();*/ RaiseIBit(cpuNum, intrtoset); /* SIMUNLOCK();*/ Update_And_Check_Interrupts( cpuNum,0 ); } else { clockState->rotor = (clockState->rotor+1)%MAX_INTERRUPT_CALLBACKS; while( EventCallbackActive(&clockState->interrupts[clockState->rotor]) ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -