-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenbinding.awk
121 lines (96 loc) · 2.99 KB
/
genbinding.awk
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
# This script should be called on the primary model header generated by
# Verilator. It will in turn generate for each I/O port detected a getter and
# setter function suitable for use with C. The header file will be emitted on
# standard error.
BEGIN {
FS = "([\\(]|[&]|[,]|[ \n\t]+)+"
# This is the list of macros that declare I/Os, which is what we want
# to generate bindings for.
#
# See: https://github.com/verilator/verilator/blob/v4.200/include/verilated.h#L262
macros["VL_SIG8"] = 1
macros["VL_SIG16"] = 1
macros["VL_SIG64"] = 1
macros["VL_SIG"] = 1
macros["VL_SIGW"] = 1
macros["VL_IN8"] = 1
macros["VL_IN16"] = 1
macros["VL_IN64"] = 1
macros["VL_IN"] = 1
macros["VL_INW"] = 1
macros["VL_INOUT8"] = 1
macros["VL_INOUT16"] = 1
macros["VL_INOUT64"] = 1
macros["VL_INOUT"] = 1
macros["VL_INOUTW"] = 1
macros["VL_OUT8"] = 1
macros["VL_OUT16"] = 1
macros["VL_OUT64"] = 1
macros["VL_OUT"] = 1
macros["VL_OUTW"] = 1
printf("\n#include \"shim_binding.h\"\n\n")
printf("#ifndef SHIM_BINDING_H\n#define SHIM_BINDING_H\n") | "cat 1>&2"
printf("\n#include \"shim.h\"\n\n") | "cat 1>&2"
printf("\n#include <stdint.h>\n\n")
#include "stdint.h"
}
# Because of how regex field splitting works, we have to explicitly drop empty
# fields.
#
# See: https://www.gnu.org/software/gawk/manual/html_node/Regexp-Field-Splitting.html
{
j = 0
for (i = 0; i < NF; i++) {
if ($i != "") {
$j = $i
if (i > j) { $i = "" }
j ++
}
}
}
$1 in macros {
bits = $3 - $4 + 1
if (bits > 64) {
printf("\n// Don't know how to handle %d bit wide signal '%s'\n\n", bits, $2)
next
}
size = 8
if (bits > 8) {
size = 16
}
if (bits > 16) {
size = 32
}
if (bits > 32) {
size = 64
}
printf("///////// %s\n", $2)
printf("\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n")
printf("uint%d_t get_%s(simulation_state* s) {\n", size, $2)
printf("\treturn (uint%d_t) s->top->%s;\n", size, $2)
printf("}\n\n")
printf("uint%d_t set_%s(simulation_state* s, uint%d_t to) {\n", size, $2, size)
printf("\treturn s->top->%s = to;\n", $2)
printf("}\n\n")
printf("unsigned int msb_%s(simulation_state* s) {\n", $2)
printf("\treturn %d;\n", $3)
printf("}\n\n")
printf("unsigned int lsb_%s(simulation_state* s) {\n", $2)
printf("\treturn %d;\n", $4)
printf("}\n\n")
printf("unsigned int bits_%s(simulation_state* s) {\n", $2)
printf("\treturn %d;\n", bits)
printf("}\n\n")
printf("#ifdef __cplusplus\n}\n#endif\n")
printf("///////// %s\n", $2) | "cat 1>&2"
printf("\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n") | "cat 1>&2"
printf("uint%d_t get_%s(simulation_state* s);\n", size, $2) | "cat 1>&2"
printf("uint%d_t set_%s(simulation_state* s, uint%d_t to);\n", size, $2, size) | "cat 1>&2"
printf("unsigned int msb_%s(simulation_state* s);\n", $2) | "cat 1>&2"
printf("unsigned int lsb_%s(simulation_state* s);\n", $2) | "cat 1>&2"
printf("unsigned int bits_%s(simulation_state* s);\n", $2) | "cat 1>&2"
printf("#ifdef __cplusplus\n}\n#endif\n\n") | "cat 1>&2"
}
END {
printf("#endif") | "cat 1>&2"
}