Текущий раздел:

Описания RDS

Описание пользователя

Глава 1. Необходимые сведения об устройстве RDS

§1.4. Статические переменные блоков

# Описание пользователя

## Глава 1. Необходимые сведения об устройстве RDS

### §1.4. Статические переменные блоков

Описываются типы статических переменных блоков. Эти переменные могут использоваться как входы и выходы для присоединения связей.

Как уже упоминалось в §1.2, блок в RDS может иметь статические и динамические переменные. Статические переменные, как правило, создаются вместе с блоком и используются как входы и выходы или для хранения промежуточных значений. Динамические переменные создаются и уничтожаются моделью блока программно и используются для скрытой от пользователя передачи данных между блоками. Со статическими переменными пользователь сталкивается чаще всего (например, при создании связей между блоками), поэтому сначала рассмотрим их.

Каждая статическая переменная имеет имя, уникальное в данном блоке. Именно это имя пользователь видит в меню подключения связи к блоку или в списке соединений блока. Имя переменной должно содержать только буквы латинского алфавита, цифры и знак подчеркивания, и при этом оно не должно начинаться с цифры. Имена чувствительны к регистру, поэтому, например, «Start» и «start» будут считаться разными переменными.

Переменные блока в RDS могут иметь один из следующих типов:

Сигнал (возможные значения: 0 и 1)
  Сигналы служат для передачи информации о наступлении каких-либо событий и передаются по связям особенным образом, отличным от других переменных. Сигнал с выхода блока передается по связи на входы блоков, соединенных с ним, только в том случае, если его значение равно 1. При этом после передачи значение выхода автоматически сбрасывается в 0, и, таким образом, блокируется повторная передача информации о том же самом событии. Поскольку нулевое значение сигнала никогда не передается по связи, модель блока, обнаружившая на сигнальном входе единицу, сама должна сбросить ее в 0, чтобы подготовится к приему информации о следующем событии. Подробнее использование сигналов и обработка их в моделях блоков рассматривается в §2.5.2 руководства программиста и §3.6.2.6 описания пользователя (для автокомпилируемых моделей).
Логический тип (возможные значения: 0 и 1)
  Нулевое значение переменной считается ложью, единичное – истиной.
char (диапазон значений: −128 … 127)
  Однобайтовая переменная, предназначенная для хранения небольших целых чисел или кодов символов, полностью эквивалентная типу signed char в C++. Этот тип используется в блоках редко, в основном, для совместимости со старыми моделями. Для работы с целыми числами чаще всего используется тип int.
short (диапазон значений: −32768 … 32767)
  Целая двухбайтовая переменная, эквивалентная типу short int в C++. В настоящее время используется редко.
int (диапазон значений: −2147483648 … 2147483647)
  Основной в RDS тип для работы с целыми числами. Эквивалентен тридцатидвухбитному типу int в C++.
float (диапазон значений модуля числа: 1.18×10−38… 3.40×1038)
  Вещественная переменная одинарной точности, эквивалентная одноименному типу в C++. Используется редко.
double (диапазон значений модуля числа: 2.23×10−308… 1.79×10308)
  Вещественная переменная двойной точности, эквивалентная одноименному типу в C++, используется во всех стандартных блоках для работы с вещественными числами.
Строка символов
  Используется для работы с текстами произвольной длины. Содержит последовательность символов, завершающуюся нулевым байтом, поэтому совместима со стандартными функциями обработки строк Windows и C++. В строках RDS всегда используется кодировка UTF8.
Матрица
  Матрица – это двумерная таблица переменных одного типа, в которой конкретный элемент определяется индексом строки и индексом столбца (индексы начинаются с нуля). Если матрица является входом или выходом блока, связи могут подключаться как к матрице в целом (при этом по связи будут передаваться все элементы матрицы одновременно), так и к отдельным ее элементам. Для обращения к конкретному элементу после имени переменной-матрицы в квадратных скобках через запятую указываются индексы строки и столбца – например, элемент матрицы «M», находящийся в третьей строке и восьмом столбце, записывается как «M[2,7]». Тип элемента матрицы может быть любым, в том числе, и другой матрицей. Максимально допускается пятикратная вложенность матриц, т.е. «матрица матриц матриц матриц матриц какого-то типа». Чаще всего в математических расчетах используются матрицы вещественных чисел, среди стандартных блоков RDS есть блоки, позволяющие вводить и отображать такие матрицы.
Массив
  Массив – это набор (вектор) переменных одного типа. Индексы элементов массива начинаются с нуля. Если массив является входом или выходом блока, связи могут подключаться как к массиву в целом, так и к отдельным его элементам. Для обращения к конкретному элементу после имени переменной-массива указывается индекс в квадратных скобках – например, третий по счету (начиная с нулевого) элемент массива «M» записывается как «M[2]». Тип элемента массива может быть любым, кроме другого массива. Если необходимо создать массив массивов, вместо него следует использовать массив матриц, поскольку матрица может быть элементом массива, а другой массив – нет. Чаще всего массивы используются для создания блоков с произвольным количеством одинаково обрабатываемых входов или выходов. Например, блок, имеющий вход в виде массива вещественных чисел и выдающий на единственный вещественный выход сумму всех элементов этого массива, может использоваться как сумматор, число входов которого может быть любым – пользователь просто подключает к разным элементам массива столько связей, сколько необходимо в данный момент. Такой сумматор входит в набор стандартных блоков RDS.
Произвольный тип
  Тип, который может изменяться в процессе работы блока. К входам произвольного типа можно подключать связи от выходов любого типа – в момент срабатывания связи такой вход получит тот же тип, что и выход, передавший ему значение. Выход произвольного типа может подстраиваться под разные типы значений при работе модели блока. Переменные произвольного типа обрабатываются RDS медленнее, чем другие, поэтому обычно они используются только для данных, тип которых заранее неизвестен (например, в моделях универсальных выключателей, мультиплексоров или демультиплексоров).
Структура
  Структура – это набор других переменных, каждая из которых имеет собственное имя и тип. Такие внутренние переменные называются полями структуры. Связи могут подключаться как к структуре в целом, так и к ее отдельным полям. У структуры есть имя типа – произвольная строка, связанная с данным конкретным набором полей. Например, стандартная структура с именем типа «Complex» содержит два поля типа double: «Re» и «Im». Структуры чаще всего используются для работы со сложными данными (например, структура упомянутого выше типа «Complex» – с комплексными числами). Состав полей структуры может редактироваться пользователем, но следует иметь в виду, что блок, использующий структуру, может отказаться работать, если состав и последовательность полей этой структуры не будет соответствовать желаниям его разработчика.

Статические переменные простого блока задаются в окне его параметров. Пользователь редко редактирует их самостоятельно – это требуется, в основном, при создании блоков-индикаторов с анимированными картинками (пример такого блока приведен в §2.10.2) и блоков с автоматически компилируемой функцией модели (созданию таких блоков посвящена глава 3 описания пользователя). Попытка изменить структуру переменных библиотечного блока может привести к его неработоспособности, о чем пользователю выводится соответствующее предупреждение. Как правило, пользователь имеет дело со статическими переменными уже готовых блоков, подключая к ним связи.

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

Рис. 7. Связи подключены к
отдельным элементам матрицы

Соединение связями возможно не только между самими входами и выходами, но и между отдельными элементами этих переменных. Например, вещественный выход может быть подключен к конкретному элементу входа, являющемуся матрицей вещественных чисел (рис. 7), или к вещественному полю структуры-входа. Точно так же отдельное вещественное поле структуры-выхода или отдельный элемент выхода-массива вещественных чисел может быть подключен к вещественному входу. Чтобы при присоединении связи подключить ее не к входу или выходу целиком, а к отдельному его элементу, следует при указании имен соединяемых переменных использовать следующий синтаксис:

- поле структуры отделяется от ее имени точкой;
- индекс массива указывается числом в квадратных скобках после его имени;
- строка и столбец матрицы указываются двумя числами через запятую в квадратных скобках после ее имени.

Например:

Запись в RDS | Значение
--- | ---
y | переменная «y»
A[3] | четвертый (т.е. с индексом 3) элемент массива «A»
M[0,1] | элемент матрицы «M», находящийся в строке с индексом 0 (первой) и столбце с индексом 1 (втором)
Out.Re | поле «Re» структуры «Out»
Y[2][0,1] | элемент, находящийся в строке 0 и столбце 1 матрицы, которая является третьим (с индексом 2) элементом массива «Y»
A[3].Re | поле «Re» структуры, являющейся четвертым (с индексом 3) элементом массива «A»
A.data[3] | четвертый (т.е. с индексом 3) элемент массива, находящегося в поле «data» структуры «A»

Подсистемы, внешние входы и внешние выходы тоже имеют статические переменные, но формируются они не так, как у простых блоков. Входы и выходы подсистемы отражают наличие в ней блоков-входов и блоков-выходов, внутренних переменных подсистемы не имеют. Пользователь может изменить порядок переменных в подсистеме (это влияет на порядок их отображения в меню подключения связи), но не может добавлять и удалять их – вместо этого он должен добавлять и удалять соответствующие блоки-входы и выходы внутри подсистемы. Внешние входы и выходы имеют единственную переменную, для которой пользователь задает только тип и имя. Будет эта переменная входом или выходом, определяется типом самого блока: единственная переменная внешнего входа будет выходом, поскольку внутри подсистемы этот блок передает данные, поступившие снаружи, а единственная переменная внешнего выхода – входом.

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

- для логических и сигналов – цифры 1 или 0;
- для целых чисел (типы char, short, int) – десятичное представление числа (например, «−24»), двоичное представление числа с префиксом «0b» (например, строка «0b11» представляет число 3), восьмеричное представление числа с префиксом «0o» (например, строка «0o11» представляет число 9) или шестнадцатеричное представление числа с префиксом «0h» или «0x» (строка «0x1f» представляет число 31);
- для вещественных чисел (типы float, double) – запись с десятичной точкой (например, «3.14») или в экспоненциальной форме с суффиксом «e» (например, «1.1e−3» представляет число 0.0011, то есть 1.1×10−3);
- для строк – последовательность символов, составляющая строку (например, «ABCD»);
- для массивов – размер в квадратных скобках, за которым следует значение по умолчанию элемента (например, «[10]3.3» задает массив из десяти элементов, каждый из которых равен 3.3);
- для матриц – число строк и столбцов через запятую в квадратных скобках, за которыми следует значение по умолчанию элемента (например, «[3,2]8» задает матрицу из трех строк и двух столбцов, каждый элемент которой равен 8);
- для структур – значения по умолчанию всех полей через запятую в фигурных скобках (например, если комплексное число хранится в структуре с двумя вещественными полями, представляющими собой вещественную и мнимую части числа, строка «{1.2,3.4}» задает число 1.2 + i 3.4).

Для массивов и матриц нельзя задать разные значения по умолчанию для отдельных элементов, необходимо указать одно значение, которое будет присвоено всем элементам матрицы или массива. Это значение будет использоваться не только при сбросе расчета, но и при увеличении размера массива/матрицы в процессе самого расчета для инициализации добавленных элементов. Можно указать только значение по умолчанию для добавляемых элементов, не указывая размер – в этом случае квадратные скобки следует оставить пустыми. Например, указав в качестве начального значения матрицы строку «[ ] 2», можно добиться того, что при сбросе расчета матрица будет пустой, а при увеличении числа ее строк и столбцов в процессе расчета добавленные элементы будут получать значение 2. Следует учитывать, что заданные по умолчанию размеры входов-матриц и массивов сохраняются только до первого срабатывания подключенной к входу связи: матрицы и массивы передаются по связям целиком, вместе с размерами и содержимым, поэтому после передачи данных по связи размер матрицы на входе станет равным размеру матрицы на выходе, который соединен с этим входом.

Для индикации текущего значения какого-либо выхода блока его обычно подключают связью к специализированному блоку-индикатору, в параметрах которого задается желаемый формат отображения. Например, на рис. 2 выход блока «y» подключен к числовому индикатору, отображающему его в виде целого числа. Если требуется наблюдать изменение значения вещественной переменной во времени, обычно ее подключают к графику, для отображения матриц тоже есть специализированные блоки и т.д. При отладке работы схемы можно посмотреть значение любой переменной, включая внутренние, на вкладке «переменные» окна параметров блока. Следует, однако, учитывать, что на этой вкладке нельзя настроить формат вывода значений, а для матриц и массивов выводится только размер без значений конкретных элементов.

Выход и вход (или два их отдельных элемента или поля, как было описано выше) всегда можно соединить связью, если их типы совпадают. Если типы не совпадают, соединение все равно возможно в тех случаях, когда тип выхода может быть преобразован к типу входа. Преобразование типов может как приводить, так и не приводить к потере данных. Например, выход типа int может без потерь быть соединен со входом типа double, а обратное соединение (выход double с входом int) ведет к округлению переданного значения до целого, или, в случае очень больших значений, к потере самого значения. Некоторые типы не могут соединяться в принципе – например, нельзя соединить вещественное число с матрицей или две структуры с разным составом полей. Ниже приведены все допустимые соединения типов и действия, выполняемые при передаче данных по такому соединению.

- Выход типа double может быть соединен со входами следующих типов:
  - double – производится копирование значения без потери точности;
  - float – производится копирование значения с потерей точности;
  - int, short, char – производится округление до целого;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица;
  - строка – вещественное число преобразуется в строку с возможным округлением;
  - произвольный тип – вход получает тип double, значение копируется.
- Выход типа float может быть соединен со входами следующих типов:
  - double, float – производится копирование значения без потери точности;
  - int, short, char – производится округление до целого;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица;
  - строка – вещественное число преобразуется в строку с возможным округлением;
  - произвольный тип – вход получает тип float, значение копируется.
- Выходы типа int, short и char (целые) могут быть соединены со входами следующих типов:
  - double, float – целое число преобразуется в вещественное;
  - int, short, char – значение копируется, возможна потеря данных при передаче числа с большой разрядностью в переменную с меньшей: int в short и char, short в char;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица;
  - строка – целое число преобразуется в строку в десятичной системе счисления;
  - произвольный тип – вход получает тип выхода, значение копируется.
- Логический выход может быть соединен со входами следующих типов:
  - логический – производится копирование значения без потерь;
  - double, float, int, short, char – в переменную записывается 0 или 1;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица, даже если передается нулевое значение логического выхода;
  - строка – формируется строка из единственного символа 0 или 1;
  - произвольный тип – вход получает логический тип, значение копируется.
- Сигнальный выход может быть соединен со входами следующих типов:
  - сигнал – если значение выхода равно 1, входу присваивается 1, а значение сигнального выхода автоматически сбрасывается в 0; если же значение выхода равно 0, вход не изменяется;
  - произвольный тип – если значение выхода равно 1, вход получает сигнальный тип и ему присваивается 1, если же значение выхода равно 0, вход не изменяет ни тип, ни значение.
- Выход-строка может быть соединен со входами следующих типов:
  - строка – строка копируется во входную переменную;
  - double, float – производится преобразование строки в вещественное число, если формат строки это позволяет;
  - int, short, char – производится преобразование строки в целое число, если формат строки это позволяет;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица;
  - произвольный тип – вход получает тип «строка», сама строка копируется.
- Выход-структура может быть соединен со входами следующих типов:
  - вход-структура в точности того же типа, что и выход – копируются все значения полей;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица;
  - произвольный тип – вход получает тип выхода, все значения полей копируются.
- Выход-массив или матрица может быть соединен со входами следующих типов:
  - вход-массив или матрица с элементами того же типа – размерность соединенного входа устанавливается равной размерности выхода и копируется все содержимое выходного массива;
  - вход-массив или матрица с элементами совместимого типа – размерность соединенного входа устанавливается равной размерности выхода и производится поэлементное копирование с преобразованием типов элементов согласно указанным выше правилам;
  - сигнал – независимо от значения выхода в сигнальный вход записывается единица;
  - произвольный тип – вход получает тип выхода (массив или матрица) и точную копию его значения.
- Выход произвольного типа может быть соединен с входом любого типа, передача данных при этом производится по указанным выше правилам согласно реальному типу этого выхода в момент передачи.

Рис. 8. К таблице
состояния сигналов

Из перечисленных выше правил видно, что к входу произвольного типа можно подключить любой выход – передача данных этого выхода автоматически присвоит входу тип выхода. Можно также заметить, что передача сигналов по связям существенно отличается от передачи всех остальных переменных. Во-первых, соединение сигнального входа с выходом любого типа, отличного от сигнального, приводит к тому, что при срабатывании связи, независимо от значения соединенного входа, в сигнальный вход записывается единица. Это позволяет использовать сигнальные входы для фиксации самого факта срабатывания связи. Во-вторых, при соединении связью двух сигнальных переменных по этой связи будет передаваться только единичное значение, причем оно автоматически сбрасывается после передачи. Это связано с тем, что сигнал предназначен для отслеживания факта наступления какого-либо события – например, срабатывания устройства или нажатия кнопки пользователем. Сигнал с выхода блока передается по связи на входы других блоков только в том случае, если его значение равно 1, то есть если событие наступило. При этом сразу после передачи значение выхода автоматически сбрасывается в 0: информация о событии передана следующему блоку и дальнейшая передача не потребуется, пока событие снова не наступит, то есть пока передающий блок снова не присвоит своему выходу единичное значение). В результате этого на входе блока-приемника будет сохраняться единичное значение до тех пор, пока его модель, отреагировав на событие, самостоятельно не сбросит значение своего входа в 0. Это можно проиллюстрировать таблицей состояния выхода и соединенного с ним входа сигнального типа (рис. 8):

До передачи данных | После передачи данных | Действие
--- | --- | ---
Выход | Вход | Выход | Вход
0 | 0 | 0 | 0 | Передача не производится, значение входа не изменяется и остается равным 0
0 | 1 | 0 | 1 | Передача не производится, значение входа не изменяется и остается равным 1
1 | 0 | 0 | 1 | Данные передаются (вход получает значение 1), значение выхода автоматически сбрасывается в 0
1 | 1 | 0 | 1 | Данные передаются (значение входа не изменяется, поскольку оно и до этого было равно 1), значение выхода автоматически сбрасывается в 0

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

Первые две переменных любого простого блока всегда являются сигнальным входом и сигнальным выходом и играют особую роль в управлении работой блока и подключенных к нему связей. Первая переменная блока (по умолчанию она называется «Start», но может быть, при желании, переименована) играет роль входного сигнала управления запуском модели блока: если для данного блока явно не указано, что он должен работать в каждом такте расчета, то в режиме расчета его модель будет вызвана только в том случае, если на вход управления запуском будет подана единица. При этом непосредственно перед вызовом модели блока этот вход управления запуском автоматически сбрасывается в 0, поскольку в противном случае после первого поступления единицы на него, как и на любой сигнальный вход, она останется там навсегда – нули по сигнальным связям не передаются.

Рис. 9. Пример использования
сигнала управления запуском

Многие стандартные блоки в RDS поддерживают управление своей работой при помощи сигнала управления запуском. Как правило, для этого в настройках блока необходимо разрешить использование этого сигнала: если оно запрещено, модель будет сама управлять своей работой, запускаясь каждый такт или при изменении одного из входов. Если же оно разрешено, модель будет ждать сигнала запуска. На рис. 9 изображено окно настройки стандартного блока умножения на константу, в котором включено ожидание сигнала запуска, и схема подключения этого блока, при которой он будет срабатывать при каждом нажатии кнопки «умножить».

Вторая переменная блока (по умолчанию – «Ready», но может быть переименована) служит выходным сигналом готовности блока: в режиме расчета данные с выходов этого блока передаются только в том случае, если она равна единице. Этой переменной автоматически присваивается единица перед запуском модели, и ноль после срабатывания связей. Модель блока обычно обнуляет сигнал готовности если по каким-либо причинам не готова выдать на выходы новые данные – таким образом, выходной сигнал готовности будет равен единице, если модель блока сработала и вычислила значения выходов, и нулю, если модель не запускалась или не подготовила данные.

Сигнал готовности вместе с сигналом управления запуском можно использовать в сложных схемах для задержки срабатывания каких-либо блоков до тех пор, пока блоки, включенные перед ними, не подготовят для них данные. На рис. 10 изображена схема, в которой значение с поля ввода (слева) подается на две параллельные ветви: в одной блок «Sum1» прибавляет к этому значению число 6, в другой – блоки «Sum2», «Sum3» и «Sum4» три раза последовательно прибавляют к нему число 2, после чего выходы обоих ветвей вычитаются блоком «Diff1» и результат подается на числовой индикатор (справа). Все блоки в этой схеме – стандартные, их модели запускаются при срабатывании любой из подключенных к входам связей.

Рис. 10. Две ветви алгебраических блоков

Теоретически, в этой схеме числовой индикатор должен всегда показывать нулевое значение, поскольку и верхняя, и нижняя ветви схемы прибавляют к значению поля ввода число шесть. Однако, если рассмотреть работу этой схемы по тактам, можно заметить, что нулевое значение на выходе блока вычитания «Diff1» устанавливается не сразу: расчет верхней ветви занимает один такт, расчет нижней – три такта (там три последовательно соединенных блока), поэтому при изменении значения во входном поле ввода новое значение на входе «x1» блока вычитания установится быстрее, чем на входе «x2», и в течение пары тактов на индикатор будет подаваться неверное значение. В большинстве случаев об этом можно не задумываться, поскольку при моделировании процессов, протекающих во времени, небольшие рассогласования в одновременности срабатывания блоков будут считаться происходящими в пределах одного дискретного шага расчета (в один и тот же момент времени), и, к тому моменту, как системное время изменится, на выходах всех цепочек блоков уже появятся правильные значения. Однако, при моделировании логических схем неодновременность срабатывания цепочек блоков разной длины может создавать проблемы, поэтому для борьбы с ней можно использовать управление запуском блоков по готовности данных.

На рис. 11 изображена такая же схема, в которой у блока вычитания «Diff1» включен режим работы по сигналу (окно настройки этого блока аналогично изображенному на рис. 9), и на его вход управления запуском «Start» подан сигнал готовности «Ready» последнего блока самой длинной ветви «Sum4». Теперь «Diff1» будет выполнять вычитание только тогда, когда сработает «Sum4», то есть когда значение в самой длинной цепочке будет полностью вычислено. При этом на числовой индикатор всегда будет подаваться нулевое значение.

Рис. 11. Две ветви алгебраических блоков с сигналом управления

Более подробно принципы работы со статическими переменными блоков, включая особенности использования сигналов, рассмотрены в §3.6.2 описания пользователя и в §2.5 руководства программиста. Эта информация нужна, в основном, разработчикам моделей блоков (в том числе, и автоматически компилируемых), обычному пользователю для работы с RDS достаточно уметь соединять переменные блоков связями и знать, какие типы можно соединять между собой. Назначение каждой переменной конкретного блока и особенности их использования рассматриваются в описаниях конкретных библиотечных блоков.