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()
146 # increment counter, Stop after 100000 cycles
148 self
.sync
+= uptime
.eq(uptime
+ 1)
149 #self.sync += If(uptime == 1000000000000, Finish())
151 # DMI FSM counter and FSM itself
152 dmicount
= Signal(10)
153 dmirunning
= Signal(1)
154 dmi_monitor
= Signal(1)
156 self
.submodules
+= dmifsm
160 If(dmi_req
& dmi_wen
,
161 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
162 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
163 self
.cpu
.dmi_req
.eq(1), # DMI request
164 self
.cpu
.dmi_wr
.eq(1), # DMI write
171 If(dmi_req
& ~dmi_wen
,
172 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
173 self
.cpu
.dmi_req
.eq(1), # DMI request
174 self
.cpu
.dmi_wr
.eq(0), # DMI read
176 # acknowledge received: capture data.
178 NextValue(dbg_addr
, dmi_addr
),
179 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
180 NextValue(dbg_msg
, 1),
187 # DMI response received: reset the dmi request and check if
191 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
193 NextState("START"), # back to start on next cycle
195 NextValue(dmi_req
, 0),
196 NextValue(dmi_addr
, 0),
197 NextValue(dmi_din
, 0),
198 NextValue(dmi_wen
, 0),
201 # "monitor" mode fires off a STAT request
202 dmifsm
.act("FIRE_MONITOR",
203 (NextValue(dmi_req
, 1),
204 NextValue(dmi_addr
, 1), # DMI STAT address
205 NextValue(dmi_din
, 0),
206 NextValue(dmi_wen
, 0), # read STAT
207 NextState("START"), # back to start on next cycle
212 self
.sync
+= If(dbg_msg
,
213 (If(active_dbg
& (dbg_addr
== 0b10), # PC
214 Display("pc : %016x", dbg_dout
),
216 If(dbg_addr
== 0b10, # PC
217 pc
.eq(dbg_dout
), # capture PC
219 #If(dbg_addr == 0b11, # MSR
220 # Display(" msr: %016x", dbg_dout),
222 If(dbg_addr
== 0b1000, # CR
223 Display(" cr : %016x", dbg_dout
),
225 If(dbg_addr
== 0b1001, # XER
226 Display(" xer: %016x", dbg_dout
),
228 If(dbg_addr
== 0b101, # GPR
229 Display(" gpr: %016x", dbg_dout
),
231 # also check if this is a "stat"
232 If(dbg_addr
== 1, # requested a STAT
233 #Display(" stat: %x", dbg_dout),
234 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
235 dmirunning
.eq(1), # continue running
236 dmi_monitor
.eq(0), # and stop monitor mode
244 self
.sync
+= If(uptime
== 0,
245 (dmi_addr
.eq(0), # CTRL
246 dmi_din
.eq(1<<0), # STOP
252 self
.sync
+= If(uptime
== 4,
256 self
.sync
+= If(dmirunning
,
257 dmicount
.eq(dmicount
+ 1),
260 # loop every 1<<N cycles
264 self
.sync
+= If(dmicount
== 4,
265 (dmi_addr
.eq(0b10), # NIA
272 self
.sync
+= If(dmicount
== 8,
273 (dmi_addr
.eq(0), # CTRL
274 dmi_din
.eq(1<<3), # STEP
277 dmirunning
.eq(0), # stop counter, need to fire "monitor"
278 dmi_monitor
.eq(1), # start "monitor" instead
282 # limit range of pc for debug reporting
283 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
284 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
285 self
.comb
+= active_dbg
.eq(1)
289 self
.sync
+= If(active_dbg
& (dmicount
== 12),
290 (dmi_addr
.eq(0b11), # MSR
296 if cpu
== "libresoc":
297 self
.comb
+= active_dbg_cr
.eq((0x10300 <= pc
) & (pc
<= 0x1094c))
298 #self.comb += active_dbg_cr.eq(1)
301 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
302 (dmi_addr
.eq(0b1000), # CR
308 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
309 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
312 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
313 (dmi_addr
.eq(0b1001), # XER
321 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
322 (dmi_addr
.eq(0b100), # GSPR addr
329 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
330 (dmi_addr
.eq(0b101), # GSPR data
336 # monitor bbus read/write
337 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
338 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
352 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
354 Display(" [%06x] iadr: %8x, s %01x w %016x",
363 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
365 Display(" [%06x] iadr: %8x, s %01x r %016x",
374 # Build -----------------------------------------------------------------------
377 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
378 parser
.add_argument("--cpu", default
="libresoc",
379 help="CPU to use: libresoc (default) or microwatt")
380 parser
.add_argument("--debug", action
="store_true",
381 help="Enable debug traces")
382 parser
.add_argument("--trace", action
="store_true",
383 help="Enable tracing")
384 parser
.add_argument("--trace-start", default
=0,
385 help="Cycle to start FST tracing")
386 parser
.add_argument("--trace-end", default
=-1,
387 help="Cycle to end FST tracing")
388 args
= parser
.parse_args()
390 sim_config
= SimConfig(default_clk
="sys_clk")
391 sim_config
.add_module("serial2console", "serial")
394 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
)
395 builder
= Builder(soc
,compile_gateware
= i
!=0)
396 builder
.build(sim_config
=sim_config
,
399 trace_start
= int(args
.trace_start
),
400 trace_end
= int(args
.trace_end
),
404 if __name__
== "__main__":