Если бы меня спросили про симуляцию некоторое время назад, то первое, что пришло бы в голову – это мой сын, рассказывающий о своем больном животе накануне контрольной в школе. Однако последние десять лет я работаю с симуляторами различных компьютерных систем, от телефонов до серверов, основанных на микропроцессорах, SOC-ах (System-On-Chip) и чипсетах одного из крупнейших производителей (к сожалению, название под NDA), и мое представление о симуляции поменялось. Но обо всем по порядку.
Я уверен, что многие из вас сталкивались с симуляторами, которые часто называют виртуальными машинами, гипервизорами. Кто-то устанавливает Parallels Studio себе на Mac, чтобы запускать Windows из MacOS, кто-то пользуется продуктом от VmWare – Workstation, чтобы иметь еще одну операционную систему (ОС), запущенную внутри уже установленной. Те, кто знаком с Linux, предпочитают KVM и QEMU. Также популярен в народе VirtualBox. Люди, профессионально занимающиеся разработкой аппаратуры на базе ПЛИС (Программируемая Логическая Интегральная Схема), знают про VCS от Synopsys и Mentor Graphics Questa. И все же это лишь небольшая часть того, что можно называть симуляторами.
Что такое симулятор?
Симулятором называют модель, как правило, программную, реального устройства. Соответственно, симуляция – это процесс работы такой модели, повторяющий работу устройства.
В принципе, можно сделать модель любого устройства, но наиболее распространенными являются симуляторы микропроцессорных устройств, то есть устройств, центральным компонентом которых является микропроцессор, и вокруг него уже строится остальная логика. Один из основных вариантов использования симулятора – это запуск программ, предназначенных для этого самого микропроцессора. При этом использование реального устройства по тем или иным причинам затруднительно, например, его может просто еще не существовать, если речь идет о моделировании будущего поколения микропроцессоров.
Airbnb в симуляции – гость и хост
Код, запускаемый внутри симулятора, называют «гостевым кодом», это может быть «гостевая программа» или целая «гостевая операционная система». Сама симулируемая система называется просто «гость». В свою очередь, система, компьютер, где запускается симулятор, называется «хостом» (англ. host), а операционная система, работающая на хосте, в которой запускается симулятор, называется «хостовой ОС».
Таким образом, можно сказать, что симулятор, реализующий определенный набор инструкций гостевой системы, моделирует их, используя имеющиеся в наличии средства хостовой системы.
Симуляция и эмуляция – какое название правильное?
Модель может повторять устройство с разной степенью точности и детализации. Часто это симуляция только внешнего поведения системы, доступного программному коду. Коду ведь «все равно», как именно внутри реализована та или иная инструкция процессора, – главное, чтобы работало. Такой вариант симуляции распространен, не сложен в разработке и довольно быстрый, не тормозит даже на обычных пользовательских компьютерах.
Однако этого недостаточно, если мы хотим узнать, например, сколько времени будет выполняться программа на реальной аппаратуре. Для этого необходимо моделирование не только внешнего поведения, но и повторение внутренней структуры и логики работы. Это тоже может быть выполнено с разной степенью детализации и точности. Такие модели правильнее называть эмуляторами, которые действительно эмулируют устройство, а не «симулируют» результаты.
Создание эмуляторов гораздо сложнее из-за большего объема функциональности, которую необходимо реализовывать в модели. Также они функционируют намного медленнее по сравнению с симуляторами внешнего поведения устройства. С эмуляторами речь вообще не идет о запуске Windows – это может занять годы. Никто не занимается созданием программного эмулятора целиком всей платформы – это очень долго и дорого. Вместо этого эмулируются отдельные компоненты системы, такие как тот же центральный процессор, и на нем запускается лишь часть симуляционного процесса. Возможны различные гибридные схемы, когда часть симулятора является верхнеуровневой моделью, часть низкоуровневой, часть в ПЛИС, а часть вообще реальная железка.
4 уровня детализации симуляции
Как я написал выше, наиболее распространенным является вариант симуляции на уровне инструкций процессора, так называемый ISA (Instruction Set Architecture), или, точнее, результата их выполнения, т.е. без эмуляции всей внутренней логики того, как это происходит в реальном процессоре, и без учета времени выполнения различных инструкций. Именно такие симуляторы называют еще функциональными. Так работают VirtualBox, Vmware Workstation, Wind River Simics, KVM и QEMU. Это позволяет удобно, без лишних дополнительных действий запускать программы, предназначенные для симулируемого устройства. Другими словами, не требуется ни перекомпиляция, ни какие-либо другие манипуляции с запускаемыми программами. В таких случаях говорят, что возможен запуск немодифицированного бинарного кода.
Если говорить про более высокий уровень абстракции, то это будет реализация определенного ABI (Application Binary Interface). В двух словах, ABI описывает бинарный интерфейс взаимодействия двух программ – как правило, пользовательской программы и библиотеки или ОС. ABI покрывает соглашения о вызовах (как передавать параметры и возвращать значения), размеры типов данных, выполнение системных вызовов. Как это работает? Например, если программе, написанной для Linux, необходимо создать дополнительный тред (от англ. thread – нить) выполнения, то вызывается функция pthread_create(). А что, если сделать библиотеку с такой функцией в Windows и реализовать необходимые механизмы связывания приложения и библиотеки (динамической линковки)? В таком случае можно будет запускать Linux приложения из Windows. Windows будет «симулировать» Linux. Именно это и было сделано в Windows subsystem for Linux в Windows 10, что позволяет запускать немодифицированные бинарные Linux приложения в Windows.
Теперь посмотрим, как выглядят более низкоуровневые и детальные уровни симуляции. Это будет уровень микроархитектуры, при котором симулируются реальные внутренние алгоритмы и блоки процессора, такие как декодер инструкций, очереди, блок внеочередной обработки, предсказатель переходов, кэш, планировщик и сами счетные устройства. Такое моделирование позволяет анализировать реальную скорость выполнения программ и, например, оптимизировать их под уже имеющиеся архитектуры. А в случае симуляции прототипов будущих микропроцессоров возможны предсказание и оценка производительности этих устройств.
Ниже уровня микроархитектурной симуляции идет уровень эмуляции логических элементов, из которых и состоят современные чипы. Такие эмуляторы бывают и программными, и аппаратными с использованием ПЛИС. Логика ПЛИС описывается с помощью RTL (Register Transfer Level) на языках Verilog, VHDL и др. После компиляции получается образ (bitstream), который потом прошивается в ПЛИС. Причем для этого необязательно пользоваться паяльником и разбираться в электротехнике. Плата подсоединяется к компьютеру, например, по USB или JTAG интерфейсу, а специальный софт от производителя ПЛИС платы выполняет запись. Стоимость таких плат начинается от десяти долларов за простейшие варианты до миллионов долларов для больших ПЛИС стендов размером со шкаф, используемых в крупных компаниях-производителях чипов. В таких компаниях симуляция с использованием ПЛИС является финальной стадией перед отдачей RTL в производство.
Если речь идет о несложных устройствах, то, имея на руках образ ПЛИС, можно обратиться в специализированные компании, которые сделают настоящее (не ПЛИС) устройство с запрограммированной логикой.
На рисунке ниже показаны описанные уровни симуляции.
Кроме этих уровней моделирования, мне также приходилось сталкиваться с гибридными симуляторами. По сути, они представляют собой соединенные друг с другом симуляторы, моделирующие на разных уровнях разные части системы. Например, необходим анализ пропускной способности новой сетевой карты, работающей вместе с разрабатываемым драйвером для определенной ОС. Такое сетевое устройство, а также ряд смежных устройств, могут быть реализованы сначала на микроархитектурном уровне для предварительного анализа, а потом и в ПЛИС, на уровне логических элементов, для финальных проверок. При этом остальная часть системы, задействованная лишь частично, реализуется на уровне инструкций. Обойтись без нее нельзя, так как она необходима, например, для загрузки ОС, а реализовывать ее на более низком и сложном уровне не имеет смысла.
Так что же на счет сравнения симуляторов и реальности?
Как теперь понятно, нет задачи сделать тот или иной симулятор максимально похожим на реальность. Есть задача, которую ставит бизнес, и симуляция выполняется со той степенью “похожести” на реальность, который является минимально достаточным для решения этой задачи, не тратя при этом лишних денег и времени. В одном случае это может быть простая библиотека, реализующая необходимый бинарный интерфейс (ABI), а в другом не обойтись без детального микроархитектурного симулятора.
Это самая базовая информация о том, что такое симуляторы и какие они бывают. В следующей статье я опишу детали реализации полноплатформенных симуляторов, потактовых моделей и работу с трассами.
GnuriaN
А когда будет продолжение?