1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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
extend_u0(RTLIL::Const & arg,int width,bool is_signed)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
const2big(const RTLIL::Const & val,bool as_signed,int & undef_bit_pos)42 static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos)
43 {
44 BigUnsigned mag;
45
46 BigInteger::Sign sign = BigInteger::positive;
47 State inv_sign_bit = RTLIL::State::S1;
48 size_t num_bits = val.bits.size();
49
50 if (as_signed && num_bits && val.bits[num_bits-1] == RTLIL::State::S1) {
51 inv_sign_bit = RTLIL::State::S0;
52 sign = BigInteger::negative;
53 num_bits--;
54 }
55
56 for (size_t i = 0; i < num_bits; i++)
57 if (val.bits[i] == RTLIL::State::S0 || val.bits[i] == RTLIL::State::S1)
58 mag.setBit(i, val.bits[i] == inv_sign_bit);
59 else if (undef_bit_pos < 0)
60 undef_bit_pos = i;
61
62 if (sign == BigInteger::negative)
63 mag += 1;
64
65 return BigInteger(mag, sign);
66 }
67
big2const(const BigInteger & val,int result_len,int undef_bit_pos)68 static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_bit_pos)
69 {
70 if (undef_bit_pos >= 0)
71 return RTLIL::Const(RTLIL::State::Sx, result_len);
72
73 BigUnsigned mag = val.getMagnitude();
74 RTLIL::Const result(0, result_len);
75
76 if (!mag.isZero())
77 {
78 if (val.getSign() < 0)
79 {
80 mag--;
81 for (int i = 0; i < result_len; i++)
82 result.bits[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1;
83 }
84 else
85 {
86 for (int i = 0; i < result_len; i++)
87 result.bits[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0;
88 }
89 }
90
91 #if 0
92 if (undef_bit_pos >= 0)
93 for (int i = undef_bit_pos; i < result_len; i++)
94 result.bits[i] = RTLIL::State::Sx;
95 #endif
96
97 return result;
98 }
99
logic_and(RTLIL::State a,RTLIL::State b)100 static RTLIL::State logic_and(RTLIL::State a, RTLIL::State b)
101 {
102 if (a == RTLIL::State::S0) return RTLIL::State::S0;
103 if (b == RTLIL::State::S0) return RTLIL::State::S0;
104 if (a != RTLIL::State::S1) return RTLIL::State::Sx;
105 if (b != RTLIL::State::S1) return RTLIL::State::Sx;
106 return RTLIL::State::S1;
107 }
108
logic_or(RTLIL::State a,RTLIL::State b)109 static RTLIL::State logic_or(RTLIL::State a, RTLIL::State b)
110 {
111 if (a == RTLIL::State::S1) return RTLIL::State::S1;
112 if (b == RTLIL::State::S1) return RTLIL::State::S1;
113 if (a != RTLIL::State::S0) return RTLIL::State::Sx;
114 if (b != RTLIL::State::S0) return RTLIL::State::Sx;
115 return RTLIL::State::S0;
116 }
117
logic_xor(RTLIL::State a,RTLIL::State b)118 static RTLIL::State logic_xor(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
logic_xnor(RTLIL::State a,RTLIL::State b)125 static RTLIL::State logic_xnor(RTLIL::State a, RTLIL::State b)
126 {
127 if (a != RTLIL::State::S0 && a != RTLIL::State::S1) return RTLIL::State::Sx;
128 if (b != RTLIL::State::S0 && b != RTLIL::State::S1) return RTLIL::State::Sx;
129 return a == b ? RTLIL::State::S1 : RTLIL::State::S0;
130 }
131
const_not(const RTLIL::Const & arg1,const RTLIL::Const &,bool signed1,bool,int result_len)132 RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
133 {
134 if (result_len < 0)
135 result_len = arg1.bits.size();
136
137 RTLIL::Const arg1_ext = arg1;
138 extend_u0(arg1_ext, result_len, signed1);
139
140 RTLIL::Const result(RTLIL::State::Sx, result_len);
141 for (size_t i = 0; i < size_t(result_len); i++) {
142 if (i >= arg1_ext.bits.size())
143 result.bits[i] = RTLIL::State::S0;
144 else if (arg1_ext.bits[i] == RTLIL::State::S0)
145 result.bits[i] = RTLIL::State::S1;
146 else if (arg1_ext.bits[i] == RTLIL::State::S1)
147 result.bits[i] = RTLIL::State::S0;
148 }
149
150 return result;
151 }
152
logic_wrapper(RTLIL::State (* logic_func)(RTLIL::State,RTLIL::State),RTLIL::Const arg1,RTLIL::Const arg2,bool signed1,bool signed2,int result_len=-1)153 static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL::State),
154 RTLIL::Const arg1, RTLIL::Const arg2, bool signed1, bool signed2, int result_len = -1)
155 {
156 if (result_len < 0)
157 result_len = max(arg1.bits.size(), arg2.bits.size());
158
159 extend_u0(arg1, result_len, signed1);
160 extend_u0(arg2, result_len, signed2);
161
162 RTLIL::Const result(RTLIL::State::Sx, result_len);
163 for (size_t i = 0; i < size_t(result_len); i++) {
164 RTLIL::State a = i < arg1.bits.size() ? arg1.bits[i] : RTLIL::State::S0;
165 RTLIL::State b = i < arg2.bits.size() ? arg2.bits[i] : RTLIL::State::S0;
166 result.bits[i] = logic_func(a, b);
167 }
168
169 return result;
170 }
171
const_and(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)172 RTLIL::Const RTLIL::const_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
173 {
174 return logic_wrapper(logic_and, arg1, arg2, signed1, signed2, result_len);
175 }
176
const_or(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)177 RTLIL::Const RTLIL::const_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
178 {
179 return logic_wrapper(logic_or, arg1, arg2, signed1, signed2, result_len);
180 }
181
const_xor(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)182 RTLIL::Const RTLIL::const_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
183 {
184 return logic_wrapper(logic_xor, arg1, arg2, signed1, signed2, result_len);
185 }
186
const_xnor(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)187 RTLIL::Const RTLIL::const_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
188 {
189 return logic_wrapper(logic_xnor, arg1, arg2, signed1, signed2, result_len);
190 }
191
logic_reduce_wrapper(RTLIL::State initial,RTLIL::State (* logic_func)(RTLIL::State,RTLIL::State),const RTLIL::Const & arg1,int result_len)192 static RTLIL::Const logic_reduce_wrapper(RTLIL::State initial, RTLIL::State(*logic_func)(RTLIL::State, RTLIL::State), const RTLIL::Const &arg1, int result_len)
193 {
194 RTLIL::State temp = initial;
195
196 for (size_t i = 0; i < arg1.bits.size(); i++)
197 temp = logic_func(temp, arg1.bits[i]);
198
199 RTLIL::Const result(temp);
200 while (int(result.bits.size()) < result_len)
201 result.bits.push_back(RTLIL::State::S0);
202 return result;
203 }
204
const_reduce_and(const RTLIL::Const & arg1,const RTLIL::Const &,bool,bool,int result_len)205 RTLIL::Const RTLIL::const_reduce_and(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
206 {
207 return logic_reduce_wrapper(RTLIL::State::S1, logic_and, arg1, result_len);
208 }
209
const_reduce_or(const RTLIL::Const & arg1,const RTLIL::Const &,bool,bool,int result_len)210 RTLIL::Const RTLIL::const_reduce_or(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
211 {
212 return logic_reduce_wrapper(RTLIL::State::S0, logic_or, arg1, result_len);
213 }
214
const_reduce_xor(const RTLIL::Const & arg1,const RTLIL::Const &,bool,bool,int result_len)215 RTLIL::Const RTLIL::const_reduce_xor(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
216 {
217 return logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len);
218 }
219
const_reduce_xnor(const RTLIL::Const & arg1,const RTLIL::Const &,bool,bool,int result_len)220 RTLIL::Const RTLIL::const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
221 {
222 RTLIL::Const buffer = logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len);
223 if (!buffer.bits.empty()) {
224 if (buffer.bits.front() == RTLIL::State::S0)
225 buffer.bits.front() = RTLIL::State::S1;
226 else if (buffer.bits.front() == RTLIL::State::S1)
227 buffer.bits.front() = RTLIL::State::S0;
228 }
229 return buffer;
230 }
231
const_reduce_bool(const RTLIL::Const & arg1,const RTLIL::Const &,bool,bool,int result_len)232 RTLIL::Const RTLIL::const_reduce_bool(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
233 {
234 return logic_reduce_wrapper(RTLIL::State::S0, logic_or, arg1, result_len);
235 }
236
const_logic_not(const RTLIL::Const & arg1,const RTLIL::Const &,bool signed1,bool,int result_len)237 RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
238 {
239 int undef_bit_pos_a = -1;
240 BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
241 RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0);
242
243 while (int(result.bits.size()) < result_len)
244 result.bits.push_back(RTLIL::State::S0);
245 return result;
246 }
247
const_logic_and(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)248 RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
249 {
250 int undef_bit_pos_a = -1, undef_bit_pos_b = -1;
251 BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
252 BigInteger b = const2big(arg2, signed2, undef_bit_pos_b);
253
254 RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
255 RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
256 RTLIL::Const result(logic_and(bit_a, bit_b));
257
258 while (int(result.bits.size()) < result_len)
259 result.bits.push_back(RTLIL::State::S0);
260 return result;
261 }
262
const_logic_or(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)263 RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
264 {
265 int undef_bit_pos_a = -1, undef_bit_pos_b = -1;
266 BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
267 BigInteger b = const2big(arg2, signed2, undef_bit_pos_b);
268
269 RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
270 RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
271 RTLIL::Const result(logic_or(bit_a, bit_b));
272
273 while (int(result.bits.size()) < result_len)
274 result.bits.push_back(RTLIL::State::S0);
275 return result;
276 }
277
278 // Shift `arg1` by `arg2` bits.
279 // If `direction` is +1, `arg1` is shifted right by `arg2` bits; if `direction` is -1, `arg1` is shifted left by `arg2` bits.
280 // If `signed2` is true, `arg2` is interpreted as a signed integer; a negative `arg2` will cause a shift in the opposite direction.
281 // Any required bits outside the bounds of `arg1` are padded with `vacant_bits` unless `sign_ext` is true, in which case any bits outside the left
282 // bounds are filled with the leftmost bit of `arg1` (arithmetic shift).
const_shift_worker(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool sign_ext,bool signed2,int direction,int result_len,RTLIL::State vacant_bits=RTLIL::State::S0)283 static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, bool signed2, int direction, int result_len, RTLIL::State vacant_bits = RTLIL::State::S0)
284 {
285 int undef_bit_pos = -1;
286 BigInteger offset = const2big(arg2, signed2, undef_bit_pos) * direction;
287
288 if (result_len < 0)
289 result_len = arg1.bits.size();
290
291 RTLIL::Const result(RTLIL::State::Sx, result_len);
292 if (undef_bit_pos >= 0)
293 return result;
294
295 for (int i = 0; i < result_len; i++) {
296 BigInteger pos = BigInteger(i) + offset;
297 if (pos < 0)
298 result.bits[i] = vacant_bits;
299 else if (pos >= BigInteger(int(arg1.bits.size())))
300 result.bits[i] = sign_ext ? arg1.bits.back() : vacant_bits;
301 else
302 result.bits[i] = arg1.bits[pos.toInt()];
303 }
304
305 return result;
306 }
307
const_shl(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool,int result_len)308 RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
309 {
310 RTLIL::Const arg1_ext = arg1;
311 extend_u0(arg1_ext, result_len, signed1);
312 return const_shift_worker(arg1_ext, arg2, false, false, -1, result_len);
313 }
314
const_shr(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool,int result_len)315 RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
316 {
317 RTLIL::Const arg1_ext = arg1;
318 extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
319 return const_shift_worker(arg1_ext, arg2, false, false, +1, result_len);
320 }
321
const_sshl(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool,int result_len)322 RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
323 {
324 return const_shift_worker(arg1, arg2, signed1, false, -1, result_len);
325 }
326
const_sshr(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool,int result_len)327 RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
328 {
329 return const_shift_worker(arg1, arg2, signed1, false, +1, result_len);
330 }
331
const_shift(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)332 RTLIL::Const RTLIL::const_shift(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
333 {
334 RTLIL::Const arg1_ext = arg1;
335 extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
336 return const_shift_worker(arg1_ext, arg2, false, signed2, +1, result_len);
337 }
338
const_shiftx(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool,bool signed2,int result_len)339 RTLIL::Const RTLIL::const_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool signed2, int result_len)
340 {
341 return const_shift_worker(arg1, arg2, false, signed2, +1, result_len, RTLIL::State::Sx);
342 }
343
const_lt(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)344 RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
345 {
346 int undef_bit_pos = -1;
347 bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos);
348 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
349
350 while (int(result.bits.size()) < result_len)
351 result.bits.push_back(RTLIL::State::S0);
352 return result;
353 }
354
const_le(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)355 RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
356 {
357 int undef_bit_pos = -1;
358 bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos);
359 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
360
361 while (int(result.bits.size()) < result_len)
362 result.bits.push_back(RTLIL::State::S0);
363 return result;
364 }
365
const_eq(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)366 RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
367 {
368 RTLIL::Const arg1_ext = arg1;
369 RTLIL::Const arg2_ext = arg2;
370 RTLIL::Const result(RTLIL::State::S0, result_len);
371
372 int width = max(arg1_ext.bits.size(), arg2_ext.bits.size());
373 extend_u0(arg1_ext, width, signed1 && signed2);
374 extend_u0(arg2_ext, width, signed1 && signed2);
375
376 RTLIL::State matched_status = RTLIL::State::S1;
377 for (size_t i = 0; i < arg1_ext.bits.size(); i++) {
378 if (arg1_ext.bits.at(i) == RTLIL::State::S0 && arg2_ext.bits.at(i) == RTLIL::State::S1)
379 return result;
380 if (arg1_ext.bits.at(i) == RTLIL::State::S1 && arg2_ext.bits.at(i) == RTLIL::State::S0)
381 return result;
382 if (arg1_ext.bits.at(i) > RTLIL::State::S1 || arg2_ext.bits.at(i) > RTLIL::State::S1)
383 matched_status = RTLIL::State::Sx;
384 }
385
386 result.bits.front() = matched_status;
387 return result;
388 }
389
const_ne(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)390 RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
391 {
392 RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len);
393 if (result.bits.front() == RTLIL::State::S0)
394 result.bits.front() = RTLIL::State::S1;
395 else if (result.bits.front() == RTLIL::State::S1)
396 result.bits.front() = RTLIL::State::S0;
397 return result;
398 }
399
const_eqx(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)400 RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
401 {
402 RTLIL::Const arg1_ext = arg1;
403 RTLIL::Const arg2_ext = arg2;
404 RTLIL::Const result(RTLIL::State::S0, result_len);
405
406 int width = max(arg1_ext.bits.size(), arg2_ext.bits.size());
407 extend_u0(arg1_ext, width, signed1 && signed2);
408 extend_u0(arg2_ext, width, signed1 && signed2);
409
410 for (size_t i = 0; i < arg1_ext.bits.size(); i++) {
411 if (arg1_ext.bits.at(i) != arg2_ext.bits.at(i))
412 return result;
413 }
414
415 result.bits.front() = RTLIL::State::S1;
416 return result;
417 }
418
const_nex(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)419 RTLIL::Const RTLIL::const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
420 {
421 RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len);
422 if (result.bits.front() == RTLIL::State::S0)
423 result.bits.front() = RTLIL::State::S1;
424 else if (result.bits.front() == RTLIL::State::S1)
425 result.bits.front() = RTLIL::State::S0;
426 return result;
427 }
428
const_ge(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)429 RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
430 {
431 int undef_bit_pos = -1;
432 bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos);
433 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
434
435 while (int(result.bits.size()) < result_len)
436 result.bits.push_back(RTLIL::State::S0);
437 return result;
438 }
439
const_gt(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)440 RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
441 {
442 int undef_bit_pos = -1;
443 bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos);
444 RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
445
446 while (int(result.bits.size()) < result_len)
447 result.bits.push_back(RTLIL::State::S0);
448 return result;
449 }
450
const_add(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)451 RTLIL::Const RTLIL::const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
452 {
453 int undef_bit_pos = -1;
454 BigInteger y = const2big(arg1, signed1, undef_bit_pos) + const2big(arg2, signed2, undef_bit_pos);
455 return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
456 }
457
const_sub(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)458 RTLIL::Const RTLIL::const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
459 {
460 int undef_bit_pos = -1;
461 BigInteger y = const2big(arg1, signed1, undef_bit_pos) - const2big(arg2, signed2, undef_bit_pos);
462 return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
463 }
464
const_mul(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)465 RTLIL::Const RTLIL::const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
466 {
467 int undef_bit_pos = -1;
468 BigInteger y = const2big(arg1, signed1, undef_bit_pos) * const2big(arg2, signed2, undef_bit_pos);
469 return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
470 }
471
472 // truncating division
const_div(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)473 RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
474 {
475 int undef_bit_pos = -1;
476 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
477 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
478 if (b.isZero())
479 return RTLIL::Const(RTLIL::State::Sx, result_len);
480 bool result_neg = (a.getSign() == BigInteger::negative) != (b.getSign() == BigInteger::negative);
481 a = a.getSign() == BigInteger::negative ? -a : a;
482 b = b.getSign() == BigInteger::negative ? -b : b;
483 return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
484 }
485
486 // truncating modulo
const_mod(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)487 RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
488 {
489 int undef_bit_pos = -1;
490 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
491 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
492 if (b.isZero())
493 return RTLIL::Const(RTLIL::State::Sx, result_len);
494 bool result_neg = a.getSign() == BigInteger::negative;
495 a = a.getSign() == BigInteger::negative ? -a : a;
496 b = b.getSign() == BigInteger::negative ? -b : b;
497 return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
498 }
499
const_divfloor(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)500 RTLIL::Const RTLIL::const_divfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
501 {
502 int undef_bit_pos = -1;
503 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
504 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
505 if (b.isZero())
506 return RTLIL::Const(RTLIL::State::Sx, result_len);
507
508 bool result_pos = (a.getSign() == BigInteger::negative) == (b.getSign() == BigInteger::negative);
509 a = a.getSign() == BigInteger::negative ? -a : a;
510 b = b.getSign() == BigInteger::negative ? -b : b;
511 BigInteger result;
512
513 if (result_pos || a == 0) {
514 result = a / b;
515 } else {
516 // bigint division with negative numbers is wonky, make sure we only negate at the very end
517 result = -((a + b - 1) / b);
518 }
519 return big2const(result, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
520 }
521
const_modfloor(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)522 RTLIL::Const RTLIL::const_modfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
523 {
524 int undef_bit_pos = -1;
525 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
526 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
527 if (b.isZero())
528 return RTLIL::Const(RTLIL::State::Sx, result_len);
529
530 BigInteger::Sign a_sign = a.getSign();
531 BigInteger::Sign b_sign = b.getSign();
532 a = a_sign == BigInteger::negative ? -a : a;
533 b = b_sign == BigInteger::negative ? -b : b;
534 BigInteger truncated = a_sign == BigInteger::negative ? -(a % b) : (a % b);
535 BigInteger modulo;
536
537 if (truncated == 0 || (a_sign == b_sign)) {
538 modulo = truncated;
539 } else {
540 modulo = b_sign == BigInteger::negative ? truncated - b : truncated + b;
541 }
542 return big2const(modulo, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
543 }
544
const_pow(const RTLIL::Const & arg1,const RTLIL::Const & arg2,bool signed1,bool signed2,int result_len)545 RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
546 {
547 int undef_bit_pos = -1;
548
549 BigInteger a = const2big(arg1, signed1, undef_bit_pos);
550 BigInteger b = const2big(arg2, signed2, undef_bit_pos);
551 BigInteger y = 1;
552
553 if (a == 0 && b < 0)
554 return RTLIL::Const(RTLIL::State::Sx, result_len);
555
556 if (a == 0 && b > 0)
557 return RTLIL::Const(RTLIL::State::S0, result_len);
558
559 if (b < 0)
560 {
561 if (a < -1 || a > 1)
562 y = 0;
563 if (a == -1)
564 y = (-b % 2) == 0 ? 1 : -1;
565 }
566
567 if (b > 0)
568 {
569 // Power-modulo with 2^result_len as modulus
570 BigInteger modulus = 1;
571 int modulus_bits = (result_len >= 0 ? result_len : 1024);
572 for (int i = 0; i < modulus_bits; i++)
573 modulus *= 2;
574
575 bool flip_result_sign = false;
576 if (a < 0) {
577 a *= -1;
578 if (b % 2 == 1)
579 flip_result_sign = true;
580 }
581
582 while (b > 0) {
583 if (b % 2 == 1)
584 y = (y * a) % modulus;
585 b = b / 2;
586 a = (a * a) % modulus;
587 }
588
589 if (flip_result_sign)
590 y *= -1;
591 }
592
593 return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
594 }
595
const_pos(const RTLIL::Const & arg1,const RTLIL::Const &,bool signed1,bool,int result_len)596 RTLIL::Const RTLIL::const_pos(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
597 {
598 RTLIL::Const arg1_ext = arg1;
599 extend_u0(arg1_ext, result_len, signed1);
600
601 return arg1_ext;
602 }
603
const_neg(const RTLIL::Const & arg1,const RTLIL::Const &,bool signed1,bool,int result_len)604 RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
605 {
606 RTLIL::Const arg1_ext = arg1;
607 RTLIL::Const zero(RTLIL::State::S0, 1);
608
609 return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len);
610 }
611
612 YOSYS_NAMESPACE_END
613
614