sigh sorting out litex pin-connections to sdram
[soc.git] / src / soc / litex / florent / ls180soc.py
1 #!/usr/bin/env python3
2
3 import os
4 import argparse
5 from functools import reduce
6 from operator import or_
7
8 from migen import (Signal, FSM, If, Display, Finish, NextValue, NextState,
9 Cat, Record, ClockSignal, wrap, ResetInserter)
10
11 from litex.build.generic_platform import Pins, Subsignal
12 from litex.build.sim import SimPlatform
13 from litex.build.io import CRG
14 from litex.build.sim.config import SimConfig
15
16 from litex.soc.integration.soc import SoCRegion
17 from litex.soc.integration.soc_core import SoCCore
18 from litex.soc.integration.soc_sdram import SoCSDRAM
19 from litex.soc.integration.builder import Builder
20 from litex.soc.integration.common import get_mem_data
21
22 from litedram import modules as litedram_modules
23 from litedram.phy.model import SDRAMPHYModel
24 #from litedram.phy.gensdrphy import GENSDRPHY, HalfRateGENSDRPHY
25 from litedram.common import PHYPadsCombiner, PhySettings
26 from litedram.phy.dfi import Interface as DFIInterface
27 from litex.soc.cores.spi import SPIMaster
28 from litex.soc.cores.pwm import PWM
29 #from litex.soc.cores.bitbang import I2CMaster
30 from litex.soc.cores import uart
31
32 from litex.tools.litex_sim import sdram_module_nphases, get_sdram_phy_settings
33
34 from litex.tools.litex_sim import Platform
35 from libresoc.ls180 import LS180Platform
36
37 from migen import Module
38 from litex.soc.interconnect.csr import AutoCSR
39
40 from libresoc import LibreSoC
41 from microwatt import Microwatt
42
43 # HACK!
44 from litex.soc.integration.soc import SoCCSRHandler
45 SoCCSRHandler.supported_address_width.append(12)
46
47 # GPIO Tristate -------------------------------------------------------
48 # doesn't work properly.
49 #from litex.soc.cores.gpio import GPIOTristate
50 from litex.soc.interconnect.csr import CSRStorage, CSRStatus, CSRField
51 from migen.genlib.cdc import MultiReg
52
53 # Imports
54 from litex.soc.interconnect import wishbone
55 from litesdcard.phy import (SDPHY, SDPHYClocker,
56 SDPHYInit, SDPHYCMDW, SDPHYCMDR,
57 SDPHYDATAW, SDPHYDATAR,
58 _sdpads_layout)
59 from litesdcard.core import SDCore
60 from litesdcard.frontend.dma import SDBlock2MemDMA, SDMem2BlockDMA
61 from litex.build.io import SDROutput, SDRInput
62
63
64 # I2C Master Bit-Banging --------------------------------------------------
65
66 class I2CMaster(Module, AutoCSR):
67 """I2C Master Bit-Banging
68
69 Provides the minimal hardware to do software I2C Master bit banging.
70
71 On the same write CSRStorage (_w), software can control SCL (I2C_SCL),
72 SDA direction and value (I2C_OE, I2C_W). Software get back SDA value
73 with the read CSRStatus (_r).
74 """
75 pads_layout = [("scl", 1), ("sda", 1)]
76 def __init__(self, pads):
77 self.pads = pads
78 self._w = CSRStorage(fields=[
79 CSRField("scl", size=1, offset=0),
80 CSRField("oe", size=1, offset=1),
81 CSRField("sda", size=1, offset=2)],
82 name="w")
83 self._r = CSRStatus(fields=[
84 CSRField("sda", size=1, offset=0)],
85 name="r")
86
87 self.connect(pads)
88
89 def connect(self, pads):
90 _sda_w = Signal()
91 _sda_oe = Signal()
92 _sda_r = Signal()
93 self.comb += [
94 pads.scl.eq(self._w.fields.scl),
95 pads.sda_oe.eq( self._w.fields.oe),
96 pads.sda_o.eq( self._w.fields.sda),
97 self._r.fields.sda.eq(pads.sda_i),
98 ]
99
100
101 class GPIOTristateASIC(Module, AutoCSR):
102 def __init__(self, pads):
103 nbits = len(pads.oe) # hack
104 self._oe = CSRStorage(nbits, description="GPIO Tristate(s) Control.")
105 self._in = CSRStatus(nbits, description="GPIO Input(s) Status.")
106 self._out = CSRStorage(nbits, description="GPIO Ouptut(s) Control.")
107
108 # # #
109
110 _pads = Record( (("i", nbits),
111 ("o", nbits),
112 ("oe", nbits)))
113 self.comb += _pads.i.eq(pads.i)
114 self.comb += pads.o.eq(_pads.o)
115 self.comb += pads.oe.eq(_pads.oe)
116
117 self.comb += _pads.oe.eq(self._oe.storage)
118 self.comb += _pads.o.eq(self._out.storage)
119 for i in range(nbits):
120 self.specials += MultiReg(_pads.i[i], self._in.status[i])
121
122 # SDCard PHY IO -------------------------------------------------------
123
124 class SDRPad(Module):
125 def __init__(self, pad, name, o, oe, i):
126 clk = ClockSignal()
127 _o = getattr(pad, "%s_o" % name)
128 _oe = getattr(pad, "%s_oe" % name)
129 _i = getattr(pad, "%s_i" % name)
130 self.specials += SDROutput(clk=clk, i=oe, o=_oe)
131 for j in range(len(_o)):
132 self.specials += SDROutput(clk=clk, i=o[j], o=_o[j])
133 self.specials += SDRInput(clk=clk, i=_i[j], o=i[j])
134
135
136 class SDPHYIOGen(Module):
137 def __init__(self, clocker, sdpads, pads):
138 # Rst
139 if hasattr(pads, "rst"):
140 self.comb += pads.rst.eq(0)
141
142 # Clk
143 self.specials += SDROutput(
144 clk = ClockSignal(),
145 i = ~clocker.clk & sdpads.clk,
146 o = pads.clk
147 )
148
149 # Cmd
150 c = sdpads.cmd
151 self.submodules.sd_cmd = SDRPad(pads, "cmd", c.o, c.oe, c.i)
152
153 # Data
154 d = sdpads.data
155 self.submodules.sd_data = SDRPad(pads, "data", d.o, d.oe, d.i)
156
157
158 class SDPHY(Module, AutoCSR):
159 def __init__(self, pads, device, sys_clk_freq,
160 cmd_timeout=10e-3, data_timeout=10e-3):
161 self.card_detect = CSRStatus() # Assume SDCard is present if no cd pin.
162 self.comb += self.card_detect.status.eq(getattr(pads, "cd", 0))
163
164 self.submodules.clocker = clocker = SDPHYClocker()
165 self.submodules.init = init = SDPHYInit()
166 self.submodules.cmdw = cmdw = SDPHYCMDW()
167 self.submodules.cmdr = cmdr = SDPHYCMDR(sys_clk_freq,
168 cmd_timeout, cmdw)
169 self.submodules.dataw = dataw = SDPHYDATAW()
170 self.submodules.datar = datar = SDPHYDATAR(sys_clk_freq,
171 data_timeout)
172
173 # # #
174
175 self.sdpads = sdpads = Record(_sdpads_layout)
176
177 # IOs
178 sdphy_cls = SDPHYIOGen
179 self.submodules.io = sdphy_cls(clocker, sdpads, pads)
180
181 # Connect pads_out of submodules to physical pads --------------
182 pl = [init, cmdw, cmdr, dataw, datar]
183 self.comb += [
184 sdpads.clk.eq( reduce(or_, [m.pads_out.clk for m in pl])),
185 sdpads.cmd.oe.eq( reduce(or_, [m.pads_out.cmd.oe for m in pl])),
186 sdpads.cmd.o.eq( reduce(or_, [m.pads_out.cmd.o for m in pl])),
187 sdpads.data.oe.eq(reduce(or_, [m.pads_out.data.oe for m in pl])),
188 sdpads.data.o.eq( reduce(or_, [m.pads_out.data.o for m in pl])),
189 ]
190 for m in pl:
191 self.comb += m.pads_out.ready.eq(self.clocker.ce)
192
193 # Connect physical pads to pads_in of submodules ---------------
194 for m in pl:
195 self.comb += m.pads_in.valid.eq(self.clocker.ce)
196 self.comb += m.pads_in.cmd.i.eq(sdpads.cmd.i)
197 self.comb += m.pads_in.data.i.eq(sdpads.data.i)
198
199 # Speed Throttling -------------------------------------------
200 self.comb += clocker.stop.eq(dataw.stop | datar.stop)
201
202
203 # Generic SDR PHY ---------------------------------------------------------
204
205 class GENSDRPHY(Module):
206 def __init__(self, pads, cl=2, cmd_latency=1):
207 pads = PHYPadsCombiner(pads)
208 addressbits = len(pads.a)
209 bankbits = len(pads.ba)
210 nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
211 databits = len(pads.dq_i)
212 assert cl in [2, 3]
213 assert databits%8 == 0
214
215 # PHY settings ----------------------------------------------------
216 self.settings = PhySettings(
217 phytype = "GENSDRPHY",
218 memtype = "SDR",
219 databits = databits,
220 dfi_databits = databits,
221 nranks = nranks,
222 nphases = 1,
223 rdphase = 0,
224 wrphase = 0,
225 rdcmdphase = 0,
226 wrcmdphase = 0,
227 cl = cl,
228 read_latency = cl + cmd_latency,
229 write_latency = 0
230 )
231
232 # DFI Interface ---------------------------------------------------
233 self.dfi = dfi = DFIInterface(addressbits, bankbits, nranks, databits)
234
235 # # #
236
237 # Iterate on pads groups ------------------------------------------
238 for pads_group in range(len(pads.groups)):
239 pads.sel_group(pads_group)
240
241 # Addresses and Commands --------------------------------------
242 p0 = dfi.p0
243 self.specials += [SDROutput(i=p0.address[i], o=pads.a[i])
244 for i in range(len(pads.a))]
245 self.specials += [SDROutput(i=p0.bank[i], o=pads.ba[i])
246 for i in range(len(pads.ba))]
247 self.specials += SDROutput(i=p0.cas_n, o=pads.cas_n)
248 self.specials += SDROutput(i=p0.ras_n, o=pads.ras_n)
249 self.specials += SDROutput(i=p0.we_n, o=pads.we_n)
250 if hasattr(pads, "cke"):
251 for i in range(len(pads.cke)):
252 self.specials += SDROutput(i=p0.cke[i], o=pads.cke[i])
253 if hasattr(pads, "cs_n"):
254 for i in range(len(pads.cs_n)):
255 self.specials += SDROutput(i=p0.cs_n[i], o=pads.cs_n[i])
256
257 # DQ/DM Data Path -------------------------------------------------
258
259 d = dfi.p0
260 wren = []
261 self.submodules.dq = SDRPad(pads, "dq", d.wrdata, d.wrdata_en, d.rddata)
262
263 if hasattr(pads, "dm"):
264 for i in range(len(pads.dm)):
265 self.specials += SDROutput(i=d.wrdata_mask[i], o=pads.dm[i])
266
267 # DQ/DM Control Path ----------------------------------------------
268 rddata_en = Signal(cl + cmd_latency)
269 self.sync += rddata_en.eq(Cat(dfi.p0.rddata_en, rddata_en))
270 self.sync += dfi.p0.rddata_valid.eq(rddata_en[-1])
271
272
273 # LibreSoC 180nm ASIC -------------------------------------------------------
274
275 class LibreSoCSim(SoCCore):
276 def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
277 sdram_module = "AS4C16M16",
278 #sdram_data_width = 16,
279 #sdram_module = "MT48LC16M16",
280 sdram_data_width = 16,
281 irq_reserved_irqs = {'uart': 0},
282 platform='sim',
283 ):
284 assert cpu in ["libresoc", "microwatt"]
285 sys_clk_freq = int(50e6)
286
287 if platform == 'sim':
288 platform = Platform()
289 uart_name = "sim"
290 elif platform == 'ls180':
291 platform = LS180Platform()
292 uart_name = "uart"
293
294 #cpu_data_width = 32
295 cpu_data_width = 64
296
297 variant = "ls180"
298
299 # reserve XICS ICP and XICS memory addresses.
300 self.mem_map['icp'] = 0xc0010000
301 self.mem_map['ics'] = 0xc0011000
302 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
303 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
304
305 ram_init = []
306 if False:
307 #ram_init = get_mem_data({
308 # ram_fname: "0x00000000",
309 # }, "little")
310 ram_init = get_mem_data(ram_fname, "little")
311
312 # remap the main RAM to reset-start-address
313
314 # without sram nothing works, therefore move it to higher up
315 self.mem_map["sram"] = 0x90000000
316
317 # put UART at 0xc000200 (w00t! this works!)
318 self.csr_map["uart"] = 4
319
320 self.mem_map["main_ram"] = 0x90000000
321 self.mem_map["sram"] = 0x00000000
322
323 # SoCCore -------------------------------------------------------------
324 SoCCore.__init__(self, platform, clk_freq=sys_clk_freq,
325 cpu_type = "microwatt",
326 cpu_cls = LibreSoC if cpu == "libresoc" \
327 else Microwatt,
328 #bus_data_width = 64,
329 csr_address_width = 14, # limit to 0x8000
330 cpu_variant = variant,
331 csr_data_width = 8,
332 l2_size = 0,
333 with_uart = False,
334 uart_name = None,
335 with_sdram = with_sdram,
336 sdram_module = sdram_module,
337 sdram_data_width = sdram_data_width,
338 integrated_rom_size = 0, # if ram_fname else 0x10000,
339 integrated_sram_size = 0x200,
340 #integrated_main_ram_init = ram_init,
341 integrated_main_ram_size = 0x00000000 if with_sdram \
342 else 0x10000000 , # 256MB
343 )
344 self.platform.name = "ls180"
345
346 # SDR SDRAM ----------------------------------------------
347 if False: # not self.integrated_main_ram_size:
348 self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"))
349
350 if cpu == "libresoc":
351 # XICS interrupt devices
352 icp_addr = self.mem_map['icp']
353 icp_wb = self.cpu.xics_icp
354 icp_region = SoCRegion(origin=icp_addr, size=0x20, cached=False)
355 self.bus.add_slave(name='icp', slave=icp_wb, region=icp_region)
356
357 ics_addr = self.mem_map['ics']
358 ics_wb = self.cpu.xics_ics
359 ics_region = SoCRegion(origin=ics_addr, size=0x1000, cached=False)
360 self.bus.add_slave(name='ics', slave=ics_wb, region=ics_region)
361
362 # CRG -----------------------------------------------------------------
363 self.submodules.crg = CRG(platform.request("sys_clk"),
364 platform.request("sys_rst"))
365
366 # PLL/Clock Select
367 clksel_i = platform.request("sys_clksel_i")
368 pll48_o = platform.request("sys_pll_48_o")
369
370 self.comb += self.cpu.clk_sel.eq(clksel_i) # allow clock src select
371 self.comb += pll48_o.eq(self.cpu.pll_48_o) # "test feed" from the PLL
372
373 #ram_init = []
374
375 if False:
376 # for niolib temporary hack
377 io_in = Signal()
378 io_out = Signal()
379
380 self.comb += io_in.eq(self.cpu.io_in)
381 self.comb += io_out.eq(self.cpu.io_out)
382
383 # SDRAM ----------------------------------------------------
384 if with_sdram:
385 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
386 sdram_module_cls = getattr(litedram_modules, sdram_module)
387 sdram_rate = "1:{}".format(
388 sdram_module_nphases[sdram_module_cls.memtype])
389 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
390 phy_settings = get_sdram_phy_settings(
391 memtype = sdram_module.memtype,
392 data_width = sdram_data_width,
393 clk_freq = sdram_clk_freq)
394 #sdrphy_cls = HalfRateGENSDRPHY
395 sdrphy_cls = GENSDRPHY
396 sdram_pads = self.cpu.cpupads['sdr']
397 self.submodules.sdrphy = sdrphy_cls(sdram_pads)
398 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
399 # phy_settings,
400 # init=ram_init
401 # )
402 self.add_sdram("sdram",
403 phy = self.sdrphy,
404 module = sdram_module,
405 origin = self.mem_map["main_ram"],
406 size = 0x80000000,
407 l2_cache_size = 0, # 8192
408 l2_cache_min_data_width = 128,
409 l2_cache_reverse = True
410 )
411 # FIXME: skip memtest to avoid corrupting memory
412 self.add_constant("MEMTEST_BUS_SIZE", 128//16)
413 self.add_constant("MEMTEST_DATA_SIZE", 128//16)
414 self.add_constant("MEMTEST_ADDR_SIZE", 128//16)
415 self.add_constant("MEMTEST_BUS_DEBUG", 1)
416 self.add_constant("MEMTEST_ADDR_DEBUG", 1)
417 self.add_constant("MEMTEST_DATA_DEBUG", 1)
418
419 # SDRAM clock
420 sys_clk = ClockSignal()
421 sdr_clk = self.cpu.cpupads['sdram_clock']
422 #self.specials += DDROutput(1, 0, , sdram_clk)
423 self.specials += SDROutput(clk=sys_clk, i=sys_clk, o=sdr_clk)
424
425 # UART
426 uart_core_pads = self.cpu.cpupads['uart']
427 self.submodules.uart_phy = uart.UARTPHY(
428 pads = uart_core_pads,
429 clk_freq = self.sys_clk_freq,
430 baudrate = 115200)
431 self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
432 tx_fifo_depth = 16,
433 rx_fifo_depth = 16))
434
435 self.csr.add("uart_phy", use_loc_if_exists=True)
436 self.csr.add("uart", use_loc_if_exists=True)
437 self.irq.add("uart", use_loc_if_exists=True)
438
439 # GPIOs (bi-directional)
440 gpio_core_pads = self.cpu.cpupads['gpio']
441 self.submodules.gpio = GPIOTristateASIC(gpio_core_pads)
442 self.add_csr("gpio")
443
444 # SPI Master
445 print ("cpupadkeys", self.cpu.cpupads.keys())
446 self.submodules.spimaster = SPIMaster(
447 pads = self.cpu.cpupads['mspi1'],
448 data_width = 8,
449 sys_clk_freq = sys_clk_freq,
450 spi_clk_freq = 8e6,
451 )
452 self.add_csr("spimaster")
453
454 # SPI SDCard (1 wide)
455 spi_clk_freq = 400e3
456 pads = self.cpu.cpupads['mspi0']
457 spisdcard = SPIMaster(pads, 8, self.sys_clk_freq, spi_clk_freq)
458 spisdcard.add_clk_divider()
459 setattr(self.submodules, 'spisdcard', spisdcard)
460 self.add_csr('spisdcard')
461
462 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
463 eintpads = self.cpu.cpupads['eint']
464 print ("eintpads", eintpads)
465 self.comb += self.cpu.interrupt[12:16].eq(eintpads)
466
467 # JTAG
468 jtagpads = platform.request("jtag")
469 self.comb += self.cpu.jtag_tck.eq(jtagpads.tck)
470 self.comb += self.cpu.jtag_tms.eq(jtagpads.tms)
471 self.comb += self.cpu.jtag_tdi.eq(jtagpads.tdi)
472 self.comb += jtagpads.tdo.eq(self.cpu.jtag_tdo)
473
474 # NC - allows some iopads to be connected up
475 # sigh, just do something, anything, to stop yosys optimising these out
476 nc_pads = platform.request("nc")
477 num_nc = len(nc_pads)
478 self.nc = Signal(num_nc)
479 self.comb += self.nc.eq(nc_pads)
480 self.dummy = Signal(num_nc)
481 for i in range(num_nc):
482 self.sync += self.dummy[i].eq(self.nc[i] | self.cpu.interrupt[0])
483
484 # PWM
485 pwmpads = self.cpu.cpupads['pwm']
486 for i in range(2):
487 name = "pwm%d" % i
488 setattr(self.submodules, name, PWM(pwmpads[i]))
489 self.add_csr(name)
490
491 # I2C Master
492 i2c_core_pads = self.cpu.cpupads['mtwi']
493 self.submodules.i2c = I2CMaster(i2c_core_pads)
494 self.add_csr("i2c")
495
496 # SDCard -----------------------------------------------------
497
498 # Emulator / Pads
499 sdcard_pads = self.cpu.cpupads['sd0']
500
501 # Core
502 self.submodules.sdphy = SDPHY(sdcard_pads,
503 self.platform.device, self.clk_freq)
504 self.submodules.sdcore = SDCore(self.sdphy)
505 self.add_csr("sdphy")
506 self.add_csr("sdcore")
507
508 # Block2Mem DMA
509 bus = wishbone.Interface(data_width=self.bus.data_width,
510 adr_width=self.bus.address_width)
511 self.submodules.sdblock2mem = SDBlock2MemDMA(bus=bus,
512 endianness=self.cpu.endianness)
513 self.comb += self.sdcore.source.connect(self.sdblock2mem.sink)
514 dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus
515 dma_bus.add_master("sdblock2mem", master=bus)
516 self.add_csr("sdblock2mem")
517
518 # Mem2Block DMA
519 bus = wishbone.Interface(data_width=self.bus.data_width,
520 adr_width=self.bus.address_width)
521 self.submodules.sdmem2block = SDMem2BlockDMA(bus=bus,
522 endianness=self.cpu.endianness)
523 self.comb += self.sdmem2block.source.connect(self.sdcore.sink)
524 dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus
525 dma_bus.add_master("sdmem2block", master=bus)
526 self.add_csr("sdmem2block")
527
528 # Debug ---------------------------------------------------------------
529 if not debug:
530 return
531
532 jtag_en = ('jtag' in variant) or variant == 'ls180'
533
534 # setup running of DMI FSM
535 dmi_addr = Signal(4)
536 dmi_din = Signal(64)
537 dmi_dout = Signal(64)
538 dmi_wen = Signal(1)
539 dmi_req = Signal(1)
540
541 # debug log out
542 dbg_addr = Signal(4)
543 dbg_dout = Signal(64)
544 dbg_msg = Signal(1)
545
546 # capture pc from dmi
547 pc = Signal(64)
548 active_dbg = Signal()
549 active_dbg_cr = Signal()
550 active_dbg_xer = Signal()
551
552 # xer flags
553 xer_so = Signal()
554 xer_ca = Signal()
555 xer_ca32 = Signal()
556 xer_ov = Signal()
557 xer_ov32 = Signal()
558
559 # increment counter, Stop after 100000 cycles
560 uptime = Signal(64)
561 self.sync += uptime.eq(uptime + 1)
562 #self.sync += If(uptime == 1000000000000, Finish())
563
564 # DMI FSM counter and FSM itself
565 dmicount = Signal(10)
566 dmirunning = Signal(1)
567 dmi_monitor = Signal(1)
568 dmifsm = FSM()
569 self.submodules += dmifsm
570
571 # DMI FSM
572 dmifsm.act("START",
573 If(dmi_req & dmi_wen,
574 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
575 self.cpu.dmi_din.eq(dmi_din), # DMI in
576 self.cpu.dmi_req.eq(1), # DMI request
577 self.cpu.dmi_wr.eq(1), # DMI write
578 If(self.cpu.dmi_ack,
579 (NextState("IDLE"),
580 )
581 ),
582 ),
583 ),
584 If(dmi_req & ~dmi_wen,
585 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
586 self.cpu.dmi_req.eq(1), # DMI request
587 self.cpu.dmi_wr.eq(0), # DMI read
588 If(self.cpu.dmi_ack,
589 # acknowledge received: capture data.
590 (NextState("IDLE"),
591 NextValue(dbg_addr, dmi_addr),
592 NextValue(dbg_dout, self.cpu.dmi_dout),
593 NextValue(dbg_msg, 1),
594 ),
595 ),
596 ),
597 )
598 )
599
600 # DMI response received: reset the dmi request and check if
601 # in "monitor" mode
602 dmifsm.act("IDLE",
603 If(dmi_monitor,
604 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
605 ).Else(
606 NextState("START"), # back to start on next cycle
607 ),
608 NextValue(dmi_req, 0),
609 NextValue(dmi_addr, 0),
610 NextValue(dmi_din, 0),
611 NextValue(dmi_wen, 0),
612 )
613
614 # "monitor" mode fires off a STAT request
615 dmifsm.act("FIRE_MONITOR",
616 (NextValue(dmi_req, 1),
617 NextValue(dmi_addr, 1), # DMI STAT address
618 NextValue(dmi_din, 0),
619 NextValue(dmi_wen, 0), # read STAT
620 NextState("START"), # back to start on next cycle
621 )
622 )
623
624 self.comb += xer_so.eq((dbg_dout & 1) == 1)
625 self.comb += xer_ca.eq((dbg_dout & 4) == 4)
626 self.comb += xer_ca32.eq((dbg_dout & 8) == 8)
627 self.comb += xer_ov.eq((dbg_dout & 16) == 16)
628 self.comb += xer_ov32.eq((dbg_dout & 32) == 32)
629
630 # debug messages out
631 self.sync += If(dbg_msg,
632 (If(active_dbg & (dbg_addr == 0b10), # PC
633 Display("pc : %016x", dbg_dout),
634 ),
635 If(dbg_addr == 0b10, # PC
636 pc.eq(dbg_dout), # capture PC
637 ),
638 #If(dbg_addr == 0b11, # MSR
639 # Display(" msr: %016x", dbg_dout),
640 #),
641 If(dbg_addr == 0b1000, # CR
642 Display(" cr : %016x", dbg_dout),
643 ),
644 If(dbg_addr == 0b1001, # XER
645 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
646 xer_so, xer_ca, xer_ca32, xer_ov, xer_ov32),
647 ),
648 If(dbg_addr == 0b101, # GPR
649 Display(" gpr: %016x", dbg_dout),
650 ),
651 # also check if this is a "stat"
652 If(dbg_addr == 1, # requested a STAT
653 #Display(" stat: %x", dbg_dout),
654 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
655 dmirunning.eq(1), # continue running
656 dmi_monitor.eq(0), # and stop monitor mode
657 ),
658 ),
659 dbg_msg.eq(0)
660 )
661 )
662
663 # kick off a "stop"
664 self.sync += If(uptime == 0,
665 (dmi_addr.eq(0), # CTRL
666 dmi_din.eq(1<<0), # STOP
667 dmi_req.eq(1),
668 dmi_wen.eq(1),
669 )
670 )
671
672 self.sync += If(uptime == 4,
673 dmirunning.eq(1),
674 )
675
676 self.sync += If(dmirunning,
677 dmicount.eq(dmicount + 1),
678 )
679
680 # loop every 1<<N cycles
681 cyclewid = 9
682
683 # get the PC
684 self.sync += If(dmicount == 4,
685 (dmi_addr.eq(0b10), # NIA
686 dmi_req.eq(1),
687 dmi_wen.eq(0),
688 )
689 )
690
691 # kick off a "step"
692 self.sync += If(dmicount == 8,
693 (dmi_addr.eq(0), # CTRL
694 dmi_din.eq(1<<3), # STEP
695 dmi_req.eq(1),
696 dmi_wen.eq(1),
697 dmirunning.eq(0), # stop counter, need to fire "monitor"
698 dmi_monitor.eq(1), # start "monitor" instead
699 )
700 )
701
702 # limit range of pc for debug reporting
703 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
704 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
705 self.comb += active_dbg.eq(1)
706
707
708 # get the MSR
709 self.sync += If(active_dbg & (dmicount == 12),
710 (dmi_addr.eq(0b11), # MSR
711 dmi_req.eq(1),
712 dmi_wen.eq(0),
713 )
714 )
715
716 if cpu == "libresoc":
717 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
718 self.comb += active_dbg_cr.eq(0)
719
720 # get the CR
721 self.sync += If(active_dbg_cr & (dmicount == 16),
722 (dmi_addr.eq(0b1000), # CR
723 dmi_req.eq(1),
724 dmi_wen.eq(0),
725 )
726 )
727
728 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
729 self.comb += active_dbg_xer.eq(active_dbg_cr)
730
731 # get the CR
732 self.sync += If(active_dbg_xer & (dmicount == 20),
733 (dmi_addr.eq(0b1001), # XER
734 dmi_req.eq(1),
735 dmi_wen.eq(0),
736 )
737 )
738
739 # read all 32 GPRs
740 for i in range(32):
741 self.sync += If(active_dbg & (dmicount == 24+(i*8)),
742 (dmi_addr.eq(0b100), # GSPR addr
743 dmi_din.eq(i), # r1
744 dmi_req.eq(1),
745 dmi_wen.eq(1),
746 )
747 )
748
749 self.sync += If(active_dbg & (dmicount == 28+(i*8)),
750 (dmi_addr.eq(0b101), # GSPR data
751 dmi_req.eq(1),
752 dmi_wen.eq(0),
753 )
754 )
755
756 # monitor bbus read/write
757 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
758 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
759 #uptime,
760 0,
761 self.cpu.dbus.adr,
762 self.cpu.dbus.we,
763 self.cpu.dbus.sel,
764 self.cpu.dbus.dat_w,
765 self.cpu.dbus.dat_r
766 )
767 )
768
769 return
770
771 # monitor ibus write
772 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
773 self.cpu.ibus.we,
774 Display(" [%06x] iadr: %8x, s %01x w %016x",
775 #uptime,
776 0,
777 self.cpu.ibus.adr,
778 self.cpu.ibus.sel,
779 self.cpu.ibus.dat_w,
780 )
781 )
782 # monitor ibus read
783 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
784 ~self.cpu.ibus.we,
785 Display(" [%06x] iadr: %8x, s %01x r %016x",
786 #uptime,
787 0,
788 self.cpu.ibus.adr,
789 self.cpu.ibus.sel,
790 self.cpu.ibus.dat_r
791 )
792 )
793
794 # Build -----------------------------------------------------------------------
795
796 def main():
797 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
798 parser.add_argument("--cpu", default="libresoc",
799 help="CPU to use: libresoc (default) or microwatt")
800 parser.add_argument("--platform", default="sim",
801 help="platform (sim or ls180)")
802 parser.add_argument("--debug", action="store_true",
803 help="Enable debug traces")
804 parser.add_argument("--trace", action="store_true",
805 help="Enable tracing")
806 parser.add_argument("--trace-start", default=0,
807 help="Cycle to start FST tracing")
808 parser.add_argument("--trace-end", default=-1,
809 help="Cycle to end FST tracing")
810 parser.add_argument("--build", action="store_true", help="Build bitstream")
811 args = parser.parse_args()
812
813
814 if args.platform == 'ls180':
815 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
816 platform=args.platform)
817 builder = Builder(soc, compile_gateware = True)
818 builder.build(run = True)
819 os.chdir("../")
820 else:
821
822 sim_config = SimConfig(default_clk="sys_clk")
823 sim_config.add_module("serial2console", "serial")
824
825 for i in range(2):
826 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
827 platform=args.platform)
828 builder = Builder(soc, compile_gateware = i!=0)
829 builder.build(sim_config=sim_config,
830 run = i!=0,
831 trace = args.trace,
832 trace_start = int(args.trace_start),
833 trace_end = int(args.trace_end),
834 trace_fst = 0)
835 os.chdir("../")
836
837 if __name__ == "__main__":
838 main()