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