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