aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modexpng_fpga_model.py197
1 files changed, 117 insertions, 80 deletions
diff --git a/modexpng_fpga_model.py b/modexpng_fpga_model.py
index cf4d7f8..0726eaa 100644
--- a/modexpng_fpga_model.py
+++ b/modexpng_fpga_model.py
@@ -77,9 +77,9 @@ _VECTOR_CLASS = "Vector"
DUMP_VECTORS = False
DUMP_INDICES = False
DUMP_MACS_CLEARING = False
-DUMP_MACS_ACCUMULATION = True
+DUMP_MACS_ACCUMULATION = False
DUMP_MULT_PARTS = False
-DUMP_RCMB = False
+DUMP_RCMB = True
#
@@ -232,7 +232,7 @@ class ModExpNG_PartRecombinator():
# dump
if dump and DUMP_RCMB:
print("RCMB -> push(): part = 0x%012x, word = 0x%04x" % (part, t))
-
+
# done
return t
@@ -241,7 +241,7 @@ class ModExpNG_PartRecombinator():
# empty results so far
words_lsb = list() # n words
words_msb = list() # n words
-
+
# recombine the lower half (n parts)
# the first tick produces null result, the last part
# produces three words and needs two extra ticks
@@ -249,37 +249,37 @@ class ModExpNG_PartRecombinator():
for i in range(ab_num_words + 1 + 2):
next_part = parts[i] if i < ab_num_words else 0
next_word = self._push_pipeline(next_part, dump)
-
+
if i > 0:
words_lsb.append(next_word)
-
+
# recombine the upper half (n-1 parts)
# the first tick produces null result
self._flush_pipeline(dump)
for i in range(ab_num_words + 1):
next_part = parts[i + ab_num_words] if i < (ab_num_words - 1) else 0
next_word = self._push_pipeline(next_part, dump)
-
+
if i > 0:
words_msb.append(next_word)
-
+
# merge words
words = list()
-
+
# merge lower half
for x in range(ab_num_words):
next_word = words_lsb[x]
words.append(next_word)
-
+
# merge upper half adding the two overlapping words
for x in range(ab_num_words):
next_word = words_msb[x]
if x < 2:
next_word += words_lsb[x + ab_num_words]
words.append(next_word)
-
+
return words
-
+
def recombine_triangle(self, parts, ab_num_words, dump):
@@ -342,30 +342,39 @@ class ModExpNG_WordMultiplier():
self._mac_aux.append(0)
self._index_aux.append(0)
- def _clear_all_macs(self):
+ def _clear_all_macs(self, t, col, dump):
for x in range(NUM_MULTS):
self._macs[x] = 0
+ if dump and DUMP_MACS_CLEARING:
+ print("t=%2d, col=%2d > clear > all" % (t, col))
+
- def _clear_one_mac(self, x):
+ def _clear_one_mac(self, x, t, col, dump):
self._macs[x] = 0
+ if dump and DUMP_MACS_CLEARING:
+ print("t=%2d, col=%2d > clear > x=%d" % (t, col, x))
- def _clear_mac_aux(self):
+
+ def _clear_mac_aux(self, t, col, dump):
self._mac_aux[0] = 0
+ if dump and DUMP_MACS_CLEARING:
+ print("t= 0, col=%2d > clear > aux" % (col))
+
def _update_one_mac(self, x, a, b):
-
+
if a > 0xFFFF:
self._a_seen_17 = True
if b > 0xFFFF:
self._b_seen_17 = True
-
+
if a > 0x1FFFF:
raise("a > 0x1FFFF!")
-
+
if b > 0x1FFFF:
raise("b > 0x1FFFF!")
-
+
p = a * b
self._macs[x] += p
@@ -379,6 +388,35 @@ class ModExpNG_WordMultiplier():
def _preset_index_aux(self, num_cols):
self._index_aux[0] = num_cols * len(self._indices)
+ def _dump_macs_helper(self, t, col, aux=False):
+ print("t=%2d, col=%2d > "% (t, col), end='')
+ for i in range(NUM_MULTS):
+ if i > 0: print(" | ", end='')
+ print("mac[%d]: 0x%012x" % (i, self._macs[i]), end='')
+ if aux:
+ print(" | mac_aux[ 0]: 0x%012x" % (self._mac_aux[0]), end='')
+ print("")
+
+ def _dump_macs(self, t, col):
+ self._dump_macs_helper(t, col)
+
+ def _dump_macs_aux(self, t, col):
+ self._dump_macs_helper(t, col, True)
+
+ def _dump_indices_helper(self, t, col, aux=False):
+ print("t=%2d, col=%2d > indices:" % (t, col), end='')
+ for i in range(NUM_MULTS):
+ print(" %2d" % self._indices[i], end='')
+ if aux:
+ print(" %2d" % self._index_aux[0], end='')
+ print("")
+
+ def _dump_indices(self, t, col):
+ self._dump_indices_helper(t, col)
+
+ def _dump_indices_aux(self, t, col):
+ self._dump_indices_helper(t, col, True)
+
def _rotate_indices(self, num_words):
for x in range(len(self._indices)):
if self._indices[x] > 0:
@@ -400,7 +438,7 @@ class ModExpNG_WordMultiplier():
if dump and DUMP_MULT_PARTS:
print("t=%2d, col=%2d > parts[%2d]: mac_aux[%d] = 0x%012x" %
(time, column, part_index, mac_index, parts[part_index]))
-
+
def multiply_square(self, a_wide, b_narrow, ab_num_words, dump=False):
if dump: print("multiply_square()")
@@ -415,26 +453,20 @@ class ModExpNG_WordMultiplier():
for t in range(ab_num_words):
- if t == 0: self._preset_indices(col)
+ # take care of indices
+ if t == 0: self._preset_indices(col)
else: self._rotate_indices(ab_num_words)
+ # take care of macs
if t == 0:
- self._clear_all_macs()
- if dump and DUMP_MACS_CLEARING:
- print("t= 0, col=%2d > clear > all" % (col))
+ self._clear_all_macs(t, col, dump)
else:
t1 = t - 1
if (t1 // 8) == col:
- self._clear_one_mac(t1 % NUM_MULTS)
- if dump and DUMP_MACS_CLEARING:
- print("t=%2d, col=%2d > clear > x=%d:" % (t, col, t1 % NUM_MULTS))
-
+ self._clear_one_mac(t1 % NUM_MULTS, t, col, dump)
- if dump and DUMP_INDICES:
- print("t=%2d, col=%2d > indices:" % (t, col), end='')
- for i in range(NUM_MULTS):
- print(" %2d" % self._indices[i], end='')
- print("")
+ # debug output
+ if dump and DUMP_INDICES: self._dump_indices(t, col)
# current b-word
bt = b_narrow.words[t]
@@ -448,12 +480,8 @@ class ModExpNG_WordMultiplier():
part_index = t
self._mult_store_part(parts, t, col, part_index, x, dump)
- if dump and DUMP_MACS_ACCUMULATION:
- print("t=%2d, col=%2d > "% (t, col), end='')
- for i in range(NUM_MULTS):
- if i > 0: print(" | ", end='')
- print("mac[%d]: 0x%012x" % (i, self._macs[i]), end='')
- print("")
+ # debug output
+ if dump and DUMP_MACS_ACCUMULATION: self._dump_macs(t, col)
# save the uppers part of product at end of column,
# for the last column don't save the very last part
@@ -481,25 +509,25 @@ class ModExpNG_WordMultiplier():
for t in range(ab_num_words + 1):
- if t == 0:
- self._preset_indices(col)
- if last_col:
- self._preset_index_aux(num_cols)
- else:
- self._rotate_indices(ab_num_words)
- if last_col:
- self._rotate_index_aux()
-
- if t == 0:
- self._clear_all_macs()
- if dump and DUMP_MACS_CLEARING:
- print("t= 0, col=%2d > clear > all" % (col))
-
- if last_col:
- self._clear_mac_aux()
- if dump and DUMP_MACS_CLEARING:
- print("t= 0, col=%2d > clear > aux" % (col))
-
+ # take care of indices
+ if t == 0: self._preset_indices(col)
+ else: self._rotate_indices(ab_num_words)
+
+ # take care of auxilary index
+ if last_col:
+ if t == 0: self._preset_index_aux(num_cols)
+ else: self._rotate_index_aux()
+
+ # take care of macs
+ if t == 0: self._clear_all_macs(t, col, dump)
+
+ # take care of auxilary mac
+ if last_col:
+ if t == 0: self._clear_mac_aux(t, col, dump)
+
+ # debug output
+ if dump and DUMP_INDICES: self._dump_indices_aux(t, col)
+
# current b-word
bt = b_narrow.words[t]
@@ -521,23 +549,18 @@ class ModExpNG_WordMultiplier():
part_index = t
self._mult_store_part_aux(parts, t, col, part_index, 0, dump)
- if dump and DUMP_MACS_ACCUMULATION:
- print("t=%2d, col=%2d > "% (t, col), end='')
- for i in range(NUM_MULTS):
- if i > 0: print(" | ", end='')
- print("mac[%d]: 0x%012x" % (i, self._macs[i]), end='')
- if last_col:
- print(" | mac_aux[ 0]: 0x%012x" % (self._mac_aux[0]), end='')
- print("")
+ # debug output
+ if dump and DUMP_MACS_ACCUMULATION: self._dump_macs_aux(t, col)
-
# shortcut
if not last_col:
if t == (NUM_MULTS * (col + 1) - 1): break
return parts
- def multiply_rectangle(self, a_wide, b_narrow, ab_num_words):
+ def multiply_rectangle(self, a_wide, b_narrow, ab_num_words, dump=False):
+
+ if dump: print("multiply_rectangle()")
num_cols = ab_num_words // NUM_MULTS
@@ -547,10 +570,22 @@ class ModExpNG_WordMultiplier():
for col in range(num_cols):
- self._clear_all_macs()
- self._preset_indices(col)
+ for t in range(ab_num_words + 1):
- for t in range(ab_num_words+1):
+ # take care of indices
+ if t == 0: self._preset_indices(col)
+ else: self._rotate_indices(ab_num_words)
+
+ # take care of macs
+ if t == 0:
+ self._clear_all_macs(t, col, dump)
+ else:
+ t1 = t - 1
+ if (t1 // 8) == col:
+ self._clear_one_mac(t1 % NUM_MULTS, t, col, dump)
+
+ # debug output
+ if dump and DUMP_INDICES: self._dump_indices(t, col)
# current b-word
bt = b_narrow.words[t]
@@ -562,15 +597,17 @@ class ModExpNG_WordMultiplier():
# don't save one value for the very last time instant per column
if t < ab_num_words and t == (col * NUM_MULTS + x):
- parts[t] = self._macs[x]
- self._clear_one_mac(x)
+ part_index = t
+ self._mult_store_part(parts, t, col, part_index, x, dump)
+
+ # debug output
+ if dump and DUMP_MACS_ACCUMULATION: self._dump_macs(t, col)
- # save the uppers part of product at end of column
+ # save the upper parts of product at end of column
if t == ab_num_words:
for x in range(NUM_MULTS):
- parts[ab_num_words + col * NUM_MULTS + x] = self._macs[x]
-
- self._rotate_indices(ab_num_words)
+ part_index = ab_num_words + col * NUM_MULTS + x
+ self._mult_store_part(parts, t, col, part_index, x, dump)
return parts
@@ -722,7 +759,7 @@ class ModExpNG_Worker():
q = ModExpNG_Operand(None, ab_num_words + 1, q_words)
# 3.
- m_parts = self.multiplier.multiply_rectangle(n, q, ab_num_words)
+ m_parts = self.multiplier.multiply_rectangle(n, q, ab_num_words, dump)
m_words = self.recombinator.recombine_rectangle(m_parts, ab_num_words, dump)
m = ModExpNG_Operand(None, 2 * ab_num_words + 1, m_words)
@@ -813,7 +850,7 @@ if __name__ == "__main__":
mp_blind_factor = worker.multiply(mp_blind, vector.p_factor, vector.p, vector.p_coeff, pq_num_words, dump=True)
mq_blind_factor = worker.multiply(mq_blind, vector.q_factor, vector.q, vector.q_coeff, pq_num_words)
-
+
sp_blind_factor = worker.exponentiate(ip_factor, mp_blind_factor, vector.dp, vector.p, vector.p_factor, vector.p_coeff, pq_num_words)
sq_blind_factor = worker.exponentiate(iq_factor, mq_blind_factor, vector.dq, vector.q, vector.q_factor, vector.q_coeff, pq_num_words)
@@ -827,7 +864,7 @@ if __name__ == "__main__":
else:
print("17-bit wide B's not detected.")
-
+
sp_blind = worker.multiply(i, sp_blind_factor, vector.p, vector.p_coeff, pq_num_words)
sq_blind = worker.multiply(i, sq_blind_factor, vector.q, vector.q_coeff, pq_num_words)