aboutsummaryrefslogtreecommitdiffstats
path: root/tests/write_read.cpp
blob: be02e5790de4decc150149c4dcd0a002ca1d6ad6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <verilated.h>
#include "Vsimtop.h"

Vsimtop *sim;
int return_value = 0;

#ifdef SPI_MASTER_SS
# define SET_SS(mod, v)
#else
# define SET_SS(mod,v) ((mod)->ss = (v))
#endif

uint32_t main_time = 0;

double sc_time_stamp() {
	return main_time;
}

static void progress() {
	sim->eval();
	main_time++;
	sim->clk = !sim->clk;
	sim->eval();
	main_time++;
	sim->clk = !sim->clk;
}

static void progress_n(int f) {
	for (int i = 0; i < f; i++)
		progress();
}

static void test_reset_pin(void) {
	sim->rst_L = 0;
	progress();
	sim->rdy = 1;
	sim->activate = 1;

	progress_n(200);
	assert(!sim->master_finished);
	sim->rst_L = 1;
}

static void test_cross_transfer(unsigned m2s, unsigned s2m) {
#ifndef SPI_MASTER_NO_WRITE
	sim->master_to_slave = m2s;
#endif
#ifndef SPI_MASTER_NO_READ
	sim->slave_to_master = s2m;
#endif

	sim->rst_L = 1;
	progress();
	SET_SS(sim, 1);
	sim->rdy = 1;
	sim->activate = 1;
	progress();

	while (!sim->master_finished)
		progress();

	progress_n(5);
	sim->activate = 0;
	SET_SS(sim, 0);
	sim->rdy = 0;
	progress_n(5);

	if (sim->err) {
		printf("slave error\n");
		return_value = 1;
	}

#ifndef SPI_MASTER_NO_WRITE
	if (sim->master_to_slave != sim->from_master) {
		printf("(m2s) %lx != %lx\n", sim->master_to_slave, sim->from_master);
		return_value = 1;
	}
#endif

#ifndef SPI_MASTER_NO_READ
	if (sim->slave_to_master != sim->from_slave) {
		printf("(m2s) %lx != %lx\n", sim->slave_to_master, sim->from_slave);
		return_value = 1;
	}
#endif
}

static void test_interrupted(unsigned m2s, unsigned s2m) {
	sim->rst_L = 1;
	progress();

	sim->rdy = 1;
	sim->activate = 1;
	progress_n(6);
	sim->rst_L = 0;
	progress_n(100);
	sim->rst_L = 1;
	test_cross_transfer(m2s, s2m);
}

int main(int argc, char **argv) {
	Verilated::commandArgs(argc, argv);
	Verilated::traceEverOn(true);

	sim = new Vsimtop;
	SET_SS(sim, 0);
	sim->clk = 0;
	sim->activate = 0;
	sim->rdy = 0;

	test_reset_pin();
	test_cross_transfer(0b101010101010101010101010, 0b010101010101010101010101);
	test_cross_transfer(0b110011001100110011001100, 0b001100110011001100110011);
	test_reset_pin();

	for (int i = 0; i < 10000; i++) {
		unsigned m2s = rand() & ((1 << WID) - 1);
		unsigned s2m = rand() & ((1 << WID) - 1);
		if (i % (((rand() + 1) % 32) + 1) == 0)
			test_interrupted(m2s, s2m);
		else
			test_cross_transfer(m2s, s2m);
		if (i % (((rand() + 1) % 64) + 1) == 0)
			test_reset_pin();

	}

	sim->final();
	delete sim;
	return return_value;
}