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