aboutsummaryrefslogtreecommitdiffstats
path: root/README.rst
blob: 23da8ecc531f974fc25e269acd958d0e487e2ba9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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