Перейти к содержанию
    

Косимуляция в Матлабе (Matlab Cosimulation, Matlab Link for Modelsim)

Выложу здесь инструкцию по косимуляции в матлабе (оно же может называться Matlab Cosimulation, Matlab Link for Modelsim). Это когда из матлаба запускается HDL код в симуляторе, входные и выходные данные передаются напрямую между симулятором и матлабом без использования промежуточных текстовых файлов (как это обычно было принято). Инструкция скорее для себя, чтобы не забыть. И может ещё кому-то полезно будет, чтобы с нуля не ходить по граблям.

Косимуляция бывает как минимум двух видов:

  1. Когда все тестовые воздействия генерятся в тестбенче симулятора, потом вход и выход симулятора передаются в малтаб, где подаются на матлаб-функцию модели HDL-кода для сравнения. В результате выдаётся вердикт: совпало или не совпало в симуляторе и в матлабе.
  2. Когда пользователь в матлабе генерит тестовые воздействия, они передаются в симулятор, а результаты с выхода HDL-кода принимаются обратно в матлаб для анализа.


Для моих работ мне больше подошёл последний вариант, поскольку при отладке DSP генерация сложного сигнала в матлабе проще, чем в симуляторе. Как и анализ результатов работы HDL-кода в матлабе проще, поскольку можно нанести несколько графиков на один рисунок, построить преобразование Фурье или другие функции. К тому же, как потом выяснилось, при таком способе возможно задавать не только воздействия на входные порты, но и переопределять любые внутренние сигналы (как делается drive в тестбенче). А также можно вычитывать в матлаб любые внутренние сигналы для анализа и отладки.

Для косимуляции требуется определённая версия матлаба и симулятора. Для Matlab R2021b требуется Modelsim SE 2020.4. Однако в такой версии моделсима у меня почему-то не получилось, и я перешёл на QuestaSim 2021.1, в такой связке у меня работает нормально. Правда выдаёт warning, что несовместимые версии, но его можно отключить, просто подправив код выдачи ворнинга, номер строки указывается в самом ворнинге.

Вообще за пример была взята эта страница:
https://www.mathworks.com/help/hdlverifier/ug/verify-viterbi-decoder-using-matlab-system-object-and-hdl-simulator.html
Там справа сверху есть команда для запуска примера в матлабе:
openExample('hdlverifier/VerifyViterbiDecoderUsingSystemObjectAndHDLSimulatorExample')
Можно открыть, поизучать, попробовать запустить. Нужно будет установить правильный тип симулятора, там сверху константы задаются. Также возможно потребуется увеличить таймаут на запуск симулятора, т.к. со штатным таймаутом почему-то не вышло.

Краткое пояснение основных шагов, необходимых для создания косимуляции:

1. В коде матлаб вставляем примерно такую конструкцию (исправляем её под себя):

hDec = hdlcosim('InputSignals', {'/viterbi_block/In1','/viterbi_block/In2','/viterbi_block/Traceback_out1'}, ...
                'OutputSignals', {'/viterbi_block/Out1', '/viterbi_block/Delay5_out1'}, ...
                'OutputSigned', false, ...
                'OutputFractionLengths', 0, ...                   
                'TCLPostSimulationCommand', 'echo "done";', ...
                'PreRunTime', {10,'ns'}, ...
                'Connection', {'Shared'}, ...
                'SampleTime', {10,'ns'});


Пока эта команда просто создаёт объект с параметрами. Здесь задаём входые и выходные сигналы. При том, как было сказано выше, можно задавать не только воздействия на входные порты, но и переопределять любые внутренние сигналы (как делается drive в тестбенче). А также можно вычитывать в матлаб любые внутренние сигналы для анализа и отладки.
Также нужно обратить внимание на PreRunTime и SampleTime и правильно задать их значения:
PreRunTime - это время предварительного выполнения симуляции для установления всех переходных процессов, требуемых перед основной симуляцией. Например это может быть длительность сигнала сброса или задержка появления сигнала на выходе (связана с Latency вашего HDL кода). Более подробно про предварительное выполнение будет понятно ниже.
SampleTime - это периодичность выборок данных (обмена данными) между матлабом и симулятором. Наиболее вероятно это будет совпадать с периодом вашей тактовой частоты clk, ведь данные у вас будут меняться каждый клок. Если у вас несколько кратных частот, то видимо придётся взять самую высокую и на ней обмениваться с матлабом. Если несколько частот некратных, то наверное данная косимуляция вообще не подойдёт, т.к. выборки будет в непредсказуемые моменты времени. Хотя... можно и сам клок ещё вытаскивать в матлаб на утроенной или упятерённой частоте, а потом определять в нём интервал неизменного состояния, для которого фиксировать данные. Короче уже извраты пошли.
Ну и может кому-то будет интересно поправить TCLPostSimulationCommand, это строка с TCL-скриптом, который будет выполнен по окончании симуляции.
Параметр Connection задаёт способ соединения с симулятором: есть через разделяемую память, а есть через сокет TCP/IP. Сами матлабохелпописатели продвигают вариант через сокет, типа крутой и многофункциональный. Но я решил оставить через память как простой, без единой настройки.

2. Далее вставляем примерно такую конструкцию (и тоже правим под себя):

hDec.TCLPreSimulationCommand = ...
    'force /viterbi_block/clk_enable 1 0; force /viterbi_block/clk 0 0 ns, 1 5 ns -repeat 10 ns; force /viterbi_block/reset 1 0 ns, 0 8 ns; ';

Здесь описывается обычный TCL скрипт, который, вобщем-то, и будет являться нашим тестбенчем, т.е. он сработает в момент начала симуляции. Как мы видим тут переопределяется поведение клока и сброса. Тут наверное всё понятно, как исправить под себя.

3. Далее вставляем такую конструкцию (в вышеупомянутом примере это довольно запутано, но вместо кучи вложенных функций и переменных можно написать всё самому плоским текстом при желании):

vsim('tclstart',viterbi_cosimulation_tclcmds('vsimmatlabsysobj'));

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

function tclCmds = viterbi_cosimulation_tclcmds(loadCmd)
srcDir   = './viterbi_hdlsrc';
% VHDL source files
srcFiles = {...
    'viterbi_block_pkg.vhd',... '
    'ACS0.vhd'};
compile_cmds = strcat({'vcom  "'}, {srcDir}, '/', srcFiles,'"');
tclCmds = [{'vlib work'}, ...
           compile_cmds, ...
           [loadCmd '  viterbi_block -voptargs=+acc=lprn'], ...
           'do wave.do', ...
           'puts "Ready for cosimulation ..."'];


Тут командой vsim() вызывается симулятор, в котором должен выполниться стартовый tcl-скрипт. Но это не тот стартовый скрипт, что упоминался выше. Выше там именно типа тестбенч, выполняемый во время самой симуляции, в самом её начале. А тут предполагается, что стартовый скрипт - это просто компиляция исходников. Т.е. tclCmds - это просто строка, в которую записаны обычные команды скрипта TCL, которые бы вы сами написали, чтобы скомпилировать ваши исходники.
Может кому-то будет полезна ещё информация, как сделать самому тестбенч. У кого опыта выше крыши - тот может сам всё написать как ему надо. Но если опыта недостаточно, можно подсмотреть, как тестбенч делает Vivado, ведь в вивадо есть встроенный инструмент для запуска симуляции в моделсиме.

Скрытый текст

Для начала нужно скомпилировать библиотеки через меню Tools - Compile Simulation Libraries. Сверху выбираем Simulator моделсим или квесту, чуть ниже семейство ПЛИС, под которые мы хотим библиотеки. Можно выбрать все возможные, но бывает нет времени ждать компиляцию всех, тогда можно выбрать только какое-то конкретное семейство. Чуть ниже выбираем путь, куда будут помещены скомпилированные библиотеки: Compiled library location. Внимание! Нужно сразу хорошо подумать и выбрать правильное расположение папки, т.к. потом будут сложности при её переносе, поскольку абсолютные пути будут прописаны в файл modelsim.ini, помещаемый в эту же папку, а этот файл будет при вызове симуляции подменять собой стандартный файл modelsim.ini. После компиляции библиотек мы заходим в меню Flow - Simulation Settings. Выбираем Target simulator как моделсим или квесту (в соответствии с тем, что у нас установлено), а чуть ниже задаём путь Compiled library location, это как раз сюда нужно прописать ту папку, куда у нас были ранее скомпилированы библиотеки. Далее нужно вызывать команду меню Flow - Run Simulation - Run Behavioral Simulation. После этого будут подготовлены все необходимые скрипты для компиляции и симуляции и будет запущена симуляция. После этого переходим в папку, где расположен ваш вивадовский проект, а далее в подпапку <название вашего вивадовского проекта>.sim\sim_1\behav\ . В этой папке можно подсмореть, как делается тестбенч, какими командами что запускается, и сделать по образу и подобию под себя.


Нужно обратить внимание в куске кода выше на строку

do wave.do


Её не было в вышеупомянутом примере, её приписал я сам для своих нужд. А нужды такие, чтобы мочь отлаживать что-то по осциллограммам в самом симуляторе, как мы это обычно делаем, если пользуемся только самим симулятором, без матлаба. Можно этот файл пока оставить пустым, если вам не нужны осциллограммы. А потом в него можно будет что-то дописать. Допустим мы выполнили косимуляцию, у нас плохой результат, нам надо подебажить внутренности по осциллограммам в симуляторе. Окно симулятора мы не закрываем по окончании косимуляции. Переходим в симулятор и мышкой или ещё как вытаскиваем нужные нам сигналы на окно waveform. Затем это окно с сигналами сохраняем в файл в wave.do просто командой сохранить. И вот тогда указанная выше строчка do wave.do при каждой косимуляции будет открывать нам окно с нужными нам сигналами и на них будут осциллограммы.

Также обращу внимание на запись

-voptargs=+acc=lprn

Её тоже не было в вышеупомянутом примере, её я дописал для своих нужд. Эта запись позволила получить видимость всех сигналов, чтобы их можно было подключить в косимуляции. Для вышеупомянутого примера это не требуется, но когда будете писать на его основе свою косимуляцию, то может так получиться, что в результате оптимизации не видно тех сигналов, с которыми требуется связаться из матлаба. Понятно, что это отключение оптимизации приведёт к тормозам, и нужно быть аккуратным с этим.
Подсказку по такой записи нашёл здесь:
https://stackoverflow.com/questions/24179095/modelsim-optimization-issue

Цитата

"While optimization is not necessary for class based debugging, you might want to use
vsim -voptargs=+acc=lprn to enable visibility into your design for RTL debugging."

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

proc vsimmatlabsysobj {args} {
  lappend sllibarg -foreign \{matlabsysobjserver \{D:/Program Files/MATLAB/R2021b/toolbox/edalink/extensions/modelsim/windows64/liblfmhdls_gcc450vc12.dll\}
  if {[catch {lsearch -exact $args -socket} idx]==0  && $idx >= 0} {
    set socket [lindex $args [expr {$idx + 1}]]
    set args [lreplace $args $idx [expr {$idx + 1}]]
    append socketarg " \; -socket " "$socket"
    lappend sllibarg $socketarg
  }
  set runmode "GUI"
  if { $runmode == "Batch" || $runmode == "Batch with Xterm"} {
    lappend sllibarg " \; -batch"
  }
  lappend sllibarg \}
  set args [linsert $args 0 vsim]
  lappend args [join $sllibarg]
  uplevel 1 [join $args]
}


Заметьте: ключевое слово vsimmatlabsysobj уже фигурировало выше, и можно проследить взаимосвязь этих кусков кода.

4. Далее в код нужно добавить такие строчки:

Timeout=90;
processid = pingHdlSim(Timeout);
% Check if HDL simulator is ready for Cosimulation.
assert(ischar(processid),['Timeout: HDL simulator took more than ', num2str(Timeout),' seconds to setup,please increase the timeout in ''pingHdlSim''']);
disp('...Simulator is ready for cosimulation.');


Эта секция приостанавливает на этом месте дальнейшее выполнение скрипта, пока симулятор не отработает предыдущее. Чтобы выполнение матлаба и симулятора было синхронизировано на нужных стадиях. Таймаут задаёт время ожидания ответа. Можно отрегулировать. Изначально в вышеупомянутом примере было 30с, но на моём компе не хватало, я увеличил.

5. Ну и самый главный пункт - основная симуляция. Описывается примерно такой строчкой:

[receivedBits, ttt]    = step(hDec,input1, input2, input3);

Т.е. указываем входные и выходные переменные. При том, как было сказано выше, возможно задавать не только воздействия на входные порты, но и переопределять любые внутренние сигналы (как делается drive в тестбенче). А также можно вычитывать в матлаб любые внутренние сигналы для анализа и отладки. Эти сигналы должны быть определены согласно п.1. Входные переменные могут быть скалярами или векторами одинаковой размерности. Каждый следующий элемент вектора подставляется в симулятор на каждом следующем периоде времени, указанном в параметре SampleTime в п.1. Метод step можно вызывать не обязательно однократно, а сколько угодно раз (в цикле например, как в вышеупомянутом примере), пока не закончатся входные данные.
Вместо

step(hDec,input1, input2, input3);


можно вызывать

hDec(input1, input2, input3);

Вот тут этому объяснение:
https://www.mathworks.com/help/matlab/ref/step.html

Цитата

"Starting in R2016b, instead of using the step method to perform the operation defined by the System object, you can call the object with arguments, as if it were a function. For example, y = step(obj,x) and y = obj(x) perform equivalent operations."


6. По окончании симуляции нужно дать следующую команду:

clear hDec;


Это удалит объект, связанный с симулятором, и разблокирует симулятор для возможности управления им мышкой пользователем (до этого момента симулятор остаётся заблокирован, и ничего с ним сделать пользователю нельзя). После разблокировки пользователь может подебажить в симуляторе обычным образом, по вэйвформам, которые были добавлены командой do wave.do в п.3.
Если на вэйвформах не хватает каких-то сигналов, то мышкой или ещё как вытаскиваем нужные нам сигналы на окно waveform. Затем это окно с сигналами сохраняем в файл в wave.do просто командой сохранить. Затем косимуляцию нужно перезапустить с начала, т.е. с п.1.

На этом всё.

Приведу дополнительные ссылки почитать для общей информации, может, будет полезно:
https://www.mathworks.com/help/releases/R2021b/hdlverifier/ref/matlabcp.html
https://www.mathworks.com/help/releases/R2021b/hdlverifier/ug/verify-raised-cosine-filter-design-using-matlab.html
https://www.mathworks.com/help/releases/R2021b/hdlverifier/ug/import-hdl-code-for-matlab-function.html#btx017h-19
https://www.mathworks.com/help/hdlverifier/ref/hdldaemon.html
https://www.mathworks.com/help/hdlverifier/ug/verify-hdl-model-with-matlab-testbench.html
https://www.mathworks.com/help/hdlverifier/ug/startup-for-hdl-cosimulation.html?s_tid=srchtitle_startup-for-hdl-cosimulation_1
https://docs.exponenta.ru/hdlverifier/ug/startup-for-hdl-cosimulation.html#bt9u4xl-3
https://docs.exponenta.ru/hdlverifier/ug/verify-hdl-model-with-matlab-testbench.html#bt9obpv-71
https://www.mathworks.com/help/hdlverifier/ref/vsim.html
https://www.embedders.org/content/sovmestnoe-modelirovanie-proektov-v-modelsim-qusestasim-i-simulink
https://exponenta.ru/hdl-verifier
https://www.mathworks.com/help/hdlverifier/ug/getting-started-with-matlab-based-systemverilog-dpi-component-generation.html
https://www.mathworks.com/help/releases/R2021b/hdlverifier/gs/supported-eda-tools.html
https://www.mathworks.com/help/hdlverifier/ug/verify-hdl-model-with-simulink-test-bench.html
https://www.edaboard.com/threads/matlab-and-modelsim-cosimulation.229534/
https://people.ece.cornell.edu/land/courses/eceprojectsland/STUDENTPROJ/2009to2010/mal283/Simulink_ModelSim_Tutorial.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно еще вот так моделировать. Писаниниы меньше Совместное моделирование проектов в Modelsim (Qusestasim) и Simulink | Embedders.org 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

спасибо за ссылку! Там правда симулинк, не голый матлаб, мож кто в симулинке не работает по каким-то причинам... А так - да, получается куда быстрее. Но в целом один раз это пройти, будет некий шаблон, который можно будет очень быстро корректировать под любую следующую косимуляцию. Долгая писанина - это с начала, шаблон создать. Да и вообще путь пройти, как это должно правильно быть написано. А последующие разы - по накатанной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Maverick_ сказал:

спасибо

Ну что вы, не за что, я отсюда столько опыта за всё своё время регистрации здесь вывез, что грузовика не хватит, так что надо по-маленьку возвращать долги ))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Just now, Krys said:

Ну что вы, не за что, я отсюда столько опыта за всё своё время регистрации здесь вывез, что грузовика не хватит, так что надо по-маленьку возвращать долги ))

 меня многому тоже форум научил...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...