-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTODO
More file actions
89 lines (84 loc) · 8.13 KB
/
TODO
File metadata and controls
89 lines (84 loc) · 8.13 KB
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
- replace customasm
- for all its flaws, i have to say hats off to the folks behind customasm; it's gotten us this far
and replacing it feels surprisingly insurmountable rn :P but,,, eventually i really ought to
write a toolchain of my own, right? said toolchain would obviously have to essentially match
what we're getting with customasm currently, along with improvements and feature additions.
or, at least an assembler that matches and surpasses customasm.
but eventually it would be pretty cool to build a more complete toolchain, including a linker
and a compiler for a higher-level language (c but a bit better.)
- allow reading MARₗₒ and MARₕᵢ onto the data bus? would shave a cycle or two off of stpc.
or better yet, replace stpc with something a little less silly? maybe something like jal on RISC-V?
of course we can't do that until we have more 16-bit registers.. so. ugh.
- more registers! maybe eight 8-bit GPRs? or at least 4. and like, prolly .. uh.. 4(?) 16-bit registers?
- rather than driving the lhs and rhs inputs to the ALU directly, treat lhs and rhs as busses that
may be driven by any of the GPRs. and like idk, select em' with a mux or sumthin.
- create a 16-bit "transfer bus" that connects to all 16-bit GPRs and the PC(?) ... maybe?
- of course we'll also still want to be able to read/write the low and high bytes of the 16-bit
registers to/from the data bus. though, maybe all of this would have a bit of redundancy and we
could be a bit smarter about it without losing much, but i digress.
- use up/down counters for 16-bit registers
- this gives us a hardware stack pointer as well as, for example, "source" and "destination" registers
- probably also assists the microcode for some instructions that have to read 16-bit values, etc.
- hardware support for more complex addressing modes
- at a minimum we can assist with indirect memory accesses by adding more 16-bit registers; currently,
i don't think there'a any way to do something like `lda [ptr]`, because like, we'd load ptr into MAR,
but then we need to load the 16-bit value MAR is pointing to into a 16-bit register which we then load
the actual value from [into A] -- but to do that we'd need another 16-bit register; can't use MAR or PC :P
- it'd be nice to also support things like, idk, `lda ptr,x` and `lda [ptr],x` where x is either a constant
or a register. well, we can already do `lda ptr,#x` since ptr and x are both known by the assembler, so it's
just a regular load from some immediate address. but for the other cases... ... i guess like, we want to have
the ability to add some number (probably a full 16-bit number?)
- would also be handy if we could not just add some offset to some base address (which could be indirect),
but also scale it. say, scale by 1, 2, 4, or 8? or 16? that sort of thing.
this'd be great for, among many other things, SP-relative addressing. at the beginning of a function we'd like
to be able to just subtract n from SP to allocate space for the functions locals and then do things like
`lda [sp],#x` or w/e the shit. currently there's a fair bit of overhead involved in doing this kind of thing.
- PC-relative addressing would be nice to have as well, to save memory in branching instructions.
- consider whether we want to keep using variable-width instructions or if it'd make sense / be worthwhile to
switch to fixed-width instructions. i did it the way it is now because it was the quick and easy thing, but
there are definitely benefits to fixed-with instructions. haven't really thought through that dichotomy lately,
but i should at some point.
- better (_smarter_) control logic. currently we have a metric fuckton of control lines (lowkey not enough.)
and simultaneously we're essentially not using the opcode at all in the decoding process, other than simply
as an index to look up what the control lines should be from the "control ROM." we'd like to
- reduce the number of control lines needed; reduce redundancy, while increasing functionality
- move from this ad-hoc "design" to something that's acutally had some thought put into it...
- remove the arduino. or at least, remove it as a component of the cpu itself. currently it's used to generate
the RST and CLK signals as well as, essentially, emulate the control ROM. granted, though, using it to emulate
the control ROM is _great_ because it makes it so much easier and faster to iterate while developing the microcode.
_but_ we at least want to get to a place where we could swap it out with EEPROM(s) and without any other changes
needed, ideally. so, we'll eventually want to stop using the arduino for RST and CLK.
oh! almost forgot: we're also using it to load code/data into RAM on startup. eventually we'd want to replace that
with some sort of bootloader that exists in ROM, but. yeah. again, the obvious advantage: iteration. but.. uh. yeah.
- SOMEDAY, it'd be great to have interrupts or at least some sort of interrupt-like thing on a timer, if not
"actual interrupts." let's explore both of those ideas:
- i don't think a bare-minimum form of interrupts would be too difficult to implement. just don't forget a clock
synchronizer. the main actual complexity, i think, is like.. what exactly are the semantics? as in, does the IRQ line
have to remain active until the interrupt is cleared by an ISR or is an edge trigger all we need? and what if
an interrupt is triggered while we're already executing an ISR. etc. -- real nitty gritty, gross type shit.
- a timer instead of an IRQ line... honestly i think like.. it'd pretty much be identical to the above, no? ...
... ... yeah i think so lol, so. anyway.
either way, we have to handle it a bit carefully: being an async event, an interrupt (or timer overflow/tick/whatever)
can and will occur while the processor is in the middle of executing some instruction. so, really, i think all we have to
do, at least, is just wait until the current instruction has retired before servicing the interrupt. ... i think that's
mostly it? *shrugs*
of course, i've been leaving out all the actual guts and details. like, obviously when servicing an interrupt, we need to
push the PC to return, at least. we probably want to push the flags too? and when returning from an interrupt, the opposite;
an `rti` is essentially a `ret`, really. mostly.
we also need to have an interrupt enable flag so code may disable interrupts as needed. furthermore, we'd want to automatically
disable interrupts when servicing an interrupt. this does raise the question: do we support nested interrupts? but, eh. nah. :P
- re. the above, about control logic: we technically have eight unused control lines available right now. sort of.
we currently only use the first eight control lines to drive the data bus when loading code/data into RAM. nothing's stopping us
from making them dual-purpose control lines, as in, if d_rd is inactive, they don't drive the data bus; they drive other
control signals. although, to do this we'd need to gate them against d_rd, at minimum, so it's not the most convenient way to
get more control lines. but on the other hand, what we're doing now is pretty wasteful, so. *shrugs*
- change the bit shift inputs from B to A so we don't have to copy A into B to shift it
- allow loading (and perhaps setting and clearing too, probably?) the Z and C flags individually
- Z flag should be touched by and, or, xor, but C shouldn't
- consolidate ctrl.asm, isa.asm, ctrl.h, and isa.h
- remove the bitwise not function from the PLD logic -- er.. fix it.
- automatically check microcode for mistakes causing multiple devices to drive to the same bus
- what if we had "skip" instructions? i.e. instead of a conditional branch, a conditional skip
of the following instruction. i think the simplest way to implement this would be to have a
flag that gets set or cleared by the skip instruction and then the following instruction would
just skip the correct number of bytes if that flag is set, rather than actually executing normally