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