2011-08-19 6 views
5

Planeo crear un emulador Sega Master System en los próximos meses, como un proyecto hobby en Java (sé que no es el mejor lenguaje para esto, pero lo encuentro muy cómodo para trabajar, y como usuario frecuente tanto de Windows como de Linux, pensé que una aplicación multiplataforma sería genial). Mi pregunta se refiere al recuento de ciclos;Pregunta sobre la precisión del recuento cíclico al emular una CPU

He revisado el código fuente de otro emulador Z80, y para otros emuladores también, y en particular, el ciclo de ejecución me intriga: cuando se invoca, se pasa un int como argumento (digamos 1000 como un ejemplo). Ahora entiendo que cada código de operación requiere un número diferente de ciclos para ejecutarse, y que a medida que se ejecutan, el número de ciclos se reduce a partir de la cifra total. Una vez que el número de ciclos restantes es < = 0, el bucle de ejecución finaliza.

Mi pregunta es que muchos de estos emuladores no tienen en cuenta que la última instrucción que se ejecutará puede llevar el número de ciclos a un valor negativo, lo que significa que entre bucles de ejecución uno puede terminar con , Se ejecutan 1002 ciclos en lugar de 1000. ¿Es esto significativo? Algunos emuladores explican esto al compensar el siguiente ciclo de ejecución y otros no, ¿qué enfoque es el mejor? Permítanme ilustrar mi pregunta ya que no soy particularmente bueno en poner a mí mismo a través de:

public void execute(int numOfCycles) 
{ //this is an execution loop method, called with 1000. 
    while (numOfCycles > 0) 
    { 
     instruction = readInstruction(); 
     switch (instruction) 
     { 
     case 0x40: dowhatever, then decrement numOfCycles by 5; 
     break; 
     //lets say for arguments sake this case is executed when numOfCycles is 3. 
     } 
} 

Después del final de este ejemplo particular, looping, numOfCycles estarían en -2. Esto solo será una pequeña inexactitud, pero ¿importa en general en la experiencia de las personas? Apreciaría la comprensión de alguien sobre este. Planeo interrumpir la CPU después de cada fotograma, ya que esto parece apropiado, así que 1000 ciclos es bajo. Lo sé, esto es sólo un ejemplo.

Muchas gracias, Phil

Respuesta

2

era un artículo muy interesante en Arstechnica hablando de simulación de la consola recientemente, también se vincula a un buen número de simuladores que podrían hacer durante bastante buena investigación:

Accuracy takes power: one man's 3GHz quest to build a perfect SNES emulator

El bit relevante es que el autor menciona, y me inclino a estar de acuerdo en que la mayoría de los juegos funcionarán correctamente, incluso con desviaciones de tiempo de +/- 20%. Es probable que el problema que mencionas nunca introduzca más de una fracción de un porcentaje de error de tiempo, que es probablemente imperceptible mientras juegas el juego final. Los autores probablemente no consideraron que vale la pena tratar con.

+0

Gracias :-) Vi este artículo hace unos días y fue una lectura muy interesante. Parece que puedo ignorar este problema: ¡recorté mi trabajo pero debería ser divertido! :-pag – PhilPotter1987

0

supongo que eso depende de cómo es exacto que desea que su emulador que sea. No creo que tenga que ser tan preciso. Piensa en la emulación de la plataforma x86, hay tantas variantes de procesadores y cada uno tiene diferentes latencias de ejecución y tasas de emisión.

+0

Bueno, yo pensaba todo el tiempo que lo ato a la velocidad de fotogramas - 50fps decir si estoy emulando una consola PAL - A continuación, entre esos marcos si ejecuto como sea que haya muchos ciclos, y luego hacer una pausa mientras actualizo la pantalla que debería ser adecuada. Supongo que lo averiguaré :-p Gracias por la respuesta. – PhilPotter1987

4
  1. la mayoría de los emuladores/simuladores de simplemente con tics de reloj de la CPU

    Eso está muy bien para juegos, etc ... Así que tienes alguna temporizador o lo que cada vez y ejecutar la simulación de la CPU hasta que la CPU simular el duración del temporizador Luego duerme hasta que ocurra el siguiente intervalo de temporizador. Esto es muy fácil de simular. puede disminuir el error de tiempo por el enfoque sobre el que está preguntando. Pero como se dice aquí para juegos, esto generalmente es innecesario.

    Este enfoque tiene un inconveniente significativo de y es que su código funciona solo en una fracción de tiempo real. Si el intervalo del temporizador (granularidad de temporización) es lo suficientemente grande, esto puede notarse incluso en los juegos.Por ejemplo, presionas Keyboard Key en el tiempo cuando la emulación duerme y luego no se detecta. (Las teclas a veces no funcionan). Puede remediar esto utilizando una granularidad de temporización más pequeña, pero eso es muy difícil en algunas plataformas. En ese caso, el error de temporización puede ser más "visible" en el software generado Sonido (al menos para las personas que pueden escucharlo y no son sordos a cosas como yo).

  2. si necesita algo más sofisticado

    Por ejemplo, si desea conectar verdadera HW a su emulación/simulación, entonces usted necesita para emular/simular BUS'es. También cosas como bus flotante o contención del sistema son muy difíciles de agregar al enfoque # 1 (es factible pero con mucho dolor).

    Si transfiere los tiempos y la emulación a ciclos de máquina las cosas se pusieron tanto mucho más fácil y de repente cosas como la contención o HW interrumpe, BUS'es flotantes son la solución a sí mismos casi por su cuenta. Transfuse mi emulador ZXSpectrum Z80 a este tipo de sincronización y veo la luz. Muchas cosas se vuelven obvias (como errores en la documentación del código de operación Z80, tiempos, etc.). También la discusión se hizo muy simple a partir de allí (solo unas pocas líneas de código en lugar de horribles tablas de decodificación casi por entrada de tipo de instrucción). La emulación HW también fue bastante fácil. Agregué cosas como los controladores FDC. Emulaciones de chips AY al Z80 de esta manera (no hacks realmente funciona en su código original ... incluso formateo Floppy :)) así que no más TAPE Loading hacks y no funciona para cargadores personalizados como TURBO

    Para hacer esto, creé mi emulación/simulación de Z80 de una manera que utiliza algo así como microcódigo para cada instrucción. Como muy a menudo corregí los errores en Z80 conjunto de instrucciones (ya que no hay ningún 100% de documentos correctos por ahí que sé, incluso si algunos de ellos afirman que están libres de errores y completos) Vengo con una forma de lidiar con sin reprogramar dolorosamente el emulador.

    Cada instrucción se representa mediante una entrada en una tabla, con información sobre el tiempo, los operandos, la funcionalidad ... Conjunto de instrucciones completo es una tabla de todas las entradas de tesis para todas las instrucciones. Luego formé una base de datos MySQL para mi conjunto de instrucciones. y forma tablas similares a cada conjunto de instrucciones que encontré. Luego, comparó dolorosamente a todos ellos seleccionando/reparando lo que está mal y lo que es correcto. El resultado se exporta a un archivo de texto único que se carga al inicio de la emulación. Suena horrible, pero en realidad simplifica mucho las cosas, incluso acelera la emulación, ya que la decodificación de instrucciones ahora solo está accediendo a los punteros.El ejemplo de archivo de datos de conjunto de instrucciones se puede encontrar aquí What's the proper implementation for hardware emulation

Pocos años atrás también publica documento sobre este (por desgracia institución que sostiene que la conferencia ya no existe lo que los servidores están abajo para siempre en esos papeles viejos por suerte todavía tiene una copia) Así que aquí la imagen de ella que describe la problemática:

CPU Scheduling

  • a) throtlle completa tiene ninguna sincronización acaba de velocidad pura
  • b) # 1 tiene grandes lagunas que causan problemas de sincronización HW
  • c) # 2 necesita dormir mucho con muy pequeña granularidad (pueden ser cosas problemáticas y más lento) pero las instrucciones se ejecutan muy cerca su tiempo real ...
  • La línea roja es la velocidad de procesamiento de la CPU del host (obviamente, lo que está encima requiere un poco más de tiempo por lo que debe cortarse e insertarse antes de la siguiente instrucción, pero sería difícil dibujar correctamente)
  • La línea magenta es la velocidad de procesamiento de CPU emulada/simulada
  • alternatin g green/blue colores representan siguiente instrucción
  • ambos son axises tiempo
Cuestiones relacionadas