aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/xilinx/tests/bram1_tb.v
blob: e75dfe31d815bccfcdbc5215c00a7952fdb8069f (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
module bram1_tb #(
	parameter ABITS = 8, DBITS = 8, TRANSP = 0
);
	reg clk;
	reg [ABITS-1:0] WR_ADDR;
	reg [DBITS-1:0] WR_DATA;
	reg WR_EN;
	reg [ABITS-1:0] RD_ADDR;
	wire [DBITS-1:0] RD_DATA;

	localparam [ABITS-1:0] INIT_ADDR_0 = 1234;
	localparam [ABITS-1:0] INIT_ADDR_1 = 4321;
	localparam [ABITS-1:0] INIT_ADDR_2 = 2**ABITS-1;
	localparam [ABITS-1:0] INIT_ADDR_3 = (2**ABITS-1) / 2;

	localparam [DBITS-1:0] INIT_DATA_0 = 128'h 51e152a7300e309ccb8cd06d34558f49;
	localparam [DBITS-1:0] INIT_DATA_1 = 128'h 07b1fe94a530ddf3027520f9d23ab43e;
	localparam [DBITS-1:0] INIT_DATA_2 = 128'h 3cedc6de43ef3f607af3193658d0eb0b;
	localparam [DBITS-1:0] INIT_DATA_3 = 128'h f6bc5514a8abf1e2810df966bcc13b46;

	bram1 #(
		// .ABITS(ABITS),
		// .DBITS(DBITS),
		// .TRANSP(TRANSP)
	) uut  (
		.clk    (clk    ),
		.WR_ADDR(WR_ADDR),
		.WR_DATA(WR_DATA),
		.WR_EN  (WR_EN  ),
		.RD_ADDR(RD_ADDR),
		.RD_DATA(RD_DATA)
	);

	reg [63:0] xorshift64_state = 64'd88172645463325252 ^ (ABITS << 24) ^ (DBITS << 16) ^ (TRANSP << 8);

	task xorshift64_next;
		begin
		// see page 4 of Marsaglia, George (July 2003). "Xorshift RNGs". Journal of Statistical Software 8 (14).
		xorshift64_state = xorshift64_state ^ (xorshift64_state << 13);
		xorshift64_state = xorshift64_state ^ (xorshift64_state >>  7);
		xorshift64_state = xorshift64_state ^ (xorshift64_state << 17);
		end
	endtask

	reg [ABITS-1:0] randaddr1;
	reg [ABITS-1:0] randaddr2;
	reg [ABITS-1:0] randaddr3;

	function [31:0] getaddr(input [3:0] n);
		begin
			case (n)
				0: getaddr = 0;
				1: getaddr = 2**ABITS-1;
				2: getaddr = 'b101 << (ABITS / 3);
				3: getaddr = 'b101 << (2*ABITS / 3);
				4: getaddr = 'b11011 << (ABITS / 4);
				5: getaddr = 'b11011 << (2*ABITS / 4);
				6: getaddr = 'b11011 << (3*ABITS / 4);
				7: getaddr = randaddr1;
				8: getaddr = randaddr2;
				9: getaddr = randaddr3;
				default: begin
					getaddr = 1 << (2*n-16);
					if (!getaddr) getaddr = xorshift64_state;
				end
			endcase
		end
	endfunction

	reg [DBITS-1:0] memory [0:2**ABITS-1];
	reg [DBITS-1:0] expected_rd, expected_rd_masked;

	event error;
	reg error_ind = 0;

	integer i, j;
	initial begin
		// $dumpfile("testbench.vcd");
		// $dumpvars(0, bram1_tb);

		memory[INIT_ADDR_0] = INIT_DATA_0;
		memory[INIT_ADDR_1] = INIT_DATA_1;
		memory[INIT_ADDR_2] = INIT_DATA_2;
		memory[INIT_ADDR_3] = INIT_DATA_3;

		xorshift64_next;
		xorshift64_next;
		xorshift64_next;
		xorshift64_next;

		randaddr1 = xorshift64_state;
		xorshift64_next;

		randaddr2 = xorshift64_state;
		xorshift64_next;

		randaddr3 = xorshift64_state;
		xorshift64_next;

		clk <= 0;
		for (i = 0; i < 512; i = i+1) begin
			if (i == 0) begin
				WR_EN <= 0;
				RD_ADDR <= INIT_ADDR_0;
			end else
			if (i == 1) begin
				WR_EN <= 0;
				RD_ADDR <= INIT_ADDR_1;
			end else
			if (i == 2) begin
				WR_EN <= 0;
				RD_ADDR <= INIT_ADDR_2;
			end else
			if (i == 3) begin
				WR_EN <= 0;
				RD_ADDR <= INIT_ADDR_3;
			end else begin
				if (DBITS > 64)
					WR_DATA <= (xorshift64_state << (DBITS-64)) ^ xorshift64_state;
				else
					WR_DATA <= xorshift64_state;
				xorshift64_next;
				WR_ADDR <= getaddr(i < 256 ? i[7:4] : xorshift64_state[63:60]);
				xorshift64_next;
				RD_ADDR <= getaddr(i < 256 ? i[3:0] : xorshift64_state[59:56]);
				WR_EN <= xorshift64_state[55];
				xorshift64_next;
			end

			#1; clk <= 1;
			#1; clk <= 0;

			if (TRANSP) begin
				if (WR_EN) memory[WR_ADDR] = WR_DATA;
				expected_rd = memory[RD_ADDR];
			end else begin
				expected_rd = memory[RD_ADDR];
				if (WR_EN) memory[WR_ADDR] = WR_DATA;
			end

			for (j = 0; j < DBITS; j = j+1)
				expected_rd_masked[j] = expected_rd[j] !== 1'bx ? expected_rd[j] : RD_DATA[j];

			$display("#OUT# %3d | WA=%x WD=%x WE=%x | RA=%x RD=%x (%x) | %s", i, WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd, expected_rd_masked === RD_DATA ? "ok" : "ERROR");
			if (expected_rd_masked !== RD_DATA) begin -> error; error_ind = ~error_ind; end
		end
	end
endmodule
n>(name) + 1; strlcpy(ELFNOTE_NAME(n), name, l); n->namesz = l; n->descsz = descsz; n->type = type; } static int sizeof_note(const char *name, int descsz) { return (sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(name)+1) + ELFNOTE_ALIGN(descsz)); } #define kexec_get(x) kexec_get_##x #endif static int kexec_get(reserve)(xen_kexec_range_t *range) { if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) { range->start = kexec_crash_area.start; range->size = kexec_crash_area.size; } else range->start = range->size = 0; return 0; } static int kexec_get(xen)(xen_kexec_range_t *range) { #ifdef CONFIG_X86_64 range->start = xenheap_phys_start; #else range->start = virt_to_maddr(_start); #endif range->size = (unsigned long)xenheap_phys_end - (unsigned long)range->start; return 0; } static int kexec_get(cpu)(xen_kexec_range_t *range) { int nr = range->nr; int nr_bytes = 0; if ( nr < 0 || nr >= num_present_cpus() ) return -EINVAL; nr_bytes += sizeof_note("CORE", sizeof(ELF_Prstatus)); nr_bytes += sizeof_note("Xen", sizeof(crash_xen_core_t)); /* The Xen info note is included in CPU0's range. */ if ( nr == 0 ) nr_bytes += sizeof_note("Xen", sizeof(crash_xen_info_t)); if ( per_cpu(crash_notes, nr) == NULL ) { Elf_Note *note; note = per_cpu(crash_notes, nr) = xmalloc_bytes(nr_bytes); if ( note == NULL ) return -ENOMEM; /* Setup CORE note. */ setup_note(note, "CORE", NT_PRSTATUS, sizeof(ELF_Prstatus)); /* Setup Xen CORE note. */ note = ELFNOTE_NEXT(note); setup_note(note, "Xen", XEN_ELFNOTE_CRASH_REGS, sizeof(crash_xen_core_t)); if (nr == 0) { /* Setup system wide Xen info note. */ xen_crash_note = note = ELFNOTE_NEXT(note); setup_note(note, "Xen", XEN_ELFNOTE_CRASH_INFO, sizeof(crash_xen_info_t)); } } range->start = __pa((unsigned long)per_cpu(crash_notes, nr)); range->size = nr_bytes; return 0; } static int kexec_get(range)(XEN_GUEST_HANDLE(void) uarg) { xen_kexec_range_t range; int ret = -EINVAL; if ( unlikely(copy_from_guest(&range, uarg, 1)) ) return -EFAULT; switch ( range.range ) { case KEXEC_RANGE_MA_CRASH: ret = kexec_get(reserve)(&range); break; case KEXEC_RANGE_MA_XEN: ret = kexec_get(xen)(&range); break; case KEXEC_RANGE_MA_CPU: ret = kexec_get(cpu)(&range); break; } if ( ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)) ) return -EFAULT; return ret; } #ifndef COMPAT static int kexec_load_get_bits(int type, int *base, int *bit) { switch ( type ) { case KEXEC_TYPE_DEFAULT: *base = KEXEC_IMAGE_DEFAULT_BASE; *bit = KEXEC_FLAG_DEFAULT_POS; break; case KEXEC_TYPE_CRASH: *base = KEXEC_IMAGE_CRASH_BASE; *bit = KEXEC_FLAG_CRASH_POS; break; default: return -1; } return 0; } #endif static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg) { xen_kexec_load_t load; xen_kexec_image_t *image; int base, bit, pos; int ret = 0; if ( unlikely(copy_from_guest(&load, uarg, 1)) ) return -EFAULT; if ( kexec_load_get_bits(load.type, &base, &bit) ) return -EINVAL; pos = (test_bit(bit, &kexec_flags) != 0); /* Load the user data into an unused image */ if ( op == KEXEC_CMD_kexec_load ) { image = &kexec_image[base + !pos]; BUG_ON(test_bit((base + !pos), &kexec_flags)); /* must be free */ #ifndef COMPAT memcpy(image, &load.image, sizeof(*image)); #else XLAT_kexec_image(image, &load.image); #endif if ( !(ret = machine_kexec_load(load.type, base + !pos, image)) ) { /* Set image present bit */ set_bit((base + !pos), &kexec_flags); /* Make new image the active one */ change_bit(bit, &kexec_flags); } } /* Unload the old image if present and load successful */ if ( ret == 0 && !test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags) ) { if ( test_and_clear_bit((base + pos), &kexec_flags) ) { image = &kexec_image[base + pos]; machine_kexec_unload(load.type, base + pos, image); } } return ret; } #ifndef COMPAT static int kexec_exec(XEN_GUEST_HANDLE(void) uarg) { xen_kexec_exec_t exec; xen_kexec_image_t *image; int base, bit, pos; if ( unlikely(copy_from_guest(&exec, uarg, 1)) ) return -EFAULT; if ( kexec_load_get_bits(exec.type, &base, &bit) ) return -EINVAL; pos = (test_bit(bit, &kexec_flags) != 0); /* Only allow kexec/kdump into loaded images */ if ( !test_bit(base + pos, &kexec_flags) ) return -ENOENT; switch (exec.type) { case KEXEC_TYPE_DEFAULT: image = &kexec_image[base + pos]; one_cpu_only(); machine_reboot_kexec(image); /* Does not return */ break; case KEXEC_TYPE_CRASH: kexec_crash(); /* Does not return */ break; } return -EINVAL; /* never reached */ } #endif ret_t do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg) { unsigned long flags; int ret = -EINVAL; if ( !IS_PRIV(current->domain) ) return -EPERM; ret = xsm_kexec(); if ( ret ) return ret; switch ( op ) { case KEXEC_CMD_kexec_get_range: ret = kexec_get(range)(uarg); break; case KEXEC_CMD_kexec_load: case KEXEC_CMD_kexec_unload: spin_lock_irqsave(&kexec_lock, flags); if (!test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags)) { ret = kexec_load_unload(op, uarg); } spin_unlock_irqrestore(&kexec_lock, flags); break; case KEXEC_CMD_kexec: ret = kexec_exec(uarg); break; } return ret; } #if defined(CONFIG_COMPAT) && !defined(COMPAT) #include "compat/kexec.c" #endif /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */