From 1fb78fa558e1d461852e8e750944773803e486a7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 28 Aug 2020 17:57:59 +0200 Subject: [PATCH] bench: cleanup, do more testing on 7-series. --- bench/arty.py | 4 +- bench/common.py | 316 +++++++++++++++++++++++++++++++--------------- bench/genesys2.py | 7 +- bench/kc705.py | 9 +- bench/kcu105.py | 33 +++-- 5 files changed, 236 insertions(+), 133 deletions(-) diff --git a/bench/arty.py b/bench/arty.py index e33a57a..5d3f070 100755 --- a/bench/arty.py +++ b/bench/arty.py @@ -119,9 +119,7 @@ def main(): freq_max = 150e6, freq_step = 1e6, vco_freq = soc.crg.main_pll.compute_config()["vco"], - bios_filename = "build/arty/software/bios/bios.bin", - bios_timeout = 10, - ) + bios_filename = "build/arty/software/bios/bios.bin") if __name__ == "__main__": main() diff --git a/bench/common.py b/bench/common.py index 378bcc2..4d51fe5 100644 --- a/bench/common.py +++ b/bench/common.py @@ -4,141 +4,247 @@ # Copyright (c) 2020 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause +# PLL Helpers -------------------------------------------------------------------------------------- + +class ClkReg1: + def __init__(self, value=0): + self.unpack(value) + + def unpack(self, value): + self.low_time = (value >> 0) & (2**6 - 1) + self.high_time = (value >> 6) & (2**6 - 1) + self.reserved = (value >> 12) & (2**1 - 1) + self.phase_mux = (value >> 13) & (2**3 - 1) + + def pack(self): + value = (self.low_time << 0) + value |= (self.high_time << 6) + value |= (self.reserved << 12) + value |= (self.phase_mux << 13) + return value + + def __repr__(self): + s = "ClkReg1:\n" + s += " low_time: {:d}\n".format(self.low_time) + s += " high_time: {:d}\n".format(self.high_time) + s += " reserved: {:d}\n".format(self.reserved) + s += " phase_mux: {:d}".format(self.phase_mux) + return s + +class ClkReg2: + def __init__(self, value=0): + self.unpack(value) + + def unpack(self, value): + self.delay_time = (value >> 0) & (2**6 - 1) + self.no_count = (value >> 6) & (2**1 - 1) + self.edge = (value >> 7) & (2**1 - 1) + self.mx = (value >> 8) & (2**2 - 1) + self.frac_wf_r = (value >> 10) & (2**1 - 1) + self.frac_en = (value >> 11) & (2**1 - 1) + self.frac = (value >> 12) & (2**3 - 1) + self.reserved = (value >> 15) & (2**1 - 1) + + def pack(self): + value = (self.delay_time << 0) + value |= (self.no_count << 6) + value |= (self.edge << 7) + value |= (self.mx << 8) + value |= (self.frac_wf_r << 10) + value |= (self.frac_en << 11) + value |= (self.frac << 12) + value |= (self.reserved << 15) + return value + + def __repr__(self): + s = "ClkReg2:\n" + s += " delay_time: {:d}\n".format(self.delay_time) + s += " no_count: {:d}\n".format(self.no_count) + s += " edge: {:d}\n".format(self.edge) + s += " mx: {:d}\n".format(self.mx) + s += " frac_wf_r: {:d}\n".format(self.frac_wf_r) + s += " frac_en: {:d}\n".format(self.frac_en) + s += " frac: {:d}\n".format(self.frac) + s += " reserved: {:d}".format(self.reserved) + return s + +class S7PLL: + def __init__(self, bus): + self.bus = bus + + def reset(self): + self.bus.regs.crg_main_pll_drp_reset.write(1) + + def read(self, adr): + self.bus.regs.crg_main_pll_drp_adr.write(adr) + self.bus.regs.crg_main_pll_drp_read.write(1) + return self.bus.regs.crg_main_pll_drp_dat_r.read() + + def write(self, adr, value): + self.bus.regs.crg_main_pll_drp_adr.write(adr) + self.bus.regs.crg_main_pll_drp_dat_w.write(value) + self.bus.regs.crg_main_pll_drp_write.write(1) + + +class USPLL: + def __init__(self, bus): + self.bus = bus + + def reset(self): + self.bus.regs.crg_pll_drp_reset.write(1) + + def read(self, adr): + self.bus.regs.crg_pll_drp_adr.write(adr) + self.bus.regs.crg_pll_drp_read.write(1) + return self.bus.regs.crg_pll_drp_dat_r.read() + + def write(self, adr, value): + self.bus.regs.crg_pll_drp_adr.write(adr) + self.bus.regs.crg_pll_drp_dat_w.write(value) + self.bus.regs.crg_pll_drp_write.write(1) + +# Bench Controller --------------------------------------------------------------------------------- + +class BenchController: + def __init__(self, bus): + self.bus = bus + + def reboot(self): + self.bus.regs.ctrl_reset.write(1) + + def load_rom(self, filename): + from litex.soc.integration.common import get_mem_data + rom_data = get_mem_data(filename, "little") + for i, data in enumerate(rom_data): + self.bus.write(self.bus.mems.rom.base + 4*i, data) + # Bench Test --------------------------------------------------------------------------------------- -def s7_bench_test(freq_min, freq_max, freq_step, vco_freq, bios_filename, bios_timeout=5): +def s7_bench_test(freq_min, freq_max, freq_step, vco_freq, bios_filename, bios_timeout=10): import time from litex import RemoteClient - wb = RemoteClient() - wb.open() + bus = RemoteClient() + bus.open() # # # - class SoCCtrl: - @staticmethod - def reboot(): - wb.regs.ctrl_reset.write(1) - - @staticmethod - def load_rom(filename): - from litex.soc.integration.common import get_mem_data - rom_data = get_mem_data(filename, "little") - for i, data in enumerate(rom_data): - wb.write(wb.mems.rom.base + 4*i, data) - - class ClkReg1: - def __init__(self, value=0): - self.unpack(value) - - def unpack(self, value): - self.low_time = (value >> 0) & (2**6 - 1) - self.high_time = (value >> 6) & (2**6 - 1) - self.reserved = (value >> 12) & (2**1 - 1) - self.phase_mux = (value >> 13) & (2**3 - 1) - - def pack(self): - value = (self.low_time << 0) - value |= (self.high_time << 6) - value |= (self.reserved << 12) - value |= (self.phase_mux << 13) - return value - - def __repr__(self): - s = "ClkReg1:\n" - s += " low_time: {:d}\n".format(self.low_time) - s += " high_time: {:d}\n".format(self.high_time) - s += " reserved: {:d}\n".format(self.reserved) - s += " phase_mux: {:d}".format(self.phase_mux) - return s - - class ClkReg2: - def __init__(self, value = 0): - self.unpack(value) - - def unpack(self, value): - self.delay_time = (value >> 0) & (2**6 - 1) - self.no_count = (value >> 6) & (2**1 - 1) - self.edge = (value >> 7) & (2**1 - 1) - self.mx = (value >> 8) & (2**2 - 1) - self.frac_wf_r = (value >> 10) & (2**1 - 1) - self.frac_en = (value >> 11) & (2**1 - 1) - self.frac = (value >> 12) & (2**3 - 1) - self.reserved = (value >> 15) & (2**1 - 1) - - def pack(self): - value = (self.delay_time << 0) - value |= (self.no_count << 6) - value |= (self.edge << 7) - value |= (self.mx << 8) - value |= (self.frac_wf_r << 10) - value |= (self.frac_en << 11) - value |= (self.frac << 12) - value |= (self.reserved << 15) - return value - - def __repr__(self): - s = "ClkReg2:\n" - s += " delay_time: {:d}\n".format(self.delay_time) - s += " no_count: {:d}\n".format(self.no_count) - s += " edge: {:d}\n".format(self.edge) - s += " mx: {:d}\n".format(self.mx) - s += " frac_wf_r: {:d}\n".format(self.frac_wf_r) - s += " frac_en: {:d}\n".format(self.frac_en) - s += " frac: {:d}\n".format(self.frac) - s += " reserved: {:d}".format(self.reserved) - return s - - class S7PLL: - def reset(self): - wb.regs.crg_main_pll_drp_reset.write(1) - - def read(self, adr): - wb.regs.crg_main_pll_drp_adr.write(adr) - wb.regs.crg_main_pll_drp_read.write(1) - return wb.regs.crg_main_pll_drp_dat_r.read() - - def write(self, adr, value): - wb.regs.crg_main_pll_drp_adr.write(adr) - wb.regs.crg_main_pll_drp_dat_w.write(value) - wb.regs.crg_main_pll_drp_write.write(1) - - # # # - - ctrl = SoCCtrl() + # Load BIOS and reboot SoC + ctrl = BenchController(bus) ctrl.load_rom(bios_filename) ctrl.reboot() - s7pll = S7PLL() - - clkout0_clkreg1 = ClkReg1(s7pll.read(0x08)) + # PLL/ClkReg + s7pll = S7PLL(bus) + clkout0_clkreg1 = ClkReg1(s7pll.read(0x8)) + # Run calibration from freq_min to freq_max and log BIOS output. + print("-"*80) + print("Running calibration; sys_clk from {:3.3f}MHz to {:3.2f}MHz (step: {:3.2f}MHz)".format( + freq_min/1e6, freq_max/1e6, freq_step/1e6)) + print("-"*80) + print("") tested_vco_divs = [] for clk_freq in range(int(freq_min), int(freq_max), int(freq_step)): + # Compute VCO divider, skip if already tested. vco_div = int(vco_freq/clk_freq) if vco_div in tested_vco_divs: continue tested_vco_divs.append(vco_div) - print("Reconfig Main PLL to {}MHz...".format(vco_freq/vco_div/1e6)) + + print("-"*40) + print("sys_clk = {}MHz...".format(vco_freq/vco_div/1e6)) + print("-"*40) + + # Reconfigure PLL to change sys_clk clkout0_clkreg1.high_time = vco_div//2 + vco_div%2 clkout0_clkreg1.low_time = vco_div//2 s7pll.write(0x08, clkout0_clkreg1.pack()) - print("Measuring sys_clk...") + # Measure/verify sys_clk duration = 5e-1 - start = wb.regs.crg_sys_clk_counter.read() + start = bus.regs.crg_sys_clk_counter.read() time.sleep(duration) - end = wb.regs.crg_sys_clk_counter.read() - print("sys_clk: {:3.2f}MHz".format((end-start)/(1e6*duration))) + end = bus.regs.crg_sys_clk_counter.read() + print("Measured sys_clk: {:3.2f}MHz.".format((end-start)/(1e6*duration))) + # Reboot SoC and log BIOS output + print("-"*40) print("Reboot SoC and get BIOS log...") + print("-"*40) ctrl.reboot() start = time.time() while (time.time() - start) < bios_timeout: - if wb.regs.uart_xover_rxfull.read(): - for c in wb.read(wb.regs.uart_xover_rxtx.addr, 16, burst="fixed"): + if bus.regs.uart_xover_rxfull.read(): + for c in bus.read(bus.regs.uart_xover_rxtx.addr, 16, burst="fixed"): print("{:c}".format(c), end="") + print("") # # # - wb.close() + bus.close() + +# Bench Test --------------------------------------------------------------------------------------- + +def us_bench_test(freq_min, freq_max, freq_step, vco_freq, bios_filename, bios_timeout=10): + import time + from litex import RemoteClient + + bus = RemoteClient() + bus.open() + + # # # + + # Load BIOS and reboot SoC + ctrl = BenchController(bus) + #ctrl.load_rom(bios_filename) + ctrl.reboot() + + # PLL/ClkReg + uspll = USPLL(bus) + clkout0_clkreg1 = ClkReg1(uspll.read(0x8)) + + # Run calibration from freq_min to freq_max and log BIOS output. + print("-"*80) + print("Running calibration; sys_clk from {:3.3f}MHz to {:3.2f}MHz (step: {:3.2f}MHz)".format( + freq_min/1e6, freq_max/1e6, freq_step/1e6)) + print("-"*80) + print("") + tested_vco_divs = [] + for clk_freq in range(int(freq_min), int(freq_max), int(freq_step)): + # Compute VCO divider, skip if already tested. + vco_div = int(vco_freq/(4*clk_freq)) + if vco_div in tested_vco_divs: + continue + tested_vco_divs.append(vco_div) + + print("-"*40) + print("sys_clk = {}MHz...".format(vco_freq/4/vco_div/1e6)) + print("-"*40) + + # Reconfigure PLL to change sys_clk + clkout0_clkreg1.high_time = vco_div//2 + vco_div%2 + clkout0_clkreg1.low_time = vco_div//2 + uspll.write(0x08, clkout0_clkreg1.pack()) + + # Measure/verify sys_clk + duration = 5e-1 + start = bus.regs.crg_sys_clk_counter.read() + time.sleep(duration) + end = bus.regs.crg_sys_clk_counter.read() + print("Measured sys_clk: {:3.2f}MHz.".format((end-start)/(1e6*duration))) + + # Reboot SoC and log BIOS output + print("-"*40) + print("Reboot SoC and get BIOS log...") + print("-"*40) + ctrl.reboot() + start = time.time() + while (time.time() - start) < bios_timeout: + if bus.regs.uart_xover_rxempty.read() == 0: + for c in bus.read(bus.regs.uart_xover_rxtx.addr, 1, burst="fixed"): + print("{:c}".format(c), end="") + print("") + # # # + + bus.close() diff --git a/bench/genesys2.py b/bench/genesys2.py index 41b8d07..feb5b82 100755 --- a/bench/genesys2.py +++ b/bench/genesys2.py @@ -75,8 +75,7 @@ class BenchSoC(SoCCore): self.submodules.ddrphy = s7ddrphy.K7DDRPHY(platform.request("ddram"), memtype = "DDR3", nphases = 4, - sys_clk_freq = sys_clk_freq, - cmd_latency = 1) + sys_clk_freq = sys_clk_freq) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, @@ -118,9 +117,7 @@ def main(): freq_max = 180e6, freq_step = 1e6, vco_freq = soc.crg.main_pll.compute_config()["vco"], - bios_filename = "build/genesys2/software/bios/bios.bin", - bios_timeout = 10, - ) + bios_filename = "build/genesys2/software/bios/bios.bin") if __name__ == "__main__": main() diff --git a/bench/kc705.py b/bench/kc705.py index ef904ac..274309d 100755 --- a/bench/kc705.py +++ b/bench/kc705.py @@ -75,8 +75,7 @@ class BenchSoC(SoCCore): self.submodules.ddrphy = s7ddrphy.K7DDRPHY(platform.request("ddram"), memtype = "DDR3", nphases = 4, - sys_clk_freq = sys_clk_freq, - cmd_latency = 1) + sys_clk_freq = sys_clk_freq) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, @@ -85,7 +84,7 @@ class BenchSoC(SoCCore): ) # UARTBone --------------------------------------------------------------------------------- - self.add_uartbone(name="serial", clk_freq=100e6, baudrate=1e6, cd="uart") + self.add_uartbone(name="serial", clk_freq=100e6, baudrate=500e3, cd="uart") # Leds ------------------------------------------------------------------------------------- from litex.soc.cores.led import LedChaser @@ -118,9 +117,7 @@ def main(): freq_max = 180e6, freq_step = 1e6, vco_freq = soc.crg.main_pll.compute_config()["vco"], - bios_filename = "build/kc705/software/bios/bios.bin", - bios_timeout = 10, - ) + bios_filename = "build/kc705/software/bios/bios.bin") if __name__ == "__main__": main() diff --git a/bench/kcu105.py b/bench/kcu105.py index 767f09e..421cc3c 100755 --- a/bench/kcu105.py +++ b/bench/kcu105.py @@ -24,22 +24,22 @@ from litedram.phy import usddrphy # CRG ---------------------------------------------------------------------------------------------- -class _CRG(Module): +class _CRG(Module, AutoCSR): def __init__(self, platform, sys_clk_freq): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) self.clock_domains.cd_pll4x = ClockDomain(reset_less=True) self.clock_domains.cd_clk200 = ClockDomain() - self.clock_domains.cd_uart = ClockDomain() + self.clock_domains.cd_uart = ClockDomain() # # # self.submodules.pll = pll = USMMCM(speedgrade=-2) self.comb += pll.reset.eq(platform.request("cpu_reset")) pll.register_clkin(platform.request("clk125"), 125e6) - pll.create_clkout(self.cd_pll4x, sys_clk_freq*4, buf=None, with_reset=False) - pll.create_clkout(self.cd_clk200, 200e6, with_reset=False) - pll.create_clkout(self.cd_uart, 100e6) + pll.create_clkout(self.cd_pll4x, sys_clk_freq*4, buf=None, with_reset=False) + pll.create_clkout(self.cd_clk200, 200e6, with_reset=False) + pll.create_clkout(self.cd_uart, 100e6) pll.expose_drp() self.specials += [ @@ -61,7 +61,7 @@ class _CRG(Module): # Bench SoC ---------------------------------------------------------------------------------------- class BenchSoC(SoCCore): - def __init__(self, sys_clk_freq=int(125e6)): + def __init__(self, sys_clk_freq=int(175e6)): platform = kcu105.Platform() # SoCCore ---------------------------------------------------------------------------------- @@ -79,18 +79,17 @@ class BenchSoC(SoCCore): self.submodules.ddrphy = usddrphy.USDDRPHY(platform.request("ddram"), memtype = "DDR4", sys_clk_freq = sys_clk_freq, - iodelay_clk_freq = 200e6, - cmd_latency = 1) + iodelay_clk_freq = 200e6) self.add_csr("ddrphy") self.add_sdram("sdram", - phy = self.ddrphy, - module = EDY4016A(sys_clk_freq, "1:4"), - origin = self.mem_map["main_ram"], - size = 0x40000000, + phy = self.ddrphy, + module = EDY4016A(sys_clk_freq, "1:4"), + origin = self.mem_map["main_ram"], + size = 0x40000000, ) # UARTBone --------------------------------------------------------------------------------- - self.add_uartbone(name="serial", clk_freq=100e6, baudrate=1e6, cd="uart") + self.add_uartbone(name="serial", clk_freq=100e6, baudrate=115200, cd="uart") # Leds ------------------------------------------------------------------------------------- self.submodules.leds = LedChaser( @@ -116,7 +115,13 @@ def main(): prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".bit")) if args.test: - raise NotImplementedError + from common import us_bench_test + us_bench_test( + freq_min = 60e6, + freq_max = 180e6, + freq_step = 1e6, + vco_freq = soc.crg.pll.compute_config()["vco"], + bios_filename = "build/kcu105/software/bios/bios.bin") if __name__ == "__main__": main()