Menu ▾ ▴

#2267 CIA: the first FLAG/SDR interrupt after 5000 quiet cycles can be lost

v3.x
open
None
CIA
29 minutes ago
1 day ago
Mihai
No

Trunk r46303, src/core/ciacore.c.

Problem. ciacore_async_interrupt() moves the idle alarm to rclk + 1 only if (idleclk > rclk + 1). If the idle alarm is already due but has not run yet, it later runs with a clock older than ifr_clock, so ciacore_idle() skips cia_ifr_current() and the new flag raises no interrupt. It is only seen with the next event: two events, one interrupt.

When. Every asynchronous flag pulls the idle alarm close, so only the first flag after CIA_MAX_IDLE_CYCLES (5000) quiet cycles can hit an alarm that is due but has not run (its time fell inside the CPU's last instruction before the event).

Seen with a 1581 counting ATN edges by FLAG interrupt: now and then the first edge after a pause raised no interrupt. Only that case was tested; every ciacore_set_flag() and ciacore_set_sdr() caller shares the path. VIA signals are not affected.

Fix. Reschedule unless the alarm is already set for the next cycle. With it: 8 runs of 60 s clean, which without it failed within seconds.

1 Attachments

Discussion

  • Olaf Seibert

    Olaf Seibert - 1 day ago
    • assigned_to: Olaf Seibert
    • Category: x64sc --> CIA
     
  • Olaf Seibert

    Olaf Seibert - 1 day ago

    That's an interesting patch, thanks!

    I ran all tests from the CIA directory of the testbench and they all still pass. However, since the change affects what happens when a FLAG, CNT or SP input line is set from "the outside", those tests probably don't really test this change.

    Would it be possible to make a small standalone test program, which fails without this patch but succeeds with it? That would be nice to add to the testbench. Although I can imagine that it is hard to make it small and simple...

     
    • Mihai

      Mihai - 21 hours ago

      Thanks for checking! Here's a small standalone test (ciaflag.prg, source for 64tass included). It needs a 1581 on device 8 in true drive emulation:

      x64sc -debugcart -drive8type 1581 -drive8truedrive -autostartprgmode 1 -autostart ciaflag.prg

      It uploads a little routine to the 1581 that counts FLAG interrupts (FLAG is ATN on the 1581) while the drive runs a busy loop with interrupts on. The C64 then sends bursts of 2 ATN pulses with a 5000-10000 cycle pause after each burst, so the first pulse of each burst comes after a long quiet stretch. Each round should count 2000 ($07D0). It runs 16 rounds and writes 0 or $ff to $d7ff, so with -debugcart it exits with 0 (pass) or 255 (fail).

      With r46303 it fails every time I've run it (usually 5-9 interrupts lost). With the patch it passes.

      You're right that it isn't really a CIA-only test, since it needs the drive. It's the simplest way I found to drive FLAG from outside at a random time relative to the drive CPU.

       
      • Olaf Seibert

        Olaf Seibert - 1 hour ago

        Thanks, I am convinced :) I will commit your patch in a moment and credit it to Mihai.
        I will also add the test program to the test program collection. Since the testbench script currently has no way to specify that a 1581 is needed, it won't be run automatically. Yet, anyway.

         
        • gpz

          gpz - 29 minutes ago

          Now it does :) cheers!

           
  • gpz

    gpz - 1 day ago

    Is this related to the unstable parallel speeders perhaps? :)

     

Log in to post a comment.