/
cfu.cpp
86 lines (71 loc) · 1.67 KB
/
cfu.cpp
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
//
// Copyright (c) 2021 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
#include "cfu.h"
void Cfu::tick(bool countEnable, uint64_t steps = 1)
{
for(uint64_t i = 0; i < steps; i++) {
*clk = 1;
evaluateModel();
*clk = 0;
evaluateModel();
}
if(countEnable) {
tickCounter += steps;
}
}
void Cfu::timeoutTick(uint8_t* signal, uint8_t expectedValue, int timeout = DEFAULT_TIMEOUT)
{
do
{
tick(true);
timeout--;
}
while((*signal != expectedValue) && timeout > 0);
if(timeout == 0) {
throw "Operation timeout";
}
}
uint64_t Cfu::execute(uint32_t functionID, uint32_t data0, uint32_t data1, int* error)
{
uint64_t result;
*req_func_id = functionID;
*req_data0 = data0;
*req_data1 = data1;
*req_valid = 1;
*resp_ready = 1;
/* Error signal is not supported by CFU yet so set it to 0 */
*error = 0;
/* Apply changed signals without changing clock's edge */
evaluateModel();
/* Make sure that CFU is ready to execute operation */
if(*req_ready != 1) {
timeoutTick(req_ready, 1);
}
/* CFU accepted a command so check if it responded immediately */
if(*resp_valid) {
result = *resp_data;
tick(true);
} else {
/* CFU did not finish operation so wait for it to assert a response */
timeoutTick(resp_valid, 1);
result = *resp_data;
}
/* CFU finished execution so CPU can deassert `req_valid` */
*req_valid = 0;
/* Apply changed signals without changing clock's edge */
evaluateModel();
/* Tick once to finish */
tick(true);
return result;
}
void Cfu::reset()
{
*rst = 1;
tick(true);
*rst = 0;
tick(true);
}