67f87fde2f2adfcf7040226cd5637be8975b6782
[soc.git] / src / soc / litex / florent / ls180soc.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 from litex.soc.integration.common import get_mem_data
18
19 from litedram import modules as litedram_modules
20 from litedram.phy.model import SDRAMPHYModel
21 from litedram.phy.gensdrphy import GENSDRPHY, HalfRateGENSDRPHY
22
23 from litex.soc.cores.gpio import GPIOInOut, GPIOIn, GPIOOut
24 from litex.soc.cores.spi import SPIMaster
25
26 from litex.tools.litex_sim import sdram_module_nphases, get_sdram_phy_settings
27
28 from litex.tools.litex_sim import Platform
29 from libresoc.ls180 import LS180Platform
30
31 from migen import Module
32 from litex.soc.interconnect.csr import AutoCSR
33
34 from libresoc import LibreSoC
35 from microwatt import Microwatt
36
37 # HACK!
38 from litex.soc.integration.soc import SoCCSRHandler
39 SoCCSRHandler.supported_address_width.append(12)
40
41
42 # LibreSoCSim -----------------------------------------------------------------
43
44 class LibreSoCSim(SoCCore):
45 def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
46 sdram_module = "AS4C16M16",
47 #sdram_data_width = 16,
48 #sdram_module = "MT48LC16M16",
49 sdram_data_width = 16,
50 irq_reserved_irqs = {'uart': 0},
51 platform='sim',
52 ):
53 assert cpu in ["libresoc", "microwatt"]
54 sys_clk_freq = int(50e6)
55
56 if platform == 'sim':
57 platform = Platform()
58 uart_name = "sim"
59 elif platform == 'ls180':
60 platform = LS180Platform()
61 uart_name = "serial"
62
63 #cpu_data_width = 32
64 cpu_data_width = 64
65
66 variant = "ls180"
67
68 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
69 # "hello_world/hello_world.bin"
70 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
71 # "tests/1.bin"
72 #ram_fname = "/tmp/test.bin"
73 #ram_fname = None
74 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
75 # "micropython/firmware.bin"
76 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
77 # "tests/xics/xics.bin"
78 ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
79 "tests/decrementer/decrementer.bin"
80 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
81 # "hello_world/hello_world.bin"
82
83 # reserve XICS ICP and XICS memory addresses.
84 self.mem_map['icp'] = 0xc0010000
85 self.mem_map['ics'] = 0xc0011000
86 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
87 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
88
89 ram_init = []
90 if ram_fname:
91 #ram_init = get_mem_data({
92 # ram_fname: "0x00000000",
93 # }, "little")
94 ram_init = get_mem_data(ram_fname, "little")
95
96 # remap the main RAM to reset-start-address
97 self.mem_map["main_ram"] = 0x00000000
98
99 # without sram nothing works, therefore move it to higher up
100 self.mem_map["sram"] = 0x90000000
101
102 # put UART at 0xc000200 (w00t! this works!)
103 self.csr_map["uart"] = 4
104
105
106 # SoCCore -------------------------------------------------------------
107 SoCCore.__init__(self, platform, clk_freq=sys_clk_freq,
108 cpu_type = "microwatt",
109 cpu_cls = LibreSoC if cpu == "libresoc" \
110 else Microwatt,
111 #bus_data_width = 64,
112 csr_address_width = 14, # limit to 0x8000
113 cpu_variant = variant,
114 csr_data_width = 8,
115 l2_size = 0,
116 uart_name = uart_name,
117 with_sdram = with_sdram,
118 sdram_module = sdram_module,
119 sdram_data_width = sdram_data_width,
120 integrated_rom_size = 0 if ram_fname else 0x10000,
121 integrated_sram_size = 0x40000,
122 #integrated_main_ram_init = ram_init,
123 integrated_main_ram_size = 0x00000000 if with_sdram \
124 else 0x10000000 , # 256MB
125 )
126 self.platform.name = "ls180"
127
128 # SDR SDRAM ----------------------------------------------
129 if False: # not self.integrated_main_ram_size:
130 self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"))
131
132
133 if cpu == "libresoc":
134 # XICS interrupt devices
135 icp_addr = self.mem_map['icp']
136 icp_wb = self.cpu.xics_icp
137 icp_region = SoCRegion(origin=icp_addr, size=0x20, cached=False)
138 self.bus.add_slave(name='icp', slave=icp_wb, region=icp_region)
139
140 ics_addr = self.mem_map['ics']
141 ics_wb = self.cpu.xics_ics
142 ics_region = SoCRegion(origin=ics_addr, size=0x1000, cached=False)
143 self.bus.add_slave(name='ics', slave=ics_wb, region=ics_region)
144
145 # CRG -----------------------------------------------------------------
146 self.submodules.crg = CRG(platform.request("sys_clk"))
147
148 #ram_init = []
149
150 # SDRAM ----------------------------------------------------
151 if with_sdram:
152 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
153 sdram_module_cls = getattr(litedram_modules, sdram_module)
154 sdram_rate = "1:{}".format(
155 sdram_module_nphases[sdram_module_cls.memtype])
156 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
157 phy_settings = get_sdram_phy_settings(
158 memtype = sdram_module.memtype,
159 data_width = sdram_data_width,
160 clk_freq = sdram_clk_freq)
161 #sdrphy_cls = HalfRateGENSDRPHY
162 sdrphy_cls = GENSDRPHY
163 self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"))
164 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
165 # phy_settings,
166 # init=ram_init
167 # )
168 self.add_sdram("sdram",
169 phy = self.sdrphy,
170 module = sdram_module,
171 origin = self.mem_map["main_ram"],
172 size = 0x40000000,
173 l2_cache_size = 0, # 8192
174 l2_cache_min_data_width = 128,
175 l2_cache_reverse = True
176 )
177 # FIXME: skip memtest to avoid corrupting memory
178 self.add_constant("MEMTEST_BUS_SIZE", 128//16)
179 self.add_constant("MEMTEST_DATA_SIZE", 128//16)
180 self.add_constant("MEMTEST_ADDR_SIZE", 128//16)
181 self.add_constant("MEMTEST_BUS_DEBUG", 1)
182 self.add_constant("MEMTEST_ADDR_DEBUG", 1)
183 self.add_constant("MEMTEST_DATA_DEBUG", 1)
184
185 # GPIOs
186 #platform.add_extension([("gpio_in", 0, Pins(8))])
187 self.submodules.gpio_in = GPIOIn(platform.request("gpio_in"))
188 self.add_csr("gpio_in")
189 self.submodules.gpio_out = GPIOIn(platform.request("gpio_out"))
190 self.add_csr("gpio_out")
191
192 # SPI Master
193 self.submodules.spi_master = SPIMaster(
194 pads = platform.request("spi_master"),
195 data_width = 8,
196 sys_clk_freq = sys_clk_freq,
197 spi_clk_freq = 8e6,
198 )
199 self.add_csr("spi_master")
200
201 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
202 self.comb += self.cpu.interrupt[12:16].eq(platform.request("eint"))
203
204 # Debug ---------------------------------------------------------------
205 if not debug:
206 return
207
208 # setup running of DMI FSM
209 dmi_addr = Signal(4)
210 dmi_din = Signal(64)
211 dmi_dout = Signal(64)
212 dmi_wen = Signal(1)
213 dmi_req = Signal(1)
214
215 # debug log out
216 dbg_addr = Signal(4)
217 dbg_dout = Signal(64)
218 dbg_msg = Signal(1)
219
220 # capture pc from dmi
221 pc = Signal(64)
222 active_dbg = Signal()
223 active_dbg_cr = Signal()
224 active_dbg_xer = Signal()
225
226 # xer flags
227 xer_so = Signal()
228 xer_ca = Signal()
229 xer_ca32 = Signal()
230 xer_ov = Signal()
231 xer_ov32 = Signal()
232
233 # increment counter, Stop after 100000 cycles
234 uptime = Signal(64)
235 self.sync += uptime.eq(uptime + 1)
236 #self.sync += If(uptime == 1000000000000, Finish())
237
238 # DMI FSM counter and FSM itself
239 dmicount = Signal(10)
240 dmirunning = Signal(1)
241 dmi_monitor = Signal(1)
242 dmifsm = FSM()
243 self.submodules += dmifsm
244
245 # DMI FSM
246 dmifsm.act("START",
247 If(dmi_req & dmi_wen,
248 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
249 self.cpu.dmi_din.eq(dmi_din), # DMI in
250 self.cpu.dmi_req.eq(1), # DMI request
251 self.cpu.dmi_wr.eq(1), # DMI write
252 If(self.cpu.dmi_ack,
253 (NextState("IDLE"),
254 )
255 ),
256 ),
257 ),
258 If(dmi_req & ~dmi_wen,
259 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
260 self.cpu.dmi_req.eq(1), # DMI request
261 self.cpu.dmi_wr.eq(0), # DMI read
262 If(self.cpu.dmi_ack,
263 # acknowledge received: capture data.
264 (NextState("IDLE"),
265 NextValue(dbg_addr, dmi_addr),
266 NextValue(dbg_dout, self.cpu.dmi_dout),
267 NextValue(dbg_msg, 1),
268 ),
269 ),
270 ),
271 )
272 )
273
274 # DMI response received: reset the dmi request and check if
275 # in "monitor" mode
276 dmifsm.act("IDLE",
277 If(dmi_monitor,
278 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
279 ).Else(
280 NextState("START"), # back to start on next cycle
281 ),
282 NextValue(dmi_req, 0),
283 NextValue(dmi_addr, 0),
284 NextValue(dmi_din, 0),
285 NextValue(dmi_wen, 0),
286 )
287
288 # "monitor" mode fires off a STAT request
289 dmifsm.act("FIRE_MONITOR",
290 (NextValue(dmi_req, 1),
291 NextValue(dmi_addr, 1), # DMI STAT address
292 NextValue(dmi_din, 0),
293 NextValue(dmi_wen, 0), # read STAT
294 NextState("START"), # back to start on next cycle
295 )
296 )
297
298 self.comb += xer_so.eq((dbg_dout & 1) == 1)
299 self.comb += xer_ca.eq((dbg_dout & 4) == 4)
300 self.comb += xer_ca32.eq((dbg_dout & 8) == 8)
301 self.comb += xer_ov.eq((dbg_dout & 16) == 16)
302 self.comb += xer_ov32.eq((dbg_dout & 32) == 32)
303
304 # debug messages out
305 self.sync += If(dbg_msg,
306 (If(active_dbg & (dbg_addr == 0b10), # PC
307 Display("pc : %016x", dbg_dout),
308 ),
309 If(dbg_addr == 0b10, # PC
310 pc.eq(dbg_dout), # capture PC
311 ),
312 #If(dbg_addr == 0b11, # MSR
313 # Display(" msr: %016x", dbg_dout),
314 #),
315 If(dbg_addr == 0b1000, # CR
316 Display(" cr : %016x", dbg_dout),
317 ),
318 If(dbg_addr == 0b1001, # XER
319 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
320 xer_so, xer_ca, xer_ca32, xer_ov, xer_ov32),
321 ),
322 If(dbg_addr == 0b101, # GPR
323 Display(" gpr: %016x", dbg_dout),
324 ),
325 # also check if this is a "stat"
326 If(dbg_addr == 1, # requested a STAT
327 #Display(" stat: %x", dbg_dout),
328 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
329 dmirunning.eq(1), # continue running
330 dmi_monitor.eq(0), # and stop monitor mode
331 ),
332 ),
333 dbg_msg.eq(0)
334 )
335 )
336
337 # kick off a "stop"
338 self.sync += If(uptime == 0,
339 (dmi_addr.eq(0), # CTRL
340 dmi_din.eq(1<<0), # STOP
341 dmi_req.eq(1),
342 dmi_wen.eq(1),
343 )
344 )
345
346 self.sync += If(uptime == 4,
347 dmirunning.eq(1),
348 )
349
350 self.sync += If(dmirunning,
351 dmicount.eq(dmicount + 1),
352 )
353
354 # loop every 1<<N cycles
355 cyclewid = 9
356
357 # get the PC
358 self.sync += If(dmicount == 4,
359 (dmi_addr.eq(0b10), # NIA
360 dmi_req.eq(1),
361 dmi_wen.eq(0),
362 )
363 )
364
365 # kick off a "step"
366 self.sync += If(dmicount == 8,
367 (dmi_addr.eq(0), # CTRL
368 dmi_din.eq(1<<3), # STEP
369 dmi_req.eq(1),
370 dmi_wen.eq(1),
371 dmirunning.eq(0), # stop counter, need to fire "monitor"
372 dmi_monitor.eq(1), # start "monitor" instead
373 )
374 )
375
376 # limit range of pc for debug reporting
377 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
378 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
379 self.comb += active_dbg.eq(1)
380
381
382 # get the MSR
383 self.sync += If(active_dbg & (dmicount == 12),
384 (dmi_addr.eq(0b11), # MSR
385 dmi_req.eq(1),
386 dmi_wen.eq(0),
387 )
388 )
389
390 if cpu == "libresoc":
391 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
392 self.comb += active_dbg_cr.eq(0)
393
394 # get the CR
395 self.sync += If(active_dbg_cr & (dmicount == 16),
396 (dmi_addr.eq(0b1000), # CR
397 dmi_req.eq(1),
398 dmi_wen.eq(0),
399 )
400 )
401
402 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
403 self.comb += active_dbg_xer.eq(active_dbg_cr)
404
405 # get the CR
406 self.sync += If(active_dbg_xer & (dmicount == 20),
407 (dmi_addr.eq(0b1001), # XER
408 dmi_req.eq(1),
409 dmi_wen.eq(0),
410 )
411 )
412
413 # read all 32 GPRs
414 for i in range(32):
415 self.sync += If(active_dbg & (dmicount == 24+(i*8)),
416 (dmi_addr.eq(0b100), # GSPR addr
417 dmi_din.eq(i), # r1
418 dmi_req.eq(1),
419 dmi_wen.eq(1),
420 )
421 )
422
423 self.sync += If(active_dbg & (dmicount == 28+(i*8)),
424 (dmi_addr.eq(0b101), # GSPR data
425 dmi_req.eq(1),
426 dmi_wen.eq(0),
427 )
428 )
429
430 # monitor bbus read/write
431 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
432 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
433 #uptime,
434 0,
435 self.cpu.dbus.adr,
436 self.cpu.dbus.we,
437 self.cpu.dbus.sel,
438 self.cpu.dbus.dat_w,
439 self.cpu.dbus.dat_r
440 )
441 )
442
443 return
444
445 # monitor ibus write
446 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
447 self.cpu.ibus.we,
448 Display(" [%06x] iadr: %8x, s %01x w %016x",
449 #uptime,
450 0,
451 self.cpu.ibus.adr,
452 self.cpu.ibus.sel,
453 self.cpu.ibus.dat_w,
454 )
455 )
456 # monitor ibus read
457 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
458 ~self.cpu.ibus.we,
459 Display(" [%06x] iadr: %8x, s %01x r %016x",
460 #uptime,
461 0,
462 self.cpu.ibus.adr,
463 self.cpu.ibus.sel,
464 self.cpu.ibus.dat_r
465 )
466 )
467
468 # Build -----------------------------------------------------------------------
469
470 def main():
471 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
472 parser.add_argument("--cpu", default="libresoc",
473 help="CPU to use: libresoc (default) or microwatt")
474 parser.add_argument("--platform", default="sim",
475 help="platform (sim or ls180)")
476 parser.add_argument("--debug", action="store_true",
477 help="Enable debug traces")
478 parser.add_argument("--trace", action="store_true",
479 help="Enable tracing")
480 parser.add_argument("--trace-start", default=0,
481 help="Cycle to start FST tracing")
482 parser.add_argument("--trace-end", default=-1,
483 help="Cycle to end FST tracing")
484 parser.add_argument("--build", action="store_true", help="Build bitstream")
485 args = parser.parse_args()
486
487
488 if args.platform == 'ls180':
489 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
490 platform=args.platform)
491 soc.add_sdcard()
492 soc.add_spi_sdcard()
493 builder = Builder(soc, compile_gateware = True)
494 builder.build(run = True)
495 os.chdir("../")
496 else:
497
498 sim_config = SimConfig(default_clk="sys_clk")
499 sim_config.add_module("serial2console", "serial")
500
501 for i in range(2):
502 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
503 platform=args.platform)
504 builder = Builder(soc, compile_gateware = i!=0)
505 builder.build(sim_config=sim_config,
506 run = i!=0,
507 trace = args.trace,
508 trace_start = int(args.trace_start),
509 trace_end = int(args.trace_end),
510 trace_fst = 0)
511 os.chdir("../")
512
513 if __name__ == "__main__":
514 main()