cdbcef133a61d16e882c0f9d23b16cf0d8654f0f
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 litedram
.phy
.gensdrphy
import GENSDRPHY
, HalfRateGENSDRPHY
23 from litex
.soc
.cores
.gpio
import GPIOInOut
, GPIOIn
, GPIOOut
24 from litex
.soc
.cores
.spi
import SPIMaster
26 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
28 from litex
.tools
.litex_sim
import Platform
29 from libresoc
.ls180
import LS180Platform
31 from migen
import Module
32 from litex
.soc
.interconnect
.csr
import AutoCSR
34 from libresoc
import LibreSoC
35 from microwatt
import Microwatt
38 from litex
.soc
.integration
.soc
import SoCCSRHandler
39 SoCCSRHandler
.supported_address_width
.append(12)
42 # LibreSoCSim -----------------------------------------------------------------
44 class LibreSoCSim(SoCCore
):
45 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
46 sdram_module
= "AS4C16M16",
47 #sdram_data_width = 16,
48 #sdram_module = "MT48LC16M16",
49 sdram_data_width
= 16,
50 irq_reserved_irqs
= {'uart': 0},
53 assert cpu
in ["libresoc", "microwatt"]
54 sys_clk_freq
= int(50e6
)
59 elif platform
== 'ls180':
60 platform
= LS180Platform()
66 if cpu_data_width
== 32:
67 variant
= "standard32"
71 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
72 # "hello_world/hello_world.bin"
73 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
75 #ram_fname = "/tmp/test.bin"
77 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
78 # "micropython/firmware.bin"
79 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
80 # "tests/xics/xics.bin"
81 ram_fname
= "/home/lkcl/src/libresoc/microwatt/" \
82 "tests/decrementer/decrementer.bin"
83 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
84 # "hello_world/hello_world.bin"
86 # reserve XICS ICP and XICS memory addresses.
87 self
.mem_map
['icp'] = 0xc0010000
88 self
.mem_map
['ics'] = 0xc0011000
89 self
.mem_map
['gpio'] = 0xc0012000
90 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
91 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
95 #ram_init = get_mem_data({
96 # ram_fname: "0x00000000",
98 ram_init
= get_mem_data(ram_fname
, "little")
100 # remap the main RAM to reset-start-address
101 self
.mem_map
["main_ram"] = 0x00000000
103 # without sram nothing works, therefore move it to higher up
104 self
.mem_map
["sram"] = 0x90000000
106 # put UART at 0xc000200 (w00t! this works!)
107 self
.csr_map
["uart"] = 4
110 # SoCCore -------------------------------------------------------------
111 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
112 cpu_type
= "microwatt",
113 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
115 #bus_data_width = 64,
116 csr_address_width
= 14, # limit to 0x8000
117 cpu_variant
= variant
,
120 uart_name
= uart_name
,
121 with_sdram
= with_sdram
,
122 sdram_module
= sdram_module
,
123 sdram_data_width
= sdram_data_width
,
124 integrated_rom_size
= 0 if ram_fname
else 0x10000,
125 integrated_sram_size
= 0x40000,
126 #integrated_main_ram_init = ram_init,
127 integrated_main_ram_size
= 0x00000000 if with_sdram \
128 else 0x10000000 , # 256MB
130 self
.platform
.name
= "sim"
132 # SDR SDRAM ----------------------------------------------
133 if False: # not self.integrated_main_ram_size:
134 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
137 if cpu
== "libresoc":
138 # XICS interrupt devices
139 icp_addr
= self
.mem_map
['icp']
140 icp_wb
= self
.cpu
.xics_icp
141 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
142 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
144 ics_addr
= self
.mem_map
['ics']
145 ics_wb
= self
.cpu
.xics_ics
146 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
147 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
149 # Simple GPIO peripheral
150 gpio_addr
= self
.mem_map
['gpio']
151 gpio_wb
= self
.cpu
.simple_gpio
152 gpio_region
= SoCRegion(origin
=gpio_addr
, size
=0x20, cached
=False)
153 self
.bus
.add_slave(name
='gpio', slave
=gpio_wb
, region
=gpio_region
)
156 # CRG -----------------------------------------------------------------
157 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
161 # SDRAM ----------------------------------------------------
163 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
164 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
165 sdram_rate
= "1:{}".format(
166 sdram_module_nphases
[sdram_module_cls
.memtype
])
167 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
168 phy_settings
= get_sdram_phy_settings(
169 memtype
= sdram_module
.memtype
,
170 data_width
= sdram_data_width
,
171 clk_freq
= sdram_clk_freq
)
172 #sdrphy_cls = HalfRateGENSDRPHY
173 sdrphy_cls
= GENSDRPHY
174 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
175 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
179 self
.add_sdram("sdram",
181 module
= sdram_module
,
182 origin
= self
.mem_map
["main_ram"],
184 l2_cache_size
= 0, # 8192
185 l2_cache_min_data_width
= 128,
186 l2_cache_reverse
= True
188 # FIXME: skip memtest to avoid corrupting memory
189 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
190 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
191 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
192 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
193 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
194 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
197 #platform.add_extension([("gpio_in", 0, Pins(8))])
198 self
.submodules
.gpio_in
= GPIOIn(platform
.request("gpio_in"))
199 self
.add_csr("gpio_in")
200 self
.submodules
.gpio_out
= GPIOIn(platform
.request("gpio_out"))
201 self
.add_csr("gpio_out")
204 self
.submodules
.spi_master
= SPIMaster(
205 pads
= platform
.request("spi_master"),
207 sys_clk_freq
= sys_clk_freq
,
210 self
.add_csr("spi_master")
212 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
213 self
.comb
+= self
.cpu
.interrupt
[12:16].eq(platform
.request("eint"))
215 # Debug ---------------------------------------------------------------
219 # setup running of DMI FSM
222 dmi_dout
= Signal(64)
228 dbg_dout
= Signal(64)
231 # capture pc from dmi
233 active_dbg
= Signal()
234 active_dbg_cr
= Signal()
235 active_dbg_xer
= Signal()
244 # increment counter, Stop after 100000 cycles
246 self
.sync
+= uptime
.eq(uptime
+ 1)
247 #self.sync += If(uptime == 1000000000000, Finish())
249 # DMI FSM counter and FSM itself
250 dmicount
= Signal(10)
251 dmirunning
= Signal(1)
252 dmi_monitor
= Signal(1)
254 self
.submodules
+= dmifsm
258 If(dmi_req
& dmi_wen
,
259 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
260 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
261 self
.cpu
.dmi_req
.eq(1), # DMI request
262 self
.cpu
.dmi_wr
.eq(1), # DMI write
269 If(dmi_req
& ~dmi_wen
,
270 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
271 self
.cpu
.dmi_req
.eq(1), # DMI request
272 self
.cpu
.dmi_wr
.eq(0), # DMI read
274 # acknowledge received: capture data.
276 NextValue(dbg_addr
, dmi_addr
),
277 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
278 NextValue(dbg_msg
, 1),
285 # DMI response received: reset the dmi request and check if
289 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
291 NextState("START"), # back to start on next cycle
293 NextValue(dmi_req
, 0),
294 NextValue(dmi_addr
, 0),
295 NextValue(dmi_din
, 0),
296 NextValue(dmi_wen
, 0),
299 # "monitor" mode fires off a STAT request
300 dmifsm
.act("FIRE_MONITOR",
301 (NextValue(dmi_req
, 1),
302 NextValue(dmi_addr
, 1), # DMI STAT address
303 NextValue(dmi_din
, 0),
304 NextValue(dmi_wen
, 0), # read STAT
305 NextState("START"), # back to start on next cycle
309 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
310 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
311 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
312 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
313 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
316 self
.sync
+= If(dbg_msg
,
317 (If(active_dbg
& (dbg_addr
== 0b10), # PC
318 Display("pc : %016x", dbg_dout
),
320 If(dbg_addr
== 0b10, # PC
321 pc
.eq(dbg_dout
), # capture PC
323 #If(dbg_addr == 0b11, # MSR
324 # Display(" msr: %016x", dbg_dout),
326 If(dbg_addr
== 0b1000, # CR
327 Display(" cr : %016x", dbg_dout
),
329 If(dbg_addr
== 0b1001, # XER
330 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
331 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
333 If(dbg_addr
== 0b101, # GPR
334 Display(" gpr: %016x", dbg_dout
),
336 # also check if this is a "stat"
337 If(dbg_addr
== 1, # requested a STAT
338 #Display(" stat: %x", dbg_dout),
339 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
340 dmirunning
.eq(1), # continue running
341 dmi_monitor
.eq(0), # and stop monitor mode
349 self
.sync
+= If(uptime
== 0,
350 (dmi_addr
.eq(0), # CTRL
351 dmi_din
.eq(1<<0), # STOP
357 self
.sync
+= If(uptime
== 4,
361 self
.sync
+= If(dmirunning
,
362 dmicount
.eq(dmicount
+ 1),
365 # loop every 1<<N cycles
369 self
.sync
+= If(dmicount
== 4,
370 (dmi_addr
.eq(0b10), # NIA
377 self
.sync
+= If(dmicount
== 8,
378 (dmi_addr
.eq(0), # CTRL
379 dmi_din
.eq(1<<3), # STEP
382 dmirunning
.eq(0), # stop counter, need to fire "monitor"
383 dmi_monitor
.eq(1), # start "monitor" instead
387 # limit range of pc for debug reporting
388 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
389 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
390 self
.comb
+= active_dbg
.eq(1)
394 self
.sync
+= If(active_dbg
& (dmicount
== 12),
395 (dmi_addr
.eq(0b11), # MSR
401 if cpu
== "libresoc":
402 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
403 self
.comb
+= active_dbg_cr
.eq(0)
406 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
407 (dmi_addr
.eq(0b1000), # CR
413 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
414 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
417 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
418 (dmi_addr
.eq(0b1001), # XER
426 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
427 (dmi_addr
.eq(0b100), # GSPR addr
434 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
435 (dmi_addr
.eq(0b101), # GSPR data
441 # monitor bbus read/write
442 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
443 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
457 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
459 Display(" [%06x] iadr: %8x, s %01x w %016x",
468 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
470 Display(" [%06x] iadr: %8x, s %01x r %016x",
479 # Build -----------------------------------------------------------------------
482 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
483 parser
.add_argument("--cpu", default
="libresoc",
484 help="CPU to use: libresoc (default) or microwatt")
485 parser
.add_argument("--platform", default
="sim",
486 help="platform (sim or ls180)")
487 parser
.add_argument("--debug", action
="store_true",
488 help="Enable debug traces")
489 parser
.add_argument("--trace", action
="store_true",
490 help="Enable tracing")
491 parser
.add_argument("--trace-start", default
=0,
492 help="Cycle to start FST tracing")
493 parser
.add_argument("--trace-end", default
=-1,
494 help="Cycle to end FST tracing")
495 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
496 args
= parser
.parse_args()
499 if args
.platform
== 'ls180':
500 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
501 platform
=args
.platform
)
504 builder
= Builder(soc
, compile_gateware
= True)
505 builder
.build(run
= True)
509 sim_config
= SimConfig(default_clk
="sys_clk")
510 sim_config
.add_module("serial2console", "serial")
513 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
514 platform
=args
.platform
)
515 builder
= Builder(soc
, compile_gateware
= i
!=0)
516 builder
.build(sim_config
=sim_config
,
519 trace_start
= int(args
.trace_start
),
520 trace_end
= int(args
.trace_end
),
524 if __name__
== "__main__":