From 841a29496d25d99e2b92bdb3dcdafefdf898e786 Mon Sep 17 00:00:00 2001 From: Sabina Sokol Date: Tue, 10 Mar 2026 13:39:06 -0400 Subject: [PATCH] opt_expr: Respect keep attribute for double-inverter folding The double-inverter optimization in opt_expr folds consecutive NOT gates without checking if the cell has the keep attribute. This causes ring oscillator PUFs and other intentional feedback loops to be broken even when explicitly marked for preservation. This patch adds a has_keep_attr() check before folding double inverters, consistent with how opt_clean handles the keep attribute. Fixes: Ring oscillator cells marked with (* keep *) being optimized away Signed-off-by: Sabina Sokol --- passes/opt/opt_expr.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 2c040b09d..6f57278f6 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1056,6 +1056,7 @@ skip_fine_alu: } if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(ID::Y)) == 1 && + !cell->has_keep_attr() && invert_map.count(assign_map(cell->getPort(ID::A))) != 0) { replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A)))); goto next_cell;