add Makefile for verilog compilation
[rv32.git] / cpu_handle_csr.py
1 """
2 /*
3 * Copyright 2018 Jacob Lifshay
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 */
24 `timescale 1ns / 1ps
25 `include "riscv.vh"
26 `include "cpu.vh"
27 """
28
29 import string
30 from migen import *
31 from migen.fhdl import verilog
32 from migen.fhdl.structure import _Operator
33
34 from riscvdefs import *
35 from cpudefs import *
36
37
38 class Misa:
39 def __init__(self, comb, sync):
40 self.comb = comb
41 self.sync = sync
42 self.misa = Signal(32)
43 cl = []
44 for l in list(string.ascii_lowercase):
45 value = 1 if l == 'i' else 0
46 cl.append(Constant(value))
47 cl.append(Constant(0, 4))
48 cl.append(Constant(0b01, 2))
49 self.comb += self.misa.eq(Cat(cl))
50
51 class MStatus:
52 def __init__(self, comb, sync):
53 self.comb = comb
54 self.sync = sync
55 self.mpie = Signal(name="mstatus_mpie")
56 self.mie = Signal(name="mstatus_mie")
57 self.mstatus = Signal(32, name="mstatus")
58
59 self.sync += self.mie.eq(0)
60 self.sync += self.mpie.eq(0)
61 self.sync += self.mstatus.eq(0)
62
63
64 class M:
65 def __init__(self, comb, sync):
66 self.comb = comb
67 self.sync = sync
68 self.mcause = Signal(32)
69 self.mepc = Signal(32)
70 self.mscratch = Signal(32)
71 self.sync += self.mcause.eq(0)
72 self.sync += self.mepc.eq(0) # 32'hXXXXXXXX;
73 self.sync += self.mscratch.eq(0) # 32'hXXXXXXXX;
74
75
76 class MIE:
77 def __init__(self, comb, sync):
78 self.comb = comb
79 self.sync = sync
80 self.meie = Signal(name="mie_meie")
81 self.mtie = Signal(name="mie_mtie")
82 self.msie = Signal(name="mie_msie")
83 self.mie = Signal(32)
84
85
86 class MIP:
87 def __init__(self):
88 self.mip = Signal(32)
89
90
91
92 class MInfo:
93 def __init__(self, comb):
94 self.comb = comb
95 # TODO
96 self.cycle_counter = Signal(64); # TODO: implement cycle_counter
97 self.time_counter = Signal(64); # TODO: implement time_counter
98 self.instret_counter = Signal(64); # TODO: implement instret_counter
99
100 self.mvendorid = Signal(32)
101 self.marchid = Signal(32)
102 self.mimpid = Signal(32)
103 self.mhartid = Signal(32)
104 self.comb += self.mvendorid.eq(Constant(0, 32))
105 self.comb += self.marchid.eq(Constant(0, 32))
106 self.comb += self.mimpid.eq(Constant(0, 32))
107 self.comb += self.mhartid.eq(Constant(0, 32))
108
109
110 class CPUHandleCSR(Module):
111 """
112 """
113
114 def __init__(self):
115 Module.__init__(self)
116 self.clk = ClockSignal()
117 self.reset = ResetSignal()
118
119 self.dc_funct3 = Signal(3)
120 self.mtvec = Signal(32)
121 self.csr_number = Signal(12)
122 self.csr_writes = Signal()
123
124 self.input_value = Signal(32)
125 self.output_value = Signal(32)
126
127 mstatus = MStatus(self.comb, self.sync)
128 m = M(self.comb, self.sync)
129 mie = MIE(self.comb, self.sync)
130 mip = MIP()
131 self.mie = mstatus.mie
132 self.mepc = m.mepc
133 self.mcause = m.mcause
134
135 minfo = MInfo(self.comb)
136 misa = Misa(self.comb, self.sync)
137
138 ms = Instance("CPUMStatus", name="cpu_mstatus",
139 o_mstatus = mstatus.mstatus,
140 i_mpie = mstatus.mpie,
141 i_mie = mstatus.mie)
142
143 self.specials += ms
144
145 mp = Instance("CPUMIP", name="cpu_mip",
146 o_mip = mip.mip)
147
148 self.specials += mp
149
150 mii = Instance("CPUMIE", name="cpu_mie",
151 o_mie = mie.mie,
152 i_meie = mie.meie,
153 i_mtie = mie.mtie,
154 i_msie = mie.msie)
155
156 self.specials += mii
157
158 written_value = Signal(32)
159
160 c = {}
161
162 # cycle
163 c[csr_cycle] = self.output_value.eq(minfo.cycle_counter[0:32])
164 c[csr_cycleh] = self.output_value.eq(minfo.cycle_counter[32:64])
165 # time
166 c[csr_time] = self.output_value.eq(minfo.time_counter[0:32])
167 c[csr_timeh] = self.output_value.eq(minfo.time_counter[32:64])
168 # instret
169 c[csr_instret] = self.output_value.eq(minfo.instret_counter[0:32])
170 c[csr_instreth] = self.output_value.eq(minfo.instret_counter[32:64])
171 # mvendorid/march/mimpl/mhart
172 c[csr_mvendorid] = self.output_value.eq(minfo.mvendorid)
173 c[csr_marchid ] = self.output_value.eq(minfo.marchid )
174 c[csr_mimpid ] = self.output_value.eq(minfo.mimpid )
175 c[csr_mhartid ] = self.output_value.eq(minfo.mhartid )
176 # misa
177 c[csr_misa ] = self.output_value.eq(misa.misa)
178 # mstatus
179 c[csr_mstatus ] = [
180 self.output_value.eq(mstatus.mstatus),
181 self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
182 written_value),
183 mstatus.mpie.eq(written_value[7]),
184 mstatus.mie.eq(written_value[3])
185 ]
186 # mie
187 c[csr_mie ] = [
188 self.output_value.eq(mie.mie),
189 self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
190 written_value),
191 mie.meie.eq(written_value[11]),
192 mie.mtie.eq(written_value[7]),
193 mie.msie.eq(written_value[3]),
194 ]
195 # mtvec
196 c[csr_mtvec ] = self.output_value.eq(self.mtvec)
197 # mscratch
198 c[csr_mscratch ] = [
199 self.output_value.eq(m.mscratch),
200 self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
201 written_value),
202 If(self.csr_writes,
203 m.mscratch.eq(written_value),
204 )
205 ]
206 # mepc
207 c[csr_mepc ] = [
208 self.output_value.eq(m.mepc),
209 self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
210 written_value),
211 If(self.csr_writes,
212 m.mepc.eq(written_value),
213 )
214 ]
215
216 # mcause
217 c[csr_mcause ] = [
218 self.output_value.eq(m.mcause),
219 self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
220 written_value),
221 If(self.csr_writes,
222 m.mcause.eq(written_value),
223 )
224 ]
225
226 # mip
227 c[csr_mip ] = [
228 self.output_value.eq(mip.mip),
229 self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
230 written_value),
231 ]
232
233 self.sync += Case(self.csr_number, c)
234
235 def evaluate_csr_funct3_op(self, funct3, previous, written):
236 c = { "default": written.eq(Constant(0, 32))}
237 for f in [F3.csrrw, F3.csrrwi]:
238 c[f] = written.eq(self.input_value)
239 for f in [F3.csrrs, F3.csrrsi]:
240 c[f] = written.eq(self.input_value | previous)
241 for f in [F3.csrrc, F3.csrrci]:
242 c[f] = written.eq(~self.input_value & previous)
243 return Case(funct3, c)
244
245
246 if __name__ == "__main__":
247 example = CPUHandleCSR()
248 print(verilog.convert(example,
249 {
250 example.dc_funct3,
251 example.mtvec,
252 example.csr_number,
253 example.csr_writes,
254 example.input_value,
255 example.output_value,
256 example.mie,
257 example.mepc,
258 example.mcause,
259 }))