set ROM to empty, set SRAM to tiny 0x200, get things working first
[soc.git] / src / soc / litex / florent / ls180soc.py
1 #!/usr/bin/env python3
2
3 import os
4 import argparse
5
6 from migen import (Signal, FSM, If, Display, Finish, NextValue, NextState)
7
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
12
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
18
19 from litedram import modules as litedram_modules
20 from litedram.phy.model import SDRAMPHYModel
21 from litedram.phy.gensdrphy import GENSDRPHY, HalfRateGENSDRPHY
22
23 from litex.soc.cores.gpio import GPIOInOut, GPIOIn, GPIOOut#, GPIOTristate
24 from litex.soc.cores.spi import SPIMaster
25
26 from litex.tools.litex_sim import sdram_module_nphases, get_sdram_phy_settings
27
28 from litex.tools.litex_sim import Platform
29 from libresoc.ls180 import LS180Platform
30
31 from migen import Module
32 from litex.soc.interconnect.csr import AutoCSR
33
34 from libresoc import LibreSoC
35 from microwatt import Microwatt
36
37 # HACK!
38 from litex.soc.integration.soc import SoCCSRHandler
39 SoCCSRHandler.supported_address_width.append(12)
40
41
42 # LibreSoCSim -----------------------------------------------------------------
43
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},
51 platform='sim',
52 ):
53 assert cpu in ["libresoc", "microwatt"]
54 sys_clk_freq = int(50e6)
55
56 if platform == 'sim':
57 platform = Platform()
58 uart_name = "sim"
59 elif platform == 'ls180':
60 platform = LS180Platform()
61 uart_name = "serial"
62
63 #cpu_data_width = 32
64 cpu_data_width = 64
65
66 variant = "ls180"
67
68 # reserve XICS ICP and XICS memory addresses.
69 self.mem_map['icp'] = 0xc0010000
70 self.mem_map['ics'] = 0xc0011000
71 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
72 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
73
74 ram_init = []
75 if False:
76 #ram_init = get_mem_data({
77 # ram_fname: "0x00000000",
78 # }, "little")
79 ram_init = get_mem_data(ram_fname, "little")
80
81 # remap the main RAM to reset-start-address
82
83 # without sram nothing works, therefore move it to higher up
84 self.mem_map["sram"] = 0x90000000
85
86 # put UART at 0xc000200 (w00t! this works!)
87 self.csr_map["uart"] = 4
88
89 self.mem_map["main_ram"] = 0x90000000
90 self.mem_map["sram"] = 0x00000000
91
92 # SoCCore -------------------------------------------------------------
93 SoCCore.__init__(self, platform, clk_freq=sys_clk_freq,
94 cpu_type = "microwatt",
95 cpu_cls = LibreSoC if cpu == "libresoc" \
96 else Microwatt,
97 #bus_data_width = 64,
98 csr_address_width = 14, # limit to 0x8000
99 cpu_variant = variant,
100 csr_data_width = 8,
101 l2_size = 0,
102 uart_name = uart_name,
103 with_sdram = with_sdram,
104 sdram_module = sdram_module,
105 sdram_data_width = sdram_data_width,
106 integrated_rom_size = 0, # if ram_fname else 0x10000,
107 integrated_sram_size = 0x200,
108 #integrated_main_ram_init = ram_init,
109 integrated_main_ram_size = 0x00000000 if with_sdram \
110 else 0x10000000 , # 256MB
111 )
112 self.platform.name = "ls180"
113
114 # SDR SDRAM ----------------------------------------------
115 if False: # not self.integrated_main_ram_size:
116 self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"))
117
118
119 if cpu == "libresoc":
120 # XICS interrupt devices
121 icp_addr = self.mem_map['icp']
122 icp_wb = self.cpu.xics_icp
123 icp_region = SoCRegion(origin=icp_addr, size=0x20, cached=False)
124 self.bus.add_slave(name='icp', slave=icp_wb, region=icp_region)
125
126 ics_addr = self.mem_map['ics']
127 ics_wb = self.cpu.xics_ics
128 ics_region = SoCRegion(origin=ics_addr, size=0x1000, cached=False)
129 self.bus.add_slave(name='ics', slave=ics_wb, region=ics_region)
130
131 # CRG -----------------------------------------------------------------
132 self.submodules.crg = CRG(platform.request("sys_clk"))
133
134 #ram_init = []
135
136 # SDRAM ----------------------------------------------------
137 if with_sdram:
138 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
139 sdram_module_cls = getattr(litedram_modules, sdram_module)
140 sdram_rate = "1:{}".format(
141 sdram_module_nphases[sdram_module_cls.memtype])
142 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
143 phy_settings = get_sdram_phy_settings(
144 memtype = sdram_module.memtype,
145 data_width = sdram_data_width,
146 clk_freq = sdram_clk_freq)
147 #sdrphy_cls = HalfRateGENSDRPHY
148 sdrphy_cls = GENSDRPHY
149 self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"))
150 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
151 # phy_settings,
152 # init=ram_init
153 # )
154 self.add_sdram("sdram",
155 phy = self.sdrphy,
156 module = sdram_module,
157 origin = self.mem_map["main_ram"],
158 size = 0x40000000,
159 l2_cache_size = 0, # 8192
160 l2_cache_min_data_width = 128,
161 l2_cache_reverse = True
162 )
163 # FIXME: skip memtest to avoid corrupting memory
164 self.add_constant("MEMTEST_BUS_SIZE", 128//16)
165 self.add_constant("MEMTEST_DATA_SIZE", 128//16)
166 self.add_constant("MEMTEST_ADDR_SIZE", 128//16)
167 self.add_constant("MEMTEST_BUS_DEBUG", 1)
168 self.add_constant("MEMTEST_ADDR_DEBUG", 1)
169 self.add_constant("MEMTEST_DATA_DEBUG", 1)
170
171 # GPIOs
172 #platform.add_extension([("gpio_in", 0, Pins(8))])
173 self.submodules.gpio_in = GPIOIn(platform.request("gpio_in"))
174 self.add_csr("gpio_in")
175 self.submodules.gpio_out = GPIOIn(platform.request("gpio_out"))
176 self.add_csr("gpio_out")
177
178 if False:
179 self.submodules.gpio = GPIOTristate(platform.request("gpio"))
180 self.add_csr("gpio")
181
182 # SPI Master
183 self.submodules.spi_master = SPIMaster(
184 pads = platform.request("spi_master"),
185 data_width = 8,
186 sys_clk_freq = sys_clk_freq,
187 spi_clk_freq = 8e6,
188 )
189 self.add_csr("spi_master")
190
191 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
192 self.comb += self.cpu.interrupt[12:16].eq(platform.request("eint"))
193
194 # Debug ---------------------------------------------------------------
195 if not debug:
196 return
197
198 # setup running of DMI FSM
199 dmi_addr = Signal(4)
200 dmi_din = Signal(64)
201 dmi_dout = Signal(64)
202 dmi_wen = Signal(1)
203 dmi_req = Signal(1)
204
205 # debug log out
206 dbg_addr = Signal(4)
207 dbg_dout = Signal(64)
208 dbg_msg = Signal(1)
209
210 # capture pc from dmi
211 pc = Signal(64)
212 active_dbg = Signal()
213 active_dbg_cr = Signal()
214 active_dbg_xer = Signal()
215
216 # xer flags
217 xer_so = Signal()
218 xer_ca = Signal()
219 xer_ca32 = Signal()
220 xer_ov = Signal()
221 xer_ov32 = Signal()
222
223 # increment counter, Stop after 100000 cycles
224 uptime = Signal(64)
225 self.sync += uptime.eq(uptime + 1)
226 #self.sync += If(uptime == 1000000000000, Finish())
227
228 # DMI FSM counter and FSM itself
229 dmicount = Signal(10)
230 dmirunning = Signal(1)
231 dmi_monitor = Signal(1)
232 dmifsm = FSM()
233 self.submodules += dmifsm
234
235 # DMI FSM
236 dmifsm.act("START",
237 If(dmi_req & dmi_wen,
238 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
239 self.cpu.dmi_din.eq(dmi_din), # DMI in
240 self.cpu.dmi_req.eq(1), # DMI request
241 self.cpu.dmi_wr.eq(1), # DMI write
242 If(self.cpu.dmi_ack,
243 (NextState("IDLE"),
244 )
245 ),
246 ),
247 ),
248 If(dmi_req & ~dmi_wen,
249 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
250 self.cpu.dmi_req.eq(1), # DMI request
251 self.cpu.dmi_wr.eq(0), # DMI read
252 If(self.cpu.dmi_ack,
253 # acknowledge received: capture data.
254 (NextState("IDLE"),
255 NextValue(dbg_addr, dmi_addr),
256 NextValue(dbg_dout, self.cpu.dmi_dout),
257 NextValue(dbg_msg, 1),
258 ),
259 ),
260 ),
261 )
262 )
263
264 # DMI response received: reset the dmi request and check if
265 # in "monitor" mode
266 dmifsm.act("IDLE",
267 If(dmi_monitor,
268 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
269 ).Else(
270 NextState("START"), # back to start on next cycle
271 ),
272 NextValue(dmi_req, 0),
273 NextValue(dmi_addr, 0),
274 NextValue(dmi_din, 0),
275 NextValue(dmi_wen, 0),
276 )
277
278 # "monitor" mode fires off a STAT request
279 dmifsm.act("FIRE_MONITOR",
280 (NextValue(dmi_req, 1),
281 NextValue(dmi_addr, 1), # DMI STAT address
282 NextValue(dmi_din, 0),
283 NextValue(dmi_wen, 0), # read STAT
284 NextState("START"), # back to start on next cycle
285 )
286 )
287
288 self.comb += xer_so.eq((dbg_dout & 1) == 1)
289 self.comb += xer_ca.eq((dbg_dout & 4) == 4)
290 self.comb += xer_ca32.eq((dbg_dout & 8) == 8)
291 self.comb += xer_ov.eq((dbg_dout & 16) == 16)
292 self.comb += xer_ov32.eq((dbg_dout & 32) == 32)
293
294 # debug messages out
295 self.sync += If(dbg_msg,
296 (If(active_dbg & (dbg_addr == 0b10), # PC
297 Display("pc : %016x", dbg_dout),
298 ),
299 If(dbg_addr == 0b10, # PC
300 pc.eq(dbg_dout), # capture PC
301 ),
302 #If(dbg_addr == 0b11, # MSR
303 # Display(" msr: %016x", dbg_dout),
304 #),
305 If(dbg_addr == 0b1000, # CR
306 Display(" cr : %016x", dbg_dout),
307 ),
308 If(dbg_addr == 0b1001, # XER
309 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
310 xer_so, xer_ca, xer_ca32, xer_ov, xer_ov32),
311 ),
312 If(dbg_addr == 0b101, # GPR
313 Display(" gpr: %016x", dbg_dout),
314 ),
315 # also check if this is a "stat"
316 If(dbg_addr == 1, # requested a STAT
317 #Display(" stat: %x", dbg_dout),
318 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
319 dmirunning.eq(1), # continue running
320 dmi_monitor.eq(0), # and stop monitor mode
321 ),
322 ),
323 dbg_msg.eq(0)
324 )
325 )
326
327 # kick off a "stop"
328 self.sync += If(uptime == 0,
329 (dmi_addr.eq(0), # CTRL
330 dmi_din.eq(1<<0), # STOP
331 dmi_req.eq(1),
332 dmi_wen.eq(1),
333 )
334 )
335
336 self.sync += If(uptime == 4,
337 dmirunning.eq(1),
338 )
339
340 self.sync += If(dmirunning,
341 dmicount.eq(dmicount + 1),
342 )
343
344 # loop every 1<<N cycles
345 cyclewid = 9
346
347 # get the PC
348 self.sync += If(dmicount == 4,
349 (dmi_addr.eq(0b10), # NIA
350 dmi_req.eq(1),
351 dmi_wen.eq(0),
352 )
353 )
354
355 # kick off a "step"
356 self.sync += If(dmicount == 8,
357 (dmi_addr.eq(0), # CTRL
358 dmi_din.eq(1<<3), # STEP
359 dmi_req.eq(1),
360 dmi_wen.eq(1),
361 dmirunning.eq(0), # stop counter, need to fire "monitor"
362 dmi_monitor.eq(1), # start "monitor" instead
363 )
364 )
365
366 # limit range of pc for debug reporting
367 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
368 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
369 self.comb += active_dbg.eq(1)
370
371
372 # get the MSR
373 self.sync += If(active_dbg & (dmicount == 12),
374 (dmi_addr.eq(0b11), # MSR
375 dmi_req.eq(1),
376 dmi_wen.eq(0),
377 )
378 )
379
380 if cpu == "libresoc":
381 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
382 self.comb += active_dbg_cr.eq(0)
383
384 # get the CR
385 self.sync += If(active_dbg_cr & (dmicount == 16),
386 (dmi_addr.eq(0b1000), # CR
387 dmi_req.eq(1),
388 dmi_wen.eq(0),
389 )
390 )
391
392 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
393 self.comb += active_dbg_xer.eq(active_dbg_cr)
394
395 # get the CR
396 self.sync += If(active_dbg_xer & (dmicount == 20),
397 (dmi_addr.eq(0b1001), # XER
398 dmi_req.eq(1),
399 dmi_wen.eq(0),
400 )
401 )
402
403 # read all 32 GPRs
404 for i in range(32):
405 self.sync += If(active_dbg & (dmicount == 24+(i*8)),
406 (dmi_addr.eq(0b100), # GSPR addr
407 dmi_din.eq(i), # r1
408 dmi_req.eq(1),
409 dmi_wen.eq(1),
410 )
411 )
412
413 self.sync += If(active_dbg & (dmicount == 28+(i*8)),
414 (dmi_addr.eq(0b101), # GSPR data
415 dmi_req.eq(1),
416 dmi_wen.eq(0),
417 )
418 )
419
420 # monitor bbus read/write
421 self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
422 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
423 #uptime,
424 0,
425 self.cpu.dbus.adr,
426 self.cpu.dbus.we,
427 self.cpu.dbus.sel,
428 self.cpu.dbus.dat_w,
429 self.cpu.dbus.dat_r
430 )
431 )
432
433 return
434
435 # monitor ibus write
436 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
437 self.cpu.ibus.we,
438 Display(" [%06x] iadr: %8x, s %01x w %016x",
439 #uptime,
440 0,
441 self.cpu.ibus.adr,
442 self.cpu.ibus.sel,
443 self.cpu.ibus.dat_w,
444 )
445 )
446 # monitor ibus read
447 self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
448 ~self.cpu.ibus.we,
449 Display(" [%06x] iadr: %8x, s %01x r %016x",
450 #uptime,
451 0,
452 self.cpu.ibus.adr,
453 self.cpu.ibus.sel,
454 self.cpu.ibus.dat_r
455 )
456 )
457
458 # Build -----------------------------------------------------------------------
459
460 def main():
461 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
462 parser.add_argument("--cpu", default="libresoc",
463 help="CPU to use: libresoc (default) or microwatt")
464 parser.add_argument("--platform", default="sim",
465 help="platform (sim or ls180)")
466 parser.add_argument("--debug", action="store_true",
467 help="Enable debug traces")
468 parser.add_argument("--trace", action="store_true",
469 help="Enable tracing")
470 parser.add_argument("--trace-start", default=0,
471 help="Cycle to start FST tracing")
472 parser.add_argument("--trace-end", default=-1,
473 help="Cycle to end FST tracing")
474 parser.add_argument("--build", action="store_true", help="Build bitstream")
475 args = parser.parse_args()
476
477
478 if args.platform == 'ls180':
479 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
480 platform=args.platform)
481 soc.add_sdcard()
482 soc.add_spi_sdcard()
483 builder = Builder(soc, compile_gateware = True)
484 builder.build(run = True)
485 os.chdir("../")
486 else:
487
488 sim_config = SimConfig(default_clk="sys_clk")
489 sim_config.add_module("serial2console", "serial")
490
491 for i in range(2):
492 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug,
493 platform=args.platform)
494 builder = Builder(soc, compile_gateware = i!=0)
495 builder.build(sim_config=sim_config,
496 run = i!=0,
497 trace = args.trace,
498 trace_start = int(args.trace_start),
499 trace_end = int(args.trace_end),
500 trace_fst = 0)
501 os.chdir("../")
502
503 if __name__ == "__main__":
504 main()