{"task":"BBQ","generated_at":"2026-10-18T06:15Z","runs":{"gemini":{"run":"run_01M4YAV50Q8D1RYJB8ZJXTMHP6","verdict":"PASS","score":37.35534286115959,"submission":"Final submission","files":["hardware/bbq/generator/bbq_level_lx.py"],"add":669,"del":5,"bytes":37556,"truncated":false,"patch":"diff --git a/hardware/bbq/generator/bbq_level_lx.py b/hardware/bbq/generator/bbq_level_lx.py\nindex a038e03..6d86b8f 100644\n--- a/hardware/bbq/generator/bbq_level_lx.py\n+++ b/hardware/bbq/generator/bbq_level_lx.py\n@@ -42,29 +42,693 @@ class BBQLevelLX(BBQLevel):\n \n     def latency(self) -> int:\n         \"\"\"Latency in cycles.\"\"\"\n+        if not self.sram_counters and not self.sram_bitmap:\n+            return 0\n         return 1 + int(self.sram_bitmap) + int(self.sram_counters)\n \n \n+    def _priority_idx_slice(self, reg_stage: int) -> str:\n+        \"\"\"Returns the priority bit-slice corresponding to this level.\"\"\"\n+        shift = self.num_bitmap_levels - self.id\n+        if shift == 0:\n+            return \"reg_priority_s[{}][HEAP_LOG_BITMAP_WIDTH-1:0]\".format(reg_stage)\n+        lo = \"{}*HEAP_LOG_BITMAP_WIDTH\".format(shift)\n+        hi = \"({}*HEAP_LOG_BITMAP_WIDTH)-1\".format(shift + 1)\n+        return \"reg_priority_s[{}][{}:{}]\".format(reg_stage, hi, lo)\n+\n+\n+    def _next_level_idx_slice(self, reg_stage: int) -> str:\n+        \"\"\"Returns the B-bit slice of the next level's address/priority corresponding to this level's index.\"\"\"\n+        if self.is_leaf:\n+            return \"reg_priority_s[{}][HEAP_LOG_BITMAP_WIDTH-1:0]\".format(reg_stage)\n+        next_name = self.next_level.name()\n+        return \"reg_{}_addr_s[{}][HEAP_LOG_BITMAP_WIDTH-1:0]\".format(next_name, reg_stage)\n+\n+\n+    def _emit_counter_update(self, cg: CodeGen, new_cnt: str, old_cnt: str, is_enq: str) -> None:\n+        \"\"\"Emits combinational waterlevel counter update.\"\"\"\n+        cg.emit([\n+            \"{}[WATERLEVEL_IDX-1:0] = ({} ? ({}[WATERLEVEL_IDX-1:0] + 1'b1) : ({}[WATERLEVEL_IDX-1:0] - 1'b1));\".format(\n+                new_cnt, is_enq, old_cnt, old_cnt),\n+            \"{}[WATERLEVEL_IDX] = ({} ? ({}[WATERLEVEL_IDX] | {}[0]) : ((|{}[WATERLEVEL_IDX-1:2]) | (&{}[1:0])));\".format(\n+                new_cnt, is_enq, old_cnt, old_cnt, old_cnt, old_cnt),\n+        ])\n+\n+\n+    def _emit_cand_defs(self, cg: CodeGen, prefix: str) -> None:\n+        \"\"\"Emits temporary signal definitions for a fast FFS/postop candidate.\"\"\"\n+        cg.align_defs([\n+            (\"bitmap_t\", \"{}_has_lo;\".format(prefix)),\n+            (\"bitmap_t\", \"{}_has_hi;\".format(prefix)),\n+            (\"bitmap_t\", \"{}_lsb_oh;\".format(prefix)),\n+            (\"bitmap_t\", \"{}_msb_oh;\".format(prefix)),\n+            (\"bitmap_t\", \"{}_lsb_fold;\".format(prefix)),\n+            (\"bitmap_t\", \"{}_deq_oh;\".format(prefix)),\n+            (\"bitmap_t\", \"{}_post;\".format(prefix)),\n+            (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_lsb_idx;\".format(prefix)),\n+            (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_msb_idx;\".format(prefix)),\n+            (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_idx;\".format(prefix)),\n+        ])\n+\n+\n+    def _emit_next_level_defs(self, cg: CodeGen, end_c: int) -> None:\n+        \"\"\"Emits stage definitions at end_cycle for next level interface.\"\"\"\n+        next_name = self.next_level.name()\n+        if self.is_leaf:\n+            cg.align_defs([\n+                (\"heap_priority_t\", \"priority_s{};\".format(end_c)),\n+            ])\n+        else:\n+            cg.align_defs([\n+                (\"logic [BITMAP_L{}_AWIDTH-1:0]\".format(self.id + 1),\n+                 \"{}_addr_s{};\".format(next_name, end_c)),\n+            ])\n+        for offset in range(1, 5):\n+            cg.align_defs([\n+                (\"logic\", \"{}_addr_conflict_s{}_s{};\".format(\n+                    next_name, end_c + offset, end_c)),\n+                (\"logic\", \"reg_{}_addr_conflict_s{}_s{};\".format(\n+                    next_name, end_c + offset, end_c)),\n+            ])\n+            if not self.sram_counters:\n+                cg.align_defs([\n+                    (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_bit_eq_s{}_s{};\".format(\n+                        next_name, end_c + offset, end_c)),\n+                ])\n+\n+\n     def emit_stage_defs(self, cg: CodeGen) -> None:\n         \"\"\"Emit this level through the supplied CodeGen instance.\"\"\"\n-        raise NotImplementedError(\"Bitmap-level implementation removed\")\n+        name = self.name()\n+        c0 = self.start_cycle + int(self.sram_bitmap)\n+        end_c = self.end_cycle\n+\n+        if self is self.bbq.bitmap_levels[0]:\n+            cg.emit([\n+                \"localparam logic [255:0] FFS_IDX_MASK [0:7] = '{\",\n+                \"    256'hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,\",\n+                \"    256'hCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC,\",\n+                \"    256'hF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0,\",\n+                \"    256'hFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00,\",\n+                \"    256'hFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000,\",\n+                \"    256'hFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000,\",\n+                \"    256'hFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000,\",\n+                \"    256'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000\",\n+                \"};\",\n+            ])\n+\n+        if self.sram_bitmap:\n+            s_bm = self.start_cycle\n+            cg.comment(\"Stage {} metadata (L{} bitmap SRAM read delay)\".format(s_bm, self.id))\n+            for offset in range(1, 5):\n+                cg.align_defs([\n+                    (\"logic\", \"reg_{}_addr_conflict_s{}_s{};\".format(\n+                        name, s_bm + offset, s_bm)),\n+                ])\n+            cg.emit()\n+\n+        if not self.sram_counters:\n+            # 1-stage level (L1: c0 == end_c)\n+            cg.comment(\"Stage {} metadata\".format(end_c))\n+            cg.align_defs([\n+                (\"bitmap_t\", \"{}_enq_oh_s{};\".format(name, end_c)),\n+                (\"bitmap_t\", \"{}_op_oh_s{};\".format(name, end_c)),\n+                (\"bitmap_t\", \"{}_bitmap_s{};\".format(name, end_c)),\n+                (\"bitmap_t\", \"reg_{}_bitmap_postop_s{};\".format(name, c0)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_idx_s{};\".format(name, end_c)),\n+                (\"counter_t\", \"old_{}_counter_s{};\".format(name, end_c)),\n+                (\"counter_t\", \"new_{}_counter_s{};\".format(name, end_c)),\n+                (\"logic\", \"{}_counter_non_zero_s{};\".format(name, end_c)),\n+            ])\n+            if not self.is_leaf and not self.next_level.sram_bitmap:\n+                cg.align_defs([\n+                    (\"bitmap_t\", \"{}_next_bm_enq_s{};\".format(name, end_c)),\n+                    (\"bitmap_t\", \"{}_next_bm_min_s{};\".format(name, end_c)),\n+                    (\"bitmap_t\", \"{}_next_bm_max_s{};\".format(name, end_c)),\n+                    (\"bitmap_t\", \"{}_next_bm_read_s{};\".format(name, end_c)),\n+                ])\n+            self._emit_cand_defs(cg, \"{}_c0_s{}\".format(name, end_c))\n+            if self.is_leaf:\n+                cg.align_defs([\n+                    (\"counter_t\", \"reg_{}_counter_s{};\".format(name, end_c)),\n+                    (\"counter_t\", \"reg_old_{}_counter_s{};\".format(name, end_c)),\n+                    (\"logic\", \"reg_{}_counter_non_zero_s{};\".format(name, end_c)),\n+                ])\n+            self._emit_next_level_defs(cg, end_c)\n+            cg.emit()\n+        else:\n+            # 3-stage counter pipeline: c0 (S0), c0+1 (S1), c0+2 = end_c (S2)\n+            s0 = c0\n+            s1 = c0 + 1\n+            s2 = end_c\n+\n+            cg.comment(\"Stage {} metadata\".format(s0))\n+            cg.align_defs([\n+                (\"bitmap_t\", \"{}_enq_oh_s{};\".format(name, s0)),\n+                (\"bitmap_t\", \"{}_cand3_post_s{};\".format(name, s0)),\n+                (\"bitmap_t\", \"{}_bitmap_postop_s{};\".format(name, s0)),\n+                (\"bitmap_t\", \"reg_{}_bitmap_postop_s{};\".format(name, s0)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_cand3_idx_s{};\".format(name, s0)),\n+                (\"logic\", \"{}_d3_take_s2_s{};\".format(name, s0)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_idx_s{};\".format(name, s0)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"reg_{}_idx_s{};\".format(name, s0)),\n+                (\"logic\", \"reg_{}_c21_both_deq_s{};\".format(name, s0)),\n+                (\"logic\", \"reg_{}_c21_same_deq_s{};\".format(name, s0)),\n+                (\"logic\", \"reg_{}_s2_le_s1_s{};\".format(name, s0)),\n+                (\"logic\", \"reg_{}_s2_ge_s1_s{};\".format(name, s0)),\n+            ])\n+            self._emit_cand_defs(cg, \"{}_c0_s{}\".format(name, s0))\n+            self._emit_cand_defs(cg, \"{}_c1_s{}\".format(name, s0))\n+            self._emit_cand_defs(cg, \"{}_c2_s{}\".format(name, s0))\n+            for offset in range(1, 5):\n+                cg.align_defs([\n+                    (\"logic\", \"reg_{}_addr_conflict_s{}_s{};\".format(\n+                        name, s0 + offset, s0)),\n+                ])\n+            cg.emit()\n+\n+            cg.comment(\"Stage {} metadata\".format(s1))\n+            cg.align_defs([\n+                (\"logic\", \"{}_rollback_s{};\".format(name, s1)),\n+                (\"logic\", \"{}_use_fwd_s2_s{};\".format(name, s1)),\n+                (\"logic\", \"{}_use_fwd_s3_s{};\".format(name, s1)),\n+                (\"bitmap_t\", \"{}_b_pre_s{};\".format(name, s1)),\n+                (\"bitmap_t\", \"{}_bitmap_postop_s{};\".format(name, s1)),\n+                (\"bitmap_t\", \"reg_{}_bitmap_postop_s{};\".format(name, s1)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"{}_idx_s{};\".format(name, s1)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"reg_{}_idx_s{};\".format(name, s1)),\n+                (\"bitmap_t\", \"{}_oh_s{};\".format(name, s1)),\n+                (\"bitmap_t\", \"reg_{}_oh_s{};\".format(name, s1)),\n+                (\"bitmap_t\", \"{}_s0_oh_s{};\".format(name, s1)),\n+                (\"logic\", \"{}_postop_zero_s{};\".format(name, s1)),\n+                (\"logic\", \"reg_{}_postop_zero_s{};\".format(name, s1)),\n+                (\"counter_t\", \"old_{}_counter_s{};\".format(name, s1)),\n+                (\"counter_t\", \"reg_old_{}_counter_s{};\".format(name, s1)),\n+            ])\n+            for offset in range(1, 5):\n+                cg.align_defs([\n+                    (\"logic\", \"reg_{}_addr_conflict_s{}_s{};\".format(\n+                        name, s1 + offset, s1)),\n+                ])\n+            cg.emit()\n+\n+            cg.comment(\"Stage {} metadata\".format(s2))\n+            cg.align_defs([\n+                (\"counter_t\", \"old_{}_counter_s{};\".format(name, s2)),\n+                (\"counter_t\", \"new_{}_counter_s{};\".format(name, s2)),\n+                (\"logic\", \"{}_counter_non_zero_s{};\".format(name, s2)),\n+                (\"logic\", \"{}_changes_bm_s{};\".format(name, s2)),\n+                (\"bitmap_t\", \"{}_bitmap_s{};\".format(name, s2)),\n+                (\"counter_t\", \"reg_{}_counter_s{};\".format(name, s2)),\n+                (\"counter_t\", \"reg_old_{}_counter_s{};\".format(name, s2)),\n+                (\"logic\", \"reg_{}_counter_non_zero_s{};\".format(name, s2)),\n+                (\"logic [HEAP_LOG_BITMAP_WIDTH-1:0]\", \"reg_{}_idx_s{};\".format(name, s2)),\n+            ])\n+            self._emit_next_level_defs(cg, s2)\n+            cg.emit()\n \n \n     def emit_state_dependent_combinational_logic(self, cg: CodeGen) -> None:\n         \"\"\"Emit this level through the supplied CodeGen instance.\"\"\"\n-        raise NotImplementedError(\"Bitmap-level implementation removed\")\n+        name = self.name()\n+        end_c = self.end_cycle\n+        seq_c = end_c - 1\n+\n+        if self.sram_bitmap:\n+            cg.emit([\n+                \"bm_{0}_wren = reg_valid_s[{1}];\".format(name, seq_c),\n+                \"bm_{0}_wraddress = reg_{0}_addr_s[{1}];\".format(name, seq_c),\n+                \"bm_{0}_data = {0}_bitmap_s{2};\".format(name, seq_c, end_c),\n+            ])\n+        if self.sram_counters:\n+            addr_expr = (\"reg_{0}_idx_s{1}\".format(name, seq_c) if self.id == 1 else\n+                         \"{{reg_{0}_addr_s[{1}], reg_{0}_idx_s{1}}}\".format(name, seq_c))\n+            cg.emit([\n+                \"counter_{0}_wren = reg_valid_s[{1}];\".format(name, seq_c),\n+                \"counter_{0}_wraddress = {1};\".format(name, addr_expr),\n+                \"counter_{0}_data = new_{0}_counter_s{2};\".format(name, seq_c, end_c),\n+            ])\n \n \n     def emit_combinational_default_assigns(self, cg: CodeGen) -> None:\n         \"\"\"Emit this level through the supplied CodeGen instance.\"\"\"\n-        raise NotImplementedError(\"Bitmap-level implementation removed\")\n+        name = self.name()\n+        end_c = self.end_cycle\n+        seq_c = end_c - 1\n+        next_name = self.next_level.name()\n+\n+        if not self.sram_counters:\n+            addr_expr = \"'0\"\n+        else:\n+            addr_expr = (\"reg_{0}_idx_s{1}\".format(name, seq_c) if self.id == 1 else\n+                         \"{{reg_{0}_addr_s[{1}], reg_{0}_idx_s{1}}}\".format(name, seq_c))\n+        if self.is_leaf:\n+            cg.emit(\"priority_s{} = {};\".format(end_c, addr_expr))\n+        else:\n+            cg.emit(\"{}_addr_s{} = {};\".format(next_name, end_c, addr_expr))\n+\n+\n+    def _emit_next_level_comb(self, cg: CodeGen, end_c: int) -> None:\n+        \"\"\"Emits combinational logic at end_cycle driving next level.\"\"\"\n+        name = self.name()\n+        seq_c = end_c - 1\n+        next_name = self.next_level.name()\n+\n+        if not self.sram_counters:\n+            addr_expr = (\"{0}_idx_s{1}\".format(name, end_c) if self.id == 1 else\n+                         \"{{reg_{0}_addr_s[{1}], {0}_idx_s{2}}}\".format(name, seq_c, end_c))\n+            if self.is_leaf:\n+                cg.emit([\n+                    \"priority_s{0} = {1};\".format(end_c, addr_expr),\n+                    \"pb_rdaddress = priority_s{0};\".format(end_c),\n+                ])\n+            else:\n+                cg.emit(\"{}_addr_s{} = {};\".format(next_name, end_c, addr_expr))\n+\n+        for offset in range(1, 5):\n+            other_idx = self._next_level_idx_slice(seq_c + offset)\n+            if self.id == 1 and not self.bbq.is_logically_partitioned:\n+                parent_match = \"reg_valid_s[{}] && reg_valid_s[{}]\".format(seq_c, seq_c + offset)\n+            else:\n+                parent_match = \"reg_{}_addr_conflict_s{}_s{}\".format(name, seq_c + offset, seq_c)\n+            target_conflict = (\"pb_addr_conflict_s{}_s{}\".format(end_c + offset, end_c)\n+                               if self.is_leaf else\n+                               \"{}_addr_conflict_s{}_s{}\".format(next_name, end_c + offset, end_c))\n+            if not self.sram_counters:\n+                enq_idx = self._priority_idx_slice(seq_c)\n+                c0_pref = \"{}_c0_s{}\".format(name, end_c)\n+                bit_eq = \"{}_bit_eq_s{}_s{}\".format(next_name, end_c + offset, end_c)\n+                cg.emit([\n+                    \"{0} = ~(reg_is_enque_s[{1}] ? ({2} ^ {3}) : (reg_is_deque_min_s[{1}] ? ({4}_lsb_idx ^ {3}) : ({4}_msb_idx ^ {3})));\".format(\n+                        bit_eq, seq_c, enq_idx, other_idx, c0_pref),\n+                    \"{0} = ({1} && (&{2}));\".format(target_conflict, parent_match, bit_eq),\n+                ])\n+            else:\n+                idx_match = \"(reg_{}_idx_s{} == {})\".format(name, seq_c, other_idx)\n+                cg.emit(\"{} = ({} && {});\".format(target_conflict, parent_match, idx_match))\n+\n+        if self.is_leaf:\n+            cg.emit(\"pb_rden = reg_valid_s[{}];\".format(seq_c))\n+            cg.start_conditional(\"if\", \"pb_addr_conflict_s{}_s{}\".format(\n+                self.next_level.end_cycle, end_c))\n+            cg.emit([\n+                \"pb_rdwr_conflict = 1;\",\n+                \"pb_rden = 0;\",\n+            ])\n+            cg.end_conditional(\"if\")\n+        elif self.next_level.sram_bitmap:\n+            cg.emit([\n+                \"bm_{0}_rden = reg_valid_s[{1}];\".format(next_name, seq_c),\n+                \"bm_{0}_rdaddress = {0}_addr_s{1};\".format(next_name, end_c),\n+            ])\n+            cg.start_conditional(\"if\", \"{}_addr_conflict_s{}_s{}\".format(\n+                next_name, self.next_level.end_cycle, end_c))\n+            cg.emit(\"bm_{}_rden = 0;\".format(next_name))\n+            cg.end_conditional(\"if\")\n+\n+\n+    def _emit_multi_cand_ffs(self, cg: CodeGen, cands: list[tuple[str, str, int]],\n+                             is_enq: str, is_min: str, enq_idx: str, enq_oh: str) -> None:\n+        \"\"\"Emits flat reduction-OR FFS for W <= 32 and log-W prefix FFS for W > 32.\"\"\"\n+        cg.start_conditional(\"if\", \"(HEAP_BITMAP_WIDTH <= 16) || ((HEAP_NUM_LEVELS <= 2) && (HEAP_BITMAP_WIDTH <= 32))\")\n+        cg.start_for(\"j\", \"j < HEAP_BITMAP_WIDTH\")\n+        for prefix, bm_expr, _ in cands:\n+            cg.emit([\n+                \"{0}_has_lo[j] = |({1} & ((HEAP_BITMAP_WIDTH'(1'b1) << j) - 1'b1));\".format(\n+                    prefix, bm_expr),\n+                \"{0}_has_hi[j] = |({1} & ~((HEAP_BITMAP_WIDTH'(2'd2) << j) - 1'b1));\".format(\n+                    prefix, bm_expr),\n+            ])\n+        cg.end_for()\n+        cg.end_conditional(\"if\")\n+        cg.start_conditional(\"else if\", \"HEAP_BITMAP_WIDTH <= 32\")\n+        cg.start_for(\"j\", \"j < (HEAP_BITMAP_WIDTH / 2)\")\n+        for prefix, bm_expr, _ in cands:\n+            cg.emit([\n+                \"{0}_has_lo[2*j +: 2] = ({{2{{|({1} & ((HEAP_BITMAP_WIDTH'(1'b1) << (2*j)) - 1'b1))}}}} | {{{1}[2*j], 1'b0}});\".format(\n+                    prefix, bm_expr),\n+                \"{0}_has_hi[2*j +: 2] = ({{2{{|({1} & ~((HEAP_BITMAP_WIDTH'(3'd4) << (2*j)) - 1'b1))}}}} | {{1'b0, {1}[(2*j)+1]}});\".format(\n+                    prefix, bm_expr),\n+            ])\n+        cg.end_for()\n+        cg.end_conditional(\"else if\")\n+        cg.start_conditional(\"else\", None)\n+        for prefix, bm_expr, _ in cands:\n+            cg.emit([\n+                \"{0}_has_lo = ({1} << 1);\".format(prefix, bm_expr),\n+                \"{0}_has_hi = ({1} >> 1);\".format(prefix, bm_expr),\n+            ])\n+        cg.start_for(\"j\", \"j < HEAP_LOG_BITMAP_WIDTH\")\n+        for prefix, _, _ in cands:\n+            cg.emit([\n+                \"{0}_has_lo = ({0}_has_lo | ({0}_has_lo << (1 << j)));\".format(prefix),\n+                \"{0}_has_hi = ({0}_has_hi | ({0}_has_hi >> (1 << j)));\".format(prefix),\n+            ])\n+        cg.end_for()\n+        cg.end_conditional(\"else\")\n+\n+        for prefix, bm_expr, _ in cands:\n+            cg.emit([\n+                \"{0}_lsb_oh = ({1} & (~{0}_has_lo));\".format(prefix, bm_expr),\n+                \"{0}_msb_oh = ({1} & (~{0}_has_hi));\".format(prefix, bm_expr),\n+                \"{0}_deq_oh = ({1} & ({2} ? (~{0}_has_lo) : (~{0}_has_hi)));\".format(\n+                    prefix, bm_expr, is_min),\n+                \"{0}_post = ({1} ? ({2} | {3}) : ({2} & ({4} ? {0}_has_lo : {0}_has_hi)));\".format(\n+                    prefix, is_enq, bm_expr, enq_oh, is_min),\n+                \"{0}_lsb_fold = {{~{0}_has_lo[HEAP_BITMAP_WIDTH-1], {0}_lsb_oh[HEAP_BITMAP_WIDTH-2:0]}};\".format(\n+                    prefix),\n+            ])\n+\n+        cg.start_for(\"j\", \"j < HEAP_LOG_BITMAP_WIDTH\")\n+        for prefix, _, _ in cands:\n+            cg.emit([\n+                \"{0}_lsb_idx[j] = |({0}_lsb_fold & bitmap_t'(FFS_IDX_MASK[j]));\".format(prefix),\n+                \"{0}_msb_idx[j] = |({0}_msb_oh & bitmap_t'(FFS_IDX_MASK[j]));\".format(prefix),\n+            ])\n+        cg.end_for()\n+\n+        for prefix, _, _ in cands:\n+            cg.emit(\"{0}_idx = ({1} ? {2} : ({3} ? {0}_lsb_idx : {0}_msb_idx));\".format(\n+                prefix, is_enq, enq_idx, is_min))\n \n \n     def emit_state_agnostic_combinational_logic(self, cg: CodeGen) -> None:\n         \"\"\"Emit this level through the supplied CodeGen instance.\"\"\"\n-        raise NotImplementedError(\"Bitmap-level implementation removed\")\n+        name = self.name()\n+        c0 = self.start_cycle + int(self.sram_bitmap)\n+        end_c = self.end_cycle\n+\n+        if not self.sram_counters:\n+            # 1-stage L1: end_c == c0\n+            seq_c = end_c - 1\n+            enq_idx = self._priority_idx_slice(seq_c)\n+            is_enq = \"reg_is_enque_s[{}]\".format(seq_c)\n+            is_min = \"reg_is_deque_min_s[{}]\".format(seq_c)\n+            enq_oh = \"{}_enq_oh_s{}\".format(name, end_c)\n+            c0_pref = \"{}_c0_s{}\".format(name, end_c)\n+\n+            cg.emit(\"{0} = (HEAP_BITMAP_WIDTH'(1'b1) << {1});\".format(enq_oh, enq_idx))\n+            self._emit_multi_cand_ffs(cg, [\n+                (c0_pref, \"l1_bitmap\", 0),\n+            ], is_enq, is_min, enq_idx, enq_oh)\n+            cg.emit([\n+                \"{0}_idx_s{1} = {2}_idx;\".format(name, end_c, c0_pref),\n+                \"{0}_op_oh_s{1} = ({2} ? {3} : {4}_deq_oh);\".format(\n+                    name, end_c, is_enq, enq_oh, c0_pref),\n+            ])\n+\n+            cg.start_for(\"j\", \"j < HEAP_BITMAP_WIDTH\")\n+            cg.emit(\n+                \"{0}_bitmap_s{1}[j] = ({2}_post[j] | (l1_bitmap[j] & {0}_counters[j][WATERLEVEL_IDX]));\".format(\n+                    name, end_c, c0_pref))\n+            cg.end_for()\n+\n+            if self.is_leaf:\n+                old_cnt = \"old_{}_counter_s{}\".format(name, end_c)\n+                new_cnt = \"new_{}_counter_s{}\".format(name, end_c)\n+                cg.emit(\"{0} = ({1} ? {2}_counters[{3}] : ({4} ? {2}_counters[{5}_lsb_idx] : {2}_counters[{5}_msb_idx]));\".format(\n+                    old_cnt, is_enq, name, enq_idx, is_min, c0_pref))\n+                self._emit_counter_update(cg, new_cnt, old_cnt, is_enq)\n+                cg.emit(\"{0}_counter_non_zero_s{1} = ({2} | {3}[WATERLEVEL_IDX]);\".format(\n+                    name, end_c, is_enq, old_cnt))\n+\n+            if not self.is_leaf and not self.next_level.sram_bitmap:\n+                next_name = self.next_level.name()\n+                cg.emit([\n+                    \"{0}_next_bm_enq_s{1} = {2}_bitmaps[{3}];\".format(name, end_c, next_name, enq_idx),\n+                    \"{0}_next_bm_min_s{1} = {2}_bitmaps[{3}_lsb_idx];\".format(name, end_c, next_name, c0_pref),\n+                    \"{0}_next_bm_max_s{1} = {2}_bitmaps[{3}_msb_idx];\".format(name, end_c, next_name, c0_pref),\n+                    \"{0}_next_bm_read_s{1} = ({2} ? {0}_next_bm_enq_s{1} : ({3} ? {0}_next_bm_min_s{1} : {0}_next_bm_max_s{1}));\".format(\n+                        name, end_c, is_enq, is_min),\n+                ])\n+\n+            self._emit_next_level_comb(cg, end_c)\n+        else:\n+            s0 = c0\n+            s1 = c0 + 1\n+            s2 = end_c\n+\n+            # 1. Stage s2 (end_c) combinational\n+            seq_s2 = s2 - 1\n+            old_cnt2 = \"old_{}_counter_s{}\".format(name, s2)\n+            new_cnt2 = \"new_{}_counter_s{}\".format(name, s2)\n+            cg.emit(\"{} = reg_old_{}_counter_s{};\".format(old_cnt2, name, seq_s2))\n+            self._emit_counter_update(cg, new_cnt2, old_cnt2, \"reg_is_enque_s[{}]\".format(seq_s2))\n+            cg.emit([\n+                \"{0}_counter_non_zero_s{1} = (reg_is_enque_s[{2}] | {3}[WATERLEVEL_IDX]);\".format(\n+                    name, s2, seq_s2, old_cnt2),\n+                \"{0}_changes_bm_s{1} = (reg_is_enque_s[{2}] | (~{3}[WATERLEVEL_IDX]));\".format(\n+                    name, s2, seq_s2, old_cnt2),\n+                \"{0}_bitmap_s{1} = ({0}_changes_bm_s{1} ? reg_{0}_bitmap_postop_s{2} : reg_{0}_bitmap_s[{2}]);\".format(\n+                    name, s2, seq_s2),\n+            ])\n+            self._emit_next_level_comb(cg, s2)\n+\n+            # 2. Stage s1 (c0 + 1) combinational\n+            seq_s1 = s1 - 1\n+            c21 = \"reg_{}_addr_conflict_s{}_s{}\".format(name, s1, s0)\n+            c31 = \"reg_{}_addr_conflict_s{}_s{}\".format(name, s2, s0)\n+            cg.start_conditional(\"if\", \"(HEAP_BITMAP_WIDTH <= 16) || ((HEAP_NUM_LEVELS <= 2) && (HEAP_BITMAP_WIDTH <= 32))\")\n+            cg.start_for(\"j\", \"j < HEAP_BITMAP_WIDTH\")\n+            cg.emit(\n+                \"{0}_s0_oh_s{1}[j] = (reg_{0}_idx_s{2} == j[HEAP_LOG_BITMAP_WIDTH-1:0]);\".format(\n+                    name, s1, seq_s1))\n+            cg.end_for()\n+            cg.end_conditional(\"if\")\n+            cg.start_conditional(\"else\", None)\n+            cg.emit(\n+                \"{0}_s0_oh_s{1} = (HEAP_BITMAP_WIDTH'(1'b1) << reg_{0}_idx_s{2});\".format(\n+                    name, s1, seq_s1))\n+            cg.end_conditional(\"else\")\n+\n+            cg.emit([\n+                \"{0}_b_pre_s{1} = ({2} ? {0}_bitmap_s{3} : ({4} ? reg_{0}_bitmap_s[{3}] : reg_{0}_bitmap_s[{5}]));\".format(\n+                    name, s1, c21, s2, c31, seq_s1),\n+                \"{0}_rollback_s{1} = (reg_{0}_c21_both_deq_s{2} && {3}[WATERLEVEL_IDX] && (reg_{0}_c21_same_deq_s{2} || reg_{0}_postop_zero_s{4}));\".format(\n+                    name, s1, seq_s1, old_cnt2, seq_s2),\n+                \"{0}_idx_s{1} = ({0}_rollback_s{1} ? reg_{0}_idx_s{2} : reg_{0}_idx_s{3});\".format(\n+                    name, s1, seq_s2, seq_s1),\n+                \"{0}_oh_s{1} = ({0}_rollback_s{1} ? reg_{0}_oh_s{2} : {0}_s0_oh_s{1});\".format(\n+                    name, s1, seq_s2),\n+                \"{0}_bitmap_postop_s{1} = ((!{2} || {0}_changes_bm_s{3}) ? reg_{0}_bitmap_postop_s{4} : ({0}_rollback_s{1} ? reg_{0}_bitmap_postop_s{5} : (reg_{0}_bitmap_postop_s{4} | reg_{0}_oh_s{5})));\".format(\n+                    name, s1, c21, s2, seq_s1, seq_s2),\n+                \"{0}_postop_zero_s{1} = ((!{2} || {0}_changes_bm_s{3}) ? ffs_{0}_inst_zero[1] : ({0}_rollback_s{1} ? reg_{0}_postop_zero_s{5} : 1'b0));\".format(\n+                    name, s1, c21, s2, seq_s1, seq_s2),\n+                \"{0}_use_fwd_s2_s{1} = ({2} && ({0}_rollback_s{1} || (reg_{0}_idx_s{3} == reg_{0}_idx_s{4})));\".format(\n+                    name, s1, c21, seq_s1, seq_s2),\n+                \"{0}_use_fwd_s3_s{1} = ({2} && (reg_{0}_idx_s{3} == reg_{0}_idx_s{4}));\".format(\n+                    name, s1, c31, seq_s1, s2),\n+                \"old_{0}_counter_s{1} = ({0}_use_fwd_s2_s{1} ? new_{0}_counter_s{2} : ({0}_use_fwd_s3_s{1} ? reg_{0}_counter_s{2} : counter_{0}_q));\".format(\n+                    name, s1, s2),\n+            ])\n+\n+            # 3. Stage s0 (c0) combinational\n+            seq_s0 = s0 - 1\n+            c10 = \"reg_{}_addr_conflict_s{}_s{}\".format(name, s0, seq_s0)\n+            c20 = \"reg_{}_addr_conflict_s{}_s{}\".format(name, s1, seq_s0)\n+            enq_idx = self._priority_idx_slice(seq_s0)\n+            is_enq = \"reg_is_enque_s[{}]\".format(seq_s0)\n+            is_min = \"reg_is_deque_min_s[{}]\".format(seq_s0)\n+            enq_oh = \"{}_enq_oh_s{}\".format(name, s0)\n+\n+            cg.emit(\"{0} = (HEAP_BITMAP_WIDTH'(1'b1) << {1});\".format(enq_oh, enq_idx))\n+            self._emit_multi_cand_ffs(cg, [\n+                (\"{}_c0_s{}\".format(name, s0), \"reg_{}_bitmap_s[{}]\".format(name, seq_s0), 0),\n+                (\"{}_c1_s{}\".format(name, s0), \"reg_{}_bitmap_postop_s{}\".format(name, s0), 1),\n+                (\"{}_c2_s{}\".format(name, s0), \"reg_{}_bitmap_postop_s{}\".format(name, seq_s2), 2),\n+            ], is_enq, is_min, enq_idx, enq_oh)\n+            cg.emit([\n+                \"{0}_d3_take_s2_s{1} = ((!{2}) && (reg_is_enque_s[{3}] ? ((({4} == reg_is_deque_min_s[{5}]) || reg_{0}_postop_zero_s{5}) && ({4} ? reg_{0}_s2_le_s1_s{1} : reg_{0}_s2_ge_s1_s{1})) : (({4} == reg_is_deque_min_s[{5}]) ? 1'b1 : ffs_{0}_inst_zero[1])));\".format(\n+                    name, s0, is_enq, seq_s1, is_min, seq_s2),\n+                \"{0}_cand3_idx_s{1} = ({0}_d3_take_s2_s{1} ? reg_{0}_idx_s{2} : {0}_c1_s{1}_idx);\".format(\n+                    name, s0, seq_s2),\n+                \"{0}_cand3_post_s{1} = ({0}_d3_take_s2_s{1} ? (reg_{0}_bitmap_postop_s{1} & ~reg_{0}_oh_s{2}) : ({0}_c1_s{1}_post | reg_{0}_oh_s{2}));\".format(\n+                    name, s0, seq_s2),\n+            ])\n+\n+            cg.start_conditional(\"if\", \"!{}\".format(c10))\n+            cg.emit([\n+                \"{0}_idx_s{1} = (({2} && {0}_changes_bm_s{3}) ? {0}_c2_s{1}_idx : {0}_c0_s{1}_idx);\".format(\n+                    name, s0, c20, s2),\n+                \"{0}_bitmap_postop_s{1} = (({2} && {0}_changes_bm_s{3}) ? {0}_c2_s{1}_post : {0}_c0_s{1}_post);\".format(\n+                    name, s0, c20, s2),\n+            ])\n+            cg.end_conditional(\"if\")\n+            cg.start_conditional(\"else if\", \"!{} || {}_changes_bm_s{}\".format(c21, name, s2))\n+            cg.emit([\n+                \"{0}_idx_s{1} = {0}_c1_s{1}_idx;\".format(name, s0),\n+                \"{0}_bitmap_postop_s{1} = {0}_c1_s{1}_post;\".format(name, s0),\n+            ])\n+            cg.end_conditional(\"else if\")\n+            cg.start_conditional(\"else if\", \"{}_rollback_s{}\".format(name, s1))\n+            cg.emit([\n+                \"{0}_idx_s{1} = {0}_c2_s{1}_idx;\".format(name, s0),\n+                \"{0}_bitmap_postop_s{1} = {0}_c2_s{1}_post;\".format(name, s0),\n+            ])\n+            cg.end_conditional(\"else if\")\n+            cg.start_conditional(\"else\", None)\n+            cg.emit([\n+                \"{0}_idx_s{1} = {0}_cand3_idx_s{1};\".format(name, s0),\n+                \"{0}_bitmap_postop_s{1} = {0}_cand3_post_s{1};\".format(name, s0),\n+            ])\n+            cg.end_conditional(\"else\")\n+\n+            cg.emit([\n+                \"counter_{0}_rden = reg_valid_s[{1}];\".format(name, seq_s0),\n+                \"counter_{0}_rdaddress = {{reg_{0}_addr_s[{1}], {0}_idx_s{2}}};\".format(name, seq_s0, s0),\n+            ])\n+\n+\n+    def _emit_common_stage_seq(self, cg: CodeGen, cycle: int,\n+                               skip_self_bm: bool = False) -> None:\n+        \"\"\"Emits common per-stage sequential register transfers.\"\"\"\n+        value_override = {}\n+        if self.is_leaf and cycle == self.end_cycle:\n+            value_override[\"reg_priority_s\"] = \"priority_s{}\".format(cycle)\n+        self.bbq.emit_sequential_primary_signals(cycle, value_override)\n+\n+        cg.emit(\"reg_op_color_s[{0}] <= reg_op_color_s[{1}];\".format(cycle, cycle - 1))\n+        for level in self.bbq.bitmap_levels:\n+            if level.id < 2:\n+                continue\n+            if level.id <= self.id:\n+                cg.emit(\"reg_{0}_addr_s[{1}] <= reg_{0}_addr_s[{2}];\".format(\n+                    level.name(), cycle, cycle - 1))\n+            if level.id < self.id or (level.id == self.id and not skip_self_bm):\n+                cg.emit(\"reg_{0}_bitmap_s[{1}] <= reg_{0}_bitmap_s[{2}];\".format(\n+                    level.name(), cycle, cycle - 1))\n+\n+\n+    def _emit_next_level_seq(self, cg: CodeGen, end_c: int) -> None:\n+        \"\"\"Emits sequential logic at end_cycle for next level interface.\"\"\"\n+        name = self.name()\n+        next_name = self.next_level.name()\n+        for offset in range(1, 5):\n+            cg.emit(\"reg_{0}_addr_conflict_s{1}_s{2} <= {0}_addr_conflict_s{1}_s{2};\".format(\n+                next_name, end_c + offset, end_c))\n+\n+        if not self.is_leaf:\n+            cg.emit(\"reg_{0}_addr_s[{1}] <= {0}_addr_s{1};\".format(next_name, end_c))\n+            if not self.next_level.sram_bitmap:\n+                if not self.sram_counters:\n+                    cg.emit(\n+                        \"reg_{0}_bitmap_s[{1}] <= ({0}_addr_conflict_s{2}_s{1} ? {0}_bitmap_s{2} : {3}_next_bm_read_s{1});\".format(\n+                            next_name, end_c, self.next_level.end_cycle, name))\n+                else:\n+                    cg.emit(\n+                        \"reg_{0}_bitmap_s[{1}] <= ({0}_addr_conflict_s{2}_s{1} ? {0}_bitmap_s{2} : {0}_bitmaps[{0}_addr_s{1}]);\".format(\n+                            next_name, end_c, self.next_level.end_cycle))\n \n \n     def emit_sequential_pipeline_logic(self, cg: CodeGen) -> None:\n         \"\"\"Emit this level through the supplied CodeGen instance.\"\"\"\n-        raise NotImplementedError(\"Bitmap-level implementation removed\")\n+        name = self.name()\n+        c0 = self.start_cycle + int(self.sram_bitmap)\n+        end_c = self.end_cycle\n+\n+        if not self.sram_counters:\n+            # 1-stage L1: end_c == c0\n+            self._emit_common_stage_seq(cg, end_c, skip_self_bm=True)\n+            cg.emit(\"reg_{0}_bitmap_postop_s{1} <= '0;\".format(name, c0))\n+            if self.is_leaf:\n+                cg.emit([\n+                    \"reg_{0}_counter_s{1} <= new_{0}_counter_s{1};\".format(name, end_c),\n+                    \"reg_old_{0}_counter_s{1} <= old_{0}_counter_s{1};\".format(name, end_c),\n+                    \"reg_{0}_counter_non_zero_s{1} <= {0}_counter_non_zero_s{1};\".format(name, end_c),\n+                ])\n+            cg.start_conditional(\"if\", \"reg_valid_s[{}]\".format(end_c - 1))\n+            cg.emit(\"l1_bitmap <= {0}_bitmap_s{1};\".format(name, end_c))\n+            cg.end_conditional(\"if\")\n+\n+            cg.start_for(\"i\", \"i < HEAP_BITMAP_WIDTH\")\n+            cg.start_conditional(\"if\", \"reg_valid_s[{0}] && {1}_op_oh_s{2}[i]\".format(\n+                end_c - 1, name, end_c))\n+            cg.emit([\n+                \"{0}_counters[i][WATERLEVEL_IDX-1:0] <= (reg_is_enque_s[{1}] ? ({0}_counters[i][WATERLEVEL_IDX-1:0] + 1'b1) : ({0}_counters[i][WATERLEVEL_IDX-1:0] - 1'b1));\".format(\n+                    name, end_c - 1),\n+                \"{0}_counters[i][WATERLEVEL_IDX] <= (reg_is_enque_s[{1}] ? ({0}_counters[i][WATERLEVEL_IDX] | {0}_counters[i][0]) : ((|{0}_counters[i][WATERLEVEL_IDX-1:2]) | (&{0}_counters[i][1:0])));\".format(\n+                    name, end_c - 1),\n+            ])\n+            cg.end_conditional(\"if\")\n+            cg.end_for()\n+\n+            self._emit_next_level_seq(cg, end_c)\n+            cg.emit()\n+        else:\n+            s0 = c0\n+            s1 = c0 + 1\n+            s2 = end_c\n+\n+            # Stage s2 (end_c)\n+            self._emit_common_stage_seq(cg, s2, skip_self_bm=True)\n+            cg.emit([\n+                \"reg_{0}_bitmap_s[{1}] <= {0}_bitmap_s{1};\".format(name, s2),\n+                \"reg_{0}_counter_s{1} <= new_{0}_counter_s{1};\".format(name, s2),\n+                \"reg_old_{0}_counter_s{1} <= old_{0}_counter_s{1};\".format(name, s2),\n+                \"reg_{0}_counter_non_zero_s{1} <= {0}_counter_non_zero_s{1};\".format(name, s2),\n+                \"reg_{0}_idx_s{1} <= reg_{0}_idx_s{2};\".format(name, s2, s1),\n+            ])\n+            if not self.sram_bitmap:\n+                cg.start_conditional(\"if\", \"HEAP_BITMAP_WIDTH <= 32\")\n+                cg.start_for(\"i\", \"i < NUM_BITMAPS_L{}\".format(self.id))\n+                cg.start_conditional(\"if\", \"reg_valid_s[{0}] && (reg_{1}_addr_s[{0}] == i[BITMAP_L{2}_AWIDTH-1:0])\".format(\n+                    s2 - 1, name, self.id))\n+                cg.emit(\"{0}_bitmaps[i] <= {0}_bitmap_s{1};\".format(name, s2))\n+                cg.end_conditional(\"if\")\n+                cg.end_for()\n+                cg.end_conditional(\"if\")\n+                cg.start_conditional(\"else\", None)\n+                cg.start_conditional(\"if\", \"reg_valid_s[{}]\".format(s2 - 1))\n+                cg.emit(\"{0}_bitmaps[reg_{0}_addr_s[{1}]] <= {0}_bitmap_s{2};\".format(\n+                    name, s2 - 1, s2))\n+                cg.end_conditional(\"if\")\n+                cg.end_conditional(\"else\")\n+            self._emit_next_level_seq(cg, s2)\n+            cg.emit()\n+\n+            # Stage s1 (c0 + 1)\n+            self._emit_common_stage_seq(cg, s1, skip_self_bm=True)\n+            cg.emit([\n+                \"reg_{0}_bitmap_s[{1}] <= {0}_b_pre_s{1};\".format(name, s1),\n+                \"reg_{0}_bitmap_postop_s{1} <= {0}_bitmap_postop_s{1};\".format(name, s1),\n+                \"reg_{0}_idx_s{1} <= {0}_idx_s{1};\".format(name, s1),\n+                \"reg_{0}_oh_s{1} <= {0}_oh_s{1};\".format(name, s1),\n+                \"reg_{0}_postop_zero_s{1} <= {0}_postop_zero_s{1};\".format(name, s1),\n+                \"reg_old_{0}_counter_s{1} <= old_{0}_counter_s{1};\".format(name, s1),\n+            ])\n+            for offset in range(1, 5):\n+                cg.emit(\"reg_{0}_addr_conflict_s{1}_s{2} <= reg_{0}_addr_conflict_s{3}_s{4};\".format(\n+                    name, s1 + offset, s1, s1 + offset - 1, s1 - 1))\n+            cg.emit()\n+\n+            # Stage s0 (c0)\n+            enq_idx_s0 = self._priority_idx_slice(s0 - 1)\n+            self._emit_common_stage_seq(cg, s0, skip_self_bm=False)\n+            cg.emit([\n+                \"reg_{0}_bitmap_postop_s{1} <= {0}_bitmap_postop_s{1};\".format(name, s0),\n+                \"reg_{0}_idx_s{1} <= {0}_idx_s{1};\".format(name, s0),\n+                \"reg_{0}_c21_both_deq_s{1} <= (reg_{0}_addr_conflict_s{1}_s{2} && (!reg_is_enque_s[{2}]) && (!reg_is_enque_s[{1}]));\".format(\n+                    name, s0, s0 - 1),\n+                \"reg_{0}_c21_same_deq_s{1} <= (reg_is_deque_min_s[{2}] == reg_is_deque_min_s[{1}]);\".format(\n+                    name, s0, s0 - 1),\n+                \"reg_{0}_s2_le_s1_s{1} <= ({0}_idx_s{2} <= {3});\".format(\n+                    name, s0, s1, enq_idx_s0),\n+                \"reg_{0}_s2_ge_s1_s{1} <= ({0}_idx_s{2} >= {3});\".format(\n+                    name, s0, s1, enq_idx_s0),\n+            ])\n+            for offset in range(1, 5):\n+                cg.emit(\"reg_{0}_addr_conflict_s{1}_s{2} <= reg_{0}_addr_conflict_s{3}_s{4};\".format(\n+                    name, s0 + offset, s0, s0 + offset - 1, s0 - 1))\n+            cg.emit()\n+\n+            # Stage s_bm (start_cycle when sram_bitmap is True)\n+            if self.sram_bitmap:\n+                s_bm = self.start_cycle\n+                self._emit_common_stage_seq(cg, s_bm, skip_self_bm=True)\n+                for offset in range(1, 5):\n+                    cg.emit(\"reg_{0}_addr_conflict_s{1}_s{2} <= reg_{0}_addr_conflict_s{3}_s{4};\".format(\n+                        name, s_bm + offset, s_bm, s_bm + offset - 1, s_bm - 1))\n+                cg.emit(\n+                    \"reg_{0}_bitmap_s[{1}] <= (reg_{0}_addr_conflict_s{2}_s{3} ? {0}_bitmap_s{4} : (reg_{0}_addr_conflict_s{4}_s{3} ? bm_{0}_data_r : bm_{0}_q));\".format(\n+                        name, s_bm, s_bm + 2, s_bm - 1, s_bm + 3))\n+                cg.emit()\n"}}}