Você está na página 1de 14

5.

Material avanado: Implementando


controladores de cache

A seo comea com o SystemVerilog do controlador de cache da Seo 5.7 em oito figuras. Depois, entra nos detalhes de um protocolo de coerncia de cache de exemplo e as
dificuldades na implementao de tal protocolo.

SystemVerilog de um controlador de cache simples


A linguagem de descrio de hardware que estamos usando nesta seo SystemVerilog. A
maior mudana das verses anteriores do Verilog que ele apanha estruturas da linguagem
C para tornar o cdigo mais fcil de ler. As Figuras de 5.9.1 a 5.9.8 mostram a descrio
em SystemVerilog do controlador de cache.
As Figuras 5.9.1 e 5.9.2 declaram as estruturas que so usadas na definio da cache nas
figuras seguintes. Por exemplo, a estrutura de tag de cache (cache_tag_type) contm
um bit de validade (valid), um bit de modificao (dirty) e um campo de tag de 18
bits (tag [TAGMSB:TAGLSB]). A Figura 5.9.3 mostra o diagrama em blocos da cache
usando os nomes da descrio Verilog.
package cache_def;
// estruturas de dados para tag e dados de cache
parameter int TAGMSB = 31; //tag msb
parameter int TAGLSB = 14; //tag lsb
// estrutura de dados para tag de cache
typedef struct packed {
bit valid; //bit valid
bit dirty; //bit dirty
bit [TAGMSB:TAGLSB]tag; //tag bits
}cache_tag_type;
// estrutura de dados para solicitao de memria cache
typedef struct {
bit [9:0]index;
// ndice de 10 bits
bit we;
// write enable
}cache_req_type;
// dados da linha de cache de 128 bits
typedef bit [127:0]cache_data_type;
FIGURA 5.9.1 Declaraes de tipo no SystemVerilog para as tags e dados de cache. O campo de tag tem 18 bits de
largura e o campo de ndice tem 10 bits de largura, enquanto um campo de 2 bits (bits 3-2) usado para indexar o
bloco e selecionar a word do bloco. O restante da declarao de tipo encontrado na figura seguinte.

Material Complementar

ELSEVIER

// Estruturas de dados para interface CPU<->Controlador de cache


// Solicitao de CPU (CPU->controlador de cache)
typedef struct {
bit [31:0]addr;
// endereo de solicitao de 32 bits
bit [31:0]data; // dados de solicitao de 32 bits (usados na
escrita)
bit rw;
// tipo de solicitao: 0 = leitura, 1 = escrita
bit valid;
// solicitao vlida
}cpu_req_type;
// Resultado da cache (controlador de cache->cpu)
typedef struct {
bit [31:0]data; // dados de 32 bits
bit ready;
// resultado est pronto
}cpu_result_type;
//-----------------------------------------------------------------// estruturas de dados para controlador de cache<->interface de memria
// solicitao de memria (controlador de cache->memria)
typedef struct {
bit [31:0]addr;
// solicita endereo do byte
bit [127:0]data; // dados de solicitao de 128 bits (usado na
escrita)
bit rw;
// tipo de solicitao : 0 = leitura, 1 = escrita
bit valid;
// solicitao vlida
}mem_req_type;
// resposta do controlador de memria (memria -> controlador de cache)
typedef struct {
cache_data_typedata; // dados de 128 bits lidos de volta
bit ready;
// dados prontos
}mem_data_type;
endpackage
FIGURA 5.9.2 Declaraes de tipo em SystemVerilog para as interfaces CPU-cache e cache-memria. Estas so
quase idnticas, exceto que os dados tm 32 bits de largura entre a CPU e a cache, e 128 bits entre a cache e a memria.

5.9 Material avanado: Implementando controladores de cache 3

FIGURA 5.9.3 Diagrama em blocos da cache simples usando os nomes do Verilog. No aparecem aqui os write enables para a memria de tag da cache e
para a memria de dados da cache, ou os sinais de controle para multiplexadores que fornecem dados para a varivel Data Write. Em vez de ter write enables
separados em cada word do bloco da cache de dados, o Verilog l o valor antigo do bloco no Data Write e depois atualiza a word nessa varivel em uma escrita.
Depois, ele escreve o bloco inteiro de 128 bits.

A Figura 5.9.4 instancia mdulos para os dados de cache (dm_cache_data) e tag de


cache (dm_cache_tag). Essas memrias podem ser lidas a qualquer momento, mas as
escritas s ocorrem na transio positiva do clock (posedge(clk)) e somente se write
enable for 1 (data_req.we ou tag_req.we).
/*cache: memria de dados, nica porta, 1024 blocos*/
module dm_cache_data(input bit clk,
input cache_req_type data_req,// requisita dados/comando, p.e.
RW, valid
input cache_data_type data_write, // porta de escrita (linha de
128 bits)
output cache_data_type data_read); // porta de leitura
timeunit 1ns; timeprecision 1ps;
cache_data_typedata_mem[0:1023];
initial begin
for (int i=0; i<1024; i++)
data_mem[i] = 0;
end

Material Complementar

ELSEVIER

assign data_read = data_mem[data_req.index];


always_ff @(posedge(clk)) begin
if (data_req.we)
data_mem[data_req.index] <= data_write;
end
endmodule
/*cache: memria de tag, nica porta, 1024 blocos*/
module dm_cache_tag(input bit clk, //clock de escrita
input cache_req_type tag_req, //requis. de tag/comando, p.e.
RW, valid
input cache_tag_type tag_write, //porta de escrita
output cache_tag_type tag_read); //porta de leitura
timeunit 1ns; timeprecision 1ps;
cache_tag_typetag_mem[0:1023];
initial begin
for (int i=0; i<1024; i++)
tag_mem[i] = 0;
end
assign tag_read = tag_mem[tag_req.index];
always_ff @(posedge(clk)) begin
if (tag_req.we)
tag_mem[tag_req.index] <= tag_write;
end
endmodule
FIGURA 5.9.4 Dados de cache e mdulos de tag no SystemVerilog. Estes so quase idnticos, exceto que os dados
tm 32 bits de largura entre a CPU e a cache, e tm 128 bits de largura entre a cache e a memria. Ambos s escrevem
nas transies de clock positivas, se o write enable estiver marcado.

A Figura 5.9.5 define as entradas, sadas e estados da FSM (mquina de estados finitos). As
entradas so as requisies da CPU (cpu_req) e as respostas da memria (mem_data), e
as sadas so as respostas CPU (cpu_res) e requisies memria (mem_req). A figura
tambm declara as variveis internas necessrias pela FSM. Por exemplo, os registradores de
estado atual e prximo estado da FSM so rstate e vstate, respectivamente.
/*mquina de estados finitos da cache*/

module dm_cache_fsm(input bit clk, input bit rst,


input cpu_req_type cpu_req, //entrada de req. de CPU
(CPU->cache)
input mem_data_type mem_data, //resp. da memria (memria->cache)
output mem_req_type mem_req, //req. de memria (cache->memria)
output cpu_result_type cpu_res //resultado da cache (cache->CPU)
);
timeunit 1ns;
timeprecision 1ps;

5.9 Material avanado: Implementando controladores de cache 5

/*clock de escrita*/
typedef enum {idle, compare_tag, allocate, write_back} cache_state_
type;
/*registrador de estado da FSM*/
cache_state_typevstate, rstate;
/*sinais de interface memria de tag*/
cache_tag_typetag_read; //resultado de leitura de tag
cache_tag_typetag_write; //dados de escrita de tag
cache_req_typetag_req; //solicitao de tag
/*sinais de interface para memria de dados da cache*/
cache_data_typedata_read; //dados de leitura da linha de cache
cache_data_typedata_write; //dados de escrita da linha de cache
cache_req_typedata_req; //requisio de dados
/*varivel temporria para resultado do controlador de cache*/
cpu_result_typev_cpu_res;
/*varivel temporria para requisio do controlador de memria*/
mem_req_typev_mem_req;
assign mem_req = v_mem_req; //conecta s portas de sada
assign cpu_res = v_cpu_res;
FIGURA 5.9.5 FSM no SystemVerilog, parte I. Esses mdulos instanciam as memrias de acordo com as definies
de tipo na figura anterior.

A Figura 5.9.6 lista os valores default dos sinais de controle, incluindo a word a ser lida
ou escrita a partir de um bloco, definindo os write enables da cache como 0, e assim por
diante. Esses valores so definidos a cada ciclo de clock, de modo que o write enable para
uma parte da cache por exemplo, tag_req.we seria definido como 1 para um
ciclo de clock nas figuras a seguir e depois seria retornado a 0 de acordo com o Verilog
nessa figura.
always_comb begin
/*-------------- valores default para todos os sinais -----------*/
/*sem mudana de estado por default*/
vstate = rstate;
v_cpu_res = {0, 0}; tag_write = {0, 0, 0};
/*l tag por default*/
tag_req.we = 0;
/*direciona ndice do mapa para tag*/
tag_req.index = cpu_req.addr[13:4];
/*l linha de cache atual por default*/
data_req.we = 0;
/*direciona ndice de mapa para dados da cache*/
data_req.index = cpu_req.addr[13:4];
/*modifica word correta (32 bits) com base no endereo*/
data_write = data_read;

Material Complementar

ELSEVIER

case(cpu_req.addr[3:2])
2b00:data_write[31:0] = cpu_req.data;
2b01:data_write[63:32] = cpu_req.data;
2b10:data_write[95:64] = cpu_req.data;
2b11:data_write[127:96] = cpu_req.data;
endcase
/*leitura da word correta (32 bits) da cache (para CPU)*/
case(cpu_req.addr[3:2])
2b00:v_cpu_res.data = data_read[31:0];
2b01:v_cpu_res.data = data_read[63:32];
2b10:v_cpu_res.data = data_read[95:64];
2b11:v_cpu_res.data = data_read[127:96];
endcase
/*endereo da requisio de memria (apanhado da req. de CPU)*/
v_mem_req.addr = cpu_req.addr;
/*dados de requisio de memria (usados na escrita)*/
v_mem_req.data = data_read;
v_mem_req.rw = 0;
FIGURA 5.9.6 FSM no SystemVerilog, parte II. Esta seo descreve o valor default de todos os sinais. As figuras seguintes definiro esses valores para um ciclo de clock, e esse Verilog retornar a esses valores no ciclo de clock seguinte.

As duas ltimas figuras mostram a FSM como uma grande instruo case (case
(rstate)), com as quatro divises de estado nas duas figuras. A Figura 5.9.7 comea com
o estado Idle (idle), que simplesmente vai para o estado Compare Tag (compare_tag)
se a CPU fizer uma requisio vlida. Depois, ela descreve a maior parte do estado Compare
Tag. O estado Compare Tag verifica se as tags combinam e a entrada vlida. Se for, ento
ela primeiro define o sinal Cache Ready (v_cpu_res.ready). Se a requisio for uma
escrita, ela define o campo de tag, o bit de validade e o bit de modificao. O estado seguinte
Idle. Se for uma perda de cache, ento o estado se prepara para mudar a entrada da tag
e os bits de validade e modificao. Se o bloco a ser substitudo estiver limpo ou invlido,
o prximo estado Allocate.
//----------------------- FSM da cache------------------------case(rstate)
/*estado idle*/
idle : begin
/*Se houver requisio de CPU, ento compara tag de cache*/
if (cpu_req.valid)
vstate = compare_tag;
end
/*estado compare_tag*/
compare_tag : begin
/*acerto de cache (tag combina e entrada de cache vlida)*/
if (cpu_req.addr[TAGMSB:TAGLSB] == tag_read.tag && tag_read.valid) begin
v_cpu_res.ready = 1;
/*acerto de escrita*/
if (cpu_req.rw) begin
/*linha de cache read/modify*/
tag_req.we = 1; data_req.we = 1;

end

5.9 Material avanado: Implementando controladores de cache 7

/*sem mudana na tag*/


tag_write.tag = tag_read.tag;
tag_write.valid = 1;
/*linha de cache modificada*/
tag_write.dirty = 1;
/*xaction terminada*/
vstate = idle;

end
/*perda de cache*/
else begin
/*gera nova tag*/
tag_req.we = 1;
tag_write.valid = 1;
/*nova tag*/
tag_write.tag = cpu_req.addr[TAGMSB:TAGLSB];
/*linha de cache modificada se houver escrita*/
tag_write.dirty = cpu_req.rw;
/*gera requisio de memria na perda de cache*/
v_mem_req.valid = 1;
/*perda compulsria ou perda com bloco limpo*/
if (tag_read.valid == 1b0 || tag_read.dirty == 1b0)
/*espera at novo bloco ser alocado*/
vstate = allocate;
FIGURA 5.9.7 FSM in SystemVerilog, parte III. Estados reais da FSM via instrues case nesta e na figura seguinte.
Esta figura tem o estado Idle e a maior parte do estado Compare Tag.

A Figura 5.9.8 continua o estado Compare Tag. Se o bloco a ser substitudo for modificado, ento o prximo estado Write-Back. A figura mostra o estado Allocate (allocate)
em seguida, que simplesmente l o novo bloco. Ele continua realizando o loop at que a
memria esteja pronta; quando estiver, ela vai para o estado Compare Tag. Isso seguido
na figura pelo estado Write-Back (write_back). Como mostra a figura, o estado Write-Back simplesmente escreve o bloco modificado na memria, mais uma vez realizando
um loop at que a memria esteja pronta. Quando a memria estiver pronta, indicando
que a escrita est concluda, passamos ao estado Allocate.
else begin
/*perda com linha modificada*/
/*endereo de write back*/
v_mem_req.addr = {tag_read.tag, cpu_req.addr[TAGLSB-1:0]};
v_mem_req.rw = 1;
/*espera at escrita terminar*/
vstate = write_back;
end
end
end
/*wait alocao de nova linha de cache*/
allocate: begin
/*controlador de memria respondeu*/
if (mem_data.ready) begin
/*compara tag novamente na perda de escrita (modificar word
correta)*/

Material Complementar

ELSEVIER

vstate = compare_tag;
data_write = mem_data.data;
/*atualiza dados da linha de cache*/
data_req.we = 1;

end
end
/*espera write back da linha de cache modificada*/
write_back : begin
/*write back completado*/
if (mem_data.ready) begin
/*emite nova req. de memria (alocando nova linha)*/
v_mem_req.valid = 1;
v_mem_req.rw = 0;
vstate = allocate;
end
end
endcase
end
always_ff @(posedge(clk)) begin
if (rst)
rstate <= idle; //retorna a estado idle
else
rstate <= vstate;
end
/*conecta memria de tag/dados da cache*/
dm_cache_tag ctag(.*);
dm_cache_data cdata(.*);
endmodule
FIGURA 5.9.8 FSM no SystemVerilog, parte IV. Estados FSM reais via instruo case na figura anterior e nesta. Esta
figura tem a ltima parte do estado Compare Tag, mais os estados Allocate e Write-Back.

O cdigo no final define o estado atual a partir do prximo estado ou reinicia a FSM
para o estado Idle na transio de clock seguinte, dependendo do sinal de reset (rst).
O CD inclui um mdulo de Caso de Teste que ser til para verificar o cdigo nessas
figuras. Este SystemVerilog poderia ser usado para criar uma cache e controlador de cache
em um FPGA.

Tcnicas bsicas de implementao de cache coerente


A chave para implementar um protocolo de invalidao o uso do barramento, ou outro
meio de transmisso, para realizar as invalidaes. Para invalidar, o processador simplesmente adquire o acesso ao barramento e transmite o endereo a ser invalidado por broadcast no barramento. Todos os processadores ficam atentos ao barramento continuamente,
observando os endereos. Os processadores verificam se o endereo no barramento est
em sua cache. Se estiver, os dados correspondentes na cache so invalidados.
Quando h uma escrita em um bloco compartilhado, o processador de escrita precisa
adquirir acesso ao barramento para transmitir sua invalidao por broadcast. Se dois
processadores tentarem escrever blocos compartilhados ao mesmo tempo, suas tentativas
de enviar por broadcast uma operao de invalidao sero serializadas quando competirem pelo barramento. O primeiro processador a obter acesso ao barramento far com
que quaisquer outras cpias do bloco em que est escrevendo sejam invalidadas. Se os
processadores estivessem tentando escrever no mesmo bloco, a serializao imposta pelo
barramento tambm serializa suas escritas. Uma implicao desse esquema que a escrita

5.9 Material avanado: Implementando controladores de cache 9

em um item de dados compartilhado no pode realmente ser completada at que obtenha o


acesso ao barramento. Todos os esquemas de coerncia exigem algum mtodo de serializar
os acessos ao mesmo bloco de cache, seja serializando o acesso ao meio de comunicao
ou outra estrutura compartilhada.
Alm de invalidar cpias pendentes de um bloco de cache que est sendo escrito, tambm precisamos localizar um item de dados quando houver uma falta de cache. Em uma
cache write-through, fcil encontrar o valor recente de um item de dados, pois todos os
dados escritos sempre so enviados memria, da qual o valor mais recente de um item
de dados sempre pode ser apanhado. Em um projeto com largura de banda de memria
adequada para dar suporte ao trfego dos processadores, o uso de write-through simplifica
a implementao da coerncia de cache.
Para uma cache write-back, encontrar o valor de dados mais recente mais difcil, pois
o valor mais recente de um item de dados pode estar em uma cache, em vez da memria.
Felizmente, as caches write-back podem usar o mesmo esquema de verificao para perdas
de cache e para escritas: cada processador verifica todos os endereos colocados no barramento. Se um processador descobrir que tem uma cpia modificada do bloco de cache
solicitado, ele oferece esse bloco de cache em resposta requisio de leitura e faz com que
o acesso memria seja abortado. A complexidade extra vem de ter de recuperar o bloco
de cache da cache de um processador, o que pode levar mais tempo do que recuper-lo
da memria compartilhada se os processadores estiverem em chips separados. Como as
caches write-back geram requisitos inferiores para a largura de banda da memria, elas
podem admitir maiores quantidades de processadores mais rpidos e tm sido a tcnica
escolhida na maioria dos multiprocessadores, apesar da complexidade adicional da coerncia da manuteno. Portanto, examinaremos a implementao da coerncia com as
caches write-back.
As tags de cache normais podem ser usadas para implementar o processo de verificao,
e o bit de validade para cada bloco torna a invalidao fcil de implementar. As faltas de
leitura, sejam elas geradas por uma invalidao ou por algum outro evento, tambm so
fceis, pois simplesmente contam com a capacidade de verificao. Para as escritas, gostaramos de saber se quaisquer outras cpias do bloco so colocadas em cache, pois no
existem outras cpias em cache, e a escrita no precisa ser colocada no barramento em
uma cache write-back. No enviar a escrita reduz o tempo gasto pela escrita e a largura
de banda exigida.
Para descobrir se um bloco de cache compartilhado ou no, podemos acrescentar um
bit de estado extra associado a cada bloco de cache, assim como temos um bit de validade e
um bit de modificao. Ao acrescentar um bit indicando se o bloco compartilhado, podemos decidir se uma escrita dever gerar uma invalidao. Quando ocorrer uma escrita em
um bloco no estado compartilhado, a cache gera uma invalidao no barramento e marca
o bloco como exclusivo. Nenhuma outra invalidao ser enviada por esse processador
para esse bloco. O processador com a nica cpia de um bloco de cache normalmente
chamado de proprietrio do bloco de cache.
Quando uma invalidao enviada, o estado do bloco de cache do proprietrio alterado de compartilhado para no compartilhado (ou exclusivo). Se outro processador
mais tarde solicitar esse bloco de cache, o estado precisa se tornar compartilhado novamente. Como nosso cache de verificao tambm v quaisquer perdas, ele sabe quando
o bloco de cache exclusivo foi solicitado por outro processador e o estado deve se tornar
compartilhado.
Cada transao de barramento precisa verificar as tags de endereo de cache, que potencialmente poderiam interferir com os acessos cache do processador. Um modo de
reduzir essa interferncia duplicar as tags. A interferncia tambm pode ser reduzida
em uma cache multinvel direcionando as solicitaes de verificao para a cache L2, que
o processador usa apenas quando tem uma perda na cache L1. Para que esse esquema
funcione, cada entrada na cache L1 precisa estar presente na cache L2, uma propriedade
chamada propriedade de incluso. Se a verificao receber um acerto na cache L2, ento ela
precisa decidir pela cache L1 para atualizar o estado e possivelmente recuperar os dados,

10

Material Complementar

ELSEVIER

o que normalmente exige um stall do processador. s vezes, ele pode ainda ser til para
duplicar as tags da cache secundria de modo a diminuir a disputa entre o processador e
a atividade de verificao.

Exemplo de um protocolo de coerncia de cache


Um protocolo de coerncia de verificao normalmente implementado incorporando
um controlador de estados finitos em cada n. Esse controlador responde a solicitaes do
processador e do barramento (ou outro meio de broadcast), alterando o estado do bloco
de cache selecionado, alm de usar o barramento para acessar dados ou invalid-los. Logicamente, voc pode pensar em um controlador separado sendo associado a cada bloco;
ou seja, as operaes de verificao ou solicitaes de cache para diferentes blocos podem
prosseguir independentemente. Em implementaes reais, um nico controlador permite
que mltiplas operaes distingam blocos para prosseguir de forma intervalada (ou seja,
uma operao pode ser iniciada antes que outra termine, embora somente um acesso
cache ou um acesso ao barramento seja permitido de cada vez). Alm disso, lembre-se de
que, embora nos refiramos a um barramento na descrio a seguir, qualquer rede de interconexo que aceita um broadcast para todos os controladores de coerncia e suas caches
associadas pode ser usada para implementar a verificao.
O protocolo simples que consideramos tem trs estados: invlido, compartilhado e
modificado. O estado compartilhado indica que o bloco potencialmente compartilhado,
enquanto o estado modificado indica que o bloco foi atualizado na cache; observe que o
estado modificado implica que o bloco exclusivo. A Figura 5.9.9 mostra as solicitaes
geradas pelo mdulo de cache de processador em um n (na metade superior da tabela),
alm daquelas vindo do barramento (na metade inferior da tabela). Esse protocolo para
uma cache write-back, mas pode ser facilmente alterada a fim de trabalhar para uma cache
write-through reinterpretando o estado modificado como um estado exclusivo e atualizando a cache nas escritas pelo modo normal para uma cache write-through. A extenso
mais comum desenvolvedor protocolo bsico o acrscimo de um estado exclusivo, que
descreve um bloco que no modificado, mas mantido em apenas uma cache; a legenda
da Figura 5.9.9 descreve esse estado e seu acrscimo com mais detalhes.
Solicitao

Origem

Estado do bloco de
cache endereado
compartilhado ou
modificado

Tipo de ao da
cache

Acerto de leitura

processador

Perda de leitura

processador

invlido

normal miss

Perda de leitura

processador

compartilhado

substituio

Perda de leitura

processador

modificado

substituio

Acerto de escrita

processador

modificado

acerto normal

Acerto de escrita

processador

compartilhado

coerncia

Perda de escrita

processador

invlido

normal miss

Perda de escrita

processador

compartilhado

substituio

acerto normal

Funo e explicao
L dados na cache.
Coloca perda de leitura no
barramento.
Resolve perda de conflito:
coloca perda de leitura no
barramento.
Resolve perda de conflito:
bloco write-back, depois
coloca perda de leitura no
barramento.
Escreve dados na cache.
Coloca invalidao
no barramento. Essas
operaes normalmente so
chamadas de upgrade ou
perdas de propriedade,
pois s alteram o estado.
Coloca perda de escrita no
barramento.
Resolve perda de conflito:
coloca perda de escrita no
barramento.

5.9 Material avanado: Implementando controladores de cache 11

Perda de escrita

processador

modificado

substituio

Perda de leitura

bus

compartilhado

nenhuma ao

Perda de leitura

bus

modificado

coerncia

Invalidar

bus

compartilhado

coerncia

Perda de escrita

bus

compartilhado

coerncia

Perda de escrita

bus

modificado

coerncia

Resolve perda de conflito:


bloco write-back, depois
coloca perda de escrita no
barramento.
Permite que a memria
atenda perda de leitura.
Tenta compartilhar dados:
coloca bloco de cache no
barramento e muda o estado
para compartilhado.
Tenta escrever bloco
compartilhado; invalida o
bloco.
Tenta escrever bloco que
compartilhado; invalida o
bloco de cache.
Tenta escrever bloco que
exclusivo em outro lugar:
faz o write-back do bloco
de cache e torna seu
estado invlido.

FIGURA 5.9.9 O mecanismo de coerncia de cache recebe solicitaes do processador e do barramento, e responde
a estas com base no tipo de solicitao, sejam acertos ou perdas na cache, e o estado do bloco de cache especificado
na solicitao. A quarta coluna descreve o tipo de ao de cache como acerto ou falta normal (o mesmo que a cache
uniprocessador veria), substituio (uma perda de substituio de cache uniprocessador) ou coerncia (exigida para
manter a coerncia da cache); uma ao normal ou de substituio pode causar uma ao de coerncia, dependendo do
estado do bloco em outras caches. Para perdas de leitura, perdas de escrita ou invalidaes verificadas no barramento,
uma ao exigida apenas se os endereos de leitura ou escrita combinarem com um bloco na cache e o bloco for vlido.
Alguns protocolos tambm introduzem um estado para designar quando um bloco est exclusivamente em uma cache,
mas ainda no foi escrito. Esse estado pode surgir se um acesso de escrita for dividido em duas partes: obtendo o bloco
exclusivamente em uma cache e depois atualizando-o subsequentemente; nesse protocolo, esse estado no modificado exclusivo transiente, terminando assim que a escrita completada. Outros protocolos utilizam e mantm um
estado exclusivo para um bloco no modificado. Em um protocolo de snooping, esse estado pode ser entrado quando
um processador l um bloco que no residente em qualquer outra cache. Como todos os acessos subsequentes so
verificados, possvel manter a preciso desse estado. Em particular, se outro processador emitir uma falta de leitura,
o estado alterado de exclusivo para compartilhado. A vantagem de acrescentar esse estado que uma escrita subsequente em um bloco no estado exclusivo pelo mesmo processador no precisa adquirir acesso ao barramento ou gerar
uma invalidao, pois o bloco conhecido como estando exclusivamente nessa cache; o processador apenas muda o
estado para modificado. Esse estado facilmente acrescentado usando o bit que codifica o estado coerente como um
estado exclusivo e usando um bit de modificao para indicar que um bloco est modificado. O protocolo MESI, que
corresponde aos quatro estados que ele inclui (modificado, exclusivo, compartilhado shared e invlido), usa essa
estrutura. O protocolo MOESI introduz outra extenso: o estado owned (possudo).

Quando uma invalidao ou uma perda de escrita feita no barramento, quaisquer


processadores com cpias do bloco de cache a invalida. Para uma cache write-through, os
dados para uma perda de escrita sempre podem ser recuperados da memria. Para uma
perda de escrita em uma cache write-back, se o bloco for exclusivo em apenas uma cache,
essa cache tambm escreve o bloco de volta; caso contrrio, os dados podem ser lidos da
memria.
A Figura 5.9.10 mostra um diagrama de transio de estados finitos para um nico bloco de cache usando um protocolo de invalidao de escrita e uma cache write-back. Para
simplificar, os trs estados do protocolo so duplicados de modo a representar transies
com base nas solicitaes do processador ( esquerda, que corresponde metade superior
da tabela na Figura 5.9.9), ao contrrio das transies com base nas solicitaes do barramento ( direita, que corresponde metade inferior da tabela na Figura 5.9.9). O texto
em negrito usado para distinguir as aes do barramento, ao contrrio das condies
em que uma transio de estado depende. O estado em cada n representa o estado do
bloco de cache selecionado, especificado pela solicitao do processador ou do barramento.

12

Material Complementar

ELSEVIER

FIGURA 5.9.10 Um protocolo de invalidao de escrita, coerncia de cache, para uma cache write-back, mostrando os estados e transies de estado para
cada bloco na cache. Os estados da cache so mostrados em crculos, com qualquer acesso permitido pelo processador sem uma transio de estado mostrada
entre parnteses sob o nome do estado. O estmulo causando uma mudana de estado aparece nos arcos de transio no tipo regular, e quaisquer aes do barramento geradas como parte da transio de estado aparecem no arco de transio em negrito. As aes de estmulo se aplicam a um bloco na cache, e no a um
endereo especfico na cache. Logo, uma perda de leitura em um bloco no estado compartilhado uma perda para esse bloco de cache, mas para um endereo
diferente. O lado esquerdo do diagrama mostra transies de estado com base em aes do processador associadas a essa cache; o lado direito mostra transies
com base nas operaes sobre o barramento. Uma perda de leitura no estado exclusivo ou compartilhado e uma perda de escrita no estado exclusivo ocorrem
quando o endereo solicitado pelo processador no corresponde ao endereo no bloco da cache. Essa uma perda de substituio de cache padro. Uma tentativa
de escrever um bloco no estado compartilhado gera uma invalidao. Sempre que ocorre uma transao de barramento, todas as caches que contm o bloco de
cache especificado na transao do barramento tomam a ao ditada pela metade direita do diagrama. O protocolo considera que a memria oferece dados em
uma perda de leitura para um bloco que est limpo em todas as caches. Nas implementaes reais, esses dois conjuntos de diagramas de estado so combinados.
Na prtica, existem muitas variaes sutis nos protocolos de invalidao, incluindo a introduo do estado no modificado exclusivo, como se um processador
ou memria oferece dados em uma perda.

Todos os estados nesse protocolo de cache seriam necessrios em uma cache uniprocessador, em que corresponderiam aos estados invlido, vlido (e limpo) e modificado. A
maior parte das mudanas de estado indicadas pelos arcos na metade esquerda da Figura
5.9.10 seria necessria em um cache de uniprocessador write-back, exceto pela invalidao
em um acerto de escrita em um bloco compartilhado. As mudanas de estado representadas
pelos arcos na metade direita da Figura 5.9.10 so necessrias apenas por coerncia, e no
apareceriam de forma alguma no controlador de cache de um uniprocessador.
Para entender por que esse protocolo funciona, observe que qualquer bloco de cache
vlido est no estado compartilhado em uma ou mais caches ou no estado exclusivo em
exatamente uma cache. Qualquer transio para o estado exclusivo (que exigido para
um processador escrever no bloco) requer que uma invalidao ou perda de escrita seja
colocada no barramento, fazendo com que todas as caches tornem o bloco invlido. Alm
disso, se alguma outra cache tivesse o bloco no estado exclusivo, ela geraria um write-back,
que fornece o bloco contendo o endereo desejado. Finalmente, se uma perda de leitura
ocorrer no barramento de um bloco no estado exclusivo, a cache com a cpia exclusiva
muda seu estado para compartilhado.
As aes em cinza na Figura 5.9.11, que tratam de perdas de leitura e escrita no barramento, so basicamente o componente de verificao do protocolo. Uma outra propriedade
que preservada nesse protocolo, e na maioria dos outros protocolos, que qualquer
bloco de memria no estado compartilhado est sempre atualizado na memria, o que
simplifica a implementao.

5.9 Material avanado: Implementando controladores de cache 13

FIGURA 5.9.11 Diagrama de estado de coerncia de cache com as transies de estado induzidas pelo processador
local mostrado em preto e pelas atividades de barramento mostradas em cinza. Assim como na Figura 5.9.10, as
atividades em uma transio aparecem em negrito.

Como j dissemos, h somente uma mquina de estados finitos por cache, com estmulos
vindo do processador conectado ou do barramento. A Figura 5.9.11 mostra como as transies de estado na metade direita da Figura 5.9.10 so combinadas com aquelas na metade
esquerda da figura para formar um nico diagrama de estados para cada bloco de cache.
Embora nosso protocolo de cache simples esteja correto, ele omite uma srie de complicaes que tornam a implementao muito mais intricada. A mais importante delas que
o protocolo assume que as operaes sejam atmicas ou seja, uma operao pode ser
feita de tal maneira que nenhuma operao possa ser intercalada. Por exemplo, o protocolo
descrito considera que as perdas de escrita podem ser detectadas, adquirem o barramento
e recebem a resposta como uma nica ao atmica. Na realidade, isso no verdade. De
modo semelhante, se usssemos um switch, como todos os multiprocessadores recentes
fazem, ento at mesmo as perdas de leitura tambm seriam atmicas.
Aes no atmicas introduzem a possibilidade de que o protocolo possa realizar
deadlock, significando que ele atinge um estado em que no pode continuar. Em breve,
exploraremos como esses protocolos so implementados sem um barramento.
Construir multiprocessadores de pequena escala (dois a quatro processadores) tornou-se
muito fcil. Por exemplo, os processadores Intel Nehalem e o AMD Opteron so projetados
para uso nos multiprocessadores coerentes com cache e possuem uma interface externa
que d suporte verificao e permite que dois a quatro processadores sejam conectados
diretamente. Eles tambm possuem maiores caches no chip, para reduzir a utilizao do
barramento. No caso dos processadores Opteron, o suporte para interconexo de mltiplos
processadores integrado ao chip processador, assim como as interfaces de memria. No
caso do projeto da Intel, um sistema de dois processadores pode ser montado apenas com

14

Material Complementar

ELSEVIER

alguns chips externos adicionais de modo a interferir com o sistema de memria e E/S.
Embora esses projetos no possam ser facilmente escalados para maiores quantidades de
processadores, eles oferecem uma soluo muito econmica para dois a quatro processadores.

Implementando coerncia de cache de verificao


O diabo est nos detalhes.
Provrbio clssico

Como j vimos, a principal complicao na implementao real do protocolo de coerncia


de verificao que descrevemos que as perdas de escrita e upgrade no so atmicas em
qualquer multiprocessador recente. As etapas de detectar uma perda de escrita ou upgrade, comunicar com os outros processadores e a memria, obter o valor mais recente para
uma perda de escrita e garantir que quaisquer invalidaes sejam processadas e atualizar
a cache no podem ser feitas como se usassem um nico ciclo.
Em um sistema de barramento nico, essas etapas podem se tornar efetivamente atmicas arbitrando o barramento primeiro (antes de mudar o estado da cache) e no liberando
o barramento at que todas as aes sejam concludas. Como o processador pode saber
quando todas as invalidaes foram concludas? Na maioria dos multiprocessadores baseados em barramento, uma nica linha usada para sinalizar quando todas as invalidaes
necessrias foram recebidas e esto sendo processadas. Aps esse sinal, o processador que
gerou a perda pode liberar o barramento, sabendo que quaisquer aes exigidas sero
concludas antes de qualquer atividade relacionada prxima perda. Mantendo o barramento exclusivamente durante essas etapas, o processador efetivamente torna as etapas
individuais atmicas.
Em um sistema sem um barramento, temos de encontrar algum outro mtodo de
tornar as etapas em uma perda atmicas. Em particular, preciso garantir que dois processadores que tentam escrever o mesmo bloco ao mesmo tempo, uma situao chamada
de race, sejam estritamente ordenados: uma escrita processada antes que a prxima
seja iniciada. No importa qual das duas escritas em uma race vence a corrida, apenas
que haja um nico vencedor, cujas aes de coerncia so completadas primeiro. Em um
sistema de verificao, garantir que uma race tenha apenas um vencedor realizado por
meio do broadcast para todas as perdas, bem como algumas propriedades bsicas da rede
de interconexo. Essas propriedades, junto com a capacidade de reiniciar o tratamento de
perda do perdedor em uma race, so as chaves para implementar a coerncia de cache de
verificao sem um barramento.

Você também pode gostar