add RangesField that tracks ranges of bits for instruction fields
[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 from typing import List
6 from soc.decoder.isa.caller import (SVP64PrefixFields, SV64P_MAJOR_SIZE,
7 SV64P_PID_SIZE, SVP64RMFields,
8 SVP64RM_EXTRA2_SPEC_SIZE,
9 SVP64RM_EXTRA3_SPEC_SIZE,
10 SVP64RM_MODE_SIZE, SVP64RM_SMASK_SIZE,
11 SVP64RM_MMODE_SIZE, SVP64RM_MASK_SIZE,
12 SVP64RM_SUBVL_SIZE, SVP64RM_EWSRC_SIZE,
13 SVP64RM_ELWIDTH_SIZE)
14 from soc.decoder.pseudo.pagereader import ISA
15 from soc.decoder.power_svp64 import SVP64RM, get_regtype, decode_extra
16 from soc.decoder.power_fields import DecodeFields
17
18
19 class InclusiveRange:
20 __slots__ = "start", "stop"
21
22 def __init__(self, start, stop=None):
23 if stop is None:
24 stop = start
25 self.start = start
26 self.stop = stop
27
28 def __len__(self) -> int:
29 return self.width
30
31 @property
32 def width(self) -> int:
33 return self.stop - self.start + 1
34
35 def __repr__(self):
36 if self.start == self.stop:
37 return f"InclusiveRange({self.start})"
38 return f"InclusiveRange({self.start}, {self.stop})"
39
40 def __str__(self):
41 if self.start == self.stop:
42 return f"{self.start}"
43 return f"{self.start}:{self.stop}"
44
45 def append(self, v):
46 if v == self.stop + 1:
47 self.stop = v
48 else:
49 raise ValueError()
50
51 def endian_reversed(self, word_length) -> "InclusiveRange":
52 # note reversed stop/start
53 return InclusiveRange(word_length - 1 - self.stop,
54 word_length - 1 - self.start)
55
56
57 class RangesField:
58 __slots__ = "ranges",
59 ranges: List[InclusiveRange]
60
61 def __init__(self, ranges=None):
62 if ranges is None:
63 ranges = []
64 if isinstance(ranges, InclusiveRange):
65 ranges = [ranges]
66 self.ranges = ranges
67
68 def __len__(self):
69 retval = 0
70 for i in self.ranges:
71 retval += len(i)
72 return retval
73
74 def __repr__(self):
75 if len(self.ranges) == 0:
76 return "RangesField()"
77 if len(self.ranges) == 1:
78 return f"RangesField({self.ranges[0]})"
79 return f"RangesField({self.ranges})"
80
81 def __str__(self):
82 if len(self.ranges) == 0:
83 return "none"
84 return ",".join(map(str, self.ranges))
85
86 def __setitem__(self, key, value):
87 assert isinstance(key, int)
88 assert isinstance(value, int)
89 assert key == len(self)
90 try:
91 self.ranges[-1].append(value)
92 return
93 except IndexError:
94 pass
95 except ValueError:
96 pass
97 self.ranges.append(InclusiveRange(value))
98
99 def endian_reversed(self, word_length) -> "RangesField":
100 return RangesField([i.endian_reversed(word_length) for i in reversed(self.ranges)])
101
102 @property
103 def contiguous(self) -> bool:
104 return len(self.ranges) == 1
105
106 @property
107 def start(self) -> int:
108 assert self.contiguous
109 return self.ranges[0].start
110
111 @property
112 def stop(self) -> int:
113 assert self.contiguous
114 return self.ranges[0].stop
115
116 @property
117 def width(self) -> int:
118 assert self.contiguous
119 return self.ranges[0].width
120
121
122 isa = ISA()
123 svp64rm = SVP64RM()
124 decode_fields = DecodeFields(bitkls=RangesField)
125 decode_fields.create_specs()
126 PO_FIELD: RangesField = decode_fields.PO
127 RT_FIELD: RangesField = decode_fields.RT
128 RA_FIELD: RangesField = decode_fields.RA
129 print(f"PO_FIELD={PO_FIELD}")
130 print(f"RT_FIELD={RT_FIELD}")
131 print(f"RA_FIELD={RA_FIELD}")
132
133 WORD_LENGTH = 32
134 PRIMARY_OPCODE_SHIFT = PO_FIELD.endian_reversed(WORD_LENGTH).start
135 # unofficial value. see https://libre-soc.org/openpower/sv/setvl/
136 # FIXME: incorrect extended opcode value
137 SETVL_OPCODE = (19 << PRIMARY_OPCODE_SHIFT) | (0 << 1)
138 SETVL_IMMEDIATE_SHIFT = 32 - 7 - 16
139 REG_FIELD_WIDTH = 5
140 RT_SHIFT = RT_FIELD.endian_reversed(WORD_LENGTH).start
141 RA_SHIFT = RA_FIELD.endian_reversed(WORD_LENGTH).start
142
143 print(f"RT_SHIFT={RT_SHIFT}")
144 print(f"RA_SHIFT={RA_SHIFT}")
145 print(f"PRIMARY_OPCODE_SHIFT={PRIMARY_OPCODE_SHIFT}")
146
147
148 def is_power_of_2(i):
149 assert isinstance(i, int)
150 return (i & (i - 1)) == 0 and i != 0
151
152
153 with open("include/simplev_cpp_generated.h", mode="w", encoding="utf-8") as o:
154 o.write("""// SPDX-License-Identifier: LGPL-2.1-or-later
155 // See Notices.txt for copyright information
156 #pragma once
157 #include <cstddef>
158 #include <cstdint>
159 #include <type_traits>
160
161 #ifdef __clang__
162 #define SIMPLEV_USE_NONPOT_VECTORS
163 #endif
164
165 // #undef SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS
166
167 namespace sv
168 {
169 template <typename ElementType, std::size_t SUB_VL, std::size_t MAX_VL, typename = void>
170 struct VecTypeStruct;
171
172 template <typename ElementType, std::size_t SUB_VL, std::size_t MAX_VL>
173 using VecType = typename VecTypeStruct<ElementType, SUB_VL, MAX_VL>::Type;
174
175 #define SIMPLEV_MAKE_VEC_TYPE(size) \\
176 template <typename ElementType, std::size_t SUB_VL, std::size_t MAX_VL> \\
177 struct VecTypeStruct<ElementType, \\
178 SUB_VL, \\
179 MAX_VL, \\
180 std::enable_if_t<sizeof(ElementType) * SUB_VL * MAX_VL == (size)>> \\
181 final \\
182 { \\
183 typedef ElementType Type __attribute__((vector_size(size))); \\
184 };
185
186 #ifdef SIMPLEV_USE_NONPOT_VECTORS
187 #define SIMPLEV_MAKE_VEC_TYPE_NONPOT(size) SIMPLEV_MAKE_VEC_TYPE(size)
188 #else
189 #define SIMPLEV_MAKE_VEC_TYPE_NONPOT(size)
190 #endif
191
192 """)
193 for i in range(1, 128 + 1):
194 if is_power_of_2(i):
195 o.write(f"SIMPLEV_MAKE_VEC_TYPE({i})\n")
196 else:
197 o.write(f"SIMPLEV_MAKE_VEC_TYPE_NONPOT({i})\n")
198 if i == 8:
199 o.write("#ifdef SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS\n")
200 o.write(f"""#endif // SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS
201
202 template <std::size_t MAX_VL>
203 struct VL final
204 {{
205 static_assert(MAX_VL > 0 && MAX_VL <= 64);
206 std::size_t value;
207 }};
208
209 template <std::size_t MAX_VL>
210 inline __attribute__((always_inline)) VL<MAX_VL> setvl(std::size_t vl)
211 {{
212 VL<MAX_VL> retval;
213 asm volatile(
214 "# setvl %[retval], %[vl], MVL=%[max_vl]\\n\\t"
215 ".long %[instr] | (%[retval] << %[rt_shift]) | (%[vl] << %[ra_shift])"
216 : [retval] "=b"(retval.value)
217 : [vl] "b"(vl), [max_vl] "n"(MAX_VL), [instr] "n"({FIXME___FINISH}));
218 return retval;
219 }}
220 }} // namespace sv
221
222 #undef SIMPLEV_MAKE_VEC_TYPE
223 #undef SIMPLEV_MAKE_VEC_TYPE_NONPOT
224 #undef SIMPLEV_USE_NONPOT_VECTORS
225 #undef SIMPLEV_USE_BIGGER_THAN_8_BYTE_VECTORS
226 """)