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