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