6 from migen
import (Signal
, FSM
, If
, Display
, Finish
, NextValue
, NextState
)
8 from litex
.build
.generic_platform
import Pins
, Subsignal
9 from litex
.build
.sim
import SimPlatform
10 from litex
.build
.io
import CRG
11 from litex
.build
.sim
.config
import SimConfig
13 from litex
.soc
.integration
.soc
import SoCRegion
14 from litex
.soc
.integration
.soc_core
import SoCCore
15 from litex
.soc
.integration
.soc_sdram
import SoCSDRAM
16 from litex
.soc
.integration
.builder
import Builder
17 from litex
.soc
.integration
.common
import get_mem_data
19 from litedram
import modules
as litedram_modules
20 from litedram
.phy
.model
import SDRAMPHYModel
21 from litedram
.phy
.gensdrphy
import GENSDRPHY
, HalfRateGENSDRPHY
23 from litex
.soc
.cores
.gpio
import GPIOInOut
, GPIOIn
, GPIOOut
#, GPIOTristate
24 from litex
.soc
.cores
.spi
import SPIMaster
26 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
28 from litex
.tools
.litex_sim
import Platform
29 from libresoc
.ls180
import LS180Platform
31 from migen
import Module
32 from litex
.soc
.interconnect
.csr
import AutoCSR
34 from libresoc
import LibreSoC
35 from microwatt
import Microwatt
38 from litex
.soc
.integration
.soc
import SoCCSRHandler
39 SoCCSRHandler
.supported_address_width
.append(12)
42 # LibreSoCSim -----------------------------------------------------------------
44 class LibreSoCSim(SoCCore
):
45 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
46 sdram_module
= "AS4C16M16",
47 #sdram_data_width = 16,
48 #sdram_module = "MT48LC16M16",
49 sdram_data_width
= 16,
50 irq_reserved_irqs
= {'uart': 0},
53 assert cpu
in ["libresoc", "microwatt"]
54 sys_clk_freq
= int(50e6
)
59 elif platform
== 'ls180':
60 platform
= LS180Platform()
68 # reserve XICS ICP and XICS memory addresses.
69 self
.mem_map
['icp'] = 0xc0010000
70 self
.mem_map
['ics'] = 0xc0011000
71 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
72 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
76 #ram_init = get_mem_data({
77 # ram_fname: "0x00000000",
79 ram_init
= get_mem_data(ram_fname
, "little")
81 # remap the main RAM to reset-start-address
83 # without sram nothing works, therefore move it to higher up
84 self
.mem_map
["sram"] = 0x90000000
86 # put UART at 0xc000200 (w00t! this works!)
87 self
.csr_map
["uart"] = 4
89 self
.mem_map
["main_ram"] = 0x90000000
90 self
.mem_map
["sram"] = 0x00000000
92 # SoCCore -------------------------------------------------------------
93 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
94 cpu_type
= "microwatt",
95 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
98 csr_address_width
= 14, # limit to 0x8000
99 cpu_variant
= variant
,
102 uart_name
= uart_name
,
103 with_sdram
= with_sdram
,
104 sdram_module
= sdram_module
,
105 sdram_data_width
= sdram_data_width
,
106 integrated_rom_size
= 0, # if ram_fname else 0x10000,
107 integrated_sram_size
= 0x200,
108 #integrated_main_ram_init = ram_init,
109 integrated_main_ram_size
= 0x00000000 if with_sdram \
110 else 0x10000000 , # 256MB
112 self
.platform
.name
= "ls180"
114 # SDR SDRAM ----------------------------------------------
115 if False: # not self.integrated_main_ram_size:
116 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
119 if cpu
== "libresoc":
120 # XICS interrupt devices
121 icp_addr
= self
.mem_map
['icp']
122 icp_wb
= self
.cpu
.xics_icp
123 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
124 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
126 ics_addr
= self
.mem_map
['ics']
127 ics_wb
= self
.cpu
.xics_ics
128 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
129 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
131 # CRG -----------------------------------------------------------------
132 self
.submodules
.crg
= CRG(platform
.request("sys_clk"),
133 platform
.request("sys_rst"))
137 # SDRAM ----------------------------------------------------
139 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
140 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
141 sdram_rate
= "1:{}".format(
142 sdram_module_nphases
[sdram_module_cls
.memtype
])
143 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
144 phy_settings
= get_sdram_phy_settings(
145 memtype
= sdram_module
.memtype
,
146 data_width
= sdram_data_width
,
147 clk_freq
= sdram_clk_freq
)
148 #sdrphy_cls = HalfRateGENSDRPHY
149 sdrphy_cls
= GENSDRPHY
150 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
151 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
155 self
.add_sdram("sdram",
157 module
= sdram_module
,
158 origin
= self
.mem_map
["main_ram"],
160 l2_cache_size
= 0, # 8192
161 l2_cache_min_data_width
= 128,
162 l2_cache_reverse
= True
164 # FIXME: skip memtest to avoid corrupting memory
165 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
166 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
167 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
168 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
169 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
170 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
173 #platform.add_extension([("gpio_in", 0, Pins(8))])
174 self
.submodules
.gpio_in
= GPIOIn(platform
.request("gpio_in"))
175 self
.add_csr("gpio_in")
176 self
.submodules
.gpio_out
= GPIOIn(platform
.request("gpio_out"))
177 self
.add_csr("gpio_out")
180 self
.submodules
.gpio
= GPIOTristate(platform
.request("gpio"))
184 self
.submodules
.spi_master
= SPIMaster(
185 pads
= platform
.request("spi_master"),
187 sys_clk_freq
= sys_clk_freq
,
190 self
.add_csr("spi_master")
192 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
193 self
.comb
+= self
.cpu
.interrupt
[12:16].eq(platform
.request("eint"))
195 # Debug ---------------------------------------------------------------
199 # setup running of DMI FSM
202 dmi_dout
= Signal(64)
208 dbg_dout
= Signal(64)
211 # capture pc from dmi
213 active_dbg
= Signal()
214 active_dbg_cr
= Signal()
215 active_dbg_xer
= Signal()
224 # increment counter, Stop after 100000 cycles
226 self
.sync
+= uptime
.eq(uptime
+ 1)
227 #self.sync += If(uptime == 1000000000000, Finish())
229 # DMI FSM counter and FSM itself
230 dmicount
= Signal(10)
231 dmirunning
= Signal(1)
232 dmi_monitor
= Signal(1)
234 self
.submodules
+= dmifsm
238 If(dmi_req
& dmi_wen
,
239 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
240 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
241 self
.cpu
.dmi_req
.eq(1), # DMI request
242 self
.cpu
.dmi_wr
.eq(1), # DMI write
249 If(dmi_req
& ~dmi_wen
,
250 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
251 self
.cpu
.dmi_req
.eq(1), # DMI request
252 self
.cpu
.dmi_wr
.eq(0), # DMI read
254 # acknowledge received: capture data.
256 NextValue(dbg_addr
, dmi_addr
),
257 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
258 NextValue(dbg_msg
, 1),
265 # DMI response received: reset the dmi request and check if
269 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
271 NextState("START"), # back to start on next cycle
273 NextValue(dmi_req
, 0),
274 NextValue(dmi_addr
, 0),
275 NextValue(dmi_din
, 0),
276 NextValue(dmi_wen
, 0),
279 # "monitor" mode fires off a STAT request
280 dmifsm
.act("FIRE_MONITOR",
281 (NextValue(dmi_req
, 1),
282 NextValue(dmi_addr
, 1), # DMI STAT address
283 NextValue(dmi_din
, 0),
284 NextValue(dmi_wen
, 0), # read STAT
285 NextState("START"), # back to start on next cycle
289 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
290 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
291 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
292 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
293 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
296 self
.sync
+= If(dbg_msg
,
297 (If(active_dbg
& (dbg_addr
== 0b10), # PC
298 Display("pc : %016x", dbg_dout
),
300 If(dbg_addr
== 0b10, # PC
301 pc
.eq(dbg_dout
), # capture PC
303 #If(dbg_addr == 0b11, # MSR
304 # Display(" msr: %016x", dbg_dout),
306 If(dbg_addr
== 0b1000, # CR
307 Display(" cr : %016x", dbg_dout
),
309 If(dbg_addr
== 0b1001, # XER
310 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
311 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
313 If(dbg_addr
== 0b101, # GPR
314 Display(" gpr: %016x", dbg_dout
),
316 # also check if this is a "stat"
317 If(dbg_addr
== 1, # requested a STAT
318 #Display(" stat: %x", dbg_dout),
319 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
320 dmirunning
.eq(1), # continue running
321 dmi_monitor
.eq(0), # and stop monitor mode
329 self
.sync
+= If(uptime
== 0,
330 (dmi_addr
.eq(0), # CTRL
331 dmi_din
.eq(1<<0), # STOP
337 self
.sync
+= If(uptime
== 4,
341 self
.sync
+= If(dmirunning
,
342 dmicount
.eq(dmicount
+ 1),
345 # loop every 1<<N cycles
349 self
.sync
+= If(dmicount
== 4,
350 (dmi_addr
.eq(0b10), # NIA
357 self
.sync
+= If(dmicount
== 8,
358 (dmi_addr
.eq(0), # CTRL
359 dmi_din
.eq(1<<3), # STEP
362 dmirunning
.eq(0), # stop counter, need to fire "monitor"
363 dmi_monitor
.eq(1), # start "monitor" instead
367 # limit range of pc for debug reporting
368 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
369 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
370 self
.comb
+= active_dbg
.eq(1)
374 self
.sync
+= If(active_dbg
& (dmicount
== 12),
375 (dmi_addr
.eq(0b11), # MSR
381 if cpu
== "libresoc":
382 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
383 self
.comb
+= active_dbg_cr
.eq(0)
386 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
387 (dmi_addr
.eq(0b1000), # CR
393 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
394 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
397 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
398 (dmi_addr
.eq(0b1001), # XER
406 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
407 (dmi_addr
.eq(0b100), # GSPR addr
414 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
415 (dmi_addr
.eq(0b101), # GSPR data
421 # monitor bbus read/write
422 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
423 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
437 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
439 Display(" [%06x] iadr: %8x, s %01x w %016x",
448 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
450 Display(" [%06x] iadr: %8x, s %01x r %016x",
459 # Build -----------------------------------------------------------------------
462 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
463 parser
.add_argument("--cpu", default
="libresoc",
464 help="CPU to use: libresoc (default) or microwatt")
465 parser
.add_argument("--platform", default
="sim",
466 help="platform (sim or ls180)")
467 parser
.add_argument("--debug", action
="store_true",
468 help="Enable debug traces")
469 parser
.add_argument("--trace", action
="store_true",
470 help="Enable tracing")
471 parser
.add_argument("--trace-start", default
=0,
472 help="Cycle to start FST tracing")
473 parser
.add_argument("--trace-end", default
=-1,
474 help="Cycle to end FST tracing")
475 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
476 args
= parser
.parse_args()
479 if args
.platform
== 'ls180':
480 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
481 platform
=args
.platform
)
484 builder
= Builder(soc
, compile_gateware
= True)
485 builder
.build(run
= True)
489 sim_config
= SimConfig(default_clk
="sys_clk")
490 sim_config
.add_module("serial2console", "serial")
493 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
494 platform
=args
.platform
)
495 builder
= Builder(soc
, compile_gateware
= i
!=0)
496 builder
.build(sim_config
=sim_config
,
499 trace_start
= int(args
.trace_start
),
500 trace_end
= int(args
.trace_end
),
504 if __name__
== "__main__":