Merge pull request #1560 from antmicro/msieron/sdram-hw-test
Add `sdram_hw_test` command
This commit is contained in:
commit
13fcbca4dc
|
@ -89,6 +89,46 @@ static void sdram_bist_handler(int nb_params, char **params)
|
|||
define_command(sdram_bist, sdram_bist_handler, "Run SDRAM Build-In Self-Test", LITEDRAM_CMDS);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Command "sdram_hw_test"
|
||||
*
|
||||
* Run SDRAM HW-accelerated memtest
|
||||
*
|
||||
*/
|
||||
#if defined(CSR_SDRAM_GENERATOR_BASE) && defined(CSR_SDRAM_CHECKER_BASE)
|
||||
static void sdram_hw_test_handler(int nb_params, char **params)
|
||||
{
|
||||
char *c;
|
||||
uint64_t origin;
|
||||
uint64_t size;
|
||||
uint64_t burst_length = 1;
|
||||
if (nb_params < 2) {
|
||||
printf("sdram_hw_test <origin> <size> [<burst_length>]");
|
||||
return;
|
||||
}
|
||||
origin = strtoull(params[0], &c, 0);
|
||||
if (*c != 0) {
|
||||
printf("Incorrect origin");
|
||||
return;
|
||||
}
|
||||
size = strtoull(params[1], &c, 0);
|
||||
if (*c != 0) {
|
||||
printf("Incorrect size");
|
||||
return;
|
||||
}
|
||||
if (nb_params > 2) {
|
||||
burst_length = strtoull(params[2], &c, 0);
|
||||
if (*c != 0) {
|
||||
printf("Incorrect burst length");
|
||||
return;
|
||||
}
|
||||
}
|
||||
int errors = sdram_hw_test(origin, size, burst_length);
|
||||
printf("%d errors found\n", errors);
|
||||
}
|
||||
define_command(sdram_hw_test, sdram_hw_test_handler, "Run SDRAM HW-accelerated memtest", LITEDRAM_CMDS);
|
||||
#endif
|
||||
|
||||
#ifdef CSR_DDRPHY_RDPHASE_ADDR
|
||||
/**
|
||||
* Command "sdram_force_rdphase"
|
||||
|
|
|
@ -5,31 +5,22 @@
|
|||
#if defined(CSR_SDRAM_GENERATOR_BASE) && defined(CSR_SDRAM_CHECKER_BASE)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <uart.h>
|
||||
#include <time.h>
|
||||
#include <console.h>
|
||||
|
||||
#include <liblitedram/bist.h>
|
||||
#include <liblitedram/utils.h>
|
||||
#include <generated/sdram_phy.h>
|
||||
|
||||
#define SDRAM_TEST_BASE 0x00000000
|
||||
#define SDRAM_TEST_DATA_BYTES (CSR_SDRAM_DFII_PI0_RDDATA_SIZE*4)
|
||||
#define SDRAM_TEST_DATA_BYTES (SDRAM_PHY_DFI_DATABITS / 8 * SDRAM_PHY_PHASES)
|
||||
|
||||
uint32_t wr_ticks;
|
||||
uint32_t wr_length;
|
||||
uint32_t rd_ticks;
|
||||
uint32_t rd_length;
|
||||
uint32_t rd_errors;
|
||||
|
||||
__attribute__((unused)) static void cdelay(int i)
|
||||
{
|
||||
#ifndef CONFIG_BIOS_NO_DELAYS
|
||||
while(i > 0) {
|
||||
__asm__ volatile(CONFIG_CPU_NOP);
|
||||
i--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static uint32_t wr_ticks = 0;
|
||||
static uint32_t wr_length = 0;
|
||||
static uint32_t rd_ticks = 0;
|
||||
static uint32_t rd_length = 0;
|
||||
static uint32_t rd_errors = 0;
|
||||
|
||||
static uint32_t pseudo_random_bases[128] = {
|
||||
0x000e4018,0x0003338d,0x00233429,0x001f589d,
|
||||
|
@ -66,65 +57,59 @@ static uint32_t pseudo_random_bases[128] = {
|
|||
0x00027e36,0x000e51ae,0x002e7627,0x00275c9f,
|
||||
};
|
||||
|
||||
void sdram_bist_loop(uint32_t loop, uint32_t burst_length, uint32_t random) {
|
||||
static void sdram_bist_write(uint32_t base, uint32_t length) {
|
||||
/* Prepare write */
|
||||
sdram_generator_reset_write(1);
|
||||
sdram_generator_random_write(1); /* Random data */
|
||||
sdram_generator_base_write(base);
|
||||
sdram_generator_end_write(base + length);
|
||||
sdram_generator_length_write(length);
|
||||
|
||||
/* Start write */
|
||||
sdram_generator_start_write(1);
|
||||
|
||||
/* Wait write */
|
||||
while(sdram_generator_done_read() == 0);
|
||||
}
|
||||
|
||||
static void sdram_bist_read(uint32_t base, uint32_t length) {
|
||||
/* Prepare read */
|
||||
sdram_checker_reset_write(1);
|
||||
sdram_checker_random_write(1); /* Random data */
|
||||
sdram_checker_base_write(base);
|
||||
sdram_checker_end_write(base + length);
|
||||
sdram_checker_length_write(length);
|
||||
|
||||
/* Start read */
|
||||
|
||||
sdram_checker_start_write(1);
|
||||
/* Wait read */
|
||||
while(sdram_checker_done_read() == 0);
|
||||
}
|
||||
|
||||
static void sdram_bist_loop(uint32_t loop, uint32_t burst_length, uint32_t random) {
|
||||
int i;
|
||||
uint32_t base;
|
||||
uint32_t length;
|
||||
length = burst_length*SDRAM_TEST_DATA_BYTES;
|
||||
length = burst_length * SDRAM_TEST_DATA_BYTES;
|
||||
|
||||
rd_errors = 0;
|
||||
for(i=0; i<128; i++) {
|
||||
for (i = 0; i < 128; i++) {
|
||||
if (random)
|
||||
base = SDRAM_TEST_BASE + pseudo_random_bases[(i+loop)%128]*SDRAM_TEST_DATA_BYTES;
|
||||
else
|
||||
base = SDRAM_TEST_BASE + ((i+loop)%128)*SDRAM_TEST_DATA_BYTES;
|
||||
if (i == 0) {
|
||||
/* Prepare first write */
|
||||
sdram_generator_reset_write(1);
|
||||
sdram_generator_reset_write(0);
|
||||
sdram_generator_random_write(1); /* Random data */
|
||||
sdram_generator_base_write(base);
|
||||
sdram_generator_end_write(base + length);
|
||||
sdram_generator_length_write(length);
|
||||
cdelay(100);
|
||||
}
|
||||
/* Start write */
|
||||
sdram_generator_start_write(1);
|
||||
/* Prepare next read */
|
||||
sdram_checker_reset_write(1);
|
||||
sdram_checker_reset_write(0);
|
||||
sdram_checker_random_write(1); /* Random data */
|
||||
sdram_checker_base_write(base);
|
||||
sdram_checker_end_write(base + length);
|
||||
sdram_checker_length_write(length);
|
||||
cdelay(100);
|
||||
/* Wait write */
|
||||
while(sdram_generator_done_read() == 0);
|
||||
|
||||
sdram_bist_write(base, length);
|
||||
/* Get write results */
|
||||
wr_length += length;
|
||||
wr_ticks += sdram_generator_ticks_read();
|
||||
/* Start read */
|
||||
sdram_checker_start_write(1);
|
||||
if (i != 127) {
|
||||
if (random)
|
||||
base = SDRAM_TEST_BASE + pseudo_random_bases[(i+1+loop)%128]*SDRAM_TEST_DATA_BYTES;
|
||||
else
|
||||
base = SDRAM_TEST_BASE + ((i+1+loop)%128)*SDRAM_TEST_DATA_BYTES;
|
||||
/* Prepare next write */
|
||||
sdram_generator_reset_write(1);
|
||||
sdram_generator_reset_write(0);
|
||||
sdram_generator_random_write(1); /* Random data */
|
||||
sdram_generator_base_write(base);
|
||||
sdram_generator_end_write(base + length);
|
||||
sdram_generator_length_write(length);
|
||||
cdelay(100);
|
||||
}
|
||||
/* Wait read */
|
||||
while(sdram_checker_done_read() == 0);
|
||||
|
||||
sdram_bist_read(base, length);
|
||||
/* Get read results */
|
||||
rd_length += length;
|
||||
rd_ticks += sdram_checker_ticks_read();
|
||||
rd_errors += sdram_checker_errors_read();
|
||||
rd_length += length;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,19 +123,14 @@ static uint32_t compute_speed_mibs(uint32_t length, uint32_t ticks) {
|
|||
void sdram_bist(uint32_t burst_length, uint32_t random)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t total_length;
|
||||
uint64_t total_length;
|
||||
uint32_t total_errors;
|
||||
|
||||
printf("Starting SDRAM BIST with burst_length=%d and random=%d\n", burst_length, random);
|
||||
printf("Starting SDRAM BIST with burst_length=%" PRIu32 " and random=%" PRIu32 "\n", burst_length, random);
|
||||
|
||||
i = 0;
|
||||
total_length = 0;
|
||||
total_errors = 0;
|
||||
for(;;) {
|
||||
/* Exit on key pressed */
|
||||
if (readchar_nonblock())
|
||||
break;
|
||||
|
||||
for (i = 0; !readchar_nonblock(); i++) { /* Exit on key pressed */
|
||||
/* Bist loop */
|
||||
sdram_bist_loop(i, burst_length, random);
|
||||
|
||||
|
@ -159,11 +139,12 @@ void sdram_bist(uint32_t burst_length, uint32_t random)
|
|||
printf("WR-SPEED(MiB/s) RD-SPEED(MiB/s) TESTED(MiB) ERRORS\n");
|
||||
}
|
||||
if (i%100 == 100-1) {
|
||||
printf("%15u %15u %12u %12u\n",
|
||||
compute_speed_mibs(wr_length, wr_ticks),
|
||||
compute_speed_mibs(rd_length, rd_ticks),
|
||||
total_length/(1024*1024),
|
||||
total_errors);
|
||||
printf("%15" PRIu32 " %15" PRIu32 "%12" PRIu64 "%12" PRIu32 "\n",
|
||||
compute_speed_mibs(wr_length, wr_ticks),
|
||||
compute_speed_mibs(rd_length, rd_ticks),
|
||||
total_length/(1024*1024),
|
||||
total_errors);
|
||||
|
||||
total_length += wr_length;
|
||||
total_errors += rd_errors;
|
||||
|
||||
|
@ -174,8 +155,55 @@ void sdram_bist(uint32_t burst_length, uint32_t random)
|
|||
rd_ticks = 0;
|
||||
rd_errors = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int sdram_hw_test(uint64_t origin, uint64_t size, uint64_t burst_length) {
|
||||
uint64_t burst_size = SDRAM_TEST_DATA_BYTES * burst_length;
|
||||
uint64_t old_burst_size = burst_size;
|
||||
int errors = 0;
|
||||
|
||||
uint64_t supported_memory = sdram_get_supported_memory();
|
||||
|
||||
if (origin >= supported_memory) {
|
||||
printf("Selected origin out of memory bounds! Supported memory: ");
|
||||
print_size(supported_memory);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (origin + size > supported_memory) {
|
||||
printf("Test would go out of memory bounds. Clipping size to memory end: ");
|
||||
print_size(supported_memory);
|
||||
printf("\n");
|
||||
size = supported_memory - origin;
|
||||
}
|
||||
|
||||
for (uint64_t address = origin; address < origin + size; address += burst_size) {
|
||||
if (address + burst_size > size) {
|
||||
old_burst_size = burst_size;
|
||||
burst_size = size - address;
|
||||
}
|
||||
|
||||
if (burst_size < SDRAM_TEST_DATA_BYTES || old_burst_size < burst_size)
|
||||
break;
|
||||
|
||||
sdram_bist_write(address, burst_size);
|
||||
|
||||
sdram_bist_read(address, burst_size);
|
||||
errors += sdram_checker_errors_read();
|
||||
|
||||
print_progress(" SDRAM HW test:", origin, address - origin + burst_size);
|
||||
}
|
||||
|
||||
if (burst_size < SDRAM_TEST_DATA_BYTES || old_burst_size < burst_size) {
|
||||
printf("\nTest would go out of memory bounds. Finished early at the end: ");
|
||||
print_size(supported_memory);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#ifndef __SDRAM_BIST_H
|
||||
#define __SDRAM_BIST_H
|
||||
|
||||
void sdram_bist_loop(uint32_t loop, uint32_t burst_length, uint32_t random);
|
||||
#include <stdint.h>
|
||||
|
||||
void sdram_bist(uint32_t burst_length, uint32_t random);
|
||||
int sdram_hw_test(uint64_t origin, uint64_t size, uint64_t burst_length);
|
||||
|
||||
#endif /* __SDRAM_BIST_H */
|
||||
|
|
|
@ -149,6 +149,7 @@ class SimSoC(SoCCore):
|
|||
sdram_data_width = 32,
|
||||
sdram_spd_data = None,
|
||||
sdram_verbosity = 0,
|
||||
with_bist = False,
|
||||
with_i2c = False,
|
||||
with_sdcard = False,
|
||||
with_spi_flash = False,
|
||||
|
@ -195,7 +196,8 @@ class SimSoC(SoCCore):
|
|||
module = sdram_module,
|
||||
l2_cache_size = kwargs.get("l2_size", 8192),
|
||||
l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128),
|
||||
l2_cache_reverse = False
|
||||
l2_cache_reverse = False,
|
||||
with_bist = with_bist
|
||||
)
|
||||
if sdram_init != []:
|
||||
# Skip SDRAM test to avoid corrupting pre-initialized contents.
|
||||
|
@ -373,6 +375,7 @@ def sim_args(parser):
|
|||
parser.add_argument("--sdram-init", default=None, help="SDRAM init file (.bin or .json).")
|
||||
parser.add_argument("--sdram-from-spd-dump", default=None, help="Generate SDRAM module based on data from SPD EEPROM dump.")
|
||||
parser.add_argument("--sdram-verbosity", default=0, help="Set SDRAM checker verbosity.")
|
||||
parser.add_argument("--with-bist", action="store_true", help="Enable SDRAM BIST modules.")
|
||||
|
||||
# Ethernet /Etherbone.
|
||||
parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.")
|
||||
|
@ -476,6 +479,7 @@ def main():
|
|||
# SoC ------------------------------------------------------------------------------------------
|
||||
soc = SimSoC(
|
||||
with_sdram = args.with_sdram,
|
||||
with_bist = args.with_bist,
|
||||
with_ethernet = args.with_ethernet,
|
||||
ethernet_phy_model = args.ethernet_phy_model,
|
||||
with_etherbone = args.with_etherbone,
|
||||
|
|
Loading…
Reference in New Issue