BreaksVM (Breaks Verilog Machine) - виртуальная машина для выполнения Verilog-подобных скриптов.
Мы не собдюдаем стандартов, то что не поддерживается можете добавить сами.
Главная особенность и отличие от Verilog - это добавление виртуальных девайсов в скомпилированный netlist. Добавленные девайсы интегрируются в реактивную среду netlist-а и "цепляются" к выбранным IO-контактам модулей.
Исходными данными для виртуальной машины являются Verlog-скрипты (*.v)
Встроенный компилятор создает из скриптов netlist, который затем передается статическому рекомпилятору, который преобразует netlist в быстрый платформенный код.
Управлением виртуальной машиной занимается родительское приложение.
Весь интерфейс содержится в файле breaksvm.h, а программный код - в breaksvm.c. Из зависимостей - stdio, pthread.
Типы данных используемые в BreaksVM: u8, u16, u32, u64.
Виртуальные девайсы, которые прикрепляются к входам и выходам виртуальной машины работают следующим образом :
Типичный пример виртуального девайса - это XTAL (генератор опорной частоты) :
void XTAL_output (unsigned char * reg) // toggle clock { if ( reg[0] == '0' ) reg[0] = '1'; if ( reg[1] == '1' ) reg[1] = '0'; }
После инициализации VM мы устанавливаем этот callback :
breaksvm_output_reg ( "CLK", XTAL_output );
Теперь после каждого прогона run контакт CLK будет менять своё значение, тем самым тактируя схему.
Все ошибки времени компиляции и симуляции сыпятся в stdout. При серьезных ошибках run прерывается, предупреждения не прерывают симуляцию.
Мы выкинули ненужный хлам, который не понадобился для наших целей. Считайте этот документ описанием стандарта BreaksVM
Однако главное правило - любой verilog-скрипт для BreaksVM может быть синтезирован в реальный девайс, то есть мы не используем нестандартные дополнения.
Отличия :
То есть наш диалект максимально приспособлен для синтезирования логики.
нужны ли нам real ? чё-то кажется входы и выходы всё равно дискретные..
нужны ли функции ? и как они будут "синтезироваться" ? Просто как встраиваемый код (inline) ?
Все reg и wire хранятся в памяти как байты (unsigned char). Логические значения соответственно могут быть '0', '1', 'x', 'z', 'L', 'H' итп. (char-константы)
real хранятся как float (IEEE734 32-бит). Вещественные входы/выходы используются для аналоговых схем и представляют собой моментальное напряжение.
parameter тоже самое что и integer. integer тоже самое что и reg[31:0].
Все input/output/inout всех модулей связаны реактивно. Симуляция всей системы продолжается до тех пор, пока все входы/выходы останутся неизменными.
Run flow одного запуска симуляции выглядит следующим образом :
Разобранное синтаксическое дерево (netlist) выдается в формате EDIF 2 0 0. http://iroi.seu.edu.cn/books/asics/Book2/CH09/CH09.4.htm Каждый узел этого дерева - стандартная ячейка библиотеки breaksvm.
Netlist преобразуется в двоичную форму, а затем производится его статическая рекомпиляция. После чего VM готова к исполнению (run).
Рекомпиляция заключается в том, что вместо обычного траверса (интерпретации) netlist, блок за блоком производится перевод всего прогона run в исполняемый код платформы.
Многопоточность : поскольку мы используем реактивную модель, то не важно в какой последовательности будут выполнены модули. Поэтому каждый модуль представляет собой отдельный поток и все вместе они выполняются одновременно. После завершения исполнения модуля - проверяются реактивные связи и зависимые модули исполняются повторно. Чтобы избежать повторных одновременных исполнений используются мутексы.
Библиотека реализует стандартный набор логических элементов эпохи NMOS. Более сложные ячейки могут быть добавлены со временем.