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