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/" \
57 #ram_init = get_mem_data({
58 # ram_fname: "0x00000000",
60 ram_init
= get_mem_data(ram_fname
, "little")
62 # remap the main RAM to reset-start-address
63 self
.mem_map
["main_ram"] = 0x00000000
65 # without sram nothing works, therefore move it to higher up
66 self
.mem_map
["sram"] = 0x90000000
69 # SoCCore -------------------------------------------------------------
70 SoCSDRAM
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
71 cpu_type
= "microwatt",
72 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
75 cpu_variant
= variant
,
79 with_sdram
= with_sdram
,
80 sdram_module
= sdram_module
,
81 sdram_data_width
= sdram_data_width
,
82 integrated_rom_size
= 0 if ram_fname
else 0x10000,
83 integrated_sram_size
= 0x40000,
84 #integrated_main_ram_init = ram_init,
85 integrated_main_ram_size
= 0x00000000 if with_sdram \
86 else 0x10000000 , # 256MB
88 self
.platform
.name
= "sim"
90 # CRG -----------------------------------------------------------------
91 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
95 # SDRAM ----------------------------------------------------
97 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
98 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
99 sdram_rate
= "1:{}".format(
100 sdram_module_nphases
[sdram_module_cls
.memtype
])
101 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
102 phy_settings
= get_sdram_phy_settings(
103 memtype
= sdram_module
.memtype
,
104 data_width
= sdram_data_width
,
105 clk_freq
= sdram_clk_freq
)
106 self
.submodules
.sdrphy
= SDRAMPHYModel(sdram_module
,
112 sdram_module
.geom_settings
,
113 sdram_module
.timing_settings
)
114 # FIXME: skip memtest to avoid corrupting memory
115 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
116 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
117 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
118 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
119 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
120 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
123 # Debug ---------------------------------------------------------------
127 # setup running of DMI FSM
130 dmi_dout
= Signal(64)
136 dbg_dout
= Signal(64)
139 # capture pc from dmi
141 active_dbg
= Signal()
142 active_dbg_cr
= Signal()
144 # increment counter, Stop after 100000 cycles
146 self
.sync
+= uptime
.eq(uptime
+ 1)
147 #self.sync += If(uptime == 1000000000000, Finish())
149 # DMI FSM counter and FSM itself
150 dmicount
= Signal(10)
151 dmirunning
= Signal(1)
152 dmi_monitor
= Signal(1)
154 self
.submodules
+= dmifsm
158 If(dmi_req
& dmi_wen
,
159 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
160 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
161 self
.cpu
.dmi_req
.eq(1), # DMI request
162 self
.cpu
.dmi_wr
.eq(1), # DMI write
169 If(dmi_req
& ~dmi_wen
,
170 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
171 self
.cpu
.dmi_req
.eq(1), # DMI request
172 self
.cpu
.dmi_wr
.eq(0), # DMI read
174 # acknowledge received: capture data.
176 NextValue(dbg_addr
, dmi_addr
),
177 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
178 NextValue(dbg_msg
, 1),
185 # DMI response received: reset the dmi request and check if
189 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
191 NextState("START"), # back to start on next cycle
193 NextValue(dmi_req
, 0),
194 NextValue(dmi_addr
, 0),
195 NextValue(dmi_din
, 0),
196 NextValue(dmi_wen
, 0),
199 # "monitor" mode fires off a STAT request
200 dmifsm
.act("FIRE_MONITOR",
201 (NextValue(dmi_req
, 1),
202 NextValue(dmi_addr
, 1), # DMI STAT address
203 NextValue(dmi_din
, 0),
204 NextValue(dmi_wen
, 0), # read STAT
205 NextState("START"), # back to start on next cycle
210 self
.sync
+= If(dbg_msg
,
211 (If(active_dbg
& (dbg_addr
== 0b10), # PC
212 Display("pc : %016x", dbg_dout
),
214 If(dbg_addr
== 0b10, # PC
215 pc
.eq(dbg_dout
), # capture PC
217 #If(dbg_addr == 0b11, # MSR
218 # Display(" msr: %016x", dbg_dout),
220 If(dbg_addr
== 0b1000, # CR
221 Display(" cr: %016x", dbg_dout
),
223 If(dbg_addr
== 0b101, # GPR
224 Display(" gpr: %016x", dbg_dout
),
226 # also check if this is a "stat"
227 If(dbg_addr
== 1, # requested a STAT
228 #Display(" stat: %x", dbg_dout),
229 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
230 dmirunning
.eq(1), # continue running
231 dmi_monitor
.eq(0), # and stop monitor mode
239 self
.sync
+= If(uptime
== 0,
240 (dmi_addr
.eq(0), # CTRL
241 dmi_din
.eq(1<<0), # STOP
247 self
.sync
+= If(uptime
== 4,
251 self
.sync
+= If(dmirunning
,
252 dmicount
.eq(dmicount
+ 1),
255 # loop every 1<<N cycles
259 self
.sync
+= If(dmicount
== 4,
260 (dmi_addr
.eq(0b10), # NIA
267 self
.sync
+= If(dmicount
== 8,
268 (dmi_addr
.eq(0), # CTRL
269 dmi_din
.eq(1<<3), # STEP
272 dmirunning
.eq(0), # stop counter, need to fire "monitor"
273 dmi_monitor
.eq(1), # start "monitor" instead
277 # limit range of pc for debug reporting
278 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
279 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
280 self
.comb
+= active_dbg
.eq(1)
284 self
.sync
+= If(active_dbg
& (dmicount
== 12),
285 (dmi_addr
.eq(0b11), # MSR
291 if cpu
== "libresoc":
292 self
.comb
+= active_dbg_cr
.eq((0x10300 <= pc
) & (pc
<= 0x105ec))
293 #self.comb += active_dbg_cr.eq(1)
296 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
297 (dmi_addr
.eq(0b1000), # CR
305 self
.sync
+= If(active_dbg
& (dmicount
== 20+(i
*8)),
306 (dmi_addr
.eq(0b100), # GSPR addr
313 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
314 (dmi_addr
.eq(0b101), # GSPR data
320 # monitor bbus read/write
321 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
322 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
336 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
338 Display(" [%06x] iadr: %8x, s %01x w %016x",
347 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
349 Display(" [%06x] iadr: %8x, s %01x r %016x",
358 # Build -----------------------------------------------------------------------
361 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
362 parser
.add_argument("--cpu", default
="libresoc",
363 help="CPU to use: libresoc (default) or microwatt")
364 parser
.add_argument("--debug", action
="store_true",
365 help="Enable debug traces")
366 parser
.add_argument("--trace", action
="store_true",
367 help="Enable tracing")
368 parser
.add_argument("--trace-start", default
=0,
369 help="Cycle to start FST tracing")
370 parser
.add_argument("--trace-end", default
=-1,
371 help="Cycle to end FST tracing")
372 args
= parser
.parse_args()
374 sim_config
= SimConfig(default_clk
="sys_clk")
375 sim_config
.add_module("serial2console", "serial")
378 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
)
379 builder
= Builder(soc
,compile_gateware
= i
!=0)
380 builder
.build(sim_config
=sim_config
,
383 trace_start
= int(args
.trace_start
),
384 trace_end
= int(args
.trace_end
),
388 if __name__
== "__main__":