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 litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
23 from litex
.tools
.litex_sim
import Platform
25 from libresoc
import LibreSoC
26 from microwatt
import Microwatt
28 # LibreSoCSim -----------------------------------------------------------------
30 class LibreSoCSim(SoCSDRAM
):
31 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
32 sdram_module
= "AS4C16M16",
33 #sdram_data_width = 16,
34 #sdram_module = "MT48LC16M16",
35 sdram_data_width
= 16,
37 assert cpu
in ["libresoc", "microwatt"]
39 sys_clk_freq
= int(100e6
)
44 if cpu_data_width
== 32:
45 variant
= "standard32"
49 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
50 # "hello_world/hello_world.bin"
51 ram_fname
= "/home/lkcl/src/libresoc/microwatt/" \
53 #ram_fname = "/tmp/test.bin"
58 #ram_init = get_mem_data({
59 # ram_fname: "0x00000000",
61 ram_init
= get_mem_data(ram_fname
, "little")
63 # remap the main RAM to reset-start-address
64 self
.mem_map
["main_ram"] = 0x00000000
66 # without sram nothing works, therefore move it to higher up
67 self
.mem_map
["sram"] = 0x90000000
70 # SoCCore -------------------------------------------------------------
71 SoCSDRAM
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
72 cpu_type
= "microwatt",
73 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
76 cpu_variant
= variant
,
80 with_sdram
= with_sdram
,
81 sdram_module
= sdram_module
,
82 sdram_data_width
= sdram_data_width
,
83 integrated_rom_size
= 0 if ram_fname
else 0x10000,
84 integrated_sram_size
= 0x40000,
85 #integrated_main_ram_init = ram_init,
86 integrated_main_ram_size
= 0x00000000 if with_sdram \
87 else 0x10000000 , # 256MB
89 self
.platform
.name
= "sim"
91 # CRG -----------------------------------------------------------------
92 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
96 # SDRAM ----------------------------------------------------
98 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
99 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
100 sdram_rate
= "1:{}".format(
101 sdram_module_nphases
[sdram_module_cls
.memtype
])
102 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
103 phy_settings
= get_sdram_phy_settings(
104 memtype
= sdram_module
.memtype
,
105 data_width
= sdram_data_width
,
106 clk_freq
= sdram_clk_freq
)
107 self
.submodules
.sdrphy
= SDRAMPHYModel(sdram_module
,
113 sdram_module
.geom_settings
,
114 sdram_module
.timing_settings
)
115 # FIXME: skip memtest to avoid corrupting memory
116 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
117 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
118 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
119 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
120 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
121 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
124 # Debug ---------------------------------------------------------------
128 # setup running of DMI FSM
131 dmi_dout
= Signal(64)
137 dbg_dout
= Signal(64)
140 # capture pc from dmi
142 active_dbg
= Signal()
143 active_dbg_cr
= Signal()
144 active_dbg_xer
= Signal()
153 # increment counter, Stop after 100000 cycles
155 self
.sync
+= uptime
.eq(uptime
+ 1)
156 #self.sync += If(uptime == 1000000000000, Finish())
158 # DMI FSM counter and FSM itself
159 dmicount
= Signal(10)
160 dmirunning
= Signal(1)
161 dmi_monitor
= Signal(1)
163 self
.submodules
+= dmifsm
167 If(dmi_req
& dmi_wen
,
168 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
169 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
170 self
.cpu
.dmi_req
.eq(1), # DMI request
171 self
.cpu
.dmi_wr
.eq(1), # DMI write
178 If(dmi_req
& ~dmi_wen
,
179 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
180 self
.cpu
.dmi_req
.eq(1), # DMI request
181 self
.cpu
.dmi_wr
.eq(0), # DMI read
183 # acknowledge received: capture data.
185 NextValue(dbg_addr
, dmi_addr
),
186 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
187 NextValue(dbg_msg
, 1),
194 # DMI response received: reset the dmi request and check if
198 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
200 NextState("START"), # back to start on next cycle
202 NextValue(dmi_req
, 0),
203 NextValue(dmi_addr
, 0),
204 NextValue(dmi_din
, 0),
205 NextValue(dmi_wen
, 0),
208 # "monitor" mode fires off a STAT request
209 dmifsm
.act("FIRE_MONITOR",
210 (NextValue(dmi_req
, 1),
211 NextValue(dmi_addr
, 1), # DMI STAT address
212 NextValue(dmi_din
, 0),
213 NextValue(dmi_wen
, 0), # read STAT
214 NextState("START"), # back to start on next cycle
218 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
219 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
220 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
221 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
222 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
225 self
.sync
+= If(dbg_msg
,
226 (If(active_dbg
& (dbg_addr
== 0b10), # PC
227 Display("pc : %016x", dbg_dout
),
229 If(dbg_addr
== 0b10, # PC
230 pc
.eq(dbg_dout
), # capture PC
232 #If(dbg_addr == 0b11, # MSR
233 # Display(" msr: %016x", dbg_dout),
235 If(dbg_addr
== 0b1000, # CR
236 Display(" cr : %016x", dbg_dout
),
238 If(dbg_addr
== 0b1001, # XER
239 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
240 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
242 If(dbg_addr
== 0b101, # GPR
243 Display(" gpr: %016x", dbg_dout
),
245 # also check if this is a "stat"
246 If(dbg_addr
== 1, # requested a STAT
247 #Display(" stat: %x", dbg_dout),
248 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
249 dmirunning
.eq(1), # continue running
250 dmi_monitor
.eq(0), # and stop monitor mode
258 self
.sync
+= If(uptime
== 0,
259 (dmi_addr
.eq(0), # CTRL
260 dmi_din
.eq(1<<0), # STOP
266 self
.sync
+= If(uptime
== 4,
270 self
.sync
+= If(dmirunning
,
271 dmicount
.eq(dmicount
+ 1),
274 # loop every 1<<N cycles
278 self
.sync
+= If(dmicount
== 4,
279 (dmi_addr
.eq(0b10), # NIA
286 self
.sync
+= If(dmicount
== 8,
287 (dmi_addr
.eq(0), # CTRL
288 dmi_din
.eq(1<<3), # STEP
291 dmirunning
.eq(0), # stop counter, need to fire "monitor"
292 dmi_monitor
.eq(1), # start "monitor" instead
296 # limit range of pc for debug reporting
297 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
298 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
299 self
.comb
+= active_dbg
.eq(1)
303 self
.sync
+= If(active_dbg
& (dmicount
== 12),
304 (dmi_addr
.eq(0b11), # MSR
310 if cpu
== "libresoc":
311 self
.comb
+= active_dbg_cr
.eq((0x10300 <= pc
) & (pc
<= 0x10e00))
312 #self.comb += active_dbg_cr.eq(1)
315 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
316 (dmi_addr
.eq(0b1000), # CR
322 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
323 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
326 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
327 (dmi_addr
.eq(0b1001), # XER
335 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
336 (dmi_addr
.eq(0b100), # GSPR addr
343 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
344 (dmi_addr
.eq(0b101), # GSPR data
350 # monitor bbus read/write
351 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
352 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
366 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
368 Display(" [%06x] iadr: %8x, s %01x w %016x",
377 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
379 Display(" [%06x] iadr: %8x, s %01x r %016x",
388 # Build -----------------------------------------------------------------------
391 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
392 parser
.add_argument("--cpu", default
="libresoc",
393 help="CPU to use: libresoc (default) or microwatt")
394 parser
.add_argument("--debug", action
="store_true",
395 help="Enable debug traces")
396 parser
.add_argument("--trace", action
="store_true",
397 help="Enable tracing")
398 parser
.add_argument("--trace-start", default
=0,
399 help="Cycle to start FST tracing")
400 parser
.add_argument("--trace-end", default
=-1,
401 help="Cycle to end FST tracing")
402 args
= parser
.parse_args()
404 sim_config
= SimConfig(default_clk
="sys_clk")
405 sim_config
.add_module("serial2console", "serial")
408 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
)
409 builder
= Builder(soc
,compile_gateware
= i
!=0)
410 builder
.build(sim_config
=sim_config
,
413 trace_start
= int(args
.trace_start
),
414 trace_end
= int(args
.trace_end
),
418 if __name__
== "__main__":