nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 18 Mar 2024 20:02



Reply to topic  [ 295 posts ]  Go to page 1, 2, 3, 4, 5 ... 20  Next
Proteus C++ DLL's 
Author Message
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Я как-то вплотную, наконец, добрался до цифровых моделей "Proteus", создаваемых как библиотеки DLL, написанные на C++.

Основной вопрос, почему библиотеки, созданные разными компиляторами C++, по разному воспринимает "Proteus",
мы совместными усилиями уяснили - всё дело в несколько разной реализации не указанных явно соглашений о
вызове функции у разных компиляторов
C++.
И поскольку мы решили поработать над серьёзной моделью процессора, я позволю себе сказать несколько слов
о принципах симуляции в "Proteus", чтобы мы одинаково понимали, как саму задачу, так и друг друга, и не возвращались
к этому по ходу дела.


В "Proteus" (да и в Electronics Workbench) моделирование цифровых и аналоговых устройств реализовано несколько разными путями, хотя, по сути, основной принцип схож.

В аналоговом устройстве симулятор "просматривает" схему, которую мы рисуем на графической консоли, и автоматически составляет по нашему рисунку SPICE-модель. При включении симуляции, SPICE-библиотека пакета симуляции составляет систему нелинейных дифференциальных уравнений методом узловых потенциалов и решает её (интегрирует) численными методами трапеций или Гира. Поэтому, если "Proteus" (или Electronics Workbench, а они оба используют похожую SPICE-библиотеку) не может что-то посчитать, не надо называть программу г...ном, а надо вспомнить, что она "играет как велели", и может быть, следует заменить численный метод трапеций на метод Гира (он безусловно устойчив), выбрать более мелкий шаг или изменить точность.

Image

Image

Очень большое значение порой имеет выбор начальных условий.

Image

Хорошо настроенный симулятор даёт точность расчета 95-98%.

Значит основной принцип симуляции аналоговых устройств - сдвиг малыми шажками по времени и одновременное интегрирование системы дифференциальных уравнений, описывающих нашу схему, на каждом таком интервале. Этот результат расчета мы обычно и видим в качестве осциллограммы.

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

Image______ Image
Реальный сигнал и чисто "цифровой" сигнал

Отсюда и "нежелание" симуляторов хорошо моделировать цифровые схемы мультивибраторов и прочих генераторов, где используются аналоговые свойства цифровых вентилей. То есть, где инвертор выступает в роли аналогового усилителя, что в реальности так и есть!
В таких случаях инвертор приходится собирать для точности эмуляции, как аналоговое устройство по его внутренней схеме, что я как-то с этой целью тут у нас и делал.

Если схема смешанная: аналоговая и цифровая (а так получится, если просто ввести хотя бы привычный всем генератор на кварце), то работают оба метода - интегрирование системы дифференциальных уравнений и обсчет цифровой части, что очень замедляет симуляцию.
Поэтому в "Proteusе" для моделирования больших чисто цифровых схем рекомендуют применять только цифровые компоненты: цифровые источники сигнала, "цифровые конденсаторы и резисторы" (как это ни странно звучит! :o но учитывается только задержка) и цифровые вентили, у которых нет протяженных фронтов, спадов, прямых и обратных переходных процессов. Только задержки распространения.

Если этот принцип всем понятен, и никто не считает, что надо что-то уточнить, то дальше перейдём к тому, как в "Proteus" реализуется цифровая модель в форме динамической библиотеки, а она гораздо быстрее всех прочих видов моделей, почему я, наконец, и решил ими вплотную заняться.
<hr>
Любая модель в "Proteus" состоит из двух частей: графической, которую мы видим на экране в виде условного графического обозначения симулируемого элемента, и, собственно, "симулирующей" поведение элемента, в качестве которой может выступать SPICE-модель, схемотехническая модель, модель в представлении Proteus-а, и DLL-модель, написанная на C++.
В нашем случае мы будем использовать DLL-модель, написанную на C++.
В дальнейшем изложении я опираюсь на документ Creation VSM - Modelos Digitales.PDF, который описывает создание модели довольно кратко и доходчиво, но с некоторыми опечатками и на английском языке. Но, тем не менее, вся процедура была мной проверена и приводит к нужным результатам.

Начнём с создания графической части модели.
В качестве тестового экземпляра я решил попробовать создать несколько упрощенный аналог прозрачной защёлки К155ТМ2, чтобы попробовать привязку к конкретным временным задержкам данной микросхемы, и чтобы мы смогли обсудить механизм создания "времянки".

Image

С К155ТМ2 трудностей быть не должно, т.к. мы хорошо представляем принцип её работы и нам будет потом с чем провести сравнительные тесты (я имею в виду готовую модель данной микросхемы в представлении Proteus-а).

Итак, открываем новый проект Proteus и начинаем создавать условное графическое обозначение одного элемента защёлки К155ТМ2. С этой целью будем использовать графические примитивы Proteus-а: прямоугольник, эллипс, линию и надпись.
Помещаем на рабочее поле проекта прямоугольник заготовки логического элемента.

Image

Размеры прямоугольника можно изменять, растягивая и сжимая его изображение курсором мыши за показанные на рисунке "реперные" метки.

Неплохо предварительно убедиться, что шаг сетки выставлен, равным 100. К сетке с таким шагом желательно "привязать" этот прямоугольник и выводы элемента. Остальные детали можно (и местами даже нужно) "привязывать" к более мелкой сетке. Но сетка с шагом, равным 100, выставляется по умолчанию, и по ней идут соединения элементов. Выводы, "привязанные" к более мелкой сетке могут искривляться на схеме.

Честно говоря, то, что мы нарисуем, никак не повлияет на функциональность модели, но я предпочитаю условное графическое обозначение близкое отечественному ГОСТУ и пропорциональное по отношению к остальным логическим элементам схемы…

Добавим линию…

Image

Установим текстовое обозначение элемента…

Image

Элементы внутри прямоугольника удобнее выставлять по самой мелкой сетке с шагом, равным 10.

Image

Укажем "начало координат" нашего элемента, относительно которого позиционируются остальные элементы схемы (иногда его устанавливают на начало левого верхнего вывода)…

Image

Теперь, установив шаг сетки, равным 100, будем располагать выводы логического элемента:

Image

Как только мы помещаем каждый вывод на лист проекта, сразу же придётся ввести необходимые обозначения во вкладке редакции свойств вывода (Edit Pin).
И это очень важный момент, поскольку…
Имена выводов (Pin Name) "C, D, Q, /Q" - это то единственное, что связывает нашу картинку с DLL-моделью!

Номера выводов (Default Pin Number) - это параметры, используемые при разводке печатной платы по разработанной схеме…




На рисунке также обозначены остальные параметры выводов, которые необходимо выставить во вкладке.
Входы элемента можно обозначить как Passive или Input, ну а выходы - Output.

После того, как элемент обзавёлся выводами, добавим под его изображением текстовый скрипт его свойств:

Image

Сразу же появится текстовое окно, куда необходимо ввести следующие строки:
Code:
{*DEVICE}
NAME=DCFF
{PREFIX=DD}
{*PROPDEFS}
{MODDLL="VSM Model DLL",HIDDEN STRING}
{PRIMITIVE="PrimitiveType",HIDDEN STRING}
{*COMPONENT}
{MODDLL=Flipflop.dll}
{PRIMITIVE=DIGITAL,DCFF}

Их можно непосредственно скопировать и вставить в окно Edit Script Block:

Image

В принципе изначально достаточно только следующих строк:
Code:
{*DEVICE}
NAME=DCFF
{PREFIX=DD}

Они обозначают, что под нашим элементом на схеме будет появляться обозначение DCFF, что в сокращенном виде предполагает, что это тактируемый по входу C D-триггер-защелка (Flip-Flop). Можно написать K155TM2 латиницей, можно написать что угодно, но под этим именем мы будем в дальнейшем находить нашу модель триггера в библиотеке Proteus.
Префикс {PREFIX=DD} - это обозначение, которое с порядковым номером будет появляться над нашим элементом в симуляциях: DD1, DD2, DD3… и т.д.

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

Рассмотрим остальные параметры:
{*PROPDEFS}
{MODDLL="VSM Model DLL",HIDDEN STRING}


эта строка обозначает, что нашу модель будет симулировать DLL-библиотека.

{PRIMITIVE="PrimitiveType",HIDDEN STRING}

изображение нашей модели создано из графических примитивов

{*COMPONENT}
{MODDLL=Flipflop.dll}


DLL-библиотека, симулирующая наш графический примитив носит название Flipflop.dll - я выбрал такое, ограничений никаких нет. (Эта строка - связка графической части модели с симулирующей DLL-библиотекой).

{PRIMITIVE=DIGITAL,DCFF}
модель цифровая и связана с классом элементов DCFF (имя элемента DCFF и класс могут не совпадать, так как в классе может быть описано сразу несколько похожих по свойствам элементов).

После того, как указанный текстовый скрипт введен, наша графическая часть модели готова к компиляции в библиотеку Proteus.

Image
<hr>
Я так подробно рассмотрел создание графической части модели, чтобы у всех было ясное представление о том, какой графический примитив отвечает за ту или иную часть отрисовки условного графического обозначения логического элемента в проекте Proteus, чтобы в случае необходимости можно было оперативно нужный примитив использовать.

В действительности, есть возможность этот процесс в значительной мере ускорить, если воспользоваться наиболее близким к желаемому готовым условным графическим изображением элемента из существующих библиотек Proteus.
В нашем случае без особо долгих раздумий я выбрал бы модель JK–триггера JKFF из меню выбора элемента (Pick Devices), в подразделе "Примитивы Моделирования" (Modelling Primitives) – как это видно на следующем рисунке.

Image

Но меня, прежде всего, интересовал вопрос, как авторы Proteus разрешили вопрос с уникальными именами для вывода "Q" и его инверсии "/Q", которые нам необходимы для связи с нашей DLL-моделью. Дело в том, что в Proteus есть специальный префикс к имени вывода$Q$, в результате применения которого инверсный вывод отрисовывается на схеме точно, как принято в ГОСТ–е.

Image

Но вот поймёт ли сам Proteus это имя$Q$как уникальное, я сомневался, и авторы этот префикс к имени инверсного выхода также не применили. Именно поэтому я применил обозначение "/Q", поскольку "!Q", мне не понравилось.
Но у aav8 это получилось: pinReset=instance->getdsimpin("$RESET$",true); // Reset

После того, как мы поместим выбранную в подразделе "Примитивы Моделирования" (Modelling Primitives) модель JK–триггера JKFF на чистый лист нового проекта Proteus, нам следует провести её декомпозицию, то есть, разобрать модель на графические примитивы, выводы и текстовый скрипт её описания.
Для этого выделим рисунок модели контуром, как на рисунке, или активизируем её правым кликом мыши, чтобы модель стала красного цвета, после чего в меню Library выберем опцию Decompose (или кликнем соответствующую пиктограмму молотка в панели инструментов).

Image

После того, как графическое изображение модели разделено на отдельные составляющие, в первую очередь необходимо отредактировать текстовый скрипт её свойств, заменив его нашим собственным.
Code:
{*DEVICE}
NAME=DCFF
{PREFIX=DD}
{*PROPDEFS}
{MODDLL="VSM Model DLL",HIDDEN STRING}
{PRIMITIVE="PrimitiveType",HIDDEN STRING}
{*COMPONENT}
{MODDLL=Flipflop.dll}
{PRIMITIVE=DIGITAL,DCFF}

Эта предосторожность связана с тем, что если мы по ошибке позже скомпилируем измененную нами модель, не изменив её текстового скрипта, то мы безвозвратно уничтожим в библиотеке Proteus исходную модель, взятую нами за образец. Конечно, нас об этом предупредят не раз, но мы очень привыкли нажимать зачастую "Next" и "Yes", не читая, что нам там пишут на этом английском… :wink:

Итак, построенная тем или другим способом графическая часть модели Proteus готова к компиляции в его библотеку!

Именно таким способом мы сконструируем условное графическое обозначение микропроцессора i8080 из имеющейся графической модели процессора Z80.

Image

Если у кого-либо этой модели в наличии нет, но есть желание принять участие в нашем проекте,
я исходную модель микропроцессора Z80, разобранного на примитивы, здесь прилагаю.

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

Image
Файл проекта, подробности - здесь...

И следующее, что я наметил в наших планах, — рассмотреть последовательность компиляции графической части модели в библиотеку Proteus.
<hr>
Рассмотрим в деталях процедуру компиляции графической части модели в библиотеку Proteus.
Выделим рисунок модели контуром, захватывая текстовый скрипт, как это показано на следующем рисунке.
Для этого обводим, удерживая левую кнопку мыши, наш рисунок, включая текстовый скрипт, и в меню Library выбираем опцию – Маке Device – создать устройство. Эту же операцию можно вызвать, кликнув по пиктограмме – Маке Device – в панели инструментов.

Image

Далее в этом процессе создания устройства для ввода параметров модели на экране последовательно появятся пять вкладок.
В первой вкладке отражаются строки
Code:
{*DEVICE}
NAME=DCFF
{PREFIX=DD}

Image

Остальные поля этой вкладки в нашем проекте не используются.

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

Image

На следующей вкладке отражены следующие строки текстового скрипта:
Code:
{*PROPDEFS}
{MODDLL="VSM Model DLL",HIDDEN STRING}

{*COMPONENT}
{MODDLL=Flipflop.dll}

Image
Code:
{PRIMITIVE="PrimitiveType",HIDDEN STRING}
...
{PRIMITIVE=DIGITAL,DCFF}

Image

Следующая вкладка позволяет сопоставить нашей модели help–файл…

Image

И на последней вкладке в окна Категория устройства (Device Category) и Изготовитель устройства (Device Manufacturer) установим через сопутствующие кнопки New соответственно Прочее (Miscellaneous) и ExUSSR (я обычно делаю так, поскольку чаще всего подходящей фирмы-изготовителя в списке не находится). Принципиального значения эти настройки не имеют, и делается это более для того, чтобы не потерять нашу модель позже в оригинальных библиотеках Proteus. Поэтому, если есть желание, можно заполнить и поля Описание устройства (Device Description – я написал здесь D-Flip-Flop), а также Заметки по устройству (Device Notes - Test model).

Image

Скорее всего, Proteus предложит разместить нашу модель в библиотеке USERDVC и другой альтернативы не предоставит.
Заканчиваем процесс создания устройства нажатием кнопки ОК.

Вновь созданная модель DCFF теперь существует в библиотеке USERDVC Proteus, она доступна для выбора любому проекту из вкладки Выбор Устройства (Pick Devices).

Image

После выбора наша модель также появляется в левой панели выбора устройств (DEVICES), что позволяет поместить её на лист проекта и запустить проект на симуляцию.

Image

Попытка симуляции закончится ошибкой компиляции проекта симулятором:
Quote:
SIMULATION LOGS
===============
...
FATAL: [ OD1 ] External model DLL "FLIPFLOP.DLL" not found. GLE=.0x00000002.
Simulation FAILED Due To Fatal Simulator Errors.

Что совершенно справедливо, поскольку Flipflop.dll мы ещё не написали.

Это и будет нашим следующим этапом: написать требуемую динамическую библиотеку в среде MSVC++, придерживаясь правил и соглашений VSM SDK от Labcenter Electronics, скомпилировать нашу Flipflop.dll и поместить её в папке MODELS в директории, где установлен симулятор Proteus.

Продолжение следует...

_________________
iLavr


Last edited by Lavr on 23 Feb 2015 09:57, edited 25 times in total.



17 Nov 2012 06:56
Profile
Maniac

Joined: 05 Nov 2008 19:47
Posts: 287
Location: 81.28.208.238
Reply with quote
Post 
Quote:
Джентльмены, я выложил материал по библиотекам "Proteus". Если вам не трудно,
посмотрите, может ли быть DLL-библиотека для "Proteus" скомпилирована под
Borland C++ Builder 5.0, в частности?

У меня Borland C++ 5.01
Попробую на нем
Но к сожалению времени пока особо нет..


17 Nov 2012 09:33
Profile
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Создание DLL-библиотеки цифровой VSM-модели под Proteus в среде MSVC++ 5.0

Частично мы уже касались обсуждения этого вопроса, некоторая непонятность
в котором заключается в том, что рекомендуется писать эти DLL сугубо на MSVC++,
причем самых последних версий... :-?

Мы пришли к выводу, что вроде бы писать эти DLL-библиотеки ничто не должно
помешать и на других версиях C++, но как мы выяснили далее, существует
проблема, заключающаяся в несколько разной реализации не указанных явно
соглашений о вызове функции у разных компиляторов C++.

Поэтому сразу скажу, что нашу тестовую VSM-модель под Proteus я буду доводить
до DLL-библиотеки в среде MSVC++ 5.0.
Без MSDN этот пакет совсем небольшой (дистрибутив 81 МБайт), так что в случае
типичной (или даже минимальной) установки у меня он вполне приемлемо
"присоседился" рядом с Borland C++ Builder 5.0 и Microsoft Visual C++ 1.0. :wink:
На последнем я учился основам C++ весьма давно, у него хорошие "хелпы" с
примерами, и он был более расточен под понятные мне вызовы функций Win API,
нежели современные "компиллеры", где всё упрятано в "обёртки и абстракции"... :-?
Это я к тому, что если у вас только "голый и компактный" MSVC++ 5.0, то на "хелпы"
без MSDN и не надейтесь... :wink:

Но приступим к делу... Сразу скажу, что я не самый продвинутый "писец" на C++, :lol:
но рискнул взяться за эту затею, поскольку C++ я преимущественно использую
именно для написания динамических библиотек (DLL), поскольку в современных условиях,
работая под Вендой, без них практически невозможно получить простой программный
доступ к управлению аппаратурой. И для написания DLL я выбрал именно C++, поскольку
в WIN32 написание DLL довольно-таки не трудно, и сам я со своими задачами справляюсь...

А прочитав документы по VSM SDK, я пришел к выводу, что написание DLL под Proteus -
не намного сложнее...
Команда Labcenter Electronics не занималась "вредительством", :lol: а приготовила вполне
продуманный, хотя и не бесплатный, интерфейс к моделям, который нам следует соблюсти
по соглашениям, указанным в VSM SDK, а внутри - при реализации движка модели - язык
C++ в выразительных средствах ничуть не хуже всех остальных... :wink:
<hr>
Итак, чтобы напомнить тем, кто берётся за это дело в первый раз, в среде MSVC++ 5.0
проект DLL-библиотеки создаётся так:

Меню [File] -> опция [New]: Project - Win32 Dynamic-Link Library

и раз уж мы создаём Flipflop.dll для цифровой модели DCFF (тактируемый по входу C, D-
триггер-защелка (Flip-Flop)), то в окне Project Name укажем: Flipflop.

Пустой проект Flipflop создан. Добавляем в него основной файл проекта - Flipflop.cpp:

Меню [Project] -> опция [Add To Project] ->[New]: C++ Source File ->
-> File name: = Flipflop.cpp.

В пустой основной текстовый файл проекта заносим следующее содержание:
Code:
//----- Основной файл модели Flipflop.cpp ------------------------------------
#include "stdafx.h" // - заголовочный файл нужен для обеспечения возможности
//---                    включения предкомпиляции заголовков.
#include "vsm.hpp"  // - заголовочный файл VSM API от Labcenter Electronics.
#include "FFDEVICE.h" //-заголовочный файл для реализации класса нашей модели.

//---------------------------------------------------------------------------
#define model_key 0x00000000 // - код авторизации от Labcenter Electronics
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//--- Ключевое слово __declspec с атрибутом dllexport помечает функцию как
//--- экспортируемую, имя функции добавляется в таблицу экспорта dll.
//---------------------------------------------------------------------------
//--- Функция IDSIMMODEL *createdsimmodel(...) реализуется для цифровой модели,
//--- для функционирования режима пакетной обработки (batch mode operation).
//--- Proteus может работать в интерактивном режиме, когда симуляция выполняется
//--- в реальном времени, либо в пакетном режиме (batch mode), когда симуляция
//--- осуществляется просто так быстро, как это возможно.
//--- 
extern "C" IDSIMMODEL __declspec(dllexport) *createdsimmodel (CHAR *device, ILICENCESERVER *ils)
{
//--- Параметры функции:
//--- CHAR *device - тип примитива в среде симлятора, к которому присоединена
//---                ваша активная модель.
//--- Вы можете использовать этот параметр, чтобы реализовать различные другие
//--- DSIM классы модели в пределах одной DLL, или поддерживать различные изменения
//--- в её поведении определённому типу имени, указанному в параметре PRIMTIVE
//--- текстового скрипта модели.
//--- ILICENCESERVER *ils - интерфейс к лицензионному серверу (Licence Server).
//---                Ваша активная модель должна пройти процедуру лицензирования,
//--- по коду model_key от Labcenter Electronics, иначе она не будет обслуживаться.
//--- Чисто коммерческая опция.

//--- Возвращаемая величина:
//--- IDSIMMODEL *   - указатель на класс в вашей модели, который должен быть
//---                 производным от IDSIMMODEL интерфейса.

//--- Тест входа в функцию createdsimmodel-----------------------------------
//---         MessageBox(0,"Выполняется авторизация модели!",
//---                          "Внимание!",MB_ICONERROR);
   if(ils->authorize(model_key))
     {
//--- Тест выхода из функцию authorize(model_key) ---------------------------
//---             MessageBox(0,"Модель прошла авторизацию!",
//---                          "Внимание!",MB_ICONERROR);
       return new FFDEVICE; // - указатель на класс модели FFDEVICE
     }
    else
     {
//--- Тест, что авторизация модели не прошла --------------------------------
            MessageBox(0,"Авторизация модели не прошла: [NULL]!",
                         "Внимание!",MB_ICONERROR);
      return NULL;
     }
}

//---------------------------------------------------------------------------
//--- Функция вызывается PROSPICE, когда пользователь заканчивает сеанс симуляции.
//--- Функция должна освободить все ресурсы, которые содержала модель, обычно вызывая
//--- деструктор.
extern "C" VOID __declspec(dllexport) deletedsimmodel (IDSIMMODEL *model)
{
   delete (FFDEVICE *)model; // - указатель на IDSIMMODEL интерфейс, который был ранее
                             // - создан функцией createdsimmodel.
}

//---------------------------------------------------------------------------
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
//---  if(fwdreason==DLL_PROCESS_ATTACH) //- Если проецируется на адр.простр.
//---    {
//---          MessageBox(0,"DLL проецируется на адресное пространство",
//---                        "Внимание!",MB_ICONERROR);
//---    }
 return 1;
}
//---------------------------------------------------------------------------
/* В Win32 определена специальная функция обратного вызова (Callback-function)
системного уровня с именем, которое может задаваться пользователем
(это пользовательская функция, вызываемая системой).
Как правило, на нее ссылаются как на DllEntryPoint. Но DllEntryPoint может иметь
практически любое имя; иногда это DllMain.
Когда вызывается функция Win API LoadLibrary(), модуль DLL загружается в память.
Затем вызываетяс код инициализации библиотеки.
Система проверяет, экспортирует ли программист в модуле функцию DllEntryPoint и
задал ли он её имя при помощи компоновщика.
Если имело место и то, и другое, система вызывает функцию DllEntryPoint. Прототип
этой функции на языке С:
BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL,  дескриптор библиотеки
                          DWORD fdwReason,     флаг причины вызова
                          LPVOID lpvReserved); детализация вызова
Параметр fdwReason:DWORD содержит значение, соответствующее причине, по которой
была вызвана функция DllEntryPoint.
Система вызывает DllEntryPoint в четырех случаях; соответственно, fdwReason может
иметь одно из четырех значений:
   DLL_PROCESS_ATTACH Процесс отображает DLL в своё адресное пространство
   DLL_PROCESS_DETACH Процесс прекращает отображение DLL в своё адресное пространство
   DLL_THREAD_ATTACH Создается поток в адресном пространстве процесса, отобразившего DLL
   DLL_THREAD_DETACH Поток, находившийся в том же адресном пространстве, куда отображена
                     DLL, удаляется.*/
//---------------------------------------------------------------------------

Я прокомментировал этот файл максимально подробно в его тексте, поэтому ничего
более объяснять не буду...

Добавляем в проект объявленный ранее в начале Flipflop.cpp заголовочный файл stdafx.h:

Меню [Project] -> опция [Add To Project] ->[New]: C/C++ Header File ->
-> File name: = stdafx.h.
Code:
//----- Заголовочный файл stdafx.h ------------------------------------
// stdafx.h: включаемый файл для стандартных системных включаемых файлов
// или включаемых файлов для конкретного проекта, которые часто используются,
// но не часто изменяются
//

#pragma once

#define WIN32_LEAN_AND_MEAN  // Исключите редко используемые компоненты из заголовков Windows
// Файлы заголовков Windows:
#include <windows.h>


// TODO. Установите здесь ссылки на дополнительные заголовки, требующиеся для программы

Добавляем в проект файл stdafx.cpp:

Меню [Project] -> опция [Add To Project] ->[New]: C++ Source File ->
-> File name: = stdafx.cpp.
Code:
//----- C++ Source File: stdafx.cpp ------------------------------------
// stdafx.cpp: исходный файл, содержащий только стандартные включаемые модули
// Flipflop.pch будет предкомпилированным заголовком
// stdafx.obj будет содержать предварительно откомпилированные сведения о типе

#include "stdafx.h"

// TODO. Установите ссылки на любые требующиеся дополнительные заголовки в файле
// STDAFX.H, а не в данном файле


Теперь в проект Flipflop надо добавить vsm.hpp - заголовочный файл VSM API
от Labcenter Electronics.
Он был объявлен нами ранее в начале файла Flipflop.cpp...

Поскольку vsm.hpp - это уже готовый текстовый файл, то подключить его можно
несколько иначе...
Но я предлагаю поступить привычным уже нам путём, чтобы не портить оригинал
vsm.hpp, так как мне пришлось внести в него правку...

Создаём свой заголовочный файл в проекте Flipflop:

Меню [Project] -> опция [Add To Project] ->[New]: C/C++ Header File ->
-> File name: = vsm.hpp.

Открываем оригинальный vsm.hpp любым текстовым редактором, выделяем
весь текст, копируем его в буфер, переходим в среду MSVC++ 5.0 и вставляем
содержимое буфера в созданный нами vsm.hpp в проекте Flipflop.

Мне пришлось внести в vsm.hpp вот такую коррекцию в самом начале его:
Code:
...
#define TRUE  1
#define FALSE 0

#endif

//--- добавлено, т.к. компилятор не находит типичного объявления NULL
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif
//--------------------------------------------------------------------

#ifdef __SC__
typedef long long LONGLONG;
...

Теперь следует открыть в проекте Flipflop последний из объявленных уже ранее
заголовочных файлов: FFDEVICE.h - заголовочный файл для реализации класса
нашей модели Flipflop.dll.

Меню [Project] -> опция [Add To Project] ->[New]: C/C++ Header File ->
-> File name: = FFDEVICE.h.
Code:
//----- Заголовочный файл FFDEVICE.h ------------------------------------
#pragma once
#include "vsm.hpp"

class FFDEVICE : public IDSIMMODEL
{
 public:
   INT isdigital (CHAR *pinname);
   VOID setup (IINSTANCE *inst, IDSIMCKT *dsim);
   VOID runctrl (RUNMODES mode);
   VOID actuate (REALTIME time, ACTIVESTATE newstate);
   BOOL indicate (REALTIME time, ACTIVEDATA *data);
   VOID simulate (ABSTIME time, DSIMMODES mode);
   VOID callback (ABSTIME time, EVENTID eventid);
 private:
   IINSTANCE *inst;
   IDSIMCKT *ckt;
   IDSIMPIN *Pin1;
   IDSIMPIN *Pin2;
   IDSIMPIN *Pin3;
   IDSIMPIN *Pin4;
};

В этом файле объявлены прототипы виртуальных функций и интерфейсов класса
нашей модели Flipflop.dll.

Ну и поскольку прототипы объявлены, надо создать C++ файл, в котором мы наполним
эти функции конкретным содержанием: FFDEVICE.cpp.

Меню [Project] -> опция [Add To Project] ->[New]: C++ Source File ->
-> File name: = FFDEVICE.cpp.

Пустой файл FFDEVICE.cpp создан, и прежде чем мы реализуем в нём какие-то действия
модели, давайте предварительно весь проект сохраним, и далее немного обсудим, что
собственно будет содержать файл FFDEVICE.cpp.

Меню [File] -> опция [Save All]...

Собственно говоря, файл FFDEVICE.cpp и будет содержать "поведение" нашей модели,
а всё предыдущее - было "расшаркиванием в любезностях" как с Proteusом, так и с
компилятором C++... :wink:

Теперь вспомним, что мы хотели сконструировать для моделирования в среде Proteus :

Image

обычный статический D-триггер. Как он себя ведёт, надеюсь, никому рассказывать
не нужно... А если кому нужно, это вполне можно найти в Интернете.

Но поскольку я для себя рассматривал этот проект более как учебный, то позволю
напомнить, что я упоминал здесь ранее о том, что вид того, что мы нарисовали никак
напрямую не связан с тем, что мы запрограммируем
... :lol:

То есть, с точки зрения нашей Flipflop.dll, нарисованная картинка - не более
чем абстракция, которая передала в динамическую библиотеку только имена своих
четырёх выводов: D, C, Q , /Q - из которых D и C - входы, их состояние можно
"послушать", а Q и /Q - выходы, их состояние можно установить.
В остальном - нет практически никаких ограничений внутри нашей Flipflop.dll на то, как
мы можем поуправлять выходами, в зависимости, (или безо всякой зависимости) от состояния
входов нашей модели...

Так что в рамках этой "парадигмы" я поэкспериментировал с нашей моделью, проделав
то, что расписано в упомянутом ранее документе: Creation VSM - Modelos Digitales.PDF.

В процессе своих экспериментов я постарался выяснить, что за какие возможности отвечает
в практической реализации цифровой модели, и это отразил в подробных комментариях.
Code:
//------- FFDEVICE.CPP ---------------------------------------------------------------
//------- собственно это конкретная реализация класса нашей модели, обеспечивающего
//------- стандартный интерфейс с PROSPICE.
#include "FFDEVICE.h" //- заголовочный файл для реализации класса нашей модели.
//------------------------------------------------------------------------------------


//--- DEVICE::isdigital --------------------------------------------------------------
//--- Каждый вывод компонента, обнаруженный PROSPICE в списке соединений ассоциируется
//--- со своей модель через эту функцию. PROSPICE создаст образец IDSIMPIN для каждого
//--- вывода, для которого получает возврат из этой функции, не равнй нулю.
//--- Эти интерфейсы с выводами доступны затем через функцию IINSTANCE::getdsimpin.
//--- DSIM интерфейс представляет вывод модели как содержимое DSIM.
//--- Он предоставляет доступ к текущему и предшествующему состоянию вывода, и методы,
//--- позволяющие изменять состояние вывода в определенное время в будущем.
//--- См. подробнее об этом VSMSDK.HLP: Class IDSIMPIN
INT FFDEVICE::isdigital (CHAR *pinname)
{
 return 1;  //--- у модели все выводы цифровые
    //--- возможны варианты:
    //---  1 вывод является цифровым или смешанного типа.
    //---  0 вывод является аналоговым или не распознаётся моделью.
    //--- -1 вывод может быть как аналоговым, так и цифровым, в зависимости от контекста.
}

//--- DEVICE::setup ------------------------------------------------------------------
//--- Эта функция вызывается PROSPICE как только установлено, что компонент имеет
//--- один или более цифровых выводов.
//--- Модели передаётся указатель на примитив симулятора к который она присоединена
//--- и на DSIM цепь, которая её содержит. По сути - это начальная инициаллизация...
VOID FFDEVICE::setup (IINSTANCE *instance, IDSIMCKT *dsimckt)
{
//------------------- IINSTANCE *instance - указатель на примитив симулятатора,
//------------------- к которой модель приосоединена.
//----------------------------------------- IDSIMCKT *ckt - указатель на DSIM цепь,
//----------------------------------------- которая включает в себя модель.

//--- Обычно, модель сохраняет оба параметра интерфейса как переменные.
  inst = instance;
   ckt = dsimckt;

//--- Большинство моделей также делает вызовы функции IINSTANCE::getdsimpin, чтобы
//--- приобрести доступ к интерфейсам, которые созданы для её выводов.
//--- Связываем переменные с именами выводов нашей модели
  Pin1 = inst->getdsimpin("D", true); //--- Pin1 ставим в соответствие "D"
  Pin2 = inst->getdsimpin("C", true); //--- Pin2 ставим в соответствие "C"
  Pin3 = inst->getdsimpin("Q", true); //--- Pin3 ставим в соответствие "Q"
  Pin4 = inst->getdsimpin("/Q", true); //-- Pin3 ставим в соответствие "/Q"

//---  установим начальное состояние выходов:
  Pin3->setstate(SLO); //--- "Q" в "0": Strong Low - SLO: Logic 0 active output.
  Pin4->setstate(SHI); //---"/Q" в "1": Strong High - SHI: Logic 1 active output.
//---  здесь уместно случайное состояние, но для простоты установим "Q" в "0"

//---  Возможны другие варианты: (см.VSMSDK State Type)
//---  Floating    FLT    Floating output - high-impedance.
//---  Power High   PHI   Logic 1 power rail.
//---  Power Low   PLO   Logic 0 power rail.   

//---  сделаем из нашей модели генератор:
  ckt->setcallback(100000000, this, 0x25);
//---  для этого назначим, что через 1 секунду (время, измеряется в пикосекундах)
//---  после того, как прозойдёт пуск будет вызвана функция возврата (callback)
//---  с кодом события (event) 0x25.
//---  реакцию на событие с кодом 0x25 добавим в FFDEVICE::callback (time, eventid)
//---  в виде: if (eventid == 0x25){ ...  };
}

//---- DEVICE::runctrl ------------------------------------------------------------------
//---- Эта функция вызывается PROSPICE в начале каждого кадра анимации во время интерактивного
//---- симулирования. Она также называется в конце кадра, который приостановлен или потому что
//---- пользователь нажал кнопку ПАУЗА, или модели передан аналогичный паузе вызов.
//---- Эта функция важна при симуляции микропроцессорных моделей для пошаговой отладки и
//---- установки контрольных точек (breakpoints).
//---- Функция обеспечивает возможность опрелелить выполняется ли симуляция в интерактивном
//---- в том случае, если функция не вызвана для пакетного режима анализа.   
//---- Функция также позволяет модели выполнять любые действия по инициаллизации, требующийся
//---- в начало каждого интервала анимации.
//----
VOID FFDEVICE::runctrl (RUNMODES mode)
{
//--- Функция может проанализировать параметр (RUNMODES mode):
//---    RM_BATCH=-1,      // BATCH-режим ни разу не вызывался;
//---    RM_START,          // Указывает самый первый кадр (фрейм) анимации.
//---    RM_STOP,         // Симуляция остановлена (нажата кнопка СТОП)
//---    RM_SUSPEND,      // Симуляция приостановлена (нажата кнопка ПАУЗА);
//---    RM_ANIMATE,      // Симуляция свободно выполняется;
//--- Эти значения представляют интерес при пошаговой отладке:
//---    RM_STEPTIME,      // Кнопка STEP(ШАГ) была нажата
//---    RM_STEPOVER,      // Выполняется "Шаг через подпрограмму"(Step Over command)
//---    RM_STEPINTO,      // Выполняется "Шаг в подпрограмму" (Step Into command)
//---    RM_STEPOUT,      // Выполняется "Шаг из подпрограмму"(Step Out command)
//---    RM_STEPTO          // Выполняется "Шаг к команде"(Step To command)
//--- их смысл становится понятен, если протестировать пошаговую отладку CPU с программой. 

//--- Здесь можно использовать VOID IINSTANCE::log (CHAR *msg, ...) для контроля.
//--- Функция добавляет сообщение к log-списку симуляции.
//--- Эта функция наиболее полезна для отладки новых моделей тогда как log-список
//--- отображается в всплывающем окне, а сообщения появятся в нём по мере их генерации.
//--- Функция аналогична "printf" в C и использует аналогичные аргументы [ ... ].
//--- Пример:
//--- if (instance) instance->log ("DIGONLY::runctrl() called with mode=%d:%s", mode, EnumToRunCtrl(mode));

//--- для сообщений без остановки симуляции интересна следующая функция сообщения:
//--- BOOL IINSTANCE::message (CHAR *msg, ...) - выводит сообщение в строке статуса ISIS.
//--- Этот сервис доступен только для интерактивного режима симуляции.
//--- Функция также аналогична "printf" в C и использует аналогичные аргументы [ ... ].

//--- Есть ряд других, похожих, но более специализированных функций, позволяющих как
//--- выводить сообщения в log, так и управлять отладкой. (См. Logging and messaging: )
}

//---- DEVICE::actuate ------------------------------------------------------------------
//---- Эта функция вызывается PROSPICE в результате изменения пользователем состояние связанного
//---- с моделью выключателя, переключателя и т.д. (Некоего устройства ввода).
//---- Обычно есть необходимость осуществлять эту функцию если Вы используете некоторый тип
//---- интерактивно управляемого во время симуляции ключа, вспомогательной клавиатуры
//---- или другого регулируемого во время симуляции компонента.
VOID FFDEVICE::actuate (REALTIME time, ACTIVESTATE newstate)
{
//---- анализируется состояние (ACTIVESTATE newstate)
}

//---- DEVICE::indicate ------------------------------------------------------------------
//---- Эта функция вызывается PROSPICE в конце каждого кадра анимации. Она позволяет
//---- электрической модели возможность передать информацию обратно на связанный с моделью
//---- указатель или в графическую модель.
//----
BOOL FFDEVICE::indicate (REALTIME time, ACTIVEDATA *data)
{
//---- обслуживается структура (ACTIVEDATA *data)
//---- через неё можно передать информацию в графическую модель(см.VSMSDK.HLP).
   return FALSE;
}

//---- DEVICE::simulate ------------------------------------------------------------------
//---- Эта функция вызывается DSIM если любая из цепей к которым подсоединены входы модели
//---- изменяет своё состояние в определенное время.
//---- Модель может опросить текущее и предшествующее состояние любого из своих выводов,
//---- используя их IDSIMPIN интерфейсы и затем может вызывать IDSIMPIN::setstate, чтобы
//---- послать любое изменение состояний на свои выходы.
//---- Модель может использовать СТАРТОВЫЙ вызов, чтобы установить начальные события
//---- возврата, использующие функцию IDSIMCKT::setcallback.
//---- СТАРТОВЫЙ вызов (DSIMMODES = BOOT, самый первый шаг по времени. Все модели получают
//---- вызов их функции "simulate" в процессе загрузки.)
VOID FFDEVICE::simulate (ABSTIME time, DSIMMODES mode)
{
//--- заставим нашу модель читать состояние её входных линий (istate()),
//--- и отображать реакцию на него в симуляции (setstate()):
//  Pin3->setstate(time, 1, Pin1->istate());
//  Pin4->setstate(time, 1, Pin2->istate());
//--- мы читаем значения состояния входов Pin1 и Pin2, и через 1 "тик" часов
//---(1 пикосекунда) относительно текущего времени (time) мы устанавливаем
//--- это же состояние на соответствующих выходах Pin3 и Pin4.
//--- в действительности таких быстрых устройства просто нет, так, что необходимо
//--- назначать большие значения задержек. Ещё лучшее, если величины задержек
//--- назначаются через константу. И ещё лучше, если они передаются в программу
//--- как параметры модели.
}

//---- DEVICE::callback ------------------------------------------------------------------
//---- Эта функция получает события возврата созданные через IDSIMCKT::setcallback
//---- Для того, чтобы осуществлять повторяющиеся события, как, например, тактовые
//---- генераторы, функция возврата должна создать следующее событие возврата,
//---- вызывая IDSIMCKT::setcallback сама.
VOID FFDEVICE::callback (ABSTIME time, EVENTID eventid)
{
//---  сделаем из нашей модели генератор:
 if(eventid == 0x25)
   {
    if(ishigh(Pin3->istate()))
      {
       Pin3->setstate(time, 1, SLO);
       Pin4->setstate(time, 1, SHI);
      }
     else
      {
       Pin3->setstate(time, 1, SHI);
       Pin4->setstate(time, 1, SLO);
//----- если наш случай вызван, мы изменяем состояние выхода на противоположное,
//----- и запускаем таймер снова на 1 секунду, после чего снова будет вызвана
//----- функция возврата (callback).
     }
    ckt->setcallback(time + 100000000, this, 0x25);
   }
}

Понятное дело, что это не D-триггер пока ещё... но мы уже можем скомпилировать
весь проект нашей модели - [F7] или Меню [Build] -> опция [Build Flipflop.dll - F7]

Я копировал всё сюда прямо из своего рабочего проекта Flipflop, так что ошибок в
компиляции быть не должно.

И в папке C:\Program Files\DevStudio\MyProjects\Flipflop\Release\ мы обнаружим Flipflop.dll! :kruto:
Если Вы не выставили компилировать проект как "Release", то Flipflop.dll найдётся в
C:\Program Files\DevStudio\MyProjects\Flipflop\Debug\ она будет "толще", т.к. содержит
отладочную информацию...

В любом случае - цифровая модель Flipflop.dll готова, копируем её в папку моделей
к Proteus: C:\Program Files\Labcenter Electronics\Proteus 6 Professional\MODELS\
или туда, где у вас расположена папка:
...Labcenter Electronics\Proteus 6 Professional\MODELS\

Собираем в Proteus ISIS следующую тестовую схему...

Image

и убеждаемся, что задуманное вполне реализовано: по истечению 100000000 пикосекунд,
Code:
ckt->setcallback(100000000, this, 0x25);

модель реагирует на событие 0x25 в функции callback и меняет состояния своих
выходов Q и /Q на противоположные...
Code:
    if(ishigh(Pin3->istate()))
      {
       Pin3->setstate(time, 1, SLO);
       Pin4->setstate(time, 1, SHI);
      }
     else
      {
       Pin3->setstate(time, 1, SHI);
       Pin4->setstate(time, 1, SLO);

Понятно, что число "100000000 пикосекунд" можно изменить на любое другое, тогда и период
повторения импульсов на выходах Q и /Q будет иной...

В модели опробована, но временно закомментирована возможность реагировать на изменение
состояний на входах модели:
Code:
//  Pin3->setstate(time, 1, Pin1->istate());
//  Pin4->setstate(time, 1, Pin2->istate());

Можно этот вариант также опробовать.

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

Я постарался перевести и понятно изложить все основные моменты по созданию динамической
библиотеки модели под Proteus, хотя понятно, что необходимость почитать VSMSDK.HLP
я не отменял!!! :D
В VSMSDK.HLP большинство необходимых сведений изложены весьма подробно, хотя
мне, как начинающему на этом поприще, хотелось бы больше практических примеров,
нежели в VSMSDK.HLP их есть... :wink:
<hr>
Ну а что же D-триггер? :lol:
Я предположил, что он должен работать так:
По изменению состояния на входе С из 0 в 1, я собирался запустить событие 0x25:
Code:
ckt->setcallback(DelUP, this, 0x25);

где DelUP - задержка распространения для триггера, равная 15nS.
После отработки 15nS, я попадал бы в функцию callback, где выставил бы флаг,
разрешающий постоянно переписывать состояние входа D на выход Q, а на
выход /Q - инверсию этого состояния.
Собственно это я в модели частично и реализовал...

А по изменению состояния на входе С из 1 в 0, я собирался запустить другое событие 0x26:
Code:
ckt->setcallback(DelDn, this, 0x26);

где DelDN - задержка распространения для триггера, равная 25nS.
После отработки 25nS, я попадал бы в функцию callback, где сбросил бы флаг,
разрешающий постоянно переписывать состояние входа D на выход Q...

Такой вот у меня был план... хотя у коллеги aav8 на этот счёт было своё иное мнение...
Но поскольку он занят вплотную построением VSM-модели микропроцессора
Z80 (или i8080), а я тоже стараюсь в этом по мере сил участвовать, да ещё
и расписываю вот эти хелпы, то может быть кто-либо успеет доделать этот учебный
D-триггер раньше нас? :wink:



PS. Приглашаю к сотрудничеству в этом топике всех, кому создание динамической библиотеки
для модели под Proteus не показалось слишком сложным!
Готов выслушать любые конструктивные замечания и исправить все ошибки или неточности,
которые могут иметь место быть...
8)

_________________
iLavr


Last edited by Lavr on 01 Dec 2012 09:33, edited 28 times in total.



17 Nov 2012 10:12
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
Quote:
Delphi will not approach because of the impossibility of the call of the members of classes, compiled C++.


Если они сделали С++ интерфейс в ихние DLL, то это означает, что не только конкретный компилятор надо использовать, НО И КОНКРЕТНУЮ ВЕРСИЮ КОНКРЕТНОГО КОМПИЛЯТОРА (из-за упомянутого выше ABI, стандарта на который из C++ не существует), т.е. если пишут VS7.0, то значит только её...

P.S. Просто авторы сильно не хотят, чтобы какие-то левые нищеброды кодили приблуды для их коммерческих продуктов. Вердикт - закопать!

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 10:24
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Post 
Я передвинул сюда начало нашего обсуждения о проблемах компиляции активных цифровых VSM-моделей Proteus в среде Borland C++ Builder 5.0 и Microsoft Visual C++ 7.0, поскольку мы уже выяснили, что вся проблема заключается в несколько разной реализации не указанных явно соглашений о вызове функции у разных компиляторов C++.
<hr>
Частично мы уже коснулись обсуждения этого вопроса, некоторая непонятность
в котором заключается в том, что рекомендуется писать эти DLL сугубо на
MSVC++, причем самых последних версий... :-?

Мы пришли к выводу, что вроде бы писать эти DLL-библиотеки ничто не должно
помешать и на других версиях C++, и именно этот вопрос я и хотел бы более
конкретно уточнить.
Команда "Proteus" как-то странно относится к материалам на эту тему и поляну
зачем-то пытается зачистить, упрятав как свою собственную документацию,
ранее доступную публично, так и изымая другие похожие материалы.

У меня вся старая документация Proteus VSM SDK сохранилась, и в настоящий
момент в сети доступны два примера, как воплотить DLL-библиотеку для
"Proteus" практически.

Англоязычный пример есть в сети под названием:
Creation VSM - Modelos Digitales.PDF, а русскоязычный, полностью опирающийся
на упомянутый англоязычный, доступен на http://kazus.ru/:
Пример создания цифровой модели 1-wire Debugger for Proteus.

Что нам говорится в английском оригинале:
Quote:
VSM–model is library *.DLL, written in language C++. Is desirable to use compiler Microsoft Visual C++ 7.0 (it is accessible for the free load from site Microsoft), or another compiler C++, for example Digital Mars. Delphi will not approach because of the impossibility of the call of the members of classes, compiled C++.

Значит, как я понимаю, compiler Microsoft Visual C++ 7.0 и неизвестный мне
компилятор C++ Digital Mars пригодны для компиляции DLL-библиотеки
для "Proteus" , а вот Borland Delphi - уже не подойдёт...
При другие компиляторы не сказано ничего.

Но я интересовался, ещё один автор работал над DLL-библиотеками для
"Proteus", он использовал "VCToolkit от Microsoft (бесплатный C++ компилятор
командной строки, совместимый с .NETовским) и утилиты nmake.exe того же
производителя.
"

Код, конечно, в примере довольно несложный, и с точки зрения C++ затруднений
вроде как не вызывает:
Code:
# include "Vsm.hpp"
// Let us add two functions:
extern "C" IDSIMMODEL __ declspec (dllexport) *
createdsimmodel (CHAR * device, ILICENCESERVER * ils)
{
  ils->.authorize(.model_.key);
Return NULL;
}

extern "C" VOID __ declspec (dllexport)
deletedsimmodel (IDSIMMODEL * model) {}

Class DSOURDEVICE: Public IDSIMMODEL
{
public:
INT isdigital (CHAR * pinname);
VOID setup (IINSTANCE * inst, IDSIMCKT * dsim);
VOID runctrl (RUNMODES mode);
VOID actuate (REALTIME time, ACTIVESTATE newstate
BOOL indicate (REALTIME time, ACTIVEDATA * data);
VOID simulate (ABSTIME time, DSIMMODES mode);
VOID callback (ABSTIME time, EVENTID eventid);
private:
IINSTANCE * instance;
IDSIMCKT * ckt;
IDSIMPIN * Pin1;
IDSIMPIN * Pin2;
IDSIMPIN * Pin3;
IDSIMPIN * Pin4;
};

INT DSOURDEVIccE::isdigital (CHAR * pinname)
{
return 1;
}

VOID DSOURDEVIccE::setup (IINSTANCE * instance, IDSIMCKT * dsimckt)
{
inst = instance;
ckt = dsimckt;
Pin1 = inst->.getdsimpin(".Pin1", true);
Pin2 = inst->.getdsimpin(".Pin2", true);
Pin3 = inst->.getdsimpin(".Pin3", true);
Pin4 = inst->.getdsimpin(".Pin4", true);
}
VOID DSOURDEVIccE::runctrl (RUNMODES mode)
{
}
VOID DSOURDEVIccE::actuate (REALTIME time, ACTIVESTATE newstate)
{
}
BOOL DSOURDEVIccE::indicate (REALTIME time, ACTIVEDATA * data)
{
Return FALSE;
}
VOID DSOURDEVIccE::simulate (ABSTIME time,DSIMMODES mode)
{
}
VOID DSOURDEVIccE::callback (ABSTIME time, EVENTID eventid)
{
}

extern "C" IDSIMMODEL __ declspec (dllexport) *
createdsimmodel (CHAR * device, ILICENCESERVER * ils)
{
if (ils->.authorize(.model_.key)
return new DSOURDEVICE;
else
Return NULL;
}
extern "C" VOID __ declspec (dllexport)
deletedsimmodel (IDSIMMODEL * model)
{
delete (DSOURDEVICE *).model;
}

VOID DSOURDEVIccE::callback (ABSTIME time, EVENTID eventid)
{
   if (eventid == 0x25)
   {
      if (ishigh(.Pin3->.istate()))
          Pin3->.setstate(.time, 1, SLO);
       Else
          Pin3->.setstate(.time, 1, SHI);
       ckt->.setcallback(.time + 1000000000000, this, 0x25);
   }
}


Возможно, я не всё скопировал, но я думаю, нашим C++-гуру этого достаточно,
чтобы оценить код.

Так вот вопрос мой заключается вот в чем - есть ли кардинальные препятствия в коде,
не позволяющие скомпилировать его в альтернативных компиляторах типа GCC или
Borland C++ Builder 5.0
?

Причем последний меня особо интересует, поскольку он у меня есть и я программирую на нем,
а ставить Microsoft Visual C++ 7.0 или что-то иное так бы не хотелось... :(


перенесено из а не замутить ли...

Lavr wrote:
...для сборки dll-модели под Proteus нужен этот самый msvc++
причем последних версий.

Ясен пень, что под моей Вендой 98 этот msvc++ работать не будет...

Но я вполне пишу себе нужные dll-ки на Борланд Билдер 5.0.
Откуда и есть вопрос - почему я не могу собрать модель в виде dll на своём Билдере?
Что мне принципиально-то помешает?

Некоторые нужные вещи у меня получалось перетаскивать из-под msvc++ под Билдер...
И я всегда удивлялся - вроде же и msvc++ и Билдер 5.0 - это та же самая "срака
такая
C++ ", и Борланд тщилась фичи msvc++ поддержать, а порой получается, -
никак замесы от msvc++ не обойти... :(

В чём основная проблема-то?

bar wrote:
Как я понимаю, там, две причины:
1. C++ меняется со временем, и код, вполне приемлимый для компилятора 10-ти летней давности, обнаруживает в себе кучи ошибок, с точки зрения современного компилятора C++. И наоборот, если компилятору десятилетней давности, скормить заголовочный файл современной библиотеки, то скорее всего компилятор офигеет от такой наглости и выдаст кучи ошибок.
2. Стандарт C++ не имеет сколько-нибудь внятного определения ABI. И, я подозреваю, что мало того, что каждый компилятор использует свой собственный ABI, так ещё и эти ABI меняются вместе с версиями компиляторов.
Есть ещё третья причина, про которую я наслышан: msvc++ имеет свои собственные несовместимости со стандартом, которыми программисты подчастую пользуются не задумываясь, а в результате их код компилируется только в msvc++.

Shaos wrote:
DLL-и как правило имеют сишный интерфейс - надо почитать доки на API у протеуса и если оно сишное, то DLL можно компилить чем угодно - хоть паскалем...

Джентльмены, я выложил материал по библиотекам "Proteus". Если вам не трудно,
посмотрите, может ли быть DLL-библиотека для "Proteus" скомпилирована под
Borland C++ Builder 5.0, в частности?
<hr>
aav8 wrote:
Quote:
Джентльмены, я выложил материал по библиотекам "Proteus". Если вам не трудно,
посмотрите, может ли быть DLL-библиотека для "Proteus" скомпилирована под
Borland C++ Builder 5.0, в частности?

У меня Borland C++ 5.01
Попробую на нем... Но к сожалению времени пока особо нет..

Ну чтобы время зря не терять, когда оно появится, попробуй сразу компильнуть готовый
проект с http://kazus.ru/: Пример создания цифровой модели 1-wire Debugger for Proteus.

Там есть готовый исходник: DigitalModel
И его на http://kazus.ru/ опробовали и откомментировали.

Просто интересует вопрос - компильнутся ли исходники OneWireDebugger
под Borland C++ 5.01
? А если не компильнутся - что подправить в них?...
Для компиляции ещё нужны заголовочные файлы...


В английских документах - на мой взгляд - зело много опечаток, и самих исходников
как таковых - нет. Приходится копировать код из .PDF...
:(
<hr>
Shaos wrote:
Если они сделали С++ интерфейс в ихние DLL, то это означает, что не только конкретный компилятор надо использовать, НО И КОНКРЕТНУЮ ВЕРСИЮ КОНКРЕТНОГО КОМПИЛЯТОРА (из-за упомянутого выше ABI, стандарта на который из C++ не существует), т.е. если пишут VS7.0, то значит только её...

У меня в этом есть некоторые сомнения, поскольку уже есть по меньшей мере
3 доступных варианта:
1) Microsoft Visual C++ 7.0
2) Digital Mars C/C++ compiler
3) Microsoft VCToolkit .

Ну если Microsoft Visual C++ 7.0 и Microsoft VCToolkit можно подозревать
в некоей идентичности и совместимости, то Digital Mars C/C++ compiler вряд ли
с ними в "сговоре". :wink:

Borland C++ Builder растачивали поддерживать возможности msvc++... и я пока
не увидел конкретных аргументов с примерами в коде, запрещающих Builder
компильнуть DLL-ку...

Всё же Borland C++ Builder - это не Delphi, а C++ Builder, разве нет?

_________________
iLavr


Last edited by Lavr on 01 Dec 2012 05:21, edited 3 times in total.



17 Nov 2012 10:58
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
Digital Mars очень аккуратно пытался передрать бинарный формат VC++ но передрал не всё и не так - так что кое-что и у него не стыкуется...

P.S. у борланда свой бинарный формат представления скомпилированного C++ кода, у гцц свой (причём разный у разных мажорных версий)

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 11:10
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Post 
Shaos wrote:
Digital Mars очень аккуратно пытался передрать бинарный формат VC++ но передрал не всё и не так - так что кое-что и у него не стыкуется...

A Borland, как я прочитал, прежде чем задать здесь вопрос, консультировали
непосредственно специалисты Microsoft, чтобы обеспечить совместимость...

Жаль, что тема Borland C++ Builder vs MSVC++ везде выливается в холивар... :(
И человеку, не знающему вопрос глубоко, трудно разобраться в этих ньюансах самому...



PS. На KAZUS.RU "пасётся" оффициальный представитель Labcenter Electronics под ником TEHb.
Shaos wrote:
Просто авторы сильно не хотят, чтобы какие-то левые нищеброды кодили приблуды для их коммерческих продуктов. Вердикт - закопать!

И он такой жесткой позиции не высказал.
TEHb wrote:
Вот один из инструментов, которых не хватает в Протеусе (OneWireDebugger). Ещё довели бы его до уровня SPI и I2C DEBUGGER. Если интересны вопросы сотрудничества - пишите в личку.

Оффициальная версия Labcenter Electronics примерно такова:
Quote:
API для создания микропроцессоров и микроконтроллеров не поставляется всем желающим ввиду повышенной сложности разработки в несколько человеко-месяцев и т.п. Однако, если вы имеете лицензионную копию и намеряны серьезно сделать свой процессор, то тогда обратитесь к разработчику, и они рассмотрят возможность помочь в этом деле.

Это несколько вольный перевод из их документов.

_________________
iLavr


17 Nov 2012 11:17
Profile
Maniac

Joined: 05 Nov 2008 19:47
Posts: 287
Location: 81.28.208.238
Reply with quote
Post 
Quote:
Если они сделали С++ интерфейс в ихние DLL, то это означает, что не только конкретный компилятор надо использовать, НО И КОНКРЕТНУЮ ВЕРСИЮ КОНКРЕТНОГО КОМПИЛЯТОРА (из-за упомянутого выше ABI, стандарта на который из C++ не существует), т.е. если пишут VS7.0, то значит только её...

Не обязательно.
Если нтерфейс сделан в стиле COM то подйти может и другой
компилятор.
Главное, что-бы он поддерживал виртуальные функции
в стиле virtual table.


17 Nov 2012 11:57
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
Интерфейс С++ не обязан поддерживать ничего "в стиле COM" (а такой ещё существует?)

http://en.wikipedia.org/wiki/Name_mangling

Quote:
Real-world effects of C++ name mangling

Because C++ symbols are routinely exported from DLL and shared object files, the name mangling scheme is not merely a compiler-internal matter. Different compilers (or different versions of the same compiler, in many cases) produce such binaries under different name decoration schemes, meaning that symbols are frequently unresolved if the compilers used to create the library and the program using it employed different schemes. For example, if a system with multiple C++ compilers installed (e.g., GNU GCC and the OS vendor's compiler) wished to install the Boost C++ Libraries, it would have to be compiled twice — once for the vendor compiler and once for GCC.

It is good for safety purposes that compilers producing incompatible object codes (codes based on different ABIs, regarding e.g., classes and exceptions) use different name mangling schemes. This guarantees that these incompatibilities are detected at the linking phase, not when executing the software (which could lead to obscure bugs and serious stability issues).

For this reason name decoration is an important aspect of any C++-related ABI.

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 13:05
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
Ещё по теме мелкомягкого C++

http://stackoverflow.com/questions/6329 ... patibility

Quote:
If we speak about C++ code then the main problem is C++ ABI: vtable layout, rtti implementation, etc. clang follows Itanium C++ ABI (which gcc use, for example, among others), VCPP - doesn't and all these are undocumented, unfortunately. There is some work going in clang in this direction, so stuff might start to work apparently. Note that most probably some parts will never be covered, e.g. seh-based exception handling on win32, because it's patented.


т.е. микрософтовский подход к бинарному представлению C++ сущностей мало того что недокументирован и не соответствует никаким другим стандартам, так он ещё и запатентован...

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 18:18
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
Lavr wrote:
Всё же Borland C++ Builder - это не Delphi, а C++ Builder, разве нет?


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

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 18:21
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Что получается практически на данном этапе.
Borland C++ Builder умеет создавать DLL сугубо в стиле MSVC++.
Это написано в его HELP-ax, а по-русски в интернете можно прочесть это,
к примеру в "Создание dll, совместимой с Visual C++".

Что получается по обсуждаемой нами теме:
Code:
//--- OURDEV.CPP ------------------------------------------------------------
#include <vcl.h>
#include "vsm.hpp"
//---------------------------------------------------------------------------
#define model_key 0x00000000
//---------------------------------------------------------------------------

extern "C" IDSIMMODEL __declspec (dllexport) *createdsimmodel (CHAR *device, ILICENCESERVER *ils)
{
  ils->authorize(model_key);
  return NULL;
}

extern "C" VOID __declspec (dllexport) deletedsimmodel (IDSIMMODEL *model)
{
}

#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
        return 1;
}
//---------------------------------------------------------------------------

Здесь компиллер от Borland всё устраивает...

Ругаться он начинает на файл vsm.hpp из VSM SDK.

Компиллеру не нравится строчка:
Code:
typedef unsigned MESSAGE;

Compiler error: E2146 Need an identifier to declare

Это немного непонятно... :(

Из-за этого компиллер далее ругается на:
Code:
// Interface through which windows messages can be passed to a USERPOPUP's owner:
class IMSGHLR
 { public:
   virtual LRESULT msghlr (HWND, MESSAGE, WPARAM, LPARAM) = 0;
 };

Compiler error: E2303 Type name expected

Ну ясен пень MESSAGE не объявилось выше...

Мне кажется слово MESSAGE не нравится компиллеру.
Если заменить на:
Code:
typedef unsigned LMESSAGE;

и
Code:
virtual LRESULT msghlr (HWND, LMESSAGE, WPARAM, LPARAM) = 0;

DLL-ка компилируется без ошибок.

Можно просто закомментировать эти строки. В результате - компиляция
также без ошибок.
Не ясно только, как такие правки повлияют далее... :-?

Но попробую продолжить дописать DLL-ку по плану в исходном документе.

_________________
iLavr


17 Nov 2012 20:09
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
Собраться то оно может и соберётся, но при попытке подсунуть плугин протеусу, всё скорее всего упадёт...

P.S. По твоей ссылке рассказывается как сделать совместимый DLL с сишным интерфейсом (не C++)
Quote:
Поместить объявления функций в блок extern ”С”. Не экспортировать классы и функции-члены классов, поскольку это все равно не удастся.

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 21:22
Profile WWW
Maniac

Joined: 05 Nov 2008 19:47
Posts: 287
Location: 81.28.208.238
Reply with quote
Post 
Quote:
Просто интересует вопрос - компильнутся ли исходники OneWireDebugger
под Borland C++ 5.01 ? А если не компильнутся - что подправить в них?...
Для компиляции ещё нужны заголовочные файлы...

Компильнулись...
в vsm.hpp закоментил определение для _int64


17 Nov 2012 21:28
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22379
Location: Silicon Valley
Reply with quote
Post 
aav8 wrote:
Quote:
Просто интересует вопрос - компильнутся ли исходники OneWireDebugger
под Borland C++ 5.01 ? А если не компильнутся - что подправить в них?...
Для компиляции ещё нужны заголовочные файлы...

Компильнулись...
в vsm.hpp закоментил определение для _int64


А протеус то уже упал? ;)

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2012 21:30
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 295 posts ]  Go to page 1, 2, 3, 4, 5 ... 20  Next

Who is online

Users browsing this forum: Bing [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.