Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

61
1 Codificador JPEG: Caso de Estudio de Co-diseño Hardware/Software Fernando Adolfo Escobar Juzga Asesor: Mauricio Guerrero Hurtado Co-Asesores: Lorena García Oscar Sánchez Universidad de los Andes Facultad de Ingeniería Departamento de Ingeniería Eléctrica y Electrónica Bogotá D.C. 2007

Transcript of Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

Page 1: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

1

Codificador JPEG: Caso de Estudio de Co-diseño Hardware/Software

Fernando Adolfo Escobar Juzga

Asesor: Mauricio Guerrero Hurtado

Co-Asesores: Lorena García Oscar Sánchez

Universidad de los Andes Facultad de Ingeniería

Departamento de Ingeniería Eléctrica y Electrónica Bogotá D.C.

2007

Page 2: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

2

Agradecimientos

A mis padres y hermanas por su constante apoy o y acompañamiento durante el transcurso educativ o a lo largo de mi vida y en la realización de este proyecto. A la familia Casas Castellanos por su gran colaboración en las últimas etapas de mi carrera. Al profesor Mauricio Guerrero por sus aportes y orientaciones en esta y muchas otras labores académicas. A Lorena García y Oscar Sánchez por su asesoría a lo largo de todo el semestre. Gracias.

Page 3: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

3

Resumen

En el presente trabajo se busca realizar la validación e implementación de una

metodología de codiseño Hardware-Software propuesta. Como caso de estudio se tomó

el compresor de imágenes JPEG dado que es un ejemplo bastante utilizado a nivel

académico y permite comparar el resultado con otros trabajos a nivel de diseño. Se parte

inicialmente del estandar JPEG como referencia y por medio de un seguimiento

detallado de la metodología se busca realizar un conjunto de descripciones, simulaciones

y particiones que inician en un nivel funcional básico y se van afinando hasta llegar a

etapas de mayor detalle que permitan apreciar los resultados del trabajo realizado. A

nivel general el trabajo busca documentar todo el proceso de codiseño para su inserción

en cursos de la facultad y fomentar su investigación. La aplicación o proyección del

presente es también lograr en una etapa futura, la extensión a aplicaciones de may or

complejidad como el procesamiento de v ideo M-PEG en tiempo real con la inclusión de

tecnologías del tipo MPSoCs o hardware reconfigurable.

Palabras Clave – JPEG, Codiseño, Hardware, Software, DCT, Huffman, RGB, YUV,

Compresión, Imagen, Cuantización, Sistema Embebido.

Page 4: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

4

Tabla de Contenido

Introducción ……………………..………………………..……………………………………. 5 1. Objetivos ………………………..………………………..…………………………………. 6

1.1 Objetivo General………………………..…………………………………...…… 6 1.2 Objetivos Específicos………………………..…………………………………. 6 1.3 Justificación………………………..…………………………………..…………. 6

2. Marco Teórico ………………………..………………………………...…..…………..…….. 7 2.1 El Codiseño Hardware-Software……………….……………..…………..…… 7 2.2 Metodología a Utilizar………………………..……………………………..…… 7 2.3 Estándar de compresión JPEG………………………..…………………….…... 9 2.4 Especificaciones y Restricciones……………………………....…………….… 12

2.4.1 Archivos .bmp………………………..……………………………….. 12 2.5 Caso de estu dio: JPEG Baseline DCT Based………………………………….. 13

2.5.1 Espacio de color RGB- YUV ……………………………..…………… 13 2.5.2 Unidad Mínima de Codificación: Bloqu e 8x8 píxels……….….. 14 2.5.3 Transformada Discreta del Coseno DCT………………………… 15

2.5.3.1 Algoritmo computacional rápido……………………...……… 15 2.5.4 Cuantificación……………………………………………….………… 17 2.5.5 Ordenamiento Zig-Zag……………………………………………….. 17 2.5.6 Codificación de entropía Huffman………………………………... 18

2.5.6.1 Codificación DC…………………………………………………… 18 2.5.6.2 Codificación A C…………………………………………………… 19

2.5.7 Escritura de Datos……………………………………………………. 21 2.5.8 Encabezados y Tablas……………………………………………….. 21

3. Desarrollo del Proyecto…………………………………………………….. 23 3.1 Validación del Algoritmo: Descripción Funcional………………………… 23 3.2 Grafos de Tareas…….…………………………………………………………………. 23

3.2.1 Grafo funcional Inicial...……………………………………………….. 23 3.2.2 Grafo de Tareas Final…………………………………………………… 24

3.3 Estimativos de Desempeño……………..……………………………….…………. 26 3.3.1 Ejecuciones en Compu tador...……………………………………….. 27 3.3.2 Análisis de Complejidad………….……………………………………. 28

3.4 Particionamiento……………………………………….……………………………… 29 3.5 Planeación de Tareas……………………………………..………………………… 30 3.6 Plataformas Disponibles para la Implementación……………………….. 32

3.6.1 ARM – FPGA ……………………………………………………………. 32 3.6.2 Soft-Processors: MicroBlaze………………………………………… 33

3.6.2.1 Simulaciones Iniciales………………………………………… 34 3.6.2.2 Optimización por velocidad………………………………..... 36

3.7 Módulos Hardware……………………………………………..…………………… 37 3.7.1 Multiplicadores de Matrices [4x4] x [4x1]……………………….. 37 3.7.2 Cuantificador…………………………………………….………………. 39

3.8 Mejora en Desempeño…………………………………………………..…………. 43 3.9 Comparación con Arquitecturas propuestas………………………………... 46

4. Conclusiones……………………………………………………………………….….. ………… 49 5. Perspectivas……………………………………………………………………………............. 50 6. Referencias…………………………………………………………………………………….… 51 7 . Anexos…………………………………………………………………………………………….... 52

Page 5: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

5

INTRODUCCIÓN

El diseño digital es una práctica que desde sus primeros estadios ha ceñido su desempeño a la implementación de soluciones Hardware o Software, de forma independiente. Sin embargo, con el tiempo han surgido metodologías de co-diseño de Hardware/Software de manera innovadora como respuesta a la búsqueda de sistemas más eficientes. No obstante, las anteriormente citadas no son procesos totalmente automatizados para cualquier aplicación o tecnología, lo que se traduce en imprecisión a la hora de ejecutarlos debido a la ausencia de una base estructurada que pueda ser empleada como plataforma inicial durante el desarrollo del co-diseño; de esta manera, la teoría del co-diseño plantea la oportunidad de realizar arquitecturas más eficaces con una distribución de recursos optimizada respecto al diseño digital tradicional. Como primera medida, conscientes de las posibilidades de analizar, validar, evaluar y retroalimentar la teoría al respecto, se busca en el presente documento aplicar una metodología propuesta por estudiantes de maestría de la Universidad de los Andes, con la adopción de un caso de estudio conocido a nivel académico para llevar a cabo un ejercicio evaluativ o y comparativo que cuente con los criterios suficientes para emitir un juicio concluyente con respecto al proyecto arriba mencionado. Para tal fin, el estado del arte pertinente al co-diseño en la academia, sugiere en repetidas ocasiones un caso particular de aplicación dada su versatilidad y aplicabilidad en diferentes sistemas y tecnologías;, se adopta el algoritmo de compresión JPEG como caso a estudiar. Seguidamente, se pretende realizar una descripción general de la metodología a seguir, para de esta forma definir el contexto sobre el cual se debe analizar y orientar el estudio del caso seleccionado; posteriormente se esboza un esquema general del algoritmo de compresión JPEG escogido y con esto se establece la información necesaria para comenzar el trabajo; finalmente se realiza una descripción de la labor realizada en sus diferentes etapas y los resultados obtenidos en cada una de estas hasta llegar a la fase final.

Page 6: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

6

1 Objetivos

1.1 Objetivo General

Generar un caso de estudio qu e permita validar una metodología estru cturada de codiseño Hardware-Software, adoptando un conjunto apropiado de herramientas capaces de soportar la complejidad y requ erimientos del diseño. El caso de estu dio preseleccionado es un codificador de imágenes JPEG. 1.2 Objetivos Específicos

Entre los diferentes alcances del proyecto se mencionan a continuación las metas secundarias qu e se bu sca abarcar a cabalidad: • Identificar y validar un conjunto de herramientas para las diferentes fases de la metodología

adoptada, buscando encontrar la mejor forma de describir y apropiar la funcionalidad de los diferentes módulos a trabajar durante el estu dio del caso y de esta manera soportar las decisiones a realizar sobre la conveniencia de la u tilización hardware o software.

• Apropiar un lenguaje de descripción a nivel de sistema qu e se adapte de la mejor forma a las

necesidades del problema y permitan obtener una representación completa y detallada de este, para así lograr dimensionar su complejidad de forma precisa y facilitar su diseño.

• Implementar un codificador JPEG como caso de estudio y aplicación de la metodología. Siendo

este un proceso bastante estudiado en la academia, permitirá comparar la efectividad de los resultados.

• Generar la documentación necesaria para su utilización académica en los cursos de diseño y/o

sistemas embebidos y así motivar el interés y la tendencia de la universidad hacia la apropiación de herramientas y metodologías modernas.

1.3 Justificación

Este proyecto, propu esto por el CMUA (Centro de Microelectrónica Universidad de los Andes), surge de la necesidad de evaluar y adoptar nu evas metodologías de diseño y planeación de sistemas digitales; además se busca tener un ejemplo de una implementación qu e u tilice este tipo de modelaje para, de esta manera, contar con datos y estimaciones qu e faciliten la enseñanza y la evaluación de esta metodología a nivel académico. Dado qu e en la actualidad existe una teoría considerablemente amplia referente al tema del codiseño, el presente trabajo pretende retomar un estudio previo realizado en la Universidad, en donde se propuso un esquema más completo y detallado de estas metodologías, el cual incluye los elementos más relevantes de cada fu ente consultada y sintetiza la información de una forma clara. Además de lo anterior, la Universidad cuenta con varios recursos qu e facili tan la realización de proyectos de este tipo; a nivel de software, se cuenta con varias licencias qu e permiten la simulación, descripción, sintetización e implementación de módulos o programas requ eridos en la consecu ción y realización del trabajo. Entre el software que pu ede llegar a utilizarse, están ISE y EDK de Xilinx, MPLA B, Keil , CodeWarrior, Quartus II, entre otros. Por otro lado, a nivel de hardware, se cuentan con tarjetas de desarrollo de Xilinx como la Spartan3 y montajes prediseñados ope n source disponibles en Internet como los de e mqbit.com qu e integran procesadores ARM con FPGA S. Conjugando los ítems ya mencionados, se presenta una perspectiva bastante positiva y prometedora en este proyecto.

Page 7: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

7

2 Marco Teórico

2.1 El Codiseño Hardware-Software Es definido como: “proceso de diseño de un sistema (desde las especificaciones hasta la impleme ntación final) que combina tanto componente s hardware como software. A dife rencia de las me todologías tradicionales, e n las que e l dise ño del hardware y del software se realizan de manera indepe ndiente, e n e l codise ño estos procesos se realizan concurrente me nte , pe rmitie ndo comunicación e interacción e ntre e llos”1. El codiseño representa una fu ente interesante de modelaje de sistemas eficientes qu e permitan optimizar la utilización de recursos para obtener soluciones más veloces qu e las plataformas software, y menos costosas qu e las arquitecturas hardware. El objetivo final de esta teoría es lograr implementaciones de alto desempeño con una distribución de funciones entre uno o varios procesadores (entidades software) , y una serie de peri féricos de propósito específico (entidades hardware); sin embargo, como se anotó anteriormente, uno de los principales inconvenientes de este ejercicio, es que no se cuenta con herramientas o estándares qu e indiqu en cómo realizar la distribu ción y asignación de tareas a cada gru po, por lo qu e en general , los diseños obtenidos son produ cto de diferentes tipos de análisis qu e no sigu en una validación detallada sino que por el contrario surgen como alternativas a las exigencias de un problema. Con la aparición y auge de herramientas y plataformas para sistemas embebidos, qu e promu even de manera implíci ta la adopción de particiones Hardware-Software, se hace más evidente la necesidad de una metodología de codiseño, que permita orientar la construcción de sistemas y validación de resultados con elementos de juicio precisos, robustos y certeros; de esta manera, teniendo claras las ventajas y alcances de esta teoría, surge la necesidad de proponer, estu diar y evaluar un criterio de desarrollo de arquitecturas de este tipo. El codiseño es cada vez más relevante en la concepción y construcción de sistemas, puesto qu e con los avances en velocidad y frecuencia de operación de los procesadores, además de los diferentes módulos especializados qu e cada día se le están adicionando, presentan no obstante, una desventaja clara respecto al desempeño qu e pu ede tener el hardware, qu e se tradu ce en la relación secuencialidad y concurrencia; sin importar la forma cómo se realizan las ejecuciones en un procesador, su desempeño siempre se ha visto limitado por la secu encialidad mientras qu e los componentes hardware no presentan este inconveniente, por lo qu e una aceleración en tiempo de ejecución es posible lograrla con módulos externos al Software qu e realicen ciertas actividades mientras este hace otras.

2.2 Metodología a Utilizar Como ya se mencionó, la metodología de codiseño a seguir fue propuesta por dos estu diantes de la Universidad de los Andes en un Curso Tu torial , asesorados por el profesor Mauricio Guerrero; ésta, fue el producto de un estudio detallado de diferentes soluciones previamente planteadas y publicadas a nivel académico, por lo cual incluye un fundamento teórico bastante amplio y objetivo. De esta manera, para entender el contexto sobre el cual se enmarcarán todas las actividades, es necesario realizar una descripción inicial de la metodología. En la Figura 1 se aprecia el diagrama de la propu esta a utilizar; como se observa, presenta una estructura parecida a un diagrama de flujo, el cual se va desarrollando por bloqu es según el orden qu e presenta; las primeras etapas se desarrollan de manera secuencial y constituyen una base fundamental en el avance del proceso puesto qu e buscan validar la operación del sistema a diseñar de manera funcional, para apropiarse completamente de su estru ctura y tener claridad en las tareas, algoritmos o funciones qu e deban implementarse en fases posteriores.

1 Metodología de Codiseño Hardware/Software. García M. Lorena, Sánchez Oscar, Gu errero Mauricio, García Antonio.

Page 8: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

8

Figura 1. Metodología a implementar con el caso de estudio seleccionado.

Una vez la etapa de validación ha concluido, es necesario realizar una descripción a nivel de tareas con cierto grado de granularización, con el fin de identificar secu encialidad y concurrencia en el algoritmo general y así , tener una bu ena estimación del flujo de los datos en el proceso, para determinar en qu é momento y en qu é tareas específicas se pu ede realizar el particionamiento; cabe resaltar qu e dependiendo de las decisiones tomadas respecto a la implementación de las funciones qu e realiza el sistema (algoritmo) a implementar, el grafo puede variar considerablemente en extensión, complejidad y paralelismo. Lu ego de la construcción del grafo, se requiere realizar estimaciones qu e permitan determinar qu é tareas pu eden ser implementadas a nivel de hardware y cuáles pu eden implementarse en software; esta etapa se desarrolla iterativamente, es decir, se realiza un particionamiento del cual pu eden realizarse simulaciones y estimaciones de desempeño, con el fin de realizar varias arquitecturas y escoger la qu e arroje los mejores resultados. Como algunas veces no se cuenta con suficiente tiempo o recursos para i terar más de una vez, es importante tener bu enas estimaciones para realizar el primer particionamiento y ser más asertivo en su elección; por tal motivo, para tener aproximaciones eficaces, es fundamental la comprensión y apropiación completa del algoritmo a implementar. En la penúltima etapa, se debe verificar el trabajo realizado con anterioridad para evaluar los resultados de las decisiones tomadas y su efectividad en desempeño; dado qu e no en todos los casos es posible o se

Page 9: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

9

desea llegar a la implementación, la metodología propone etapas de descripción de entidades software y hardware, para luego realizar simulaciones individuales y, si se dispone de la herramienta, co-simulaciones de la totalidad de los módulos, buscando una aproximación bastante cercana a la realidad. Es imprescindible en esta fase, tener un bu en conocimiento de la disponibilidad de herramientas software qu e permitan realizar este tipo de acercamientos para poder validar y evaluar el trabajo realizado. La etapa de simulación, a pesar de no ser la última fase de la metodología, aporta información bastante cercana a la realidad ya qu e generalmente las herramientas utilizadas, presentan precisión de ciclos de reloj y tiempos en micro o nanosegundos, además de otras opciones de evaluación especí ficas que son desarrolladas con detalle para brindar buenas estimaciones a los usuarios. En última instancia se plantea la implementación total del diseño y su verificación; aunque muchas veces esta etapa se traduce en la programación de circuitos, pu ede haber factores externos o errores humanos qu e logran afectar el correcto funcionamiento del diseño por lo que se necesita realizar esta tarea repetidas veces.

2.3 Estándar de Compresión JPEG El Estándar JPEG estipula una variedad de algoritmos y procedimientos para el tratamiento y compresión de imágenes que permiten obtener archivos con extensiones *.jpg,*.jfif, *.jpe entre otros; las posibilidades varían dependiendo de la forma de procesar la imagen, la cantidad de escaneos qu e se realizan, la cantidad de operaciones qu e se llevan a cabo, la cantidad de componentes de una imagen, etc. Existen dos grandes grupos entre los cuales se pu ede realizar una primera clasificación de imágenes comprimidas: Imágenes con pérdidas e imágenes sin pérdidas; las imágenes con pérdidas son aqu ellas con las cuales se realizan operaciones aritméticas y en alguna fase del procesamiento de los datos, existen cálculos qu e generan pérdida de información; por ejemplo, cuando los datos enteros se convierten en números reales, y al final , lu ego de pasar por varias operaciones, se redondean a un valor entero, bien sea aproximándolos o su primiendo su parte decimal. Por otro lado, la compresión sin pérdidas es aqu ella donde no existe pérdida de información pues los procesos qu e se realizan no alteran los datos iniciales; en este tratamiento de imágenes, existe un bloqu e qu e se encarga de predecir la información qu e debe ir en determinado píxel, y se codifica la diferencia entre el valor real y la predicción, así , como se pu ede ver, si se tienen los valores de la predicción, la imagen se pu ede reconstruir tal como se comprimió. En las siguientes Figuras, tomadas del estándar, se aprecia el diagrama de bloqu es de cada uno de los tipos de compresión mencionados: Figura 2. Diagrama de Bloques Compresión sin Pérdidas. Solo se realiza una resta y se codifica la diferencia entre el valor real y el valor estimado.

Page 10: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

10

Figura 3. Diagrama de Bloques Compresión con Pérdidas. Se realizan varios procesos que modifican los datos: Transformada del Coseno (FDCT), y Cuantización. Los datos a codificar deben ser enteros por lo que es necesario redondearlos. Por otro lado, el tipo de compresión más común es el qu e incluye pérdidas ya qu e permite una mayor simplificación de información redundante y realiza tratamientos a la imagen a través de transformadas para condensar la información y redu cirla aún mas. Para el estándar JPEG, existen otros parámetros de clasificación de compresión según como se realice la codificación a una imagen: procesando y codificando la información en cada lectura (secuencial) o procesando selectivamente la información, codificándola parcialmente, almacenándola en un buffer, y al final tener una codificación compuesta de las todas anteriores (progresivo). Esta diferencia pu ede comprenderse mejor con la Figura 4, tomada del estándar.

Figura 4. Diferencias entre la compresión Progresiva, que realiza almacenamientos temporales y codifica la información al final, y la Secuencial que codifica la información a medida que la lee. Existe además de las anteriores dos clasi ficaciones una tercera categoría qu e también es importante tener en cuenta en el momento de comprimir una imagen; para entender este concepto, es necesario aclarar qu e cada imagen suele tener entre 2 y 4 componentes (R-G-B, Y-U-V, etc.) por lo qu e los escaneos a la información se pu eden realizar de diferentes maneras: N o intercalados o Intercalados. Cuando se realizan de manera N o Intercalada, en un barrido se abarcan todas las componentes de la imagen (de forma secuencial o progresiva) y cuando se realiza de manera Intercalada, por cada escaneo se abarca una sola componente (de forma secuencial o progresiva). La Figura 5 ejemplifica las diferencias entre los escaneos Intercalados y N o Intercalados

Page 11: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

11

Figura 5. Escaneos No intercalados: se requieren 3 escaneos para abarcar las 3 componentes de la imagen. Escaneo intercalado: un solo escaneo abarca las 3 componentes. Otro criterio para la clasificación de archivos jpg, es el tipo de codificación qu e utilizan; en la actualidad está el algoritmo de Huffman y la codificación Aritmética. Cada uno recibe el nombre de codificador de entropía ya qu e buscan asignar códigos más cortos a símbolos de mayor repetición y códigos más largos a los de menor repetición; generalmente se utiliza más la codificación Huffman para todos los formatos. Es importante resal tar qu e los algoritmos de compresión con pérdida utilizan generalmente la Transformada Discreta del Coseno (FDCT) para realizar el tratamiento de los datos y codificarlos; esta operación pretende proporcionar la información más relevante de la densidad del color en la imagen. La transformada se aplica a un bloqu e de 8x8 píxels y da como resultado otro bloque de igual tamaño pero con coeficientes distintos. Existen otras facetas de estos tipos de compresión qu e son más complejos de tratar; a manera de información, se sabe qu e los algoritmos más recientes utilizan la Transformada Wavelet, para originar archivos jpeg2000. A continuación se presenta la clasificación qu e hace el estándar, de acu erdo con la información proporcionada hasta el momento. Tipos de imágenes jpg:

• Baseline DCT Based – Secuencial - Huffman • Extended DCT Based

o Secu encial/Progresivo o Aritmética/Hu ffman

• Predictiva sin Pérdida • Jerárquica, DCT extendida

Los formatos extendidos utilizan datos de entrada de 12 bits ya que lo más común es utilizar datos de 8 bits. Para concluir, es necesario mencionar qu e puesto que las imágenes constan de más de una componente, hay algunas de ellas qu e se pu eden omitir parcial o totalmente sin qu e el ojo humano detecte cambios fácilmente. Por ejemplo, como se mencionará más adelante, las imágenes se procesan cuando están en formato YUV ; cuando en la compresión se toma el mismo número de píxeles para cada componente, se denomina 4:4:4, si se toma la mitad de la información en U y V es 4:2:2, si se toma un cuarto de la información es 4:2:0, y si solo se toma solo la información Y (la más importante), se denomina 4:0:0. Todos los tipos de codificación JPEG, soportan este tipo de muestreos.

Page 12: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

12

2.4 Especif icaciones y Restricciones Para la realización del codificador, lu ego de analizar la información referente a los tipos de imágenes disponibles y los formatos a comprimir, se llegó a un listado de criterios mínimos para la implementación final , qu e se expone a continuación:

• Formato de imagen inicial : *.bmp, 24 bits, no comprimido. • Dimensiones de la imagen: n x m; n, m múltiplo de 8. Inicialmente en formato V GA (640 x 480). • Formato de salida: *.jpg • Lectura de datos: Bit-stream

Es importante definir estas características ya qu e, aunqu e la compresión sea la misma para todas las imágenes, la forma de leer los encabezados de cada formato y abstraer la información de la imagen a procesar pu ede variar de un formato a otro.

2.4.1 Archivos .bmp El formato .bmp (bitmap) es un formato desarrollado por Windows y es bastante utilizado por todos los usuarios de este sistema operativo; al igual qu e el formato jpeg, existen diferentes categorías para clasificar los archivos bmp: Monocromáticos(1 bit), 16 colores (4 bits), 255 colores (8bits), 65.536 colores (16 bits) y 16.777.216 colores (24 bits); además hay algunos qu e presentan compresiones básicas que no es necesario explicar en este contexto. Los archivos constan de un encabezado, un encabezado de información, una paleta opcional de colores, y los datos. La figura 6 permite apreciar esta distribución:

Figura 6. Formato de almacenamiento de los archivos bmp. Para el caso de 24bits RGB, no hay paleta opcional. Hay dos particularidades de este formato que es necesario considerar cuando se leen los datos: la primera es qu e si la imagen tiene un ancho de un número impar de píxels, por cu estiones de alineamiento el formato agrega tantos ceros como sea necesario para qu e cada línea sea de tamaño de un múltiplo de 4; por ejemplo, si el ancho es de 17 píxels, el archivo agregará 3 ceros en cada línea para qu e sea un múltiplo de 4. Esta es una de las razones por las cuales se especificó qu e las dimensiones de los archivos a considerar debían ser de tamaño de múltiplos de 8. La segunda particularidad de los bmp, es qu e la información se encu entra almacenada desde la última línea hasta la primera, es decir, la imagen se guarda invertida, por lo qu e al leerla hay que comenzar por la última línea y terminar en la primera. Teniendo en cuenta esta breve descripción del formato, se tomaron imágenes de 8bits RGB, es decir 24 bits sin compresión.

Page 13: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

13

2.5 Caso de Estudio: JPEG Baseline – DCT Based Lu ego de haber descri to de manera general los algoritmos de compresión JPEG, se selecciona el caso del JPEG Baseline ya qu e según la bibliografía consultada, es el caso más estu diado a nivel académico; El algoritmo es denominado baseline ya qu e realiza los procesos más básicos y sencillos dentro de toda la gama de opciones expu esta anteriormente: codificación secu encial y datos intercalados (en este caso, pu es se soporta también la operación no intercalada); además, el algoritmo está basado en la DCT lo qu e lo hace un algoritmo de compresión con pérdida.. Como se mencionó, existen procesos específicos dentro del algoritmo qu e pueden ser implementados de diferentes maneras para disminuir su complejidad y aumentar su eficiencia. El diagrama mostrado en la Figura 3 es un bosquejo general de los procedimientos a realizar en la mayoría de versiones de compresión JPEG, sin embargo, las diferencias entre cada una, radican en la forma como se realizan estas operaciones; a continuación se exponen cada uno de los procesos en detalle y la explicación de cómo se van a implementar, una vez se haya realizado la validación funcional :.

2.5.1 Espacio de color RGB – YUV Para comenzar a realizar cualquier tipo de tratamiento con la información de la imagen y comprimirla, se requiere que dicha esté en formato YUV , es decir, con una componente de Luminancia “Y” y dos de Crominancia “U”y “V”; no obstante, la mayoría de imágenes no comprimidas se encuentra en formato RGB, es decir, almacenan 3 datos por píxel : Un dato es la componente en Rojo (R), el segundo es V erde (G) y el tercero es Azul (B). (Caso de los archivos bmp). Figura 7. Equivalencia de una imagen al transformarse de espacio de color. La componente de Luminancia es la “escala de grises” de la imagen y las componentes de Crominancia brindan información del color. Con esta restricción, el primer proceso a realizar es una transformación de espacio de color de la información, qu e se logra realizar de acu erdo con unas ecuaciones previamente establecidas; además de este proceso, es necesario centrar el rango de los datos entre –128 y 127 antes de continuar con otras etapas, lo cual se logra restándole 128 a cada componente lu ego de transformarla. Las ecuaciones de conversión se resumen de la siguiente manera:

• Y = (0.257R) + (0.504G) + (0.098B) + 16 (1) • U = (-0.148R) – (0.291G) + (0.439B) + 128 (2) • V = (0.439R) – (0.368G) – (0.071B) + 128 (3)

Ecuaciones tomadas de http://es.wikipedia.org/wiki/Joint_Photographic_Experts_Group Con el redondeo las ecuaciones son:

• Y = (0.257R) + (0.504G) + (0.098B) – 112 (4) • U = (-0.148R) – (0.291G) + (0.439B) (5) • V = (0.439R) – (0.368G) – (0.071B) (6)

Una vez se transforma la totalidad de la imagen y cada valor RGB de cada píxel se convierte en información YUV, se pu ede avanzar a una etapa posterior en la compresión JPEG. Este bloque no presenta gran complejidad dentro del algoritmo.

Page 14: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

14

2.5.2 Unidad Mínima de Codificación (MCU) : Bloque 8 x 8 píxels La compresión de imágenes se realiza procesando bloqu es o unidades de información de manera secuencial e iterativa; la mínima cantidad de información necesaria para realizar una iteración del algoritmo se denomina MCU (Unidad Mínima de Codificación), qu e en este caso es un bloque de 8x8 píxels. La cantidad de MCU’s a procesar depende de las dimensiones de la imagen, no obstante, cuando las imágenes son de un tamaño (largo o ancho) qu e no es múltiplo de 8, el estándar especifica qu e se debe replicar la información de la última fila o columna para completar el MCU y poder realizar la codificación; para evitar complicaciones en este respecto, se determinó qu e una de las restricciones es qu e si las imágenes no son en tamaño V GA por lo menos deben tener dimensiones qu e sean múltiplos enteros de 8 para facilitar su tratamiento. Un factor importante al momento de acceder a la información para comenzar a codificarla, es saber en qu é orden realizarlo, lu ego para el caso de compresión Base line, los datos deben ser leídos de izquierda-derecha y de arriba-abajo de la imagen; este ordenamiento es necesario tenerlo en cu enta ya qu e para los archivos bmp la información se encu entra almacenada en forma invertida, por lo qu e para este formato específico, la información se leerá de izquierda-derecha, abajo-arriba.

LECTURA DE IMAGEN LECTURA DEL .bmp Figura 8. (Izq) Orientación de cómo leer los datos de una imagen en el estándar JPEG. (Der) Adaptación al fichero bmp, que guarda los datos de forma inversa. Cada cuadrícula es un bloque de 8x8 píxels. Pu esto qu e las imágenes están en formato YUV, se tienen 3 fuentes de información de las dimensiones de la imagen, disponibles para codificar, por lo qu e la forma de realizar este tratamiento es de manera intercalada, es decir, se lee un MCU de Y, se procesa y codifica; luego se lee un MCU de U, se procesa y codifica también, y lu ego se repite el proceso con la componente V hasta abarcar toda la imagen en cada componente.

Figura 9. Para la compresión de una imagen con componentes YUV, el codificador extrae un MCU de una de ellas para codificarlo y continuar con la siguiente componente. El proceso se realiza en el orden Y –U –V, y además tiene unas tablas de especificación que utiliza en la codificación: dependiendo de qué bloque procese, escoge la tabla correcta.

Page 15: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

15

2.5.3 Transformada Discreta del Coseno (DCT) Una vez se cu enta un MCU de alguna componente, se debe aplicar la DCT; esta transformada constituye una parte fundamental en el tratamiento de imágenes pues realiza un mapeo del dominio del espacio al dominio de la frecuencia en donde se pu eden observar características más descriptivas de la imagen. Esta transformada tiene la propiedad de qu e opera únicamente con números reales y posee características de alta compactación de energía; además no presenta correlación entre los coeficientes calculados, propiedad qu e permite operar con cada uno por separado en etapas posteriores. La transformada es bidimensional pues se opera con una matriz y se realiza aplicando la siguiente ecuación:

∑∑= =

++=

7

0

7

0 16)12(

cos*16

)12(cos

41

x xyxvuvu

vyuxsCCS

ππ (7)

21, =vu CC , si u, v = 0

1, =vu CC , d.l .c. A pesar de ser una sola ecuación se pu ede apreciar que la cantidad de operaciones a realizar en este paso es bastante considerable, y además se incluyen funciones trigonométricas. Considerando la complejidad de este bloqu e en el momento de realizar la implementación, es claro qu e para hallar un coeficiente, se debe realizar:

• 8 multiplicaciones • 7 sumas • Lo anterior 8 veces, es decir : 64 multiplicaciones y 56 sumas • Finalmente 3 multiplicaciones más

Con esta información, para hallar un solo coeficiente de la DCT, se requiere un total de 67 multiplicaciones y 56 sumas; por lo tanto, para hallar los 64 coeficientes son necesarias:

• 4288 multiplicaciones • 3584 sumas

Todo lo anterior sin contar las multiplicaciones internas de los argumentos de la función trigonométrica, y el cálculo de la misma. Sin importar la velocidad de procesamiento de los datos, si se tiene en cuenta qu e las imágenes son inicialmente en formato V GA de 640x480 píxels, es decir 4800 MCU’s por cada componente (Y,U,V) , la cantidad de operaciones crece considerablemente. Desde la descripción del algoritmo, se aprecia qu e seguramente, el cálculo de la DCT será una de las tareas de mayor complejidad, por lo tanto se buscaron formas de implementarla eficientemente para reducir su tiempo de ejecución.

2.5.3.1 Algoritmo Computacional Rápido Con el fin de desarrollar soluciones para calcular la DCT eficientemente, se han propuesto modificaciones qu e aprovechan elementos repetitivos presentes en las sumatorias; una de las solu ciones más eficientes encontrada, fu e la propu esta por Wen-Hsiung Chen, Harrison Smith y S.C Fralick, en donde se propone una implementación diferente basada en multiplicaciones de matrices por constantes. Como la DCT qu e se requiere es bidimensional , esta implementación considera la aplicación de una primera aproximación unidimensional y a este resultado, aplicarle el mismo procedimiento, transponiendo una matriz:

Page 16: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

16

Figura 10. Implementación por matrices de la DCT bidimensional; se realiza una transposición de la memoria luego de la primera DCT y se procesa nuevamente. En el bloqu e de procesamiento de DCT la operación qu e se realiza es una multiplicación de matrices de 8x8; la matriz de entrada es el MCU a procesar, y la otra matriz es la que se muestra a continuación: Figura 11. Matriz que permite implementar la DCT unidimensional. Las constantes de la matriz son las que se indexan en la parte derecha. Como la multiplicación de matrices de 8x8 representa aún, una carga bastante amplia, se realizó otra reducción importante que aprovecha algunas particularidades y simetrías entre las filas de esta matriz; las multiplicaciones se redu cen y se obtienen las siguientes operaciones po submatrices:

Figura 12. Sub-matrices encontradas para la operación de la DCT. Las operaciones se realizan por columnas de los datos de entrada. Este resultado se traduce en que por cada su b-matriz hay 16 multiplicaciones y 12 sumas, es decir por cada columna del MCU son 32 multiplicaciones y 24 sumas; para toda la matriz se realizarían 256 multiplicaciones y 192 sumas para una DCT unidimensional . Como el proceso se realiza 2 veces se tiene qu e para la DCT completa habría:

• 512 multiplicaciones 88 % menos operaciones • 384 sumas 90 % menos operaciones

Es decir, la eficiencia aumenta en un 90% en promedio respecto al planteamiento inicial .

Page 17: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

17

2.5.4 Cuantif icación Despu és de terminar con la DCT es probable encontrar coeficientes de valores elevados por lo qu e el estándar propone una cuantificación de los datos obtenidos; el proceso se realiza una sola vez por cada MCU y realiza 64 divisiones u tilizando una matriz de constantes específica. En esta etapa del proceso, pu eden realizarse cambios en las matrices de cuantificación dependiendo de la calidad qu e se requiera. La cuantificación se realiza con 2 matrices: una para la luminancia (Componente Y) y otra para la crominancia (Componentes U, V ).

Matriz de Cuantificación Luminancia Matriz de Cuantificación Crominancia

Figura 13. Matices estipuladas por el estándar para realizar la Cuantificación de los datos resultantes de la DCT. La componente Y se cuantifica con la matriz izquierda y las componentes U, V con la matriz derecha.

2.5.5 Ordenamiento en Zig-Zag En esta instancia los datos están listos para codificarse, sin embargo, el estándar especi fica qu e la matriz se debe reorganizar para ser codificada; este ordenamiento permite agrupar los datos más importantes en las posiciones más cercanas a la esquina su perior izquierda, ya qu e luego de la cuantificación, varios coeficientes fueron reducidos a un valor de 0, y para lograr una codificación eficiente, es necesario agru par tantos ceros como sea posible. El ordenamiento es en forma de zig-zag como se aprecia en la Figura 14 Figura 14. Ordenamiento de los datos en forma de zig-zag. Luego de la Cuantificación el primer dato se convierte en el coeficiente DC y los otros 63 en los coeficientes AC. Lu ego de reorganizar los datos, a medida de qu e se recorre la matriz, la cantidad de ceros aumentará, ya qu e como se pu do observar en las tablas de cuantización, los valores más grandes están en la parte derecha inferior de la matriz.

Page 18: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

18

2.5.6 Codificación de Entropía de Huffman La codificación de Hu ffman bu sca asignar códigos de longitu d variable a símbolos, palabras o números, según sea su repetición. Las tablas de asignación de símbolos pueden ser construidas si se tiene una estadística de la repetición de estos en los datos hallados, sin embargo, el estándar propone unas tablas preestablecidas, diseñadas de acu erdo al cri terio de ellos. Estas son las tablas qu e se utilizan en la compresión Baseline . La codificación de Hu ffman se realiza en dos pasos: Codificación del valor DC, es decir, del valor de la posición (0,0) de la matriz, y codificación de las componentes A C, el resto de los números. También es importante notar qu e las tablas de codificación u tilizadas son diferentes para la Luminancia y la Crominancia aunqu e el principio es el mismo. Para entender el funcionamiento de la codificación, es necesario considerar los casos particulares por aparte; para realizar estas explicaciones se propone el siguiente ejemplo: Codificar la trama: 91, 54, 45, 0, 0, -13, 0, 0, 0, 0, 0, 0, 0, 0, 12 ,35, 0,...........0, de Luminancia.

2.5.6.1 Codificación DC Los valores DC de las matrices se codifican de la siguiente manera:

Se halla el mínimo número de bits necesarios para representar la magnitu d del número en binario:

Para el ejemplo propu esto el coeficiente DC es 91, qu e equivale a 1011011 en binario, es decir, qu e se necesitan como mínimo 7 bits para representarlo.

Se determina si la información es de Luminancia o Crominancia y se toma la tabla de Huffman para coeficientes DC correspondiente, para hallar el código del número a representar según sea su tamaño en bits.

En este caso la información es de Luminancia, y el código Huffman para un número de 7 bits es: 11110. Los códigos de las tablas para los coeficientes DC se encuentran agrupados por categorías, en donde cada categoría es el número mínimo de bits requerido para representar el dato a codificar. La tabla de Luminancia DC se puede apreciar a continuación: Figura 15. Tabla de clasificación de códigos Huffman para los coeficientes DC de Luminancia. Como se observa, para la categoría 7 (bits) el código es 11110.

Page 19: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

19

Se escribe el código Hu ffman hallado, seguido del número en binario, y esta es la información a imprimir en el archivo final. Si el número es negativo, se coloca el código Huffman y lu ego el complemento del número en binario.

Con este paso final , la trama a escribir es: 11110-1011011. Si el número hubiera sido negativo, es decir, -91, la trama sería: 11110-0100100. Al concluir este paso se observa que en lugar de escribir el número normalmente en binario, lo cual ocuparía 8 bits, se están escribiendo 12 bits, es decir, más información qu e “aumenta” el tamaño del archivo final , sin embargo, para números más pequ eños la información se reduce y la compresión se pu ede apreciar mejor con la codificación A C. Un aspecto importante de la codificación DC, es qu e el valor a codificar no es el coeficiente DC, sino la difere ncia e ntre e l coe ficie nte DC de l bloque e n proceso y e l coe ficie nte DC de l bloque ante rior; esto se debe a qu e los valores DC son los de mayor magnitu d en todo el bloque, y existe una relación entre los MCU’s su cesivos (continuidad de color en la imagen) por lo qu e es probable qu e la componente DC de uno de ellos, sea la misma qu e la del siguiente. Con la adición de esta característica, se pu ede apreciar qu e si se tienen 3 bloqu es consecutivos con coeficiente 91, en el primero se codifica el valor total , y en los otros el valor a codificar es 0, lo qu e implica un código Huffman menor y menos datos a escribir.

Figura 16. Codificación diferencial de componentes DC; como los valores están relacionados debido la continuidad de la imagen, los valores se reducen considerablemente.

2.5.6.2 Codificación AC Como los coeficientes A C son 63 valores de los cuales varios se convierten en 0, se utiliza una técnica llamada run/lenght coding; en esta, el primer término run se refiere al número de 0’s qu e están antes del coeficiente a codificar y le nght es el tamaño en bits del coeficiente A C. Para entender el algoritmo, se trata por pasos:

Para las componentes A C, el primer paso a realizar es el mismo qu e en la codificación DC; para el ejemplo que se está desarrollando se tiene:

• 54 110110 6 bits le nght = 6; • 45 101101 6 bits le nght = 6; • 13 1101 4 bi ts le nght = 4; • 12 1100 4 bi ts le nght = 4; • 35 100011 6 bits le nght = 6;

Se determina el número de ceros qu e están presentes antes del coeficiente a codificar:

• 54 run = 0; • 45 run = 0; • -13 run = 2; • 12 run = 8; • 35 run = 0; • Como el resto de números es 0, el estándar lo denomina run=0/le nght=0.

Page 20: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

20

Se hallan los códigos Huffman para cada una de las parejas run/le nght halladas y se escribe el código, seguido del número en binario. La tabla de Huffman a utilizar depende de si es Luminancia o Crominancia.

• 54 ([0/6],54) 111000 – 110110 • 45 ([0/6],45) 111000 – 101101 • 13 ([2/4],-13) 1111111110001001 – 0010 (El número se niega porqu e es

negativo) • 12 ([8/4],12) 11111111110111000 – 1100 • 35 ([0/6],35) 111000 – 100011 • (0/0) 1010 Se denomina comúnmente EOB (Fin de Bloqu e)

Una vez codificados los datos, la trama a escribir qu eda:

• 111000110110111000101101111111111000100100101111111111011100011001110001000111010

• Se incluyen 80 bits para 63 datos qu e hubieran ocu pado mucho más espacio. Tanto la tabla de códigos Huffman A C de Luminancia como la de Crominancia trae códigos qu e incluyen desde run= 0 hasta run=15, y en cada gru po desde lenght=1 hasta lenght=10, (y adicionalmente el marcador de fin de bloqu e run=0/le nght=0) es decir 151 códigos para cada componente. Existen casos especiales cuando el número de 0’s es mayor a 15, en estos casos, se hacen grupos de 16 ceros y se escribe el marcador run = 0, le nght =15 para representarlos, y despu és se codifican los ceros restantes, por ejemplo:

([31/4] ,12), es decir, 31 ceros y lu ego el número 12, se codifica: ([15/0],0), para los primeros 16 ceros, y (15/4,12) para los 15 ceros restantes, y el dato

Para observar la información de los códigos, se muestra a continuación la Tabla de coeficientes para Luminancia A C. Figura 16. Tabla de clasificación de códigos Huffman para los coeficientes AC de Luminancia. Se agrupa por parejas run/lenght.

Page 21: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

21

2.5.7 Escritura de Datos

Hasta el momento es posible ver qu e superada la etapa de codificación los datos se pueden comenzar a escribir en el archivo final ; para el ejemplo anterior, la escri tura del bloque completo es la conjugación de la codificación DC con la A C, es decir, la información a escribir es:

11110-1011011-111000-110110-111000-101101-1111111110001001-0010-11111111110111000-1100-111000-100011-1010, en hexadecimal equivale a:

F5-BE-36-ES-DF-F8-92-FF-00-DC-67-11-C…. Existe una diferencia entre los datos codificados en binario, y los datos escritos en hexadecimal ; lu ego de escribir el valor FF, se agrega un byte de 0’s ya que, como se explicará en la siguiente sección, el fichero jpg, contiene una serie de marcadores y encabezados qu e necesitan ser demarcados de alguna manera para poder ser interpretados por el decodificador; los marcadores de encabezados e información están definidos como FF XX, donde XX varía según la información qu e se desee escribir. Como la trama a escribir es una concatenación de cadenas de bits, es muy probable qu e (como en el ejemplo) se encu entren secuencias FF XX, por lo qu e el estándar estipula que en estos casos se adiciona un byte 00 para diferenciar los datos de los encabezados.

2.5.8 Encabezados y Tablas Como última instancia, puesto qu e la imágenes JPEG pueden ser de di ferentes categorías, la información sobre los procesos realizados para comprimir la imagen también debe estar almacenada en el archivo, por lo qu e el estándar especi fica un orden de escritura de información qu e va al principio de l archivo, es de cir, antes de cualquie r tratamiento a la image n. El diagrama general de la organización de la información se puede apreciar en el siguiente gráfico propuesto en el estándar:

Figura 17. Organización general de la información que se requiere tener en el archivo final. Dentro de la información más importante qu e se requerida en los encabezados, está:

Tipo de codificación realizada: Base line DCT-Base d. Dimensiones de la imagen Factores de muestreo (4:4:4) Tablas de Cuantificación Número de Componentes de la Imagen Tablas de Hu ffman

Page 22: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

22

A nivel general se deben incluir los parámetros mencionados, sin embargo, cada uno tiene una forma de escribirse muy detallada, qu e en este trabajo no se expondrá a pesar de haberse implementado.

Page 23: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

23

3 Desarrollo del Proyecto

3.1 Validación del Algoritmo: Descripción Funcional Como primer paso en el desarrollo de la metodología, se requiere validar el algoritmo de compresión JPEG para comprobar su correcta aplicación y funcionamiento; a pesar de haber realizado un estudio detallado de la compresión JPEG, es necesario seguir rigurosamente cada uno de los procedimientos estipulados para la consecución exitosa de un codificador o compresor JPEG. Inicialmente se propuso realizar esta descripción a nivel de sistema, utilizando el lenguaje SystemC como lo propone la metodología; sin embargo, dado qu e este lenguaje soporta entidades hardware y software, el hecho de u tilizarlo implicaría realizar una descripción totalmente software, totalmente hardware, o particionada. Por lo anterior, como en esta etapa se espera ver el funcionamiento apropiado del algoritmo de compresión, se utilizará una descripción completamente software, lo que equivale a utilizar el lenguaje C. Además de lo anterior, la ventaja de la utilización de este lenguaje de programación es que la mayoría de componentes y procesadores disponibles, sintetiza y ejecuta código escrito en C, en ocasiones, con la necesidad de realizar modificaciones mínimas al código original . La aproximación inicial al algoritmo y el desarrollo del programa, tomó un tiempo considerable puesto qu e se realizaron diferentes descripciones software hasta encontrar la más óptima, la cual procesaba la información con el menor número de accesos a memoria y almacenamientos temporales; el archivo ejecutable final fu e de 35.9KB, tuvo aproximadamente 850 líneas de código y la ejecución con un archivo bmp en formato V GA tomó 1.5 segundos sobre un PC Pentium IV de 256MB de RA M y frecu encia de 2.8GHz. Los aspectos más importantes durante esta etapa de descripción fu eron la posibilidad de validar el mecanismo de compresión por completo y la identificación de funciones y procesos específicos qu e permitieron construir el grafo de tareas de forma acertada.

3.2 Grafos de Tareas Para esta etapa se tomó como referencia el algoritmo desarrollado previamente en C; el programa se estructuró inicialmente con llamados a funciones de alta complejidad que realizaban más de un proceso interno, razón por la cual se generó un primer grafo de tareas como primera aproximación a la solución final . Con el avance del estu dio de cada uno de los bloqu es propu estos, fu e posible encontrar ru tinas de menor complejidad, qu e permitieron bosqu ejar el grafo de tareas final. Se realizaron diversos análisis sobre cómo redu cir aún más las operaciones redundantes o innecesarias y se definió un esqu ema final qu e fue la base para realizar el análisis del particionamiento Hardware-Software. Un factor importante que se consideró en esta etapa del proceso fu e la realización de Redes de Petri para estudiar el comportamiento y flu jo de los datos durante la compresión de la imagen, además de evaluar el papel del control sobre el algoritmo puesto qu e en el grafo de tareas no se representa de manera clara este aspecto. Se plantearon de 2 esqu emas de Redes de Petri qu e no aportaron nu eva información comparándolos con los grafos de Tareas propuestos, por lo qu e se prescindió de su utilización. A continuación se presentan los dos diagramas qu e tuvieron más relevancia.

3.2.1 Grafo funcional Inicial Fu e construido con base en los bloques descritos por el estándar; las tareas se concentraron en cada paso de la compresión y codificación de la información para cada componente de la imagen. Además, este diagrama inicial fue la representación gráfica del primer programa realizado en C que realizó la compresión JPEG exitosamente.

Page 24: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

24

A pesar de no proporcionar datos puntuales a nivel de tareas específicas, con esta validación, se identificó un paralelismo inicial qu e a futuro plantea la posibilidad de incluir soluciones software qu e implementen hilos de procesamiento o en etapas más complejas, diseños con MPSoCs.

Figura 18. Primera aproximación a un grafo de tareas del algoritmo de compresión JPEG. El grafo es la extensión de 3 hilos qu e realizan los mismos procedimientos; el procesamiento en cada hilo es independiente de los demás siempre y cuando se posea la información inicial qu e se toma del archivo RGB. Las tareas planteadas son:

Ycomp: Encargada de tomar toda la información RGB y transformarla para hallar la componente Y de toda la imagen.

Yblock: Lee un bloqu e de 8x8 (un MCU) en el orden preestablecido por el estándar para procesarlo.

DCT: Encargado de realizar la DCT al bloqu e abstraído. Quant-Ord: Realiza la cuantificación y el ordenamiento zig-zag del bloqu e procesado

previamente. Codificación: Se encarga de codificar los componentes A C y DC del bloqu e procesado.

Como los datos se escriben de forma intercalada, existe una dependencia entre ellos ya qu e es necesario escribir primero la componente Y, luego la U y lu ego la V .

En esta propu esta la información del archivo inicial se lee completamente y se forman 3 sub-archivos, cada uno con una componente de Luminancia o Crominancia. Posteriormente se necesita volver a leer cada uno de estos nuevos ficheros para abstraer los bloqu es, razón por la cual se consume mu cho tiempo y espacio con esta solu ción.

3.2.2 Grafo de Tareas Final Partiendo del grafo anterior, se realizaron optimizaciones en la forma de tomar la información del archivo inicial y además se granuralizaron los bloqu es para encontrar procesos más puntuales para entender cuáles de bían ser necesariamente secu enciales y cuáles podrían ser concurrentes. De igual manera que en el primer grafo, se identifican 3 hilos principales (uno por cada componente) pero la extensión es mayor ya qu e los procesos se hicieron más específicos, es decir, se analizaron con una granuralidad más fina. El grafo representa la máxima forma de paralelizar eficientemente el algoritmo general y los procesos de cada hilo; aunque se pu eden realizar más extensiones, el grafo presenta suficiente cantidad de información, para realizar el particionamiento buscando el máximo desempeño/costo. Antes de presentar el grafo, se presenta una tabla con la explicación de las tareas presentes en el mismo. Las tareas son realizadas de igual forma para cada componente, lu ego en el grafo se denotan con la letra de la componente y un su bíndice qu e indica la tarea qu e se realiza.

Page 25: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

25

Figura 19. Listado de tareas representadas en el grafo final obtenido.

El grafo obtenido se mu estra a continuación.

Figura 20. Grafo final obtenido.

Page 26: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

26

La información qu e u tiliza el grafo para la compresión se lista a continuación:

• BMP : Archivo en formato RGB a comprimir. • Mat1 : Matriz 1 de 4x4 para el procesamiento de la DCT (V er Figura 12) • Mat2 : Matriz 2 de 4x4 para el procesamiento de la DCT (V er Figura 12) • Q-Lm : Matriz de Cuantificación de Luminancia. • Q-Cr : Matriz de Cuantificación de Crominancia. • DC-Lm : Tabla de Huffman para los coeficientes DC de Luminancia. • A C-Lm : Tabla de Huffman para los coeficientes A C de Luminancia. • DC-Cr : Tabla de Huffman para los coeficientes DC de Crominancia. • A C-Cr : Tabla de Huffman para los coeficientes A C de Crominancia. • OrdM : Tabla qu e permite realizar el ordenamiento Zig-Zag de los Datos.

Como se mencionó al describir la metodología, la complejidad y extensión del grafo dependieron directamente de la forma como se implementaron cada una de las tareas del algoritmo.

La conversión RGB - YUV fue redu cida con la adopción de las siguientes ecuaciones:

• Y = (0.257R) + (0.504G) + (0.098B) + 16 (7) • U = 0.492(B – Y) (8) • V = 0.877(R – Y ) (9)

La DCT fu e implementada con el algoritmo de alto rendimiento, propu esto en el marco teórico; además fue dividida en varios bloqu es qu e facili taron la identificación de tareas paralelas para obtener un mejor desempeño. A di ferencia de la propu esta del diseño de la DCT qu e consta de 1 ciclo para procesar la totalidad de la matriz, en el grafo propuesto, se decidió realizar una expansión de esta repetición para tener una mejor perspectiva respecto a las tareas qu e necesariamente deben ser secu enciales y las qu e deben ser concurrentes. Las tareas 2 - 10 constituyen todo el proceso de la DCT y pu eden ser paralelizadas aún más ya qu e las operaciones internas qu e se realizan son independientes entre si.

Las tareas 11 – 15 son las encargadas de realizar la cuantificación, ordenamiento y codificación de la matriz resultante de la DCT; son necesariamente secuenciales puesto qu e la información qu e manejan y manipulan depende de las etapas anteriores.

En última instancia se presentan las tareas 16 y 17 qu e están encargadas de la escri tura de los datos en el archivo final; la tarea 16 es un almacenamiento temporal de los datos codificados qu e se planteó con el fin de que cada hilo de procesamiento pu diese avanzar en la codificación para tener la trama de bits lista en el momento de ser requ erida, no obstante, esta tarea será posible implementarla únicamente a nivel hardware en caso de ser esta la decisión a tomar; si la etapa de escritura es realizada en software, esta tarea desaparecerá del grafo en cada hilo.

El paso a seguir una vez el grafo ha sido definido, es realizar los estimativos necesarios para determinar en qu é tareas se presenta la mayor complejidad y retardos con el fin de realizar las particiones Hardware y Software.

3.3 Estimativos de Desempeño Pu esto qu e el algoritmo fue desarrollado a nivel de software, los estimativos a realizar estuvieron enmarcados en este mismo contexto; se propusieron 2 tipos de análisis: el primero fue realizar la ejecución software y ver el tiempo de procesador utilizado por cada una de las tareas y el segundo fu e hacer una estadística de complejidad en donde se enumeraron la cantidad de sumas, multiplicaciones y divisiones de cada módulo para clasificarlos.

Page 27: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

27

Aunqu e estas estimaciones no son muy precisas en cuanto al tiempo real de ejecución ya qu e no se conoce en qu é plataforma se implementará el diseño, permiten saber en cuáles tareas se está tomando más tiempo de procesamiento y además, en cuáles se concentran las operaciones más complejas.

3.3.1 Ejecuciones en Computador Una de las ventajas de haber implementado el algoritmo en C es qu e pu ede ser ejecutado en cualquier compu tador y posee funciones y librerías de manejo y adquisición de tiempos que facilitaron la verificación de las mediciones. Para tener una mejor estimación de los resultados, se propu so realizar la pru eba en diferentes compu tadores para ver si existía alguna relación entre la información proporcionada por cada uno de ellos, así qu e se realizaron las pruebas en un computador de escritorio y un portátil , bajo Windows XP. Se intentó realizar las mismas pru ebas con el SO Linux (distribución Kubuntu ), pero el muestreo de tiempo no funcionó adecuadamente. Para determinar el tiempo de procesamiento de cada una de las funciones se utilizó la función clock() de la librería time.h de C; dado qu e estas funciones tienen una precisión de milisegundos, fu e necesario realizar programas independientes para cada tarea y ejecutar ciclos muy grandes para obtener un tiempo medible. Los resultados se mu estran a continuación:

Figura 21. Cuadro comparativo de los tiempos de ejecución en cada tarea; las tareas de Multiplicar se agruparon en solo 2 categorías (aunque son 4 bloques), ya que realizan el mismo proceso. La tarea de Escribir depende de la cantidad de bits que contengan los datos codificados, como este parámetro depende de la imagen a comprimir, el tiempo de ejecución por bloque es incierto.

• Portatil WinXP : Pentium Centrino, 512MB de RAM y frecuencia de 1.6GHz • PC WinXP : Pentium IV, 256 MB de RAM y frecuencia de 2.8 GHz

Page 28: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

28

Al observar los datos presentados en la tabla se puede notar qu e los tiempos de ejecución en ambos compu tadores fu eron distintos, sin embargo, en cada uno la complejidad de las tareas presenta el mismo ordenamiento, es decir, las tareas qu e toman más tiempo en ejecutarse en una plataforma, también toman más tiempo de ejecu ción en la otra. La tabla presenta dos columnas por cada categoría, esto se debe a que se compararon las tareas teniendo en cu enta el tiempo qu e tomaban ejecutándose una vez, y el tiempo total qu e tomaban para procesar un MCU (un bloqu e de 8x8), dependiendo del número de llamadas a la función requ eridas. El porcentaje del tiempo consumido a nivel general por cada una de las tareas también se calculó para tener un diagnóstico más acertado: Figura 21. Gráfica de porcentaje de tiempos encontrado para el procesamiento de un bloque de 8x8.

En la gráfica anterior, se aprecia qu e a pesar de haber funciones qu e se ejecutan varias veces (Y, U, V ), en términos generales no son tan complejas como otras qu e se realizan con menos frecu encia. Las tareas más complejas según este grafo, son las de multiplicar las constantes por los datos de entrada, y cuantificar información; como las tareas de multiplicación realizan el producto de una matriz de 4x4 por un vector 4x1, soportan una al ta carga de operaciones y consumen bastante tiempo de procesador, por otro lado la cuantificación es una tarea qu e solo ocurre una vez para cada bloqu e pero realiza la división de 64 datos secuencialmente por lo qu e consti tuye otra tarea computacionalmente compleja. Ambas tareas se realizan con números reales.

3.3.2 Análisis de Complejidad Con la intención de crear una estadística de las operaciones realizadas por cada tarea, se construyó una tabla en donde se enumeran la cantidad de sumas (restas), multiplicaciones y divisiones realizadas por cada nodo del grafo final para evaluar su complejidad; pu esto qu e no se tienen mediciones exactas del tiempo o los ciclos de reloj qu e tarda cada operación (ya qu e esto depende de la tecnología en donde se vaya a implementar el proceso), se pu eden sin embargo, hacer suposiciones respecto al desempeño de cada uno de los módulos. La tabla construida se mu estra a continuación:

Page 29: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

29

Figura 22. Tabla de cantidad de operaciones que se realizan en cada una de las funciones del algoritmo. Las últimas funciones de codificación y escritura de datos dependen de la imagen a comprimir por lo que no se incluyen. Analizando la tabla mostrada se observa qu e por llamado a función, la tarea que realiza más cantidad de operaciones es el Cuantificador seguido por los Multiplicadores de Matrices y la transformación RGB – Y. Pu esto qu e se quiere analizar el proceso completo de compresión de una porción de la imagen (un MCU), es necesario revisar la cantidad de operaciones por bloque qu e se ejecu tan; para este caso, el ordenamiento varía: primero se encu entran los Multiplicadores de Matrices, luego la transformación RGB-Y y lu ego la Cuantificación. A pesar de qu e la complejidad de la tarea de transformación de espacio de color (Y) presenta una cantidad considerable de operaciones por cada MCU, las restricciones del proyecto implican qu e la información se recibirá por un bit-stre am por lo qu e esta es una tarea qu e no se pu ede paralelizar. Por otro lado se observa claramente qu e las tareas de Multiplicación de Matrices son las qu e más realizan operaciones aritméticas qu e incluyen multiplicaciones y sumas; esta estimación concuerda con los resultados obtenidos en los tiempos de ejecu ción pu es el mayor consumo de tiempo fu e obtenido en ellas. El resto de tareas qu e aún admite particiones hardware son las sumas/restas con un total de 64 operaciones, y el cuantificador también con 64 operaciones; como ya se mencionó, no es posible saber la cantidad de ciclos de reloj necesarios para la ejecución de cada una de las operaciones a realizar, sin embargo, es posible saber de antemano qu e la división es un proceso más complejo que la suma (resta) y qu e una sola división implica por lo menos una de ellas; siguiendo este razonamiento, como la cantidad de operaciones es igual para estas 3 tareas se deduce que es más eficiente realizar una implementación hardware del cuantificador qu e de los sumadores/restadores.

3.4 Particionamiento Con la información recopilada hasta esta etapa, se propuso un particionamiento Hardware-Software tomando como base las estimaciones realizadas; como se pu do apreciar, ambos procedimientos de análisis arrojaron el mismo resultado, qu e las tareas a implementar en Hardware son:

• Multiplicadores de Matrices [4x4] por vectores [4x1] • Cuantificador. (Divisor de Matrices[8x8] por Matrices [8x8])

Una vez se toma esta decisión, surge la pregunta de cuántos módulos Hardware es óptimo implementar si no se quiere caer en el error de sobredimensionar el diseño y comprometer área en módulos qu e van a estar inactivos durante la compresión, o bien sub-dimensionarlo para obtener resul tados qu e no aceleren la compresión de manera notoria. Como se están realizando los análisis sobre un hilo de procesamiento se pu ede advertir que hay 4 multiplicadores de matrices qu e realizan el mismo procedimiento en instantes diferentes; además, la

Page 30: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

30

multiplicación se debe realizar 8 veces en cada uno de los tiempos donde se localizan estas tareas, por lo tanto el planteamiento inicial es la inclusión de 4 multiplicadores hardware. Una implementación de este tipo le permitiría al software procesar las multiplicaciones en el acelerador mientras prepara los datos de otra componente para re utilizar el módulo, sin embargo, como se espera un desempeño de alto rendimiento por parte de los aceleradores hardware es bastante probable qu e al llegar al segundo instante de tiempo donde se multiplican los datos, los módulos queden libres e inactivos si los datos de otra componente no están listos para enviarlos. Teniendo en cu enta este planteamiento se decidió qu e la mejor opción era la realización de 2 módulos aceleradores hardware para la multiplicación de matrices, ya qu e pu eden ser reutilizados en instantes de tiempo diferentes. En el caso del cuanti ficador, se requiere procesar la división de una matriz de 8x8, entre otra; la matriz divisora varía si se están tratando MCU’s de Luminancia o Crominancia, es decir, la división se realiza por dos sets de constantes diferentes qu e en principio deben estar almacenados en el módulo para reducir el intercambio de información entre el procesador y los aceleradores hardware. Si se quiere independizar por completo la cuantificación sería necesario hacer 2 módulos para esta tarea (uno por cada componente), sin embargo se pu ede construir una sola entidad qu e soporte los dos tipos de cuantificación y qu e almacene más datos constantes. Para desarrollar cada componente se debe analizar el tiempo qu e se demora cada tarea en un solo llamado con el fin de optimizar estas operaciones; no obstante, para conocer esta información se requiere saber en qué plataforma se implementará el diseño pues cada una u tiliza tecnologías diferentes para realizar los cálculos. Adicionalmente, antes de analizar las plataformas, es necesario realizar la planeación de tareas con el fin de encontrar una asignación óptima qu e ocupe tanto los módulos Hardware como los recursos Software el mayor tiempo posible y verificar si la decisión tomada fu e acertada.

3.5 Planeación de Tareas Con la disponibilidad de 3 recursos hardware el tiempo de ejecu ción del proceso se pu ede redu cir considerablemente ya qu e en un mismo instante de tiempo pueden trabajar los módulos hardware y el procesador en tareas completamente di ferentes; la asignación de estas tareas pu ede significar el éxito o fracaso del particionamiento por lo qu e es necesario ser cuidadoso y riguroso en esta etapa. Para saber de qu é manera y con qu é prioridad se debe recorrer el grafo, es necesario recordar en primera instancia qu e la información debe estar intercalada en el orden Y – U – V, por lo qu e la prelación está determinada por ese mismo orden; además, es necesario qu e mientras el hardware realiza ciertas operaciones, el software adelante otras qu e permitan reutilizar sus periféricos en el siguiente instante de tiempo. La utilización de los módulos multiplicadores requiere qu e los datos de las etapas inmediatamente anteriores estén disponibles; en este orden de ideas, el procesador tendría qu e recorrer el grafo de manera horizontal para aprovechar todos los recursos y evitar tiempo mu erto en el mismo. El bloqu e cuantificador necesita la información resultante de la DCT, qu e concluye con las segundas multiplicaciones realizadas; puesto qu e este efectúa las operaciones más largas (divisiones), va requ erir más tiempo para concluir su trabajo pero también se utilizará menos veces qu e los demás módulos. Con estas consideraciones, se proyecta una distribución de tareas como se mu estra en la Figura 23. La correspondencia de cada tarea se presenta en la Figura 24.

Page 31: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

31

Figura 23. Tabla de la distribución final de tareas; la nomenclatura de las tareas cambió ya que al decidir de qué manera implementar el algoritmo final, algunas fueron removidas.

Figura 24. Tabla de la nomenclatura final de las tareas.

En esta planeación se buscó la forma de operar en paralelo con todos los módulos con el fin de realizar la máxima cantidad de operaciones en el menor tiempo posible; puesto que solo las tareas más simples y de poco consumo de tiempo se dejaron en el procesador, la reducción general fue bastante amplia. En las zonas iniciales y finales de la tabla se observa qu e los aceleradores hardware se encuentran inactivos, lo anterior es normal ya qu e existen tareas qu e solo pu eden ser desarrolladas secu encialmente con el particionamiento propu esto, por la cual se limita la optimización de tiempo en el proceso. En la sección de estimativos se mencionó qu e cada módulo multiplicador y cuantificador debe ser invocado 8 veces en cada uno de los lugares donde aparece en el grafo de tareas, por lo tanto, la tabla de la Figura 23 no es precisa en lo qu e se refiere a la escala de tiempo; lo qu e se quiere mostrar es qu e en el mismo intervalo qu e se realizan las operaciones qu e aparecen en la columna “Sw”, se bu sca completar la totalidad de las tareas qu e aparecen en las columnas “Hw – M1/M2/C”. Por ejemplo, mientras qu e se realizan las tareas U2 y U3, es decir la suma y resta de 4 pares de datos, (un total de 8 sumas), el hardware debe haberse utilizado 8 veces para completar la primera parte de la DCT;

Page 32: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

32

se asume qu e después de cada una de las 8 sumas a realizar, el procesador tendrá qu e atender una interru pción para almacenar la nu eva información proveniente del hardware, y enviarle nuevos datos a este para que continúe operando. De igual manera, cuando se utilizan los 3 módulos en paralelo, la información qu e va hacia los multiplicadores es diferente a la información qu e va hacia el cuantificador por lo qu e el procesador debe recibir primero la información de un módulo, luego la de otro módulo y enviarles nu evamente los datos correspondientes a cada uno para qu e continúen su ejecución. El proceso tiene nu evas tareas no explícitas qu e son la recepción y escritura de datos, sin embargo, las anteriores no consumen la misma cantidad de tiempo qu e las removidas del entorno software por lo qu e si existe una aceleración.

3.6 Plataformas Disponibles para la Implementación Existen 2 alternativas para la implementación del codificador JPEG que manejan un entorno Hardware-Software eficiente y de gran capacidad de almacenamiento y procesamiento: La primera es la u tilización de un hard-core processor con un FPGA, como el mostrado en la Figura 25, qu e incluye un A TMEL A T91RM9200 y un Spartan3 (XC3S400), y la segunda es con un soft-processor qu e integre módulos hardware como periféricos del procesador; entre las posibilidades para esta opción se encu entran el Microblaze de XILINX o el Nios II de Altera. La consideración de cada uno se expone a continuación:

3.6.1 ARM – FPGA Los procesadores ARM tienen la ventaja de operar con registros de 32 bits, lo cual facilita y acelera las operaciones con datos de esta longitu d; ejecu tan la mayoría de instrucciones en 1 ciclo y poseen una estructura pipe line qu e les permite incrementar su velocidad; realiza multiplicaciones con el algoritmo de booth. El FPGA Spartan 3 tiene 400.000 compu ertas. Esta tarjeta fu e adquirida por la universidad anteriormente pero no se ha utilizado en este tipo de proyectos hasta el momento ya qu e su uso ha limitado a la programación del procesador, dejando de lado el FPGA. El inconveniente con esta solución es qu e se buscaron herramientas de simulación del ARM qu e permitieran observar el desempeño del procesador con las diferentes tareas pero se encontraron pocas soluciones qu e emulaban la ejecu ción de los procesos bajo un SO Linux; a pesar de qu e se pudo ver la ejecución del algoritmo completo, no se pudo establecer los tiempos qu e tardaba cada una de las tareas en completarse. Por otro lado, el software conseguido, solicitaba unas licencias con las qu e no se contaba por lo qu e se di ficultó aún más su adopción. Otro factor qu e puso en desventaja a esta opción fue qu e el tamaño del S partan3 es bastante limitado para las funciones qu e se quieren realizar en el . Las operaciones de los multiplicadores y el cuantificador requieren almacenamiento de por lo menos 150 datos de 32 bits, manejo de multiplexores de 32 bits, bu ses internos, etc. Se estimó qu e era bastante probable que el tamaño del FPGA no fuera suficiente para almacenar esta cantidad de funciones e información.

Figura 25. Tarjeta de desarrollo diseñada en emqbit.com. Foto tomada de http://wiki.emqbit.com/ecb-at91-v2

Page 33: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

33

Conjugando los factores ya mencionados se descartó la u tilización de la tarjeta para el proyecto; como alternativa surgió la posibilidad de utilizar soft-processors, qu e se describe a continuación.

3.6.2 Soft-Processors: MicroBlaze En la actualidad las tendencias de diseño se están centrando en la u tilización de soft-processors, es decir, procesadores embebidos en FPGA’s, puesto qu e permiten la implementación de módulos Hardware y algoritmos Software en un solo chip, con mucha más facilidad para interconectar las diferentes entidades, simularlas y programarlas; este tipo de componentes están directamente relacionados con aplicaciones a sistemas embebidos y codiseño Hardware-Software. Actualmente las dos opciones del mercado son el MicroBlaze de Xilinx y el Nios II de Altera; ambos procesadores tienen una arquitectura RISC, soportan operaciones con 32 bits, multiplicación hardware, tienen estructura pipeline (3 e tapas para MicroBlaze, 6 e tapas para Nios II), división en multiciclos, etc. Por otro lado, las herramientas de Xilinx han sido utilizadas con mayor frecu encia en la Universidad por lo qu e hay mayor familiaridad con las mismas en comparación con las de Altera; por lo anterior, después de realizar las comparaciones con los datashee ts de cada uno, a excepción de la estru ctura de pipelining, no se encontraron mayores ventajas de un core sobre el otro por lo qu e se decidió utilizar el MicroBlaze . Este procesador permite realizar implementaciones en diferentes FPGA’s, encontrando limitaciones únicamente en el tamaño de las mismas para su adición de peri féricos; estos pu eden ser configurados y conectados por el usuario u tilizando dos tipos de buses, el OPB (On-Chip Pe riphe ral Bus) qu e es compartido, o el FSL (Fast S imple x Link) qu e solo se conecta al módulo. La arquitectura general de este procesador se puede apreciar en la Figura 26:

Figura 26. Diagrama de bloques general para el MicroBlaze. Los buses FSL son unidireccionales pero pueden aumentarse hasta 8 en cada sentido. Como solo se van a conectar 3 módulos Hardware, se utilizarán solamente 6 FSL’s, lo cual es suficiente para el proyecto. El MicroBlaze tiene una opción para activar un FPU (Floating Point Unit) que permite acelerar las operaciones de punto flotante con la activación de un módulo especial para el tratamiento eficiente de estos formatos. El software requ erido para la construcción y adicionamiento del MicroBlaze y sus módulos es el EDK (Embe dded Design Kit), el cual utiliza el programa Eclipse para la ejecución y detección de errores del software a ejecutar. Para realizar estimaciones reales de los tiempos de operación de cada una de las tareas se utilizó Eclipse y la herramienta Xilinx Profiler qu e contabiliza el tiempo de ejecución de cada función, el número de

Page 34: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

34

llamados qu e se le realizan, el número de funciones qu e llama y el porcentaje de tiempo que empleó du rante todo el programa qu e ejecuta el MicroBlaze. A demás de las anteriores, se pu ede configurar la simulación para qu e el procesador realice optimizaciones en tiempo o área dependiendo del desempeño bu scado. Con estas herramientas se realizaron simulaciones para analizar el máximo y mínimo desempeño de cada uno de los módulos estudiados.

3.6.2.1 Simulaciones Iniciales Se realizaron simulaciones de las tareas más complejas a implementar utilizando las herramientas del EDK; se ejecutó el código tal como se desarrolló inicialmente en la descripción funcional y se obtuvo la siguiente gráfica qu e representa el porcentaje del tiempo total utilizado por cada una de las funciones en el procesador:

Figura 27. Estadística porcentual del tiempo de procesamiento consumido por las tareas más complejas del algoritmo de compresión. Como se pu ede apreciar en el diagrama, las tareas más complejas son las tareas de multiplicación, con un consumo del 22.5% (cada una), una función llamada floatsisf, lu ego la cuantificación y otra función llamada fixsfsi. La información referente a las funciones de multiplicación concu erda con las estimaciones realizadas con anterioridad y presentan un comportamiento semejante al expu esto en la Figura 21. Por otro lado, la tarea de cuantificación aparentemente no consume tanto tiempo de procesamiento pues solo arroja un valor de 7.19%, sin embargo la herramienta de simulación posee una herramienta denominada call table view en donde fu e posible verificar qu e las funciones desconocidas mencionadas fu eron invocadas por la función de Cuantificación; su operación consiste en convertir números en punto flotante a enteros con signo ya qu e es en esta etapa donde se hacen los redondeos pertinentes para convertir los datos a números enteros. Con esta aclaración, se observa qu e en total la función de Cuantificación consumió 38% del tiempo de procesamiento, resultado qu e también concuerda con la Figura 21. A continuación se presenta la tabla qu e permitió establecer la correspondencia de las llamadas floatsisf y fixsfsi; ambas funciones fu eron llamadas por la tarea Cuanti ficación; la primera fue llamada 384 veces y la segunda, 192.

Page 35: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

35

Figura 28. Tabla construida en Eclipse con la aplicación Xilinx Profiler; se observa el número de llamados realizado por la función de Cuantificación. Los datos presentados en el pie, pu eden también ser apreciados en la siguiente tabla, la cual los expone en unidades de tiempo

Figura 29. Tabla que muestra el número de llamadas realizadas a cada función (columna 3), el tiempo que cada una utiliza el procesador (columna 4) y el tiempo total consumido por ellas sumando el retardo producido por las sub-funciones a las que invocan. La Cuantificación tarda en total 647 microsegundos. Una vez se estableció la complejidad de las tareas en la plataforma real, se intentó optimizar el algoritmo en funciones crí ticas, para esto, en la multiplicación de matrices se expandieron los ciclos propu estos y se programó el código linealmente, indexando cada multiplicación y suma por separado; aunqu e se esperaba un resultado muy similar al ya encontrado, se halló qu e el desempeño aumentaba considerablemente con esta mejoría. Se aceleraron las multiplicaciones en un 20%. En la figura 29 se presentan estos resultados.

Figura 29. Implementación de la Multiplicación de matrices con ciclos (derecha) y sin ciclos (izquierda). El desempeño pasa de 51.7% a 30.4%, es decir hay una mejora del 21.3%

Page 36: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

36

Con este resul tado fu e posible acelerar el proceso con una modificación mínima en el código; no obstante, como se busca evaluar el desempeño máximo del algoritmo software, se mencionó la posibilidad de hacer mejorías y optimizaciones por velocidad en las simulaciones; dichas estimaciones se presentan a continuación.

3.6.2.2 Optimización por velocidad Se seleccionó el nivel de simulación –O3 y se realizaron las estimaciones nu evamente con la optimización al código encontrada en la etapa anterior. Los tiempos de ejecu ción disminuyeron considerablemente pu es se redujeron en al tos porcentajes; otro aspecto importante fu e que la aceleración de las tareas no cambió el ordenamiento de las mismas en cuanto a su complejidad, la gráfica de la Figura 30 permite apreciar estos resultados: Las tareas de multiplicación de matrices, cuantificación y sus sub-funciones fu eron las que ocuparon más tiempo el procesador.

Figura 30. Simulación con el máximo nivel de optimización; nuevamente las funciones llamadas por el cuantificador y las multiplicaciones de matrices ocupan el mayor porcentaje de tiempo.

Figura 31. Tabla de tiempos obtenida para la máxima aceleración software posible. Las tareas de multiplicación aumentan considerablemente su desempeño.

Page 37: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

37

Como se aprecia, la reducción de las tareas de multiplicación cambió de 16 a 2.81us, la cuantificación disminuyó de 97 a 36us, sin embargo en total mantiene un promedio de 630us de consumo de tiempo comparados con los 645us de la simulación anterior; lo anterior confirma qu e realizar un módulo hardware para estas tareas, constituye una buena decisión. A pesar de qu e las tareas de suma y resta no se especi fican en la tabla (ya qu e probablemente no fueron significativas en el promedio general), se observa qu e la función main tomó un tiempo total de 2227.9us en comparación con los 3769us de la simulación inicial ; lo anterior implica qu e el ciclo más complejo del algoritmo pu ede ser realizado en mínimo 2227.9us para las 3 componentes. Con los análisis qu e se presentarán en las siguientes secciones podrá establecerse el tiempo mínimo logrado para completar todo el proceso para un MCU de cada componente.

3.7 Módulos Hardware Teniendo en cu enta la planeación de tareas propu esta, se requiere diseñar 3 módulos hardware qu e logren cumplir con las exigencias de tiempo impu estas por la Figura 23; como se observa en la misma, el tiempo que tarda el algoritmo en realizar 8 sumas debe ser suficiente para concluir la primera fase de la DCT, es decir, los 2 módulos deben realizar un promedio de 128 multiplicaciones y 128 sumas cada uno en este tiempo; así mismo, el bloqu e cuanti ficador debe estar en capacidad de realizar 64 divisiones en el mismo intervalo. Lo anterior parece poco factible teniendo en cu enta la complejidad de cada operación si se compara con la suma; por lo mismo, se debe intentar paralelizar al máximo los procesos internos de cada módulo para su plir estas necesidades. Con el fin de obtener los mejores resul tados se buscaron algoritmos de al to rendimiento para realizar cada operación básica (suma, resta, multiplicación, división) y se encontraron documentos qu e permitieron tomar estas decisiones acertadamente, soportándose en datos y estadísticas precisas y veraces. En las secciones siguientes se observa el análisis realizado con cada operación y módulo hardware.

3.7.1 Multiplicadores de Matrices [4x4] x [4x1] Estos bloqu es deben recibir 4 datos para procesar las multiplicaciones, además deben realizar este procedimiento 8 veces; para evitar retardos en la comunicación, las constantes de las matrices deben estar almacenadas en los módulos para agilizar el proceso. Como la multiplicación debe realizarse por fila-columna, 4 veces, se especificó qu e este proceso fu era realizado en paralelo por cada fila, es decir, se multiplica la primera fila por el vector de entrada y al mismo tiempo se procesa la multiplicación de la segunda, tercera y cuarta fila por el mismo vector. Con este algoritmo la ejecución solo estaría limitada por el tiempo qu e acarree la conclusión de 4 multiplicaciones hechas secuencialmente y 4 sumas. El diagrama del módulo básico propu esto para este proceso es el qu e se mu estra en la Figura 32.

Figura 32. Módulo básico de multiplicación Fila-Columna. Todos los buses son de 32 bits.

Page 38: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

38

En este diagrama, se observa la operación del algoritmo a nivel secuencial : la señal de reloj habilita el contador qu e direcciona el dato y la constante por la cuál debe ser multiplicada; se almacena el produ cto en la posición de memoria correspondiente y al final se realizan sumas en paralelo de los resultados parciales hasta obtener una suma final que arrojará el resultado requ erido. El bloqu e multiplicador de matrices requiere elementos específicos como lo son un multiplicador y un sumador; se realizó una consulta detallada de los tipos de algoritmos e implementaciones de multiplicadores más utilizados por su gran desempeño, y se encontró un estu dio realizado en la Universidad del Valle (*) donde se hacen estas comparaciones tanto con multiplicadores secuenciales como paralelos; los resultados establecieron qu e para el caso secuencial, la implementación más rápida es e l algoritmo de booth y para el caso paralelo, las estructuras pipeline. Como se necesita implementar 4 multiplicadores en cada módulo (es decir 8 multiplicadores), se decidió utilizar el algoritmo de booth para ahorrar espacio ya qu e además, los datos se transforman de 32 a 64 bits; por otro lado, se sabe que cada constante almacenada tiene un tamaño de 14 bits pu es se tomaron como datos en punto fi jo, así qu e lu ego de hacer la multiplicación el redondeo consiste en almacenar solo el valor entero del produ cto hallado. Para el bloqu e sumador se realizaron también varias consultas en diferentes fu entes (*) y se encontró qu e la implementación más eficiente era con módulos CLA ’S, (Carry Look-Ahe ad); como el tamaño de los sumandos era de 32 bits, se realizaron módulos de CLA ’s de 4 bits, con estos se realizaron 2 módulos de CLA ’s de 16 bits para formar un módulo CLA de 32 bits. Lu ego de definir los detalles del módulo en general, se planteó el diagrama completo de cada multiplicador de matrices: puesto qu e son 4 filas para un mismo set de datos, se busca replicar el bloqu e 4 veces y adicionar bu ses para interconectar cada señal con el módulo correspondiente; los valores constantes se encuentran en cada módulo y difieren para cada multiplicador de matrices (ya qu e son matrices diferentes). En general , cada acelerador hardware tiene la siguiente estructura:

Figura 33. Diagrama de cada uno de los bloques de Multiplicación de Matrices; se agrupan 4 módulos iguales y se realizan las conexiones para cada uno. Antes de presentar las simulaciones realizadas para cada multiplicador se debe establecer la diferencia entre los mismos, la cual reside únicamente en las matrices qu e almacenan; las constantes de las sub-matrices presentadas en las figuras 11 y 12 fueron calculadas y los resultados obtenidos se muestran a continuación:

Page 39: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

39

Figura 34. (Izq) Matriz requerida para el bloque Multiplicador 1. (Der) Matriz para el bloque Multiplicador 2. El código fu e desarrollado en VHDL y la simulación permitió establecer qu e el tiempo qu e tarda cada módulo en multiplicar una fila-columna es 4 ciclos de reloj qu e coincidencialmente es el tiempo qu e tarda el MicroBlaze en ejecu tar una operación ari tmética; pu esto qu e los módulos están en paralelo, el retardo máximo de 4 ciclos de reloj se conserva para el procesamiento completo de toda la matriz; a continuación se aprecian algunas simulaciones de un bloqu e multiplicador 2.

Figura 35. Multiplicación de matrices por vectores implementada en VHDL. Para esta simulación se supuso que los datos se almacenaban en un ciclo de reloj, sin embargo, como se observa, una vez han sido almacenados, en el siguiente ciclo de reloj pueden comenzar a leerse los resultados, direccionándolos adecuadamente.

Figura 36. Segunda simulación realizada con datos diferentes; el comportamiento es el mismo que el apreciado en la primera simulación. El ahorro en tiempo para estos componentes se debe a qu e las multiplicaciones se están realizando en punto fi jo y se redondean los resul tados a números signados de 32 bits; estos redondeos y simplificaciones son posibles ya qu e las matrices de constantes tienen coeficientes menores qu e 1 por lo qu e cada produ cto será siempre menor qu e el factor, es decir, ocupará menos de 32 bits. Por otro lado, los datos de entrada podrán ser de máximo 12 bits, luego al realizar la suma de los produ ctos hallados, el resultado no ocupará más de 14 o 15; con estas consideraciones es válido realizar las aproximaciones 32 bits. Para estos módulos la escritura se hace colocando el bus de direcciones entre 0 y 3, y la lectura se realiza con las direcciones 8 – 11.

3.7.2 Cuantif icador El bloqu e de cuantificación como se estableció, consta de una serie de divisores en paralelo para acelerar el proceso y realizarlo en 8 ciclos; se hizo también un estu dio sobre los algoritmos de división más eficientes computacionalmente para construir un módulo de gran velocidad. Entre las diferentes opciones analizadas se seleccionó la división parale la sin restauración. Este proceso se basa en la construcción de bloqu es sumadores de 1 bit en complemento a 2 u bicados de tal forma qu e se van evaluando sumas y restas en paralelo, dependiendo de los resultados obtenidos en cada una de las etapas previas. Básicamente el algoritmo toma la parte más significativa del dividendo y la resta con el divisor, si la suma es positiva se coloca un ‘1’ en el cociente, si no, se coloca un ‘0’. Al resultado obtenido se le adiciona un bit más del dividendo en su LSB, de esta manera se realiza nu evamente una suma/resta; para determinar si

Page 40: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

40

se debe sumar o restar se mira el resul tado anterior, si fue positivo se continúa restando, de lo contrario se suma. El diagrama en bloqu es del sistema se muestra a continuación:

Figura 37. Diagrama parcial del algoritmo de división paralelo sin restauración. La cantidad de etapas está determinada por la cantidad de bits que se desee tener en el cociente. El Dividendo se toma de 22 bits y el divisor de 8 bits para un cociente de 14 bits. En el diagrama solo se observan 4 etapas, sin embargo el divisor tiene 14 etapas (para un cociente de 14 bits); en total se construyeron 126 módulos sumadores de 1 bi t. La razón por la cual el divisor tiene un tamaño de 22 bits es porqu e los datos a utilizar no van a tener un tamaño superior a este valor y el cociente fu e de 14 bits para darle un rango amplio de división al módulo sin desbordarse. El inconveniente principal del divisor es qu e no trabaja con números negativos, por lo tanto cuando el dividendo sea negativo es necesario hallar su complemento a dos para poder realizar la operación, y al final hallar nuevamente el complemento a 2 del cociente. Con estas modificaciones, el módulo básico a replicar es como el expu esto en la Figura 38.

Figura 38. Módulo básico de división; el MUX selecciona la constante dependiendo de la fila y el tipo de componente que se esté procesando; el detector de signo cambia la representación del número a dividir pues el algoritmo no soporta negativos y al final vuelve a cambiar el signo del resultado. Como en este bloqu e cuantificador se va procesar la división de matrices (64 valores) de acuerdo con el tipo de la información (Luminancia o Crominancia), en principio se plantea un almacenamiento de 128 constantes de 8 bits, sin embargo, las matrices de cuantificación tienen cierta similitud pu es a medida qu e las coordenadas de la misma aumentan, los valores tienden a ser iguales y de gran valor por lo qu e se pu eden almacenar menos datos. Para entender esta situación basta considerar las matrices a almacenar: Figura 39. Matrices de cuantificación de Luminancia (Izq) y Crominancia (Der). Como se observa hay varios grupos de constantes repetidas por lo que no es necesario almacenar tantos valores.

Page 41: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

41

Las constantes se agru pan en cada módulo por columnas, la redu cción la permite realizar el bloqu e cuantificador de Crominancia pu es repite muchas veces el mismo valor. Pu esto qu e se pretende procesar la división de 8 datos en paralelo, el diagrama completo del cuantificador es el qu e se aprecia en la Figura 40

Figura 40. Bloques que componen el cuantificador en su totalidad. Cada módulo contiene los elementos mostrados en la Figura 38. Dependiendo de la dirección recibida el módulo habilita las entradas o las salidas. La simulación obtenida para un primer grupo de datos de Luminancia qu e se dividen por la primera y segunda filas de la matriz de la izquierda de la Figura 39, es la presentada a continuación:

Figura 41. Simulación del cuantificador; no se requiere señal de reloj para su funcionamiento, solamente necesita tener un direccionamiento apropiado tanto para escribir los datos como para leerlos. En la parte inferior se observa el resultado de las divisiones de los datos de entrada por la fila 1 de la matriz de cuantificación de Luminancia.

Figura 42. Simulación del mismo proceso dividiendo por las constantes de la fila 2 de la matriz de cuantificación de Luminancia.

Figura 43. Simulación del mismo proceso incluyendo datos negativos para verificar el funcionamiento correcto del módulo. El primer y cuarto dato son cambiados por números negativos y se obtiene un cociente negativo. Para este bloqu e cuantificador se requiere un detalle mayor respecto a las direcciones manejadas para asegurar el correcto funcionamiento del mismo. El bus de direcciones de 32 bits se encu entra dividido en secciones qu e le permiten al módulo identificar qu é constantes utilizar y qu é tipo de información se va a cuantificar (Luminancia o Crominancia).

Page 42: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

42

El diagrama qu e se mu estra a continuación permite entender cómo operar el módulo:

Figura 44. Diagrama de divisiones para acceder al módulo con el bus de direcciones. Para la escritura de datos se debe tener el bit 7 en 0 y para la lectura en 1. El cuantificador debe accederse procesando los datos por filas. Para entender este diagrama pu ede pensarse qu e si se quiere enviar la tercera fila de una componente de Crominancia para cuantificarse, en primer los datos deben ser enviados con el bi t 7 en 0 y los bits 0, 1 y 2 con la posición correspondiente a la columna de cada dato; además, como se está trabajando con Crominancia, el bit 6 debe estar en 1, y cómo se está procesando la tercera fila, los bits 3, 4 y 5 deben estar en 010 (pues comienza en 000). La serie presentada debe tener el siguiente aspecto:

Figura 45. Secuencia de direcciones requeridas para procesar la cuantificación de la fila 3 de una componente de Crominancia.

Figura 46. Secuencia de direcciones requeridas para leer el resultado de la cuantificación de la fila 3 de una componente de Crominancia. Como se pu do apreciar, la aceleración en este módulo se realizó con la división por filas, es decir 8 divisiones en paralelo; a pesar de qu e no se consideran redondeos detallados como lo realiza el MicroBlaze, se está emulando el desarrollo logrado con la implementación en C, ya qu e en esta, los redondeos se realizaban truncando la parte fraccional del número, obteniendo bu enos resultados.

Page 43: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

43

3.8 Mejora en Desempeño Una vez los módulos hardware han sido diseñados y verificados, se quiere evaluar el desempeño máximo del nu evo sistema Hardware-Software. Pu esto qu e las tareas de mayor consumo de recursos fueron su primidas de la plataforma Software el tiempo total consumido por el algoritmo está determinado por el consumo del mismo en las tareas qu e aún ejecuta y el tiempo que tarda la lectura y escri tura de datos en los periféricos. En el datashee t del MicroBlaze se establece qu e el tiempo de lectura/escri tura para el bus FSL es de 2 ciclos de reloj, por lo qu e conociendo la frecuencia de operación del procesador se pu ede saber el tiempo qu e toma la totalidad del proceso. Para realizar este análisis se retoman los valores obtenidos en la tabla de la Figura 29 y se desarrollan las siguientes aclaraciones:

El tiempo qu e tarda el algoritmo en concluir las tareas de suma es en promedio 1540 ns en 48 llamados a la función.

Una invocación a la función toma 32ns. Por cada llamado a función realiza 4 sumas (restas). Por cada suma/resta tarda 8ns, lo cual es consistente con las especificaciones del MicroBlaze

ya qu e toma 4 ciclos de reloj en completar una operación aritmética y el reloj oscila a 50 MHz.

Con estas explicaciones es necesario también retomar la planeación de tareas para entender cómo calcular los retardos por lectura/escri tura de datos con los periféricos. Debido a qu e cada tarea indexada debe realizarse 8 veces (excepto la cuantificación), la figura 23 no es clara respecto a estos ciclos, sin embargo, con una expansión de cada tarea 8 veces, se clarifica esta proyección. La Figura 47 expone el llamado a funciones y módulos a implementar:

Figura 47. Planeación de Tareas detallada. Las tareas 2 – 9 se realizan 8 veces para cada componente; la tarea 10 se realiza una sola vez. Finalmente, las tareas 11-14 dependen de la imagen para determinar cuántas veces se ejecutan.

Page 44: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

44

Si se observa el hilo de procesamiento software se observa qu e solo se utilizan las funciones más simples, sin embargo, como hay bastante transferencia de información entre los periféricos y el procesador, hay qu e tener en cu enta el tiempo consumido en estas operaciones: Cuando se va a u tilizar un módulo se debe escribir la dirección en un bus y escribir los datos en otro, por lo tanto se consumen 4 ciclos de reloj. Cuando se lee la información de igual manera hay qu e enviar una dirección y realizar una lectura, es decir, también se consumen 4 ciclos de reloj. Para las tareas de Multiplicación, con cada llamado a un solo módulo Hardware se estarían consumiendo 16 ciclos de reloj para enviar los datos a procesar y 16 ciclos de reloj para leer los resultados anteriores (ya qu e se escriben y leen gru pos de a 4); este proceso se realiza 8 veces, es decir, se consumen 256 ciclos para procesar la mitad de multiplicaciones de una DCT unidimensional ; para procesar la totalidad de multiplicaciones de la DCT unidimensional se requ erirían 256 ciclos más (para utilizar el segundo multiplicador), luego para procesar todas las multiplicaciones de una DCT unidimensional , se utilizan 512 ciclos de reloj. Como la DCT unidimensional se debe realizar 2 veces, en total las tareas de multiplicación para una componente consumirían 1024 ciclos de reloj; si se extiende el mismo análisis para las 3, se halla un total de 3072 ciclos de reloj o 6144ns. Por otro lado, la cuantificación debe realizarse solo 3 veces en el procesamiento de un MCU; dado qu e al módulo se le envían 8 datos en cada llamado, se consumirían 32 ciclos de reloj para enviar 8 datos y 32 más para leer los resultados anteriores; de esta manera, al procesador utiliza 64 ciclos de reloj para el procesamiento de 1 fila. Como se deben procesar 8 filas, para la cuantificación de una componente, se consumen 512 ci cl os de rel oj, lo qu e implica qu e para las 3, se consumen 1536 ciclos o 3072ns. Los datos anteriores permiten evaluar el desempeño del sistema particionado, de acuerdo con los resultados obtenidos en las simulaciones previas y registrados en las Figuras 29 y 31 las comparaciones fu eron:

Figura 48. Tabla comparativa de rendimiento de ambas plataformas; en este caso el MicroBlaze ejecuta sus funciones sin optimización en velocidad. La aceleración más significativa se consigue en el cuantificador ya que no se utilizan funciones complejas para el redondeo.

Figura 49. Tabla comparativa de rendimiento cuando el MicroBlaze ejecuta sus funciones con optimización en velocidad y sin ciclos en las tareas de multiplicación. Para este caso el desempeño software fue superior al hardware ya que el MicroBlaze puede realizar multiplicaciones con una unidad especial hardware. Como se observa en las tablas de las Figuras 48 y 49 para ambos casos se obtiene un mejoramiento en desempeño debido principalmente a la eficacia del Cuantificador; sin embargo, cuando se optimiza tanto

Page 45: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

45

el código a ejecutar como los módulos del procesador, los resultados para las tareas de multiplicación son mejores a nivel software. Optimizar el procesador tiene un compromiso a nivel de área utilizada en el FPGA por lo cual es probable qu e con esta configuración solo se pu eda implementar un acelerador Hardware sobre el mismo chip, no obstante una implementación con un cuantificador y el MicroBlaze optimizado arrojarían el mejor desempeño posible:

Figura 50. Tabla comparativa de rendimiento para las posibles plataformas a implementar. La Plataforma más eficiente fue el MicroBlaze Optimizado con un Cuantificador Hardware.

Figura 51. Gráfico de las posibles implementaciones para una implementación física de alto rendimiento. La mejor opción es el Cuantificador con el MicroBlaze Optimizado. Por otro lado, si se omite el llamado a las funciones realizado por el bloqu e cuantificador, las tablas indicadas muestran qu e para el mejor caso, el tiempo utilizado de esta tarea se redu ce a 36760ns. Puesto qu e este es un dato más consistente con los resultados obtenidos en las estimaciones previas, se construye la tabla de la Figura 49 nu evamente para evaluar la aceleración:

Figura 51. Tabla de resultados de la aceleración lograda para la cuantificación, despreciando el llamado a las funciones floatsisf y fixfsi que este realiza. Este resultado es más coherente con lo esperado ya que la implementación software del compresor en lugar de utilizar funciones de redondeo detallado, trunca la parte decimal de la división; con este nuevo valor de consumo, la aceleración lograda es del 78.25%.

Page 46: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

46

3.9 Comparación con Arquitecturas Propuestas A nivel académico se han realizado di ferentes aproximaciones al algoritmo de compresión JPEG; algunas de ellas realizan estudios minuciosos de su estructura y procesos internos, buscando proponer arquitecturas eficientes qu e soporten la validez de los análisis previamente realizados, mientras que otros solo hacen comentarios alusivos a la posibilidad de implementar teorías y criterios de diseño en el . En esta sección se presentarán algunos de los estu dios encontrados en lo referente a particionamientos Hardware-Software del algoritmo en cuestión.

El documento titulado Hardware-Software Partitioning and Pipeline d Sche duling of Transformative Applications, se realizan consideraciones de algoritmos de al to paralelismo y pocos protocolos de control que facili tan la identificación de hilos de procesamiento independientes sintetizables a nivel hardware; no obstante, el objeto de este estudio no es realizar particionamientos Hardware-Software sino implementar procesadores software y procesadores hardware con etapas de pipe lining de alto rendimiento para llegar a un desempeño tan bueno como el de una arquitectura particionada. Esta teoría parte también de un grafo de tareas qu e para el caso del JPEG es el qu e se presenta a continuación:

Figura 52. Grafo de Tareas JPEG propuesto en este documento; los bloques de procesamiento son de 4x4 ya que solo se busca realizar una aproximación de la metodología propuesta con un ejemplo.

Con este grafo se plantean diferentes algoritmos que son capaces de determinar cuáles tareas deben ser implementadas en el procesador software, y cuáles en el procesador hardware con etapas de pipe lining. En general se mu estran comparaciones entre velocidad y área de las posibles asignaciones de tareas pero no se ejemplifica qu é grado de aceleración logra tener el proceso mostrado.

De este estu dio se pu ede apreciar qu e la constru cción del grafo se hace con una granuralidad mediana ya qu e las tareas 2 –9, que constituyen la DCT, no se definen en su totalidad por lo qu e, con conocimiento del algoritmo, cada una de ellas debe a lo sumo realizar una resta por cada multiplicación qu e complete. Sin embargo, dado que se proponen procesadores con estru cturas de pipe lining pu ede qu e el grafo sea el más apropiado para explotar estas funcionalidades.

Otra fu ente consultada fu e el artículo llamado Hardware-Software codesign of Re source Constrained Syste ms on a Chip, en donde se citan las diferentes metodologías de codiseño propuestas y además se propone una nu eva qu e realiza di ferentes análisis de interconexiones entre módulos y procesadores, para encontrar un diseño óptimo y veloz. También se realiza una propuesta de grafo de tareas para el JPEG:

Page 47: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

47

Figura 53. Grafo de Tareas JPEG propuesto; se presenta una estructura más parecida al grafo planteado en este trabajo ya que se realizan subdivisiones más detalladas de la DCT.

En este documento se realizan estimativos de desempeño basados en las subdivisiones propuestas; se proponen 3 módulos básicos: Procesadores de Propósito General (GPP), Sumadores (A ) y Multiplicadores (M). En la tabla mostrada a continuación, se puede apreciar la aceleración del proceso para diferentes configuraciones.

Figura 54. Tabla de rendimientos y optimización de tiempos de ejecución con varios módulos HW y GPP’s.

Con la tabla se pudo apreciar una mejoría máxima de 27.84%; sin embargo se utilizaron 3 procesadores para lograr esta meta; la referencia de estos es Microprocesadores TSMC de 0,18u y 5x5mm2. A pesar de presentar una mejoría considerable, este tipo de diseños se prestan para teorías más complejas como los MPSoC’s y no tanto para el codiseño Hardware-Software.

Otra aproximación académica de codiseño con el JPEG, fu e un proyecto ope n core en donde se

desarrolló una librería de un códec JPEG completamente sintetizable en FPGA ’s con un el soft-processor MicroBlaze. En esta implementación no se muestran estudios de particionamientos sino se mu estra la arquitectura general del codificador con sus módulos hardware. De igual manera que en los resultados obtenidos en este trabajo, la arquitectura propu esta utiliza los buses FSL para conectar los 3 aceleradores: DCT, Codificación Huffman y Conversor de espacio de color en caso de ser necesario. N o se presentan datos en cuanto a la eficiencia y mejoramiento de la compresión, sin embargo se bosqueja un diagrama general de los módulos qu e se muestra en la Figura xx.

Page 48: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

48

Figura 55. Bosquejo general de la arquitectura final de este core.

Finalmente, se encontró un artículo denominado A FPGA-based S oft Multiprocessor S yste m for

JPEG Compression, en el cual se u tiliza una Virtex-II Pro para realizar el montaje de un compresor u tilizando 4 procesadores MicroBlaze en diferentes configuraciones, dependiendo de cómo se realiza la interconexión entre los diversos procesadores (por Bus, por FIFO, Memorias de doble pu erto o DMA ’s). A demás se presentan dos configuraciones para cada tipo de conexión: una hardware y otra software, en la hardware los procesadores se conectan con todos los demás al mismo tiempo, y en la software se conectan en cascada (aunque cada uno opera por separado). La división de tareas se realiza por cada uno de los pasos del algoritmo:

Figura 56. Distribución de tareas en cada uno de los procesadores para la implementación del códec. Las funciones de Cuantificación y Codificación se trabajan en un módulo mientras la DCT se ejecuta en otro.

La configuración de mejor desempeño fue utilizando una mezcla de FIFO y DMA , sin embargo el trabajo concluye qu e el principal inconveniente es que el diseño del DMA para su correcta operación es bastante complejo.

Figura 57. Diagrama de la arquitectura más eficiente aunque la más compleja; los módulos DMA requieren un

diseño detallado y preciso.

Page 49: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

49

4 Conclusiones Fu e posible validar la metodología propu esta con un caso de estudio versátil como el compresor JPEG y además verificar su funcionalidad, efectividad y aplicabilidad; además, demostró ser un proceso robusto pu es su estructura tiene en cu enta las necesidades qu e se van presentando conforme se avanza en cada etapa hasta llegar a instancias finales. Se identificaron herramientas qu e permitieron desarrollar descripciones en los diferentes niveles (funcional , estructural , algorítmico, etc) qu e se van abarcando con el avance en el proceso; aunqu e no se utilizó la totalidad de las mismas, se pudo hacer un listado de las más relevantes: lenguajes C, SystemC, V HDL y los grafos de tareas. Con el estudio e implementación de esta nu eva metodología de codiseño se pu do conocer, entender y apropiar la gran variedad de opciones qu e se tienen en el momento de planear la constru cción de un sistema digital sin limitarse a la adopción de plataformas netamente software o hardware por separado; fu e posible evaluar y manejar nuevas herramientas CA D durante todo el proceso de diseño. Es fundamental la inclusión de nuevas teorías como el codiseño Hardware-Software, MPSoC’s, Hardware Reconfigurable, Sistemas Embebidos y soft-processors entre otros, en los cursos propu estos por la Universidad ya qu e constituyen una amplia fu ente de información y progreso en la constru cción de sistemas novedosos y eficientes en Ingeniería Electrónica. Se requiere la implementación de más casos de estu dio qu e permitan valorar con objetividad este tipo de ejercicios y además faciliten la construcción de un registro de proyectos en donde se fomente el avance y el acceso a la información en este campo. A pesar de la existencia de diversos casos de estu dio de codiseño con el JPEG, se encontró qu e cada uno le da un enfoqu e diferente y pretende abarcar la mayor cantidad de variables y limitantes existentes, para proponer una solución basada en componentes Hardware y Software qu e no siempre sigu en un estudio concienzu do para su particionamiento. Una de las metas logradas en este proyecto fue qu e se tuvieron siempre bases concretas para la toma de decisiones a lo largo del trabajo. El proceso de diseño toma un tiempo considerable siguiendo la metodología tal como se propuso; a pesar de qu e se pu dieron obtener bu enos resul tados y aceleraciones, en la arquitectura final , el consumo de tiempo fue significativo y es una variable a tener en cu enta para fu turas implementaciones.

Page 50: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

50

5 Perspectivas Como se pudo observar una parte de la metodología implementada no pu do concluirse por cuestiones de tiempo: la co-simulación, integración y verificación del sistema completo. Los anteriores constituyen un paso fundamental para la validación del trabajo efectuado ya qu e permite evaluarlo en tiempo real con ejemplos concretos. A futuro qu eda planteado el desarrollo de estas etapas finales para así poder retroalimentar el trabajo concluido y tener la oportunidad de compararlo con otras propu estas a nivel académico; con una implementación física, se abre la posibilidad de realizar apreciaciones en calidad de imagen, factores de compresión, tiempo empleado y versatilidad del diseño.

Page 51: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

51

6 Referencias [1] García Lorena y Sánchez Oscar. “Metodología de Co-diseño Hardware/Software. Curso Tu torial”. Universidad de los Andes. [2] S.Pillement, L.Torres, M.Robert y G.Cambon. “Fast Prototyping: A Case Stu dy the JPEG Compression Algorithm”. Université de Montpellier. [3] Nattawu t Thepayasuwan y Alex Doboli . “Hardware-Software Codesign of Resource Constrained Systems on a Chip”. State Universi ty of N ew Y ork at Stony Brook. [4] Björn Jonsson. “A JPEG Encoder in System C. Master’s Thesis”. Lulea Unversity of Technology. [5] Cai Lukai , Olivarez Mike, Kritzinger Paul, Gajski Dan. “C/C++ Based System Design Flow Using SpecC, V CC and SystemC”. Universi ty of California. Junio 14,2002. [6] S.Stuijk. “Design and Implementation of a JPEG Decoder”. Eidhoven University of Technology. Diciembre 2001 [7] ITU, CCITT. JPEG Standard [8] García Rozo Antonio, Gu errero Hurtado Mauricio, Cortés Luis Alejandro. “Sistemas Digitales, Elementos para un diseño a Alto Nivel. Capítulo III: Codiseño Hardware-Software”. Bogotá, Febrero de 1999. [9] http://pu b.ufasta.edu .ar/SISD/jpeg/jpg.htm [10] “JPEG Baseline Sequ ential Syntax Overview”. National Taiwan University . [11] http://www.des.udc.es/~adriana/Peri fericos/Trabajos2006/Trabajo1_jpeg_apuntes.pdf

Page 52: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

52

7 Anexos

Código en C del Codificador int main(){ char YUV[3][8]; float Ydct[8][8],Udct[8][8],Vdct[8][8]; float Ydct1[8][8],Udct1[8][8],Vdct1[8][8]; float vector[8]; int orden[64],blocks,dim; unsigned int dato_btw[2]; int DCPREV_Y=0; int DCPREV_U=0; int DCPREV_V=0; struct bgr_data pixel; short i,j,k,BTW,run; unsigned char remainder[2],dato[4]; FILE *JPEG; FILE *fileptr1; unsigned short size[2],A; if((fileptr1 = fopen("test.bmp","rb"))==NULL || (JPEG=fopen("Image.jpg","wb"))==NULL){ return 0; } else{ RGB_Header(fileptr1,size); JPEG_Header(JPEG,size); } dim=(size[0]*size[1])/64; for(blocks=0;blocks<dim;blocks++) { for(j=0;j<8;j++){ for(i=0;i<8;i++){ YUV[0][i]=Tarea1_Y(pixel); YUV[1][i]=Tarea2_U(pixel.B,YUV[0][i]); YUV[2][i]=Tarea3_V(pixel.R,YUV[0][i]); } for(k=0;k<3;k++){ Tarea4_Restar(vector,YUV,k); Tarea5_Sumar(vector,YUV,k); if(k==0){ Tarea6_MultiplicarM1(vector,Ydct,j); Tarea7_MultiplicarM2(vector,Ydct,j); } else if (k==1){ Tarea6_MultiplicarM1(vector,Udct,j); Tarea7_MultiplicarM2(vector,Udct,j); } else{ Tarea6_MultiplicarM1(vector,Vdct,j); Tarea7_MultiplicarM2(vector,Vdct,j); } } } for(j=0;j<8;j++){ for(k=0;k<3;k++){ if(k==0){ Tarea4P_Restar(vector,Ydct,j); Tarea5P_Sumar(vector,Ydct,j); Tarea6_MultiplicarM1(vector,Ydct1,j); Tarea7_MultiplicarM2(vector,Ydct1,j); } else if(k==1){ Tarea4P_Restar(vector,Udct,j); Tarea5P_Sumar(vector,Udct,j); Tarea6_MultiplicarM1(vector,Udct1,j);

Page 53: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

53

Tarea7_MultiplicarM2(vector,Udct1,j); } else{ Tarea4P_Restar(vector,Vdct,j); Tarea5P_Sumar(vector,Vdct,j); Tarea6_MultiplicarM1(vector,Vdct1,j); Tarea7_MultiplicarM2(vector,Vdct1,j); } } } Tarea8_Cuantizar(Ydct1,1); Tarea8_Cuantizar(Udct1,2); Tarea8_Cuantizar(Vdct1,2); for(k=0;k<3;k++){ if(k==0){ Tarea9_ZigZag(Ydct1,orden); orden[0]=orden[0]-DCPREV_Y; DCPREV_Y=Ydct[0][0]; } else if(k==1){ Tarea9_ZigZag(Udct1,orden); orden[0]=orden[0]-DCPREV_U; DCPREV_U=Udct[0][0]; } else{ Tarea9_ZigZag(Vdct1,orden); orden[0]=orden[0]-DCPREV_V; DCPREV_V=Vdct[0][0]; } Tarea10_Representar(orden[0],dato_btw); Tarea11_HuffmanDC(dato_btw,k); BTW=Tarea13_Escribir(JPEG,dato_btw,rema inder,BTW); for(i=1;i<64;i++){ if(orden[i]==0){ run+=1; if(i==64){ run=0; Tarea10_Representar(orden[i],dato_btw); Tarea12_HuffmanAC(dato_btw,run,k); BTW=Tarea13_Escribir(JPEG,dato_btw,remainder,BTW); } } else{ while(run>15){ run-=16; dato_btw[0]=0; dato_btw[1]=0; Tarea12_HuffmanAC(dato_btw,15,k); BTW=Tarea13_Escribir(JPEG,dato_btw,rema inder,BTW); } Tarea10_Representar(orden[i],dato_btw); Tarea12_HuffmanAC(dato_btw,run,k); BTW=Tarea13_Escribir(JPEG,dato_btw,remainder,BTW); run=0; } } } } return 0; } void RGB_Header(FILE* fileptr1, unsigned short size[2]){ struct BMP_header HEADER; char width[4], height[4]; fread(&HEADER,sizeof(struct BMP_header),1,fileptr1); printf(" \n\n\n ***** Primary BMP file opened ***** \n\n\n"); size[0] = Hexa_To_Decimal(HEADER.INFO[16],HEADER.INFO[17],HEADER.INFO[18],HEADER.INFO[ 19]); size[1] = Hexa_To_Decimal(HEADER.INFO[20],HEADER.INFO[21],HEADER.INFO[ 22],HEAD ER.INFO[23]); printf(" ***** Image resolution is %u x %u ***** \n",size[0],size[1]); return; }

Page 54: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

54

void JPEG_Header(FILE* JPEG, unsigned short size[2]){ unsigned char marker[2],Remainder1[1]; unsigned short hsize; hsize=size[0]; marker[0]=0xff; marker[1]=0xd8; fprintf(JPEG,"%c%c",marker[0],marker[1]); marker[1]=0xdb; fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0x43,0x00); fwrite(&Quant_Luminance,sizeof(Quant_Luminance),1,JPEG); fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0x43,0x01); fwrite(&Quant_Chrominance,sizeof(Quant_Chrominance),1,JPEG); marker[1]=0xc0; fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0x11,0x08); hsize=size[1]; hsize>>=8; fprintf(JPEG,"%c%c",hsize,size[1]); hsize=size[0]; hsize>>=8; fprintf(JPEG,"%c",hsize,size[0]); fprintf(JPEG,"%c%c%c%c%c%c%c%c%c%c",0x03,0x01,0x11,0x00,0x0 2,0x11,0x01,0x0 3,0x11,0x01); marker[1]=0xc4; fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0x1f,0x00); fwrite(&Huff_LuminanceDC,sizeof(Huff_LuminanceDC),1,JPEG); fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0xb5,0x10); fwrite(&Huff_LuminanceAC,sizeof(Huff_LuminanceAC),1,JPEG); fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0x1f,0x01); fwrite(&Huff_ChrominanceDC,sizeof(Huff_ChrominanceDC),1,JPEG); fprintf(JPEG,"%c%c%c%c%c",marker[0],marker[ 1],0x00,0xb5,0x11); fwrite(&Huff_ChrominanceAC,sizeof(Huff_ChrominanceAC),1,JPEG); marker[1]=0xda; fprintf(JPEG,"%c%c%c%c%c%c%c%c%c%c%c%c",marker[0],marke r[1],0x00,0x0c,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00); return; } char Tarea1_Y(struct bgr_data pixel){ return 0.257*pixel.R + 0.504*pixel.G + 0.098*pixel.B - 112;} char Tarea2_U(unsigned char pixel, char Y){ return 0.492*(pixel - Y)-128;} char Tarea3_V(unsigned char pixel, char Y){ return 0.877*(pixel - Y)-128;} void Tarea4_Restar(float vector[8],char col[3][8],short k){ vector[1]= col[k][0]-col[k][7]; vector[3]= col[k][1]-col[k][6]; vector[5]= col[k][2]-col[k][ 5]; vector[7]= col[k][3]-col[k][4]; return;} void Tarea5_Sumar(float vector[8],char col[3][8],short k){ vector[0]= col[k][0]+col[k][7]; vector[2]= col[k][1]+col[ k][6]; vector[4]= col[k][2]+col[k][5]; vector[6]= col[k][3]+col[k][4]; return;} void Tarea6_MultiplicarM1(float vector[8], float Matrix[8][8],short j) { float c1,c2; c1 = vector[0]+ vector[6]; c2 = vector[2]+ vector[4]; Matrix[j][0]= (c1+c2)*0.3535; Matrix[j][4]= (c1-c2)*0.3535; c1 = vector[0]- vector[6]; c2 = vector[2]- vector[4]; Matrix[j][2]= c1*0.4619 + c2*1913; Matrix[j][6]= c1*0.1913 + c2*0.4619;

Page 55: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

55

return; } void Tarea7_MultiplicarM2(float vector[8], float Matrix[8][8],short j){ short k,m; for(k=0;k<4;k++){ Matrix[j][2*k+1]=0; for(m=0;m<4;m++){ Matrix[j][2*k+1] = vector[ 2*m+1]*DCT2[ k][m]+ Matrix[j][2* k+1]; } } return; } void Tarea4P_Restar(float vector[8],float col[8][8],short k){ vector[1]= col[0][k]-col[7][k]; vector[3]= col[1][k]-col[6][k]; vector[5]= col[2][k]-col[5][ k]; vector[7]= col[3][k]-col[4][k]; return; } void Tarea5P_Sumar(float vector[8],float col[8][8],short k) { vector[0]= col[0][k]+col[7][k]; vector[2]= col[1][k]+col[6][k]; vector[4]= col[2][k]+col[5][k]; vector[6]= col[3][k]+col[4][k]; return; } void Tarea8_Cuantizar(float dct_data[8][8], short type){ short i,j,tmp; if(type==1){ for(i=0;i<8;i++){ for(j=0;j<8;j++){ dct_data[i][j]= dct_data[i][j]/Quant_Luminance[i*8+j]; tmp=dct_data[i][j]; dct_data[i][j]=tmp; } } } else{ for(i=0;i<8;i++){ for(j=0;j<8;j++){ dct_data[i][j]= dct_data[i][j]/Quant_Chrominance[i*8+j]; tmp=dct_data[i][j]; dct_data[i][j]=tmp; } } } return;} void Tarea9_ZigZag(float dct_data[8][8],int orden[64]){ short i,j; int dctTemp[64]; for(i=0;i<8;i++){ for(j=0;j<8;j++){ dctTemp[i*8+j]=dct_data[i][j];}} for(j=0;j<64;j++){ orden[Matrix_order[j]]=dctTemp[j];} return;} void Tarea10_Representar(int lenght, unsigned int dato_btw[2]){ short n=0; int tmp,i; tmp=1; if(lenght<0){lenght=-1*lenght; n=1;} else{dato_btw[0]=lenght; n=0;} if(lenght==0){dato_btw[1]=0;} else if(lenght==1){ dato_btw[1]=1; } else if(lenght>1 && lenght<4){ dato_btw[1]=2;} else if(lenght>3 && lenght<8){ dato_btw[1]=3;} else if(lenght>7 && lenght<16){ dato_btw[1]=4;} else if(lenght>15 && lenght<32){ dato_btw[1]=5;} else if(lenght>31 && lenght<64){ dato_btw[1]=6;}

Page 56: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

56

else if(lenght>63 && lenght<128){ dato_btw[1]=7;} else if(lenght>127 && lenght<256){ dato_btw[1]=8;} else if(lenght>255 && lenght<512){ dato_btw[1]=9;} else{dato_btw[1]=10;} if(n==1){ for(i=0;i<dato_btw[1];i++){ tmp=tmp*2; } tmp-=1; dato_btw[0]=tmp; lenght=~lenght; dato_btw[0]&=lenght;} else{dato_btw[0]=lenght;} return;} void Tarea11_HuffmanDC(unsigned int dato_btw[2], short type){ int dc; unsigned int temp; temp=dato_btw[1]; if(type==1){ switch(temp){ case 0: dc=0x0; dato_btw[1]=2; break; case 1: dc=0x2; dato_btw[1]+=3; break; case 2: dc=0x3; dato_btw[1]+=3; break; case 3: dc=0x4; dato_btw[1]+=3; break; case 4: dc=0x5; dato_btw[1]+=3; break; case 5: dc=0x6; dato_btw[1]+=3; break; case 6: dc=0xe; dato_btw[1]+=4; break; case 7: dc=0x1e; dato_btw[1]+=5; break; case 8: dc=0x3e; dato_btw[1]+=6; break; case 9: dc=0x7e; dato_btw[1]+=7; break; case 10: dc=0xfe; dato_btw[1]+=8; break; case 11: dc=0x1fe; dato_btw[1]+=9; break;}} else{ switch(temp){ case 0: dc=0x0; dato_btw[1]=2; break; case 1: dc=0x1; dato_btw[1]+=2; break; case 2: dc=0x2; dato_btw[1]+=2; break; case 3: dc=0x6; dato_btw[1]+=3; break; case 4: dc=0xe; dato_btw[1]+=4; break; case 5: dc=0x1e; dato_btw[1]+=5; break; case 6: dc=0x3e; dato_btw[1]+=6; break; case 7: dc=0x7e; dato_btw[1]+=7; break; case 8: dc=0xfe; dato_btw[1]+=8; break; case 9: dc=0x1fe; dato_btw[1]+=9; break; case 10: dc=0x3fe; dato_btw[1]+=10; break; case 11: dc=0x7fe; dato_btw[1]+=11; break;}} dc<<=temp; dato_btw[0]+=dc; return;} void Tarea12_HuffmanAC(unsigned int dato_btw[2], short run, short type){ int ac,btwac; int size; size=dato_btw[1]; if(type==1){ switch(run){ case 0: switch(size){ case 0: ac=Run0.c0; btwac=4; break; case 1: ac=Run0.c1; btwac=3; break; case 2: ac=Run0.c2; btwac=4; break; case 3: ac=Run0.c3; btwac=6; break; case 4: ac=Run0.c4; btwac=8; break; case 5: ac=Run0.c5; btwac=10; break; case 6: ac=Run0.c6; btwac=13; break; case 7: ac=Run0.c7; btwac=15; break; case 8: ac=Run0.c8; btwac=18; break; case 9: ac=Run0.c9; btwac=25; break; case 10: ac=Run0.c10; btwac=26; break;} break; case 1: switch(size){ case 1: ac=Run1.c1; btwac=5; break; case 2: ac=Run1.c2; btwac=7; break; case 3: ac=Run1.c3; btwac=10; break; case 4: ac=Run1.c4; btwac=13; break; case 5: ac=Run1.c5; btwac=16; break;

Page 57: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

57

case 6: ac=Run1.c6; btwac=22; break; case 7: ac=Run1.c7; btwac=23; break; case 8: ac=Run1.c8; btwac=24; break; case 9: ac=Run1.c9; btwac=25; break; case 10: ac=Run1.c10; btwac=26; break;}break; case 2: switch(size){ case 1: ac=Run2.c1; btwac=6; break; case 2: ac=Run2.c2; btwac=10; break; case 3: ac=Run2.c3; btwac=13; break; case 4: ac=Run2.c4; btwac=16; break; case 5: ac=Run2.c5; btwac=21; break; case 6: ac=Run2.c6; btwac=22; break; case 7: ac=Run2.c7; btwac=23; break; case 8: ac=Run2.c8; btwac=24; break; case 9: ac=Run2.c9; btwac=25; break; case 10: ac=Run2.c10; btwac=26; break;}break; case 3: switch(size){ case 1: ac=Run3.c1; btwac=7; break; case 2: ac=Run3.c2; btwac=11; break; case 3: ac=Run3.c3; btwac=15; break; case 4: ac=Run3.c4; btwac=20; break; case 5: ac=Run3.c5; btwac=21; break; case 6: ac=Run3.c6; btwac=22; break; case 7: ac=Run3.c7; btwac=23; break; case 8: ac=Run3.c8; btwac=24; break; case 9: ac=Run3.c9; btwac=25; break; case 10: ac=Run3.c10; btwac=26; break;}break; case 4: switch(size){ case 1: ac=Run4.c1; btwac=7; break; case 2: ac=Run4.c2; btwac=12; break; case 3: ac=Run4.c3; btwac=19; break; case 4: ac=Run4.c4; btwac=20; break; case 5: ac=Run4.c5; btwac=21; break; case 6: ac=Run4.c6; btwac=22; break; case 7: ac=Run4.c7; btwac=23; break; case 8: ac=Run4.c8; btwac=24; break; case 9: ac=Run4.c9; btwac=25; break; case 10: ac=Run4.c10; btwac=26; break;}break; case 5: switch(size){ case 1: ac=Run5.c1; btwac=8; break; case 2: ac=Run5.c2; btwac=13; break; case 3: ac=Run5.c3; btwac=19; break; case 4: ac=Run5.c4; btwac=20; break; case 5: ac=Run5.c5; btwac=21; break; case 6: ac=Run5.c6; btwac=22; break; case 7: ac=Run5.c7; btwac=23; break; case 8: ac=Run5.c8; btwac=24; break; case 9: ac=Run5.c9; btwac=25; break; case 10: ac=Run5.c10; btwac=26; break;}break; case 6: switch(size){ case 1: ac=Run6.c1; btwac=8; break; case 2: ac=Run6.c2; btwac=14; break; case 3: ac=Run6.c3; btwac=19; break; case 4: ac=Run6.c4; btwac=20; break; case 5: ac=Run6.c5; btwac=21; break; case 6: ac=Run6.c6; btwac=22; break; case 7: ac=Run6.c7; btwac=23; break; case 8: ac=Run6.c8; btwac=24; break; case 9: ac=Run6.c9; btwac=25; break; case 10: ac=Run6.c10; btwac=26; break;}break; case 7: switch(size){ case 1: ac=Run7.c1; btwac=9; break; case 2: ac=Run7.c2; btwac=14; break; case 3: ac=Run7.c3; btwac=19; break; case 4: ac=Run7.c4; btwac=20; break; case 5: ac=Run7.c5; btwac=21; break; case 6: ac=Run7.c6; btwac=22; break; case 7: ac=Run7.c7; btwac=23; break; case 8: ac=Run7.c8; btwac=24; break; case 9: ac=Run7.c9; btwac=25; break; case 10: ac=Run7.c10; btwac=26; break;}break; case 8: switch(size){ case 1: ac=Run8.c1; btwac=10; break; case 2: ac=Run8.c2; btwac=17; break; case 3: ac=Run8.c3; btwac=19; break; case 4: ac=Run8.c4; btwac=20; break; case 5: ac=Run8.c5; btwac=21; break; case 6: ac=Run8.c6; btwac=22; break; case 7: ac=Run8.c7; btwac=23; break;

Page 58: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

58

case 8: ac=Run8.c8; btwac=24; break; case 9: ac=Run8.c9; btwac=25; break; case 10: ac=Run8.c10; btwac=26; break;}break; case 9: switch(size){ case 1: ac=Run9.c1; btwac=10; break; case 2: ac=Run9.c2; btwac=18; break; case 3: ac=Run9.c3; btwac=19; break; case 4: ac=Run9.c4; btwac=20; break; case 5: ac=Run9.c5; btwac=21; break; case 6: ac=Run9.c6; btwac=22; break; case 7: ac=Run9.c7; btwac=23; break; case 8: ac=Run9.c8; btwac=24; break; case 9: ac=Run9.c9; btwac=25; break; case 10: ac=Run9.c10; btwac=26; break;}break; case 10: switch(size){ case 1: ac=Run10.c1; btwac=10; break; case 2: ac=Run10.c2; btwac=18; break; case 3: ac=Run10.c3; btwac=19; break; case 4: ac=Run10.c4; btwac=20; break; case 5: ac=Run10.c5; btwac=21; break; case 6: ac=Run10.c6; btwac=22; break; case 7: ac=Run10.c7; btwac=23; break; case 8: ac=Run10.c8; btwac=24; break; case 9: ac=Run10.c9; btwac=25; break; case 10: ac=Run10.c10; btwac=26; break;} break; case 11: switch(size){ case 1: ac=Run11.c1; btwac=11; break; case 2: ac=Run11.c2; btwac=18; break; case 3: ac=Run11.c3; btwac=19; break; case 4: ac=Run11.c4; btwac=20; break; case 5: ac=Run11.c5; btwac=21; break; case 6: ac=Run11.c6; btwac=22; break; case 7: ac=Run11.c7; btwac=23; break; case 8: ac=Run11.c8; btwac=24; break; case 9: ac=Run11.c9; btwac=25; break; case 10: ac=Run11.c10; btwac=26; break;}break; case 12:switch(size){ case 1: ac=Run12.c1; btwac=11; break; case 2: ac=Run12.c2; btwac=18; break; case 3: ac=Run12.c3; btwac=19; break; case 4: ac=Run12.c4; btwac=20; break; case 5: ac=Run12.c5; btwac=21; break; case 6: ac=Run12.c6; btwac=22; break; case 7: ac=Run12.c7; btwac=23; break; case 8: ac=Run12.c8; btwac=24; break; case 9: ac=Run12.c9; btwac=25; break; case 10: ac=Run12.c10; btwac=26; break;}break; case 13:switch(size){ case 1: ac=Run13.c1; btwac=12; break; case 2: ac=Run13.c2; btwac=18; break; case 3: ac=Run13.c3; btwac=19; break; case 4: ac=Run13.c4; btwac=20; break; case 5: ac=Run13.c5; btwac=21; break; case 6: ac=Run13.c6; btwac=22; break; case 7: ac=Run13.c7; btwac=23; break; case 8: ac=Run13.c8; btwac=24; break; case 9: ac=Run13.c9; btwac=25; break; case 10: ac=Run13.c10; btwac=26; break;}break; case 14: switch(size){ case 1: ac=Run14.c1; btwac=17; break; case 2: ac=Run14.c2; btwac=18; break; case 3: ac=Run14.c3; btwac=19; break; case 4: ac=Run14.c4; btwac=20; break; case 5: ac=Run14.c5; btwac=21; break; case 6: ac=Run14.c6; btwac=22; break; case 7: ac=Run14.c7; btwac=23; break; case 8: ac=Run14.c8; btwac=24; break; case 9: ac=Run14.c9; btwac=25; break; case 10: ac=Run14.c10; btwac=26; break;}break; case 15: switch(size){ case 0: ac=Run15.c0; btwac=11; break; case 1: ac=Run15.c1; btwac=17; break; case 2: ac=Run15.c2; btwac=18; break; case 3: ac=Run15.c3; btwac=19; break; case 4: ac=Run15.c4; btwac=20; break; case 5: ac=Run15.c5; btwac=21; break; case 6: ac=Run15.c6; btwac=22; break; case 7: ac=Run15.c7; btwac=23; break; case 8: ac=Run15.c8; btwac=24; break;

Page 59: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

59

case 9: ac=Run15.c9; btwac=25; break; case 10: ac=Run15.c10; btwac=26; break;}}} else{switch(run){case 0:switch(size){ case 0: ac=Run0C.c0; btwac=2; break; case 1: ac=Run0C.c1; btwac=3; break; case 2: ac=Run0C.c2; btwac=5; break; case 3: ac=Run0C.c3; btwac=7; break; case 4: ac=Run0C.c4; btwac=9; break; case 5: ac=Run0C.c5; btwac=10; break; case 6: ac=Run0C.c6; btwac=12; break; case 7: ac=Run0C.c7; btwac=14; break; case 8: ac=Run0C.c8; btwac=17; break; case 9: ac=Run0C.c9; btwac=19; break; case 10: ac=Run0C.c10; btwac=22; break;}break; case 1:switch(size){ case 1: ac=Run1C.c1; btwac=5; break; case 2: ac=Run1C.c2; btwac=8; break; case 3: ac=Run1C.c3; btwac=11; break; case 4: ac=Run1C.c4; btwac=13; break; case 5: ac=Run1C.c5; btwac=16; break; case 6: ac=Run1C.c6; btwac=18; break; case 7: ac=Run1C.c7; btwac=23; break; case 8: ac=Run1C.c8; btwac=24; break; case 9: ac=Run1C.c9; btwac=25; break; case 10: ac=Run1C.c10; btwac=26; break;}break; case 2:switch(size){ case 1: ac=Run2C.c1; btwac=6; break; case 2: ac=Run2C.c2; btwac=10; break; case 3: ac=Run2C.c3; btwac=13; break; case 4: ac=Run2C.c4; btwac=16; break; case 5: ac=Run2C.c5; btwac=20; break; case 6: ac=Run2C.c6; btwac=22; break; case 7: ac=Run2C.c7; btwac=23; break; case 8: ac=Run2C.c8; btwac=24; break; case 9: ac=Run2C.c9; btwac=25; break; case 10: ac=Run2C.c10; btwac=26; break;}break; case 3:switch(size){ case 1: ac=Run3C.c1; btwac=6; break; case 2: ac=Run3C.c2; btwac=10; break; case 3: ac=Run3C.c3; btwac=13; break; case 4: ac=Run3C.c4; btwac=16; break; case 5: ac=Run3C.c5; btwac=21; break; case 6: ac=Run3C.c6; btwac=22; break; case 7: ac=Run3C.c7; btwac=23; break; case 8: ac=Run3C.c8; btwac=24; break; case 9: ac=Run3C.c9; btwac=25; break; case 10: ac=Run3C.c10; btwac=26; break;}break; case 4:switch(size){ case 1: ac=Run4C.c1; btwac=7; break; case 2: ac=Run4C.c2; btwac=11; break; case 3: ac=Run4C.c3; btwac=19; break; case 4: ac=Run4C.c4; btwac=20; break; case 5: ac=Run4C.c5; btwac=21; break; case 6: ac=Run4C.c6; btwac=22; break; case 7: ac=Run4C.c7; btwac=23; break; case 8: ac=Run4C.c8; btwac=24; break; case 9: ac=Run4C.c9; btwac=25; break; case 10: ac=Run4C.c10; btwac=26; break;}break; case 5:switch(size){ case 1: ac=Run5C.c1; btwac=7; break; case 2: ac=Run5C.c2; btwac=12; break; case 3: ac=Run5C.c3; btwac=19; break; case 4: ac=Run5C.c4; btwac=20; break; case 5: ac=Run5C.c5; btwac=21; break; case 6: ac=Run5C.c6; btwac=22; break; case 7: ac=Run5C.c7; btwac=23; break; case 8: ac=Run5C.c8; btwac=24; break; case 9: ac=Run5C.c9; btwac=25; break; case 10: ac=Run5C.c10; btwac=26; break;}break; case 6:switch(size){ case 1: ac=Run6C.c1; btwac=8; break; case 2: ac=Run6C.c2; btwac=13; break; case 3: ac=Run6C.c3; btwac=19; break; case 4: ac=Run6C.c4; btwac=20; break; case 5: ac=Run6C.c5; btwac=21; break; case 6: ac=Run6C.c6; btwac=22; break; case 7: ac=Run6C.c7; btwac=23; break; case 8: ac=Run6C.c8; btwac=24; break; case 9: ac=Run6C.c9; btwac=25; break;

Page 60: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

60

case 10: ac=Run6C.c10; btwac=26; break;}break; case 7:switch(size){ case 1: ac=Run7C.c1; btwac=8; break; case 2: ac=Run7C.c2; btwac=13; break; case 3: ac=Run7C.c3; btwac=19; break; case 4: ac=Run7C.c4; btwac=20; break; case 5: ac=Run7C.c5; btwac=21; break; case 6: ac=Run7C.c6; btwac=22; break; case 7: ac=Run7C.c7; btwac=23; break; case 8: ac=Run7C.c8; btwac=24; break; case 9: ac=Run7C.c9; btwac=25; break; case 10: ac=Run7C.c10; btwac=26; break;}break; case 8:switch(size){ case 1: ac=Run8C.c1; btwac=9; break; case 2: ac=Run8C.c2; btwac=18; break; case 3: ac=Run8C.c3; btwac=19; break; case 4: ac=Run8C.c4; btwac=20; break; case 5: ac=Run8C.c5; btwac=21; break; case 6: ac=Run8C.c6; btwac=22; break; case 7: ac=Run8C.c7; btwac=23; break; case 8: ac=Run8C.c8; btwac=24; break; case 9: ac=Run8C.c9; btwac=25; break; case 10: ac=Run8C.c10; btwac=26; break;}break; case 9:switch(size){ case 1: ac=Run9C.c1; btwac=10; break; case 2: ac=Run9C.c2; btwac=18; break; case 3: ac=Run9C.c3; btwac=19; break; case 4: ac=Run9C.c4; btwac=20; break; case 5: ac=Run9C.c5; btwac=21; break; case 6: ac=Run9C.c6; btwac=22; break; case 7: ac=Run9C.c7; btwac=23; break; case 8: ac=Run9C.c8; btwac=24; break; case 9: ac=Run9C.c9; btwac=25; break; case 10: ac=Run9C.c10; btwac=26; break;}break; case 10:switch(size){ case 1: ac=Run10C.c1; btwac=10; break; case 2: ac=Run10C.c2; btwac=18; break; case 3: ac=Run10C.c3; btwac=19; break; case 4: ac=Run10C.c4; btwac=20; break; case 5: ac=Run10C.c5; btwac=21; break; case 6: ac=Run10C.c6; btwac=22; break; case 7: ac=Run10C.c7; btwac=23; break; case 8: ac=Run10C.c8; btwac=24; break; case 9: ac=Run10C.c9; btwac=25; break; case 10: ac=Run10C.c10;btwac=26; break;}break; case 11:switch(size){ case 1: ac=Run11C.c1; btwac=10; break; case 2: ac=Run11C.c2; btwac=18; break; case 3: ac=Run11C.c3; btwac=19; break; case 4: ac=Run11C.c4; btwac=20; break; case 5: ac=Run11C.c5; btwac=21; break; case 6: ac=Run11C.c6; btwac=22; break; case 7: ac=Run11C.c7; btwac=23; break; case 8: ac=Run11C.c8; btwac=24; break; case 9: ac=Run11C.c9; btwac=25; break; case 10: ac=Run11C.c10;btwac=26; break;}break; case 12:switch(size){ case 1: ac=Run12C.c1; btwac=10; break; case 2: ac=Run12C.c2; btwac=18; break; case 3: ac=Run12C.c3; btwac=19; break; case 4: ac=Run12C.c4; btwac=20; break; case 5: ac=Run12C.c5; btwac=21; break; case 6: ac=Run12C.c6; btwac=22; break; case 7: ac=Run12C.c7; btwac=23; break; case 8: ac=Run12C.c8; btwac=24; break; case 9: ac=Run12C.c9; btwac=25; break; case 10: ac=Run12C.c10;btwac=26; break;}break; case 13:switch(size){ case 1: ac=Run13C.c1; btwac=12; break; case 2: ac=Run13C.c2; btwac=18; break; case 3: ac=Run13C.c3; btwac=19; break; case 4: ac=Run13C.c4; btwac=20; break; case 5: ac=Run13C.c5; btwac=21; break; case 6: ac=Run13C.c6; btwac=22; break; case 7: ac=Run13C.c7; btwac=23; break; case 8: ac=Run13C.c8; btwac=24; break; case 9: ac=Run13C.c9; btwac=25; break; case 10: ac=Run13C.c10;btwac=26; break;}break; case 14:switch(size){ case 1: ac=Run14C.c1; btwac=15; break;

Page 61: Codificador JPEG: Caso de Estudio de Co-diseño Hardware ...

61

case 2: ac=Run14C.c2; btwac=18; break; case 3: ac=Run14C.c3; btwac=19; break; case 4: ac=Run14C.c4; btwac=20; break; case 5: ac=Run14C.c5; btwac=21; break; case 6: ac=Run14C.c6; btwac=22; break; case 7: ac=Run14C.c7; btwac=23; break; case 8: ac=Run14C.c8; btwac=24; break; case 9: ac=Run14C.c9; btwac=25; break; case 10: ac=Run14C.c10;btwac=26; break;}break; case 15:switch(size){ case 0: ac=Run15C.c0; btwac=10; break; case 1: ac=Run15C.c1; btwac=16; break; case 2: ac=Run15C.c2; btwac=18; break; case 3: ac=Run15C.c3; btwac=19; break; case 4: ac=Run15C.c4; btwac=20; break; case 5: ac=Run15C.c5; btwac=21; break; case 6: ac=Run15C.c6; btwac=22; break; case 7: ac=Run15C.c7; btwac=23; break; case 8: ac=Run15C.c8; btwac=24; break; case 9: ac=Run15C.c9; btwac=25; break; case 10: ac=Run15C.c10;btwac=26; break;}}} ac<<=size; ac=ac+dato_btw[0]; dato_btw[0]=ac; dato_btw[1]=btwac; return; } int Tarea13_Escribir(FILE* JPEG,unsigned int dato[2],unsigned char Remainder[2],short BTWrem){ unsigned int B; unsigned int j; unsigned char w1,w2,w3,w4,w5,w6,w7,w8; if(BTWrem!=0){ j=Remainder[0]; j<<=dato[1]; j=j+dato[0]; B=BTWrem+dato[1];} else{ j=dato[0]; B=dato[1]; } j<<=(32- B); w1=j; j>>=8; w2=j; j>>=8; w3=j; j>>=8; w4=j; j=0; j=w1; j<<=8; j=j+w 2; j<<=8; j=j+w3; j<<=8; j=j+w4; if(B<8){ j>>=(8-B); w1=j; Remainder[0]=w1; return B;} else{ while(B>=8){ w1=j; fprintf(JPEG,"%c",w1); if(w1==0xff){ fprintf(JPEG,"%c",0x00);} B-=8; j>>=8;} w1=j; w1>>=(8-B); Remainder[0]=w1; return B;}}