SystemC 30 Communication - port array
When declaring a port:
- the first argument is the name of an interface proper, which is also the type of the port:
- a port can only be bound to a channel derived from the type of the port or to another port or export with a type derived from the type of the port.
- the second argument is an optional integer value that specifies the maximum number of channel instances to which the port instance may be bound:
- a) the default value is 1.
- b) if the value is zero, the port may be bound to an arbitrary number of channel instances.
- c) it’s an error to bind a port to more channel instances than the number permitted.
- the third argument is an optional port policy of type
sc_port_policy
that determines the rules for binding multiports and the rules for unbound ports:- a)
[default] SC_ONE_OR_MORE_BOUND
: the port shall be bound to one or more channels, the maximum number being determined by the value of the second argument. It’s an error for the port to remain unbound at the end of elaboration. - b)
SC_ZERO_OR_MORE_BOUND
: the port shall be bound to zero or more channels, the maximum number being determined by the value of the second argument. The port may remain unbound at the end of elaboration. - c)
SC_ALL_BOUND
: the port shall be bound to exactly the number of channel instances given by value of the second argument, no more and no less, provided that value is greater than zero.- If the value of the second argument is zero, policy
SC_ALL_BOUND
has the same meaning as policySC_ONE_OR_MORE_BOUND
. - It’s an error for the port to remain unbound at the end of elaboration, or to be bound to fewer channel than the number required by the second argument.
- If the value of the second argument is zero, policy
- a)
It’s an error to bind a given port to a given channel more than once, whether directly or through another port.
Another way to define port array is using the C/C++ array syntax:
-
sc_port<IF> p[10]
or vector<sc_port<IF>> p(10);
Example
1
2
3
4
5
6
7
8
9
1. sc_port<IF> // Bound to exactly 1 channel instance
2. sc_port<IF,0> // Bound to 1 or more channel instances, with no upper limit
3. sc_port<IF,3> // Bound to 1, 2, or 3 channel instances
4. sc_port<IF,0,SC_ZERO_OR_MORE_BOUND> // Bound to 0 or more channel instances, with no upper limit
5. sc_port<IF,1,SC_ZERO_OR_MORE_BOUND> // Bound to 0 or 1 channel instances
6. sc_port<IF,3,SC_ZERO_OR_MORE_BOUND> // Bound to 0, 1, 2, or 3 channel instances
7. sc_port<IF,3,SC_ALL_BOUND> // Bound to exactly 3 channel instances
8. sc_port<IF> p[3] // an array of 3 ports, each binds to exactly 1 channel instance
9. vector<sc_port<IF>> p(3) // an array of 3 ports, each binds to exactly 1 channel instance
Code
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
// Learn with Examples, 2020, MIT license
#include <systemc>
#include <vector> // used to define a vector of ports
using namespace sc_core;
SC_MODULE(WRITER) {
sc_port<sc_signal_out_if<int>> p1; // #1: exactly 1 channel
sc_port<sc_signal_out_if<int>, 0> p2; // #2: 1 or more channels, no upper limit
sc_port<sc_signal_out_if<int>, 3> p3; // #3: 1, 2, or 3 channels
sc_port<sc_signal_out_if<int>, 0, SC_ZERO_OR_MORE_BOUND> p4; // #4: 0 or more channels, no upper limit
sc_port<sc_signal_out_if<int>, 1, SC_ZERO_OR_MORE_BOUND> p5; // #5: 0 or 1 channels
sc_port<sc_signal_out_if<int>, 3, SC_ZERO_OR_MORE_BOUND> p6; // #6: 0, 1, 2, or 3 channels
sc_port<sc_signal_out_if<int>, 3, SC_ALL_BOUND> p7; // #7: exactly 3 channels
std::vector<sc_port<sc_signal_out_if<int>>> p9; // #9: vector of port
SC_CTOR(WRITER) : p9(3) { // init p9 to size of 3
SC_THREAD(writer);
}
void writer() {
int v = 1;
while (true) {
p9[0]->write(v); // write to p9[0]
p7[1]->write(v++); // write to p7[1]
wait(1, SC_SEC);
}
}
};
SC_MODULE(READER) {
sc_port<sc_signal_in_if<int>> p1; // #1: exactly 1 channel
sc_port<sc_signal_in_if<int>, 0> p2; // #2: 1 or more channels, no upper limit
sc_port<sc_signal_in_if<int>, 3> p3; // #3: 1, 2, or 3 channels
sc_port<sc_signal_in_if<int>, 0, SC_ZERO_OR_MORE_BOUND> p4; // #4: 0 or more channels, no upper limit
sc_port<sc_signal_in_if<int>, 1, SC_ZERO_OR_MORE_BOUND> p5; // #5: 0 or 1 channels
sc_port<sc_signal_in_if<int>, 3, SC_ZERO_OR_MORE_BOUND> p6; // #6: 0, 1, 2, or 3 channels
sc_port<sc_signal_in_if<int>, 3, SC_ALL_BOUND> p7; // #7: exactly 3 channels
std::vector<sc_port<sc_signal_in_if<int>>> p9; // #9: exactly 3 channels
SC_CTOR(READER) : p9(3) { // init p9 to size of 3
SC_THREAD(reader7);
sensitive << p7; // sensitive to any element of port array p7
dont_initialize();
SC_THREAD(reader9);
sensitive << p9[0] << p9[1] << p9[2]; // sensitive to any element of port array p9
dont_initialize();
}
void reader7() {
while (true) {
std::cout << sc_time_stamp() << "; reader7, port 0/1/2 = " << p7[0]->read() << "/" << p7[1]->read() << "/" << p7[2]->read() << std::endl;
wait();
}
}
void reader9() {
while (true) {
std::cout << sc_time_stamp() << "; reader9, port 0/1/2 = " << p9[0]->read() << "/" << p9[1]->read() << "/" << p9[2]->read() << std::endl;
wait();
}
}
};
int sc_main(int, char*[]) {
WRITER writer("writer"); // instantiate writer
READER reader("reader"); // instantiate reader
// declare channels
sc_signal<int> s1; // 1 channel
std::vector<sc_signal<int>> s2(10); // 10 channels
std::vector<sc_signal<int>> s3(2); // 2 channel
// leave s4 un-bound
sc_signal<int> s5; // 1 channel
std::vector<sc_signal<int>> s6(2); // 2 channels
std::vector<sc_signal<int>> s7(3); // 3 channels
// #8 is same as #9, omitted
std::vector<sc_signal<int>> s9(3); // 3 channels
// bind ports
writer.p1(s1); // #1
reader.p1(s1); // #1
for (unsigned int i = 0; i < s2.size(); ++i) { // #2
writer.p2(s2[i]);
reader.p2(s2[i]);
}
for (unsigned int i = 0; i < s3.size(); ++i) { // #3
writer.p3(s3[i]);
reader.p3(s3[i]);
}
// s4 un-bound
writer.p5(s5); // #5
reader.p5(s5); // #5
for (unsigned int i = 0; i < s6.size(); ++i) { // #6
writer.p6(s6[i]);
reader.p6(s6[i]);
}
for (unsigned int i = 0; i < s7.size(); ++i) { // #7
writer.p7(s7[i]);
reader.p7(s7[i]);
}
for (unsigned int i = 0; i < s9.size(); ++i) { // #9
writer.p9[i](s9[i]);
reader.p9[i](s9[i]);
}
sc_start(2, SC_SEC);
return 0;
}
// Result:
// p9[0] has value
0 s; reader9, port 0/1/2 = 1/0/0
// p7[1] has value
0 s; reader7, port 0/1/2 = 0/1/0
// p9[0] updated
1 s; reader9, port 0/1/2 = 2/0/0
//p7[1] updated
1 s; reader7, port 0/1/2 = 0/2/0