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