soc: add add_constant/add_config methods
[litex.git] / litex / soc / integration / soc.py
1 #!/usr/bin/env python3
2
3 # This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
4 # License: BSD
5
6 import logging
7 import time
8 import datetime
9
10 from migen import *
11
12 from litex.soc.cores.identifier import Identifier
13 from litex.soc.cores.timer import Timer
14
15 from litex.soc.interconnect.csr import *
16 from litex.soc.interconnect import csr_bus
17 from litex.soc.interconnect import wishbone
18 from litex.soc.interconnect import wishbone2csr
19
20 # TODO:
21 # - replace raise with exit on logging error.
22 # - add configurable CSR paging.
23 # - manage IO/Linker regions.
24
25 logging.basicConfig(level=logging.INFO)
26
27 # Helpers ------------------------------------------------------------------------------------------
28 def colorer(s, color="bright"):
29 header = {
30 "bright": "\x1b[1m",
31 "green": "\x1b[32m",
32 "cyan": "\x1b[36m",
33 "red": "\x1b[31m",
34 "yellow": "\x1b[33m",
35 "underline": "\x1b[4m"}[color]
36 trailer = "\x1b[0m"
37 return header + str(s) + trailer
38
39 def build_time(with_time=True):
40 fmt = "%Y-%m-%d %H:%M:%S" if with_time else "%Y-%m-%d"
41 return datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S")
42
43 # SoCConstant --------------------------------------------------------------------------------------
44
45 def SoCConstant(value):
46 return value
47
48 # SoCRegion ----------------------------------------------------------------------------------------
49
50 class SoCRegion:
51 def __init__(self, origin=None, size=None, mode="rw", cached=True):
52 self.logger = logging.getLogger("SoCRegion")
53 self.origin = origin
54 self.size = size
55 self.mode = mode
56 self.cached = cached
57
58 def decoder(self):
59 origin = self.origin
60 size = self.size
61 origin &= ~0x80000000
62 size = 2**log2_int(size, False)
63 if (origin & (size - 1)) != 0:
64 self.logger.error("Origin needs to be aligned on size:")
65 self.logger.error(self)
66 raise
67 origin >>= 2 # bytes to words aligned
68 size >>= 2 # bytes to words aligned
69 return lambda a: (a[log2_int(size):-1] == (origin >> log2_int(size)))
70
71 def __str__(self):
72 r = ""
73 if self.origin is not None:
74 r += "Origin: {}, ".format(colorer("0x{:08x}".format(self.origin)))
75 if self.size is not None:
76 r += "Size: {}, ".format(colorer("0x{:08x}".format(self.size)))
77 r += "Mode: {}, ".format(colorer(self.mode.upper()))
78 r += "Cached: {}".format(colorer(self.cached))
79 return r
80
81
82 class SoCLinkerRegion(SoCRegion):
83 pass
84
85 # SoCBusHandler ------------------------------------------------------------------------------------
86
87 class SoCBusHandler(Module):
88 supported_standard = ["wishbone"]
89 supported_data_width = [32, 64]
90 supported_address_width = [32]
91
92 # Creation -------------------------------------------------------------------------------------
93 def __init__(self, standard, data_width=32, address_width=32, timeout=1e6, reserved_regions={}):
94 self.logger = logging.getLogger("SoCBusHandler")
95 self.logger.info(colorer("Creating new Bus Handler...", color="cyan"))
96
97 # Check Standard
98 if standard not in self.supported_standard:
99 self.logger.error("Unsupported Standard: {} supporteds: {:s}".format(
100 colorer(standard, color="red"),
101 colorer(", ".join(self.supported_standard), color="green")))
102 raise
103
104 # Check Data Width
105 if data_width not in self.supported_data_width:
106 self.logger.error("Unsupported Data_Width: {} supporteds: {:s}".format(
107 colorer(data_width, color="red"),
108 colorer(", ".join(str(x) for x in self.supported_data_width), color="green")))
109 raise
110
111 # Check Address Width
112 if address_width not in self.supported_address_width:
113 self.logger.error("Unsupported Address Width: {} supporteds: {:s}".format(
114 colorer(data_width, color="red"),
115 colorer(", ".join(str(x) for x in self.supported_address_width), color="green")))
116 raise
117
118 # Create Bus
119 self.standard = standard
120 self.data_width = data_width
121 self.address_width = address_width
122 self.masters = {}
123 self.slaves = {}
124 self.regions = {}
125 self.timeout = timeout
126 self.logger.info("{}-bit {} Bus, {}GiB Address Space.".format(
127 colorer(data_width), colorer(standard), colorer(2**address_width/2**30)))
128
129 # Adding reserved regions
130 self.logger.info("Adding {} Regions...".format(colorer("reserved")))
131 for name, region in reserved_regions.items():
132 if isinstance(region, int):
133 region = SoCRegion(origin=region, size=0x1000000)
134 self.add_region(name, region)
135
136 self.logger.info(colorer("Bus Handler created.", color="cyan"))
137
138 # Add/Allog/Check Regions ----------------------------------------------------------------------
139 def add_region(self, name, region):
140 allocated = False
141 # Check if SoCLinkerRegion
142 if isinstance(region, SoCLinkerRegion):
143 self.logger.info("FIXME: SoCLinkerRegion")
144 # Check if SoCRegion
145 elif isinstance(region, SoCRegion):
146 # If no origin specified, allocate region.
147 if region.origin is None:
148 allocated = True
149 region = self.alloc_region(region.size, region.cached)
150 self.regions[name] = region
151 # Else add region and check for overlaps.
152 else:
153 self.regions[name] = region
154 overlap = self.check_region(self.regions)
155 if overlap is not None:
156 self.logger.error("Region overlap between {} and {}:".format(
157 colorer(overlap[0], color="red"),
158 colorer(overlap[1], color="red")))
159 self.logger.error(str(self.regions[overlap[0]]))
160 self.logger.error(str(self.regions[overlap[1]]))
161 raise
162 self.logger.info("{} Region {} {}.".format(
163 colorer(name, color="underline"),
164 colorer("allocated" if allocated else "added", color="yellow" if allocated else "green"),
165 str(region)))
166 else:
167 self.logger.error("{} is not a supported Region".format(colorer(name, color="red")))
168 raise
169
170 def alloc_region(self, size, cached=True):
171 self.logger.info("Allocating {} Region of size {}...".format(
172 colorer("Cached" if cached else "IO"),
173 colorer("0x{:08x}".format(size))))
174
175 # Limit Search Regions
176 uncached_regions = {}
177 for _, region in self.regions.items():
178 if region.cached == False:
179 uncached_regions[name] = region
180 if cached == False:
181 search_regions = uncached_regions
182 else:
183 search_regions = {"main": SoCRegion(origin=0x00000000, size=2**self.address_width-1)}
184
185 # Iterate on Search_Regions to find a Candidate
186 for _, search_region in search_regions.items():
187 origin = search_region.origin
188 while (origin + size) < (search_region.origin + search_region.size):
189 # Create a Candicate.
190 candidate = SoCRegion(origin=origin, size=size, cached=cached)
191 overlap = False
192 # Check Candidate does not overlap with allocated existing regions
193 for _, allocated in self.regions.items():
194 if self.check_region({"0": allocated, "1": candidate}) is not None:
195 origin = allocated.origin + allocated.size
196 overlap = True
197 break
198 if not overlap:
199 # If no overlap, the Candidate is selected
200 return candidate
201
202 self.logger.error("Not enough Address Space to allocate Region")
203 raise
204
205 def check_region(self, regions):
206 i = 0
207 while i < len(regions):
208 n0 = list(regions.keys())[i]
209 r0 = regions[n0]
210 for n1 in list(regions.keys())[i+1:]:
211 r1 = regions[n1]
212 if isinstance(r0, SoCLinkerRegion) or isinstance(r1, SoCLinkerRegion):
213 continue
214 if r0.origin >= (r1.origin + r1.size):
215 continue
216 if r1.origin >= (r0.origin + r0.size):
217 continue
218 return (n0, n1)
219 i += 1
220 return None
221
222 # Add Master/Slave -----------------------------------------------------------------------------
223 def add_master(self, name=None, master=None, io_regions={}):
224 if name is None:
225 name = "master{:d}".format(len(self.masters))
226 if name in self.masters.keys():
227 self.logger.error("{} already declared as Bus Master:".format(colorer(name, color="red")))
228 self.logger.error(self)
229 raise
230 if master.data_width != self.data_width:
231 self.logger.error("{} Bus Master {} from {}-bit to {}-bit.".format(
232 colorer(name),
233 colorer("converted", color="yellow"),
234 colorer(master.data_width),
235 colorer(self.data_width)))
236 new_master = wishbone.Interface(data_width=self.data_width)
237 self.submodules += wishbone.Converter(master, new_master)
238 master = new_master
239 self.masters[name] = master
240 self.logger.info("{} {} as Bus Master.".format(colorer(name, color="underline"), colorer("added", color="green")))
241 # FIXME: handle IO regions
242
243 def add_slave(self, name=None, slave=None, region=None):
244 no_name = name is None
245 no_region = region is None
246 if no_name and no_region:
247 self.logger.error("Please specify at least {} or {} of Bus Slave".format(
248 colorer("name", color="red"),
249 colorer("region", color="red")))
250 raise
251 if no_name:
252 name = "slave{:d}".format(len(self.slaves))
253 if no_region:
254 region = self.regions.get(name, None)
255 if region is None:
256 self.logger.error("Unable to find Region {}".format(colorer(name, color="red")))
257 raise
258 else:
259 self.add_region(name, region)
260 if name in self.slaves.keys():
261 self.logger.error("{} already declared as Bus Slave:".format(colorer(name, color="red")))
262 self.logger.error(self)
263 raise
264 if slave.data_width != self.data_width:
265 self.logger.error("{} Bus Slave {} from {}-bit to {}-bit.".format(
266 colorer(name),
267 colorer("converted", color="yellow"),
268 colorer(slave.data_width),
269 colorer(self.data_width)))
270 new_slave = wishbone.Interface(data_width=self.data_width)
271 self.submodules += wishbone.Converter(slave, new_slave)
272 slave = new_slave
273 self.slaves[name] = slave
274 self.logger.info("{} {} as Bus Slave.".format(
275 colorer(name, color="underline"),
276 colorer("added", color="green")))
277
278 # Str ------------------------------------------------------------------------------------------
279 def __str__(self):
280 r = "{}-bit {} Bus, {}GiB Address Space.\n".format(
281 colorer(self.data_width), colorer(self.standard), colorer(2**self.address_width/2**30))
282 r += "Bus Regions: ({})\n".format(len(self.regions.keys())) if len(self.regions.keys()) else ""
283 for name, region in self.regions.items():
284 r += colorer(name, color="underline") + " "*(20-len(name)) + ": " + str(region) + "\n"
285 r += "Bus Masters: ({})\n".format(len(self.masters.keys())) if len(self.masters.keys()) else ""
286 for name in self.masters.keys():
287 r += "- {}\n".format(colorer(name, color="underline"))
288 r += "Bus Slaves: ({})\n".format(len(self.slaves.keys())) if len(self.slaves.keys()) else ""
289 for name in self.slaves.keys():
290 r += "- {}\n".format(colorer(name, color="underline"))
291 r = r[:-1]
292 return r
293
294 # SoCLocHandler --------------------------------------------------------------------------------------
295
296 class SoCLocHandler(Module):
297 # Creation -------------------------------------------------------------------------------------
298 def __init__(self, name, n_locs):
299 self.name = name
300 self.locs = {}
301 self.n_locs = n_locs
302
303 # Add ------------------------------------------------------------------------------------------
304 def add(self, name, n=None, use_loc_if_exists=False):
305 allocated = False
306 if not (use_loc_if_exists and name in self.locs.keys()):
307 if name in self.locs.keys():
308 self.logger.error("{} {} name already used.".format(colorer(name, "red"), self.name))
309 self.logger.error(self)
310 raise
311 if n in self.locs.values():
312 self.logger.error("{} {} Location already used.".format(colorer(n, "red"), self.name))
313 self.logger.error(self)
314 raise
315 if n is None:
316 allocated = True
317 n = self.alloc(name)
318 else:
319 if n < 0:
320 self.logger.error("{} {} Location should be positive.".format(
321 colorer(n, color="red"),
322 self.name))
323 raise
324 if n > self.n_locs:
325 self.logger.error("{} {} Location too high (Up to {}).".format(
326 colorer(n, color="red"),
327 self.name,
328 colorer(self.n_csrs, color="green")))
329 raise
330 self.locs[name] = n
331 else:
332 n = self.locs[name]
333 self.logger.info("{} {} {} at Location {}.".format(
334 colorer(name, color="underline"),
335 self.name,
336 colorer("allocated" if allocated else "added", color="yellow" if allocated else "green"),
337 colorer(n)))
338
339 # Alloc ----------------------------------------------------------------------------------------
340 def alloc(self, name):
341 for n in range(self.n_locs):
342 if n not in self.locs.values():
343 return n
344 self.logger.error("Not enough Locations.")
345 self.logger.error(self)
346 raise
347
348 # Str ------------------------------------------------------------------------------------------
349 def __str__(self):
350 r = "{} Locations: ({})\n".format(self.name, len(self.locs.keys())) if len(self.locs.keys()) else ""
351 for name in self.locs.keys():
352 r += "- {}{}: {}\n".format(colorer(name, color="underline"), " "*(20-len(name)), colorer(self.locs[name]))
353 return r
354
355 # SoCCSRHandler ------------------------------------------------------------------------------------
356
357 class SoCCSRHandler(SoCLocHandler):
358 supported_data_width = [8, 32]
359 supported_address_width = [14, 15]
360 supported_alignment = [32, 64]
361 supported_paging = [0x800]
362
363 # Creation -------------------------------------------------------------------------------------
364 def __init__(self, data_width=32, address_width=14, alignment=32, paging=0x800, reserved_csrs={}):
365 SoCLocHandler.__init__(self, "CSR", n_locs=4*2**address_width//paging) # FIXME
366 self.logger = logging.getLogger("SoCCSRHandler")
367 self.logger.info(colorer("Creating new CSR Handler...", color="cyan"))
368
369 # Check Data Width
370 if data_width not in self.supported_data_width:
371 self.logger.error("Unsupported data_width: {} supporteds: {:s}".format(
372 colorer(data_width, color="red"),
373 colorer(", ".join(str(x) for x in self.supported_data_width)), color="green"))
374 raise
375
376 # Check Address Width
377 if address_width not in self.supported_address_width:
378 self.logger.error("Unsupported address_width: {} supporteds: {:s}".format(
379 colorer(address_width, color="red"),
380 colorer(", ".join(str(x) for x in self.supported_address_width), color="green")))
381 raise
382
383 # Check Alignment
384 if alignment not in self.supported_alignment:
385 self.logger.error("Unsupported alignment: {} supporteds: {:s}".format(
386 colorer(alignment, color="red"),
387 colorer(", ".join(str(x) for x in self.supported_alignment), color="green")))
388 raise
389 if data_width > alignment:
390 self.logger.error("Alignment ({}) should be >= data_width ({})".format(
391 colorer(alignment, color="red"),
392 colorer(data_width, color="red")))
393 raise
394
395 # Check Paging
396 if paging not in self.supported_paging:
397 self.logger.error("Unsupported paging: {} supporteds: {:s}".format(
398 colorer(paging, color="red"),
399 colorer(", ".join(str(x) for x in self.supported_paging), color="green")))
400 raise
401
402 # Create CSR Handler
403 self.data_width = data_width
404 self.address_width = address_width
405 self.alignment = alignment
406 self.paging = paging
407 self.logger.info("{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
408 colorer(self.data_width),
409 colorer(2**self.address_width/2**10),
410 colorer(self.paging),
411 colorer(self.n_locs)))
412
413 # Adding reserved CSRs
414 self.logger.info("Adding {} CSRs...".format(colorer("reserved")))
415 for name, n in reserved_csrs.items():
416 self.add(name, n)
417
418 self.logger.info(colorer("CSR Bus Handler created.", color="cyan"))
419
420 # Str ------------------------------------------------------------------------------------------
421 def __str__(self):
422 r = "{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
423 colorer(self.data_width),
424 colorer(2**self.address_width/2**10),
425 colorer(self.paging),
426 colorer(self.n_locs))
427 r += SoCLocHandler.__str__(self)
428 r = r[:-1]
429 return r
430
431 # SoCIRQHandler ------------------------------------------------------------------------------------
432
433 class SoCIRQHandler(SoCLocHandler):
434 # Creation -------------------------------------------------------------------------------------
435 def __init__(self, n_irqs=32, reserved_irqs={}):
436 SoCLocHandler.__init__(self, "IRQ", n_locs=n_irqs)
437 self.logger = logging.getLogger("SoCIRQHandler")
438 self.logger.info(colorer("Creating new SoC IRQ Handler...", color="cyan"))
439
440 # Check IRQ Number
441 if n_irqs > 32:
442 self.logger.error("Unsupported IRQs number: {} supporteds: {:s}".format(
443 colorer(n, color="red"), colorer("Up to 32", color="green")))
444 raise
445
446 # Create IRQ Handler
447 self.logger.info("IRQ Handler (up to {} Locations).".format(colorer(n_irqs)))
448
449 # Adding reserved IRQs
450 self.logger.info("Adding {} IRQs...".format(colorer("reserved")))
451 for name, n in reserved_irqs.items():
452 self.add(name, n)
453
454 self.logger.info(colorer("IRQ Handler created.", color="cyan"))
455
456 # Str ------------------------------------------------------------------------------------------
457 def __str__(self):
458 r ="IRQ Handler (up to {} Locations).\n".format(colorer(self.n_locs))
459 r += SoCLocHandler.__str__(self)
460 r = r[:-1]
461 return r
462
463 # SoCController ------------------------------------------------------------------------------------
464
465 class SoCController(Module, AutoCSR):
466 def __init__(self):
467 self._reset = CSRStorage(1, description="""
468 Write a ``1`` to this register to reset the SoC.""")
469 self._scratch = CSRStorage(32, reset=0x12345678, description="""
470 Use this register as a scratch space to verify that software read/write accesses
471 to the Wishbone/CSR bus are working correctly. The initial reset value of 0x1234578
472 can be used to verify endianness.""")
473 self._bus_errors = CSRStatus(32, description="""
474 Total number of Wishbone bus errors (timeouts) since last reset.""")
475
476 # # #
477
478 # Reset
479 self.reset = Signal()
480 self.comb += self.reset.eq(self._reset.re)
481
482 # Bus errors
483 self.bus_error = Signal()
484 bus_errors = Signal(32)
485 self.sync += \
486 If(bus_errors != (2**len(bus_errors)-1),
487 If(self.bus_error, bus_errors.eq(bus_errors + 1))
488 )
489 self.comb += self._bus_errors.status.eq(bus_errors)
490
491 # SoC ----------------------------------------------------------------------------------------------
492
493 class SoC(Module):
494 def __init__(self,
495 bus_standard = "wishbone",
496 bus_data_width = 32,
497 bus_address_width = 32,
498 bus_timeout = 1e6,
499 bus_reserved_regions = {},
500
501 csr_data_width = 32,
502 csr_address_width = 14,
503 csr_alignment = 32,
504 csr_paging = 0x800,
505 csr_reserved_csrs = {},
506
507 irq_n_irqs = 32,
508 irq_reserved_irqs = {},
509 ):
510
511 self.logger = logging.getLogger("SoC")
512 self.logger.info(colorer(" __ _ __ _ __ ", color="bright"))
513 self.logger.info(colorer(" / / (_) /____ | |/_/ ", color="bright"))
514 self.logger.info(colorer(" / /__/ / __/ -_)> < ", color="bright"))
515 self.logger.info(colorer(" /____/_/\\__/\\__/_/|_| ", color="bright"))
516 self.logger.info(colorer(" Build your hardware, easily!", color="bright"))
517
518 self.logger.info(colorer("-"*80, color="bright"))
519 self.logger.info(colorer("Creating new SoC... ({})".format(build_time()), color="cyan"))
520 self.logger.info(colorer("-"*80, color="bright"))
521
522 # SoC attributes ---------------------------------------------------------------------------
523 self.constants = {}
524
525 # SoC Bus Handler --------------------------------------------------------------------------
526 self.submodules.bus = SoCBusHandler(
527 standard = bus_standard,
528 data_width = bus_data_width,
529 address_width = bus_address_width,
530 timeout = bus_timeout,
531 reserved_regions = bus_reserved_regions,
532 )
533
534 # SoC Bus Handler --------------------------------------------------------------------------
535 self.submodules.csr = SoCCSRHandler(
536 data_width = csr_data_width,
537 address_width = csr_address_width,
538 alignment = csr_alignment,
539 paging = csr_paging,
540 reserved_csrs = csr_reserved_csrs,
541 )
542
543 # SoC IRQ Handler --------------------------------------------------------------------------
544 self.submodules.irq = SoCIRQHandler(
545 n_irqs = irq_n_irqs,
546 reserved_irqs = irq_reserved_irqs
547 )
548
549 self.logger.info(colorer("-"*80, color="bright"))
550 self.logger.info(colorer("Initial SoC:", color="cyan"))
551 self.logger.info(colorer("-"*80, color="bright"))
552 self.logger.info(self.bus)
553 self.logger.info(self.csr)
554 self.logger.info(self.irq)
555 self.logger.info(colorer("-"*80, color="bright"))
556
557
558 # SoC Helpers ----------------------------------------------------------------------------------
559 def check_if_exists(self, name):
560 if hasattr(self, name):
561 self.logger.error("{} SubModule already declared.".format(colorer(name, "red")))
562 raise
563
564 def add_constant(self, name, value=None):
565 name = name.upper()
566 if name in self.constants.keys():
567 self.logger.error("{} Constant already declared.".format(colorer(name, "red")))
568 raise
569 self.constants[name] = SoCConstant(value)
570
571 def add_config(self, name, value):
572 name = "CONFIG_" + name
573 if isinstance(value, str):
574 self.add_constant(name + "_" + value)
575 else:
576 self.add_constant(name, value)
577
578 # SoC Main components --------------------------------------------------------------------------
579 def add_ram(self, name, origin, size, contents=[], mode="rw"):
580 ram_bus = wishbone.Interface(data_width=self.bus.data_width)
581 ram = wishbone.SRAM(size, bus=ram_bus, init=contents, read_only=(mode == "r"))
582 self.bus.add_slave(name, ram.bus, SoCRegion(origin=origin, size=size, mode=mode))
583 self.check_if_exists(name)
584 self.logger.info("RAM {} {} {}.".format(
585 colorer(name),
586 colorer("added", color="green"),
587 self.bus.regions[name]))
588 setattr(self.submodules, name, ram)
589
590 def add_rom(self, name, origin, size, contents=[]):
591 self.add_ram(name, origin, size, contents, mode="r")
592
593 def add_controller(self, name="ctrl"):
594 self.check_if_exists(name)
595 setattr(self.submodules, name, SoCController())
596 self.csr.add(name, use_loc_if_exists=True)
597
598 def add_identifier(self, name="identifier", identifier="LiteX SoC", with_build_time=True):
599 self.check_if_exists(name)
600 if with_build_time:
601 identifier += " " + build_time()
602 setattr(self.submodules, name, Identifier(ident))
603 self.csr.add(name + "_mem", use_loc_if_exists=True)
604
605 def add_timer(self, name="timer0"):
606 self.check_if_exists(name)
607 setattr(self.submodules, name, Timer())
608 self.csr.add(name, use_loc_if_exists=True)
609 self.irq.add(name, use_loc_if_exists=True)
610
611 def add_csr_bridge(self, origin):
612 self.submodules.csr_bridge = wishbone2csr.WB2CSR(
613 bus_csr = csr_bus.Interface(
614 address_width = self.csr.address_width,
615 data_width = self.csr.data_width))
616 csr_size = 2**(self.csr.address_width + 2)
617 self.bus.add_slave("csr", self.csr_bridge.wishbone, SoCRegion(origin=origin, size=csr_size))
618
619 # SoC finalization -----------------------------------------------------------------------------
620 def do_finalize(self):
621 self.logger.info(colorer("-"*80, color="bright"))
622 self.logger.info(colorer("Finalized SoC:", color="cyan"))
623 self.logger.info(colorer("-"*80, color="bright"))
624 self.logger.info(self.bus)
625 self.logger.info(self.csr)
626 self.logger.info(self.irq)
627 self.logger.info(colorer("-"*80, color="bright"))
628
629 # SoC Bus Interconnect ---------------------------------------------------------------------
630 bus_masters = self.bus.masters.values()
631 bus_slaves = [(self.bus.regions[n].decoder(), s) for n, s in self.bus.slaves.items()]
632 if len(bus_masters) and len(bus_slaves):
633 self.submodules.bus_interconnect = wishbone.InterconnectShared(
634 masters = bus_masters,
635 slaves = bus_slaves,
636 register = True,
637 timeout_cycles = self.bus.timeout)
638
639 # Test (FIXME: move to litex/text and improve) -----------------------------------------------------
640
641 if __name__ == "__main__":
642 bus = SoCBusHandler("wishbone", reserved_regions={
643 "rom": SoCRegion(origin=0x00000100, size=1024),
644 "ram": SoCRegion(size=512),
645 }
646 )
647 bus.add_master("cpu", None)
648 bus.add_slave("rom", None, SoCRegion(size=1024))
649 bus.add_slave("ram", None, SoCRegion(size=1024))
650
651
652 csr = SoCCSRHandler(reserved_csrs={"ctrl": 0, "uart": 1})
653 csr.add("csr0")
654 csr.add("csr1", 0)
655 #csr.add("csr2", 46)
656 csr.add("csr3", -1)
657 print(bus)
658 print(csr)
659
660 irq = SoCIRQHandler(reserved_irqs={"uart": 1})
661
662 soc = SoC()