soc: Don't update CSR alignment when there is no CPU
[litex.git] / litex / soc / integration / soc.py
index 11e8dd2b2f55285ec3ce99cba9a0b327ffff1b66..651f450d71697a5c7e91a5d4a7eef4e57cd10991 100644 (file)
@@ -282,7 +282,8 @@ class SoCBusHandler(Module):
         return is_io
 
     # Add Master/Slave -----------------------------------------------------------------------------
-    def add_adapter(self, name, interface):
+    def add_adapter(self, name, interface, direction="m2s"):
+        assert direction in ["m2s", "s2m"]
         if interface.data_width != self.data_width:
             self.logger.info("{} Bus {} from {}-bit to {}-bit.".format(
                 colorer(name),
@@ -290,7 +291,11 @@ class SoCBusHandler(Module):
                 colorer(interface.data_width),
                 colorer(self.data_width)))
             new_interface = wishbone.Interface(data_width=self.data_width)
-            self.submodules += wishbone.Converter(interface, new_interface)
+            if direction == "m2s":
+                converter = wishbone.Converter(master=interface, slave=new_interface)
+            if direction == "s2m":
+                converter = wishbone.Converter(master=new_interface, slave=interface)
+            self.submodules += converter
             return new_interface
         else:
             return interface
@@ -304,7 +309,7 @@ class SoCBusHandler(Module):
                 colorer("already declared", color="red")))
             self.logger.error(self)
             raise
-        master = self.add_adapter(name, master)
+        master = self.add_adapter(name, master, "m2s")
         self.masters[name] = master
         self.logger.info("{} {} as Bus Master.".format(
             colorer(name,    color="underline"),
@@ -336,7 +341,7 @@ class SoCBusHandler(Module):
                 colorer("already declared", color="red")))
             self.logger.error(self)
             raise
-        slave = self.add_adapter(name, slave)
+        slave = self.add_adapter(name, slave, "s2m")
         self.slaves[name] = slave
         self.logger.info("{} {} as Bus Slave.".format(
             colorer(name, color="underline"),
@@ -753,8 +758,8 @@ class SoC(Module):
     def add_csr_bridge(self, origin):
         self.submodules.csr_bridge = wishbone2csr.WB2CSR(
             bus_csr       = csr_bus.Interface(
-            address_width = self.csr.address_width,
-            data_width    = self.csr.data_width))
+                address_width = self.csr.address_width,
+                data_width    = self.csr.data_width))
         csr_size   = 2**(self.csr.address_width + 2)
         csr_region = SoCRegion(origin=origin, size=csr_size, cached=False)
         self.bus.add_slave("csr", self.csr_bridge.wishbone, csr_region)
@@ -762,7 +767,7 @@ class SoC(Module):
         self.add_config("CSR_DATA_WIDTH", self.csr.data_width)
         self.add_config("CSR_ALIGNMENT",  self.csr.alignment)
 
-    def add_cpu(self, name="vexriscv", variant="standard", reset_address=None):
+    def add_cpu(self, name="vexriscv", variant="standard", cls=None, reset_address=None):
         if name not in cpu.CPUS.keys():
             self.logger.error("{} CPU {}, supporteds: {}".format(
                 colorer(name),
@@ -770,12 +775,19 @@ class SoC(Module):
                 colorer(", ".join(cpu.CPUS.keys()))))
             raise
         # Add CPU
-        self.submodules.cpu = cpu.CPUS[name](self.platform, variant)
+        cpu_cls = cls if cls is not None else cpu.CPUS[name]
+        self.submodules.cpu = cpu_cls(self.platform, variant)
         # Update SoC with CPU constraints
         for n, (origin, size) in enumerate(self.cpu.io_regions.items()):
             self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False))
         self.mem_map.update(self.cpu.mem_map) # FIXME
-        self.csr.update_alignment(self.cpu.data_width)
+
+        # We don't want the CSR alignemnt reduced from 64-bit to 32-bit on
+        # a standalone system with a 64-bit WB and no CPU.
+        # Should we instead only update alignment if the CPU is *bigger*
+        # than the CSR ?
+        if name != "None":
+            self.csr.update_alignment(self.cpu.data_width)
         # Add Bus Masters/CSR/IRQs
         if not isinstance(self.cpu, cpu.CPUNone):
             if reset_address is None:
@@ -794,6 +806,9 @@ class SoC(Module):
         # Add constants
         self.add_config("CPU_TYPE",    str(name))
         self.add_config("CPU_VARIANT", str(variant.split('+')[0]))
+        self.add_constant("CONFIG_CPU_HUMAN_NAME", getattr(self.cpu, "human_name", "Unknown"))
+        if hasattr(self.cpu, "nop"):
+            self.add_constant("CONFIG_CPU_NOP", self.cpu.nop)
 
     def add_timer(self, name="timer0"):
         self.check_if_exists(name)
@@ -815,7 +830,14 @@ class SoC(Module):
         # SoC Bus Interconnect ---------------------------------------------------------------------
         bus_masters = self.bus.masters.values()
         bus_slaves  = [(self.bus.regions[n].decoder(self.bus), s) for n, s in self.bus.slaves.items()]
-        if len(bus_masters) and len(bus_slaves):
+        # One master and one slave, use a point to point interconnect, this is useful for
+        # generating standalone components such as LiteDRAM whose external control
+        # interface is a wishbone.
+        if len(bus_masters) == 1 and len(bus_slaves) == 1:
+            self.submodules.bus_interconnect = wishbone.InterconnectPointToPoint(
+                master = list(bus_masters)[0],
+                slave  = list(self.bus.slaves.values())[0])
+        elif len(bus_masters) and len(bus_slaves):
             self.submodules.bus_interconnect = wishbone.InterconnectShared(
                 masters        = bus_masters,
                 slaves         = bus_slaves,
@@ -922,13 +944,9 @@ class LiteXSoC(SoC):
             if name == "stub":
                 self.comb += self.uart.sink.ready.eq(1)
 
-        # Bridge
-        elif name in ["bridge"]:
-            self.submodules.uart = uart.UARTWishboneBridge(
-                pads     = self.platform.request("serial"),
-                clk_freq = self.sys_clk_freq,
-                baudrate = baudrate)
-            self.bus.add_master(name="uart_bridge", master=self.uart.wishbone)
+        # UARTBone / Bridge
+        elif name in ["uartbone", "bridge"]:
+            self.add_uartbone(baudrate=baudrate)
 
         # Crossover
         elif name in ["crossover"]:
@@ -957,8 +975,8 @@ class LiteXSoC(SoC):
                 tx_fifo_depth = fifo_depth,
                 rx_fifo_depth = fifo_depth))
 
-        # USB CDC (with ValentyUSB core)
-        elif name in ["usb_cdc"]:
+        # USB ACM (with ValentyUSB core)
+        elif name in ["usb_acm"]:
             import valentyusb.usbcore.io as usbio
             import valentyusb.usbcore.cpu.cdc_eptri as cdc_eptri
             usb_pads = self.platform.request("usb")
@@ -982,6 +1000,15 @@ class LiteXSoC(SoC):
         else:
             self.add_constant("UART_POLLING")
 
+    # Add UARTbone ---------------------------------------------------------------------------------
+    def add_uartbone(self, name="serial", baudrate=115200):
+        from litex.soc.cores import uart
+        self.submodules.uartbone = uart.UARTBone(
+            pads     = self.platform.request(name),
+            clk_freq = self.sys_clk_freq,
+            baudrate = baudrate)
+        self.bus.add_master(name="uartbone", master=self.uartbone.wishbone)
+
     # Add SDRAM ------------------------------------------------------------------------------------
     def add_sdram(self, name, phy, module, origin, size=None,
         l2_cache_size           = 8192,
@@ -1013,7 +1040,8 @@ class LiteXSoC(SoC):
             sdram_size = min(sdram_size, size)
 
         # Add SDRAM region
-        self.bus.add_region("main_ram", SoCRegion(origin=origin, size=sdram_size))
+        if self.cpu_type is not None:
+            self.bus.add_region("main_ram", SoCRegion(origin=origin, size=sdram_size))
 
         # SoC [<--> L2 Cache] <--> LiteDRAM --------------------------------------------------------
         if len(self.cpu.memory_buses):
@@ -1064,7 +1092,7 @@ class LiteXSoC(SoC):
                     # Else raise Error.
                     else:
                         raise NotImplementedError
-        else:
+        elif self.cpu_type is not None:
             # When CPU has no direct memory interface, create a Wishbone Slave interface to LiteDRAM.
 
             # Request a LiteDRAM native port.
@@ -1129,7 +1157,7 @@ class LiteXSoC(SoC):
             eth_tx_clk)
 
     # Add Etherbone --------------------------------------------------------------------------------
-    def add_etherbone(self, name="etherbone", phy=None,
+    def add_etherbone(self, name="etherbone", phy=None, clock_domain=None,
         mac_address = 0x10e2d5000000,
         ip_address  = "192.168.1.50",
         udp_port    = 1234):
@@ -1142,9 +1170,21 @@ class LiteXSoC(SoC):
             mac_address = mac_address,
             ip_address  = ip_address,
             clk_freq    = self.clk_freq)
+        if clock_domain is not None: # FIXME: Could probably be avoided.
+            ethcore = ClockDomainsRenamer("eth_tx")(ethcore)
         self.submodules += ethcore
+
+        # Clock domain renaming
+        if clock_domain is not None: # FIXME: Could probably be avoided.
+            self.clock_domains.cd_etherbone = ClockDomain("etherbone")
+            self.comb += self.cd_etherbone.clk.eq(ClockSignal(clock_domain))
+            self.comb += self.cd_etherbone.rst.eq(ResetSignal(clock_domain))
+            clock_domain = "etherbone"
+        else:
+            clock_domain = "sys"
+
         # Etherbone
-        etherbone = LiteEthEtherbone(ethcore.udp, udp_port)
+        etherbone = LiteEthEtherbone(ethcore.udp, udp_port, cd=clock_domain)
         setattr(self.submodules, name, etherbone)
         self.add_wb_master(etherbone.wishbone.bus)
         # Timing constraints
@@ -1164,10 +1204,10 @@ class LiteXSoC(SoC):
     # Add SPI Flash --------------------------------------------------------------------------------
     def add_spi_flash(self, name="spiflash", mode="4x", dummy_cycles=None, clk_freq=None):
         assert dummy_cycles is not None                 # FIXME: Get dummy_cycles from SPI Flash
-        assert mode in ["4x"]                           # FIXME: Add 1x support.
+        assert mode in ["1x", "4x"]
         if clk_freq is None: clk_freq = self.clk_freq/2 # FIXME: Get max clk_freq from SPI Flash
         spiflash = SpiFlash(
-            pads         = self.platform.request(name + mode),
+            pads         = self.platform.request(name if mode == "1x" else name + mode),
             dummy        = dummy_cycles,
             div          = ceil(self.clk_freq/clk_freq),
             with_bitbang = True,