litex/misoclib/gensoc/__init__.py

225 lines
8.3 KiB
Python

from operator import itemgetter
from math import ceil
from migen.fhdl.std import *
from migen.bank import csrgen
from migen.bus import wishbone, csr, lasmibus, dfi
from migen.bus import wishbone2lasmi, wishbone2csr
from misoclib import uart, identifier, timer
from misoclib.cpu import lm32, mor1kx
from misoclib.sdram import lasmicon
from misoclib.sdram import dfii
from misoclib.sdram import memtest
from misoclib.sdram.minicon import Minicon
def mem_decoder(address, start=26, end=29):
return lambda a: a[start:end] == ((address >> (start+2)) & (2**(end-start))-1)
class GenSoC(Module):
csr_map = {
"crg": 0, # user
"uart": 1, # provided by default
"identifier": 2, # provided
"timer0": 3, # provided
"buttons": 4, # user
"leds": 5, # user
}
interrupt_map = {
"uart": 0,
"timer0": 1,
}
mem_map = {
"rom": 0x00000000, # (shadow @0x80000000)
"sram": 0x10000000, # (shadow @0x90000000)
"csr": 0x60000000, # (shadow @0xe0000000)
}
def __init__(self, platform, clk_freq, cpu_reset_address, sram_size=4096, l2_size=0, with_uart=True, cpu_type="lm32",
csr_data_width=8, csr_address_width=14):
self.clk_freq = clk_freq
self.cpu_reset_address = cpu_reset_address
self.sram_size = sram_size
self.l2_size = l2_size
self.cpu_type = cpu_type
self.csr_data_width = csr_data_width
self.csr_address_width = csr_address_width
self.cpu_memory_regions = []
self.cpu_csr_regions = [] # list of (name, origin, busword, csr_list/Memory)
self._rom_registered = False
# Wishbone
if cpu_type == "lm32":
self.submodules.cpu = lm32.LM32(platform, cpu_reset_address)
elif cpu_type == "or1k":
self.submodules.cpu = mor1kx.MOR1KX(platform, cpu_reset_address)
else:
raise ValueError("Unsupported CPU type: "+cpu_type)
self.submodules.sram = wishbone.SRAM(sram_size)
self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(csr_data_width, csr_address_width))
# rom 0x00000000 (shadow @0x80000000) from register_rom
# SRAM/debug 0x10000000 (shadow @0x90000000) provided
# CSR bridge 0x60000000 (shadow @0xe0000000) provided
self._wb_masters = [self.cpu.ibus, self.cpu.dbus]
self._wb_slaves = [
(mem_decoder(self.mem_map["sram"]), self.sram.bus),
(mem_decoder(self.mem_map["csr"]), self.wishbone2csr.wishbone)
]
self.add_cpu_memory_region("sram", self.mem_map["sram"], sram_size)
# CSR
if with_uart:
self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200)
platform_id = 0x554E if not hasattr(platform, "identifier") else platform.identifier
self.submodules.identifier = identifier.Identifier(platform_id, int(clk_freq),
log2_int(l2_size) if l2_size else 0)
self.submodules.timer0 = timer.Timer()
def register_rom(self, rom_wb_if, bios_size=0xa000):
if self._rom_registered:
raise FinalizeError
self._rom_registered = True
self.add_wb_slave(mem_decoder(self.mem_map["rom"]), rom_wb_if)
self.add_cpu_memory_region("rom", self.cpu_reset_address, bios_size)
def add_wb_master(self, wbm):
if self.finalized:
raise FinalizeError
self._wb_masters.append(wbm)
def add_wb_slave(self, address_decoder, interface):
if self.finalized:
raise FinalizeError
self._wb_slaves.append((address_decoder, interface))
def check_cpu_memory_region(self, name, origin):
for n, o, l in self.cpu_memory_regions:
if n == name or o == origin:
raise ValueError("Memory region conflict between {} and {}".format(n, name))
def add_cpu_memory_region(self, name, origin, length):
self.check_cpu_memory_region(name, origin)
self.cpu_memory_regions.append((name, origin, length))
def check_cpu_csr_region(self, name, origin):
for n, o, l, obj in self.cpu_csr_regions:
if n == name or o == origin:
raise ValueError("CSR region conflict between {} and {}".format(n, name))
def add_cpu_csr_region(self, name, origin, busword, obj):
self.check_cpu_csr_region(name, origin)
self.cpu_csr_regions.append((name, origin, busword, obj))
def do_finalize(self):
if not self._rom_registered:
raise FinalizeError("Need to call GenSoC.register_rom()")
# Wishbone
self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
self._wb_slaves, register=True)
# CSR
self.submodules.csrbankarray = csrgen.BankArray(self,
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override],
data_width=self.csr_data_width, address_width=self.csr_address_width)
self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses())
for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
self.add_cpu_csr_region(name, self.mem_map["csr"]+0x80000000+0x800*mapaddr, flen(rmap.bus.dat_w), csrs)
for name, memory, mapaddr, mmap in self.csrbankarray.srams:
self.add_cpu_csr_region(name, self.mem_map["csr"]+0x80000000+0x800*mapaddr, flen(rmap.bus.dat_w), memory)
# Interrupts
for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)):
if hasattr(self, k):
self.comb += self.cpu.interrupt[v].eq(getattr(self, k).ev.irq)
def ns(self, t, margin=True):
clk_period_ns = 1000000000/self.clk_freq
if margin:
t += clk_period_ns/2
return ceil(t/clk_period_ns)
def do_exit(self, vns):
pass
class IntegratedBIOS:
def __init__(self, bios_size=0x8000):
self.submodules.rom = wishbone.SRAM(bios_size, read_only=True)
self.register_rom(self.rom.bus, bios_size)
def init_bios_memory(self, data):
self.rom.mem.init = data
class SDRAMSoC(GenSoC):
csr_map = {
"dfii": 6,
"lasmicon": 7,
"memtest_w": 8,
"memtest_r": 9
}
csr_map.update(GenSoC.csr_map)
mem_map = {
"sdram": 0x40000000, # (shadow @0xc0000000)
}
mem_map.update(GenSoC.mem_map)
def __init__(self, platform, clk_freq, cpu_reset_address, with_memtest=False, sram_size=4096, l2_size=8192, with_uart=True, ramcon_type="lasmicon", **kwargs):
GenSoC.__init__(self, platform, clk_freq, cpu_reset_address, sram_size, l2_size, with_uart, **kwargs)
self.with_memtest = with_memtest
self.ramcon_type = ramcon_type
self._sdram_phy_registered = False
def register_sdram_phy(self, phy_dfi, phy_settings, sdram_geom, sdram_timing):
if self._sdram_phy_registered:
raise FinalizeError
self._sdram_phy_registered = True
# DFI
self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a,
phy_settings.dfi_d, phy_settings.nphases)
self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, phy_dfi)
# LASMICON
if self.ramcon_type == "lasmicon":
self.submodules.lasmicon = lasmicon.LASMIcon(phy_settings, sdram_geom, sdram_timing)
self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave)
self.submodules.lasmixbar = lasmibus.Crossbar([self.lasmicon.lasmic], self.lasmicon.nrowbits)
if self.with_memtest:
self.submodules.memtest_w = memtest.MemtestWriter(self.lasmixbar.get_master())
self.submodules.memtest_r = memtest.MemtestReader(self.lasmixbar.get_master())
# Wishbone bridge
self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(self.l2_size//4, self.lasmixbar.get_master())
self.add_wb_slave(mem_decoder(self.mem_map["sdram"]), self.wishbone2lasmi.wishbone)
self.add_cpu_memory_region("sdram", self.mem_map["sdram"],
2**self.lasmicon.lasmic.aw*self.lasmicon.lasmic.dw*self.lasmicon.lasmic.nbanks//8)
# MINICON
elif self.ramcon_type == "minicon":
self.submodules.minicon = sdramcon = Minicon(phy_settings, sdram_geom, sdram_timing)
self.submodules.dficon1 = dfi.Interconnect(sdramcon.dfi, self.dfii.slave)
sdram_width = flen(sdramcon.bus.dat_r)
if (sdram_width == 32):
self.add_wb_slave(mem_decoder(self.mem_map["sdram"]), sdramcon.bus)
elif (sdram_width < 32):
self.submodules.dc = wishbone.DownConverter(32, sdram_width)
self.submodules.intercon = wishbone.InterconnectPointToPoint(self.dc.wishbone_o, sdramcon.bus)
self.add_wb_slave(mem_decoder(self.mem_map["sdram"]), self.dc.wishbone_i)
else:
raise NotImplementedError("Unsupported SDRAM width of {} > 32".format(sdram_width))
# Wishbone bridge
self.add_cpu_memory_region("sdram", self.mem_map["sdram"],
2**(sdram_geom.bank_a+sdram_geom.row_a+sdram_geom.col_a)*sdram_width//8)
else:
raise ValueError("Unsupported SDRAM controller type: {}".format(self.ramcon_type))
def do_finalize(self):
if not self._sdram_phy_registered:
raise FinalizeError("Need to call SDRAMSoC.register_sdram_phy()")
GenSoC.do_finalize(self)