]> Witch of Git - jade-rose/blob - hardware/core.py
Begin implementing CPU with fetching and decoding
[jade-rose] / hardware / core.py
1 from nmigen import *
2 from enum import Enum
3
4
5 class CpuState(Enum):
6 READ = 0
7 EXEC = 1
8 EXEC2 = 2
9 HALT = 3
10
11
12 class Core(Elaboratable):
13 def __init__(self):
14 self.regs = Array(Signal(8, reset=0) for _ in range(4))
15 self.it = Signal(8, reset=0)
16 self.data1 = Signal(8, reset=255)
17 self.data2 = Signal(8, reset=254)
18 self.code = Signal(8, reset=1)
19 self.link = Signal(8, reset=0)
20
21 self.pc = Signal(16, reset=0)
22 self.state = Signal(CpuState)
23 self.inst = Signal(8)
24
25 self.addr = Signal(16)
26 self.r_en = Signal()
27 self.w_en = Signal()
28 self.d_in = Signal(8)
29 self.d_out = Signal(8)
30 self.debug = Signal(8)
31 self.debug_en = Signal()
32
33 def elaborate(self, platform):
34 m = Module()
35 with m.If(self.state == CpuState.HALT):
36 pass # We're halted :)
37 with m.Elif(self.state == CpuState.READ):
38 m.d.sync += self.state.eq(CpuState.EXEC)
39 m.d.sync += self.pc.eq(self.pc + 1)
40 m.d.comb += [
41 self.addr.eq(self.pc),
42 self.r_en.eq(True),
43 ]
44 with m.Elif(self.state == CpuState.EXEC):
45 m.d.sync += self.state.eq(CpuState.READ)
46 m.d.sync += self.inst.eq(self.d_in)
47 m.d.sync += self.pc.eq(self.pc + 2)
48 m.d.comb += [
49 self.addr.eq(self.pc + 1),
50 self.r_en.eq(True),
51 ]
52 self.execute(m, self.d_in)
53 with m.Elif(self.state == CpuState.EXEC2):
54 m.d.sync += self.state.eq(CpuState.READ)
55 self.execute2(m, self.inst, self.d_in)
56 return m
57
58 def execute(self, m, inst):
59 m.d.sync += self.state.eq(CpuState.READ)
60 with m.Switch(inst):
61 with m.Case("00000000"): # HALT
62 m.d.sync += self.state.eq(CpuState.HALT)
63 with m.Case("00000001"): # NOPE
64 pass
65 with m.Case("00000010"): # PRNT
66 m.d.comb += self.debug.eq(self.it)
67 m.d.comb += self.debug_en.eq(True)
68 with m.Case("00000011"): # WAIT
69 pass # @TODO: Implement WAIT
70 with m.Case("0000010-"): # reserved
71 pass
72 with m.Case("00000110"): # CABA
73 pass # @TODO: Implement CABA
74 with m.Case("00000111"): # COFA
75 pass # @TODO: Implement COFA
76 with m.Case("00001---"): # ALU1
77 self.inst_alu1(m, inst)
78 with m.Case("000100--"): # GET?
79 pass
80 with m.Case("000101--"): # UNSPECIFIED
81 m.d.sync += self.state.eq(CpuState.HALT)
82 with m.Case("000110--"): # SET?
83 pass
84 with m.Case("000111--"): # UNSPECIFIED
85 m.d.sync += self.state.eq(CpuState.HALT)
86 with m.Case("000111--"): # UNSPECIFIED
87 pass
88 with m.Case("00100---"): # GETR
89 pass
90 with m.Case("00101---"): # SETR
91 pass
92 with m.Case("00110---"): # SWAP
93 pass
94 with m.Case("00111---"): # ISLT
95 pass
96 with m.Case("01------"): # ALUR
97 pass
98 with m.Case("10------"): # LD/ST [12][UR}
99 pass
100 with m.Case("110-----"): # RESERVED
101 m.d.sync += self.state.eq(CpuState.HALT)
102 with m.Case("11100---"): # LD2D
103 pass
104 with m.Case("11101---"): # ST2D
105 pass
106 with m.Case("1111----"): # WITH-IMM
107 m.d.sync += self.state.eq(CpuState.EXEC2)
108 m.d.sync += self.pc.eq(self.pc)
109 pass
110
111 def execute2(self, m, base, imm):
112 with m.Switch(Cat(imm, base)):
113 with m.Case("111100----------"): # ALUI
114 pass
115 with m.Case("11110100--------"): # BEZI
116 pass
117 with m.Case("11110101--------"): # JOFI
118 pass
119 with m.Case("11110110--------"): # CABI
120 pass
121 with m.Case("11110111--------"): # COFI
122 pass
123 with m.Case("111110----------"): # Reserved
124 m.d.sync += self.state.eq(CpuState.HALT)
125 with m.Case("1111110---------"): # Reserved
126 m.d.sync += self.state.eq(CpuState.HALT)
127 with m.Case("11111110--------"): # GETI
128 m.d.sync += self.it.eq(imm)
129 with m.Case("11111111--------"): # EXT1 (reserved)
130 m.d.sync += self.state.eq(CpuState.HALT)
131
132 def inst_alu1(self, m, inst):
133 op = inst[0:3]
134 with m.Switch(op):
135 with m.Case("000"):
136 m.d.sync += self.it.eq(0)
137 with m.Case("001"):
138 m.d.sync += self.it.eq(self.it << 1)
139 with m.Case("010"):
140 m.d.sync += self.it.eq(self.it >> 1)
141 with m.Case("011"):
142 m.d.sync += self.it.eq(self.it // 2)
143 with m.Case("100"):
144 m.d.sync += self.it.eq(self.it + 1)
145 with m.Case("101"):
146 m.d.sync += self.it.eq(self.it - 1)
147 with m.Case("110"):
148 m.d.sync += self.it.eq(~self.it)
149 with m.Case("111"):
150 m.d.sync += self.it.eq(-self.it)
151
152 def inputs(self):
153 return [self.d_in]
154
155 def outputs(self):
156 return [self.addr, self.d_out, self.r_en, self.w_en, self.debug]
157
158 def ports(self):
159 return self.inputs() + self.outputs()