aboutsummaryrefslogtreecommitdiff
path: root/triscv/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'triscv/README.md')
-rw-r--r--triscv/README.md272
1 files changed, 272 insertions, 0 deletions
diff --git a/triscv/README.md b/triscv/README.md
new file mode 100644
index 0000000..3b8beeb
--- /dev/null
+++ b/triscv/README.md
@@ -0,0 +1,272 @@
+# `triscv`, a trinary riscv-like ISA simulator
+
+An attempt at creating a trinary computer simulator capable of running simple
+operating systems, with virtual memory and user/system separation.
+
+Natural bases of three used as trit groupings, i.e.
+3^0 = trit
+3^1 = nit (likely not actually used?)
+3^2 = tryte (base size of characters etc, similar to byte)
+3^3 = tri (base word size)
+
+Ideally I would like to extend support up to 3^4 (tril?) that would be
+equivalent to 64 bit groupings on conventional hardware, but the my trinary
+arithmetic library underlying the simulator doesn't support 81 trits due to
+efficiency/portability concerns. 128 bit integers could be usable on at least
+x86, but not really portable. Something like `gmp` could also be used, but would
+be very slow. Alternatively, consider 45 trit as an equivalence to 64 bit
+computers, as they are approximately the same in value and divisible by three.
+
+Heavy inspiration taken from riscv.
+
+M-mode/S-mode/U-mode fits pretty nicely into trinary, heh.
+
+# Operation set
+
+27 trit ops, registers 3^4?
+
+ 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+|-----------------------------------------------------|
+| fn5 | rs2 | rs1 | fn0 | rd | opcode | R-type
+|-----------------------------------------------------|
+| imm9 | rs1 | fn0 | rd | opcode | I-type
+|-----------------------------------------------------|
+| imm5 | rs2 | rs1 | fn0 | imm4 | opcode | S-type
+|-----------------------------------------------------|
+| imm18 | rd | opcode | U-type
+|-----------------------------------------------------|
+| imm5 | rs2 | rs1 | immd | rd | opcode | D-type
+|-----------------------------------------------------|
+(D is a variant of R, where immd is actually fn0, but used as an immediate)
+
+Compressed instructions probably possible to implement in future but left alone
+for now.
+
+Exact instructions still TBD, but R type probably reserves one fn trit value for
+diops. It's unclear to me how readily diops can be implemented in hardware, so
+consider this more exploratory than anythin else.
+
+Similarly, I-type reserved on fn trit value to unops.
+
+Turns out it's literally just a mapping, i.e. unops use a three-way mux with
+the input value as the selection trit and the three control bits inputs to the
+mux. Similarly, diops are just a nine-way mux.
+
+# Registers
+
+81, of which x0 is constant 0. ABI TBD but probably similar to riscv.
+
+# Virtual memory
+
+Physical memory consists of PPN[2], PPN[1], PPN[0] and page offset. 27 trits is enough
+for about 7 teratrytes of memory, which probably doesn't need range extensions
+like 32bit computers tend to use.
+
+Page table entries:
+
+ 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+|-----------------------------------------------------|
+| PPN[2] | PPN[1] | PPN[0] |RSW|G|U|X|A|R|V|
+|------------------------------------------------D-W--|
+| TAG |
+|-----------------------------------------------------|
+| Reserved |
+|-----------------------------------------------------|
+
+TAG is a tag that allows us to separate one address space into multiple regions,
+similar to CODOMS system but scaled down a lot. If left 0, code executing in the
+region is allowed to access other regions but outside regions are not allowed to
+access the zero region, except executing a migration jump.
+
+The reserved region might come
+in handy for 'extensions' in the future, but can probably be set to zero for
+now.
+
+R/W and A/D work by the following table:
+
+N => both (R and W, A and D)
+O => none
+P => top (R, A)
+
+RSW is reserved for S-mode usage.
+
+The idea here is a page marked write must also be marked read, and a dirty page
+must also have been accessed. Whether an interrupt is raised when A/D is updated
+is set by a status CSR, to be determined later. Three-level page tables.
+
+Each base page is 3^8 = 6561, and since each PTE
+takes up 9 trytes, each base page can fit 3^6 PTEs. Therefore, to cover the full
+27 bit address space, we need three `satp` CSRs, `satpn`, `satpo`, `satpp`,
+corresponding to the first trit in the address. This can give reasonably
+efficient separation of user/kernelspace, for example -1 for kernel and 1 for
+user. Still about 2.5 tera per space.
+
+This can be extended to 81 bits, although with no nice whole number that maps to
+81. Not a huge deal, by any means, although kind of annoying that the number of
+elements per PTE shrinks to 243. Maybe not a huge issue, but might limit
+useability somewhat as the number of page levels has to be increased much more
+rapidly to get larger virtual address spaces.
+
+Requiring physical addresses to be the same width as virtual addresses
+simplifies hypervisor stuff somewhat, could be useful? Not that allocating some
+pages in series is too big of an issue, but still feels like an unnecessary
+complication in the RISC-V specs. Apparently the explanation given is that is
+can be useful to emulate larger physical address spaces than virtual spaces,
+though I'd like to see some examples. I guess easier masking of some addresses?
+Dunno.
+
+I might want to add in a bus error to separate it from pmp errors, there's been
+some discussion about it in riscv mailing lists.
+
+# CSRs
+
+TDB
+
+# Extensions
+
+## I
+
+addi, slti
+|-----------------------------------------------------|
+| imm0 | rs1 | fn0 | rd | OP-IMM | I-type
+|-----------------------------------------------------|
+
+unop (some macro instructions might be available in assembler)
+|-----------------------------------------------------|
+| 0 |N|O|P| rs1 | fn0 | rd | OP-IMM | I-type
+|-----------------------------------------------------|
+
+slli, srli (shifts work differently in balanced forms, have to be careful)
+ (shmt is 'unsigned', i.e. the actual shift amount is shmt + 13)
+|-----------------------------------------------------|
+| imm0 |shmt | rs1 | fn0 | rd | OP-IMM | I-type
+|-----------------------------------------------------|
+
+lui
+|-----------------------------------------------------|
+| imm9 | rd | LUI | U-type
+|-----------------------------------------------------|
+
+auipc
+|-----------------------------------------------------|
+| imm9 | rd | AUIPC | U-type
+|-----------------------------------------------------|
+
+add, slt, sge, seq, sne, sll, srl, sub
+|-----------------------------------------------------|
+| 0 | rs2 | rs1 | fn0 | rd | OP | R-type
+|-----------------------------------------------------|
+
+diop
+|-----------------------------------------------------|
+|N|O|P|N|O| rs2 | rs1 |P|N|O|P|0| rd | DIOP | D-type
+|-----------------------------------------------------|
+
+nop
+|-----------------------------------------------------|
+| 0 | x0 | 0 | x0 | OP-IMM | I-type
+|-----------------------------------------------------|
+
+jal
+|-----------------------------------------------------|
+| imm9 | rd | JAL | U-type
+|-----------------------------------------------------|
+
+jalr
+|-----------------------------------------------------|
+| imm0 | rs1 | 0 | rd | JALR | I-type
+|-----------------------------------------------------|
+
+beq, bne, blt, bge
+|-----------------------------------------------------|
+| imm0 | rs2 | rs1 | fn0 | imm4 | BRANCH | S-type
+|-----------------------------------------------------|
+
+load (w = width, i = 1 tryte, 0 = 3 trytes, 1 = 9 trytes)
+|-----------------------------------------------------|
+| imm0 | rs1 |w| 0 | rd | LOAD | I-type
+|-----------------------------------------------------|
+
+store
+|-----------------------------------------------------|
+| imm5 | rs2 | rs1 |w| 0 | imm4 | STORE | S-type
+|-----------------------------------------------------|
+
+fence (todo)
+|-----------------------------------------------------|
+| imm0 | rs1 | fn0 | rd | MEM | I-type
+|-----------------------------------------------------|
+
+ecall, ebreak, pcall
+|-----------------------------------------------------|
+| imm0 | x0 | fn0 | x0 | SYSTEM | I-type
+|-----------------------------------------------------|
+
+hints, any OP-IMM or OP with rd = x0. Additionally,
+a number of maybe-instructions in SYSTEM for future use, if unimplemented
+just write 0 to rd.
+
+## M
+
+mul
+|-----------------------------------------------------|
+| fn5 | rs2 | rs1 | fn0 | rd | OP | R-type
+|-----------------------------------------------------|
+
+div
+|-----------------------------------------------------|
+| fn5 | rs2 | rs1 | fn0 | rd | OP | R-type
+|-----------------------------------------------------|
+
+rem
+|-----------------------------------------------------|
+| fn5 | rs2 | rs1 | fn0 | rd | OP | R-type
+|-----------------------------------------------------|
+
+## A
+
+stt (start transaction)
+cst (checked store)
+ent (end transaction)
+cat (cancel transaction)
+
+Each system has a buffer with at least three slots for checked transactions.
+Each checked transaction is written to the buffer when an stc is encountered.
+stc clears out this buffer and ent checks if all stores are valid and flushes
+the buffer to real memory, or cache or wherever. A system is allowed to give
+each core a buffer or use a global buffer, but the size should be given in a CSR
+somewhere. Platforms may require at least n slots. Maybe? Reads inside
+transaction read from memory. Slow commits, at least somewhat, but probably
+somewhat simpler. Spinlock (and by extension, mutex) would then be
+
+spinlock:
+ // spin until a zero appears
+ lw x1, (x2)
+ bnez x1, spinlock
+
+ // start transaction, try to write 1
+ stt
+ li x1, 1
+ stc x1, (x2)
+ ent x1
+ // someone else tried at the same time, wait for next zero
+ // preferably also do a spin for a random but increasing time to try to
+ // avoid livelock, or rely on whatever system we're dealing with to
+ // provide it for us
+ beqz x1, spinlock
+
+could probably also provide simple atomics, like add or something, but eh
+
+## Zicsr
+
+csrrw, csrrs, csrrc
+|-----------------------------------------------------|
+| imm0 | rs | fn0 | rd | SYSTEM | I-type
+|-----------------------------------------------------|
+
+The CSR numbers are specified in the future.
+
+Also, possibly floating point stuff in the future, though I haven't chosen a
+floating point format yet.