openhwgroup / corev-binutils-gdb Goto Github PK
View Code? Open in Web Editor NEWLicense: GNU General Public License v2.0
License: GNU General Public License v2.0
A while ago I rewrote and ported the pulp gcc and pulp binutils to a newer gcc release. I imported the new tests that were added to the assembler and I found a few discrepancies:
From https://cv32e40p.readthedocs.io/en/latest/instruction_set_extensions/#general-alu-encoding
cv.extbs t0,t1
is encoded as 0x040362b3
, but I think this should be 0x100362b3
. The 28-th bit (counting from zero) should be 1. (python -c 'print(0x100362b3 >> 28 & 1)'
). Similar issue with the other ext*
instructions.From https://cv32e40p.readthedocs.io/en/latest/instruction_set_extensions/#hardware-loops
cv-hwlp-fail-operand-01.s
it assumes that the branch offset must be an even integer in [0, 4094]
. Looking at the encoding though (12-bit unsigned immediate) it seems to me the range should be an even integer in [0, 8190]
Robert
For all cv.shuffleI*.sci.* instructions, the specification is maybe not clear enough but immediate values should always be treated as unsigned. Because this immediate value is not representing a number (its sub-parts are individually used as indexes).
Specification will be improved for that point.
cv.elw is generated using v1 encoding:
01cfef83 cv.elw x31,28(x31)
while it should be
01cfbf8b cv.elw x31,28(x31)
v2 specification extract:
+-------------+--------+----------+--------+------------+---------------------------+
| 31 : 20 | 19 :15 | 14 : 12 | 11 :07 | 06 : 00 | |
+-------------+--------+----------+--------+------------+---------------------------+
| imm[11:0] | rs1 | funct3 | rd | opcode | Mnemonic |
+=======+=====+======+=====+=======+================+
| offset | base | 011 | dest | 000 1011 | cv.elw rD, Imm(rs1) |
+-------------+--------+----------+--------+------------+---------------------------+
Hi,
During the PULP instructions re-encoding, it appeared that some instructions were redundant and have been removed.
They are cv.mulu, cv.muls, cv.mulhhu and cv.mulhhs.
Toolchain should generate an error when trying to use them or
assembler pseudo-instruction should be added to emulate them (cv.mul* ... => cv.mul*N ... , 0).
It looks like we used CFI information from msave restore to implement push/pop, while they are reversed ?
This could potentially mean that the debugger wont work when we have exception and we try to unwind stack frame
ref : riscvarchive/riscv-code-size-reduction#182
hi,
https://github.com/openhwgroup/corev-binutils-gdb/blob/development/bfd/elfnn-riscv.c
For R_RISCV_CALL and R_RISCV_CALL_PLT, in relax_pass 0 and relax_trip 2 of _bfd_riscv_relax_section, if benifical the auipc is replaced by zcmt instruction in _bfd_riscv_table_jump_mark.
But in relax_pass 1 of _bfd_riscv_relax_call, it seems the marked instruction fails to be relaxed to a zcmt insntruction if auipc+jalr could not be shortened to jal or jalr(near zero) due to the following condition check:
/* See if this function call can be shortened. */
if (!VALID_JTYPE_IMM (foff) && !(!bfd_link_pic (link_info) && near_zero)
&& link_info->relax_pass != 0)
return true;
Seems we need to move the following codes to the top of function to avoid being blocked by the condition above.
/* Relax a table jump instruction that is marked. */
if (link_info->relax_pass == 1
&& ((auipc ^ MATCH_TABLE_JUMP) & MASK_CM_JALT) == 0)
{
rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TABLE_JUMP);
*again = true;
return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 6, link_info, pcgp_relocs);
}
BR
Joshcafe
Hi,
Running the following sequence of commands with binutils corev-openhw-gcc-centos7-20230310
results in a segfault. This appear to only happen when the source file for the compile and link command to gcc is a file written in assembly, I have not yet observed this error when the source file is a C-file.
collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
compilation terminated.
Code located here and is reproducible on my end with the following commands:
riscv32-corev-elf-gcc -Os -g -static -mabi=ilp32 -march=rv32im_zba1p00_zbb1p00_zbc1p00_zbs1p00_zicsr_zca_zcb_zcmp_zcmt_zifencei -Wall -pedantic -mno-relax -c ./bsp/crt0.S -o ./bsp/crt0.o
riscv32-corev-elf-gcc -Os -g -static -mabi=ilp32 -march=rv32im_zba1p00_zbb1p00_zbc1p00_zbs1p00_zicsr_zca_zcb_zcmp_zcmt_zifencei -Wall -pedantic -mno-relax -c ./bsp/handlers.S -o ./bsp/handlers.o
riscv32-corev-elf-gcc -Os -g -static -mabi=ilp32 -march=rv32im_zba1p00_zbb1p00_zbc1p00_zbs1p00_zicsr_zca_zcb_zcmp_zcmt_zifencei -Wall -pedantic -mno-relax -c ./bsp/syscalls.c -o ./bsp/syscalls.o
riscv32-corev-elf-gcc -Os -g -static -mabi=ilp32 -march=rv32im_zba1p00_zbb1p00_zbc1p00_zbs1p00_zicsr_zca_zcb_zcmp_zcmt_zifencei -Wall -pedantic -mno-relax -c ./bsp/vectors.S -o ./bsp/vectors.o
riscv32-corev-elf-ar rcs ./bsp/libcv-verif.a ./bsp/crt0.o ./bsp/handlers.o ./bsp/syscalls.o ./bsp/vectors.o
// The following gcc invocations both result in segmentation faults:
riscv32-corev-elf-gcc -Os -g -static -mabi=ilp32 -march=rv32im_zba1p00_zbb1p00_zbc1p00_zbs1p00_zicsr_zca_zcb_zcmp_zcmt_zifencei -Wall -pedantic -I ./bsp -o generic_exception_test.elf -nostartfiles ./generic_exception_test.S -T ./link.ld -L ./bsp -lcv-verif
riscv32-corev-elf-gcc -Os -g -static -mabi=ilp32 -march=rv32im_zba1p00_zbb1p00_zbc1p00_zbs1p00_zicsr_zca_zcb_zcmp_zcmt_zifencei -Wall -pedantic -I ./bsp -o cv32e40s_readonly_csr_access_test.elf -nostartfiles ./cv32e40s_readonly_csr_access_test.S -T ./link.ld -L ./bsp -lcv-verif
Hello,
we're using the cv32e40p on FPGA and building FW for it using the corev-gcc toolchain. We added a custom instruction and I could add it to corev-gcc so we can actually use it (btw, thanks for the great work).
I was now looking for a simulator (doesn't have to be cycle-accurate), and I stumble upon the gdb sim target for risc-v and the one from Imperas. From what I understood so far, the risc-v gdb simulator doesn't support any corev extension, which are on the other hand supported by the Imperas simulator. If I understand correctly, however, to add a custom instruction the Imperas simulator requires to get in touch with Imperas, as the simulator is not open source.
On the simulator landscape is also Spike, which seems to be straightforward to extend with new instructions. I was wondering if there is any reason why the corev extensions are not present in Spike, and what would be in your opinion the best way to add corev and custom extensions to an open source simulator.
Status: IN PROGRESS: Links to Work in Progress Branches:
Status: IN PROGRESS: Links to Patch Reviews:
Status: Upstream
The question of relocation has not been addressed for the Event Load Word instruction. Does it need a custom relocation?
As per discussion in openhwgroup/corev-gcc#71, these instructions have an immediate whose range is not the full range, [0, 63], is there special care needed to be taken for these instructions?
Note that
cv.sll/sra/srl.b/h
only uses the lower 3 or 4 bits since each element of the vector is 8 or 16 bits long.The assembler handles this. However, no errors or warnings are generated if the input to the immediate is larger than 4 bits.
Also,
cv.extract/extractu.b/h
only uses the lower 1 or 2 bits since the length of the vectors is 2 or 4.Same for
cv.extract/extractu.b/h
.
Originally posted by @MaryBennett in openhwgroup/corev-gcc#71 (comment)
hi,
When I used the toolchain that enabled zcmt extension to compile the executable program using newlib, I found that the _localeconv_r
was compiled into redundant cm.jalt
instructions, which caused the program to enter a dead loop. That was inconsistent with the actual behavior of the function.
The test cases are as follows:
80002fe4 <_localeconv_r>:
80002fe4: 0fffd517 auipc a0,0xfffd
80002fe8: a17a cm.jalt 94 # 80002fe4 <_sp+0xefff2fe4>
80002fea: 16c0 addi s0,sp,868
80002fec: 8082 ret
80004088 <_localeconv_r>:
80004088: 0fffc517 auipc a0,0xfffc
8000408c: 0c850513 addi a0,a0,200 # 90000150 <__global_locale+0xf0>
80004090: 00008067 ret
Two issues:
Latest build of binutils (20230220):
The following sources were used in this build:
binutils-gdb: 457bde5 (https://github.com/openhwgroup/corev-binutils-gdb.git)
build-scripts: f838fc127e015bf4d755e6796098903947b3c89e (https://github.com/embecosm/embecosm-toolchain-releases.git)
gcc: 0976f97e333d9abfe666dfe81f5b8d3fcb85a1c6 (https://github.com/openhwgroup/corev-gcc.git)
newlib: f0417a620182083fa787eea90e2e1d9884c8e573 (https://mirrors.git.embecosm.com/mirrors/newlib-cygwin.git)
binutils-gdb-sim: 18ea42a432d16db09fbed5bc9e60b4e3b7c2caa7 (https://github.com/embecosm/riscv-binutils-gdb.git)
I am seeing these error messages in my log when trying to compile assembly code:
Make the change: openhwgroup/cv32e40p#833
Actions:
For all cv.min/maxu.sci.* instructions, immediate values should be treated as unsigned as stated in the specification:
3. Immediate scalar replication mode (.sci), vector-scalar operation. Operand 1 is treated as vector, while operand 2 is treated as a scalar and comes from an immediate. The immediate is either sign- or zero-extended, depending on the operation. If not specified, the immediate is sign-extended.
But the compiler is giving an error:
Error: immediate value must be 6-bit signed, 50 is out of range
Hi,
Using following standard RISC-V bit manipulation instruction with hexadecimal value (for immediate) having 6th bit set to one to have sign-extension is giving an error from assembler:
c.andi x8, 0x3c
test.S: Assembler messages:
test.S:247: Error: illegal operands `c.andi x8,0x3c'
while c.andi x8, 0x1c is not having error.
Only way to achieve required final mask (0xffff_fffc) without error is to use decimal value for immediate:
c.andi x8, -4
I know this is the preferred way for disassembler to print short immediate using decimal representation.
But I was expecting assembler would accept both hexadecimal/decimal representation as it is weird to use decimal values for masks in bit manipulation instructions.
Hi,
Is there a way to force the linker to include the Zcmt jump table? I am trying to build some projects using the Zcmt extension but the linker does not seem to be adding the jump table in my specific case. To test this issue I created some other small projects and it seems like the jump table is added in some cases but not in all cases.
For instance if I create a small hello-world project using printf() and linking with newlib libc.a then the jump table is added and used, however if I link the same application with newlib-nano libc_nano.a then the jump table is not included. What is triggering the inclusion of the jump table in some cases and not in others?
When building code with the zc* extensions enabled I notice that functions are always word aligned and padding bytes are added which makes the code size larger than expected. Is this a bug in the binutils part of the toolchain, or somewhere else? Is there a way I can force the compiler to accept half-word aligned functions? I am using the following march and mabi arguments:
-march=rv32ima_zca_zcb_zcmb_zcmp_zcmt -mabi=ilp32
Toolchain version:
corev-openhw-gcc-centos7-20230504
Problem Statement:
In the generated dump file.
PC instruction
1c02442a: 810707db cv.muls a5,a4,a6
as per CV manual below, the opcode of the instruction is 1011011, which matches with cv.insert instead of cv.muls.
10 | Luimm5[4:0] | Iuimm5[4:0] | src | 000 | dest | 101 1011 | cv.insert rD, rs1, Is3, Is2 |
---|
clipr/clipur instructions description have been updated in cv32e40p_v1.7.0 User Manual/tag.
rs2 MSB is now masked and is not used by HW.
Maybe a warning should be printed in case rs2 MSB is at 1 to signal that it will not be used.
https://github.com/openhwgroup/corev-binutils-gdb/blob/development/gas/testsuite/gas/riscv/cv-mem-lb.s
cv.lb t0, -2048(t2)
cv.lb t4, 15(t1)
cv.lb t3, 2047(t5)
these instructions should be updated to:
cv.lb t0, -2048(t2!)
cv.lb t4, 15(t1!)
cv.lb t3, 2047(t5!)
Raised from openhwgroup/corev-llvm-project#48 (comment).
This can be confirmed that in cv-simd-srl-sci-b-pass.s, tests assume negative shift amount, which should be unsigned:
The latest version makes some changes to the current work. See specification draft 1.0.0rv5.5.
Consider the following:
# Test if symbolic arguments to starti work.
#
# Macro to generate word length NOPS
#
.macro wnops count=1
nop
nop
.ifne \count
wnops "(\count-1)"
.endif
.endm
#
# Declare as a global function so it will link
#
.global main
.func main
main:
cv.setupi 0, 42, lp0
wnops 29
lp0:
cv.setupi 0, 561, lp1
wnops 30
lp1:
Compile and link
riscv32-corev-elf-gcc -march=rv32imac_xcorevhwlp1p0 /tmp/1.s -o /tmp/1.o
Note no errors, but objdump shows the second of these, the branch has overflowed:
$ riscv32-corev-elf-objdump -d /tmp/1.o
000101ee <lp0>:
101ee: 2310462b cv.setupi 0,561,101ee <lp0>
101f2: 0001 nop
101f4: 0001 nop
101f6: 0001 nop
...
Instructions like the MAC instructions and SIMD Shuffle and Pack instructions use mixed case e.g. cv.muluRN rD, rs1, rs2, Is3 or cv.shuffleI1.sci.b rD, rs1, Imm6.
The current implementation uses lowercase.
Although you can implement instructions as mixed case the disassembler will output the instructions in lowercase.
I am raising this as an issue so that we can discuss a way to use mixed case instructions in the assembler and disassembler.
For the compressed instructions we have the .option rvc
and .option norvc
assembler directives, however
with the introduction of Zc*, these are no longer usable and the current situation is as follows:
.option rvc
:
.option norvc
:
The behavior for these options with Zc should either be clearly defined, and apply to the previous C-instructions; or should have its own options defined.
Some possible solutions:
.option rvc/norvc
: Applies to all Zc* instructions.option rvc/norvc
: Applies to all Zc instructions (in effect, identical to previous C-behavior).option rvzc/norvzc
: Same as option 1, but renamed.option rvzc*/norvzc*
: Specific options for each sub-extension, would there actually be a need for this?.option rvzc/norvzc
+ option rvzc*/norvzc*
: Both "catch-all" option and specific sub-extension option(This bug was originally found by a downstream user of the zcmt changes, but has been replicated with the CORE-V tools)
Generation of the Zcmt table appears to be resulting in branches being incorrectly resolved (amongst other corruptions).
Using embench-1.0 and my CORE-V toolchain build using these tools, if I build embench with:
./build_all.py --clean --arch riscv32 --board ri5cyverilator --cc riscv32-corev-elf-gcc --chip generic --cflags '-save-temps -c -march=rv32im_zcmt -mabi=ilp32 -mcmodel=medany -static -O2' --ldflags '-march=rv32im_zcmt -mabi=ilp32 -mcmodel=medany -static -nostdlib -nostartfiles' --user-libs '-lm_nano -lc_nano -lgcc' --verbose
and disassemble nsichneu
, looking for the first use of cm.jt
, I find the following:
11b9e: 01cf0463 beq t5,t3,11ba6 <benchmark_body+0x1af0>
11ba2: a062 cm.jt 24
11ba4: 02872e03 lw t3,40(a4)
11ba8: 03472f03 lw t5,52(a4)
Noting the branch target of that first branch, 11ba6
is in the middle of the first lw
instruction quoted, so cannot be where we are expecting to branch to.
For cv.shuffle.sci.h Imm6[5:2] must be 0.
When it is not, this should generate an error.
[ ]+4:[ ]+5e6040ab[ ]+cv.starti[ ]+1,bd0 +<target+0xbd0>
the new spec: https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/instruction_set_extensions.rst
| 31 : 20 | 19 :15 | 14 : 12 | 11 :08 | 07 | 06 : 00 | |
| uimmL[11:0] | 00000 | 100 | 0000 | L | 010 1011 | cv.starti L, uimmL |
According to the new spec, the cv.starti 1,bd0 seems to be bd, 00, 40, ab, not 5e, 60, 40, ab?
Hi,
Like in RISC-V specification (JAL example) , all PULP instructions are described using following notation for immediate:
immx[0|x-1:1] means for a decimal value encoded on x bits, bit 0 comes first and then (x-1):1
For instance:
24 =0x18 => imm6[5:0] = 0b01_1000 so imm6[0|5:1] = 0b00_1100
Right now assembler is using imm6[5:0] rather than imm6[0|5:1] in binary encoding of PULP instructions.
Cheers,
Pascal.
Hi,
The Zc instruction set extension spec (Zc* v1.0) said that ZCMT jump table must be a minimum of 64-byte aligned, but in the branch development-eddf4096b97, the tablejump section was defined to be aligned on a 4-byte boundary. The detailed code is as follows (/bfd/elfnn-riscv.c bfd_elf_riscv_make_tablejump_section):
if (sec == NULL
|| !bfd_set_section_alignment (sec, bed->s->log_file_align)
|| !bfd_set_section_size (sec, 256 * RISCV_ELF_WORD_BYTES))
return false;
htab->table_jump_htab->tablejump_sec = sec;
htab->table_jump_htab->tablejump_sec_owner = abfd;
}
bfd_set_section_alignment (sec, bed->s->log_file_align)
In my test, bfd_set_section_alignment (sec, 6) can work normally, please help me see if this modification is appropriate. Thank you for your time.
There are cases where compilation of a single, bare-metal .S-file with the zcmt-flag march-flag enabled causes the linker to replace jumps inside the assembly with table jump instructions - this creates several issues and does not really make sense to me:
Technically, this can be avoided with -mno-relax
-flag to the linker, but I would not expect this to be necessary, as that also leads to an impact of potentially blocking other relaxations.
That leads me to the question of what kind of scenario with tablejump-relaxation of a manually crafted assembly file would actually be useful?
I do not currently have an example on hand to reproduce this, but I will try to add that here as soon as possible. Posting this now to raise awareness of this issue.
See openhwgroup/corev-llvm-project#26, which suggests this encoding may be wrong.
hi
https://github.com/openhwgroup/corev-binutils-gdb/blob/development/bfd/elfnn-riscv.c
In relax pass 0 and relax_trip 2 of _bfd_riscv_relax_section, if table jump can save size, and then we replace all targeted
instructions/instruction pairs(e.g. auipc+jalr or jal) to zcmt instructions by _bfd_riscv_table_jump_mark function.
But seems we try to call _bfd_riscv_table_jump_mark for all kinds of relocation types, which exposes a risk to replace an un-targeted instruction with a zcmt instruction.
So propose to tighten condition for calls of _bfd_riscv_table_jump_mark for R_RISCV_CALL/R_RISCV_CALL_PLT/R_RISCV_JAL only.
relax_func = NULL;
if (info->relax_pass == 0)
{
if (!riscv_use_table_jump (info))
return true;
if (info->relax_trip == 0)
{
if (type == R_RISCV_CALL
|| type == R_RISCV_CALL_PLT)
relax_func = _bfd_riscv_relax_call;
else if (type == R_RISCV_JAL)
relax_func = _bfd_riscv_record_jal;
else
continue;
*again = true;
}
else if (info->relax_trip == 2) // tighten condition for R_RISCV_CALL/R_RISCV_CALL_PLT/R_RISCV_JAL only
relax_func = _bfd_riscv_table_jump_mark;
}
The encoding is incorrect for all Bit Manipulation instructions. Is2 and Is3 are interchanged in final bit encoding.
Maybe because they are declared differently than other instructions : ... rD, rs1, Is3, Is2
This different instruction presentation is because this is easier to understand what is extracted:
Is3 is most significant bit and Is2 is least significant bit.
Update instruction names to match documentation.
Corresponding GCC issue: openhwgroup/corev-gcc#60
ARM-like
Pre-* cv.lw rd, (rs1, +/- imm/rs2)!
Post-* cv.lw rd, (rs1), +/-imm/rs2
The set of default CSRs used by GDB in the absence of an XML target description is not appropriate for CORE-V. It will cause the GDB server (e.g. OpenOCD) to time out.
A minimal set of mandatory CSRs is appropriate as the default in these circumstances.
Hi,
Using this test and 20231128 or 20231205 toolchain, the following error is produced:
corev_rand_pulp_hwloop_exception_1743992155.S:428:(.text+0x614): relocation truncated to fit: R_RISCV_CVPCREL_URS1 against `hwloop1_end_stream1_id0'
collect2: error: ld returned 1 exit status
Regards,
Pascal.
In openhwgroup/cv32e40p@f2a1997, a change of spec demands that the immediate argument of shift instructions no longer allow values greater than the number of bits in a register, while the testsuite still tests for values out of this range:
Similarly, openhwgroup/cv32e40p@cdee092 changes cv.avgu
to zero-extension(unsigned), while the testsuite still tests for negative values:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.