@@ -177,6 +177,7 @@ def _create_deepseek_v4_cache_manager(
177177 tp_size : int = 1 ,
178178 enable_attention_dp : bool = False ,
179179 enable_swa_scratch_reuse : bool = False ,
180+ spec_config : object | None = None ,
180181 ) -> Tuple [DeepseekV4CacheManager , DeepSeekV4SparseAttentionConfig ]:
181182 """Helper to create a DeepseekV4CacheManager for testing."""
182183
@@ -224,6 +225,7 @@ def _create_deepseek_v4_cache_manager(
224225 max_num_tokens = max_batch_size * (max_input_len + 1 ),
225226 sparse_attn_config = sparse_attn_config ,
226227 is_draft = is_draft ,
228+ spec_config = spec_config ,
227229 )
228230
229231 return cache_manager , sparse_attn_config
@@ -1450,6 +1452,7 @@ def test_swa_scratch_reuse_disabled_by_default_for_main_manager(self):
14501452 try :
14511453 assert not cache_manager .enable_swa_scratch_reuse
14521454 assert not cache_manager .kv_cache_manager_py_config .enable_swa_scratch_reuse
1455+ assert cache_manager .kv_cache_manager_py_config .swa_scratch_reuse is None
14531456 assert cache_manager .num_attention_op_pools == cache_manager .num_local_layers
14541457 finally :
14551458 cache_manager .shutdown ()
@@ -1468,10 +1471,40 @@ def test_swa_scratch_reuse_enabled_by_config_for_main_manager(self):
14681471 try :
14691472 assert cache_manager .enable_swa_scratch_reuse
14701473 assert cache_manager .kv_cache_manager_py_config .enable_swa_scratch_reuse
1474+ assert cache_manager .kv_cache_manager_py_config .swa_scratch_reuse is not None
1475+ assert cache_manager .kv_cache_manager_py_config .swa_scratch_reuse .max_rewind_len == 0
14711476 assert cache_manager .num_attention_op_pools == cache_manager .num_local_layers
14721477 finally :
14731478 cache_manager .shutdown ()
14741479
1480+ def test_swa_scratch_reuse_uses_extra_kv_tokens_for_rewind (self ):
1481+ spec_config = SimpleNamespace (
1482+ max_draft_len = 7 ,
1483+ max_total_draft_tokens = 7 ,
1484+ spec_dec_mode = SimpleNamespace (
1485+ is_eagle3_one_model = lambda : False ,
1486+ is_mtp_one_model = lambda : False ,
1487+ use_one_engine = lambda : True ,
1488+ ),
1489+ )
1490+ cache_manager , _ = self ._create_deepseek_v4_cache_manager (
1491+ tokens_per_block = self .tokens_per_block ,
1492+ max_batch_size = 1 ,
1493+ max_seq_len = 1024 ,
1494+ compress_ratios = [1 ],
1495+ dtype = DataType .BF16 ,
1496+ compressor_dtype = DataType .FLOAT ,
1497+ spec_config = spec_config ,
1498+ enable_swa_scratch_reuse = True ,
1499+ )
1500+
1501+ try :
1502+ scratch_reuse = cache_manager .kv_cache_manager_py_config .swa_scratch_reuse
1503+ assert scratch_reuse is not None
1504+ assert scratch_reuse .max_rewind_len == spec_config .max_draft_len - 1
1505+ finally :
1506+ cache_manager .shutdown ()
1507+
14751508 def test_draft_cache_manager_disables_swa_scratch_reuse (self ):
14761509 cache_manager , _ = self ._create_deepseek_v4_cache_manager (
14771510 tokens_per_block = self .tokens_per_block ,
@@ -1487,6 +1520,7 @@ def test_draft_cache_manager_disables_swa_scratch_reuse(self):
14871520 try :
14881521 assert not cache_manager .enable_swa_scratch_reuse
14891522 assert not cache_manager .kv_cache_manager_py_config .enable_swa_scratch_reuse
1523+ assert cache_manager .kv_cache_manager_py_config .swa_scratch_reuse is None
14901524 assert cache_manager .num_attention_op_pools == cache_manager .num_local_layers
14911525 finally :
14921526 cache_manager .shutdown ()
0 commit comments