Este proyecto es educativo y Open Source. No se copia código de otros emuladores. Implementación basada únicamente en documentación técnica y tests permitidas.
Corrección de Errores de Compilación Cython: setPPU y run_scanline
Resumen
Después de implementar el método run_scanline() en C++ y su wrapper en Cython, la compilación falló con múltiples errores relacionados con declaraciones de tipos y métodos faltantes. Este Step documenta la corrección sistemática de estos errores: eliminación de declaraciones duplicadas de PyPPU, adición de métodos faltantes en cpu.pxd (setPPU y run_scanline), y corrección del orden de inclusión en native_core.pyx para resolver dependencias entre módulos Cython.
Concepto de Hardware
Este Step no implementa nueva funcionalidad de hardware, sino que corrige problemas de infraestructura en el puente Python-C++ (Cython). Sin embargo, es crítico para la arquitectura implementada en el Step 0175: sin estos cambios, el método run_scanline() no puede ser compilado y expuesto a Python, bloqueando completamente la nueva arquitectura de emulación ciclo a ciclo.
Importancia: Cython requiere que todas las clases C++ estén correctamente declaradas en archivos .pxd para generar el código de enlace apropiado. Las declaraciones forward y el orden de inclusión son críticos cuando hay dependencias circulares entre módulos.
Implementación
Problemas Identificados
La compilación de Cython falló con los siguientes errores:
- Declaración duplicada de PyPPU: La clase
PyPPUestaba declarada tanto encpu.pyx(como forward declaration) como enppu.pyx(definición completa), causando conflicto durante la compilación. - Métodos faltantes en cpu.pxd: Los métodos
setPPUyrun_scanlineestaban implementados en C++ pero no declarados encpu.pxd, por lo que Cython no podía generar el código de enlace. - Falta de forward declaration de PPU: El archivo
cpu.pxdno tenía una forward declaration de la clasePPU, necesaria para el métodosetPPU(PPU* ppu). - Orden de inclusión incorrecto: En
native_core.pyx,cpu.pyxse incluía antes queppu.pyx, perocpu.pyxnecesitaba acceso aPyPPUdefinido enppu.pyx.
Correcciones Aplicadas
A. Eliminación de Declaración Duplicada (cpu.pyx)
Se eliminó la forward declaration de PyPPU en cpu.pyx, ya que la definición completa en ppu.pyx será accesible cuando ambos módulos se incluyan en native_core.pyx.
# ANTES (causaba conflicto):
cdef class PyPPU:
cdef ppu.PPU* _ppu
# DESPUÉS (eliminado, PyPPU disponible desde ppu.pyx):
# PyPPU estará disponible cuando ppu.pyx se incluya antes que cpu.pyx
B. Actualización de cpu.pxd
Se añadieron la forward declaration de PPU y los métodos faltantes:
# Forward declaration de PPU
cdef extern from "PPU.hpp":
cdef cppclass PPU:
pass
# Métodos añadidos a la clase CPU
cdef cppclass CPU:
# ... métodos existentes ...
void setPPU(PPU* ppu) # NUEVO
void run_scanline() # NUEVO
C. Corrección del Orden de Inclusión (native_core.pyx)
Se cambió el orden para que ppu.pyx se incluya antes de cpu.pyx, asegurando que PyPPU esté disponible cuando cpu.pyx se compile:
# ANTES:
include "mmu.pyx"
include "registers.pyx"
include "cpu.pyx"
include "ppu.pyx"
# DESPUÉS:
include "mmu.pyx"
include "registers.pyx"
include "ppu.pyx" # Movido antes de cpu.pyx
include "cpu.pyx" # Ahora puede usar PyPPU
D. Corrección del Método set_ppu (cpu.pyx)
Se ajustó el método set_ppu para declarar la variable cdef PyPPU ppu_obj al principio del método (fuera de bloques condicionales), cumpliendo con las reglas de Cython:
cpdef set_ppu(self, object ppu_wrapper):
cdef PyPPU ppu_obj # Declaración al principio
if ppu_wrapper is None:
self._cpu.setPPU(NULL)
else:
ppu_obj = <PyPPU>ppu_wrapper
self._cpu.setPPU(ppu_obj._ppu)
Componentes Modificados
src/core/cython/cpu.pyx: Eliminada declaración duplicada de PyPPU, corregido método set_ppu.src/core/cython/cpu.pxd: Añadida forward declaration de PPU y métodos setPPU/run_scanline.src/core/cython/native_core.pyx: Corregido orden de inclusión (ppu.pyx antes de cpu.pyx).
Archivos Afectados
src/core/cython/cpu.pyx- Eliminada forward declaration duplicada de PyPPU, corregido método set_ppusrc/core/cython/cpu.pxd- Añadida forward declaration de PPU y métodos setPPU/run_scanlinesrc/core/cython/native_core.pyx- Corregido orden de inclusión de módulos
Tests y Verificación
La verificación se realizó mediante compilación exitosa del módulo C++:
- Compilación:
python setup.py build_ext --inplacecompletada exitosamente - Script de rebuild:
.\rebuild_cpp.ps1ejecutado sin errores - Errores resueltos: Todos los errores de compilación de Cython fueron eliminados
- Warnings: Solo warnings menores relacionados con truncamiento de punteros (normales en código generado por Cython)
Validación de Módulo Compilado C++
El módulo viboy_core.cp313-win_amd64.pyd se generó correctamente, confirmando que:
- Los métodos
setPPUyrun_scanlineestán correctamente enlazados - La clase
PyPPUes accesible desdePyCPU - No hay dependencias circulares que bloqueen la compilación
Fuentes Consultadas
- Documentación oficial de Cython - Declaraciones de tipos, forward declarations, orden de inclusión
- Cython: Sharing Declarations Between Cython Modules - Mecanismos de forward declarations
Integridad Educativa
Lo que Entiendo Ahora
- Declaraciones Forward en Cython: Cuando un módulo Cython necesita referenciar una clase definida en otro módulo, hay dos opciones: usar una forward declaration (si solo se necesita el tipo para punteros) o asegurar que el módulo que define la clase se incluya antes en el archivo que los agrupa.
- Archivos .pxd: Los archivos
.pxdson críticos para declarar la interfaz de clases C++ a Cython. Sin declarar métodos en.pxd, Cython no puede generar el código de enlace correcto, incluso si los métodos están implementados en C++. - Orden de Inclusión: En Cython, cuando se usan directivas
include, el orden importa. Simódulo_a.pyxnecesita tipos demódulo_b.pyx,módulo_b.pyxdebe incluirse primero. - Declaraciones cdef en Métodos cpdef: Las variables
cdefen métodoscpdefdeben declararse al principio del método, fuera de bloques condicionales, para cumplir con las reglas de Cython.
Lo que Falta Confirmar
- Funcionalidad completa: Aunque el módulo compila correctamente, aún falta verificar que
run_scanline()funciona correctamente en tiempo de ejecución y resuelve el deadlock de sincronización.
Hipótesis y Suposiciones
No hay suposiciones críticas. Todas las correcciones se basan en documentación oficial de Cython y reglas estándar de compilación.
Próximos Pasos
- [ ] Verificar que
run_scanline()funciona correctamente en tiempo de ejecución - [ ] Actualizar
viboy.pypara usar el nuevo métodorun_scanline()en lugar del bucle Python - [ ] Probar el emulador con Tetris para confirmar que el deadlock de sincronización está resuelto
- [ ] Verificar que la PPU se actualiza correctamente después de cada instrucción de la CPU