/* * Copyright (C) 2009 Citrix Ltd. * Author Vincent Hanquez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; version 2.1 only. with the special * exception on linking described in file LICENSE. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. */ #include "libxl_internal.h" #include /* * It is safe to store gc in the struct because: * - If it an actual gc, then the flexarray should not be used after the gc * have been freed. * - If it is a NOGC, then this point to a structure embedded in libxl_ctx, * therefore will survive across several libxl calls. */ flexarray_t *flexarray_make(libxl__gc *gc, int size, int autogrow) { flexarray_t *array; GCNEW(array); array->size = size; array->autogrow = autogrow; array->count = 0; array->gc = gc; GCNEW_ARRAY(array->data, size); return array; } void flexarray_free(flexarray_t *array) { assert(!libxl__gc_is_real(array->gc)); free(array->data); free(array); } void flexarray_grow(flexarray_t *array, int extents) { int newsize; libxl__gc *gc = array->gc; newsize = array->size + extents; GCREALLOC_ARRAY(array->data, newsize); array->size += extents; } int flexarray_set(flexarray_t *array, unsigned int idx, void *ptr) { if (idx >= array->size) { int newsize; if (!array->autogrow) return 1; newsize = (array->size * 2 < idx) ? idx + 1 : array->size * 2; flexarray_grow(array, newsize - array->size); } if ( idx + 1 > array->count ) array->count = idx + 1; array->data[idx] = ptr; return 0; } int flexarray_append(flexarray_t *array, void *ptr) { return flexarray_set(array, array->count, ptr); } int flexarray_append_pair(flexarray_t *array, void *ptr1, void *ptr2) { int rc = flexarray_append(array, ptr1); if (!rc) rc = flexarray_append(array, ptr2); return rc; } int flexarray_vappend(flexarray_t *array, ...) { va_list va; void *ptr; int ret; va_start(va, array); for(ret = 0; (ptr = va_arg(va, void *)); ret++) { if ( flexarray_append(array, ptr) ) break; } va_end(va); return ret; } int flexarray_get(flexarray_t *array, int idx, void **ptr) { if (idx >= array->size) return 1; *ptr = array->data[idx]; return 0; } void **flexarray_contents(flexarray_t *array) { void **data; data = array->data; if (!libxl__gc_is_real(array->gc)) free(array); return data; } /* * Local variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ ious/async.v?id=4cd2f03e36d09f936d39f8499e26fb0a2bc897f9'>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
`define MAXQ 2
module uut (
	input clk,
	input d, r, e,
	output [`MAXQ:0] q
);
	reg q0;
	always @(posedge clk) begin
		if (r)
			q0 <= 0;
		else if (e)
			q0 <= d;
	end

	reg q1;
	always @(posedge clk, posedge r) begin
		if (r)
			q1 <= 0;
		else if (e)
			q1 <= d;
	end

	reg q2;
	always @(posedge clk, negedge r) begin
		if (!r)
			q2 <= 0;
		else if (!e)
			q2 <= d;
	end

	assign q = {q2, q1, q0};
endmodule

`ifdef TESTBENCH
module \$ff #(
	parameter integer WIDTH = 1
) (
	input [WIDTH-1:0] D,
	output reg [WIDTH-1:0] Q
);
	wire sysclk = testbench.sysclk;
	always @(posedge sysclk)
		Q <= D;
endmodule

module testbench;
	reg sysclk;
	always #5 sysclk = (sysclk === 1'b0);

	reg clk;
	always @(posedge sysclk) clk = (clk === 1'b0);

	reg d, r, e;

	wire [`MAXQ:0] q_uut;
	uut uut (.clk(clk), .d(d), .r(r), .e(e), .q(q_uut));

	wire [`MAXQ:0] q_syn;
	syn syn (.clk(clk), .d(d), .r(r), .e(e), .q(q_syn));

	wire [`MAXQ:0] q_prp;
	prp prp (.clk(clk), .d(d), .r(r), .e(e), .q(q_prp));

	wire [`MAXQ:0] q_a2s;
	a2s a2s (.clk(clk), .d(d), .r(r), .e(e), .q(q_a2s));

	wire [`MAXQ:0] q_ffl;
	ffl ffl (.clk(clk), .d(d), .r(r), .e(e), .q(q_ffl));

	task printq;
		reg [5*8-1:0] msg;
		begin
			msg = "OK";
			if (q_uut !== q_syn) msg = "SYN";
			if (q_uut !== q_prp) msg = "PRP";
			if (q_uut !== q_a2s) msg = "A2S";
			if (q_uut !== q_ffl) msg = "FFL";
			$display("%6t %b %b %b %b %b %s", $time, q_uut, q_syn, q_prp, q_a2s, q_ffl, msg);
			if (msg != "OK") $finish;
		end
	endtask

	initial if(0) begin
		$dumpfile("async.vcd");
		$dumpvars(0, testbench);
	end

	initial begin
		@(posedge clk);
		d <= 0;
		r <= 0;
		e <= 0;
		@(posedge clk);
		e <= 1;
		@(posedge clk);
		e <= 0;
		repeat (10000) begin
			@(posedge clk);
			printq;
			d <= $random;
			r <= $random;
			e <= $random;
		end
		$display("PASS");
		$finish;
	end
endmodule
`endif