Как придать эмуляции нужную скорость?

Я хочу написать эмулятор для особенно медленного процессора, работающего на частоте 600 или около того килогерц. Если бы я написал эмулятор процессора наивным способом (т.е. эмулируя одну инструкцию за раз без каких-либо других действий), эмуляция была бы намного быстрее, чем 600 кГц.

Как запрограммировать эмулятор для эмуляции ЦП с правильной скоростью, независимо от скорости хоста? Какой метод обычно используется для этого в реальных эмуляторах? Как избежать дрожания, замедляющего эмуляцию?


person fuz    schedule 13.09.2014    source источник
comment
О каком именно эмуляторе идет речь? qemu, ПЛИС и т. д.? Я имею в виду, какую среду программирования вы собираетесь использовать для этого эмулятора?   -  person Sam Protsenko    schedule 11.04.2015
comment
Типичный метод (использование медленного таймера для эмуляции 6000 циклов десять раз в секунду) работает только в среднем и имеет много джиттера, поэтому я предполагаю, что здесь он недостаточно хорош?   -  person harold    schedule 11.04.2015
comment
@SamProtsenko Мой конкретный вариант использования — написать эмулятор для 8-битного процессора (например, домашнего компьютера), который работает в операционной системе POSIX.   -  person fuz    schedule 11.04.2015
comment
@harold Я не уверен, что такое стандартная техника, и исследования не выявили ничего интересного. Не могли бы вы уточнить стандартную технику в ответе, чтобы я мог проголосовать за нее и, возможно, присудить награду?   -  person fuz    schedule 11.04.2015
comment
@FUZxxl, так что это будет просто ваше собственное приложение в пользовательском пространстве, написанное на C и использующее POSIX API, верно? Какую ОС вы собираетесь использовать (например, Linux, FreeBSD)? А также какая версия ядра?   -  person Sam Protsenko    schedule 11.04.2015
comment
@SamProtsenko Правильно. В настоящее время я использую Linux с намерением вскоре перейти на FreeBSD, но меня интересуют портативные решения для POSIX.   -  person fuz    schedule 11.04.2015
comment
@chuex Действительно, это так!   -  person fuz    schedule 16.04.2015


Ответы (1)


На типичной платформе единственные доступные «периодические события» являются неточными и низкочастотными, уж точно не 0,6 МГц. Но используя «медленный» таймер (возможно, 100 Гц или около того), вы можете «запустить много коротких спринтов», с достаточным временем «отдыха» между ними, что в среднем вы эмулируете нужное количество циклов в секунду. Время обычно можно измерить довольно точно, поэтому вы можете эмулировать точное количество циклов в каждом «спринте».

На высоком уровне это может выглядеть примерно так:

int cycle_budget = 0;
time last_sprint = something;

// on timer fire
cycle_budget += (current_time - last_sprint) * clock_rate;
last_sprint = current_time;
while (cycle_budget >= slowest_instruction)
    tick(); // emulates one instruction, subtracts from cycle_budget

Есть несколько очевидных вариантов, например, вы можете позволить бюджету стать отрицательным вместо того, чтобы проверять, достаточно ли его для запуска медленной инструкции. Или вы можете расшифровать инструкцию, а затем проверить, достаточно ли бюджета для ее выполнения. Все это предполагает, что инструкция не займет произвольно много времени, но, насколько я знаю, это никогда не проблема (даже что-то вроде строковых инструкций z80, они фактически зацикливаются, разветвляясь и повторно выполняя себя).

person harold    schedule 11.04.2015
comment
Звучит разумно. Некоторые системы используют точно рассчитанные по времени прерывания для воспроизведения звука. Я понимаю, что это не будет воспроизводимо с описанным вами подходом к эмуляции. В моем случае я могу эмулировать часть, которая звучит по-другому, но есть ли какая-то хитрость, чтобы получить такие вещи в зависимости от точного времени? - person fuz; 11.04.2015
comment
@FUZxxl там все сложнее, один подход, который я видел, помечает внешние события точным временем, которое они должны иметь (на основе счетчика циклов), а затем они обрабатываются так, как если бы они произошли в это время. Но это не обязательно работает для всего - person harold; 11.04.2015
comment
@harold Как насчет упреждения? Должен ли ваш метод это учитывать? Я имею в виду, если мы знаем квант времени планировщика (который мы можно обойтись sched_rr_get_interval()) -- нужно ли нам использовать это значение в ваших расчетах, чтобы один цикл эмулируемого процессора не прерывался планировщиком? - person Sam Protsenko; 11.04.2015
comment
@SamProtsenko прошедшее время будет отражать это и выделять больший бюджет, это делает все колебания времени (что обычно неточно) - person harold; 11.04.2015