Руководство по созданию высокоуровневых моделей
Создание графического представления корпуса устройства
Каждая высокоуровневая модель представляется в виде графического рисунка. Привязка к модели устройства осуществляется через настройку параметров. Для создания рисунка корпуса устройства и определения контактов необходимо:
Модель представляет собой двоичный интерфейс (таблица методов интерфейса), который расположен во внешнем исполняемом файле (динамической библиотеке - DLL), обеспечивающий моделирование поведения устройства. Библиотека должна содержать функцию, которая создает интерфейс и возвращает на него указатель (описание интерфейса модели и другие структуры, связанные с моделированием, описаны в модуле IntTypes в папке Projects\Units). Каждая модель устройства может предоставить VHDL-описание своей работы, чтобы обеспечить автоматическое построение VHDL-описания для схем, в которых используется это устройство. Кроме этого, модель может автоматически сгенерировать схему устройства (в терминах системы), состоящую из более простых устройств (см. Модель SAD).
В общем смысле модель должна подавать на выходы устройства значения в зависимости от значений на входах устройства и/или его внутреннего состояния. Модель может активизироваться в одной из двух ситуаций (иногда в обеих):
Первым способом удобно описывать работу устройств комбинационной логики (когда по значениям на входах определяются значения выходов), а вторым - тактовые генераторы. Обеими - процессоры.
Функция создания модели должна импортироваться из
динамической библиотеки и иметь имя ИМЯ_Init, где
ИМЯ - это имя процедуры, указанное для корпуса
устройства в параметрах моделирования.
Формат функции следующий:
function Device1_Init(HLCCAD: IHLCCAD; Action: integer):IModel; stdcall; exports Device1_Init;
extern "C" IModel** __stdcall __export Device1_Init(IHLCCAD **HLCCAD, int Action)
где
HLCCAD - интерфейс работы с системой
Action - указывает для чего создается модель
Пример
Pascal:
function ROM_Init(HLCCAD: IHLCCAD; Action: integer):IModel; stdcall;
begin
Result := TROM.Create(HLCCAD, Action);
end;
C:
extern "C" IModel** __stdcall __export ROM_Init(IHLCCAD **HLCCAD, int Action)
{
static IModel *m;
m = new ROM(*HLCCAD);
return &m;
}
Формат значений входов/выходов
Значение входых/выходых представляются в виде
двоичной строки, длиной совпадающей с
размерностью контакта. Входное значение может
содержать следующие символы:
0,1 - логические значения 0 и 1 на линии
U - невозможно определить состояние линии
P - запрещенное состояние на линии (устанавливается при одновременном установлении
значений нескольких выходов на линию)
Z - состояние высокого сопротивления (третьего) на линии
Выходное значение, устанавливаемое моделью, должно содержать ТОЛЬКО символы '0','1' и 'Z'.
Система предоставляет модели механизм работы с памятью. Допускается создание памяти (выделение блока указанного размера) или наложение на участок уже выделенной ранее памяти. В обоих случаях будет предоставлен интерфейс управления IMemory. Допускается изменение содержимого непосредственно с памятью. Однако если вся работу с памятью осуществляется через методы интерфейса, то пользователь получает возможность анализировать динамику изменений памяти за любое время из смоделированного диапазона.
Поэтому настоятельно рекомендуется при разработке устройств с памятью (где содержимое памяти существенно для того, кто использует модель) пользоваться внутренним механизмом памяти системы.
Пример:
Mem : IMemory;
// Создадим память
HLCCAD.MemNew("REGISTER", 8, 0, 8, atRead+atWrite+atRegister, Mem);
// Если на вход пришла "1" установим содержимое памяти со значения входа
if (*pGET=='1')
Mem->WriteStr(0, 8, pIn);
IModel = interface(IUnknown)
function Version:integer; stdcall;
// Устройство успешно инициализировано
function Correct:boolean; stdcall;
// Тип модели (обычная модель, генератор VHDL-описания или процессор
function Options:longint; stdcall;
// Не используется
function MemorySize:longint; stdcall;
// Вызывается в 0 момент модельного времени
procedure AutoStart; stdcall;
// Вызывается при изменении значений на входных контактах
procedure OnChanged; stdcall;
// Вызывается в 0 момент времени. Как результат возвращается
// количество модельных единиц через которые
// необходимо повторить вызов. Если результат равен -1 - функция больше
// не вызывается
function ExecAfter:int64; stdcall;
// Вызывается после создания модели устройства и
// всех внутренних системных структур модели
procedure AfterCreate; stdcall;
// Вывести все окна модели на передний план
procedure ShowForms; stdcall;
// Не используется
procedure Syn(AParam: integer); stdcall;
// Вызывается перед удалением модели
procedure OnDestroy; stdcall;
// Данная группа функций не используется
procedure DizAssembler(Data:Pointer; var AsmLine, LabelLine, DebugLine : PChar); stdcall;
function GetInstrSize(Data : byte):integer; stdcall;
Function GetMaxInstrLength: integer; stdcall;
Function IsInstructionRun: integer; stdcall;
Function GetCodeMemoryWordSize: integer; stdcall;
Procedure Save; stdcall;
Procedure Load; stdcall;
// Получить имя VHDL-устройства модели
// Имя должно быть уникальным для соответсвующей конфигурации
// курпуса устройства (контактов, параметров).
Function VHDLGetName: PChar; stdcall;
// Процедура строит VHDL-описание и передёт полученный текст
// через функцию IHLCCAD.InsertVHDLString
Procedure VHDLBuildDescribe; stdcall;
// Процедура генерирует подключение необходимых дополнительных библиотек
// через функцию IHLCCAD.InsertVHDLString
Procedure VHDLLibraryDescribe; stdcall;
// Не используются
Procedure SaveEvent (ME: TModelEvent); stdcall;
Function LoadEvent (HE: THLCCADEvent): TModelEvent; stdcall;
procedure ExecEvent (ME: TModelEvent); stdcall;
// Получить количество выполненных моделью инструкций (для процессоров)
function GetExecutedInstructionCount:integer; stdcall;
end;
IHLCCAD = interface(IUnknown)
// Возвращает True если после последнего вызова хоть один вызов GetContact был безуспешным.
function LinkFault:boolean; stdcall;
procedure ErrorMsg (Code: integer; Param: pointer); stdcall;
// Признак что моделированию нужно остановить
function TerminationOn:boolean; stdcall;
// Handle главного окна
function MainHandle: HWND; stdcall;
// Получить текущее модельное время
function GetTime:comp; stdcall;
// Получить значение параметра по имени
Procedure GetDeviceParamValue (S: PChar; Var Data: Pointer; Var Size: integer); stdcall;
// Получить имя контакта
function GetContactName(Contact: pointer):PChar; stdcall;
// Получить параметры контакта
function GetContactCType (Contact: pointer):word; stdcall; // ctXXXX
function GetContactMType (Contact: pointer):word; stdcall; // mtXXXX
function GetContactPType (Contact: pointer):word; stdcall; // ptXXXX
// Получить задуржку устройства
function GetDeviceDelay:comp; stdcall;
// Получить размерность контакта
function GetContactDim(Contact : pointer):longint; stdcall;
// Получить количество контактов на корпусе
function GetContactCount:longint; stdcall;
// Найти контакт по имени
function GetContact(Name : PChar):pointer; stdcall;
// Получить контакт по номеру
function GetContactAt(i : integer):pointer; stdcall;
// Получить указатель на значение контакта (только для чтения)
function GetContactValue(Contact : pointer):PChar; stdcall;
// Получить значение на контакте в бинарном виде
function GetValidContactValue(Contact : pointer):PChar; stdcall;
// Установить значение на контакт
procedure SetContactValue(Contact : pointer; Value : PChar); stdcall;
// Установить все линии контакта в Z состояние
procedure SetZ(Contact : pointer); stdcall;
// Не используются
Procedure ReadBytes(Addr,Count : integer; Var Buf); stdcall;
Procedure WriteBytes(Addr,Count : integer; Var Buf); stdcall;
function LoadMemoryFromTextFile(ACapacity : integer; AName : PChar):integer; stdcall;
function CreateMemory(Size : integer; Name : PChar) : integer; stdcall;
function mLoadMemoryFromTextFile(Index : integer; ACapacity : integer; AName: PChar):integer; stdcall;
function mReadValue(Index,Addr,Count : integer):PChar; stdcall;
Procedure mWriteValue(Index,Addr : integer; Value : PChar); stdcall;
Procedure mReadBytes(Index,Addr,Count : integer; Var Buf); stdcall;
Procedure mWriteBytes(Index,Addr,Count : integer; Var Buf); stdcall;
function CreateValue(AName: PChar; AAddr,ASize: integer) : pointer; stdcall;
function mCreateValue(Index : integer; AName: PChar; AAddr,ASize: integer) : Pointer; stdcall;
function ReadValue(Addr,Count : longint):PChar; stdcall;
procedure WriteValue(Addr : longint; Value : PChar); stdcall;
// Добавить строку VHDL-описания устройства
procedure InsertVHDLString(S: PChar); stdcall;
// Получить параметры генерации VHDL-описания
function GetVHDLOptions : integer; stdcall;
// Получить путь каталога с проектом схемы
function GetProjectPath : PChar; stdcall;
// Конвертировать файл прошивки в HEX формат
Procedure SaveMemFileAsHex (SourceFileName, DestFileName: PChar);
// Не используются
function GetPosition:integer; stdcall;
procedure SetPosition(APos: integer); stdcall;
function Seek(Offset: Longint; Origin: Word): Longint;
procedure ReadBuffer(Dest: pointer; Count: integer); stdcall;
procedure WriteBuffer(Source: pointer; Count: integer); stdcall;
// Изменить параметры модели
procedure SetModelOptions(AOptions: integer); stdcall;
// Добавить дополнительный обработчик события после времени Time
function AddEvent(ME : TModelEvent; ALevel: integer; Time : comp) : THLCCADEvent; stdcall;
// Удалить обработчик
procedure DelEvent(HE : THLCCADEvent); stdcall;
// Изменить подвремя (используется для более точного моделирования)
procedure SetSubTime(ASubTime: comp); stdcall;
// Получить интерфейс контакта IContact
procedure GetContactInterface (AContact: pointer; Var P:IContact); stdcall;
// Получить текущее время анализа (для отображения значений из истории контактов
function GetViewTime:comp; stdcall;
// Установить анализируемое время
procedure SetViewTime (ATime: comp); stdcall;
// Получить путь к файлу модели
function GetModelPath:PChar; stdcall;
// Получить имя файла проекта
function GetSourceProjectName: PChar; stdcall;
// Получить значения параметров устройства
Procedure SetDeviceParamValue(S : PChar; Value : Pointer; Size : integer); stdcall;
Procedure SetDeviceParamData(S : PChar; Data : Pointer; Size : integer); stdcall;
Procedure GetDeviceParamData(S : PChar; Var Data : Pointer; Var Size : integer); stdcall;
// Добавить строку в лог
procedure Log(aMsg: PChar; aImmediately: boolean); stdcall;
function GetHInstance:cardinal; stdcall;
// Дать системе обработать полученные сообщения
procedure Idle; stdcall;
// Создать внутреннюю память модели
procedure MemNew (aName: PChar; aBitSize, aBitOffset, aBPW: integer; aOptions: word; Var IMem : IMemory); stdcall;
// Зарегестрировать внутреннюю память модели
procedure MemReg (aName: PChar; aBuffer: pointer; aBitSize,aBitOffset,aBPW: integer; aOptions: word; Var IMem : IMemory); stdcall;
// Получить опции системы
function CheckFlag(cfFlag: integer):integer; stdcall;
// Изменить задержку устройства
procedure SetDeviceDelay(const aDelay: comp); stdcall;
// Получить стартовый каталог для генерации VHDL-описания
function GetVHDLoutputDir:pchar; stdcall;
// Получить название текущего языка системы
function GetLanguage:pChar; stdcall;
// Получить текущий режим компиляции устройства
function GetCompileMode:integer; stdcall;
// Получить текущее модельное время
function GetMTime : integer; stdcall;
// Не используется
function RunInstruction(aInstrType : TInstrType) : boolean; stdcall;
// Добавить сообщение в систему
procedure AddMsg(MSGType : integer; Text : PChar); stdcall;
// Скомпилировать WInter проект программного обеспечения
function CompileWProject(FileName : PChar) : HResult; stdcall;
// Получить имя корпуса устройства
function GetCorpusName : PChar; stdcall;
// Остановить процесс симуляции
function StopSimulateProcess : HResult; stdcall;
end;
Интерфейс работы с памятью IMemory
IMemory = interface(IUnknown)
// Создать новый наложенный интерфейс доступа к памяти
procedure Map(aName: PChar; aBitAddr, aBitSize, aBitOffset, aBPW: integer; aOptions: word; Var IMem : IMemory); stdcall;
function GetPtr:pointer; stdcall;// Return first byte ptr for direct access
// Чтение/Запись содержимого памяти
procedure ReadBits (aBitAddr, aBitSize: integer; aDst: pointer); stdcall;
procedure WriteBits (aBitAddr, aBitSize: integer; aSrc: pointer); stdcall;
procedure WriteBytes(aByteAddr, aByteSize: integer; aSrc: pointer); stdcall;
procedure ReadStr(aBitAddr, aBitCount: integer; aDst: PChar); stdcall;
procedure WriteStr(aBitAddr, aBitCount: integer; aSrc: PChar); stdcall;
procedure Readln(aDst: pointer); stdcall; // write all!
procedure Writeln(aSrc: pointer); stdcall; // write all - Optimized!
// Загрузка сожержимого файла прошивки
function LoadFromFile(aFileName: PChar):boolean; stdcall;
// Управление режимом трассировки
Procedure SetTraced(F : boolean); //stdcall;
function GetTraced : boolean; stdcall;
// Установить имя регистра-указателя для отладки по шагам (для кодовой памяти обычно PC)
procedure SetPointerName(P : PChar); stdcall;
end;
Помощь и документация по работе модели
Файл с описанием функционирования устройства указывается в редакторе корпуса в параметре "Файл помощи". Имя файла может быть указано относительно имени файла проекта.
Помощь по устройству может быть получено из локального меню в инспекторе проектов, в редакторе схемы и отладчике.
При вызове помощи для устройств в редакторе устройств и отладчике происходит поиск файла помощи в ниже указанном порядке:
Для инспектора проектов поиск производится по дереву вложенности до тех пор, пока не найдётся установленный файл помощи к элементу. Если файл помощи найден, но он установлен не для текущего элемента, то дополнительно указывается переход по ссылке "имя элемента".
Поиск файла осуществляется поэтапно:
Следует также отметить, что в качестве помощи могут выступать файлы произвольного формата. Однако отображение доступно лишь для файлов в формате HTML и тех, для которых установлено приложение поддерживающее технологию электронных документов (OLE).
Для SAD устройств можно получить из меню "Помощь|SAD". Поиск файлов осуществляется по вышеописанному способу.
Ещё один из способов документирования - создание пошагового учебника. Все учебники доступны из главного меню "Помощь|Учебник". Список учебников строится при обращении к вышеописанному пункту меню: анализируются подпапки в Help\"Название языка"\Teach. В папке должен находится файл "Dirinfo". Первая строка в файле - это название учебника. В файле "contents.lst" перечисляются названия тем учебника. Каждой теме соответствует файл "N.htm" с содержанием данной темы. N - номер темы (нумерация с 0).
Примеры исходных текстов высокоуровневых моделей: Indicators, InOut, SMPort.