Escolar Documentos
Profissional Documentos
Cultura Documentos
1.1 Introdução
A velocidade da evolução dos sistemas computacionais é sem precedentes na
história de quaisquer outros sistemas inventados pelo homem, excetuando-
se, talvez, hoje, a evolução dos sistemas de sequenciamento genético. Se os
sistemas de transporte tivessem evoluído tão rápido quanto os sistemas
computacionais de 1940 (década da implementação do primeiro computador
com código armazenado) até hoje, por exemplo, seria possível viajar de
Manaus a Vitória em 15 segundos pelo custo de aproximadamente R$1,00.
Cada vez que os computadores ficam mais baratos e mais rápidos, novas
aplicações se tornam viáveis. No passado recente, aplicações que eram
completamente impraticáveis se tornaram comuns. Por exemplo: caixas
automáticos, computadores em automóveis, laptops, etc.
0001110010100000
aula1.doc 1 de 4
Usar números binários para se comunicar com um computador é
extremamente tedioso. Por essa razão, programadores logo inventaram uma
notação mais próxima de como pensamos para fazer esta comunicação.
AR A, B #A=A+ B
para
0001110010100000
aula1.doc 2 de 4
Linguagens de alto nível, tais como C, FORTRAN, Pascal, etc, oferecem
importantes benefícios por aumentarem a produtividade dos programadores
– uma linha de código em linguagem de alto nível pode, muitas vezes,
representar várias instruções em linguagem de máquina.
aula1.doc 3 de 4
Com a evolução das técnicas de programação, muitos profissionais
perceberam que a reutilização dos programas era muito mais eficiente que
sempre reescreve-los do zero.
Software pode ser categorizado pelo seu uso. Temos, então, system software
e aplicações, onde o primeiro conjunto compreende os programas de suporte
à execução e ao desenvolvimento de novos programas e o segundo, os
programas para o usuário não desenvolvedor.
aula1.doc 4 de 4
1.3 Hardware dos Computadores: mouse, display, CPU, discos,
networks.
1.3.1 Mouse
O primeiro computador a usar um mouse foi o Alto, da Xerox, em 1973.
aula2.doc 1 de 10
Em um mouse óptico, um CI semelhante a uma câmera “fotografa” o mouse
pad ou superfície muitas vezes por segundo e mede os deslocamentos da
imagem.
1.3.2 Monitor
O tubo de raios catódicos (cathode ray tube – CRT) dos monitores, produz
imagens desenhando-as linha a linha. O CRT é, na verdade, uma válvula
eletrônica.
aula2.doc 2 de 10
Diodo termiônico
Triodo termiônico
aula2.doc 3 de 10
Em um CRT, um filamento aquece um catodo polarizado negativamente
com relação a outros elementos dentro do CRT.
aula2.doc 4 de 10
Um CRT colorido possui três canhões que são focados precisamente em
pontos específicos da tela recobertos por compostos à base de fósforo que
emitem luz de três cores diferentes: vermelho, verde e azul. As demais cores
observadas são produzidas através da composição destas três cores básicas.
aula2.doc 5 de 10
Monitores LCD (Liquid Crystal Display) do tipo TFT (Thin-Film Transistor)
usam transistors para controlar cada pixel que pode aparecer na imagem.
Uma placa de material plástico que polariza a luz que fica na frente das
regiões de cristal líquido impedem que luz polarizada de forma diferente
passe por ela. Assim, o transistor permite ou não a passagem da luz.
Milhares de transistores são necessários para um display moderno.
aula2.doc 6 de 10
aula2.doc 7 de 10
Um display TFT colorido possui filtros para as cores vermelho, verde e azul
e transistores específicos para cada cor de cada pixel.
aula2.doc 8 de 10
aula2.doc 9 de 10
1.3.4 Discos
Os discos do computador são responsáveis por armazenar os programas e
dados que devem ser preservados quando o computador está desligado.
Os discos têm este nome porque eles são, na verdade, implementados através
de discos recobertos com material magnético.
aula2.doc 10 de 10
1.4 Circuitos Integrados
Quando usado em circuitos integrados (CIs) computacionais, um
transistor é simplesmente uma chave liga/desliga controlada por
eletricidade.
aula3.doc 1 de 7
Áreas que conduzem ou isolam a eletricidade de acordo com um
comando elétrico (transistores)
aula3.doc 2 de 7
Se nenhuma voltagem é aplicada ao gate, o transistor não conduz
eletricidade (off-state).
aula3.doc 3 de 7
Este funcionamento do transistor é viabilizado por processos físicos
(quânticos) que ocorrem na junção P-N.
aula3.doc 4 de 7
Neste processo, uma camada de material foto-sensível é colocada sobre o
silício e uma máscara, contendo os padrões geométricos dos componentes
dos transistores e suas interligações, é colocada entre uma fonte de luz e o
silício.
As partes do material foto-sensível atingidas pela luz são afetadas por ela
e removidas quimicamente. Em seguida as partes expostas do silício
recebem impurezas ou metal vaporizado em um forno – com o calor, as
impurezas penetram o silício ou o metal vaporizado adere a ele.
Estes lingotes são cortados em fatias, ou “wafers”, de não mais que 0.1”
(2,5mm) de espessura. Estes wafers passam pela série de processos físico-
químicos que constróem transistores, condutores e isolantes em suas
superfícies que, em conjunto, formam CIs.
aula3.doc 5 de 7
A figura abaixo mostra uma foto bastante ampliada de um CI.
aula3.doc 6 de 7
A figura abaixo mostra a foto de dois waffers com vários CIs em cada
um. Observe que o waffer mais ao fundo na foto tem um menor número
de CIs, mas estes são maiores.
aula3.doc 7 de 7
2. Sobre o Desempenho dos Computadores
2.1 Comparando o Desempenho de Dois Computadores
Sejam X e Y dois computadores. X é mais rápido que Y se:
Tempo de execução em X
_____________________ < 1
Tempo de execução em Y
1
_____________________
Tempo de execução em X
aula4.doc 1 de 9
Exemplos adequados de programas reais para medir desempenho são
programas que usamos no dia-a-dia, como compiladores por exemplo.
Synthetic Benchmarks são programas artificiais. Eles não fazem nada útil e
são criados apenas para medida de desempenho.
Estas benchmark suites são compostas por programas reais, escolhidos para
serem representativos de programas que tipicamente demandam muita CPU
e pouco I/O. Os programas inteiros do SPEC95 são:
aula4.doc 2 de 9
Os programas de ponto-flutuante do SPEC95 são:
aula4.doc 3 de 9
179.art C Image Recognition / Neural Networks
183.equake C Seismic Wave Propagation Simulation
187.facerec Fortran 90 Image Processing: Face Recognition
188.ammp C Computational Chemistry
189.lucas Fortran 90 Number Theory / Primality Testing
191.fma3d Fortran 90 Finite-element Crash Simulation
200.sixtrack Fortran 77 High Energy Nuclear Physics Accelerator Design
301.apsi Fortran 77 Meteorology: Pollutant Distribution
aula4.doc 4 de 9
Sequence profile hidden Markov models
(profile HMMs)
aula4.doc 5 de 9
computations. For the SPEC
workload, self-consistent
field calculations are
performed using the
Restricted Hartree Fock
method, Restricted open-
shell Hartree-Fock, and
Multi-Configuration Self-
Consistent Field
aula4.doc 6 de 9
437.leslie3d Fortran Fluid Dynamics Computational Fluid
Dynamics (CFD) using
Large-Eddy Simulations
with Linear-Eddy Model in
3D. Uses the MacCormack
Predictor-Corrector time
integration scheme.
aula4.doc 7 de 9
library.
aula4.doc 8 de 9
2.5 Reportando Medidas de Desempenho
O mais importante aspecto a ser observado quando estamos reportando
desempenho é reprodutibilidade – deve-se listar tudo que outro
experimentador vai precisar para duplicar os resultados sendo reportados.
aula4.doc 9 de 9
2.6 Comparando e Sumarizando Desempenho
Mesmo tomando o cuidado de indicar todos os parâmetros relevantes,
dúvidas podem surgir quando comparamos ou sumarizamos desempenho.
aula5.doc 1 de 4
aula5.doc 2 de 4
A média geométrica dos tempos normalizados é também utilizada para
sumarizar desempenho.
n
Média geométrica do Tempo Normalizado (i,n) = n
Tnormalizado i
i 1
Normalizado por A
Computador A Computador B Computador C
Programa P1 (seg.) 1.0 10.0 20.0
Programa P2 (seg.) 1.0 0.1 0.02
Média Aritmética 1.0 5.05 10.01
Média Geométrica 1.0 1.0 0.63
Tempo Total 1.0 0.11 0.04
A lei de Amdahl define o speedup que pode ser obtido por um atributo
particular de um sistema.
aula5.doc 3 de 4
2.8 O Tempo de Execução de um Programa
Se apenas o processador (CPU) é levado em consideração, o tempo de
execução de um programa pode ser definido como:
aula5.doc 4 de 4
2.9 O Desempenho da CPU
O desempenho de uma CPU na execução de um programa pode ser medido
através do tempo que esta CPU gasta para executar este programa. Quanto
menor o tempo, maior o desempenho. O tempo de execução de um
programa, T, pode ser expresso por:
O número de segundos (na verdade, nano ou pico segundos hoje em dia) por
ciclo de máquina normalmente é indicado no manual da máquina.
O CPI, por outro lado, depende de vários fatores, tais como a organização de
memória da máquina, o conjunto de instruções do processador, a mistura de
instruções executadas pela aplicação, a arquitetura do processador, etc.
Respostas:
aula6.doc 1 de 3
1: seq1 = 2+1+2 = 5 instruções; seq2 = 4+1+1 = 6 instruções, logo, resposta = seq2
2: seq1 = 2x1 + 1x 2 + 2x3 = 10 ciclos; seq2 = 4x1 + 1x2 + 1x3 = 9 ciclos
3: CPI(seq1) = 10 ciclos / 5 instruções = 2 CPI; CPI(seq2) = 9 / 6 = 1.5 CPI
aula6.doc 2 de 3
MFLOPS = número de operações de ponto flutuante em um programa
/ tempo de execução x 106
Embora, a primeira vista, o número de operações de ponto flutuante de um
programa pareça ser o mesmo para diferentes computadores, ele não é
devido ao fato de diferentes computadores terem conjuntos de instruções de
ponto flutuante diferentes. Por esse e outros problemas, MFLOPS também
não é uma boa unidade de medida de performance.
2.10.3 SPEC
Medir o tempo de execução usando um conjunto de programas de uso
generalizado, com entradas conhecidas, e sob circunstâncias conhecidas e
especificadas é a melhor maneira de se medir o desempenho de um
computador. As unidades de medidas SPECint e SPECfp são consideradas,
atualmente, boas unidades de medida de desempenho.
aula6.doc 3 de 3
3 Instruções: A Linguagem da Máquina
Para controlar o hardware de um computador você precisa falar a linguagem
dele. As palavras que um computador entende são chamadas instruções e seu
vocabulário é chamado conjunto de instruções (“instruction set”).
add a, b, c
add a, b, c
add a, a, d
add a, a, e
aula7.doc 1 de 4
Um compilador recebe um programa em linguagem de alto nível e gera
como saída um programa em linguagem de máquina. Uma forma mais
legível de linguagem de máquina é a linguagem de montagem, ou “assembly
language”.
3.2 Operandos
Operandos de instruções de máquina não podem ser de qualquer tipo: na ISA
MIPS eles têm que ser um dos registradores do processador, uma constante
ou o conteúdo de uma posição de memória.
aula7.doc 2 de 4
Estruturas de dados maiores que 32 bits, como matrizes por exemplo, são
mantidas na memória. Para operar sobre elas, o processador tem que trazê-
las, por partes, para seus registradores, realizar as operações, e transferi-las
por partes de volta para a memória.
Exemplo:
g = h + A[i]; /* Código C. A é um vetor de bytes. */
aula7.doc 3 de 4
Para escrever dados na memória a instrução “store” é utilizada:
A[i] = h + A[i];
aula7.doc 4 de 4
3.3 O Formato das Instruções
Para fornecer instruções ao computador temos que usar códigos em binário
(números na base 10 são ditos decimais, na base 2, binários). Para facilitar a
leitura humana de números binários, a base 16 – ou números em
hexadecimal – é, muitas vezes, utilizada:
aula8.doc 1 de 3
Cada campo tem um nome:
op = operação (também conhecido como opcode);
rs e rt = 1o. e 2o. registradores fonte, respectivamente;
rd = registrador destino;
shamt = tamanho do deslocamento (shift amount, usando em
instruções de deslocamento, que veremos adiante); e
funct = função (function, indica uma variação específica da instrução
indicada em op).
lw $8, 1200($19)
nome op rs rt Address
No. bits 6 5 5 16
decimal 35 19 8 1200
aula8.doc 2 de 3
Exemplo de Exercício: Traduza o trecho de código em C abaixo para
linguagem assembly e para linguagem de máquina. O endereço do vetor de
words, A, está no registrador $17, o registrador $18 contem o valor da
variável h e $19 contem 4 vezes i.
A[i] = h + A[i];
Assembly
add $7, $17, $19 # o temporário $7 recebe A + (i * 4)
lw $8, 0($7) # o registrador temporário $8 recebe A[i]
add $8, $18, $8 # o registrador temporário $8 recebe h + A[i]
sw $8, 0($7) # escreve h + A[i] em A[i]
linguagem de máquina
decimal 0 17 19 7 0 32
decimal 35 7 8 0
decimal 0 18 8 8 0 32
decimal 43 7 8 0
aula8.doc 3 de 3
O funcionamento dos computadores é baseado em dois princípios chave:
memória
Editor (código de máquina)
processador
Texto em linguagem C
aula8.doc 4 de 3
3.4 Instruções de Desvio
Um processador é capaz de tomar decisões baseado nos dados de entrada e
nos valores computados durante a execução das instruções.
Em linguagens de alto nível, o comando if (se) pode ser usado para tomada
de decisões. Na MIPS ISA, a instrução abaixo é usada para tomar uma
decisão de acordo com o conteúdo de dois registradores.
if (i == j) goto L1;
i = g + h;
L1: f = f – i;
Resposta:
aula9.doc 1 de 3
Outro exemplo: i == j i == j? i != j
C
Else:
if (i == j)
f = g + h; f=g+h f=g-h
else
f = g – h;
Exit:
Assembly
bne $19, $20, Else
add $16, $17, $18
j Exit
Else: sub $16, $17, $18
Exit:
Mais um exemplo:
Faça um programa em C que some os salários de todos os funcionários de
uma firma. A firma tem 10 funcionários e os salários estão guardados no
vetor SAL. Traduza o programa para o assembly da MIPS ISA.
C
total = 0;
i = 0;
while (i != 10) /* enquanto i for diferente de 10 */
{
total = total + SAL[i];
i = i + 1;
}
aula9.doc 2 de 3
A MIPS ISA inclui uma instrução para fazer testes sobre o conteúdo de
registradores – a instrução slt, ou “set on less than” (ligue se menor que).
aula9.doc 3 de 3
Muitas linguagens possuem comando equivalente ao “switch” do C:
switch (k)
{
case 0: /* k == 0 */
f = i + j;
break;
case 1: /* k == 1 */
f = g + h;
break;
case 2: /* k == 2 */
f = g - h;
break;
case 3: /* k == 3 */
f = i - j;
break;
default:
f = 0;
}
aula10.doc 1 de 7
Exemplo: Assumindo que as variáveis f, g, …, k estão alocadas nos
registradores $16, …, $21 e que o vetor JumpTable contém o endereço dos
comandos case acima, o código assembly abaixo é equivalente ao código C
acima:
aula10.doc 2 de 7
Procedimentos e funções são utilizados para tornar os programas mais
legíveis e para permitir a fácil reutilização de código (a linguagem C só tem
funções).
Exemplo:
#include <stdio.h>
int main ()
{
int x, a, b;
a = 1;
b = 2;
x = maior (a, b);
printf (“a = %d, b = %d, maior = %d\n”, a, b, x);
return (0);
}
A função printf faz parte de um conjunto de funções que já vem junto com o
compilador.
Ela imprime na saída o que está entre aspas, a menos que apareçam os
caracteres % e \.
aula10.doc 3 de 7
Para permitir a chamada de procedimentos em assembly, são necessárias
uma (i) instrução para desviar para o inicio de uma função e (ii) outra para
retornar para a instrução logo após a instrução de desvio, após a execução da
função.
A instrução da MIPS ISA que é usada para desviar para o início da função é
instrução “jump-and-link” ou jal:
Função: …
…
jr $31 # fim de “Função”
Esta instrução salta para o endereço Função e, além disso, guarda o endereço
da instrução seguinte a ela própria (no caso acima, o endereço Seguinte) no
registrador $31.
aula10.doc 4 de 7
Note, contudo, que, quando uma função chama outra função, o endereço de
retorno pode ser perdido. Exemplo:
C: …
…
jr $31 # esta instrução retorna para retB…
B: …
jal C # após este jal, $31 contém o endereço retB: retA foi
# perdido!
retB:
…
jr $31 # esta instrução desviaria para retB…
A: …
jal B # após este jal, $31 contém o endereço retA
retA:
…
jr $31
…
aula10.doc 5 de 7
Para evitar isso, uma estrutura de dados chamada de “stack” (pilha) é
utilizada para guardar os endereços de retorno. Por convenção da linguagem
assembly do MIPS, o registrador $29 aponta para o primeiro elemento livre
do stack e o stack cresce para baixo (endereços menores).
C: …
…
jr $31 # esta instrução desvia para retB…
B: …
sw $31, 0($29) # guarda o antigo valor de $31 na pilha (retA)
sub $29, $29, 4 # ajusta o ponteiro da pilha
jal C # após este jal, $31 contém o endereço retB
retB:
…
add $29, $29, 4 # prepara para remover um item da pilha
lw $31, 0($29) # lê o endereço de retorno anterior para $31 (retA)
jr $31 # retorna para A
A: …
sw $31, 0($29) # guarda o antigo valor de $31 na pilha
sub $29, $29, 4 # ajusta o ponteiro da pilha
jal B # após este jal, $31 contém o endereço retA
retA:
…
add $29, $29, 4 # prepara para remover um item da pilha
lw $31, 0($29)
jr $31
…
aula10.doc 6 de 7
Além de um padrão para qual registrador aponta para o stack e de como ele
cresce, outras convenções também são necessárias. Seguem algumas
convenções da linguagem assembly do MIPS:
$1 ($at), $26 ($k0) e $27 ($k1) são reservados para o sistema operacional
e o assembler e não devem ser utilizados pelo usuário
$4-$7 ($a0-$a3) são usados para passar os primeiros 4 argumentos para
funções (argumentos adicionais são passados via stack)
$2, $3 ($v0, $v1) são usados para retornar valores de funções
$8-$15, $24 e $25 ($t0-$t9) são registradores temporários “caller-saved”:
podem ser usados para guardar valores que não precisam ser mantidos
entre chamadas de função
$16-$23 ($s0-$s7) são registradores “callee-saved”: contém valores que
devem ser preservados entre chamadas de função
$28 ($gp) “global pointer”: aponta para as variáveis globais
$29 ($sp) “stack pointer”: aponta para a primeira posição livre do stack
$30 ($fp) “frame pointer”: aponta para o inicio da área de trabalho da
função corrente que acaba no stack
$31 ($ra) contém o “return address” gerado pelas instruções jal
aula10.doc 7 de 7
No nível de linguagem de montagem, quando uma função chama outra
(caller chama callee) as convenções mencionadas tem que ser observadas
para garantir que elas operem em conjunto corretamente.
O stack frame consiste na área de memória entre o frame pointer, que aponta
para a primeira word do stack frame, e o stack pointer, que aponta para a
primeira word após o stack frame.
Como o stack (pilha) cresce para baixo (endereços menores), o frame pointer
contém um endereço mais alto que o stack pointer.
#include <stdio.h>
int main ()
{
int a, b, x;
a = 1;
b = 2;
x = maior (a, b);
printf (“a = %d, b = %d, maior = %d\n”, a, b, x);
return (0);
aula11.doc 1 de 5
}
aula11.doc 2 de 5
No programa em assembly, um stack frame como o mostrado a seguir é
empregado:
Stack Frame
Antes de uma função caller chamar uma callee, o stack pointer aponta para a
primeira posição livre do stack. Depois da chamada, uma função callee
simples prepara seu stack frame como mostrado acima, por exemplo.
Stack frames podem ser maiores e ter várias seções, dependendo da função
callee. Funções callee mais complexas requerem stack frames maiores para
guardar o conteúdo de registradores que ela precisa salvar antes de usar,
como por exemplo $s0-$s7, e suas variáveis locais que não puderem ser
alocadas em registradores, como vetores, por exemplo.
aula11.doc 3 de 5
Versão em assembly do programa em C (pode ser simulada com o programa
PCspim: (http://pages.cs.wisc.edu/~larus/spim.html):
# Parâmetros de maior()
move $a0, $t0 # os parâmetros são passados em $a0
move $a1, $t1 # e $a1
jal maior # maior() retorna o maior em $v0
# Parâmetros de printf()
la $a0, MENS # coloca o endereço MENS em $a0
move $a1, $t0 # coloca a e b em $a1 e $a2
move $a2, $t1
move $a3, $v0 # x=maior(a, b); x é colocado em $a3
# jal printf # parâmetros em $a0, $a1, $a2, $a3
aula11.doc 4 de 5
add $v0, $0, 0 # return (0)
lw $ra, 20($sp) # restaura o $ra para o S.O.
lw $fp, 16($sp) # restaura o frame pointer do S.O.
addu $sp, $sp, 32 # remove o stack frame de main()
jr $ra # retorna para o S.O.
aula11.doc 5 de 5
3.5 Endereçamento
Instruções podem ser classificadas de acordo com o número de endereços
que elas utilizam.
Instruções de zero, um, dois e três endereços são comuns. Instruções de dois
endereços compõem grande parte da ISA IBM370. A instrução do IBM370:
add
aula12.doc 1 de 6
3.5.1 Endereçamento de Registrador
Operandos de instruções podem ser acessados de diversas maneiras
diferentes. No modo de endereçamento conhecido como endereçamento de
registrador, o conteúdo de um registrador é o operando. Exemplo:
nome op rs rt immediate
No. bits 6 5 5 16
decimal 8 2 3 10
nome op rs rt immediate
No. bits 6 5 5 16
decimal 15 0 8 255
aula12.doc 2 de 6
Uma instrução or (ou lógico) pode, então, ser usada junto com a lui para
compor constantes de 32 bits:
0xaaaa4444:.ascii “string”
nome op rs rt immediate
No. bits 6 5 5 16
decimal 5 8 21 100
Para saber qual instrução deve ser trazida da memória para ser executada, o
processador usa o registrador PC (“Program Counter” – contador de
programa).
aula12.doc 3 de 6
Para tornar o hardware mais simples e poderoso, a constante indica, na
verdade, a distância relativa à instrução imediatamente após o desvio e a
distância é indicada em instruções (words, ou 4 bytes) a partir da instrução
seguinte.
j 10000
nome op Address
No. bits 6 26
decimal 2 10000
Exemplo:
label endereço instrução
loop: 1000 add $t0, $t0, 1
1004 beq $t0, $t1, Exit (1) # PC = PC + 4 + Exit (1) * 4 =
# 1012
1008 j loop (250) # PC = loop * 4 = 1000 (os dois
# bits de mais alta ordem de PC
# são iguais a zero)
Exit: 1012
aula12.doc 4 de 6
3.5.3 Endereçamento Base mais Deslocamento
Este tipo de endereçamento é utilizado pelas instruções load/store:
lw $8, 1200($19)
Nome op rs rt address
No. bits 6 5 5 16
Decimal 35 19 8 1200
sw $8, 1200($19)
nome op rs rt Address
No. bits 6 5 5 16
decimal 43 19 8 1200
(1200+$19)
aula12.doc 5 de 6
Sumário:
aula12.doc 6 de 6
3.6 Arrays versus Pointers
Muitos programadores iniciantes acham o conceito de “pointer” difícil de
entender. Contudo, um exemplo em assembly pode tornar o entendimento
deste conceito mais fácil. O trecho de código em C abaixo limpa (zera) o
conteúdo de um array.
void
clear_array (char array[], int size)
{
int i;
void
clear_array_p (char *array, int size)
{
char *p;
aula13.doc 1 de 2
O trecho em assembly abaixo implementa a versão usando pointers.
A versão com pointers é mais rápida (apenas três instruções no loop) porque
a variável i não precisa ser mantida – o pointer p aponta diretamente para o
item a ser alterado.
aula13.doc 2 de 2
4. Montadores, Ligadores, Carregadores, Compiladores e
Interpretadores
4.1 Montadores
Os montadores, ou “assemblers”, montam um programa em linguagem de
máquina a partir de sua versão em linguagem de montagem, ou
linguagem “assembly”. Eles:
1. Acham um endereço inicial para o programa
2. Convertem pseudo-instruções para o conjunto de instruções
equivalente
3. Convertem macros no conjunto de instruções e dados equivalentes
4. Transformam cada parte dos comandos em linguagem assembly em
opcode, número de registrador, constante, etc.
5. Escrevem o programa em linguagem de máquina em um arquivo
com as instruções ordenadas e com os endereços indicados por
elas, especificados como labels, já convertidos para números
quando possível
aula14.doc 1 de 5
Formato de um header de arquivo a.out antigo:
struct _exec_header
{
unsigned char dynToolVer;
unsigned char machineType;
unsigned short int magicNumber;
unsigned int textSize;
unsigned int dataSize; /* initialized global and static variables */
unsigned int bssSize; /* noninitialized global and static variables */
unsigned int symbolTabSize;
unsigned int entryPoint;
unsigned int textRelSize;
unsigned int dataRelSize;
};
aula14.doc 2 de 5
4.2 Ligadores
Muitas vezes, um programa pode ser decomposto em várias rotinas, cada
uma responsável por aspectos específicos da computação a ser executada
pelo programa.
float
calcula_um_salário (float salário_base)
{
float salário_total;
float
salário_total (float salário_base[], int numero_funcionários)
{
int i;
float total;
total = 0.0;
for (i = 0; i < numero_funcionários; i++)
total = total + calcula_um_salário (salário_base [i]);
return (total);
}
aula14.doc 3 de 5
Um linker realiza, então, quatro tarefas básicas:
1. Determina as posições de memória para os trechos de código de
cada módulo que compõe o programa sendo “linkado”
2. Resolve as referências entre os arquivos
3. Procura nas bibliotecas (libraries), indicadas pelo programador, as
rotinas usadas nos fontes de cada módulo
4. Indica ao programador quais são os labels que não foram
resolvidos (não tenham correspondente em nenhum módulo ou
library indicados)
4.3 Carregadores
Programas que tenham sido linkados sem erros podem ser executados.
Para executar um programa, um programa carregador, ou loader, é
utilizado. O loader é, em geral, parte do sistema operacional.
4.4 Compiladores
Compiladores são programas que recebem como entrada arquivos texto
contendo módulos escritos em linguagem de alto nível e geram como
saída arquivos objeto correspondentes a cada módulo, ou, se todas as
bibliotecas e módulos são apresentados como entrada, geram um
programa executável diretamente.
aula14.doc 4 de 5
4.5 Interpretadores
Programas interpretadores recebem como entrada arquivos texto
contendo programas em linguagem assembly ou linguagem de alto nível,
ou arquivos binários com instruções de máquina, e os executam
diretamente.
aula14.doc 5 de 5
5. Aritmética de Computador
5.1 Números negativos
Números podem ser representados em qualquer base. Nós, humanos,
preferimos usar a base 10, talvez porque tenhamos 5 dedos em cada mão.
Esta regra também vale quando o computador tem menos bits para
representar números inteiros. Assim, temos:
Com 32 bits:
base 2 (binário) base 10 (decimal)
0000 0000 0000 0000 0000 0000 0000 0000 = 0
0000 0000 0000 0000 0000 0000 0000 0001 = 1
0000 0000 0000 0000 0000 0000 0000 0010 = 2
...
0111 1111 1111 1111 1111 1111 1111 1101 = 2.147.483.645
0111 1111 1111 1111 1111 1111 1111 1110 = 2.147.483.646
0111 1111 1111 1111 1111 1111 1111 1111 = 2.147.483.647
1000 0000 0000 0000 0000 0000 0000 0000 = 2.147.483.648
1000 0000 0000 0000 0000 0000 0000 0001 = 2.147.483.647
1000 0000 0000 0000 0000 0000 0000 0010 = 2.147.483.646
1000 0000 0000 0000 0000 0000 0000 0011 = 2.147.483.645
...
1111 1111 1111 1111 1111 1111 1111 1110 = 2
aula15.doc 1 de 4
1111 1111 1111 1111 1111 1111 1111 1111 = 1
aula15.doc 2 de 4
Com 4 bits:
base 2 (binário) base 10 (decimal)
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 7
1010 = 6
1011 = 5
1100 = 4
1101 = 3
1110 = 2
1111 = 1
Em alguns casos, números negativos não são úteis ou não faz sentido
utiliza-los. Este é o caso de endereços de memória, por exemplo. Não faz
sentido usar endereços de memória negativos.
Exercício:
Suponha que $16 contenha o número binário:
1111 1111 1111 1111 1111 1111 1111 1111
aula15.doc 3 de 4
5.2 Soma e Subtração
Para somar números binários podemos usar a mesma técnica que usamos
quando somamos números decimais: somar dois dígitos de cada vez.
Exemplo:
18 = 0001 0010
complemento bit-a-bit = 1110 1101
complemento bit-a-bit +1 = 1110 1110
aula15.doc 4 de 4
Um problema ocorre quando os números somados produzem um
resultado com mais bits do que o que pode ser representado.
add (soma com sinal) e addi (soma imediato com sinal), podem
causar exceções quando o processador é configurado para tal
addu (soma sem sinal), addui (soma imediato sem sinal), não
causam exceções
binário (8 bits)
0001 0010
&0001 1001 =
--------------
0001 0000
aula15.doc 5 de 4
5.4 Unidade Aritmética e Lógica (Arithmetic and Logic Unit – ALU)
A ALU é a parte central do hardware de uma CPU. Ela é responsável por
realizar operações aritméticas e lógicas básicas, e pode ser implementada
com quatro componentes: porta E (And), porta OU (Or), inversor
(Inverter) e multiplexador (multiplexer).
a b c=a.b
0 0 0
E (AND) a
b c 0 1 0
1 0 0
1 1 1
a b c=a+b
0 0 0
OU (OR) a
b
c 0 1 1
1 0 1
1 1 1
a c=a
Inversor a c 0 1
1 0
d
d c=
Multiplexador a 0
c 0 a
b 1
1 b
a
Resultado
b
aula16.doc 1 de 6
Entradas Saídas
a b “vem um” “vai um” soma
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1
vem um
vai um
aula16.doc 2 de 6
Uma ALU de 1 bit para a soma, o E e o OU lógicos pode ser
implementada como abaixo:
Operação
vem um
a
0
1 Resultado
b
2
vai um
vem um Operação
a0 vem um
ALU0 resultado0
b0 vai um
a1 vem um
ALU1 resultado1
b1 vai um
.
.
.
a31 vem um
ALU31 resultado31
b31 vai um
aula16.doc 3 de 6
Para implementar a subtração, podemos mudar nossa ALU de um bit
básica para permitir a inversão da entrada b e a soma de 1 através do
“vem um”:
b_invertido Operação
vem um
a 0
b 0 1 Resultado
1 2
vai um
Para incluir a operação feita pela instrução slt (“set on less than”), temos
que adicionar uma entrada “less” no multiplexador de resultado.
Esta entrada é conectada a zero nas ALUs dos bits 1 até 31 (ALU[1-31]).
A ALU do bit de mais alta ordem (ALU31) é modificada para gerar o
sinal “set”, que será igual a 1 se a < b. O sinal set é conectado à entrada
less do bit de mais baixa ordem (ALU0).
b_invertido Operação
vem um
a 0
b 0 1 Resultado
1 2
+
less 3
set
Detecção de
overflow
overflow
vai um
aula16.doc 4 de 6
As instruções de desvio, beq e bne, podem também usar a ALU para
saber se dois registradores são iguais ou diferentes. Para isso, basta
subtrair o valor em um registrador pelo valor no outro e testar se o
resultado é igual a zero.
vem um Operação
a0 vem um
ALU0 resultado0
less
b0 vai um
a1 vem um
ALU0 resultado1
0 less
b1 vai um
.
. .
.
. zero
.
a31 vem um
ALU0 resultado31
0 less
b31 vai um
overflow
set
aula16.doc 5 de 6
O símbolo normalmente usado para representar uma ALU é como abaixo:
aula16.doc 6 de 6
5.4 Multiplicação Inteira
Podemos realizar a operação de multiplicação de números decimais como
abaixo:
1000 multiplicando
x 1001 multiplicador
------
1000
0000
0000
1000
-----------
1001000 produto
Flip-Flops
Flip-flops são dispositivos eletrônicos capazes de guardar estado. O mais
simples é o S-R:
aula17.doc 1 de 11
Um tipo muito importante de flip-flop é o flip-flop tipo D. Existem dois
tipos: acionado por nível e acionado pela borda. Abaixo o acionado por
nível:
aula17.doc 2 de 11
Podemos agrupar flip-flops acionados pela borda ou por nível de modo a
implementar registradores como os de um processador MIPS.
aula17.doc 3 de 11
Podemos agrupar registradores do tipo D acionados pela borda de modo a
implementar um registrador de deslocamento:
aula17.doc 4 de 11
Além disso, o hardware desloca o conteúdo do registrador multiplicador
de um bit para a direita e o valor do registrador multiplicando de um bit
para a esquerda. Este processo é repetido até que o registrador
multiplicador tenha sido deslocado de 32 bits.
aula17.doc 5 de 11
Exemplo de funcionamento:
11
aula17.doc 6 de 11
Segundo hardware e algoritmo para a multiplicação
Pioneiros da computação observaram que metade dos bits do
multiplicando do nosso hardware anterior era sempre igual a zero. Assim,
uma ALU de 64 bits era um desperdício.
aula17.doc 7 de 11
A figura abaixo mostra o algoritmo implementado por este hardware.
aula17.doc 8 de 11
Veja um exemplo da operação do nosso segundo hardware de
multiplicação inteira:
aula17.doc 9 de 11
Terceiro hardware e algoritmo para a multiplicação
Os pioneiros da computação logo observaram que, no último hardware
apresentado, metade dos bits do produto era jogada fora no processo de
multiplicação, ao mesmo tempo em que um número de bits igual era
jogado fora do multiplicador. Assim, eles criaram o nosso terceiro
hardware, que é como abaixo.
aula17.doc 10 de 11
A figura abaixo mostra o algoritmo implementado por nosso hardware
final.
aula17.doc 11 de 11
5.5 Divisão Inteira
A divisão é o recíproco da multiplicação; ela é menos freqüente nos
programas e é mais complexa de se implementar em hardware.
dividendo divisor
1001010 1000
1000 1001 quociente
0001
10
101
1010
1000
0010 resto
aula18.doc 1 de 16
Primeiro hardware e algoritmo para a divisão
A figura abaixo mostra o nosso primeiro hardware para divisão.
Este hardware imita o algoritmo que usamos para a divisão decimal. Para
iniciar uma divisão, zeramos o registrador de quocient, carregamos os 32
bits de mais alta ordem do registrador divisor com o divisor e o
registrador remaider com o dividendo.
aula18.doc 2 de 16
A figura abaixo apresenta o funcionamento deste hardware de divisão na
forma algorítmica.
aula18.doc 3 de 16
Exemplo de funcionamento do algoritmo:
00
aula18.doc 4 de 16
Segundo hardware e algoritmo para a divisão
Como no caso da multiplicação, os pioneiros da computação observaram
que metade dos bits do divisor do nosso hardware anterior era sempre
igual a zero. Assim, uma ALU de 64 bits era um desperdício.
aula18.doc 5 de 16
A figura abaixo mostra o algoritmo implementado pelo segundo hardware
de divisão.
aula18.doc 6 de 16
Veja agora um exemplo da operação do nosso segundo hardware de
divisão inteira:
aula18.doc 7 de 16
Terceiro hardware e algoritmo para a divisão
Como no caso da multiplicação, os pioneiros da computação observaram
que, no último hardware apresentado, a metade dos bits do registrador
remainder era jogada fora no processo de divisão, ao mesmo tempo em
que um número igual de bits era jogado fora do registrador quotient.
Assim, eles criaram o nosso terceiro hardware, que é como abaixo.
aula18.doc 8 de 16
A figura abaixo mostra o algoritmo implementado por nosso hardware
final.
aula18.doc 9 de 16
Veja abaixo um exemplo de divisão usando este último
hardware/algoritmo.
1110
aula18.doc 10 de 16
/
/
A divisão por zero produz infinito como resultado. Esta é uma operação
ilegal em qualquer computador. Muitas máquinas detectam divisão por
zero em hardware, gerando uma exceção.
aula18.doc 11 de 16
5.5 Números de Ponto Flutuante
Além dos números inteiros, com e sem sinal, linguagens de programação
de alto-nível incluem facilidades para representar os números reais da
matemática. Veja alguns exemplos de números reais:
3.141592… (pi)
2.71828… (e)
0.000000001 ou 1.0 x 10-9
3,155,760,000 ou 3.15576 x 109
1.0 x 2-1
1.xxxxxx x 2yyyy
aula18.doc 12 de 16
Os números de ponto flutuante da MIPS ISA podem ser representados em
dois formatos distintos, que são parte do IEEE 754 floating-point
standard (Standard 754 do Instituto dos Engenheiros Eletricistas e
Eletrônicos dos Estados Unidos):
aula18.doc 13 de 16
Uma vez que o número zero não tem um 1 antes do ponto, ele é
representado com o expoente reservado, zero (ver mais detalhes abaixo).
Por isso que o bit de sinal é o bit de mais alta ordem, o que permite fazer
o teste de maior ou menor que zero facilmente, usando as mesmas
instruções para este teste em inteiros.
aula18.doc 14 de 16
Como mencionado anteriormente o expoente igual a zero é usado para
representar o zero.
aula18.doc 15 de 16
Resposta:
Precisão simples
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 0 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Precisão dupla
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 0 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
aula18.doc 16 de 16
5.7 Operações Aritméticas com números de Ponto Flutuante
Para somar dois números na base 10 em notação científica temos que:
2. Somamos
3. Normalizamos
4. Arredondamos
aula19.doc 1 de 6
Um hardware para somar números de ponto flutuante tem que fazer as
mesmas operações com números binários. O algoritmo para soma de
números em ponto flutuante abaixo pode ser implementado em hardware.
aula19.doc 2 de 6
Primeiro, vamos converter os números para notação binária:
Passo 4: Arredondamento
1.000 x 2-4
aula19.doc 3 de 6
O hardware abaixo pode ser utilizado para soma de números de ponto
flutuante conforme o algoritmo apresentado.
aula19.doc 4 de 6
A figura abaixo apresenta as instruções de ponto flutuante da MIPS ISA.
aula19.doc 5 de 6
Esta tabela mostra o quanto cada uma das instruções estudadas até agora
é usada em dois programas reais: gcc – um compilador, e spice – um
programa para analisar o comportamento de circuitos elétricos.
aula19.doc 6 de 6
6 O Processador
6.1 Introdução
aula20.doc 1 de 10
A memória pode ser vista como uma caixa preta, contendo um registrador
específico para cada endereço, sendo que cada um deles pode ser lido ou
escrito independentemente. O banco de registradores de um computador é,
na verdade, uma pequena memória de acesso rápido.
clock
Registradores
Lógica Combinacional
clock
aula20.doc 2 de 10
Um computador é, na verdade, uma máquina de estados bastante complexa,
projetada para, a partir de um estado inicial, mudar seu estado interno
(memória, registradores, etc) de acordo com o especificado por uma
seqüência instruções, que são, na verdade, parte do estado inicial!
aula20.doc 3 de 10
Estes circuitos podem ser agrupados para compor a parte do datapath
responsável por trazer instruções da memória:
aula20.doc 4 de 10
Os componentes abaixo podem ser usados para compor a parte do datapath
responsável por implementar a maioria das instruções lógicas e aritméticas:
aula20.doc 5 de 10
Os componentes mostrados na figura anterior podem ser agrupados como
abaixo:
Na figura acima, uma parte dos bits da instrução é usada para determinar
quais registradores serão lidos e qual será escrito durante a execução da
instrução. Por exemplo, se a instrução é a
A ALU recebe estes valores e opera sobre eles, conforme o que determina a
instrução, e disponibiliza o resultado da operação na sua saída. Esta, é levada
à entrada Write data (Dado de escrita).
aula20.doc 6 de 10
No final do ciclo de clock, o valor computado pela ALU é escrito no
registrador especificado em Write register.
aula20.doc 7 de 10
Como no caso das instruções lógicas e aritméticas, parte dos bits da
instrução é usada para determinar quais registradores serão lidos e qual será
escrito durante a execução da instrução (se a instrução for de leitura na
memória).
lw $8, 1200($19)
nome op rs rt address
campo 1 2 3 4
No. bits 6 5 5 16
decimal 35 19 8 1200
aula20.doc 8 de 10
A ALU recebe o conteúdo de $19 e a constante 1200 extendida de sinal e
disponibiliza a soma destes dois valores na sua saída. Esta, é levada às
entradas Read address (Endereço de leitura) e Write address (Endereço de
escrita) da Data memory (Memória de dados).
aula20.doc 9 de 10
No caso da instrução
bne $8, $21, 100
nome op rs rt address
campo 1 2 3 4
No. bits 6 5 5 16
decimal 5 8 21 100
aula20.doc 10 de 10
6.3 Uma Implementação Exemplo de um Processador
Agora estamos prontos para implementar um processador inteiro a partir dos
blocos básicos que estudamos. A figura abaixo mostra um datapath capaz de
executar instruções de leitura e escrita na memória e instruções lógicas e
aritméticas.
aula21.doc 1 de 21
Os bits que compõem as primeiras duas instruções são como abaixo:
Note que o campo op é igual para o add e o sub: é o campo funct que
diferencia as duas instruções.
Note também que o campo de 16 bits mais a direita não tem o mesmo nome
para as instruções addi e lw.
aula21.doc 2 de 21
Podemos adicionar ao datapath anterior os circuitos responsáveis por trazer
uma instrução da memória como demonstrado abaixo.
aula21.doc 3 de 21
Com mais alguns circuitos podemos fazer um datapath capaz de executar
instruções de desvio:
aula21.doc 4 de 21
As diversas instruções da MIPS ISA possuem formatos diferentes, cada um
para uma classe específica de instruções.
aula21.doc 5 de 21
No datapath abaixo, os bits que compõem a instrução foram separados e
levados a diversas partes do datapath para exercer seu controle. Contudo,
alguns circuitos precisam de controle adicional, como o banco de
registradores, o multiplexador que determina Write Register, o multiplexador
na entrada inferior da ALU, etc, indicados na figura.
aula21.doc 6 de 21
PAREI AQUI: Para implementar o controle adicional incluímos uma
unidade de controle como indicado abaixo:
aula21.doc 7 de 21
A figura anterior mostra um processador completo, com um datapath e o
circuito de controle deste datapath. Este processador pode executar a
instrução add $2, $3, $4 seguindo os seguintes passos:
aula21.doc 8 de 21
Vamos ver agora como a instrução lw $2, 1000($3) pode ser executada pelo
mesmo processador. Os passos abaixo mostram o fluxo de informações no
datapath durante a execução desta instrução:
A instrução beq $3, $4, 1000 pode ser executada com os seguintes passos:
aula21.doc 9 de 21
6.4 Um Exemplo com Múltiplos Ciclos de Clock por Instrução
Na implementação do processador MIPS mostrada, todas as instruções
executam em um ciclo e, assim, o CPI de todas elas é igual a 1. Isso, no
entanto, faz com que o tempo de ciclo tenha que ser igual ao da instrução
que demora mais para executar.
Exercício:
Se assumirmos que em uma implementação de um processador MIPS:
a) As memórias tenham um tempo de acesso (da aplicação do endereço de
acesso até a disponibilização dos dados na saída) de 10 ns.
b) A ALU e os somadores demorem 10 ns para fazer suas operações.
c) O banco de registradores tenha um tempo de acesso de 5 ns.
d) Os multiplexadores, a unidade de controle, a unidade de extensão de
sinal, acessos ao PC e os fios conectando os componentes não atrasem a
propagação dos sinais.
Qual é o valor ideal do período de clock para as instruções add, lw e beq?
Qual é o período de clock que este processador tem que ter?
Resposta:
Para executar cada uma das instruções temos que:
add fetch leitura dos ALU escrita no
registradores registrador
lw fetch leitura dos ALU acesso à escrita no
registradores memória registrador
beq fetch leitura dos ALU
registradores
aula21.doc 10 de 21
Através do exemplo dado por este exercício podemos ver que o ideal seria
termos um tempo de ciclo diferente para cada instrução ou uma solução
equivalente.
Observe que nenhum passo necessita de mais que uma operação de ALU ou
soma de endereço.
aula21.doc 11 de 21
Assim, apenas uma ALU bastaria para implementar todo o processador se
usássemos múltiplos ciclos para executar cada instrução: teríamos apenas
que direcionar os dados corretos para a ALU a cada ciclo.
aula21.doc 12 de 21
aula21.doc 13 de 21
A unidade de controle deste processador não é combinacional, como a da
primeira implementação – esta unidade de controle é uma máquina de
estados. Um diagrama de blocos desta máquina de estados seria como
abaixo:
aula21.doc 14 de 21
aula21.doc 15 de 21
Os círculos representam os estados e as setas indicam as transições de um
estado para outro. Uma transição de estado ocorre a cada ciclo de clock.
aula21.doc 16 de 21
6.5 Microprogramação
Implementar um processador como o discutido na seção anterior é fácil se a
ISA possui apenas umas poucas instruções. Mas mesmo a MIPS ISA, que é
uma ISA bem simples, possui cerca de 100 instruções.
aula21.doc 17 de 21
A figura abaixo mostra uma unidade de controle microprogramada.
aula21.doc 18 de 21
A figura abaixo mostra um microprograma, com 10 microinstruções, é capaz
de emular algumas instruções que estudamos usando a micromáquina acima
e o datapath da Figura 5.39.
M0
M1
M2
M3
M4
M5
M6
M7
M8
M9
aula21.doc 19 de 21
Um micro-assembler é geralmente usado para converter o microprograma
simbólico em um microprograma em linguagem de micro máquina (bits).
aula21.doc 20 de 21
aula21.doc 21 de 21
6.7 Paralelismo Temporal e Espacial
Uma ALU permite a execução em paralelo de operações sobre vários bits (32,
64, etc.). Acima do paralelismo no nível de bit, temos o Paralelismo no Nível
Instrução (Instruction Level Paralelism – ILP). Existem dois tipos básicos de
ILP: temporal e espacial.
(a)
Clock Cycle 0 1 2 3 4 5 7
Fetch Stage I1 I2 I3 I4 I5 I6 I7
Decode Stage I1 I2 I3 I4 I5 I6
Execute Stage I1 I2 I3 I4 I5
M. Access Stage I1 I2 I3 I4
W. Back Stage I1 I2 I3
(b)
Porque as operações realizadas por cada estágio do pipeline são simples, cada
um destes estágios pode ser implementado com hardware simples, o que resulta
em uma máquina capaz de funcionar com uma alta frequência de clock.
aula21a.doc 1 de 27
ILP espacial é aquele presente em processadores com múltiplas unidades
funcionais. Refere-se à execução de mais de uma instrução simultaneamente em
diferentes unidades funcionais do processador.
FU FU FU FU FU Execute
Write Back
Result Buses
Data Memory (b)
(a)
aula21a.doc 2 de 27
6.8 Pipelining
aula21a.doc 3 de 27
Na figura abaixo á apresentado conjunto de instruções da MIPS 64.
aula21a.doc 4 de 27
A arquitetura anterior pode ser implementada usando pipelining como abaixo.
aula21a.doc 5 de 27
A Figura abaixo ajuda a visualizar melhor a evolução da execução das instruções
no pipeline.
Na figura, a execução de uma sequencia de instruções (no lado direito) pode ser
analisada a cada ciclo de clock (colunas); isto é, podemos visualizar onde cada
instrução estará no pipeline a partir do ciclo onde a primeira entra no pipeline
(cycle 1).
aula21a.doc 6 de 27
Na figura acima, não há dependências entre as instruções, mas elas podem
ocorrer, como no caso abaixo.
Na figura acima, três instruções têm sua execução afetada pela necessidade do
dado produzido pela primeira (r1). Ou seja, elas possuem dependência de dados
com a primeira.
aula21a.doc 7 de 27
I: add r1,r2,r3 I: sub r4,r1,r3
J: sub r4,r1,r3 J: add r1,r2,r3
K: mul r6,r1,r7
Dependência Verdadeira (RAW) Anti Dependência (WAR)
I: sub r1,r4,r3
J: add r1,r2,r3
K: mul r6,r1,r7
Dependência de Saída (WAW)
Dependência de Controle
Na figura abaixo, o dado produzido pela primeira instrução precisa ser, de algum
modo, comunicado para as instruções que precisam dele em estágios anteriores
do pipeline.
aula21a.doc 8 de 27
aula21a.doc 9 de 27
Uma técnica conhecida como forwarding pode ser empregada para resolver o
problema de dependências verdadeiras dentro de pipeline. A figura abaixo ilustra
como a técnica forwarding resolve o problema de dependências de dados
verdadeiras dentro do pipeline.
aula21a.doc 10 de 27
Contudo, há casos como o abaixo que não tem solução e uma “bolha” tem que
ser inserida no pipeline.
aula21a.doc 11 de 27
As figuras a seguir mostram a execução de uma sequencia de instruções sem
dependência de dados:
aula21a.doc 12 de 27
aula21a.doc 13 de 27
aula21a.doc 14 de 27
As figuras a seguir mostram a execução de uma sequencia de instruções com
dependência de dados e sem forwarding:
aula21a.doc 15 de 27
aula21a.doc 16 de 27
aula21a.doc 17 de 27
aula21a.doc 18 de 27
As figuras a seguir mostram a execução de uma sequencia de instruções com
dependência de dados e com forwarding:
aula21a.doc 19 de 27
aula21a.doc 20 de 27
aula21a.doc 21 de 27
As figuras a seguir mostram que, mesmo com forwarding, há casos que não é
possível evitar bolhas no pipeline:
aula21a.doc 22 de 27
aula21a.doc 23 de 27
A figura abaixo ilustra uma dependência de controle.
aula21a.doc 24 de 27
aula21a.doc 25 de 27
Note que, se não aproveitarmos os dados disponíveis no estágio de execução
(linhas em vermelho) para determinar o próximo PC, teremos que anular 3
instruções.
aula21a.doc 26 de 27
Dependências de controle podem ser tratadas em máquinas pipelined
basicamente de quatro formas diferentes:
1. Parando (stall) o pipeline até que a direção do desvio seja conhecida
2. Predizendo que o desvio não vai ser tomado
3. Predizendo que o desvio vai ser tomado
4. Incluindo o conceito de desvio atrasado (delayed branch) na ISA
aula21a.doc 27 de 27
7 Hierarquia de Memória
7.1 Introdução
Os programadores sempre quiseram quantidades ilimitadas de memória
rápida desde a criação do primeiro computador.
Se algum tópico não está coberto em nenhum dos livros na mesa, você
vai novamente às estantes da biblioteca e pega mais um livro contendo
aquele tópico.
Depois de algum tempo, todos os livros que você precisa vão estar na
mesa se ela for grande o suficiente para abrigá-los.
Esta estratégia toma muito menos tempo que trazer um livro para a mesa,
consultá-lo, devolvê-lo à estante e, só então, ir buscar um outro livro para
consulta.
Do mesmo modo que você não pesquisa todos os livros da biblioteca com
igual probabilidade, um programa não acessa todos os dados e instruções
presentes na memória com igual probabilidade.
aula22.doc 1 de 7
As técnicas mencionadas acima são baseadas no princípio da localidade.
Existem dois tipos de localidade:
Localidade temporal: Se um item é referenciado, ele tende a ser
referenciado novamente em um curto espaço de tempo;
Localidade espacial: Se um item é referenciado, itens próximos a
ele tendem a ser referenciados também em um curto espaço de
tempo.
Memórias rápidas são, em geral, mais caras que memórias lentas e, por
isso, elas são, em geral, menores.
aula22.doc 2 de 7
As relações de preço não mudaram muito desde então, como mostram as
tabelas a seguir.
Memórias DRAM
HDs
aula22.doc 3 de 7
No gráfico abaixo é apresentada a evolução do preço de diversos tipos de
memória de 1950 até o presente.
aula22.doc 4 de 7
Do mesmo modo que você encontra mais freqüentemente as informações
de que você precisa na mesa em que você está trabalhando na biblioteca,
o processador encontra mais freqüentemente as instruções e os dados de
que ele precisa nos níveis da hierarquia de memória mais próximos dele.
O hit rate (taxa de acerto), ou hit ratio, é igual ao total de hits divido pelo
total de acessos em um determinado nível. A miss rate é igual a (1.0 – hit
rate), que é proporcional ao percentual de acessos que não encontraram a
informação em um determinado nível da hierarquia de memória.
aula22.doc 5 de 7
7.2 Cache
Uma memória cache é uma memória rápida que contém os dados e/ou
instruções mais recentemente referenciados pelo processador.
A figura acima deixa duas perguntas: (i) Onde procurar o dado dentro da
cache? (ii) Como saber se o dado de interesse realmente está neste lugar?
aula22.doc 6 de 7
Na figura, os 14 bits de mais baixa ordem do endereço são usados para
escolher um dos blocos, onde pode estar o dado de interesse.
aula22.doc 7 de 7
7.2.1 Cache hits e cache misses
Quando o processador acessa uma das caches (a de instruções ou a de
dados) pode ocorrer um miss ou um hit; muito mais hits do que misses, na
verdade. Primeiramente, vamos examinar o miss.
aula23.doc 1 de 17
O sinal hit, sendo igual a zero, informa ao processador para esperar até
que a cache possa entregar o conteúdo da posição de memória
endereçada.
aula23.doc 2 de 17
A figura a seguir mostra uma pequena cache, com oito entradas, e o que
ocorre a cada miss para sequência de acessos de leitura: 10110 (miss),
11010 (miss), 10110 (hit), 11010 (hit), 10000 (miss), 00100 (miss), 10000
(hit), e 10010 (miss).
Memory (11010two)
Memory (10000two) Y
aula23.doc 3 de 17
7.2.2 Políticas de escrita na cache
Até aqui assumimos acessos de leitura apenas. Em acessos de escrita na
cache podem ocorrer hits ou misses mas, em qualquer dos casos, o dado
tem que ser escrito na memória.
aula23.doc 4 de 17
Acessos de escrita subsequentes vão sendo enfileirados no buffer ao
mesmo tempo em que os valores dentro dele vão sendo escritos na
memória. Se o buffer encher, aí sim o processador tem que esperar até
que haja uma entrada livre no buffer. O cache de dados da DECStation
3100 possui um buffer de 4 entradas.
aula23.doc 5 de 17
Um buffer de escrita pode também ser usado em caches com política de
escrita write back; contudo, eles são menos importantes neste caso, já que
a próprio cache atua como um buffer de escrita. A política write back é
mais complexa, mas resulta em menos misses.
A figura abaixo mostra o desempenho da cache que temos visto até agora
quando usada para dados e para instruções (a DECStation 3100 tem
caches iguais para dados e para instruções).
aula23.doc 6 de 17
aula23.doc 7 de 17
7.2.3 Tirando proveito da localidade espacial
Um observador atento deve ter notado que a cache que temos estudado
até agora não tira vantagem da localidade espacial, mas apenas da
localidade temporal. Isso porque cada bloco (entrada) da cache vista até
agora só acomodava uma palavra de memória.
aula23.doc 8 de 17
Na cache da Figura 7.9, cada bloco possui quatro palavras de 32 bits.
Quando ela é acessada, o endereço é separado em campos como indicado.
Um novo campo foi incluído: o campo block offset.
Este campo vai dizer qual das palavras de um bloco está sendo acessada.
O multiplexador da figura separa esta palavra usando o campo block
offset.
Acessos de leitura, sejam eles hits ou misses, são tratados nesta cache da
mesma forma que na cache com blocos de uma palavra apenas. Escritas
que resultam em hits também são tratadas como anteriormente, seja a
cache write through ou write back. Acessos de escrita que resultam em
misses, por outro lado, têm que ser tratados de forma diferente.
aula23.doc 9 de 17
A figura abaixo mostra como os desempenhos das caches da DECStation
3100 melhoram se mudarmos o tamanho do bloco das caches para quatro
palavras e mantivermos o restante (a capacidade do cache,
principalmente) inalterado.
aula23.doc 10 de 17
O desempenho melhora, principalmente o da cache de instruções, porque
agora estamos tirando proveito da localidade espacial. Contudo, se o
bloco é muito grande comparado com o tamanho total da cache, o
desempenho pode cair.
aula23.doc 11 de 17
7.2.4 Formas de comunicação cache-memória
A forma básica de se ligar uma cache à memória é a da Figura 7.12a,
abaixo:
aula23.doc 12 de 17
7.2.5 Associatividade das caches
Podemos melhorar o desempenho das caches ainda mais se pudermos
procurar por um dado em mais de um bloco ao mesmo tempo. Ou seja, se
pudermos fazer o que é conhecido como uma busca associativa pelo dado
na cache.
aula23.doc 13 de 17
Em uma cache com associatividade igual a dois, um único endereço está
associado a dois blocos: para se saber qual é o bloco correto as duas tags
(ver Figura 7.23) têm que ser comparadas com a parte alta do endereço.
Caches com maior grau de associatividade requerem mais comparações.
aula23.doc 14 de 17
Quando um ocorre um miss em uma cache com associatividade maior que
1 temos que decidir que bloco deve ser substituído.
aula23.doc 15 de 17
7.2.5 Entendendo o comportamento das caches
Existem três tipos de miss:
1. Compulsório: O primeiro acesso a um bloco de memória é um miss
compulsório (não pode ser evitado).
2. De capacidade: Se uma cache é pequena demais para conter todos
os blocos necessários à execução de um programa, ocorrerão
misses de capacidade devido aos blocos que têm que ser
descartados e depois relidos.
3. De conflito: Em caches direct mapped ou associativas por sets,
mais de um bloco de memória é mapeado no mesmo bloco ou
conjunto de blocos da cache. Quando ocorrem acessos a blocos de
memória associados ao mesmo set em maior número que o número
de blocos no set, teremos misses de conflito.
aula23.doc 16 de 17
Exercício: A figura abaixo mostra uma cache com associatividade 4, 256
sets e blocos de uma palavra de tamanho (32bits). A política de
substituição de blocos é LRU. Supondo que, inicialmente:
todos os blocos têm bit de válido igual a zero
os blocos sejam numerados da direita para esquerda e que todos
eles tenham sido usados em ordem uma vez (o primeiro a ser usado
sendo o da esquerda e o último o da direita)
diga que blocos de quais sets (em hexadecimal) são modificados se a
sequência de escritas abaixo é realizada pelo processador.
aula23.doc 17 de 17
7.3 Memória Virtual
Do mesmo modo que caches permitem acesso rápido a instruções e dados
armazenados na memória e usados recentemente pelo processador, a
memória também pode permitir acesso rápido aos dados e programas
armazenados em unidades de armazenamento secundário (usualmente discos
rígidos).
A técnica usada para isso é conhecida como memória virtual. Existem duas
motivações principais para o uso desta técnica: (i) permitir o
compartilhamento eficiente da memória entre vários programas, e (ii)
remover as dificuldades de programação introduzidas por uma memória
principal pequena.
aula24.doc 1 de 15
A memória virtual, que foi inventada para tirar este trabalho dos
programadores, gerencia automaticamente os dois níveis de hierarquia de
memória representados pela memória principal e pelas unidades de
armazenamento secundário.
aula24.doc 2 de 15
Através da relocação de endereços, um sistema de memória virtual também
simplifica a tarefa de carregar um programa na memória para execução.
aula24.doc 3 de 15
No mapeamento acima, uma página possui 4Kbytes. O número máximo de
páginas físicas permitido é igual a 218, o que resulta em uma memória física
de no máximo 1Gbyte. O espaço de endereçamento virtual, contudo, pode
ter 4Gbytes.
aula24.doc 4 de 15
7.3.1 Mapeamento Memória Virtual - Memória Física
Uma página virtual pode ser mapeada em qualquer página física. Assim,
sistemas de memória virtual são fully associative (totalmente associativos).
Se uma página virtual pode ser mapeada para qualquer página física, nós
precisamos de um mecanismo para encontrá-la na memória física. Este
mecanismo é implementado através de tabelas de páginas.
Cada programa tem a sua própria tabela de páginas, que mapeia seus
endereços virtuais (escolhidos durante a compilação) aos seus endereços
físicos (escolhidos pelo sistema operacional durante a execução).
aula24.doc 5 de 15
Na figura, parte do endereço virtual é mapeado diretamente para o endereço
físico por meio dos bits conhecidos como page offset.
Estes bits escolhem qual endereço dentro da página que o processador deseja
acessar e não precisam ser manipulados pelo processo de tradução do
endereço virtual para o endereço físico.
Na verdade, estes bits são um índice para a tabela e apontam para a entrada
dela que contém o número da página física correspondente à página virtual.
aula24.doc 6 de 15
Um bit de válido na tabela indica se existe de fato esta correspondência, isto
é, se existe uma página física associada à página virtual desejada pelo
processador.
aula24.doc 7 de 15
Sempre que o processador fizer acessos a páginas, seja para instruções ou
dados, cujos bits de válido são iguais a zero, ele será interrompido e chamará
o S.O. para que ele:
i. ache a página requisitada pelo programa no disco;
ii. escolha uma página física para colocar a página trazida do disco;
iii. transfira a página do disco para a página física escolhida;
iv. atualize a tabela de páginas;
v. e transferira o controle do processador ao programa outra vez.
aula24.doc 8 de 15
Para ajudar o S.O. a ter uma ideia de qual página foi usada há mais tempo, as
implementações de memória virtual geralmente incluem um vetor de estado,
com um conjunto de bits para cada página física, que servem para indicar se
uma página física foi acessada e de que modo.
Um outro bit do vetor de estado é o dirty bit, que indica se uma página foi
escrita. Se uma página escolhida para dar lugar à outra em um page fault foi
escrita ela precisa ser copiada de volta no disco antes de ser sobrescrita, caso
contrário, ela pode simplesmente ser sobrescrita.
aula24.doc 9 de 15
PTR
aula24.doc 10 de 15
Para evitar isso, computadores com memória virtual possuem um pequeno
cache com as traduções de endereços virtuais para endereços físicos mais
recentes chamado de TLB.
aula24.doc 11 de 15
TLBs são pequenos – usualmente possuem entre 64 e 512 entradas. Cada
entrada guarda o número da página física correspondente a uma página
virtual, um bit de válido, além de outros bits. TLBs são em geral fully
associative e o número da página virtual é usado como tag do TLB.
Se os 20 bits que indicam a página são iguais a qualquer uma das entradas
do TBL, o número da página física guardado no TLB é usado para acessar a
memória junto com os 12 bits que indicam o dado desejado.
aula24.doc 12 de 15
Quando o processador tenta um acesso à memória ele consulta primeiro o
TLB para ver se já existe nele uma tradução da página virtual desejada para
a página física correspondente.
Caso não exista, temos um TLB miss. TLB misses podem ser tratados por
hardware, ou por software via exceção (a diferença de desempenho entre
estas duas opções é pequena).
Quando de um TLB miss, a tabela de páginas, que está na memória, tem que
ser consultada.
aula24.doc 13 de 15
Se a página correspondente ao endereço virtual acessado pelo processador já
estiver mapeada na memória física, este mapeamento (o número da página
física) é copiado para o TLB junto com outros bits, como o dirty bit da
página por exemplo.
Nestes casos, uma das entradas do TLB tem que ser selecionada para ser
sobrescrita. A seleção é feita randomicamente ou usando a política LRU.
Quando esta entrada contiver informações sobre uma página de memória
que foi escrita, os bits associados à página e guardados no TLB têm que ser
escritos de volta na tabela de páginas para manter a consistência da tabela de
páginas.
A figura abaixo apresenta o algoritmo que tem que ser obedecido em todos
os acessos à memória feitos em um computador que empregue memória
virtual.
aula24.doc 14 de 15
aula24.doc 15 de 15
8. Entrada e Saída (Input/Output – I/O)
8.1 Introdução
Um computador é composto pelo processador, memória e dispositivos de
I/O. Nós já estudamos o processador e a memória e, no início do curso,
alguns dispositivos de I/O. Agora vamos estudar alguns mecanismos de
I/O.
aula25.doc 1 de 12
As velocidades exigidas de cada dispositivo de I/O variam fortemente. De
alguns dispositivos não se requer, hoje, mais velocidade. Nesta categoria
poderíamos incluir o teclado e o mouse, por exemplo.
aula25.doc 2 de 12
8.2 Performance de Entrada/Saída (Input/Output – I/O)
Os principais parâmetros de desempenho de I/O são latência e taxa de
transferência (throughput).
8.3 Barramentos
aula25.doc 3 de 12
Barramentos de memória conectam o cache do processador à memória
principal. Eles são os mais rápidos e, por isso, são geralmente curtos
(poucos centímetros separam a CPU da memória) devido à velocidade de
propagação dos sinais nos fios, limitada pela velocidade da luz.
aula25.doc 4 de 12
A figura abaixo mostra exemplos de como os diferentes tipos de
barramentos podem ser usados em conjunto.
aula25.doc 5 de 12
Barramentos podem ser síncronos ou assíncronos. Um barramento
síncrono possui um clock que determina o momento de todas as
operações: todos os dispositivos têm que realizar suas operações dentro
de um número de ciclos de clock e os momentos em que os dados e
endereços têm que ser apresentados, relativos à subida e/ou descida do
clock, também têm que ser precisos.
aula25.doc 6 de 12
Na Figura 8.10, os sinais ReadReq, Ack, e DataRdy são sinais de controle
de um bit e são carregados em um fio, enquanto que Data carrega os
sinais de dados e endereços e é implementado com 8 fios, 16 fios, 32 fios,
etc, dependendo do tamanho dos dados ou endereços sendo comunicados
através do barramento.
aula25.doc 7 de 12
ReadReq, e segue como indicado nos passos abaixo (acompanhe pela
Figura 8.10):
1. Quando o Escravo “vê” o sinal ReadReq ligado, ele lê o endereço e
liga o sinal Ack para indicar que o endereço já foi lido.
2. O Mestre percebe que o sinal Ack está ligado, desliga o sinal
ReadReq e libera as linhas Data.
3. O Escravo percebe que o sinal ReadReq foi desligado e desliga o
sinal Ack.
4. Quando o Escravo tem pronto o dado pedido pelo Mestre, ele liga
o sinal DataRdy e coloca o dado em Data.
5. Quando o Mestre vê que DataRdy está ligado, ele lê o dado de
Data e liga o sinal Ack.
6. O Escravo percebe que o sinal Ack está ligado e desliga o sinal
DataRdy e libera as linhas Data.
7. O Mestre percebe que DataRdy foi desligado e desliga o sinal Ack.
Isto termina a transferência.
aula25.doc 8 de 12
8.4 Direct Memory Access (DMA)
A figura abaixo mostra o protocolo de handshaking de leitura descrito na
forma de máquinas de estado. Na figura, o Mestre é o I/O Device
(dispositivo de I/O) e o Escravo é a Memory (memória). Dispositivos de
I/O capazes de acessar diretamente a memória são conhecidos como
dispositivos com capacidade de DMA (Direct Memory Access).
aula25.doc 9 de 12
8.5 Arbitração de Barramentos
Para se tornar Mestre do barramento, a CPU, memória ou os dispositivos
de I/O tem que “pedir” o barramento. O processo de solicitação e entrega
do barramento a um Mestre é chamado de arbitração de barramento (bus
arbitration).
aula25.doc 10 de 12
8.6 I/O Serial
Quando o I/O é serial apenas um bit pode ser transferido de cada vez. I/O
serial pode ser síncrono ou assíncrono, e estes dois tipos de comunicação
serial podem ocorrer em canais de comunicação simplex, half-duplex e
full-duplex.
aula25.doc 11 de 12
Quando aparece um nível lógico igual a zero no canal, o receptor sabe
que o transmissor está enviando um start bit. Assim, logo após o start bit,
o transmissor envia e o receptor recebe os bits de dados e depois os stop
bits, a partir dos quais pode vir um novo start bit, dados, stop bits, etc,
continuamente.
aula25.doc 12 de 12