|
@@ -0,0 +1,489 @@
|
|
|
+
|
|
|
+ * To change this license header, choose License Headers in Project Properties.
|
|
|
+ * To change this template file, choose Tools | Templates
|
|
|
+ * and open the template in the editor.
|
|
|
+ */
|
|
|
+package cache;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+
|
|
|
+
|
|
|
+ *
|
|
|
+ * @author Juninho Carlos
|
|
|
+ */
|
|
|
+public class Cache {
|
|
|
+
|
|
|
+ private long escritaCache;
|
|
|
+ private long leituraCache;
|
|
|
+ private long escritaRedundancia;
|
|
|
+ private long leituraRedundancia;
|
|
|
+
|
|
|
+ private long contadorDeCiclos;
|
|
|
+ private long contadorDeWB;
|
|
|
+ private long contadorDeWBForcado;
|
|
|
+
|
|
|
+ private long contadorDeLeituraEspecial;
|
|
|
+
|
|
|
+ private long contadorDeHit;
|
|
|
+ private long contadorDeMiss;
|
|
|
+
|
|
|
+ private long ContadorIncachavel;
|
|
|
+
|
|
|
+ private long escritaSDRAM;
|
|
|
+ private long leituraSDRAM;
|
|
|
+
|
|
|
+ private Redundancia redundancia;
|
|
|
+ private Conjunto[] conjuntos;
|
|
|
+
|
|
|
+ public Cache() {
|
|
|
+ this.redundancia = new Redundancia();
|
|
|
+
|
|
|
+ this.escritaCache = 0;
|
|
|
+ this.escritaRedundancia = 0;
|
|
|
+
|
|
|
+ this.leituraCache = 0;
|
|
|
+ this.leituraRedundancia = 0;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ this.contadorDeCiclos = 0;
|
|
|
+ this.contadorDeWB = 0;
|
|
|
+ this.contadorDeWBForcado = 0;
|
|
|
+ this.contadorDeLeituraEspecial = 0;
|
|
|
+
|
|
|
+ this.contadorDeHit = 0;
|
|
|
+ this.contadorDeMiss = 0;
|
|
|
+
|
|
|
+ this.ContadorIncachavel = 0;
|
|
|
+
|
|
|
+ this.escritaSDRAM = 0;
|
|
|
+ this.leituraSDRAM = 0;
|
|
|
+
|
|
|
+ this.conjuntos = new Conjunto[32];
|
|
|
+ for (int i = 0; i < 32; i++) {
|
|
|
+ this.conjuntos[i] = new Conjunto();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getEscritaSDRAM(){
|
|
|
+ return this.escritaSDRAM;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getLeituraSDRAM(){
|
|
|
+ return this.leituraSDRAM;
|
|
|
+ }
|
|
|
+ public long getContadorIncachavel(){
|
|
|
+ return this.ContadorIncachavel;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getcontadorLeituraEspecial(){
|
|
|
+ return this.contadorDeLeituraEspecial;
|
|
|
+ }
|
|
|
+ public long getWBForcado(){
|
|
|
+ return this.contadorDeWBForcado;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getHit(){
|
|
|
+ return this.contadorDeHit;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getMiss(){
|
|
|
+ return this.contadorDeMiss;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getEscritaCache(){
|
|
|
+ return this.escritaCache;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getEscritaRedundancia(){
|
|
|
+ return this.escritaRedundancia;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getLeituraCache(){
|
|
|
+ return this.leituraCache;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getLeituraRedundancia(){
|
|
|
+ return this.leituraRedundancia;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ *
|
|
|
+ * @param address endereço solicitado à cache
|
|
|
+ * @param read true -> leitura(lw), false -> escrita(sw)
|
|
|
+ */
|
|
|
+ public void requisicaoParaCache(long address, boolean read) {
|
|
|
+ Requisicao end = new Requisicao(address, read);
|
|
|
+
|
|
|
+ if (isHit(end)) {
|
|
|
+
|
|
|
+ this.contadorDeHit++;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (read) {
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.hit_read;
|
|
|
+ } else {
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.hit_write;
|
|
|
+ }
|
|
|
+
|
|
|
+ int bloco = this.conjuntos[end.conjunto].getBlocoFromReq(end);
|
|
|
+
|
|
|
+ boolean erro = this.conjuntos[end.conjunto].getBloco(bloco).getErroFromPalavra(end.palavra);
|
|
|
+ if(!read){
|
|
|
+ if(erro){
|
|
|
+ this.escritaRedundancia++;
|
|
|
+ }else{
|
|
|
+ this.escritaCache++;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(erro){
|
|
|
+ this.leituraRedundancia++;
|
|
|
+ }else{
|
|
|
+ this.leituraCache++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ this.contadorDeMiss++;
|
|
|
+
|
|
|
+ if (read) {
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.leitura_miss;
|
|
|
+ } else {
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.escrita_miss;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.requisicaoDeBlocoNoConjunto(end);
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void inserirErroRedundancia(int conjunto, int bloco, int palavra) {
|
|
|
+ this.redundancia.inserirErro(conjunto, bloco, palavra);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ArrayList<Integer> escreverBlocoNaRed(Requisicao requisicao, int bloco) {
|
|
|
+
|
|
|
+ Requisicao req = new Requisicao(requisicao.endereco, requisicao.read);
|
|
|
+
|
|
|
+ ArrayList<Integer> enderecosToWB = new ArrayList<>();
|
|
|
+ Conjunto c = this.conjuntos[req.conjunto];
|
|
|
+ for (int i = 0; i < 32; i++) {
|
|
|
+ Requisicao aux = req;
|
|
|
+ aux.palavra = i;
|
|
|
+ if (c.getBloco(bloco).getErroDasPalavraDoBloco()[i]) {
|
|
|
+
|
|
|
+ this.contadorDeCiclos += 3;
|
|
|
+ this.leituraRedundancia++;
|
|
|
+ this.escritaRedundancia++;
|
|
|
+
|
|
|
+ Integer numToWB = redundancia.escreverPalavraNaRedMiss(aux, bloco);
|
|
|
+ if (numToWB != null && numToWB == -1) {
|
|
|
+
|
|
|
+ ArrayList<Integer> bosta = new ArrayList<>();
|
|
|
+ bosta.add(-1);
|
|
|
+ return bosta;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (numToWB != null) {
|
|
|
+ if (!c.arrayHasTheValue(enderecosToWB, numToWB)) {
|
|
|
+ enderecosToWB.add(numToWB);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ this.escritaCache++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return enderecosToWB;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void leituraEspecial(int tag, int bloco) {
|
|
|
+ this.leituraRedundancia += 32;
|
|
|
+ this.redundancia.leituraEspecial(tag, tag % 4, bloco);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Escreve palavra com erro na redundancia e faz os wb forçados/LE dos
|
|
|
+ * blocos necessários
|
|
|
+ *
|
|
|
+ * @param req
|
|
|
+ * @param c
|
|
|
+ *
|
|
|
+ * Retorna true quando detecta o erro na redundacia e false quando ñ tem
|
|
|
+ * erro na red
|
|
|
+ */
|
|
|
+ private boolean trataBlocoComErro(Requisicao req, Conjunto c, int bloco) {
|
|
|
+ ArrayList<Integer> enderecosToWB = escreverBlocoNaRed(req, bloco);
|
|
|
+
|
|
|
+ if (enderecosToWB.size() == 1 && enderecosToWB.get(0) == -1) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (enderecosToWB.size() > 0) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ for (Integer integer : enderecosToWB) {
|
|
|
+ this.leituraEspecial(integer, bloco);
|
|
|
+ Conjunto wb = this.conjuntos[integer];
|
|
|
+
|
|
|
+ if (wb.getBlocos()[bloco].isSujo()) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ this.contadorDeWBForcado++;
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.WB;
|
|
|
+ this.leituraRedundancia += 32;
|
|
|
+ this.escritaSDRAM += 32;
|
|
|
+ wb.desalocaBloco(bloco);
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ this.contadorDeLeituraEspecial++;
|
|
|
+ this.leituraRedundancia+=32;
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.leitura_especial;
|
|
|
+ wb.desalocaBloco(bloco);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ public long getWB(){
|
|
|
+ return this.contadorDeWB;
|
|
|
+ }
|
|
|
+ public long getCiclos(){
|
|
|
+ return this.contadorDeCiclos;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void tratarWB(Requisicao req, int numBloco) {
|
|
|
+ Conjunto c = this.conjuntos[req.conjunto];
|
|
|
+
|
|
|
+ if (c.getBloco(numBloco).hasErrorInBloco()) {
|
|
|
+ this.leituraEspecial(req.conjunto, numBloco);
|
|
|
+ if(!c.getBloco(numBloco).isSujo()){
|
|
|
+
|
|
|
+ this.contadorDeLeituraEspecial++;
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.leitura_especial;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (c.getBloco(numBloco).isSujo()) {
|
|
|
+
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.WB;
|
|
|
+ this.contadorDeWB++;
|
|
|
+ this.escritaSDRAM += 32;
|
|
|
+
|
|
|
+ }
|
|
|
+ c.desalocaBloco(numBloco);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void tratarErroNaRed(Requisicao req, int numBloco) {
|
|
|
+ Conjunto c = this.conjuntos[req.conjunto];
|
|
|
+ this.leituraEspecial(req.conjunto, c.getRR());
|
|
|
+ c.getBloco(numBloco).setarComoInvalido();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void contabilizaEscrita(Conjunto c, Requisicao req, int bloco){
|
|
|
+ if(!req.read){
|
|
|
+ if(c.getBloco(bloco).getErroDasPalavraDoBloco()[req.palavra]){
|
|
|
+ this.escritaRedundancia++;
|
|
|
+ }else{
|
|
|
+ this.escritaCache++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void contabilizaLeitura(int conjunto,int numBloco, int palavra){
|
|
|
+ boolean erro = this.conjuntos[conjunto].getBloco(numBloco).getErroFromPalavra(palavra);
|
|
|
+ if(erro){
|
|
|
+ this.leituraRedundancia++;
|
|
|
+ }else{
|
|
|
+ this.leituraCache++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void requisicaoDeBlocoNoConjunto(Requisicao req) {
|
|
|
+
|
|
|
+ Conjunto c = this.conjuntos[req.conjunto];
|
|
|
+ boolean flagAlocaBloco = true;
|
|
|
+
|
|
|
+ if (c.hasBlocoLivre()) {
|
|
|
+
|
|
|
+ if (c.getBloco(c.getRR()).isCachavel()) {
|
|
|
+
|
|
|
+ this.leituraSDRAM +=32;
|
|
|
+
|
|
|
+ if(req.read){
|
|
|
+ this.contabilizaLeitura(req.conjunto, c.getRR(), req.palavra);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (c.isBlocoOcupado(c.getRR())) {
|
|
|
+
|
|
|
+ this.tratarWB(req, c.getRR());
|
|
|
+ }
|
|
|
+ if (c.getBloco(c.getRR()).hasErrorInBloco()) {
|
|
|
+
|
|
|
+ flagAlocaBloco = !this.trataBlocoComErro(req, c, c.getRR());
|
|
|
+ }else{
|
|
|
+ this.escritaCache += 32;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flagAlocaBloco) {
|
|
|
+
|
|
|
+
|
|
|
+ this.contabilizaEscrita(c,req,c.getRR());
|
|
|
+
|
|
|
+ c.alocarBloco(req, c.getRR());
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ this.contadorDeWBForcado++;
|
|
|
+ this.escritaSDRAM += 32;
|
|
|
+
|
|
|
+ if (req.read) {
|
|
|
+ this.contadorDeCiclos += 1 + 1;
|
|
|
+ } else {
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.tratarErroNaRed(req,c.getRR());
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ c.lru.atualizaLRU(c.getRR());
|
|
|
+ c.atualizaRR();
|
|
|
+ } else {
|
|
|
+ this.ContadorIncachavel++;
|
|
|
+
|
|
|
+
|
|
|
+ c.atualizaRR();
|
|
|
+
|
|
|
+
|
|
|
+ if (req.read) {
|
|
|
+ this.contadorDeCiclos += 1;
|
|
|
+ this.leituraSDRAM += 1;
|
|
|
+ } else {
|
|
|
+ this.escritaSDRAM += 1;
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ int blocoSelecionado = c.lru.getBlocoFromLru();
|
|
|
+ if (c.getBloco(blocoSelecionado).isCachavel()) {
|
|
|
+
|
|
|
+ this.leituraSDRAM +=32;
|
|
|
+ if(req.read){
|
|
|
+ this.contabilizaLeitura(req.conjunto, blocoSelecionado, req.palavra);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (c.getBloco(blocoSelecionado).hasErrorInBloco()) {
|
|
|
+
|
|
|
+
|
|
|
+ this.tratarWB(req, blocoSelecionado);
|
|
|
+
|
|
|
+
|
|
|
+ flagAlocaBloco = !this.trataBlocoComErro(req, c, blocoSelecionado);
|
|
|
+
|
|
|
+ if (flagAlocaBloco) {
|
|
|
+
|
|
|
+
|
|
|
+ this.contabilizaEscrita(c, req,blocoSelecionado);
|
|
|
+ c.alocarBloco(req, c.getRR());
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ this.contadorDeWBForcado++;
|
|
|
+ this.tratarErroNaRed(req,blocoSelecionado);
|
|
|
+
|
|
|
+ if (req.read) {
|
|
|
+ this.contadorDeCiclos += 1;
|
|
|
+ } else {
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else{
|
|
|
+ this.escritaCache += 32;
|
|
|
+
|
|
|
+ if (c.getBlocos()[blocoSelecionado].isSujo()) {
|
|
|
+
|
|
|
+ this.tratarWB(req, blocoSelecionado);
|
|
|
+ c.alocarBloco(req, blocoSelecionado);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ c.alocarBloco(req, blocoSelecionado);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ this.ContadorIncachavel++;
|
|
|
+ if(req.read){
|
|
|
+ this.leituraSDRAM+=1;
|
|
|
+ this.contadorDeCiclos += 1;
|
|
|
+ }else{
|
|
|
+ this.escritaSDRAM+=1;
|
|
|
+ this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ c.lru.atualizaLRU(blocoSelecionado);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ * Insere erro na memória cache
|
|
|
+ * @param conjunto - Número do conjunto
|
|
|
+ * @param bloco - Número do bloco
|
|
|
+ * @param palavra - Número da palavra
|
|
|
+ */
|
|
|
+ public void inserirErro(int conjunto, int bloco, int palavra) {
|
|
|
+ this.conjuntos[conjunto].getBlocos()[bloco].inserirErro(palavra);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Conjunto[] getConjuntos() {
|
|
|
+ return this.conjuntos;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isHit(Requisicao address) {
|
|
|
+ return conjuntos[address.conjunto].verificaHit(address);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Redundancia getRedundancia() {
|
|
|
+ return this.redundancia;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ String s = "";
|
|
|
+ Bloco[] b;
|
|
|
+ int i = 0;
|
|
|
+ for (Conjunto conjunto : conjuntos) {
|
|
|
+ s += "Conjunto " + i + "\n";
|
|
|
+
|
|
|
+ b = conjunto.getBlocos();
|
|
|
+ int j = 0;
|
|
|
+ for (Bloco bloco : b) {
|
|
|
+ s += "Bloco " + j + "\n";
|
|
|
+ s += bloco + "\n";
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+ s += "\n\n\n";
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|