git.s-ol.nu subv / master README.rst
master

Tree @master (Download .tar.gz)

README.rst @masterview rendered · raw · history · blame

SubV
====

This is a wip clone of SubX_ for the RISC-V RV32I base ISA.

::

   $ <examples/hello_world.subv ./validate.py | ./survey.py | ./format.py | ./pack.py | ./elf.py >examples/hello_world.elf
   $ ./qemu.sh examples/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 <examples/ex.subv   >examples/ex.valid
   $ ./survey.py   <examples/ex.valid  >examples/ex.survey
   $ ./format.py   <examples/ex.survey >examples/ex.format
   $ ./pack.py     <examples/ex.format >examples/ex.pack
   $ ./elf.py      <examples/ex.pack   >examples/ex.elf
   $ ./qemu.sh ex.elf

``ex.subv``: hand-writable::

   == code 0x80400000
   # repeatedly print "Hi\n"
   main:
     # load 0x10000000 (UART0) into t0
     37/lui 5/rd/t0 10000/imm20
     # store 0x48 (H) in UART0+0
     13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12
     23/store 0/width/byte 5/rs/t0 0/off12 6/rs/t1
     # store 0x69 (i) in UART0+0
     13/opi 0/subop/add 6/rd/t1 0/rs/x0 69/imm12
     23/store 0/width/byte 5/rs/t0 0/off12 6/rs/t1
     # store 0x0a (\n) in UART0+0
     13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12
     23/store 0/width/byte 5/rs/t0 0/off12 6/rs/t1
     # jump back up to the top
     6f/jal 0/rd/x0 main/off21

``ex.valid``: mnemonics validated and discarded::

   == code 0x80400000
   # repeatedly print "Hi\n"
   main:
   # load 0x10000000 (UART0) into t0
   37/u 5/rd 10000/imm20
   # store 0x48 (H) in UART0+0
   13/i 6/rd 0/funct3 0/rs 48/imm12
   23/s 0/funct3 5/rs1 0/imm12 6/rs2
   # store 0x69 (i) in UART0+0
   13/i 6/rd 0/funct3 0/rs 69/imm12
   23/s 0/funct3 5/rs1 0/imm12 6/rs2
   # store 0x0a (\n) in UART0+0
   13/i 6/rd 0/funct3 0/rs a/imm12
   23/s 0/funct3 5/rs1 0/imm12 6/rs2
   # jump back up to the top
   6f/j 0/rd main/off21

``ex.survey``: references resolved and labels removed::

   == code 0x80400000
   # repeatedly print "Hi\n"
   # main:
   # load 0x10000000 (UART0) into t0
   37/u 5/rd 10000/imm20
   # store 0x48 (H) in UART0+0
   13/i 6/rd 0/funct3 0/rs 48/imm12
   23/s 0/funct3 5/rs1 0/imm12 6/rs2
   # store 0x69 (i) in UART0+0
   13/i 6/rd 0/funct3 0/rs 69/imm12
   23/s 0/funct3 5/rs1 0/imm12 6/rs2
   # store 0x0a (\n) in UART0+0
   13/i 6/rd 0/funct3 0/rs a/imm12
   23/s 0/funct3 5/rs1 0/imm12 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