3 # This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
12 from litex
.soc
.cores
.identifier
import Identifier
13 from litex
.soc
.cores
.timer
import Timer
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
21 # - replace raise with exit on logging error.
22 # - add configurable CSR paging.
23 # - manage IO/Linker regions.
25 logging
.basicConfig(level
=logging
.INFO
)
27 # Helpers ------------------------------------------------------------------------------------------
28 def colorer(s
, color
="bright"):
35 "underline": "\x1b[4m"}[color
]
37 return header
+ str(s
) + trailer
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")
43 # SoCConstant --------------------------------------------------------------------------------------
45 def SoCConstant(value
):
48 # SoCRegion ----------------------------------------------------------------------------------------
51 def __init__(self
, origin
=None, size
=None, mode
="rw", cached
=True):
52 self
.logger
= logging
.getLogger("SoCRegion")
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
)
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
)))
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
))
82 class SoCLinkerRegion(SoCRegion
):
85 # SoCBusHandler ------------------------------------------------------------------------------------
87 class SoCBusHandler(Module
):
88 supported_standard
= ["wishbone"]
89 supported_data_width
= [32, 64]
90 supported_address_width
= [32]
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"))
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")))
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")))
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")))
119 self
.standard
= standard
120 self
.data_width
= data_width
121 self
.address_width
= address_width
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)))
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
)
136 self
.logger
.info(colorer("Bus Handler created.", color
="cyan"))
138 # Add/Allog/Check Regions ----------------------------------------------------------------------
139 def add_region(self
, name
, region
):
141 # Check if SoCLinkerRegion
142 if isinstance(region
, SoCLinkerRegion
):
143 self
.logger
.info("FIXME: SoCLinkerRegion")
145 elif isinstance(region
, SoCRegion
):
146 # If no origin specified, allocate region.
147 if region
.origin
is None:
149 region
= self
.alloc_region(region
.size
, region
.cached
)
150 self
.regions
[name
] = region
151 # Else add region and check for overlaps.
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]]))
162 self
.logger
.info("{} Region {} {}.".format(
163 colorer(name
, color
="underline"),
164 colorer("allocated" if allocated
else "added", color
="yellow" if allocated
else "green"),
167 self
.logger
.error("{} is not a supported Region".format(colorer(name
, color
="red")))
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
))))
175 # Limit Search Regions
176 uncached_regions
= {}
177 for _
, region
in self
.regions
.items():
178 if region
.cached
== False:
179 uncached_regions
[name
] = region
181 search_regions
= uncached_regions
183 search_regions
= {"main": SoCRegion(origin
=0x00000000, size
=2**self
.address_width
-1)}
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
)
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
199 # If no overlap, the Candidate is selected
202 self
.logger
.error("Not enough Address Space to allocate Region")
205 def check_region(self
, regions
):
207 while i
< len(regions
):
208 n0
= list(regions
.keys())[i
]
210 for n1
in list(regions
.keys())[i
+1:]:
212 if isinstance(r0
, SoCLinkerRegion
) or isinstance(r1
, SoCLinkerRegion
):
214 if r0
.origin
>= (r1
.origin
+ r1
.size
):
216 if r1
.origin
>= (r0
.origin
+ r0
.size
):
222 # Add Master/Slave -----------------------------------------------------------------------------
223 def add_master(self
, name
=None, master
=None, io_regions
={}):
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
)
230 if master
.data_width
!= self
.data_width
:
231 self
.logger
.info("{} Bus Master {} from {}-bit to {}-bit.".format(
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
)
239 self
.masters
[name
] = master
240 self
.logger
.info("{} {} as Bus Master.".format(
241 colorer(name
, color
="underline"),
242 colorer("added", color
="green")))
243 # FIXME: handle IO regions
245 def add_slave(self
, name
=None, slave
=None, region
=None):
246 no_name
= name
is None
247 no_region
= region
is None
248 if no_name
and no_region
:
249 self
.logger
.error("Please specify at least {} or {} of Bus Slave".format(
250 colorer("name", color
="red"),
251 colorer("region", color
="red")))
254 name
= "slave{:d}".format(len(self
.slaves
))
256 region
= self
.regions
.get(name
, None)
258 self
.logger
.error("Unable to find Region {}".format(colorer(name
, color
="red")))
261 self
.add_region(name
, region
)
262 if name
in self
.slaves
.keys():
263 self
.logger
.error("{} already declared as Bus Slave:".format(colorer(name
, color
="red")))
264 self
.logger
.error(self
)
266 if slave
.data_width
!= self
.data_width
:
267 self
.logger
.error("{} Bus Slave {} from {}-bit to {}-bit.".format(
269 colorer("converted", color
="yellow"),
270 colorer(slave
.data_width
),
271 colorer(self
.data_width
)))
272 new_slave
= wishbone
.Interface(data_width
=self
.data_width
)
273 self
.submodules
+= wishbone
.Converter(slave
, new_slave
)
275 self
.slaves
[name
] = slave
276 self
.logger
.info("{} {} as Bus Slave.".format(
277 colorer(name
, color
="underline"),
278 colorer("added", color
="green")))
280 # Str ------------------------------------------------------------------------------------------
282 r
= "{}-bit {} Bus, {}GiB Address Space.\n".format(
283 colorer(self
.data_width
), colorer(self
.standard
), colorer(2**self
.address_width
/2**30))
284 r
+= "Bus Regions: ({})\n".format(len(self
.regions
.keys())) if len(self
.regions
.keys()) else ""
285 for name
, region
in self
.regions
.items():
286 r
+= colorer(name
, color
="underline") + " "*(20-len(name
)) + ": " + str(region
) + "\n"
287 r
+= "Bus Masters: ({})\n".format(len(self
.masters
.keys())) if len(self
.masters
.keys()) else ""
288 for name
in self
.masters
.keys():
289 r
+= "- {}\n".format(colorer(name
, color
="underline"))
290 r
+= "Bus Slaves: ({})\n".format(len(self
.slaves
.keys())) if len(self
.slaves
.keys()) else ""
291 for name
in self
.slaves
.keys():
292 r
+= "- {}\n".format(colorer(name
, color
="underline"))
296 # SoCLocHandler --------------------------------------------------------------------------------------
298 class SoCLocHandler(Module
):
299 # Creation -------------------------------------------------------------------------------------
300 def __init__(self
, name
, n_locs
):
305 # Add ------------------------------------------------------------------------------------------
306 def add(self
, name
, n
=None, use_loc_if_exists
=False):
308 if not (use_loc_if_exists
and name
in self
.locs
.keys()):
309 if name
in self
.locs
.keys():
310 self
.logger
.error("{} {} name already used.".format(colorer(name
, "red"), self
.name
))
311 self
.logger
.error(self
)
313 if n
in self
.locs
.values():
314 self
.logger
.error("{} {} Location already used.".format(colorer(n
, "red"), self
.name
))
315 self
.logger
.error(self
)
322 self
.logger
.error("{} {} Location should be positive.".format(
323 colorer(n
, color
="red"),
327 self
.logger
.error("{} {} Location too high (Up to {}).".format(
328 colorer(n
, color
="red"),
330 colorer(self
.n_csrs
, color
="green")))
335 self
.logger
.info("{} {} {} at Location {}.".format(
336 colorer(name
, color
="underline"),
338 colorer("allocated" if allocated
else "added", color
="yellow" if allocated
else "green"),
341 # Alloc ----------------------------------------------------------------------------------------
342 def alloc(self
, name
):
343 for n
in range(self
.n_locs
):
344 if n
not in self
.locs
.values():
346 self
.logger
.error("Not enough Locations.")
347 self
.logger
.error(self
)
350 # Str ------------------------------------------------------------------------------------------
352 r
= "{} Locations: ({})\n".format(self
.name
, len(self
.locs
.keys())) if len(self
.locs
.keys()) else ""
353 for name
in self
.locs
.keys():
354 r
+= "- {}{}: {}\n".format(colorer(name
, color
="underline"), " "*(20-len(name
)), colorer(self
.locs
[name
]))
357 # SoCCSRHandler ------------------------------------------------------------------------------------
359 class SoCCSRHandler(SoCLocHandler
):
360 supported_data_width
= [8, 32]
361 supported_address_width
= [14, 15]
362 supported_alignment
= [32, 64]
363 supported_paging
= [0x800]
365 # Creation -------------------------------------------------------------------------------------
366 def __init__(self
, data_width
=32, address_width
=14, alignment
=32, paging
=0x800, reserved_csrs
={}):
367 SoCLocHandler
.__init
__(self
, "CSR", n_locs
=4*2**address_width
//paging
) # FIXME
368 self
.logger
= logging
.getLogger("SoCCSRHandler")
369 self
.logger
.info(colorer("Creating new CSR Handler...", color
="cyan"))
372 if data_width
not in self
.supported_data_width
:
373 self
.logger
.error("Unsupported data_width: {} supporteds: {:s}".format(
374 colorer(data_width
, color
="red"),
375 colorer(", ".join(str(x
) for x
in self
.supported_data_width
)), color
="green"))
378 # Check Address Width
379 if address_width
not in self
.supported_address_width
:
380 self
.logger
.error("Unsupported address_width: {} supporteds: {:s}".format(
381 colorer(address_width
, color
="red"),
382 colorer(", ".join(str(x
) for x
in self
.supported_address_width
), color
="green")))
386 if alignment
not in self
.supported_alignment
:
387 self
.logger
.error("Unsupported alignment: {} supporteds: {:s}".format(
388 colorer(alignment
, color
="red"),
389 colorer(", ".join(str(x
) for x
in self
.supported_alignment
), color
="green")))
391 if data_width
> alignment
:
392 self
.logger
.error("Alignment ({}) should be >= data_width ({})".format(
393 colorer(alignment
, color
="red"),
394 colorer(data_width
, color
="red")))
398 if paging
not in self
.supported_paging
:
399 self
.logger
.error("Unsupported paging: {} supporteds: {:s}".format(
400 colorer(paging
, color
="red"),
401 colorer(", ".join(str(x
) for x
in self
.supported_paging
), color
="green")))
405 self
.data_width
= data_width
406 self
.address_width
= address_width
407 self
.alignment
= alignment
410 self
.logger
.info("{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
411 colorer(self
.data_width
),
412 colorer(2**self
.address_width
/2**10),
413 colorer(self
.paging
),
414 colorer(self
.n_locs
)))
416 # Adding reserved CSRs
417 self
.logger
.info("Adding {} CSRs...".format(colorer("reserved")))
418 for name
, n
in reserved_csrs
.items():
421 self
.logger
.info(colorer("CSR Handler created.", color
="cyan"))
423 # Add Master -----------------------------------------------------------------------------------
424 def add_master(self
, name
=None, master
=None):
426 name
= "master{:d}".format(len(self
.masters
))
427 if name
in self
.masters
.keys():
428 self
.logger
.error("{} already declared as CSR Master:".format(colorer(name
, color
="red")))
429 self
.logger
.error(self
)
432 if master
.data_width
!= self
.data_width
:
433 self
.logger
.error("{} Master/Handler data_width {} ({} vs {}).".format(
435 colorer("missmatch"),
436 colorer(master
.data_width
, color
="red"),
437 colorer(self
.data_width
, color
="red")))
439 self
.masters
[name
] = master
440 self
.logger
.info("{} {} as CSR Master.".format(
441 colorer(name
, color
="underline"),
442 colorer("added", color
="green")))
443 # FIXME: handle IO regions
445 # Address map ----------------------------------------------------------------------------------
446 def address_map(self
, name
, memory
):
447 if memory
is not None:
448 name
= name
+ "_" + memory
.name_override
449 if self
.locs
.get(name
, None) is None:
450 self
.logger
.error("Undefined {} CSR.".format(colorer(name
, color
="red")))
452 return self
.locs
[name
]
454 # Str ------------------------------------------------------------------------------------------
456 r
= "{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
457 colorer(self
.data_width
),
458 colorer(2**self
.address_width
/2**10),
459 colorer(self
.paging
),
460 colorer(self
.n_locs
))
461 r
+= SoCLocHandler
.__str
__(self
)
465 # SoCIRQHandler ------------------------------------------------------------------------------------
467 class SoCIRQHandler(SoCLocHandler
):
468 # Creation -------------------------------------------------------------------------------------
469 def __init__(self
, n_irqs
=32, reserved_irqs
={}):
470 SoCLocHandler
.__init
__(self
, "IRQ", n_locs
=n_irqs
)
471 self
.logger
= logging
.getLogger("SoCIRQHandler")
472 self
.logger
.info(colorer("Creating new SoC IRQ Handler...", color
="cyan"))
476 self
.logger
.error("Unsupported IRQs number: {} supporteds: {:s}".format(
477 colorer(n
, color
="red"), colorer("Up to 32", color
="green")))
481 self
.logger
.info("IRQ Handler (up to {} Locations).".format(colorer(n_irqs
)))
483 # Adding reserved IRQs
484 self
.logger
.info("Adding {} IRQs...".format(colorer("reserved")))
485 for name
, n
in reserved_irqs
.items():
488 self
.logger
.info(colorer("IRQ Handler created.", color
="cyan"))
490 # Str ------------------------------------------------------------------------------------------
492 r
="IRQ Handler (up to {} Locations).\n".format(colorer(self
.n_locs
))
493 r
+= SoCLocHandler
.__str
__(self
)
497 # SoCController ------------------------------------------------------------------------------------
499 class SoCController(Module
, AutoCSR
):
501 self
._reset
= CSRStorage(1, description
="""
502 Write a ``1`` to this register to reset the SoC.""")
503 self
._scratch
= CSRStorage(32, reset
=0x12345678, description
="""
504 Use this register as a scratch space to verify that software read/write accesses
505 to the Wishbone/CSR bus are working correctly. The initial reset value of 0x1234578
506 can be used to verify endianness.""")
507 self
._bus
_errors
= CSRStatus(32, description
="""
508 Total number of Wishbone bus errors (timeouts) since last reset.""")
513 self
.reset
= Signal()
514 self
.comb
+= self
.reset
.eq(self
._reset
.re
)
517 self
.bus_error
= Signal()
518 bus_errors
= Signal(32)
520 If(bus_errors
!= (2**len(bus_errors
)-1),
521 If(self
.bus_error
, bus_errors
.eq(bus_errors
+ 1))
523 self
.comb
+= self
._bus
_errors
.status
.eq(bus_errors
)
525 # SoC ----------------------------------------------------------------------------------------------
528 def __init__(self
, platform
, sys_clk_freq
,
530 bus_standard
= "wishbone",
532 bus_address_width
= 32,
534 bus_reserved_regions
= {},
537 csr_address_width
= 14,
540 csr_reserved_csrs
= {},
543 irq_reserved_irqs
= {},
546 self
.logger
= logging
.getLogger("SoC")
547 self
.logger
.info(colorer(" __ _ __ _ __ ", color
="bright"))
548 self
.logger
.info(colorer(" / / (_) /____ | |/_/ ", color
="bright"))
549 self
.logger
.info(colorer(" / /__/ / __/ -_)> < ", color
="bright"))
550 self
.logger
.info(colorer(" /____/_/\\__/\\__/_/|_| ", color
="bright"))
551 self
.logger
.info(colorer(" Build your hardware, easily!", color
="bright"))
553 self
.logger
.info(colorer("-"*80, color
="bright"))
554 self
.logger
.info(colorer("Creating new SoC... ({})".format(build_time()), color
="cyan"))
555 self
.logger
.info(colorer("-"*80, color
="bright"))
557 # SoC attributes ---------------------------------------------------------------------------
558 self
.platform
= platform
559 self
.sys_clk_freq
= sys_clk_freq
562 # SoC Bus Handler --------------------------------------------------------------------------
563 self
.submodules
.bus
= SoCBusHandler(
564 standard
= bus_standard
,
565 data_width
= bus_data_width
,
566 address_width
= bus_address_width
,
567 timeout
= bus_timeout
,
568 reserved_regions
= bus_reserved_regions
,
571 # SoC Bus Handler --------------------------------------------------------------------------
572 self
.submodules
.csr
= SoCCSRHandler(
573 data_width
= csr_data_width
,
574 address_width
= csr_address_width
,
575 alignment
= csr_alignment
,
577 reserved_csrs
= csr_reserved_csrs
,
580 # SoC IRQ Handler --------------------------------------------------------------------------
581 self
.submodules
.irq
= SoCIRQHandler(
583 reserved_irqs
= irq_reserved_irqs
586 self
.logger
.info(colorer("-"*80, color
="bright"))
587 self
.logger
.info(colorer("Initial SoC:", color
="cyan"))
588 self
.logger
.info(colorer("-"*80, color
="bright"))
589 self
.logger
.info(self
.bus
)
590 self
.logger
.info(self
.csr
)
591 self
.logger
.info(self
.irq
)
592 self
.logger
.info(colorer("-"*80, color
="bright"))
595 # SoC Helpers ----------------------------------------------------------------------------------
596 def check_if_exists(self
, name
):
597 if hasattr(self
, name
):
598 self
.logger
.error("{} SubModule already declared.".format(colorer(name
, "red")))
601 def add_constant(self
, name
, value
=None):
603 if name
in self
.constants
.keys():
604 self
.logger
.error("{} Constant already declared.".format(colorer(name
, "red")))
606 self
.constants
[name
] = SoCConstant(value
)
608 def add_config(self
, name
, value
):
609 name
= "CONFIG_" + name
610 if isinstance(value
, str):
611 self
.add_constant(name
+ "_" + value
)
613 self
.add_constant(name
, value
)
615 # SoC Main components --------------------------------------------------------------------------
616 def add_ram(self
, name
, origin
, size
, contents
=[], mode
="rw"):
617 ram_bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
)
618 ram
= wishbone
.SRAM(size
, bus
=ram_bus
, init
=contents
, read_only
=(mode
== "r"))
619 self
.bus
.add_slave(name
, ram
.bus
, SoCRegion(origin
=origin
, size
=size
, mode
=mode
))
620 self
.check_if_exists(name
)
621 self
.logger
.info("RAM {} {} {}.".format(
623 colorer("added", color
="green"),
624 self
.bus
.regions
[name
]))
625 setattr(self
.submodules
, name
, ram
)
627 def add_rom(self
, name
, origin
, size
, contents
=[]):
628 self
.add_ram(name
, origin
, size
, contents
, mode
="r")
630 def add_controller(self
, name
="ctrl"):
631 self
.check_if_exists(name
)
632 setattr(self
.submodules
, name
, SoCController())
633 self
.csr
.add(name
, use_loc_if_exists
=True)
635 def add_identifier(self
, name
="identifier", identifier
="LiteX SoC", with_build_time
=True):
636 self
.check_if_exists(name
)
638 identifier
+= " " + build_time()
639 setattr(self
.submodules
, name
, Identifier(ident
))
640 self
.csr
.add(name
+ "_mem", use_loc_if_exists
=True)
642 def add_timer(self
, name
="timer0"):
643 self
.check_if_exists(name
)
644 setattr(self
.submodules
, name
, Timer())
645 self
.csr
.add(name
, use_loc_if_exists
=True)
646 self
.irq
.add(name
, use_loc_if_exists
=True)
648 def add_csr_bridge(self
, origin
):
649 self
.submodules
.csr_bridge
= wishbone2csr
.WB2CSR(
650 bus_csr
= csr_bus
.Interface(
651 address_width
= self
.csr
.address_width
,
652 data_width
= self
.csr
.data_width
))
653 csr_size
= 2**(self
.csr
.address_width
+ 2)
654 self
.bus
.add_slave("csr", self
.csr_bridge
.wishbone
, SoCRegion(origin
=origin
, size
=csr_size
))
655 self
.csr
.add_master(name
="bridge", master
=self
.csr_bridge
.csr
)
657 # SoC Peripherals ------------------------------------------------------------------------------
658 def add_uart(self
, name
, baudrate
=115200):
659 from litex
.soc
.cores
import uart
660 if name
in ["stub", "stream"]:
661 self
.submodules
.uart
= uart
.UART()
663 self
.comb
+= self
.uart
.sink
.ready
.eq(1)
664 elif name
== "bridge":
665 self
.submodules
.uart
= uart
.UARTWishboneBridge(
666 pads
= self
.platform
.request("serial"),
667 clk_freq
= self
.sys_clk_freq
,
669 self
.bus
.master(name
="uart_bridge", master
=self
.uart
.wishbone
)
670 elif name
== "crossover":
671 self
.submodules
.uart
= uart
.UARTCrossover()
673 if name
== "jtag_atlantic":
674 from litex
.soc
.cores
.jtag
import JTAGAtlantic
675 self
.submodules
.uart_phy
= JTAGAtlantic()
676 elif name
== "jtag_uart":
677 from litex
.soc
.cores
.jtag
import JTAGPHY
678 self
.submodules
.uart_phy
= JTAGPHY(device
=self
.platform
.device
)
680 self
.submodules
.uart_phy
= uart
.UARTPHY(
681 pads
= self
.platform
.request(name
),
682 clk_freq
= self
.sys_clk_freq
,
684 self
.submodules
.uart
= ResetInserter()(uart
.UART(self
.uart_phy
))
685 self
.csr
.add("uart_phy", use_loc_if_exists
=True)
686 self
.csr
.add("uart", use_loc_if_exists
=True)
687 self
.irq
.add("uart", use_loc_if_exists
=True)
689 # SoC finalization -----------------------------------------------------------------------------
690 def do_finalize(self
):
691 self
.logger
.info(colorer("-"*80, color
="bright"))
692 self
.logger
.info(colorer("Finalized SoC:", color
="cyan"))
693 self
.logger
.info(colorer("-"*80, color
="bright"))
694 self
.logger
.info(self
.bus
)
695 self
.logger
.info(self
.csr
)
696 self
.logger
.info(self
.irq
)
697 self
.logger
.info(colorer("-"*80, color
="bright"))
699 # SoC Bus Interconnect ---------------------------------------------------------------------
700 bus_masters
= self
.bus
.masters
.values()
701 bus_slaves
= [(self
.bus
.regions
[n
].decoder(), s
) for n
, s
in self
.bus
.slaves
.items()]
702 if len(bus_masters
) and len(bus_slaves
):
703 self
.submodules
.bus_interconnect
= wishbone
.InterconnectShared(
704 masters
= bus_masters
,
707 timeout_cycles
= self
.bus
.timeout
)
708 if hasattr(self
, "ctrl") and self
.bus
.timeout
is not None:
709 self
.comb
+= self
.ctrl
.bus_error
.eq(self
.bus_interconnect
.timeout
.error
)
711 # SoC CSR Interconnect ---------------------------------------------------------------------
712 self
.submodules
.csr_bankarray
= csr_bus
.CSRBankArray(self
,
713 address_map
= self
.csr
.address_map
,
714 data_width
= self
.csr
.data_width
,
715 address_width
= self
.csr
.address_width
,
716 alignment
= self
.csr
.alignment
718 if len(self
.csr
.masters
):
719 self
.submodules
.csr_interconnect
= csr_bus
.InterconnectShared(
720 masters
= list(self
.csr
.masters
.values()),
721 slaves
= self
.csr_bankarray
.get_buses())
723 # SoC IRQ Interconnect ---------------------------------------------------------------------
724 if hasattr(self
, "cpu"):
725 if hasattr(self
.cpu
, "interrupt"):
726 for name
, loc
in sorted(self
.irq
.locs
.items()):
727 if name
in self
.cpu
.interrupts
.keys():
729 if hasattr(self
, name
):
730 module
= getattr(self
, name
)
731 if not hasattr(module
, "ev"):
732 self
.logger
.error("No EventManager found on {} SubModule".format(
733 colorer(name
, color
="red")))
734 self
.comb
+= self
.cpu
.interrupt
[loc
].eq(module
.ev
.irq
)
735 self
.add_constant(name
+ "_INTERRUPT", loc
)