soc_core: add back identifier
[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 # CPU parameters
65 cpu_type = "vexriscv",
66 cpu_reset_address = 0x00000000,
67 cpu_variant = None,
68 # ROM parameters
69 integrated_rom_size = 0,
70 integrated_rom_init = [],
71 # SRAM parameters
72 integrated_sram_size = 0x1000,
73 integrated_sram_init = [],
74 # MAIN_RAM parameters
75 integrated_main_ram_size = 0,
76 integrated_main_ram_init = [],
77 # CSR parameters
78 csr_data_width = 8,
79 csr_alignment = 32,
80 csr_address_width = 14,
81 # Identifier parameters
82 ident = "",
83 ident_version = False,
84 # UART parameters
85 with_uart = True,
86 uart_name = "serial",
87 uart_baudrate = 115200,
88 # Timer parameters
89 with_timer = True,
90 # Controller parameters
91 with_ctrl = True,
92 # Wishbone parameters
93 with_wishbone = True,
94 wishbone_timeout_cycles = 1e6,
95 # Others
96 **kwargs):
97
98 # New LiteXSoC class ----------------------------------------------------------------------------
99 LiteXSoC.__init__(self, platform, clk_freq,
100 bus_standard = "wishbone",
101 bus_data_width = 32,
102 bus_address_width = 32,
103 bus_timeout = wishbone_timeout_cycles,
104 bus_reserved_regions = {},
105
106 csr_data_width = csr_data_width,
107 csr_address_width = csr_address_width,
108 csr_alignment = csr_alignment,
109 csr_paging = 0x800,
110 csr_reserved_csrs = self.csr_map,
111
112 irq_n_irqs = 32,
113 irq_reserved_irqs = {},
114 )
115
116 # Attributes
117 self.mem_regions = self.bus.regions
118 self.clk_freq = self.sys_clk_freq
119 self.mem_map = self.mem_map
120 self.config = {}
121
122 # Parameters management --------------------------------------------------------------------
123 cpu_type = None if cpu_type == "None" else cpu_type
124 cpu_variant = cpu.check_format_cpu_variant(cpu_variant)
125
126 if not with_wishbone:
127 self.mem_map["csr"] = 0x00000000
128
129 self.cpu_type = cpu_type
130 self.cpu_variant = cpu_variant
131
132 self.integrated_rom_size = integrated_rom_size
133 self.integrated_rom_initialized = integrated_rom_init != []
134 self.integrated_sram_size = integrated_sram_size
135 self.integrated_main_ram_size = integrated_main_ram_size
136
137 self.csr_data_width = csr_data_width
138
139 self.with_wishbone = with_wishbone
140 self.wishbone_timeout_cycles = wishbone_timeout_cycles
141
142 self.wb_slaves = {}
143
144 # Modules instances ------------------------------------------------------------------------
145
146 # Add SoCController
147 if with_ctrl:
148 self.add_controller("ctrl")
149
150 # Add CPU
151 self.add_cpu(
152 name = str(cpu_type),
153 variant = "standard" if cpu_variant is None else cpu_variant,
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)
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)
179
180 # Add Timer
181 if with_timer:
182 self.add_timer(name="timer0")
183
184 # Add Wishbone to CSR bridge
185 if with_wishbone:
186 self.add_csr_bridge(self.mem_map["csr"])
187
188 # Methods --------------------------------------------------------------------------------------
189
190 def add_interrupt(self, interrupt_name, interrupt_id=None, use_loc_if_exists=False):
191 self.irq.add(interrupt_name, interrupt_id, use_loc_if_exists=use_loc_if_exists)
192
193 def add_csr(self, csr_name, csr_id=None, use_loc_if_exists=False):
194 self.csr.add(csr_name, csr_id, use_loc_if_exists=use_loc_if_exists)
195
196 def initialize_rom(self, data):
197 self.rom.mem.init = data
198
199 def add_wb_master(self, wbm):
200 self.bus.add_master(master=wbm)
201
202 def add_wb_slave(self, address, interface, size=None):
203 wb_name = None
204 for name, region in self.bus.regions.items():
205 if address == region.origin:
206 wb_name = name
207 break
208 if wb_name is None:
209 self.wb_slaves[address] = interface
210 else:
211 self.bus.add_slave(name=wb_name, slave=interface)
212
213 def add_memory_region(self, name, origin, length, type="cached"):
214 self.bus.add_region(name, SoCRegion(origin=origin, size=length,
215 cached="cached" in type,
216 linker="linker" in type))
217
218 def register_mem(self, name, address, interface, size=0x10000000):
219 self.bus.add_slave(name, interface, SoCRegion(origin=address, size=size))
220
221 def register_rom(self, interface, rom_size=0xa000):
222 self.bus.add_slave("rom", interface, SoCRegion(origin=self.cpu.reset_address, size=rom_size))
223
224 def add_csr_region(self, name, origin, busword, obj):
225 self.csr_regions[name] = SoCCSRRegion(origin, busword, obj)
226
227 # Finalization ---------------------------------------------------------------------------------
228
229 def do_finalize(self):
230 # Retro-compatibility
231 for address, interface in self.wb_slaves.items():
232 wb_name = None
233 for name, region in self.bus.regions.items():
234 if address == region.origin:
235 wb_name = name
236 break
237 self.bus.add_slave(name=wb_name, slave=interface)
238
239 SoC.do_finalize(self)
240 # Retro-compatibility
241 for region in self.bus.regions.values():
242 region.length = region.size
243 region.type = "cached" if region.cached else "io"
244 self.csr_regions = self.csr.regions
245 for name, value in self.config.items():
246 self.add_config(name, value)
247
248 # SoCCore arguments --------------------------------------------------------------------------------
249
250 def soc_core_args(parser):
251 # CPU parameters
252 parser.add_argument("--cpu-type", default=None,
253 help="select CPU: {}, (default=vexriscv)".format(", ".join(iter(cpu.CPUS.keys()))))
254 parser.add_argument("--cpu-variant", default=None,
255 help="select CPU variant, (default=standard)")
256 parser.add_argument("--cpu-reset-address", default=None, type=int,
257 help="CPU reset address (default=0x00000000 or ROM)")
258 # ROM parameters
259 parser.add_argument("--integrated-rom-size", default=0x8000, type=int,
260 help="size/enable the integrated (BIOS) ROM (default=32KB)")
261 parser.add_argument("--integrated-rom-file", default=None, type=str,
262 help="integrated (BIOS) ROM binary file")
263 # SRAM parameters
264 parser.add_argument("--integrated-sram-size", default=0x1000, type=int,
265 help="size/enable the integrated SRAM (default=4KB)")
266 # MAIN_RAM parameters
267 parser.add_argument("--integrated-main-ram-size", default=None, type=int,
268 help="size/enable the integrated main RAM")
269 # CSR parameters
270 parser.add_argument("--csr-data-width", default=None, type=int,
271 help="CSR bus data-width (8 or 32, default=8)")
272 parser.add_argument("--csr-address-width", default=14, type=int,
273 help="CSR bus address-width")
274 # Identifier parameters
275 parser.add_argument("--ident", default=None, type=str,
276 help="SoC identifier (default=\"\"")
277 parser.add_argument("--ident-version", default=None, type=bool,
278 help="add date/time to SoC identifier (default=False)")
279 # UART parameters
280 parser.add_argument("--with-uart", default=None, type=bool,
281 help="with UART (default=True)")
282 parser.add_argument("--uart-name", default="serial", type=str,
283 help="UART type/name (default=serial)")
284 parser.add_argument("--uart-baudrate", default=None, type=int,
285 help="UART baudrate (default=115200)")
286 parser.add_argument("--uart-stub", default=False, type=bool,
287 help="enable UART stub (default=False)")
288 # Timer parameters
289 parser.add_argument("--with-timer", default=None, type=bool,
290 help="with Timer (default=True)")
291 # Controller parameters
292 parser.add_argument("--with-ctrl", default=None, type=bool,
293 help="with Controller (default=True)")
294
295 def soc_core_argdict(args):
296 r = dict()
297 rom_file = getattr(args, "integrated_rom_file", None)
298 if rom_file is not None:
299 args.integrated_rom_init = get_mem_data(rom_file, "little") # FIXME: endianness
300 args.integrated_rom_size = len(args.integrated_rom_init)*4
301 for a in inspect.getargspec(SoCCore.__init__).args:
302 if a not in ["self", "platform"]:
303 arg = getattr(args, a, None)
304 if arg is not None:
305 r[a] = arg
306 return r
307
308 # SoCMini ---------------------------------------------------------------------------------------
309
310 class SoCMini(SoCCore):
311 def __init__(self, *args, **kwargs):
312 if "cpu_type" not in kwargs.keys():
313 kwargs["cpu_type"] = "None"
314 if "integrated_sram_size" not in kwargs.keys():
315 kwargs["integrated_sram_size"] = 0
316 if "with_uart" not in kwargs.keys():
317 kwargs["with_uart"] = False
318 if "with_timer" not in kwargs.keys():
319 kwargs["with_timer"] = False
320
321 SoCCore.__init__(self, *args, **kwargs)
322
323 # SoCMini arguments -----------------------------------------------------------------------------
324
325 soc_mini_args = soc_core_args
326 soc_mini_argdict = soc_core_argdict