Описание пользователя
Глава 3. Использование стандартных модулей автокомпиляции
§3.5. Окно редактора модели
§3.5.2. Статические переменные блока
Описывается добавление в модель блока статических переменных, которые могут служить входами и выходами этого блока. Именно через статические переменные блоки получают данные по связям.
Статические и динамические переменные блока задаются на вкладке «» дополнительной (левой) панели окна редактора модели. Если эта панель отключена, ее можно снова включить пунктом меню «».
Рис. 336. Вкладка «»
дополнительной панели
Вкладка (рис. 336) разделена по вертикали на две части: в верхней вводятся статические переменные, в нижней – динамические (границу раздела можно перетаскивать вверх и вниз левой кнопкой мыши). Задание динамических переменных описываются в §3.5.3.
Статические переменные используются как входы и выходы блока, а также для хранения промежуточных значений. Статическими эти переменные называются потому, что они создаются перед подключением модели к блоку и, хотя их значения и изменяются в процессе работы, их структура остается постоянной. Технически RDS позволяет моделям блоков изменять структуру и типы своих статических переменных в процессе работы при помощи специальных вызовов, но эта возможность используется редко и не поддерживается стандартными модулями автокомпиляции. Таким образом, в автокомпилируемой модели набор статических переменных с их именами и и типами остается постоянным в течение всего времени жизни блока.
Каждая статическая переменная имеет роль (вход, выход или внутренняя переменная), определенный тип, уникальное в блоке имя, значение по умолчанию и, возможно, комментарий, выводящийся вместе с ее именем в меню подключения связи к блоку. Кроме того, с входами и выходами могут быть связаны дополнительные переменные, разрешающие или запрещающие работу выхода и получающие сигнал о срабатывании входа.
Входы и выходы – основные роли статических переменных блока. Большинство блоков, как стандартных, так и пользовательских, занимаются тем, что считывают полученные по связям от других блоков значения со своих входов и вычисляют по ним значения своих выходов, которые точно так же, по связям, передаются в другие блоки. Простейший пример модели блока, выдающего на выход сумму двух своих входов, приведен в §3.2. Если у блока нет входов или выходов, к нему невозможно подключить связи, и он может обмениваться информацией с другими только через вызовы функций или динамические переменные – такие блоки тоже встречаются, но гораздо реже. Внутренние статические переменные используются, в основном, для хранения промежуточных значений.
Возможные типы переменных блока, поддерживаемые RDS, подробно описаны в §1.4. Все они, за исключением произвольного, то есть программно изменяемого, типа, поддерживаются стандартным модулем автокомпиляции. Таким образом, статическая переменная в автокомпилируемом блоке может иметь один из следующих типов:
- Целые типы – «char», «short» и «int» – предназначены для работы с целыми числами. В автокомпилируемых моделях лучше всего применять тип «int»: из всех трех целых типов у него самая большая разрядность (32 бита), и в переменной такого типа может храниться число в диапазоне −2147483648 … +2147483647. Типы «short» и «char» добавлены в RDS для совместимости и используются крайне редко.
- Вещественные типы – «float» и «double» – позволяют работать с вещественными числами. В автокомпилируемых моделях имеет смысл использовать тип «double»: у него больше разрядность и диапазон значений – модуль числа типа double может находиться в диапазоне 2.23×10−308 … 1.79×10308. Кроме того, все стандартные математические блоки в RDS используют именно тип «double», и для него предусмотрено специальное значение, обозначающее ошибку выполнения математической операции. В автокомпилируемых моделях это значение хранится в глобальной переменной rdsbcppHugeDouble (пример ее использования приведен в §3.6.2.1).
- Логический тип – переменная такого типа может принимать значения 0 («ложь») и 1 («истина»).
- Сигнальный тип – как и логический, может иметь только значения 0 и 1, но передача сигналов по связям принципиально отличается: значение сигнального выхода передается на сигнальный вход только в том случае, если оно равно единице. Таким образом, появившаяся на сигнальном входе блока единица никогда не будет заменена нулем по связи и останется там до тех пор, пока сам блок не сотрет значение своего собственного входа – это полезно для регистрации наступления какого-либо события, обозначаемого сигнальной связью. Особенности передачи сигналов подробно рассмотрены в §1.4 описания пользователя и в §2.5.2 руководства программиста. Пример автокомпилируемой модели, использующей сигнальные переменные, приведен в §3.6.2.6.
- Массив – набор пронумерованных переменных одинакового типа. Элементы массива нумеруются начиная с нуля, для обращения к конкретному элементу его индекс, как принято в языке C, записывается в квадратных скобках: i-й элемент массива A записывается как «A[i]». Тип элемента массива может быть любым, за исключением другого массива (тем не менее, можно создавать массивы матриц, см. ниже). Размер массива не фиксирован, он может изменяться в процессе работы блока. По умолчанию проверка допустимости индекса не производится, и если попытаться обратиться к элементу за пределами текущего размера массива, работа модели будет аварийно завершена. В параметрах модели можно включить такую проверку – это может замедлить работу модели блока, но зато, при ошибке, модель выдаст более понятное диагностическое сообщение. Пример работы с массивами в модели блока приведен в §3.6.2.3.
- Матрица – двумерная таблица переменных одинакового типа. Элемент матрицы определяется индексом строки и индексом столбца, начинающимися с нуля. Обращения к конкретному элементу матрицы в интерфейсе RDS (например, при присоединении к нему связи) и в программе отличаются: в RDS индексы перечисляются в квадратных скобках через запятую («M[2,7]» – элемент матрицы M в строке с индексом 2 и столбце с индексом 7), а в программе индексы пишутся в отдельных квадратных скобках по правилам языка C («M[r][c]» – элемент матрицы M в строке с индексом r и столбце с индексом c). Тип элемента матрицы может быть любым, в том числе и другой матрицей (в RDS вложенность матриц ограничена пятью). Размер матрицы, как и у массива, не фиксирован, он может изменяться в процессе работы блока. По умолчанию обращение к элементу матрицы за пределами ее текущего размера не отслеживается и может прервать работу модели. В параметрах модели можно включить такую проверку ценой некоторого уменьшения скорости работы. Пример работы с матрицами в модели блока приведен в §3.6.2.2.
- Строка – последовательность символов в кодировке UTF8, завершающаяся нулевым байтом.
- Структура – жестко заданный набор полей, каждое из которых имеет свое имя и тип. Всей структуре целиком присваивается имя типа, под которым она будет известна пользователю. Набор полей структуры с именами и типами и имя ее собственного типа задаются через окно списка структур, вызываемое пунктом главного меню RDS «». Стандартные блоки RDS используют единственную структуру с именем типа «Complex» и двумя вещественными полями «Re» и «Im», предназначенную для работы с комплексными числами. Пользователь может добавлять и редактировать свои структуры, но следует иметь в виду, что редактирование состава полей структуры, уже используемой в модели какого-либо блока, может привести к неработоспособности этого блока. К автокомпилируемым моделям это относится в меньшей степени: после редактирования структуры следует просто скомпилировать модель заново, и, если в тексте программы нет обращений к удаленным полям структуры, блок восстановит работоспособность. Пример работы со структурами в модели блока приведен в §3.6.2.4.
Первые две переменные простого блока всегда представляют собой сигнальный вход и сигнальный выход, пользователь не может ни удалить их, ни изменить их роль и тип – их можно только переименовать. Сигнальный вход (по умолчанию он называется «Start») разрешает срабатывание модели блока, если в параметрах блока не установлен флажок «запуск каждый такт». Сигнальный выход (по умолчанию – «Ready») сообщает подключенным к нему блокам об успешном срабатывании данного блока. Подробнее эти фиксированные сигналы описаны в §1.4 и в примерах в §3.6.2.6 и §3.6.3.1.
Список статических переменных блока отображается на верхней части вкладки «» в окне редактора модели (см. рис. 336). В списке – четыре колонки:
- колонка без названия – роль переменной (вход, выход или внутренняя), изображаемая такими же картинками, как и в меню присоединения связей: «круг и стрелка от него» – выход, «круг и стрелка к нему» – вход, отсутствие картинки – внутренняя;
- «» – имя переменной;
- «» – название или условное обозначение типа переменной;
- «» – имя вспомогательной логической, сигнальной или целой переменной, подключенной к данной (см. примеры в §3.6.2.7 и §3.6.2.8);
- «» – значение переменной по умолчанию, которое она получает при сбросе расчета.
Колонки в списке можно переставлять и менять их ширину, перетаскивая левой кнопкой мыши их заголовки или границы заголовков. Нажатием Ctrl + C выделенную в списке переменную можно скопировать в буфер обмена для последующей вставки в текст программы. Редактировать переменные непосредственно в списке нельзя, для этого следует нажимать кнопку «» под списком, которая вызывает стандартное окно редактора переменных RDS. Кнопка «» полностью очищает список статических переменных блока – при пустом списке для блоков с данной моделью не будет устанавливаться структура переменных. Разумеется, упомянутые выше сигнальные переменные «Start» и «Ready» у простых блоков все равно будут присутствовать, просто они будут недоступны для программы модели.
Для каждой статической переменной в формируемый модулем автокомпиляции текст программы автоматически добавляется одноименный объект, принадлежащий одному из специальных классов доступа к статическим переменным. При этом внутри реакций на события, которые вводятся в правой части окна редактора, к переменным можно обращаться просто по имени, используя их в стандартных выражениях языка C. Если, например, в модели заданы вещественные статические переменные «x», «y» и «K», в тексте программы можно писать «y=K*x;». К полям структур можно обращаться, как и принято в C, отделяя их точкой от имени переменной структуры, индексы массивов и матриц указываются в квадратных скобках (примеры моделей, использующих различные типы переменных, приведены в §3.6.2. При этом следует помнить, что, с точки зрения компилятора, все переменные блока – это объекты некоторых специальных классов C++, для которых определены операторы присваивания, операторы приведения типов и т.п. и за которыми скрыты «настоящие» переменные блока. Это не имеет значения, если переменные используются в математических выражениях: в приведенном выше примере «y=K*x;» для объектов K и x будет автоматически вызван оператор приведения к вещественному типу, а для объекта y – оператор присваивания этому объекту вещественного числа. Однако, если попытаться взять указатель на y, это будет не указатель на вещественное число, а указатель на объект некоторого класса, что следует учитывать при написании моделей.