Тема: Часто задаваемые вопросы (FAQ)
1. Что понимается под кодогенерацией, как и в каком виде она создаётся?
Кодогенерация – это процесс автоматического создания программного обеспечения (ПО). Она выполняется на основе текущего загруженного проекта с помощью внешнего подключаемого к САПР модуля расширения. Перед этим происходит автоматическая проверка проекта на удовлетворение всем необходимым для кодогенерации требованиям. По её результатам формируется несколько программных файлов с расширениями *.h и *.c на языке С. Они содержат всю математику, логику и графическую прорисовку, заданную пользователем. Генерируемые САПР файлы представляют собой первую часть из всех необходимых для компиляции исходников. Вторую часть принято называть графической библиотекой. Она позволяет привязать и адаптировать ПО кодогенерации к внешним условиям, в которых оно будет работать. В случае генерации программного кода для операционных систем Windows и Linux, львиная часть графической библиотеки создаётся кодогенератором. Для остальных случаев, она разрабатывается вручную один раз, и в дальнейшем используется в неизменном виде.
В файлах кодогенерации объявляются и создаются тела трёх функций:
OnImitation. Для записи во входные переменные значений подыгрыша или инициализации их значениями из памяти, по адресам указанным для них в проекте САПР.
OnPaint. Это основная функция. Её выполнение аналогично рекурсивному обходу дерева прорисовки в САПР сверху вниз с отработкой логики, вычислениями формул, вызовами функций и вычислительных узлов проекта и прорисовкой графических примитивов.
OnExtraction. Запись значений выходных переменных в память, по адресам заданным пользователем в проекте.
Вызов описанных выше функций кодогенерации происходит из графической библиотеки и выполняется циклически с некоторым временем синхронизации. Функции должны вызываться в приведённом выше порядке. Разработчик графической библиотеки вправе сам решить, в каком месте производить вызов функций. До, после и между вызовами может быть размещён любой необходимый ему программный код.
Формат ПО, создаваемого кодогенератором, максимально адаптирован для дальнейшей реализации прорисовки графики на основе графической библиотеки OpenGL. ПО аппаратно и платформенно независимо и позволяет скомпилировать его под любую программную среду (или операционную систему) на основе любого аппаратного обеспечения. Для поддержания данной абстракции зависимые части выносятся из него и должны быть реализованы в отдельно создаваемом программном коде. Он компилируется совместно с файлами кодогенерации и предоставляет недостающие тела функций, вызовы которых могут содержаться в кодогенерации. К такой внешней функциональности необходимой для дополнительной реализации относятся:
Набор функций управления графическим выводом: смещение и поворот системы координат, 3 вида маскирования, управление сглаживанием, обводкой и заливкой примитивов, выбор выравнивания текста, выбор по индексу текущих цветов и толщин примитивов и их обводки, а также типов рисуемых линий, шрифтов и символов. Частично реализуется внутри графической библиотеки, частично доступными графическими средствами целевой платформы.
Графические примитивы. Реализуются доступными графическими средствами целевой платформы.
Тригонометрические и алгебраические функции. Реализуются вызовами (перенаправлением) аналогичных функций текущей доступной стандартной библиотеки языка C.
Функции работы со строками. Также перенаправляются на функции стандартной библиотеки C.
Кроме реализации описанной выше функциональности, графическая библиотека может выполнять любую другую необходимую ей работу, как самостоятельно, так и с помощью подключения внешних статических или динамических библиотек.
2. Каково назначение создаваемых при кодогенерации файлов?
В файлах InputVar.h/InputVar.c и OutputVar.h/OutputVar.c объявляются соответственно входные и выходные переменные ветви проекта, а так же ветви задачи, для которой выполняется генерация программного кода.
Файлы Imitation.h/Imitation.c содержат функцию инициализации входных переменных OnImitation. Значение переменным присваивается по следующему алгоритму (сверху вниз):
Если для переменной задана инициализация её значением из памяти, то в функцию OnImitation вставляется программный код взятия значения из памяти и записи его в данную переменную.
Иначе, если в настройках кодогенератора включено создание программного кода подыгрыша, и выбранный тестовый сценарий имеет ссылку на данную переменную, т.е. её подыгрывает, то в начало файла Imitation.c и в функцию OnImitation в нём вставляется программный код подыгрыша данной переменной.
Иначе в функцию OnImitation вставляется код инициализации переменной её значением по умолчанию.
Файлы Extraction.h/Extraction.c содержат функцию OnExtraction. Внутри функции формируется программный код записи значений выходных переменных в память. Но в данную функцию попадают только те выходные переменные, в свойствах которых включено сохранение их значений в память. Если для выходной переменной пользователь не включил сохранение, то он может использовать её просто, как глобальную переменную, для хранения и переноса значений между циклами моделирования в САПР или между вызовами OnPaint при отработке кодогенерации.
Вызов функций OnImitation и OnExtraction должен производиться из графической библиотеки. В соответствии с назначением, вызов OnImitation должен осуществляться перед вызовом функции прорисовки задачи OnPaint для инициализации входных переменных, а вызов OnExtraction – после обращения к OnPaint для сохранения в памяти результатов её отработки.
В файлах Paint.h/Paint.c объявляется уже упомянутая функция OnPaint. По сути, она является реализацией содержимого дерева в окне прорисовки в интерфейсе САПР. В неё входит вся логика и математика, описанная пользователем в проекте, по которому производилась генерация программного кода. Так же функция OnPaint содержит вызовы внешних функций прорисовки графики и тела всех задействованных функций вычисления и прорисовки САПР, а так же вычислительных узлов.
Файл GraphLib.h является заголовочным файлом графической библиотеки. В нём содержится объявление ряда функций, тела которых должны быть предоставлены дополнительно. Например, их реализация содержится в описанном ниже файле GraphLibOGL.c или может быть создана вручную в графической библиотеке. Каждый раз, когда кодогенератору в файле Paint.c необходимо изменить графическое состояние, прорисовать примитив или вычислить математическую функцию, в программный код Paint.c вставляется вызов соответствующей функции, объявленной в файле GraphLib.h. Это обеспечивает независимость создаваемого при кодогенерации программного кода от внешней программной и аппаратной среды. Сам файл GraphLib.h не изменяется и для конкретной версии кодогенератора имеет постоянное содержимое.
При включении в настройках кодогенератора опции внешней привязки, автоматически создаются файлы GraphLibOGL.h/GraphLibOGL.c. Они вбирают в себя львиную долю программного кода графической библиотеки и полностью ответственны за прорисовку графики. В них содержится реализация (тела) всех функций, прототипы которых описаны в заголовочном файле графической библиотеки GraphLib.h. Универсальность GraphLibOGL.c/GraphLibOGL.h достигается за счёт использования библиотеки OpenGL и стандартной библиотеки языка С. Но остаются две вещи, работа с которыми в разных ОС может отличаться, – это графические файлы и шрифты. Для операций с ними в файле GraphLibOGL.h объявлена группа функций, которые реализуются в графической библиотеке.
3. Каким инструментарием возможна сборка?
Подойдёт любой компилятор языка С, обеспечивающий формирование исполнительных файлов в формате приемлемом для их выполнения в целевой программной среде.
4. Есть ли возможность проверить корректность функции кодогенерации САПР?
Для проверки корректности кодогенерации предназначаются проекты графических библиотек, которые входят в официальную поставку САПР. Мы распространяем один проект под Microsoft Visual Studio для ОС Windows, и два проекта под Qt Creator для компиляции и выполнения в OC Linux x86 и x64, соответственно.
Такая проверка может быть выполнена, используя ряд проектов САПР, охватывающих все аспекты его функциональности. Необходимо провести кодогенерацию с последующей компиляцией с графической библиотекой каждого из них. Для этого можно использовать одну из поставляемых нами графических библиотек. Полученное программное обеспечение необходимо запустить и визуальным способом проверить на правильность и соответствие тому, что предполагалось в проектах САПР.
5. Каков механизм обеспечения совпадения графики в САПР и бортовом индикаторе?
Файлы, полученные после кодогенерации, представляют собой абстрактный, независящий от конечной программной и аппаратной архитектуры, уровень. Эту зависимость обеспечивает графическая библиотека, с которой файлы кодогенерации должны компилироваться. Именно она привязывает абстрактные вызовы установки графического состояния, прорисовки и вычисления к реальным возможностям аппаратуры и операционной системы (при её наличии). Важно то, чтобы существующее программно-аппаратное окружение смогло покрыть необходимый для файлов кодогенерации функционал. Модель графики в САПР полностью основана на прорисовке треугольника, все графические примитивы рисуются с его помощью. При этом приоритетным является использование библиотек OpenGL и DirectX. Обе эти библиотеки полностью покрывают необходимый для кодогенерации графический функционал. Разработка графической библиотеки для файлов кодогенерации, никак не должна приводить к какому-либо изменению или адаптации содержания кодогенерации. Модель кодогенерации сформирована, она абстрактна и универсальна.
Механизм обеспечения совпадения изображения связан с определённым видом реализации графики в САПР, с особенностями реализации модуля кодогенерации и графической библиотеки для кодогенерации, а так же со способами и видом прорисовки в аппаратуре. Для точного попиксельного совпадения графики в окне САПР с той, что будет прорисовываться созданными при кодогенерации программными файлами, нужно соблюдение двух условий:
Прорисовка в графической библиотеке должна происходить на основе построения треугольников с использованием библиотеки OpenGL или DirectX.
Математика и логика прорисовки в графической библиотеке должна полностью совпадать с той, что используется в САПР.
Для решения данной задачи можно использовать механизм внешней привязки кодогенератора. При его включении дополнительно создаются два файла GraphLibOGL.h/GraphLibOGL.c. Они прорисовывают графику с помощью библиотеки OpenGL в точности, как это делает САПР. Но использовать внешнюю привязку можно только, если вы создаёте программное обеспечение для ОС Windows или ОС Linux. В противном случае, вы можете сами адаптировать файлы GraphLibOGL.h/GraphLibOGL.c для работы в своей среде или заказать эту работу нам.
6. Как организуется информационный обмен с готовой программой, формирующей индикационные кадры?
Кроме локальных переменных, проект САПР может включать в себя входные и выходные переменные.
Входные переменные обеспечивают заведение (получение) значений извне. В САПР значения им задаются механизмом подыгрыша. Для кодогенерации, значения входных переменных так же могут браться из подыгрыша. При этом в настройках модуля генерации программного кода должен быть указан необходимый тестовый сценарий. Кроме этого, в проекте САПР входным переменным может ставиться в соответствие некоторый аппаратный адрес памяти, по которому потом будет браться значение для записи в данную входную переменную. Значение по этому адресу может быть положено непосредственно аппаратурой или графической библиотекой.
Кроме входных, пользователь в САПР может использовать и выходные переменные. При необходимости для них так же может быть указан некоторый адрес. В последующем, при выполнении в аппаратуре, значения выходных переменных будут сохраняться по этому адресу.
7. Какая версия библиотеки OpenGL необходима для прорисовки графики в создаваемом программном обеспечении?
Разработанные нами графические библиотеки для ОС Windows и ОС Linux, ориентированы на первую версию OpenGL, начиная с 1.2. Но для прорисовки графики в созданных с помощью кодогенерации файлах, можно использовать любую версию OpenGL новее 1.1, а так же библиотеку DirectX, начиная с версии 7. В этом случае придётся модифицировать нужную вам существующую графическую библиотеку самим или заказать эту работу у нас.
8. Для чего в кодогенераторе есть поддержка Unicode строк?
САПР является полностью юникод (unicode) приложением. Это значит, что для хранения текстовых строк используются строки состоящие из юникод символов, способных хранить любой символ любого алфавита. Но наличие юникода привело к некоторому дополнительному требованию. Т.к. САПР работает с юникод символами, то создаваемый им программный код также должен иметь возможность отображать эти символы. Иначе говоря, если у вас в проекте используются не только стандартные клавиатурные символы, цифры и символы латинского алфавита, то генерацию программного кода вы должны производить с использованием юникод строк. Это же относится и к графической библиотеке. Она должна работать с тем же набором символов, что и файлы кодогенерации.
9. Хранение текста в виде юникод строк приводит к увеличению потребления памяти. Можно ли с этим что-то сделать?
Никто не заставляет пользователя использовать юникод, хоть данный вид строк и выбран по умолчанию. Вы имеете возможность выбрать в настройках модуля кодогенерации однобайтовый вид строк, но рискуете потерять многие строчные символы в процессе кодогенерации при преобразовании юникод символов в однобайтовые.
10. После объявления и инициализации переменных встречаются примерно следующие конструкции:
uint32 unv_s_mash = (uint32)1;
uint32 unv_m_mash = (uint32)1;
…
unv_s_mash;
vn_m_mash;
Для чего нужно повторное упоминание имён ‘unv_s_mash’ и ‘vn_m_mash’?
Это классический приём в программировании для избежания предупреждений компилятора при объявлении переменной и её неиспользовании. Т.е., если в проекте САПР пользователь создал переменную, но её нигде не использовал, то это позволит избежать предупреждения со стороны компилятора. Это никак не влияет на содержимое и оптимальность конечного машинного кода.
11. Во многих формулах выполняется преобразование типов к int32, что является избыточным и приводит к дополнительной нагрузке на процессор. Для чего это сделано?
Частично – это результат операций приведения, указанных пользователем. А частично – это вызвано соблюдением правил приведения типов по умолчанию, заложенных в вычислитель САПР и необходимых для повторения при кодогенерации. Это достаточно важно, т.к. влияет на повторяемость кодогенерацией логики и математики, описанной пользователем в проекте САПР. В любом случае, не стоит этого бояться. Приведения типов обрабатываются на первых стадиях компиляции, лишние (избыточные) операции не учитываются и не оказывают влияния на конечный машинный код.
12. Для сборки используется стандартная библиотека языка C версии C89, и функция vsnprintf в ней не реализована. Что делать?
Функцию vsnprintf можно заменить вызовом функции vsprintf. Тело функции sfSnprintf при этом будет выглядеть так:
int8 *sfSnprintf(int8 *dst, int32 /*limit*/, int8 const *format, ... )
{ va_list args;
va_start(args,format);
vsprintf(dst,format,args);
return dst;
}
Такая замена должна быть сделана в графической библиотеке или, в случае использования при кодогенерации внешней привязки, в файле GraphLibOGL.c, используя её опции настройки.
К сожалению, при такой замене, защитой от переполнения входящего буфера dst придётся пожертвовать. Понадобятся дополнительные прогоны конечного ПО для проверки, что переполнение ни в каких случаях не происходит. Хотя, такие прогоны и при использовании vsnprintf должны иметь место, для уверенности, что все строки отображаются полностью. Если позволяет оперативная память, то можно несколько перестраховаться, увеличив размер буферов, используемых для хранения строк. В интерфейсе кодогенератора за это отвечает параметр ‘Размер массива’ группы ‘Строки’ закладки ‘Общее’.