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()
143 # increment counter, Stop after 100000 cycles
145 self
.sync
+= uptime
.eq(uptime
+ 1)
146 #self.sync += If(uptime == 1000000000000, Finish())
148 # DMI FSM counter and FSM itself
149 dmicount
= Signal(10)
150 dmirunning
= Signal(1)
151 dmi_monitor
= Signal(1)
153 self
.submodules
+= dmifsm
157 If(dmi_req
& dmi_wen
,
158 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
159 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
160 self
.cpu
.dmi_req
.eq(1), # DMI request
161 self
.cpu
.dmi_wr
.eq(1), # DMI write
168 If(dmi_req
& ~dmi_wen
,
169 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
170 self
.cpu
.dmi_req
.eq(1), # DMI request
171 self
.cpu
.dmi_wr
.eq(0), # DMI read
173 # acknowledge received: capture data.
175 NextValue(dbg_addr
, dmi_addr
),
176 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
177 NextValue(dbg_msg
, 1),
184 # DMI response received: reset the dmi request and check if
188 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
190 NextState("START"), # back to start on next cycle
192 NextValue(dmi_req
, 0),
193 NextValue(dmi_addr
, 0),
194 NextValue(dmi_din
, 0),
195 NextValue(dmi_wen
, 0),
198 # "monitor" mode fires off a STAT request
199 dmifsm
.act("FIRE_MONITOR",
200 (NextValue(dmi_req
, 1),
201 NextValue(dmi_addr
, 1), # DMI STAT address
202 NextValue(dmi_din
, 0),
203 NextValue(dmi_wen
, 0), # read STAT
204 NextState("START"), # back to start on next cycle
209 self
.sync
+= If(dbg_msg
,
210 (If(active_dbg
& (dbg_addr
== 0b10), # PC
211 Display("pc : %016x", dbg_dout
),
213 If(dbg_addr
== 0b10, # PC
214 pc
.eq(dbg_dout
), # capture PC
216 #If(dbg_addr == 0b11, # MSR
217 # Display(" msr: %016x", dbg_dout),
219 If(dbg_addr
== 0b101, # GPR
220 Display(" gpr: %016x", dbg_dout
),
222 # also check if this is a "stat"
223 If(dbg_addr
== 1, # requested a STAT
224 #Display(" stat: %x", dbg_dout),
225 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
226 dmirunning
.eq(1), # continue running
227 dmi_monitor
.eq(0), # and stop monitor mode
235 self
.sync
+= If(uptime
== 0,
236 (dmi_addr
.eq(0), # CTRL
237 dmi_din
.eq(1<<0), # STOP
243 self
.sync
+= If(uptime
== 4,
247 self
.sync
+= If(dmirunning
,
248 dmicount
.eq(dmicount
+ 1),
251 # loop every 1<<N cycles
255 self
.sync
+= If(dmicount
== 4,
256 (dmi_addr
.eq(0b10), # NIA
263 self
.sync
+= If(dmicount
== 8,
264 (dmi_addr
.eq(0), # CTRL
265 dmi_din
.eq(1<<3), # STEP
268 dmirunning
.eq(0), # stop counter, need to fire "monitor"
269 dmi_monitor
.eq(1), # start "monitor" instead
273 # limit range of pc for debug reporting
274 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
275 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
276 self
.comb
+= active_dbg
.eq(1)
279 self
.sync
+= If(active_dbg
& (dmicount
== 12),
280 (dmi_addr
.eq(0b11), # MSR
288 self
.sync
+= If(active_dbg
& (dmicount
== 14+(i
*8)),
289 (dmi_addr
.eq(0b100), # GSPR addr
296 self
.sync
+= If(active_dbg
& (dmicount
== 18+(i
*8)),
297 (dmi_addr
.eq(0b101), # GSPR data
303 # monitor bbus read/write
304 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
305 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
319 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
321 Display(" [%06x] iadr: %8x, s %01x w %016x",
330 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
332 Display(" [%06x] iadr: %8x, s %01x r %016x",
341 # Build -----------------------------------------------------------------------
344 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
345 parser
.add_argument("--cpu", default
="libresoc",
346 help="CPU to use: libresoc (default) or microwatt")
347 parser
.add_argument("--debug", action
="store_true",
348 help="Enable debug traces")
349 parser
.add_argument("--trace", action
="store_true",
350 help="Enable tracing")
351 parser
.add_argument("--trace-start", default
=0,
352 help="Cycle to start FST tracing")
353 parser
.add_argument("--trace-end", default
=-1,
354 help="Cycle to end FST tracing")
355 args
= parser
.parse_args()
357 sim_config
= SimConfig(default_clk
="sys_clk")
358 sim_config
.add_module("serial2console", "serial")
361 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
)
362 builder
= Builder(soc
,compile_gateware
= i
!=0)
363 builder
.build(sim_config
=sim_config
,
366 trace_start
= int(args
.trace_start
),
367 trace_end
= int(args
.trace_end
),
371 if __name__
== "__main__":