5 from functools
import reduce
6 from operator
import or_
8 from migen
import (Signal
, FSM
, If
, Display
, Finish
, NextValue
, NextState
,
9 Cat
, Record
, ClockSignal
, wrap
, ResetInserter
)
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
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
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
32 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
34 from litex
.tools
.litex_sim
import Platform
35 from libresoc
.ls180
import LS180Platform
37 from migen
import Module
38 from litex
.soc
.interconnect
.csr
import AutoCSR
40 from libresoc
import LibreSoC
41 from microwatt
import Microwatt
44 from litex
.soc
.integration
.soc
import SoCCSRHandler
45 SoCCSRHandler
.supported_address_width
.append(12)
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
54 from litex
.soc
.interconnect
import wishbone
55 from litesdcard
.phy
import (SDPHY
, SDPHYClocker
,
56 SDPHYInit
, SDPHYCMDW
, SDPHYCMDR
,
57 SDPHYDATAW
, SDPHYDATAR
,
59 from litesdcard
.core
import SDCore
60 from litesdcard
.frontend
.dma
import SDBlock2MemDMA
, SDMem2BlockDMA
61 from litex
.build
.io
import SDROutput
, SDRInput
64 # I2C Master Bit-Banging --------------------------------------------------
66 class I2CMaster(Module
, AutoCSR
):
67 """I2C Master Bit-Banging
69 Provides the minimal hardware to do software I2C Master bit banging.
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).
75 pads_layout
= [("scl", 1), ("sda", 1)]
76 def __init__(self
, 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)],
83 self
._r
= CSRStatus(fields
=[
84 CSRField("sda", size
=1, offset
=0)],
89 def connect(self
, pads
):
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
),
101 class GPIOTristateASIC(Module
, AutoCSR
):
102 def __init__(self
, name
, pads
, prange
=None):
104 prange
= range(nbits
)
107 self
._oe
= CSRStorage(nbits
, description
="GPIO Tristate(s) Control.")
108 self
._in
= CSRStatus(nbits
, description
="GPIO Input(s) Status.")
109 self
._out
= CSRStorage(nbits
, description
="GPIO Ouptut(s) Control.")
113 _pads
= Record( ((name
+"i", nbits
),
116 _o
= getattr(_pads
, name
+"o")
117 _oe
= getattr(_pads
, name
+"oe")
118 _i
= getattr(_pads
, name
+"i")
119 for j
, i
in enumerate(prange
):
120 self
.comb
+= _i
[j
].eq(pads
.i
[i
])
121 self
.comb
+= pads
.o
[i
].eq(_o
[j
])
122 self
.comb
+= pads
.oe
[i
].eq(_oe
[j
])
125 o
= self
._out
.storage
126 oe
= self
._oe
.storage
128 for j
in range(nbits
):
129 self
.specials
+= SDROutput(clk
=clk
, i
=oe
[j
], o
=_oe
[j
])
130 self
.specials
+= SDROutput(clk
=clk
, i
=o
[j
], o
=_o
[j
])
131 self
.specials
+= SDRInput(clk
=clk
, i
=_i
[j
], o
=i
[j
])
132 #for i in range(nbits):
133 #self.comb += _pads.oe[i].eq(self._oe.storage[i])
134 #self.comb += _pads.o[i].eq(self._out.storage[i])
135 #self.specials += MultiReg(_pads.i[i], self._in.status[i])
137 # SDCard PHY IO -------------------------------------------------------
139 class SDRPad(Module
):
140 def __init__(self
, pad
, name
, o
, oe
, i
):
142 _o
= getattr(pad
, "%s_o" % name
)
143 _oe
= getattr(pad
, "%s_oe" % name
)
144 _i
= getattr(pad
, "%s_i" % name
)
145 self
.specials
+= SDROutput(clk
=clk
, i
=oe
, o
=_oe
)
146 for j
in range(len(_o
)):
147 self
.specials
+= SDROutput(clk
=clk
, i
=o
[j
], o
=_o
[j
])
148 self
.specials
+= SDRInput(clk
=clk
, i
=_i
[j
], o
=i
[j
])
151 class SDPHYIOGen(Module
):
152 def __init__(self
, clocker
, sdpads
, pads
):
154 if hasattr(pads
, "rst"):
155 self
.comb
+= pads
.rst
.eq(0)
158 self
.specials
+= SDROutput(
160 i
= ~clocker
.clk
& sdpads
.clk
,
166 self
.submodules
.sd_cmd
= SDRPad(pads
, "cmd", c
.o
, c
.oe
, c
.i
)
170 self
.submodules
.sd_data
= SDRPad(pads
, "data", d
.o
, d
.oe
, d
.i
)
173 class SDPHY(Module
, AutoCSR
):
174 def __init__(self
, pads
, device
, sys_clk_freq
,
175 cmd_timeout
=10e-3, data_timeout
=10e-3):
176 self
.card_detect
= CSRStatus() # Assume SDCard is present if no cd pin.
177 self
.comb
+= self
.card_detect
.status
.eq(getattr(pads
, "cd", 0))
179 self
.submodules
.clocker
= clocker
= SDPHYClocker()
180 self
.submodules
.init
= init
= SDPHYInit()
181 self
.submodules
.cmdw
= cmdw
= SDPHYCMDW()
182 self
.submodules
.cmdr
= cmdr
= SDPHYCMDR(sys_clk_freq
,
184 self
.submodules
.dataw
= dataw
= SDPHYDATAW()
185 self
.submodules
.datar
= datar
= SDPHYDATAR(sys_clk_freq
,
190 self
.sdpads
= sdpads
= Record(_sdpads_layout
)
193 sdphy_cls
= SDPHYIOGen
194 self
.submodules
.io
= sdphy_cls(clocker
, sdpads
, pads
)
196 # Connect pads_out of submodules to physical pads --------------
197 pl
= [init
, cmdw
, cmdr
, dataw
, datar
]
199 sdpads
.clk
.eq( reduce(or_
, [m
.pads_out
.clk
for m
in pl
])),
200 sdpads
.cmd
.oe
.eq( reduce(or_
, [m
.pads_out
.cmd
.oe
for m
in pl
])),
201 sdpads
.cmd
.o
.eq( reduce(or_
, [m
.pads_out
.cmd
.o
for m
in pl
])),
202 sdpads
.data
.oe
.eq(reduce(or_
, [m
.pads_out
.data
.oe
for m
in pl
])),
203 sdpads
.data
.o
.eq( reduce(or_
, [m
.pads_out
.data
.o
for m
in pl
])),
206 self
.comb
+= m
.pads_out
.ready
.eq(self
.clocker
.ce
)
208 # Connect physical pads to pads_in of submodules ---------------
210 self
.comb
+= m
.pads_in
.valid
.eq(self
.clocker
.ce
)
211 self
.comb
+= m
.pads_in
.cmd
.i
.eq(sdpads
.cmd
.i
)
212 self
.comb
+= m
.pads_in
.data
.i
.eq(sdpads
.data
.i
)
214 # Speed Throttling -------------------------------------------
215 self
.comb
+= clocker
.stop
.eq(dataw
.stop | datar
.stop
)
218 # Generic SDR PHY ---------------------------------------------------------
220 class GENSDRPHY(Module
):
221 def __init__(self
, pads
, cl
=2, cmd_latency
=1):
222 pads
= PHYPadsCombiner(pads
)
223 addressbits
= len(pads
.a
)
224 bankbits
= len(pads
.ba
)
225 nranks
= 1 if not hasattr(pads
, "cs_n") else len(pads
.cs_n
)
226 databits
= len(pads
.dq_i
)
228 assert databits
%8 == 0
230 # PHY settings ----------------------------------------------------
231 self
.settings
= PhySettings(
232 phytype
= "GENSDRPHY",
235 dfi_databits
= databits
,
243 read_latency
= cl
+ cmd_latency
,
247 # DFI Interface ---------------------------------------------------
248 self
.dfi
= dfi
= DFIInterface(addressbits
, bankbits
, nranks
, databits
)
252 # Iterate on pads groups ------------------------------------------
253 for pads_group
in range(len(pads
.groups
)):
254 pads
.sel_group(pads_group
)
256 # Addresses and Commands --------------------------------------
258 self
.specials
+= [SDROutput(i
=p0
.address
[i
], o
=pads
.a
[i
])
259 for i
in range(len(pads
.a
))]
260 self
.specials
+= [SDROutput(i
=p0
.bank
[i
], o
=pads
.ba
[i
])
261 for i
in range(len(pads
.ba
))]
262 self
.specials
+= SDROutput(i
=p0
.cas_n
, o
=pads
.cas_n
)
263 self
.specials
+= SDROutput(i
=p0
.ras_n
, o
=pads
.ras_n
)
264 self
.specials
+= SDROutput(i
=p0
.we_n
, o
=pads
.we_n
)
265 if hasattr(pads
, "cke"):
266 for i
in range(len(pads
.cke
)):
267 self
.specials
+= SDROutput(i
=p0
.cke
[i
], o
=pads
.cke
[i
])
268 if hasattr(pads
, "cs_n"):
269 for i
in range(len(pads
.cs_n
)):
270 self
.specials
+= SDROutput(i
=p0
.cs_n
[i
], o
=pads
.cs_n
[i
])
272 # DQ/DM Data Path -------------------------------------------------
276 self
.submodules
.dq
= SDRPad(pads
, "dq", d
.wrdata
, d
.wrdata_en
, d
.rddata
)
278 if hasattr(pads
, "dm"):
279 print ("sdr pads dm len", pads
.dm
, len(pads
.dm
))
280 for i
in range(len(pads
.dm
)):
281 self
.specials
+= SDROutput(i
=d
.wrdata_en
&d
.wrdata_mask
[i
],
284 # DQ/DM Control Path ----------------------------------------------
285 rddata_en
= Signal(cl
+ cmd_latency
)
286 self
.sync
+= rddata_en
.eq(Cat(dfi
.p0
.rddata_en
, rddata_en
))
287 self
.sync
+= dfi
.p0
.rddata_valid
.eq(rddata_en
[-1])
290 # LibreSoC 180nm ASIC -------------------------------------------------------
292 class LibreSoCSim(SoCCore
):
293 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
294 sdram_module
= "AS4C16M16",
295 #sdram_data_width = 16,
296 #sdram_module = "MT48LC16M16",
297 sdram_data_width
= 16,
298 irq_reserved_irqs
= {'uart': 0},
303 assert cpu
in ["libresoc", "microwatt"]
304 sys_clk_freq
= int(50e6
)
306 platform_name
= platform
307 if platform
== 'sim':
308 platform
= Platform()
309 self
.platform
.name
= 'ls180'
311 elif 'ls180' in platform
:
312 platform
= LS180Platform()
318 variant
= "ls180nopll"
320 # reserve XICS ICP and XICS memory addresses.
321 self
.mem_map
['icp'] = 0xc0010000
322 self
.mem_map
['ics'] = 0xc0011000
323 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
324 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
328 #ram_init = get_mem_data({
329 # ram_fname: "0x00000000",
331 ram_init
= get_mem_data(ram_fname
, "little")
333 # remap the main RAM to reset-start-address
335 # without sram nothing works, therefore move it to higher up
336 self
.mem_map
["sram"] = 0x90000000
338 # put UART at 0xc000200 (w00t! this works!)
339 self
.csr_map
["uart"] = 4
341 self
.mem_map
["main_ram"] = 0x90000000
343 self
.mem_map
["sram"] = 0x00000000
344 self
.mem_map
["sram1"] = 0x00000200
345 self
.mem_map
["sram2"] = 0x00000400
346 self
.mem_map
["sram3"] = 0x00000600
347 self
.mem_map
["sram4"] = 0x00000800
350 sram_size
= 0x80 # ridiculously small
351 if "sram4k" not in variant
:
352 sram_size
= 0x200 # no 4k SRAMs, make slightly bigger
353 self
.mem_map
["sram"] = 0x00000000
354 self
.mem_map
["sram1"] = 0x00000700
355 self
.mem_map
["sram4k_0"] = 0x00001000
356 self
.mem_map
["sram4k_1"] = 0x00002000
357 self
.mem_map
["sram4k_2"] = 0x00003000
358 self
.mem_map
["sram4k_3"] = 0x00004000
360 # SoCCore -------------------------------------------------------------
361 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
362 cpu_type
= "microwatt",
363 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
365 #bus_data_width = 64, # don't add this! stops conversion
366 csr_address_width
= 14, # limit to 0x8000
367 cpu_variant
= variant
,
372 with_sdram
= with_sdram
,
373 sdram_module
= sdram_module
,
374 sdram_data_width
= sdram_data_width
,
375 integrated_rom_size
= 0, # if ram_fname else 0x10000,
376 #integrated_sram_size = 0x1000, - problem with yosys ABC
377 integrated_sram_size
= sram_size
,
378 #integrated_main_ram_init = ram_init,
379 integrated_main_ram_size
= 0x00000000 if with_sdram \
380 else 0x10000000 , # 256MB
383 self
.platform
.name
= platform_name
386 # add 4 more 4k integrated SRAMs
387 self
.add_ram("sram1", self
.mem_map
["sram1"], 0x200)
388 self
.add_ram("sram2", self
.mem_map
["sram2"], 0x200)
389 self
.add_ram("sram3", self
.mem_map
["sram3"], 0x200)
390 self
.add_ram("sram4", self
.mem_map
["sram4"], 0x200)
392 self
.add_ram("sram1", self
.mem_map
["sram1"], 0x80) # tiny!
394 # SDR SDRAM ----------------------------------------------
395 if False: # not self.integrated_main_ram_size:
396 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
398 if cpu
== "libresoc":
399 # XICS interrupt devices
400 icp_addr
= self
.mem_map
['icp']
401 icp_wb
= self
.cpu
.xics_icp
402 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
403 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
405 ics_addr
= self
.mem_map
['ics']
406 ics_wb
= self
.cpu
.xics_ics
407 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
408 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
411 for i
, sram_wb
in enumerate(self
.cpu
.srams
):
412 name
= 'sram4k_%d' % i
413 sram_adr
= self
.mem_map
[name
]
414 ics_region
= SoCRegion(origin
=sram_adr
, size
=0x1000)
415 self
.bus
.add_slave(name
=name
, slave
=sram_wb
, region
=ics_region
)
417 # CRG -----------------------------------------------------------------
418 self
.submodules
.crg
= CRG(platform
.request("sys_clk"),
419 platform
.request("sys_rst"))
421 if hasattr(self
.cpu
, "clk_sel"):
423 clksel_i
= platform
.request("sys_clksel_i")
424 pll18_o
= platform
.request("sys_pll_18_o")
425 pll_lck_o
= platform
.request("sys_pll_lck_o")
427 self
.comb
+= self
.cpu
.clk_sel
.eq(clksel_i
) # allow clock src select
428 self
.comb
+= pll18_o
.eq(self
.cpu
.pll_18_o
) # "test feed" from PLL
429 self
.comb
+= pll_lck_o
.eq(self
.cpu
.pll_lck_o
) # PLL lock flag
433 # SDRAM ----------------------------------------------------
435 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
436 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
437 sdram_rate
= "1:{}".format(
438 sdram_module_nphases
[sdram_module_cls
.memtype
])
439 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
440 phy_settings
= get_sdram_phy_settings(
441 memtype
= sdram_module
.memtype
,
442 data_width
= sdram_data_width
,
443 clk_freq
= sdram_clk_freq
)
444 #sdrphy_cls = HalfRateGENSDRPHY
445 sdrphy_cls
= GENSDRPHY
446 sdram_pads
= self
.cpu
.cpupads
['sdr']
447 self
.submodules
.sdrphy
= sdrphy_cls(sdram_pads
)
448 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
452 self
.add_sdram("sdram",
454 module
= sdram_module
,
455 origin
= self
.mem_map
["main_ram"],
457 l2_cache_size
= 0, # 8192
458 l2_cache_min_data_width
= 128,
459 l2_cache_reverse
= True
461 # FIXME: skip memtest to avoid corrupting memory
462 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
463 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
464 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
465 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
466 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
467 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
470 sys_clk
= ClockSignal()
471 #sdr_clk = self.cpu.cpupads['sdram_clock']
472 sdr_clk
= sdram_pads
.clock
473 #self.specials += DDROutput(1, 0, , sdram_clk)
474 self
.specials
+= SDROutput(clk
=sys_clk
, i
=sys_clk
, o
=sdr_clk
)
477 uart_core_pads
= self
.cpu
.cpupads
['uart']
478 self
.submodules
.uart_phy
= uart
.UARTPHY(
479 pads
= uart_core_pads
,
480 clk_freq
= self
.sys_clk_freq
,
482 self
.submodules
.uart
= ResetInserter()(uart
.UART(self
.uart_phy
,
486 self
.csr
.add("uart_phy", use_loc_if_exists
=True)
487 self
.csr
.add("uart", use_loc_if_exists
=True)
488 self
.irq
.add("uart", use_loc_if_exists
=True)
490 # GPIOs (bi-directional)
491 gpio_core_pads
= self
.cpu
.cpupads
['gpio']
492 self
.submodules
.gpio0
= GPIOTristateASIC("gpio0", gpio_core_pads
,
494 self
.add_csr("gpio0")
496 self
.submodules
.gpio1
= GPIOTristateASIC("gpio1", gpio_core_pads
,
498 self
.add_csr("gpio1")
501 print ("cpupadkeys", self
.cpu
.cpupads
.keys())
502 if hasattr(self
.cpu
.cpupads
, 'mspi0'):
504 pads
= self
.cpu
.cpupads
['mspi0']
505 spimaster
= SPIMaster(pads
, 8, self
.sys_clk_freq
, sd_clk_freq
)
506 spimaster
.add_clk_divider()
507 setattr(self
.submodules
, 'spimaster', spimaster
)
508 self
.add_csr('spimaster')
510 if hasattr(self
.cpu
.cpupads
, 'mspi1'):
511 # SPI SDCard (1 wide)
513 pads
= self
.cpu
.cpupads
['mspi1']
514 spisdcard
= SPIMaster(pads
, 8, self
.sys_clk_freq
, spi_clk_freq
)
515 spisdcard
.add_clk_divider()
516 setattr(self
.submodules
, 'spisdcard', spisdcard
)
517 self
.add_csr('spisdcard')
519 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
520 eintpads
= self
.cpu
.cpupads
['eint']
521 print ("eintpads", eintpads
)
522 self
.eint_tmp
= Signal(len(eintpads
))
523 for i
in range(len(eintpads
)):
524 self
.comb
+= self
.cpu
.interrupt
[13+i
].eq(self
.eint_tmp
[i
])
525 self
.comb
+= self
.eint_tmp
[i
].eq(getattr(eintpads
, "%d" % i
))
528 jtagpads
= platform
.request("jtag")
529 self
.comb
+= self
.cpu
.jtag_tck
.eq(jtagpads
.tck
)
530 self
.comb
+= self
.cpu
.jtag_tms
.eq(jtagpads
.tms
)
531 self
.comb
+= self
.cpu
.jtag_tdi
.eq(jtagpads
.tdi
)
532 self
.comb
+= jtagpads
.tdo
.eq(self
.cpu
.jtag_tdo
)
534 # NC - allows some iopads to be connected up
535 # sigh, just do something, anything, to stop yosys optimising these out
536 nc_pads
= platform
.request("nc")
537 num_nc
= len(nc_pads
)
538 self
.nc
= Signal(num_nc
)
539 self
.comb
+= self
.nc
.eq(nc_pads
)
540 self
.dummy
= Signal(num_nc
)
541 for i
in range(num_nc
):
542 self
.sync
+= self
.dummy
[i
].eq(self
.nc
[i
] | self
.cpu
.interrupt
[0])
545 if hasattr(self
.cpu
.cpupads
, 'pwm'):
546 pwmpads
= self
.cpu
.cpupads
['pwm']
549 setattr(self
.submodules
, name
, PWM(pwmpads
[i
]))
553 i2c_core_pads
= self
.cpu
.cpupads
['mtwi']
554 self
.submodules
.i2c
= I2CMaster(i2c_core_pads
)
557 # SDCard -----------------------------------------------------
559 if hasattr(self
.cpu
.cpupads
, 'sd0'):
561 sdcard_pads
= self
.cpu
.cpupads
['sd0']
564 self
.submodules
.sdphy
= SDPHY(sdcard_pads
,
565 self
.platform
.device
, self
.clk_freq
)
566 self
.submodules
.sdcore
= SDCore(self
.sdphy
)
567 self
.add_csr("sdphy")
568 self
.add_csr("sdcore")
571 bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
,
572 adr_width
=self
.bus
.address_width
)
573 self
.submodules
.sdblock2mem
= SDBlock2MemDMA(bus
=bus
,
574 endianness
=self
.cpu
.endianness
)
575 self
.comb
+= self
.sdcore
.source
.connect(self
.sdblock2mem
.sink
)
576 dma_bus
= self
.bus
if not hasattr(self
, "dma_bus") else self
.dma_bus
577 dma_bus
.add_master("sdblock2mem", master
=bus
)
578 self
.add_csr("sdblock2mem")
581 bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
,
582 adr_width
=self
.bus
.address_width
)
583 self
.submodules
.sdmem2block
= SDMem2BlockDMA(bus
=bus
,
584 endianness
=self
.cpu
.endianness
)
585 self
.comb
+= self
.sdmem2block
.source
.connect(self
.sdcore
.sink
)
586 dma_bus
= self
.bus
if not hasattr(self
, "dma_bus") else self
.dma_bus
587 dma_bus
.add_master("sdmem2block", master
=bus
)
588 self
.add_csr("sdmem2block")
590 # Debug ---------------------------------------------------------------
594 jtag_en
= ('jtag' in variant
) or ('ls180' in variant
)
596 # setup running of DMI FSM
599 dmi_dout
= Signal(64)
605 dbg_dout
= Signal(64)
608 # capture pc from dmi
610 active_dbg
= Signal()
611 active_dbg_cr
= Signal()
612 active_dbg_xer
= Signal()
621 # increment counter, Stop after 100000 cycles
623 self
.sync
+= uptime
.eq(uptime
+ 1)
624 #self.sync += If(uptime == 1000000000000, Finish())
626 # DMI FSM counter and FSM itself
627 dmicount
= Signal(10)
628 dmirunning
= Signal(1)
629 dmi_monitor
= Signal(1)
631 self
.submodules
+= dmifsm
635 If(dmi_req
& dmi_wen
,
636 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
637 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
638 self
.cpu
.dmi_req
.eq(1), # DMI request
639 self
.cpu
.dmi_wr
.eq(1), # DMI write
646 If(dmi_req
& ~dmi_wen
,
647 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
648 self
.cpu
.dmi_req
.eq(1), # DMI request
649 self
.cpu
.dmi_wr
.eq(0), # DMI read
651 # acknowledge received: capture data.
653 NextValue(dbg_addr
, dmi_addr
),
654 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
655 NextValue(dbg_msg
, 1),
662 # DMI response received: reset the dmi request and check if
666 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
668 NextState("START"), # back to start on next cycle
670 NextValue(dmi_req
, 0),
671 NextValue(dmi_addr
, 0),
672 NextValue(dmi_din
, 0),
673 NextValue(dmi_wen
, 0),
676 # "monitor" mode fires off a STAT request
677 dmifsm
.act("FIRE_MONITOR",
678 (NextValue(dmi_req
, 1),
679 NextValue(dmi_addr
, 1), # DMI STAT address
680 NextValue(dmi_din
, 0),
681 NextValue(dmi_wen
, 0), # read STAT
682 NextState("START"), # back to start on next cycle
686 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
687 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
688 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
689 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
690 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
693 self
.sync
+= If(dbg_msg
,
694 (If(active_dbg
& (dbg_addr
== 0b10), # PC
695 Display("pc : %016x", dbg_dout
),
697 If(dbg_addr
== 0b10, # PC
698 pc
.eq(dbg_dout
), # capture PC
700 #If(dbg_addr == 0b11, # MSR
701 # Display(" msr: %016x", dbg_dout),
703 If(dbg_addr
== 0b1000, # CR
704 Display(" cr : %016x", dbg_dout
),
706 If(dbg_addr
== 0b1001, # XER
707 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
708 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
710 If(dbg_addr
== 0b101, # GPR
711 Display(" gpr: %016x", dbg_dout
),
713 # also check if this is a "stat"
714 If(dbg_addr
== 1, # requested a STAT
715 #Display(" stat: %x", dbg_dout),
716 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
717 dmirunning
.eq(1), # continue running
718 dmi_monitor
.eq(0), # and stop monitor mode
726 self
.sync
+= If(uptime
== 0,
727 (dmi_addr
.eq(0), # CTRL
728 dmi_din
.eq(1<<0), # STOP
734 self
.sync
+= If(uptime
== 4,
738 self
.sync
+= If(dmirunning
,
739 dmicount
.eq(dmicount
+ 1),
742 # loop every 1<<N cycles
746 self
.sync
+= If(dmicount
== 4,
747 (dmi_addr
.eq(0b10), # NIA
754 self
.sync
+= If(dmicount
== 8,
755 (dmi_addr
.eq(0), # CTRL
756 dmi_din
.eq(1<<3), # STEP
759 dmirunning
.eq(0), # stop counter, need to fire "monitor"
760 dmi_monitor
.eq(1), # start "monitor" instead
764 # limit range of pc for debug reporting
765 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
766 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
767 self
.comb
+= active_dbg
.eq(1)
771 self
.sync
+= If(active_dbg
& (dmicount
== 12),
772 (dmi_addr
.eq(0b11), # MSR
778 if cpu
== "libresoc":
779 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
780 self
.comb
+= active_dbg_cr
.eq(0)
783 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
784 (dmi_addr
.eq(0b1000), # CR
790 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
791 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
794 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
795 (dmi_addr
.eq(0b1001), # XER
803 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
804 (dmi_addr
.eq(0b100), # GSPR addr
811 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
812 (dmi_addr
.eq(0b101), # GSPR data
818 # monitor bbus read/write
819 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
820 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
834 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
836 Display(" [%06x] iadr: %8x, s %01x w %016x",
845 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
847 Display(" [%06x] iadr: %8x, s %01x r %016x",
856 # Build -----------------------------------------------------------------------
859 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
860 parser
.add_argument("--cpu", default
="libresoc",
861 help="CPU to use: libresoc (default) or microwatt")
862 parser
.add_argument("--platform", default
="sim",
863 help="platform (sim or ls180)")
864 parser
.add_argument("--debug", action
="store_true",
865 help="Enable debug traces")
866 parser
.add_argument("--trace", action
="store_true",
867 help="Enable tracing")
868 parser
.add_argument("--trace-start", default
=0,
869 help="Cycle to start FST tracing")
870 parser
.add_argument("--trace-end", default
=-1,
871 help="Cycle to end FST tracing")
872 parser
.add_argument("--num-srams", default
=5,
873 help="number of srams")
874 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
875 args
= parser
.parse_args()
877 print ("number of SRAMs", args
.num_srams
)
879 if 'ls180' in args
.platform
:
880 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
881 platform
=args
.platform
,
882 dff_srams
=args
.num_srams
)
883 builder
= Builder(soc
, compile_gateware
= True)
884 builder
.build(run
= True)
888 sim_config
= SimConfig(default_clk
="sys_clk")
889 sim_config
.add_module("serial2console", "serial")
892 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
893 platform
=args
.platform
,
894 dff_srams
=args
.num_srams
)
895 builder
= Builder(soc
, compile_gateware
= i
!=0)
896 builder
.build(sim_config
=sim_config
,
899 trace_start
= int(args
.trace_start
),
900 trace_end
= int(args
.trace_end
),
904 if __name__
== "__main__":