Cache.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package cache;
  7. import java.util.ArrayList;
  8. /**
  9. *
  10. * @author Juninho Carlos
  11. */
  12. public class Cache {
  13. private long escritaCache; //Ultimo contador que fiz
  14. private long leituraCache; //done
  15. private long escritaRedundancia; //done
  16. private long leituraRedundancia;
  17. private long contadorDeCiclos; //feito
  18. private long contadorDeWB; //feito
  19. private long contadorDeWBForcado; //feito
  20. private long contadorDeLeituraEspecial; //feito
  21. private long contadorDeHit; //feito
  22. private long contadorDeMiss; //feito
  23. private long ContadorIncachavel;
  24. private long escritaSDRAM;
  25. private long leituraSDRAM;
  26. private Redundancia redundancia;
  27. private Conjunto[] conjuntos;
  28. public Cache() {
  29. this.redundancia = new Redundancia();
  30. this.escritaCache = 0;
  31. this.escritaRedundancia = 0;
  32. this.leituraCache = 0;
  33. this.leituraRedundancia = 0;
  34. this.contadorDeCiclos = 0;
  35. this.contadorDeWB = 0;
  36. this.contadorDeWBForcado = 0;
  37. this.contadorDeLeituraEspecial = 0;
  38. this.contadorDeHit = 0;
  39. this.contadorDeMiss = 0;
  40. this.ContadorIncachavel = 0;
  41. this.escritaSDRAM = 0;
  42. this.leituraSDRAM = 0;
  43. this.conjuntos = new Conjunto[32];
  44. for (int i = 0; i < 32; i++) {
  45. this.conjuntos[i] = new Conjunto();
  46. }
  47. }
  48. public long getEscritaSDRAM(){
  49. return this.escritaSDRAM;
  50. }
  51. public long getLeituraSDRAM(){
  52. return this.leituraSDRAM;
  53. }
  54. public long getContadorIncachavel(){
  55. return this.ContadorIncachavel;
  56. }
  57. public long getcontadorLeituraEspecial(){
  58. return this.contadorDeLeituraEspecial;
  59. }
  60. public long getWBForcado(){
  61. return this.contadorDeWBForcado;
  62. }
  63. public long getHit(){
  64. return this.contadorDeHit;
  65. }
  66. public long getMiss(){
  67. return this.contadorDeMiss;
  68. }
  69. public long getEscritaCache(){
  70. return this.escritaCache;
  71. }
  72. public long getEscritaRedundancia(){
  73. return this.escritaRedundancia;
  74. }
  75. public long getLeituraCache(){
  76. return this.leituraCache;
  77. }
  78. public long getLeituraRedundancia(){
  79. return this.leituraRedundancia;
  80. }
  81. /**
  82. *
  83. * @param address endereço solicitado à cache
  84. * @param read true -> leitura(lw), false -> escrita(sw)
  85. */
  86. public void requisicaoParaCache(long address, boolean read) {
  87. Requisicao end = new Requisicao(address, read);
  88. // System.out.println("pal = "+end.palavra);
  89. if (isHit(end)) { //Verifica se é hit, e, se for, atualiza o bit de sujeira, caso necessário.
  90. this.contadorDeHit++;
  91. // System.err.println("HIT: endereco: " + end.endereco);
  92. // System.err.println("");
  93. if (read) {
  94. this.contadorDeCiclos += ConstanteDeTempo.hit_read;
  95. } else {
  96. this.contadorDeCiclos += ConstanteDeTempo.hit_write; //contabiliza ciclos, inclusive os da comparação
  97. }
  98. int bloco = this.conjuntos[end.conjunto].getBlocoFromReq(end);
  99. boolean erro = this.conjuntos[end.conjunto].getBloco(bloco).getErroFromPalavra(end.palavra);
  100. if(!read){
  101. if(erro){
  102. this.escritaRedundancia++;
  103. }else{
  104. this.escritaCache++;
  105. }
  106. }else{
  107. if(erro){
  108. this.leituraRedundancia++;
  109. }else{
  110. this.leituraCache++;
  111. }
  112. }
  113. //Tem que atualizar bit de sujeira caso seja escrita
  114. //Deu hit e tem que verificar se tá na cache ou na redundancia
  115. //contadorDeHit++;
  116. } else {
  117. //Deu miss
  118. //System.err.println("MISS " + address);
  119. this.contadorDeMiss++;
  120. if (read) {
  121. this.contadorDeCiclos += ConstanteDeTempo.leitura_miss;
  122. } else {
  123. this.contadorDeCiclos += ConstanteDeTempo.escrita_miss;
  124. }
  125. this.requisicaoDeBlocoNoConjunto(end);
  126. //conjuntos[end.conjunto].requisicaoDeBlocoNoConjunto(end,this.redundancia);
  127. }
  128. }
  129. public void inserirErroRedundancia(int conjunto, int bloco, int palavra) {
  130. this.redundancia.inserirErro(conjunto, bloco, palavra);
  131. }
  132. private ArrayList<Integer> escreverBlocoNaRed(Requisicao requisicao, int bloco) {
  133. Requisicao req = new Requisicao(requisicao.endereco, requisicao.read);
  134. ArrayList<Integer> enderecosToWB = new ArrayList<>();
  135. Conjunto c = this.conjuntos[req.conjunto];
  136. for (int i = 0; i < 32; i++) {
  137. Requisicao aux = req;
  138. aux.palavra = i;
  139. if (c.getBloco(bloco).getErroDasPalavraDoBloco()[i]) {
  140. this.contadorDeCiclos += 3; //1 ciclo para escreve, um para ler, outro para comparar
  141. this.leituraRedundancia++;
  142. this.escritaRedundancia++;
  143. Integer numToWB = redundancia.escreverPalavraNaRedMiss(aux, bloco);
  144. if (numToWB != null && numToWB == -1) {
  145. //Deu bosta
  146. ArrayList<Integer> bosta = new ArrayList<>();
  147. bosta.add(-1);
  148. return bosta;
  149. }
  150. if (numToWB != null) {
  151. if (!c.arrayHasTheValue(enderecosToWB, numToWB)) {
  152. enderecosToWB.add(numToWB);
  153. }
  154. }
  155. }else{
  156. this.escritaCache++;
  157. }
  158. }
  159. return enderecosToWB;
  160. }
  161. private void leituraEspecial(int tag, int bloco) {
  162. this.leituraRedundancia += 32;
  163. this.redundancia.leituraEspecial(tag, tag % 4, bloco);
  164. }
  165. /**
  166. * Escreve palavra com erro na redundancia e faz os wb forçados/LE dos
  167. * blocos necessários
  168. *
  169. * @param req
  170. * @param c
  171. *
  172. * Retorna true quando detecta o erro na redundacia e false quando ñ tem
  173. * erro na red
  174. */
  175. private boolean trataBlocoComErro(Requisicao req, Conjunto c, int bloco) {
  176. ArrayList<Integer> enderecosToWB = escreverBlocoNaRed(req, bloco);
  177. if (enderecosToWB.size() == 1 && enderecosToWB.get(0) == -1) { //Tentou escrever na Red e deu erro
  178. return true;
  179. }
  180. if (enderecosToWB.size() > 0) { //Tratar WBs ou LE
  181. //Requisicao r = new Requisicao(RR, true)
  182. // System.err.println("Fazendo WB forçado");
  183. // System.err.println("conjuntos wbackado/LE: " + enderecosToWB.toString());
  184. // System.err.println("bloco: " + bloco);
  185. for (Integer integer : enderecosToWB) {
  186. this.leituraEspecial(integer, bloco);
  187. Conjunto wb = this.conjuntos[integer];
  188. if (wb.getBlocos()[bloco].isSujo()) {
  189. //Faz WB-FORCADO
  190. // System.err.println("Fazendo WB-forcado do conjunto " + integer);
  191. this.contadorDeWBForcado++;
  192. this.contadorDeCiclos += ConstanteDeTempo.WB;
  193. this.leituraRedundancia += 32;
  194. this.escritaSDRAM += 32;
  195. wb.desalocaBloco(bloco);
  196. } else {
  197. // System.err.println("Fazendo LE do conjunto " + integer);
  198. //Contabilizar leitura especial
  199. this.contadorDeLeituraEspecial++;
  200. this.leituraRedundancia+=32;
  201. this.contadorDeCiclos += ConstanteDeTempo.leitura_especial;
  202. wb.desalocaBloco(bloco);
  203. }
  204. }
  205. }
  206. return false;
  207. }
  208. public long getWB(){
  209. return this.contadorDeWB;
  210. }
  211. public long getCiclos(){
  212. return this.contadorDeCiclos;
  213. }
  214. private void tratarWB(Requisicao req, int numBloco) {
  215. Conjunto c = this.conjuntos[req.conjunto];
  216. if (c.getBloco(numBloco).hasErrorInBloco()) {
  217. this.leituraEspecial(req.conjunto, numBloco);
  218. if(!c.getBloco(numBloco).isSujo()){
  219. //Só contabiliza leitura especial se o bloco tiver erro
  220. this.contadorDeLeituraEspecial++;
  221. this.contadorDeCiclos += ConstanteDeTempo.leitura_especial;
  222. }
  223. }
  224. if (c.getBloco(numBloco).isSujo()) {
  225. //Contabilizar um WB
  226. this.contadorDeCiclos += ConstanteDeTempo.WB;
  227. this.contadorDeWB++;
  228. this.escritaSDRAM += 32;
  229. // System.err.println("fazer WB");
  230. }
  231. c.desalocaBloco(numBloco);
  232. }
  233. private void tratarErroNaRed(Requisicao req, int numBloco) {
  234. Conjunto c = this.conjuntos[req.conjunto];
  235. this.leituraEspecial(req.conjunto, c.getRR());
  236. c.getBloco(numBloco).setarComoInvalido();
  237. }
  238. private void contabilizaEscrita(Conjunto c, Requisicao req, int bloco){
  239. if(!req.read){
  240. if(c.getBloco(bloco).getErroDasPalavraDoBloco()[req.palavra]){
  241. this.escritaRedundancia++;
  242. }else{
  243. this.escritaCache++;
  244. }
  245. }
  246. }
  247. private void contabilizaLeitura(int conjunto,int numBloco, int palavra){
  248. boolean erro = this.conjuntos[conjunto].getBloco(numBloco).getErroFromPalavra(palavra);
  249. if(erro){
  250. this.leituraRedundancia++;
  251. }else{
  252. this.leituraCache++;
  253. }
  254. }
  255. private void requisicaoDeBlocoNoConjunto(Requisicao req) {
  256. //Se está nesse método,é porque deu miss
  257. Conjunto c = this.conjuntos[req.conjunto];
  258. boolean flagAlocaBloco = true;
  259. if (c.hasBlocoLivre()) { //USA RR
  260. // System.err.println("Vai usar RR. Vai para o bloco: "+c.getRR());
  261. if (c.getBloco(c.getRR()).isCachavel()) {
  262. this.leituraSDRAM +=32;
  263. if(req.read){
  264. this.contabilizaLeitura(req.conjunto, c.getRR(), req.palavra);
  265. }
  266. //Caso seja um bloco ocupado, precisa fazer verificar a necessidade de WB
  267. if (c.isBlocoOcupado(c.getRR())) {
  268. // System.err.println("O bloco já estava ocupado. Vai fazer WB");
  269. this.tratarWB(req, c.getRR()); //Aqui já contabiliza ciclos e WB
  270. }
  271. if (c.getBloco(c.getRR()).hasErrorInBloco()) { //Verifica se tem erro nas palavras do bloco
  272. // System.err.println("Tem erro no bloco");
  273. flagAlocaBloco = !this.trataBlocoComErro(req, c, c.getRR());//Contabiliza escrita na cache
  274. }else{
  275. this.escritaCache += 32;
  276. }
  277. if (flagAlocaBloco) {
  278. // System.err.println("Vai alocar o bloco");
  279. // System.err.println("");
  280. this.contabilizaEscrita(c,req,c.getRR());
  281. c.alocarBloco(req, c.getRR());
  282. } else {
  283. // System.err.println("ñ Vai alocar o bloco");
  284. // System.err.println("");
  285. this.contadorDeWBForcado++;
  286. this.escritaSDRAM += 32;
  287. //Não foi colocado em Cache pois tem erro na red
  288. if (req.read) {
  289. this.contadorDeCiclos += 1 + 1; //1 ciclo para devolver + 1 para acessar vetor de erros
  290. } else {
  291. this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
  292. }
  293. this.tratarErroNaRed(req,c.getRR());
  294. //Aqui falta contabilizar algumas coisas (tempo se for write)
  295. }
  296. //Atualiza as variáves da política de substituição de bloco
  297. c.lru.atualizaLRU(c.getRR());
  298. c.atualizaRR();
  299. } else {
  300. this.ContadorIncachavel++;
  301. c.atualizaRR();
  302. // System.err.println("Incachavel");
  303. //Só contabiliza o custo da operação na memória principal
  304. if (req.read) {
  305. this.contadorDeCiclos += 1;
  306. this.leituraSDRAM += 1;
  307. } else {
  308. this.escritaSDRAM += 1;
  309. this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
  310. }
  311. }
  312. } else {
  313. //Usa LRU
  314. // System.err.println("Vai usar LRU. Vai para o bloco: "+c.lru.getBlocoFromLru());
  315. int blocoSelecionado = c.lru.getBlocoFromLru();
  316. if (c.getBloco(blocoSelecionado).isCachavel()) {
  317. this.leituraSDRAM +=32;
  318. if(req.read){
  319. this.contabilizaLeitura(req.conjunto, blocoSelecionado, req.palavra);
  320. }
  321. if (c.getBloco(blocoSelecionado).hasErrorInBloco()) {
  322. // System.err.println("Tem erro no bloco");
  323. //Faz WB do bloco que foi selecionado para ser retirado da Cache
  324. this.tratarWB(req, blocoSelecionado); //Já contabiliza ciclos e WB
  325. //Escreve novo bloco na cache e os endereços com erro na red. Além disso, faz WBF e LE
  326. flagAlocaBloco = !this.trataBlocoComErro(req, c, blocoSelecionado); //Contabiliza escrita
  327. if (flagAlocaBloco) {
  328. // System.err.println("Vai alocar o bloco\n");
  329. // System.err.println("");
  330. this.contabilizaEscrita(c, req,blocoSelecionado);
  331. c.alocarBloco(req, c.getRR());
  332. } else {
  333. // System.err.println("ñ Vai alocar o bloco\n");
  334. // System.err.println("");
  335. //Não foi colocado em Cache pois tem erro na red
  336. this.contadorDeWBForcado++;
  337. this.tratarErroNaRed(req,blocoSelecionado);
  338. if (req.read) {
  339. this.contadorDeCiclos += 1;
  340. } else {
  341. this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
  342. }
  343. }
  344. } else{ //Caso o bloco não tenha erro, tratar as usual
  345. this.escritaCache += 32;
  346. //Caso o Bloco esteja Sujo, precisa fazer WB
  347. if (c.getBlocos()[blocoSelecionado].isSujo()) {
  348. //Contabilizar WB
  349. this.tratarWB(req, blocoSelecionado); //Já contabiliza WB
  350. c.alocarBloco(req, blocoSelecionado);
  351. } else {//Caso precise só trocar o bloco, pois está limpo
  352. // Contabiliza nada aqui, pois o bloco tá limpo
  353. c.alocarBloco(req, blocoSelecionado);
  354. }
  355. }
  356. } else {
  357. //System.err.println("Incachavel");
  358. //Só contabiliza o custo da operação na memória principal
  359. this.ContadorIncachavel++;
  360. if(req.read){
  361. this.leituraSDRAM+=1;
  362. this.contadorDeCiclos += 1;
  363. }else{
  364. this.escritaSDRAM+=1;
  365. this.contadorDeCiclos += ConstanteDeTempo.escrita_1_palavra_na_SDRAM;
  366. }
  367. }
  368. //Atualiza politica de substituição LRU
  369. c.lru.atualizaLRU(blocoSelecionado);
  370. }
  371. }
  372. /**
  373. * Insere erro na memória cache
  374. * @param conjunto - Número do conjunto
  375. * @param bloco - Número do bloco
  376. * @param palavra - Número da palavra
  377. */
  378. public void inserirErro(int conjunto, int bloco, int palavra) {
  379. this.conjuntos[conjunto].getBlocos()[bloco].inserirErro(palavra);
  380. }
  381. private Conjunto[] getConjuntos() {
  382. return this.conjuntos;
  383. }
  384. private boolean isHit(Requisicao address) {
  385. return conjuntos[address.conjunto].verificaHit(address);
  386. }
  387. public Redundancia getRedundancia() {
  388. return this.redundancia;
  389. }
  390. @Override
  391. public String toString() {
  392. String s = "";
  393. Bloco[] b;
  394. int i = 0;
  395. for (Conjunto conjunto : conjuntos) {
  396. s += "Conjunto " + i + "\n";
  397. //s += conjunto;
  398. b = conjunto.getBlocos();
  399. int j = 0;
  400. for (Bloco bloco : b) {
  401. s += "Bloco " + j + "\n";
  402. s += bloco + "\n";
  403. j++;
  404. }
  405. s += "\n\n\n";
  406. i++;
  407. }
  408. return s; //To change body of generated methods, choose Tools | Templates.
  409. }
  410. }