P-21 · Evidencia de las tres corridas desatendidas (3 y 4 de octubre de 2026)¶
Esta carpeta conserva las capturas del ILA de las tres corridas desatendidas que se hicieron para
medir cada cuánto se atasca el MM2S del estímulo. Está aquí, y no en build/soak/, porque
build/ está en .gitignore y la evidencia se habría perdido en el primer borrado del árbol de
construcción.
El trabajo quedó aparcado, no cerrado: ver P-21 para el estado y el razonamiento. Lo que sigue es el dato en bruto y su lectura, para que quien lo retome no tenga que repetir las noches.
Cómo se produjo¶
Las tres corridas usaron el mismo bitstream de depuración, el mismo firmware (sondeo del MM2S a
1 ms, configTICK_RATE_HZ (1000)) y el mismo orquestador tools/noche_p21.sh, sin un solo cambio
entre ellas. Cada corrida arranca sobre una placa recién encendida con SW8: el atasco de P-21 es
permanente por diseño del firmware —set_modo_ddr(true) corre antes de submit_pass() y la ruta
de fallo no lo baja— así que una corrida equivale exactamente a un atasco, y no hay recuperación
por software.
El conductor es un bucle de tools/sweep_catalogo.py --settle 1, que encadena selecciones de
estímulo. Las capturas se leen con tools/ila_p21_leer.py.
Resultado¶
| corrida 1 | corrida 2 | corrida 3 | |
|---|---|---|---|
| directorio original | noche-20261003-215159 |
noche-20261004-071308 |
noche-20261004-122254 |
| inicio | 2026-10-03T21:54:27 | 2026-10-04T07:15:54 | 2026-10-04T12:25:39 |
| atasco | 2026-10-03T22:02:09 | 2026-10-04T08:12:12 | 2026-10-04T13:27:53 |
| tiempo hasta el atasco | 7 min 42 s | 56 min 18 s | 62 min 14 s |
| selecciones encadenadas | 323 | 2837 | 3141 |
| pasadas completas del catálogo | 41 | 354 | 392 |
líneas precursoras (pasada sin completar tras) |
7 | 0 | 0 |
disparos naturales del ILA (flanco de stalled) |
4 | 0 | 0 |
trig_gaps al final |
2 (d=2) | 30 (d=2) | 50 (d=2) |
snd_fail al final |
38 | 325 | 364 |
trig_gaps y snd_fail escalan con la duración de la corrida y son artefactos de la interacción
con el cliente (del orden de 1500 ciclos de conexión y desconexión por corrida). No son
indicadores de salud y no se usan como tales.
Lo primero que dice el dato: hay dos modos de fallo distintos, no una sola distribución¶
Las corridas 2 y 3 coinciden entre sí dentro del 10 % en selecciones y en tiempo, y sus capturas son idénticas columna por columna. La corrida 1 es ocho veces más corta, es la única con líneas precursoras, la única en la que el ILA disparó solo, y su estado final es el opuesto. Promediar las tres como si fueran muestras de la misma distribución daría una «cola larga» que el dato no respalda.
Modo A — la cadena se queda llena y bloqueada (corrida 1)¶
Los cuatro disparos naturales (c1-flanco-1.csv … c1-flanco-4.csv) son idénticos entre sí, y
son la evidencia más valiosa del conjunto porque llevan calificación de almacenamiento sobre
moved: de las 4096 muestras, 4095 son los últimos ciclos en que la cadena avanzó una muestra, y
la última es el ciclo del disparo.
En las 4095 muestras con movimiento: ddr_mode = 0, timing_paced = 0, moved = 1,
idle_cnt = 0. En la muestra del disparo: ddr_mode = 1, timing_paced = 1, moved = 0,
stalled = 1, idle_cnt = 1048576 exactamente, o sea 2²⁰, el umbral.
El hecho es que en los últimos 4095 avances de muestra antes de cada parada, ddr_mode valía 0
todas las veces. La inferencia inmediata, y es fuerte: en esa corrida la cadena no avanzó ni una
sola muestra con ddr_mode = 1. El camino DDR no entregó nada, nunca, en lugar de entregar unas
cuantas y atascarse después.
El estado congelado (c1-forzado.csv, las 4096 muestras constantes) es el de una cadena llena que
nadie vacía: m_ray_valid = 1 con m_ray_ready = 0 —el S2MM no acepta—, gate_valid = 0b111 con
gate_ready = 0b000, s_vec_valid = 0 con s_vec_ready = 1, y idle_cnt saturado en
0xffffff. Los cuatro disparos cayeron a intervalos de 26 a 27 segundos, y el cuarto coincide con
la marca de tiempo del mensaje de atasco.
Modo B — la cadena se queda vacía y drenada (corridas 2 y 3)¶
c2-forzado.csv y c3-forzado.csv son el inverso exacto, y entre sí son indistinguibles. Las
4096 muestras son constantes y consecutivas (idle_cnt incrementa de uno en uno, sin calificación
de almacenamiento, porque son capturas forzadas con -trigger_now):
dbg_s_vec = 2 s_vec_valid=0 s_vec_ready=1 s_vec_last=0
dbg_m_ray = 2 m_ray_valid=0 m_ray_ready=1 m_ray_last=0
dbg_ctrl = 07 ddr_mode=1 timing_enable=1 timing_paced=1 moved=0 pulse_trig=0 stalled=0
vs_valid = 0b000 vs_ready = 0b111
ddc_valid = 0b000 gate_valid = 0b000 gate_ready = 0b000
overrun = 0b000 truncated = 0b000
Aquí el S2MM sí acepta (m_ray_ready = 1) y no hay nada que entregarle. No hay contrapresión
desde el consumidor: simplemente no llega dato desde el MM2S.
Las dos incógnitas que quedan vivas¶
1. stalled no dispara en el modo B, y por eso el instrumento no sirve tal como está. Tres
corridas seguidas, 118 minutos acumulados de cadena parada, y el flanco de stalled no subió ni
una vez en las corridas 2 y 3. Sin la foto forzada por el vigía no habría quedado nada. Quien
retome esto tiene que cambiar la condición de disparo antes de volver a correr una noche.
2. Algo resetea idle_cnt periódicamente durante el atasco del modo B, y no se sabe qué. En la
foto forzada de la corrida 2, idle_cnt recorre 11223 → 15318; en la de la corrida 3, 20864 →
24959. Las dos fotos se tomaron entre 45 y 49 segundos después del mensaje de atasco. Si nada
reseteara el contador llevaría del orden de 3·10⁹ ciclos y estaría saturado en 0xffffff, como en
la corrida 1. O sea que el contador se reinicia cada pocas décimas de milisegundo mientras la
cadena está supuestamente muerta.
drx_debug_probe.sv solo tiene dos condiciones de reseteo: !armed o moved, con
armed = ddr_mode || s_vec_valid. Dentro de las ventanas capturadas ddr_mode vale 1 y moved
vale 0 en las 4096 muestras, así que el reseteo ocurre fuera de la ventana. Quedan dos
explicaciones, y el instrumento actual no las distingue:
- el MM2S entrega una muestra suelta de vez en cuando, o sea el atasco es un goteo y no una
parálisis total — esto explicaría además por qué
idle_cntnunca llega a 2²⁰ ystallednunca sube; ddr_modecae durante algún ciclo.
La primera parece más probable porque explica las dos observaciones a la vez, pero con dos puntos de dato es una hipótesis, no un hallazgo.
3. El modo A no reprodujo. Dos horas de intento entre las corridas 2 y 3, y el estado final de la corrida 1 no volvió a aparecer. La «inversión de causalidad» —que el S2MM deje de aceptar antes de que el MM2S se quede sin alimentar— descansa sobre una sola corrida y está contradicha por las otras dos. No se escribió como hallazgo por eso.
Lo que no es evidencia¶
Los volcados de los registros del AXI DMA leídos por JTAG sobre la cadena congelada son basura y
no deben usarse. Los punteros de descriptor de scatter-gather tienen que estar alineados a 64
bytes, y tres de los cuatro leídos no lo están (MM2S_CURDESC = 0x02345920,
MM2S_TAILDESC = 0x02346048, S2MM_TAILDESC = 0x02321216; solo S2MM_CURDESC = 0x02321600
cumple). Son valores imposibles, no lecturas con ruido. El mismo veredicto que ya se había
registrado para el MM2S_DMASR = 0x00086281 de la primera sesión. El ILA es el único instrumento
fiable sobre esta placa con la cadena parada.
Ficheros¶
| Fichero | Qué es |
|---|---|
c1-flanco-1.csv … c1-flanco-4.csv |
corrida 1, los cuatro disparos naturales por flanco de stalled, con calificación sobre moved |
c1-forzado.csv |
corrida 1, estado congelado tras el atasco permanente |
c2-forzado.csv, c3-forzado.csv |
corridas 2 y 3, estado congelado (no hubo disparos naturales) |
c1-disparos.tsv, c2-disparos.tsv, c3-disparos.tsv |
bitácora de disparos de cada corrida: marca, iteración, estado y modo |
Para leer cualquiera de ellos:
python3 tools/ila_p21_leer.py docs/implementacion/evidencia/p-21/c3-forzado.csv
Conviene recordar que ila_p21_leer.py imprime solo dos muestras. En las capturas forzadas todas
las columnas menos idle_cnt son constantes, así que esas dos bastan; en las capturas con
calificación de almacenamiento, no — ahí hay que mirar la distribución de las 4096 filas, que es
donde está el dato de ddr_mode = 0 en todos los avances.