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