You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(29) |
Dec
(16) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(2) |
Feb
(6) |
Mar
(2) |
Apr
|
May
(3) |
Jun
(1) |
Jul
(32) |
Aug
(15) |
Sep
(5) |
Oct
(5) |
Nov
|
Dec
(1) |
| 2002 |
Jan
(12) |
Feb
|
Mar
(6) |
Apr
(1) |
May
(5) |
Jun
(1) |
Jul
(3) |
Aug
(3) |
Sep
(4) |
Oct
(2) |
Nov
(19) |
Dec
(14) |
| 2003 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
(56) |
Jun
(41) |
Jul
(324) |
Aug
(46) |
Sep
(123) |
Oct
(62) |
Nov
(53) |
Dec
(102) |
| 2004 |
Jan
(84) |
Feb
(67) |
Mar
(8) |
Apr
(68) |
May
(52) |
Jun
(119) |
Jul
(19) |
Aug
(43) |
Sep
(51) |
Oct
(189) |
Nov
(74) |
Dec
(67) |
| 2005 |
Jan
(43) |
Feb
(43) |
Mar
(139) |
Apr
(20) |
May
(56) |
Jun
(160) |
Jul
(94) |
Aug
(91) |
Sep
(53) |
Oct
(79) |
Nov
(198) |
Dec
(106) |
| 2006 |
Jan
(103) |
Feb
(116) |
Mar
(135) |
Apr
(97) |
May
(72) |
Jun
(49) |
Jul
(51) |
Aug
(45) |
Sep
(67) |
Oct
(91) |
Nov
(51) |
Dec
(81) |
| 2007 |
Jan
(100) |
Feb
(57) |
Mar
(72) |
Apr
(81) |
May
(49) |
Jun
(13) |
Jul
(5) |
Aug
(32) |
Sep
(37) |
Oct
(42) |
Nov
(84) |
Dec
(41) |
| 2008 |
Jan
(32) |
Feb
(45) |
Mar
(68) |
Apr
(91) |
May
(38) |
Jun
(50) |
Jul
(83) |
Aug
(52) |
Sep
(108) |
Oct
(84) |
Nov
(125) |
Dec
(99) |
| 2009 |
Jan
(166) |
Feb
(188) |
Mar
(129) |
Apr
(88) |
May
(88) |
Jun
(117) |
Jul
(112) |
Aug
(82) |
Sep
(32) |
Oct
(79) |
Nov
(68) |
Dec
(71) |
| 2010 |
Jan
(49) |
Feb
(65) |
Mar
(113) |
Apr
(63) |
May
(71) |
Jun
(107) |
Jul
(59) |
Aug
(113) |
Sep
(103) |
Oct
(86) |
Nov
(132) |
Dec
(144) |
| 2011 |
Jan
(124) |
Feb
(67) |
Mar
(114) |
Apr
(134) |
May
(81) |
Jun
(120) |
Jul
(137) |
Aug
(83) |
Sep
(143) |
Oct
(165) |
Nov
(288) |
Dec
(137) |
| 2012 |
Jan
(337) |
Feb
(135) |
Mar
(159) |
Apr
(278) |
May
(358) |
Jun
(110) |
Jul
(77) |
Aug
(522) |
Sep
(301) |
Oct
(312) |
Nov
(319) |
Dec
(344) |
| 2013 |
Jan
(216) |
Feb
(318) |
Mar
(196) |
Apr
(61) |
May
(369) |
Jun
(387) |
Jul
(338) |
Aug
(308) |
Sep
(247) |
Oct
(168) |
Nov
(335) |
Dec
(347) |
| 2014 |
Jan
(322) |
Feb
(157) |
Mar
(414) |
Apr
(244) |
May
(152) |
Jun
(189) |
Jul
(152) |
Aug
(138) |
Sep
(108) |
Oct
(113) |
Nov
(65) |
Dec
(60) |
| 2015 |
Jan
(97) |
Feb
(65) |
Mar
(109) |
Apr
(132) |
May
(153) |
Jun
(103) |
Jul
(117) |
Aug
(186) |
Sep
(113) |
Oct
(143) |
Nov
(115) |
Dec
(221) |
| 2016 |
Jan
(157) |
Feb
(113) |
Mar
(145) |
Apr
(10) |
May
(95) |
Jun
(93) |
Jul
(159) |
Aug
(53) |
Sep
(94) |
Oct
(213) |
Nov
(88) |
Dec
(112) |
| 2017 |
Jan
(124) |
Feb
(59) |
Mar
(82) |
Apr
(101) |
May
(27) |
Jun
(78) |
Jul
(144) |
Aug
(52) |
Sep
(48) |
Oct
(35) |
Nov
(63) |
Dec
(43) |
| 2018 |
Jan
(38) |
Feb
(26) |
Mar
(63) |
Apr
(21) |
May
(75) |
Jun
(70) |
Jul
(72) |
Aug
(41) |
Sep
(84) |
Oct
(102) |
Nov
(28) |
Dec
(60) |
| 2019 |
Jan
(13) |
Feb
(92) |
Mar
(141) |
Apr
(25) |
May
(138) |
Jun
(95) |
Jul
(121) |
Aug
(75) |
Sep
(32) |
Oct
(43) |
Nov
(122) |
Dec
(64) |
| 2020 |
Jan
(54) |
Feb
(84) |
Mar
(239) |
Apr
(492) |
May
(182) |
Jun
(139) |
Jul
(126) |
Aug
(165) |
Sep
(162) |
Oct
(74) |
Nov
(108) |
Dec
(12) |
| 2021 |
Jan
(59) |
Feb
(61) |
Mar
(22) |
Apr
(129) |
May
(97) |
Jun
(108) |
Jul
(96) |
Aug
(59) |
Sep
(36) |
Oct
(105) |
Nov
(46) |
Dec
(17) |
| 2022 |
Jan
(67) |
Feb
(111) |
Mar
(104) |
Apr
(168) |
May
(58) |
Jun
(172) |
Jul
(118) |
Aug
(114) |
Sep
(177) |
Oct
(66) |
Nov
(208) |
Dec
(196) |
| 2023 |
Jan
(99) |
Feb
(47) |
Mar
(53) |
Apr
(93) |
May
(70) |
Jun
(33) |
Jul
(45) |
Aug
(54) |
Sep
(89) |
Oct
(127) |
Nov
(41) |
Dec
(102) |
| 2024 |
Jan
(38) |
Feb
(53) |
Mar
(78) |
Apr
(25) |
May
(26) |
Jun
(21) |
Jul
(56) |
Aug
(10) |
Sep
(65) |
Oct
(45) |
Nov
(38) |
Dec
(37) |
| 2025 |
Jan
(78) |
Feb
(17) |
Mar
(47) |
Apr
(45) |
May
(6) |
Jun
(33) |
Jul
(68) |
Aug
(49) |
Sep
(28) |
Oct
(69) |
Nov
(93) |
Dec
(50) |
| 2026 |
Jan
(109) |
Feb
(55) |
Mar
(153) |
Apr
(33) |
May
(21) |
Jun
(55) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Nicklas SB K. <nk...@nk...> - 2026-06-09 16:06:01
|
> I was talking more about the user experience and the possibility to > avoid conv_X_Y functions, with accessors, linking different numerical > types could be possible, e.g. connect a bit output to a int input. Some programming languages do automatic type conversion in some cases. A bit will always fit inside an integer but in most cases it is probably a misstake then a bit output is connected to an integer input. Once started on a backend for gnetlist, lepton-netlist to output a netlist in form of .hal file. Was able to produce some output but have been constantly busy with other things for years so did not have time to finish it. Otherwise this would make add explicit conversion simple. It is probably a good idea with explicit conversion of bit or bool to integer. Nicklas Karlsson |
|
From: Robert S. <rm...@un...> - 2026-06-09 15:18:14
|
On Di, 2026-06-09 at 01:08 +0100, andy pugh wrote:
> On Mon, 8 Jun 2026 at 11:40, Bertho Stultiens <lc...@va...>
> wrote:
> >
> > I'm not sure I can "see" the problem anymore ;-)
>
> > > (U8)((U32)((U32)((U32)((U32)((U32)((U32)((U32)((S32)(((FLAG)((S32
> > > )((S32)(((FLAG)((S32)
> > > ((S32)(((FLAG)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0)
>
> I wonder if it matters, or if the compiler loses it all?
>
> I might need to manually strip the casts, compile both and inspect.
> (And if it is actually different, and worse, have words. we pay for
> this)
>
>
Most of the casts just don't make much sense (and are of no
consequence), it just populates a uint8 bitfield with the results of
various comparisons.
the last part (bit 7) reads
(U32)
(
(S32)
(
(
((U32)Var1 == Lv2) ? ((S32)1) : ((S32)0)) * 64)
)
so depending on Var1==Lv2 being nonzero it takes either 0 or 64 as
signed 32bit int, casts that to unsigned 32bit, adds it to the results
of the previous clauses. finally the result is cast to 8 bit and put
into tmp_VectorConcatenate_atij[1].
I guess human would write that differently.
--
Robert Schöftner <rm...@un...>
|
|
From: Robert S. <rm...@un...> - 2026-06-09 15:18:13
|
On Mo, 2026-06-08 at 22:09 +0200, Bertho Stultiens wrote: > > Another approach that would be possible in principle with accessors > > would be to do conversion between types in the setter/getter > > functions. > > That is exactly the idea. If you change the underlying model, then > the > code does not need adjusting because the getter/setter code will > capture > and adapt to the changes so your API is a constant. > > > > The disadvantage would be that this could lead to surprising > > behaviour > > and you can't explicitely decide if you want to truncate, saturate, > > round or whatever to convert a value. > > FWIW, the current code assumes truncation nearly everywhere. > Otherwise > it codes around the problem (or crashes if the programmer didn't care > to > take account for it). I was talking more about the user experience and the possibility to avoid conv_X_Y functions, with accessors, linking different numerical types could be possible, e.g. connect a bit output to a int input. -- Robert Schöftner <rm...@un...> |
|
From: Bertho S. <lc...@va...> - 2026-06-09 14:24:07
|
On 6/9/26 2:08 AM, andy pugh wrote: >> I'm not sure I can "see" the problem anymore ;-) >>> (U8)((U32)((U32)((U32)((U32)((U32)((U32)((U32)((S32)(((FLAG)((S32)((S32)(((FLAG)((S32) >>> ((S32)(((FLAG)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) > > I wonder if it matters, or if the compiler loses it all? Quite a few of the casts are duplicates and can be discarded. The compiler will detect the constants. It will most certainly be able to do quite a bit of folding if you let it. If the input variables are real bool type, then the ternaries will be reduced further. Even the multiplications turn out to be constants (it multiplies a ternary 0/1 result). Only the FLAG cast might be consequential if it is a bool. However, looking at it would only cast ternary 0 or 1 results to bool, which is, well, a bool in C. > I might need to manually strip the casts, compile both and inspect. > (And if it is actually different, and worse, have words. we pay for this) Compile inspecting may be interesting. My guess is it just works fine. But when it generates this, then, regardless whether it works, you pay too much. ;-) -- Greetings Bertho (disclaimers are disclaimed) |
|
From: andy p. <bod...@gm...> - 2026-06-09 00:09:46
|
On Mon, 8 Jun 2026 at 11:40, Bertho Stultiens <lc...@va...> wrote: > > I'm not sure I can "see" the problem anymore ;-) > > (U8)((U32)((U32)((U32)((U32)((U32)((U32)((U32)((S32)(((FLAG)((S32)((S32)(((FLAG)((S32) > > ((S32)(((FLAG)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) I wonder if it matters, or if the compiler loses it all? I might need to manually strip the casts, compile both and inspect. (And if it is actually different, and worse, have words. we pay for this) -- atp "A motorcycle is a bicycle with a pandemonium attachment and is designed for the especial use of mechanical geniuses, daredevils and lunatics." — George Fitch, Atlanta Constitution Newspaper, 1912 |
|
From: Bertho S. <lc...@va...> - 2026-06-08 20:10:06
|
On 6/8/26 6:29 PM, Robert Schöftner wrote: > Multiple implementations of access to hal shared memory are to be > avoided if possible, I would make some exceptions for C++ template code > if it is warranted (e.g. by making python bindings easier via pybind). Multiple implementations of access to HAL shared memory are to be avoided. To say it in Highlander mode: There can be only one. Making exceptions is why we are in the trouble we are in. Halmodule using pybind does not need any low-level access to shared memory. A C++ wrapper for other code doesn't need access to shared memory either. Everything can be mapped using the C API (which does need some adjustments from the current state, regardless). We must keep the single API approach. That is the only way to guarantee that you can change the underlying stuff in HAL-lib without breaking code that uses the abstraction. > I would probably keep some sort of "type", even if the underlying bits > will eventually be double or whatever, just as a hint for the user and > GUIs. Also the difference between parameter and pin should be kept as > some sort of "metadata" And that is exactly what is done today. No change of model needed. Just update/modernize the implementation. > Another approach that would be possible in principle with accessors > would be to do conversion between types in the setter/getter functions. That is exactly the idea. If you change the underlying model, then the code does not need adjusting because the getter/setter code will capture and adapt to the changes so your API is a constant. > The disadvantage would be that this could lead to surprising behaviour > and you can't explicitely decide if you want to truncate, saturate, > round or whatever to convert a value. FWIW, the current code assumes truncation nearly everywhere. Otherwise it codes around the problem (or crashes if the programmer didn't care to take account for it). Conversions are always a problem regardless which system you use. At least with the getter/setter approach you provide a uniform API for the programmer. All software (primarily interfacing hardware) is already confronted with the problem. There is no one-answer here and it always depends on what you are trying to achieve. Therefore, I cannot see any disadvantage. Surprising behaviour is caused by code that does not know its boundary conditions (i.e. programmer error). But remember, there is a clear distinction between how this is handled internally (components) verses externally (user interfacing). -- Greetings Bertho (disclaimers are disclaimed) |
|
From: Robert S. <rm...@un...> - 2026-06-08 16:29:27
|
Am Montag, dem 08.06.2026 um 12:35 +0200 schrieb Bertho Stultiens: > This is along post. Please read it in its entirety. [...] you are right, the question of the underlying datatype is orthogonal to getter/setter. Having dealt with the mess in the noparam branch and seen all different "hacks" how pins and parameters are created and what it would entail to unify them (for the purpose of making parameters linkable which would be a very very nice feature) and the challenges it poses to debug that stuff, I'm very much in favor of cleaning up the interface and requiring access to HAL pins go through explicit accessor methods. Multiple implementations of access to hal shared memory are to be avoided if possible, I would make some exceptions for C++ template code if it is warranted (e.g. by making python bindings easier via pybind). I would probably keep some sort of "type", even if the underlying bits will eventually be double or whatever, just as a hint for the user and GUIs. Also the difference between parameter and pin should be kept as some sort of "metadata", with the distinction being "pins" contain runtime process-data that is supposed to change whereas "parameters" contain configuration data that is usually not supposed to change while a program is executing. The naming-thing is a UI problem IMO, so if you want pins and parameters in one treeview, halshow et al should be changed to offer such additional views. Another approach that would be possible in principle with accessors would be to do conversion between types in the setter/getter functions. The disadvantage would be that this could lead to surprising behaviour and you can't explicitely decide if you want to truncate, saturate, round or whatever to convert a value. -- Robert Schöftner <rm...@un...> |
|
From: Robert S. <rm...@un...> - 2026-06-08 16:12:03
|
Am Montag, dem 08.06.2026 um 15:47 +0200 schrieb mark.vandoesburg--- via Emc-developers: > To me it seems unwise to remove the integer types. Both signed and > unsigned are usefull. The unsigned type is especially usefull for > encoders, since it will properly overflow/underflow. For the signed > type > overflow/underflow is implementation defined. that overflow typically doesn't happen in the HAL layer, there you want to deal with scaled quantities like a length or an angle. if you look at the definition of the floating point format, you will see that it can store integers from -2^53 to 2^53 exactly (+-9e15 roughly or 9000km in nm-resolution). -- Robert Schöftner <rm...@un...> |
|
From: <mar...@he...> - 2026-06-08 14:08:59
|
To me it seems unwise to remove the integer types. Both signed and unsigned are usefull. The unsigned type is especially usefull for encoders, since it will properly overflow/underflow. For the signed type overflow/underflow is implementation defined. Since C++20 the conversion from unsigned to signed is also well defined, and is supposed to do what everybody already expected. Titus Newswanger <nw...@ma...> wrote: On 6/8/26 3:39 AM, Luca Toniolo wrote: > Trim to three, bool, real, int, where int absorbs s32/u32/s64/u64 and > carries bit patterns, I don't understand well enough how replacing s32/u32/s64/u64 with int would work, to outright agree or disagree with that. We'd basically have one int type s64 called int ? Now I can see doing that... |
|
From: andy p. <bod...@gm...> - 2026-06-08 14:03:08
|
On Mon, 8 Jun 2026 at 13:34, Bertho Stultiens <lc...@va...> wrote: > If you want to keep the status quo, then by all means go ahead. But then > you are just messing about and digging a deeper hole filled with > techdept for every small change. No, I am not saying that, not at all. Let's get it right. -- atp "A motorcycle is a bicycle with a pandemonium attachment and is designed for the especial use of mechanical geniuses, daredevils and lunatics." — George Fitch, Atlanta Constitution Newspaper, 1912 |
|
From: Robert S. <rm...@un...> - 2026-06-08 13:33:24
|
Am Montag, dem 08.06.2026 um 11:25 +0100 schrieb andy pugh: > In the day-job we auto-generate code from Simulink. > Today it created this horror. > I count 18 casts in a row at the beginning. > > > * S-Function (sfix_bitop): '<S230>/BitwiseOperator1' > */ > tmp_VectorConcatenate_atij[1] = > (U8)((U32)((U32)((U32)((U32)((U32)((U32)((U32)((S32)(((FLAG)((S32)((S > 32)(((FLAG)((S32) > ((S32)(((FLAG)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) | > (S32)(tmp_Switch1_c2ot ? 1 : 0)) != 0)) ? 1 : 0) | (S32) > (tmp_tmp_RelationalOperator2_idx_2 ? 1 : 0)) != 0)) ? 1 : 0) | > (S32)(tmp_Switch1_dhzf ? 1 : 0)) != 0)) ? 1 : 0)) + > (U32)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) * 2))) + > (U32)((S32)((S32)(tmp_Switch1_c2ot ? 1 : 0) * 4))) + (U32)((S32) > ((S32)(tmp_tmp_RelationalOperator2_idx_2 ? 1 : 0) * 8))) + > (U32)((S32)((S32)(tmp_Switch1_dhzf ? 1 : 0) * 16))) + > (U32)((S32)((((U32)Var1 == Lv1) ? ((S32)1) : ((S32)0)) * 32))) + > (U32)((S32)((((U32) > Var1 == Lv2) ? ((S32)1) : ((S32)0)) * 64)))); > The international obfuscated C code contest announced the '25 winners a few days ago, but you are probably not too late to submit it for the '26 prize -- Robert Schöftner <rm...@un...> |
|
From: Titus N. <nw...@ma...> - 2026-06-08 12:39:37
|
On 6/8/26 3:39 AM, Luca Toniolo wrote: > Trim to three, bool, real, int, where int absorbs s32/u32/s64/u64 and > carries bit patterns, I don't understand well enough how replacing s32/u32/s64/u64 with int would work, to outright agree or disagree with that. We'd basically have one int type s64 called int ? Now I can see doing that... |
|
From: Bertho S. <lc...@va...> - 2026-06-08 12:31:26
|
On 6/8/26 2:01 PM, andy pugh wrote: >> The answer is as obvious and simple as it is intricately complex. The >> "abstraction" in HAL is there in name only and not in the >> implementation. Code is accessing private HAL constructs and data with >> complete disregard of the - abstraction - that is promised by HAL. This >> is also known as a layer violation. > > I think that you may be applying a modern definition of a "HAL" to our "HAL" > LinuxCNC HAL does function as intended, it allows the integrator to > link data sources and sinks freely. That is all it was ever meant to > do. I disagree. HAL has two sides. One side is the external side is where user-space can abstractly manipulate components, functions, pins, params and signals. This is the side you are talking about. The other side is the internal HAL where components, functions, pins, params and signals are implemented. This is the side I've been talking about. They have to be abstract on both sides. Currently, only the external side is abstract and the internal side is a mess. If you want to keep the status quo, then by all means go ahead. But then you are just messing about and digging a deeper hole filled with techdept for every small change. -- Greetings Bertho (disclaimers are disclaimed) |
|
From: andy p. <bod...@gm...> - 2026-06-08 12:03:01
|
On Mon, 8 Jun 2026 at 11:38, Bertho Stultiens <lc...@va...> wrote: > The answer is as obvious and simple as it is intricately complex. The > "abstraction" in HAL is there in name only and not in the > implementation. Code is accessing private HAL constructs and data with > complete disregard of the - abstraction - that is promised by HAL. This > is also known as a layer violation. I think that you may be applying a modern definition of a "HAL" to our "HAL" LinuxCNC HAL does function as intended, it allows the integrator to link data sources and sinks freely. That is all it was ever meant to do. -- atp "A motorcycle is a bicycle with a pandemonium attachment and is designed for the especial use of mechanical geniuses, daredevils and lunatics." — George Fitch, Atlanta Constitution Newspaper, 1912 |
|
From: Bertho S. <lc...@va...> - 2026-06-08 10:38:09
|
I'm not sure I can "see" the problem anymore ;-) -- Greetings Bertho (disclaimers are disclaimed) On 6/8/26 12:25 PM, andy pugh wrote: > In the day-job we auto-generate code from Simulink. > Today it created this horror. > I count 18 casts in a row at the beginning. > > * S-Function (sfix_bitop): '<S230>/BitwiseOperator1' > */ > tmp_VectorConcatenate_atij[1] = > (U8)((U32)((U32)((U32)((U32)((U32)((U32)((U32)((S32)(((FLAG)((S32)((S32)(((FLAG)((S32) > ((S32)(((FLAG)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) | > (S32)(tmp_Switch1_c2ot ? 1 : 0)) != 0)) ? 1 : 0) | (S32) > (tmp_tmp_RelationalOperator2_idx_2 ? 1 : 0)) != 0)) ? 1 : 0) | > (S32)(tmp_Switch1_dhzf ? 1 : 0)) != 0)) ? 1 : 0)) + > (U32)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) * 2))) + > (U32)((S32)((S32)(tmp_Switch1_c2ot ? 1 : 0) * 4))) + (U32)((S32) > ((S32)(tmp_tmp_RelationalOperator2_idx_2 ? 1 : 0) * 8))) + > (U32)((S32)((S32)(tmp_Switch1_dhzf ? 1 : 0) * 16))) + > (U32)((S32)((((U32)Var1 == Lv1) ? ((S32)1) : ((S32)0)) * 32))) + > (U32)((S32)((((U32) > Var1 == Lv2) ? ((S32)1) : ((S32)0)) * 64)))); |
|
From: Bertho S. <lc...@va...> - 2026-06-08 10:35:53
|
This is along post. Please read it in its entirety.
Having only floating point pins is both an interesting question and at
the same time completely irrelevant for the issue at hand.
If the issue was as simple as suggested, then we can change the pins to
floating point today simply by redefining the hal_xxx_t types to use
double as backing store and be done with it. It doesn't matter that
user-space still uses multiple type indicators
(HAL_[SU]{32,64}|HAL_FLOAT|HAL_BIT). The compiler will do all conversion
for us from and to floating point and integer.
However, doing so will crash and burn. The question is: Why doesn't it work?
The answer is as obvious and simple as it is intricately complex. The
"abstraction" in HAL is there in name only and not in the
implementation. Code is accessing private HAL constructs and data with
complete disregard of the - abstraction - that is promised by HAL. This
is also known as a layer violation.
Any proper working HAL abstraction would entail that no program,
library, component or other piece may access the shared memory directly
and all access must go through HAL-lib, which is the narrowly defined
interface published in hal.h.
Instead, multiple implementations exist in LinuxCNC to access shared
memory and they all bypass the actual abstraction required. The
user-space program halcmd and python interface library halmodule call
directly into HAL's private API (hal_priv.h) and dereference internal
structures. The pyhal interface (now retired) and the hal.hh constructs
re-implement access to shared memory and bypass the published API entirely.
[A very clear indication that something is very wrong is the fact that
the HAL mutex is used by code that is not part of the HAL library code.]
Based on this observation, it is impossible to make any significant
changes to any part that touches HAL because the promised central
authority, implied by an abstraction, is violated. Therefore, changing
the user-visible types is impossible and doomed. You cannot change the
type system, external or internal, when you cannot control access in any
meaningful way.
That is why the discussion of using floating point everywhere is
completely irrelevant. We first need to fix the code to _use_ the
/abstraction/ and _only_ use the abstraction.
This is also where the discussion of issue #3286 becomes relevant and
you are encouraged to go there and read it from start to end.
Eliminating the 32-bit types from HAL entails a complete overhaul of the
internal structure. Code /assumes/ how things are laid out, uses direct
access and cannot cope with moving all 32-bit types to 64-bit types. Why
could anybody believe that we could change the current code base to use
floating point exclusively when we can't even upgrade the 32-bit types?
The reason, of course, are the layer violations by all the code and the
assumptions it makes and uses to accomplish its task.
The getter/setter approach is solving /one/ of the problems we have in
the layer violation. It eliminates direct access to the underlying
shared memory and enforces _using_ the HAL API. It is the prelude to
eliminating the distinction between 32/64 types. It is outlined in the
described sequence of changes that need to be performed in order to do so.
Once you have a getter/setter interface, then you have decoupled the
type seen by the component and the type available to the user. The
getters and setters will do all translation for you on demand. But you
first need to assure that *no one* bypasses the getter/setter API.
Otherwise you will have the same mess we are in today. And that is also
why talking about "make all floating point" is completely irrelevant at
this time.
The next fix, after getter/setter, must be to eliminate other layer
violations that are present in programs and code that access HAL private
structures. These need to use the narrowly defined API in hal.h and that
API needs some adaptions for it to become a true abstraction. There
cannot be any access to any parts of HAL shared memory that bypass the
official HAL API.
Talking about floating point everywhere is only relevant *after* the HAL
abstraction is actually a fully functional abstraction. Changes would
then just be adaptations of the HAL library and no other core changes
would be required (and, of course, the presentation layer needs
equivalent adaptions).
Note on why you need all those different getters and setters:
The code that uses the pin data, f.ex. a component, needs to have types
that are appropriate for the component to work with, like hardware
interfacing. The abstraction decouples the component's view from the
underlying data/view with the getter/setter. The getters and setters
perform all appropriate read, write and data/type translation for you as
required for operation. User-space's view of pins and such may be
completely different. That is why this is called an abstraction.
Note on the pin/param issue:
There is a genuine difference between what a pin represents and what a
parameter represents. There is no need to eliminate parameters.
Actually, the getter/setter changes require pins and parameters to
become extremely close relatives and will ultimately share the exact
same underlying structure out of necessity.
The issue mentioned, that you cannot find the one or the other is not an
issue of pins and parameters, but an issue of presentation. Halshow does
not need to show two trees because the names of pins and parameters
/cannot/ overlap. The namespaces are only separated by
attribute/function, not by name. Therefore, there is nothing that
prevents you from showing one tree and have a uniform search.
Another issue is that halcmd's setp function addresses both pins and
parameters, so a name collision between the two would hide one over the
other. This too has (already) been fixed by first checking for collision
while creating them. It will ultimately result in merging the pins and
parameters internally. The only difference between the to will be the
attributes. The user-space programs will be adapted accordingly to
provide a consistent interface.
--
Greetings Bertho
(disclaimers are disclaimed)
|
|
From: andy p. <bod...@gm...> - 2026-06-08 10:26:28
|
In the day-job we auto-generate code from Simulink. Today it created this horror. I count 18 casts in a row at the beginning. * S-Function (sfix_bitop): '<S230>/BitwiseOperator1' */ tmp_VectorConcatenate_atij[1] = (U8)((U32)((U32)((U32)((U32)((U32)((U32)((U32)((S32)(((FLAG)((S32)((S32)(((FLAG)((S32) ((S32)(((FLAG)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) | (S32)(tmp_Switch1_c2ot ? 1 : 0)) != 0)) ? 1 : 0) | (S32) (tmp_tmp_RelationalOperator2_idx_2 ? 1 : 0)) != 0)) ? 1 : 0) | (S32)(tmp_Switch1_dhzf ? 1 : 0)) != 0)) ? 1 : 0)) + (U32)((S32)((S32)(tmp_Switch1_bhzg ? 1 : 0) * 2))) + (U32)((S32)((S32)(tmp_Switch1_c2ot ? 1 : 0) * 4))) + (U32)((S32) ((S32)(tmp_tmp_RelationalOperator2_idx_2 ? 1 : 0) * 8))) + (U32)((S32)((S32)(tmp_Switch1_dhzf ? 1 : 0) * 16))) + (U32)((S32)((((U32)Var1 == Lv1) ? ((S32)1) : ((S32)0)) * 32))) + (U32)((S32)((((U32) Var1 == Lv2) ? ((S32)1) : ((S32)0)) * 64)))); -- atp "A motorcycle is a bicycle with a pandemonium attachment and is designed for the especial use of mechanical geniuses, daredevils and lunatics." — George Fitch, Atlanta Constitution Newspaper, 1912 |
|
From: Luca T. <lu...@ai...> - 2026-06-08 08:40:07
|
>> On 64-bit masks being hypothetical: they already exist. The EtherCAT >> distributed clock is a 64-bit value and the Beckhoff EL5032 puts a >> 64-bit count on the PDO, both in linuxcnc-ethercat now. The hi/lo >> split >> is what we do today, and it's the thing to avoid, not the fallback: >> two >> pins tear (low from one cycle, high from the next, off by 2^32) and >> tools can't show the real value. > It is not obvious if those enourmous ranges of values really are needed > and if it could be acceptable to limit the range. > > > Anyway, it is a tradeoff, the question is what is more inconvenient, > having different pin types that are a hassle and require a number of > conv_X_Y components and generally complicate everything or having to > deal with some exceptional cases where 64bit integers would have to be > either truncated or split into two pins. That's a fair way to frame it, and you're right on two counts: the six-type plus conv_* zoo is a genuine hassle, and in practice the huge ranges can often be limited without anyone noticing. No argument there. But I think the tradeoff as posed is a false binary, "type hassle with conversions" versus "one double with a few 64-bit exceptions." There's a third option, and it dominates both. The conv_* clutter comes from having six numeric types (n-squared conversions), not from types existing at all. Trim to three, bool, real, int, where int absorbs s32/u32/s64/u64 and carries bit patterns, and the conversion matrix nearly vanishes (only real-to-int remains, the one crossing that genuinely matters). You get rid of the hassle you dislike and keep clean integer wrap and bit patterns. You don't have to trade one for the other. On whether the big ranges are really needed: for counts, you're right, 53 bits is almost always enough. But the 64-bit cases that survive aren't about magnitude, they're about a device handing you an exact 64-bit value, a register or a clock, where the question isn't "do we need the range" but "do we truncate data the hardware gave us." Even there truncation is often tolerable, so it's not the hill I'd die on. The point is just that trimming to three types removes the conversion pain without forcing any truncation at all. So I'd reframe it as: the problem is type proliferation, not types. Fewer types fixes the hassle; zero types creates a different set of problems we then patch around. Three seems to be where the standards landed too. |
|
From: Robert S. <rm...@un...> - 2026-06-08 08:30:32
|
Am Montag, dem 08.06.2026 um 09:07 +0800 schrieb Luca Toniolo: > On 64-bit masks being hypothetical: they already exist. The EtherCAT > distributed clock is a 64-bit value and the Beckhoff EL5032 puts a > 64-bit count on the PDO, both in linuxcnc-ethercat now. The hi/lo > split > is what we do today, and it's the thing to avoid, not the fallback: > two > pins tear (low from one cycle, high from the next, off by 2^32) and > tools can't show the real value. It is not obvious if those enourmous ranges of values really are needed and if it could be acceptable to limit the range. Anyway, it is a tradeoff, the question is what is more inconvenient, having different pin types that are a hassle and require a number of conv_X_Y components and generally complicate everything or having to deal with some exceptional cases where 64bit integers would have to be either truncated or split into two pins. |
|
From: Robert S. <rm...@un...> - 2026-06-08 08:16:50
|
Am Montag, dem 08.06.2026 um 09:07 +0800 schrieb Luca Toniolo: > On the counter point specifically: the clean wrap is exactly a > property > the standards keep by keeping integer types. hal_extend_counter() > reconstructs an integer count with modular arithmetic, no lost > counts. A > double can't do that; past 2^53 it degrades and the low bits are > gone, > and a getter/setter warning can flag it but can't recover them. So if > a > count becomes a double pin, we lose the clean wrap that integers give > us > for free. counters could also be made to wrap at 2^53. |
|
From: Robert S. <rm...@un...> - 2026-06-08 08:14:32
|
Am Montag, dem 08.06.2026 um 09:07 +0800 schrieb Luca Toniolo: > My worry is that "all numbers are one fungible double" isn't how the > systems HAL has to talk to work. IEC 61131-3, CANopen/EtherCAT object > dictionaries, modbus, OPC UA all keep integer, real and bit-string as > distinct types with explicit conversion between them. None of them > has a > universal number type. The modbus I know only has bits and "registers", 16 bit signed quantities. Everything else is a non-standard extension and there seem to exist all sorts of combinations of byte-order and bit-width of those extended data types. modbus is "big endian" and there even are mixed "big/little" endian mappings of 23bit quantities onto registers. So in the case of modbus, some sort of component that knows what it is talking to is needed in any case if you have non-standard quantities. Also there is no standard discoverable process-data description, the only thing you can do is try to read an input / coil / register and look if the address exists. -- Robert Schöftner <rm...@un...> |
|
From: Luca T. <lu...@ai...> - 2026-06-08 01:07:37
|
No argument that the conv_* matrix is cruft, and collapsing conversions between numeric types is a real, appealing win. So I'm with you on the goal. My worry is that "all numbers are one fungible double" isn't how the systems HAL has to talk to work. IEC 61131-3, CANopen/EtherCAT object dictionaries, modbus, OPC UA all keep integer, real and bit-string as distinct types with explicit conversion between them. None of them has a universal number type. So an internally type-erased HAL doesn't remove the type problem, it pushes it to every external boundary, and converting a typed 64-bit value to a double at that boundary is lossy. As HAL becomes more of a bridge to those buses, that cost grows rather than shrinks. The configgen in linuxcnc-ethercat already maps EtherCAT int64 straight to s64; that 1:1 mapping is what we'd be giving up. On the counter point specifically: the clean wrap is exactly a property the standards keep by keeping integer types. hal_extend_counter() reconstructs an integer count with modular arithmetic, no lost counts. A double can't do that; past 2^53 it degrades and the low bits are gone, and a getter/setter warning can flag it but can't recover them. So if a count becomes a double pin, we lose the clean wrap that integers give us for free. On 64-bit masks being hypothetical: they already exist. The EtherCAT distributed clock is a 64-bit value and the Beckhoff EL5032 puts a 64-bit count on the PDO, both in linuxcnc-ethercat now. The hi/lo split is what we do today, and it's the thing to avoid, not the fallback: two pins tear (low from one cycle, high from the next, off by 2^32) and tools can't show the real value. And that's what bitslice/bitmerge want underneath: a word/bit type, with bool as its 1-bit member. Emitting 32 floats of 0/1 instead drops the bool type, and your cosmic-ray note actually argues the same way, a defined bit is more robust than a float near 1. So I'd keep the split the standards already draw, integer, real, and bit-string as distinct, and aim the simplification at the conversions that are genuinely redundant, rather than erasing types we then have to reconstruct at every fieldbus boundary. On 6/8/2026 6:31 AM, andy pugh wrote: > On Sun, 7 Jun 2026 at 15:59, Luca Toniolo<lu...@ai...> wrote: > >> Fair, the magnitude case is rare and I won't push it. But the behaviour at the limit differs. An integer counter wraps at a known point and we already reconstruct it: hal_extend_counter() extends limited-width counters to 64 bits with the usual modular trick, so the count just keeps going, no discontinuity, no lost counts. A float past 53 bits doesn't wrap, it degrades silently, x + 1 == x and the count eventually sticks, with no boundary to detect and nothing to recover. So where it matters, the integer keeps counting correctly and the float quietly loses count. > A getter/setter interface could warn/error at this point. > I _think_ that the underlying driver code would ask for a specific > type back from the interface, it would be absolutely _only_ the pins > that were all fungible doubles. > The motivation is to make HAL easier for users. Doing this would make > the conv_*_* components unnecessary. You can connect anything to > anything. (and you are on your own if that's a silly thing :-) ) > >> Either way, magnitude isn't the only reason for integer pins. It's also the values that aren't counts: registers, status and fault words, masks. Those don't round or wrap, the bit pattern just has to survive, which a double can't do. sserial already carries them as hal_u32_t pins for exactly that reason. > It does, but currently we have no 64-bit masks or registers. > Worst-case if those appear the driver component would have to provide > high-byte and low-byte HAL pins. > >> One honest question: what would bitslice and bitmerge operate on without an integer type? Their job is word-to-bits and bits-to-word. > These would probably remain as 32-bit components. The pin-names would > be the same, they could be connected freely to any other HAL pin, > internally they would be interpreted as 32-bit ints and treated > accordingly. > (And bitslice would output 32 floats with values of 0 or 1) [1] > > [1] In Sinclair basic, on the Z80, "True" was 0xFF and "False" was > 0x00. That seems like a better scheme, more resilient to single-bit > flips by cosmic rays. > |
|
From: andy p. <bod...@gm...> - 2026-06-07 22:32:19
|
On Sun, 7 Jun 2026 at 15:59, Luca Toniolo <lu...@ai...> wrote: > Fair, the magnitude case is rare and I won't push it. But the behaviour at the limit differs. An integer counter wraps at a known point and we already reconstruct it: hal_extend_counter() extends limited-width counters to 64 bits with the usual modular trick, so the count just keeps going, no discontinuity, no lost counts. A float past 53 bits doesn't wrap, it degrades silently, x + 1 == x and the count eventually sticks, with no boundary to detect and nothing to recover. So where it matters, the integer keeps counting correctly and the float quietly loses count. A getter/setter interface could warn/error at this point. I _think_ that the underlying driver code would ask for a specific type back from the interface, it would be absolutely _only_ the pins that were all fungible doubles. The motivation is to make HAL easier for users. Doing this would make the conv_*_* components unnecessary. You can connect anything to anything. (and you are on your own if that's a silly thing :-) ) > Either way, magnitude isn't the only reason for integer pins. It's also the values that aren't counts: registers, status and fault words, masks. Those don't round or wrap, the bit pattern just has to survive, which a double can't do. sserial already carries them as hal_u32_t pins for exactly that reason. It does, but currently we have no 64-bit masks or registers. Worst-case if those appear the driver component would have to provide high-byte and low-byte HAL pins. > One honest question: what would bitslice and bitmerge operate on without an integer type? Their job is word-to-bits and bits-to-word. These would probably remain as 32-bit components. The pin-names would be the same, they could be connected freely to any other HAL pin, internally they would be interpreted as 32-bit ints and treated accordingly. (And bitslice would output 32 floats with values of 0 or 1) [1] [1] In Sinclair basic, on the Z80, "True" was 0xFF and "False" was 0x00. That seems like a better scheme, more resilient to single-bit flips by cosmic rays. -- atp "A motorcycle is a bicycle with a pandemonium attachment and is designed for the especial use of mechanical geniuses, daredevils and lunatics." — George Fitch, Atlanta Constitution Newspaper, 1912 |
|
From: Robert S. <rm...@un...> - 2026-06-07 19:47:38
|
On So, 2026-06-07 at 15:24 +0200, Nicklas SB Karlsson wrote: > Totally agree about the guarding problem. Software complain if pieces > does not fit together is something good. > > Even stronger typing do in many cases make sense. Creating voltage, > current, temperature, angle and linear length types > is some examples. Put a temperature value where an angle value is > expected will rarely if ever make sense. Some > programming languages even have types with limited range. The HAL types only distinguish numerical types and don't carry units. So it is absolutely possible to connect a temperature value to an angle input. We could keep a type as a "hint" and use double as storage at the same time. -- Robert Schöftner <rm...@un...> |
|
From: Robert S. <rm...@un...> - 2026-06-07 18:45:33
|
On Sa, 2026-06-06 at 17:35 +0200, Robert Schöftner wrote: > Hi, > > it's been another two weeks and I wanted to send the reminder / > invitation > > > According to our bi-weekly schedule alternating between "early" and > "late", next video meeting is this sunday at 10:00 CEST. > > [https://greenlight.bbb.uni-rostock.de/b/ste-c4d-brs-3k6](https://greenlight.bbb.uni-rostock.de/b/ste-c4d-brs-3k6) > Access code: 869782 > > [https://www.timeanddate.com/worldclock/meetingdetails.html?year=2026&month=6&day=07&hour=8&min=0&sec=0&p1=319&p2=236&p3=240&p4=136](https://www.timeanddate.com/worldclock/meetingdetails.html?year=2026&month=6&day=07&hour=8&min=0&sec=0&p1=319&p2=236&p3=240&p4=136) > > see you there and then > > Some notes: we discussed: * how are docs generated and uploaded? →get rid of buildbot, get docs out of github CI * apt sources file for trixie, missing key? * translations? ## Pull Requests * UI smoke tests * generate differences of screen shots * merge #4128 AC coupling * merge #4127 * #4126: not ready yet * #4123: not ready yet * merge #4117 * merge #4116 * #4113: changes look of documentation, big improvement. conflict needs resolving. * merge #4112 * merge #4111 * #4110: conflict * merge #4109: relocate man pages * merge #4108 * merge #4106 * #4099 getter/setter * discussion about hal types: maybe replace everything with double? * hal.hh module: pybind11 branch vs. master * clearly needs more discussion * merge #4098 * #4009: not ready yet. maybe too complicated? * #3930: conflicts relating to weblate #4099 was discussed ore broadly, it was suggested to replace the underlying storage type with double (except maybe for hal_port). All datatypes available in 2.9 would fit into a double, and there seem to be no real use cases that would require HAL pins with 64bit integers. Even fast counting encoders would fit easily into the 52bit mantissa of a double (i.e. it would take 5 days spinning a 24bit encoder with 36000rpm to lose one bit of precision). STMBL was given as an example of a similar HAL system that works completely with float, running of 72MHz resp. 168MHz Arm Cortex-M4 Microcontrollers (32bit, 16/32bit thumb instructions, FPU) and doing motor control loops with up to 15kHz. Going for one datatype would make some things much easier and get rid of cruft like n*(n-1) conversion functions (which are error-prone to use). As there was no consensus reached and cleary further discussion is needed it was decided to postpone the PR. I didn't catch the last 10 minutes due to audio problems -- ``` Robert Schöftner <rm...@un...> ``` |