Skip to content
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

Closed
basilhussain opened this issue Nov 17, 2024 · 90 comments
Closed

Please reinstate the rv32ec/ilp32e libraries #38

basilhussain opened this issue Nov 17, 2024 · 90 comments
Assignees
Labels
enhancement New feature or request

Comments

@basilhussain
Copy link

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?

@ilg-ul
Copy link
Member

ilg-ul commented Nov 17, 2024

Was there a specific reason for the removal?

I have nothing agains rv32ec in particular, just that the previous list of libraries was combinatorial and grew too large. Having no other inspiration, when I had to cut it to a reasonable size, I used the same list as Debian packages.

Could you please reinstate the rv32ec/ilp32e libraries?

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?

@ilg-ul
Copy link
Member

ilg-ul commented Nov 17, 2024

I took a look at the current list. As a temporary workaround, if your code does not use atomic instructions, could you use the rv32eac library?

@basilhussain
Copy link
Author

I'll consider this for the next release.

Thanks! 😃

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'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:

  • QingKeV2A - RV32EC
  • QingKeV2C - RV32EmC*
  • QingKeV3A - RV32IMAC
  • QingKeV3B - RV32IMCB*
  • QingKeV3C - RV32IMCB*
  • QingKeV4A - RV32IMAC
  • QingKeV4B - RV32IMAC
  • QingKeV4C - RV32IMAC
  • QingKeV4F - RV32IMACF

(* '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:

  • EC
  • IMC
  • IMAC
  • IMACF

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.

As a temporary workaround, if your code does not use atomic instructions, could you use the rv32eac library?

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.

@ilg-ul
Copy link
Member

ilg-ul commented Nov 17, 2024

but I found this article

Yes, good article.

I think it's safe to say that at least the following is needed...

imacf is present as rv32imafc_zicsr.

So only ec, imc, imac are missing?

Tommy @TommyMurphyTM1234, any comments on this proposal?

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.

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.

@ilg-ul ilg-ul self-assigned this Nov 17, 2024
@ilg-ul ilg-ul added the enhancement New feature or request label Nov 17, 2024
@TommyMurphyTM1234
Copy link

Tommy @TommyMurphyTM1234, any comments on this proposal?

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...

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.

That's my understanding too - i.e. that the compiler will never "automatically" generate atomic instructions.

@basilhussain
Copy link
Author

So only ec, imc, imac are missing?

That would appear to be the case, yes. I would bet that set of 4 would cover 99% of RISC-V microcontrollers.

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.

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 addi a3,a3,-1316 that has become a addi a3,a3,-1315. No idea why an offset literal value would change when literally every other byte in the binary is identical... 😕)

It'll probably take me some time, possibly a few weeks, to prepare a new maintenance release with the new libraries.

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.

@ilg-ul
Copy link
Member

ilg-ul commented Nov 17, 2024

To summarise, the missing libraries are:

  • rv32ec
  • rv32imc
  • rv32imac

The WCH specific extensions are out of my scope.

@TommyMurphyTM1234
Copy link

The WCH specific extensions are out of my scope.

Can you clarify what you're referring to here?
I presume something like...

  1. __attribute __ ((interrupt("WCH-Interrupt-fast")))
  2. WCH (or QingKe?) proprietory non-standard extension xw
  3. Other?

@ilg-ul
Copy link
Member

ilg-ul commented Nov 18, 2024

All of the above.

@basilhussain
Copy link
Author

The WCH specific extensions are out of my scope.

Yes, of course, because none of that is in mainline GCC. Although it would be nice if they added XW support.

@ilg-ul
Copy link
Member

ilg-ul commented Nov 18, 2024

it would be nice if they added XW support.

Sure, ask them, perhaps they'll do it. I have no contacts there.

@TommyMurphyTM1234
Copy link

The WCH specific extensions are out of my scope.

Yes, of course, because none of that is in mainline GCC. Although it would be nice if they added XW support.

Did MounRiver ever release their modifications to GCC that added support for it, as they're obviously obliged to do under GPL?

@ilg-ul
Copy link
Member

ilg-ul commented Nov 18, 2024

No idea.

@cnlohr
Copy link

cnlohr commented Nov 18, 2024

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.

@cnlohr
Copy link

cnlohr commented Nov 18, 2024

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.

@ilg-ul
Copy link
Member

ilg-ul commented Nov 18, 2024

have you considered separating out RV32/RV64 as different packages

Only as a last resort.

500MB download

Now the archives are in the 300MB range. Still large, but somehow manageable.

@cnlohr
Copy link

cnlohr commented Nov 20, 2024

All fair. Just 🙏 for the rv32ec/ilp32e.

@cnlohr
Copy link

cnlohr commented Dec 4, 2024

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

@ilg-ul
Copy link
Member

ilg-ul commented Dec 4, 2024

I'm really busy these days with the new web for the whole xPack project. It might take 1-2 more weeks.

@TommyMurphyTM1234
Copy link

TommyMurphyTM1234 commented Dec 4, 2024

To summarise, the missing libraries are:

  • rv32ec
  • rv32imc
  • rv32imac

The WCH specific extensions are out of my scope.

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 rv32ec-ilp32e-- should be added? Should it have any additional aliasing - e.g. rv32ec-ilp32e--m - or not?

(2) rv32imc is listed above as missing but isn't it already covered by this (below) or should that be replaced by the explicit rv32imc-ilp32-- in order to take advantage of compressed instructions?

(3) rv32imac is listed above as missing but this seems to be already catered for?

(4) Should anything be change/be added here?

(5) If making changes I would endeavour to update the multilib-generator comment and any other relevant comments:

  • # ./multilib-generator rv32e-ilp32e--c rv32ea-ilp32e--m rv32em-ilp32e--c rv32eac-ilp32e-- rv32emac-ilp32e-- rv32i-ilp32--c rv32ia-ilp32--m rv32im-ilp32--c rv32if-ilp32f-rv32ifd-c rv32iaf-ilp32f-rv32imaf,rv32iafc-d rv32imf-ilp32f-rv32imfd-c rv32iac-ilp32-- rv32imac-ilp32-- rv32imafc-ilp32f-rv32imafdc- rv32ifd-ilp32d--c rv32imfd-ilp32d--c rv32iafd-ilp32d-rv32imafd,rv32iafdc- rv32imafdc-ilp32d-- rv64i-lp64--c rv64ia-lp64--m rv64im-lp64--c rv64if-lp64f-rv64ifd-c rv64iaf-lp64f-rv64imaf,rv64iafc-d rv64imf-lp64f-rv64imfd-c rv64iac-lp64-- rv64imac-lp64-- rv64imafc-lp64f-rv64imafdc- rv64ifd-lp64d--m,c rv64iafd-lp64d-rv64imafd,rv64iafdc- rv64imafdc-lp64d--
  • # Possible future 'light' releases should include:
    # - rv32imac, rv64imafdc: for QEMU tests
    # - rv32imac: for SiFive HiFive1 (16K RAM only!)
    # - rv32ec: for the small WCH CH32V003
    # - rv32imac, rv32imacf: for WCH QingKe V4 series (xw!)
    # like CH32V20[38]*, CH32V30[357]*
    # https://www.wch-ic.com/downloads/QingKeV4_Processor_Manual_PDF.html
  • etc.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 4, 2024

The problem is not adding three lines in the script, but the many hours that the builds take.

@TommyMurphyTM1234
Copy link

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.
They are not clear to me from the previous discussion.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 4, 2024

I would really like to switch the target for ch32v003fun to xpack

What platform are using? I can make a pre-release these days so you can try it.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 4, 2024

It would still help to clearly identify the changes that need to be made.

I updated the build script. There were only two changes needed, the other two combinations were already there.

  • rv32e-ilp32e--c was changed to rv32e-ilp32e-- and rv32ec-ilp32e--
  • rv32im-ilp32--c was changed to rv32im-ilp32-- and rv32imc-ilp32--

The meaning of --c is that the given combination (like rv32e) is used for both rv32e and rv32ec. In other words, the library is compiled with rv32e (without c) and is linked to applications compiled with or without c. The result is perfectly functional, but the libraries, not using the compressed instructions, are slightly larger, as @basilhussain noticed.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 4, 2024

BTW @cnlohr, did you try the existing binaries and you could not build your application due to lack of space in flash?

@cnlohr
Copy link

cnlohr commented Dec 4, 2024

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 ilp32e--c, and instead just ilp32e I can definitely test it out!

I am personally unaware of any differences at all between ilp32e and ilp32e--c or between rv32e-ilp32e-- / rv32ec-ilp32e-- but, the core ilp32ec is a pretty hard requirement for us to use it... And, there are massive differences between ilp32 and ilp32e

EDIT: Sorry, I'm not up n up on much GCC past GCC12.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 4, 2024

If you have a test build ready without the extra ilp32e--c, and instead just ilp32e I can definitely test it out!

I'll have a darwin-x64 archive probably in a few hours.

@cnlohr
Copy link

cnlohr commented Dec 5, 2024

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.

@TommyMurphyTM1234
Copy link

TommyMurphyTM1234 commented Dec 5, 2024

It "looks like" it might be linking to the libgcc.a in lib\gcc\riscv-none-elf\14.2.0 - not in any of the arch-specific folders. Which has mulsi3, but, oddly enough other functions in there seem to assume rv32imac

FYI...

If a specific multilib cannot be matched for the arch/abi selected at compile/link time (taking account of any "reuse" patterns if applicable) then the linker will fall back on linking the toolchain default libs. And in the case of the xPack toolchain that's rv32imac/ilp32.

Since this uses the ilp32 ABI it presumably won't work correctly on an rv32e target which requires ilp32e?

@TommyMurphyTM1234
Copy link

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.

Sorry, what exactly do you mean by "vendored" GCC/libgcc here?

@ilg-ul
Copy link
Member

ilg-ul commented Dec 5, 2024

If a specific multilib cannot be matched for the arch/abi selected at compile/link time (taking account of any "reuse" patterns if applicable) then the linker will fall back on linking the toolchain default libs. And in the case of the xPack toolchain that's rv32imac/ilp32.

Right, but this is not the case with 14.2.0-2, since the rv32e-ilp32e--c is exactly this, a reuse pattern of the rv32e-ilp32e library for builds with rv32ec-ilp32e. So normally the use of rv32imac/ilp32 should not occur in this case.

But indeed, this might be a potential source of errors.

@TommyMurphyTM1234
Copy link

If a specific multilib cannot be matched for the arch/abi selected at compile/link time (taking account of any "reuse" patterns if applicable) then the linker will fall back on linking the toolchain default libs. And in the case of the xPack toolchain that's rv32imac/ilp32.

Right, but this is not the case with 14.2.0-2, since the rv32e-ilp32e--c is exactly this, a reuse pattern of the rv32e-ilp32e library for builds with rv32ec-ilp32e. So normally the use of rv32imac/ilp32 should not occur in this case.

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 rv32ec/ilp32e so the toolchain default with a different and potentially incompatible arch/abi was linked instead.

But the references to "vendored" GCC/libgcc make things unclear for me. It would help if clearer information was posted for each test/incident.

@basilhussain
Copy link
Author

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:

                              obj\Release\flash.o (__riscv_save_2)
C:/Users/Basil/AppData/Roaming/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-13.3.0-1/bin/../lib/gcc/riscv-none-elf/13.3.0/rv32ec/ilp32e\libgcc.a(muldi3.o)
                              obj\Release\main.o (__mulsi3)
C:/Users/Basil/AppData/Roaming/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-13.3.0-1/bin/../lib/gcc/riscv-none-elf/13.3.0/rv32ec/ilp32e\libgcc.a(div.o)
                              obj\Release\uart.o (__divsi3)
C:/Users/Basil/AppData/Roaming/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-13.3.0-1/bin/../lib/gcc/riscv-none-elf/13.3.0/../../../../riscv-none-elf/lib/rv32ec/ilp32e\libc_nano.a(libc_a-strcat.o)
                              obj\Release\main.o (strcat)
C:/Users/Basil/AppData/Roaming/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-13.3.0-1/bin/../lib/gcc/riscv-none-elf/13.3.0/../../../../riscv-none-elf/lib/rv32ec/ilp32e\libc_nano.a(libc_a-memset.o)
                              obj\Release\main.o (memset)
C:/Users/Basil/AppData/Roaming/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-13.3.0-1/bin/../lib/gcc/riscv-none-elf/13.3.0/../../../../riscv-none-elf/lib/rv32ec/ilp32e\libc_nano.a(libc_a-memcpy-asm.o)
                              obj\Release\i2c.o (memcpy)

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:

  rv32ec (13.3.0-1) rv32e (13.3.0-2) Difference
__riscv_save_2 20 40 +20
__mulsi3 22 36 +14
__divsi3 126 180 +54
strcat 28 44 +16
memset 16 28 +12
memcpy 22 36 +14
  234 364 +130

For example, __mulsi3 with rv32ec from 13.3.0-1:

000000b4 <__mulsi3>:
      b4:	       862a                	mv	a2,a0
      b6:	       4501                	li	a0,0
      b8:	/----> 0015f693          	andi	a3,a1,1
      bc:	|  /-- c291                	beqz	a3,c0 <__mulsi3+0xc>
      be:	|  |   9532                	add	a0,a0,a2
      c0:	|  \-> 8185                	srli	a1,a1,0x1
      c2:	|      0606                	slli	a2,a2,0x1
      c4:	\----- f9f5                	bnez	a1,b8 <__mulsi3+0x4>
      c6:	       8082                	ret
      c8:	       0000                	unimp

And __mulsi3 with rv32e from 13.3.0-2:

000000c8 <__mulsi3>:
      c8:	       00050613          	mv	a2,a0
      cc:	       00000513          	li	a0,0
      d0:	,----> 0015f693          	andi	a3,a1,1
      d4:	|  ,-- 00068463          	beqz	a3,dc <__mulsi3+0x14>
      d8:	|  |   00c50533          	add	a0,a0,a2
      dc:	|  '-> 0015d593          	srli	a1,a1,0x1
      e0:	|      00161613          	slli	a2,a2,0x1
      e4:	'----- fe0596e3          	bnez	a1,d0 <__mulsi3+0x8>
      e8:	       00008067          	ret

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.)

@ilg-ul
Copy link
Member

ilg-ul commented Dec 5, 2024

When you only have 16K to play with, that's already becoming significant.

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.

@TommyMurphyTM1234
Copy link

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.

Do you have a link to the code that you're using for your tests please?

@basilhussain
Copy link
Author

Do you have a link to the code that you're using for your tests please?

Sorry, no. It's not a public project.

@TommyMurphyTM1234
Copy link

I can give an example from one of my codebases for CH32V003.

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 can give an example from one of my codebases for CH32V003.

I'll use the ch32v003fun repo for some tests instead so.

@cnlohr
Copy link

cnlohr commented Dec 5, 2024

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.

Sorry, what exactly do you mean by "vendored" GCC/libgcc here?

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.

(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.)

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.

Sorry, no. It's not a public project.

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.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 6, 2024

Fixed in 14.2.0-3, on 2024-12-06.

@ilg-ul ilg-ul closed this as completed Dec 6, 2024
@TommyMurphyTM1234
Copy link

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 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?

@cnlohr
Copy link

cnlohr commented Dec 6, 2024

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.

@ilg-ul
Copy link
Member

ilg-ul commented Dec 6, 2024

I don't think that the xPack toolchain is going to include and such tailoring

That's correct.

I believe it was the rv32ec libgcc.a from GCC12

I think that messing with libraries like this is simply asking for trouble. Not exactly a professional solution and not recommended.

@TommyMurphyTM1234
Copy link

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.

Ok, this suggests that it may be the riscv-gnu-toolchain GCC 12.2.0 libgcc.a configured/built for rv32ec/ilp32e?

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. 🙂

@cnlohr
Copy link

cnlohr commented Dec 6, 2024

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.

@TommyMurphyTM1234
Copy link

TommyMurphyTM1234 commented Dec 6, 2024

I plan to use and document the xpack .a and vendor it instead...

Sorry, what exactly does this mean? What does ".a" and "vendor it" mean?

There's just a lot of weird corner cases where the host provided libgcc.a is ... sub-par. Even on Linux distros.

Can you be more specific about what "host provided" library and sub-par characteristics you're referring to?

@cnlohr
Copy link

cnlohr commented Dec 6, 2024

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.

@TommyMurphyTM1234
Copy link

Many gcc builds by default do not include a suitable at all libgcc.a

In what way specifically? Surely the regular riscv-gnu-toolchain Newlib libgcc.a compiled for rv32ec/ilp32e (at least for the CH32V003 and similar devices?) is completely adequate? What other features or customisations are needed (assuming that we're ignoring proprietary WCH features like the xw ISA and fast interrupt extensions?)? Are other WCH devices that ch32v003fun supports using different architectures, ABIs and/or extensions that might necessiate a toolchain with a specific set of multilibs perhaps?

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:

especially for Arch users.

What's the issue with Arch Linux?

a LOT of users do not have a suitable compiler.

In which case something like the xPack RISC-V GCC addresses this issue I presume?
(I'm assuming that it works on Arch Linux as long as the host GLIBC version requirements are met).

@ilg-ul
Copy link
Member

ilg-ul commented Dec 8, 2024

the regular riscv-gnu-toolchain Newlib libgcc.a

libgcc.a is part of gcc, not newlib.

@TommyMurphyTM1234
Copy link

the regular riscv-gnu-toolchain Newlib libgcc.a

libgcc.a is part of gcc, not newlib.

Ah - OK. But the same questions still apply.

In what way specifically? Surely the regular riscv-gnu-toolchain Newlib libgcc.a compiled for rv32ec/ilp32e (at least for the CH32V003 and similar devices?) is completely adequate? What other features or customisations are needed (assuming that we're ignoring proprietary WCH features like the xw ISA and fast interrupt extensions?)? Are other WCH devices that ch32v003fun supports using different architectures, ABIs and/or extensions that might necessiate a toolchain with a specific set of multilibs perhaps?

@cnlohr
Copy link

cnlohr commented Dec 9, 2024

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

@cnlohr
Copy link

cnlohr commented Dec 9, 2024

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.

@TommyMurphyTM1234
Copy link

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

I'm still confused as to what the original (and ongoing?) issue is with libgcc.a and rv32ec/ilp32e.

If, for example, I build the riscv-gnu-toolchain as follows:

git clone https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=`pwd`/installed-tools --with-multilib-generator="rv32ec-ilp32e--"
make

Then I get this:

cd installed-tools
find . -name "libgcc*" -print
./lib/gcc/riscv64-unknown-elf/14.2.0/libgcc.a
./lib/gcc/riscv64-unknown-elf/14.2.0/rv32ec/ilp32e/libgcc.a

And the second libgcc.a is compiled with/for rv32ec/ilp32e.

In this case the toolchain default arch/abi is rv64gc/lp64d but I could have changed this (as xPack does - it uses rv32imac/ilp32) or even configured the toolchain specifically for rv32ec/ilp32e (using configure --with-arch=rv32ec --with-abi=ilp32e ...).

There is no mismatch between the rv32ec/ilp32e libgcc.a with an rv32ec/ilp32e target such as WCH32V003, no renaming of the library is required, no customisation of the library is needed, and no "vendoring" (?) is needed.

Am I still missing something here?

@ilg-ul
Copy link
Member

ilg-ul commented Dec 9, 2024

the issue is with libgcc, not newlib.

Actually the issue is neither with libgcc nor with newlib. Properly built toolchains are fine and do not need such kludges.

@TommyMurphyTM1234
Copy link

the issue is with libgcc, not newlib.

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.

@cnlohr
Copy link

cnlohr commented Dec 10, 2024

The proper steps for building a toolchain from source are irrelevant.

Everyone just sudo pacman -S riscv64-elf-newlib apt-get install gcc-riscv64-unknown-elf or dnf install gcc-riscv64-linux-gnu

And I'm happy to support them.

@TommyMurphyTM1234
Copy link

The proper steps for building a toolchain from source are irrelevant.

If you want a toolchain that supports a custom set of multilibs - e.g. including rv32ec/ilp32e, and maybe others? - then the (xPack or riscv-gnu-toolchain) build steps for making this happen are very much relevant.

Everyone just sudo pacman -S riscv64-elf-newlib apt-get install gcc-riscv64-unknown-elf or dnf install gcc-riscv64-linux-gnu

And I'm happy to support them.

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 arch/abi's then you probably need to engage with them for this to happen.

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.

dnf install gcc-riscv64-linux-gnu

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants