Эй, Симулятор! Покажи свой язык

f3d2554a677c40088dcbafd9934b5491.jpeg
Написанию этого материала способствовала статья Зачем язык Verilog программисту микроконтроллеров, где описывается возможность тестирования алгоритма (Си файла) проекта микроконтроллера в Verilog проекте. Т.е. симулятор Verilog HDL взаимодействует с Сишным кодом микроконтроллера и тестирует реализованный алгоритм на возможные логические ошибки.

Подобные методы отладки кода для микроконтроллеров уже реализованы производителями. За всех не поручусь, но могу показать на примере симулятора MPLAB SIM компании Microchip Technology Inc.


Много-много лет назад, в Microchip, в команде разработчиков симулятора MPLAB был разработан VHDL-подобный язык SCL — Stimulus Control Language, с помощью которого можно создавать testbench для помощи в отладке кода. Однако, в связи с уходом из команды автора реализации SCL и «сложности» языка, было решено создать GUI, которая освобождает embedded-программиста от вникания в тонкости VHDL-подобного SCL и помогает создать последовательности тестовых сигналов и инжекций данных в регистры симулируемого микроконтроллера. Такая GUI-обертка в среде разработки MPLAB IDE называется Stimulus.

Секретный язык
Microchip особо не продвигал SCL и не предоставлял описание языка. В 2006 году даже было объявлено, что в следующей версии MPLAB IDE v8.xx вообще уберут поддержку SCL, но участники forum.microchip.com высказались против этого и SCL оставили в следующих релизах.

Некоторые энтузиасты даже начали «реверсить» SCL (благо Stimulus может генерировать SCL-файлы) и создавать учебник по SCL и репозиторий примеров. Особо стоит отметить русскоязычный труд с описанием SCL, сопровождающийся несколькими примерами (от простого генератора, до эмуляции UART и генерации DTMF сигналов).

В связи с тем, что новое поколение MPLAB X IDE полностью переписано и получило кроссплатформенность (MPLAB X основан на NetBeans), то реализация SCL так же переписана и нынешние разработчики включили «неофициальный» SCL User«s Guide в документацию к MPLAB X IDE.


Сейчас Stimulus позволяет:
А) создавать синхронные последовательности изменений состояний выводов или значений регистров (удобно для формирования повторяющихся последовательностей:
Во время Хn состояние (pin, регистр) = ХХ
Во время Хm состояние (pin, регистр) = YY
Процесс можно повторять начиная с шага i; между повторами задать задержку ii.

Б) создавать комплексные воздействия:
Если выполняется условие, что (pin, bit или регистр) становится (=, !=, <=, <, >= или >), то через N (тактов, нс, мкс, мс или ч.м.с) выполнить (однократно или с периодом M) воздействие (одно или несколько): записать в регистр значение, изменить состояние pin или bit, установить напряжение на аналоговом входе.

В) генерировать сигналы:
На выводе (pin_уу) с начальным значением (ВЫСОКОЕ или НИЗКОЕ) выдать последовательность (задается длительность ВЫСОКОГО и НИЗКОГО состояния). Задаются условия запуска и останова (старт программы или по значению программного счетчика или в заданное время или когда значение на pin_хх == ВЫСОКОЕ или НИЗКОЕ).

Г) инжекция данных в регистры:
Из указанного файла взять значение и записать его в заданный регистр. Действие произвести когда: происходит чтение из регистра (т.е. в отлаживаемой программе читаем регистр) или программный счетчик примет зафиксированное значение или выполнится указанное в файле условие. Например, можно инжектировать в UART данные из файла вида:

wait 1 sec // ждать 1 секунду
01 54 106 // инжектируемые данные
02 55
wait 200 ms // ждать 200 мс
"hello” // инжектируемые данные
rand 1 15 sec // случайная пауза от 1 до 15с
32 33 34

Stimulus, помимо описанного, позволяет сохранить созданные воздействия в виде SCL файла и (!) загружать собственные SCL сценарии.


Stimulus является достаточно мощным инструментом, но имеет существенные ограничения — служит в основном для задания простых и детерминированных воздействий, не всякую модель поведения «внешней среды» можно описать с помощью предлагаемой в среде разработки GUI.
SCL, являясь языком программирования, дает больше гибкости: доступны условные выражения (конструкции if-elsif-else), циклы, инструкции работы с файлами и др.

Некоторые возможности SCL:

  • Инжектирование значения в pin или в память данных микроконтроллера
  • Чтение значения pin или из памяти данных
  • Чтение и обработка файлов
  • Выполнение действий на основании времени симуляции, командных циклов и на основании значения программного счетчика
  • Выдача информационных сообщений в окно симулятора

То есть SCL может все, что доступно через GUI Stimulus в MPLAB IDE. Но SCL имеет более широкие возможности и позволяет формировать сложные зависимости между значениями на выводах и значениями регистров микроконтроллера; моделировать взаимодействие с внешней периферией; моделировать воздействия, которые сложно воспроизвести в «железе» и выявлять ситуации, приводящие к ошибкам. Кроме того, среда разработки позволяет подключать несколько SCL файлов, для их параллельного выполнения. Это может пригодиться, например, для подключения к проекту типовых testbench-ев.


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

c14e8ac94bc04c3eab9a0f77bb7d3e8f.png

Теперь, если нужно изменить первый бит, то нужно переписать всю последовательность.

Другое дело, если формировать последовательность с использованием SCL: пишем testbench, который берет входной битовый поток (не кодированный), кодирует его и отправляет на вход симулируемого микроконтроллера. Для удобства изменения данных, входной битовый поток можно брать из внешнего файла. Попутно наш testbench может выводить информационные сообщения в окно симулятора.

Пример SCL файла:

configuration for "pic16f1509" is
 end configuration;

 testbench for "pic16f1509" is
 begin

  process is
      file fileVar : text;
      variable lineVar : line; -- Строка, прочитанная из файла
      variable status  : file_open_status;
      variable data_in : integer;

   begin
     loop
       file_open(status, fileVar, "dat.txt", read_mode);

while endfile(fileVar) == false loop -- Обрабатываем, пока файл не пуст

         readline(fileVar, lineVar);
         report("Прочитана строка");
         RB5 <= '1'; -- стартовый бит (1/2 битового интервала)
         report ("== start bit ==");
         wait for 500 us; 

         while match(lineVar, "") == false loop   -- Обрабатываем строку, пока она не пуста

            read(lineVar, data_in);
            if data_in == 0 then -- кодируем 0
               report ("== 0 ==");
               RB5 <= '0';
               wait for 500 us; 
               RB5 <= '1';
               wait for 500 us; 
               elsif data_in == 1 then -- кодируем 1
               report ("== 1 ==");
               RB5 <= '1';
               wait for 500 us; 
               RB5 <= '0';
               wait for 500 us; 
            else
               report("Ошибка данных!");
               end if;
         end loop; -- match InLine
       end loop;   -- endfile
       RB5 <= '0';
       file_close(fileVar);
       wait for 15 ms; -- пауза между пакетами
     end loop;  
     wait;
   end process;
  end testbench;

Файл внешних данных с битовой последовательностью:


0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 1 1 1 0 0 0 0 0 0 1 1
1 1 1 0 1 0 1 0 0 1 1 1 0 0 0

В случае применения SCL гораздо проще изменять данные, длину последовательности и временные параметры симулируемого потока, что облегчает проверку алгоритма, обработку ошибок и т.п…

2a71711c08af4ffd8dcd9d1b7e17ca25.png

Скрипт SCL может разбирать входной файл и получать внешние команды. Например, помимо битового потока, можно изменять параметры сигналов.

Пример задания параметров ШИМ-кодированной посылки с синхро-преамбулой (команды парсятся SCL-скриптом и выставлябт соответствующие задержки):
sync_bit_hi 2000 us
sync_bit_lo 500 us
pulse_lo 500 us
pulse_hi_0 500 us
pulse_hi_1 1000 us
1 0 0 0 1 1 0 1
wait 2 ms
1 1 1 1 0 0 0 0 1 0 1 0 1 0 1 0
wait 3 ms
0 0 0 0 1 1 1 1
1 0 1 0 1 0 1 1
wait 15 ms

0bf5b74d27534980981f9964b0d360c9.png

Умение работать с внешними файлами существенно расширяет возможности симуляции. Так, в «репозитории SCL» (ссылка в конце статьи) есть пример получения данных для симуляции из внешнего приложения (Input to a Simulation From an External Application). Данный пример симулирует матричную клавиатуру и входной сигнал для АЦП (написано на VBA в Excel). «Нажатия» кнопок и изменения напряжения записываются в два файла, SCL скрипт читает эти файлы и симулирует изменение логических уровней портов В/В и напряжение на входе АЦП.

fddbe03f875b445c9e15bd60d00b4615.jpg


SCL-программе доступны метки, адреса и переменные отлаживаемого.с или .asm кода. Доступно состояния регистров, программного счетчика микроконтроллера, время симуляции. SCL позволяет формировать несколько параллельных процессов в пределах одного testbench. Например, на одном входе формируем битовую последовательность, читаем данные с другого pin, обрабатываем и управляем состоянием других входов или состоянием регистров микроконтроллера.

Таким образом, SCL помогает организовать testbench-и для отладки кода микроконтроллера. Так как SCL является частью родного симулятора, то в одном проекте и в одном цикле отладки доступны SCL-сценарии (да, к отлаживаемому проекту можно подключать несколько SCL скриптов), точки останова, секундомер, стек, логический анализатор и др., выполняется симуляция периферии (таймера, UART, АЦП и пр.), прерывания и все это работает в одной среде разработки.

Следует отметить и некоторые недостатки текущей реализации SCL:
— ограниченные возможности отладки SCL кода (при подключении к проекту скрипта с ошибкой получаем лишь сообщение типа «ошибка парсера в строке № xx»). Если при подключении скрипта вы получили сообщение о дублировании переменных, то, скорее всего, вы подключили этот же тестбенч второй раз

— некоторые упрощения в текущей реализации (MPLAB X)

Подробнее о SCL можно почитать тут:


© Geektimes