Вопрос о точности подсчета тактов при эмуляции процессора

Я планирую создать эмулятор Sega Master System в течение следующих нескольких месяцев в качестве хобби-проекта на Java (я знаю, что это не лучший язык для этого, но мне очень удобно работать, и как частый пользователь как для Windows, так и для Linux, я подумал, что кроссплатформенное приложение было бы здорово). Мой вопрос касается подсчета циклов;

Я просмотрел исходный код другого эмулятора Z80, а также других эмуляторов, и, в частности, меня заинтриговал цикл выполнения - при его вызове в качестве аргумента передается целое число (скажем, 1000 в качестве примера). Теперь я понимаю, что для выполнения каждого кода операции требуется разное количество циклов, и что по мере их выполнения количество циклов уменьшается от общего числа. Как только количество оставшихся циклов ‹= 0, цикл выполнения завершается.

Мой вопрос заключается в том, что многие из этих эмуляторов не учитывают тот факт, что последняя выполняемая инструкция может увеличить количество циклов до отрицательного значения, что означает, что между циклами выполнения можно получить, скажем, 1002 цикла. выполняется вместо 1000. Это существенно? Некоторые эмуляторы учитывают это, компенсируя следующий цикл выполнения, а некоторые нет — какой подход лучше? Позвольте мне проиллюстрировать мой вопрос, поскольку я не особенно хорошо умею выражаться:

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.
      }
}

После окончания этого конкретного примера цикла numOfCycles будет равно -2. Это всегда будет лишь небольшой неточностью, но имеет ли это значение в целом для человеческого опыта? Я был бы признателен за чье-либо понимание этого. Я планирую прерывать ЦП после каждого кадра, поскольку это кажется уместным, поэтому я знаю, что 1000 циклов мало, но это всего лишь пример.

Большое спасибо, Фил


person PhilPotter1987    schedule 19.08.2011    source источник


Ответы (3)


Недавно была довольно интересная статья на Arstechnica, в которой говорилось о консольном моделировании, а также ссылки на довольно много симуляторов, которые могли бы послужить хорошим исследованием:

Точность берет верх: задача одного человека создать идеальный эмулятор SNES

Важно отметить, что автор упоминает, и я склонен согласиться с этим, что большинство игр будут работать довольно правильно даже при отклонении времени на +/- 20%. Упомянутая вами проблема, похоже, никогда не приведет к ошибке синхронизации, превышающей долю процента, что, вероятно, незаметно во время игры в финальную игру. Вероятно, авторы не сочли нужным иметь с ним дело.

person Charles Keepax    schedule 19.08.2011
comment
Спасибо :-) Я видел эту статью несколько дней назад, и это было очень интересно читать. Похоже, я могу проигнорировать эту проблему - моя работа вырезана, но должно быть весело! :-п - person PhilPotter1987; 19.08.2011

  1. большинство эмуляторов/симуляторов имеют дело только с тактами ЦП

    Это нормально для игр и т. Д. Итак, у вас есть таймер или что-то еще, и вы запускаете симуляцию ЦП до тех пор, пока ЦП не имитирует продолжительность таймера. Затем он спит до следующего интервала таймера. Это очень легко смоделировать. вы можете уменьшить ошибку синхронизации с помощью подхода, о котором вы спрашиваете. Но, как сказано здесь, для игр это обычно не нужно.

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

  2. если вам нужно что-то более сложное

    Например, если вы хотите подключить реальное оборудование к своей эмуляции/симуляции, вам необходимо эмулировать/симулировать BUS. Также такие вещи, как плавающая шина или соревнование системы, очень сложно добавить к подходу #1 (это выполнимо, но с большими трудностями).

    Если вы перенесете тайминги и эмуляцию на машинные циклы, все станет намного проще, и внезапно возникнут такие проблемы, как конфликты или аппаратные прерывания, плавающие BUS'ы решаются почти сами по себе. Я портировал свой эмулятор ZXSpectrum Z80 на такой тайминг и увидел свет. Многие вещи становятся очевидными (например, ошибки в документации по кодам операций Z80, тайминги и т. д.). Кроме того, спор стал очень простым (всего несколько строк кода вместо ужасных таблиц декодирования почти для каждой записи типа инструкции). Эмуляция HW также стала довольно простой. Я добавил такие вещи, как эмуляции чипов AY контроллеров FDC, к Z80 таким образом (никаких хаков, он действительно работает на своем исходном коде ... даже форматирование дискеты :)), так что больше никаких хаков TAPE Loading и не работает для нестандартных загрузчиков, таких как TURBO

    Чтобы это работало, я создал свою эмуляцию/моделирование Z80 таким образом, что он использует что-то вроде микрокода для каждой инструкции. Поскольку я очень часто исправлял ошибки в наборе инструкций Z80 (поскольку я не знаю ни одного на 100% правильного документа, даже если некоторые из них утверждают, что они не содержат ошибок и полны), я пришел с как с этим бороться без мучительного перепрограммирования эмулятора.

    Каждая инструкция представлена ​​записью в таблице с информацией о времени, операндах, функциональности... Весь набор инструкций представляет собой таблицу всех этих записей для всех инструкций. Затем я формирую базу данных MySQL для своего набора инструкций. и сформируйте аналогичные таблицы для каждого набора инструкций, который я нашел. Потом мучительно сравнивал их всех, выбирая/чиня что не так, а что правильно. Результат экспортируется в один текстовый файл, который загружается при запуске эмуляции. Это звучит ужасно, но на самом деле это значительно упрощает работу, даже ускоряет эмуляцию, поскольку декодирование инструкций теперь просто обращается к указателям. Пример файла данных набора инструкций можно найти здесь Какова правильная реализация аппаратной эмуляции

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

Планирование ЦП

  • a) Полный газ не имеет синхронизации, только скорость
  • b) #1 имеет большие пробелы, вызывающие проблемы с синхронизацией оборудования
  • c) #2 нужно много спать с очень мелкой детализацией (может быть проблематично и замедлять работу) Но инструкции выполняются очень близко к их реальному времени...
  • Красная линия — это скорость обработки процессора хоста (очевидно, что то, что выше, требует немного больше времени, поэтому его следует обрезать и вставить перед следующей инструкцией, но это будет сложно правильно нарисовать)
  • Пурпурная линия — скорость обработки эмулированного/симулированного процессора.
  • чередующиеся green/blue цвета обозначают следующую инструкцию
  • обе оси - время

[edit1] более точное изображение

Тот, что выше, был нарисован вручную... Этот сгенерирован программой VCL/C++:

время

генерируется по этим параметрам:

const int iset[]={4,6,7,8,10,15,21,23}; // possible timings [T]
const int n=128,m=sizeof(iset)/sizeof(iset[0]); // number of instructions to emulate, size of iset[]
const int Tps_host=25;  // max possible simulation speed [T/s]
const int Tps_want=10;  // wanted simulation speed [T/s]
const int T_timer=500;  // simulation timer period [T]

поэтому хост может моделировать на 250% от желаемой скорости, а степень детализации моделирования составляет 500T. Инструкции генерируются псевдослучайно...

person Spektre    schedule 24.10.2015

Я думаю, это зависит от того, насколько точным вы хотите, чтобы ваш эмулятор был. Я не думаю, что это должно быть так точно. Подумайте об эмуляции платформы x86, существует так много вариантов процессоров, и каждый из них имеет разные задержки выполнения и частоту проблем.

person wilx    schedule 19.08.2011
comment
Ну, я подумал, пока я привязываю это к частоте кадров - скажем, 50 кадров в секунду, если я эмулирую консоль PAL - Затем между этими кадрами, если я выполняю сколько циклов, а затем делаю паузу, пока я обновляю экран, который должен быть адекватным . Думаю, я узнаю :-p Спасибо за ответ. - person PhilPotter1987; 19.08.2011