Assignment — Control Systems/Base Blocks
Control_Systems/Base_Blocks/Assignment · 2 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text
Description#
The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.
Assignment
Control Systems / Base Blocks
Passes an array through, overwriting the elements you name: y = Y0, then y(indexk) = Uk for every entry of the index list. Everything not named keeps its value from Y0, so the block edits a signal in place rather than building a new one.
Ports
- Y0 – the array to modify, of any size [m,n]. It sets the output size, and every element the index list does not name passes straight through.
- U – the values to write. It must carry exactly as many elements as the index list has entries, in any shape: the k-th element of U goes to the k-th index. A single index therefore takes a scalar U.
- Output – the modified array y, always the size of Y0, whatever U's shape is.
Parameters
- Indices – which elements of Y0 to overwrite, as a vector such
as
[3 1]. They are linear indices read column by column – down the first column, then the second, which is how MATLAB and Simulink number the elements of an array, so for a column-vector signal the index is just the row. They need not be sorted and need not be distinct: the list is applied in the order written, so a repeated index keeps the last value assigned to it. Defaults to1, the first element. - Index Mode – whether the list is One-based (the first element is 1, the default and MATLAB's convention) or Zero-based (the first element is 0, C's convention). It shifts how the numbers in Indices are read; it changes nothing else.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text.
The index list is structural and is resolved at export time rather than exposed as a tunable parameter: it decides which element is wired to which, and a core whose wiring could be re-pointed at run time would need a bounds check on every element on every step. The generated body is therefore a flat list of one assignment per output element, identical in shape across all ten backends. If you need the destination to move while the core runs, that is a different block.
The three HDL targets are fully synthesizable and carry no arithmetic at all – an assignment is a wire – so the fixed-point datapath is bit-identical to the reference.
Simulink bridge
Import and export, mapped to
simulink/Math Operations/Assignment. "Indices" goes to
Indices as a pass-through value (the two languages write a vector
the same way, and both number elements column by column), "Index Mode" to
IndexMode with a 1:1 One-based/Zero-based table that
is therefore lossless in both directions, and "Sampling Time (s)" to
SampleTime, as on every block.
Three Simulink parameters are always implied rather than chosen, and are
written out as such: NumberOfDimensions 1,
IndexOptions Index vector (dialog) and
OutputInitialize Initialize using input port <Y0>.
Those are the settings that make Simulink's block do what this one does. Taking
the indices from an input port, assigning across two dimensions with a
row and a column list, and initializing the output from a size table instead of
a Y0 port all have no counterpart here.
Notes
- Algebraic, with no state: the output depends only on the current inputs.
- Linear – it is a selection matrix on Y0 plus a placement matrix on U – but it carries no state space, because a state space holds one input and model reduction only merges SISO blocks, so a two-input block can never be merged whatever it declares. Sum is just as linear and carries none for the same reason.
- An index outside Y0, a non-whole index, or a U whose element count does not match the list, is reported with the block's path and stops the run rather than writing past the array.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Base_Blocks/Assignment |
| family | Control_Systems/Base_Blocks |
| solver environment class | ICoreBlock_0_Control_Systems_1_Base_Blocks_2_Assignment |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Base_Blocks/Assignment/ICoreBlock_0_Control_Systems_1_Base_Blocks_2_Assignment.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Base_Blocks/Assignment/ICoreBlock_0_Control_Systems_1_Base_Blocks_2_Assignment.h |
| default size on canvas | 80 × 70 px |
| ports at insert | 2 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | Y0 |
| 2 | in | ICoreDouble | U |
| 3 | out | ICoreDouble | y |
Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.
Configuration variables#
| Config variable | Default | Simulink parameter |
|---|---|---|
Indices | 1 | Indices |
Index Mode | One-based%~%Zero-based~~One-based | IndexMode |
Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.
Simulink bridge#
| support | Support::Both |
| Simulink path | simulink/Math Operations/Assignment |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
| always set | NumberOfDimensions = 1, IndexOptions = Index vector (dialog), OutputInitialize = Initialize using input port <Y0> |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Indices | Indices | passes through |
Index Mode | IndexMode | One-based → One-based, Zero-based → Zero-based |
Caveat (shown to the user): the indices are a dialog value here: taking them from an input port, assigning across two dimensions, and sizing the output from a table instead of a Y0 port have no counterpart
Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.
The verdict above is
tools/docs/check_block_descriptions.py(P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.
File banner (developer view)#
The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).
Assignment block -- overwrite selected elements of a signal y = Y0, with the elements named by "Indices" replaced by the elements of U, taken in the order the index list is written. Two inputs (Y0 the array to modify, U the values to write), one output the size of Y0. Algebraic and stateless, no state space (see the header).
Positions are LINEAR indices read COLUMN-MAJOR -- down each column, then across -- which is MATLAB's and Simulink's own linear indexing, so "Indices" means the same thing on both sides of the bridge and needs no translation. That is deliberately NOT the row-major order the reductions in this family accumulate in: an accumulation order is an arithmetic choice, but an index is a name for an element, and the name has to be the one the far side uses.
Every backend receives the SAME resolved answer: one source per output element, computed here from the index list and the two signal shapes. Nothing downstream re-derives the indexing, so ten languages cannot disagree about it, and a repeated index behaves like MATLAB's (the last write wins) by construction rather than by emission order.
Sample results#
| t | in ICoreDouble-Out-0 | in ICoreDouble-Out-0 | out ICoreDouble-Out-0 |
|---|---|---|---|
| 0 | -2 | -2 | -2 |
| 0.4 | 0.5 | 0.5 | 0.5 |
| 0.8 | -2 | -2 | -2 |
| 1.2 | 0.5 | 0.5 | 0.5 |
| 1.6 | -2 | -2 | -2 |
| 2 | 0.5 | 0.5 | 0.5 |
| 2.4 | -2 | -2 | -2 |
| 2.8 | 0.5 | 0.5 | 0.5 |
| 3.2 | -2 | -2 | -2 |
| 3.6 | 0.5 | 0.5 | 0.5 |
| 4 | -2 | -2 | -2 |
| 4.4 | 0.5 | 0.5 | 0.5 |
| 4.8 | -2 | -2 | -2 |
| 5.2 | 0.5 | 0.5 | 0.5 |
Every 4th of 60 samples, from the table stimulus.
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 1 |
ramp | Ramp: slope 1 from t = 0 | 0 … 5.8 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | -1 … 0.9996 |
step | Step: 0 -> 1 at t = 1 s | 0 … 1 |
Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample
Category static · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Control_Systems__Base_Blocks__Assignment.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).