Skip to content

Commit fd5312f

Browse files
committed
[otbn,rtl] Register local escalation signals for timing optimization
Signals contributing to the local controller escalation signal directly factor into the insn_executing signal inside the otbn_controller.sv. This then drives various commit signals as well as the DMEM request signal (lsu_load_req_o). By cutting these escalation signals, these paths are shortened which results in better timing/area results. Signed-off-by: Pascal Etterli <[email protected]>
1 parent 44f4035 commit fd5312f

File tree

1 file changed

+107
-16
lines changed

1 file changed

+107
-16
lines changed

hw/ip/otbn/rtl/otbn_core.sv

Lines changed: 107 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ module otbn_core
113113
logic [31:0] insn_fetch_resp_data;
114114
logic insn_fetch_resp_clear;
115115
logic insn_fetch_err;
116-
logic insn_addr_err;
116+
logic insn_addr_err_d, insn_addr_err;
117117

118118
rf_predec_bignum_t rf_predec_bignum;
119119
alu_predec_bignum_t alu_predec_bignum;
@@ -156,7 +156,7 @@ module otbn_core
156156
logic rf_base_rd_commit;
157157
logic rf_base_call_stack_sw_err;
158158
logic rf_base_call_stack_hw_err;
159-
logic rf_base_intg_err;
159+
logic rf_base_intg_err_d, rf_base_intg_err;
160160
logic rf_base_spurious_we_err;
161161
logic rf_base_sec_wipe_err;
162162

@@ -175,7 +175,7 @@ module otbn_core
175175

176176
logic [BaseIntgWidth-1:0] lsu_base_rdata;
177177
logic [ExtWLEN-1:0] lsu_bignum_rdata;
178-
logic lsu_rdata_err;
178+
logic lsu_rdata_err_d, lsu_rdata_err;
179179

180180
logic [WdrAw-1:0] rf_bignum_wr_addr;
181181
logic [WdrAw-1:0] rf_bignum_wr_addr_ctrl;
@@ -241,7 +241,7 @@ module otbn_core
241241
logic urnd_advance;
242242
logic urnd_advance_start_stop_control;
243243
logic [WLEN-1:0] urnd_data;
244-
logic urnd_all_zero;
244+
logic urnd_all_zero_d, urnd_all_zero;
245245

246246
logic controller_start;
247247

@@ -281,7 +281,7 @@ module otbn_core
281281
logic start_stop_fatal_error;
282282
logic rf_bignum_predec_error, alu_bignum_predec_error, ispr_predec_error, mac_bignum_predec_error;
283283
logic controller_predec_error;
284-
logic rd_predec_error, predec_error;
284+
logic rd_predec_error, predec_error_d, predec_error;
285285

286286
logic req_sec_wipe_urnd_keys_q;
287287

@@ -361,7 +361,7 @@ module otbn_core
361361
.insn_fetch_resp_data_o (insn_fetch_resp_data),
362362
.insn_fetch_resp_clear_i(insn_fetch_resp_clear),
363363
.insn_fetch_err_o (insn_fetch_err),
364-
.insn_addr_err_o (insn_addr_err),
364+
.insn_addr_err_o (insn_addr_err_d),
365365

366366
.rf_predec_bignum_o (rf_predec_bignum),
367367
.alu_predec_bignum_o (alu_predec_bignum),
@@ -416,7 +416,7 @@ module otbn_core
416416
rf_predec_bignum.rf_ren_b,
417417
ispr_predec_bignum.ispr_rd_en} & ~insn_valid;
418418

419-
assign predec_error =
419+
assign predec_error_d =
420420
((alu_bignum_predec_error | mac_bignum_predec_error | controller_predec_error) & insn_valid) |
421421
rf_bignum_predec_error |
422422
ispr_predec_error |
@@ -589,10 +589,100 @@ module otbn_core
589589
controller_err_bits.bad_internal_state,
590590
controller_err_bits.reg_intg_violation};
591591

592-
logic non_controller_reg_intg_violation;
593-
assign non_controller_reg_intg_violation =
594-
|{alu_bignum_reg_intg_violation_err, mac_bignum_reg_intg_violation_err, rf_base_intg_err};
595-
592+
logic non_controller_reg_intg_violation_d, non_controller_reg_intg_violation;
593+
assign non_controller_reg_intg_violation_d =
594+
|{alu_bignum_reg_intg_violation_err, mac_bignum_reg_intg_violation_err, rf_base_intg_err_d};
595+
596+
////////////////////////////////////////////////////////////////
597+
// Register local escalation signals for timinig optimization //
598+
////////////////////////////////////////////////////////////////
599+
// Signals contributing to the local controller escalation signal directly factor into the
600+
// insn_executing signal inside the otbn_controller.sv. This then drives various commit signals
601+
// as well as the DMEM request signal (lsu_load_req_o). By cutting these escalation signals,
602+
// these paths are shortened which results in better timing/area results. Signals contributing to
603+
// the start/stop escalation are also cut to synchronize the escalation such that transitioning
604+
// into LOCKED and the start of wiping activities happen at the same time. The error bits are
605+
// also updated delayed to have the same behaviour as without a cut.
606+
//
607+
// Registered signals:
608+
// - urnd_all_zero: Is high when the local PRNG is all zero and locks up.
609+
// Potentially timing critical.
610+
// - predec_error: Generated by checking all the registered, predecoded signals with decoded
611+
// signals and combining these.
612+
// Potentially timing critical.
613+
// - lsu_rdata_err: DMEM ECC errors of data read from DMEM.
614+
// Timing critical because source is in memory.
615+
// - insn_addr_err: Depends on insn_fetch_req_addr_o from the controller which factors in
616+
// lots of combinatorial signals.
617+
// Likely timing critical.
618+
// - rf_base_intg_err: ECC errors triggered with in the base register file. The control signals
619+
// for the base register file are not predecoded.
620+
// So this is likely timing critical.
621+
// - non_controller_reg_intg_violation: Based on alu_bignum_reg_intg_violation_err,
622+
// mac_bignum_reg_intg_violation_err and rf_base_intg_err.
623+
// The former two are generated by checking the ECC of the
624+
// MOD / ACC values. The checks depends on the actual
625+
// ALU / MAC datapath outputs.
626+
// **Highly** timing critical.
627+
//
628+
// Not registered signals:
629+
// - escalate_en_i: This must NOT be not cut. It stems from the system wide escalation
630+
// control mechanism and such a global escalation must be as fast as
631+
// possible.
632+
// - start_stop_fatal_error: The error signal of the start stop FSM. Based on EDN urnd ack
633+
// signal and internal state checking. This error is not cut to
634+
// synchronize the escalation of the controller and start/stop
635+
// control.
636+
// - controller_fatal_err: The error signal of the controller towards the start/stop logic.
637+
// This error is not cut to synchronize the escalation of the
638+
// controller and start/stop control.
639+
// - rf_base_spurious_we_err: This error is already registered at the source.
640+
// - insn_fetch_err: IMEM ECC errors, not computed on the IMEM output but on a flopped
641+
// signal.
642+
//
643+
// Security considerations:
644+
// With the registering, the reaction to escalation sources is delayed by one cycle. Any faulty
645+
// instruction therefore still commits and updates registers or the memory. This does not affect
646+
// security because:
647+
// - While executing a program, the IMEM and DMEM are locked and cannot be read by Ibex.
648+
// - They become readable once the execution finishes without a fatal error. In addition, only a
649+
// part of the DMEM is readable by Ibex.
650+
// - If a fatal error occurs OTBN locks up and none of the memories become readable again.
651+
// - SCA and FI combined attacks are out of scope. As of this, any leakage due to FI attacks is
652+
// considered unusable because the OpenTitan chip scraps itself when too many FI attacks were
653+
// detected.
654+
// - When escalating, OTBN asserts locking_o and therefore any memory reads are killed
655+
// immediately. This handles the case where the final instruction is targeted. An error during
656+
// the final instruction does not prevent the OTBN of going into IDLE and thus the memories are
657+
// theoretically unlocked for one cycle. However, OTBN will escalate immediately and also kill
658+
// any read requests. The memories are therefore never readable except maybe some glitching
659+
// activities on the port. However, assuming a single fault per execution, when targeting the
660+
// last instruction, any program should have run correctly up to this point and thus should not
661+
// expose any secrets in the readable DMEM section. Additionally, converting the ECALL
662+
// instruction into a meaningful memory instruction is infeasible with only 1 fault. Also, a
663+
// BN.SID instruction takes two cycles to execute and therefore only a SW instruction could
664+
// be performed.
665+
666+
// TODO: Does this need a prim_flop or is a regular flop sufficient?
667+
// We drop the _q suffix for the registered signals such that DV and tracing can stay the same
668+
// whether there is a cut or not.
669+
always_ff @(posedge clk_i or negedge rst_ni) begin
670+
if (!rst_ni) begin
671+
urnd_all_zero <= '0;
672+
predec_error <= '0;
673+
rf_base_intg_err <= '0;
674+
lsu_rdata_err <= '0;
675+
non_controller_reg_intg_violation <= '0;
676+
insn_addr_err <= '0;
677+
end else begin
678+
urnd_all_zero <= urnd_all_zero_d;
679+
predec_error <= predec_error_d;
680+
rf_base_intg_err <= rf_base_intg_err_d;
681+
lsu_rdata_err <= lsu_rdata_err_d;
682+
non_controller_reg_intg_violation <= non_controller_reg_intg_violation_d;
683+
insn_addr_err <= insn_addr_err_d;
684+
end
685+
end
596686

597687
// Generate an err_bits output by combining errors from all the blocks in otbn_core
598688
assign err_bits_d = '{
@@ -633,11 +723,12 @@ module otbn_core
633723

634724
// Pass an "escalation" signal down to the controller by ORing in error signals from the other
635725
// modules in otbn_core. Note that each error signal except escalate_en_i that appears here also
636-
// appears somewhere in err_bits_o above (checked in ErrBitsIfControllerEscalate_A)
726+
// appears somewhere in err_bits_o above (checked in ErrBitsIfControllerEscalate_A).
727+
// The error rf_base_intg_err is already factored into non_controller_reg_intg_violation.
637728
assign controller_fatal_escalate_en =
638729
mubi4_or_hi(escalate_en_i,
639730
mubi4_bool_to_mubi(|{start_stop_fatal_error, urnd_all_zero, predec_error,
640-
rf_base_intg_err, rf_base_spurious_we_err, lsu_rdata_err,
731+
rf_base_spurious_we_err, lsu_rdata_err,
641732
insn_fetch_err, non_controller_reg_intg_violation,
642733
insn_addr_err}));
643734

@@ -684,7 +775,7 @@ module otbn_core
684775

685776
.lsu_base_rdata_o (lsu_base_rdata),
686777
.lsu_bignum_rdata_o(lsu_bignum_rdata),
687-
.lsu_rdata_err_o (lsu_rdata_err)
778+
.lsu_rdata_err_o (lsu_rdata_err_d)
688779
);
689780

690781
// Base Instruction Subset =======================================================================
@@ -716,7 +807,7 @@ module otbn_core
716807

717808
.call_stack_sw_err_o(rf_base_call_stack_sw_err),
718809
.call_stack_hw_err_o(rf_base_call_stack_hw_err),
719-
.intg_err_o (rf_base_intg_err),
810+
.intg_err_o (rf_base_intg_err_d),
720811
.spurious_we_err_o (rf_base_spurious_we_err),
721812
.sec_wipe_err_o (rf_base_sec_wipe_err)
722813
);
@@ -910,7 +1001,7 @@ module otbn_core
9101001
.urnd_reseed_ack_o (urnd_reseed_ack),
9111002
.urnd_advance_i (urnd_advance),
9121003
.urnd_data_o (urnd_data),
913-
.urnd_all_zero_o (urnd_all_zero),
1004+
.urnd_all_zero_o (urnd_all_zero_d),
9141005

9151006
.edn_rnd_req_o,
9161007
.edn_rnd_ack_i,

0 commit comments

Comments
 (0)