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