You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm writing a chess engine wrapper which uses a 64-bit bitboard for board positions, so it is important that it works on ESP32.
While writing a native dynamic module in C, I ran into two issues: (1) It appears the code is not being executed properly on a 32-bit architecture (ESP32 for example) when using 64-bit integer; (2) generating a 64-bit mask using left/right shift operator 1ULL << n compiles successfully on ESP32 platform but fails to link to a .mpy file. The module works as expected when running on 64-bit linux.
I ran into some issues passing a 64-bit integer to a native module function and passed values being parsed into 32-bit. However, ESP32 does support 64-bit integer as evident shown below. Looks like the Micropython native module functions are not converting numbers correctly.
If i assign a large value (e.g. 0xf0c00c000030c0f0) to a python variable as integer, it is stored correctly and output correctly. But if I pass that value into a function, mp_obj_get_int() converted it to a 32-bit integer instead of 64-bit integer. Even casting it to uint64_t doesn't do a thing.
The above output is produced with the following code snippet below. For the uchess.test_64bit() function to test 64-bit integer functionality in ESP32 as a native module function. Without a parameter, it uses a default value, otherwise it is parsed with mp_obj_get_int function. It uses a fixed bitwise mask to test a bit while shifting the 64-bit integer to either left or right.
STATICmp_obj_tuchess_test_64bit(size_tn_args, constmp_obj_t*args_in) {
uint64_ttest_int=0;
if (n_args==0) {
test_int=0xf0c00c000030c0f0;
mp_printf(&mp_plat_print, "default hex value: 0xf0c00c000030c0f0\n");
} elseif(n_args==1) {
test_int= (uint64_t)mp_obj_get_int(args_in[0]);
mp_printf(&mp_plat_print, "parameter passed: %lu\n", test_int);
}
intbits=get_num_bits();
mp_printf(&mp_plat_print, "num bits: %d\n", bits);
uint64_ttest_bits=test_int;
mp_printf(&mp_plat_print, "Using left shift with '& 0x8000000000000000 bitwise' mask\n", bits);
for (inti=0; i<bits; i++) {
if (test_bits&0x8000000000000000) {
mp_printf(&mp_plat_print, "1");
} else {
mp_printf(&mp_plat_print, "0");
}
test_bits <<= 1;
}
mp_printf(&mp_plat_print, "\n");
if (n_args==0) {
mp_printf(&mp_plat_print, "Correct expected bit output:\n");
mp_printf(&mp_plat_print, "1111000011000000000011000000000000000000001100001100000011110000\n", bits);
}
mp_printf(&mp_plat_print, "\nUsing right shift with '& 0x0000000000000001 bitwise' mask (expected output should be flipped from above)\n", bits);
test_bits=test_int;
for (inti=0; i<bits; i++) {
if (test_bits&0x0000000000000001) {
mp_printf(&mp_plat_print, "1");
} else {
mp_printf(&mp_plat_print, "0");
}
test_bits >>= 1;
}
mp_printf(&mp_plat_print, "\n");
if (n_args==0) {
mp_printf(&mp_plat_print, "Correct expected bit output:\n");
mp_printf(&mp_plat_print, "0000111100000011000011000000000000000000001100000000001100001111\n", bits);
}
returnmp_const_none;
}
STATICMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uchess_test_64bit_obj, 0, 1, uchess_test_64bit);
In the following code snippet below, uchess.test_64bit_lshift() uses left shift << bit operation to generate a mask for a & bitwise operation test. It would function properly if 1ULL << i is used, however, when compiled, it throws a linking error. It is unable to link __ashldi3 symbol. Which I think this particular function handles 64-bit integer left/right shift operation. I also have seen the same link error with the __lshldi3 symbol as well. If using bit test operator (& , |, ^, etc) only (as evident in the first test above), it works as expected and does not require these symbols.
So I used 1UL instead and it compiled properly but gives wrong results as seen above because it is 32-bit integer, so it couldn't do proper bit test operation.
Code using shift operator to generate bitwise operation mask
I would expect Micropython to properly parse 64-bit integer on ESP32 as it is evident it can handle 64-bit integer as shown in the REPL output, but when using with custom written native module, it becomes 32-bit. And I would expect it to be able to do shift operation on a 64-bit integer.
The native module works properly when executed on 64-bit platform like Linux with 1ULL.
The return value of mp_obj_get_int is of type mp_int_t. If you are on a platform where mp_int_t is defined as a 32bit integer type, as seems to be the case for esp32 seeing it has typedef int32_t mp_int_t; in its mpconfigport.h, it is impossible to get a non-truncated 64bit number out of that function. That's not really a bug. You should use a function appropriate for your platform; IIRC there is no builtin one: see rather old #2783 for background and e.g. #8089 for another implementation.
Issue
I'm writing a chess engine wrapper which uses a 64-bit bitboard for board positions, so it is important that it works on ESP32.
While writing a native dynamic module in C, I ran into two issues: (1) It appears the code is not being executed properly on a 32-bit architecture (ESP32 for example) when using 64-bit integer; (2) generating a 64-bit mask using left/right shift operator
1ULL << n
compiles successfully on ESP32 platform but fails to link to a.mpy
file. The module works as expected when running on 64-bit linux.I ran into some issues passing a 64-bit integer to a native module function and passed values being parsed into 32-bit. However, ESP32 does support 64-bit integer as evident shown below. Looks like the Micropython native module functions are not converting numbers correctly.
If i assign a large value (e.g. 0xf0c00c000030c0f0) to a python variable as integer, it is stored correctly and output correctly. But if I pass that value into a function,
mp_obj_get_int()
converted it to a 32-bit integer instead of 64-bit integer. Even casting it touint64_t
doesn't do a thing.Example testing output:
The above output is produced with the following code snippet below. For the
uchess.test_64bit()
function to test 64-bit integer functionality in ESP32 as a native module function. Without a parameter, it uses a default value, otherwise it is parsed withmp_obj_get_int
function. It uses a fixed bitwise mask to test a bit while shifting the 64-bit integer to either left or right.In the following code snippet below,
uchess.test_64bit_lshift()
uses left shift<<
bit operation to generate a mask for a&
bitwise operation test. It would function properly if1ULL << i
is used, however, when compiled, it throws a linking error. It is unable to link__ashldi3
symbol. Which I think this particular function handles 64-bit integer left/right shift operation. I also have seen the same link error with the__lshldi3
symbol as well. If using bit test operator (&
,|
,^
, etc) only (as evident in the first test above), it works as expected and does not require these symbols.Compile error when using 1ULL
So I used
1UL
instead and it compiled properly but gives wrong results as seen above because it is 32-bit integer, so it couldn't do proper bit test operation.Code using shift operator to generate bitwise operation mask
Expected outcome
I would expect Micropython to properly parse 64-bit integer on ESP32 as it is evident it can handle 64-bit integer as shown in the REPL output, but when using with custom written native module, it becomes 32-bit. And I would expect it to be able to do shift operation on a 64-bit integer.
The native module works properly when executed on 64-bit platform like Linux with
1ULL
.Output on 64-bit architecture (Linux)
Proposed Fix
I think this issue can be fixed if it is able to link to
__ashldi3
or__lashldi3
symbol at compile time.Build Environment
Using version 4.4 ESP-IDF toolchain.
The text was updated successfully, but these errors were encountered: