add (disabled) tri-state GPIO
[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
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 if False:
193 self.submodules.gpio = GPIOTristate(platform.request("gpio"))
194 self.add_csr("gpio")
195
196 # SPI Master
197 self.submodules.spi_master = SPIMaster(
198 pads = platform.request("spi_master"),
199 data_width = 8,
200 sys_clk_freq = sys_clk_freq,
201 spi_clk_freq = 8e6,
202 )
203 self.add_csr("spi_master")
204
205 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
206 self.comb += self.cpu.interrupt[12:16].eq(platform.request("eint"))
207
208 # Debug ---------------------------------------------------------------
209 if not debug:
210 return
211
212 # setup running of DMI FSM
213 dmi_addr = Signal(4)
214 dmi_din = Signal(64)
215 dmi_dout = Signal(64)
216 dmi_wen = Signal(1)
217 dmi_req = Signal(1)
218
219 # debug log out
220 dbg_addr = Signal(4)
221 dbg_dout = Signal(64)
222 dbg_msg = Signal(1)
223
224 # capture pc from dmi
225 pc = Signal(64)
226 active_dbg = Signal()
227 active_dbg_cr = Signal()
228 active_dbg_xer = Signal()
229
230 # xer flags
231 xer_so = Signal()
232 xer_ca = Signal()
233 xer_ca32 = Signal()
234 xer_ov = Signal()
235 xer_ov32 = Signal()
236
237 # increment counter, Stop after 100000 cycles
238 uptime = Signal(64)
239 self.sync += uptime.eq(uptime + 1)
240 #self.sync += If(uptime == 1000000000000, Finish())
241
242 # DMI FSM counter and FSM itself
243 dmicount = Signal(10)
244 dmirunning = Signal(1)
245 dmi_monitor = Signal(1)
246 dmifsm = FSM()
247 self.submodules += dmifsm
248
249 # DMI FSM
250 dmifsm.act("START",
251 If(dmi_req & dmi_wen,
252 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
253 self.cpu.dmi_din.eq(dmi_din), # DMI in
254 self.cpu.dmi_req.eq(1), # DMI request
255 self.cpu.dmi_wr.eq(1), # DMI write
256 If(self.cpu.dmi_ack,
257 (NextState("IDLE"),
258 )
259 ),
260 ),
261 ),
262 If(dmi_req & ~dmi_wen,
263 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
264 self.cpu.dmi_req.eq(1), # DMI request
265 self.cpu.dmi_wr.eq(0), # DMI read
266 If(self.cpu.dmi_ack,
267 # acknowledge received: capture data.
268 (NextState("IDLE"),
269 NextValue(dbg_addr, dmi_addr),
270 NextValue(dbg_dout, self.cpu.dmi_dout),
271 NextValue(dbg_msg, 1),
272 ),
273 ),
274 ),
275 )
276 )
277
278 # DMI response received: reset the dmi request and check if
279 # in "monitor" mode
280 dmifsm.act("IDLE",
281 If(dmi_monitor,
282 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
283 ).Else(
284 NextState("START"), # back to start on next cycle
285 ),
286 NextValue(dmi_req, 0),
287 NextValue(dmi_addr, 0),
288 NextValue(dmi_din, 0),
289 NextValue(dmi_wen, 0),
290 )
291
292 # "monitor" mode fires off a STAT request
293 dmifsm.act("FIRE_MONITOR",
294 (NextValue(dmi_req, 1),
295 NextValue(dmi_addr, 1), # DMI STAT address
296 NextValue(dmi_din, 0),
297 NextValue(dmi_wen, 0), # read STAT
298 NextState("START"), # back to start on next cycle
299 )
300 )
301
302 self.comb += xer_so.eq((dbg_dout & 1) == 1)
303 self.comb += xer_ca.eq((dbg_dout & 4) == 4)
304 self.comb += xer_ca32.eq((dbg_dout & 8) == 8)
305 self.comb += xer_ov.eq((dbg_dout & 16) == 16)
306 self.comb += xer_ov32.eq((dbg_dout & 32) == 32)
307
308 # debug messages out
309 self.sync += If(dbg_msg,
310 (If(active_dbg & (dbg_addr == 0b10), # PC
311 Display("pc : %016x", dbg_dout),
312 ),
313 If(dbg_addr == 0b10, # PC
314 pc.eq(dbg_dout), # capture PC
315 ),
316 #If(dbg_addr == 0b11, # MSR
317 # Display(" msr: %016x", dbg_dout),
318 #),
319 If(dbg_addr == 0b1000, # CR
320 Display(" cr : %016x", dbg_dout),
321 ),
322 If(dbg_addr == 0b1001, # XER
323 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
324 xer_so, xer_ca, xer_ca32, xer_ov, xer_ov32),
325 ),
326 If(dbg_addr == 0b101, # GPR
327 Display(" gpr: %016x", dbg_dout),
328 ),
329 # also check if this is a "stat"
330 If(dbg_addr == 1, # requested a STAT
331 #Display(" stat: %x", dbg_dout),
332 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
333 dmirunning.eq(1), # continue running
334 dmi_monitor.eq(0), # and stop monitor mode
335 ),
336 ),
337 dbg_msg.eq(0)
338 )
339 )
340
341 # kick off a "stop"
342 self.sync += If(uptime == 0,
343 (dmi_addr.eq(0), # CTRL
344 dmi_din.eq(1<<0), # STOP
345 dmi_req.eq(1),
346 dmi_wen.eq(1),
347 )
348 )
349
350 self.sync += If(uptime == 4,
351 dmirunning.eq(1),
352 )
353
354 self.sync += If(dmirunning,
355 dmicount.eq(dmicount + 1),
356 )
357
358 # loop every 1<<N cycles
359 cyclewid = 9
360
361 # get the PC
362 self.sync += If(dmicount == 4,
363 (dmi_addr.eq(0b10), # NIA
364 dmi_req.eq(1),
365 dmi_wen.eq(0),
366 )
367 )
368
369 # kick off a "step"
370 self.sync += If(dmicount == 8,
371 (dmi_addr.eq(0), # CTRL
372 dmi_din.eq(1<<3), # STEP
373 dmi_req.eq(1),
374 dmi_wen.eq(1),
375 dmirunning.eq(0), # stop counter, need to fire "monitor"
376 dmi_monitor.eq(1), # start "monitor" instead
377 )
378 )
379
380 # limit range of pc for debug reporting
381 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
382 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
383 self.comb += active_dbg.eq(1)
384
385
386 # get the MSR
387 self.sync += If(active_dbg & (dmicount == 12),
388 (dmi_addr.eq(0b11), # MSR
389 dmi_req.eq(1),
390 dmi_wen.eq(0),
391 )
392 )
393
394 if cpu == "libresoc":
395 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
396 self.comb += active_dbg_cr.eq(0)
397
398 # get the CR
399 self.sync += If(active_dbg_cr & (dmicount == 16),
400 (dmi_addr.eq(0b1000), # CR
401 dmi_req.eq(1),
402 dmi_wen.eq(0),
403 )
404 )
405
406 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
407 self.comb += active_dbg_xer.eq(active_dbg_cr)
408
409 # get the CR
410 self.sync += If(active_dbg_xer & (dmicount == 20),
411 (dmi_addr.eq(0b1001), # XER
412 dmi_req.eq(1),
413 dmi_wen.eq(0),
414 )
415 )
416
417 # read all 32 GPRs
418 for i in range(32):
419 self.sync += If(active_dbg & (dmicount == 24+(i*8)),
420 (dmi_addr.eq(0b100), # GSPR addr
421 dmi_din.eq(i), # r1
422 dmi_req.eq(1),
423 dmi_wen.eq(1),
424 )
425 )
426
427 self.sync += If(active_dbg & (dmicount == 28+(i*8)),
428 (dmi_addr.eq(0b101), # GSPR data
429 dmi_req.eq(1),
430 dmi_wen.eq(0),
431 )
432 )
433
434 # monitor bbus read/write
435 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
436 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
437 #uptime,
438 0,
439 self.cpu.dbus.adr,
440 self.cpu.dbus.we,
441 self.cpu.dbus.sel,
442 self.cpu.dbus.dat_w,
443 self.cpu.dbus.dat_r
444 )
445 )
446
447 return
448
449 # monitor ibus write
450 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
451 self.cpu.ibus.we,
452 Display(" [%06x] iadr: %8x, s %01x w %016x",
453 #uptime,
454 0,
455 self.cpu.ibus.adr,
456 self.cpu.ibus.sel,
457 self.cpu.ibus.dat_w,
458 )
459 )
460 # monitor ibus read
461 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
462 ~self.cpu.ibus.we,
463 Display(" [%06x] iadr: %8x, s %01x r %016x",
464 #uptime,
465 0,
466 self.cpu.ibus.adr,
467 self.cpu.ibus.sel,
468 self.cpu.ibus.dat_r
469 )
470 )
471
472 # Build -----------------------------------------------------------------------
473
474 def main():
475 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
476 parser.add_argument("--cpu", default="libresoc",
477 help="CPU to use: libresoc (default) or microwatt")
478 parser.add_argument("--platform", default="sim",
479 help="platform (sim or ls180)")
480 parser.add_argument("--debug", action="store_true",
481 help="Enable debug traces")
482 parser.add_argument("--trace", action="store_true",
483 help="Enable tracing")
484 parser.add_argument("--trace-start", default=0,
485 help="Cycle to start FST tracing")
486 parser.add_argument("--trace-end", default=-1,
487 help="Cycle to end FST tracing")
488 parser.add_argument("--build", action="store_true", help="Build bitstream")
489 args = parser.parse_args()
490
491
492 if args.platform == 'ls180':
493 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
494 platform=args.platform)
495 soc.add_sdcard()
496 soc.add_spi_sdcard()
497 builder = Builder(soc, compile_gateware = True)
498 builder.build(run = True)
499 os.chdir("../")
500 else:
501
502 sim_config = SimConfig(default_clk="sys_clk")
503 sim_config.add_module("serial2console", "serial")
504
505 for i in range(2):
506 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
507 platform=args.platform)
508 builder = Builder(soc, compile_gateware = i!=0)
509 builder.build(sim_config=sim_config,
510 run = i!=0,
511 trace = args.trace,
512 trace_start = int(args.trace_start),
513 trace_end = int(args.trace_end),
514 trace_fst = 0)
515 os.chdir("../")
516
517 if __name__ == "__main__":
518 main()