Float Extract Bits — Control Systems/Logic And Bit Operations
Control_Systems/Logic_And_Bit_Operations/Float_Extract_Bits · 1 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.
Float Extract Bits
Control Systems / Logic And Bit Operations
Reads its input as an IEEE-754 floating-point number and answers a contiguous field of the bits that represent it: y = (bits(u) ÷ 2low) mod 2n, with bit 0 the LEAST significant bit. The word is one sign bit at the top, then E biased exponent bits, then M mantissa bits – 1/8/23 for a single, 1/11/52 for a double. Applied entry by entry, so a matrix signal keeps its size.
Ports
- Input – the number u, of any size [m,n]. It is first ROUNDED to the chosen float type, exactly as feeding Simulink's block through a Data Type Conversion does, and the bits of that rounded value are what is read.
- Output – y, of the SAME size [m,n], carrying the requested field as an ordinary real signal.
Parameters
- Output Mode – which field is taken. This selects the field rather than
retuning it, so each option is its own code path.
- All bits – the whole word: low = 0, n = W. The default, as in Simulink. On a double this is a 64-bit field and is refused – see Notes.
- Range of bits – the window named by Bit Range.
- Sign – the top bit alone: 1 for a negative value, 0 otherwise. A negative zero reports 1, as IEEE-754 says and as Simulink answers.
- Mantissa – the low M bits, with no implied leading one.
- Exponent – the E BIASED exponent bits: 127 for 1.0 as a single, 1023 as a double. Zero and the subnormals report 0; an infinity or a NaN reports all ones.
- Bit Range – a two-entry [low high] pair, INCLUSIVE at both ends, used only in Range of bits. The low bound must not exceed the high one – Simulink makes that a hard error and so does this block. A window reaching above the top of the word reads zeros there.
- Input Float Type – single (8 exponent, 23 mantissa) or double (11 exponent, 52 mantissa): which layout the bits are read in, and which type the input is rounded to first. This has no Simulink parameter behind it – see Simulink bridge.
- 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 – but not every one of them in every configuration, and a target that cannot carry the configuration refuses it by name rather than exporting arithmetic that overflows in silence.
- The three HDL targets carry this library's arithmetic in Q16.16 fixed point, so the value reaching the generated body has already been quantized and has no IEEE-754 mantissa left to read – bits below 2−16 are gone. What survives quantization is the MAGNITUDE, which is what the sign and the exponent are made of. So those three implement any field lying entirely at or above bit M – Sign, Exponent, and a Range of bits that does not reach into the mantissa – and refuse the rest. They also refuse a field wider than 15 bits, because the answer goes back out through a Q16.16 port that tops out at 32767.
- PLC Structured Text has a real LREAL and keeps every field the software
targets do, up to the 2147483647 its
TRUNCyields as a DINT. So it refuses All bits and a double's Mantissa, and carries the rest. - The seven software targets carry every configuration the block accepts at all.
The field, the layout and every power of two are resolved when the model is built and inlined as literals; nothing here is a tunable parameter on the generated core.
Simulink bridge
Import and export, mapped to simulink/Logic and Bit Operations/Float Extract Bits.
Output Mode → OutputMode and Bit Range →
BitRange, both 1:1 and lossless: the enum table is Simulink's own five strings.
"Input Float Type" does NOT cross, and is reported rather than dropped. In Simulink
the layout comes from the input SIGNAL's data type, which is a property of the wire and not a
parameter of the block, so there is no set_param that could carry it – a
model crossing either way needs a Data Type Conversion of the matching type in front of
the block. This is the same gap Extract Bits carries for its word length, and for the
same reason: every ICore wire is a matrix of doubles.
The rate does NOT cross. That block defines no SampleTime parameter
– verified by set_param against R2026a, which answers "FloatExtractBits block
does not have a parameter named 'SampleTime'" – so "Sampling Time (s)" stays on the ICore
side.
Notes
- Algebraic and stateless. Deliberately carries no state space: reading a bit field is a piecewise-constant function of the input, so there is no A/B/C/D that represents it.
- A field wider than 53 bits is refused by the block itself, in every language and in the live run, because an ICore signal carries whole numbers exactly only that far. That is exactly All bits on a double, whose word is 64 bits wide. On a single the whole 32-bit word fits exactly and All bits is offered.
- Negative zero is the one place the HDL targets cannot agree with the others. IEEE gives −0 a sign bit of 1 and Simulink reports it; Q16.16 fixed point has no negative zero at all, so an HDL core reports 0 there. Every other input agrees exactly. This is the port's limit rather than the block's, and it is stated here because nothing else would reveal it.
- An HDL core reads the exponent of the QUANTIZED value. Where the input is exactly representable in Q16.16 – any multiple of 2−16 below 32768 – that is the same number the other targets read. Where it is not, the two can differ by one for a sample lying within a quantum of a power of two.
- An infinity reports an exponent of all ones and a mantissa of zero; a NaN reports all ones and a quiet-NaN mantissa. A NaN's own payload does not survive.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Logic_And_Bit_Operations/Float_Extract_Bits |
| family | Control_Systems/Logic_And_Bit_Operations |
| solver environment class | ICoreBlock_0_Control_Systems_1_Logic_And_Bit_Operations_2_Float_Extract_Bits |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Logic_And_Bit_Operations/Float_Extract_Bits/ICoreBlock_0_Control_Systems_1_Logic_And_Bit_Operations_2_Float_Extract_Bits.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Logic_And_Bit_Operations/Float_Extract_Bits/ICoreBlock_0_Control_Systems_1_Logic_And_Bit_Operations_2_Float_Extract_Bits.h |
| default size on canvas | 100 × 70 px |
| ports at insert | 1 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 | — |
| 2 | out | ICoreDouble | — |
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 |
|---|---|---|
Output Mode | All bits%~%Range of bits%~%Sign%~%Mantissa%~%Exponent~~Al… | OutputMode |
Bit Range | [0 15] | BitRange |
Input Float Type | single (8 exponent, 23 mantissa)%~%double (11 exponent, 5… | not crossed |
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/Logic and Bit Operations/Float Extract Bits |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| deliberately not crossed | Input Float Type |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Output Mode | OutputMode | All bits → All bits, Range of bits → Range of bits, Sign → Sign, Mantissa → Mantissa, Exponent → Exponent |
Bit Range | BitRange | passes through |
Caveat (shown to the user): "Input Float Type" has no Simulink parameter behind it -- there the exponent and mantissa widths come from the input signal's own float type, so a model crossing either way needs a Data Type Conversion to the matching type in front of the block; the Simulink block has NO SampleTime parameter, so "Sampling Time (s)" does not cross either. A configuration whose field is wider than 53 bits -- which is "All bits" on a double -- is refused by this block in every language, an ICore signal carrying whole numbers exactly only that far
Catalog contract: src/ICoreBlocks/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:
B0no sample under docs/generated/samples/ — nothing to cross-check (P8.1)
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).
Float Extract Bits -- a field of the IEEE-754 bits that represent the input y = (bits(u) / 2^low) mod 2^n, entry by entry. See the header for the layout, for why the fields are built by arithmetic rather than by a reinterpret-cast, and for the two places the block stops and says so instead of answering.
THE FIELD IS ASSEMBLED FROM THREE PIECES, WHICH IS WHAT MAKES THE HDL RULE A LINE RATHER THAN A SPECIAL CASE. A float's word is three contiguous components -- the mantissa at bit 0, the biased exponent at bit M, the sign at bit W-1 -- so a requested window [low, high] takes a slice of each one it OVERLAPS and adds them at their own weights. partFor() decides each slice once, at config-load time, and every one of the ten generators emits only the pieces its part list says are needed. A target that cannot supply the mantissa is then a target that refuses exactly the configurations whose mantissa part is needed, which is one predicate rather than a table of modes.
ONE ALGORITHM, TEN TIMES, ON PURPOSE. The sign, exponent and mantissa come from normalizing |v| into [1,2) by halving and doubling -- operations that are exact in binary floating point -- and reading off what is left. A reinterpret-cast would be shorter in five of the ten targets, unavailable in the other five, and would need a different correctness argument in each. This way the reference in compute_h and the nine translations of it are visibly the same arithmetic.
Sample results#
No sample run is committed for this block. Samples come from the headless harness (DOCS_PLAN.md P8.1) into docs/generated/samples/; until one exists this block's behaviour is witnessed by the parity and export-verification suites, not by a plot here.