GTKWave(https://github.com/gtkwave/gtkwave) Alias Files and External Disassemblers for RISCV.
scripts/generate_csrs.py- Generate CSR Alias Filessrc/decode_addr.cpp- Convert elf file to alias files. (Generate GTKWave Translate File)src/decode_addr.cpp- Decode elf file to variable names. (GTKWave Filter process)src/decode_inst.cpp- Decode opcodes to instructions. (GTKWave Filter process)
src/decode_elf_addr.hpp- Decode elf files.src/gtkwave_loop.hpp- Core loop for GTKWave filter process
csr_data/- Alias Files for CSRs<csr>.gtkw- Decode fields for a given CSR
Assumes gtkwave is in the path.
-
example/Makefile- Generates symbol files and runs gtkwave. -
example/vcd-trace.gtkw- Example GTKWave save file. -
example/main.elf- Example firmware image. -
example/vcd-trace.vcd- Trace ofmain.elfrunning. -
example/vcd-trace.fst- Trace ofmain.elfrunning. -
example/symbols_data.gtkw- Symbols from example firmware image. -
example/symbols_func.gtkw- Functions from example firmware image.
Convert files and run GTKWave.
> make run
> make
> make install PREFIX_DIR=~/.local/
DECODE_ELF=<elf file> ./decode_addr
Filter process for example/main.elf
e.g.
$ cd src/
$ DECODE_ELF=../example/main.elf ./decode_addr
0
-
0000
-
0000000020010000
_enter
0000000080000008
mti_count
decode_addr <elf file> <output prefix>
<elf file>: RISC-V elf binary<output prefix>: Prefix for output files.
e.g.
./decode_addr build_tidy/main.elf main
Creates:
main_data.gtkwmain_func.gtkw
Example Function File:
0000000020010000 _enter
...
00000000200100fe _enter
0000000020010100 main
...
0000000020010afc memset
0000000020010afe .text.end
Example Data File:
0000000080000000 ecall_count
0000000080000004 ecall_count+4
0000000080000008 timestamp
000000008000000c timestamp+4
0000000080000010 .stack.start
...
0000000080000f08 .stack.start+3832
0000000080000f0c .stack.start+3836
0000000080000f10 .heap.start
0000000080000f14 .heap.start+4
0000000080000f18 .heap.start+8
...
000000008000170c .heap.start+2044
0000000080001710 .heap.end
The decode_inst takes hex decimal opcodes as stdin and writes the decoded assembly on stdout.
e.g.
Hex opcode data from objdump.
$ tail main.disasm
20010ae2: 00000297 auipc t0,0x0
20010ae6: 9696 add a3,a3,t0
20010ae8: 8286 mv t0,ra
20010aea: fa8680e7 jalr -88(a3)
20010aee: 8096 mv ra,t0
20010af0: 17c1 addi a5,a5,-16
20010af2: 8f1d sub a4,a4,a5
20010af4: 963e add a2,a2,a5
20010af6: f8c374e3 bgeu t1,a2,20010a7e <memset+0x2a>
20010afa: b7a5 j 20010a62 <memset+0xe>
Piped into decode_inst.
$ cat main.disasm | cut -f2 -d: | cut -c -10 | ./decode_inst | tail
auipc t0, 0x0
c.add a3, t0
c.mv t0, ra
jalr ra, a3, -88
c.mv ra, t0
c.addi a5, -16
c.sub a4, a5
c.add a2, a5
bgeu t1, a2, pc - 120
c.j pc - 152
