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