cpu/vexriscv_smp: move litedram import, remove os.path import.
[litex.git] / litex / soc / cores / cpu / vexriscv_smp / core.py
1 # This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
2 # This file is Copyright (c) 2020 Dolu1990 <charles.papon.90@gmail.com>
3 # License: BSD
4
5 import os
6 from os import path
7
8 from litex import get_data_mod
9 from migen import *
10
11 from litex.soc.interconnect import wishbone
12 from litex.soc.interconnect.csr import *
13 from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32
14
15 import os
16
17
18 CPU_VARIANTS = {
19 "linux": "VexRiscv",
20 }
21
22 class Open(Signal): pass
23
24 class VexRiscvSMP(CPU):
25 name = "vexriscv"
26 human_name = "VexRiscv SMP"
27 variants = CPU_VARIANTS
28 data_width = 32
29 endianness = "little"
30 gcc_triple = CPU_GCC_TRIPLE_RISCV32
31 linker_output_format = "elf32-littleriscv"
32 nop = "nop"
33 io_regions = {0x80000000: 0x80000000} # origin, length
34
35 cpu_count = 1
36 dcache_size = 8192
37 icache_size = 8192
38 dcache_ways = 2
39 icache_ways = 2
40 coherent_dma = False
41 litedram_width = 128
42 dbus_width = 64
43 ibus_width = 64
44
45 @staticmethod
46 def args_fill(parser):
47 parser.add_argument("--cpu-count", default=1, help="")
48 parser.add_argument("--dcache-size", default=8192, help="")
49 parser.add_argument("--dcache-ways", default=2, help="")
50 parser.add_argument("--icache-size", default=8192, help="")
51 parser.add_argument("--icache-ways", default=2, help="")
52
53
54 @staticmethod
55 def args_read(args):
56 VexRiscvSMP.cpu_count = args.cpu_count
57 VexRiscvSMP.dcache_size = args.dcache_size
58 VexRiscvSMP.icache_size = args.icache_size
59 VexRiscvSMP.dcache_ways = args.dcache_ways
60 VexRiscvSMP.icache_ways = args.icache_ways
61
62 @property
63 def mem_map(self):
64 return {
65 "rom": 0x00000000,
66 "sram": 0x10000000,
67 "main_ram": 0x40000000,
68 "csr": 0xf0000000,
69 "clint": 0xf0010000,
70 }
71
72 @property
73 def gcc_flags(self):
74 flags = " -march=rv32ima -mabi=ilp32"
75 flags += " -D__vexriscv__"
76 flags += " -DUART_POLLING"
77 return flags
78
79 @staticmethod
80 def generate_cluster_name():
81 VexRiscvSMP.cluster_name = f"VexRiscvLitexSmpCluster_Cc{VexRiscvSMP.cpu_count}_Iw{VexRiscvSMP.ibus_width}Is{VexRiscvSMP.icache_size}Iy{VexRiscvSMP.icache_ways}_Dw{VexRiscvSMP.dbus_width}Ds{VexRiscvSMP.dcache_size}Dy{VexRiscvSMP.dcache_ways}_Ldw{VexRiscvSMP.litedram_width}{'_Cdma' if VexRiscvSMP.coherent_dma else ''}"
82
83 @staticmethod
84 def generate_default_configs():
85 VexRiscvSMP.ibus_width = 64
86 VexRiscvSMP.dbus_width = 64
87 VexRiscvSMP.dcache_size = 8192
88 VexRiscvSMP.icache_size = 8192
89 VexRiscvSMP.dcache_ways = 2
90 VexRiscvSMP.icache_ways = 2
91 VexRiscvSMP.litedram_width = 128
92
93 VexRiscvSMP.coherent_dma = True
94 for core_count in [1,2,4]:
95 VexRiscvSMP.cpu_count = core_count
96 VexRiscvSMP.generate_cluster_name()
97 VexRiscvSMP.generate_netlist()
98
99 VexRiscvSMP.coherent_dma = False
100 for core_count in [1]:
101 VexRiscvSMP.cpu_count = core_count
102 VexRiscvSMP.generate_cluster_name()
103 VexRiscvSMP.generate_netlist()
104
105
106 @staticmethod
107 def generate_netlist():
108 print(f"Generating cluster netlist")
109 vdir = get_data_mod("cpu", "vexriscv_smp").data_location
110
111 gen_args = []
112 if(VexRiscvSMP.coherent_dma) : gen_args.append("--coherent-dma")
113 gen_args.append(f"--cpu-count={VexRiscvSMP.cpu_count}")
114 gen_args.append(f"--ibus-width={VexRiscvSMP.ibus_width}")
115 gen_args.append(f"--dbus-width={VexRiscvSMP.dbus_width}")
116 gen_args.append(f"--dcache-size={VexRiscvSMP.dcache_size}")
117 gen_args.append(f"--icache-size={VexRiscvSMP.icache_size}")
118 gen_args.append(f"--dcache-ways={VexRiscvSMP.dcache_ways}")
119 gen_args.append(f"--icache-ways={VexRiscvSMP.icache_ways}")
120 gen_args.append(f"--litedram-width={VexRiscvSMP.litedram_width}")
121 gen_args.append(f"--netlist-name={VexRiscvSMP.cluster_name}")
122 gen_args.append(f"--netlist-directory={vdir}")
123
124 cmd = 'cd {path} && sbt "runMain vexriscv.demo.smp.VexRiscvLitexSmpClusterCmdGen {args}"'.format(path=os.path.join(vdir, "ext", "VexRiscv"), args=" ".join(gen_args))
125 os.system(cmd)
126
127 def __init__(self, platform, variant):
128 self.platform = platform
129 self.variant = "standard"
130 self.human_name = self.human_name + "-" + variant.upper()
131 self.reset = Signal()
132 self.jtag_clk = Signal()
133 self.jtag_enable = Signal()
134 self.jtag_capture = Signal()
135 self.jtag_shift = Signal()
136 self.jtag_update = Signal()
137 self.jtag_reset = Signal()
138 self.jtag_tdo = Signal()
139 self.jtag_tdi = Signal()
140 self.interrupt = Signal(32)
141 self.pbus = pbus = wishbone.Interface()
142 self.cbus = cbus = wishbone.Interface()
143 self.plicbus = plicbus = wishbone.Interface()
144
145 self.periph_buses = [pbus]
146 self.memory_buses = [] # Added dynamically
147
148 VexRiscvSMP.generate_cluster_name()
149
150 # # #
151 self.cpu_params = dict(
152 # Clk / Rst
153 i_debugCd_external_clk = ClockSignal(),
154 i_debugCd_external_reset = ResetSignal() | self.reset,
155
156 # Interrupts
157 i_interrupts = self.interrupt,
158
159 # JTAG
160 i_jtag_clk = self.jtag_clk,
161 i_debugPort_enable = self.jtag_enable,
162 i_debugPort_capture = self.jtag_capture,
163 i_debugPort_shift = self.jtag_shift,
164 i_debugPort_update = self.jtag_update,
165 i_debugPort_reset = self.jtag_reset,
166 i_debugPort_tdi = self.jtag_tdi,
167 o_debugPort_tdo = self.jtag_tdo,
168
169 # Peripheral Bus (Master)
170 o_peripheral_CYC = pbus.cyc,
171 o_peripheral_STB = pbus.stb,
172 i_peripheral_ACK = pbus.ack,
173 o_peripheral_WE = pbus.we,
174 o_peripheral_ADR = pbus.adr,
175 i_peripheral_DAT_MISO = pbus.dat_r,
176 o_peripheral_DAT_MOSI = pbus.dat_w,
177 o_peripheral_SEL = pbus.sel,
178 i_peripheral_ERR = pbus.err,
179 o_peripheral_CTI = pbus.cti,
180 o_peripheral_BTE = pbus.bte,
181
182 # CLINT Bus (Slave)
183 i_clintWishbone_CYC = cbus.cyc,
184 i_clintWishbone_STB = cbus.stb,
185 o_clintWishbone_ACK = cbus.ack,
186 i_clintWishbone_WE = cbus.we,
187 i_clintWishbone_ADR = cbus.adr,
188 o_clintWishbone_DAT_MISO = cbus.dat_r,
189 i_clintWishbone_DAT_MOSI = cbus.dat_w,
190
191 # PLIC Bus (Slave)
192 i_plicWishbone_CYC = plicbus.cyc,
193 i_plicWishbone_STB = plicbus.stb,
194 o_plicWishbone_ACK = plicbus.ack,
195 i_plicWishbone_WE = plicbus.we,
196 i_plicWishbone_ADR = plicbus.adr,
197 o_plicWishbone_DAT_MISO = plicbus.dat_r,
198 i_plicWishbone_DAT_MOSI = plicbus.dat_w
199 )
200
201 if self.coherent_dma:
202 self.dma_bus = dma_bus = wishbone.Interface(data_width=64)
203
204 dma_bus_stall = Signal()
205 dma_bus_inhibit = Signal()
206
207 self.cpu_params.update(
208 i_dma_wishbone_CYC = dma_bus.cyc,
209 i_dma_wishbone_STB = dma_bus.stb & ~dma_bus_inhibit,
210 o_dma_wishbone_ACK = dma_bus.ack,
211 i_dma_wishbone_WE = dma_bus.we,
212 i_dma_wishbone_SEL = dma_bus.sel,
213 i_dma_wishbone_ADR = dma_bus.adr,
214 o_dma_wishbone_DAT_MISO = dma_bus.dat_r,
215 i_dma_wishbone_DAT_MOSI = dma_bus.dat_w,
216 o_dma_wishbone_STALL = dma_bus_stall
217 )
218
219 self.sync += [
220 If(dma_bus.stb & dma_bus.cyc & ~dma_bus_stall,
221 dma_bus_inhibit.eq(1),
222 ),
223 If(dma_bus.ack,
224 dma_bus_inhibit.eq(0)
225 )
226 ]
227
228 from litedram.common import LiteDRAMNativePort
229 if "mp" in variant:
230 ncpus = int(variant[-2]) # FIXME
231 for n in range(ncpus):
232 ibus = LiteDRAMNativePort(mode="both", address_width=32, data_width=128)
233 dbus = LiteDRAMNativePort(mode="both", address_width=32, data_width=128)
234 self.memory_buses.append(ibus)
235 self.memory_buses.append(dbus)
236 self.cpu_params.update({
237 # Instruction Memory Bus (Master)
238 "o_io_iMem_{}_cmd_valid".format(n) : ibus.cmd.valid,
239 "i_io_iMem_{}_cmd_ready".format(n) : ibus.cmd.ready,
240 "o_io_iMem_{}_cmd_payload_we".format(n) : ibus.cmd.we,
241 "o_io_iMem_{}_cmd_payload_addr".format(n) : ibus.cmd.addr,
242 "o_io_iMem_{}_wdata_valid".format(n) : ibus.wdata.valid,
243 "i_io_iMem_{}_wdata_ready".format(n) : ibus.wdata.ready,
244 "o_io_iMem_{}_wdata_payload_data".format(n) : ibus.wdata.data,
245 "o_io_iMem_{}_wdata_payload_we".format(n) : ibus.wdata.we,
246 "i_io_iMem_{}_rdata_valid".format(n) : ibus.rdata.valid,
247 "o_io_iMem_{}_rdata_ready".format(n) : ibus.rdata.ready,
248 "i_io_iMem_{}_rdata_payload_data".format(n) : ibus.rdata.data,
249
250 # Data Memory Bus (Master)
251 "o_io_dMem_{}_cmd_valid".format(n) : dbus.cmd.valid,
252 "i_io_dMem_{}_cmd_ready".format(n) : dbus.cmd.ready,
253 "o_io_dMem_{}_cmd_payload_we".format(n) : dbus.cmd.we,
254 "o_io_dMem_{}_cmd_payload_addr".format(n) : dbus.cmd.addr,
255 "o_io_dMem_{}_wdata_valid".format(n) : dbus.wdata.valid,
256 "i_io_dMem_{}_wdata_ready".format(n) : dbus.wdata.ready,
257 "o_io_dMem_{}_wdata_payload_data".format(n) : dbus.wdata.data,
258 "o_io_dMem_{}_wdata_payload_we".format(n) : dbus.wdata.we,
259 "i_io_dMem_{}_rdata_valid".format(n) : dbus.rdata.valid,
260 "o_io_dMem_{}_rdata_ready".format(n) : dbus.rdata.ready,
261 "i_io_dMem_{}_rdata_payload_data".format(n) : dbus.rdata.data,
262 })
263 else:
264 ibus = LiteDRAMNativePort(mode="both", address_width=32, data_width=128)
265 dbus = LiteDRAMNativePort(mode="both", address_width=32, data_width=128)
266 self.memory_buses.append(ibus)
267 self.memory_buses.append(dbus)
268 self.cpu_params.update(
269 # Instruction Memory Bus (Master)
270 o_iBridge_dram_cmd_valid = ibus.cmd.valid,
271 i_iBridge_dram_cmd_ready = ibus.cmd.ready,
272 o_iBridge_dram_cmd_payload_we = ibus.cmd.we,
273 o_iBridge_dram_cmd_payload_addr = ibus.cmd.addr,
274 o_iBridge_dram_wdata_valid = ibus.wdata.valid,
275 i_iBridge_dram_wdata_ready = ibus.wdata.ready,
276 o_iBridge_dram_wdata_payload_data = ibus.wdata.data,
277 o_iBridge_dram_wdata_payload_we = ibus.wdata.we,
278 i_iBridge_dram_rdata_valid = ibus.rdata.valid,
279 o_iBridge_dram_rdata_ready = ibus.rdata.ready,
280 i_iBridge_dram_rdata_payload_data = ibus.rdata.data,
281
282 # Data Memory Bus (Master)
283 o_dBridge_dram_cmd_valid = dbus.cmd.valid,
284 i_dBridge_dram_cmd_ready = dbus.cmd.ready,
285 o_dBridge_dram_cmd_payload_we = dbus.cmd.we,
286 o_dBridge_dram_cmd_payload_addr = dbus.cmd.addr,
287 o_dBridge_dram_wdata_valid = dbus.wdata.valid,
288 i_dBridge_dram_wdata_ready = dbus.wdata.ready,
289 o_dBridge_dram_wdata_payload_data = dbus.wdata.data,
290 o_dBridge_dram_wdata_payload_we = dbus.wdata.we,
291 i_dBridge_dram_rdata_valid = dbus.rdata.valid,
292 o_dBridge_dram_rdata_ready = dbus.rdata.ready,
293 i_dBridge_dram_rdata_payload_data = dbus.rdata.data,
294 )
295
296 # Add verilog sources
297 self.add_sources(platform, variant)
298
299 def set_reset_address(self, reset_address):
300 assert not hasattr(self, "reset_address")
301 self.reset_address = reset_address
302 assert reset_address == 0x00000000
303
304 def add_sources(self, platform, variant):
305 vdir = get_data_mod("cpu", "vexriscv_smp").data_location
306 print(f"VexRiscv cluster : {self.cluster_name}")
307 if not path.exists(os.path.join(vdir, self.cluster_name + ".v")):
308 self.generate_netlist()
309
310 platform.add_source(os.path.join(vdir, "RamXilinx.v"), "verilog")
311 platform.add_source(os.path.join(vdir, self.cluster_name + ".v"), "verilog")
312
313 def do_finalize(self):
314 assert hasattr(self, "reset_address")
315 self.specials += Instance(self.cluster_name, **self.cpu_params)