Merge branch 'master' of https://github.com/enjoy-digital/litex
[litex.git] / litex / soc / integration / soc_core.py
1 import os
2 import struct
3 import inspect
4 import json
5 from operator import itemgetter
6
7 from migen import *
8
9 from litex.soc.cores import identifier, timer, uart
10 from litex.soc.cores.cpu import *
11 from litex.soc.interconnect.csr import *
12 from litex.soc.interconnect import wishbone, csr_bus, wishbone2csr
13
14
15 __all__ = [
16 "mem_decoder",
17 "get_mem_data",
18 "csr_map_update",
19 "SoCCore",
20 "soc_core_args",
21 "soc_core_argdict"
22 ]
23
24
25 def version(with_time=True):
26 import datetime
27 import time
28 if with_time:
29 return datetime.datetime.fromtimestamp(
30 time.time()).strftime("%Y-%m-%d %H:%M:%S")
31 else:
32 return datetime.datetime.fromtimestamp(
33 time.time()).strftime("%Y-%m-%d")
34
35
36 def mem_decoder(address, start=26, end=29):
37 return lambda a: a[start:end] == ((address >> (start+2)) & (2**(end-start))-1)
38
39
40 def get_mem_data(filename, endianness="big", mem_size=None):
41 # create memory regions
42 _, ext = os.path.splitext(filename)
43 if ext == ".json":
44 f = open(filename, "r")
45 regions = json.load(f)
46 f.close()
47 else:
48 regions = {filename: "0x00000000"}
49
50 # determine data_size
51 data_size = 0
52 for filename, base in regions.items():
53 data_size = max(int(base, 16) + os.path.getsize(filename), data_size)
54 assert data_size > 0
55 if mem_size is not None:
56 assert data_size < mem_size, (
57 "file is too big: {}/{} bytes".format(
58 data_size, mem_size))
59
60 # fill data
61 data = [0]*(data_size//4)
62 for filename, base in regions.items():
63 with open(filename, "rb") as f:
64 i = 0
65 while True:
66 w = f.read(4)
67 if not w:
68 break
69 if len(w) != 4:
70 for i in range(len(w), 4):
71 w += b'\x00'
72 if endianness == "little":
73 data[i] = struct.unpack("<I", w)[0]
74 else:
75 data[i] = struct.unpack(">I", w)[0]
76 i += 1
77 return data
78
79 class ReadOnlyDict(dict):
80 def __readonly__(self, *args, **kwargs):
81 raise RuntimeError("Cannot modify ReadOnlyDict")
82 __setitem__ = __readonly__
83 __delitem__ = __readonly__
84 pop = __readonly__
85 popitem = __readonly__
86 clear = __readonly__
87 update = __readonly__
88 setdefault = __readonly__
89 del __readonly__
90
91
92 def csr_map_update(csr_map, csr_peripherals):
93 csr_map.update(dict((n, v)
94 for v, n in enumerate(csr_peripherals, start=max(csr_map.values()) + 1)))
95
96
97 class SoCController(Module, AutoCSR):
98 def __init__(self):
99 self._reset = CSR()
100 self._scratch = CSRStorage(32, reset=0x12345678)
101 self._bus_errors = CSRStatus(32)
102
103 # # #
104
105 # reset
106 self.reset = Signal()
107 self.comb += self.reset.eq(self._reset.re)
108
109 # bus errors
110 self.bus_error = Signal()
111 bus_errors = Signal(32)
112 self.sync += \
113 If(bus_errors != (2**len(bus_errors)-1),
114 If(self.bus_error,
115 bus_errors.eq(bus_errors + 1)
116 )
117 )
118 self.comb += self._bus_errors.status.eq(bus_errors)
119
120
121 class SoCCore(Module):
122 csr_map = {
123 "ctrl": 0, # provided by default (optional)
124 "crg": 1, # user
125 "uart_phy": 2, # provided by default (optional)
126 "uart": 3, # provided by default (optional)
127 "identifier_mem": 4, # provided by default (optional)
128 "timer0": 5, # provided by default (optional)
129 "buttons": 6, # user
130 "leds": 7, # user
131 }
132 interrupt_map = {}
133 soc_interrupt_map = {
134 "timer0": 1, # LiteX Timer
135 "uart": 2, # LiteX UART (IRQ 2 for UART matches mor1k standard config).
136 }
137 mem_map = {
138 "rom": 0x00000000, # (default shadow @0x80000000)
139 "sram": 0x10000000, # (default shadow @0x90000000)
140 "main_ram": 0x40000000, # (default shadow @0xc0000000)
141 "csr": 0x60000000, # (default shadow @0xe0000000)
142 }
143 def __init__(self, platform, clk_freq,
144 cpu_type="lm32", cpu_reset_address=0x00000000, cpu_variant=None,
145 integrated_rom_size=0, integrated_rom_init=[],
146 integrated_sram_size=4096,
147 integrated_main_ram_size=0, integrated_main_ram_init=[],
148 shadow_base=0x80000000,
149 csr_data_width=8, csr_address_width=14, csr_expose=False,
150 with_uart=True, uart_name="serial", uart_baudrate=115200, uart_stub=False,
151 ident="", ident_version=False,
152 wishbone_timeout_cycles=1e6,
153 reserve_nmi_interrupt=True,
154 with_timer=True,
155 with_ctrl=True):
156 self.config = dict()
157
158 self.platform = platform
159 self.clk_freq = clk_freq
160
161 if cpu_type == "None":
162 cpu_type = None
163 self.cpu_type = cpu_type
164 self.cpu_variant = cpu_variant
165 if integrated_rom_size:
166 cpu_reset_address = self.mem_map["rom"]
167 self.cpu_reset_address = cpu_reset_address
168 self.config["CPU_RESET_ADDR"] = self.cpu_reset_address
169
170 self.integrated_rom_size = integrated_rom_size
171 self.integrated_rom_initialized = integrated_rom_init != []
172 self.integrated_sram_size = integrated_sram_size
173 self.integrated_main_ram_size = integrated_main_ram_size
174
175 self.with_uart = with_uart
176 self.uart_baudrate = uart_baudrate
177
178 self.shadow_base = shadow_base
179
180 self.wishbone_timeout_cycles = wishbone_timeout_cycles
181
182 self.csr_data_width = csr_data_width
183 self.csr_address_width = csr_address_width
184 self.csr_expose = csr_expose
185 if csr_expose:
186 self.csr = csr_bus.Interface(csr_data_width, csr_address_width)
187
188 self.with_ctrl = with_ctrl
189
190 self._memory_regions = [] # list of (name, origin, length)
191 self._csr_regions = [] # list of (name, origin, busword, csr_list/Memory)
192 self._constants = [] # list of (name, value)
193
194 self._wb_masters = []
195 self._wb_slaves = []
196
197 if with_ctrl:
198 self.submodules.ctrl = SoCController()
199
200 if cpu_type is not None:
201 if cpu_type == "lm32":
202 self.add_cpu(lm32.LM32(platform, self.cpu_reset_address, self.cpu_variant))
203 elif cpu_type == "or1k":
204 self.add_cpu(mor1kx.MOR1KX(platform, self.cpu_reset_address, self.cpu_variant))
205 elif cpu_type == "picorv32":
206 self.add_cpu(picorv32.PicoRV32(platform, self.cpu_reset_address, self.cpu_variant))
207 elif cpu_type == "vexriscv":
208 self.add_cpu(vexriscv.VexRiscv(platform, self.cpu_reset_address, self.cpu_variant))
209 elif cpu_type == "minerva":
210 self.add_cpu(minerva.Minerva(platform, self.cpu_reset_address, self.cpu_variant))
211 else:
212 raise ValueError("Unsupported CPU type: {}".format(cpu_type))
213 self.add_wb_master(self.cpu.ibus)
214 self.add_wb_master(self.cpu.dbus)
215 if with_ctrl:
216 self.comb += self.cpu.reset.eq(self.ctrl.reset)
217 self.config["CPU_TYPE"] = str(cpu_type).upper()
218 if self.cpu_variant:
219 self.config["CPU_VARIANT"] = str(cpu_type).upper()
220
221 if integrated_rom_size:
222 self.submodules.rom = wishbone.SRAM(integrated_rom_size, read_only=True, init=integrated_rom_init)
223 self.register_rom(self.rom.bus, integrated_rom_size)
224
225 if integrated_sram_size:
226 self.submodules.sram = wishbone.SRAM(integrated_sram_size)
227 self.register_mem("sram", self.mem_map["sram"], self.sram.bus, integrated_sram_size)
228
229 # Note: Main Ram can be used when no external SDRAM is available and use SDRAM mapping.
230 if integrated_main_ram_size:
231 self.submodules.main_ram = wishbone.SRAM(integrated_main_ram_size, init=integrated_main_ram_init)
232 self.register_mem("main_ram", self.mem_map["main_ram"], self.main_ram.bus, integrated_main_ram_size)
233
234 self.submodules.wishbone2csr = wishbone2csr.WB2CSR(
235 bus_csr=csr_bus.Interface(csr_data_width, csr_address_width))
236 self.config["CSR_DATA_WIDTH"] = csr_data_width
237 self.add_constant("CSR_DATA_WIDTH", csr_data_width)
238 self.register_mem("csr", self.mem_map["csr"], self.wishbone2csr.wishbone)
239
240 if reserve_nmi_interrupt:
241 self.soc_interrupt_map["nmi"] = 0 # Reserve zero for "non-maskable interrupt"
242
243 if with_uart:
244 if uart_stub:
245 self.submodules.uart = uart.UARTStub()
246 else:
247 self.submodules.uart_phy = uart.RS232PHY(platform.request(uart_name), clk_freq, uart_baudrate)
248 self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy))
249
250 #else:
251 # del self.soc_interrupt_map["uart"]
252
253 if ident:
254 if ident_version:
255 ident = ident + " " + version()
256 self.submodules.identifier = identifier.Identifier(ident)
257 self.config["CLOCK_FREQUENCY"] = int(clk_freq)
258 self.add_constant("SYSTEM_CLOCK_FREQUENCY", int(clk_freq))
259
260 if with_timer:
261 self.submodules.timer0 = timer.Timer()
262 #else:
263 # del self.soc_interrupt_map["timer0"]
264
265 # Invert the interrupt map.
266 interrupt_rmap = {}
267 for mod_name, interrupt in self.interrupt_map.items():
268 assert interrupt not in interrupt_rmap, (
269 "Interrupt vector conflict for IRQ %s, user defined %s conflicts with user defined %s" % (
270 interrupt, mod_name, interrupt_rmap[interrupt]))
271
272 interrupt_rmap[interrupt] = mod_name
273
274 # Add the base SoC's interrupt map
275 for mod_name, interrupt in self.soc_interrupt_map.items():
276 assert interrupt not in interrupt_rmap or mod_name == interrupt_rmap[interrupt], (
277 "Interrupt vector conflict for IRQ %s, user defined %s conflicts with SoC inbuilt %s" % (
278 interrupt, mod_name, interrupt_rmap[interrupt]))
279
280 self.interrupt_map[mod_name] = interrupt
281 interrupt_rmap[interrupt] = mod_name
282
283 # Make sure other functions are not using this value.
284 self.soc_interrupt_map = None
285
286 # Make the interrupt vector read only
287 self.interrupt_map = ReadOnlyDict(self.interrupt_map)
288
289 # Save the interrupt reverse map
290 self.interrupt_rmap = ReadOnlyDict(interrupt_rmap)
291
292
293 def add_cpu(self, cpu):
294 if self.finalized:
295 raise FinalizeError
296 if hasattr(self, "cpu"):
297 raise NotImplementedError("More than one CPU is not supported")
298 self.submodules.cpu = cpu
299
300 def add_cpu_or_bridge(self, cpu_or_bridge):
301 print("[WARNING] Please update SoCCore's \"add_cpu_or_bridge\" call to \"add_cpu\"")
302 self.add_cpu(cpu_or_bridge)
303 self.cpu_or_bridge = self.cpu
304
305 def initialize_rom(self, data):
306 self.rom.mem.init = data
307
308 def add_wb_master(self, wbm):
309 if self.finalized:
310 raise FinalizeError
311 self._wb_masters.append(wbm)
312
313 def add_wb_slave(self, address_decoder, interface):
314 if self.finalized:
315 raise FinalizeError
316 self._wb_slaves.append((address_decoder, interface))
317
318 def add_memory_region(self, name, origin, length):
319 def in_this_region(addr):
320 return addr >= origin and addr < origin + length
321 for n, o, l in self._memory_regions:
322 if n == name or in_this_region(o) or in_this_region(o+l-1):
323 raise ValueError("Memory region conflict between {} and {}".format(n, name))
324
325 self._memory_regions.append((name, origin, length))
326
327 def register_mem(self, name, address, interface, size=None):
328 self.add_wb_slave(mem_decoder(address), interface)
329 if size is not None:
330 self.add_memory_region(name, address, size)
331
332 def register_rom(self, interface, rom_size=0xa000):
333 self.add_wb_slave(mem_decoder(self.mem_map["rom"]), interface)
334 self.add_memory_region("rom", self.cpu_reset_address, rom_size)
335
336 def get_memory_regions(self):
337 return self._memory_regions
338
339 def check_csr_range(self, name, addr):
340 if addr >= 1<<(self.csr_address_width+2):
341 raise ValueError("{} CSR out of range, increase csr_address_width".format(name))
342
343 def check_csr_region(self, name, origin):
344 for n, o, l, obj in self._csr_regions:
345 if n == name or o == origin:
346 raise ValueError("CSR region conflict between {} and {}".format(n, name))
347
348 def add_csr_region(self, name, origin, busword, obj):
349 self.check_csr_region(name, origin)
350 self._csr_regions.append((name, origin, busword, obj))
351
352 def get_csr_regions(self):
353 return self._csr_regions
354
355 def add_constant(self, name, value=None):
356 self._constants.append((name, value))
357
358 def get_constants(self):
359 r = []
360 for interrupt, name in sorted(self.interrupt_rmap.items()):
361 r.append((name.upper() + "_INTERRUPT", interrupt))
362 r += self._constants
363 return r
364
365 def get_csr_dev_address(self, name, memory):
366 if memory is not None:
367 name = name + "_" + memory.name_override
368 try:
369 return self.csr_map[name]
370 except KeyError as e:
371 msg = "Undefined \"{}\" CSR.\n".format(name)
372 msg += "Avalaible CSRs in {} ({}):\n".format(
373 self.__class__.__name__, inspect.getfile(self.__class__))
374 for k in sorted(self.csr_map.keys()):
375 msg += "- {}\n".format(k)
376 raise RuntimeError(msg)
377 except ValueError:
378 return None
379
380 def do_finalize(self):
381 registered_mems = {regions[0] for regions in self._memory_regions}
382 if self.cpu_type is not None:
383 for mem in "rom", "sram":
384 if mem not in registered_mems:
385 raise FinalizeError("CPU needs a {} to be registered with SoC.register_mem()".format(mem))
386
387 if len(self._wb_masters):
388 # Wishbone
389 self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
390 self._wb_slaves, register=True, timeout_cycles=self.wishbone_timeout_cycles)
391 if self.with_ctrl and (self.wishbone_timeout_cycles is not None):
392 self.comb += self.ctrl.bus_error.eq(self.wishbonecon.timeout.error)
393
394 # CSR
395 self.submodules.csrbankarray = csr_bus.CSRBankArray(self,
396 self.get_csr_dev_address,
397 data_width=self.csr_data_width, address_width=self.csr_address_width)
398 if self.csr_expose:
399 self.submodules.csrcon = csr_bus.InterconnectShared(
400 [self.csr, self.wishbone2csr.csr], self.csrbankarray.get_buses())
401 else:
402 self.submodules.csrcon = csr_bus.Interconnect(
403 self.wishbone2csr.csr, self.csrbankarray.get_buses())
404 for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
405 self.check_csr_range(name, 0x800*mapaddr)
406 self.add_csr_region(name, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, csrs)
407 for name, memory, mapaddr, mmap in self.csrbankarray.srams:
408 self.check_csr_range(name, 0x800*mapaddr)
409 self.add_csr_region(name + "_" + memory.name_override, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, memory)
410 for name, constant in self.csrbankarray.constants:
411 self._constants.append(((name + "_" + constant.name).upper(), constant.value.value))
412 for name, value in sorted(self.config.items(), key=itemgetter(0)):
413 self._constants.append(("CONFIG_" + name.upper(), value))
414
415 # Interrupts
416 if hasattr(self, "cpu"):
417 if hasattr(self.cpu, "interrupt"):
418 for interrupt, mod_name in sorted(self.interrupt_rmap.items()):
419 if mod_name == "nmi":
420 continue
421 if hasattr(self, mod_name):
422 mod_impl = getattr(self, mod_name)
423 assert hasattr(mod_impl, 'ev'), "Submodule %s does not have EventManager (xx.ev) module" % mod_name
424 self.comb += self.cpu.interrupt[interrupt].eq(mod_impl.ev.irq)
425
426 def build(self, *args, **kwargs):
427 return self.platform.build(self, *args, **kwargs)
428
429
430 def soc_core_args(parser):
431 parser.add_argument("--cpu-type", default=None,
432 help="select CPU: lm32, or1k, picorv32, vexriscv, minerva")
433 parser.add_argument("--cpu-variant", default=None,
434 help="select CPU variant")
435 parser.add_argument("--integrated-rom-size", default=None, type=int,
436 help="size/enable the integrated (BIOS) ROM")
437 parser.add_argument("--integrated-main-ram-size", default=None, type=int,
438 help="size/enable the integrated main RAM")
439 parser.add_argument("--uart-stub", default=False, type=bool,
440 help="enable uart stub")
441
442
443 def soc_core_argdict(args):
444 r = dict()
445 for a in [
446 "cpu_type",
447 "cpu_variant",
448 "integrated_rom_size",
449 "integrated_main_ram_size",
450 "uart_stub"]:
451 arg = getattr(args, a)
452 if arg is not None:
453 r[a] = arg
454 return r