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
#, GPIOTristate
24 from litex
.soc
.cores
.spi
import SPIMaster
25 from litex
.soc
.cores
.pwm
import PWM
26 from litex
.soc
.cores
.bitbang
import I2CMaster
28 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
30 from litex
.tools
.litex_sim
import Platform
31 from libresoc
.ls180
import LS180Platform
33 from migen
import Module
34 from litex
.soc
.interconnect
.csr
import AutoCSR
36 from libresoc
import LibreSoC
37 from microwatt
import Microwatt
40 from litex
.soc
.integration
.soc
import SoCCSRHandler
41 SoCCSRHandler
.supported_address_width
.append(12)
44 # LibreSoCSim -----------------------------------------------------------------
46 class LibreSoCSim(SoCCore
):
47 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
48 sdram_module
= "AS4C16M16",
49 #sdram_data_width = 16,
50 #sdram_module = "MT48LC16M16",
51 sdram_data_width
= 16,
52 irq_reserved_irqs
= {'uart': 0},
55 assert cpu
in ["libresoc", "microwatt"]
56 sys_clk_freq
= int(50e6
)
61 elif platform
== 'ls180':
62 platform
= LS180Platform()
70 # reserve XICS ICP and XICS memory addresses.
71 self
.mem_map
['icp'] = 0xc0010000
72 self
.mem_map
['ics'] = 0xc0011000
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
85 # without sram nothing works, therefore move it to higher up
86 self
.mem_map
["sram"] = 0x90000000
88 # put UART at 0xc000200 (w00t! this works!)
89 self
.csr_map
["uart"] = 4
91 self
.mem_map
["main_ram"] = 0x90000000
92 self
.mem_map
["sram"] = 0x00000000
94 # SoCCore -------------------------------------------------------------
95 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
96 cpu_type
= "microwatt",
97 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
100 csr_address_width
= 14, # limit to 0x8000
101 cpu_variant
= variant
,
104 uart_name
= uart_name
,
105 with_sdram
= with_sdram
,
106 sdram_module
= sdram_module
,
107 sdram_data_width
= sdram_data_width
,
108 integrated_rom_size
= 0, # if ram_fname else 0x10000,
109 integrated_sram_size
= 0x200,
110 #integrated_main_ram_init = ram_init,
111 integrated_main_ram_size
= 0x00000000 if with_sdram \
112 else 0x10000000 , # 256MB
114 self
.platform
.name
= "ls180"
116 # SDR SDRAM ----------------------------------------------
117 if False: # not self.integrated_main_ram_size:
118 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
120 if cpu
== "libresoc":
121 # XICS interrupt devices
122 icp_addr
= self
.mem_map
['icp']
123 icp_wb
= self
.cpu
.xics_icp
124 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
125 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
127 ics_addr
= self
.mem_map
['ics']
128 ics_wb
= self
.cpu
.xics_ics
129 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
130 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
132 # CRG -----------------------------------------------------------------
133 self
.submodules
.crg
= CRG(platform
.request("sys_clk"),
134 platform
.request("sys_rst"))
138 # SDRAM ----------------------------------------------------
140 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
141 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
142 sdram_rate
= "1:{}".format(
143 sdram_module_nphases
[sdram_module_cls
.memtype
])
144 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
145 phy_settings
= get_sdram_phy_settings(
146 memtype
= sdram_module
.memtype
,
147 data_width
= sdram_data_width
,
148 clk_freq
= sdram_clk_freq
)
149 #sdrphy_cls = HalfRateGENSDRPHY
150 sdrphy_cls
= GENSDRPHY
151 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
152 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
156 self
.add_sdram("sdram",
158 module
= sdram_module
,
159 origin
= self
.mem_map
["main_ram"],
161 l2_cache_size
= 0, # 8192
162 l2_cache_min_data_width
= 128,
163 l2_cache_reverse
= True
165 # FIXME: skip memtest to avoid corrupting memory
166 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
167 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
168 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
169 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
170 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
171 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
174 #platform.add_extension([("gpio_in", 0, Pins(8))])
175 self
.submodules
.gpio_in
= GPIOIn(platform
.request("gpio_in"))
176 self
.add_csr("gpio_in")
177 self
.submodules
.gpio_out
= GPIOIn(platform
.request("gpio_out"))
178 self
.add_csr("gpio_out")
181 self
.submodules
.gpio
= GPIOTristate(platform
.request("gpio"))
185 self
.submodules
.spi_master
= SPIMaster(
186 pads
= platform
.request("spi_master"),
188 sys_clk_freq
= sys_clk_freq
,
191 self
.add_csr("spi_master")
193 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
194 self
.comb
+= self
.cpu
.interrupt
[12:16].eq(platform
.request("eint"))
197 jtagpads
= platform
.request("jtag")
198 self
.comb
+= self
.cpu
.jtag_tck
.eq(jtagpads
.tck
)
199 self
.comb
+= self
.cpu
.jtag_tms
.eq(jtagpads
.tms
)
200 self
.comb
+= self
.cpu
.jtag_tdi
.eq(jtagpads
.tdi
)
201 self
.comb
+= jtagpads
.tdo
.eq(self
.cpu
.jtag_tdo
)
206 setattr(self
.submodules
, name
, PWM(platform
.request("pwm", i
)))
210 self
.submodules
.i2c
= I2CMaster(platform
.request("i2c"))
213 # Debug ---------------------------------------------------------------
217 # setup running of DMI FSM
220 dmi_dout
= Signal(64)
226 dbg_dout
= Signal(64)
229 # capture pc from dmi
231 active_dbg
= Signal()
232 active_dbg_cr
= Signal()
233 active_dbg_xer
= Signal()
242 # increment counter, Stop after 100000 cycles
244 self
.sync
+= uptime
.eq(uptime
+ 1)
245 #self.sync += If(uptime == 1000000000000, Finish())
247 # DMI FSM counter and FSM itself
248 dmicount
= Signal(10)
249 dmirunning
= Signal(1)
250 dmi_monitor
= Signal(1)
252 self
.submodules
+= dmifsm
256 If(dmi_req
& dmi_wen
,
257 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
258 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
259 self
.cpu
.dmi_req
.eq(1), # DMI request
260 self
.cpu
.dmi_wr
.eq(1), # DMI write
267 If(dmi_req
& ~dmi_wen
,
268 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
269 self
.cpu
.dmi_req
.eq(1), # DMI request
270 self
.cpu
.dmi_wr
.eq(0), # DMI read
272 # acknowledge received: capture data.
274 NextValue(dbg_addr
, dmi_addr
),
275 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
276 NextValue(dbg_msg
, 1),
283 # DMI response received: reset the dmi request and check if
287 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
289 NextState("START"), # back to start on next cycle
291 NextValue(dmi_req
, 0),
292 NextValue(dmi_addr
, 0),
293 NextValue(dmi_din
, 0),
294 NextValue(dmi_wen
, 0),
297 # "monitor" mode fires off a STAT request
298 dmifsm
.act("FIRE_MONITOR",
299 (NextValue(dmi_req
, 1),
300 NextValue(dmi_addr
, 1), # DMI STAT address
301 NextValue(dmi_din
, 0),
302 NextValue(dmi_wen
, 0), # read STAT
303 NextState("START"), # back to start on next cycle
307 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
308 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
309 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
310 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
311 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
314 self
.sync
+= If(dbg_msg
,
315 (If(active_dbg
& (dbg_addr
== 0b10), # PC
316 Display("pc : %016x", dbg_dout
),
318 If(dbg_addr
== 0b10, # PC
319 pc
.eq(dbg_dout
), # capture PC
321 #If(dbg_addr == 0b11, # MSR
322 # Display(" msr: %016x", dbg_dout),
324 If(dbg_addr
== 0b1000, # CR
325 Display(" cr : %016x", dbg_dout
),
327 If(dbg_addr
== 0b1001, # XER
328 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
329 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
331 If(dbg_addr
== 0b101, # GPR
332 Display(" gpr: %016x", dbg_dout
),
334 # also check if this is a "stat"
335 If(dbg_addr
== 1, # requested a STAT
336 #Display(" stat: %x", dbg_dout),
337 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
338 dmirunning
.eq(1), # continue running
339 dmi_monitor
.eq(0), # and stop monitor mode
347 self
.sync
+= If(uptime
== 0,
348 (dmi_addr
.eq(0), # CTRL
349 dmi_din
.eq(1<<0), # STOP
355 self
.sync
+= If(uptime
== 4,
359 self
.sync
+= If(dmirunning
,
360 dmicount
.eq(dmicount
+ 1),
363 # loop every 1<<N cycles
367 self
.sync
+= If(dmicount
== 4,
368 (dmi_addr
.eq(0b10), # NIA
375 self
.sync
+= If(dmicount
== 8,
376 (dmi_addr
.eq(0), # CTRL
377 dmi_din
.eq(1<<3), # STEP
380 dmirunning
.eq(0), # stop counter, need to fire "monitor"
381 dmi_monitor
.eq(1), # start "monitor" instead
385 # limit range of pc for debug reporting
386 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
387 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
388 self
.comb
+= active_dbg
.eq(1)
392 self
.sync
+= If(active_dbg
& (dmicount
== 12),
393 (dmi_addr
.eq(0b11), # MSR
399 if cpu
== "libresoc":
400 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
401 self
.comb
+= active_dbg_cr
.eq(0)
404 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
405 (dmi_addr
.eq(0b1000), # CR
411 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
412 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
415 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
416 (dmi_addr
.eq(0b1001), # XER
424 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
425 (dmi_addr
.eq(0b100), # GSPR addr
432 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
433 (dmi_addr
.eq(0b101), # GSPR data
439 # monitor bbus read/write
440 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
441 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
455 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
457 Display(" [%06x] iadr: %8x, s %01x w %016x",
466 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
468 Display(" [%06x] iadr: %8x, s %01x r %016x",
477 # Build -----------------------------------------------------------------------
480 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
481 parser
.add_argument("--cpu", default
="libresoc",
482 help="CPU to use: libresoc (default) or microwatt")
483 parser
.add_argument("--platform", default
="sim",
484 help="platform (sim or ls180)")
485 parser
.add_argument("--debug", action
="store_true",
486 help="Enable debug traces")
487 parser
.add_argument("--trace", action
="store_true",
488 help="Enable tracing")
489 parser
.add_argument("--trace-start", default
=0,
490 help="Cycle to start FST tracing")
491 parser
.add_argument("--trace-end", default
=-1,
492 help="Cycle to end FST tracing")
493 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
494 args
= parser
.parse_args()
497 if args
.platform
== 'ls180':
498 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
499 platform
=args
.platform
)
502 builder
= Builder(soc
, compile_gateware
= True)
503 builder
.build(run
= True)
507 sim_config
= SimConfig(default_clk
="sys_clk")
508 sim_config
.add_module("serial2console", "serial")
511 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
512 platform
=args
.platform
)
513 builder
= Builder(soc
, compile_gateware
= i
!=0)
514 builder
.build(sim_config
=sim_config
,
517 trace_start
= int(args
.trace_start
),
518 trace_end
= int(args
.trace_end
),
522 if __name__
== "__main__":