diff options
| author | s-ol <s+removethis@s-ol.nu> | 2021-07-06 10:26:46 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2021-07-06 11:08:54 +0000 |
| commit | 631f09462050c8173dacb22a83e6ef3dacc3c8a1 (patch) | |
| tree | 4cbd147e158991e229ce1fc2001525078a020b83 | |
| parent | good helloworld example (diff) | |
| download | subv-631f09462050c8173dacb22a83e6ef3dacc3c8a1.tar.gz subv-631f09462050c8173dacb22a83e6ef3dacc3c8a1.zip | |
update README/ex example
| -rw-r--r-- | ISA_notes.md (renamed from notes.md) | 3 | ||||
| -rw-r--r-- | README.md | 158 | ||||
| -rw-r--r-- | README.rst | 142 | ||||
| -rw-r--r-- | ex.elf | bin | 8228 -> 8224 bytes | |||
| -rw-r--r-- | ex.format | 13 | ||||
| -rw-r--r-- | ex.pack | 11 | ||||
| -rw-r--r-- | ex.subv | 11 | ||||
| -rw-r--r-- | ex.survey | 25 | ||||
| -rw-r--r-- | ex.valid | 16 | ||||
| -rw-r--r-- | hello_world.subv (renamed from test.subv) | 0 | ||||
| -rwxr-xr-x | subv.sh | 39 |
11 files changed, 214 insertions, 204 deletions
@@ -1,4 +1,3 @@ - # RISC-V full size Instructions Formats (32bit): ## R-format: op(rs1, rs2) -> rd @@ -81,7 +80,7 @@ opcode: 0b0100011 / 0x23 | 0x1 | SH | i16, imm12 in half-words | | 0x2 | SW | i32, imm13 in words | -## SB-format: op(rs1, rs2, imm12/13) +## B-format: op(rs1, rs2, imm12/13) `opcode[7] imm11[1] imm4:1[4] funct3[3] rs1[5] rs2[5] imm10:5[6] imm12[1]` branch diff --git a/README.md b/README.md deleted file mode 100644 index cd47df9..0000000 --- a/README.md +++ /dev/null @@ -1,158 +0,0 @@ -# SubV - -This is a wip clone of [SubX][mu] for the RISC-V RV31I base ISA. - - $ <label_test.subv ./format.py | ./survey.py | ./pack.py | ./elf.py >out.elf - $ ./qemu.sh out.elf - -## Status - -Features: - -- ELF output: ✔️ -- Free arg order: ❌ -- SubX cross-asm: ❌ - -Instruction Groups: - -- OP-IMM: ✔️✔️ -- OP: ✔️❌ -- LUI: ✔️✔️ -- AIUPC: ✔️❌ -- JAL: ✔️✔️ -- JALR: ✔️❌ -- BRANCH: ❌❌ -- LOAD: ✔️❌ -- STORE: ✔️✔️ - -(✔️❌: implemented but untested) - -## Pipeline - -back to front: - -- `elf.py`: takes hex bytes and segment headers, outputs an ELF file -- `pack.py`: packs bitfields (`3/3 1/1 f/4`) into hex bytes (`fb`) -- `format.py`: bit-packs ops into ISA format -- `survey.py`: replaces label references by their addresses -- `validate.py`: checks op-arguments and puts them into canonical order - -and now front to back with a little example: - - $ ./validate.py <ex.subv >ex.valid - $ ./survey.py <ex.valid >ex.survey - $ ./format.py <ex.survey >ex.format - $ ./pack.py <ex.format >ex.pack - $ ./elf.py <ex.pack >ex.elf - $ ./qemu.sh ex.elf - -`ex.subv`: hand-writable. - - == code 0x80000000 - # repeatedly print "Hi\\n" - main: - # load 0x10010000 (UART0) into t0 - 37/lui 5/rd/t0 0x10010/imm20 - # store 0x48 (H) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 - # store 0x69 (i) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 69/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 - # store 0x0a (\n) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 - # jump back up to the top - 6f/jal 0/rd/x0 main/off21 - -`ex.format`: mnemonics validated and discarded - - == code 0x80000000 - # repeatedly print "Hi\n" - main: - # load 0x10010000 (UART0) into t0 - 37/u 05/rd 10010/imm20 - # store 0x48 (H) in UART0+0 - 13/i 0/subop 6/rd 0/rs 48/imm12 - 23/s 2/subop 5/rs2 6/rs1 0/off12 - # store 0x69 (i) in UART0+0 - 13/i 0/subop 6/rd 0/rs 69/imm12 - 23/s 2/subop 5/rs2 6/rs1 0/off12 - # store 0x0a (\n) in UART0+0 - 13/i 0/subop 6/rd 0/rs 0a/imm12 - 23/s 2/subop 5/rs2 6/rs1 0/off12 - # jump back up to the top - 6f/j 0/4d main/off21 - -`ex.survey`: references resolved and labels removed - - == code 0x80000000 - # repeatedly print "Hi\n" - # main: - # load 0x10010000 (UART0) into t0 - 37/u 05/rd 10010/imm20 - # store 0x48 (H) in UART0+0 - 13/i 0/subop 6/rd 0/rs 48/imm12 - 23/s 2/subop 5/rs2 6/rs1 0/off12 - # store 0x69 (i) in UART0+0 - 13/i 0/subop 6/rd 0/rs 69/imm12 - 23/s 2/subop 5/rs2 6/rs1 0/off12 - # store 0x0a (\n) in UART0+0 - 13/i 0/subop 6/rd 0/rs 0a/imm12 - 23/s 2/subop 5/rs2 6/rs1 0/off12 - # jump back up to the top - 6f/j 0/4d fffe4/off21 - -`ex.format`: arguments sliced and diced and put into the ISA order. - - == code 0x80000000 - # repeatedly print "Hi\n" - # main: - # load 0x10010000 (UART0) into t0 - 37/7 05/5 10010/20 - # store 0x48 (H) in UART0+0 - 13/7 06/5 00/3 00/5 48/12 - 23/7 00/5 02/3 05/5 06/5 00/7 - # store 0x69 (i) in UART0+0 - 13/7 06/5 00/3 00/5 69/12 - 23/7 00/5 02/3 05/5 06/5 00/7 - # store 0x0a (\n) in UART0+0 - 13/7 06/5 00/3 00/5 0a/12 - 23/7 00/5 02/3 05/5 06/5 00/7 - # jump back up to the top - 6f/7 00/5 ff/8 01/1 3f2/10 01/1 - -`ex.pack`: fully packed, ready to run bare-metal - - == code 0x80000000 - # repeatedly print "Hi\n" - # main: - # load 0x10010000 (UART0) into t0 - b7 02 01 10 - # store 0x48 (H) in UART0+0 - 13 03 80 04 - 23 a0 62 00 - # store 0x69 (i) in UART0+0 - 13 03 90 06 - 23 a0 62 00 - # store 0x0a (\n) in UART0+0 - 13 03 a0 00 - 23 a0 62 00 - # jump back up to the top - 6f f0 5f fe - -`ex.elf`: binary file for use with `qemu` (see next section). - -## Debugging - -You can hook gdb into `qemu` using the `-s` flag, and make it halt on start -using the `-S` flag. `gdb` can be attached using `target remote localhost:1234`: - - $ ./qemu.sh out.elf -S -s - # in another terminal - $ riscv32-elf-gdb -iex "target remote localhost:1234" - layout asm # show assembly trace - nexti # step forward one instruction - c # free-run forward - -[mu]: https://github.com/akkartik/mu diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..ed8ddd2 --- /dev/null +++ b/README.rst @@ -0,0 +1,142 @@ +SubV +==== + +This is a wip clone of SubX_ for the RISC-V RV32I base ISA. + +:: + + $ <hello_world.subv ./validate.py | ./survey.py | ./format.py | ./pack.py | ./elf.py >hello_world.elf + $ ./qemu.sh hello_world.elf + +Pipeline +-------- + +back to front: + +- ``elf.py``: takes hex bytes and segment headers, outputs an ELF file +- ``pack.py``: packs bitfields (``3/3 1/1 f/4``) into hex bytes (``fb``) +- ``format.py``: bit-packs ops into ISA format +- ``survey.py``: replaces label references by their addresses +- ``validate.py``: checks op-arguments and puts them into canonical order + +and now front to back with a little example:: + + $ ./validate.py <ex.subv >ex.valid + $ ./survey.py <ex.valid >ex.survey + $ ./format.py <ex.survey >ex.format + $ ./pack.py <ex.format >ex.pack + $ ./elf.py <ex.pack >ex.elf + $ ./qemu.sh ex.elf + +``ex.subv``: hand-writable:: + + == code 0x80000000 + # repeatedly print "Hi\n" + main: + # load 0x10010000 (UART0) into t0 + 37/lui 5/rd/t0 0x10010/imm20 + # store 0x48 (H) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12 + 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x69 (i) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 69/imm12 + 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x0a (\n) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 + 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12 + # jump back up to the top + 6f/jal 0/rd/x0 main/off21 + +``ex.valid``: mnemonics validated and discarded:: + + == code 0x80000000 + # repeatedly print "Hi\n" + main: + # load 0x10010000 (UART0) into t0 + 37/u 5/rd 10010/imm20 + # store 0x48 (H) in UART0+0 + 13/i 6/rd 0/funct3 0/rs 48/imm12 + 23/s 5/rs1 0/imm12 2/funct3 6/rs2 + # store 0x69 (i) in UART0+0 + 13/i 6/rd 0/funct3 0/rs 69/imm12 + 23/s 5/rs1 0/imm12 2/funct3 6/rs2 + # store 0x0a (\n) in UART0+0 + 13/i 6/rd 0/funct3 0/rs a/imm12 + 23/s 5/rs1 0/imm12 2/funct3 6/rs2 + # jump back up to the top + 6f/j 0/rd main/off21 + +``ex.survey``: references resolved and labels removed:: + + == code 0x80000000 + # repeatedly print "Hi\n" + # main: + # load 0x10010000 (UART0) into t0 + 37/u 5/rd 10010/imm20 + # store 0x48 (H) in UART0+0 + 13/i 6/rd 0/funct3 0/rs 48/imm12 + 23/s 5/rs1 0/imm12 2/funct3 6/rs2 + # store 0x69 (i) in UART0+0 + 13/i 6/rd 0/funct3 0/rs 69/imm12 + 23/s 5/rs1 0/imm12 2/funct3 6/rs2 + # store 0x0a (\n) in UART0+0 + 13/i 6/rd 0/funct3 0/rs a/imm12 + 23/s 5/rs1 0/imm12 2/funct3 6/rs2 + # jump back up to the top + 6f/j 0/rd -1c/imm21 + +``ex.format``: arguments sliced and diced and put into the ISA order:: + + == code 0x80000000 + # repeatedly print "Hi\n" + # main: + # load 0x10010000 (UART0) into t0 + 37/7 05/5 10010/20 + # store 0x48 (H) in UART0+0 + 13/7 06/5 0/3 00/5 048/12 + 23/7 00/5 2/3 05/5 06/5 00/7 + # store 0x69 (i) in UART0+0 + 13/7 06/5 0/3 00/5 069/12 + 23/7 00/5 2/3 05/5 06/5 00/7 + # store 0x0a (\n) in UART0+0 + 13/7 06/5 0/3 00/5 00a/12 + 23/7 00/5 2/3 05/5 06/5 00/7 + # jump back up to the top + 6f/7 00/5 ff/8 1/1 3f2/10 1/1 + +``ex.elf``: ELF binary for loading in qemu:: + + $ riscv32-elf-readelf -l ex.elf + + Elf file type is EXEC (Executable file) + Entry point 0x80000000 + There is 1 program header, starting at offset 52 + + Program Headers: + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + LOAD 0x002000 0x80000000 0x80000000 0x00020 0x00020 R E 0x1000 + +Repo Contents +------------- + +- ``{validate,survey,format,pack,elf}.py``: pipeline stages +- ``{subv,bits}.py``: helpers for pipeline stages +- ``subv.sh``: Helper for running SubV code through all pipeline stages. + It will keep intermediate results in a temporary directory if errors occur, + and can be made to keep these results next to the input file with `--keep`. + + +Debugging +--------- + +You can hook `gdb` into `qemu` using the `-s` flag, and make it halt on start +using the `-S` flag. `gdb` can be attached using `target remote localhost:1234`: + + $ ./qemu.sh hello_world.elf -S -s + # in another terminal + $ riscv32-elf-gdb -iex "target remote localhost:1234" + layout asm # show assembly trace + nexti # step forward one instruction + c # free-run forward + +.. _SubX: https://github.com/akkartik/mu/blob/main/subx.md Binary files differ@@ -1,6 +1,6 @@ == code 0x80000000 # repeatedly print "Hi\n" -main: +# main: # load 0x10010000 (UART0) into t0 37/7 05/5 10010/20 # store 0x48 (H) in UART0+0 @@ -12,12 +12,5 @@ main: # store 0x0a (\n) in UART0+0 13/7 06/5 0/3 00/5 00a/12 23/7 00/5 2/3 05/5 06/5 00/7 -# jump back up to the top (three versions): -# a) jal 21bit relative (with 0th bit forced to 0) -# 6f/jal 0/rd/x0 main/off21 -# b) auipc+jalr 32bit relative (note label offset) -17/7 07/5 main/off32/[31:12] -67/7 00/5 0/3 07/5 main+4/off32/[11:0] -# c) lui+jalr 32bit absolute -# 37/lui 7/rd/t2 main/imm32 -# 67/jalr 0/subop 0/rd/x0 7/rs/t2 main/imm32 +# jump back up to the top +6f/7 00/5 ff/8 1/1 3f2/10 1/1 @@ -12,12 +12,5 @@ b7 02 01 10 # store 0x0a (\n) in UART0+0 13 03 a0 00 23 a0 62 00 -# jump back up to the top (three versions): -# a) jal 21bit relative (with 0th bit forced to 0) -# 6f/jal 0/rd/x0 main/off21 -# b) auipc+jalr 32bit relative (note label offset) -97 f3 ff ff -67 80 43 fe -# c) lui+jalr 32bit absolute -# 37/lui 7/rd/t2 main/imm32 -# 67/jalr 0/subop 0/rd/x0 7/rs/t2 main/imm32 +# jump back up to the top +6f f0 5f fe @@ -12,12 +12,5 @@ main: # store 0x0a (\n) in UART0+0 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12 - # jump back up to the top (three versions): - # a) jal 21bit relative (with 0th bit forced to 0) - # 6f/jal 0/rd/x0 main/off21 - # b) auipc+jalr 32bit relative (note label offset) - 17/auipc 7/rd/t2 main/off20hi - 67/jalr 0/subop 0/rd/x0 7/rs/t2 main+4/off12lo - # c) lui+jalr 32bit absolute - # 37/lui 7/rd/t2 main/imm32 - # 67/jalr 0/subop 0/rd/x0 7/rs/t2 main/imm32 + # jump back up to the top + 6f/jal 0/rd/x0 main/off21 @@ -2,22 +2,15 @@ # repeatedly print "Hi\n" # main: # load 0x10010000 (UART0) into t0 -37/7 05/5 10010/20 +37/u 5/rd 10010/imm20 # store 0x48 (H) in UART0+0 -13/7 06/5 00/3 00/5 48/12 -23/7 00/5 02/3 05/5 06/5 00/7 +13/i 6/rd 0/funct3 0/rs 48/imm12 +23/s 5/rs1 0/imm12 2/funct3 6/rs2 # store 0x69 (i) in UART0+0 -13/7 06/5 00/3 00/5 69/12 -23/7 00/5 02/3 05/5 06/5 00/7 +13/i 6/rd 0/funct3 0/rs 69/imm12 +23/s 5/rs1 0/imm12 2/funct3 6/rs2 # store 0x0a (\n) in UART0+0 -13/7 06/5 00/3 00/5 0a/12 -23/7 00/5 02/3 05/5 06/5 00/7 -# jump back up to the top (three versions): -# a) jal 21bit relative (with 0th bit forced to 0) -# 6f/jal 0/rd/x0 main/off21 -# b) auipc+jalr 32bit relative (note label offset) -17/7 07/5 fffff/20 -67/7 00/5 00/3 07/5 fe4/12 -# c) lui+jalr 32bit absolute -# 37/lui 7/rd/t2 main/imm32 -# 67/jalr 0/subop 0/rd/x0 7/rs/t2 main/imm32 +13/i 6/rd 0/funct3 0/rs a/imm12 +23/s 5/rs1 0/imm12 2/funct3 6/rs2 +# jump back up to the top +6f/j 0/rd -1c/imm21 diff --git a/ex.valid b/ex.valid new file mode 100644 index 0000000..1652954 --- /dev/null +++ b/ex.valid @@ -0,0 +1,16 @@ +== code 0x80000000 +# repeatedly print "Hi\n" +main: +# load 0x10010000 (UART0) into t0 +37/u 5/rd 10010/imm20 +# store 0x48 (H) in UART0+0 +13/i 6/rd 0/funct3 0/rs 48/imm12 +23/s 5/rs1 0/imm12 2/funct3 6/rs2 +# store 0x69 (i) in UART0+0 +13/i 6/rd 0/funct3 0/rs 69/imm12 +23/s 5/rs1 0/imm12 2/funct3 6/rs2 +# store 0x0a (\n) in UART0+0 +13/i 6/rd 0/funct3 0/rs a/imm12 +23/s 5/rs1 0/imm12 2/funct3 6/rs2 +# jump back up to the top +6f/j 0/rd main/off21 diff --git a/test.subv b/hello_world.subv index 60d9065..60d9065 100644 --- a/test.subv +++ b/hello_world.subv @@ -0,0 +1,39 @@ +#!/bin/sh +set -e + +if [ "$#" -eq 2 -a \( \( "$1" = "--keep" \) -o \( "$1" = "-k" \) \) ]; then + INPUT="$2" + BASE=$(dirname "$INPUT")/$(basename "$INPUT" .subv) +elif [ "$#" -eq 1 ]; then + INPUT="$1" + DIR=$(mktemp -dt subv.XXXXXX) + BASE="$DIR"/$(basename "$INPUT" .subv) +else + echo "Error: invalid arguments" 1>&2 + echo "Usage: $0 [-k|--keep] input.subv" 1>&2 + exit 1 +fi + +msg() { + echo -e "\e[1;32m$1\e[00m" 1>&2 +} + +msg "OUTPUTTING TO $BASE.*" + +msg VALIDATING... +./validate.py <"$INPUT" >"$BASE.valid" +msg SURVEYING... +./survey.py <"$BASE.valid" >"$BASE.survey" +msg FORMATTING... +./format.py <"$BASE.survey" >"$BASE.format" +msg PACKING... +./pack.py <"$BASE.format" >"$BASE.pack" +msg ELFING... +./elf.py <"$BASE.pack" >"$BASE.elf" +msg DONE! + +if [ -n "$DIR" ]; then + cat "$BASE.elf" + rm "$BASE".* + rmdir "$DIR" +fi |
