f88fbf9226a9d84e2c6a186e45559fb859dd0468
[litex.git] / litex / soc / integration / soc_core.py
1 # This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
2 # This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
3 # This file is Copyright (c) 2018 Dolu1990 <charles.papon.90@gmail.com>
4 # This file is Copyright (c) 2019 Gabriel L. Somlo <gsomlo@gmail.com>
5 # This file is Copyright (c) 2019 Ilia Sergachev <ilia.sergachev@protonmail.ch>
6 # This file is Copyright (c) 2018 Jean-François Nguyen <jf@lambdaconcept.fr>
7 # This file is Copyright (c) 2015 Robert Jordens <jordens@gmail.com>
8 # This file is Copyright (c) 2018 Sean Cross <sean@xobs.io>
9 # This file is Copyright (c) 2018 Stafford Horne <shorne@gmail.com>
10 # This file is Copyright (c) 2018-2017 Tim 'mithro' Ansell <me@mith.ro>
11 # This file is Copyright (c) 2015 whitequark <whitequark@whitequark.org>
12 # This file is Copyright (c) 2014 Yann Sionneau <ys@m-labs.hk>
13 # License: BSD
14
15 ####################################################################################################
16 # DISCLAIMER: Provides retro-compatibility layer for existing SoCCore based designs.
17 # Most of the SoC code has been refactored/improved and is now located in integration/soc.py
18 ####################################################################################################
19
20 import os
21 import inspect
22
23 from migen import *
24
25 from litex.soc.cores import cpu
26 from litex.soc.interconnect import wishbone
27 from litex.soc.integration.common import *
28 from litex.soc.integration.soc import *
29
30 __all__ = [
31 "mem_decoder",
32 "get_mem_data",
33 "SoCCore",
34 "soc_core_args",
35 "soc_core_argdict",
36 "SoCMini",
37 "soc_mini_args",
38 "soc_mini_argdict",
39 ]
40
41 # Helpers ------------------------------------------------------------------------------------------
42
43 def mem_decoder(address, size=0x10000000):
44 size = 2**log2_int(size, False)
45 assert (address & (size - 1)) == 0
46 address >>= 2 # bytes to words aligned
47 size >>= 2 # bytes to words aligned
48 return lambda a: (a[log2_int(size):] == (address >> log2_int(size)))
49
50 # SoCCore ------------------------------------------------------------------------------------------
51
52 class SoCCore(LiteXSoC):
53 # default register/interrupt/memory mappings (can be redefined by user)
54 csr_map = {}
55 interrupt_map = {}
56 mem_map = {
57 "rom": 0x00000000,
58 "sram": 0x01000000,
59 "main_ram": 0x40000000,
60 "csr": 0x82000000,
61 }
62
63 def __init__(self, platform, clk_freq,
64 # Bus parameters
65 bus_standard = "wishbone",
66 bus_data_width = 32,
67 bus_address_width = 32,
68 bus_timeout = 1e6,
69 # CPU parameters
70 cpu_type = "vexriscv",
71 cpu_reset_address = None,
72 cpu_variant = None,
73 cpu_cls = None,
74 # ROM parameters
75 integrated_rom_size = 0,
76 integrated_rom_init = [],
77 # SRAM parameters
78 integrated_sram_size = 0x2000,
79 integrated_sram_init = [],
80 # MAIN_RAM parameters
81 integrated_main_ram_size = 0,
82 integrated_main_ram_init = [],
83 # CSR parameters
84 csr_data_width = 8,
85 csr_address_width = 14,
86 csr_paging = 0x800,
87 # Identifier parameters
88 ident = "",
89 ident_version = False,
90 # UART parameters
91 with_uart = True,
92 uart_name = "serial",
93 uart_baudrate = 115200,
94 uart_fifo_depth = 16,
95 # Timer parameters
96 with_timer = True,
97 timer_uptime = False,
98 # Controller parameters
99 with_ctrl = True,
100 # Others
101 **kwargs):
102
103 # New LiteXSoC class ----------------------------------------------------------------------------
104 LiteXSoC.__init__(self, platform, clk_freq,
105 bus_standard = bus_standard,
106 bus_data_width = bus_data_width,
107 bus_address_width = bus_address_width,
108 bus_timeout = bus_timeout,
109 bus_reserved_regions = {},
110
111 csr_data_width = csr_data_width,
112 csr_address_width = csr_address_width,
113 csr_paging = csr_paging,
114 csr_reserved_csrs = self.csr_map,
115
116 irq_n_irqs = 32,
117 irq_reserved_irqs = {},
118 )
119
120 # Attributes
121 self.mem_regions = self.bus.regions
122 self.clk_freq = self.sys_clk_freq
123 self.mem_map = self.mem_map
124 self.config = {}
125
126 # Parameters management --------------------------------------------------------------------
127 cpu_type = None if cpu_type == "None" else cpu_type
128 cpu_reset_address = None if cpu_reset_address == "None" else cpu_reset_address
129
130 self.cpu_type = cpu_type
131 self.cpu_variant = cpu_variant
132 self.cpu_cls = cpu_cls
133
134 self.integrated_rom_size = integrated_rom_size
135 self.integrated_rom_initialized = integrated_rom_init != []
136 self.integrated_sram_size = integrated_sram_size
137 self.integrated_main_ram_size = integrated_main_ram_size
138
139 self.csr_data_width = csr_data_width
140
141 self.wb_slaves = {}
142
143 # Modules instances ------------------------------------------------------------------------
144
145 # Add SoCController
146 if with_ctrl:
147 self.add_controller("ctrl")
148
149 # Add CPU
150 self.add_cpu(
151 name = str(cpu_type),
152 variant = "standard" if cpu_variant is None else cpu_variant,
153 cls = cpu_cls,
154 reset_address = None if integrated_rom_size else cpu_reset_address)
155
156 # Add User's interrupts
157 for name, loc in self.interrupt_map.items():
158 self.irq.add(name, loc)
159
160 # Add integrated ROM
161 if integrated_rom_size:
162 self.add_rom("rom", self.cpu.reset_address, integrated_rom_size, integrated_rom_init)
163
164 # Add integrated SRAM
165 if integrated_sram_size:
166 self.add_ram("sram", self.mem_map["sram"], integrated_sram_size)
167
168 # Add integrated MAIN_RAM (only useful when no external SRAM/SDRAM is available)
169 if integrated_main_ram_size:
170 self.add_ram("main_ram", self.mem_map["main_ram"], integrated_main_ram_size, integrated_main_ram_init)
171
172 # Add Identifier
173 if ident != "":
174 self.add_identifier("identifier", identifier=ident, with_build_time=ident_version)
175
176 # Add UART
177 if with_uart:
178 self.add_uart(name=uart_name, baudrate=uart_baudrate, fifo_depth=uart_fifo_depth)
179
180 # Add Timer
181 if with_timer:
182 self.add_timer(name="timer0")
183 if timer_uptime:
184 self.timer0.add_uptime()
185
186 # Add CSR bridge
187 self.add_csr_bridge(self.mem_map["csr"])
188
189 # Methods --------------------------------------------------------------------------------------
190
191 def add_interrupt(self, interrupt_name, interrupt_id=None, use_loc_if_exists=False):
192 self.irq.add(interrupt_name, interrupt_id, use_loc_if_exists=use_loc_if_exists)
193
194 def add_csr(self, csr_name, csr_id=None, use_loc_if_exists=False):
195 self.csr.add(csr_name, csr_id, use_loc_if_exists=use_loc_if_exists)
196
197 def initialize_rom(self, data):
198 self.rom.mem.init = data
199
200 def add_wb_master(self, wbm):
201 self.bus.add_master(master=wbm)
202
203 def add_wb_slave(self, address, interface, size=None):
204 wb_name = None
205 for name, region in self.bus.regions.items():
206 if address == region.origin:
207 wb_name = name
208 break
209 if wb_name is None:
210 self.wb_slaves[address] = interface
211 else:
212 self.bus.add_slave(name=wb_name, slave=interface)
213
214 def add_memory_region(self, name, origin, length, type="cached"):
215 self.bus.add_region(name, SoCRegion(origin=origin, size=length,
216 cached="cached" in type,
217 linker="linker" in type))
218
219 def register_mem(self, name, address, interface, size=0x10000000):
220 self.bus.add_slave(name, interface, SoCRegion(origin=address, size=size))
221
222 def register_rom(self, interface, rom_size=0xa000):
223 self.bus.add_slave("rom", interface, SoCRegion(origin=self.cpu.reset_address, size=rom_size))
224
225 def add_csr_region(self, name, origin, busword, obj):
226 self.csr_regions[name] = SoCCSRRegion(origin, busword, obj)
227
228 # Finalization ---------------------------------------------------------------------------------
229
230 def do_finalize(self):
231 # Retro-compatibility
232 for address, interface in self.wb_slaves.items():
233 wb_name = None
234 for name, region in self.bus.regions.items():
235 if address == region.origin:
236 wb_name = name
237 break
238 self.bus.add_slave(name=wb_name, slave=interface)
239
240 SoC.do_finalize(self)
241 # Retro-compatibility
242 for region in self.bus.regions.values():
243 region.length = region.size
244 region.type = "cached" if region.cached else "io"
245 if region.linker:
246 region.type += "+linker"
247 self.csr_regions = self.csr.regions
248 for name, value in self.config.items():
249 self.add_config(name, value)
250
251 # SoCCore arguments --------------------------------------------------------------------------------
252
253 def soc_core_args(parser):
254 # Bus parameters
255 parser.add_argument("--bus-standard", default="wishbone",
256 help="select bus standard: {}, (default=wishbone)".format(
257 ", ".join(SoCBusHandler.supported_standard)))
258 parser.add_argument("--bus-data-width", default=32, type=auto_int,
259 help="Bus data width (default=32)")
260 parser.add_argument("--bus-address-width", default=32, type=auto_int,
261 help="Bus address width (default=32)")
262 parser.add_argument("--bus-timeout", default=1e6, type=float,
263 help="Bus timeout in cycles (default=1e6)")
264
265 # CPU parameters
266 parser.add_argument("--cpu-type", default=None,
267 help="select CPU: {}, (default=vexriscv)".format(", ".join(iter(cpu.CPUS.keys()))))
268 parser.add_argument("--cpu-variant", default=None,
269 help="select CPU variant, (default=standard)")
270 parser.add_argument("--cpu-reset-address", default=None, type=auto_int,
271 help="CPU reset address (default=None (Integrated ROM)")
272 # ROM parameters
273 parser.add_argument("--integrated-rom-size", default=0x8000, type=auto_int,
274 help="size/enable the integrated (BIOS) ROM (default=32KB)")
275 parser.add_argument("--integrated-rom-file", default=None, type=str,
276 help="integrated (BIOS) ROM binary file")
277 # SRAM parameters
278 parser.add_argument("--integrated-sram-size", default=0x2000, type=auto_int,
279 help="size/enable the integrated SRAM (default=8KB)")
280 # MAIN_RAM parameters
281 parser.add_argument("--integrated-main-ram-size", default=None, type=auto_int,
282 help="size/enable the integrated main RAM")
283 # CSR parameters
284 parser.add_argument("--csr-data-width", default=None, type=auto_int,
285 help="CSR bus data-width (8 or 32, default=8)")
286 parser.add_argument("--csr-address-width", default=14, type=auto_int,
287 help="CSR bus address-width")
288 parser.add_argument("--csr-paging", default=0x800, type=auto_int,
289 help="CSR bus paging")
290 # Identifier parameters
291 parser.add_argument("--ident", default=None, type=str,
292 help="SoC identifier (default=\"\"")
293 parser.add_argument("--ident-version", default=None, type=bool,
294 help="add date/time to SoC identifier (default=False)")
295 # UART parameters
296 parser.add_argument("--no-uart", action="store_true",
297 help="Disable UART (default=False)")
298 parser.add_argument("--uart-name", default="serial", type=str,
299 help="UART type/name (default=serial)")
300 parser.add_argument("--uart-baudrate", default=None, type=auto_int,
301 help="UART baudrate (default=115200)")
302 parser.add_argument("--uart-fifo-depth", default=16, type=auto_int,
303 help="UART FIFO depth (default=16)")
304 # Timer parameters
305 parser.add_argument("--no-timer", action="store_true",
306 help="Disable Timer (default=False)")
307 # Controller parameters
308 parser.add_argument("--no-ctrl", action="store_true",
309 help="Disable Controller (default=False)")
310
311 def soc_core_argdict(args):
312 r = dict()
313 rom_file = getattr(args, "integrated_rom_file", None)
314 if rom_file is not None:
315 args.integrated_rom_init = get_mem_data(rom_file, "little") # FIXME: endianness
316 args.integrated_rom_size = len(args.integrated_rom_init)*4
317 for a in inspect.getargspec(SoCCore.__init__).args:
318 if a not in ["self", "platform"]:
319 if a in ["with_uart", "with_timer", "with_ctrl"]:
320 arg = not getattr(args, a.replace("with", "no"), True)
321 else:
322 arg = getattr(args, a, None)
323 if arg is not None:
324 r[a] = arg
325 return r
326
327 # SoCMini ---------------------------------------------------------------------------------------
328
329 class SoCMini(SoCCore):
330 def __init__(self, *args, **kwargs):
331 if "cpu_type" not in kwargs.keys():
332 kwargs["cpu_type"] = "None"
333 if "integrated_sram_size" not in kwargs.keys():
334 kwargs["integrated_sram_size"] = 0
335 if "with_uart" not in kwargs.keys():
336 kwargs["with_uart"] = False
337 if "with_timer" not in kwargs.keys():
338 kwargs["with_timer"] = False
339
340 SoCCore.__init__(self, *args, **kwargs)
341
342 # SoCMini arguments -----------------------------------------------------------------------------
343
344 soc_mini_args = soc_core_args
345 soc_mini_argdict = soc_core_argdict