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