Question about 68k cpu

Technical discussion for those interested in Supermodel development and Model 3 reverse engineering. Prospective contributors welcome.
Forum rules
Keep it classy!

  • No ROM requests or links.
  • Do not ask to be a play tester.
  • Do not ask about release dates.
  • No drama!

Question about 68k cpu

Postby Spindizzi » Tue Apr 04, 2017 9:17 am

Hi,
Just a little technical question about 68k cpu
I Would like to know if musashi 68k in supermodel with its 68k interface, support multiple cpu ?
Every time I create a new 68k cpu, it's accessed the soundboard instead the new one (with different context of course). The PC (of the new created one) moved while I'm not running the new cpu. And the init completely breaks the soundboard. Furthermore, I can't see the new cpu in the supermodel debugger

Is that the reason ?
-> Caution: 68K emulator is not thread-safe (68k.h).
-> only a single CPU is supported (68k.cpp)
but Soundboard is a 68k and dsb2 is also a 68k, so already 2 cpus...

I certainly forget something important...
++
Spindizzi
 
Posts: 196
Joined: Thu Nov 17, 2016 8:55 am
Location: France

Re: Question about 68k cpu

Postby Bart » Tue Apr 04, 2017 9:25 am

The 68K and PowerPC cores are definitely not thread-safe (the Z80 is).

When Supermodel needs to run 2 68Ks (sound board and DSB2), they are run in the same thread and the context is switched between them manually using M68KSetContext()/M68KGetContext(). This is how it was done in the old days when emulators were written by pimply-faced teenagers and 20-somethings like me on single core PCs :)

Musashi would have to be heavily modified to be thread-safe. The CPU emulator should be defined as a class. Every instruction handler should be either a member function of that class or should accept a context parameter. It's a lot of work but doable if you're careful. Before embarking on such a project, either email me directly or let's discuss here. This is something that should be handled very carefully.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Question about 68k cpu

Postby Ian » Tue Apr 04, 2017 9:29 am

the z80 code has an interesting compile warning in visual studio that might be worth a look at

It's this ..

AF = (-(AF & 0xff00) & 0xff00);
z80.cpp(2480): warning C4146: unary minus operator applied to unsigned type, result still unsigned
Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Question about 68k cpu

Postby Bart » Tue Apr 04, 2017 9:32 am

Here's more detail about how it works. Look carefully at SoundBoard.cpp:

Code: Select all
// SCSP callback for running the 68K
int SCSP68KRunCallback(int numCycles)
{
   return M68KRun(numCycles) - numCycles;
}

...

bool CSoundBoard::RunFrame(void)
{
   // Run sound board first to generate SCSP audio
   if (m_config["EmulateSound"].ValueAs<bool>())
   {
      M68KSetContext(&M68K);
      SCSP_Update();
      M68KGetContext(&M68K);
   }
   else
   {
      memset(audioL, 0, 44100/60*sizeof(INT16));
      memset(audioR, 0, 44100/60*sizeof(INT16));
   }
   
   // Run DSB and mix with existing audio
   if (NULL != DSB)
      DSB->RunFrame(audioL, audioR);


ElSemi's SCSP emulator makes this even grosser than it needs to be. It actually runs the 68K emulation (!) from inside SCSP_Update() by calling a callback (SCSP68KRunCallback).

Beginning at CSoundBoard::RunFrame(), you can see that we first set the global 68K context (all the 68K emulation state variables: registers and memory pointers). Then we run SCSP_Update(), which will in turn run the 68K. I think it runs the 68K itself in order to generate IRQs at specific times (the timing of which is broken, but never mind for now).

After it has emulated one frame, it copies back the context using M68KGetContext() and then calls the DSB RunFrame function, which for DSB2 will be CDSB2::RunFrame():

Code: Select all
void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
{
   if (!m_config["EmulateDSB"].ValueAs<bool>())
   {
      // DSB code applies SCSP volume, too, so we must still mix
      memset(mpegL, 0, (32000/60+2)*sizeof(INT16));
      memset(mpegR, 0, (32000/60+2)*sizeof(INT16));
      retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, volume[0], volume[1], 44100/60, 32000/60+2, 44100, 32000);
      return;
   }

   M68KSetContext(&M68K);
   //printf("DSB2 run frame PC=%06X\n", M68KGetPC());
   
   // While FIFO not empty...
   while (fifoIdxR != fifoIdxW)
   {
      cmdLatch = fifo[fifoIdxR];   // retrieve next command byte
      fifoIdxR++;
      fifoIdxR &= 127;   
      
      M68KSetIRQ(1);   // indicate pending command
      //printf("68K INT fired\n");
      M68KRun(500);
   }   

   // Per-frame interrupt
   M68KSetIRQ(2);
   M68KRun(4000000/60);
   
   M68KGetContext(&M68K);
   
   // Decode MPEG for this frame
   INT16 *mpegFill[2] = { &mpegL[retainedSamples], &mpegR[retainedSamples] };
   MPEG_Decode(mpegFill, 32000/60-retainedSamples+2);
   retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, volume[0], volume[1], 44100/60, 32000/60+2, 44100, 32000);
}


Here you can see that the DSB2's context is copied in, the 68K is executed, and then the context is read back.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Question about 68k cpu

Postby Bart » Tue Apr 04, 2017 9:35 am

Ian wrote:the z80 code has an interesting compile warning in visual studio that might be worth a look at

It's this ..

AF = (-(AF & 0xff00) & 0xff00);
z80.cpp(2480): warning C4146: unary minus operator applied to unsigned type, result still unsigned


I think that's fine. A two's complement inversion is desired. I can fix this warning later (I think I'll do more extensive code cleanup after the release). Need to be very careful. If AF is uint16_t, it could probably be made: uint16_t(-int16_t(AF & 0xff00)) & 0xff00; but I would want to run a little sanity check to be absolutely sure.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Question about 68k cpu

Postby Bart » Tue Apr 04, 2017 9:40 am

Actually, to be more precise: the 68K and PowerPC code are not only non-thread-safe, they are also non-reentrant and stateful, both storing their execution context in global variables. You must maintain separate contexts and swap them in/out as needed and even with that, you cannot run them in different threads. This is standard practice in non-object-oriented CPU cores (e.g., Starscream 68K, Neil Bradley's cores, etc., etc.).
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Question about 68k cpu

Postby Spindizzi » Wed Apr 05, 2017 12:40 am

Hello,
Many thanks for your time to answer to me, and the amount of infos
The only thing I've done was to create a thread with a new 68k cpu and switching context when needed (init, reset, run). As you've said, that is impossible in this state due to the globals variables context. This is why I can't access the new cpu but only the sound board cpu <- It takes me time to understand what's really cooking!
Sadly, I'm not good enough in programming to rewrite a thread safe cpu emulator
May be the only "simple" solution would be to use turbo68k (or other) instead of Musashi to launch another 68k cpu that not be overlaped by existant ones
++
Spindizzi
 
Posts: 196
Joined: Thu Nov 17, 2016 8:55 am
Location: France

Re: Question about 68k cpu

Postby Bart » Wed Apr 05, 2017 6:33 am

Why are you trying to create another 68K? Using Turbo68K is not a good solution and I'm thinking of removing it from the project altogether. It only works on x86 (not x64). Unless you're really pushing the limits of system performance, you should be able to emulate three 68Ks in a single thread similar to how I have hooked up two. Just call yours after the soundboard and DSB are finished.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Question about 68k cpu

Postby Spindizzi » Thu Apr 06, 2017 12:55 am

Hi,
I just want to try to make a squeleton for the netboard (I lack of knowledge, so I'll never go any further)
For now I've got the 68k microcode downloading from the games (pointers to ram and 68k prog) I even see in the ram, the vectors to boot (I think). But of course I'm stuck here because of the netboard 68k cpu is overlapped by the 68k cpu soundboard.
Bart wrote:you should be able to emulate three 68Ks in a single thread similar to how I have hooked up two. Just call yours after the soundboard and DSB are finished.

You mean I should use the soundboard thread to create the new cpu instead of a new thread ?
++
Spindizzi
 
Posts: 196
Joined: Thu Nov 17, 2016 8:55 am
Location: France

Re: Question about 68k cpu

Postby Bart » Thu Apr 06, 2017 7:42 am

Ah. I understand.

You'll need pretty tight synchronization between the PowerPC and the network board, at least initially until the protocol can be deduced and implemented with a high-level emulation (which may or may not be possible, and may be game-specific). Therefore, you need to run the 68K in the main CPU thread. Initially, you can get away with this by simply disabling audio emulation in your builds when running the network board 68K. It's a quick and dirty hack until Musashi is made thread-safe.

I forget exactly how Nik did it. If Musashi has an option to generate an identifier prefix (some CPU emulators support this), he may have even generated a second 68K to do this.

For the time being, my recommendation is to run this 68K from the main thread and simply ensure "-no-sound" and "-no-dsb" are always forced on in your dev build. You're not going to care about sound initially :)
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Next

Return to The Dark Room

Who is online

Users browsing this forum: No registered users and 1 guest