Tengo una pregunta conceptual: ¿Qué significa "alta" densidad de código? ¿Y por qué es tan importante?
Tengo una pregunta conceptual: ¿Qué significa "alta" densidad de código? ¿Y por qué es tan importante?
La densidad del código se refiere a cuántas instrucciones del microprocesador toma para realizar una acción solicitada, y cuánto espacio ocupa cada instrucción. En términos generales, cuanto menos espacio ocupa una instrucción y más trabajo por instrucción que puede hacer un microprocesador, más denso es su código.
Observo que has etiquetado tu pregunta con la etiqueta 'arm'; Puedo ilustrar la densidad del código usando instrucciones ARM.
Supongamos que desea copiar un bloque de datos de un lugar de la memoria a otro. Conceptualmente, su código de alto nivel se vería así:
void memcpy(void *dest, void *source, int count_bytes)
{
char *s, *d;
s = source; d = dest;
while(count_bytes--) { *d++ = *s++; }
}
Ahora, un compilador simple para un microprocesador simple puede convertir esto en algo como lo siguiente:
movl r0, count_bytes
movl r1, s
movl r2, d
loop: ldrb r3, [r1]
strb [r2], r3
movl r3, 1
add r1, r3
add r2, r3
sub r0, r3
cmp r0, 0
bne loop
(mi brazo está un poco oxidado, pero entiendes la idea)
Ahora este sería un compilador muy simple y un microprocesador muy simple, pero puedes ver en el ejemplo que estamos viendo 8 instrucciones por iteración del bucle (7 si movemos el '1' a otro registro y mover la carga fuera del bucle). Eso no es realmente denso en absoluto. La densidad del código también afecta el rendimiento; Si sus bucles son más largos porque el código no es denso, es posible que necesite más caché de instrucciones para mantener el bucle. Más caché significa un procesador más costoso, pero nuevamente, la decodificación de instrucciones complejas significa más transistores para descifrar la instrucción solicitada, por lo que es un problema de ingeniería clásico.
ARM es bastante agradable a este respecto. Cada instrucción puede ser condicional, la mayoría de las instrucciones pueden aumentar o disminuir el valor de los registros, y la mayoría de las instrucciones pueden actualizar opcionalmente los indicadores del procesador. En ARM y con un compilador de utilidad moderada, el mismo bucle puede tener este aspecto:
movl r0, count_bytes
movl r1, s
movl r2, d
loop: ldrb r3, [r1++]
strb [r2++], r3
subs r0, r0, 1
bne loop
Como puede ver, el bucle principal ahora es de 4 instrucciones. El código es más denso porque cada instrucción en el bucle principal hace más. Esto generalmente significa que puede hacer más con una cantidad determinada de memoria, porque se usa menos para describir cómo realizar el trabajo.
Ahora, el código ARM nativo a menudo tenía la queja de que no era muy denso; esto se debe a dos razones principales: primero, 32 bits es una instrucción terriblemente "larga", por lo que muchos de los bits parecen desperdiciarse por instrucciones más simples, y segundo, el código se hinchó debido a la naturaleza de ARM: cada instrucción es 32 bits de largo, sin excepción. Esto significa que hay una gran cantidad de valores literales de 32 bits que no puede cargar en un registro. Si quisiera cargar "0x12345678" en r0, ¿cómo puedo codificar una instrucción que no solo incluya 0x12345678, sino que también describa "cargar literal a r0"? No hay bits restantes para codificar la operación real. La instrucción literal de carga ARM es una pequeña bestia interesante, y el ensamblador ARM también debe ser un poco más inteligente que los ensambladores normales, ya que tiene que "capturar" este tipo de instrucciones y codificarlas como un valor almacenado en el archivo objeto y una indirecta. carga de esa dirección al registro solicitado.
De todos modos, para responder a estas quejas, ARM creó el modo Pulgar. En lugar de 32 bits por instrucción, la longitud de la instrucción es ahora de 16 bits para casi todas las instrucciones y de 32 bits para las ramas. Hubo algunos sacrificios con el modo Pulgar, pero en general estos sacrificios fueron fáciles de realizar, ya que el pulgar le proporcionó una mejora del 40% en la densidad del código al reducir la longitud de la instrucción.
La "densidad de código" de un conjunto de instrucciones es una medida de la cantidad de cosas que puede obtener en una cantidad determinada de memoria de programa o cuántos bytes de memoria de programa necesita para almacenar una cantidad determinada de funcionalidad.
Como señaló Andrew Kohlsmith, incluso en la misma MCU, diferentes compiladores pueden obtener una densidad de código diferente.
Podrías disfrutar leyendo "Insectos del mundo informático" por Miro Samek, que compara una variedad de MCUs.
Lea otras preguntas en las etiquetas microcontroller arm software