a00ba5f0d582f77e831cbe5bb6119733425ccbc6
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)
41 # LiteScope IO -------------------------------------------------
43 class SoCGPIO(Module
, AutoCSR
):
44 def __init__(self
, in_pads
, out_pads
):
45 self
.input = Signal(len(in_pads
))
46 self
.output
= Signal(len(out_pads
))
50 self
.submodules
.gpio
= GPIOInOut(self
.input, self
.output
)
53 return self
.gpio
.get_csrs()
56 # LibreSoCSim -----------------------------------------------------------------
58 class LibreSoCSim(SoCCore
):
59 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
60 sdram_module
= "AS4C16M16",
61 #sdram_data_width = 16,
62 #sdram_module = "MT48LC16M16",
63 sdram_data_width
= 16,
64 irq_reserved_irqs
= {'uart': 0},
67 assert cpu
in ["libresoc", "microwatt"]
68 sys_clk_freq
= int(50e6
)
73 elif platform
== 'ls180':
74 platform
= LS180Platform()
80 if cpu_data_width
== 32:
81 variant
= "standard32"
85 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
86 # "hello_world/hello_world.bin"
87 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
89 #ram_fname = "/tmp/test.bin"
91 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
92 # "micropython/firmware.bin"
93 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
94 # "tests/xics/xics.bin"
95 ram_fname
= "/home/lkcl/src/libresoc/microwatt/" \
96 "tests/decrementer/decrementer.bin"
97 #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
98 # "hello_world/hello_world.bin"
100 # reserve XICS ICP and XICS memory addresses.
101 self
.mem_map
['icp'] = 0xc0010000
102 self
.mem_map
['ics'] = 0xc0011000
103 self
.mem_map
['gpio'] = 0xc0012000
104 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
105 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
109 #ram_init = get_mem_data({
110 # ram_fname: "0x00000000",
112 ram_init
= get_mem_data(ram_fname
, "little")
114 # remap the main RAM to reset-start-address
115 self
.mem_map
["main_ram"] = 0x00000000
117 # without sram nothing works, therefore move it to higher up
118 self
.mem_map
["sram"] = 0x90000000
120 # put UART at 0xc000200 (w00t! this works!)
121 self
.csr_map
["uart"] = 4
124 # SoCCore -------------------------------------------------------------
125 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
126 cpu_type
= "microwatt",
127 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
129 #bus_data_width = 64,
130 csr_address_width
= 14, # limit to 0x8000
131 cpu_variant
= variant
,
134 uart_name
= uart_name
,
135 with_sdram
= with_sdram
,
136 sdram_module
= sdram_module
,
137 sdram_data_width
= sdram_data_width
,
138 integrated_rom_size
= 0 if ram_fname
else 0x10000,
139 integrated_sram_size
= 0x40000,
140 #integrated_main_ram_init = ram_init,
141 integrated_main_ram_size
= 0x00000000 if with_sdram \
142 else 0x10000000 , # 256MB
144 self
.platform
.name
= "sim"
146 # SDR SDRAM ----------------------------------------------
147 if False: # not self.integrated_main_ram_size:
148 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
151 if cpu
== "libresoc":
152 # XICS interrupt devices
153 icp_addr
= self
.mem_map
['icp']
154 icp_wb
= self
.cpu
.xics_icp
155 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
156 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
158 ics_addr
= self
.mem_map
['ics']
159 ics_wb
= self
.cpu
.xics_ics
160 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
161 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
163 # Simple GPIO peripheral
164 gpio_addr
= self
.mem_map
['gpio']
165 gpio_wb
= self
.cpu
.simple_gpio
166 gpio_region
= SoCRegion(origin
=gpio_addr
, size
=0x20, cached
=False)
167 self
.bus
.add_slave(name
='gpio', slave
=gpio_wb
, region
=gpio_region
)
170 # CRG -----------------------------------------------------------------
171 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
175 # SDRAM ----------------------------------------------------
177 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
178 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
179 sdram_rate
= "1:{}".format(
180 sdram_module_nphases
[sdram_module_cls
.memtype
])
181 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
182 phy_settings
= get_sdram_phy_settings(
183 memtype
= sdram_module
.memtype
,
184 data_width
= sdram_data_width
,
185 clk_freq
= sdram_clk_freq
)
186 #sdrphy_cls = HalfRateGENSDRPHY
187 sdrphy_cls
= GENSDRPHY
188 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
189 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
193 self
.add_sdram("sdram",
195 module
= sdram_module
,
196 origin
= self
.mem_map
["main_ram"],
198 l2_cache_size
= 0, # 8192
199 l2_cache_min_data_width
= 128,
200 l2_cache_reverse
= True
202 # FIXME: skip memtest to avoid corrupting memory
203 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
204 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
205 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
206 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
207 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
208 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
211 #platform.add_extension([("gpio_in", 0, Pins(8))])
212 self
.submodules
.gpio_in
= GPIOIn(platform
.request("gpio_in"))
213 self
.add_csr("gpio_in")
214 self
.submodules
.gpio_out
= GPIOIn(platform
.request("gpio_out"))
215 self
.add_csr("gpio_out")
218 self
.submodules
.spi_master
= SPIMaster(
219 pads
= platform
.request("spi_master"),
221 sys_clk_freq
= sys_clk_freq
,
224 self
.add_csr("spi_master")
227 # Debug ---------------------------------------------------------------
231 # setup running of DMI FSM
234 dmi_dout
= Signal(64)
240 dbg_dout
= Signal(64)
243 # capture pc from dmi
245 active_dbg
= Signal()
246 active_dbg_cr
= Signal()
247 active_dbg_xer
= Signal()
256 # increment counter, Stop after 100000 cycles
258 self
.sync
+= uptime
.eq(uptime
+ 1)
259 #self.sync += If(uptime == 1000000000000, Finish())
261 # DMI FSM counter and FSM itself
262 dmicount
= Signal(10)
263 dmirunning
= Signal(1)
264 dmi_monitor
= Signal(1)
266 self
.submodules
+= dmifsm
270 If(dmi_req
& dmi_wen
,
271 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
272 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
273 self
.cpu
.dmi_req
.eq(1), # DMI request
274 self
.cpu
.dmi_wr
.eq(1), # DMI write
281 If(dmi_req
& ~dmi_wen
,
282 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
283 self
.cpu
.dmi_req
.eq(1), # DMI request
284 self
.cpu
.dmi_wr
.eq(0), # DMI read
286 # acknowledge received: capture data.
288 NextValue(dbg_addr
, dmi_addr
),
289 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
290 NextValue(dbg_msg
, 1),
297 # DMI response received: reset the dmi request and check if
301 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
303 NextState("START"), # back to start on next cycle
305 NextValue(dmi_req
, 0),
306 NextValue(dmi_addr
, 0),
307 NextValue(dmi_din
, 0),
308 NextValue(dmi_wen
, 0),
311 # "monitor" mode fires off a STAT request
312 dmifsm
.act("FIRE_MONITOR",
313 (NextValue(dmi_req
, 1),
314 NextValue(dmi_addr
, 1), # DMI STAT address
315 NextValue(dmi_din
, 0),
316 NextValue(dmi_wen
, 0), # read STAT
317 NextState("START"), # back to start on next cycle
321 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
322 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
323 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
324 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
325 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
328 self
.sync
+= If(dbg_msg
,
329 (If(active_dbg
& (dbg_addr
== 0b10), # PC
330 Display("pc : %016x", dbg_dout
),
332 If(dbg_addr
== 0b10, # PC
333 pc
.eq(dbg_dout
), # capture PC
335 #If(dbg_addr == 0b11, # MSR
336 # Display(" msr: %016x", dbg_dout),
338 If(dbg_addr
== 0b1000, # CR
339 Display(" cr : %016x", dbg_dout
),
341 If(dbg_addr
== 0b1001, # XER
342 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
343 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
345 If(dbg_addr
== 0b101, # GPR
346 Display(" gpr: %016x", dbg_dout
),
348 # also check if this is a "stat"
349 If(dbg_addr
== 1, # requested a STAT
350 #Display(" stat: %x", dbg_dout),
351 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
352 dmirunning
.eq(1), # continue running
353 dmi_monitor
.eq(0), # and stop monitor mode
361 self
.sync
+= If(uptime
== 0,
362 (dmi_addr
.eq(0), # CTRL
363 dmi_din
.eq(1<<0), # STOP
369 self
.sync
+= If(uptime
== 4,
373 self
.sync
+= If(dmirunning
,
374 dmicount
.eq(dmicount
+ 1),
377 # loop every 1<<N cycles
381 self
.sync
+= If(dmicount
== 4,
382 (dmi_addr
.eq(0b10), # NIA
389 self
.sync
+= If(dmicount
== 8,
390 (dmi_addr
.eq(0), # CTRL
391 dmi_din
.eq(1<<3), # STEP
394 dmirunning
.eq(0), # stop counter, need to fire "monitor"
395 dmi_monitor
.eq(1), # start "monitor" instead
399 # limit range of pc for debug reporting
400 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
401 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
402 self
.comb
+= active_dbg
.eq(1)
406 self
.sync
+= If(active_dbg
& (dmicount
== 12),
407 (dmi_addr
.eq(0b11), # MSR
413 if cpu
== "libresoc":
414 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
415 self
.comb
+= active_dbg_cr
.eq(0)
418 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
419 (dmi_addr
.eq(0b1000), # CR
425 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
426 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
429 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
430 (dmi_addr
.eq(0b1001), # XER
438 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
439 (dmi_addr
.eq(0b100), # GSPR addr
446 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
447 (dmi_addr
.eq(0b101), # GSPR data
453 # monitor bbus read/write
454 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
455 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
469 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
471 Display(" [%06x] iadr: %8x, s %01x w %016x",
480 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
482 Display(" [%06x] iadr: %8x, s %01x r %016x",
491 # Build -----------------------------------------------------------------------
494 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
495 parser
.add_argument("--cpu", default
="libresoc",
496 help="CPU to use: libresoc (default) or microwatt")
497 parser
.add_argument("--platform", default
="sim",
498 help="platform (sim or ls180)")
499 parser
.add_argument("--debug", action
="store_true",
500 help="Enable debug traces")
501 parser
.add_argument("--trace", action
="store_true",
502 help="Enable tracing")
503 parser
.add_argument("--trace-start", default
=0,
504 help="Cycle to start FST tracing")
505 parser
.add_argument("--trace-end", default
=-1,
506 help="Cycle to end FST tracing")
507 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
508 args
= parser
.parse_args()
511 if args
.platform
== 'ls180':
512 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
513 platform
=args
.platform
)
516 builder
= Builder(soc
, compile_gateware
= True)
517 builder
.build(run
= True)
521 sim_config
= SimConfig(default_clk
="sys_clk")
522 sim_config
.add_module("serial2console", "serial")
525 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
526 platform
=args
.platform
)
527 builder
= Builder(soc
, compile_gateware
= i
!=0)
528 builder
.build(sim_config
=sim_config
,
531 trace_start
= int(args
.trace_start
),
532 trace_end
= int(args
.trace_end
),
536 if __name__
== "__main__":