OVH Cloud OVH Cloud

Emulation et cycle d'horloge

13 réponses
Avatar
pthfndr
Bonjour à tous,



Je veux émuler un Z80 à 5 MHz.
Chaque cycle d'horloge vaut donc 1/5*10**6 seconde soit 0.2
microseconde.
Si je fais "émuler" mon émulateur sans controle , la vitesse équivaut à
un processeur tournant à 20 MHZ ( je cherche l'exactitude en temps, à
disons 10 %
près).
La question est donc de stopper l'émulateur (par un wait ?) le temps
d'un cycle d'horloge (0.2 us) mais en y retranchant la durée qu'a déjà
consommé l'émulation de l'instruction.
Peut-on générer sous windows des durées si courtes (2/10 de us) ?
Je vois cela comme ça :


temps_fin_instruction_en_us = temps_actuel_en_us + temps_de_cycle_en_us
for(;;)
{
while (temps_actuel_en_us < temps_fin_instruction_en_us)
{
;
}
temps_fin_instruction_en_us += temps_de_cycle_en_us ;
traitement du l'instruction simulée
...
}

Mais on doit pouvoir, au lieu du while{;} faire un wait() ou suspend()
et redémarrer le process par un timer, non ?

Merci pour vos conseils et expertises en matière d'émulations et de
temps réel.


Pthfndr.

3 réponses

1 2
Avatar
Mickael Pointier
> Merci à tous, en particulier François Müller et Arnaux Debaene.
Pour ce dernier, je désire simuler à vitesse réelle, d'où la question.



Bein en fait tout dépend de ce que tu veux/peux te contenter:
- Vitesse réelle constante. Typiquement ce qui peut servir à accéder à
un périphérique hardware que tu as branché sur un port d'extension de
ton pc...
- Vitesse réelle ammortie. Faire en sorte que le temps global pris pas
"n" instructions (degré de granularité) soit équivalent à ce qu'aurait
fait un z80 à 5mhz.

Faire le premier est difficile sur un OS qui n'est pas temps réel, le
second est bien plus faisable.


Mike
Avatar
Arnaud Debaene
HalfWolf wrote:
Salut,

Je pense qu'un mélange entre l'utilisation de Sleep et de
QueryPerformanceCounter peut faire l'affaire :

Tu fais Sleep(1) qui correspondra à une attente de la valeur du tick
de windows (de l'ordre de 10ms), tu mesures précisément le temps qui
c'est réellement écoulé pendant le Sleep avec QueryPerformanceCounter
(car d'autres tâches peuvent s'être éxécutées entre temps), à partir
du temps tu en déduis le nombre d'instructions de ton Z80 que tu dois
exécuter, tu les éxécutes et tu revient au Sleep(1).

Un humain ne verra pas la différence, car il verra qu'1 seconde sur le
Z80 fera bien 1 seconde dans son monde.



Bonne idée, mais ca ne marchera que si tu fais des Sleep(1) suffisamment
souveznt pour être sûr que tu ne seras jamais interrompu par le scheduler
quand ton time slice est achevé ... pas évident.
Il y a égalemetn d'autres effets non maîtrisables, comme par exemple les
effets de cache processeur, de swap, qui peuvent modifier du tout au tout le
temps d'exécution d'une "instruction" Z80.

Arnaud
Avatar
halfwolf
Salut,

Je ne vois pas où est le problème d'être préempté pendant l'exécution
des instructions du Z80. Il est vrai que j'ai dit qu'on mesurait le
temps du Sleep(1), il aurait été plus exact de dire que l'on mesurait
le temps mesuré depuis la dernière mesure de ce temps (mais j'avais
peur que ce soit moins clair). De telle sorte, même si on est préempté
pendant l'exécution des instructions du Z80, la fois suivante on
exécutera en plus le nombre d'instructions qui auraient eu lieu
pendant ce temps.

En gros :

Mesure du temps
TANT QUE VRAI
Sleep(1)
Mesure du temps écoulé depuis la dernière mesure
Calcul du nombre d'instructions Z80 à exécuter
Exécution des instructions Z80
FIN TANT QUE

Il faut bien sûr que le temps d'exécution des instructions Z80 ne soit
pas trop grand pour éviter de diverger dans le temps, mais ça ne
devrait pas être un problème, vu l'écart de génération entre un Z80 et
un PC moderne.

HalfWolf

"Arnaud Debaene" wrote in message news:<3f58c45e$0$2784$...
HalfWolf wrote:
> Tu fais Sleep(1) qui correspondra à une attente de la valeur du tick
> de windows (de l'ordre de 10ms), tu mesures précisément le temps qui
> c'est réellement écoulé pendant le Sleep avec QueryPerformanceCounter
> (car d'autres tâches peuvent s'être éxécutées entre temps), à partir
> du temps tu en déduis le nombre d'instructions de ton Z80 que tu dois
> exécuter, tu les éxécutes et tu revient au Sleep(1).

Bonne idée, mais ca ne marchera que si tu fais des Sleep(1) suffisamment
souveznt pour être sûr que tu ne seras jamais interrompu par le scheduler
quand ton time slice est achevé ... pas évident.
Il y a égalemetn d'autres effets non maîtrisables, comme par exemple les
effets de cache processeur, de swap, qui peuvent modifier du tout au tout le
temps d'exécution d'une "instruction" Z80.

Arnaud


1 2