eb2afafb934520213eeb680655a0c843ecfe532a
[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 pll18_o = platform.request("sys_pll_18_o")
369 pll_lck_o = platform.request("sys_pll_lck_o")
370
371 self.comb += self.cpu.clk_sel.eq(clksel_i) # allow clock src select
372 self.comb += pll18_o.eq(self.cpu.pll_18_o) # "test feed" from the PLL
373 self.comb += pll_lck_o.eq(self.cpu.pll_lck_o) # PLL lock flag
374
375 #ram_init = []
376
377 # SDRAM ----------------------------------------------------
378 if with_sdram:
379 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
380 sdram_module_cls = getattr(litedram_modules, sdram_module)
381 sdram_rate = "1:{}".format(
382 sdram_module_nphases[sdram_module_cls.memtype])
383 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
384 phy_settings = get_sdram_phy_settings(
385 memtype = sdram_module.memtype,
386 data_width = sdram_data_width,
387 clk_freq = sdram_clk_freq)
388 #sdrphy_cls = HalfRateGENSDRPHY
389 sdrphy_cls = GENSDRPHY
390 sdram_pads = self.cpu.cpupads['sdr']
391 self.submodules.sdrphy = sdrphy_cls(sdram_pads)
392 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
393 # phy_settings,
394 # init=ram_init
395 # )
396 self.add_sdram("sdram",
397 phy = self.sdrphy,
398 module = sdram_module,
399 origin = self.mem_map["main_ram"],
400 size = 0x80000000,
401 l2_cache_size = 0, # 8192
402 l2_cache_min_data_width = 128,
403 l2_cache_reverse = True
404 )
405 # FIXME: skip memtest to avoid corrupting memory
406 self.add_constant("MEMTEST_BUS_SIZE", 128//16)
407 self.add_constant("MEMTEST_DATA_SIZE", 128//16)
408 self.add_constant("MEMTEST_ADDR_SIZE", 128//16)
409 self.add_constant("MEMTEST_BUS_DEBUG", 1)
410 self.add_constant("MEMTEST_ADDR_DEBUG", 1)
411 self.add_constant("MEMTEST_DATA_DEBUG", 1)
412
413 # SDRAM clock
414 sys_clk = ClockSignal()
415 sdr_clk = self.cpu.cpupads['sdram_clock']
416 #self.specials += DDROutput(1, 0, , sdram_clk)
417 self.specials += SDROutput(clk=sys_clk, i=sys_clk, o=sdr_clk)
418
419 # UART
420 uart_core_pads = self.cpu.cpupads['uart']
421 self.submodules.uart_phy = uart.UARTPHY(
422 pads = uart_core_pads,
423 clk_freq = self.sys_clk_freq,
424 baudrate = 115200)
425 self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
426 tx_fifo_depth = 16,
427 rx_fifo_depth = 16))
428
429 self.csr.add("uart_phy", use_loc_if_exists=True)
430 self.csr.add("uart", use_loc_if_exists=True)
431 self.irq.add("uart", use_loc_if_exists=True)
432
433 # GPIOs (bi-directional)
434 gpio_core_pads = self.cpu.cpupads['gpio']
435 self.submodules.gpio = GPIOTristateASIC(gpio_core_pads)
436 self.add_csr("gpio")
437
438 # SPI Master
439 print ("cpupadkeys", self.cpu.cpupads.keys())
440 self.submodules.spimaster = SPIMaster(
441 pads = self.cpu.cpupads['mspi1'],
442 data_width = 8,
443 sys_clk_freq = sys_clk_freq,
444 spi_clk_freq = 8e6,
445 )
446 self.add_csr("spimaster")
447
448 # SPI SDCard (1 wide)
449 spi_clk_freq = 400e3
450 pads = self.cpu.cpupads['mspi0']
451 spisdcard = SPIMaster(pads, 8, self.sys_clk_freq, spi_clk_freq)
452 spisdcard.add_clk_divider()
453 setattr(self.submodules, 'spisdcard', spisdcard)
454 self.add_csr('spisdcard')
455
456 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
457 eintpads = self.cpu.cpupads['eint']
458 print ("eintpads", eintpads)
459 self.comb += self.cpu.interrupt[12:16].eq(eintpads)
460
461 # JTAG
462 jtagpads = platform.request("jtag")
463 self.comb += self.cpu.jtag_tck.eq(jtagpads.tck)
464 self.comb += self.cpu.jtag_tms.eq(jtagpads.tms)
465 self.comb += self.cpu.jtag_tdi.eq(jtagpads.tdi)
466 self.comb += jtagpads.tdo.eq(self.cpu.jtag_tdo)
467
468 # NC - allows some iopads to be connected up
469 # sigh, just do something, anything, to stop yosys optimising these out
470 nc_pads = platform.request("nc")
471 num_nc = len(nc_pads)
472 self.nc = Signal(num_nc)
473 self.comb += self.nc.eq(nc_pads)
474 self.dummy = Signal(num_nc)
475 for i in range(num_nc):
476 self.sync += self.dummy[i].eq(self.nc[i] | self.cpu.interrupt[0])
477
478 # PWM
479 pwmpads = self.cpu.cpupads['pwm']
480 for i in range(2):
481 name = "pwm%d" % i
482 setattr(self.submodules, name, PWM(pwmpads[i]))
483 self.add_csr(name)
484
485 # I2C Master
486 i2c_core_pads = self.cpu.cpupads['mtwi']
487 self.submodules.i2c = I2CMaster(i2c_core_pads)
488 self.add_csr("i2c")
489
490 # SDCard -----------------------------------------------------
491
492 # Emulator / Pads
493 sdcard_pads = self.cpu.cpupads['sd0']
494
495 # Core
496 self.submodules.sdphy = SDPHY(sdcard_pads,
497 self.platform.device, self.clk_freq)
498 self.submodules.sdcore = SDCore(self.sdphy)
499 self.add_csr("sdphy")
500 self.add_csr("sdcore")
501
502 # Block2Mem DMA
503 bus = wishbone.Interface(data_width=self.bus.data_width,
504 adr_width=self.bus.address_width)
505 self.submodules.sdblock2mem = SDBlock2MemDMA(bus=bus,
506 endianness=self.cpu.endianness)
507 self.comb += self.sdcore.source.connect(self.sdblock2mem.sink)
508 dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus
509 dma_bus.add_master("sdblock2mem", master=bus)
510 self.add_csr("sdblock2mem")
511
512 # Mem2Block DMA
513 bus = wishbone.Interface(data_width=self.bus.data_width,
514 adr_width=self.bus.address_width)
515 self.submodules.sdmem2block = SDMem2BlockDMA(bus=bus,
516 endianness=self.cpu.endianness)
517 self.comb += self.sdmem2block.source.connect(self.sdcore.sink)
518 dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus
519 dma_bus.add_master("sdmem2block", master=bus)
520 self.add_csr("sdmem2block")
521
522 # Debug ---------------------------------------------------------------
523 if not debug:
524 return
525
526 jtag_en = ('jtag' in variant) or variant == 'ls180'
527
528 # setup running of DMI FSM
529 dmi_addr = Signal(4)
530 dmi_din = Signal(64)
531 dmi_dout = Signal(64)
532 dmi_wen = Signal(1)
533 dmi_req = Signal(1)
534
535 # debug log out
536 dbg_addr = Signal(4)
537 dbg_dout = Signal(64)
538 dbg_msg = Signal(1)
539
540 # capture pc from dmi
541 pc = Signal(64)
542 active_dbg = Signal()
543 active_dbg_cr = Signal()
544 active_dbg_xer = Signal()
545
546 # xer flags
547 xer_so = Signal()
548 xer_ca = Signal()
549 xer_ca32 = Signal()
550 xer_ov = Signal()
551 xer_ov32 = Signal()
552
553 # increment counter, Stop after 100000 cycles
554 uptime = Signal(64)
555 self.sync += uptime.eq(uptime + 1)
556 #self.sync += If(uptime == 1000000000000, Finish())
557
558 # DMI FSM counter and FSM itself
559 dmicount = Signal(10)
560 dmirunning = Signal(1)
561 dmi_monitor = Signal(1)
562 dmifsm = FSM()
563 self.submodules += dmifsm
564
565 # DMI FSM
566 dmifsm.act("START",
567 If(dmi_req & dmi_wen,
568 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
569 self.cpu.dmi_din.eq(dmi_din), # DMI in
570 self.cpu.dmi_req.eq(1), # DMI request
571 self.cpu.dmi_wr.eq(1), # DMI write
572 If(self.cpu.dmi_ack,
573 (NextState("IDLE"),
574 )
575 ),
576 ),
577 ),
578 If(dmi_req & ~dmi_wen,
579 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
580 self.cpu.dmi_req.eq(1), # DMI request
581 self.cpu.dmi_wr.eq(0), # DMI read
582 If(self.cpu.dmi_ack,
583 # acknowledge received: capture data.
584 (NextState("IDLE"),
585 NextValue(dbg_addr, dmi_addr),
586 NextValue(dbg_dout, self.cpu.dmi_dout),
587 NextValue(dbg_msg, 1),
588 ),
589 ),
590 ),
591 )
592 )
593
594 # DMI response received: reset the dmi request and check if
595 # in "monitor" mode
596 dmifsm.act("IDLE",
597 If(dmi_monitor,
598 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
599 ).Else(
600 NextState("START"), # back to start on next cycle
601 ),
602 NextValue(dmi_req, 0),
603 NextValue(dmi_addr, 0),
604 NextValue(dmi_din, 0),
605 NextValue(dmi_wen, 0),
606 )
607
608 # "monitor" mode fires off a STAT request
609 dmifsm.act("FIRE_MONITOR",
610 (NextValue(dmi_req, 1),
611 NextValue(dmi_addr, 1), # DMI STAT address
612 NextValue(dmi_din, 0),
613 NextValue(dmi_wen, 0), # read STAT
614 NextState("START"), # back to start on next cycle
615 )
616 )
617
618 self.comb += xer_so.eq((dbg_dout & 1) == 1)
619 self.comb += xer_ca.eq((dbg_dout & 4) == 4)
620 self.comb += xer_ca32.eq((dbg_dout & 8) == 8)
621 self.comb += xer_ov.eq((dbg_dout & 16) == 16)
622 self.comb += xer_ov32.eq((dbg_dout & 32) == 32)
623
624 # debug messages out
625 self.sync += If(dbg_msg,
626 (If(active_dbg & (dbg_addr == 0b10), # PC
627 Display("pc : %016x", dbg_dout),
628 ),
629 If(dbg_addr == 0b10, # PC
630 pc.eq(dbg_dout), # capture PC
631 ),
632 #If(dbg_addr == 0b11, # MSR
633 # Display(" msr: %016x", dbg_dout),
634 #),
635 If(dbg_addr == 0b1000, # CR
636 Display(" cr : %016x", dbg_dout),
637 ),
638 If(dbg_addr == 0b1001, # XER
639 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
640 xer_so, xer_ca, xer_ca32, xer_ov, xer_ov32),
641 ),
642 If(dbg_addr == 0b101, # GPR
643 Display(" gpr: %016x", dbg_dout),
644 ),
645 # also check if this is a "stat"
646 If(dbg_addr == 1, # requested a STAT
647 #Display(" stat: %x", dbg_dout),
648 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
649 dmirunning.eq(1), # continue running
650 dmi_monitor.eq(0), # and stop monitor mode
651 ),
652 ),
653 dbg_msg.eq(0)
654 )
655 )
656
657 # kick off a "stop"
658 self.sync += If(uptime == 0,
659 (dmi_addr.eq(0), # CTRL
660 dmi_din.eq(1<<0), # STOP
661 dmi_req.eq(1),
662 dmi_wen.eq(1),
663 )
664 )
665
666 self.sync += If(uptime == 4,
667 dmirunning.eq(1),
668 )
669
670 self.sync += If(dmirunning,
671 dmicount.eq(dmicount + 1),
672 )
673
674 # loop every 1<<N cycles
675 cyclewid = 9
676
677 # get the PC
678 self.sync += If(dmicount == 4,
679 (dmi_addr.eq(0b10), # NIA
680 dmi_req.eq(1),
681 dmi_wen.eq(0),
682 )
683 )
684
685 # kick off a "step"
686 self.sync += If(dmicount == 8,
687 (dmi_addr.eq(0), # CTRL
688 dmi_din.eq(1<<3), # STEP
689 dmi_req.eq(1),
690 dmi_wen.eq(1),
691 dmirunning.eq(0), # stop counter, need to fire "monitor"
692 dmi_monitor.eq(1), # start "monitor" instead
693 )
694 )
695
696 # limit range of pc for debug reporting
697 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
698 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
699 self.comb += active_dbg.eq(1)
700
701
702 # get the MSR
703 self.sync += If(active_dbg & (dmicount == 12),
704 (dmi_addr.eq(0b11), # MSR
705 dmi_req.eq(1),
706 dmi_wen.eq(0),
707 )
708 )
709
710 if cpu == "libresoc":
711 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
712 self.comb += active_dbg_cr.eq(0)
713
714 # get the CR
715 self.sync += If(active_dbg_cr & (dmicount == 16),
716 (dmi_addr.eq(0b1000), # CR
717 dmi_req.eq(1),
718 dmi_wen.eq(0),
719 )
720 )
721
722 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
723 self.comb += active_dbg_xer.eq(active_dbg_cr)
724
725 # get the CR
726 self.sync += If(active_dbg_xer & (dmicount == 20),
727 (dmi_addr.eq(0b1001), # XER
728 dmi_req.eq(1),
729 dmi_wen.eq(0),
730 )
731 )
732
733 # read all 32 GPRs
734 for i in range(32):
735 self.sync += If(active_dbg & (dmicount == 24+(i*8)),
736 (dmi_addr.eq(0b100), # GSPR addr
737 dmi_din.eq(i), # r1
738 dmi_req.eq(1),
739 dmi_wen.eq(1),
740 )
741 )
742
743 self.sync += If(active_dbg & (dmicount == 28+(i*8)),
744 (dmi_addr.eq(0b101), # GSPR data
745 dmi_req.eq(1),
746 dmi_wen.eq(0),
747 )
748 )
749
750 # monitor bbus read/write
751 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
752 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
753 #uptime,
754 0,
755 self.cpu.dbus.adr,
756 self.cpu.dbus.we,
757 self.cpu.dbus.sel,
758 self.cpu.dbus.dat_w,
759 self.cpu.dbus.dat_r
760 )
761 )
762
763 return
764
765 # monitor ibus write
766 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
767 self.cpu.ibus.we,
768 Display(" [%06x] iadr: %8x, s %01x w %016x",
769 #uptime,
770 0,
771 self.cpu.ibus.adr,
772 self.cpu.ibus.sel,
773 self.cpu.ibus.dat_w,
774 )
775 )
776 # monitor ibus read
777 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
778 ~self.cpu.ibus.we,
779 Display(" [%06x] iadr: %8x, s %01x r %016x",
780 #uptime,
781 0,
782 self.cpu.ibus.adr,
783 self.cpu.ibus.sel,
784 self.cpu.ibus.dat_r
785 )
786 )
787
788 # Build -----------------------------------------------------------------------
789
790 def main():
791 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
792 parser.add_argument("--cpu", default="libresoc",
793 help="CPU to use: libresoc (default) or microwatt")
794 parser.add_argument("--platform", default="sim",
795 help="platform (sim or ls180)")
796 parser.add_argument("--debug", action="store_true",
797 help="Enable debug traces")
798 parser.add_argument("--trace", action="store_true",
799 help="Enable tracing")
800 parser.add_argument("--trace-start", default=0,
801 help="Cycle to start FST tracing")
802 parser.add_argument("--trace-end", default=-1,
803 help="Cycle to end FST tracing")
804 parser.add_argument("--build", action="store_true", help="Build bitstream")
805 args = parser.parse_args()
806
807
808 if args.platform == 'ls180':
809 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
810 platform=args.platform)
811 builder = Builder(soc, compile_gateware = True)
812 builder.build(run = True)
813 os.chdir("../")
814 else:
815
816 sim_config = SimConfig(default_clk="sys_clk")
817 sim_config.add_module("serial2console", "serial")
818
819 for i in range(2):
820 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
821 platform=args.platform)
822 builder = Builder(soc, compile_gateware = i!=0)
823 builder.build(sim_config=sim_config,
824 run = i!=0,
825 trace = args.trace,
826 trace_start = int(args.trace_start),
827 trace_end = int(args.trace_end),
828 trace_fst = 0)
829 os.chdir("../")
830
831 if __name__ == "__main__":
832 main()