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