[otbn] Update M, L, Z flags from bitwise ops in simulator and docs
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/data/bignum-insns.yml b/hw/ip/otbn/data/bignum-insns.yml
index ccb3475..5d637b1 100644
--- a/hw/ip/otbn/data/bignum-insns.yml
+++ b/hw/ip/otbn/data/bignum-insns.yml
@@ -489,6 +489,7 @@
Performs a bitwise and operation.
Takes the values stored in registers referenced by `wrs1` and `wrs2` and stores the result in the register referenced by `wrd`.
The content of the second source register can be shifted by an immediate before it is consumed by the operation.
+ The M, L and Z flags in flag group 0 are updated with the result of the operation.
decode: &bn-and-decode |
d = UInt(wrd)
a = UInt(wrs1)
@@ -501,6 +502,8 @@
result = a & b_shifted
WDR[d] = result
+ flags_out = FlagsForResult(result)
+ FLAGS[0] = {M: flags_out.M, L: flags_out.L, Z: flags_out.Z, C: FLAGS[0].C}
encoding:
scheme: bna
mapping:
@@ -520,12 +523,15 @@
Performs a bitwise or operation.
Takes the values stored in WDRs referenced by `wrs1` and `wrs2` and stores the result in the WDR referenced by `wrd`.
The content of the second source WDR can be shifted by an immediate before it is consumed by the operation.
+ The M, L and Z flags in flag group 0 are updated with the result of the operation.
decode: *bn-and-decode
operation: |
b_shifted = ShiftReg(b, st, sb)
result = a | b_shifted
WDR[d] = result
+ flags_out = FlagsForResult(result)
+ FLAGS[0] = {M: flags_out.M, L: flags_out.L, Z: flags_out.Z, C: FLAGS[0].C}
encoding:
scheme: bna
mapping:
@@ -551,6 +557,7 @@
doc: |
Negates the value in `wrs` and stores the result in the register referenced by `wrd`.
The source value can be shifted by an immediate before it is consumed by the operation.
+ The M, L and Z flags in flag group 0 are updated with the result of the operation.
decode: |
d = UInt(wrd)
a = UInt(wrs1)
@@ -562,6 +569,8 @@
result = ~a_shifted
WDR[d] = result
+ flags_out = FlagsForResult(result)
+ FLAGS[0] = {M: flags_out.M, L: flags_out.L, Z: flags_out.Z, C: FLAGS[0].C}
encoding:
scheme: bna
mapping:
@@ -581,12 +590,15 @@
Performs a bitwise xor operation.
Takes the values stored in WDRs referenced by `wrs1` and `wrs2` and stores the result in the WDR referenced by `wrd`.
The content of the second source WDR can be shifted by an immediate before it is consumed by the operation.
+ The M, L and Z flags in flag group 0 are updated with the result of the operation.
decode: *bn-and-decode
operation: |
b_shifted = ShiftReg(b, st, sb)
result = a ^ b_shifted
WDR[d] = result
+ flags_out = FlagsForResult(result)
+ FLAGS[0] = {M: flags_out.M, L: flags_out.L, Z: flags_out.Z, C: FLAGS[0].C}
encoding:
scheme: bnaf
mapping:
diff --git a/hw/ip/otbn/dv/otbnsim/sim/insn.py b/hw/ip/otbn/dv/otbnsim/sim/insn.py
index 59d83c5..387de72 100644
--- a/hw/ip/otbn/dv/otbnsim/sim/insn.py
+++ b/hw/ip/otbn/dv/otbnsim/sim/insn.py
@@ -585,8 +585,10 @@
def execute(self, state: OTBNState) -> None:
b_shifted = ShiftReg(state.wreg[self.wrs2],
self.shift_type, self.shift_bytes)
- a = state.wreg[self.wrs1]
- state.wreg[self.wrd] = a & b_shifted
+ a = state.wreg[self.wrs1].unsigned()
+ result = a & b_shifted
+ state.wreg[self.wrd] = result
+ state.update_mlz_flags(0, result)
class BNOR(OTBNInsn):
@@ -604,7 +606,9 @@
b_shifted = ShiftReg(state.wreg[self.wrs2],
self.shift_type, self.shift_bytes)
a = state.wreg[self.wrs1]
- state.wreg[self.wrd] = a | b_shifted
+ result = a | b_shifted
+ state.wreg[self.wrd] = result
+ state.update_mlz_flags(0, result)
class BNNOT(OTBNInsn):
@@ -620,7 +624,9 @@
def execute(self, state: OTBNState) -> None:
b_shifted = ShiftReg(state.wreg[self.wrs],
self.shift_type, self.shift_bytes)
- state.wreg[self.wrd] = ~b_shifted
+ result = ~b_shifted
+ state.wreg[self.wrd] = result
+ state.update_mlz_flags(0, result)
class BNXOR(OTBNInsn):
@@ -638,7 +644,9 @@
b_shifted = ShiftReg(state.wreg[self.wrs2],
self.shift_type, self.shift_bytes)
a = state.wreg[self.wrs1]
- state.wreg[self.wrd] = a ^ b_shifted
+ result = a ^ b_shifted
+ state.wreg[self.wrd] = result
+ state.update_mlz_flags(0, result)
class BNRSHI(OTBNInsn):
diff --git a/hw/ip/otbn/dv/otbnsim/sim/state.py b/hw/ip/otbn/dv/otbnsim/sim/state.py
index 2470862..86bdd3a 100644
--- a/hw/ip/otbn/dv/otbnsim/sim/state.py
+++ b/hw/ip/otbn/dv/otbnsim/sim/state.py
@@ -233,6 +233,19 @@
setattr(self, n, getattr(self._new_val, n))
self._new_val = None
+ @staticmethod
+ def mlz_for_result(C: bool, result: int) -> 'FlagReg':
+ '''Generate flags for the result of an operation.
+
+ C is the value for the C flag. result is the wide-side result value
+ that is used to generate M, L and Z.
+
+ '''
+ M = bool((result >> 255) & 1)
+ L = bool(result & 1)
+ Z = bool(result == 0)
+ return FlagReg(C=C, M=M, L=L, Z=Z)
+
class FlagGroups:
def __init__(self) -> None:
@@ -389,14 +402,14 @@
@staticmethod
def add_with_carry(a: int, b: int, carry_in: int) -> Tuple[int, FlagReg]:
result = a + b + carry_in
-
carryless_result = result & ((1 << 256) - 1)
- flags_out = FlagReg(C=bool((result >> 256) & 1),
- M=bool((result >> 255) & 1),
- L=bool(result & 1),
- Z=bool(1 if carryless_result == 0 else 0))
+ C = bool((result >> 256) & 1)
- return (carryless_result, flags_out)
+ return (carryless_result, FlagReg.mlz_for_result(C, carryless_result))
+
+ def update_mlz_flags(self, fg: int, result: int) -> None:
+ '''Update M, L, Z flags for the given result'''
+ self.flags[fg] = FlagReg.mlz_for_result(self.flags[fg].C, result)
def post_insn(self) -> None:
'''Update state after running an instruction but before commit'''