Организация и функционирование ЭВМ\Помощь по HLCCAD\
Руководство по созданию высокоуровневых моделей

Руководство по созданию высокоуровневых моделей

  1. Создание графического представления корпуса устройства
  2. Внешняя модель
  3. Функция создания модели
  4. Формат значений входов/выходов
  5. Память модели
  6. Интерфейс модели IModel
  7. Интерфейс системы IHLCCAD
  8. Интерфейс работы с памятью IMemory
  9. Помощь и документация по работе модели
  10. Примеры высокоуровневых моделей

Создание графического представления корпуса устройства

Каждая высокоуровневая модель представляется в виде графического рисунка. Привязка к модели устройства осуществляется через настройку параметров. Для создания рисунка корпуса устройства и определения контактов необходимо:

  1. Создать (или открыть существующий) проект, в котором предполагается описать устройство, которое в дальнейшем можно будет использовать в других проектах
  2. Создать новое устройство
  3. Отредактировать его корпус (этот корпус будет появляться на схеме, где вы будете использовать это устройство): создать контакты необходимого типа и размерности, установить размеры корпуса и т.п.
  4. В параметрах корпуса нужно указать имя DLL файла (в котором находится модель) и имя модели. Имя файла относительно каталога проекта-владельца.

Внешняя модель

Модель представляет собой двоичный интерфейс (таблица методов интерфейса), который расположен во внешнем исполняемом файле (динамической библиотеке - 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

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

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.