41179d045cdbf1442ad1f31e818124d9ced00705
[yosys.git] / kernel / calc.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 // [[CITE]] Power-Modulus Algorithm
21 // Schneier, Bruce (1996). Applied Cryptography: Protocols, Algorithms, and Source Code in C,
22 // Second Edition (2nd ed.). Wiley. ISBN 978-0-471-11709-4, page 244
23
24 #include "kernel/yosys.h"
25 #include "libs/bigint/BigIntegerLibrary.hh"
26
27 YOSYS_NAMESPACE_BEGIN
28
29 static void extend_u0(RTLIL::Const &arg, int width, bool is_signed)
30 {
31 RTLIL::State padding = RTLIL::State::S0;
32
33 if (arg.bits.size() > 0 && is_signed)
34 padding = arg.bits.back();
35
36 while (int(arg.bits.size()) < width)
37 arg.bits.push_back(padding);
38
39 arg.bits.resize(width);
40 }
41
42 static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos)
43 {
44 BigInteger result = 0, this_bit = 1;
45 for (size_t i = 0; i < val.bits.size(); i++) {
46 if (val.bits[i] == RTLIL::State::S1) {
47 if (as_signed && i+1 == val.bits.size())
48 result -= this_bit;
49 else
50 result += this_bit;
51 }
52 else if (val.bits[i] != RTLIL::State::S0) {
53 if (undef_bit_pos < 0)
54 undef_bit_pos = i;
55 }
56 this_bit *= 2;
57 }
58 return result;
59 }
60
61 static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_bit_pos)
62 {
63 if (undef_bit_pos >= 0)
64 return RTLIL::Const(RTLIL::State::Sx, result_len);
65
66 BigUnsigned mag = val.getMagnitude();
67 RTLIL::Const result(0, result_len);
68
69 if (!mag.isZero())
70 {
71 if (val.getSign() < 0)
72 {
73 mag--;
74 for (int i = 0; i < result_len; i++)
75 result.bits[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1;
76 }
77 else
78 {
79 for (int i = 0; i < result_len; i++)
80 result.bits[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0;
81 }
82 }
83
84 #if 0
85 if (undef_bit_pos >= 0)
86 for (int i = undef_bit_pos; i < result_len; i++)
87 result.bits[i] = RTLIL::State::Sx;
88 #endif
89
90 return result;
91 }
92
93 static RTLIL::State logic_and(RTLIL::State a, RTLIL::State b)
94 {
95 if (a == RTLIL::State::S0) return RTLIL::State::S0;
96 if (b == RTLIL::State::S0) return RTLIL::State::S0;
97 if (a != RTLIL::State::S1) return RTLIL::State::Sx;
98 if (b != RTLIL::State::S1) return RTLIL::State::Sx;
99 return RTLIL::State::S1;
100 }
101
102 static RTLIL::State logic_or(RTLIL::State a, RTLIL::State b)
103 {
104 if (a == RTLIL::State::S1) return RTLIL::State::S1;
105 if (b == RTLIL::State::S1) return RTLIL::State::S1;
106 if (a != RTLIL::State::S0) return RTLIL::State::Sx;
107 if (b != RTLIL::State::S0) return RTLIL::State::Sx;
108 return RTLIL::State::S0;
109 }
110
111 static RTLIL::State logic_xor(RTLIL::State a, RTLIL::State b)
112 {
113 if (a != RTLIL::State::S0 && a != RTLIL::State::S1) return RTLIL::State::Sx;
114 if (b != RTLIL::State::S0 && b != RTLIL::State::S1) return RTLIL::State::Sx;
115 return a != b ? RTLIL::State::S1 : RTLIL::State::S0;
116 }
117
118 static RTLIL::State logic_xnor(RTLIL::State a, RTLIL::State b)
119 {
120 if (a != RTLIL::State::S0 && a != RTLIL::State::S1) return RTLIL::State::Sx;
121 if (b != RTLIL::State::S0 && b != RTLIL::State::S1) return RTLIL::State::Sx;
122 return a == b ? RTLIL::State::S1 : RTLIL::State::S0;
123 }
124
125 RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
126 {
127 if (result_len < 0)
128 result_len = arg1.bits.size();
129
130 RTLIL::Const arg1_ext = arg1;
131 extend_u0(arg1_ext, result_len, signed1);
132
133 RTLIL::Const result(RTLIL::State::Sx, result_len);
134 for (size_t i = 0; i < size_t(result_len); i++) {
135 if (i >= arg1_ext.bits.size())
136 result.bits[i] = RTLIL::State::S0;
137 else if (arg1_ext.bits[i] == RTLIL::State::S0)
138 result.bits[i] = RTLIL::State::S1;
139 else if (arg1_ext.bits[i] == RTLIL::State::S1)
140 result.bits[i] = RTLIL::State::S0;
141 }
142
143 return result;
144 }
145
146 static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL::State),
147 RTLIL::Const arg1, RTLIL::Const arg2, bool signed1, bool signed2, int result_len = -1)
148 {
149 if (result_len < 0)
150 result_len = std::max(arg1.bits.size(), arg2.bits.size());
151
152 extend_u0(arg1, result_len, signed1);
153 extend_u0(arg2, result_len, signed2);
154
155 RTLIL::Const result(RTLIL::State::Sx, result_len);
156 for (size_t i = 0; i < size_t(result_len); i++) {
157 RTLIL::State a = i < arg1.bits.size() ? arg1.bits[i] : RTLIL::State::S0;
158 RTLIL::State b = i < arg2.bits.size() ? arg2.bits[i] : RTLIL::State::S0;
159 result.bits[i] = logic_func(a, b);
160 }
161
162 return result;
163 }
164
165 RTLIL::Const RTLIL::const_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
166 {
167 return logic_wrapper(logic_and, arg1, arg2, signed1, signed2, result_len);
168 }
169
170 RTLIL::Const RTLIL::const_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
171 {
172 return logic_wrapper(logic_or, arg1, arg2, signed1, signed2, result_len);
173 }
174
175 RTLIL::Const RTLIL::const_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
176 {
177 return logic_wrapper(logic_xor, arg1, arg2, signed1, signed2, result_len);
178 }
179
180 RTLIL::Const RTLIL::const_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
181 {
182 return logic_wrapper(logic_xnor, arg1, arg2, signed1, signed2, result_len);
183 }
184
185 static RTLIL::Const logic_reduce_wrapper(RTLIL::State initial, RTLIL::State(*logic_func)(RTLIL::State, RTLIL::State), const RTLIL::Const &arg1, int result_len)
186 {
187 RTLIL::State temp = initial;
188
189 for (size_t i = 0; i < arg1.bits.size(); i++)
190 temp = logic_func(temp, arg1.bits[i]);
191
192 RTLIL::Const result(temp);
193 while (int(result.bits.size()) < result_len)
194 result.bits.push_back(RTLIL::State::S0);
195 return result;
196 }
197
198 RTLIL::Const RTLIL::const_reduce_and(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
199 {
200 return logic_reduce_wrapper(RTLIL::State::S1, logic_and, arg1, result_len);
201 }
202
203 RTLIL::Const RTLIL::const_reduce_or(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
204 {
205 return logic_reduce_wrapper(RTLIL::State::S0, logic_or, arg1, result_len);
206 }
207
208 RTLIL::Const RTLIL::const_reduce_xor(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
209 {
210 return logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len);
211 }
212
213 RTLIL::Const RTLIL::const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
214 {
215 RTLIL::Const buffer = logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len);
216 if (!buffer.bits.empty()) {
217 if (buffer.bits.front() == RTLIL::State::S0)
218 buffer.bits.front() = RTLIL::State::S1;
219 else if (buffer.bits.front() == RTLIL::State::S1)
220 buffer.bits.front() = RTLIL::State::S0;
221 }
222 return buffer;
223 }
224
225 RTLIL::Const RTLIL::const_reduce_bool(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
226 {
227 return logic_reduce_wrapper(RTLIL::State::S0, logic_or, arg1, result_len);
228 }
229
230 RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
231 {
232 int undef_bit_pos_a = -1;
233 BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
234 RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0);
235
236 while (int(result.bits.size()) < result_len)
237 result.bits.push_back(RTLIL::State::S0);
238 return result;
239 }
240
241 RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
242 {
243 int undef_bit_pos_a = -1, undef_bit_pos_b = -1;
244 BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
245 BigInteger b = const2big(arg2, signed2, undef_bit_pos_b);
246
247 RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
248 RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
249 RTLIL::Const result(logic_and(bit_a, bit_b));
250
251 while (int(result.bits.size()) < result_len)
252 result.bits.push_back(RTLIL::State::S0);
253 return result;
254 }
255
256 RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
257 {
258 int undef_bit_pos_a = -1, undef_bit_pos_b = -1;
259 BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
260 BigInteger b = const2big(arg2, signed2, undef_bit_pos_b);
261
262 RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
263 RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
264 RTLIL::Const result(logic_or(bit_a, bit_b));
265
266 while (int(result.bits.size()) < result_len)
267 result.bits.push_back(RTLIL::State::S0);
268 return result;
269 }
270
271 static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, int direction, int result_len)
272 {
273 int undef_bit_pos = -1;
274 BigInteger offset = const2big(arg2, false, undef_bit_pos) * direction;
275
276 if (result_len < 0)
277 result_len = arg1.bits.size();
278
279 RTLIL::Const result(RTLIL::State::Sx, result_len);
280 if (undef_bit_pos >= 0)
281 return result;
282
283 for (int i = 0; i < result_len; i++) {
284 BigInteger pos = BigInteger(i) + offset;
285 if (pos < 0)
286 result.bits[i] = RTLIL::State::S0;
287 else if (pos >= arg1.bits.size())
288 result.bits[i] = sign_ext ? arg1.bits.back() : RTLIL::State::S0;
289 else
290 result.bits[i] = arg1.bits[pos.toInt()];
291 }
292
293 return result;
294 }
295
296 RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
297 {
298 RTLIL::Const arg1_ext = arg1;
299 extend_u0(arg1_ext, result_len, signed1);
300 return const_shift_worker(arg1_ext, arg2, false, -1, result_len);
301 }
302
303 RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
304 {
305 RTLIL::Const arg1_ext = arg1;
306 extend_u0(arg1_ext, std::max(result_len, SIZE(arg1)), signed1);
307 return const_shift_worker(arg1_ext, arg2, false, +1, result_len);
308 }
309
310 RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
311 {
312 if (!signed1)
313 return const_shl(arg1, arg2, signed1, signed2, result_len);
314 return const_shift_worker(arg1, arg2, true, -1, result_len);
315 }
316
317 RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
318 {
319 if (!signed1)
320 return const_shr(arg1, arg2, signed1, signed2, result_len);
321 return const_shift_worker(arg1, arg2, true, +1, result_len);
322 }
323
324 static RTLIL::Const const_shift_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool signed2, int result_len, RTLIL::State other_bits)
325 {
326 int undef_bit_pos = -1;
327 BigInteger offset = const2big(arg2, signed2, undef_bit_pos);
328
329 if (result_len < 0)
330 result_len = arg1.bits.size();
331
332 RTLIL::Const result(RTLIL::State::Sx, result_len);
333 if (undef_bit_pos >= 0)
334 return result;
335
336 for (int i = 0; i < result_len; i++) {
337 BigInteger pos = BigInteger(i) + offset;
338 if (pos < 0 || pos >= arg1.bits.size())
339 result.bits[i] = other_bits;
340 else
341 result.bits[i] = arg1.bits[pos.toInt()];
342 }
343
344 return result;
345 }
346
347 RTLIL::Const RTLIL::const_shift(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
348 {
349 return const_shift_shiftx(arg1, arg2, signed1, signed2, result_len, RTLIL::State::S0);
350 }
351
352 RTLIL::Const RTLIL::const_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
353 {
354 return const_shift_shiftx(arg1, arg2, signed1, signed2, result_len, RTLIL::State::Sx);
355 }
356
357 RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
358 {
359 int undef_bit_pos = -1;
360 bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos);
361 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
362
363 while (int(result.bits.size()) < result_len)
364 result.bits.push_back(RTLIL::State::S0);
365 return result;
366 }
367
368 RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
369 {
370 int undef_bit_pos = -1;
371 bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos);
372 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
373
374 while (int(result.bits.size()) < result_len)
375 result.bits.push_back(RTLIL::State::S0);
376 return result;
377 }
378
379 RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
380 {
381 RTLIL::Const arg1_ext = arg1;
382 RTLIL::Const arg2_ext = arg2;
383 RTLIL::Const result(RTLIL::State::S0, result_len);
384
385 int width = std::max(arg1_ext.bits.size(), arg2_ext.bits.size());
386 extend_u0(arg1_ext, width, signed1 && signed2);
387 extend_u0(arg2_ext, width, signed1 && signed2);
388
389 RTLIL::State matched_status = RTLIL::State::S1;
390 for (size_t i = 0; i < arg1_ext.bits.size(); i++) {
391 if (arg1_ext.bits.at(i) == RTLIL::State::S0 && arg2_ext.bits.at(i) == RTLIL::State::S1)
392 return result;
393 if (arg1_ext.bits.at(i) == RTLIL::State::S1 && arg2_ext.bits.at(i) == RTLIL::State::S0)
394 return result;
395 if (arg1_ext.bits.at(i) > RTLIL::State::S1 || arg2_ext.bits.at(i) > RTLIL::State::S1)
396 matched_status = RTLIL::State::Sx;
397 }
398
399 result.bits.front() = matched_status;
400 return result;
401 }
402
403 RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
404 {
405 RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len);
406 if (result.bits.front() == RTLIL::State::S0)
407 result.bits.front() = RTLIL::State::S1;
408 else if (result.bits.front() == RTLIL::State::S1)
409 result.bits.front() = RTLIL::State::S0;
410 return result;
411 }
412
413 RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
414 {
415 RTLIL::Const arg1_ext = arg1;
416 RTLIL::Const arg2_ext = arg2;
417 RTLIL::Const result(RTLIL::State::S0, result_len);
418
419 int width = std::max(arg1_ext.bits.size(), arg2_ext.bits.size());
420 extend_u0(arg1_ext, width, signed1 && signed2);
421 extend_u0(arg2_ext, width, signed1 && signed2);
422
423 for (size_t i = 0; i < arg1_ext.bits.size(); i++) {
424 if (arg1_ext.bits.at(i) != arg2_ext.bits.at(i))
425 return result;
426 }
427
428 result.bits.front() = RTLIL::State::S1;
429 return result;
430 }
431
432 RTLIL::Const RTLIL::const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
433 {
434 RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len);
435 if (result.bits.front() == RTLIL::State::S0)
436 result.bits.front() = RTLIL::State::S1;
437 else if (result.bits.front() == RTLIL::State::S1)
438 result.bits.front() = RTLIL::State::S0;
439 return result;
440 }
441
442 RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
443 {
444 int undef_bit_pos = -1;
445 bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos);
446 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
447
448 while (int(result.bits.size()) < result_len)
449 result.bits.push_back(RTLIL::State::S0);
450 return result;
451 }
452
453 RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
454 {
455 int undef_bit_pos = -1;
456 bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos);
457 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
458
459 while (int(result.bits.size()) < result_len)
460 result.bits.push_back(RTLIL::State::S0);
461 return result;
462 }
463
464 RTLIL::Const RTLIL::const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
465 {
466 int undef_bit_pos = -1;
467 BigInteger y = const2big(arg1, signed1, undef_bit_pos) + const2big(arg2, signed2, undef_bit_pos);
468 return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
469 }
470
471 RTLIL::Const RTLIL::const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
472 {
473 int undef_bit_pos = -1;
474 BigInteger y = const2big(arg1, signed1, undef_bit_pos) - const2big(arg2, signed2, undef_bit_pos);
475 return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
476 }
477
478 RTLIL::Const RTLIL::const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
479 {
480 int undef_bit_pos = -1;
481 BigInteger y = const2big(arg1, signed1, undef_bit_pos) * const2big(arg2, signed2, undef_bit_pos);
482 return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
483 }
484
485 RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
486 {
487 int undef_bit_pos = -1;
488 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
489 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
490 if (b.isZero())
491 return RTLIL::Const(RTLIL::State::Sx, result_len);
492 bool result_neg = (a.getSign() == BigInteger::negative) != (b.getSign() == BigInteger::negative);
493 a = a.getSign() == BigInteger::negative ? -a : a;
494 b = b.getSign() == BigInteger::negative ? -b : b;
495 return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
496 }
497
498 RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
499 {
500 int undef_bit_pos = -1;
501 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
502 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
503 if (b.isZero())
504 return RTLIL::Const(RTLIL::State::Sx, result_len);
505 bool result_neg = a.getSign() == BigInteger::negative;
506 a = a.getSign() == BigInteger::negative ? -a : a;
507 b = b.getSign() == BigInteger::negative ? -b : b;
508 return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
509 }
510
511 RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
512 {
513 int undef_bit_pos = -1;
514
515 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
516 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
517 BigInteger y = 1;
518
519 if (a == 0 && b < 0)
520 return RTLIL::Const(RTLIL::State::Sx, result_len);
521
522 if (a == 0 && b > 0)
523 return RTLIL::Const(RTLIL::State::S0, result_len);
524
525 if (b < 0)
526 {
527 if (a < -1 || a > 1)
528 y = 0;
529 if (a == -1)
530 y = (-b % 2) == 0 ? 1 : -1;
531 }
532
533 if (b > 0)
534 {
535 // Power-modulo with 2^result_len as modulus
536 BigInteger modulus = 1;
537 int modulus_bits = (result_len >= 0 ? result_len : 1024);
538 for (int i = 0; i < modulus_bits; i++)
539 modulus *= 2;
540
541 bool flip_result_sign = false;
542 if (a < 0) {
543 a *= -1;
544 if (b % 2 == 1)
545 flip_result_sign = true;
546 }
547
548 while (b > 0) {
549 if (b % 2 == 1)
550 y = (y * a) % modulus;
551 b = b / 2;
552 a = (a * a) % modulus;
553 }
554
555 if (flip_result_sign)
556 y *= -1;
557 }
558
559 return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
560 }
561
562 RTLIL::Const RTLIL::const_pos(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
563 {
564 RTLIL::Const arg1_ext = arg1;
565 extend_u0(arg1_ext, result_len, signed1);
566
567 return arg1_ext;
568 }
569
570 RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
571 {
572 RTLIL::Const arg1_ext = arg1;
573 RTLIL::Const zero(RTLIL::State::S0, 1);
574
575 return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len);
576 }
577
578 YOSYS_NAMESPACE_END
579