void check_current_timer_irq(void) { uint8 i=next_expired_timer & 0x1f; // get the timer # viatype *V=(i<9) ? &via[i] : NULL; // get VIA # if it's a via seek_mouse_event(); // ALERT_LOG(0,"Entering check_current_timer_irq. cpu68k_clocks:%016llx timer that expired:%d %s", // cpu68k_clocks,next_expired_timer,gettimername(next_expired_timer)); //printregs(buglog,""); // DEBUG_LOG(0,"Timer #%d expired. Clocks at :%ld\n",next_expired_timer,cpu68k_clocks); // DEBUG_LOG(0,"vertical:%ld(%s)\n cops_event:%ld(%s)\n tenth:%ld(%s)\npc24=%08x\n", // virq_start, (virq_start >cpu68k_clocks ? "Good":"*Lost*"), // cops_event, (cops_event >cpu68k_clocks ? "Good":"*Lost*"), // tenth_sec_cycles, (tenth_sec_cycles>cpu68k_clocks ? "Good":"*Lost*"),pc24 ); // null cycle timer - just allow host ui to get an event, etc. if (!next_expired_timer) {//STAMP("timer=0"); DEBUG_LOG(0,"Waaa! Could not find a timer! cpu68k_clocks:%016llx before get_next_timer_event",cpu68k_clocks); get_next_timer_event(); DEBUG_LOG(0,"Woot! cpu68k_clocks:%016llx after get_next_timer_event. Got %d %s as the next timer.",cpu68k_clocks, next_expired_timer,gettimername(next_expired_timer)); if (cpu68k_clocks < cpu68k_clocks_stop) return; if (!next_expired_timer) {DEBUG_LOG(0,"Got 0, bye."); return;} } if (next_expired_timer>=CYCLE_TIMER_SCC_B_XMT_BUF_EMPTY && next_expired_timer<=CYCLE_TIMER_SCC_A_SPECIAL) { switch(next_expired_timer) { case CYCLE_TIMER_SCC_B_XMT_BUF_EMPTY: break; case CYCLE_TIMER_SCC_B_EXT_STAT_CHG: break; case CYCLE_TIMER_SCC_B_RCVD_CHAR: break; case CYCLE_TIMER_SCC_B_SPECIAL: break; case CYCLE_TIMER_SCC_A_XMT_BUF_EMPTY: break; case CYCLE_TIMER_SCC_A_EXT_STAT_CHG: break; case CYCLE_TIMER_SCC_A_RCVD_CHAR: break; case CYCLE_TIMER_SCC_A_SPECIAL: break; } } if ((next_expired_timer & 0x7f)==CYCLE_TIMER_VERTICAL_RETRACE) // non-via timer such as vertical irq { /* This was wrong. We have 0=entering retrace, 1= vertical off, but still in retrace, 2=display it's 15 lines each for 0,1, and 364 for the rest. 1 video bit = 5ns or 20Mhz. 1 line is 720 bits + h_sync of 11 words. 1 cpu cycle=4 bits. 720 bits = 180 cpu cycles + 11 (16 bit words) + 44 cycles H_SYNC=224 cycles/line 364 lines=81536 cpu cycles for the main display 15 lines 1/2 vsync = 3360 cpu cycles. */ vcount++; if (vcount>2) vcount=0; // 0=normal display, 1=vertical retrace with signal on, 2=vertical retrace, signal off // exiting vertical retrace, entering start of video frame. DEBUG_LOG(0,"Vertical Retrace Phase:%d, VTIR is %d:",vcount,videoirq); switch(vcount) { case 0: { DEBUG_LOG(0,"vertical retrace phase 0"); // if ( (screenrefreshcount=(screenrefreshcount+1) & 0x01)==0 ) LisaScreenRefresh(); // entering refresh cycle, so update screen with changes next_expired_timer=0; get_next_timer_event(); video_scan=cpu68k_clocks; // keep track of where we are virq_start=cpu68k_clocks+FULL_FRAME_CYCLES; return; } // entering vertical retrace, signal IRQ if enabled case 1: { DEBUG_LOG(0,"vertical retrace phase 1, VIDEOIRQ PHASE/ENABLED is:%d",videoirq); virq_start=cpu68k_clocks + VERT_RETRACE_ON; vertical=1; verticallatch=1; if (videoirq & 1) // Interrupt if turned on. {//STAMP("autovector: firing video IRQ\n"); DEBUG_LOG(0,"Firing IRQ1 for vertical retrace"); reg68k_external_autovector(IRQ_VIDEO); // this was wrong - should be EXTERNAL! } else DEBUG_LOG(0,"Not firing IRQ1 for vertical retrace because it's off (videoirq=%d)",videoirq); next_expired_timer=0; get_next_timer_event(); // setup next cycle return; } // exiting vertical retrace, shut vertical retrace signal off case 2 : { DEBUG_LOG(0,"Vertical retrace phase 2"); virq_start=cpu68k_clocks+VERT_RETRACE_CYCLES; vertical=0; // not sure if vertical=0 s/b here! next_expired_timer=0; get_next_timer_event(); // setup next cycle return; } } // this should be unreachable code. next_expired_timer=0; get_next_timer_event(); // setup next cycle return; } // COPS mouse timer if ((next_expired_timer & 0x7f)==CYCLE_TIMER_COPS_MOUSE_IRQ) { // need to be careful with the next line as it calls reg68k_internal vector while *OUTSIDE*!!!! DEBUG_LOG(0," CYCLE_TIMER_COPS_MOUSE_IRQ"); SET_COPS_NEXT_EVENT(0); //DEBUG_LOG(0,"COPS Timer Entered:: cpu68k_clocks:%ld, cops_event:%ld cops_mouse:%d\n",cpu68k_clocks,cops_event,cops_mouse); // Are COPS IRQ's enabled? If so, either mouse timer IRQ's enabled? or was there a keystroke? // then, fire the IRQ. if ( (cops_event>0 || copsqueuelen) ) // 20060609 was (via[1].via[IER] & VIA_IRQ_BIT_CA1) && { DEBUG_LOG(0,"Setting IFR because either of these happened:"); DEBUG_LOG(0,"via[1].via[IER] & CA1 bit:%d", (via[1].via[IER] & VIA_IRQ_BIT_CA1) ); DEBUG_LOG(0,"(cops_event>0 is:%016llx || copsqueuelen is %d)",cops_event,copsqueuelen); via[1].via[IFR] |= VIA_IRQ_BIT_CA1; // DEBUG_LOG(0,"queuing COPS [mouse timed irq:] copsqlen:%d items, %d mouse items. mouse is:%d\n", // copsqueuelen,mousequeuelen,cops_mouse); //20060118-disabled this as it's handled via get_pending_vector! // reg68k_external_autovector(IRQ_COPS); } else DEBUG_LOG(0,"Did not queue IRQ COPS"); //STAMP("timer=0 - setting up next cycle");get_next_timer_event(); // setup next cycle next_expired_timer=0; get_next_timer_event(); return; } if ((next_expired_timer & 0x7f)==CYCLE_TIMER_COPS_CLOCK_DSEC) { // update system clock // might want to find a better place for this, but since 1/10th of a second occurs relatively // rarely compared to the 1/60th sec vertical redraw, it's somewhat better. #ifdef DEBUG #ifdef DEBUG_ON_SCREENHASH if ( cmp_screen_hash(debug_hash,get_screen_hash()) > SCREENHASH_LIMIT && 0==debug_log_enabled) { debug_on("screenhash-met"); debug_log_enabled=1;} #endif #ifdef DEBUG_OFF_SCREENHASH if ( cmp_screen_hash(debug_hash_off,get_screen_hash()) > SCREENHASH_LIMIT && debug_log_enabled) { debug_off(); debug_log_enabled=0; ALERT_LOG(0,"Debug OFf SCREENHASH_OFF Met");} #endif #endif DEBUG_LOG(0,"COPS Decisecond timer entered.\n"); // take care of some other housekeeping too if (floppy_ram[0]) floppy_go6504(); if (scc_running>2) scc_control_loop(); seek_mouse_event(); if (scc_running) scc_control_loop(); next_expired_timer=0; get_next_timer_event(); // lisa can ask COPS to disable the clock. When this is done, don't track time until re-enabled if (!lisa_clock_on) {STAMP("lisa clock is disabled, therefore frozen"); return;} #ifndef USE64BITTIMER if (lasttenth>HALF_CLK) lasttenth=CLKDIV2(lasttenth); #endif if ((lasttenth+TENTH_OF_A_SECOND)>cpu68k_clocks) return; // ensure we're not updating too often. //decisecond_clk_tick(); // handled by lisaem_wx.cpp OnIdle loop //20070409// tenth_sec_cycles =cpu68k_clocks+TENTH_OF_A_SECOND; // schedule next 1/10th second IRQ to fire //ALERT_LOG(0,"1/10th tick. cpu clk:%lld\n",cpu68k_clocks); //printlisatime(buglog); return; } /// Floppy FDIR events ///////////////////////////////////////////////////////////////////////////////////////////////////////// if ((next_expired_timer & 0x7f)==CYCLE_TIMER_FDIR) { DEBUG_LOG(0,"Entering CYCLE_TIMER_FDIR"); next_expired_timer=0; get_next_timer_event(); if (fdir_timer==-1) return; // prevent duplicate IRQ's. fdir_timer=-1; // clear the timer FloppyIRQ_time_up(); if (!floppy_FDIR) //20060605 - then the thing is cleared here! {DEBUG_LOG(0,"floppy_FDIR is not set, so no IRQ to fire."); return;} // was it suppressed already? ignore it. if ( (floppy_irq_top && (floppy_ram[DRIVE] & 0x80)) || (floppy_irq_bottom && (floppy_ram[DRIVE]&0x08)) ) { DEBUG_LOG(0,"Adding AUTOVECTOR FDIR IRQ to queue because FDIR is on"); reg68k_external_autovector(1); } return; } if (next_expired_timer==CYCLE_TIMER_Z8530) { DEBUG_LOG(0,"[zilog8530.c:]Count Zero Interrupt"); z8530_event=-1; z8530_last_irq_status_bits=128; } // Handle VIA related timers from this point on if (!V) return; // if we have an erroneous timer, return; /// Shift register events ////////////////////////////////////////////////////////////////////////////////////////////////////// if (next_expired_timer & 0x40) // shift register { DEBUG_LOG(0,"Handling Shift Register"); flag_via_sr_irq(i); next_expired_timer=0; get_next_timer_event(); return; } /// VIA Timer 1 and Timer 2 Events //////////////////////////////////////////////////////////////////////////////////////////// DEBUG_LOG(0,"Handling timer 1 or 2"); if (next_expired_timer & 0x80) flag_via_t2_irq(i); else flag_via_t1_irq(i); next_expired_timer=0; get_next_timer_event(); return; }
int main() { SshTimeMeasure total_timer; SshTimeMeasure timer_1; SshTimeMeasure timer_2; SshTimeMeasure timer_3; SshTimeMeasure timer_4; SshTimeMeasure timer_5; static struct SshTimeMeasureRec timer_6_rec = SSH_TIME_MEASURE_INITIALIZER; SshTimeMeasure timer_6; int i; double rv = 0.0; int ev = 0; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; #endif /* HAVE_GETTIMEOFDAY */ SshUInt64 seconds; SshUInt32 nanoseconds; total_timer = ssh_time_measure_allocate(); timer_1 = ssh_time_measure_allocate(); timer_2 = ssh_time_measure_allocate(); timer_3 = ssh_time_measure_allocate(); timer_4 = ssh_time_measure_allocate(); timer_5 = ssh_time_measure_allocate(); timer_6 = &timer_6_rec; if (ssh_time_measure_get(timer_5, SSH_TIME_GRANULARITY_NANOSECOND) != 0) { ssh_warning("Weird initial stamp value.\n"); ev++; } if (ssh_time_measure_get(timer_6, SSH_TIME_GRANULARITY_NANOSECOND) != 0) { ssh_warning("Weird initial (static) stamp value.\n"); ev++; } rv = (double)ssh_time_measure_get(total_timer, SSH_TIME_GRANULARITY_SECOND); if ((rv < 0.0) || (rv > 0.0)) { ssh_warning("Weird initial value.\n"); ev++; } ssh_time_measure_granularity(&seconds, &nanoseconds); if ((seconds == 0) && (nanoseconds == 0)) { ssh_warning("Weird granularity.\n"); ev++; } else { printf("granularity is %lu sec %lu nsec\n", (unsigned long)seconds, (unsigned long)nanoseconds); } START(total_timer); START(timer_1); START(timer_3); START(timer_4); START(timer_5); STAMP(total_timer); printf("testing stamps\n"); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(2000000); STAMP(total_timer); SET(timer_5, 12345, 12345678); INTERMEDIATE(timer_5); if ((rv < 12345.0) || (rv > 12350.0)) { ssh_warning("Weird intermediate after running set.\n"); ev++; } INTERMEDIATE(timer_1); if (rv < 1.0) { ssh_warning("Weird intermediate.\n"); ev++; } STOP(timer_3); if (rv < 1.0) { ssh_warning("Weird stop value.\n"); ev++; } START(timer_2); RESET(timer_4); USLEEP(3000000); STAMP(total_timer); INTERMEDIATE(timer_2); INTERMEDIATE(timer_5); START(timer_3); if (rv < 1.0) { ssh_warning("Weird restart value.\n"); ev++; } RESET(timer_4); STOP(timer_1); USLEEP(4000000); STAMP(total_timer); STOP(timer_5); #ifdef SSHUINT64_IS_64BITS printf("Setting timer_5 to big value.\n"); ssh_time_measure_set_value(timer_5, ((SshUInt64)0xffffffff) * ((SshUInt64)30), 987654321); INTERMEDIATE(timer_5); if ((rv < 128849018000.0) || (rv > 128849019000.0)) { ssh_warning("Weird intermediate after stopped set.\n"); ev++; } #else SET(timer_5, 1234567890, 987654321); INTERMEDIATE(timer_5); if ((rv < 1234567890.0) || (rv > 1234567900.0)) { ssh_warning("Weird intermediate after stopped set.\n"); ev++; } #endif STOP(timer_4); STOP(timer_3); STOP(timer_2); STOP(timer_1); #define TIMESTAMPS 1000000 ssh_time_measure_reset(timer_1); ssh_time_measure_reset(timer_2); printf("\nGenerating %d timestamps.\n", TIMESTAMPS); START(timer_2); START(timer_1); for (i = 1; i < TIMESTAMPS; i++) { ssh_time_measure_stamp(timer_2, SSH_TIME_GRANULARITY_MICROSECOND); } STOP(timer_1); STOP(timer_2); printf("Time elapsed %.12f seconds (%.12f seconds/timestamp", (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND), (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) / (double)TIMESTAMPS); if ((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) > 0.0) printf(", %d timestamps/second", (int)((double)TIMESTAMPS / (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND))); printf(")\n"); ssh_time_measure_reset(timer_3); ssh_time_measure_reset(timer_4); printf("\nFor reference generating %d timestamps with time(3).\n", TIMESTAMPS); START(timer_4); START(timer_3); for (i = 1; i < TIMESTAMPS; i++) { ssh_time(); } STOP(timer_3); STOP(timer_4); printf("Time elapsed %.12f seconds (%.12f seconds/timestamp", (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND), (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) / (double)TIMESTAMPS); if ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0) printf(", %d timestamps/second", (int)((double)TIMESTAMPS / (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND))); printf(")\n"); if (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) > 0.0) && ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0)) printf("Using time(3) is %2.1f%% faster than ssh_..._stamp.\n", (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) - (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND)) / (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND)) * 100.0); #ifdef HAVE_GETTIMEOFDAY ssh_time_measure_reset(timer_3); ssh_time_measure_reset(timer_4); printf("\nFor reference generating %d timestamps with gettimeofday.\n", TIMESTAMPS); START(timer_4); START(timer_3); for (i = 1; i < TIMESTAMPS; i++) { gettimeofday(&tv, NULL); } STOP(timer_3); STOP(timer_4); printf("Time elapsed %.12f seconds (%.12f seconds/timestamp", (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND), (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) / (double)TIMESTAMPS); if ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0) printf(", %d timestamps/second", (int)((double)TIMESTAMPS / (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND))); printf(")\n"); if (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) > 0.0) && ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0)) printf("Using gettimeofday(3) is %2.1f%% faster than ssh_..._stamp.\n", (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) - (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND)) / (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND)) * 100.0); #endif /* HAVE_GETTIMEOFDAY */ printf("making start stop test. timers are silently started and stopped.\n"); printf("timer_3 runs while timer_4 is started and stopped in loop.\n"); ssh_time_measure_stop(timer_3); ssh_time_measure_stop(timer_4); ssh_time_measure_reset(timer_3); ssh_time_measure_reset(timer_4); ssh_time_measure_start(timer_3); for (i = 0; i < 1000000; i++) { ssh_time_measure_start(timer_4); ssh_time_measure_stop(timer_4); } ssh_time_measure_stop(timer_3); INTERMEDIATE(timer_4); INTERMEDIATE(timer_3); STOP(total_timer); GET_INT(timer_1); INTERMEDIATE(timer_1); GET_INT(timer_2); INTERMEDIATE(timer_2); GET_INT(timer_3); INTERMEDIATE(timer_3); GET_INT(timer_4); INTERMEDIATE(timer_4); GET_INT(timer_5); INTERMEDIATE(timer_5); GET_INT(total_timer); INTERMEDIATE(total_timer); printf("Testing granularities\n"); GET_NANOSECONDS(total_timer); GET_MICROSECONDS(total_timer); GET_MILLISECONDS(total_timer); GET_SECONDS(total_timer); GET_MINUTES(total_timer); GET_HOURS(total_timer); GET_DAYS(total_timer); GET_WEEKS(total_timer); GET_MONTHS(total_timer); GET_YEARS(total_timer); GET_NANOSECONDS(timer_5); GET_MICROSECONDS(timer_5); GET_MILLISECONDS(timer_5); GET_SECONDS(timer_5); GET_MINUTES(timer_5); GET_HOURS(timer_5); GET_DAYS(timer_5); GET_WEEKS(timer_5); GET_MONTHS(timer_5); GET_MONTHS_2(timer_5); GET_YEARS(timer_5); GET_YEARS_2(timer_5); GET_YEARS_3(timer_5); ssh_time_measure_free(timer_5); ssh_time_measure_free(timer_4); ssh_time_measure_free(timer_3); ssh_time_measure_free(timer_2); ssh_time_measure_free(timer_1); ssh_time_measure_free(total_timer); exit(ev); }