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
|
#include <gran/ideal_noc.h>
struct reg {
struct packet pkt;
bool busy;
};
struct noc {
struct component component;
uint32_t elems;
size_t latency;
size_t counter;
struct reg *in; /* countedby[elems] */
struct reg *out; /* countedby[elems] */
struct component **lower; /* countedby[elems] */
};
stat ideal_noc_receive(struct noc *n, struct component *from, struct packet pkt)
{
(void)from; /* unused */
uint32_t elem;
addr_ideal_noc(pkt.to, &elem, NULL);
assert(elem < n->elems);
if (n->in[elem].busy)
return EBUSY;
pkt.timestamp = n->counter;
n->in[elem].pkt = pkt;
n->in[elem].busy = true;
return OK;
}
stat ideal_noc_clock(struct noc *n)
{
size_t counter = n->latency == 0 ? 0 : (n->counter + 1) % n->latency;
if (counter != 0)
return OK;
for (size_t i = 0; i < n->elems; ++i) {
struct reg *in = &n->in[i];
if (!in->busy)
continue;
uint32_t elem;
addr_ideal_noc(in->pkt.to, &elem, NULL);
assert(elem < n->elems);
struct reg *out = &n->out[elem];
if (out->busy && out->pkt.timestamp < in->pkt.timestamp)
continue;
out->pkt = in->pkt;
out->busy = true;
in->busy = false;
}
for (size_t i = 0; i < n->elems; ++i) {
struct reg *out = &n->out[i];
if (!out->busy)
continue;
uint32_t elem;
addr_ideal_noc(out->pkt.to, &elem, NULL);
struct component *lower = n->lower[elem];
assert(lower);
stat ret = SEND(n, lower, out->pkt);
if (ret == EBUSY)
continue;
assert(ret == OK);
out->busy = false;
}
return OK;
}
void ideal_noc_destroy(struct noc *n)
{
free(n->in);
free(n->out);
free(n->lower);
free(n);
}
stat ideal_noc_connect(struct component *node, struct component *component, uint32_t elem)
{
struct noc *n = (struct noc *)node;
assert(elem < n->elems);
assert(n->lower[elem] == NULL);
n->lower[elem] = component;
return OK;
}
struct component *create_ideal_noc(uint32_t elems, size_t latency)
{
struct noc *n = (struct noc *)calloc(1, sizeof(struct noc));
if (!n)
return NULL;
n->in = (struct reg *)calloc(elems, sizeof(struct reg));
if (!n->in) {
free(n);
return NULL;
}
n->out = (struct reg *)calloc(elems, sizeof(struct reg));
if (!n->out) {
free(n->in);
free(n);
return NULL;
}
n->lower = (struct component **)calloc(elems, sizeof(struct component *));
if (!n->lower) {
free(n->out);
free(n->in);
free(n);
return NULL;
}
n->component.destroy = (destroy_callback)ideal_noc_destroy;
n->component.receive = (receive_callback)ideal_noc_receive;
n->component.clock = (clock_callback)ideal_noc_clock;
n->latency = latency;
n->elems = elems;
return (struct component *)n;
}
|