Generated reference › Matrix Concatenate — Control Systems/Base Blocks
kind: generated#block#control-systems-base-blocks

Matrix Concatenate — Control Systems/Base Blocks

Control_Systems/Base_Blocks/Matrix_Concatenate · 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.

Matrix Concatenate

Control Systems / Base Blocks

Joins its input signals into one larger signal, along the dimension chosen by Concatenate Dimension: stacking them on top of each other, or side by side.

Ports

  • Inputs – two by default, and the count is user-editable. At least two are required. What they must agree on depends on the dimension: when stacking rows they must share a column count, and when stacking columns they must share a row count.
  • Output – the join, in port order. Stacking rows, it has as many rows as all the inputs together and their shared column count; stacking columns, their shared row count and as many columns as all of them together.

Parameters

  • Concatenate Dimension – which way the signals are joined. This selects the arithmetic rather than retuning it, so each option is a separate code path.
    • 1 – Vertical (stack rows) – a [2,3] and a [4,3] become a [6,3].
    • 2 – Horizontal (stack columns) – a [3,2] and a [3,4] become a [3,6]. This is the default, as in Simulink.
  • 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 join is unrolled at export time, so the generated code is plain assignment with no loop over ports and no dimension branch left in it.

The three HDL targets are fully synthesizable. Concatenation is data movement, so the values stay in the Q16.16 datapath and nothing is converted at the port boundary or approximated.

Simulink bridge

Import and export, mapped to simulink/Math Operations/Matrix Concatenate. "Concatenate Dimension" to ConcatenateDimension, one option for one option (1, 2), so that round trip is lossless; the input port count becomes Simulink's NumInputs number and an imported count becomes this port list.

Mode is always written as Multidimensional array, because this block has no choice to offer there. Simulink's other value, Vector, concatenates 1-D signals – a kind of signal ICore does not have, since every ICore signal is a 2-D [m,n] matrix. Writing the value explicitly is what keeps the exported block on the behaviour implemented here instead of leaving Simulink on a default the two would read differently.

The Simulink block has no SampleTime parameter, so the rate is not carried across: it stays on the ICore side, and a block configured with an explicit positive rate reports that the rate did not cross.

simulink/Signal Routing/Vector Concatenate imports as this block too. It is the same Simulink block under a second library path – same Concatenate type, same three parameters – offered with Mode preset to Vector and the dimension to 1. An imported one becomes a Matrix Concatenate stacking rows, which is what its vector concatenation was doing; exporting again writes the Math Operations path.

Notes

  • Algebraic, with no state – pure signal joining; nothing is scaled or reordered.
  • The output size is derived from the inputs, so it is only settled once the upstream blocks have resolved theirs.
  • Deliberately carries no state space, even though concatenation is linear: it RESHAPES, and a D matrix can rescale a signal but never re-index one into a larger one.
  • Stacking rows computes what Mux computes. They are separate blocks in Simulink and separate here: Mux is signal routing with no parameter behind its width, and this is the Math Operations block whose direction is a config.

Code facts#

FactValue
registered typeControl_Systems/Base_Blocks/Matrix_Concatenate
familyControl_Systems/Base_Blocks
solver environment classICoreBlock_0_Control_Systems_1_Base_Blocks_2_Matrix_Concatenate
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Base_Blocks/Matrix_Concatenate/ICoreBlock_0_Control_Systems_1_Base_Blocks_2_Matrix_Concatenate.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Base_Blocks/Matrix_Concatenate/ICoreBlock_0_Control_Systems_1_Base_Blocks_2_Matrix_Concatenate.h
default size on canvas80 × 80 px
ports at insert2 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDouble
2inICoreDouble
3outICoreDouble

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 variableDefaultSimulink parameter
Concatenate Dimension1 - Vertical (stack rows)%~%2 - Horizontal (stack columns…ConcatenateDimension

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.

supportSupport::Both
Simulink pathsimulink/Math Operations/Matrix Concatenate
port-count rulePortsParam::ConcatNumInputs
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
always setMode = Multidimensional array
ICore configSimulink parameterValue translation
Concatenate DimensionConcatenateDimension1 - Vertical (stack rows)1, 2 - Horizontal (stack columns)2

Caveat (shown to the user): the two dimensions map 1:1 onto Simulink's, so the choice is lossless in both directions; Simulink's Vector mode concatenates 1-D signals, which ICore does not have - every ICore signal is a 2-D matrix - so the multidimensional mode is always written out

Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 Ports lists 2 entries for 3 ports (2 in, 1 out) — grouped, or one undocumented? a reader must say

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).

Matrix Concatenate -- several signals joined into one along a chosen dimension Measured against Simulink R2026a, [1 2; 3 4] and [5 6; 7 8]:

ConcatenateDimension = 1 -> [4,2] 1 2 ConcatenateDimension = 2 -> [2,4] 3 4 1 2 5 6 5 6 3 4 7 8 7 8

So dimension 1 stacks ROWS and dimension 2 stacks COLUMNS, and each requires the inputs to agree on the OTHER extent.

SIMULINK'S "Mode" IS NOT OFFERED, and the entry says so with a fixedParam. Its two values are "Vector" and "Multidimensional array"; the vector mode exists to concatenate 1-D signals, a thing Simulink has and ICore does not - every ICore signal is a 2-D [m,n] matrix, so there is no 1-D case for it to mean anything different in. Writing "Multidimensional array" unconditionally is what makes the export land on the behaviour this block actually implements, rather than leaving Simulink on its own default and having the two disagree about what a column vector is.

Note the deliberate overlap with Mux: Mux is signal ROUTING and always stacks vertically with no parameter behind it, so this block's dimension-1 case computes the same thing. They are separate blocks in Simulink and separate here, and the descriptions say so.

HDL is SYNTHESIZABLE: concatenation is data movement, so the values stay in the Q16.16 datapath and nothing is converted or approximated.

Algebraic and stateless. No state space -- see the header for why.

Sample results#

Matrix Concatenate — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleMatrix Concatenate — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0 [1x2] entry 0
tin ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0 [1x2] entry 0
0-2-2[-2, -2]
0.40.50.5[0.5, 0.5]
0.8-2-2[-2, -2]
1.20.50.5[0.5, 0.5]
1.6-2-2[-2, -2]
20.50.5[0.5, 0.5]
2.4-2-2[-2, -2]
2.80.50.5[0.5, 0.5]
3.2-2-2[-2, -2]
3.60.50.5[0.5, 0.5]
4-2-2[-2, -2]
4.40.50.5[0.5, 0.5]
4.8-2-2[-2, -2]
5.20.50.5[0.5, 0.5]

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 1
rampRamp: slope 1 from t = 00 … 5.8
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias-1 … 0.9996
stepStep: 0 -> 1 at t = 1 s0 … 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__Matrix_Concatenate.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).