Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions hardfloat/src/main/scala/DivSqrtRecFN_small.scala
Original file line number Diff line number Diff line change
Expand Up @@ -492,17 +492,46 @@ class
val divSqrtRecFNToRaw =
Module(new DivSqrtRecFNToRaw_small(expWidth, sigWidth, options))

io.inReady := divSqrtRecFNToRaw.io.inReady
divSqrtRecFNToRaw.io.inValid := io.inValid
//------------------------------------------------------------------------
// Optional constant-time padding (gated on divSqrtOpt_constTime):
// when enabled, every divide / sqrt completes at a fixed worst-case
// latency of sigWidth + 5 cycles, regardless of operand class. This
// closes the operand-dependent +1-cycle skipCycle2 timing channel.
// When the option is OFF (default), behaviour is identical to before:
// io.outValid_* is driven directly from the inner module's pulses,
// and io.inReady mirrors the inner inReady, preserving cycle-exact
// backward compatibility.
//------------------------------------------------------------------------
val ctEnable = ((options & divSqrtOpt_constTime) != 0).B
val ctTarget = (sigWidth + 5).U
val ct_counter = RegInit(0.U(8.W))
val ct_pending_div = RegInit(false.B)
val ct_pending_sqrt = RegInit(false.B)

val ct_busy = ct_counter =/= 0.U || ct_pending_div || ct_pending_sqrt
io.inReady := divSqrtRecFNToRaw.io.inReady && !(ctEnable && ct_busy)
divSqrtRecFNToRaw.io.inValid := io.inValid && !(ctEnable && ct_busy)
divSqrtRecFNToRaw.io.sqrtOp := io.sqrtOp
divSqrtRecFNToRaw.io.a := io.a
divSqrtRecFNToRaw.io.b := io.b
divSqrtRecFNToRaw.io.roundingMode := io.roundingMode

//------------------------------------------------------------------------
//------------------------------------------------------------------------
io.outValid_div := divSqrtRecFNToRaw.io.rawOutValid_div
io.outValid_sqrt := divSqrtRecFNToRaw.io.rawOutValid_sqrt
when (ctEnable && io.inValid && io.inReady) {
ct_counter := ctTarget
} .elsewhen (ctEnable && ct_counter =/= 0.U) {
ct_counter := ct_counter - 1.U
}

when (ctEnable && divSqrtRecFNToRaw.io.rawOutValid_div) { ct_pending_div := true.B }
when (ctEnable && divSqrtRecFNToRaw.io.rawOutValid_sqrt) { ct_pending_sqrt := true.B }

val ct_emit = ctEnable && ct_counter === 1.U
io.outValid_div := Mux(ctEnable, ct_emit && ct_pending_div, divSqrtRecFNToRaw.io.rawOutValid_div)
io.outValid_sqrt := Mux(ctEnable, ct_emit && ct_pending_sqrt, divSqrtRecFNToRaw.io.rawOutValid_sqrt)
when (ct_emit) {
ct_pending_div := false.B
ct_pending_sqrt := false.B
}

val roundRawFNToRecFN =
Module(new RoundRawFNToRecFN(expWidth, sigWidth, 0))
Expand Down
7 changes: 7 additions & 0 deletions hardfloat/src/main/scala/common.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ object consts {
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
def divSqrtOpt_twoBitsPerCycle = 16
/*------------------------------------------------------------------------
| When set, DivSqrtRecFN_small pads every divide / sqrt to a fixed
| worst-case latency of `sigWidth + 5` cycles, eliminating the
| operand-dependent timing channel created by skipCycle2. Off by
| default; enable in security-sensitive deployments.
*------------------------------------------------------------------------*/
def divSqrtOpt_constTime = 32
}

class RawFloat(val expWidth: Int, val sigWidth: Int) extends Bundle
Expand Down