thanks to daveshah, added simulation of dram
[soc.git] / src / soc / litex / florent / sim.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
18 from litedram import modules as litedram_modules
19 from litedram.phy.model import SDRAMPHYModel
20 from litex.tools.litex_sim import sdram_module_nphases, get_sdram_phy_settings
21
22 from litex.tools.litex_sim import Platform
23
24 from libresoc import LibreSoC
25 from microwatt import Microwatt
26
27 # LibreSoCSim -----------------------------------------------------------------
28
29 class LibreSoCSim(SoCSDRAM):
30 def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
31 #sdram_module = "AS4C16M16",
32 #sdram_data_width = 16,
33 sdram_module = "MT48LC16M16",
34 sdram_data_width = 32,
35 ):
36 assert cpu in ["libresoc", "microwatt"]
37 platform = Platform()
38 sys_clk_freq = int(100e6)
39
40 # SoCCore -------------------------------------------------------------
41 SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
42 cpu_type = "microwatt",
43 cpu_cls = LibreSoC if cpu == "libresoc" \
44 else Microwatt,
45 #bus_data_width = 64,
46 uart_name = "sim",
47 with_sdram = with_sdram,
48 sdram_module = sdram_module,
49 sdram_data_width = sdram_data_width,
50 integrated_rom_size = 0x10000,
51 integrated_main_ram_size = 0x00000000 if with_sdram \
52 else 0x10000000 , # 256MB
53 )
54 self.platform.name = "sim"
55
56 # CRG -----------------------------------------------------------------
57 self.submodules.crg = CRG(platform.request("sys_clk"))
58
59 ram_init = []
60
61 # SDRAM ----------------------------------------------------
62 if with_sdram:
63 sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings
64 sdram_module_cls = getattr(litedram_modules, sdram_module)
65 sdram_rate = "1:{}".format(
66 sdram_module_nphases[sdram_module_cls.memtype])
67 sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate)
68 phy_settings = get_sdram_phy_settings(
69 memtype = sdram_module.memtype,
70 data_width = sdram_data_width,
71 clk_freq = sdram_clk_freq)
72 self.submodules.sdrphy = SDRAMPHYModel(sdram_module,
73 phy_settings,
74 init=ram_init
75 )
76 self.register_sdram(
77 self.sdrphy,
78 sdram_module.geom_settings,
79 sdram_module.timing_settings)
80 # FIXME: skip memtest to avoid corrupting memory
81 self.add_constant("MEMTEST_BUS_SIZE", 64//16)
82 self.add_constant("MEMTEST_DATA_SIZE", 64//16)
83 self.add_constant("MEMTEST_ADDR_SIZE", 64//16)
84
85
86 # Debug ---------------------------------------------------------------
87 if not debug:
88 return
89
90 # setup running of DMI FSM
91 dmi_addr = Signal(3)
92 dmi_din = Signal(64)
93 dmi_dout = Signal(64)
94 dmi_wen = Signal(1)
95 dmi_req = Signal(1)
96
97 # debug log out
98 dbg_addr = Signal(3)
99 dbg_dout = Signal(64)
100 dbg_msg = Signal(1)
101
102 uptime = Signal(64)
103 # increment counter, Stop after 100000 cycles
104 uptime = Signal(64)
105 self.sync += uptime.eq(uptime + 1)
106 self.sync += If(uptime == 100000, Finish())
107
108 dmifsm = FSM()
109 self.submodules += dmifsm
110
111 # DMI FSM
112 dmifsm.act("START",
113 If(dmi_req & dmi_wen,
114 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
115 self.cpu.dmi_din.eq(dmi_din), # DMI in
116 self.cpu.dmi_req.eq(1), # DMI request
117 self.cpu.dmi_wr.eq(1), # DMI write
118 If(self.cpu.dmi_ack,
119 (NextState("IDLE"),
120 )
121 ),
122 ),
123 ),
124 If(dmi_req & ~dmi_wen,
125 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
126 self.cpu.dmi_req.eq(1), # DMI request
127 self.cpu.dmi_wr.eq(0), # DMI read
128 If(self.cpu.dmi_ack,
129 (NextState("IDLE"),
130 NextValue(dbg_addr, dmi_addr),
131 NextValue(dbg_dout, self.cpu.dmi_dout),
132 NextValue(dbg_msg, 1),
133 )
134 ),
135 ),
136 )
137 )
138
139 dmifsm.act("IDLE",
140 (NextValue(dmi_req, 0),
141 NextValue(dmi_addr, 0),
142 NextValue(dmi_din, 0),
143 NextValue(dmi_wen, 0),
144 NextState("START"), # back to start on next cycle
145 )
146 )
147
148 # debug messages out
149 self.sync += If(dbg_msg,
150 (If(dbg_addr == 0b10, # PC
151 Display("pc : %016x", dbg_dout),
152 ),
153 If(dbg_addr == 0b11, # PC
154 Display(" msr: %016x", dbg_dout),
155 ),
156 If(dbg_addr == 0b101, # GPR
157 Display(" gpr: %016x", dbg_dout),
158 ),
159 dbg_msg.eq(0)
160 )
161 )
162
163 # kick off a "stop"
164 self.sync += If(uptime == 0,
165 (dmi_addr.eq(0), # CTRL
166 dmi_din.eq(1<<0), # STOP
167 dmi_req.eq(1),
168 dmi_wen.eq(1),
169 )
170 )
171
172 # loop every 1<<N cycles
173 cyclewid = 9
174
175 # get the PC
176 self.sync += If(uptime[0:cyclewid] == 4,
177 (dmi_addr.eq(0b10), # NIA
178 dmi_req.eq(1),
179 dmi_wen.eq(0),
180 )
181 )
182
183 # kick off a "step"
184 self.sync += If(uptime[0:cyclewid] == 8,
185 (dmi_addr.eq(0), # CTRL
186 dmi_din.eq(1<<3), # STEP
187 dmi_req.eq(1),
188 dmi_wen.eq(1),
189 )
190 )
191
192 # get the MSR
193 self.sync += If(uptime[0:cyclewid] == 28,
194 (dmi_addr.eq(0b11), # MSR
195 dmi_req.eq(1),
196 dmi_wen.eq(0),
197 )
198 )
199
200 # read all 32 GPRs
201 for i in range(32):
202 self.sync += If(uptime[0:cyclewid] == 30+(i*8),
203 (dmi_addr.eq(0b100), # GSPR addr
204 dmi_din.eq(i), # r1
205 dmi_req.eq(1),
206 dmi_wen.eq(1),
207 )
208 )
209
210 self.sync += If(uptime[0:cyclewid] == 34+(i*8),
211 (dmi_addr.eq(0b101), # GSPR data
212 dmi_req.eq(1),
213 dmi_wen.eq(0),
214 )
215 )
216
217 # monitor ibus write
218 self.sync += If(self.cpu.ibus.stb & self.cpu.ibus.ack &
219 self.cpu.ibus.we,
220 Display(" [%06x] iadr: %8x, s %01x w %016x",
221 uptime,
222 self.cpu.ibus.adr,
223 self.cpu.ibus.sel,
224 self.cpu.ibus.dat_w,
225 )
226 )
227 # monitor ibus read
228 self.sync += If(self.cpu.ibus.stb & self.cpu.ibus.ack &
229 ~self.cpu.ibus.we,
230 Display(" [%06x] iadr: %8x, s %01x r %016x",
231 uptime,
232 self.cpu.ibus.adr,
233 self.cpu.ibus.sel,
234 self.cpu.ibus.dat_r
235 )
236 )
237
238 # monitor bbus read/write
239 self.sync += If(self.cpu.dbus.stb & self.cpu.dbus.ack,
240 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
241 uptime,
242 self.cpu.dbus.adr,
243 self.cpu.dbus.we,
244 self.cpu.dbus.sel,
245 self.cpu.dbus.dat_w,
246 self.cpu.dbus.dat_r
247 )
248 )
249
250 # Build -----------------------------------------------------------------------
251
252 def main():
253 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
254 parser.add_argument("--cpu", default="libresoc",
255 help="CPU to use: libresoc (default) or microwatt")
256 parser.add_argument("--debug", action="store_true",
257 help="Enable debug traces")
258 parser.add_argument("--trace", action="store_true",
259 help="Enable tracing")
260 parser.add_argument("--trace-start", default=0,
261 help="Cycle to start FST tracing")
262 parser.add_argument("--trace-end", default=-1,
263 help="Cycle to end FST tracing")
264 args = parser.parse_args()
265
266 sim_config = SimConfig(default_clk="sys_clk")
267 sim_config.add_module("serial2console", "serial")
268
269 for i in range(2):
270 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug)
271 builder = Builder(soc,compile_gateware = i!=0)
272 builder.build(sim_config=sim_config,
273 run = i!=0,
274 trace = args.trace,
275 trace_start = int(args.trace_start),
276 trace_end = int(args.trace_end),
277 trace_fst = 0)
278 os.chdir("../")
279
280 if __name__ == "__main__":
281 main()