Yes, newlib is a pig! But in the demo project, no library function is ever called. Yes, I imagine some C library functions might be called but it seems unlikely given the code that was written. I can't see where newlib comes into this project.
.platformio/packages/framework-freedom-e-sdk/env/freedom-e300-hifive1/init.c:225:25
printf("core freq at %d Hz\n", get_cpu_freq());
On newer versions I've replaced that with a custom itoa() and three puts() which cuts the bloat hugely.
I need to look around in the IDE and find the compile/link options. They have to be there somewhere. I want to see the assembly output and the link map.
PlatformIO isn't supplying all the tools, for example there is no objdump :-(
If you want to poke more deeply you'll be better off using the command-line freedom-e-sdk direct from SiFive. I recommend building it -- it's 25 minutes on a quad core. (but there are precompiled binaries too)
https://github.com/sifive/freedom-e-sdkThe interesting part of RISC ISAs is how the hardware handles hazards. The deeper the pipeline, the more complex it gets. Throwing away partially executed instructions because a branch was taken but couldn't be predicted because the condition code hadn't been updated from an arithmetic operation that hadn't completed - it gets complicated!
No problem in an in-order CPU, which includes everything anyone has shipped so far. Instructions after the branch have been fetched and decoded and their operands fetched, but they don't *execute* until after the branch does .. at which point it is known whether it will branch or not. If the prediction was wrong then execution of already-fetched instructions is squashed and fetch/decode starts again at the correct place.
Next question: How many of the more esoteric op codes does the compiler use? The problem with building an FPGA version is to ensure you have implemented enough of the instruction set to allow the compiler to generate workable code. Or, be prepared to rewrite the code generation of the C compiler!
All of them!
If you want to build your own CPU in an FPGA then you only need to implement RV32I, which has only and exactly what is needed to compile C code ... but omitting multiply and divide. gcc will happily emit code for this, using library functions for multiply and divide.
The complete RV32I instruction set:
Registers r0 ... r31. r0 is always 0, can be used to discard unwanted results (e.g. jal/jalr)
PC is separate. There is no dedicated SP or LR at the hardware level.
All immediate values are signed.
OP rd, rs1, rs2 ; OP = add/sub, slt/sltu (rd=1 if less than, else 0), and/or/xor, sll/srl/sla (shifts)
OPi rd, rs1, 0xNNN ; OP = add, slt/sltu, and/or/xor, sll/srl/sra
lui rd, 0xNNNNN ; load immediate<<12 into rd
auipc rd, 0xNNNNN ; add immediate<<12 to the PC and store in rd
jal rd, 0xNNNNN ; add immediate<<1 to the PC. Store old PC in rd
jalr rd, 0xNNN(rs1) ; add immediate to rs1, clear the low bit, store in the PC. Store old PC in rd
bOP rs1, rs2, 0xNNN ; if rs1 OP rs2 is true add immediate<<1 to PC; OP = eq/ne/lt/ltu/ge/geu
sSZ rs2, 0xNNN(rs1); add immediate to rs1, use as address to store from rs2, SZ = b/h/w
lSZ rd, 0xNNN(rs1); load to rd. SZ = b/bu/h/hu/w (u zero extends, others sign extend)
ecall/ebreak ; no arguments. Call OS or debugger.
There's not a lot of fat there.
Optional: implement only r0 .. r15 and then use -march=rv32e to gcc ("e" for embedded)
Optional: implement multiply/divide -march=rv32im (or em)
Optional: implement atomic operations for SMP -march=rv32a
Optional: implement 16 bit opcodes duplicating the most common 32 bit opcodes for code density comparable to Thumb2 instead of comparable to ARM -march=rv32ic
Optional: implement floating point -march=rv32if or rv32ifd
You can compile any normal C/C++ code and newlib using rv32i or rv32e. The linux kernel and glibc require at least rv32ia (actually I think they require rv64ia at present, but that is being fixed).
At the moment, the RISC V is in its infancy. It's been around a while but there is strong competition from ARM and ARM covers quite a broad spectrum of computing. In the meantime, it's worth knowing how the RISC V works. If you like knowing that kind of stuff...
Yes, it's early days, but momentum is building.
There is no great *technical* advantage over ARM or MIPS, but also no disadvantage. Compare code size, compare Dhrystone or Coremark or SPEC ... it's a photo finish in most cases. MIPS code is the biggest (and microMIPS doesn't help as much as Thumb or rvc), rv32i is comparable to ARM, rv32ic to Thumb2. In 64 bit, rv64ic is much smaller than anything else (ARM didn't see fit to duplicate Thumb in 64 bit!).
The advantage is that absolutely anyone is free to implement their own CPU (FPGA, ASIC, emulator), call it "RISC-V" if it passes the conformance tests, and use it, sell it, give it away as you please. You are not going to get any nasty lawyers letters.
The advantage over implementing your own instruction set is that someone else already wrote/ported a huge amount of software for you.