Notas
Notas
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Sistemas de Numeración
Arquitectura de Computadoras
(Versión 4.4 - 2024)
Arquitectura de Computadoras Notas de Teórico
1 SISTEMAS DE NUMERACIÓN
1.1 Introducción
No por sencillo el tema deja de ser importante pues nos permite comenzar a
acostumbrarnos a los sistemas de numeración utilizados en computación, especialmente el
binario y el hexadecimal, tarea no trivial si tenemos en cuenta el "lastre" que significan años
y años de práctica con el sistema decimal exclusivamente.
Dentro de los sistemas posicionales están incluidos los que serán objeto de nuestro
estudio: los sistemas con base.
La base es igual a la cantidad de símbolos del sistema. Notando que los dígitos son
la representación en el sistema de los números enteros menores que la base, tenemos que
se cumple la condición b ai 0.
La base del sistema en el que está representado un número se suele indicar con un
subíndice al final del número y en los casos particulares de base 2 (binario), base 8 (octal),
base 16 (hexadecimal) con un subfijo con las letras b, o (ó q) y h respectivamente. En el
caso de base 16 también se utiliza el prefijo 0x. Si no se indica nada se asume base 10.
Ejemplos:
1011.11(2 = 1011.11b = 1.23 + 0.22 + 1.21 + 1.20 + 1.2-1 + 1.2-2 = 11.75 (decimal)
Caso A:
Conversión de una base B a una base b usando la aritmética de la base b (muy útil
para pasar de cualquier base a la base 10).
Caso B:
Conversión de una base B a una base b usando la aritmética de la base B (muy útil
para pasar de base 10 a cualquier base)
Previamente notemos que cualquier número N se puede expresar como:
donde se repite la división entera entre b hasta llegar a un Nn menor que b (la
próxima división daría cociente 0).
Por lo que los valores a0 . . . an son los restos de las divisiones de N entre b realizadas
en la aritmética de la base B.
653 = 1010001101b
653 = 10103(5
Los ejemplos vistos son siempre de decimal a otra base; si quisiéramos pasar desde
una base b1 (b1 <> 10) a la base b2 existe la posibilidad de hacer las operaciones con la
base b1 o, por simplicidad, cambiar primero a base 10 y luego de esta a la base b2.
Sea un número N = Ne + Nf = an bn +...+ a1 b + a0 + a-1 b-1 + ... donde Ne y Nf son la
parte entera y la parte fraccionaria respectivamente. La parte fraccionaria sigue siempre a la
parte entera en cualquier base. Por lo tanto Ne puede convertirse igual que antes y Nf se
convierte por separado
Caso A:
Conversión de base B a una base b usando la aritmética de la base b (muy útil para
pasar de cualquier base a base 10 )
1
El valor numérico para x será:
8
Caso B:
Conversión de una base B a una base b operando con la aritmética de la B (lo que la
hace muy útil para pasar de base 10 a cualquier base)
Para determinar los coeficientes a-1, a-2, etc. para la base b se observa que cada uno
de tales coeficientes es, en si mismo un entero.
La base 8 (octal) y la base 16 (hexadecimal) tienen una íntima relación con la base
2. Puesto que 8 = 23 cada dígito octal corresponde a 3 dígitos binarios. El procedimiento
entonces para convertir un número binario en número octal es dividir en grupos de 3 bits a
partir del punto binario y asignando el dígito octal correspondiente a cada grupo.
11
001010
011.111
110011
3123.7630 (8
3 1 2 3 7 6 3
7328 es
78 = 111b
38 = 011b => 7328 = 111011010b
28 = 010b
Ejemplo :
1101
10111000
0110.1010
0011 0DB86.A3h
D B 8 6 A 3
0000 0 1000 8
0001 1 1001 9
0010 2 1010 A
0011 3 1011 B
0100 4 1100 C
0101 5 1101 D
0110 6 1110 E
0111 7 1111 F
Tabla 1 - Conversión binario hexadecimal.
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Códigos y Errores
Arquitectura de Computadoras
(Versión 4.3b - 2016)
2 CODIGOS Y ERRORES
2.1 Introducción
Los distintos tipos de datos se construyen en base a estructuras de bits, los cuales
serán en general “tiras” (sucesión ordenada de bits) de n elementos que reciben el nombre
de palabra de largo n. En el caso particular de n = 8 la tira se denomina byte.
Por lo anterior resulta que los distintos tipos de datos se representan a través de
códigos binarios. Es decir existe un proceso de codificación de los objetos de información
en función de otros (las estructuras de bits) con los que se trabajará en realidad.
Conviene alertar que el término “código” se usa indistintamente para referirse tanto a
un código binario particular (la respresentación de un objeto), como a un sistema de
codificación. Que sea una u otra acepción dependerá del contexto.
No nos referiremos aquí a errores en la codificación de los objetos sino a los que
aparecen cuando se manipula con ellos. Usualmente los objetos de información se
almacenan y/o se transmiten. Estas dos operaciones comunes se realizan, en definitiva,
utilizando medios físicos (memorias, discos, canales de comunicación, etc.) los cuales no
están libres de errores. Por tanto es de particular interés el estudio de la posibilidad de
detectar o corregir errores en códigos binarios. De esta manera nos aseguraríamos que un
dato recuperado de una unidad de almacenamiento es correcto (coincide con el
almacenado) o que un dato recibido por un canal de comunicaciones lo es (coincide con el
enviado por el emisor).
Esta afirmación quedará más clara cuando veamos las distintas estrategias
utilizadas. De todas formas un ejemplo puede ser de utilidad: supongamos que tenemos 16
objetos a representar; en principio, con un código binario de 4 bits alcanzaría (2 4 = 16), pero
con 4 bits no estaríamos en condiciones de detectar errores puesto que todos los valores
posibles del código binario utilizado corresponderían a objetos válidos. De esta manera si,
por ejemplo, hubiera un error en un bit del código que representa a un objeto A se
transformaría en el código que representa a un objeto B por lo que no habría posibilidad de
detectarlo.
2.3 Distancia
la distancia entre ellos está dada por la cantidad de unos en el código formado por:
01101
10110
La "distancia" tal cual la hemos definido tiene las siguientes propiedades (que no
vamos a demostrar):
1) d(a,b) = d(b,a)
2) d(a,b) = 0 si y sólo si a = b
3) d(a,b) + d(b,c) d(a,c)
d e
t
A B
e<d
d
e<
2
Por ejemplo para poder corregir errores de hasta un bit, hay que utilizar un código de
distancia 3 por lo menos.
2p p + k + 1
El razonamiento detrás de esta afirmación es que para poder identificar el bit que
tiene error dipondremos de 2p combinaciones posibles, generadas por los p bits. Con esas
combinaciones debemos poder señalar cual es el bit errado de los p + k bits que tendrá el
código completo (el original más los bits de redundancia agregados). Además precisaremos
tener una combinación para indicar que no hay error y de ahí surge que el lado derecho de
la expresión es p + k + 1.
25 = 32 5 + 16 + 1 = 22
La siguiente tabla muestra los valores de p (bits agregados) para distintos valores de
k (bits del código original).
k p
4 3
8 4
16 5
32 6
64 7
128 8
2.5 Paridad
La idea es agregar a cada código binario de n bits que representan objetos válidos,
un nuevo bit calculado en función de los restantes. La forma en que se calcula el bit de
redundancia (de paridad) es tal que la cantidad de unos en el código completo (original + bit
de paridad) sea par (en cuyo caso hablamos de paridad par) o impar (en cuyo caso se
trata de paridad impar).
P = b0 b1 . . . bn (paridad par)
ó
P = ( b0 b1 . . . bn )’ (paridad impar)
P b0 b1 . . . bn
a0 a1 a2 a3 a4 a5 a6 a7 ah
b0 b1 b2 b3 b4 b5 b6 b7 bh
.............
.............
v0 v1 v 2 v3 v4 v5 v6 v7 vh
ah = a0 a1 . . . a7 (idem para b, c, d, e, f, g, h)
vi = ai bi . . . hi ( i= 0, 1, 2, 3, 4, 5, 6, 7, h)
2.6 2 de 5
Los sistemas de codificación con capacidad de manejar los errores pueden ser
construidos a partir de un sistema de codificación que no tenga esa capacidad (como es el
caso de la “paridad” ya visto) o pueden contruirse desde el comienzo con una distancia
mayor o igual a 2 de forma que tengan incoporada la caractaerística desde el comienzo.
Un ejemplo de esta segunda categoría es el código " 2 de 5", el cuál puede tener la
forma:
01100 - 0
11000 - 1
10100 - 2
10010 - 3
10001 - 4
01010 - 5
01001 - 6
00110 - 7
00101 - 8
00011 - 9
Como vemos este código tiene distancia 2 ya que todos los elementos del código
difieren por lo menos en 2 bits (ej: 11000 y 10100). De los 32 posibles objetos que permiten
representar 5 bits, este código permite representar tan solo 10 objetos.
Notar que luego de la secuencia de inicio fina oscura, fina clara, fina oscura,
fina clara, vienen las siguientes barras oscuras: AfffA, intercaladas con las siguientes
barras claras: fAffA. Esto es porque se toman los dos primeros dígitos (12) y se
representa al 1 con las barras oscuras y al 2 con las claras intercalando oscuras con
claras.
Los códigos de Hamming son una forma práctica de generar códigos de distancia 3.
Los veremos a través de un ejemplo en concreto. Supongamos que tenemos 16 objetos
representados, en principio, en binario:
a4 a3 a2 a1
+ 1 = 8)
p3 p2 p1
a4 a3 a2 p3 a1 p2 p1
p1 = a4 a2 a1
p2 = a4 a3 a1
p3 = a4 a3 a2
podemos al recuperar el código calcular los bits "s" que están vinculados, al igual
que los "p" a la posición de los distintos bits en el código:
a4 a3 a2 p3 a1 p2 p1
S0 x x x x
S1 x x x x
S2 x x x x
s0 = p1 a4 a2 a1
s1 = p2 a4 a3 a1
s2 = p3 a4 a3 a2
S = S2 S1 S0
Si al calcular "S" se da que es cero no hay errores (por lo menos para nuestro
sistema de codificación). Si " S" da distinto de 0, el número que de me indica el bit que está
errado (siendo el 1 el de más a la derecha, o sea p 1). De esta manera es posible reconstruir
el valor correcto del código, cambiando el bit que identificamos como corrupto (si está en 0
lo pasamos a 1 y viceversa).
Como fue mencionado los sistemas de detección por paridad son aptos para
trabajar en la hipótesis que la falla de un bit es un suceso probabilísticamente independiente
de la falla de un bit "vecino". Los códigos de Hamming también se apoyan en esta hipótesis
para asegurar eficacia en la detección y corrección del error de un bit.
Esta hipótesis se cumple muy bien en dispositivos como ser las memorias de las
computadoras (RAM). Sin embargo en los sistemas de almacenamiento masivo en base a
discos magnéticos u ópticos, o en sistemas de transmisión serie, la hipótesis no es cierta y
por tanto estos mecanismos de manejo de errores no son del todo efectivos.
Para estos casos se utilizan otros métodos, diseñados para ser capaces de manejar
errores múltiples ó "errores en ráfaga" (un error en ráfaga significa que fallan varios bits
contiguos en forma simultánea).
01001000
+01101111
+01101100
+01100001
+00100001
+00100001
---------------
111000110 que si nos quedamos con los 8 bits menos significativos es: 11000110
Si bien es simple de implementar no es muy efectivo (es fácil ver que hay
combinaciones de bits erróneos que computan el mismo “checksum”).
Es sencillo comprobar que T(x) es divisible por G(x). T(x) es el polinomio que se
transmite (o almacena). En realidad los que se transmiten (o almacenan) son los bits
coeficientes de T(x). Notemos que los primeros m bits de T(x) son los mismos que M(x), ya
que R(x) es a lo sumo de grado r-1 y por tanto no afecta ninguno de los coeficientes de
xrM(x). R(x) por tener grado r-1 agrega entonces r coeficientes (bits) al mensaje
representado por T(x) y es, en definitiva, el CRC del mensaje original M(x).
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Arquitectura de Computadoras
(Versión 4.3c - 2016)
Arquitectura del Computador 1 Notas de Teórico
3.1 Introducción
3.2.1 Introducción
De los 128 valores posibles del código (7 bits) 10 se utilizan para los dígitos
decimales (del 30h al 39h), 26 para las letras mayúsculas (del 41h al 5Ah), 26 para letras
minúsculas (del 61h al 7Ah), 34 para símbolos especiales (espacio, !, #,$,%,/,&,+,-,*, etc.) y
los 32 primeros se denominan genéricamente "caracteres de control" y se utilizan
básicamente en la comunicación de datos y con fines de dar formato a los textos en
impresoras y pantallas de video.
Algunos de estos caracteres de control son:
00h NUL (Null) Es la ausencia de información, se utiliza como carácter de relleno.
02h STX (Start of Text) Muchos protocolos de comunicación lo utilizan para
indicar el comienzo de un texto.
03h ETX (End of Text) Idem para fin de texto.
06h ACK (Acknowledge) Se utiliza en comunicaciones para contestar
afirmativamente la recepción correcta de un mensaje.
15h NAK (Negative acknowledge) Idem para recepción incorrecta.
0Ah LF (Line Feed) Indica pasar a la siguiente línea (en una impresora o
pantalla).
0Ch FF (Form Feed) Indica pasar a página siguiente.
0Dh CR (Carriage Return) Indica volver a la primera posición dentro de la línea.
11h DC1 (Data Control 1) Indica dispositivo libre (disponible).
12h DC2 (Data Control 2) Indica dispositivo ocupado (no disponible).
0 1 2 3 4 5 6 7
0 NUL DLE SP 0 @ P ` p
1 SOH DC1 ! 1 A Q a Q
2 STX DC2 " 2 B R b R
3 ETX DC # 3 C S c S
4 EOT DC4 $ 4 D T d T
5 ENQ NAK % 5 E U e U
6 ACK SYN & 6 F V f V
7 BEL ETB ' 7 G W g W
8 BS CAN ( 8 H X h X
9 HT EM ) 9 I Y i Y
A LF SUB * : J Z j Z
B VT ESC + ; K [ k {
C FF FS , < L \ l |
D CR GS - = M ] m }
E SO RS . > N ^ n ~
F SI US / ? O _ o DEL
Como ya hemos establecido, el ASCII codifica los caracteres utilizados para escribir
textos en idioma Inglés y los signos de puntuación y símbolos especiales propios de dicha
lengua. ¿Qué pasa entonces con otras lenguas como el español, en particular?. Cómo se
puede observar, la Ñ, por ejemplo, no está codificada, tampoco las letras acentuadas, así
como signos de puntuación característicos de nuestro idioma como "¿" y "¡". La situación en
este campo fue confusa hasta la última década del pasado siglo y existieron distintas
propuestas de codificación aceptadas.
Se propusieron dos mecanismos básicos para atacar el problema: uno fue modificar
el ASCII de 7 bits adaptándolo a cada lengua; el otro fue utilizar un código de 8 bits, que en
sus primeros 128 valores coincidiera con el ASCII y los restantes utilizarlos para representar
los caracteres propios de un conjunto relativamente grande de idiomas.
Un ejemplo del mecanismo de modificación del ASCII es el que fue utilizado por
EPSON en sus impresoras y que se convirtió en un "estándar de facto" en el mundo de las
computadoras personales al ser aceptado y soportado por la casi totalidad de los otros
fabricantes de impresoras. El mecanismo consiste en sustituir caracteres (en general
símbolos especiales) por los caracteres que le "faltan" al ASCII para adaptarse a cada
lengua en particular. Así tenemos un "ASCII español", un "ASCII francés", un "ASCII inglés
(de Inglaterra)", etc.
Tabla 4 - ISO-8859-1 (en las filas 80 y 90 están los caracteres agregados por
Windows-1252).
Por ejemplo para la lengua tibetana los caracteres previstos en Unicode/ISO 10646
son:
Nota: la tabla presenta los dígitos más significativos del “punto de código” en las
columnas.
El UCS se definió de tal modo que los primeros 127 caracteres coinciden con los
definidos en el ASCII original.
Los “puntos de código” se codifican de distintas formas. Las más utilizadas con el
UTF-16 y el UTF-8.
Una segunda manera es reservar un código especial para fin de string. Este
código especial no podrá formar parte del string. Por ejemplo, el lenguaje "C"
utiliza el NULL para fin de string. Cuando se utiliza combinado con codificación la
codificación de los caracteres en ASCII (u otro sistema de representación de
caracteres similar). Esta representación recibe el nombre de ASCIIZ.
Las operaciones elementales de este tipo son las cuatro usuales para los números
enteros (+ - * / ).
Por ejemplo en la suma de 2 enteros sin signo, se aplica el algoritmo usual para los
números binarios. Veamos un par de casos considerando representaciones de 8 bits
Ejemplo 1:
99 01100011
Ejemplo 2:
Los tamaños usuales para esta representación son: el byte ( 0 a 255 ), la palabra de
2 bytes (16 bits, 0 a (216)-1 ), la palabra de 4 bytes (32 bits, 0 a (2 32)-1) y, actualmente, la
palabra de 8 bytes (64 bits, 0 a (2 64)-1). En general el rango de la representación para n bits
será:
0 N 2n 1
Si tenemos n bits para representar el número, tomamos uno para el signo y el resto
representa el valor absoluto del número en binario (expresión del numero en base 2).
Msb lsb
bn-1 bn-2 ... b1 b0
bn-1 = Signo.
bn-2 ... b1 b0 = Valor absoluto
0110 6
1110 -6
(2 n1 1) N 2 n1 1
(2 n1 1) N 2 n1 1
n=8
msb Lsb
5 0000 0101
-5 1111 1010
Ejemplo: (n = 4)
-7 1000
-6 1001
-5 1010
-4 1011
-3 1100
-2 1101
-1 1110
0 0000
0 1111
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
Ejemplo: n=4, d= 8
-8 0000
-7 0001
....
-1 0111
0 1000
1 1001
....
7 1111
N N2 si N 0
01000110 (70)
10111001 (complemento a 1)
1
10111010 (-70)
Mantiene la suma (la suma con o sin signo es la misma operación, es decir que
el algoritmo es el mismo). Es decir la suma de las representaciones da la
representación de la suma de los números representados, sean estos positivos
o negativos.
00000000 0
11111111 not 0
1
00000000
repr( 0 ) = repr( -0 )
A - B = A + ( -B ) = A + not B + 1
Al igual que en toda representación de largo fijo las operaciones pueden generar
overflow. Pero a diferencia del caso de la representación binaria (entero sin signo) en este
caso el bit de carry no indica por sí solo esta condición. Veamos algunos ejemplos
Ejemplo 1:
000110000 carry final = 0
25 00011001
+ 74 01001010
Ejemplo 2:
111110000 carry final = 1
25 00011001
+ -22 11101010
Ejemplo 3:
011100000 carry final = 0
25 00011001
+ 114 01110010
Ejemplo 4:
100010100 carry final = 1
-120 10001000
+ -22 11101010
En esta repreentación para saber si hubo overflow al final de la operación hay que
verificar la existencia de acarreo en los dos bits más significativos. Dejamos a cargo del
lector determinar la expresión lógica del overflow en función de dichos acarreos.
Ejemplo 1:
25 00011001
x 3 00000011
15 00011001
6 00011001
-22 11101010
x 3 00000011
6 11101010
6 11101010
N + N = 2n - 1
Por tanto:
N + N + 1 = 2n
o sea:
N + N = 2n -N = -1 x 2n + N
dicho de otra manera el complemento a 2 de un número es lo que le falta para llegar
a 2n (por ejemplo en 8 bits, el complemento a 2 de 22 es 234, el complemento a 2 de 117
es 139 y así). La segunda parte es una forma equivalente de plantear la primera, de forma
de evidenciar lo que viene a continuación.
N = 0 x 2n + N
-N = -1 x 2n + N
La codificación típica es utilizando ASCII para los dígitos, signo y punto (o cualquier
otro sistema de codificación de caracteres compatible con él):
0 -> 00110000
1 -> 00110001
.........
9 -> 00111001
Los algoritmos para las operaciones son similares a los empleados en las
operaciones decimales hechas a mano. Para sumar, por ejemplo, primero se deben alinear
los strings de modo que los finales estén enfrentados. Se deben rellenar hacia la izquierda
el mas corto con “0” para que los dos strings tengan el mismo largo. Luego se recorre de
derecha a izquierda dígito a dígito. Se debe obtener el valor del dígito de cada sumando a
partir de su representación como carácter. Si la codificación es ASCII se puede hacer una
operación de “máscara” (AND bit a bit) con 0x0F, ó restar el carácter ‘0’ (si el lenguaje lo
permite) ó utilizar la función “ordinal” o similar que algunos lenguajes poseen (que recibe el
carácter como argumento y devuelve el dígito que representa como número entero).
Luego que se obtiene la pareja de dígitos se realiza la operación (teniendo en
cuenta los signos de los sumandos). Si el resultado es mayor que nueve (para el caso de
suma) se resta 10 y se acarrea 1 para la suma de los próximos dígitos. Si el resultado es
menor que cero (para la resta), se suma 10 y se acarrea un -1 para la resta de la siguiente
pareja de dígitos.
Al finalizar el proceso se deben quitar los 0 a la izquierda del número para terminar
de darle formato al string que representará al resultado de la operación.
1 2 3 4 5 +
El nibble más a la derecha se utiliza como marca de fin e indica el signo del número.
El código 1100 (C hexadecimal) indica el fin de un positivo, mientras que el 1101 (D) indica
el fin de un negativo. A veces también se utiliza el código 1111 (F) para indicar el fin (sería
sin signo, es decir positivo).
Para operar con estas representaciones es necesario alinear los números (para que
los dígitos del mismo peso queden enfrentados) y luego se suma dígito a dígito teniendo en
cuenta el signo. Para obtener cada dígito recurro a técnicas de “máscara” (AND con 0x0F)
para obtener el dígito del nibble inferior y de desplazamiento (SHIFT) a la derecha (4 bits)
para obtener el dígito del nibble superior. En el resto el algoritmo es como el descripto para
el caso de la representación Decimal. Luego que se tienen los dos digitos de un byte del
resultado se arma el byte desplazando el digito de la parte alta del byte a la izquierda (4 bits)
y haciendo un OR con el dígito de la parte baja del byte.
En este caso para sumar primero se deben alinear los strings de modo que los
puntos decimales estén enfrentados. Se deben rellenar hacia la derecha y/o izquierda con
“0” para que los dos strings tengan el mismo largo. Luego el algoritmo es análogo al ya
descripto para la representación Decimal.
N (1) s .b e .M
donde: s es el signo
e es el exponente
M es la mantisa
b es la base de representación
Las bases utilizadas han sido, normalmente, 10 y 2. Dado que esta representación
es ambigua (existen varias representaciones para un mismo numero) se utiliza una versión
más restringida que se llama normalizada. Los números normalizados son aquellos en que
el bit más significativo de la mantisa es distinto de cero o, lo que es equivalente, son
aquellos en que la mantisa sea máxima.
Para que los números representados en punto flotante fueran posibles intercambiar
entre distintas arquitecturas se establece el estándar IEEE 754 que define el formato y las
operaciones con estos. El estándar IEEE 754 usa la base 2 (b = 2) y su mantisa
normalizada es de la forma 1,F. La representación utiliza el signo, el exponente (codificado
usando repreentación desplazamiento) y la parte fraccional de la mantisa (lo que está
después de la “coma binaria”). En definitiva el número se representa por la terna de códigos
binarios S (codificación del signo),E (codificación del exponente en desplazamiento),F
(codificación de la parte fraccional de la mantisa en binario).
Los números normalizados son de la forma : (-1)s 1,F 2e, donde el bit más
significativo de la mantisa es un 1. Como todos los números normalizados tienen un uno en
el bit más significativo el estándar define una representación que omite este bit (para
optimizar). Esta consiste en: un 1 implícito, una coma implícita y luego la parte "fraccional"
de la mantisa.
Las clases se distinguen principalmente por el valor del campo “E” (exponente),
siendo modificada ésta por el campo “F” (fracción). Cada clase se representa con los
siguientes rangos de valores:
E (Exponente) F (Fracción)
Normalizados 0000….0 < Exp < 1111….1 Cualquier combinación
Desnormalizados 0000………………………..0 0
Cero 0000………………………..0 0
Infinito 1111..................................1 0
Not a Number 1111..................................1 0
Los números desnormalizados sirven para operar con números menores que el
menor número normalizado representable. Estos números asumen un 0 implícito en vez del
1 implícito de los números normalizados. Por lo tanto cuando tenemos un número en
notación punto flotante desnormalizado estamos representando el número (ejemplo para
simple precisión):
(1) s .2 126.(0, F )
Como vimos los números normalizados son de la forma: 1,F. donde el bit más
significativo de la mantisa es un 1. Todos los números deben ser representados en su
forma normalizada (siempre que se pueda) y los resultados finales de operaciones se
deben normalizar.
El método de normalización utilizado es mover la coma a la parte más significativa
de la cifra, es decir, variando el peso aritmético de los dígitos que lo componen.
Ejemplo: Representación de un decimal a binario en punto flotante (precisión
simple):
S E F
1 10000101 11011010100000000000000
exponentes) hace que el bit más significativo sea menos significante que el bit menos
significativo de la otra mantisa: al sumar y tomar los bits mas significativos sólo se estarán
considerando los bits de la mantisa del número mayor.
Para representar cantidades monetarias se suele utilizar una representación del tipo
"punto fijo", con un numero suficiente de dígitos luego de punto fraccional de forma de darle
cierta precisión a las operaciones financieras hasta el nivel de los "centavos".
Una forma alternativa de verlo es pensar que lo que se almacena es la parte entera
de la cantidad multiplicada por una potencia de 10. Por ejemplo el BASIC de Microsoft
define el tipo "currency" como un entero de 64 bits que resulta de multiplicar la cantidad
original por 10.000.
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Álgebra de Boole
Arquitectura de Computadoras
(Versión 4.3a - 2016)
Arquitectura de Computadoras Notas de Teórico
4 ALGEBRA DE BOOLE
4.1 Introducción.
4.2 Axiomas.
2. (a) Se define una regla de combinación "+" en tal forma que a + b está en G siempre
que tanto a como b lo estén.
(b) Se define una regla de combinación "" en tal forma que a b está en G siempre
que tanto a como b lo estén.
3. Neutros.
(a) Existe un elemento 0 en G tal que para cada a de G: a + 0 = a
(b) Existe un elemento 1 en G tal que para cada a de G: a 1 = a
4. Conmutativos.
Para todo par de elementos a y b pertenecientes a G se cumple:
(a) a + b = b + a
(b) a b = b a
5. Distributivos.
Para toda terna de elementos a, b, c pertenecientes a G se cumple:
(a) a + (b c) = (a + b) (a + c)
(b) a (b + c) = a . b + a c
6. Complemento.
Para cada elemento a de G existe un elemento a tal que:
aa 0
a a 1
Existe similitud de muchos de estos postulados con los del álgebra común. Sin
embargo, la primera de las reglas distributivas (sobre la suma) y la existencia del
complemento diferencian en forma fundamental esta álgebra de la común.
de acuerdo al axioma 4
0 1 1 1 0 0
y teniendo presente el axioma 5 :
1 (1 0) (1 1) (1 0) (5a con a 1, b 1, c 0)
1 0 (1 1) 1
1 11 (por axioma 3)
0 (0 1) 0 0 0 1 (5b con a 0, b 0, c 1)
0 1 0 0 0
0 00 (por axioma 3)
4.4 Propiedades.
Dualidad
Asociativa
a) a (b c) (a b) c
b) a (b c) (a b) c
Si bien las leyes asociativas son muchas veces incluidas dentro del cuerpo
axiomático, de hecho son demostrables a partir de los axiomas aquí presentados
(demostración que no haremos) por lo cual las presentamos como propiedades.
Idempotencia
aa a
aa a
Demostración:
a a (a a) 1 (3b)
a a (a a ) (a a ) (6)
a a a (a a ) (5a)
aa a0 (6)
aa a
aa a (Dualidad)
Neutros Cruzados
a 1 1
a0 0
Demostración:
a 1 a (a a ) (6)
a 1 (a a ) a (asociativa)
a 1 a a (idempotencia)
a 1 1
a0 0 (Dualidad)
Muchas veces las reglas de combinación se presentan como tablas (como las
funciones booleanas más generales que veremos más tarde)
a b a+b a b ab
0 0 0 0 0 0
0 1 1 0 1 0
1 0 1 1 0 0
1 1 1 1 1 1
En general notaremos ab como ab, además la operación “” tendrá mayor
precedencia que la operación “+”.
Complemento de complemento
a ab a
a ( a b) a
a ab a b
a(a b) ab
Ley de De Morgan
( a b) ab
(ab) a b
Los valores que pueden asignarse a un juicio, desde el punto de vista lógico, son
dos: verdadero (V) o falso (F).
Dos juicios pueden combinarse para formar un tercero mediante los operadores
lógicos "o" e "y".
Por lo cual se puede concluir que el modelo "lógico" es isomorfo con el "aritmético"
(binario) realizando la correspondencia.
F0
V 1
.
Otro modelo posible es el que surge de considerar llaves eléctricas y asociar el valor
A a la llave abierta (no pasa corriente, circuito abierto) y el valor C con la llave cerrada
(pasa corriente, circuito cerrado).
paralelo
serie
A0
C 1
paralelo
serie
Llamamos constante a todo elemento del conjunto G que define al álgebra. Las
variables podrán tomar como valor cualquier elemento de G ( 0 o 1 en el caso en que
trabajamos).
Una expresión la podemos definir recursivamente como
Una función "F" de n variables x1 ... x n booleanas es una aplicación del espacio Gn
sobre el espacio G de tal forma que para cada valor posible de la n-upla x 1 ... x n, donde
cada variable puede tomar cualquier valor del conjunto (en nuestro caso {0, 1} ), se asocia
un valor del recorrido G.
a b c F
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 1
Otras formas de representar F incluyen el método de indicar sólo los puntos en los
cuales F vale 1 o sólo los puntos en los cuales vale 0 (representaciones y
respectivamente). Para indicar los puntos en que la función vale 1 puede usarse la notación
en lugar de .
f ( a, b, c ) (1,4,5,7) f ( a, b, c) (0,2,3,6)
f ac ab abc
Nota :
la NOR es el complemento de la OR
la NAND es el complemento de AND
la XOR ("O" exclusivo) puede definirse como:
a b ab ab
4.8.2 OR exclusivo.
El XOR es una función muy importante (es la suma aritmética binaria módulo 2) y
cumple las propiedades :
1) Asociativa
2) Conmutativa
3) Distributiva: a(b c) ab ac
4) a 0 a
5) a 1 a
6) a a 0
7) Cancelativa: a b a c b c
Es decir toda función de n variables puede expresarse como la suma de todos sus
productos canónicos afectado cada producto canónico por un coeficiente. Este coeficiente
es el valor de la función evaluado en el punto tal que las variables que en el producto
canónico asociado aparecen simples tengan el valor 1 y las que aparecen complementadas
el valor 0.
a b c F
0 0 0 0
0 0 1 1 abc
0 1 0 0
0 1 1 1 abc
1 0 0 1 abc
1 0 1 0
1 1 0 0
1 1 1 0
Como todo en el álgebra de Boole, existe un método dual del anterior: el producto
de sumas canónicas. En este caso deben considerarse los puntos en los que la función
vale 0 y buscar las sumas canónicas asociadas que son aquellas en las que la variable
aparece simple si tiene valor 0 y complementada si tiene valor 1.
Es fácil probar que el conjunto OR, NOT es lógicamente completo notando que el
AND se puede construir como:
a # a (a.a) a (complemento)
(a # b)# (a # b) (a # b) (a.b) a.b (AND)
(a # a)# (b# b) (a.b) (a b) a b (OR) por De Morgan
4.10 Simplificación.
Resumamos aquí algunas propiedades vistas del álgebra que serán de utilidad en la
tarea de simplificar:
1) f f 0
2) f f 1
3) g f g f f
4) g f f f
5) f f g f g
Por la aplicación de la propiedad 3 a los primeros dos términos y a los dos últimos
queda
f 1 ab bc
f 2 ab ac bc
f 2 ac ab
Este método consiste en representar en forma gráfica una función como suma de
productos canónicos y hacerlo de tal forma que sea sencillo establecer procedimientos
sistemáticos para hallar las agrupaciones de términos más convenientes para simplificar la
expresión. Esto se logra utilizando una cuadrícula en la cual a cada cuadrado elemental
corresponde un producto canónico posible y tal que al pasar de uno a otro cualquiera de
sus cuatro adyacentes solo cambie el valor de una de las variables en juego. Por ejemplo
para tres variables la cuadrícula es:
c\ab 00 01 11 10
0
1
cd\ab 00 01 11 10
00
01
11
10
e=0 e=1
cd\ab 00 01 11 10 cd\ab 00 01 11 10
00 00
01 01
11 11
10 10
En esta cuadrícula se marcan con "1" los lugares para los cuales la combinación de
valores de las variables hace que la función valga 1 y el método consiste en buscar agrupar
los "unos" formando los rectángulos más grandes posibles (que tengan todos 1 en su
interior), repitiendo este proceso hasta que todos los puntos donde la función vale "1" estén
comprendidos en algún rectángulo (siendo la cantidad total de rectángulos utilizados la
menor posible). Es necesario aclarar que la cantidad de elementos agrupados debe ser una
potencia de 2.
Nota: el diagrama es circular (los elementos de cada borde son adyacentes con los
del borde simétrico)
Ejemplos:
cd\ab 00 01 11 10
00 1 1
01 1 1 1
11
10
cd\ab 00 01 11 10
00 1 1 1
01 1 1
11
10 1 1
1) f 3 ac bcd
2) f 4 ad abc acd
c\ab 00 01 11 10
0 1
1 1 1 1
La primer expresión de f2 hallada con dicho método tenía además el término bc que
corresponde al rectángulo formado por los dos extremos inferiores del diagrama que aquí
queda evidente que no era necesario puesto que con los otros dos términos cubrimos
todos los puntos donde la función vale "1".
Cuando la función booleana que se desea minimizar tiene puntos en los cuáles no
está definida, es decir que no importa el valos que toma para ciertas combinaciones
específicas de sus variable de entrada, se puede utilizar esta propiedad para eventualmente
lograr una minimización más importante de la expresión algebraica.
Para ello se colocan “x” en el diagrama de Karnaugh correspondiente a esos puntos
no definidos y las “x” se podrán tomar como 1 en caso que permitan lograr un rectángulo de
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Circuitos Combinatorios
Arquitectura de Computadoras
(Versión 4.3b - 2016)
Arquitectura de Computadoras Notas de Teórico
5 CIRCUITOS COMBINATORIOS
5.1 Introducción
En general trabajaremos con los "Circuitos Combinatorios", que los definimos como
aquellos cuya salida está determinada, en todo instante, por el valor actual de sus entradas.
5.2 Transistores
Para ello el primer mecanismo que se usó (de hecho en la computadora MARK I en
la década del 40) fue el relé (llave electromagnética). El diagrama de un dispositivo de
estas características es:
I
i
ia I
ib
Los relés fueron luego reemplazados por las válvulas de vacío. Estos dispositivos
fueron los primeros completamente electrónicos utilizados en una computadora: la ENIAC.
C
B
I
i
E
I = hFE * i
siendo hFE una constante típica de cada modelo de transistor. Esta relación de
proporcionalidad es válida en el denominado modo de funcionamiento "lineal" y es utilizada
por ejemplo en los dispositivos que trabajan con señales analógicas, como equipos de
audio, televisores, etc. El funcionamiento en modo "lineal" depende, básicamente, del
circuito donde el transistor se coloca.
Sin embargo en las aplicaciones de lógica digital a los transistores se los hace
trabajar en el modo de funcionamiento "saturación", donde la corriente I alcanza su valor
máximo (determinado por otros parámetros del circuito).
Por otra parte, y al igual que en las aplicaciones analógicas, la magnitud eléctrica
que se considera es la diferencia de potencial eléctrico (o "voltaje") en lugar de la corriente.
Dada la conocida relación entre diferencia de potencial y corriente eléctrica dada por la Ley
de Ohm:
ΔV = R * I
Como muchas veces se consideran las diferencias de potencial ΔV con respecto a
una referencia común (denominada "tierra lógica") es que se aplica la relación anterior en la
forma:
V = R * I
Entonces veamos como queda el transistor cuando agregamos resistencias en su
base y en su colector:
El valor de VCEsat es aproximadamente 0,2 Volts, pero a los efectos se toma como
0.
Por su lado la corriente IBE circula cuando Ve > VBE siendo VBE una diferencia de
potencial que se produce entre base y emisor de un transistor y cuyo valor un parámetro
característico de los mismos y vale aproximadamente 0,6 Volts. Por ley de Ohm la corriente
de base cumple:
Ve - VBE = RB * IBE
Por otra parte si no circula corriente entre base y emisor tampoco circulará corriente
entre colector y emisor. Esto significa que no circulará corriente por la resistencia de
colector y, de acuerdo a la ley de Ohm, no habrá entonces caída de potencial entre los
extremos de la misma, por lo que se cumplirá que:
si Ve = 0 entonces Vs = VCC
5.3 Lógicas
En base a las ideas manejadas en el circuito del NOT hecho en base a un transistor
y resistencias se pueden construir las demás conectivas binarias. En particular dado que el
NOR es un operador lógicamente completo alcanza con mostrar como se puede construir
con transistores y resistencias para poder afirmar que es posible construir cualquier función
si Va = 0 y Vb = 0 entonces Vs = VCC
si Va = 0 y Vb = VCC entonces Vs = 0
si Va = VCC y Vb = 0 entonces Vs = 0
si Va = VCC y Vb = VCC entonces Vs = 0
Dicho comportamiento en voltajes equivale a la tabla de verdad del NOR. Por tanto
hemos logrado mostrar que es posible construir cualquier función lógica en base a un
diseño RTL.
Uno de los problemas de la lógica TTL sigue siendo el relativo alto consumo de
energía y su relativa baja performance en alta frecuencia. Esto se mejoró con la utilización
de transistores de mejores prestaciones, denominados Schottky (en honor a su inventor).
Esto dio lugar a variantes de la familia 74, conocidas como 74S, 74LS y 74ALS. Las letras
adicionales significan:
S = Schottky
LS = Low power Schottky
ALS = Advanced Low power Schottky
se construyen los circuitos con ellos sólo disipan energía cuando conmutan (sus salidas
pasan de un valor a otro respondiendo al cambio de sus entradas). Por otro lado su
resistencia interna es prácticamente nula en modo de conducción. La desventaja inicial que
tenían de mala respuesta a cambios rápidos de sus entradas (o sea mala respuesta en
frecuencia) fue superada con el tiempo con lo que han terminado por reemplazar totalmente
a los transistores bipolares.
Un transistor IGFET (Insulated Gate Field Effect Transistor, también conocido como
MOSFET) se puede considerar como una llave electrónica controlada por voltaje casi
perfecta, cuyo símbolo es:
Tomado de www.learnabout-electronics.org
Los MOSFET de canal-n tienen "lógica positiva", mientras que los canal-p tienen
"lógica negativa", ya que funcionan de acuerdo al siguiente esquema:
5.4 Compuertas
Una forma siempre aplicable (aunque en algunos casos más trabajosa) para
construir un circuito lógico parte de la función booleana a implementar representada, por
ejemplo, mediante su tabla de verdad. A partir de ella y mediante Diagramás de Karnaugh
(u otro método) se realiza la minimización (en dos niveles) de la misma. De esa forma se
Una alternativa es identificar partes del circuito que se puedan realizar con otros
"bloques constructivos" de mayor nivel, tales como sumadores de n bits, multiplexores,
decodificadores, comparadores, selectores, etc. Luego se reúnen y conectan
adecuadamente estos bloques minimizando, de ser necesario, la lógica de dichas
conexiones mediante Diagramás de Karnaugh.
a b c M
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1
c\ab 00 01 11 10
0 1
1 1 1 1
M = ab + ac + bc
a1 a0 b1 b0 s1 s0 c
0 0 0 0 0 0 0
0 0 0 1 0 1 0
0 0 1 0 1 0 0
0 0 1 1 1 1 0
0 1 0 0 0 1 0
0 1 0 1 1 0 0
0 1 1 0 1 1 0
0 1 1 1 0 0 1
a1 a0 b1 b0 s1 s0 c
1 0 0 0 1 0 0
1 0 0 1 1 1 0
1 0 1 0 0 0 1
1 0 1 1 0 1 1
1 1 0 0 1 1 0
1 1 0 1 0 0 1
1 1 1 0 0 1 1
1 1 1 1 1 0 1
s1
b1b0\ a1a0 00 01 11 10
00 1 1
01 1 1
11 1 1
10 1 1
s0
b1b0\ a1a0 00 01 11 10
00 1 1
01 1 1
11 1 1
10 1 1
b1b0\ a1a0 00 01 11 10
00
01 1
11 1 1 1
10 1 1
Los esquemas de los circuitos basados en compuertas para las tres salidas en
función de sus expresiones mínimas se presentan a continuación.
Dado que los tres circuitos corresponden al mismo sistema y tienen las mismas
entradas, también puede considerarse un circuito que reutiliza las compuertas NOT y
genera las tres salidas como en el siguiente esquema.
A B C Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
0 0 0 0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 1 0 0
0 1 1 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0 0 0
1 0 1 0 0 1 0 0 0 0 0
1 1 0 0 1 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0
es decir dada una combinación de unos y ceros a la entrada todas las salidas
estarán en 0 salvo la que corresponda al número binario coincidente con la combinación de
entradas.
En la práctica este circuito está disponible con lógica negativa (las salidas son 1
salvo la seleccionada) y con entradas adicionales funcionando como un demultiplexor
(circuito que veremos más adelante).
A B C Y
0 0 0 D0
0 0 1 D1
0 1 0 D2
0 1 1 D3
1 0 0 D4
1 0 1 D5
1 1 0 D6
1 1 1 D7
es decir que la salida Y toma el valor de la entrada D cuyo índice coincida con el
número binario representado por las entradas A, B y C. Las entradas A, B y C se llaman
entradas de "control" y las entradas D se llaman de "datos".
a b c M
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1
que coincide con la tabla de verdad del circuito Mayoría (a, b, c).
Los circuitos integrados disponibles (como el 74251) disponen de salida "tri-state" (el
concepto de tri-state se verá más adelante) controlada por una entrada adicional G y una
salida de lógica invertida W:
A B C Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
0 0 0 0 0 0 0 0 0 0 G
0 0 1 0 0 0 0 0 0 G 0
0 1 0 0 0 0 0 0 G 0 0
0 1 1 0 0 0 0 G 0 0 0
1 0 0 0 0 0 G 0 0 0 0
1 0 1 0 0 G 0 0 0 0 0
1 1 0 0 G 0 0 0 0 0 0
1 1 1 G 0 0 0 0 0 0 0
a b cin S cout
0 0 0 0 0
0 0 1 1 0
0 1 0 1 0
0 1 1 0 1
1 0 0 1 0
1 0 1 0 1
1 1 0 0 1
1 1 1 1 1
cin \ab 00 01 11 10
0 1 1
1 1 1
cout
cin \ab 00 01 11 10
0 1
1 1 1 1
(Nota: observar que cout tiene el mismo diagrama que el circuito Mayoría)
Podemos observar en la expresión anterior que ahora queda el exor entre el exor de
a y b con cin.
S = (ab)cin
cout = ab + (a+b)cin
y esto es equivalente a:
cout = ab + (ab)cin
(esto se debe a que el único caso donde a+b es distinto de ab es cuando a y b son
1 simultáneamente y allí ab es 1 y por tanto el or general da 1 de todos modos).
que, como se puede observar directamente, posee muchas menos compuertas que
la versión anterior. Como nada es "gratis" también se observa que el circuito tiene un nivel
más de compuertas (normalmente el nivel de compuertas "not" no se cuenta, por lo que el
circuito original tiene 2 niveles y este tiene 3).
t
E
t
En el diagrama se ha omitido considerar el retardo de propagación de la compuerta
AND, porque de hecho no interesa a los efectos de analizar el problema. El retardo de
propagación en la compuerta NOT produce que cuando la entrada E cambia a 1, la salida
del NOT demora en pasar a 0 un cierto tiempo Tp. Durante ese tiempo ambas entradas del
AND están en 1 con lo cual su salida pasará a 1 (en vez de quedarse en 0 que sería su
estado lógico de acuerdo al circuito, si éste fuera ideal). Recién cuando la salida del NOT
cambie la salida del AND irá a su valor correcto. El fenómeno produjo un "pulso" a la salida
que no debería haber existido. El fenómeno se puede compensar con técnicas apropiadas
de diseño de los circuitos lógicos, las que se basan en compensación de recorridos de las
distintas señales y en agregar compuertas, asociadas a rectángulos redundantes en los
diagramas de Karnaugh, de modo de evitar la generación de estas salidas espúreas. Estos
fenómenos se denominan genéricamente "azares estáticos".
Por este fenómeno es que normalmente se prefieren circuitos con pocos niveles de
compuertas entre sus entradas y sus salidas. Si pensamos que el circuito de sumador
completo de 1 bit que usamos para generar el circuito sumador de 4 bits tiene un retardo
Tp, entonces el sumador de 4 bits tendrá 4xTp, o en general NxTp, siendo N el número de
bloques en cascada que se conecten. Al crecer el retardo de propagación, las salidas
demoran más en ser válidas y poder ser consideradas como entradas para etapas
siguientes. Además la velocidad a la que podemos cambiar las señales (frecuencia de
conmutación) estará en relación inversa al tiempo de propagación, ya que cuanto más alto
este tiempo menor será la velocidad a la que podré cambiar las entradas (para darle tiempo
a que las salidas se estabilicen antes de cambiar nuevamente las entradas).
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Memorias ROM
Arquitectura de Computadoras
(Versión 4.3a - 2016)
6 MEMORIAS ROM
6.1 Introducción
Las entradas se identifican por A0 a A13 y las salidas por D0 a D7 (en este caso).
Para un caso genérico sería: A0 a Am-1 y D0 a Dn-1. Más adelante veremos que son y para
qué se usan las entradas CS y OE.
6.2 Características
Entradas Salidas
Am-1 Am-2 Am-3 …. …. A2 A1 A0 Dn-1 Dn-2 … D1 D0
0 0 0 …. …. 0 0 0 0 0 …. 0 0
0 0 0 …. …. 0 0 1 1 0 …. 1 0
0 0 0 …. …. 0 1 0 0 0 …. 0 0
…. …. …. …. …. …. …. …. …. …. …. …. ….
…. …. …. …. …. …. …. …. …. …. …. …. ….
1 1 1 …. …. 1 0 1 1 1 …. 1 1
1 1 1 …. …. 1 1 0 0 1 …. 0 1
1 1 1 …. …. 1 1 1 1 1 …. 1 1
Dij
siendo
0 < i < 2m - 1
0<j<n-1
Esta tabla de verdad puede verse como la descripción del contenido de un "array"
de 2m elementos que tienen n bits cada uno. Como es un circuito combinatorio, los valores
concretos de los bits de los elementos (los Dij) son fijos, predeterminados. Por estas dos
características a estos circuitos se los llama Read Only Memory (Memoria de Solo Lectura),
o, más brevemente, ROM.
Es fácil observar que con una ROM se puede implementar cualquier función lógica
de m variables de entrada y n salidas. Basta con especificar el "contenido" de la ROM de
manera que los n bits de cada palabra (posición del array) correspondan al valor de la
función en el punto (que coincide con el índice del array).
El circuito interno de una ROM tiene, para cada bit de salida, la siguiente forma:
Las ROMs así construidas tienen el inconveniente que una vez que se fabrican no
es posible cambiar su contenido.
Esto no sería un problema significativo cuando usamos las ROMs como circuito
combinatorio. Sin embargo el uso habitual de las ROMs es el de almacenar programas fijos
(ej: las rutinas de inicio de un computador, el programa almacenado de un controlador de
un semáforo, un ascensor, un lavarropas, etc). Los programas tienen correcciones y
mejoras constantes, por lo que es poco práctico (y poco rentable) tener que producir
nuevas ROMs cada vez que hay un cambio.
Por ello se fueron desarrollando con el tiempo nuevos circuitos que dieran respuesta
a esta situación: por un lado fueran memorias permanentes (no perdieran su contenido al
quedar sin energía eléctrica) y por otro pudiera ser modificado su contenido de alguna
forma.
6.4.1 PROM
Las PROM son Programmable ROM. Una PROM es una ROM cuyo contenido
puede ser definido a posteriori de construida, mediante una actividad de programación que
se realiza utilizando un circuito electrónico especial (un Programador de PROMs).
En esencia son ROMs que tienen en su entrada Dij a las ANDs de selección una
conexión tanto a ground (0) como a Vcc (1). Esta conexión está realizada mediante un
fusible, el cual se quema al momento de "programar" el contenido de la PROM. Si quiero
grabar un 0 quemo el fusible de la conexión a Vcc y si quiero grabar un 1 quemo el fusible
de la conexión a tierra.
Estos fusibles no pueden reconstruirse. Cuando se graba una PROM con un cierto
contenido no hay marcha atrás.
6.4.2 EPROM
Si bien las PROMs significaron un avance, el hecho de no tener "vuelta atrás" aún
significaba una restricción para el uso intensivo de PROMs en el almacenamiento de
programas. De esa necesidad no del todo satisfecha surgió la tecnología de las EPROM
(Erasable PROM).
Una EPROM es una ROM que puede ser borrada. El mecanismo de borrado es
totalmente distinto al de programación e implica un proceso de exposición del circuito a luz
ultravioleta por varios minutos. La gran ventaja es que puede reutilizar las EPROMs muchas
veces borrando su contenido y grabando uno nuevo.
Esta ventana está normalmente tapada de forma de evitar exponer el silicio a la luz
normal (que contiene componentes ultravioletas) para que el contenido de la EPROM no se
altere.
6.4.3 EEPROM
Es así que surgieron las EEPROM (Electrical EPROM), o sea una EPROM cuyo
proceso de borrado se hace eléctricamente y puede efectuarse sin retirar el circuito
integrado del sistema. Posee otra diferencia importante con la EPROM: una EEPROM
normalmente tiene la capacidad de borrar cada bit en forma individual (también hay
implementaciones que borran una palabra completa en cada operación de borrado).
Este tipo de memoria es una variante de las EEPROM que se desarrolló con el
objetivo de mejorar el tiempo de borrado, de forma de habilitar su uso para aplicaciones de
almacenamiento masivo.
Si bien el nombre está asociado al concepto de velocidad (lo que se corresponde
con lo antedicho), el nombre se origina en la similitud que uno de sus creadores veía entre
el proceso de borrado y el destello del flash de una cámara de fotos.
En la foto siguiente se puede ver la parte interna de una Memoria USB, que
actualmente se usa para almacenar información en forma transportable (lo que antes se
hacía con disquetes).
Las memorias ROM están caracterizadas por una cierta capacidad, que se mide en
bits (ó Kilobits, Megabits ó Gigabits) y una determinada organización, que se expresa en
cantidad de palabras de tantos bits.
Ejemplos:
- ROM de 8 Kbits, con organización de 1Kx8 (1 Kilo palabras de 8 bits)
- ROM de 8 Kbits, con organización de 4Kx2 (4 Kilo palabras de 2 bits)
- ROM de 1 Kbits, con organización de 1Kx1 (1 Kilo palabras de 1 bit)
En este caso el objetivo es lograr una memoria ROM de n bits de salida a partir de
memorias de menor cantidad de bits (su tamaño de palabra es menor que el requerido).
En este caso el objetivo es lograr una memoria ROM de m bits de entrada a partir
de memorias de menor cantidad de bits de dirección.
En el caso anterior cada ROM contribuía con una parte de los bits de salida. En este
caso cada ROM contribuirá con una parte del rango de direcciones. La ROM a construir
tiene 11 bits de entrada, con un rango de direcciones de 0 a 2047. Cada ROM disponible
tiene 10 bits de entrada, con un rango de direcciones de 0 a 1023. Por tanto cada ROM
contribuirá con la mitad de las posiciones: una de ellas aportará las posiciones de 0 a 1023
y la otra las posiciones de 1024 a 2047. Para seleccionar qué ROM se conecta a la salida
utilizamos multiplexores de 2x1, controlados por el bit más significativo de las entradas de
dirección.
En otras palabras las compuertas ANDs están incluidas dentro del chip de la ROM y
el selector es la entrada CS.
En las ROMs más modernas la entrada CS en 0 tiene un efecto un poco distinto por
el cual el circuito interno de la ROM pasa a un estado de bajo consumo de energía y el
estado de sus salidas tiene un comportamiento similar al "tri-state" que veremos en el
próximo punto.
A los efectos del curso consideraremos que el comportamiento es el primero de los
descriptos (las salidas pasan a estado lógico 0).
El circuito de la ROM de 2Kx8 queda simplificado por el uso del CS de esta manera:
Dada esa propiedad alguien podría verse tentado de quitar las OR y unir las salidas.
Eso desde el punto de vista lógico no es posible porque sería equivalente a igualar dos
variables de valor en principio distinto (una de ellas con valor 0 y la otra con 0 ó 1). Desde el
punto de vista del circuito provocaría un cortocircuito que posiblemente dañe las salidas que
se unieran de esa forma.
Los circuitos que tienen este tipo de salida disponen también de una entrada
denominada OE (Output Enable) o similar. Cuando dicha entrada de control está en 0, la
salida pasa al "estado de alta impedancia" y cuando la entrada de control está en 1, la
salida está en estado lógico 0 ó 1.
6.8.1 Aplicación de Lógica Tri-state con Output Enable (OE) a Arreglos de Memorias
Veamos a continuación como queda del circuito de la ROM de 2Kx8 simplificado por
el uso de la lógica de tres estados a través de la entrada de control OE:
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Flip-Flops
Arquitectura de Computadoras
(Versión 4.3b - 2023)
Arquitectura de Computadoras Notas de Teórico
7 FLIP-FLOPS
7.1 Introducción
7.2 Flip-Flop
El Flip-Flop (FF) R-S Asíncrono (también denominado Latch) es un circuito que tiene
la forma:
_
Tiene dos salidas que se denominan Q y Q (que anotaremos en adelante Q'), y dos
entradas R y S (nombres determinados por sus características, que veremos al analizar el
comportamiento del circuito).
Es sencillo comprobar que si los valores a la entrada son R=1 y S=0, entonces las
salidas serán Q=0 y Q'=1. Esto es porque R=1 fuerza la salida del NOR de arriba a 0 y
entonces ambas entradas del NOR de abajo serán 0 y su salida quedará en 1.
Por un razonamiento análogo se puede ver que si R=0 y S=1, entonces las salidas
serán inversas, Q=1 y Q'=0.
Ahora si las entradas son R=0 y S=0, resulta que los valores de las salidas no
quedan totalmente determinados, ya que tanto Q=0 y Q'=1 como Q=1 y Q'=0 son
combinaciones válidas (notar que no son válidas Q=Q', ya sea ambos 0 ó ambos 1, porque
al ser R=S=0 las salidas quedan obligadas a ser complementarias por la topología del
circuito). Para saber cual de las combinaciones de salidas se produce debemos analizar
cuales eran los valores anteriores de R y S.
Si se llega a R=S=0 desde R=1 y S=0 resulta que las salidas serán Q=0 y Q'=1, pero
si antes las entradas estaban en R=0 y S=1 al pasar a R=S=0 las salidas serán Q=1 y Q'=0.
Esta propiedad permite afirmar que al pasar sus entradas a 0 el circuito "recuerda" cual fue
la ultima entrada en 1. Este es el concepto de memoria asociado al hecho que la salida del
circuito no depende solamente del valor actual de las entradas sino que también de los
valores anteriores.
Queda por analizar el caso de las entradas R=S=1. En este caso las salidas son
ambas 0 (Q=Q'=0) ya que ambos NORs tienen al menos una entrada en 1. Esto en principio
no es problema. Pero si analizamos que pasa cuando las entradas dejan de ser ambas 1
veremos que aparece un problema con el comportamiento del circuito. Si R pasa de 1 a 0,
mientras S permanece en 1, el circuito pasará a tener salidas Q=1, Q'=0. Si la que pasa a 0
es la entrada S, entonces las salidas pasan a Q=0, Q'=1. Pero, ¿qué pasa si ambas pasan
simultáneamente a 0?. En ese caso el valor de las salidas no quedan determinados, pueden
ser indistintamente Q=1, Q'=0 ó Q=0 y Q'=1 (notar que otra combinación es inválida para la
topología del circuito). ¿Cuál de las dos combinaciones posibles será la que adopte el
circuito?. En principio no se sabe, se trata de una indeterminación. En la práctica lo que
sucede es que una de las entradas cambiará antes que la otra (aunque sea por un tiempo
sumamente pequeño de diferencia), por lo que estaremos en uno de los casos anteriores.
El problema es que a todos los efectos el comportamiento en este caso sigue siendo
indeterminístico y por tanto la combinación R=S=1 es "prohibida" (se debe evitar su
aparición a la entrada de un latch tipo R-S).
R S Qn+1
0 0 Qn
0 1 1
1 0 0
1 1 -
Por su parte el símbolo que se utiliza para representar el bloque de circuito es:
Uno de los problemas que se presentan al intentar utilizar este tipo de circuitos como
elementos de memoria es el hecho que las funciones que generan los valores de las
señales R y S pueden variar en momentos no deseados y el flip-flop responderá a esos
cambios según su tabla de verdad.
Para evitar esta situación se introduce una señal de sincronismo para el circuito (la
habilitación ó el reloj) que indicará cuando son válidos los valores de R y S y cualquier otra
señal significativa para el circuito completo. Esta entrada de control puede actuar de
En este caso donde las entradas se consideran mientras la entrada de control esté
en 1, se dice que el sistema trabaja "por nivel", ya que lo que interesa es el estado de la
señal de control: si vale 1 entonces el resto de las señales serán válidas y si vale 0 no lo
serán. Esta modalidad de funcionamiento se denomina "control por compuerta", "control por
habilitación" ó "control por nivel".
7.2.3 Flip-Flop D
Este flip-flop puede verse como una variante del flip-flop R-S, que tiene el siguiente
circuito interno (en la modalidad de control por nivel):
D Qn+1
0 0
1 1
Qn+1 = Dn
En otras palabras lo que indica la ecuación característica o su tabla de verdad
equivalente es que el nuevo valor de la salida Q (identificado con el subíndice n+1)
corresponde al valor actual de la entrada D (identificado con el subíndice n).
Para ser más precisos: en el caso de los flip-flops con entrada de control por nivel, el
nuevo valor de la salida corresponde al valor de la entrada D mientras la señal de control
(G) está en 1. Mientras la señal de control G está en 0 la salida mantiene el valor de la
entrada D inmediatamente antes de la transición de 1 a 0 de la entrada G.
En el caso de los flip-flops con entrada de control por flanco, el nuevo valor de la
salida corresponde al valor de la entrada D al momento de la transición de la entrada de
reloj (CLK) de 0 a 1 (es decir el "flanco ascendente"). Este nuevo valor de la salida es
adoptado inmediatamente después de ocurrido dicho flanco.
7.2.4 Flip-Flop T
T Qn+1
0 Qn
1 Q'n
Notar que tanto la tabla como la ecuación describen un circuito que o bien mantiene
su salida incambiada en el tiempo (cuando T = 0) o bien la invierte en cada flanco
(ascendente) de su entrada de control (cuando T = 1).
Este flip-flop busca resolver definitivamente el problema del flip-flop R-S. Consiste en
dos flip-flops R-S sincrónicos por nivel conectados en "cascada" y realimentados de la
siguiente manera:
por el contrario Q (segundo FF) = 1, y por tanto Q' (segundo FF) = 0, resulta R (primer FF) =
0 y S (primer FF) = 1 y esto lleva Q (primer FF) a 1, lo que a su vez implica R (segundo FF)
= 1 y S (segundo FF) = 0, que termina generando una salida Q (segundo FF) = 0.
Por tanto el efecto neto cuando J = K = 1 es que el flip-flop complementa su salida.
J K Q Qn+
n 1
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 1
1 1 1 0
Qn \JK 00 01 11 10
0 1 1
1 1 1
J K Qn+
1
0 0 Qn
0 1 0
1 0 1
1 1 Q'n
Las implementaciones prácticas de los flip-flops sincrónicos con activación por flanco
usualmente disponen de dos entradas de control adicionales las cuales actúan en forma
asíncrona (actúan por nivel) y sirven para poner a 1 (Set ó Preset) ó a 0 (Clear) el circuito.
Especialmente para el caso de los flip-flops D usados como "bits de memoria" surge el
problema de cómo almacenar en el FF solamente cuando interesa y no cada vez que el
reloj genera un flanco, ya que normalmente se usa un reloj de onda cuadrada que cambia
constantemente.
Una solución posible sería hacer un AND a la entrada de CLK del FF entre el reloj del
sistema y una señal de activación que pase a "alto" cuando interesa escribir el valor en el
flip-flop. Esto potencialmente genera problemas de falsos pulso de reloj aplicados al flip-flop
si esta señal de activación no está perfectamente sincronizada con el reloj general. Para ello
algunos flip-flops implementan una entrada adicional llamada Clock Enable, que funciona
como un habilitador de la señal del clock hacia dentro del flip-flop, aunque en realidad la
implementación interna más común está esquematizada por el circuito:
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Contadores
Arquitectura de Computadoras
(Versión 4.3 - 2016)
Arquitectura de Computadoras Notas de Teórico
8 CONTADORES
8.1 Contadores
Para analizar el comportamiento del circuito supongamos que inicialmente todas las
salidas de los FF están en 0.
Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Tercer flanco 1 1 0 1
Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Tercer flanco 1 1 0 1
Cuarto flanco 1 1 0 0
Quinto flanco 1 0 1 1
Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Tercer flanco 1 1 0 1
Cuarto flanco 1 1 0 0
Quinto flanco 1 0 1 1
Sexto flanco 1 0 1 0
Séptimo flanco 1 0 0 1
Octavo flanco 1 0 0 0
Noveno flanco 0 1 1 1
Décimo flanco 0 1 1 0
Onceavo flanco 0 1 0 1
Doceavo flanco 0 1 0 0
Treceavo flanco 0 0 1 1
Catorceavo flanco 0 0 1 0
Quinceavo flanco 0 0 0 1
Dieciseisavo flanco 0 0 0 0
Notemos que al cabo de 16 flancos llegamos a la misma condición inicial, por lo que
a partir de ese momento la secuencia se repetirá.
Si observamos la tabla que quedó notamos enseguida que las salidas Q3, Q2, Q1,
Q0 forman un numero en binario de 4 bits que va disminuyendo desde 1111 (15) hasta
0000 (0) en forma cíclica (llegado a 0 luego vuelve a 15 y comienza de nuevo a disminuir)
Por tanto el circuito formado por los flip-flops T conectados de esa manera se
comporta como un contador binario descendente de 4 bits.
Para tener un número mayor de bits (y por tanto mayor capacidad de cuenta) basta
con agregar más flip-flops T conectados de manera análoga. Por cada flip-flop que se
agrega se duplica la capacidad de cuenta.
0
1
----
11
10
----
110
111
101
100
----
1100
1101
1111
1110
1010
1011
1001
1000
Notar que el código se genera espejando lo ya hecho hasta los lugares potencia de
dos (indicados por las líneas punteadas) agregándole un 1 delante.
Si tomamos, arbitrariamente, que el primer código representa el 0, nos queda la
siguiente tabla de codificación:
0 0000
1 0001
2 0011
3 0010
4 0110
5 0111
6 0101
7 0100
8 1100
9 1101
10 1111
11 1110
12 1010
13 1011
14 1001
15 1000
Para el caso que nos ocupa tomamos los códigos binarios desde el 1 al 10.
Obviamente, y como era de esperar, precisamos 4 dígitos para representar los códigos
Gray de estos números, por lo que nuestro contador requiere de 4 flip-flops.
El siguiente paso en escribir una tabla que nos indique en función del valor actual de
las salidas Q3, Q2, Q1, Q0, cuál deben ser los nuevos valores de forma que el circuito se
comporte como deseamos (notar que por haber elegido un numero de cuenta que no es
potencia de 2, el código no queda "perfectamente" cíclico en Gray):
Actuales Nuevos
Q3Q2Q1Q0 Q3Q2Q1Q0
1 0 0 0 1 0 0 1 1
2 0 0 1 1 0 0 1 0
3 0 0 1 0 0 1 1 0
4 0 1 1 0 0 1 1 1
5 0 1 1 1 0 1 0 1
6 0 1 0 1 0 1 0 0
7 0 1 0 0 1 1 0 0
8 1 1 0 0 1 1 0 1
9 1 1 0 1 1 1 1 1
10 1 1 1 1 0 0 0 1
De esta manera nos queda una tabla de verdad de un circuito combinatorio, cuyas
entradas son los valores actuales de los Qj y sus salidas son los valores actuales de Dj
necesarios para lograr la transición deseada.
Tenemos entonces la siguiente tabla de verdad del circuito combinatorio:
Q3 Q2 Q1 Q0 D3 D2 D1 D0
0 0 0 1 0 0 1 1
0 0 1 1 0 0 1 0
0 0 1 0 0 1 1 0
0 1 1 0 0 1 1 1
0 1 1 1 0 1 0 1
0 1 0 1 0 1 0 0
0 1 0 0 1 1 0 0
1 1 0 0 1 1 0 1
1 1 0 1 1 1 1 1
1 1 1 1 0 0 0 1
D3
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X 1 1 X
01 1 X
11 X
10 X X
D2
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X 1 1 X
01 1 1 X
11 1 X
10 1 1 X X
D1
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X X
01 1 1 X
11 1 X
10 1 1 X X
D0
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X 1 X
01 1 1 X
11 1 1 X
10 1 X X
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Memorias RAM
Arquitectura de Computadoras
(Versión 4.3b - 2016)
9 MEMORIAS RAM
9.1 Introducción
El nombre RAM es una sigla que corresponde a Random Access Memory. Este
nombre no es del todo feliz y seguramente fue elegido históricamente por tres causas:
- para diferenciar estos dispositivos de las primeras memorias que funcionaban de
modo "secuencial" (para leer una posición había que leer previamente todas las
anteriores). Lo de Random estaría apuntando al tipo de acceso "directo" a la
posición requerida.
- para que se pareciera a la sigla de la "memoria" ROM, lo que seguramente llevó a
Random (por la R) en vez de Direct, que sería lo correcto. Pensemos que nadie
querría almacenar información en un dispositivo que la devolvería en forma
aleatoria, por lo que definitivamente las memorias RAM no son Random.
- por esa manía existente en la industria informática de nombrar a las cosas
utilizando tres letras.
Nota: en francés a las memorias RAM se las llama "memoire vivre" (memoria viva) y a las
ROM se las llama "memoire morte" (memoria muerta), términos que parecen mucho mas
apropiados a las características de estos dispositivos.
Hay distintos tipos de organizaciones de memorias del tipo RAM. Los elementos que
determinan estas variantes son:
- si los datos de entrada (lo que se va a escribir) y de salida (lo que se lee)
comparten los mismos caminos físicos o están separados.
- si tienen mas de una única palabra de n bits.
- si requieren de circuitos de "refresco" (veremos qué significa esto mas adelante).
Cuando se tiene una memoria de una única palabra, con entradas y salidas
diferenciadas se habla de Latch o Registro, cuando se tienen multiples palabras y no se
requiere de circuitos de "refresco", se habla en general de SRAM, por Static RAM (otro
nombre para la polémica, ¿cómo algo que puede ser modificado recibe el nombre de
"estático"?). Lo normal son las SRAM que tienen la entrada y salida coincidentes en las
conexiones, mientras que las de múltiples palabras con entradas y salidas diferenciadas, si
bien existen, están reservadas a aplicaciones específicas (ej: memorias para tarjetas de
video). Finalmente las memorias de multiples palabras que necesitan circuito de refresco,
reciben el nombre de DRAM por Dynamic RAM (no existen memorias tipo Registro que
sean a su vez Dinámicas).
Registro (ó Latch):
Static RAM:
Dynamic RAM:
Registro ó Latch:
Tienen el circuito mas simple. Son un conjunto de flip-flops tipo D, sincrónicos (flanco
ascendente) conectados con su entrada de reloj en común y un control de tercer estado,
también común, en sus salidas.
Están construidas en base a flip-flops tipo D, los cuales tienen sus entradas de
habilitación controladas por un circuito de selección en base a la decodificación de las
entradas de direción (Am).
Veamos como es el circuito asociado al bit Dij (bit j-ésimo de los n de la palabra i-
ésima de las 2m palabras de la memoria), para una memoria SRAM con entrada y salida
independiente:
En el caso que fuera una memoria SRAM con entrada y salida combinadas, el circuito
del elemento de memoria sería de la forma:
Aunque en la práctica se realiza una optimización a nivel del circuito con transistores
que implementa el circuito lógico mostrado para el elemento de memoria, se requieren al
menos 6 transistores para construir cada bit de una memoria del tipo SRAM. Dado que en
cada momento de la evolución de la tecnología la cantidad de transistores que se pueden
colocar en un mismo chip está limitada por la tecnología disponible en ese momento, es un
dato muy importante el número de transistores que se requieren para cada bit, ya que una
disminución en ese número tiene un inmediato impacto en la capacidad del chip de
memoria obtenido.
A este punto se dirige el diseño de las DRAM. Estas memorias utilizan una propiedad
de los transistores: la existencia de la junta entre la base y el emisor (o entre el gate y el
source) produce como efecto lateral la formación de un condensador (capacidad parásita).
Esto lleva a que en este tipo de memorias se requiera solamente un transistor por
cada bit a almacenar. Este hecho ha resultado determinante para el éxito de este diseño, ya
que permite hasta 6 veces mayores capacidades de almacenamiento para cada estadio
tecnológico de la fabricación de chips y ha disimulado las notorias complicaciones de la
circuitería auxiliar requerida por estas memorias para funcionar.
Teniendo como objetivo primario minimizar el tiempo requerido para refrescar un chip
completo de DRAM, y de paso disminuir la cantidad de "patitas" necesarias para el circuito
integrado (en el pasado este fue un problema técnico a resolver, dado que los primeros
encapsulamientos disponibles tenían un número acotado de pinos), estas memorias están
organizadas en forma matricial y la dirección se presenta separada en fila (row) y columna
(column).
Como vemos tanto en el diagrama de bloques como en el pinout, esta DRAM tiene 11
bits de entrada de dirección. Es claro que con 11 bits de dirección no es posible direccionar
directamente los 4 Mbits que dispone la memoria (para ello se requerirían el doble, o sea
22).
El punto es que, como se dijo, estos chips no reciben la información de dirección toda
junta sino que reciben primero la información de la fila y luego la información de columna,
usando los mismos bits de entrada de dirección en momentos distintos. Para ello poseen
los registros internos RAB (Row Address Buffer), también denominado RAR (Row Address
Register) y CAB (Column Address Buffer), también denominado CAR (Column Address
Register), los cuales son cargados con la dirección presente en los bits An en el flanco de
las señales RAS (Row Address Strobe) y CAS (Column Address Strobe).
9.4 Parámetros
9.5.1 SRAM
9.5.2 DRAM
Una de las primeras mejoras al diseño DRAM fue el denominado Fast Page Mode,
donde se optimizaba al acceso, permitiendo múltiples CAS para el mismo RAS. De esta
forma se mejoraba sensiblemente el tiempo de acceso. El nombre se debe a que cada fila
se puede asociar a una página de un libro: una vez que encontré una "palabra" (un bit) en
una "pagina" (fila del chip) las siguientes palabras (bits) las encontraré más rápido si están
en la misma página (fila).
Las DRAM Enhanced Data Out son una mejora sobre las FPM, consistente en
acelerar el acceso al próximo bit, iniciando una lectura por adelantado al bit contiguo al
accedido en un momento dado. De esta forma se ahorra la espera por la circuitería interna
de detección de la carga de almacenamiento.
Las Burst EDO son una mejora, relativamente menor, sobre las EDO, para cuando
las lecturas son en modo de ráfaga (burst).
9.5.6 SDRAM
Las Synchronous DRAM utilizan un reloj para marcar los tiempos de los ciclos de
lectura o escritura y mantener en sincronismo la memoria con el resto del sistema (en
particular con la CPU). Este sincronismo le permite mejorar los tiempos de acceso respecto
a las memorias EDO. En la actualidad todas las memorias DRAM son del tipo sincrónico.
Las SDRAM se sub-clasifican en función de la frecuencia del reloj para la que están
diseñadas, para lo que se utiliza una clasificación propuesta por Intel en su especificación
del computador tipo PC:
9.5.7 RDRAM
Las Rambus DRAM son la propuesta de un fabricante para diseños de DRAM de alta
frecuencia (y por lo tanto altas velocidades de transferencia). Los chips de memoria están
implementados de forma de utilizar ambos flancos del reloj a los efectos de sincronizar las
transferencias. Las frecuencias de reloj disponibles van desde 300 MHz (equivalentes a 600
MHz), 350 MHz (equivalentes a 700 MHz), 400 MHz (equivalentes a 800 MHz), 533 MHz
(equivalente a 1066 MHz) hasta 600 MHz (equivalente a 1200 MHz).
La tecnología que utilizan estas memorias fue diseñada por la empresa Rambus que
licenció sus patentes a distintos fabricantes, entre ellos Intel. Los problemas legales y los
juicios que inició contra distintos fabricantes de memorias (reclamando que la tecnología
DDR desarrollada mas tarde por otros "copia" conceptos de su diseño y por tanto infringen
sus patentes) son tan o incluso más conocidos que sus productos.
Estas memorias utilizan ambos flancos del reloj para realizar las operaciones, de allí
que reciben el nombre de Double Data Rate (Transferencia de Datos Doble). Son un
desarrollo estándar realizado por un conjunto de fabricantes para enfrentar el diseño
patentado de Rambus.
Por razones de mercadeo los nombres comerciales de este tipo de memorias han
sido bastante confusos, en particular porque hacen mención a la "frecuencia equivalente"
que tendría una memoria SDRAM "clásica" que solo hiciera una operación por ciclo.
DDR-200: reloj de 100 MHz (equivale a 200 MHz, también denominada PC-200)
DDR-266: reloj de 133 MHz (equivale a 266 MHz, también denominada PC-266)
DDR-333: reloj de 167 MHz (equivale a 333 MHz, también denominada PC-333)
DDR-400: reloj de 200 MHz (equivale a 400 MHz, también denominada PC-400)
DDR2-400: reloj de 200 MHz (equivale a 400 MHz, también denominada PC2-3200)
DDR2-533: reloj de 266 MHz (equivale a 533 MHz, también denominada PC2-4200)
DDR2-667: reloj de 333 MHz (equivale a 667 MHz, también denominada PC2-5300)
DDR2-800: reloj de 400 MHz (equivale a 800 MHz, también denominada PC2-6400)
DDR2-1066: reloj de 533 MHz (equivale a 1066 MHz, también denominada PC2-
5300)
DDR2-1200: reloj de 600 MHz (equivale a 1200 MHz, también denominada PC2-
9000)
DDR3-800: reloj de 400 MHz (equivale a 800 MHz, también denominada PC3-6400)
DDR3-1066: reloj de 533 MHz (equivale a 1066 MHz, también denominada PC3-
8500)
DDR3-1333: reloj de 667 MHz (equivale a 1333 MHz, también denominada PC3-
10600)
DDR3-1600: reloj de 800 MHz (equivale a 1600 MHz, también denominada PC3-
12800)
Son un paso más en la evolución de las SDRAM, con un voltaje de trabajo menor y
frecuencias mayores a las DDR3, que permiten un menor consumo y una mayor
performance, llegando a frecuencias equivalentes de 4000 MHz.
9.5.12 VRAM
Para los controladores de video de los computadores hasta hace un tiempo se solía
utilizar un tipo especial de memoria (ya sea basada en tecnología SRAM o DRAM), que se
denomina Video RAM y cuya característica principal es contar con "doble puerta". Es decir
son dispositivos que pueden ser leídos a la misma vez que escritos (en direcciones
distintas). Esto es útil para poder mantener el refresco de la información en el monitor a una
velocidad constante (leyendo) a la misma vez que el programa actualiza la información a
desplegar en la pantalla (escribiendo).
Este tipo de memoria son como los "latch" pero organizados en múltiples palabras. En
la actualidad la tendencia es a utilizar memorias GDDR4 / GDDR5 (GDDR = Graphics
DDR), basadas en memorias DDR3, con un sistema de acceso simultáneo a dos páginas,
con lo que simula ser “dual port” como la VRAM.
9.5.13 NVRAM
La Non Volatile RAM es una memoria del tipo RAM que puede conservar su
información aún cuando el sistema donde está insertada queda sin alimentación eléctrica.
La forma tradicional de implementar este tipo de memorias es con un SRAM de bajo
consumo y una batería (ó pila) que le dé alimentación mientras no se dispone de la
alimentación eléctrica general del sistema.
SIMM:
Estos fueron los primeros módulos en imponerse en la industria del PC. La sigla
significa Single In-line Memory Module, ya que si bien la placa de circuito tenía contactos en
ambas caras estos eran en realidad redundantes. Existieron en dos variantes:
DIMM:
Fueron la evolución de los SIMM asociados con la aparición de las SDRAM y las
arquitecturas de memoria de 64 bits (aun para procesadores de 32 bits). La sigla significa
Dual In-line Memory Module.
Los módulos DDR3 también utilizan 240 contactos, aunque como son incompatibles
eléctricamente, tiene la "mueca" de identificación (cortes en forma de "media luna" que
poseen en ambos extremos y en el medio) en otro lugar para evitar confusiones, mientras
que los DDR4 utilizan 288 contactos.
También existen alternativas a cada uno de los tipos anteriores con menor cantidad
de contactos (logrando módulos más pequeños físicamente) diseñados para equipos
portátiles (Notebooks, Palms, etc.).
También existen variantes respecto al voltaje de alimentación (5 Volts, 3.3 Volts, 1.5
Volts) y respecto a si son "buffereados" (también se los denomina "registrados") ó no. Los
módulos "registrados" disponen de circuitería adicional que amplifica las señales entre el
modulo de memoria y el controlador de memoria de la placa principal, dotando de mayor
estabilidad y confiabilidad al circuito. Ambas características se reconocen por la posición de
las muecas de codificación.
RIMM:
Son los módulos utilizados para memorias con tecnología Rambus. También hay
variantes con distinta cantidad de contactos.
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Máquinas de Estado
Arquitectura de Computadoras
(Versión 4.3 - 2012)
10 MAQUINAS DE ESTADO
10.1 Introducción
Dado que puede haber infinitas secuencias de entrada(s) que, a su vez, pueden ser
de largo infinito resulta muy útil introducir una regla que las agrupe y que permita encarar el
problema con un conjunto finito de elementos: los estados.
10.2 Estado
Secuencia A: 011100110101111001101111000000110101011100....
Salida: 000000000000010101010000001000000000001000....
Secuencia B: 101010111001100000000110101011100....
Salida: 000010101010000001000000000001000....
del sistema para entradas posteriores, ya que dicho comportamiento es siempre el mismo
para la misma combinación estado – entrada. De esta característica viene el término de
determinista.
A continuación veremos un caso especial de AFDs, los AFD con salida: las
máquinas secuenciales.
Existen dos planteamientos distintos para este tipo de autómata, la salida puede
estar asociada con el estado (máquina de Moore), ó con la transición (máquina de Mealy).
Consideremos ahora el siguiente ejemplo M = ({e0, e1, e2}, {0, 1}, {y, n}, δ, λ, e0),
donde δ y λ vienen dadas por la siguientes tablas.
δ 0 1
e0 e1 e2
e1 e1 e2
e2 e1 e2
λ 0 1
e0 n n
e1 y n
e2 n y
0/y
e1
0/n
e0 1/n 0/n
1/n
e2
1/y
En el autómata anterior, dada una entrada 01100 genera como salida nnyny. De
esta forma podemos ver como un autómata con salida, computa una función con dominio
tiras del alfabeto Σ, y genera como salida una tira del alfabeto ∆, formada por la
concatenación de los símbolos asociados a cada transición, por la que pasó el autómata al
procesar la tira de entrada.
Podemos ver una versión similar al ejemplo visto para Mealy, pero con las salidas
ahora asociadas a los estados.
e0-/-
1 0
0
e1y/y
0
1
e2n/n e1n/n
1
e2y/y 0
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Circuitos Secuenciales
Arquitectura de Computadoras
(Versión 4.3 - 2012)
7 CIRCUITOS SECUENCIALES
7.1 Definición
Y = G(X, E)
E' = H (X, E)
siendo Y la salida, X la entrada, E el estado interno y E’ el nuevo valor del estado luego de
la transición provocada por la presencia de una nueva entrada.
X
G Y
E Memoria E'
Esto significa que la salida no depende solo de las entradas (como en los sistemas
combinatorios) sino también del llamado vector de estado E.
Los rótulos de los arcos indican los eventos que generan cambios de estado, que
corresponden a los posibles valores del vector de entrada para un nuevo vector de entrada.
Notemos que decir “nuevo vector de entrada” no implica que exista un “nuevo valor del
vector de entrada” (el valor puede ser el mismo que el anterior). Por esto es necesario que
el sistema tenga una forma de reconocer que debe procesar una nueva entrada (aunque el
Y = G(X, E)
E' = H (X, E)
Si el diseño fuera hecho en base a la Máquina de Moore, las ecuaciones deberían lucir así:
Y = G(E)
E' = H (X, E)
ya que en el caso de Moore la salida depende solamente del estado actual de la máquina,
mientras que el nuevo estado nuevo sí depende del estado actual y la entrada.
7.3 Ejemplos
En este primer ejemplo vamos a diseñar un contador de módulo 4 (de 0 a 3). Este
circuito es bastante particular ya que no tiene entrada, por lo que el cambio de estado es
incondicional y ocurre en cada flanco ascendente del reloj. Si se quiere contar los cambios
de nivel (flanco ascendente) de una señal cualquiera, basta utilizar esa señal como reloj del
contador. Si, en cambio, se desea contar las transiciones de 0 a 1 de una señal en forma
sincrónica respecto a un reloj general del sistema, entonces se debe utilizar el contador que
veremos en el próximo punto.
x/0 e0 x/3
e1 e3
x/1 e2 x/2
En En+1 Salida
e0 e1 0
e1 e2 1
e2 e3 2
e3 e0 3
Tengamos presente que esta tabla no hace otra cosa que mostrar la información de
las funciones de transición δ y de salida λ, resumidas en el comúnmente llamado “Diagrama
de Estados” del AFD M = ({e0, e1, e2, e3}, {}, {0, 1, 2, 3}, δ, λ, e0) con salida dibujado.
El diagrama de estados tiene cuatro estados por lo que necesitamos dos flip-flops
para poder representarlos (cuyas salidas anotaremos q1 y q0).
En En+1 Salida
q1 q0 q1 q0 s1s0
00 01 00
01 10 01
10 11 10
11 00 11
Usaremos flip-flops tipo D, por lo que de la tabla anterior podemos pasar a la Tabla
de Verdad, usando la ecuación del flip-flop tipo D:
Qn+1 = Dn
y queda:
q1 q0 d1 d0 s1 s0
00 0 1 0 0
01 1 0 0 1
10 1 1 1 0
11 0 0 1 1
Ahora lo que resta es hacer los diagramas de Karnaugh que minimicen los circuitos
combinatorios que implementarán la función de transición y la función de salida, en base a
las tablas de verdad obtenidas. Dichos circuitos tienen como entrada la(s) entrada(s) del
circuito secuencial, y el valor del estado anterior y como salidas deben dar el próximo
estado (que oficiarán como entradas de los flip-flops tipo D) y la(s) salida(s) esperada(s) del
circuito secuencial en su conjunto, respectivamente.
Dado que la codificación elegida para los estados coincide exactamente con la
salida, resulta que el circuito combinatorio que implementa la función de salida es la
identidad sobre salidas q de los FF. Por esto sólo nos resta minimizar el circuito
combinatorio para la función de transición.
d1
q1 \ q0 0 1
0 0 1
1 1 0
q1 \ q0 0 1
0 1 0
1 1 0
d0 = q0’
0/3
1/0 e0 1/3
0/0 e1 e3 0/2
1/1 e2 1/2
0/1
Al igual que en el caso anterior tenemos cuatro estados por lo que necesitamos dos
flip-flops para poder representarlos. Haremos la misma codificación de los estados en base
al subíndice en binario. La Tabla de Transiciones y Salidas queda de la siguiente forma:
En este caso también usaremos flip-flops tipo D, con lo que pasamos a las
siguientes tablas de verdad:
q1 q0 e d1 d0 s1 s0
000 0 0 1 1
001 0 1 0 0
010 0 1 0 0
011 1 0 0 1
100 1 0 0 1
101 1 1 1 0
110 1 1 1 0
111 0 0 1 1
d1
q1 q0 \ e 0 1
00
01 1
11 1
10 1 1
d0
q1 q0 \ e 0 1
00 1
01 1
11 1
10 1
d0 = q0.e’ + q0’.e
s1
q1 q0 \ e 0 1
00 1
01
11 1 1
10 1
s0
q1 q0 \ e 0 1
00 1
01 1
11 1
10 1
s0 = q0'.e’ + q0.e
El circuito queda entonces:
0/0
1/0 e0 1/3
0/1 e1 e3 0/3
1/1 e2 1/2
0/2
Notemos que el efecto que tiene este cambio sobre el comportamiento del circuito
es que provoca que los cambios en el valor de las salidas del contador ocurren en el flanco
descendente de la entrada (cuando cambia de 1 a 0), en vez del flanco ascendente (cambio
de 0 a 1) como ocurría en el diseño original. Si mantenemos la codificación de los estados
este diagrama se traduce en la siguiente Tabla de Transición y Salida:
q1 q0 e d1 d0 s1 s0
000 0 0 0 0
001 0 1 0 0
010 0 1 0 1
011 1 0 0 1
100 1 0 1 0
101 1 1 1 0
110 1 1 1 1
111 0 0 1 1
Alternativa 1:
V1 1/F
1/F
0/F
0/F E1 V11 1/F
V1101 V110
1/F
Alternativa 2:
V1 1/F
1/F
0/F
0/F E1 V11 1/F
0/F
0/F 1/V 0/F
V1101 V110
1/F
En este caso tenemos 5 estados, por lo que requerimos 3 flip-flops para almacenar
la codificación de los mismos.
q2 q1 q0 e q2 q1 q0 s
0000 0 0 0 0
0001 0 0 1 0
0010 0 0 0 0
0011 0 1 0 0
0100 0 1 1 0
0101 0 1 0 0
0110 0 0 0 0
0111 1 0 0 0
1000 0 0 0 0
1001 0 1 0 1
1010 X X X X
1011 X X X X
1100 X X X X
1101 X X X X
1110 X X X X
1111 X X X X
d2
q 0e \ q 2q 1 00 01 11 10
00 X
01 X
11 1 X X
10 X X
d2 = q1.q0.e
d1
q 0e \ q 2q 1 00 01 11 10
00 1 X
01 1 X 1
11 1 X X
10 X X
d0
q 0e \ q 2q 1 00 01 11 10
00 1 X
01 1 X
11 X X
10 X X
d0 = q'2.q'1.q'0.e + q1.q'0.e'
q 0e \ q 2q 1 00 01 11 10
00 X
01 X 1
11 X X
10 X X
s = q2.e
El circuito queda entonces de la siguiente forma:
Este ascensor atenderá tres pisos: PB, 1° y 2°. Con sideraremos solamente la
botonera interna en la caja como entrada (botones PB, 1° y 2°) y como salida deberemos
controlar el encendido del motor (ON/OFF) y el sentido de marcha (SUBE/BAJA). No nos
preocuparemos de cómo es que se detiene el motor al llegar al piso (obviamente en un
control de ascensor real esto debería ser tenido en cuenta).
PB/OFF,X PB 2° 2°/OFF, X
PB/ON, BAJA 1°/ON, BAJA
PB/ON, BAJA
2°/ON, SUBE
En este caso tenemos 3 estados por lo que precisamos 2 bits para representarlos
(PB → 00, 1° → 01, 2° → 10). Por su lado vamos a codificar la entrada también en 2 bits
(usaremos la misma codificación que para los estados), mientras que para las salidas
tomaremos 1 bit para cada una (OFF → 0, ON → 1, BAJA → 0, SUBE → 1).
q1 q0 e1 e0 q1 q0 m s
0000 0 0 0 X
0001 0 1 1 1
0010 1 0 1 1
0011 X X X X
0100 0 0 1 0
0101 0 1 0 X
0110 1 0 1 1
0111 X X X X
1000 0 0 1 0
1001 0 1 1 0
1010 1 0 0 X
1011 X X X X
1100 X X X X
1101 X X X X
1110 X X X X
1111 X X X X
d1
e1e0 \ q1q0 00 01 11 10
00 X
01 X
11 X X X X
10 1 1 X 1
d1 = e1
d0
e1e0 \ q1q0 00 01 11 10
00 X
01 1 1 X 1
11 X X X X
10 X
d0 = e0
m
e1e0 \ q1q0 00 01 11 10
00 1 X 1
01 1 X 1
11 X X X X
10 1 1 X
s
E1e0 \ q1q0 00 01 11 10
00 X X
01 1 X X
11 X X X X
10 1 1 X X
s = e1 + q'1.e0
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Arquitectura de Computadoras
(Versión 4.3 - 2012)
12.1 Introducción
Y = G (X, E)
E' = H (X, E)
siendo:
Y = salida actual
E' = próximo estado
X = entrada actual
E = estado actual
G = función de salida
H = función de estado
Por tanto una máquina de estados es una máquina lógica general, en el sentido que
puede actuar reconociendo secuencias como traduciendo símbolos. De acuerdo a lo
expresado en la introducción de este capítulo esto significa que una máquina de estas
características es capaz de resolver cualquier problema computable que pueda
presentarse.
X
ROM Y
ROM
E RAM E'
X Y
ROM
E RAM E'
donde hemos juntado las dos ROMs que implementan las funciones G y H en una
sola.
Por tanto la anterior aseveración sobre la máquina lógica general se puede traducir
en que dado un problema cualquiera "resoluble" (multiplicar números o liquidar sueldos, por
decir dos ejemplos) puedo construir una máquina que lo haga.
X Y
RAM
E RAM E'
12.4 Computadora
El esquema anterior si bien es, como dijimos, el más general que podemos utilizar
para representar una computadora, dista bastante de lo que conocemos cotidianamente por
estos equipos. No es sencillo ni directo reconocer en él al "Pentium", el “Core Duo” (o al
"procesador" que sea), ni el disco duro; apenas la memoria parece estar asociada de
alguna manera a la RAM. Ni hablemos del teclado, el mouse y el monitor de video…….
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Arquitectura de Computadoras
(Versión 4.2 - 2011)
13.1 Introducción
Esta arquitectura fue la propuesta por el matemático John von Neumann para la
construcción de la computadora EDVAC en 1945 (la máquina se terminó de construir en
1949), sucesora de la que se considera la primer computadora electrónica, la ENIAC
(1946).
Los conceptos que propuso von Neumann han tenido una vigencia mucho más allá
de la esperada en una industria como la de las tecnologías de la información. Por más que
llame la atención todos los computadores modernos disponibles comercialmente poseen en
el fondo la misma arquitectura que la EDVAC, definida en 1945. Mucho se ha adelantado
en materia de los circuitos lógicos (la organización) que implementan la arquitectura, pero
casi nada en los principios de diseño que planteó von Neumann hace más de 60 años (que
en materia tecnológica representan más de una decena de generaciones completas).
Se puede decir que la idea fundamental de von Neumann se apoya en el hecho que
una operación compleja normalmente se puede dividir como una secuencia ordenada de
operaciones más simples. En otras palabras lo que propuso fue construir una máquina
capaz de ejecutar algoritmos en forma explícita. Para ello introdujo el concepto de
"programa almacenado" como una "secuencia lógicamente ordenada de instrucciones",
siendo las "instrucciones" las operaciones básicas que implementa el hardware a través de
sus circuitos lógicos.
CPU MEM
E/S
13.2 CPU
Para ello la arquitectura de von Neumann propone que la misma cuente con los
siguientes elementos básicos:
De allí que se utilice poca memoria rápida (por el costo) y que se ubique en las
cercanías de donde se va a utilizar (dentro de la CPU) para minimizar su tiempo de acceso.
Así una arquitectura particular (ej: Intel x86, PowerPC, SPARC, MIPS, etc) establece
en forma diferenciada los siguientes elementos característicos, los que deben ser
conocidos por los programadores "de bajo nivel" para poder escribir programas para una de
esas arquitecturas:
Al igual que para los demás tipos de datos manipulados que vimos (caracteres,
números) los computadores trabajan con una representación de las instrucciones mediante
un código binario.
El código binario reserva una serie de bits para identificar la operación realizada por
la instrucción, otros indican los operandos a utilizar y sus direcciones, así como la
indicación de dónde se almacena el resultado.
Los atributos que definen el formato de las instrucciones incluyen aspectos tales
como si los códigos binarios asociados son de largo fijo o variable y si las instrucciones
tienen operandos y destino independientes (en cuyo caso se habla de "arquitectura de 3
direcciones") ó solapados (correspondiente a "arquitectura de 2 direcciones").
MEM
DATOS
E/S CPU
MEM
PROG
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Arquitectura de Computadoras
(Versión 4.3a - 2012)
14.1 Introducción
Como ya dijimos antes una CPU (Centrol Processor Unit) está conformada por tres
sub-sistemas fundamentales: la ALU (Arithmetic Logic Unit, Unidad Aritmética y Lógica), la
CU (Control Unit, Unidad de Control) y el Register Set (también denominado Register Bank)
ó sea Conjunto (o Banco) de Registros.
ALU
Banco de
Registros
Unidad
de
Control
La Unidad de Control es, en definitiva, una máquina secuencial que realiza el “ciclo
de instrucción”: conjunto de acciones ordenado y secuencial que interconectan
adecuadamente los distintos elementos en el tiempo, para lograr el objetivo de ejecutar la
instrucción realizando la operación indicada sobre los operandos correspondientes y
almacenando el resultado en el lugar indicado. Esta máquina secuencial funciona
sincronizada por un reloj, el cual también es utilizado para sincronizar todas las actividades
de los otros elementos del sistema (memoria y entrada/salida). En las primeras
computadoras el reloj era el mismo para todos los elementos. Últimamente se utilizan
relojes independientes (aunque vinculados) para cada sub-sistema. En muchos diseños se
utilizan más de un reloj para la CPU, con la misma frecuencia, pero desfasados (0º, 90º,
180º y 270º, por ejemplo) a los efectos de ser utilizados para sincronizar distintas partes del
circuito compensando los diferentes retardos de propagación de las señales en los circuitos
internos de la CPU.
Notemos que no todas las instrucciones requieren de todos los pasos indicados
para su ejecución. Por ejemplo las instrucciones que tienen sus operandos en registros, no
requieren del paso “read”, mientras que las que no guardan un resultado no requieren del
paso “write”.
PC
AC
SP
IR
TIR
+1
-1
AMASK
SMASK
M0
F
Bus Direcciones
L0 A Latch B Latch L1
MAR
MBR
RD M1, M2, M3
N
F0, F1 Z
WR ALU
S0, S1 Shifter
Notas:
- La interfaz con la memoria y la E/S se realiza a través del bus de datos, el bus
de direcciones y el bus de control (formado por las señales RD y WR).
- Los registros, la ALU y la unidad de Shift son de 16 bits de tamaño de palabra.
- La unidad de desplazamiento no siempre se explicita como en el ejemplo ya que
se puede considerar que forma parte de la ALU.
- Normalmente las ALUs calculan también las salidas C (Carry) y V (oVerflow).
- Los valores de las constantes de los distintos registros está vinculada con las
necesidades de la “macroarquitectura” asociada a la MIC-1 y no constituyen un
requisito en otras microarquitecturas.
- Tener presente que este es tan solo un ejemplo de cómo se puede construir
internamente una CPU y ni siquiera es uno que pueda considerarse óptimo.
- A3, A2, A1, A0: seleccionan un registro y conectan su salida al bus A (ej:
0000/PC, 0001/AC, 0010/SP, 0010/IR, 0100/TIR, 0101/0, 0110/+1, 0111/-1,
1000/AMASK, 1001/SMASK, 1010/A, 1011/B … 1111/F)
- B3, B2, B1, B0: seleccionan un registro y conectan su salida al bus B (ej: idem a
la codificación para A)
- C3, C2, C1, C0: seleccionan un registro y conectan su entrada al bus C (ej: idem
a la codificación para A)
- ENC: habilita el bus C para que se guarde el valor en el registro seleccionado
- X0: selecciona si conecta a su salida la entrada que viene desde el MBR o
desde el bus A (ej: 0 – MBR, 1 – Bus A)
- F1, F0: codifican la operación a realizar por la ALU (ej: 00 – A+B, 01 – A and B,
10 – A, 11 – not A)
- S1, S0: codifican la operación de desplazamiento (ej: 00 – no desplaza, 01 – un
bit a la derecha, 10 – un bit a la izquierda)
- L1, L0: controlan la carga de los registros intermedios del bus B y el bus A
respectivamente.
- M0: controla la carga en el MAR (ej: 1 – carga)
- M1, M2, M3: controlan la forma que se cargan los datos en el MBR, cuando y
desde donde se produce. M1 activa la carga (ej: 1 – carga). M2 es la señal de
lectura de memoria RD (ej: 1 – lee la memoria). M3 es la señal de escritura de
memoria (eg: 1 – escribe la memorias).
Veamos como manejaría la Unidad de Control estas señales de control para lograr
ejecutar el ciclo de instrucción. Consideremos el ejemplo en el que se va a ejecutar una
suma entre un operando en memoria y el acumulador, con modo de direccionamiento
directo (la dirección está en los últimos 12 bits de la instrucción).
Para realizar el paso de read se debe cargar la dirección del operando (contenida en
los últimos 12 bits de la instrucción) en el MAR, para luego realizar una operación de lectura
desde memoria, cargando el MBR desde el bus de datos, de forma de almacenar en él el
operando. Para ello hay que:
- conectar la salida del registro IR al bus B (B3 = 0, B2 = 0, B1 = 1, B0 = 0)
- conectar la salida del registro AMASK al bus A (A3 = 1, A2 = 0, A1 = 0, A0 = 0)
- seleccionar cargar el ALatch (L1 = 1)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar Bus A en el A Mux (X0 = 1)
- seleccionar A and B en la ALU (F1 = 0, F0 = 1)
- seleccionar no desplazamiento en el Shifter (S0 = 0, S1 = 0)
- conectar la entrada del registro A al bus C (C3 = 1, C2 = 0, C1 = 1, C0 = 0)
- habilitar bus C (ENC = 1)
con estas señales y sincronizado por el reloj se guarda la dirección contenida en la
instrucción en el registro A. A continuación (próximo ciclo de reloj) se colocan las señales:
- conectar la salida del registro A al bus B (B3 = 1, B2 = 0, B1 = 1, B0 = 0)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar cargar MAR (M0 = 1)
- seleccionar cargar el MBR (M1 = 1)
- seleccionar lectura de memoria (M2 = 1)
En el paso siguiente se realiza el execute. Para ello se deben activar las siguientes
señales:
- conectar la salida del registro AC al bus B (B3 = 0, B2 = 0, B1 = 0, B0 =1)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar MBR en el A Mux (X0 = 0)
- seleccionar la operación A + B en la ALU (F0 = 0, F1 = 0)
- seleccionar no desplazamiento en el Shifter (S0 = 0, S1 = 0)
- conectar la entrada del registro AC al bus C (C0 = 1, C1 = 1, C2 = 0, C3 =1)
- habilitar bus C (ENC = 1)
Cabe destacar que al ser una instrucción cuyo resultado se almacena en un registro,
no corresponde que exista un paso de write.
cada bus (1 bit para cada uno de los registros) en vez de los 4 utilizados en forma
codificada.
14.7 Microinstrucciones
Cada microinstrucción deberá tener bits disponibles para indicar los valores (0/1) de
las señales que controlan los distintos elementos, a saber:
4 bits para control de bus A
4 bits para control de bus B
4 bits para control de bus C
1 bit para habilitar el bus C
2 bits para control de latches de bus
2 bits para control de la ALU
2 bits para control del Shifter
1 bit para control de AMux
1 bit para control del MAR
3 bits para control del MBR
Por ejemplo:
AMUX
COND
ADDR
ALU
MBR
MAR
ENC
SH
RD
WR
A
0 00 10 00 0 1 1 0 0 0000 0000 0000 00000000 0x10c00000
0 00 10 00 0 0 1 0 0 0000 0000 0000 00000000 0x10400000
1 00 10 00 0 0 0 0 1 0011 0000 0000 00000000 0x90130000
0 00 00 00 0 0 0 0 1 0000 0110 0000 00000000 0x00106000
ADDR
ALU
MBR
MAR
ENC
SH
RD
WR
Las cuatro operaciones de la ALU se representan así (los registros usados son a
modo de ejemplo):
ac:=ac + d ac:=band(ir, smask) f:=ac c:=inv(a)
los registros destino pueden ser cualquiera (incluyendo el MAR y el MBR), pero el MAR no
puede ser operando.
Las distintas expresiones pueden ser combinadas en una misma microinstrucción (la
misma “sentencia”):
tir:=lshift(tir + tir); if n then goto 33
el efecto de esta microinstrucción es guardar en el registro TIR el resultado de realizar un
desplazamiento a la izquierda de 2 bits del propio registro TIR y saltar a la microinstrucción
33 si es que el segundo bit más significativo del valor original del TIR es 1 (notar que la
ALU hace solo la suma que representa el desplazamiento a la izquierda de un bit y por
tanto allí el bit más significativo del resultado es el segundo bit más significativo del
original).
Hay un caso particular de sentencias, donde solo nos interesa determinar un salto
en alguna condición de los bits de un registro, pero no queremos asignarlo a ningún otro
registro. Para ese caso se dispone del “registro virtual” denominado “alu”, que se usa así:
alu:=lshift(tir + tir); if n then goto 33
en este caso el resultado de la operación sobre TIR no afecta a ningún registro, pero la
ALU actúa y computa el valor de la salida N según el resultado de la operación.
Por ejemplo: las codificaciones del primer ejemplo mostrado corresponden a las
siguientes microinstrucciones:
mar:=pc; rd
rd
ir:=mbr
pc:=pc + 1
secuencia que analizada implica que el registro PC (Program Counter) se carga en el MAR
y se activa la señal RD para realizar una lectura de memoria. Luego en la segunda
microinstrucción se mantiene RD activa (esto es porque se está asumiendo que la lectura
de la memoria demora dos ciclos de reloj). La siguiente microinstrucción mueve el
contenido del MBR (lo que fue leído de memoria) al registro IR y finalmente la última
microinstrucción le suma uno al PC. No es difícil identificar esta sucesión de eventos con la
etapa de fetch del ciclo instrucción.
Notar que las instrucciones que tienen operandos directos a memoria contienen una
dirección de 12 bits. Por su lado las operaciones “insp” y “desp” usan un operando
inmediato de 8 bits. Justamente para poder manipular estos valores es que existen los
registros AMASK (máscara de 12 bits) y SMASK (máscara de 8 bits).
Tener en cuenta que esta opción de diseño del formato de instrucción condiciona la
capacidad de direccionamiento de esta CPU (un máximo de 4096 palabras de 16 bits).
También condiciona los modos de direccionamiento de los operandos (solo directo para las
operaciones aritméticas), la disponibilidad de registros (solo se dispone del AC como
registro para operaciones) y los tipos de salto (son todos absolutos).
Notar también que los códigos de operación que definen de qué instrucción se trata
están armados como un “árbol” (a medida que se avanza hacia la derecha aparecen más
opciones según los valores de los bits anteriores). Este diseño determina la forma en que
se puede hacer la decodificación (básicamente a fuerza de desplazamientos sucesivos y
verificación del valor del bit más significativo resultante), aunque la misma es realmente
poco eficiente realizada de esta forma.
NOTAS DE CURSO
(Versión 2.2)
ÍNDICE
DIRECCIONAMIENTO DE MEMORIA............................................................................................................. 2
MODOS DE DIRECCIONAMIENTO................................................................................................................. 3
REGISTRO.......................................................................................................................................................................................3
VALOR o INMEDIATO.....................................................................................................................................................................3
DIRECTO..........................................................................................................................................................................................3
INDIRECTO......................................................................................................................................................................................3
INSTRUCCIONES............................................................................................................................................ 5
CÓDIGO.................................................................................5
ARITMÉTICAS..................................................................................................................................................................................6
ADD....................................................................................6
ADC....................................................................................6
SUB ...................................................................................6
SBB....................................................................................6
MUL....................................................................................7
DIV....................................................................................8
NEG....................................................................................9
CBW....................................................................................9
INC....................................................................................9
DEC...................................................................................10
LÓGICAS........................................................................................................................................................................................11
AND...................................................................................11
OR....................................................................................11
XOR...................................................................................11
NOT...................................................................................12
CMP...................................................................................12
DESPLAZAMIENTO.......................................................................................................................................................................13
SAL/SHL...............................................................................13
SHR...................................................................................14
SAR...................................................................................14
ROL...................................................................................15
ROR...................................................................................16
MOVIMIENTO e I/O........................................................................................................................................................................17
MOV...................................................................................17
IN....................................................................................17
OUT...................................................................................18
MANEJO DE FLAGS......................................................................................................................................................................19
CLC...................................................................................19
STC...................................................................................19
CLI...................................................................................19
STI...................................................................................20
BIFURCACIÓN INCONDICIONAL.................................................................................................................................................21
CALL..................................................................................21
JMP...................................................................................22
RET...................................................................................22
BIFURCACIÓN CONDICIONAL.....................................................................................................................................................23
JA / JNBE (no considera signo)........................................................23
JB / JNAE / JC (no considera signo)...................................................24
JNB / JAE / JNC (no considera signo)..................................................24
JBE/JNA (no considera signo)..........................................................25
JE/JZ ................................................................................25
JG/JNLE (considera signo).............................................................26
JNG/JLE (considera signo).............................................................26
JNE/JNZ...............................................................................27
JNO...................................................................................27
JNS...................................................................................28
JO....................................................................................28
JS....................................................................................29
MANEJO DE STACK......................................................................................................................................................................30
PUSH..................................................................................30
POP...................................................................................30
PUSHF.................................................................................30
POPF..................................................................................31
INTERRUPCIONES.......................................................................................................................................................................32
INT...................................................................................32
IRET..................................................................................32
DIRECCIONAMIENTO DE MEMORIA
Los registros del 8086 son de 16 bits, por lo tanto el número de direcciones posibles a
direccionar con 1 solo registro es:
216 = 6553610 = 1000016
lo cual representa un total de 64 Kbytes y los valores de direcciones se encuentran en el
rango de 0 a FFFF.
Para superar este límite se utilizan 2 registros para direccionar memoria: Uno de
SEGMENTO y otro de DESPLAZAMIENTO (offset) dentro del segmento. La notación
utilizada para una dirección segmentada es:
SEGMENTO:DESPLAZAMIENTO
La relación entre la dirección de memoria real y la dirección segmentada es:
DIR = SEGMENTO * 16 + DESPLAZAMIENTO
Al multiplicar por 16 se obtienen 4 bits más con lo que ahora se tiene:
2 20 = 104857610 = 10000016
con lo cual tenemos un total de 1024Kb = 1Mb de memoria direccionable. Los valores para
las direcciones reales se encuentran en el rango 0 a FFFFFh.
Es importante hacer notar que una misma dirección de memoria puede ser direccionada
con distintos valores de segmento y desplazamiento
Ej:
100:50 = 105:0 =0:1050, trabajando en base 16.
MODOS DE DIRECCIONAMIENTO
Se entiende por modos de direccionamiento a las diferentes formas que pueden tomar los
parámetros de las instrucciones del procesador.
Diferentes autores clasifican en forma distinta los modos de direccionamiento del 8086.
Nosotros distinguiremos fundamentalmente cuatro modos diferentes:
REGISTRO
Un parámetro que direcciona a un registro está utilizando el modo de direccionamiento
REGISTRO.
Ej: MOV Ax,Bx
En este ejemplo los dos parámetros direccionan un registro.
VALOR o INMEDIATO
El modo de direccionamiento INMEDIATO es utilizado cuando se hace referencia a un valor
constante. Este se codifica junto con la instrucción. Es decir dicho parámetro representa a su
valor y no a una dirección de memoria o un registro que lo contiene.
Ej: MOV Ax,500
En este ejemplo el número 500 es un parámetro inmediato.
DIRECTO
Se utiliza el modo directo cuando se referencia a una dirección de memoria y la misma esta
codificada junto con la instrucción.
Ej:
MOV Al,[127]
En este ejemplo el desplazamiento de la dirección de memoria se codifica junto con la
instrucción y el segmento se asume a DS.
Si MEMORIA es un array de bytes que representa a la memoria la instrucción anterior se
puede poner como:
Al := MEMORIA[ DS:127 ]
INDIRECTO
Se utiliza el modo directo cuando se referencia a una dirección de memoria a través de uno
o varios registros
Ej: MOV Al,[Bx]
Aquí el offset de la dirección de memoria está contenido en el registro Bx y al igual que el
caso anterior como no se especifica el segmento se asume DS.
Si MEMORIA es un array de bytes que representa a la memoria la instrucción anterior se
puede poner como:
Al := MEMORIA[ DS:Bx ]
La especificación completa de las expresiones que van dentro de los paréntesis rectos es:
{ Bx | Bp } [ + { Si | Di } ] [ + desplazamiento ] |
{ Si | Di } [ + desplazamiento ] |
desplazamiento
En la Tabla 1 se indican las combinaciones posibles entre registros índice y los segmentos
así como las asignaciones por defecto.
Tabla 1.Combinación entre registros de segmento e indices.
CS SS DS ES
IP Si
SP si
BP Prefijo por defecto prefijo prefijo
BX Prefijo prefijo por defecto prefijo
SI Prefijo prefijo por defecto prefijo
DI Prefijo prefijo por defecto por defecto
(cadenas)
INSTRUCCIONES
Para describir a cada una de las instrucciones usaremos el siguiente formato:
CÓDIGO
Formato: CÓDIGO op1 , op2
Tipo Args: Se indica qué forma puede tomar cada parámetro poniendo debajo del
mismo una lista de códigos entre paréntesis que definimos así:
A dirección absoluta inmediata ( 4 bytes )
a dirección absoluta inmediata ( 2 bytes )
i operando inmediato ( 1 o 2 bytes )
d desplazamiento inmediato ( 1 byte )
r registro de uso general ( 8 o 16 bits )
R registro de uso general ( 16 bits )
m palabra de memoria ( 1 o 2 bytes )
M palabra de memoria ( 2 bytes )
W doble palabra de memoria ( 4 bytes )
CL el nombre de un registro en particular
ARITMÉTICAS
ADD
Formato: ADD op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 + op2
Descripción: Suma los dos operandos y almacena el resultado en op1 , por lo tanto
ambos deben tener el mismo tipo
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
ADC
Formato: ADC op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 + op2 + c
Descripción: Idem a ADD pero además suma el valor del carry.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
SUB
Formato: SUB op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 − op2
Descripción: Idem a ADD pero realiza la resta en lugar de la suma.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
SBB
Formato: SBB op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 − op2 − c
Descripción: Idem a SUB pero además resta el carry.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
MUL
Formato: MUL op
Tipo Args: ( r,m)
Lógica:
si op es de tipo byte ⇒
Ax = Al *op
sino si op es de tipo palabra ⇒
Dx, Ax = Ax* op
fin si
si la mitad superior del resultado es 0
CF = 0
sino
CF = 1
fin si
OF = CF
Descripción: Multiplica sin considerar el signo, el acumulador ( Ax o Ax) por el
operando op según este último sea de tipo byte o palabra.
En caso que op sea de tipo byte ls resultado se almacena en Ax si es de
tipo palabra se almacena en el par de registros Ax , Dx colocando la parte
más significativa en Dx .
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - ? ? ? ? X
DIV
Formato: DIV op
Tipo Args: ( r,m)
Lógica:
si op es de tipo byte ⇒
si Ax div op > FFh ⇒
INT 0
else
Al = Ax div op
Ah = Ax mod op
fin si
fin si
sino si op es de tipo palabra ⇒
si Dx: Ax div op > FFh ⇒
INT 0
else
Ax = Dx: Ax div op
Dx = Ax mod op
fin si
NEG
Formato: NEG op
Tipo Args: ( r,m)
Lógica:
si op es de tipo byte ⇒
op = FFh − op
op = op + 1
sino si op es de tipo palabra ⇒
op = FFFFh− op
op = op + 1
fin si
Descripción: Calcula el complemento a 2 de op
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
CBW
Formato: CBW
Lógica:
siAl < 80h
Ah = 00h
sino
Ah = FFh
fin si
Descripción: Copia el bit 7 del registro AL en todos los bits del registro AH; es decir
expande el bit de signo de AL
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
INC
Formato: INC op
Tipo Args: ( r,m)
Lógica: op = op + 1
Descripción: Incrementa el operando destino.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X -
DEC
Formato: DEC op
Tipo Args: ( r,m)
Lógica: op = op − 1
Descripción: Decrementa el operando destino.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X -
LÓGICAS
AND
Formato: AND op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica:
op1 ← op1 ∧ op2
CF = OF = 0
Descripción: Calcula el "y" lógico bit a bit entre op1 y op2 .
Banderas:
OF DF IF TF SF ZF AF PF CF
0 - - - X X ? X 0
OR
Formato: OR op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica:
op1 ← op1 ∨ op2
CF = OF = 0
Descripción: Calcula el "o" lógico inclusivo bit a bit entre op1 y op2
Banderas:
OF DF IF TF SF ZF AF PF CF
0 - - - X X ? X 0
XOR
Formato: XOR op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica:
op1 ← op1 ⊗ op2
CF = OF = 0
Descripción: Calcula el "o" lógico exclusivo bit a bit entre op1 y op2 .
Banderas:
OF DF IF TF SF ZF AF PF CF
0 - - - X X ? X 0
NOT
Formato: NOT op
Tipo Args: ( r,m)
Lógica: op ← ¬op
CMP
Formato: CMP op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 − op2
Descripción: Resta op1 de op2 pero solo afecta las flags ignorando el resultado. Los
operandos quedan inalterados pudiéndose consultar las flags mediante una
operación de bifurcación condicional.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
DESPLAZAMIENTO
SAL/SHL
Formato: SAL op1 , op2
SHL op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: corre op1 , op2 lugares a la izq.
Ej: SAL Al,1
CF Al
Antes ? a b c d e f g h
Al
Despues h b c d e f g h 0
Descripción: Desplaza a la izquierda los bits de op1 el nro. de bits especificado por op2 .
Los bits a la derecha se rellenan con ceros.
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X ? X X
SHR
Formato: SHR op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: corre op1 , op2 lugares a la der.
Ej: SHR Al,1
Al CF
Antes a b c d e f g h ?
Al
Despues 0 a b c d e f g h
Descripción: Desplaza a la derecha los bits de op1 el nro. de bits especificado por op2 .
Los bits a la derecha se rellenan con ceros.
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X ? X X
SAR
Formato: SAR op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: corre op1 , op2 lugares a la derecha expandiendo el signo.
Ej: SAR Al,1
Al CF
Antes a b c d e f g h ?
Al
Despues a a b c d e f g h
Descripción: Desplaza a la derecha los bits de op1 el nro. de bits especificado por op2 .
Los bits a la derecha se rellenan con el signo del primero operando.
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X ? X X
ROL
Formato: ROL op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: rota op1 , op2 lugares a la izquierda.
Ej: ROL Al,1
CF Al
Antes ? a b c d e f g h
Al
Despues a b c d e f g h a
Descripción: Rota a la izquierda los bits de op1 el numero de bits especificado por op2
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
OF contiene el xor del CF con el bit más significativo del resultado.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - - - - - X
ROR
Formato: ROR op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: rota op1 , op2 lugares a la izquierda.
Ej: ROR Al,1
Al CF
Antes a b c d e f g h ?
Al
Despues h a b c d e f g h
Descripción: Rota a la derecha los bits de op1 el numero de bits especificado por op2
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
OF contiene el xor del CF con el bit menos significativo del resultado.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - - - - - X
MOVIMIENTO e I/O
MOV
Formato: MOV op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op2
Descripción: Transfiere un byte o una palabra desde el operando fuente al operando
destino.
Ambos operandos deben ser del mismo tipo (byte o palabra).
El contenido especificado por el elemento fuente se copia sobre el
elemento destino, quedando inalterado el elemento fuente.
Atención: No se puede mover memoria a memoria.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
IN
Formato: IN op1 , op2
Tipo Args: (AL, AX) (i,DX)
Lógica:
si op1 = Al
Al = I/ O(op 2 )
sino si op1 = AX
Ax = I/ O(op 2 )
fin si
Descripción: Transfiere un byte o una palabra de una puerta de entrada del procesador
al registro Al o Ax, respectivamente.
El nro. de la puerta se puede especificar mediante:
• Un valor fijo (de o a 255).
• Un valor variable, el contenido en el registro Dx (de 0 a 65535),
pudiéndose acceder a 64K puertas de entrada.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
OUT
Formato: OUT op1 , op2
Tipo Args: (i,DX) (Al, Ax)
Lógica:
si op1 = Al
I/ O(op 2 ) = Al
sino si op1 = Ax
I/ O(op 2 ) = Ax
fin si
Descripción: Transfiere un byte o una palabra desde el registro Al o Ax a una puerta de
salida del procesador
El nro. de la puerta se puede especificar mediante:
• Un valor fijo (de o a 255).
• Un valor variable, el contenido en el registro Dx ( de 0 a 65535),
pudiéndose acceder a 64K puertas de salida.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
MANEJO DE FLAGS
CLC
Formato: CLC
Lógica: CF := 0
Descripción: Borra la bandera de acarreo (CF) sin afectar a ninguna otra bandera.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - 0
STC
Formato: STC
Lógica: CF := 1
Descripción: Pone en 1 la bandera de acarreo (CF) sin afectar a ninguna otra bandera.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - 1
CLI
Formato: CLI
Lógica: IF := 0
Descripción: Borra la bandera de activación de interrupciones (IF) y desactiva las
interrupciones enmascarables (las que aparecen sobre la linea INTR del
procesador).
• Las interrupciones enmascarables se pueden activar o desactivar.
• Las interrupciones no enmascarables (las que aparecen sobre la
linea NMI) no se pueden desactivar.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - 0 - - - - - -
STI
Formato: STI
Lógica: IF := 1
Descripción: Pone en 1 la bandera de activación de interrupciones (IF) y activa las
interrupciones enmascarables (las que aparecen sobre la linea INTR del
procesador)
Una interrupción pendiente no será reconocida hasta que no se haya
ejecutado la instrucción que sigue a STI.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - 1 - - - - - -
BIFURCACIÓN INCONDICIONAL
CALL
Formato: CALL op1
Tipo Args: (R,M,a,A,W)
Lógica:
Si llamada FAR
PUSH CS
PUSH IP
CS := segmento op1
IP := offset op1
sino { llamada NEAR }
PUSH IP
IP := op1
fin si
Descripción: Modifica el flujo de control, cambiando el puntero de programa (CS:IP) a la
dirección indicada por op1 , guardando previamente en la pila la dirección
de la instrucción siguiente, para volver a esta instrucción una vez ejecutado
el procedimiento.
El procedimiento llamado puede estar:
• Dentro del mismo segmento (llamada NEAR). En este caso, se
almacena en la pila el desplazamiento de la instrucción siguiente.
• En otro segmento (llamada FAR). En este caso se almacena en la
pila primero el segmento y segundo el desplazamiento de la
instrucción siguiente.
La llamada puede ser a su vez:
JMP
Formato: JMP op1
Tipo Args: (R,M,a,A,W)
Lógica:
Si llamada FAR
CS := segmento op1
IP := offset op1
sino
IP := op1
fin si
Descripción: Igual al CALL sin guardar la dirección de retorno en el stack:
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
RET
Formato: RET
Lógica:
POP IP
si procedimiento FAR
POP CS
fin si
Descripción: Retorna de un procedimiento invocado por un CALL, utilizando como
dirección de retorno el valor almacenado en el tope del stack.
El ensamblador genera un RET distinto según el procedimiento sea NEAR
o FAR:
• SI es NEAR se asume que en el tope del STACK contiene el nuevo
valor de IP.
• SI es FAR se asume que en el tope del STACK contiene el nuevo
valor de IP y luego esta el nuevo valor de CS.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
BIFURCACIÓN CONDICIONAL
Este conjunto de instrucciones se utilizan para efectuar un salto CONDICIONAL a una
dirección de memoria ubicada en el segmento CS a una distancia menor a 128 bytes de la
instrucción actual.
Todas verifican cierta condición que deben cumplir algunos bits del registro de flags para
realizar la transferencia de control. Si dicha condición no se cumple entonces el salto no se
realiza.
JE/JZ
Formato: JE op1
JZ op1
Tipo Args: (d)
Lógica:
Si ZF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
ZF=1 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JC DIR. ; saltar a DIR si a = b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
JNE/JNZ
Formato: JNE op1
JNZ op1
Tipo Args: (d)
Lógica:
Si ZF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
ZF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNE DIR. ; saltar a DIR si a ≠b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
JNO
Formato: JNO op1
Tipo Args: (d)
Lógica:
Si OF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
OF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
ADD a,b ; a=a+b
JNO DIR. ; saltar a DIR si no hubo overflow
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
JNS
Formato: JNS op1
Tipo Args: (d)
Lógica:
Si SF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
SF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNS DIR. ; saltar a DIR si a ≥b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
JO
Formato: JO op1
Tipo Args: (d)
Lógica:
Si OF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
OF=1.
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
ADD a,b ; a=a+b
JO DIR. ; saltar a DIR si hubo overflow
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
JS
Formato: JS op1
Tipo Args: (d)
Lógica:
Si SF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
SF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNS DIR. ; saltar a DIR si a < b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
MANEJO DE STACK
El stack del 8086 está implementado utilizando fundamentalmente las operaciones PUSH
y POP conjuntamente con los registros SS y SP.
El tope del stack está apuntado por SS:SP y las operaciones PUSH y POP los actualizan
de forma de obtener la semántica de stack como veremos más adelante.
PUSH
Formato: PUSH op1
Tipo Args: (R,M)
Lógica:
SP=SP-2
MOV SS:[SP], op1
Descripción: Decrementa el puntero del stack, SP y transfiere la palabra especificada
por op1 a la dirección SS:SP
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
POP
Formato: POP op1
Tipo Args: (R,M)
Lógica:
MOV op1 ,SS:[SP]
SP=SP+2
Descripción: Transfiere la palabra en tope del stack al operando op1 y luego incrementa
el puntero del stack, SP.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
PUSHF
Formato: PUSHF
Lógica:
SP=SP-2
MOV SS:[SP],FLAGS
Descripción: Coloca el registro de flags en al tope del stack.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
POPF
Formato: POPF
Lógica:
SP=SP-2
MOV FLAGS, SS:[SP]
Descripción: Restaura los registros de flags desde el tope del stack.
Banderas:
OF DF IF TF SF ZF AF PF CF
X X X X X X X X X
INTERRUPCIONES
La tabla de interrupciones del 8086 se encuentra en la dirección absoluta 0 y ocupa el
primer kilobyte de memoria.
Dicha tabla posee 256 entradas de 4 bytes cada una. La entrada i-ésima de esta tabla
posee la dirección de memoria del manejador de la interrupción i. Los primeros 2 bytes
corresponden al offset del manejador y los últimos 2 corresponden al segmento del mismo.
INT
Formato: INT op1
Tipo Args: (i)
Lógica:
PUSHF
IF=0
TF=0
CALL FAR tabla_int( op1 )
Descripción: Genera una interrupción software tipo op1 .
Banderas:
OF DF IF TF SF ZF AF PF CF
- - x x - - - - -
IRET
Formato: IRET
Lógica:
RET
POPF
Descripción: Retorna de una interrupción. Funciona en forma equivalente al RET
utilizado para retornar de una llamada CALL con la diferencia que esta
instrucción restaura las flags del stack antes de retornar.
Banderas:
OF DF IF TF SF ZF AF PF CF
X x x x x x x x x
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Entrada / Salida
Arquitectura de Computadoras
(Versión 4.4 - 2024)
15 ENTRADA/SALIDA
15.1 Introducción
15.2 Buses
CPU MEM
E/S
Por lo indicado en este bus principal pueden distinguirse a su vez tres buses
secundarios:
bus de direcciones:
formado por las líneas de conexión que transportan las direcciones de
memoria o E/S a ser accedidas durante la transferencia
bus de datos:
formado por las líneas de conexión que transportan la información que es
transferida sobre el bus entre los distintos componentes conectados
bus de control:
formado por las líneas de conexión que transportan señales que controlan el
uso del bus y la comunicación sobre el mismo. Algunas de las señales típicas
presentes en este bus son:
Memory_Read (indica una operación de lectura sobre la memoria)
Memory_Write (indica una operación de escritura sobre la memoria)
Según sea el tamaño del sub-bus de datos se habla de buses de 16, 32 o 64 bits
(estos son los tamaños habituales al presente). También caracteriza a un bus si el sub-bus
de datos es separado del sub-bus de direcciones o está multiplexado en el tiempo con él.
En particular estas dos características, unidas a la frecuencia del reloj utilizado para el
sincronismo, determinan la capacidad de transferencia de información del bus.
Bus Simple
Este tipo de buses se implementan en una filosofía "Master-Slave" ("Maestro-
Esclavo"). Existe una sola entidad que controla el uso del bus en todo momento (el
"Master"), típicamente la CPU, quien inicia, controla y participa de todas las
transferencias que se realizan en el bus. Todas las transacciones sobre el bus se
realizan bajo su supervisión. Las entidades "esclavas" que deseen utilizar el bus
tienen que esperar ser habilitados por el "maestro", el cual o bien utiliza técnicas de
"polling" (consulta) para determinar si una entidad esclava desea hacer una
transferencia o bien dispone de algún mecanismo por el cual la entidad interesada
en realizar una transferencia le avisa de este interés (ej: por un pedido de
interrupción).
Bus Inteligente
En estos buses cualquier entidad conectada puede tener, al menos potencialmente,
la capacidad de convertirse en el "Master" del bus (se dice que tiene la capacidad de
"bus mastering") y comandar una transferencia. Al momento que una o varias
entidades requieren hacer uso del bus ocurre una competencia por el uso del
mismo, la cual es resuelta por un mecanismo de arbitraje que determina cuál de los
contendientes pasa a ser el "master", mientras que el resto permanecerá como
"slave" hasta que se termine la transacción.
Existe otra clasificación de los buses que apunta a categorizarlos según sea la
aplicación a la que se destinan, en función de la ubicación de las entidades a conectar en
relación a lo que se podría definir como "frontera" del sistema. Si bien esta clasificación es
discutible y eventualmente varía con el tiempo ó con el alcance de lo que consideremos
"sistema", los buses se suelen distinguir entre:
Por otra parte están los que podemos denominar buses de expansión, que se
Es un bus histórico que tiene sus orígenes en la década del 70. Fue diseñado por
Motorola, originalmente para su familia de microprocesadores 68000. Mantiene su
aplicabilidad en sistemas embebidos y sistemas de control en general. Es un bus
inteligente con arbitraje centralizado, realizado por la tarjeta que se inserte en la
primera ranura, con prioridad jerárquica o circular. Utiliza conectores (formato DIN
europeo) tanto en la tarjeta de expansión como en el “backplane” (conjunto de
conectores “macho” con alimentación que implementa el bus). Un sistema construido
con VMEbus dispone de un chasis con el “backplane” y la fuente de alimentación en
el cual se insertan las tarjetas. El procesador (tarjeta que contiene el
microprocesador y la memoria) es una tarjeta que se inserta como cualquier otra de
expansión (normalmente en el primer slot para oficiar como árbitro del bus).
La siguiente fotografía muestra un chasis con bus VME y una tarjeta para el mismo.
NuBus
Los dispositivos periféricos de entrada/salida son los que realizan el vínculo del
computador con el mundo exterior. A través de ellos se realiza el ingreso de programas y
datos a procesar (mediante teclados, lectores de distinto tipo, etc) y se obtienen los
resultados del proceso de la información en un formato que sea "legible" para el ser humano
(impreso en papel, desplegado en una pantalla, etc) ó se provoca alguna alteración del
mundo físico circundante (ej: encendido de una luz). A este tipo de periféricos a veces se
los denomina "de interfaz" o "transductores".
Transductores:
Teclado
Apuntador (más conocido como Ratón)
Impresora (Matriz, Chorro de Tinta, Laser)
Monitor (CRT, LCD, Plasma)
Escáner
Tableta de Digitalización
Almacenamiento:
Diskettera
Disco Magnético
Disco Optico (CD, DVD)
Cinta (QIC, DAT, DLT)
Comunicación:
Modem (Analógico, RDSI, ADSL)
Red Ethernet
CPU MEM
Cont. Perif.
CPU MEM
Bridge
Cont. Perif.
CPU MEM
CPU MEM
Cont. Perif.
CPU MEM
Bridge
Cont. Perif.
CPU MEM
Una propiedad interesante de los registros de E/S es que aún en el caso que se
accedan como memoria, no se comportan como memoria, pudiendo tener comportamientos
bien diferentes tales como:
sólo lectura:
el registro solo puede ser leído y si se escribe en él no se logra ningún efecto
(es decir si luego de escribir se lee, lo que se lee no es lo que se escribió).
sólo escritura:
el registro solo puede ser escrito y si se lee se obtiene un resultado
impredecible (los datos que se leen pueden ser cualquier cosa).
lectura/escritura independiente:
en este caso se tienen dos registros diferentes, uno de sólo lectura y otro de
sólo escritura accesibles en la misma dirección de E/S. Por lo que si bien se
puede escribir y leer en la misma dirección, las posiciones de memoria
accedidas son separadas e independientes, por lo que, obviamente, lo que
se escribe no puede ser leído posteriormente.
lectura/escritura normal:
estos registros de E/S se comportan como una posición de memoria normal,
lo que se escribe puede ser leído más tarde
palabra pueden tomar cualquier valor, con lo que la comparación del contenido del byte ó
palabra con valores debe hacerse mediante el uso de máscaras (haciendo el AND bit a bit
con un valor que tenga en uno aquellos bits que nos interesan, de forma que el resultado
tenga únicamente en cuenta los bits que sí están definidos ó aquellos que nos interesan en
cada momento). Algo similar ocurre al escribir, en algunos registros determinados bits que
no están definidos deben, de todos modos, escribirse en un valor determinado (0 ó 1).
Datos Entrada:
este registro contiene un dato destinado a la CPU, proveniente del periférico,
del propio controlador o de la línea de comunicaciones.
Datos Salida:
este registro contiene un dato proveniente de la CPU y destinado al
periférico, al propio controlador o a la línea de comunicaciones.
Estado:
este registro contiene bits que indican el estado del controlador en sí mismo
o del periférico que controla (ej; si hay un dato en el registro de entrada, si
está libre el registro de salida, si hay un pedido de interrupción pendiente, si
hay alguna condición de error en el controlador ó el periférico, etc).
Control:
este registro contiene bits que le indican al controlador de E/S ó al periférico
realizar determinada acción (ej: ponerse en línea, reiniciarse, que lea el dato
del registro de salida, etc). En algunos controladores de E/S antiguos
también se controlaban qué registros eran accesible en cada momento en
una dirección de E/S específica (por ejemplo se implementaban stacks de
registros y con un bit del registro de control se hacía el “push” y con otro el
“pop”).
Con la aparición del bus PCI en 1993 y el bus AGP en 1997 la topología cambió y la
mayor complejidad del sistema de memoria y la necesidad de un mejor manejo del DMA
(Direct Memory Access) llevó a la aparición de dos controladores con funciones
especializadas: el “Northbridge” que se encarga del control de los accesos a la memoria y
de los buses especializados (como el AGP) y el “Souhbridge” responsable del control de los
demás buses y periféricos.
El esquema es:
A partir del año 2000, Intel introduce cambios y deja de utilizar el PCI como “bus
central” del sistema, buscando lograr mejores velocidades de transferencia entre los
distintos componentes. De allí que reemplaza la terminología “northbidge” y “southbridge”
por la de “hubs”: MCH (Memory Controller Hub = Northbridge) y ICH (IO Controller Hub =
Southbridge).
Estos dos controladores están inicialmente unidos por el “Hub Link Bus”,
actualmente reemplazado por el DMI (Direct Memory Interface). Otra característica
importante de este re-diseño es que desaparece el ISA Bus, y las conexiones con
dispositivos de baja velocidad (el Super IO y el Firmware = BIOS) se hace a través de un
nuevo bus: el LPC (Low Pin Count).
La tendencia a partir de 2007 fue eliminar el uso de los buses AGP y PCI y basar
toda la E/S en el bus PCI-Express (PCI-e). Esta tendencia aparece asociada al desarrollo
de los “chipsets” vinculados a los procesadores “Core 2” de Intel.
En el caso del Core i5 se busca un diseño simple de bajo costo, realizable con
básicamente dos chips: la CPU y un PCH (Peripheral Controller Hub) que reemplaza al ICH.
Para el Core i7 se busca un diseño de alta performance con un IOH (Input Output
Hub) destinado en exclusivo para los dispositivos de muy altos requerimientos de
transferencia de datos, como los controladores gráficos.
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Interrupciones
Arquitectura de Computadoras
(Versión 4.3 - 2012)
16 INTERRUPCIONES
16.1 Introducción
Una forma de diseño de este programa implica que el programa esté en un “loop”
(con una estructura tipo while) esperando por la aparición de un carácter en el puerto serie
del computador al que está conectado el terminal. Cuando éste aparece lo procesa para
desplegarlo en la pantalla, mueve el cursor un lugar hacia delante (eventualmente
cambiando de línea) y vuelve al bucle de espera por un nuevo carácter.
Esto significa que el tiempo entre que el usuario digita una letra y la siguiente es del
orden de 0,2 segundos (200 ms).
Una idea que surge casi enseguida es: ¿porqué no utilizar esas “instrucciones
muertas” para atender los requerimientos de otros usuarios?. Podríamos, por ejemplo,
conectar múltiples terminales “tontas” con un programa de edición de texto que fuera
consultando los distintos puertos de comunicación serie de forma de detectar los caracteres
que vayan llegando y procesando los mismos.
Otra razón por la cual se utiliza este mecanismo tiene que ver con la eficiencia del
acceso a los dispositivos de entrada/salida y, en particular, a los dispositivos de
almacenamiento masivo.
Una gran proporción de los programas utiliza las unidades de disco para almacenar
la información que requieren procesar y para guardar el resultado de ese proceso en los
denominados sistemas de archivos. Estos dispositivos involucran habitualmente
elementos mecánicos en su construcción (ej: discos que giran y que son leídos por una
cabeza que se desplaza movida por un "actuador"). Los "tiempos de respuesta" de los
dispositivos mecánicos son siempre varios órdenes de magnitud más lentos que los
electrónicos. Por ejemplo un disco moderno tiene un muy buen tiempo de acceso (se
denomina así al tiempo promedio para acceder al bloque de información grabado en alguna
de sus pistas) respecto a los diseños originales, estando actualmente por debajo de los 10
ms. Sin embargo ese tiempo es "una eternidad" si lo comparamos con el tiempo de acceso
de una memoria electrónica (entre 10 ns y 100 ns).
Esta situación lleva al hecho que si un programa requiere un dato de un disco debe
esperar del orden de 10 ms para poder disponer de él. Aún si tomamos el ejemplo del
procesador de 1 MIPS (en la práctica hoy se utilizan procesadores capaces de ejecutar
cientos de MIPS) vemos que durante ese tiempo de espera el procesador podría haber
ejecutado del orden de 10.000 instrucciones. Por esto realizar la sincronización de la
entrada/salida mediante la técnica de enviar el comando correspondiente y quedarse a
esperar la respuesta resulta en algo sumamente ineficiente.
Al igual que en el caso de las terminales tontas, aquí conviene utilizar el procesador
para ejecutar otros programas mientras los controladores de E/S, con su inteligencia propia,
realizan la operación requerida y cuando terminan "avisan" que los datos ya están
disponibles en algún lugar accesible a tiempos "electrónicos" (ej: un "buffer" en el
controlador de E/S ó incluso en la propia memoria del sistema).
Al igual que en el caso anterior la solución pasa por un programa especial (el
Sistema Operativo) que se encargue de la E/S y por el mecanismo de interrupciones que
habilite la posibilidad de avisar de la culminación de la operación de E/S solicitada.
16.3 Definición
Por otro lado nos referimos a que es en respuesta a un evento externo, que está
generado por el hardware de entrada/salida, es decir que no es el programa que lo genera
(al menos no en forma directa), siendo provocado por el hardware, en particular el asociado
a los dispositivos de entrada/salida, más concretamente: los controladores de E/S.
Este pedido se genera a raíz de alguna condición detectada por el controlador (ej:
dispone de un dato para ser leído por la CPU, terminó de ejecutar la lectura del sector de
disco solicitada, hay una condición de error en el byte recibido por la línea de
comunicaciones, etc, etc).
Las condiciones que generan el pedido varían de acuerdo al tipo de controlador que
se trate y de acuerdo a como esté configurado el mismo. Hay controladores capaces de
solicitar interrupciones ante determinadas y diferentes condiciones de error, pero que
pueden ser programados para no hacerlo a través de bits que habilitan/deshablitan la
posibilidad que una situación particular pueda generar, o no, una interrupción.
En las CPUs también existe esta señal, que recibe denominaciones similares (INT,
IRQ, etc), pero que es de entrada. Esta entrada es la que el hardware de la CPU consulta
para determinar si hay algún pedido de interrupción por parte de algún controlador de E/S.
Luego veremos que esto tiene sus implicancias en el diseño de las rutinas de
servicio a las interrupciones.
Para atender una solicitud de interrupción, la CPU realiza los siguientes pasos:
• salva el valor actual del puntero de instrucción (IP), como forma de poder
regresar a ejecutar la siguiente instrucción del programa que fue interrumpido,
luego de la ejecución de la rutina de servicio a la interrupción.
Es de destacar que las distintas arquitecturas realizan esta actividad de
diferentes formas. Podemos distinguir básicamente dos:
- utilizando un stack. Esta vía es la habitual en las arquitecturas que
implementan un stack por hardware, como es el caso de los
procesadores Intel.
- utilizando un registro. Esta vía es la habitual de las arquitecturas RISC,
en particular la SPARC.
Es normal que un sistema tenga múltiples controladores de E/S. Por tanto hay que
tener un mecanismo que permita saber cuál controlador de E/S generó un pedido concreto
En este caso el propio CPU tiene múltiples entradas INT (numeradas, por ej: INT0,
INT1, INT2, etc) y la idea es conectar un controlador de E/S a cada una de ellas. La
identificación es entonces por hardware y directa: el controlador que está pidiendo la
interrupción es el que está conectado a la entrada INTn donde se detecta la solicitud. En
este caso hay una dirección de la rutina de servicio a la interrupción por cada línea de
pedido disponible.
CPU MEM
INT
Este mecanismo, si bien técnicamente es viable, parte del supuesto que cada
controlador de E/S existente tendrá su propio identificador (fijado en el hardware). Esto
sumado al hecho que inicialmente se reservaron solamente 8 bits para dicho identificador
llevó a que no fuera posible acomodar las distintas variantes de controladores que los
distintos fabricantes diseñaban. Esto sumado al hecho que solamente los
microprocesadores de Intel tenían este mecanismo, llevó esta propuesta al fracaso
comercial y en poco tiempo la propia Intel debió reconocer que no podía imponer a la
industria su idea y generó el concepto de controlador de interrupciones como forma de
permitir que un controlador de E/S que no estuviera diseñado para usar este mecanismo
pudiera de todos modos conectarse a un sistema con INTA.
CPU MEM
INT IRQ0
Cont. Cont.
INTA Int.
IRQ7
Cont.
Esta categoría aplica cuando todos los controladores de E/S conecten su salida de
pedido de interrupción en OR-Cableado a la única entrada INT de la CPU. Más
genéricamente aplica cuando hay múltiples controladores conectados en OR a la misma
entrada de INT, sea ésta única o no. En esta situación la rutina de servicio de la
interrupción debe tener una parte inicial que consista en el recorrido de los distintos
controladores de E/S, leyendo los registros de estado hasta encontrar aquél que tenga su
bit de "pedido de interrupción" en "1". En ese caso se invocará a la sub-rutina asociada a
ese controlador específico.
INT CPU
INT-B
INT-A
Enfrentado a este problema una primer solución que viene a la mente es que la
rutina de servicio de la interrupción consulte el estado del controlador B antes de terminar
su ejecución. Si el controlador B tiene un pedido pendiente se lo atiende y entonces su
salida baja a 0 y se resuelve el tema. ¿Se resuelve?. Falso. Porque si bien resolvimos la
situación concreta analizada, es fácil ver que si mientras estoy atendiendo al controlador B,
el controlador A vuelve a pedir interrupción y al terminar de procesar el B la rutina de
servicio termina, estaremos en un problema similar (sólo que esta vez será el A el que
bloquea el mecanismo). Esta situación podría repetirse múltiples veces, con lo que
parecería no haber solución al problema. Sin embargo existe una estrategia de diseño de la
rutina de servicio que permite que el sistema de pedidos de interrupción no se tranque al
utilizar detección por flanco con múltiples controladores en la misma línea de solicitud. Esta
estrategia será motivo de un ejercicio práctico, aunque se puede adelantar que la misma
tiene que ver con asegurarse de alguna forma que la entrada INT estuvo en algún momento
en 0, con lo que no interesa el estado de dicha entrada al momento de salir de la rutina de
servicio de la interrupción. Si esto ocurrió (INT estuvo en 0 en algún momento), entonces se
habrá detectado un nuevo flanco y por tanto si el flanco existió la rutina de atención será
invocada nuevamente.
16.8 Prioridades
sido habilitadas.
Como regla general sólo se aceptará una interrupción de un nivel igual o superior
(en algunas arquitecturas puede ser solamente si es superior en sentido estricto) al de la
interrupción que está siendo actualmente atendida.
una nueva solicitud, se compara el nivel de la interrupción asociado al nuevo pedido con el
actual y sólo se procede si es mayor ó igual (ó mayor estricto) al actual. Ese valor es
actualizado al momento de invocar la rutina de interrupción.
Parte de este contexto es salvado por el hardware quién, además del puntero de
instrucción, en algunas arquitecturas salva el registro de estado del procesador (o registro
de banderas o flags) como es el caso de Intel x86. Pero el resto debe ser salvado (o no
alterado) por la propia rutina de interrupción, con las consideraciones correspondientes a
dos situaciones distintas: no es lo mismo si la máquina es no dedicada que si es
dedicada.
recursos compartidos del sistema (típicamente los registros de la CPU) de forma que se
evite la necesidad de tener que salvarlos en la rutina de interrupción e incluso puede existir
la necesidad de que la rutina de interrupción modifique alguna variable del programa
interrumpido (típicamente el programa principal) de forma de alertarlo de alguna condición
ocurrida en la E/S y comunicada por este mecanismo.
No hay una regla general que indique cuál de las estrategias es la más apropiada.
Quizás lo que sí se pueda decir es que conviene alguno de los casos extremos, porque la
distribución de la lógica entre el programa principal y las rutinas vuelve bastante engorroso
el análisis y la depuración (debug) del código resultante.
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Jerarquía de Memoria
Arquitectura de Computadoras
(Versión 4.3 - 2012)
19 JERARQUIA DE MEMORIA
19.1 Introducción
Este capítulo está dedicado al análisis de los distintos niveles de memoria existentes
en un computador, con especial énfasis en los sistemas de “cache”.
1ns Cache L1 Ks
10ns Cache L2 Ms
Mb cuesta unos U$S 8, mientras que un chip DRAM (construido con tecnología de
memorias dinámicas) de 2 Gb sale U$S 1. Esto significa que la memoria SRAM cuesta
4000 veces más que la memoria DRAM !!. Esto lleva a la inviabilidad económica de
construir computadoras con memoria principal basada en tecnología SRAM.
Por otra parte en la década de los 90 del siglo pasado las tecnologías utilizadas para
implementar tanto la lógica de los procesadores como la de las memorias era bastante
similar en materia de la frecuencia de trabajo. Sin embargo la frecuencia de trabajo de la
lógica empezó a aumentar a un ritmo mayor que la de la memoria (en particular los circuitos
de memoria utilizados para la memoria RAM principal).
Memoria Logica
6000
5000
4000
MHz
3000
2000
1000
0
1992 1994 1996 1998 2000 2002 2004 2006 2008 2010
Este fenómeno de diferencia notoria en las frecuencias de trabajo fue la que llevó a
la necesidad de mejorar y ampliar el uso de las memorias cache (tipo de memoria que
desarrollaremos más adelante) y de hecho se pasó de una sola memoria de este tipo a
tener dos (L1 y L2) y hasta tres niveles (L1, L2 y L3), como forma de mejorar el rendimiento
de las computadoras sin elevar excesivamente el costo.
Hay una serie de términos que se utilizan cuando se habla de jerarquía de memoria.
Hit
Miss
Hit Rate
Miss Rate
Hit Time
Miss Penalty
Tiempo promedio de acceso a memoria = Hit Time + Miss Rate * Miss Penalty
Tiempo de Ciclo: es el tiempo mínimo que debe pasar entre un acceso y el siguiente
(las memorias requieren de un cierto tiempo de recuperación antes de poder iniciar un
nuevo ciclo de acceso). Es la suma del tiempo de acceso más el de recuperación.
CPU
Memoria
CPU
Memoria
CPU
0
0
Memoria 1 Memoria 2
19.6.1 Introducción
CPU
Transferencia de Palabras
Memoria
Cache
Transferencia de Bloques
Memoria
Principal
Comienzo
Se recibe
pedido de
lectura de
una palabra
La
palabra No
está en
cache? Se lee el
bloque de
Si memoria que
tiene la palabra
Se elige una
linea de la
cache para
alojar el bloque
Se entrega la Se transfiere
Se entrega la
palabra a la el bloque
palabra a la
CPU desde la hacia la
CPU
cache cache
Fin
Notemos que cuando ocurre un “miss” (la palabra buscada no está en la memoria
cahce) al realizar la transferencia desde memoria principal del bloque entero que contiene
la palabra buscada hacia la memoria cache, estamos aprovechando el principio de localidad
ya que lo mas probable es que el próximo requerimiento de acceso a la memoria sea una
palabra próxima (seguramente la de la dirección siguiente), por lo que probablemente
estará contenida en el bloque recién leído desde memoria. Es decir, luego de un “miss” lo
más probable es que ocurra un “hit” por la estrategia de mover bloques (y no palabras)
Tamaño
El estado del arte actual de los procesadores comerciales disponibles indican que se
utilizan 3 niveles de cache: el L1 de unos 10KB a 20KB, el L2 de 128KB a 512 KB y el L3 de
4MB a 12MB. Si consideramos que una computadora actual puede tener 4GB y más de
memoria, vemos que la relación entre el tamaño de la memoria principal y la cache (L3) es
de 1000 a 1.
Este elemento de diseño determina como se asocia una cierta posición de memoria
con su posible ubicación en la memoria cache. La memoria cache está formada por un
cierto conjunto de líneas. En cada línea se puede almacenar un bloque de memoria. Por
tanto la función de correspondencia establece para cada bloque de memoria cuales son las
líneas posibles de ser utilizadas en la cache para almacenarlo. La relación puede ser desde
que cualquier línea de la cache puede recibir a un bloque dado de memoria (denominada
correspondencia “completamente asociativa”) hasta que solo una línea determinada puede
recibir un bloque dado (denominada correspondencia “directa”), pasando por que cierto
conjunto de n líneas puede alojar un bloque dado (es la correspondencia “asociativa por
conjuntos de n vías”).
Algoritmo de Sustitución
Política de Escritura
Un aspecto que debe analizarse es el tamaño del bloque (y por tanto de la línea del
cache). Para un tamaño de memoria cache dado, ¿qué conviene más? ¿una línea más
grande o más cantidad de líneas?.
En el primer caso por el principio de localidad la probabilidad de un hit luego de un
miss aumenta, pero se puede sufrir ante cambios de contexto en ambientes de
multiprogramación.
Tag: es el campo que identifica cual de los posibles bloques está en cada línea. Son
los bits más significativos de la dirección Tiene 8 bits de largo para el ejemplo propuesto.
Línea ó Slot: son los bits que identifica la línea asociada con el bloque. En el caso
del ejemplo son 14 bits (que identificaremos con la letra r).
Byte o Palabra: son los bits menos significativos de la dirección e identifican al byte
o a la palabra individual dentro de la línea de cache o el bloque de memoria. Para el caso
son 2 bits (en general w bits).
con la fórmula Bloque % Cantidad de Líneas de la cache. El Tag se calcula como Bloque /
Cantidad de Líneas de cache.
Por tanto la correspondencia directa determina en que línea del cache se puede
almacenar cada bloque de memoria, Si m = cantidad de líneas de cache y B = número total
s
de bloques de memoria (que es 2 ), queda:
Con los r bits selecciono la única línea de la memoria cache en que puede estar el
bloque de memoria. En esa línea además del bloque está almacenado el tag
correspondiente al bloque. Entonces para determinar si hay un hit, comparo el tag
almacenado con los bits de tag de la dirección. Si coinciden tengo un hit y la lectura la hago
desde la memoria cache, usando los bits w para seleccionar la palabra dentro del bloque.
En caso contrario debo ir a la memoria principal.
Una forma de ver esta forma de correspondencia es que cada región de memoria
principal de tamaño igual a la memoria cache puede estar contenida completamente en la
memoria cache. Pero dos bloques ubicados en regiones distintas, separados un múltiplo del
tamaño de la memoria cache competirán por la misma linea de la cache.
TAG BYTE
23 2 1 0
comparar los tags correspondientes a los bloques almacenados en todas las líneas de la
cache. Y esto se debe hacer lo más rápido posible. De hecho en el mismo ciclo de reloj del
acceso de memoria, ya que no tendría sentido implementar una memoria cache rápida que
luego perdiera varios ciclos de reloj en la búsqueda del tag por cada acceso.
Los bits de tag de la dirección deben compararse al unísono con todos los tags
almacenados en la memoria cache. Esto se hace a través de la memoria asociativa
descripta. Si hay un hit la palabra se lee desde la memoria cache, usando los bits w para
seleccionar la palabra dentro del bloque.
Tag: es el campo que identifica cual de los posibles bloques está en cada línea. Son
los bits más significativos de la dirección Tiene 9 bits de largo para el ejemplo propuesto.
Conjunto: son los bits que identifica al conjunto de líneas asociado con el bloque.
En el caso del ejemplo son 13 bits (que identificaremos con la letra d).
Byte o Palabra: son los bits menos significativos de la dirección e identifican al byte
o a la palabra individual dentro de la línea de cache o el bloque de memoria. Para el caso
son 2 bits (en general w bits).
Para el caso de la función de correspondencia directa hay una sola línea posible por
lo que este problema no existe. Pero para los casos de correspondencia totalmente
asociativa o asociativa por conjuntos de n vías hay más de una posibilidad y se requiere
definir la manera en que se determinará la selección.
Este algoritmo selecciona para reemplazar, dentro de las líneas posibles, la que
tenga el bloque que haya sido accedido hace más tiempo. Una implementación sencila de
este algoritmo para una memoria cache asociativa por conjuntos de 2 vías es usar un bit
que indica cual fue la última línea que se accedió. En cada acceso a un conjunto se
actualizan los bits de ambas líneas del conjunto.
En este caso se selecciona la línea que contiene el bloque que haya sido traído
primero desde la memoria principal (el más antiguo), sin importar si fue accedido ni que
tantas veces lo fue. Una manera de implementar este algoritmo en hardware es mediante
un buffer circular (con un puntero de circular por conjunto que señala la línea a reemplazar
que se actualiza en cada reemplazo).
Este algoritmo utiliza la cantidad de veces que han sido accedidos los bloques de
las líneas candidatas a ser reemplazadas. Para su implementación se pueden utilizar
contadores en cada línea.
Random
DMA con Write-Through: para optimizar los intercambios de datos entre los
dispositivos de Entrada / Salida y la memoria principal se utilizan sistemas de acceso
directo a memoria (DMA = Direct Access Memory). Estos sistemas permiten realizar
transferencias en ambos sentidos, entre la E/S y la memoria, sin la intervención de la CPU.
El problema de la coherencia aparece porque si bien cuando usamos política de escritura
write-through la memoria principal está siempre actualizada respecto a los cambios
producidos por la CPU, si ocurre una escritura en la memoria principal realizada por el DMA
en un bloque que está almacenado también en la cache, quedarán fuera de sincronismo.
La forma de solucionar es invalidando la entrada del cache, de forma que el próximo
acceso al bloque por parte de la CPU produzca un miss y entonces se forzará la lectura del
bloque nuevamente hacia la memoria cache. La técnica que implementa el monitoreo del
sistema de memoria principal para determinar si hay un acceso por parte del DMA se
denomina bus snooping.
Universidad de la República
Montevideo - Uruguay
Notas de Teórico
Pipeline
Arquitectura de Computadoras
(Versión 4.3b - 2020)
18 PIPELINE
18.1 Introducción
6 7 8 9 10 11 12
Tiempo
O 30 40 20 30 40 20 30 40 20 30 40 20
r
d A
e
n
B
T
a
r C
e
a
s
D
6 7 8 9 10 11 12
Tiempo
O
r 30 40 40 40 40 20
d
e A
n
T B
a
r
e C
a
s D
6 7 8 9 10 11 12
Tiempo
O
r 30 40 40 40 40 20
d
e A
n
T B
a
r
e C
a
s D
Notar que ambas alternativas dan como resultado el mismo tiempo total: 30 + 40 +
40 + 40 + 40 + 20 = 210 minutos (3,5 horas). Es decir con la “lavandería en pipeline”
logramos mejorar de 6 horas a 3,5 horas. Dicho de otra manera, pasamos de un promedio
de una carga de ropa cada 90 minutos a un promedio de una carga cada 52,5 minutos!!.
Otro elemento que ha estado implícito en toda esta descripción es que las tareas
involucradas en la línea de montaje deben ser independientes entre sí y no pueden tener
otro vínculo que el de fin a comienzo. Supongamos por un momento que en la lavandería
hay un único enchufe para alimentar eléctricamente las máquinas (o, más realistamente,
que hay una llave eléctrica limitadora que, para proteger la instalación eléctrica, impide
poner a funcionar ambas máquinas en forma simultánea por el alto consumo de cada una).
En este caso no hay paralelismo posible entre el lavado y el secado, aunque sí entre
cualquiera de ellas y el doblado. Esto hace que las tareas de lavado y secado funcionen
como una sola y por tanto el rendimiento desciende a 1 carga / 70 minutos (70 minutos es la
duración combinada, serialmente, de ambas tareas).
18.3 Pipelines
Instrucción Instrucción
Fetch Execute
Instrucción Instrucción
Fetch Execute
Si asumimos que todas las etapas se ejecutan en el mismo tiempo (ej: un ciclo de
reloj), el diagrama de tiempos del pipeline sería:
tiempo
1 2 3 4 5 6 7 8 9 10
Instrucción 1 F D R E W
Instrucción 2 F D R E W
Instrucción 3 F D R E W
Instrucción 4 F D R E W
Instrucción 5 F D R E W
Instrucción 6 F D R E W
Aun suponiendo que el Fetch se haga en un solo ciclo de reloj (lo que no es cierto si
se tratara de una arquitectura CISC que tiene largo variable de instrucción), hay algunos
elementos que pueden afectar el funcionamiento óptimo del pipeline. El más evidente es
que existe el mismo problema con las instrucciones de salto que vimos para el caso
anterior. Ya sea que identifiquemos el salto en la etapa de Decode (si es incondicional) ó en
la etapa de Execute (si es condicional), las instrucciones siguientes que ya se hayan leído
se deberán descartar.
Este no es el único problema como veremos más adelante.
Los diseñadores de MIPS eligieron que todas las instrucciones recorran todas las
etapas aún cuando no las requieran. Esto incluso para el caso de la etapa de acceso a
memoria, que solo está presente en las instrucciones LOAD y STORE del set de
instrucciones. Esto es porque optaron por un diseño del pipeline radical: no tiene
mecanismos de hardware para resolver ese tipo de situaciones, donde eventualmente una
etapa del proceso no se ejecute. De hecho la sigla MIPS corresponde a Microprocessor
without Interlocks Pipeline Stages (Microprocesador sin Dependencias en las Etapas de
Pipeline).
Next PC
MUX
Add
4 Zero?
RS1
MEM/WB
EX/MEM
Reg File
Memory
MUX
RS2
ID/EX
IF/ID
ALU
PC
Memory
IR
Data
MUX
MUX
WB Data
Sign
Imm Extend
RD RD RD
Aceleración: S = nk / [n + k - 1]
Como dijimos para que un pipeline pueda funcionar de manera óptima, no deben
existir dependencias entre las etapas del mismo. En la práctica esto no es posible. El
ejemplo más simple es el del salto (condicional o no), ya que invalida el fecth de la próxima
instrucción ya realizado (y eventualmente otras etapas que también haya recorrido la
próxima instrucción y, eventualmente las siguientes, dependiendo del momento en que se
determina el salto).
Hazards Estructurales: hay un conflicto de hardware entre dos o más etapas del
pipeline para alguna combinación de instrucciones.
Hazards de Datos: existen dependencias de datos entre instrucciones. Por ejemplo
la ejecución de una instrucción depende del resultado de otra previa, que aún
está en el pipeline.
Hazards de Control: causados por instrucciones de salto u otras modificaciones del
registro IP (Instruction Pointer ó PC = Program Counter).
tiempo
1 2 3 4 5 6 7 8 9 10
Instrucción 1 F D R E W
Instrucción 2 F D R E W
Instrucción 3 F D R E W
Instrucción 4 F D R E W
Instrucción 5 F D R E W
Instrucción 6 F D R E W
Otro ejemplo (señalado con rojo) podría darse si pensamos que la etapa de Fetch
necesita calcular la dirección de la próxima instrucción (sumando 4, por ejemplo en el caso
de RISC). Si para esta operación intentara utilizar la ALU generaría un conflicto con la etapa
de Execute de otra instrucción (ej: instrucciones 1 y 4 del diagrama de tiempo). Esto se
puede solucionar agregando un sumador independiente de la ALU para el cálculo de la
dirección de la próxima instrucción.
En este caso el problema aparece porque hay datos en común entre instrucciones
que están en el pipeline, ya sea una instrucción siguiente que utiliza un resultado aún no
calculado como operando ó altera un operando antes que sea leído como operando.
RAW (Read After Write): ocurre cuando una instrucción posterior intenta obtener un
operando que está siendo calculado por una instrucción anterior, que aún está en el
pipeline y aún no llegó a la etapa donde escribe el resultado en el registro destino (W
ó WB). Este tipo de obstáculo se denomina “dependencia”.
Veamos un ejemplo (usaremos instrucciones de 3 operandos, el primero es destino
y los otros dos son origen):
tiempo
1 2 3 4 5 6 7 8 9 10
Instrucción 1 F D R E W
Instrucción 2 F D R E W
Instrucción 3 F D R E W
Instrucción 4 F D R E W
Instrucción 5 F D R E W
Instrucción 6 F D R E W
WAR (Write After Read): ocurre cuando una instrucción posterior escribe un
registro que actúa como operando de una instrucción anterior antes que ésta pueda
leerlo. Este tipo de hazard de datos, que se denomina “anti-dependencia” no es
posible en los pipelines que hemos visto (porque en todos la etapa de Write está
luego de la de Read). Sin embargo es posible que sucedieran en diseños más
avanzados (del tipo “out of order execution”), los que obviamente dispondrán de
mecanismos para evitarlos.
WAR (Write After Write): ocurre cuando una instrucción anterior escribe un registro
que también actúa como resultado de una instrucción posterior después de ésta.
Este tipo de hazard de datos, que se denomina “dependencia de salida” tampoco es
posible en los pipelines que hemos visto (porque en todos la etapa de Write está
luego de la de Read). También como en el caso anterior es posible que sucedieran
en diseños más avanzados (del tipo “out of order execution”), los que obviamente
dispondrán de mecanismos para evitarlos.
Para el caso del RAW las formas de resolver el problema pueden ser:
• esperar (introducir una burbuja en el pipeline)
• recurrir a técnicas avanzadas como la ejecución fuera de orden (out of order
execution)
• hacer register forwarding. Esta técnica consiste en propagar hacia las etapas
tempranas del pipeline los resultados apenas estén disponibles, sin necesidad de
esperar a que culmine la etapa de Write. En este caso la etapa de Read podrá
leer el operando desde el registro indicado ó desde la salida de la ALU
directamente, en función de la lógica de control que implemente esta
funcionalidad.
Las técnicas para resolver la penalización provocada por este tipo de hazards
incluyen: prefetch del destino, multiples flujos (streams), salto demorado y predicción del
salto.
Este caso va un poco más allá del anterior y duplica las etapas del pipeline que
están ubicadas hasta la que decide el salto. De esta manera se puede avanzar en la
ejecución de ambos flujos de instrucciones, por lo que al momento de tomar el salto no hay
ninguna penalización, ya que no es necesario “vaciar” el pipeline (en realidad se vacía uno
de los dos: el que estaba ejecutando el flujo que finalmente no resultó elegido por el salto).
El salto demorado es una técnica muy utilizada en los procesadores RISC. La idea
es simple: siempre se ejecuta la instrucción que está luego del salto (se dice que la
instrucción luego del salto está ubicada en el “delayed slot”). Es responsabilidad del
compilador (ó del programador de bajo nivel) acomodar allí una instrucción útil. Si no hay
forma de hacerlo se deberá colocar un NOP y se recomienda nunca colocar dos saltos
seguidos (en algunos casos si se hace se produce una “excepción”).
La idea se complementa con el hecho que los procesadores que utilizan este
recurso deben resolver las instrucciones de salto en la segunda etapa del pipeline. De esta
manera no incurren en penalización por salto, ya que no se requiere vaciar el pipeline. Esto
es cierto para las primeras generaciones de procesadores RISC (ej: los primeros diseños de
MIPS y SPARC).
Asumir que nunca se ejecuta: este criterio es como si se considerara el salto como
una instrucción cualquiera. Siempre se carga la próxima instrucción en memoria.
Asumir que siempre se ejecuta: este criterio continúa la carga de instrucciones en
la dirección destino del salto. Estadísticamente los saltos condicionales se toman en más
del 50% de los casos.
Predicción basada en la condición del salto: parte de la constatación que
determinados tipos de condición del salto (que están codificados en el código de operación
de la instrucción de salto) tienen mayor tendencia a realizar el salto y otros a no realizarlo.
Con esta técnica se consigue más del 75% de aciertos.
Conmutar Taken / No Taken: utiliza la historia reciente de los saltos, mediante una
máquina de estados que “recuerda” si el último salto fue tomado o no. La predicción debe
fallar dos veces seguida para cambiarla. El problema de la técnica es que predice el
comportamiento de un salto en función de lo que hizo uno anterior que no tiene por qué ser
el mismo. Por eso es que es apropiado para bucles (loops), pero no en general.
Tabla de Historia de Saltos (BHT = Branch History Table): es un
perfeccionamiento del mecanismo anterior, donde se almacena en una tabla la información
de un cierto conjunto de saltos recientemente evaluados. Entonces permite realizar el
algoritmo anterior sobre el comportamiento del mismo salto, sin que sea interferido por otros
saltos. Esto mejora la eficiencia de la predicción.
Una de las propuestas más radicales para atender toda la problemática de los
distintos tipos de “hazards” que ocurren en los pipeline es la posibilidad de realizar la
ejecución de las instrucciones fuera del orden establecido por su ubicación en memoria
pero, obviamente, respetando su orden lógico para mantener la integridad de los resultados.
Para lograr esto los procesadores que utilizan esta técnica manejan un conjunto de
instrucciones que ya fueron leídas desde la memoria hacia una especie de
“estacionamiento, y las van catalogando como “prontas para ejecutar” o no en función que
sus dependencias de datos y control hayan sido satisfechas. Las instrucciones “prontas
para ejecutar” avanzan en el pipeline a la etapa de ejecución y a medida que se van
generando nuevos resultados, se van actualizando los estados de las instrucciones que aún
esperan. De esta manera nuevas instrucciones quedan prontas para ejecutar y así sigue el
proceso.
El orden lógico de ejecución es el que determina, en definitiva, la existencia de
restricciones de datos o control (los hazards) y por tanto es tenido en cuenta al momento de
determinar la condición de “pronta para ejecutar” de una instrucción.
Un sistema de este tipo, si bien tiene una lógica de control muy compleja, permite
altas tasas de ocupación de las etapas del pipeline y, en particular, de la ALU. Es decir logra
una gran eficiencia del pipeline.