c797a43d8ba56d698e624ac7a0dc152f31226fe6
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
29 from litex
.soc
.integration
.soc
import SoCCSRHandler
30 SoCCSRHandler
.supported_address_width
.append(12)
32 # LibreSoCSim -----------------------------------------------------------------
34 class LibreSoCSim(SoCSDRAM
):
35 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
36 sdram_module
= "AS4C16M16",
37 #sdram_data_width = 16,
38 #sdram_module = "MT48LC16M16",
39 sdram_data_width
= 16,
40 irq_reserved_irqs
= {'uart': 0},
42 assert cpu
in ["libresoc", "microwatt"]
44 sys_clk_freq
= int(100e6
)
49 if cpu_data_width
== 32:
50 variant
= "standard32"
52 variant
= "standardjtag"
54 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
55 # "hello_world/hello_world.bin"
56 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
58 #ram_fname = "/tmp/test.bin"
59 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
60 # "micropython/firmware.bin"
61 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
62 # "tests/xics/xics.bin"
63 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
64 # "tests/decrementer/decrementer.bin"
65 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
66 # "hello_world/hello_world.bin"
69 # reserve XICS ICP and XICS memory addresses.
70 self
.mem_map
['icp'] = 0xc0004000
71 self
.mem_map
['ics'] = 0xc0005000
72 self
.mem_map
['gpio'] = 0xc0007000
73 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
74 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
78 #ram_init = get_mem_data({
79 # ram_fname: "0x00000000",
81 ram_init
= get_mem_data(ram_fname
, "little")
83 # remap the main RAM to reset-start-address
84 self
.mem_map
["main_ram"] = 0x00000000
86 # without sram nothing works, therefore move it to higher up
87 self
.mem_map
["sram"] = 0x90000000
89 # put UART at 0xc000200 (w00t! this works!)
90 self
.csr_map
["uart"] = 4
93 # SoCCore -------------------------------------------------------------
94 SoCSDRAM
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
95 cpu_type
= "microwatt",
96 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
99 csr_address_width
= 12, # limit to 0x4000
100 cpu_variant
= variant
,
104 with_sdram
= with_sdram
,
105 sdram_module
= sdram_module
,
106 sdram_data_width
= sdram_data_width
,
107 integrated_rom_size
= 0 if ram_fname
else 0x10000,
108 integrated_sram_size
= 0x40000,
109 #integrated_main_ram_init = ram_init,
110 integrated_main_ram_size
= 0x00000000 if with_sdram \
111 else 0x10000000 , # 256MB
113 self
.platform
.name
= "sim"
115 if cpu
== "libresoc":
116 # XICS interrupt devices
117 icp_addr
= self
.mem_map
['icp']
118 icp_wb
= self
.cpu
.xics_icp
119 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
120 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
122 ics_addr
= self
.mem_map
['ics']
123 ics_wb
= self
.cpu
.xics_ics
124 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
125 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
127 # Simple GPIO peripheral
128 gpio_addr
= self
.mem_map
['gpio']
129 gpio_wb
= self
.cpu
.simple_gpio
130 gpio_region
= SoCRegion(origin
=gpio_addr
, size
=0x20, cached
=False)
131 self
.bus
.add_slave(name
='gpio', slave
=gpio_wb
, region
=gpio_region
)
134 # CRG -----------------------------------------------------------------
135 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
139 # SDRAM ----------------------------------------------------
141 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
142 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
143 sdram_rate
= "1:{}".format(
144 sdram_module_nphases
[sdram_module_cls
.memtype
])
145 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
146 phy_settings
= get_sdram_phy_settings(
147 memtype
= sdram_module
.memtype
,
148 data_width
= sdram_data_width
,
149 clk_freq
= sdram_clk_freq
)
150 self
.submodules
.sdrphy
= SDRAMPHYModel(sdram_module
,
156 sdram_module
.geom_settings
,
157 sdram_module
.timing_settings
)
158 # FIXME: skip memtest to avoid corrupting memory
159 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
160 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
161 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
162 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
163 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
164 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
167 # add JTAG platform pins
168 platform
.add_extension([
170 Subsignal("tck", Pins(1)),
171 Subsignal("tms", Pins(1)),
172 Subsignal("tdi", Pins(1)),
173 Subsignal("tdo", Pins(1)),
177 jtagpads
= platform
.request("jtag")
178 self
.comb
+= self
.cpu
.jtag_tck
.eq(jtagpads
.tck
)
179 self
.comb
+= self
.cpu
.jtag_tms
.eq(jtagpads
.tms
)
180 self
.comb
+= self
.cpu
.jtag_tdi
.eq(jtagpads
.tdi
)
181 self
.comb
+= jtagpads
.tdo
.eq(self
.cpu
.jtag_tdo
)
184 # Debug ---------------------------------------------------------------
188 # setup running of DMI FSM
191 dmi_dout
= Signal(64)
197 dbg_dout
= Signal(64)
200 # capture pc from dmi
202 active_dbg
= Signal()
203 active_dbg_cr
= Signal()
204 active_dbg_xer
= Signal()
213 # increment counter, Stop after 100000 cycles
215 self
.sync
+= uptime
.eq(uptime
+ 1)
216 #self.sync += If(uptime == 1000000000000, Finish())
218 # DMI FSM counter and FSM itself
219 dmicount
= Signal(10)
220 dmirunning
= Signal(1)
221 dmi_monitor
= Signal(1)
223 self
.submodules
+= dmifsm
227 If(dmi_req
& dmi_wen
,
228 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
229 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
230 self
.cpu
.dmi_req
.eq(1), # DMI request
231 self
.cpu
.dmi_wr
.eq(1), # DMI write
238 If(dmi_req
& ~dmi_wen
,
239 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
240 self
.cpu
.dmi_req
.eq(1), # DMI request
241 self
.cpu
.dmi_wr
.eq(0), # DMI read
243 # acknowledge received: capture data.
245 NextValue(dbg_addr
, dmi_addr
),
246 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
247 NextValue(dbg_msg
, 1),
254 # DMI response received: reset the dmi request and check if
258 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
260 NextState("START"), # back to start on next cycle
262 NextValue(dmi_req
, 0),
263 NextValue(dmi_addr
, 0),
264 NextValue(dmi_din
, 0),
265 NextValue(dmi_wen
, 0),
268 # "monitor" mode fires off a STAT request
269 dmifsm
.act("FIRE_MONITOR",
270 (NextValue(dmi_req
, 1),
271 NextValue(dmi_addr
, 1), # DMI STAT address
272 NextValue(dmi_din
, 0),
273 NextValue(dmi_wen
, 0), # read STAT
274 NextState("START"), # back to start on next cycle
278 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
279 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
280 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
281 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
282 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
285 self
.sync
+= If(dbg_msg
,
286 (If(active_dbg
& (dbg_addr
== 0b10), # PC
287 Display("pc : %016x", dbg_dout
),
289 If(dbg_addr
== 0b10, # PC
290 pc
.eq(dbg_dout
), # capture PC
292 #If(dbg_addr == 0b11, # MSR
293 # Display(" msr: %016x", dbg_dout),
295 If(dbg_addr
== 0b1000, # CR
296 Display(" cr : %016x", dbg_dout
),
298 If(dbg_addr
== 0b1001, # XER
299 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
300 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
302 If(dbg_addr
== 0b101, # GPR
303 Display(" gpr: %016x", dbg_dout
),
305 # also check if this is a "stat"
306 If(dbg_addr
== 1, # requested a STAT
307 #Display(" stat: %x", dbg_dout),
308 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
309 dmirunning
.eq(1), # continue running
310 dmi_monitor
.eq(0), # and stop monitor mode
318 self
.sync
+= If(uptime
== 0,
319 (dmi_addr
.eq(0), # CTRL
320 dmi_din
.eq(1<<0), # STOP
326 self
.sync
+= If(uptime
== 4,
330 self
.sync
+= If(dmirunning
,
331 dmicount
.eq(dmicount
+ 1),
334 # loop every 1<<N cycles
338 self
.sync
+= If(dmicount
== 4,
339 (dmi_addr
.eq(0b10), # NIA
346 self
.sync
+= If(dmicount
== 8,
347 (dmi_addr
.eq(0), # CTRL
348 dmi_din
.eq(1<<3), # STEP
351 dmirunning
.eq(0), # stop counter, need to fire "monitor"
352 dmi_monitor
.eq(1), # start "monitor" instead
356 # limit range of pc for debug reporting
357 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
358 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
359 self
.comb
+= active_dbg
.eq(1)
363 self
.sync
+= If(active_dbg
& (dmicount
== 12),
364 (dmi_addr
.eq(0b11), # MSR
370 if cpu
== "libresoc":
371 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
372 self
.comb
+= active_dbg_cr
.eq(0)
375 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
376 (dmi_addr
.eq(0b1000), # CR
382 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
383 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
386 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
387 (dmi_addr
.eq(0b1001), # XER
395 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
396 (dmi_addr
.eq(0b100), # GSPR addr
403 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
404 (dmi_addr
.eq(0b101), # GSPR data
410 # monitor bbus read/write
411 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
412 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
426 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
428 Display(" [%06x] iadr: %8x, s %01x w %016x",
437 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
439 Display(" [%06x] iadr: %8x, s %01x r %016x",
448 # Build -----------------------------------------------------------------------
451 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
452 parser
.add_argument("--cpu", default
="libresoc",
453 help="CPU to use: libresoc (default) or microwatt")
454 parser
.add_argument("--debug", action
="store_true",
455 help="Enable debug traces")
456 parser
.add_argument("--trace", action
="store_true",
457 help="Enable tracing")
458 parser
.add_argument("--trace-start", default
=0,
459 help="Cycle to start FST tracing")
460 parser
.add_argument("--trace-end", default
=-1,
461 help="Cycle to end FST tracing")
462 args
= parser
.parse_args()
464 sim_config
= SimConfig(default_clk
="sys_clk")
465 sim_config
.add_module("serial2console", "serial")
466 sim_config
.add_module("jtagremote", "jtag", args
={'port': 44853})
469 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
)
470 builder
= Builder(soc
,compile_gateware
= i
!=0)
471 builder
.build(sim_config
=sim_config
,
474 trace_start
= int(args
.trace_start
),
475 trace_end
= int(args
.trace_end
),
479 if __name__
== "__main__":