use longer memtest in litex sim
[soc.git] / src / soc / litex / florent / sim.py
1 #!/usr/bin/env python3
2
3 import os
4 import argparse
5
6 from migen import (Signal, FSM, If, Display, Finish, NextValue, NextState)
7
8 from litex.build.generic_platform import Pins, Subsignal
9 from litex.build.sim import SimPlatform
10 from litex.build.io import CRG
11 from litex.build.sim.config import SimConfig
12
13 from litex.soc.integration.soc import SoCRegion
14 from litex.soc.integration.soc_core import SoCCore
15 from litex.soc.integration.soc_sdram import SoCSDRAM
16 from litex.soc.integration.builder import Builder
17
18 from litedram import modules as litedram_modules
19 from litedram.phy.model import SDRAMPHYModel
20 from litex.tools.litex_sim import sdram_module_nphases, get_sdram_phy_settings
21
22 from litex.tools.litex_sim import Platform
23
24 from libresoc import LibreSoC
25 from microwatt import Microwatt
26
27 # LibreSoCSim -----------------------------------------------------------------
28
29 class LibreSoCSim(SoCSDRAM):
30 def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
31 #sdram_module = "AS4C16M16",
32 #sdram_data_width = 16,
33 sdram_module = "MT48LC16M16",
34 sdram_data_width = 32,
35 ):
36 assert cpu in ["libresoc", "microwatt"]
37 platform = Platform()
38 sys_clk_freq = int(100e6)
39
40 # SoCCore -------------------------------------------------------------
41 SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
42 cpu_type = "microwatt",
43 cpu_cls = LibreSoC if cpu == "libresoc" \
44 else Microwatt,
45 #bus_data_width = 64,
46 uart_name = "sim",
47 with_sdram = with_sdram,
48 sdram_module = sdram_module,
49 sdram_data_width = sdram_data_width,
50 integrated_rom_size = 0x10000,
51 integrated_main_ram_size = 0x00000000 if with_sdram \
52 else 0x10000000 , # 256MB
53 )
54 self.platform.name = "sim"
55
56 # CRG -----------------------------------------------------------------
57 self.submodules.crg = CRG(platform.request("sys_clk"))
58
59 ram_init = []
60
61 # SDRAM ----------------------------------------------------
62 if with_sdram:
63 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
64 sdram_module_cls = getattr(litedram_modules, sdram_module)
65 sdram_rate = "1:{}".format(
66 sdram_module_nphases[sdram_module_cls.memtype])
67 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
68 phy_settings = get_sdram_phy_settings(
69 memtype = sdram_module.memtype,
70 data_width = sdram_data_width,
71 clk_freq = sdram_clk_freq)
72 self.submodules.sdrphy = SDRAMPHYModel(sdram_module,
73 phy_settings,
74 init=ram_init
75 )
76 self.register_sdram(
77 self.sdrphy,
78 sdram_module.geom_settings,
79 sdram_module.timing_settings)
80 # FIXME: skip memtest to avoid corrupting memory
81 #self.add_constant("MEMTEST_BUS_SIZE", 64//16)
82 #self.add_constant("MEMTEST_DATA_SIZE", 64//16)
83 #self.add_constant("MEMTEST_ADDR_SIZE", 64//16)
84 self.add_constant("MEMTEST_BUS_DEBUG", 1)
85
86
87 # Debug ---------------------------------------------------------------
88 if not debug:
89 return
90
91 # setup running of DMI FSM
92 dmi_addr = Signal(3)
93 dmi_din = Signal(64)
94 dmi_dout = Signal(64)
95 dmi_wen = Signal(1)
96 dmi_req = Signal(1)
97
98 # debug log out
99 dbg_addr = Signal(3)
100 dbg_dout = Signal(64)
101 dbg_msg = Signal(1)
102
103 # capture pc from dmi
104 pc = Signal(64)
105 active_dbg = Signal()
106
107 # increment counter, Stop after 100000 cycles
108 uptime = Signal(64)
109 self.sync += uptime.eq(uptime + 1)
110 #self.sync += If(uptime == 1000000000000, Finish())
111
112 dmifsm = FSM()
113 self.submodules += dmifsm
114
115 # DMI FSM
116 dmifsm.act("START",
117 If(dmi_req & dmi_wen,
118 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
119 self.cpu.dmi_din.eq(dmi_din), # DMI in
120 self.cpu.dmi_req.eq(1), # DMI request
121 self.cpu.dmi_wr.eq(1), # DMI write
122 If(self.cpu.dmi_ack,
123 (NextState("IDLE"),
124 )
125 ),
126 ),
127 ),
128 If(dmi_req & ~dmi_wen,
129 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
130 self.cpu.dmi_req.eq(1), # DMI request
131 self.cpu.dmi_wr.eq(0), # DMI read
132 If(self.cpu.dmi_ack,
133 (NextState("IDLE"),
134 NextValue(dbg_addr, dmi_addr),
135 NextValue(dbg_dout, self.cpu.dmi_dout),
136 NextValue(dbg_msg, 1),
137 )
138 ),
139 ),
140 )
141 )
142
143 dmifsm.act("IDLE",
144 (NextValue(dmi_req, 0),
145 NextValue(dmi_addr, 0),
146 NextValue(dmi_din, 0),
147 NextValue(dmi_wen, 0),
148 NextState("START"), # back to start on next cycle
149 )
150 )
151
152 # debug messages out
153 self.sync += If(dbg_msg,
154 (If(active_dbg & (dbg_addr == 0b10), # PC
155 Display("pc : %016x", dbg_dout),
156 ),
157 If(dbg_addr == 0b10, # PC
158 pc.eq(dbg_dout), # capture PC
159 ),
160 If(dbg_addr == 0b11, # MSR
161 Display(" msr: %016x", dbg_dout),
162 ),
163 If(dbg_addr == 0b101, # GPR
164 Display(" gpr: %016x", dbg_dout),
165 ),
166 dbg_msg.eq(0)
167 )
168 )
169
170 # kick off a "stop"
171 self.sync += If(uptime == 0,
172 (dmi_addr.eq(0), # CTRL
173 dmi_din.eq(1<<0), # STOP
174 dmi_req.eq(1),
175 dmi_wen.eq(1),
176 )
177 )
178
179 # loop every 1<<N cycles
180 cyclewid = 9
181
182 # get the PC
183 self.sync += If(uptime[0:cyclewid] == 4,
184 (dmi_addr.eq(0b10), # NIA
185 dmi_req.eq(1),
186 dmi_wen.eq(0),
187 )
188 )
189
190 # kick off a "step"
191 self.sync += If(uptime[0:cyclewid] == 8,
192 (dmi_addr.eq(0), # CTRL
193 dmi_din.eq(1<<3), # STEP
194 dmi_req.eq(1),
195 dmi_wen.eq(1),
196 )
197 )
198
199 # limit range of pc for debug reporting
200 self.comb += active_dbg.eq((0x5108 <= pc) & (pc <= 0x5234))
201 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
202
203 # get the MSR
204 self.sync += If(active_dbg & (uptime[0:cyclewid] == 28),
205 (dmi_addr.eq(0b11), # MSR
206 dmi_req.eq(1),
207 dmi_wen.eq(0),
208 )
209 )
210
211 # read all 32 GPRs
212 for i in range(32):
213 self.sync += If(active_dbg & (uptime[0:cyclewid] == 30+(i*8)),
214 (dmi_addr.eq(0b100), # GSPR addr
215 dmi_din.eq(i), # r1
216 dmi_req.eq(1),
217 dmi_wen.eq(1),
218 )
219 )
220
221 self.sync += If(active_dbg & (uptime[0:cyclewid] == 34+(i*8)),
222 (dmi_addr.eq(0b101), # GSPR data
223 dmi_req.eq(1),
224 dmi_wen.eq(0),
225 )
226 )
227
228 # monitor ibus write
229 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
230 self.cpu.ibus.we,
231 Display(" [%06x] iadr: %8x, s %01x w %016x",
232 uptime,
233 self.cpu.ibus.adr,
234 self.cpu.ibus.sel,
235 self.cpu.ibus.dat_w,
236 )
237 )
238 # monitor ibus read
239 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
240 ~self.cpu.ibus.we,
241 Display(" [%06x] iadr: %8x, s %01x r %016x",
242 uptime,
243 self.cpu.ibus.adr,
244 self.cpu.ibus.sel,
245 self.cpu.ibus.dat_r
246 )
247 )
248
249 # monitor bbus read/write
250 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
251 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
252 uptime,
253 self.cpu.dbus.adr,
254 self.cpu.dbus.we,
255 self.cpu.dbus.sel,
256 self.cpu.dbus.dat_w,
257 self.cpu.dbus.dat_r
258 )
259 )
260
261 # Build -----------------------------------------------------------------------
262
263 def main():
264 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
265 parser.add_argument("--cpu", default="libresoc",
266 help="CPU to use: libresoc (default) or microwatt")
267 parser.add_argument("--debug", action="store_true",
268 help="Enable debug traces")
269 parser.add_argument("--trace", action="store_true",
270 help="Enable tracing")
271 parser.add_argument("--trace-start", default=0,
272 help="Cycle to start FST tracing")
273 parser.add_argument("--trace-end", default=-1,
274 help="Cycle to end FST tracing")
275 args = parser.parse_args()
276
277 sim_config = SimConfig(default_clk="sys_clk")
278 sim_config.add_module("serial2console", "serial")
279
280 for i in range(2):
281 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug)
282 builder = Builder(soc,compile_gateware = i!=0)
283 builder.build(sim_config=sim_config,
284 run = i!=0,
285 trace = args.trace,
286 trace_start = int(args.trace_start),
287 trace_end = int(args.trace_end),
288 trace_fst = 0)
289 os.chdir("../")
290
291 if __name__ == "__main__":
292 main()