From 07b9cabd0d99e628ed522f7991b236be7600edad Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 27 Feb 2015 15:28:37 +0100 Subject: [PATCH] gensoc: make it more generic (a SoC does not necessarily have a CPU) --- make.py | 39 +++-- misoclib/cpu/__init__.py | 4 + misoclib/cpu/lm32/__init__.py | 4 +- misoclib/cpu/mor1kx/__init__.py | 4 +- misoclib/gensoc/__init__.py | 244 ++++++++++++++++++++------------ software/libbase/system.c | 4 + targets/simple.py | 23 +-- 7 files changed, 190 insertions(+), 132 deletions(-) diff --git a/make.py b/make.py index 93af739f..8e9d804e 100755 --- a/make.py +++ b/make.py @@ -7,6 +7,7 @@ from migen.util.misc import autotype from migen.fhdl import simplify from misoclib.gensoc import cpuif +from misoclib.cpu import CPU from misoclib.sdram.phy import initsequence from misoc_import import misoc_import @@ -121,7 +122,7 @@ CPU type: {} actions["build-bios"] = True if not actions["load-bitstream"]: actions["flash-bitstream"] = True - if not hasattr(soc, "init_bios_memory"): + if not soc.with_rom: actions["flash-bios"] = True if actions["build-bitstream"] and hasattr(soc, "init_bios_memory"): actions["build-bios"] = True @@ -144,28 +145,30 @@ CPU type: {} */ """.format(platform_name, args.target, top_class.__name__, soc.cpu_type) + if isinstance(soc.cpu_or_bridge, CPU): cpu_mak = cpuif.get_cpu_mak(soc.cpu_type) write_to_file("software/include/generated/cpu.mak", cpu_mak) linker_output_format = cpuif.get_linker_output_format(soc.cpu_type) write_to_file("software/include/generated/output_format.ld", linker_output_format) - linker_regions = cpuif.get_linker_regions(soc.cpu_memory_regions) + linker_regions = cpuif.get_linker_regions(soc.memory_regions) write_to_file("software/include/generated/regions.ld", boilerplate + linker_regions) - try: - flash_boot_address = soc.flash_boot_address - except AttributeError: - flash_boot_address = None - mem_header = cpuif.get_mem_header(soc.cpu_memory_regions, flash_boot_address) - write_to_file("software/include/generated/mem.h", boilerplate + mem_header) - csr_header = cpuif.get_csr_header(soc.cpu_csr_regions, soc.interrupt_map) - write_to_file("software/include/generated/csr.h", boilerplate + csr_header) + for sdram_phy in ["sdrphy", "ddrphy"]: if hasattr(soc, sdram_phy): sdram_phy_header = initsequence.get_sdram_phy_header(getattr(soc, sdram_phy)) write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header) + try: + flash_boot_address = soc.flash_boot_address + except AttributeError: + flash_boot_address = None + mem_header = cpuif.get_mem_header(soc.memory_regions, flash_boot_address) + write_to_file("software/include/generated/mem.h", boilerplate + mem_header) + csr_header = cpuif.get_csr_header(soc.csr_regions, soc.interrupt_map) + write_to_file("software/include/generated/csr.h", boilerplate + csr_header) if actions["build-csr-csv"]: - csr_csv = cpuif.get_csr_csv(soc.cpu_csr_regions) + csr_csv = cpuif.get_csr_csv(soc.csr_regions) write_to_file(args.csr_csv, csr_csv) if actions["build-bios"]: @@ -174,16 +177,8 @@ CPU type: {} raise OSError("BIOS build failed") if actions["build-bitstream"]: - if hasattr(soc, "init_bios_memory"): - with open("software/bios/bios.bin", "rb") as bios_file: - bios_data = [] - while True: - w = bios_file.read(4) - if not w: - break - bios_data.append(struct.unpack(">I", w)[0]) - soc.init_bios_memory(bios_data) - + if soc.with_rom: + soc.init_rom() for decorator in args.decorate: soc = getattr(simplify, decorator)(soc) build_kwargs = dict((k, autotype(v)) for k, v in args.build_option) @@ -209,4 +204,4 @@ CPU type: {} if actions["flash-bios"]: prog = platform.create_programmer() prog.set_flash_proxy_dir(args.flash_proxy_dir) - prog.flash(soc.cpu_reset_address, "software/bios/bios.bin") + prog.flash(soc.cpu_reset_address, soc.cpu_boot_file) diff --git a/misoclib/cpu/__init__.py b/misoclib/cpu/__init__.py index e69de29b..39ce2389 100644 --- a/misoclib/cpu/__init__.py +++ b/misoclib/cpu/__init__.py @@ -0,0 +1,4 @@ +from migen.fhdl.std import * + +class CPU(Module): + pass diff --git a/misoclib/cpu/lm32/__init__.py b/misoclib/cpu/lm32/__init__.py index ac6b3764..8a4776d4 100644 --- a/misoclib/cpu/lm32/__init__.py +++ b/misoclib/cpu/lm32/__init__.py @@ -3,7 +3,9 @@ import os from migen.fhdl.std import * from migen.bus import wishbone -class LM32(Module): +from misoclib.cpu import CPU + +class LM32(CPU): def __init__(self, platform, eba_reset): self.ibus = i = wishbone.Interface() self.dbus = d = wishbone.Interface() diff --git a/misoclib/cpu/mor1kx/__init__.py b/misoclib/cpu/mor1kx/__init__.py index bc7ef281..2a5140ba 100644 --- a/misoclib/cpu/mor1kx/__init__.py +++ b/misoclib/cpu/mor1kx/__init__.py @@ -3,7 +3,9 @@ import os from migen.fhdl.std import * from migen.bus import wishbone -class MOR1KX(Module): +from misoclib.cpu import CPU + +class MOR1KX(CPU): def __init__(self, platform, reset_pc): self.ibus = i = wishbone.Interface() self.dbus = d = wishbone.Interface() diff --git a/misoclib/gensoc/__init__.py b/misoclib/gensoc/__init__.py index 28ae0b41..4f18f455 100644 --- a/misoclib/gensoc/__init__.py +++ b/misoclib/gensoc/__init__.py @@ -1,3 +1,4 @@ +import os, struct from operator import itemgetter from math import ceil @@ -7,7 +8,7 @@ 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.cpu import CPU, lm32, mor1kx from misoclib.sdram import lasmicon from misoclib.sdram import dfii from misoclib.sdram import memtest @@ -19,9 +20,9 @@ def mem_decoder(address, start=26, end=29): class GenSoC(Module): csr_map = { "crg": 0, # user - "uart": 1, # provided by default - "identifier": 2, # provided - "timer0": 3, # provided + "uart": 1, # provided by default (optional) + "identifier": 2, # provided by default (optional) + "timer0": 3, # provided by default (optional) "buttons": 4, # user "leds": 5, # user } @@ -32,54 +33,105 @@ class GenSoC(Module): mem_map = { "rom": 0x00000000, # (shadow @0x80000000) "sram": 0x10000000, # (shadow @0x90000000) + "sdram": 0x40000000, # (shadow @0xc0000000) "csr": 0x60000000, # (shadow @0xe0000000) } - def __init__(self, platform, clk_freq, cpu_reset_address, sram_size=4096, with_uart=True, cpu_type="lm32", - csr_data_width=8, csr_address_width=14): + def __init__(self, platform, clk_freq, cpu_or_bridge=None, + with_cpu=True, cpu_type="lm32", cpu_reset_address=0x00000000, + cpu_boot_file="software/bios/bios.bin", + with_rom=False, rom_size=0x8000, rom_init_now=False, + with_sram=True, sram_size=4096, + with_sdram=False, sdram_size=64*1024, + with_csr=True, csr_data_width=8, csr_address_width=14, + with_uart=True, uart_baudrate=115200, + with_identifier=True, + with_timer=True): + self.platform = platform self.clk_freq = clk_freq + self.cpu_or_bridge = cpu_or_bridge + + self.with_cpu = with_cpu + self.cpu_type = cpu_type self.cpu_reset_address = cpu_reset_address + self.cpu_boot_file = cpu_boot_file + + self.with_rom = with_rom + self.rom_size = rom_size + self.rom_init_now = rom_init_now + + self.with_sram = with_sram self.sram_size = sram_size - self.cpu_type = cpu_type + + self.with_sdram = with_sdram + self.sdram_size = sdram_size + + self.with_uart = with_uart + self.uart_baudrate = uart_baudrate + + self.with_identifier = with_identifier + + self.with_csr = with_csr 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) + self.memory_regions = [] + self.csr_regions = [] # list of (name, origin, busword, csr_list/Memory) - # 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)) - 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._wb_masters = [] + self._wb_slaves = [] - 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) + if with_cpu: + 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.cpu_or_bridge = self.cpu + self._wb_masters += [self.cpu.ibus, self.cpu.dbus] + + if with_rom: + self.submodules.rom = wishbone.SRAM(rom_size, read_only=True) + self.register_mem("rom", self.mem_map["rom"], self.rom.bus, rom_size) + if rom_init_now: + self.init_rom() + + if with_sram: + self.submodules.sram = wishbone.SRAM(sram_size) + self.register_mem("sram", self.mem_map["sram"], self.sram.bus, sram_size) + + if with_sdram: + self.submodules.sdram = wishbone.SRAM(sdram_size) + self.register_mem("sdram", self.mem_map["sdram"], self.sdram.bus, sdram_size) + + if with_csr: + self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(csr_data_width, csr_address_width)) + self.register_mem("csr", self.mem_map["csr"], self.wishbone2csr.wishbone) + + if with_uart: + self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=uart_baudrate) + + if with_identifier: + platform_id = 0x554E if not hasattr(platform, "identifier") else platform.identifier + self.submodules.identifier = identifier.Identifier(platform_id, int(clk_freq)) + + if with_timer: + self.submodules.timer0 = timer.Timer() + + def init_rom(self, filename=None): + if filename is None: + filename = self.cpu_boot_file + filename_ext = os.path.splitext(filename)[1] + if filename_ext != ".bin": + raise ValueError("rom_init only supports .bin files") + with open(filename, "rb") as boot_file: + boot_data = [] + while True: + w = boot_file.read(4) + if not w: + break + boot_data.append(struct.unpack(">I", w)[0]) + self.rom.mem.init = boot_data def add_wb_master(self, wbm): if self.finalized: @@ -91,46 +143,60 @@ class GenSoC(Module): 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: + def check_memory_region(self, name, origin): + for n, o, l in self.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 add_memory_region(self, name, origin, length): + self.check_memory_region(name, origin) + self.memory_regions.append((name, origin, length)) - def check_cpu_csr_region(self, name, origin): - for n, o, l, obj in self.cpu_csr_regions: + def register_mem(self, name, address, interface, size=None): + self.add_wb_slave(mem_decoder(address), interface) + if size is not None: + self.add_memory_region(name, address, size) + + # XXX for retro-compatibilty, we should maybe use directly register_mem in targets + def register_rom(self, interface): + self.register_mem("rom", self.mem_map["rom"], interface, size=self.rom_size) + + def check_csr_region(self, name, origin): + for n, o, l, obj in self.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 add_csr_region(self, name, origin, busword, obj): + self.check_csr_region(name, origin) + self.csr_regions.append((name, origin, busword, obj)) def do_finalize(self): - if not self._rom_registered: - raise FinalizeError("Need to call GenSoC.register_rom()") + registered_mems = [regions[0] for regions in self.memory_regions] + if isinstance(self.cpu_or_bridge, CPU): + for mem in ["rom", "sram"]: + if mem not in registered_mems: + raise FinalizeError("CPU needs a {} to be registered with GenSoC.register_mem()".format(mem)) # 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) + if self.with_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_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_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) + 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) def ns(self, t, margin=True): clk_period_ns = 1000000000/self.clk_freq @@ -141,14 +207,6 @@ class GenSoC(Module): 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, @@ -159,16 +217,19 @@ class SDRAMSoC(GenSoC): } csr_map.update(GenSoC.csr_map) - mem_map = { - "sdram": 0x40000000, # (shadow @0xc0000000) - } - mem_map.update(GenSoC.mem_map) + def __init__(self, platform, clk_freq, + ramcon_type="lasmicon", + with_l2=True, l2_size=8192, + with_memtest=False, + **kwargs): + GenSoC.__init__(self, platform, clk_freq, **kwargs) + self.ramcon_type = ramcon_type - 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, with_uart, **kwargs) + self.with_l2 = with_l2 self.l2_size = l2_size + 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): @@ -192,29 +253,30 @@ class SDRAMSoC(GenSoC): 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) + if self.with_l2: + self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(self.l2_size//4, self.lasmixbar.get_master()) + sdram_size = 2**self.lasmicon.lasmic.aw*self.lasmicon.lasmic.dw*self.lasmicon.lasmic.nbanks//8 + self.register_mem("sdram", self.mem_map["sdram"], self.wishbone2lasmi.wishbone, sdram_size) + # MINICON elif self.ramcon_type == "minicon": + if with_l2: + raise ValueError("MINICON does not implement L2 cache (Use LASMICON)") + 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) + sdram_size = 2**(sdram_geom.bank_a+sdram_geom.row_a+sdram_geom.col_a)*sdram_width//8 + if (sdram_width == 32): - self.add_wb_slave(mem_decoder(self.mem_map["sdram"]), sdramcon.bus) + self.register_mem("sdram", self.mem_map["sdram"], sdramcon.bus, sdram_size) 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) + self.register_mem("sdram", self.mem_map["sdram"], self.dc.wishbone_i, sdram_size) 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)) diff --git a/software/libbase/system.c b/software/libbase/system.c index ea4c7617..4a71b206 100644 --- a/software/libbase/system.c +++ b/software/libbase/system.c @@ -85,4 +85,8 @@ void flush_l2_cache(void) #endif } } +#else +void flush_l2_cache(void) +{ +} #endif diff --git a/targets/simple.py b/targets/simple.py index e0eae490..02b23385 100644 --- a/targets/simple.py +++ b/targets/simple.py @@ -1,7 +1,7 @@ from migen.fhdl.std import * from migen.bus import wishbone -from misoclib.gensoc import GenSoC, IntegratedBIOS, mem_decoder +from misoclib.gensoc import GenSoC, mem_decoder class _CRG(Module): def __init__(self, clk_in): @@ -17,24 +17,13 @@ class _CRG(Module): self.cd_sys.rst.eq(~rst_n) ] -class SimpleSoC(GenSoC, IntegratedBIOS): - mem_map = { - "sdram": 0x40000000, # (shadow @0xc0000000) - } - mem_map.update(GenSoC.mem_map) - - def __init__(self, platform): +class SimpleSoC(GenSoC): + def __init__(self, platform, **kwargs): GenSoC.__init__(self, platform, clk_freq=int((1/(platform.default_clk_period))*1000000000), - cpu_reset_address=0) - IntegratedBIOS.__init__(self) - + with_rom=True, + with_sdram=True, sdram_size=16*1024, + **kwargs) self.submodules.crg = _CRG(platform.request(platform.default_clk_name)) - # use on-board SRAM as SDRAM - sys_ram_size = 16*1024 - self.submodules.sys_ram = wishbone.SRAM(sys_ram_size) - self.add_wb_slave(mem_decoder(self.mem_map["sdram"]), self.sys_ram.bus) - self.add_cpu_memory_region("sdram", self.mem_map["sdram"], sys_ram_size) - default_subtarget = SimpleSoC -- 2.30.2