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