bleh. add XICS_ICS and XICS_ICP but the patch is
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 14 Apr 2022 13:42:45 +0000 (14:42 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 14 Apr 2022 13:42:45 +0000 (14:42 +0100)
a little bigger than expected.
note that a bug ECP5CRG(clk_freq, dram_clk_freq=None, pod_bits=pod_bits)
is also fixed here (whoops)

firstly, the XICS ICP and ICS need adding. but, they are
using make_wb_layout not wishbone.Interface.  therefore,
create a wishbone.Interface (sigh) and map the Signals across
one by one (just like with cvtuartbus)

secondly, the incoming IRQs are wired to GenericInterruptController
which is different from how Testissuer does it.

thirdly, eth_macs IRQ number is moved to 1 in order to match with
the Microwatt soc.vhdl

fourthly, uart_irq is set to 0

fifthly, UART16550 and EthMac needed to have their IRQLine
constructed *here* and passed in, otherwise the entire soc repo
becomes dependent on LambdaSoC just for that one import

sixthly, at the same time, DDRSoC has a uart_addr-0xc0002000 added
to match what soc.vhdl does

seventhly, eth0_cfg_addr is moved to 0xc000_c000 to get it out
of the way of XICS_ICP/ICS at 0xc000_4000 and 0xc000_5000

eigthly, xicx icp/ics are added at 0xc000_4000 and 0xc000_5000

totally broke the "one-purpose, one-commit" rule but not entirely
because after all this is "add XICS controller

src/ls2.py

index 4819cdc23ca7ee285ee36e493395ff85dfc67564..9f20828a618aed0688e36f091c54b7f22caac691 100644 (file)
@@ -23,6 +23,7 @@ from nmigen_stdio.serial import AsyncSerial
 from nmigen_boards.resources.memory import HyperRAMResource
 from lambdasoc.periph.hyperram import HyperRAM, HyperRAMPads, HyperRAMPHY
 
+from lambdasoc.periph.event import IRQLine
 from lambdasoc.periph.intc import GenericInterruptController
 from lambdasoc.periph.sram import SRAMPeripheral
 from lambdasoc.periph.timer import TimerPeripheral
@@ -34,6 +35,7 @@ from soc.bus.opencores_ethmac import EthMAC # OpenCores 10/100 Ethernet MAC
 from soc.bus.external_core import ExternalCore # external libresoc/microwatt
 from soc.bus.wb_downconvert import WishboneDownConvert
 from soc.bus.syscon import MicrowattSYSCON
+from soc.interrupts.xics import XICS_ICP, XICS_ICS
 
 # DDR3
 from gram.common import (PhySettings, get_cl_cw, get_sys_latency,
@@ -240,10 +242,12 @@ class DDR3SoC(SoC, Elaboratable):
                  ddr_pins, ddrphy_addr, dramcore_addr, ddr_addr,
                  fw_addr=0x0000_0000,
                  firmware=None,
+                 uart_addr=None, uart_irqno,
                  spi0_addr, spi0_cfg_addr,
                  eth0_cfg_addr, eth0_irqno,
                  hyperram_addr=None,
                  hyperram_pins=None,
+                 xics_icp_addr=None, xics_ics_addr=None,
                  clk_freq=50e6,
                  add_cpu=True):
 
@@ -282,7 +286,7 @@ class DDR3SoC(SoC, Elaboratable):
         if fpga in ['versa_ecp5', 'versa_ecp5_85', 'isim', 'ulx3s']:
             if fpga in ['isim']:
                 pod_bits = 6
-            self.crg = ECP5CRG(clk_freq, pod_bits)
+            self.crg = ECP5CRG(clk_freq, dram_clk_freq=None, pod_bits=pod_bits)
         if fpga in ['arty_a7']:
             self.crg = ArtyA7CRG(clk_freq)
 
@@ -300,8 +304,27 @@ class DDR3SoC(SoC, Elaboratable):
             self.cvtibus = cvtibus
             self.cvtdbus = cvtdbus
 
-            # CPU interrupt controller
+            # CPU interrupt controller, needs stall to be added, also
+            # compat with wishbone.Interface
             self.intc = GenericInterruptController(width=len(self.cpu.irq))
+            self.xics_icp = icp = XICS_ICP()
+            self.xics_ics = ics = XICS_ICS()
+            self.int_level_i = self.xics_ics.int_level_i
+
+            self.pbus = pbus = wishbone.Interface(name="xics_icp_bus",
+                                         addr_width=10, data_width=32,
+                                         granularity=8, features={'stall'})
+            self.sbus = sbus = wishbone.Interface(name="xics_ics_bus",
+                                         addr_width=10, data_width=32,
+                                         granularity=8, features={'stall'})
+            pmap = MemoryMap(addr_width=12, data_width=8, name="icp_map")
+            pbus.memory_map = pmap
+            self._decoder.add(pbus, addr=xics_icp_addr) # ICP addr
+
+            smap = MemoryMap(addr_width=12, data_width=8, name="ics_map")
+            sbus.memory_map = smap
+            self._decoder.add(sbus, addr=xics_ics_addr) # ICP addr
+
 
         # SRAM (but actually a ROM, for firmware)
         if fw_addr is not None:
@@ -334,16 +357,21 @@ class DDR3SoC(SoC, Elaboratable):
         # UART at 0xC000_2000, convert 32-bit bus down to 8-bit in an odd way
         if uart_pins is not None:
             # sigh actual UART in microwatt is 8-bit
+            self.uart_irq = IRQLine()
             self.uart = UART16550(data_width=8, pins=uart_pins,
-                                  features={'stall'})
+                                  features={'stall'},
+                                  irq=self.uart_irq)
             # but (see soc.vhdl) 8-bit regs are addressed at 32-bit locations
+            # strictly speaking this is a nmigen-soc "sparse" arrangement
+            # which should be handled by MemoryMap, but needs investigation
             cvtuartbus = wishbone.Interface(addr_width=5, data_width=32,
                                             granularity=8,
                                             features={'stall'})
             umap = MemoryMap(addr_width=7, data_width=8, name="uart_map")
             cvtuartbus.memory_map = umap
-            self._decoder.add(cvtuartbus, addr=0xc0002000) # 16550 UART addr
+            self._decoder.add(cvtuartbus, addr=uart_addr) # 16550 UART addr
             self.cvtuartbus = cvtuartbus
+            self.intc.add_irq(self.uart.irq, index=uart_irqno)
 
         # SDRAM module using opencores sdr_ctrl
         """
@@ -463,10 +491,11 @@ class DDR3SoC(SoC, Elaboratable):
         if ethmac_0_pins is not None and fpga in ['versa_ecp5',
                                                   'versa_ecp5_85',
                                                   'isim']:
+            self.eth_irq = IRQLine()
             # The OpenCores Ethernet MAC contains two independent Wishbone
             # interfaces, a slave (configuration) interface and a master (DMA)
             # interface.
-            self.eth0 = EthMAC(pins=ethmac_0_pins)
+            self.eth0 = EthMAC(pins=ethmac_0_pins, irq=self.eth_irq)
             self._arbiter.add(self.eth0.master_bus)
             self._decoder.add(self.eth0.slave_bus, addr=eth0_cfg_addr)
             self.intc.add_irq(self.eth0.irq, index=eth0_irqno)
@@ -507,7 +536,8 @@ class DDR3SoC(SoC, Elaboratable):
             comb += self.uart.ri_i.eq(0)
             comb += self.uart.dcd_i.eq(1)
             # sigh connect up the wishbone bus manually to deal with
-            # the mis-match on the data
+            # the mis-match on the data.  nmigen-soc "sparse" MemoryMap
+            # should be able to deal with this. TODO, investigate
             uartbus = self.uart.bus
             comb += uartbus.adr.eq(self.cvtuartbus.adr)
             comb += uartbus.stb.eq(self.cvtuartbus.stb)
@@ -559,8 +589,35 @@ class DDR3SoC(SoC, Elaboratable):
         comb += self._arbiter.bus.connect(self._decoder.bus)
 
         if hasattr(self, "cpu"):
-            # wire up the CPU interrupts
-            comb += self.cpu.irq.eq(self.intc.ip)
+            m.submodules.xics_icp = icp = self.xics_icp
+            m.submodules.xics_ics = ics = self.xics_ics
+            comb += icp.ics_i.eq(ics.icp_o)           # connect ICS to ICP
+            comb += self.cpu.irq.eq(icp.core_irq_o) # connect ICP to core
+
+            # wire up the CPU interrupts from the GenericInterrupt
+            comb += self.int_level_i.eq(self.intc.ip)
+
+            # grrr
+            comb += self.pbus.stall.eq(self.pbus.cyc & ~self.pbus.ack)
+            comb += self.sbus.stall.eq(self.sbus.cyc & ~self.sbus.ack)
+
+            # and also wire up make_wb_layout() to wishbone.Interface.
+            # really, XICS_ICS and XICS_ICP both need to be converted
+            # to use wishbone.Interface and this all goes
+            comb += icp.bus.adr.eq(self.pbus.adr)
+            comb += icp.bus.dat_w.eq(self.pbus.dat_w)
+            comb += icp.bus.cyc.eq(self.pbus.cyc)
+            comb += icp.bus.stb.eq(self.pbus.stb)
+            comb += icp.bus.we.eq(self.pbus.we)
+            comb += self.pbus.ack.eq(icp.bus.ack)
+            comb += self.pbus.dat_r.eq(icp.bus.dat_r)
+            comb += ics.bus.adr.eq(self.sbus.adr)
+            comb += ics.bus.dat_w.eq(self.sbus.dat_w)
+            comb += ics.bus.cyc.eq(self.sbus.cyc)
+            comb += ics.bus.stb.eq(self.sbus.stb)
+            comb += ics.bus.we.eq(self.sbus.we)
+            comb += self.sbus.ack.eq(ics.bus.ack)
+            comb += self.sbus.dat_r.eq(ics.bus.dat_r)
 
         if platform is None:
             return m
@@ -838,17 +895,21 @@ def build_platform(fpga, firmware):
                   ddr_addr=0x00000000,      # DRAM_BASE
                   spi0_addr=0xf0000000,     # SPI0_BASE
                   spi0_cfg_addr=0xc0006000, # SPI0_CTRL_BASE
-                  eth0_cfg_addr=0xc0004000, # ETH0_CTRL_BASE (4k)
-                  eth0_irqno=0,             # ETH0_IRQ number
+                  eth0_cfg_addr=0xc000c000, # ETH0_CTRL_BASE (4k)
+                  eth0_irqno=1,             # ETH0_IRQ number (match microwatt)
                   hyperram_addr=0xa0000000, # HYPERRAM_BASE
                   fw_addr=fw_addr,
                   #fw_addr=None,
                   ddr_pins=ddr_pins,
                   uart_pins=uart_pins,
+                  uart_irqno=0,             # UART_IRQ number (match microwatt)
+                  uart_addr=0xc0002000, # UART0_ADDR
                   spi_0_pins=spi_0_pins,
                   ethmac_0_pins=ethmac_0_pins,
                   hyperram_pins=hyperram_pins,
                   firmware=firmware,
+                  xics_icp_addr=0xc000_4000, # XICS_ICP_BASE
+                  xics_ics_addr=0xc000_5000, # XICS_ICS_BASE
                   clk_freq=clk_freq,
                   add_cpu=True)