diff --git a/litex/boards/targets/arty.py b/litex/boards/targets/arty.py index 75d58a9b5..64d892f87 100755 --- a/litex/boards/targets/arty.py +++ b/litex/boards/targets/arty.py @@ -124,7 +124,7 @@ class MiniSoC(BaseSoC): csr_map.update(BaseSoC.csr_map) interrupt_map = { - "ethmac": 2, + "ethmac": 3, } interrupt_map.update(BaseSoC.interrupt_map) diff --git a/litex/boards/targets/kc705.py b/litex/boards/targets/kc705.py index 37297f330..541d3dea9 100755 --- a/litex/boards/targets/kc705.py +++ b/litex/boards/targets/kc705.py @@ -104,7 +104,7 @@ class MiniSoC(BaseSoC): csr_map.update(BaseSoC.csr_map) interrupt_map = { - "ethmac": 2, + "ethmac": 3, } interrupt_map.update(BaseSoC.interrupt_map) diff --git a/litex/boards/targets/nexys_video.py b/litex/boards/targets/nexys_video.py index 75774e945..77b54688b 100755 --- a/litex/boards/targets/nexys_video.py +++ b/litex/boards/targets/nexys_video.py @@ -113,7 +113,7 @@ class MiniSoC(BaseSoC): csr_map.update(BaseSoC.csr_map) interrupt_map = { - "ethmac": 2, + "ethmac": 3, } interrupt_map.update(BaseSoC.interrupt_map) diff --git a/litex/boards/targets/sim.py b/litex/boards/targets/sim.py index 1624441fc..04371fd9f 100755 --- a/litex/boards/targets/sim.py +++ b/litex/boards/targets/sim.py @@ -68,7 +68,7 @@ class MiniSoC(BaseSoC): csr_map.update(BaseSoC.csr_map) interrupt_map = { - "ethmac": 2, + "ethmac": 3, } interrupt_map.update(BaseSoC.interrupt_map) diff --git a/litex/boards/targets/simple.py b/litex/boards/targets/simple.py index 179581b43..88c8afd37 100755 --- a/litex/boards/targets/simple.py +++ b/litex/boards/targets/simple.py @@ -30,7 +30,7 @@ class MiniSoC(BaseSoC): csr_map.update(BaseSoC.csr_map) interrupt_map = { - "ethmac": 2, + "ethmac": 3, } interrupt_map.update(BaseSoC.interrupt_map) diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index c747945b1..170e67e25 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -31,33 +31,49 @@ if _have_colorama: ] -def settings(path, ver=None, sub=None): - if ver is None: - vers = list(tools.versions(path)) - if not vers: - raise OSError("no version directory for Xilinx tools found in " - + path) - ver = max(vers) +def settings(path, name=None, ver=None, first=None): + if first == "version": + if not ver: + vers = tools.versions(path) + ver = max(vers) - full = os.path.join(path, str(ver)) - if sub: - full = os.path.join(full, sub) + full = os.path.join(path, str(ver), name) + + elif first == "name": + path = os.path.join(path, name) + + if not ver: + vers = tools.versions(path) + ver = max(vers) + + full = os.path.join(path, str(ver)) + + if not vers: + raise OSError( + "no version directory for Xilinx tools found in {}".format( + path)) search = [64, 32] if tools.arch_bits() == 32: - search.reverse() + search = [32] if sys.platform == "win32" or sys.platform == "cygwin": script_ext = "bat" else: script_ext = "sh" + searched_in = [] for b in search: settings = os.path.join(full, "settings{0}.{1}".format(b, script_ext)) if os.path.exists(settings): return settings + searched_in.append(settings) - raise OSError("no Xilinx tools settings file found") + raise OSError( + "no Xilinx tools settings file found.\n" + "Looked in:\n" + " " + + "\n ".join(searched_in)) class XilinxMultiRegImpl(MultiRegImpl): diff --git a/litex/build/xilinx/ise.py b/litex/build/xilinx/ise.py index 0356f9644..171fbef0c 100644 --- a/litex/build/xilinx/ise.py +++ b/litex/build/xilinx/ise.py @@ -96,7 +96,7 @@ def _run_ise(build_name, ise_path, source, mode, ngdbuild_opt, build_script_contents = "# Autogenerated by LiteX\nset -e\n" fail_stmt = "" if source: - settings = common.settings(ise_path, ver, "ISE_DS") + settings = common.settings(ise_path, "ISE_DS", ver, first="version") build_script_contents += source_cmd + settings + "\n" ext = "ngc" diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 8051e1676..8511a5c50 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -59,7 +59,7 @@ def _run_vivado(build_name, vivado_path, source, ver=None): command = build_script_file else: build_script_contents = "# Autogenerated by LiteX\nset -e\n" - settings = common.settings(vivado_path, ver) + settings = common.settings(vivado_path, "Vivado", ver, first="name") build_script_contents += "source " + settings + "\n" build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" build_script_file = "build_" + build_name + ".sh" @@ -172,11 +172,11 @@ class XilinxVivadoToolchain: toolchain_path=None, source=True, run=True, **kwargs): if toolchain_path is None: if sys.platform == "win32": - toolchain_path = "C:\\Xilinx\\Vivado" + toolchain_path = "C:\\Xilinx" elif sys.platform == "cygwin": - toolchain_path = "/cygdrive/c/Xilinx/Vivado" + toolchain_path = "/cygdrive/c/Xilinx" else: - toolchain_path = "/opt/Xilinx/Vivado" + toolchain_path = "/opt/Xilinx" os.makedirs(build_dir, exist_ok=True) cwd = os.getcwd() os.chdir(build_dir) diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 13723e4ef..6274216a2 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -25,6 +25,19 @@ def mem_decoder(address, start=26, end=29): return lambda a: a[start:end] == ((address >> (start+2)) & (2**(end-start))-1) +class ReadOnlyDict(dict): + def __readonly__(self, *args, **kwargs): + raise RuntimeError("Cannot modify ReadOnlyDict") + __setitem__ = __readonly__ + __delitem__ = __readonly__ + pop = __readonly__ + popitem = __readonly__ + clear = __readonly__ + update = __readonly__ + setdefault = __readonly__ + del __readonly__ + + class SoCCore(Module): csr_map = { "crg": 0, # user @@ -35,9 +48,11 @@ class SoCCore(Module): "buttons": 5, # user "leds": 6, # user } - interrupt_map = { - "uart": 0, - "timer0": 1, + interrupt_map = {} + soc_interrupt_map = { + "nmi": 0, # Reserve zero for "non-maskable interrupt" + "timer0": 1, # LiteX Timer + "uart": 2, # LiteX UART (IRQ 2 for UART matches mor1k standard config). } mem_map = { "rom": 0x00000000, # (default shadow @0x80000000) @@ -123,6 +138,8 @@ class SoCCore(Module): else: self.submodules.uart_phy = uart.RS232PHY(platform.request("serial"), clk_freq, uart_baudrate) self.submodules.uart = uart.UART(self.uart_phy) + else: + del self.soc_interrupt_map["uart"] if ident: if ident_version: @@ -133,6 +150,36 @@ class SoCCore(Module): if with_timer: self.submodules.timer0 = timer.Timer() + else: + del self.soc_interrupt_map["timer0"] + + # Invert the interrupt map. + interrupt_rmap = {} + for mod_name, interrupt in self.interrupt_map.items(): + assert interrupt not in interrupt_rmap, ( + "Interrupt vector conflict for IRQ %s, user defined %s conflicts with user defined %s" % ( + interrupt, mod_name, interrupt_rmap[interrupt])) + + interrupt_rmap[interrupt] = mod_name + + # Add the base SoC's interrupt map + for mod_name, interrupt in self.soc_interrupt_map.items(): + assert interrupt not in interrupt_rmap, ( + "Interrupt vector conflict for IRQ %s, user defined %s conflicts with SoC inbuilt %s" % ( + interrupt, mod_name, interrupt_rmap[interrupt])) + + self.interrupt_map[mod_name] = interrupt + interrupt_rmap[interrupt] = mod_name + + # Make sure other functions are not using this value. + self.soc_interrupt_map = None + + # Make the interrupt vector read only + self.interrupt_map = ReadOnlyDict(self.interrupt_map) + + # Save the interrupt reverse map + self.interrupt_rmap = ReadOnlyDict(interrupt_rmap) + def add_cpu_or_bridge(self, cpu_or_bridge): if self.finalized: @@ -192,7 +239,7 @@ class SoCCore(Module): def get_constants(self): r = [] - for name, interrupt in sorted(self.interrupt_map.items(), key=itemgetter(1)): + for interrupt, name in sorted(self.interrupt_rmap.items()): r.append((name.upper() + "_INTERRUPT", interrupt)) r += self._constants return r @@ -234,9 +281,13 @@ class SoCCore(Module): # Interrupts if hasattr(self.cpu_or_bridge, "interrupt"): - for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)): - if hasattr(self, k): - self.comb += self.cpu_or_bridge.interrupt[v].eq(getattr(self, k).ev.irq) + for interrupt, mod_name in sorted(self.interrupt_rmap.items()): + if mod_name == "nmi": + continue + assert hasattr(self, mod_name), "Missing module for interrupt %s" % mod_name + mod_impl = getattr(self, mod_name) + assert hasattr(mod_impl, 'ev'), "Submodule %s does not have EventManager (xx.ev) module" % mod_name + self.comb += self.cpu_or_bridge.interrupt[interrupt].eq(mod_impl.ev.irq) def build(self, *args, **kwargs): return self.platform.build(self, *args, **kwargs)