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()
145 # increment counter, Stop after 100000 cycles
147 self
.sync
+= uptime
.eq(uptime
+ 1)
148 #self.sync += If(uptime == 1000000000000, Finish())
150 # DMI FSM counter and FSM itself
151 dmicount
= Signal(10)
152 dmirunning
= Signal(1)
153 dmi_monitor
= Signal(1)
155 self
.submodules
+= dmifsm
159 If(dmi_req
& dmi_wen
,
160 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
161 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
162 self
.cpu
.dmi_req
.eq(1), # DMI request
163 self
.cpu
.dmi_wr
.eq(1), # DMI write
170 If(dmi_req
& ~dmi_wen
,
171 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
172 self
.cpu
.dmi_req
.eq(1), # DMI request
173 self
.cpu
.dmi_wr
.eq(0), # DMI read
175 # acknowledge received: capture data.
177 NextValue(dbg_addr
, dmi_addr
),
178 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
179 NextValue(dbg_msg
, 1),
186 # DMI response received: reset the dmi request and check if
190 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
192 NextState("START"), # back to start on next cycle
194 NextValue(dmi_req
, 0),
195 NextValue(dmi_addr
, 0),
196 NextValue(dmi_din
, 0),
197 NextValue(dmi_wen
, 0),
200 # "monitor" mode fires off a STAT request
201 dmifsm
.act("FIRE_MONITOR",
202 (NextValue(dmi_req
, 1),
203 NextValue(dmi_addr
, 1), # DMI STAT address
204 NextValue(dmi_din
, 0),
205 NextValue(dmi_wen
, 0), # read STAT
206 NextState("START"), # back to start on next cycle
211 self
.sync
+= If(dbg_msg
,
212 (If(active_dbg
& (dbg_addr
== 0b10), # PC
213 Display("pc : %016x", dbg_dout
),
215 If(dbg_addr
== 0b10, # PC
216 pc
.eq(dbg_dout
), # capture PC
218 #If(dbg_addr == 0b11, # MSR
219 # Display(" msr: %016x", dbg_dout),
221 If(dbg_addr
== 0b1000, # CR
222 Display(" cr: %016x", dbg_dout
),
224 If(dbg_addr
== 0b101, # GPR
225 Display(" gpr: %016x", dbg_dout
),
227 # also check if this is a "stat"
228 If(dbg_addr
== 1, # requested a STAT
229 #Display(" stat: %x", dbg_dout),
230 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
231 dmirunning
.eq(1), # continue running
232 dmi_monitor
.eq(0), # and stop monitor mode
240 self
.sync
+= If(uptime
== 0,
241 (dmi_addr
.eq(0), # CTRL
242 dmi_din
.eq(1<<0), # STOP
248 self
.sync
+= If(uptime
== 4,
252 self
.sync
+= If(dmirunning
,
253 dmicount
.eq(dmicount
+ 1),
256 # loop every 1<<N cycles
260 self
.sync
+= If(dmicount
== 4,
261 (dmi_addr
.eq(0b10), # NIA
268 self
.sync
+= If(dmicount
== 8,
269 (dmi_addr
.eq(0), # CTRL
270 dmi_din
.eq(1<<3), # STEP
273 dmirunning
.eq(0), # stop counter, need to fire "monitor"
274 dmi_monitor
.eq(1), # start "monitor" instead
278 # limit range of pc for debug reporting
279 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
280 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
281 self
.comb
+= active_dbg
.eq(1)
285 self
.sync
+= If(active_dbg
& (dmicount
== 12),
286 (dmi_addr
.eq(0b11), # MSR
292 if cpu
== "libresoc":
293 self
.comb
+= active_dbg_cr
.eq((0x10300 <= pc
) & (pc
<= 0x1094c))
294 #self.comb += active_dbg_cr.eq(1)
297 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
298 (dmi_addr
.eq(0b1000), # CR
306 self
.sync
+= If(active_dbg
& (dmicount
== 20+(i
*8)),
307 (dmi_addr
.eq(0b100), # GSPR addr
314 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
315 (dmi_addr
.eq(0b101), # GSPR data
321 # monitor bbus read/write
322 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
323 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
337 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
339 Display(" [%06x] iadr: %8x, s %01x w %016x",
348 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
350 Display(" [%06x] iadr: %8x, s %01x r %016x",
359 # Build -----------------------------------------------------------------------
362 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
363 parser
.add_argument("--cpu", default
="libresoc",
364 help="CPU to use: libresoc (default) or microwatt")
365 parser
.add_argument("--debug", action
="store_true",
366 help="Enable debug traces")
367 parser
.add_argument("--trace", action
="store_true",
368 help="Enable tracing")
369 parser
.add_argument("--trace-start", default
=0,
370 help="Cycle to start FST tracing")
371 parser
.add_argument("--trace-end", default
=-1,
372 help="Cycle to end FST tracing")
373 args
= parser
.parse_args()
375 sim_config
= SimConfig(default_clk
="sys_clk")
376 sim_config
.add_module("serial2console", "serial")
379 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
)
380 builder
= Builder(soc
,compile_gateware
= i
!=0)
381 builder
.build(sim_config
=sim_config
,
384 trace_start
= int(args
.trace_start
),
385 trace_end
= int(args
.trace_end
),
389 if __name__
== "__main__":