-
Notifications
You must be signed in to change notification settings - Fork 0
/
sint.py
343 lines (301 loc) · 11.5 KB
/
sint.py
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
import uint
from math import *
def two_comp(val, bits):
val = val ^ ( (1 << bits) - 1)
val = (val +1)&((1<<bits)-1)# mask
return val
def signed_subtract(a,b,bits):
if b > a:
return two_comp(b-a, bits)
return a - b
# def signed_add(a,b,bits):
# if a + b < 0:
# return two_comp(b-a, bits)
# return a + b
def signed(x,w):
if (x >= 0):
return x
else:
return 2**w + x
def utos(x, w):
if (x >= 2**(w-1)):#negative, then remove MSB
return (x - 2**w)*-1
else:
return x
def getbitsize(value):
if value == 0:
return 1
return ceil(log2(value+1))
class model_sint:
def __init__(self, value, bitsize=None):
self.type = "sint"
if bitsize == None:
self.bitsize = getbitsize(value)
elif bitsize <= 0:
# print("incorrect bitsize")
self.bitsize=1
else:
self.bitsize = bitsize
self.sign = (value >> (self.bitsize - 1)) & 1
self.realval = value
if self.sign:
self.value = two_comp(value, self.bitsize)
else:
self.value = value
def __eq__ (self, other):
if isinstance(other, uint.model_uint) or isinstance(other, model_sint):
if self.value == other.value and self.bitsize == other.bitsize:
return True
return False
# for a and b, if MSB is 1, then find 2's complement
# if MSB is 1, that means its negative, therefore do normal addition taking that into account
# if reslt is negative, return 2's complement
def sint_add(self, other):
maxbit=max(self.bitsize,other.bitsize)
if self.sign and other.sign:
val = two_comp(self.value + other.value, maxbit+1)
elif self.sign and not other.sign:
val = signed_subtract(other.value, self.value, maxbit+1)
elif not self.sign and other.sign:
val = signed_subtract(self.value, other.value, maxbit+1)
else: # not self.sign andnot other.sign:
val = self.value + other.value
return model_sint(val, maxbit+1)
def sint_sub(self, other):
maxbit=max(self.bitsize,other.bitsize)
if self.sign and other.sign:
# val = signed_subtract(self.value, other.value, maxbit+1)
val = signed_subtract(other.value, self.value, maxbit+1)
elif self.sign and not other.sign:
val = two_comp(self.value + other.value, maxbit+1)
elif not self.sign and other.sign:
val = other.value + self.value
else: # not self.sign and not other.sign:
val = signed_subtract(self.value, other.value, maxbit + 1)
return model_sint(val, maxbit+1)
# if result is negative, return 2's complement
# if val's MSB is 1, then find 2's complement. that is the real number
# do operation with the real number. if MSB was 1, find 2's complement
def sint_mul(self, other):
val = self.value * other.value
if self.sign ^ other.sign:
val = two_comp(val, self.bitsize+other.bitsize)
return model_sint(val, self.bitsize + other.bitsize)
def sint_div(self, other):
if other.value == 0:
print("ERROR: divide by zero")
return model_sint(0, self.bitsize)
val = int(self.value / other.value)
if self.sign ^ other.sign:
val = two_comp(val, self.bitsize+1)
return model_sint(val, self.bitsize + 1)
def sint_mod(self, other):
if other.value == 0:
print("ERROR: divide by zero")
return model_sint(0, self.bitsize)
minsize = min(self.bitsize, other.bitsize)
r = self.value % other.value
if self.sign and other.sign:
r = two_comp(r,minsize)
return model_sint(r, minsize)
def sint_lt(self, other):
if self.sign and not other.sign:
return model_sint(0x1, 1)
if not self.sign and other.sign:
return model_sint(0x0, 1)
if not self.sign and not other.sign:
if self.value < other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
else:
if self.value > other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
def sint_leq(self, other):
if self.sign and not other.sign:
return model_sint(0x1, 1)
if not self.sign and other.sign:
return model_sint(0x0, 1)
if not self.sign and not other.sign:
if self.value <= other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
else:
if self.value >= other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
def sint_gt(self, other):
if self.sign and not other.sign:
return model_sint(0x0, 1)
if not self.sign and other.sign:
return model_sint(0x1, 1)
if not self.sign and not other.sign:
if self.value > other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
else:
if self.value < other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
def sint_geq(self,other):
if self.sign and not other.sign:
return model_sint(0x0, 1)
if not self.sign and other.sign:
return model_sint(0x1, 1)
if not self.sign and not other.sign:
if self.value >= other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
else:
if self.value <= other.value:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
def sint_eq(self, other):
if self.value == other.value and self.sign == other.sign:
return model_sint(0x1, 1)
return model_sint(0x0, 1)
def sint_neq(self, other):
if self.value == other.value and self.sign == other.sign:
return model_sint(0x0, 1)
return model_sint(0x1, 1)
def sint_pad(self, n):
if n < 0:
print("ERROR: pad size must be positive")
return self
if n <= self.bitsize:
return self
if self.sign == 0:
return model_sint(self.value, n)
extend = (1 << (n-self.bitsize)) - 1
realval = two_comp(self.value, self.bitsize)
val = (extend << self.bitsize) | realval
return model_sint(val, n)
def sint_asUInt(self):#cant figure out the difference between asUInt and cvt
if self.sign:
val = two_comp(self.value, self.bitsize)
else:
val = self.value
return uint.model_uint(val, self.bitsize)
def sint_asSInt(self):
return self
def sint_shl(self, n):
# if self.sign:
# val = two_comp(self.value, self.bitsize)
# else:
# val = self.value
val = self.realval << n
return model_sint(val, self.bitsize + n)
def sint_shr(self, n):
newlength = max(self.bitsize - n, 1)
if self.bitsize <= n and self.sign:
return model_sint(0x1, newlength)
val = self.realval >> n
return model_sint(val, newlength)
def sint_dshl(self, shift):
val = self.value
val <<= shift.value
newsize = self.bitsize + 2**shift.bitsize-1
if self.sign:
# extend = ((1 << (newsize-self.bitsize))-1) << self.bitsize
# extend = 1 << (newsize-1)
# val = val | extend
val = two_comp(val, newsize)
return model_sint(val, newsize)
def sint_dshr(self, shift):
val = self.realval
if self.sign:
if self.bitsize > shift.value:
val >>= shift.value
extend = ((2<< (shift.bitsize))-1) << (self.bitsize-shift.value)
val = val | extend
else:
val = (1<< self.bitsize)-1
else:
val >>= shift.value
return model_sint(val, self.bitsize)
def sint_cvt(self): #cant figure out the difference between asUInt and cvt
return self
def sint_neg(self):
val = two_comp(self.realval, self.bitsize)
if not self.sign:
val = val | (1<<self.bitsize)
return model_sint(val, self.bitsize+1)
def sint_not(self):
result = 0
for i in range(self.bitsize):
result |= ((~self.realval>>i)&1) << i
return uint.model_uint(result, self.bitsize)
def sint_and(self, other):
result = 0
maxbits = max(self.bitsize, other.bitsize)
a = model_sint(self.realval, self.bitsize).sint_pad(maxbits)
b = model_sint(other.realval, other.bitsize).sint_pad(maxbits)
for i in range(maxbits):
result |= ((a.realval>>i)&1 & (b.realval>>i)&1) << i
return model_sint(result, maxbits)
def sint_or(self, other):
result = 0
maxbits = max(self.bitsize, other.bitsize)
a = model_sint(self.realval, self.bitsize).sint_pad(maxbits)
b = model_sint(other.realval, other.bitsize).sint_pad(maxbits)
for i in range(maxbits):
result |= ((a.realval>>i)&1 | (b.realval>>i)&1) << i
return model_sint(result, maxbits)
def sint_xor(self, other):
result = 0
maxbits = max(self.bitsize, other.bitsize)
a = model_sint(self.realval, self.bitsize).sint_pad(maxbits)
b = model_sint(other.realval, other.bitsize).sint_pad(maxbits)
for i in range(maxbits):
result |= ((a.realval>>i)&1 ^ (b.realval>>i)&1) << i
return model_sint(result, maxbits)
def sint_andr(self):
result = 1
for i in range(self.bitsize):
bit_i = (self.realval & (1<<i))>>i
result = result & bit_i
return model_sint(result, 1)
def sint_orr(self):
result = 0
for i in range(self.bitsize):
bit_i = (self.realval & (1<<i))>>i
result = result | bit_i
return model_sint(result, 1)
def sint_xorr(self):
result = 0
for i in range(self.bitsize):
bit_i = (self.realval & (1<<i))>>i
result = result ^ bit_i
return model_sint(result, 1)
def sint_cat(self, other):
if other.value == 0:
return model_sint((self.realval<<other.bitsize), self.bitsize+other.bitsize)
return model_sint((self.realval<<other.bitsize)|other.realval, self.bitsize+other.bitsize)
def sint_bits(self, hi, lo):
if hi > lo and hi < self.bitsize:
return uint.model_uint((self.realval>>lo)&(2**(hi-lo+1)-1), hi-lo+1)
if hi == lo:
return uint.model_uint(0,0)
return uint.model_uint(0,1)
def sint_head(self, n):
if n >= 0 and n <= self.bitsize:
return uint.model_uint(self.realval>>(self.bitsize-n), n)
return uint.model_uint(0,1)
def sint_tail(self, n):
if n == self.bitsize:
return uint.model_uint(0,0)
if self.bitsize > n:
return uint.model_uint(self.realval & (2**(self.bitsize-n)-1), self.bitsize-n)
print("tail: this should not happen")
return uint.model_uint(0,0)
def tohex(self):
mask = (1<<self.bitsize)-1
return hex(mask & self.value)
def print_bits(self):
result = "realval: s("
result += hex(self.realval)#self.tohex()
result += ") "
result += "val: s("
result += hex(self.value)#self.tohex()
result += ")"
print(self.bitsize, result)