6 from migen
import (Signal
, FSM
, If
, Display
, Finish
, NextValue
, NextState
,
9 from litex
.build
.generic_platform
import Pins
, Subsignal
10 from litex
.build
.sim
import SimPlatform
11 from litex
.build
.io
import CRG
12 from litex
.build
.sim
.config
import SimConfig
14 from litex
.soc
.integration
.soc
import SoCRegion
15 from litex
.soc
.integration
.soc_core
import SoCCore
16 from litex
.soc
.integration
.soc_sdram
import SoCSDRAM
17 from litex
.soc
.integration
.builder
import Builder
18 from litex
.soc
.integration
.common
import get_mem_data
20 from litedram
import modules
as litedram_modules
21 from litedram
.phy
.model
import SDRAMPHYModel
22 from litedram
.phy
.gensdrphy
import GENSDRPHY
, HalfRateGENSDRPHY
24 from litex
.soc
.cores
.spi
import SPIMaster
25 from litex
.soc
.cores
.pwm
import PWM
26 from litex
.soc
.cores
.bitbang
import I2CMaster
28 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
30 from litex
.tools
.litex_sim
import Platform
31 from libresoc
.ls180
import LS180Platform
33 from migen
import Module
34 from litex
.soc
.interconnect
.csr
import AutoCSR
36 from libresoc
import LibreSoC
37 from microwatt
import Microwatt
40 from litex
.soc
.integration
.soc
import SoCCSRHandler
41 SoCCSRHandler
.supported_address_width
.append(12)
43 # GPIO Tristate -------------------------------------------------------
44 # doesn't work properly.
45 #from litex.soc.cores.gpio import GPIOTristate
46 from litex
.soc
.interconnect
.csr
import CSRStorage
, CSRStatus
47 from migen
.genlib
.cdc
import MultiReg
50 class GPIOTristateASIC(Module
, AutoCSR
):
51 def __init__(self
, pads
):
52 nbits
= len(pads
.oe
) # hack
53 self
._oe
= CSRStorage(nbits
, description
="GPIO Tristate(s) Control.")
54 self
._in
= CSRStatus(nbits
, description
="GPIO Input(s) Status.")
55 self
._out
= CSRStorage(nbits
, description
="GPIO Ouptut(s) Control.")
59 _pads
= Record( (("i", nbits
),
62 self
.comb
+= _pads
.i
.eq(pads
.i
)
63 self
.comb
+= pads
.o
.eq(_pads
.o
)
64 self
.comb
+= pads
.oe
.eq(_pads
.oe
)
66 self
.comb
+= _pads
.oe
.eq(self
._oe
.storage
)
67 self
.comb
+= _pads
.o
.eq(self
._out
.storage
)
68 for i
in range(nbits
):
69 self
.specials
+= MultiReg(_pads
.i
[i
], self
._in
.status
[i
])
72 # LibreSoCSim -----------------------------------------------------------------
74 class LibreSoCSim(SoCCore
):
75 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
76 sdram_module
= "AS4C16M16",
77 #sdram_data_width = 16,
78 #sdram_module = "MT48LC16M16",
79 sdram_data_width
= 16,
80 irq_reserved_irqs
= {'uart': 0},
83 assert cpu
in ["libresoc", "microwatt"]
84 sys_clk_freq
= int(50e6
)
89 elif platform
== 'ls180':
90 platform
= LS180Platform()
98 # reserve XICS ICP and XICS memory addresses.
99 self
.mem_map
['icp'] = 0xc0010000
100 self
.mem_map
['ics'] = 0xc0011000
101 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
102 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
106 #ram_init = get_mem_data({
107 # ram_fname: "0x00000000",
109 ram_init
= get_mem_data(ram_fname
, "little")
111 # remap the main RAM to reset-start-address
113 # without sram nothing works, therefore move it to higher up
114 self
.mem_map
["sram"] = 0x90000000
116 # put UART at 0xc000200 (w00t! this works!)
117 self
.csr_map
["uart"] = 4
119 self
.mem_map
["main_ram"] = 0x90000000
120 self
.mem_map
["sram"] = 0x00000000
122 # SoCCore -------------------------------------------------------------
123 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
124 cpu_type
= "microwatt",
125 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
127 #bus_data_width = 64,
128 csr_address_width
= 14, # limit to 0x8000
129 cpu_variant
= variant
,
132 uart_name
= uart_name
,
133 with_sdram
= with_sdram
,
134 sdram_module
= sdram_module
,
135 sdram_data_width
= sdram_data_width
,
136 integrated_rom_size
= 0, # if ram_fname else 0x10000,
137 integrated_sram_size
= 0x200,
138 #integrated_main_ram_init = ram_init,
139 integrated_main_ram_size
= 0x00000000 if with_sdram \
140 else 0x10000000 , # 256MB
142 self
.platform
.name
= "ls180"
144 # SDR SDRAM ----------------------------------------------
145 if False: # not self.integrated_main_ram_size:
146 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
148 if cpu
== "libresoc":
149 # XICS interrupt devices
150 icp_addr
= self
.mem_map
['icp']
151 icp_wb
= self
.cpu
.xics_icp
152 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
153 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
155 ics_addr
= self
.mem_map
['ics']
156 ics_wb
= self
.cpu
.xics_ics
157 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
158 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
160 # CRG -----------------------------------------------------------------
161 self
.submodules
.crg
= CRG(platform
.request("sys_clk"),
162 platform
.request("sys_rst"))
166 # SDRAM ----------------------------------------------------
168 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
169 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
170 sdram_rate
= "1:{}".format(
171 sdram_module_nphases
[sdram_module_cls
.memtype
])
172 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
173 phy_settings
= get_sdram_phy_settings(
174 memtype
= sdram_module
.memtype
,
175 data_width
= sdram_data_width
,
176 clk_freq
= sdram_clk_freq
)
177 #sdrphy_cls = HalfRateGENSDRPHY
178 sdrphy_cls
= GENSDRPHY
179 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
180 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
184 self
.add_sdram("sdram",
186 module
= sdram_module
,
187 origin
= self
.mem_map
["main_ram"],
189 l2_cache_size
= 0, # 8192
190 l2_cache_min_data_width
= 128,
191 l2_cache_reverse
= True
193 # FIXME: skip memtest to avoid corrupting memory
194 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
195 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
196 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
197 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
198 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
199 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
201 # GPIOs (bi-directional)
202 self
.submodules
.gpio
= GPIOTristateASIC(platform
.request("gpio"))
206 self
.submodules
.spi_master
= SPIMaster(
207 pads
= platform
.request("spi_master"),
209 sys_clk_freq
= sys_clk_freq
,
212 self
.add_csr("spi_master")
214 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
215 self
.comb
+= self
.cpu
.interrupt
[12:16].eq(platform
.request("eint"))
218 jtagpads
= platform
.request("jtag")
219 self
.comb
+= self
.cpu
.jtag_tck
.eq(jtagpads
.tck
)
220 self
.comb
+= self
.cpu
.jtag_tms
.eq(jtagpads
.tms
)
221 self
.comb
+= self
.cpu
.jtag_tdi
.eq(jtagpads
.tdi
)
222 self
.comb
+= jtagpads
.tdo
.eq(self
.cpu
.jtag_tdo
)
227 setattr(self
.submodules
, name
, PWM(platform
.request("pwm", i
)))
231 self
.submodules
.i2c
= I2CMaster(platform
.request("i2c"))
234 # Debug ---------------------------------------------------------------
238 # setup running of DMI FSM
241 dmi_dout
= Signal(64)
247 dbg_dout
= Signal(64)
250 # capture pc from dmi
252 active_dbg
= Signal()
253 active_dbg_cr
= Signal()
254 active_dbg_xer
= Signal()
263 # increment counter, Stop after 100000 cycles
265 self
.sync
+= uptime
.eq(uptime
+ 1)
266 #self.sync += If(uptime == 1000000000000, Finish())
268 # DMI FSM counter and FSM itself
269 dmicount
= Signal(10)
270 dmirunning
= Signal(1)
271 dmi_monitor
= Signal(1)
273 self
.submodules
+= dmifsm
277 If(dmi_req
& dmi_wen
,
278 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
279 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
280 self
.cpu
.dmi_req
.eq(1), # DMI request
281 self
.cpu
.dmi_wr
.eq(1), # DMI write
288 If(dmi_req
& ~dmi_wen
,
289 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
290 self
.cpu
.dmi_req
.eq(1), # DMI request
291 self
.cpu
.dmi_wr
.eq(0), # DMI read
293 # acknowledge received: capture data.
295 NextValue(dbg_addr
, dmi_addr
),
296 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
297 NextValue(dbg_msg
, 1),
304 # DMI response received: reset the dmi request and check if
308 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
310 NextState("START"), # back to start on next cycle
312 NextValue(dmi_req
, 0),
313 NextValue(dmi_addr
, 0),
314 NextValue(dmi_din
, 0),
315 NextValue(dmi_wen
, 0),
318 # "monitor" mode fires off a STAT request
319 dmifsm
.act("FIRE_MONITOR",
320 (NextValue(dmi_req
, 1),
321 NextValue(dmi_addr
, 1), # DMI STAT address
322 NextValue(dmi_din
, 0),
323 NextValue(dmi_wen
, 0), # read STAT
324 NextState("START"), # back to start on next cycle
328 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
329 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
330 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
331 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
332 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
335 self
.sync
+= If(dbg_msg
,
336 (If(active_dbg
& (dbg_addr
== 0b10), # PC
337 Display("pc : %016x", dbg_dout
),
339 If(dbg_addr
== 0b10, # PC
340 pc
.eq(dbg_dout
), # capture PC
342 #If(dbg_addr == 0b11, # MSR
343 # Display(" msr: %016x", dbg_dout),
345 If(dbg_addr
== 0b1000, # CR
346 Display(" cr : %016x", dbg_dout
),
348 If(dbg_addr
== 0b1001, # XER
349 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
350 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
352 If(dbg_addr
== 0b101, # GPR
353 Display(" gpr: %016x", dbg_dout
),
355 # also check if this is a "stat"
356 If(dbg_addr
== 1, # requested a STAT
357 #Display(" stat: %x", dbg_dout),
358 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
359 dmirunning
.eq(1), # continue running
360 dmi_monitor
.eq(0), # and stop monitor mode
368 self
.sync
+= If(uptime
== 0,
369 (dmi_addr
.eq(0), # CTRL
370 dmi_din
.eq(1<<0), # STOP
376 self
.sync
+= If(uptime
== 4,
380 self
.sync
+= If(dmirunning
,
381 dmicount
.eq(dmicount
+ 1),
384 # loop every 1<<N cycles
388 self
.sync
+= If(dmicount
== 4,
389 (dmi_addr
.eq(0b10), # NIA
396 self
.sync
+= If(dmicount
== 8,
397 (dmi_addr
.eq(0), # CTRL
398 dmi_din
.eq(1<<3), # STEP
401 dmirunning
.eq(0), # stop counter, need to fire "monitor"
402 dmi_monitor
.eq(1), # start "monitor" instead
406 # limit range of pc for debug reporting
407 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
408 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
409 self
.comb
+= active_dbg
.eq(1)
413 self
.sync
+= If(active_dbg
& (dmicount
== 12),
414 (dmi_addr
.eq(0b11), # MSR
420 if cpu
== "libresoc":
421 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
422 self
.comb
+= active_dbg_cr
.eq(0)
425 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
426 (dmi_addr
.eq(0b1000), # CR
432 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
433 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
436 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
437 (dmi_addr
.eq(0b1001), # XER
445 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
446 (dmi_addr
.eq(0b100), # GSPR addr
453 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
454 (dmi_addr
.eq(0b101), # GSPR data
460 # monitor bbus read/write
461 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
462 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
476 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
478 Display(" [%06x] iadr: %8x, s %01x w %016x",
487 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
489 Display(" [%06x] iadr: %8x, s %01x r %016x",
498 # Build -----------------------------------------------------------------------
501 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
502 parser
.add_argument("--cpu", default
="libresoc",
503 help="CPU to use: libresoc (default) or microwatt")
504 parser
.add_argument("--platform", default
="sim",
505 help="platform (sim or ls180)")
506 parser
.add_argument("--debug", action
="store_true",
507 help="Enable debug traces")
508 parser
.add_argument("--trace", action
="store_true",
509 help="Enable tracing")
510 parser
.add_argument("--trace-start", default
=0,
511 help="Cycle to start FST tracing")
512 parser
.add_argument("--trace-end", default
=-1,
513 help="Cycle to end FST tracing")
514 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
515 args
= parser
.parse_args()
518 if args
.platform
== 'ls180':
519 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
520 platform
=args
.platform
)
523 builder
= Builder(soc
, compile_gateware
= True)
524 builder
.build(run
= True)
528 sim_config
= SimConfig(default_clk
="sys_clk")
529 sim_config
.add_module("serial2console", "serial")
532 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
533 platform
=args
.platform
)
534 builder
= Builder(soc
, compile_gateware
= i
!=0)
535 builder
.build(sim_config
=sim_config
,
538 trace_start
= int(args
.trace_start
),
539 trace_end
= int(args
.trace_end
),
543 if __name__
== "__main__":