コード例 #1
0
ファイル: irq.c プロジェクト: rayarachelian/lisaem-1.2.6.2
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;
}
コード例 #2
0
ファイル: t-timemeasure.c プロジェクト: AnthraX1/rk
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);
}