3 * Copyright 2018 Jacob Lifshay
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:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
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
31 from migen
.fhdl
import verilog
32 from migen
.fhdl
.structure
import _Operator
34 from riscvdefs
import *
39 def __init__(self
, comb
, sync
):
42 self
.misa
= Signal(32)
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
))
52 def __init__(self
, comb
, sync
):
55 self
.mpie
= Signal(name
="mstatus_mpie")
56 self
.mie
= Signal(name
="mstatus_mie")
57 self
.mstatus
= Signal(32, name
="mstatus")
59 self
.sync
+= self
.mie
.eq(0)
60 self
.sync
+= self
.mpie
.eq(0)
61 self
.sync
+= self
.mstatus
.eq(0)
65 def __init__(self
, comb
, 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;
77 def __init__(self
, comb
, sync
):
80 self
.meie
= Signal(name
="mie_meie")
81 self
.mtie
= Signal(name
="mie_mtie")
82 self
.msie
= Signal(name
="mie_msie")
93 def __init__(self
, comb
):
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
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))
110 class CPUHandleCSR(Module
):
115 Module
.__init
__(self
)
116 self
.clk
= ClockSignal()
117 self
.reset
= ResetSignal()
119 self
.dc_funct3
= Signal(3)
120 self
.mtvec
= Signal(32)
121 self
.csr_number
= Signal(12)
122 self
.csr_writes
= Signal()
124 self
.input_value
= Signal(32)
125 self
.output_value
= Signal(32)
127 mstatus
= MStatus(self
.comb
, self
.sync
)
128 m
= M(self
.comb
, self
.sync
)
129 mie
= MIE(self
.comb
, self
.sync
)
131 self
.mie
= mstatus
.mie
133 self
.mcause
= m
.mcause
135 minfo
= MInfo(self
.comb
)
136 misa
= Misa(self
.comb
, self
.sync
)
138 ms
= Instance("CPUMStatus", name
="cpu_mstatus",
139 o_mstatus
= mstatus
.mstatus
,
140 i_mpie
= mstatus
.mpie
,
145 mp
= Instance("CPUMIP", name
="cpu_mip",
150 mii
= Instance("CPUMIE", name
="cpu_mie",
158 written_value
= Signal(32)
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])
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])
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
)
177 c
[csr_misa
] = self
.output_value
.eq(misa
.misa
)
180 self
.output_value
.eq(mstatus
.mstatus
),
181 self
.evaluate_csr_funct3_op(self
.dc_funct3
, self
.output_value
,
183 mstatus
.mpie
.eq(written_value
[7]),
184 mstatus
.mie
.eq(written_value
[3])
188 self
.output_value
.eq(mie
.mie
),
189 self
.evaluate_csr_funct3_op(self
.dc_funct3
, self
.output_value
,
191 mie
.meie
.eq(written_value
[11]),
192 mie
.mtie
.eq(written_value
[7]),
193 mie
.msie
.eq(written_value
[3]),
196 c
[csr_mtvec
] = self
.output_value
.eq(self
.mtvec
)
199 self
.output_value
.eq(m
.mscratch
),
200 self
.evaluate_csr_funct3_op(self
.dc_funct3
, self
.output_value
,
203 m
.mscratch
.eq(written_value
),
208 self
.output_value
.eq(m
.mepc
),
209 self
.evaluate_csr_funct3_op(self
.dc_funct3
, self
.output_value
,
212 m
.mepc
.eq(written_value
),
218 self
.output_value
.eq(m
.mcause
),
219 self
.evaluate_csr_funct3_op(self
.dc_funct3
, self
.output_value
,
222 m
.mcause
.eq(written_value
),
228 self
.output_value
.eq(mip
.mip
),
229 self
.evaluate_csr_funct3_op(self
.dc_funct3
, self
.output_value
,
233 self
.sync
+= Case(self
.csr_number
, c
)
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
)
246 if __name__
== "__main__":
247 example
= CPUHandleCSR()
248 print(verilog
.convert(example
,
255 example
.output_value
,