single-step and print out PC using DMI in litex sim
[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.builder import Builder
16
17 from litex.tools.litex_sim import Platform
18
19 from libresoc import LibreSoC
20 from microwatt import Microwatt
21
22 # LibreSoCSim -----------------------------------------------------------------
23
24 class LibreSoCSim(SoCCore):
25 def __init__(self, cpu="libresoc", debug=False):
26 assert cpu in ["libresoc", "microwatt"]
27 platform = Platform()
28 sys_clk_freq = int(1e6)
29
30 # SoCCore -------------------------------------------------------------
31 SoCCore.__init__(self, platform, clk_freq=sys_clk_freq,
32 cpu_type = "microwatt",
33 cpu_cls = LibreSoC if cpu == "libresoc" \
34 else Microwatt,
35 uart_name = "sim",
36 integrated_rom_size = 0x10000,
37 integrated_main_ram_size = 0x10000000) # 256MB
38 self.platform.name = "sim"
39
40 # CRG -----------------------------------------------------------------
41 self.submodules.crg = CRG(platform.request("sys_clk"))
42
43 # Debug ---------------------------------------------------------------
44 if not debug:
45 return
46
47 # setup running of DMI FSM
48 dmi_addr = Signal(3)
49 dmi_din = Signal(64)
50 dmi_dout = Signal(64)
51 dmi_wen = Signal(1)
52 dmi_req = Signal(1)
53
54 # debug log out
55 dbg_addr = Signal(3)
56 dbg_dout = Signal(64)
57 dbg_msg = Signal(1)
58
59 uptime = Signal(64)
60 # increment counter, Stop after 100000 cycles
61 uptime = Signal(64)
62 self.sync += uptime.eq(uptime + 1)
63 self.sync += If(uptime == 100000, Finish())
64
65 dmifsm = FSM()
66 self.submodules += dmifsm
67
68 # DMI FSM
69 dmifsm.act("START",
70 If(dmi_req & dmi_wen,
71 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
72 self.cpu.dmi_din.eq(dmi_din), # DMI in
73 self.cpu.dmi_req.eq(1), # DMI request
74 self.cpu.dmi_wr.eq(1), # DMI write
75 If(self.cpu.dmi_ack,
76 (NextState("IDLE"),
77 )
78 ),
79 ),
80 ),
81 If(dmi_req & ~dmi_wen,
82 (self.cpu.dmi_addr.eq(dmi_addr), # DMI Addr
83 self.cpu.dmi_req.eq(1), # DMI request
84 self.cpu.dmi_wr.eq(0), # DMI read
85 If(self.cpu.dmi_ack,
86 (NextState("IDLE"),
87 NextValue(dbg_addr, dmi_addr),
88 NextValue(dbg_dout, self.cpu.dmi_dout),
89 NextValue(dbg_msg, 1),
90 )
91 ),
92 ),
93 )
94 )
95
96 dmifsm.act("IDLE",
97 (NextValue(dmi_req, 0),
98 NextValue(dmi_addr, 0),
99 NextValue(dmi_din, 0),
100 NextValue(dmi_wen, 0),
101 NextState("START"), # back to start on next cycle
102 )
103 )
104
105 # debug messages out
106 self.sync += If(dbg_msg,
107 (Display("[%06x] dbg: %1x, %016x", uptime, dbg_addr, dbg_dout),
108 dbg_msg.eq(0)
109 )
110 )
111
112 # kick off a "stop"
113 self.sync += If(uptime == 0,
114 (dmi_addr.eq(0), # CTRL
115 dmi_din.eq(1<<0), # STOP
116 dmi_req.eq(1),
117 dmi_wen.eq(1),
118 )
119 )
120
121 # loop every 1<<N cycles
122 cyclewid = 8
123
124 # kick off a "step"
125 self.sync += If(uptime[0:cyclewid] == 4,
126 (dmi_addr.eq(0), # CTRL
127 dmi_din.eq(1<<3), # STEP
128 dmi_req.eq(1),
129 dmi_wen.eq(1),
130 )
131 )
132
133 # get the PC
134 self.sync += If(uptime[0:cyclewid] == 8,
135 (dmi_addr.eq(0b10), # NIA
136 dmi_req.eq(1),
137 dmi_wen.eq(0),
138 )
139 )
140
141 # monitor ibus write
142 self.sync += If(self.cpu.ibus.stb & self.cpu.ibus.ack &
143 self.cpu.ibus.we,
144 Display("[%06x] iadr: %8x, s %01x w %016x",
145 uptime,
146 self.cpu.ibus.adr,
147 self.cpu.ibus.sel,
148 self.cpu.ibus.dat_w,
149 )
150 )
151 # monitor ibus read
152 self.sync += If(self.cpu.ibus.stb & self.cpu.ibus.ack &
153 ~self.cpu.ibus.we,
154 Display("[%06x] iadr: %8x, s %01x r %016x",
155 uptime,
156 self.cpu.ibus.adr,
157 self.cpu.ibus.sel,
158 self.cpu.ibus.dat_r
159 )
160 )
161
162 # monitor bbus read/write
163 self.sync += If(self.cpu.dbus.stb & self.cpu.dbus.ack,
164 Display("[%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
165 uptime,
166 self.cpu.dbus.adr,
167 self.cpu.dbus.we,
168 self.cpu.dbus.sel,
169 self.cpu.dbus.dat_w,
170 self.cpu.dbus.dat_r
171 )
172 )
173
174 # Build -----------------------------------------------------------------------
175
176 def main():
177 parser = argparse.ArgumentParser(description="LiteX LibreSoC CPU Sim")
178 parser.add_argument("--cpu", default="libresoc",
179 help="CPU to use: libresoc (default) or microwatt")
180 parser.add_argument("--debug", action="store_true",
181 help="Enable debug traces")
182 parser.add_argument("--trace", action="store_true",
183 help="Enable tracing")
184 parser.add_argument("--trace-start", default=0,
185 help="Cycle to start FST tracing")
186 parser.add_argument("--trace-end", default=-1,
187 help="Cycle to end FST tracing")
188 args = parser.parse_args()
189
190 sim_config = SimConfig(default_clk="sys_clk")
191 sim_config.add_module("serial2console", "serial")
192
193 for i in range(2):
194 soc = LibreSoCSim(cpu=args.cpu, debug=args.debug)
195 builder = Builder(soc,compile_gateware = i!=0)
196 builder.build(sim_config=sim_config,
197 run = i!=0,
198 trace = args.trace,
199 trace_start = int(args.trace_start),
200 trace_end = int(args.trace_end),
201 trace_fst = 0)
202 os.chdir("../")
203
204 if __name__ == "__main__":
205 main()