-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Code size for resource-constrained target #418
Comments
This is a great summary. Thank you so much for taking the time to write it down and posting it here! |
Great, this is an issue for all resource-constrained targets, calling |
Yes, actually, I thought there would be many functions like Since So I'll actually just implement these changes in the PR right away and step away from the |
Haha that actually worked quite well. Now I'm getting this code size, which is even better:
Now I feel silly from spending all that time exploring the
to
|
Thanks for the great insight, @magnmaeh . It is surprising how big of an impact print functions could have on code size! |
This issue comes from the discussion: lf-lang/lingua-franca#2262 (comment)
FlexPRET uses scratchpad memories for instruction and data memory (ISPM and DSPM, respectively). This provides predictable timing, but is very expensive. When realized on an Field Programmable Gate Array (FPGA), ISPM and DSPM is realized as block RAM (BRAM), which is a limited resource. For FlexPRET running on Zedboard FPGA, a realistic amount of ISPM and DSPM is ~64 kB each. One can be increased if the other is reduced.
This means code size must be as small as possible. To achieve this, FlexPRET has its own lightweight implementation of
printf
. However, artifacts fromnewlib
'sprintf
are still present in the final executable. This drastically increases code size to the point where code is no longer runnable. Thenewlib
artifacts appear because when e.g., callingctime
, it references many othernewlib
functions. The following is the chain of referencesnewlib
functions from callingctime
.ctime
->tzset
->_tzset_unlocked_r
->_malloc_r
,siscanf
siscanf
->__ssvfiscanf_r
From just a single call to
ctime
, references to many large functions have been created and must be linked into the final executable._malloc_r
is ~2kB, while__ssvfiscanf_r
is ~6.7 kB. There are most likely multiple "chains" like this. The result is that a simple testconcurrent/TimeoutZeroTest.lf
produces code too large to run on FlexPRET realized on an FPGA. (In the case below the test was compiled for the emulator, which can have unlimited ISPM/DSPM.)There are probably many other "top-level" functions that have similar chains of references. The best solution is to find all these and sanitize them out from the source code/replace them with lightweight versions when compiling for embedded systems. However, that probably takes some effort.
The second best solution is to filter out some of the massive
newlib
function. That can be done using the linker's--wrap
flag. (https://linux.die.net/man/1/ld.) When passing--wrap=function
, all calls tofunction
will be replaced with__wrap_function
andfunction
is renamed to__real_function
. In this way, wrappers around a function can be created:However, if the
__real_function
is not called, there are no longer any references to it. Therefore, a way to entirely remove all references to e.g.,__ssvfiscanf_r
(and save lots of code space) looks like this:Pass
--wrap=__ssvfiscanf_r
to linker.This works because we are not really using
__ssvfiscanf_r
. It is just an artifact ofnewlib
.On the FlexPRET support PR, this was done for three functions:
_vfprintf_r
,__ssvfiscanf_r
,_svfiprintf_r
. This reduced the code size of the testconcurrent/TimeoutZeroTest.lf
by more than 50%.The three functions were found by running
nm <compiled program> --size-sort
, which shows all the symbols in a program sorted by size. The three largest functions related to printing/scanning were selected.There are exactly two files that implement this.
low_level_platform/api/CMakeLists.txt
andlow_level_platform/impl/src/lf_flexpret_stubs.c
. A goal should be to remove the--wrap
solution and instead sanitize the source code for high-footprint functions.The text was updated successfully, but these errors were encountered: