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