diff --git a/litex/build/lattice/diamond.py b/litex/build/lattice/diamond.py index cf44d096b..9e6ee704d 100644 --- a/litex/build/lattice/diamond.py +++ b/litex/build/lattice/diamond.py @@ -4,7 +4,9 @@ # License: BSD import os +import re import sys +import math import subprocess import shutil @@ -40,7 +42,7 @@ def _format_lpf(signame, pin, others, resname): return "\n".join(lpf) -def _build_lpf(named_sc, named_pc, build_name): +def _build_lpf(named_sc, named_pc, clocks, vns, build_name): lpf = [] lpf.append("BLOCK RESETPATHS;") lpf.append("BLOCK ASYNCPATHS;") @@ -51,7 +53,16 @@ def _build_lpf(named_sc, named_pc, build_name): else: lpf.append(_format_lpf(sig, pins[0], others, resname)) if named_pc: - lpf.append("\n\n".join(named_pc)) + lpf.append("\n".join(named_pc)) + + # Note: .lpf is only used post-synthesis, Synplify constraints clocks by default to 200MHz. + for clk, period in clocks.items(): + clk_name = vns.get_name(clk) + lpf.append("FREQUENCY {} \"{}\" {} MHz;".format( + "PORT" if clk_name in [name for name, _, _, _ in named_sc] else "NET", + clk_name, + str(1e3/period))) + tools.write_to_file(build_name + ".lpf", "\n".join(lpf)) # Project (.tcl) ----------------------------------------------------------------------------------- @@ -67,13 +78,15 @@ def _build_tcl(device, sources, vincpaths, build_name): "-synthesis \"synplify\"" ])) + def tcl_path(path): return path.replace("\\", "/") + # Add include paths - vincpath = ';'.join(map(lambda x: x.replace('\\', '/'), vincpaths)) + vincpath = ";".join(map(lambda x: tcl_path(x), vincpaths)) tcl.append("prj_impl option {include path} {\"" + vincpath + "\"}") # Add sources for filename, language, library in sources: - tcl.append("prj_src add \"" + filename.replace("\\", "/") + "\" -work " + library) + tcl.append("prj_src add \"{}\" -work {}".format(tcl_path(filename), library)) # Set top level tcl.append("prj_impl option top \"{}\"".format(build_name)) @@ -89,6 +102,10 @@ def _build_tcl(device, sources, vincpaths, build_name): tcl.append("prj_run Export -impl impl -task Bitgen") if _produces_jedec(device): tcl.append("prj_run Export -impl impl -task Jedecgen") + + # Close project + tcl.append("prj_project close") + tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) # Script ------------------------------------------------------------------------------------------- @@ -130,6 +147,34 @@ def _run_script(script): if subprocess.call(shell + [script]) != 0: raise OSError("Subprocess failed") +def _check_timing(build_name): + lines = open("impl/{}_impl.par".format(build_name), "r").readlines() + runs = [None, None] + for i in range(len(lines)-1): + if lines[i].startswith("Level/") and lines[i+1].startswith("Cost "): + runs[0] = i + 2 + if lines[i].startswith("* : Design saved.") and runs[0] is not None: + runs[1] = i + break + assert all(map(lambda x: x is not None, runs)) + + p = re.compile(r"(^\s*\S+\s+\*?\s+[0-9]+\s+)(\S+)(\s+\S+\s+)(\S+)(\s+.*)") + for l in lines[runs[0]:runs[1]]: + m = p.match(l) + if m is None: continue + limit = 1e-8 + setup = m.group(2) + hold = m.group(4) + # If there were no freq constraints in lpf, ratings will be dashed. + # results will likely be terribly unreliable, so bail + assert not setup == hold == "-", "No timing constraints were provided" + setup, hold = map(float, (setup, hold)) + if setup > limit and hold > limit: + # At least one run met timing + # XXX is this necessarily the run from which outputs will be used? + return + raise Exception("Failed to meet timing") + # LatticeDiamondToolchain -------------------------------------------------------------------------- class LatticeDiamondToolchain: @@ -149,12 +194,14 @@ class LatticeDiamondToolchain: special_overrides = common.lattice_ecp5_special_overrides def __init__(self): + self.clocks = {} self.false_paths = set() # FIXME: use it def build(self, platform, fragment, build_dir = "build", build_name = "top", run = True, + timingstrict = True, **kwargs): # Create build directory @@ -175,7 +222,7 @@ class LatticeDiamondToolchain: platform.add_source(v_file) # Generate design constraints file (.lpf) - _build_lpf(named_sc, named_pc, build_name) + _build_lpf(named_sc, named_pc, self.clocks, v_output.ns, build_name) # Generate design script file (.tcl) _build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name) @@ -186,6 +233,8 @@ class LatticeDiamondToolchain: # Run if run: _run_script(script) + if timingstrict: + _check_timing(build_name) os.chdir(cwd) @@ -193,9 +242,12 @@ class LatticeDiamondToolchain: def add_period_constraint(self, platform, clk, period): clk.attr.add("keep") - # TODO: handle differential clk - platform.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format( - freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) + period = math.floor(period*1e3)/1e3 # round to lowest picosecond + if clk in self.clocks: + if period != self.clocks[clk]: + raise ValueError("Clock already constrained to {:.2f}ns, new constraint to {:.2f}ns" + .format(self.clocks[clk], period)) + self.clocks[clk] = period def add_false_path_constraint(self, platform, from_, to): from_.attr.add("keep") diff --git a/litex/build/lattice/icestorm.py b/litex/build/lattice/icestorm.py index 2822a9b53..059363c04 100644 --- a/litex/build/lattice/icestorm.py +++ b/litex/build/lattice/icestorm.py @@ -93,32 +93,35 @@ def parse_device(device): _build_template = [ "yosys -l {build_name}.rpt {build_name}.ys", "nextpnr-ice40 --json {build_name}.json --pcf {build_name}.pcf --asc {build_name}.txt \ - --pre-pack {build_name}_pre_pack.py --{architecture} --package {package} {timefailarg}", + --pre-pack {build_name}_pre_pack.py --{architecture} --package {package} {timefailarg} {ignoreloops} --seed {seed}", "icepack -s {build_name}.txt {build_name}.bin" ] -def _build_script(build_template, build_name, architecture, package, timingstrict): +def _build_script(build_template, build_name, architecture, package, timingstrict, ignoreloops, seed): if sys.platform in ("win32", "cygwin"): script_ext = ".bat" - build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" + script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" fail_stmt = " || exit /b" else: script_ext = ".sh" - build_script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" + script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" fail_stmt = "" for s in build_template: s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early. - build_script_contents += s_fail.format( + script_contents += s_fail.format( build_name = build_name, architecture = architecture, package = package, timefailarg = "--timing-allow-fail" if not timingstrict else "", - fail_stmt = fail_stmt) + ignoreloops = "--ignore-loops" if ignoreloops else "", + fail_stmt = fail_stmt, + seed = seed) - build_script_file = "build_" + build_name + script_ext - tools.write_to_file(build_script_file, build_script_contents,force_unix=False) - return build_script_file + script_file = "build_" + build_name + script_ext + tools.write_to_file(script_file, script_contents, force_unix=False) + + return script_file def _run_script(script): if sys.platform in ("win32", "cygwin"): @@ -158,6 +161,8 @@ class LatticeIceStormToolchain: synth_opts = "", run = True, timingstrict = False, + ignoreloops = False, + seed = 1, **kwargs): # Create build directory @@ -190,7 +195,7 @@ class LatticeIceStormToolchain: (family, architecture, package) = parse_device(platform.device) # Generate build script - script = _build_script(self.build_template, build_name, architecture, package, timingstrict) + script = _build_script(self.build_template, build_name, architecture, package, timingstrict, ignoreloops, seed) # Run if run: @@ -207,3 +212,18 @@ class LatticeIceStormToolchain: raise ValueError("Clock already constrained to {:.2f}ns, new constraint to {:.2f}ns" .format(self.clocks[clk], period)) self.clocks[clk] = period + +def icestorm_args(parser): + parser.add_argument("--nextpnr-timingstrict", action="store_true", + help="fail if timing not met, i.e., do NOT pass '--timing-allow-fail' to nextpnr") + parser.add_argument("--nextpnr-ignoreloops", action="store_true", + help="ignore combinational loops in timing analysis, i.e. pass '--ignore-loops' to nextpnr") + parser.add_argument("--nextpnr-seed", default=1, type=int, + help="seed to pass to nextpnr") + +def icestorm_argdict(args): + return { + "timingstrict": args.nextpnr_timingstrict, + "ignoreloops": args.nextpnr_ignoreloops, + "seed": args.nextpnr_seed, + } \ No newline at end of file diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index bc908a942..3c4eded4b 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -117,11 +117,11 @@ nextpnr_ecp5_architectures = { _build_template = [ "yosys -l {build_name}.rpt {build_name}.ys", "nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config \ - --{architecture} --package {package} --speed {speed_grade} {timefailarg} {ignoreloops}", - "ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit --bootaddr={bootaddr}" + --{architecture} --package {package} --speed {speed_grade} {timefailarg} {ignoreloops} --seed {seed}", + "ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit" ] -def _build_script(source, build_template, build_name, architecture, package, speed_grade, timingstrict, ignoreloops, bootaddr): +def _build_script(source, build_template, build_name, architecture, package, speed_grade, timingstrict, ignoreloops, bootaddr, seed): if sys.platform in ("win32", "cygwin"): script_ext = ".bat" script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" @@ -141,7 +141,8 @@ def _build_script(source, build_template, build_name, architecture, package, spe timefailarg = "--timing-allow-fail" if not timingstrict else "", ignoreloops = "--ignore-loops" if ignoreloops else "", bootaddr = bootaddr, - fail_stmt = fail_stmt) + fail_stmt = fail_stmt, + seed = seed) script_file = "build_" + build_name + script_ext tools.write_to_file(script_file, script_contents, force_unix=False) @@ -188,6 +189,7 @@ class LatticeTrellisToolchain: timingstrict = False, ignoreloops = False, bootaddr = 0, + seed = 1, **kwargs): # Create build directory @@ -219,8 +221,7 @@ class LatticeTrellisToolchain: # Generate build script script = _build_script(False, self.build_template, build_name, architecture, package, - speed_grade, timingstrict, ignoreloops, bootaddr) - + speed_grade, timingstrict, ignoreloops, bootaddr, seed) # Run if run: _run_script(script) @@ -248,11 +249,14 @@ def trellis_args(parser): help="ignore combinational loops in timing analysis, i.e. pass '--ignore-loops' to nextpnr") parser.add_argument("--ecppack-bootaddr", default=0, help="Set boot address for next image, i.e. pass '--bootaddr xxx' to ecppack") + parser.add_argument("--nextpnr-seed", default=1, type=int, + help="seed to pass to nextpnr") def trellis_argdict(args): return { "nowidelut": args.yosys_nowidelut, "timingstrict": args.nextpnr_timingstrict, "ignoreloops": args.nextpnr_ignoreloops, - "bootaddr": args.ecppack_bootaddr + "bootaddr": args.ecppack_bootaddr, + "seed": args.nextpnr_seed, } diff --git a/litex/soc/cores/cpu/__init__.py b/litex/soc/cores/cpu/__init__.py index bc1067123..4c273e50b 100644 --- a/litex/soc/cores/cpu/__init__.py +++ b/litex/soc/cores/cpu/__init__.py @@ -88,6 +88,7 @@ CPU_VARIANTS = { "minimal" : ["min",], "lite" : ["light", "zephyr", "nuttx"], "standard": [None, "std"], + "imac": [], "full": [], "linux" : [], "linuxd" : [], diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index dc267ce98..9b981506f 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -25,6 +25,8 @@ CPU_VARIANTS = { "lite+debug": "VexRiscv_LiteDebug", "standard": "VexRiscv", "standard+debug": "VexRiscv_Debug", + "imac": "VexRiscv_IMAC", + "imac+debug": "VexRiscv_IMACDebug", "full": "VexRiscv_Full", "full+debug": "VexRiscv_FullDebug", "linux": "VexRiscv_Linux", @@ -47,6 +49,8 @@ GCC_FLAGS = { "lite+debug": "-march=rv32i -mabi=ilp32", "standard": "-march=rv32im -mabi=ilp32", "standard+debug": "-march=rv32im -mabi=ilp32", + "imac": "-march=rv32imac -mabi=ilp32", + "imac+debug": "-march=rv32imac -mabi=ilp32", "full": "-march=rv32im -mabi=ilp32", "full+debug": "-march=rv32im -mabi=ilp32", "linux": "-march=rv32ima -mabi=ilp32", diff --git a/litex/soc/cores/led.py b/litex/soc/cores/led.py new file mode 100644 index 000000000..54c1d2a08 --- /dev/null +++ b/litex/soc/cores/led.py @@ -0,0 +1,34 @@ +# This file is Copyright (c) 2020 Florent Kermarrec +# License: BSD + +from migen import * +from migen.genlib.misc import WaitTimer + +from litex.soc.interconnect.csr import * + +# Led Chaser --------------------------------------------------------------------------------------- + +_CHASER_MODE = 0 +_CONTROL_MODE = 1 + +class LedChaser(Module, AutoCSR): + def __init__(self, pads, sys_clk_freq, period=1e0): + self._out = CSRStorage(len(pads), description="Led Output(s) Control.") + + # # # + + n = len(pads) + chaser = Signal(n) + mode = Signal(reset=_CHASER_MODE) + timer = WaitTimer(int(period*sys_clk_freq/(2*n))) + self.submodules += timer + self.comb += timer.wait.eq(~timer.done) + self.sync += If(timer.done, chaser.eq(Cat(~chaser[-1], chaser))) + self.sync += If(self._out.re, mode.eq(_CONTROL_MODE)) + self.comb += [ + If(mode == _CONTROL_MODE, + pads.eq(self._out.storage) + ).Else( + pads.eq(chaser) + ) + ] diff --git a/litex/soc/cores/uart.py b/litex/soc/cores/uart.py index e6315016d..07fdac305 100644 --- a/litex/soc/cores/uart.py +++ b/litex/soc/cores/uart.py @@ -239,11 +239,13 @@ class UART(Module, AutoCSR, UARTInterface): self.ev.rx.trigger.eq(~rx_fifo.source.valid) ] -class UARTWishboneBridge(WishboneStreamingBridge): +class UARTBone(WishboneStreamingBridge): def __init__(self, pads, clk_freq, baudrate=115200): self.submodules.phy = RS232PHY(pads, clk_freq, baudrate) WishboneStreamingBridge.__init__(self, self.phy, clk_freq) +class UARTWishboneBridge(UARTBone): pass + # UART Multiplexer --------------------------------------------------------------------------------- class UARTMultiplexer(Module): diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 8d5107625..b2e492968 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -282,7 +282,8 @@ class SoCBusHandler(Module): return is_io # Add Master/Slave ----------------------------------------------------------------------------- - def add_adapter(self, name, interface): + def add_adapter(self, name, interface, direction="m2s"): + assert direction in ["m2s", "s2m"] if interface.data_width != self.data_width: self.logger.info("{} Bus {} from {}-bit to {}-bit.".format( colorer(name), @@ -290,7 +291,11 @@ class SoCBusHandler(Module): colorer(interface.data_width), colorer(self.data_width))) new_interface = wishbone.Interface(data_width=self.data_width) - self.submodules += wishbone.Converter(interface, new_interface) + if direction == "m2s": + converter = wishbone.Converter(master=interface, slave=new_interface) + if direction == "s2m": + converter = wishbone.Converter(master=new_interface, slave=interface) + self.submodules += converter return new_interface else: return interface @@ -304,7 +309,7 @@ class SoCBusHandler(Module): colorer("already declared", color="red"))) self.logger.error(self) raise - master = self.add_adapter(name, master) + master = self.add_adapter(name, master, "m2s") self.masters[name] = master self.logger.info("{} {} as Bus Master.".format( colorer(name, color="underline"), @@ -336,7 +341,7 @@ class SoCBusHandler(Module): colorer("already declared", color="red"))) self.logger.error(self) raise - slave = self.add_adapter(name, slave) + slave = self.add_adapter(name, slave, "s2m") self.slaves[name] = slave self.logger.info("{} {} as Bus Slave.".format( colorer(name, color="underline"), @@ -753,8 +758,8 @@ class SoC(Module): def add_csr_bridge(self, origin): self.submodules.csr_bridge = wishbone2csr.WB2CSR( bus_csr = csr_bus.Interface( - address_width = self.csr.address_width, - data_width = self.csr.data_width)) + address_width = self.csr.address_width, + data_width = self.csr.data_width)) csr_size = 2**(self.csr.address_width + 2) csr_region = SoCRegion(origin=origin, size=csr_size, cached=False) self.bus.add_slave("csr", self.csr_bridge.wishbone, csr_region) @@ -926,13 +931,9 @@ class LiteXSoC(SoC): if name == "stub": self.comb += self.uart.sink.ready.eq(1) - # Bridge - elif name in ["bridge"]: - self.submodules.uart = uart.UARTWishboneBridge( - pads = self.platform.request("serial"), - clk_freq = self.sys_clk_freq, - baudrate = baudrate) - self.bus.add_master(name="uart_bridge", master=self.uart.wishbone) + # UARTBone / Bridge + elif name in ["uartbone", "bridge"]: + self.add_uartbone(baudrate=baudrate) # Crossover elif name in ["crossover"]: @@ -986,6 +987,15 @@ class LiteXSoC(SoC): else: self.add_constant("UART_POLLING") + # Add UARTbone --------------------------------------------------------------------------------- + def add_uartbone(self, name="serial", baudrate=115200): + from litex.soc.cores import uart + self.submodules.uartbone = uart.UARTBone( + pads = self.platform.request(name), + clk_freq = self.sys_clk_freq, + baudrate = baudrate) + self.bus.add_master(name="uartbone", master=self.uartbone.wishbone) + # Add SDRAM ------------------------------------------------------------------------------------ def add_sdram(self, name, phy, module, origin, size=None, l2_cache_size = 8192, @@ -1133,7 +1143,7 @@ class LiteXSoC(SoC): eth_tx_clk) # Add Etherbone -------------------------------------------------------------------------------- - def add_etherbone(self, name="etherbone", phy=None, + def add_etherbone(self, name="etherbone", phy=None, clock_domain=None, mac_address = 0x10e2d5000000, ip_address = "192.168.1.50", udp_port = 1234): @@ -1146,9 +1156,21 @@ class LiteXSoC(SoC): mac_address = mac_address, ip_address = ip_address, clk_freq = self.clk_freq) + if clock_domain is not None: # FIXME: Could probably be avoided. + ethcore = ClockDomainsRenamer("eth_tx")(ethcore) self.submodules += ethcore + + # Clock domain renaming + if clock_domain is not None: # FIXME: Could probably be avoided. + self.clock_domains.cd_etherbone = ClockDomain("etherbone") + self.comb += self.cd_etherbone.clk.eq(ClockSignal(clock_domain)) + self.comb += self.cd_etherbone.rst.eq(ResetSignal(clock_domain)) + clock_domain = "etherbone" + else: + clock_domain = "sys" + # Etherbone - etherbone = LiteEthEtherbone(ethcore.udp, udp_port) + etherbone = LiteEthEtherbone(ethcore.udp, udp_port, cd=clock_domain) setattr(self.submodules, name, etherbone) self.add_wb_master(etherbone.wishbone.bus) # Timing constraints @@ -1168,10 +1190,10 @@ class LiteXSoC(SoC): # Add SPI Flash -------------------------------------------------------------------------------- def add_spi_flash(self, name="spiflash", mode="4x", dummy_cycles=None, clk_freq=None): assert dummy_cycles is not None # FIXME: Get dummy_cycles from SPI Flash - assert mode in ["4x"] # FIXME: Add 1x support. + assert mode in ["1x", "4x"] if clk_freq is None: clk_freq = self.clk_freq/2 # FIXME: Get max clk_freq from SPI Flash spiflash = SpiFlash( - pads = self.platform.request(name + mode), + pads = self.platform.request(name if mode == "1x" else name + mode), dummy = dummy_cycles, div = ceil(self.clk_freq/clk_freq), with_bitbang = True, diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index f61555a31..68499ad2b 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -61,6 +61,11 @@ class SoCCore(LiteXSoC): } def __init__(self, platform, clk_freq, + # Bus parameters + bus_standard = "wishbone", + bus_data_width = 32, + bus_address_width = 32, + bus_timeout = 1e6, # CPU parameters cpu_type = "vexriscv", cpu_reset_address = None, @@ -92,18 +97,15 @@ class SoCCore(LiteXSoC): with_timer = True, # Controller parameters with_ctrl = True, - # Wishbone parameters - with_wishbone = True, - wishbone_timeout_cycles = 1e6, # Others **kwargs): # New LiteXSoC class ---------------------------------------------------------------------------- LiteXSoC.__init__(self, platform, clk_freq, - bus_standard = "wishbone", - bus_data_width = 32, - bus_address_width = 32, - bus_timeout = wishbone_timeout_cycles, + bus_standard = bus_standard, + bus_data_width = bus_data_width, + bus_address_width = bus_address_width, + bus_timeout = bus_timeout, bus_reserved_regions = {}, csr_data_width = csr_data_width, @@ -127,9 +129,6 @@ class SoCCore(LiteXSoC): cpu_reset_address = None if cpu_reset_address == "None" else cpu_reset_address cpu_variant = cpu.check_format_cpu_variant(cpu_variant) - if not with_wishbone: - self.mem_map["csr"] = 0x00000000 - self.cpu_type = cpu_type self.cpu_variant = cpu_variant self.cpu_cls = cpu_cls @@ -141,9 +140,6 @@ class SoCCore(LiteXSoC): self.csr_data_width = csr_data_width - self.with_wishbone = with_wishbone - self.wishbone_timeout_cycles = wishbone_timeout_cycles - self.wb_slaves = {} # Modules instances ------------------------------------------------------------------------ @@ -187,9 +183,8 @@ class SoCCore(LiteXSoC): if with_timer: self.add_timer(name="timer0") - # Add Wishbone to CSR bridge - if with_wishbone: - self.add_csr_bridge(self.mem_map["csr"]) + # Add CSR bridge + self.add_csr_bridge(self.mem_map["csr"]) # Methods -------------------------------------------------------------------------------------- diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index e7e754c65..81f48f488 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -191,6 +191,13 @@ void sdrwlon(void) sdram_dfii_pi0_address_write(DDRX_MR1 | (1 << 7)); sdram_dfii_pi0_baddress_write(1); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); + +#ifdef SDRAM_PHY_DDR4_RDIMM + sdram_dfii_pi0_address_write((DDRX_MR1 | (1 << 7)) ^ 0x2BF8) ; + sdram_dfii_pi0_baddress_write(1 ^ 0xF); + command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); +#endif + ddrphy_wlevel_en_write(1); } @@ -199,6 +206,13 @@ void sdrwloff(void) sdram_dfii_pi0_address_write(DDRX_MR1); sdram_dfii_pi0_baddress_write(1); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); + +#ifdef SDRAM_PHY_DDR4_RDIMM + sdram_dfii_pi0_address_write(DDRX_MR1 ^ 0x2BF8); + sdram_dfii_pi0_baddress_write(1 ^ 0xF); + command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); +#endif + ddrphy_wlevel_en_write(0); } @@ -903,7 +917,7 @@ static void memspeed(void) end = timer0_value_read(); read_speed = (8*MEMTEST_DATA_SIZE*(CONFIG_CLOCK_FREQUENCY/1000000))/(start - end); - printf("Memspeed Writes: %dMbps Reads: %dMbps\n", write_speed, read_speed); + printf("Memspeed Writes: %ldMbps Reads: %ldMbps\n", write_speed, read_speed); } int memtest(void)