aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-07-06 10:26:46 +0000
committers-ol <s+removethis@s-ol.nu>2021-07-06 11:08:54 +0000
commit631f09462050c8173dacb22a83e6ef3dacc3c8a1 (patch)
tree4cbd147e158991e229ce1fc2001525078a020b83
parentgood helloworld example (diff)
downloadsubv-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.md158
-rw-r--r--README.rst142
-rw-r--r--ex.elfbin8228 -> 8224 bytes
-rw-r--r--ex.format13
-rw-r--r--ex.pack11
-rw-r--r--ex.subv11
-rw-r--r--ex.survey25
-rw-r--r--ex.valid16
-rw-r--r--hello_world.subv (renamed from test.subv)0
-rwxr-xr-xsubv.sh39
11 files changed, 214 insertions, 204 deletions
diff --git a/notes.md b/ISA_notes.md
index cc051da..8f56686 100644
--- a/notes.md
+++ b/ISA_notes.md
@@ -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
diff --git a/ex.elf b/ex.elf
index 66dfc13..a509aaf 100644
--- a/ex.elf
+++ b/ex.elf
Binary files differ
diff --git a/ex.format b/ex.format
index 5fb48d8..6727dd1 100644
--- a/ex.format
+++ b/ex.format
@@ -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
diff --git a/ex.pack b/ex.pack
index 5a6cdf4..e0cb8b9 100644
--- a/ex.pack
+++ b/ex.pack
@@ -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
diff --git a/ex.subv b/ex.subv
index 16e9baf..408dabb 100644
--- a/ex.subv
+++ b/ex.subv
@@ -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
diff --git a/ex.survey b/ex.survey
index 09e8475..e30860c 100644
--- a/ex.survey
+++ b/ex.survey
@@ -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
diff --git a/subv.sh b/subv.sh
new file mode 100755
index 0000000..feb7f6c
--- /dev/null
+++ b/subv.sh
@@ -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