f3c259a7def6c96b248643855768c4d7f1bb4faa
[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
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 print ("sdr pads dm len", pads.dm, len(pads.dm))
267 for i in range(len(pads.dm)):
268 self.specials += SDROutput(i=d.wrdata_en&d.wrdata_mask[i],
269 o=pads.dm[i])
270
271 # DQ/DM Control Path ----------------------------------------------
272 rddata_en = Signal(cl + cmd_latency)
273 self.sync += rddata_en.eq(Cat(dfi.p0.rddata_en, rddata_en))
274 self.sync += dfi.p0.rddata_valid.eq(rddata_en[-1])
275
276
277 # LibreSoC 180nm ASIC -------------------------------------------------------
278
279 class LibreSoCSim(SoCCore):
280 def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
281 sdram_module = "AS4C16M16",
282 #sdram_data_width = 16,
283 #sdram_module = "MT48LC16M16",
284 sdram_data_width = 16,
285 irq_reserved_irqs = {'uart': 0},
286 platform='sim',
287 ):
288 assert cpu in ["libresoc", "microwatt"]
289 sys_clk_freq = int(50e6)
290
291 if platform == 'sim':
292 platform = Platform()
293 uart_name = "sim"
294 elif platform == 'ls180':
295 platform = LS180Platform()
296 uart_name = "uart"
297
298 #cpu_data_width = 32
299 cpu_data_width = 64
300
301 variant = "ls180"
302
303 # reserve XICS ICP and XICS memory addresses.
304 self.mem_map['icp'] = 0xc0010000
305 self.mem_map['ics'] = 0xc0011000
306 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
307 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
308
309 ram_init = []
310 if False:
311 #ram_init = get_mem_data({
312 # ram_fname: "0x00000000",
313 # }, "little")
314 ram_init = get_mem_data(ram_fname, "little")
315
316 # remap the main RAM to reset-start-address
317
318 # without sram nothing works, therefore move it to higher up
319 self.mem_map["sram"] = 0x90000000
320
321 # put UART at 0xc000200 (w00t! this works!)
322 self.csr_map["uart"] = 4
323
324 self.mem_map["main_ram"] = 0x90000000
325 self.mem_map["sram"] = 0x00000000
326 self.mem_map["sram1"] = 0x00000200
327 self.mem_map["sram2"] = 0x00000400
328 self.mem_map["sram3"] = 0x00000600
329 self.mem_map["sram4"] = 0x00000800
330 self.mem_map["sram4k_0"] = 0x00001000
331 self.mem_map["sram4k_1"] = 0x00002000
332 self.mem_map["sram4k_2"] = 0x00003000
333 self.mem_map["sram4k_3"] = 0x00004000
334
335 # SoCCore -------------------------------------------------------------
336 SoCCore.__init__(self, platform, clk_freq=sys_clk_freq,
337 cpu_type = "microwatt",
338 cpu_cls = LibreSoC if cpu == "libresoc" \
339 else Microwatt,
340 bus_data_width = 64,
341 csr_address_width = 14, # limit to 0x8000
342 cpu_variant = variant,
343 csr_data_width = 8,
344 l2_size = 0,
345 with_uart = False,
346 uart_name = None,
347 with_sdram = with_sdram,
348 sdram_module = sdram_module,
349 sdram_data_width = sdram_data_width,
350 integrated_rom_size = 0, # if ram_fname else 0x10000,
351 #integrated_sram_size = 0x1000, - problem with yosys ABC
352 integrated_sram_size = 0x200,
353 #integrated_main_ram_init = ram_init,
354 integrated_main_ram_size = 0x00000000 if with_sdram \
355 else 0x10000000 , # 256MB
356 )
357 self.platform.name = "ls180"
358
359 # add 4 more 4k integrated SRAMs
360 self.add_ram("sram1", self.mem_map["sram1"], 0x200)
361 self.add_ram("sram2", self.mem_map["sram2"], 0x200)
362 self.add_ram("sram3", self.mem_map["sram3"], 0x200)
363 self.add_ram("sram4", self.mem_map["sram4"], 0x200)
364
365 # SDR SDRAM ----------------------------------------------
366 if False: # not self.integrated_main_ram_size:
367 self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"))
368
369 if cpu == "libresoc":
370 # XICS interrupt devices
371 icp_addr = self.mem_map['icp']
372 icp_wb = self.cpu.xics_icp
373 icp_region = SoCRegion(origin=icp_addr, size=0x20, cached=False)
374 self.bus.add_slave(name='icp', slave=icp_wb, region=icp_region)
375
376 ics_addr = self.mem_map['ics']
377 ics_wb = self.cpu.xics_ics
378 ics_region = SoCRegion(origin=ics_addr, size=0x1000, cached=False)
379 self.bus.add_slave(name='ics', slave=ics_wb, region=ics_region)
380
381 # add 4x 4k SRAMs
382 for i, sram_wb in enumerate(self.cpu.srams):
383 name = 'sram4k_%d' % i
384 sram_adr = self.mem_map[name]
385 ics_region = SoCRegion(origin=sram_adr, size=0x1000)
386 self.bus.add_slave(name=name, slave=sram_wb, region=ics_region)
387
388 # CRG -----------------------------------------------------------------
389 self.submodules.crg = CRG(platform.request("sys_clk"),
390 platform.request("sys_rst"))
391
392 # PLL/Clock Select
393 clksel_i = platform.request("sys_clksel_i")
394 pll18_o = platform.request("sys_pll_18_o")
395 pll_lck_o = platform.request("sys_pll_lck_o")
396
397 self.comb += self.cpu.clk_sel.eq(clksel_i) # allow clock src select
398 self.comb += pll18_o.eq(self.cpu.pll_18_o) # "test feed" from the PLL
399 self.comb += pll_lck_o.eq(self.cpu.pll_lck_o) # PLL lock flag
400
401 #ram_init = []
402
403 # SDRAM ----------------------------------------------------
404 if with_sdram:
405 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
406 sdram_module_cls = getattr(litedram_modules, sdram_module)
407 sdram_rate = "1:{}".format(
408 sdram_module_nphases[sdram_module_cls.memtype])
409 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
410 phy_settings = get_sdram_phy_settings(
411 memtype = sdram_module.memtype,
412 data_width = sdram_data_width,
413 clk_freq = sdram_clk_freq)
414 #sdrphy_cls = HalfRateGENSDRPHY
415 sdrphy_cls = GENSDRPHY
416 sdram_pads = self.cpu.cpupads['sdr']
417 self.submodules.sdrphy = sdrphy_cls(sdram_pads)
418 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
419 # phy_settings,
420 # init=ram_init
421 # )
422 self.add_sdram("sdram",
423 phy = self.sdrphy,
424 module = sdram_module,
425 origin = self.mem_map["main_ram"],
426 size = 0x80000000,
427 l2_cache_size = 0, # 8192
428 l2_cache_min_data_width = 128,
429 l2_cache_reverse = True
430 )
431 # FIXME: skip memtest to avoid corrupting memory
432 self.add_constant("MEMTEST_BUS_SIZE", 128//16)
433 self.add_constant("MEMTEST_DATA_SIZE", 128//16)
434 self.add_constant("MEMTEST_ADDR_SIZE", 128//16)
435 self.add_constant("MEMTEST_BUS_DEBUG", 1)
436 self.add_constant("MEMTEST_ADDR_DEBUG", 1)
437 self.add_constant("MEMTEST_DATA_DEBUG", 1)
438
439 # SDRAM clock
440 sys_clk = ClockSignal()
441 sdr_clk = self.cpu.cpupads['sdram_clock']
442 #self.specials += DDROutput(1, 0, , sdram_clk)
443 self.specials += SDROutput(clk=sys_clk, i=sys_clk, o=sdr_clk)
444
445 # UART
446 uart_core_pads = self.cpu.cpupads['uart']
447 self.submodules.uart_phy = uart.UARTPHY(
448 pads = uart_core_pads,
449 clk_freq = self.sys_clk_freq,
450 baudrate = 115200)
451 self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
452 tx_fifo_depth = 16,
453 rx_fifo_depth = 16))
454
455 self.csr.add("uart_phy", use_loc_if_exists=True)
456 self.csr.add("uart", use_loc_if_exists=True)
457 self.irq.add("uart", use_loc_if_exists=True)
458
459 # GPIOs (bi-directional)
460 gpio_core_pads = self.cpu.cpupads['gpio']
461 self.submodules.gpio = GPIOTristateASIC(gpio_core_pads, range(8))
462 self.add_csr("gpio")
463
464 self.submodules.gpio = GPIOTristateASIC(gpio_core_pads, range(8,16))
465 self.add_csr("gpio1")
466
467 # SPI Master
468 print ("cpupadkeys", self.cpu.cpupads.keys())
469 self.submodules.spimaster = SPIMaster(
470 pads = self.cpu.cpupads['mspi1'],
471 data_width = 8,
472 sys_clk_freq = sys_clk_freq,
473 spi_clk_freq = 8e6,
474 )
475 self.add_csr("spimaster")
476
477 # SPI SDCard (1 wide)
478 spi_clk_freq = 400e3
479 pads = self.cpu.cpupads['mspi0']
480 spisdcard = SPIMaster(pads, 8, self.sys_clk_freq, spi_clk_freq)
481 spisdcard.add_clk_divider()
482 setattr(self.submodules, 'spisdcard', spisdcard)
483 self.add_csr('spisdcard')
484
485 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
486 eintpads = self.cpu.cpupads['eint']
487 print ("eintpads", eintpads)
488 self.comb += self.cpu.interrupt[12:16].eq(eintpads)
489
490 # JTAG
491 jtagpads = platform.request("jtag")
492 self.comb += self.cpu.jtag_tck.eq(jtagpads.tck)
493 self.comb += self.cpu.jtag_tms.eq(jtagpads.tms)
494 self.comb += self.cpu.jtag_tdi.eq(jtagpads.tdi)
495 self.comb += jtagpads.tdo.eq(self.cpu.jtag_tdo)
496
497 # NC - allows some iopads to be connected up
498 # sigh, just do something, anything, to stop yosys optimising these out
499 nc_pads = platform.request("nc")
500 num_nc = len(nc_pads)
501 self.nc = Signal(num_nc)
502 self.comb += self.nc.eq(nc_pads)
503 self.dummy = Signal(num_nc)
504 for i in range(num_nc):
505 self.sync += self.dummy[i].eq(self.nc[i] | self.cpu.interrupt[0])
506
507 # PWM
508 pwmpads = self.cpu.cpupads['pwm']
509 for i in range(2):
510 name = "pwm%d" % i
511 setattr(self.submodules, name, PWM(pwmpads[i]))
512 self.add_csr(name)
513
514 # I2C Master
515 i2c_core_pads = self.cpu.cpupads['mtwi']
516 self.submodules.i2c = I2CMaster(i2c_core_pads)
517 self.add_csr("i2c")
518
519 # SDCard -----------------------------------------------------
520
521 # Emulator / Pads
522 sdcard_pads = self.cpu.cpupads['sd0']
523
524 # Core
525 self.submodules.sdphy = SDPHY(sdcard_pads,
526 self.platform.device, self.clk_freq)
527 self.submodules.sdcore = SDCore(self.sdphy)
528 self.add_csr("sdphy")
529 self.add_csr("sdcore")
530
531 # Block2Mem DMA
532 bus = wishbone.Interface(data_width=self.bus.data_width,
533 adr_width=self.bus.address_width)
534 self.submodules.sdblock2mem = SDBlock2MemDMA(bus=bus,
535 endianness=self.cpu.endianness)
536 self.comb += self.sdcore.source.connect(self.sdblock2mem.sink)
537 dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus
538 dma_bus.add_master("sdblock2mem", master=bus)
539 self.add_csr("sdblock2mem")
540
541 # Mem2Block DMA
542 bus = wishbone.Interface(data_width=self.bus.data_width,
543 adr_width=self.bus.address_width)
544 self.submodules.sdmem2block = SDMem2BlockDMA(bus=bus,
545 endianness=self.cpu.endianness)
546 self.comb += self.sdmem2block.source.connect(self.sdcore.sink)
547 dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus
548 dma_bus.add_master("sdmem2block", master=bus)
549 self.add_csr("sdmem2block")
550
551 # Debug ---------------------------------------------------------------
552 if not debug:
553 return
554
555 jtag_en = ('jtag' in variant) or variant == 'ls180'
556
557 # setup running of DMI FSM
558 dmi_addr = Signal(4)
559 dmi_din = Signal(64)
560 dmi_dout = Signal(64)
561 dmi_wen = Signal(1)
562 dmi_req = Signal(1)
563
564 # debug log out
565 dbg_addr = Signal(4)
566 dbg_dout = Signal(64)
567 dbg_msg = Signal(1)
568
569 # capture pc from dmi
570 pc = Signal(64)
571 active_dbg = Signal()
572 active_dbg_cr = Signal()
573 active_dbg_xer = Signal()
574
575 # xer flags
576 xer_so = Signal()
577 xer_ca = Signal()
578 xer_ca32 = Signal()
579 xer_ov = Signal()
580 xer_ov32 = Signal()
581
582 # increment counter, Stop after 100000 cycles
583 uptime = Signal(64)
584 self.sync += uptime.eq(uptime + 1)
585 #self.sync += If(uptime == 1000000000000, Finish())
586
587 # DMI FSM counter and FSM itself
588 dmicount = Signal(10)
589 dmirunning = Signal(1)
590 dmi_monitor = Signal(1)
591 dmifsm = FSM()
592 self.submodules += dmifsm
593
594 # DMI FSM
595 dmifsm.act("START",
596 If(dmi_req & dmi_wen,
597 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
598 self.cpu.dmi_din.eq(dmi_din), # DMI in
599 self.cpu.dmi_req.eq(1), # DMI request
600 self.cpu.dmi_wr.eq(1), # DMI write
601 If(self.cpu.dmi_ack,
602 (NextState("IDLE"),
603 )
604 ),
605 ),
606 ),
607 If(dmi_req & ~dmi_wen,
608 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
609 self.cpu.dmi_req.eq(1), # DMI request
610 self.cpu.dmi_wr.eq(0), # DMI read
611 If(self.cpu.dmi_ack,
612 # acknowledge received: capture data.
613 (NextState("IDLE"),
614 NextValue(dbg_addr, dmi_addr),
615 NextValue(dbg_dout, self.cpu.dmi_dout),
616 NextValue(dbg_msg, 1),
617 ),
618 ),
619 ),
620 )
621 )
622
623 # DMI response received: reset the dmi request and check if
624 # in "monitor" mode
625 dmifsm.act("IDLE",
626 If(dmi_monitor,
627 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
628 ).Else(
629 NextState("START"), # back to start on next cycle
630 ),
631 NextValue(dmi_req, 0),
632 NextValue(dmi_addr, 0),
633 NextValue(dmi_din, 0),
634 NextValue(dmi_wen, 0),
635 )
636
637 # "monitor" mode fires off a STAT request
638 dmifsm.act("FIRE_MONITOR",
639 (NextValue(dmi_req, 1),
640 NextValue(dmi_addr, 1), # DMI STAT address
641 NextValue(dmi_din, 0),
642 NextValue(dmi_wen, 0), # read STAT
643 NextState("START"), # back to start on next cycle
644 )
645 )
646
647 self.comb += xer_so.eq((dbg_dout & 1) == 1)
648 self.comb += xer_ca.eq((dbg_dout & 4) == 4)
649 self.comb += xer_ca32.eq((dbg_dout & 8) == 8)
650 self.comb += xer_ov.eq((dbg_dout & 16) == 16)
651 self.comb += xer_ov32.eq((dbg_dout & 32) == 32)
652
653 # debug messages out
654 self.sync += If(dbg_msg,
655 (If(active_dbg & (dbg_addr == 0b10), # PC
656 Display("pc : %016x", dbg_dout),
657 ),
658 If(dbg_addr == 0b10, # PC
659 pc.eq(dbg_dout), # capture PC
660 ),
661 #If(dbg_addr == 0b11, # MSR
662 # Display(" msr: %016x", dbg_dout),
663 #),
664 If(dbg_addr == 0b1000, # CR
665 Display(" cr : %016x", dbg_dout),
666 ),
667 If(dbg_addr == 0b1001, # XER
668 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
669 xer_so, xer_ca, xer_ca32, xer_ov, xer_ov32),
670 ),
671 If(dbg_addr == 0b101, # GPR
672 Display(" gpr: %016x", dbg_dout),
673 ),
674 # also check if this is a "stat"
675 If(dbg_addr == 1, # requested a STAT
676 #Display(" stat: %x", dbg_dout),
677 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
678 dmirunning.eq(1), # continue running
679 dmi_monitor.eq(0), # and stop monitor mode
680 ),
681 ),
682 dbg_msg.eq(0)
683 )
684 )
685
686 # kick off a "stop"
687 self.sync += If(uptime == 0,
688 (dmi_addr.eq(0), # CTRL
689 dmi_din.eq(1<<0), # STOP
690 dmi_req.eq(1),
691 dmi_wen.eq(1),
692 )
693 )
694
695 self.sync += If(uptime == 4,
696 dmirunning.eq(1),
697 )
698
699 self.sync += If(dmirunning,
700 dmicount.eq(dmicount + 1),
701 )
702
703 # loop every 1<<N cycles
704 cyclewid = 9
705
706 # get the PC
707 self.sync += If(dmicount == 4,
708 (dmi_addr.eq(0b10), # NIA
709 dmi_req.eq(1),
710 dmi_wen.eq(0),
711 )
712 )
713
714 # kick off a "step"
715 self.sync += If(dmicount == 8,
716 (dmi_addr.eq(0), # CTRL
717 dmi_din.eq(1<<3), # STEP
718 dmi_req.eq(1),
719 dmi_wen.eq(1),
720 dmirunning.eq(0), # stop counter, need to fire "monitor"
721 dmi_monitor.eq(1), # start "monitor" instead
722 )
723 )
724
725 # limit range of pc for debug reporting
726 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
727 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
728 self.comb += active_dbg.eq(1)
729
730
731 # get the MSR
732 self.sync += If(active_dbg & (dmicount == 12),
733 (dmi_addr.eq(0b11), # MSR
734 dmi_req.eq(1),
735 dmi_wen.eq(0),
736 )
737 )
738
739 if cpu == "libresoc":
740 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
741 self.comb += active_dbg_cr.eq(0)
742
743 # get the CR
744 self.sync += If(active_dbg_cr & (dmicount == 16),
745 (dmi_addr.eq(0b1000), # CR
746 dmi_req.eq(1),
747 dmi_wen.eq(0),
748 )
749 )
750
751 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
752 self.comb += active_dbg_xer.eq(active_dbg_cr)
753
754 # get the CR
755 self.sync += If(active_dbg_xer & (dmicount == 20),
756 (dmi_addr.eq(0b1001), # XER
757 dmi_req.eq(1),
758 dmi_wen.eq(0),
759 )
760 )
761
762 # read all 32 GPRs
763 for i in range(32):
764 self.sync += If(active_dbg & (dmicount == 24+(i*8)),
765 (dmi_addr.eq(0b100), # GSPR addr
766 dmi_din.eq(i), # r1
767 dmi_req.eq(1),
768 dmi_wen.eq(1),
769 )
770 )
771
772 self.sync += If(active_dbg & (dmicount == 28+(i*8)),
773 (dmi_addr.eq(0b101), # GSPR data
774 dmi_req.eq(1),
775 dmi_wen.eq(0),
776 )
777 )
778
779 # monitor bbus read/write
780 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
781 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
782 #uptime,
783 0,
784 self.cpu.dbus.adr,
785 self.cpu.dbus.we,
786 self.cpu.dbus.sel,
787 self.cpu.dbus.dat_w,
788 self.cpu.dbus.dat_r
789 )
790 )
791
792 return
793
794 # monitor ibus write
795 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
796 self.cpu.ibus.we,
797 Display(" [%06x] iadr: %8x, s %01x w %016x",
798 #uptime,
799 0,
800 self.cpu.ibus.adr,
801 self.cpu.ibus.sel,
802 self.cpu.ibus.dat_w,
803 )
804 )
805 # monitor ibus read
806 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
807 ~self.cpu.ibus.we,
808 Display(" [%06x] iadr: %8x, s %01x r %016x",
809 #uptime,
810 0,
811 self.cpu.ibus.adr,
812 self.cpu.ibus.sel,
813 self.cpu.ibus.dat_r
814 )
815 )
816
817 # Build -----------------------------------------------------------------------
818
819 def main():
820 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
821 parser.add_argument("--cpu", default="libresoc",
822 help="CPU to use: libresoc (default) or microwatt")
823 parser.add_argument("--platform", default="sim",
824 help="platform (sim or ls180)")
825 parser.add_argument("--debug", action="store_true",
826 help="Enable debug traces")
827 parser.add_argument("--trace", action="store_true",
828 help="Enable tracing")
829 parser.add_argument("--trace-start", default=0,
830 help="Cycle to start FST tracing")
831 parser.add_argument("--trace-end", default=-1,
832 help="Cycle to end FST tracing")
833 parser.add_argument("--build", action="store_true", help="Build bitstream")
834 args = parser.parse_args()
835
836
837 if args.platform == 'ls180':
838 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
839 platform=args.platform)
840 builder = Builder(soc, compile_gateware = True)
841 builder.build(run = True)
842 os.chdir("../")
843 else:
844
845 sim_config = SimConfig(default_clk="sys_clk")
846 sim_config.add_module("serial2console", "serial")
847
848 for i in range(2):
849 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
850 platform=args.platform)
851 builder = Builder(soc, compile_gateware = i!=0)
852 builder.build(sim_config=sim_config,
853 run = i!=0,
854 trace = args.trace,
855 trace_start = int(args.trace_start),
856 trace_end = int(args.trace_end),
857 trace_fst = 0)
858 os.chdir("../")
859
860 if __name__ == "__main__":
861 main()