upsilon/gateware/rtl/waveform/bram_interface_sim.cpp

113 lines
2.5 KiB
C++
Raw Normal View History

2023-06-15 12:24:35 -04:00
/* Copyright 2023 (C) Peter McGoron
* This file is a part of Upsilon, a free and open source software project.
* For license terms, refer to the files in `doc/copying` in the Upsilon
* source distribution.
*/
2023-01-22 23:43:51 -05:00
#include <limits>
#include <cstdlib>
#include <random>
#include <unistd.h>
#include <verilated.h>
#include "Vbram_interface_sim.h"
2023-01-27 17:27:20 -05:00
#include "../testbench.hpp"
2023-01-22 23:43:51 -05:00
std::array<uint32_t, WORD_AMNT> ram_refresh_data;
TB<Vbram_interface_sim> *tb;
2023-01-22 23:43:51 -05:00
static void handle_read_aa(size_t &i) {
2023-01-27 17:27:20 -05:00
if (tb->mod.word_ok) {
uint32_t val = sign_extend(tb->mod.word, 20);
tb->mod.word_next = 0;
2023-01-22 23:43:51 -05:00
my_assert(val == ram_refresh_data[i], "received value %x (%zu) != %x", i, val, ram_refresh_data[i]);
i++;
2023-01-27 17:27:20 -05:00
} else if (!tb->mod.word_next) {
tb->mod.word_next = 1;
2023-01-22 23:43:51 -05:00
}
}
/* Test reading the entire array twice. */
static void test_aa_read_1() {
size_t ind = 0;
2023-01-27 17:27:20 -05:00
tb->mod.word_next = 1;
tb->run_clock();
while (!tb->mod.word_last || (tb->mod.word_last && tb->mod.word_next)) {
2023-01-22 23:43:51 -05:00
handle_read_aa(ind);
2023-01-27 17:27:20 -05:00
tb->run_clock();
2023-01-22 23:43:51 -05:00
}
my_assert(ind == WORD_AMNT, "read value %zu != %d\n", ind, WORD_AMNT);
2023-01-27 17:27:20 -05:00
tb->mod.word_next = 1;
tb->run_clock();
2023-01-22 23:43:51 -05:00
ind = 0;
2023-01-27 17:27:20 -05:00
while (!tb->mod.word_last || (tb->mod.word_last && tb->mod.word_next)) {
2023-01-22 23:43:51 -05:00
handle_read_aa(ind);
2023-01-27 17:27:20 -05:00
tb->run_clock();
2023-01-22 23:43:51 -05:00
}
my_assert(ind == WORD_AMNT, "second read value %zu != %d\n", ind, WORD_AMNT);
}
2023-01-22 23:58:38 -05:00
static void test_aa_read_interrupted() {
size_t ind = 0;
2023-01-27 17:27:20 -05:00
tb->mod.word_next = 1;
tb->run_clock();
2023-01-22 23:58:38 -05:00
for (int i = 0; i < 100; i++) {
handle_read_aa(ind);
2023-01-27 17:27:20 -05:00
tb->run_clock();
my_assert(!tb->mod.word_last, "too many reads");
2023-01-22 23:58:38 -05:00
}
2023-01-27 17:27:20 -05:00
tb->mod.word_rst = 1;
tb->run_clock();
tb->mod.word_rst = 0;
tb->run_clock();
2023-01-22 23:58:38 -05:00
test_aa_read_1();
}
2023-01-22 23:47:12 -05:00
static void refresh_data() {
2023-02-25 16:17:04 -05:00
for (size_t i = 0; i < WORD_AMNT; i++) {
uint32_t val = mask_extend(rand(), 20);
ram_refresh_data[i] = val;
tb->mod.backing_store[i*2] = val & 0xFFFF;
tb->mod.backing_store[i*2+1] = val >> 16;
2023-01-22 23:43:51 -05:00
}
2023-01-27 17:27:20 -05:00
tb->mod.refresh_start = 1;
tb->mod.start_addr = 0x12340;
2023-01-27 17:27:20 -05:00
tb->run_clock();
2023-01-22 23:43:51 -05:00
while (!tb->mod.refresh_finished)
2023-01-27 17:27:20 -05:00
tb->run_clock();
2023-01-22 23:43:51 -05:00
2023-01-27 17:27:20 -05:00
tb->mod.refresh_start = 0;
tb->run_clock();
2023-01-22 23:43:51 -05:00
2023-01-22 23:47:12 -05:00
}
2023-01-27 17:27:20 -05:00
int main(int argc, char *argv[]) {
Verilated::commandArgs(argc, argv);
2023-01-27 17:27:20 -05:00
Verilated::traceEverOn(true);
Verilated::fatalOnError(false);
2023-03-14 11:42:41 -04:00
tb = new TB<Vbram_interface_sim>();
2023-05-10 14:35:57 -04:00
tb->mod.rst_L = 1;
2023-01-22 23:47:12 -05:00
2023-01-22 23:58:38 -05:00
printf("test basic read/write\n");
2023-01-22 23:47:12 -05:00
refresh_data();
2023-05-10 14:35:57 -04:00
printf("\ttest 1\n");
2023-01-22 23:47:12 -05:00
test_aa_read_1();
refresh_data();
2023-05-10 14:35:57 -04:00
printf("\ttest 2\n");
2023-01-22 23:43:51 -05:00
test_aa_read_1();
2023-01-22 23:58:38 -05:00
printf("test resetting\n");
test_aa_read_interrupted();
2023-01-22 23:43:51 -05:00
printf("ok\n");
return 0;
}