generating setvl function works
[simplev-cpp.git] / generate_headers.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # See Notices.txt for copyright information
4
5 import sys
6 from io import StringIO
7 from typing import List
8 from soc.decoder.pseudo.pagereader import ISA
9 from soc.decoder.power_svp64 import SVP64RM
10 from soc.decoder.power_fields import DecodeFields
11 from soc.decoder.power_decoder import create_pdecode
12
13
14 class InclusiveRange:
15 __slots__ = "start", "stop"
16
17 def __init__(self, start, stop=None):
18 if stop is None:
19 stop = start
20 self.start = start
21 self.stop = stop
22
23 def __len__(self) -> int:
24 return self.width
25
26 @property
27 def width(self) -> int:
28 return self.stop - self.start + 1
29
30 def __repr__(self):
31 if self.start == self.stop:
32 return f"InclusiveRange({self.start})"
33 return f"InclusiveRange({self.start}, {self.stop})"
34
35 def __str__(self):
36 if self.start == self.stop:
37 return f"{self.start}"
38 return f"{self.start}:{self.stop}"
39
40 def append(self, v):
41 if v == self.stop + 1:
42 self.stop = v
43 else:
44 raise ValueError()
45
46 def endian_reversed(self, word_length) -> "InclusiveRange":
47 # note reversed stop/start
48 return InclusiveRange(word_length - 1 - self.stop,
49 word_length - 1 - self.start)
50
51
52 class RangesField:
53 __slots__ = "ranges",
54 ranges: List[InclusiveRange]
55
56 def __init__(self, ranges=None):
57 if ranges is None:
58 ranges = []
59 if isinstance(ranges, InclusiveRange):
60 ranges = [ranges]
61 self.ranges = ranges
62
63 def __len__(self):
64 retval = 0
65 for i in self.ranges:
66 retval += len(i)
67 return retval
68
69 def __repr__(self):
70 if len(self.ranges) == 0:
71 return "RangesField()"
72 if len(self.ranges) == 1:
73 return f"RangesField({self.ranges[0]})"
74 return f"RangesField({self.ranges})"
75
76 def __str__(self):
77 if len(self.ranges) == 0:
78 return "none"
79 return ",".join(map(str, self.ranges))
80
81 def __setitem__(self, key, value):
82 assert isinstance(key, int)
83 assert isinstance(value, int)
84 assert key == len(self)
85 try:
86 self.ranges[-1].append(value)
87 return
88 except IndexError:
89 pass
90 except ValueError:
91 pass
92 self.ranges.append(InclusiveRange(value))
93
94 def endian_reversed(self, word_length) -> "RangesField":
95 return RangesField([i.endian_reversed(word_length)
96 for i in reversed(self.ranges)])
97
98 @property
99 def contiguous(self) -> bool:
100 return len(self.ranges) == 1
101
102 @property
103 def start(self) -> int:
104 assert self.contiguous
105 return self.ranges[0].start
106
107 @property
108 def stop(self) -> int:
109 assert self.contiguous
110 return self.ranges[0].stop
111
112 @property
113 def width(self) -> int:
114 assert self.contiguous
115 return self.ranges[0].width
116
117
118 try:
119 # shut-up excessive printing
120 old_stdout = sys.stdout
121 new_stdout = StringIO()
122 sys.stdout = new_stdout
123 isa = ISA()
124 svp64rm = SVP64RM()
125 decode_fields = DecodeFields(bitkls=RangesField)
126 decode_fields.create_specs()
127 decoder = create_pdecode()
128 sys.stdout = old_stdout
129 except:
130 sys.stdout = old_stdout
131 print(new_stdout.getvalue())
132 raise
133
134
135 def flatten(v):
136 if isinstance(v, list):
137 for i in v:
138 yield from flatten(i)
139 else:
140 yield v
141
142
143 def find_opcode(internal_op):
144 retval = None
145 for primary_subdecoder in decoder.dec:
146 for extended_subdecoder in flatten(primary_subdecoder.subdecoders):
147 for opcode in extended_subdecoder.opcodes:
148 if opcode['internal op'] == internal_op:
149 if retval is not None:
150 raise ValueError(f"internal_op={internal_op!r} "
151 "found more than once")
152 retval = extended_subdecoder.pattern, \
153 int(opcode['opcode'], base=0)
154 if retval is None:
155 raise ValueError(f"internal_op={internal_op!r} not found")
156 return retval
157
158
159 SETVL_PO, SETVL_XO = find_opcode("OP_SETVL")
160 PO_FIELD: RangesField = decode_fields.PO
161 RT_FIELD: RangesField = decode_fields.RT
162 RA_FIELD: RangesField = decode_fields.RA
163 SVL_SVi_FIELD: RangesField = decode_fields.FormSVL.SVi
164 SVL_vs_FIELD: RangesField = decode_fields.FormSVL.vs
165 SVL_ms_FIELD: RangesField = decode_fields.FormSVL.ms
166 SVL_XO_FIELD: RangesField = decode_fields.FormSVL.XO
167 SVL_Rc_FIELD: RangesField = decode_fields.FormSVL.Rc
168 print(f"SETVL_PO={SETVL_PO}")
169 print(f"SETVL_XO={SETVL_XO}")
170 print(f"PO_FIELD={PO_FIELD}")
171 print(f"RT_FIELD={RT_FIELD}")
172 print(f"RA_FIELD={RA_FIELD}")
173 print(f"SVL_SVi_FIELD={SVL_SVi_FIELD}")
174 print(f"SVL_vs_FIELD={SVL_vs_FIELD}")
175 print(f"SVL_ms_FIELD={SVL_ms_FIELD}")
176 print(f"SVL_XO_FIELD={SVL_XO_FIELD}")
177 print(f"SVL_Rc_FIELD={SVL_Rc_FIELD}")
178
179 WORD_LENGTH = 32
180 PO_SHIFT = PO_FIELD.endian_reversed(WORD_LENGTH).start
181 RT_SHIFT = RT_FIELD.endian_reversed(WORD_LENGTH).start
182 RA_SHIFT = RA_FIELD.endian_reversed(WORD_LENGTH).start
183 SVL_SVi_SHIFT = SVL_SVi_FIELD.endian_reversed(WORD_LENGTH).start
184 SVL_vs_SHIFT = SVL_vs_FIELD.endian_reversed(WORD_LENGTH).start
185 SVL_ms_SHIFT = SVL_ms_FIELD.endian_reversed(WORD_LENGTH).start
186 SVL_XO_SHIFT = SVL_XO_FIELD.endian_reversed(WORD_LENGTH).start
187 SVL_Rc_SHIFT = SVL_Rc_FIELD.endian_reversed(WORD_LENGTH).start
188
189 print(f"RT_SHIFT={RT_SHIFT}")
190 print(f"RA_SHIFT={RA_SHIFT}")
191 print(f"PO_SHIFT={PO_SHIFT}")
192 print(f"SVL_SVi_SHIFT={SVL_SVi_SHIFT}")
193 print(f"SVL_vs_SHIFT={SVL_vs_SHIFT}")
194 print(f"SVL_ms_SHIFT={SVL_ms_SHIFT}")
195 print(f"SVL_XO_SHIFT={SVL_XO_SHIFT}")
196 print(f"SVL_Rc_SHIFT={SVL_Rc_SHIFT}")
197
198
199 def is_power_of_2(i):
200 assert isinstance(i, int)
201 return (i & (i - 1)) == 0 and i != 0
202
203
204 with open("include/simplev_cpp_generated.h", mode="w", encoding="utf-8") as o:
205 o.write("""// SPDX-License-Identifier: LGPL-2.1-or-later
206 // See Notices.txt for copyright information
207 // This file is automatically generated by generate_headers.py,
208 // do not edit by hand
209 #pragma once
210 #include <cstddef>
211 #include <cstdint>
212 #include <type_traits>
213
214 #ifdef __clang__
215 #define SIMPLEV_USE_NONPOT_VECTORS
216 #endif
217
218 // #undef SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS
219
220 namespace sv
221 {
222 template <typename ElementType, std::size_t SUB_VL, std::size_t MAX_VL, typename = void>
223 struct VecTypeStruct;
224
225 template <typename ElementType, std::size_t SUB_VL, std::size_t MAX_VL>
226 using VecType = typename VecTypeStruct<ElementType, SUB_VL, MAX_VL>::Type;
227
228 #define SIMPLEV_MAKE_VEC_TYPE(size) \\
229 template <typename ElementType, std::size_t SUB_VL, std::size_t MAX_VL> \\
230 struct VecTypeStruct<ElementType, \\
231 SUB_VL, \\
232 MAX_VL, \\
233 std::enable_if_t<sizeof(ElementType) * SUB_VL * MAX_VL == (size)>> \\
234 final \\
235 { \\
236 typedef ElementType Type __attribute__((vector_size(size))); \\
237 };
238
239 #ifdef SIMPLEV_USE_NONPOT_VECTORS
240 #define SIMPLEV_MAKE_VEC_TYPE_NONPOT(size) SIMPLEV_MAKE_VEC_TYPE(size)
241 #else
242 #define SIMPLEV_MAKE_VEC_TYPE_NONPOT(size)
243 #endif
244
245 """)
246 for i in range(1, 128 + 1):
247 if is_power_of_2(i):
248 o.write(f"SIMPLEV_MAKE_VEC_TYPE({i})\n")
249 else:
250 o.write(f"SIMPLEV_MAKE_VEC_TYPE_NONPOT({i})\n")
251 if i == 8:
252 o.write("#ifdef SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS\n")
253 o.write(f"""#endif // SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS
254
255 template <std::size_t MAX_VL>
256 struct VL final
257 {{
258 static_assert(MAX_VL > 0 && MAX_VL <= 64);
259 std::size_t value;
260 }};
261
262 template <std::size_t MAX_VL>
263 inline __attribute__((always_inline)) VL<MAX_VL> setvl(std::size_t vl)
264 {{
265 VL<MAX_VL> retval;
266 asm volatile(
267 "# setvl %[retval], %[vl], MVL=%[max_vl]\\n\\t"
268 ".long %[instr] | (%[retval] << %[rt_shift]) | (%[vl] << %[ra_shift])"
269 : [retval] "=b"(retval.value)
270 : [vl] "b"(vl),
271 [max_vl] "n"(MAX_VL),
272 [instr] "n"(((MAX_VL - 1) << {SVL_SVi_SHIFT}) | {hex(
273 (1 << SVL_vs_SHIFT)
274 | (1 << SVL_ms_SHIFT)
275 | (SETVL_XO << SVL_XO_SHIFT)
276 | (SETVL_PO << PO_SHIFT))}),
277 [rt_shift] "n"({RT_SHIFT}),
278 [ra_shift] "n"({RA_SHIFT})
279 : "memory");
280 return retval;
281 }}
282 }} // namespace sv
283
284 #undef SIMPLEV_MAKE_VEC_TYPE
285 #undef SIMPLEV_MAKE_VEC_TYPE_NONPOT
286 #undef SIMPLEV_USE_NONPOT_VECTORS
287 #undef SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS
288 """)