diff --git a/litex/build/openocd.py b/litex/build/openocd.py index c9160c51c..62644da5f 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -27,12 +27,13 @@ class OpenOCD(GenericProgrammer): ]) self.call(["openocd", "-f", config, "-c", script]) - def flash(self, address, data, set_qe=False): + def flash(self, address, data, set_qe=False, init_commands=[]): config = self.find_config() flash_proxy = self.find_flash_proxy() script = "; ".join([ "init", - "jtagspi_init 0 {{{}}}".format(flash_proxy), + "jtagspi_init 0 {{{}}}".format(flash_proxy) + ] + init_commands + [ "jtagspi set_qe 0 1" if set_qe else "", "jtagspi_program {{{}}} 0x{:x}".format(data, address), "fpga_program", diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 6c286355f..11e6d06b9 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -2092,6 +2092,72 @@ class LiteXSoC(SoC): self.add_module(name=f"{name}_core", module=spiflash_core) spiflash_region = SoCRegion(origin=self.mem_map.get(name, None), size=module.total_size) self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region) + self.comb += spiflash_core.mmap.offset.eq(self.bus.regions.get(name, None).origin) + + # Constants. + self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq) + self.add_constant(f"{name}_MODULE_NAME", module.name) + self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size) + self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size) + if mode in [ "4x" ]: + if SpiNorFlashOpCodes.READ_1_1_4 in module.supported_opcodes: + self.add_constant(f"{name}_MODULE_QUAD_CAPABLE") + if SpiNorFlashOpCodes.READ_4_4_4 in module.supported_opcodes: + self.add_constant(f"{name}_MODULE_QPI_CAPABLE") + if software_debug: + self.add_constant(f"{name}_DEBUG") + + # Add SPI RAM -------------------------------------------------------------------------------- + def add_spi_ram(self, name="spiram", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False, + l2_cache_size = 8192, + l2_cache_reverse = False, + l2_cache_full_memory_we = True, + **kwargs): + # Imports. + from litespi import LiteSPI + from litespi.phy.generic import LiteSPIPHY + from litespi.opcodes import SpiNorFlashOpCodes + + # Checks/Parameters. + assert mode in ["1x", "4x"] + default_divisor = math.ceil(self.sys_clk_freq/(2*clk_freq)) - 1 + clk_freq = int(self.sys_clk_freq/(2*(default_divisor + 1))) + + # PHY. + spiram_phy = phy + if spiram_phy is None: + self.check_if_exists(f"{name}_phy") + spiram_pads = self.platform.request(name if mode == "1x" else name + mode) + spiram_phy = LiteSPIPHY(spiram_pads, module, device=self.platform.device, default_divisor=default_divisor, rate=rate) + self.add_module(name=f"{name}_phy", module=spiram_phy) + + # Core. + self.check_if_exists(f"{name}_mmap") + spiram_core = LiteSPI(spiram_phy, mmap_endianness=self.cpu.endianness, with_mmap_write=True, **kwargs) + self.add_module(name=f"{name}_core", module=spiram_core) + spiram_region = SoCRegion(origin=self.mem_map.get(name, None), size=module.total_size) + + # Create Wishbone Slave. + wb_spiram = wishbone.Interface(data_width=32, address_width=32, addressing="word") + self.bus.add_slave(name=name, slave=wb_spiram, region=spiram_region) + self.comb += spiram_core.mmap.offset.eq(self.bus.regions.get(name, None).origin) + + # L2 Cache + if l2_cache_size != 0: + # Insert L2 cache inbetween Wishbone bus and LiteSPI + l2_cache_size = max(l2_cache_size, int(2*32/8)) # Use minimal size if lower + l2_cache_size = 2**int(log2(l2_cache_size)) # Round to nearest power of 2 + l2_cache = wishbone.Cache( + cachesize = l2_cache_size//4, + master = wb_spiram, + slave = spiram_core.bus, + reverse = l2_cache_reverse) + if l2_cache_full_memory_we: + l2_cache = FullMemoryWE()(l2_cache) + self.l2_cache = l2_cache + self.add_config("L2_SIZE", l2_cache_size) + else: + self.submodules += wishbone.Converter(wb_spiram, spiram_core.bus) # Constants. self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq) diff --git a/litex/soc/software/bios/helpers.c b/litex/soc/software/bios/helpers.c index 0f8e9bfab..6b384ec0e 100644 --- a/litex/soc/software/bios/helpers.c +++ b/litex/soc/software/bios/helpers.c @@ -18,18 +18,24 @@ extern unsigned int _ftext, _edata_rom; #define NUMBER_OF_BYTES_ON_A_LINE 16 void dump_bytes(unsigned int *ptr, int count, unsigned long addr) { - char *data = (char *)ptr; + uint32_t *dptr = (uint32_t *)ptr; + char data[NUMBER_OF_BYTES_ON_A_LINE]; int line_bytes = 0, i = 0; + fputs("Memory dump:", stdout); while (count > 0) { line_bytes = (count > NUMBER_OF_BYTES_ON_A_LINE)? NUMBER_OF_BYTES_ON_A_LINE : count; + for (i = 0; i < line_bytes; i+=4){ + *((uint32_t*)&data[i]) = *(dptr++); + } + printf("\n0x%08lx ", addr); for (i = 0; i < line_bytes; i++) - printf("%02x ", *(unsigned char *)(data+i)); + printf("%02x ", (unsigned char)data[i]); for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++) printf(" "); @@ -37,16 +43,15 @@ void dump_bytes(unsigned int *ptr, int count, unsigned long addr) printf(" "); for (i = 0; i 0x7e)) + if ((data[i] < 0x20) || (data[i] > 0x7e)) printf("."); else - printf("%c", *(data+i)); + printf("%c", data[i]); } for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++) printf(" "); - data += (char)line_bytes; count -= line_bytes; addr += line_bytes; }