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
.sim
import SimPlatform
12 from litex
.build
.io
import CRG
13 from litex
.build
.sim
.config
import SimConfig
15 from litex
.soc
.integration
.soc
import SoCRegion
16 from litex
.soc
.integration
.soc_core
import SoCCore
17 from litex
.soc
.integration
.soc_sdram
import SoCSDRAM
18 from litex
.soc
.integration
.builder
import Builder
19 from litex
.soc
.integration
.common
import get_mem_data
21 from litedram
import modules
as litedram_modules
22 from litedram
.phy
.model
import SDRAMPHYModel
23 #from litedram.phy.gensdrphy import GENSDRPHY, HalfRateGENSDRPHY
24 from litedram
.common
import PHYPadsCombiner
, PhySettings
25 from litedram
.phy
.dfi
import Interface
as DFIInterface
26 from litex
.soc
.cores
.spi
import SPIMaster
27 from litex
.soc
.cores
.pwm
import PWM
28 #from litex.soc.cores.bitbang import I2CMaster
29 from litex
.soc
.cores
import uart
31 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
33 from litex
.tools
.litex_sim
import Platform
34 from libresoc
.ls180
import LS180Platform
, io
36 from migen
import Module
37 from litex
.soc
.interconnect
.csr
import AutoCSR
39 from libresoc
import LibreSoC
40 from microwatt
import Microwatt
43 from litex
.soc
.integration
.soc
import SoCCSRHandler
44 SoCCSRHandler
.supported_address_width
.append(12)
46 # GPIO Tristate -------------------------------------------------------
47 # doesn't work properly.
48 #from litex.soc.cores.gpio import GPIOTristate
49 from litex
.soc
.interconnect
.csr
import CSRStorage
, CSRStatus
, CSRField
50 from migen
.genlib
.cdc
import MultiReg
53 from litex
.soc
.interconnect
import wishbone
54 from litesdcard
.phy
import (SDPHY
, SDPHYClocker
,
55 SDPHYInit
, SDPHYCMDW
, SDPHYCMDR
,
56 SDPHYDATAW
, SDPHYDATAR
,
58 from litesdcard
.core
import SDCore
59 from litesdcard
.frontend
.dma
import SDBlock2MemDMA
, SDMem2BlockDMA
60 from litex
.build
.io
import SDROutput
, SDRInput
62 from soc
.debug
.jtag
import Pins
, dummy_pinset
# TODO move to suitable location
63 from c4m
.nmigen
.jtag
.tap
import IOType
64 from litex
.build
.generic_platform
import ConstraintManager
67 def make_pad(res
, dirn
, name
, suffix
, cpup
, iop
):
68 cpud
, iod
= ('i', 'o') if dirn
else ('o', 'i')
69 res
['%s_%s__core__%s' % (cpud
, name
, suffix
)] = cpup
70 res
['%s_%s__pad__%s' % (iod
, name
, suffix
)] = iop
73 def make_jtag_ioconn(res
, pin
, cpupads
, iopads
):
74 (fn
, pin
, iotype
, pin_name
, scan_idx
) = pin
75 #serial_tx__core__o, serial_rx__pad__i,
76 print ("cpupads", cpupads
)
77 print ("iopads", iopads
)
78 print ("pin", fn
, pin
, iotype
, pin_name
)
83 name
= "%s_%s" % (fn
, pin
)
85 if iotype
in (IOType
.In
, IOType
.Out
):
86 cpup
= getattr(cpu
, pin
)
87 iop
= getattr(io
, pin
)
89 if iotype
== IOType
.Out
:
90 # output from the pad is routed through C4M JTAG and so
91 # is an *INPUT* into core. ls180soc connects this to "real" peripheral
92 make_pad(res
, True, name
, "o", cpup
, iop
)
94 elif iotype
== IOType
.In
:
95 # input to the pad is routed through C4M JTAG and so
96 # is an *OUTPUT* into core. ls180soc connects this to "real" peripheral
97 make_pad(res
, False, name
, "i", cpup
, iop
)
99 elif iotype
== IOType
.InTriOut
:
100 if fn
== 'gpio': # sigh decode GPIO special-case
102 cpup
, iop
= cpu
.i
[idx
], io
.i
[idx
]
103 make_pad(res
, False, name
, "i", cpup
, iop
)
104 cpup
, iop
= cpu
.o
[idx
], io
.o
[idx
]
105 make_pad(res
, True, name
, "o", cpup
, iop
)
106 cpup
, iop
= cpu
.oe
[idx
], io
.oe
[idx
]
107 make_pad(res
, True, name
, "oe", cpup
, iop
)
109 if iotype
in (IOType
.In
, IOType
.InTriOut
):
110 sigs
.append(("i", 1))
111 if iotype
in (IOType
.Out
, IOType
.TriOut
, IOType
.InTriOut
):
112 sigs
.append(("o", 1))
113 if iotype
in (IOType
.TriOut
, IOType
.InTriOut
):
114 sigs
.append(("oe", 1))
117 # I2C Master Bit-Banging --------------------------------------------------
119 class I2CMaster(Module
, AutoCSR
):
120 """I2C Master Bit-Banging
122 Provides the minimal hardware to do software I2C Master bit banging.
124 On the same write CSRStorage (_w), software can control SCL (I2C_SCL),
125 SDA direction and value (I2C_OE, I2C_W). Software get back SDA value
126 with the read CSRStatus (_r).
128 pads_layout
= [("scl", 1), ("sda", 1)]
129 def __init__(self
, pads
):
131 self
._w
= CSRStorage(fields
=[
132 CSRField("scl", size
=1, offset
=0),
133 CSRField("oe", size
=1, offset
=1),
134 CSRField("sda", size
=1, offset
=2)],
136 self
._r
= CSRStatus(fields
=[
137 CSRField("sda", size
=1, offset
=0)],
142 def connect(self
, pads
):
147 pads
.scl
.eq(self
._w
.fields
.scl
),
148 pads
.sda_oe
.eq( self
._w
.fields
.oe
),
149 pads
.sda_o
.eq( self
._w
.fields
.sda
),
150 self
._r
.fields
.sda
.eq(pads
.sda_i
),
154 class GPIOTristateASIC(Module
, AutoCSR
):
155 def __init__(self
, pads
):
156 nbits
= len(pads
.oe
) # hack
157 self
._oe
= CSRStorage(nbits
, description
="GPIO Tristate(s) Control.")
158 self
._in
= CSRStatus(nbits
, description
="GPIO Input(s) Status.")
159 self
._out
= CSRStorage(nbits
, description
="GPIO Ouptut(s) Control.")
163 _pads
= Record( (("i", nbits
),
166 self
.comb
+= _pads
.i
.eq(pads
.i
)
167 self
.comb
+= pads
.o
.eq(_pads
.o
)
168 self
.comb
+= pads
.oe
.eq(_pads
.oe
)
170 self
.comb
+= _pads
.oe
.eq(self
._oe
.storage
)
171 self
.comb
+= _pads
.o
.eq(self
._out
.storage
)
172 for i
in range(nbits
):
173 self
.specials
+= MultiReg(_pads
.i
[i
], self
._in
.status
[i
])
175 # SDCard PHY IO -------------------------------------------------------
177 class SDRPad(Module
):
178 def __init__(self
, pad
, name
, o
, oe
, i
):
180 _o
= getattr(pad
, "%s_o" % name
)
181 _oe
= getattr(pad
, "%s_oe" % name
)
182 _i
= getattr(pad
, "%s_i" % name
)
183 self
.specials
+= SDROutput(clk
=clk
, i
=oe
, o
=_oe
)
184 for j
in range(len(_o
)):
185 self
.specials
+= SDROutput(clk
=clk
, i
=o
[j
], o
=_o
[j
])
186 self
.specials
+= SDRInput(clk
=clk
, i
=_i
[j
], o
=i
[j
])
189 class SDPHYIOGen(Module
):
190 def __init__(self
, clocker
, sdpads
, pads
):
192 if hasattr(pads
, "rst"):
193 self
.comb
+= pads
.rst
.eq(0)
196 self
.specials
+= SDROutput(
198 i
= ~clocker
.clk
& sdpads
.clk
,
204 self
.submodules
.sd_cmd
= SDRPad(pads
, "cmd", c
.o
, c
.oe
, c
.i
)
208 self
.submodules
.sd_data
= SDRPad(pads
, "data", d
.o
, d
.oe
, d
.i
)
211 class SDPHY(Module
, AutoCSR
):
212 def __init__(self
, pads
, device
, sys_clk_freq
,
213 cmd_timeout
=10e-3, data_timeout
=10e-3):
214 self
.card_detect
= CSRStatus() # Assume SDCard is present if no cd pin.
215 self
.comb
+= self
.card_detect
.status
.eq(getattr(pads
, "cd", 0))
217 self
.submodules
.clocker
= clocker
= SDPHYClocker()
218 self
.submodules
.init
= init
= SDPHYInit()
219 self
.submodules
.cmdw
= cmdw
= SDPHYCMDW()
220 self
.submodules
.cmdr
= cmdr
= SDPHYCMDR(sys_clk_freq
,
222 self
.submodules
.dataw
= dataw
= SDPHYDATAW()
223 self
.submodules
.datar
= datar
= SDPHYDATAR(sys_clk_freq
,
228 self
.sdpads
= sdpads
= Record(_sdpads_layout
)
231 sdphy_cls
= SDPHYIOGen
232 self
.submodules
.io
= sdphy_cls(clocker
, sdpads
, pads
)
234 # Connect pads_out of submodules to physical pads --------------
235 pl
= [init
, cmdw
, cmdr
, dataw
, datar
]
237 sdpads
.clk
.eq( reduce(or_
, [m
.pads_out
.clk
for m
in pl
])),
238 sdpads
.cmd
.oe
.eq( reduce(or_
, [m
.pads_out
.cmd
.oe
for m
in pl
])),
239 sdpads
.cmd
.o
.eq( reduce(or_
, [m
.pads_out
.cmd
.o
for m
in pl
])),
240 sdpads
.data
.oe
.eq(reduce(or_
, [m
.pads_out
.data
.oe
for m
in pl
])),
241 sdpads
.data
.o
.eq( reduce(or_
, [m
.pads_out
.data
.o
for m
in pl
])),
244 self
.comb
+= m
.pads_out
.ready
.eq(self
.clocker
.ce
)
246 # Connect physical pads to pads_in of submodules ---------------
248 self
.comb
+= m
.pads_in
.valid
.eq(self
.clocker
.ce
)
249 self
.comb
+= m
.pads_in
.cmd
.i
.eq(sdpads
.cmd
.i
)
250 self
.comb
+= m
.pads_in
.data
.i
.eq(sdpads
.data
.i
)
252 # Speed Throttling -------------------------------------------
253 self
.comb
+= clocker
.stop
.eq(dataw
.stop | datar
.stop
)
256 # Generic SDR PHY ---------------------------------------------------------
258 class GENSDRPHY(Module
):
259 def __init__(self
, pads
, cl
=2, cmd_latency
=1):
260 pads
= PHYPadsCombiner(pads
)
261 addressbits
= len(pads
.a
)
262 bankbits
= len(pads
.ba
)
263 nranks
= 1 if not hasattr(pads
, "cs_n") else len(pads
.cs_n
)
264 databits
= len(pads
.dq_i
)
266 assert databits
%8 == 0
268 # PHY settings ----------------------------------------------------
269 self
.settings
= PhySettings(
270 phytype
= "GENSDRPHY",
273 dfi_databits
= databits
,
281 read_latency
= cl
+ cmd_latency
,
285 # DFI Interface ---------------------------------------------------
286 self
.dfi
= dfi
= DFIInterface(addressbits
, bankbits
, nranks
, databits
)
290 # Iterate on pads groups ------------------------------------------
291 for pads_group
in range(len(pads
.groups
)):
292 pads
.sel_group(pads_group
)
294 # Addresses and Commands --------------------------------------
296 self
.specials
+= [SDROutput(i
=p0
.address
[i
], o
=pads
.a
[i
])
297 for i
in range(len(pads
.a
))]
298 self
.specials
+= [SDROutput(i
=p0
.bank
[i
], o
=pads
.ba
[i
])
299 for i
in range(len(pads
.ba
))]
300 self
.specials
+= SDROutput(i
=p0
.cas_n
, o
=pads
.cas_n
)
301 self
.specials
+= SDROutput(i
=p0
.ras_n
, o
=pads
.ras_n
)
302 self
.specials
+= SDROutput(i
=p0
.we_n
, o
=pads
.we_n
)
303 if hasattr(pads
, "cke"):
304 for i
in range(len(pads
.cke
)):
305 self
.specials
+= SDROutput(i
=p0
.cke
[i
], o
=pads
.cke
[i
])
306 if hasattr(pads
, "cs_n"):
307 for i
in range(len(pads
.cs_n
)):
308 self
.specials
+= SDROutput(i
=p0
.cs_n
[i
], o
=pads
.cs_n
[i
])
310 # DQ/DM Data Path -------------------------------------------------
314 self
.submodules
.dq
= SDRPad(pads
, "dq", d
.wrdata
, d
.wrdata_en
, d
.rddata
)
316 if hasattr(pads
, "dm"):
317 for i
in range(len(pads
.dm
)):
318 self
.specials
+= SDROutput(i
=d
.wrdata_mask
[i
], o
=pads
.dm
[i
])
320 # DQ/DM Control Path ----------------------------------------------
321 rddata_en
= Signal(cl
+ cmd_latency
)
322 self
.sync
+= rddata_en
.eq(Cat(dfi
.p0
.rddata_en
, rddata_en
))
323 self
.sync
+= dfi
.p0
.rddata_valid
.eq(rddata_en
[-1])
326 # LibreSoC 180nm ASIC -------------------------------------------------------
328 class LibreSoCSim(SoCCore
):
329 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
330 sdram_module
= "AS4C16M16",
331 #sdram_data_width = 16,
332 #sdram_module = "MT48LC16M16",
333 sdram_data_width
= 16,
334 irq_reserved_irqs
= {'uart': 0},
337 assert cpu
in ["libresoc", "microwatt"]
338 sys_clk_freq
= int(50e6
)
340 if platform
== 'sim':
341 platform
= Platform()
343 elif platform
== 'ls180':
344 platform
= LS180Platform()
352 # reserve XICS ICP and XICS memory addresses.
353 self
.mem_map
['icp'] = 0xc0010000
354 self
.mem_map
['ics'] = 0xc0011000
355 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
356 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
360 #ram_init = get_mem_data({
361 # ram_fname: "0x00000000",
363 ram_init
= get_mem_data(ram_fname
, "little")
365 # remap the main RAM to reset-start-address
367 # without sram nothing works, therefore move it to higher up
368 self
.mem_map
["sram"] = 0x90000000
370 # put UART at 0xc000200 (w00t! this works!)
371 self
.csr_map
["uart"] = 4
373 self
.mem_map
["main_ram"] = 0x90000000
374 self
.mem_map
["sram"] = 0x00000000
376 # SoCCore -------------------------------------------------------------
377 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
378 cpu_type
= "microwatt",
379 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
381 #bus_data_width = 64,
382 csr_address_width
= 14, # limit to 0x8000
383 cpu_variant
= variant
,
388 with_sdram
= with_sdram
,
389 sdram_module
= sdram_module
,
390 sdram_data_width
= sdram_data_width
,
391 integrated_rom_size
= 0, # if ram_fname else 0x10000,
392 integrated_sram_size
= 0x200,
393 #integrated_main_ram_init = ram_init,
394 integrated_main_ram_size
= 0x00000000 if with_sdram \
395 else 0x10000000 , # 256MB
397 self
.platform
.name
= "ls180"
399 # Create link pads --------------------------------------------------
401 # urr yuk. have to expose iopads / pins from core to litex
402 # then back again. cut _some_ of that out by connecting
403 self
.cpuresources
= io()
404 self
.padresources
= io()
405 self
.cpu_cm
= ConstraintManager(self
.cpuresources
, [])
406 self
.pad_cm
= ConstraintManager(self
.cpuresources
, [])
407 self
.cpupads
= {'uart': self
.cpu_cm
.request('uart', 0),
408 'gpio': self
.cpu_cm
.request('gpio', 0)}
409 self
.iopads
= {'uart': self
.pad_cm
.request('uart', 0),
410 'gpio': self
.pad_cm
.request('gpio', 0)}
412 p
= Pins(dummy_pinset())
414 make_jtag_ioconn(self
.cpu
.cpu_params
, pin
, self
.cpupads
,
417 # SDR SDRAM ----------------------------------------------
418 if False: # not self.integrated_main_ram_size:
419 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
421 if cpu
== "libresoc":
422 # XICS interrupt devices
423 icp_addr
= self
.mem_map
['icp']
424 icp_wb
= self
.cpu
.xics_icp
425 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
426 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
428 ics_addr
= self
.mem_map
['ics']
429 ics_wb
= self
.cpu
.xics_ics
430 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
431 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
433 # CRG -----------------------------------------------------------------
434 self
.submodules
.crg
= CRG(platform
.request("sys_clk"),
435 platform
.request("sys_rst"))
438 clksel_i
= platform
.request("sys_clksel_i")
439 pll48_o
= platform
.request("sys_pll_48_o")
441 self
.comb
+= self
.cpu
.clk_sel
.eq(clksel_i
) # allow clock src select
442 self
.comb
+= pll48_o
.eq(self
.cpu
.pll_48_o
) # "test feed" from the PLL
446 # SDRAM ----------------------------------------------------
448 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
449 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
450 sdram_rate
= "1:{}".format(
451 sdram_module_nphases
[sdram_module_cls
.memtype
])
452 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
453 phy_settings
= get_sdram_phy_settings(
454 memtype
= sdram_module
.memtype
,
455 data_width
= sdram_data_width
,
456 clk_freq
= sdram_clk_freq
)
457 #sdrphy_cls = HalfRateGENSDRPHY
458 sdrphy_cls
= GENSDRPHY
459 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
460 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
464 self
.add_sdram("sdram",
466 module
= sdram_module
,
467 origin
= self
.mem_map
["main_ram"],
469 l2_cache_size
= 0, # 8192
470 l2_cache_min_data_width
= 128,
471 l2_cache_reverse
= True
473 # FIXME: skip memtest to avoid corrupting memory
474 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
475 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
476 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
477 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
478 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
479 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
482 sys_clk
= ClockSignal()
483 sdr_clk
= platform
.request("sdram_clock")
484 #self.specials += DDROutput(1, 0, , sdram_clk)
485 self
.specials
+= SDROutput(clk
=sys_clk
, i
=sys_clk
, o
=sdr_clk
)
488 uart_core_pads
= self
.cpupads
['uart']
489 self
.submodules
.uart_phy
= uart
.UARTPHY(
490 pads
= uart_core_pads
,
491 clk_freq
= self
.sys_clk_freq
,
493 self
.submodules
.uart
= ResetInserter()(uart
.UART(self
.uart_phy
,
496 # "real" pads connect to C4M JTAG iopad
497 uart_pads
= platform
.request(uart_name
) # "real" (actual) pin
498 uart_io_pads
= self
.iopads
['uart'] # C4M JTAG pads
499 self
.comb
+= uart_pads
.tx
.eq(uart_io_pads
.tx
)
500 self
.comb
+= uart_io_pads
.rx
.eq(uart_pads
.rx
)
502 self
.csr
.add("uart_phy", use_loc_if_exists
=True)
503 self
.csr
.add("uart", use_loc_if_exists
=True)
504 self
.irq
.add("uart", use_loc_if_exists
=True)
506 # GPIOs (bi-directional)
507 gpio_core_pads
= self
.cpupads
['gpio']
508 self
.submodules
.gpio
= GPIOTristateASIC(gpio_core_pads
)
511 gpio_pads
= platform
.request("gpio") # "real" (actual) pins
512 gpio_io_pads
= self
.iopads
['gpio'] # C4M JTAG pads
513 self
.comb
+= gpio_io_pads
.i
.eq(gpio_pads
.i
)
514 self
.comb
+= gpio_pads
.o
.eq(gpio_io_pads
.o
)
515 self
.comb
+= gpio_pads
.oe
.eq(gpio_io_pads
.oe
)
518 self
.submodules
.spi_master
= SPIMaster(
519 pads
= platform
.request("spi_master"),
521 sys_clk_freq
= sys_clk_freq
,
524 self
.add_csr("spi_master")
526 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
527 self
.comb
+= self
.cpu
.interrupt
[12:16].eq(platform
.request("eint"))
530 jtagpads
= platform
.request("jtag")
531 self
.comb
+= self
.cpu
.jtag_tck
.eq(jtagpads
.tck
)
532 self
.comb
+= self
.cpu
.jtag_tms
.eq(jtagpads
.tms
)
533 self
.comb
+= self
.cpu
.jtag_tdi
.eq(jtagpads
.tdi
)
534 self
.comb
+= jtagpads
.tdo
.eq(self
.cpu
.jtag_tdo
)
536 # NC - allows some iopads to be connected up
537 # sigh, just do something, anything, to stop yosys optimising these out
538 nc_pads
= platform
.request("nc")
539 num_nc
= len(nc_pads
)
540 self
.nc
= Signal(num_nc
)
541 self
.comb
+= self
.nc
.eq(nc_pads
)
542 self
.dummy
= Signal(num_nc
)
543 for i
in range(num_nc
):
544 self
.sync
+= self
.dummy
[i
].eq(self
.nc
[i
] | self
.cpu
.interrupt
[0])
549 setattr(self
.submodules
, name
, PWM(platform
.request("pwm", i
)))
553 self
.submodules
.i2c
= I2CMaster(platform
.request("i2c"))
556 # SDCard -----------------------------------------------------
559 sdcard_pads
= self
.platform
.request("sdcard")
562 self
.submodules
.sdphy
= SDPHY(sdcard_pads
,
563 self
.platform
.device
, self
.clk_freq
)
564 self
.submodules
.sdcore
= SDCore(self
.sdphy
)
565 self
.add_csr("sdphy")
566 self
.add_csr("sdcore")
569 bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
,
570 adr_width
=self
.bus
.address_width
)
571 self
.submodules
.sdblock2mem
= SDBlock2MemDMA(bus
=bus
,
572 endianness
=self
.cpu
.endianness
)
573 self
.comb
+= self
.sdcore
.source
.connect(self
.sdblock2mem
.sink
)
574 dma_bus
= self
.bus
if not hasattr(self
, "dma_bus") else self
.dma_bus
575 dma_bus
.add_master("sdblock2mem", master
=bus
)
576 self
.add_csr("sdblock2mem")
579 bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
,
580 adr_width
=self
.bus
.address_width
)
581 self
.submodules
.sdmem2block
= SDMem2BlockDMA(bus
=bus
,
582 endianness
=self
.cpu
.endianness
)
583 self
.comb
+= self
.sdmem2block
.source
.connect(self
.sdcore
.sink
)
584 dma_bus
= self
.bus
if not hasattr(self
, "dma_bus") else self
.dma_bus
585 dma_bus
.add_master("sdmem2block", master
=bus
)
586 self
.add_csr("sdmem2block")
588 # Debug ---------------------------------------------------------------
592 # setup running of DMI FSM
595 dmi_dout
= Signal(64)
601 dbg_dout
= Signal(64)
604 # capture pc from dmi
606 active_dbg
= Signal()
607 active_dbg_cr
= Signal()
608 active_dbg_xer
= Signal()
617 # increment counter, Stop after 100000 cycles
619 self
.sync
+= uptime
.eq(uptime
+ 1)
620 #self.sync += If(uptime == 1000000000000, Finish())
622 # DMI FSM counter and FSM itself
623 dmicount
= Signal(10)
624 dmirunning
= Signal(1)
625 dmi_monitor
= Signal(1)
627 self
.submodules
+= dmifsm
631 If(dmi_req
& dmi_wen
,
632 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
633 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
634 self
.cpu
.dmi_req
.eq(1), # DMI request
635 self
.cpu
.dmi_wr
.eq(1), # DMI write
642 If(dmi_req
& ~dmi_wen
,
643 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
644 self
.cpu
.dmi_req
.eq(1), # DMI request
645 self
.cpu
.dmi_wr
.eq(0), # DMI read
647 # acknowledge received: capture data.
649 NextValue(dbg_addr
, dmi_addr
),
650 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
651 NextValue(dbg_msg
, 1),
658 # DMI response received: reset the dmi request and check if
662 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
664 NextState("START"), # back to start on next cycle
666 NextValue(dmi_req
, 0),
667 NextValue(dmi_addr
, 0),
668 NextValue(dmi_din
, 0),
669 NextValue(dmi_wen
, 0),
672 # "monitor" mode fires off a STAT request
673 dmifsm
.act("FIRE_MONITOR",
674 (NextValue(dmi_req
, 1),
675 NextValue(dmi_addr
, 1), # DMI STAT address
676 NextValue(dmi_din
, 0),
677 NextValue(dmi_wen
, 0), # read STAT
678 NextState("START"), # back to start on next cycle
682 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
683 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
684 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
685 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
686 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
689 self
.sync
+= If(dbg_msg
,
690 (If(active_dbg
& (dbg_addr
== 0b10), # PC
691 Display("pc : %016x", dbg_dout
),
693 If(dbg_addr
== 0b10, # PC
694 pc
.eq(dbg_dout
), # capture PC
696 #If(dbg_addr == 0b11, # MSR
697 # Display(" msr: %016x", dbg_dout),
699 If(dbg_addr
== 0b1000, # CR
700 Display(" cr : %016x", dbg_dout
),
702 If(dbg_addr
== 0b1001, # XER
703 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
704 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
706 If(dbg_addr
== 0b101, # GPR
707 Display(" gpr: %016x", dbg_dout
),
709 # also check if this is a "stat"
710 If(dbg_addr
== 1, # requested a STAT
711 #Display(" stat: %x", dbg_dout),
712 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
713 dmirunning
.eq(1), # continue running
714 dmi_monitor
.eq(0), # and stop monitor mode
722 self
.sync
+= If(uptime
== 0,
723 (dmi_addr
.eq(0), # CTRL
724 dmi_din
.eq(1<<0), # STOP
730 self
.sync
+= If(uptime
== 4,
734 self
.sync
+= If(dmirunning
,
735 dmicount
.eq(dmicount
+ 1),
738 # loop every 1<<N cycles
742 self
.sync
+= If(dmicount
== 4,
743 (dmi_addr
.eq(0b10), # NIA
750 self
.sync
+= If(dmicount
== 8,
751 (dmi_addr
.eq(0), # CTRL
752 dmi_din
.eq(1<<3), # STEP
755 dmirunning
.eq(0), # stop counter, need to fire "monitor"
756 dmi_monitor
.eq(1), # start "monitor" instead
760 # limit range of pc for debug reporting
761 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
762 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
763 self
.comb
+= active_dbg
.eq(1)
767 self
.sync
+= If(active_dbg
& (dmicount
== 12),
768 (dmi_addr
.eq(0b11), # MSR
774 if cpu
== "libresoc":
775 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
776 self
.comb
+= active_dbg_cr
.eq(0)
779 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
780 (dmi_addr
.eq(0b1000), # CR
786 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
787 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
790 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
791 (dmi_addr
.eq(0b1001), # XER
799 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
800 (dmi_addr
.eq(0b100), # GSPR addr
807 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
808 (dmi_addr
.eq(0b101), # GSPR data
814 # monitor bbus read/write
815 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
816 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
830 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
832 Display(" [%06x] iadr: %8x, s %01x w %016x",
841 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
843 Display(" [%06x] iadr: %8x, s %01x r %016x",
852 # Build -----------------------------------------------------------------------
855 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
856 parser
.add_argument("--cpu", default
="libresoc",
857 help="CPU to use: libresoc (default) or microwatt")
858 parser
.add_argument("--platform", default
="sim",
859 help="platform (sim or ls180)")
860 parser
.add_argument("--debug", action
="store_true",
861 help="Enable debug traces")
862 parser
.add_argument("--trace", action
="store_true",
863 help="Enable tracing")
864 parser
.add_argument("--trace-start", default
=0,
865 help="Cycle to start FST tracing")
866 parser
.add_argument("--trace-end", default
=-1,
867 help="Cycle to end FST tracing")
868 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
869 args
= parser
.parse_args()
872 if args
.platform
== 'ls180':
873 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
874 platform
=args
.platform
)
876 builder
= Builder(soc
, compile_gateware
= True)
877 builder
.build(run
= True)
881 sim_config
= SimConfig(default_clk
="sys_clk")
882 sim_config
.add_module("serial2console", "serial")
885 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
886 platform
=args
.platform
)
887 builder
= Builder(soc
, compile_gateware
= i
!=0)
888 builder
.build(sim_config
=sim_config
,
891 trace_start
= int(args
.trace_start
),
892 trace_end
= int(args
.trace_end
),
896 if __name__
== "__main__":