From: Luke Kenneth Casson Leighton Date: Thu, 14 Apr 2022 13:42:45 +0000 (+0100) Subject: bleh. add XICS_ICS and XICS_ICP but the patch is X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b9c0f4568515743e463391a72728ea8ed4fe45f2;p=ls2.git bleh. add XICS_ICS and XICS_ICP but the patch is 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 --- diff --git a/src/ls2.py b/src/ls2.py index 4819cdc..9f20828 100644 --- a/src/ls2.py +++ b/src/ls2.py @@ -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)