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
|
// Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;
SC_MODULE(FIFO) {
sc_fifo<int> f1, f2, f3;
SC_CTOR(FIFO) : f1(2), f2(2), f3(2) { // fifo with size 2
SC_THREAD(generator1);
SC_THREAD(consumer1);
SC_THREAD(generator2);
SC_THREAD(consumer2);
SC_THREAD(generator3);
SC_THREAD(consumer3);
}
void generator1() { // blocking write
int v = 0;
while (true) {
f1.write(v); // same as f = v, which is not recommended.
std::cout << sc_time_stamp() << ": generator1 writes " << v++ << std::endl;
wait(1, SC_SEC); // write every 1 s
}
}
void consumer1() { // blocking read
int v = -1;
while (true) {
f1.read(v); // same as v = int(f), which is not recommended; or, v = f1.read();
std::cout << sc_time_stamp() << ": consumer1 reads " << v << std::endl;
wait(3, SC_SEC); // read every 3 s, fifo will fill up soon
}
}
void generator2() { // non-blocking write
int v = 0;
while (true) {
while (f2.nb_write(v) == false ) { // nb write until succeeded
wait(f2.data_read_event()); // if not successful, wait for data read (a fifo slot becomes available)
}
std::cout << sc_time_stamp() << ": generator2 writes " << v++ << std::endl;
wait(1, SC_SEC); // write every 1 s
}
}
void consumer2() { // non-blocking read
int v = -1;
while (true) {
while (f2.nb_read(v) == false) {
wait(f2.data_written_event());
}
std::cout << sc_time_stamp() << ": consumer2 reads " << v << std::endl;
wait(3, SC_SEC); // read every 3 s, fifo will fill up soon
}
}
void generator3() { // free/available slots before/after write
int v = 0;
while (true) {
std::cout << sc_time_stamp() << ": generator3, before write, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl;
f3.write(v++);
std::cout << sc_time_stamp() << ": generator3, after write, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl;
wait(1, SC_SEC);
}
}
void consumer3() { // free/available slots before/after read
int v = -1;
while (true) {
std::cout << sc_time_stamp() << ": consumer3, before read, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl;
f3.read(v);
std::cout << sc_time_stamp() << ": consumer3, after read, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl;
wait(3, SC_SEC); // read every 3 s, fifo will fill up soon
}
}
};
int sc_main(int, char*[]) {
FIFO fifo("fifo");
sc_start(10, SC_SEC);
return 0;
}
// Result:
// f1 and f2 have same behavior, depite the block/non-blocking methods
// read is slower than write, fifo soon becomes full. write speed reduces to same speed as read.
// g1 writes at 0 s
0 s: generator1 writes 0
0 s: generator2 writes 0
0 s: generator3, before write, #free/#available=2/0
//write reduces #write slot, #read slot un-increased till next delta cycle
0 s: generator3, after write, #free/#available=1/0
0 s: consumer3, before read, #free/#available=1/0
// c1 reads at 0 s
0 s: consumer1 reads 0
0 s: consumer2 reads 0
0 s: consumer3, after read, #free/#available=1/0
// g1 writes at 1 s
1 s: generator1 writes 1
1 s: generator2 writes 1
1 s: generator3, before write, #free/#available=2/0
1 s: generator3, after write, #free/#available=1/0
// g1 writes at 2 s
2 s: generator1 writes 2
2 s: generator2 writes 2
2 s: generator3, before write, #free/#available=1/1
2 s: generator3, after write, #free/#available=0/1
3 s: consumer3, before read, #free/#available=0/2
3 s: consumer3, after read, #free/#available=0/1
3 s: generator3, before write, #free/#available=0/1
// c1 reads at 3 s
3 s: consumer1 reads 1
3 s: consumer2 reads 1
3 s: generator3, after write, #free/#available=0/1
// g1 writes at 3 s
3 s: generator1 writes 3
3 s: generator2 writes 3
4 s: generator3, before write, #free/#available=0/2
// c1 reads at 6 s
6 s: consumer1 reads 2
6 s: consumer3, before read, #free/#available=0/2
6 s: consumer3, after read, #free/#available=0/1
6 s: consumer2 reads 2
// g1 writes at 6 s (skips 4, 5 s)
6 s: generator1 writes 4
6 s: generator3, after write, #free/#available=0/1
6 s: generator2 writes 4
7 s: generator3, before write, #free/#available=0/2
9 s: consumer3, before read, #free/#available=0/2
// read reduces #read slot, #write slot un-increased till next delta cycle
9 s: consumer3, after read, #free/#available=0/1
// c1 reads at 9 s
9 s: consumer1 reads 3
9 s: consumer2 reads 3
9 s: generator3, after write, #free/#available=0/1
// g1 writes at 9 s (skips 7, 8 s)
9 s: generator1 writes 5
9 s: generator2 writes 5
|