-
-
Notifications
You must be signed in to change notification settings - Fork 18
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
Please reinstate the rv32ec/ilp32e libraries #38
Comments
I have nothing agains
I'll consider this for the next release. I would like to ask you a favour. I have no experience with the new RISC-V devices available on the market. Could you do a small study and check if their architectures are supported by the xPack toolchain, and possibly suggest new libraries to be included? |
I took a look at the current list. As a temporary workaround, if your code does not use atomic instructions, could you use the |
Thanks! 😃
I'm not really familiar with the variety of what's around, but I found this article which seems to give a pretty good run-down. For WCH microcontrollers in particular (which is what I'm most familiar with), while device models are too numerous to list here, they basically only have three different CPU cores:
(* 'm' - Zmmul only; 'B' - unsure if conforms to ratified standard) As far as microcontrollers goes in general - as opposed to larger SoCs - I think it's safe to say that at least the following is needed:
RISC-V microcontrollers pretty much always support 'C', because small code size is typically of great importance in embedded applications, due to limited on-chip flash sizes.
If it means the library code will contain Atomic extension instructions, then no. CH32V00x is strictly RV32EC only; I suspect you'd just get an illegal instruction hard fault if it tried to execute any 'A' instruction. |
Yes, good article.
So only Tommy @TommyMurphyTM1234, any comments on this proposal?
I did not check the compiler and the library source code, so I might be wrong, but I don't think that the compiler has any reasons to generates atomic instructions for usual C code, you need to explicitly include <stdatomic.h> to get atomic support, which I doubt you do. I suggest you give it a try. It'll probably take me some time, possibly a few weeks, to prepare a new maintenance release with the new libraries. |
I saw the issue being logged and updated but I haven't had a chance yet to review matters and the proposed modified set of multilibs...
That's my understanding too - i.e. that the compiler will never "automatically" generate atomic instructions. |
That would appear to be the case, yes. I would bet that set of 4 would cover 99% of RISC-V microcontrollers.
I would hope that would be the case, but I wouldn't feel safe relying on that assumption. In any case, I tried compiling one of my code bases with 13.3.0-2 and rv32eac and I only get a single-byte difference between that and the same compiled with 13.3.0-1 and rv32ec. So, for this code base at least (which uses minimal libgcc and libc functions), I get usable results. (Side note: I'm a bit confused by this single-byte difference, as it's in a section of my own code, and it's a
Not a problem for me personally. I'm just continuing to use the older versions anyway. 😄 For people who've inadvertently upgraded their riscv-none-elf-gcc package, in the meantime they could downgrade I suppose. |
To summarise, the missing libraries are:
The WCH specific extensions are out of my scope. |
Can you clarify what you're referring to here?
|
All of the above. |
Yes, of course, because none of that is in mainline GCC. Although it would be nice if they added XW support. |
Sure, ask them, perhaps they'll do it. I have no contacts there. |
Did MounRiver ever release their modifications to GCC that added support for it, as they're obviously obliged to do under GPL? |
No idea. |
For ch32v003fun, we just use these for generating it manually if you wanted the opcodes: https://github.com/cnlohr/ch32v003fun/blob/master/ch32v003fun/ch32v003fun.h#L14043-L14086 We don't "expect" GCC to support XW. It would be great if it did, but it is crucial for us to get rv32ec/ilp32e asap. Please do not hold up release of rv32ec in seeking XW support. |
Also - somewhat unrelated - have you considered separating out RV32/RV64 as different packages? I will admit the 500MB download was quite the chonker, compared to sysprog's RV32 compiler zip (which even bundles Make) at an 82MB zip. I don't have a strong preference, was just curious. |
Only as a last resort.
Now the archives are in the 300MB range. Still large, but somehow manageable. |
All fair. Just 🙏 for the rv32ec/ilp32e. |
Just wondering, what is the timeframe for expected inclusion? I would really like to switch the target for ch32v003fun to xpack, from sysprogs, since they are stuck back at GCC10. Also, there is question regarding its savoryness. cnlohr/rv003usb#67 |
I'm really busy these days with the new web for the whole xPack project. It might take 1-2 more weeks. |
If it helps at all I can prepare a PR for this. If so then maybe I can get some clarification. (1) I presume that
(2)
(3)
(4) Should anything be change/be added here?
(5) If making changes I would endeavour to update the
|
The problem is not adding three lines in the script, but the many hours that the builds take. |
It would still help to clearly identify the changes that need to be made. |
What platform are using? I can make a pre-release these days so you can try it. |
I updated the build script. There were only two changes needed, the other two combinations were already there.
The meaning of |
BTW @cnlohr, did you try the existing binaries and you could not build your application due to lack of space in flash? |
Just for background, I'm the lead maintainer of https://github.com/cnlohr/ch32v003fun - for projects like the rv003usb bootloader where the USB stack has to fit into the 1920-byte bootloader, the C extension is absolutely required. If you have a test build ready without the extra I am personally unaware of any differences at all between ilp32e and ilp32e--c or between EDIT: Sorry, I'm not up n up on much GCC past GCC12. |
I'll have a darwin-x64 archive probably in a few hours. |
Aaaha! Sorry, I have always used objdump to make my map files, it is indeed better to do map file creation by the linker. It turns out it's using a vendored libgcc! Thanks for having me check that. If I don't use the vendored gcc, it does still works with -2, but, the flash usage goes back up, since it is using the non-c libgcc. Also, I tested your pre-release binaries and they work perfectly. I will base my install off of them. Thank you so much for your effort on this. |
FYI... If a specific multilib cannot be matched for the Since this uses the |
Sorry, what exactly do you mean by "vendored" GCC/libgcc here? |
Right, but this is not the case with 14.2.0-2, since the But indeed, this might be a potential source of errors. |
I presume that @cnlohr's earlier test where this was happening was using some other toolchain or an earlier version of the xPack one. In particular, some toolchain where no multilib was matched for But the references to "vendored" GCC/libgcc make things unclear for me. It would help if clearer information was posted for each test/incident. |
To give some illustration on the differences I have been seeing when compiled against rv32ec versus rv32e, I can give an example from one of my codebases for CH32V003. It's not a particularly complex codebase, and doesn't actually end up making much use of libgcc/libc library code. The only things linked in, according to the map file, are:
Like I said originally, you have to look at the paths in the linker's map file output to see exactly what libraries are being linked, because otherwise (as far as I can tell) the only other sign is to look at the disassembly and see usage (or lack thereof) of compressed instructions. The size differences (in bytes) for these library functions are as follows:
For example,
And
So you can see even for this rather small collection of libgcc/libc functions, the overall difference is in the hundreds of bytes. My compiled firmware image size goes from 13,136 to 13,264 bytes. When you only have 16K to play with, that's already becoming significant. And if like @cnlohr you're trying to squeeze something into a 1,920 byte bootloader, it becomes super-critical. (BTW, I'm not sure why the firmware binary size difference doesn't correspond exactly with the total difference from the sum of sizes of individual functions above - 128 vs. 130. Maybe a couple of bytes were superfluous and got shaved somehow during linking.) |
I'm fully with you on this, I still remember while in the 80's I was spending a lot of time to optimise 8080 assembly code to fit in 2K EEPROMs. However I think that today this madness is no longer needed. 32-bit devices have large address spaces and can have any reasonably large amounts of Flash to no longer have to chase for the last free byte, and the vendors who sell those tiny devices are actually mocking on software developers time. My rule of thumb is that if the release binary needs more than half the available memory, your device selection is questionable. This is because a debug binary, compiled with -O0 and many trace messages, would need a lot more memory. However I accept that development can be done on a development board with a device variant with more memory, as long as the memory size is the only difference between the devices, and the production device does not go past 2/3, max 3/4 of total memory. Anyway, I just started the builds, hopefully tomorrow we'll have the new release. |
Do you have a link to the code that you're using for your tests please? |
Sorry, no. It's not a public project. |
OK - I thought that this meant that you were in a position to share the code and not just the results of compiling/linking:
I'll use the ch32v003fun repo for some tests instead so. |
ch32v003fun defaults to using a specifically tailored libgcc from gcc12. It doesn't take advantage of the xw extension, but it is known to be much better than many buggy libgcc's that have been distributed with compilers. I wonder if the actual source for errors in some of the other cases is GCC may have been using an emac or eac libgcc. We will continue to have to ship a "known good" libgcc.a, but, I would like to, if possible, maybe make the default not use our known-good libgcc.a. Also related to above discussion, I have modified ch32v003fun behavior to make the linker output the .map file instead of objdump, so it provides the link information you need, here cnlohr/ch32v003fun#471.
GCC aligns functions and codeblocks to 4-byte boundaries when targeting -ec. THANK GOODNESS too, since jumping to non-4-byte-aligned-places sometimes causes an extra cycle delay.
As seems to be the case for the majority of people working on the 003. I'm really glad to see how quickly industry has taken to it. Again, thank you for making all this happen. I am very excited to have a straightforward solution for people hoping to dev for the 003 in Windows that doesn't involve the old sysprogs GCC. |
Fixed in 14.2.0-3, on 2024-12-06. |
I still don't understand. Where does this tailored libgcc come from? What toolchain distro? Or is it the library here? Where are the sources? I don't think that the xPack toolchain is going to include and such tailoring so (how) is that going to affect results? |
Gosh I wish I documented that better. But, I believe it was the rv32ec libgcc.a from GCC12. I don't remember which distro specifically. It does not use the XW extension, so not from WCH. |
That's correct.
I think that messing with libraries like this is simply asking for trouble. Not exactly a professional solution and not recommended. |
Ok, this suggests that it may be the I agree with @ilg-ul that such tinkering with using standalone builds of such libraries isn't a good idea and it would be much better to use a the standard library from a known good build of the toolchain such as the latest xPack version if at all possible. And, to be fair, it sounds like that's what you (@cnlohr) would prefer too. 🙂 |
It is. Once I get more testing in, I plan to use and document the xpack .a and vendor it instead... There's just a lot of weird corner cases where the host provided libgcc.a is ... sub-par. Even on Linux distros. |
Sorry, what exactly does this mean? What does ".a" and "vendor it" mean?
Can you be more specific about what "host provided" library and sub-par characteristics you're referring to? |
libgcc.a and vendor = distribute a copy with the ch32v003fun repo. Many gcc builds by default do not include a suitable at all libgcc.a, especially for Arch users. So, we don't want to cause them extra pain. If someone wants to use GCC 7, they should be able to use GCC 7. But, from a practical standpoint a LOT of users do not have a suitable compiler. This thread is an example of that. In this case people were quick to correct, but there are lots of other situations where this is not addressed. And users live there. |
In what way specifically? Surely the regular BTW, if this PR could eventually be pushed through to completion then Picolibc might be another useful alternative to Newlibc: Even if that PR is not pushed through then a bare-metal RISC-V GCC with Picolib support can be built using crosstool-NG:
What's the issue with Arch Linux?
In which case something like the xPack RISC-V GCC addresses this issue I presume? |
libgcc.a is part of gcc, not newlib. |
Ah - OK. But the same questions still apply.
|
We don't rely on newlib, libc, etc... the usual culprits are all just weak-linked in ch32v003fun.c. So, if you do want to use a libc, you can, but you don't have to. But as ilg-ul pointed out, the issue is with libgcc, not newlib. And, it would be great if more people compiled libgcc.a for rv32ec, but I only added the .a, after several people complained about issues where their code either didn't compile, or was bigger than they expected. People don't want to be locked into a specific compiler. Vendoring libgcc.a removes all those variables. As long as their compiler can target rv32ec, they're good to go... Which as far as I can tell is everyone. To reiterate, I only added a copy of libgcc.a because a lot of users were complaining. For other processors, no one seems to have complained. I just let the compiler do its thing - and until people start complaining, I am going to leave it that way. https://github.com/cnlohr/ch32v003fun/blob/master/ch32v003fun/ch32v003fun.mk#L44 |
Oh, also, I found the underlying issue. When targeting Platform IO, the build system does not by default use the bundled libgcc.a, so, for those users it is more important that the compiler includes this. Thanks again for adding this. |
I'm still confused as to what the original (and ongoing?) issue is with libgcc.a and If, for example, I build the
Then I get this:
And the second libgcc.a is compiled with/for In this case the toolchain default There is no mismatch between the Am I still missing something here? |
Actually the issue is neither with libgcc nor with newlib. Properly built toolchains are fine and do not need such kludges. |
I agree. I just still don't understand what the (actual or perceived) rationale was for having to provide a standalone (custom[ised?]?) libgcc.a with the ch32v003fun project. |
The proper steps for building a toolchain from source are irrelevant. Everyone just And I'm happy to support them. |
If you want a toolchain that supports a custom set of multilibs - e.g. including
If you want the maintainers of specific GNU/Linux distros to have their software repositories host a RISC-V bare-metal toolchain that bundles specific multilibs for specific I'm not sure why you mention the RISC-V Linux toolchain here as it seems completely irrelevant to a tiny embedded device like WCH32V003 and similar devices from WCH.
|
I note that all new releases since September 2024 (v14.2.0-2, v13.3.0-2, v12.4.0-2, v11.5.0-2) no longer feature rv32ec/ilp32e libraries. Was there a specific reason for the removal?
Such removal is detrimental to all (myself included) who rely on xPack RISC-V GCC to compile code for RV32E microcontrollers that support the 'C' compact instruction extension. For example, the very popular CH32V00x series of microcontrollers.
The impact is that any code being compiled and linked with
-mabi=ilp32e -march=rv32ec
gets silently 'downgraded' to instead use the rv32e/ilp32e libraries, and the resulting compiled binaries become larger, even with no other changes. When this happens, there may be no clue readily apparent to the user as to why - I believe the only indication is via the library paths given in map file output (i.e. from-Wl,-Map
).Without the rv32ec library functions, compiled binary sizes can increase by hundreds of bytes or potentially kilobytes! When dealing with microcontrollers that have flash memory measured in only tens of kilobytes, such increases could make the difference between code fitting within the available flash and suddenly not.
Could you please reinstate the rv32ec/ilp32e libraries?
The text was updated successfully, but these errors were encountered: