From 8c5a91578ca929f3a94b54628f6431c136dc417d Mon Sep 17 00:00:00 2001 From: JulianCamacho Date: Tue, 3 Oct 2023 01:39:00 -0600 Subject: comentarios --- rtl/cache/cache_control.sv | 1 + rtl/cache/offsets.sv | 2 +- rtl/cache/routing.sv | 2 ++ rtl/cache/sram.sv | 5 +++++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/rtl/cache/cache_control.sv b/rtl/cache/cache_control.sv index 7186e95..85378d5 100644 --- a/rtl/cache/cache_control.sv +++ b/rtl/cache/cache_control.sv @@ -29,6 +29,7 @@ module cache_control output ring_token out_token, output logic out_token_valid, + // Señales para la SRAM input addr_tag tag_rd, input line data_rd, input line_state state_rd, diff --git a/rtl/cache/offsets.sv b/rtl/cache/offsets.sv index a933d1c..f9ad2ff 100644 --- a/rtl/cache/offsets.sv +++ b/rtl/cache/offsets.sv @@ -13,7 +13,7 @@ module cache_offsets output word core_readdata, output line_be core_byteenable_line ); - + //Simplificar offsets line line_mask; word be_extend, mask3, mask2, mask1, mask0; word_be be3, be2, be1, be0; diff --git a/rtl/cache/routing.sv b/rtl/cache/routing.sv index c72d9b5..8f744dd 100644 --- a/rtl/cache/routing.sv +++ b/rtl/cache/routing.sv @@ -48,6 +48,7 @@ module cache_routing BYPASS } state; + //Arbitrar el bus del lado de la cache assign cached = io == 3'b000; assign cache_mem = cache_mem_read || cache_mem_write; @@ -61,6 +62,7 @@ module cache_routing always_comb begin transition = 0; core_waitrequest = cache_core_waitrequest; + // Desde el punto de vista de cache, mem le hace waitreq a cache cache_mem_waitrequest = 1; unique case (state) diff --git a/rtl/cache/sram.sv b/rtl/cache/sram.sv index 986c09b..8d68b7e 100644 --- a/rtl/cache/sram.sv +++ b/rtl/cache/sram.sv @@ -27,6 +27,10 @@ module cache_sram addr_tag tag_file[DEPTH] /*verilator public*/; line_state state_file[DEPTH] /*verilator public*/; + // Hace 3 cosas: + // 1. Si se necesita escribir un dato: escribe en los tag y data files en la posición del index de escritura + // 2. Si se necesita escribir un estado: escribe en el state file en la posición del index de escritura + // 3. Cada ciclo retorna siempre lo que esté en todos los files en la posición de index de lectura always_ff @(posedge clk) begin if (write_data) begin tag_file[index_wr] <= tag_wr; @@ -41,6 +45,7 @@ module cache_sram state_rd <= state_file[index_rd]; end + // Se inicializan todas las líneas del state file como INVALID //FIXME: rst_n para state_file? initial for (int i = 0; i < DEPTH; ++i) -- cgit v1.2.3 From bc466f0511d8b3029c0822f415ebc9ae152b9d09 Mon Sep 17 00:00:00 2001 From: JulianCamacho Date: Tue, 3 Oct 2023 16:55:27 -0600 Subject: sram, offset and routing comments --- rtl/cache/offsets.sv | 12 ++++++++---- rtl/cache/routing.sv | 9 +++++++++ rtl/cache/sram.sv | 11 ++++++----- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/rtl/cache/offsets.sv b/rtl/cache/offsets.sv index f9ad2ff..205d847 100644 --- a/rtl/cache/offsets.sv +++ b/rtl/cache/offsets.sv @@ -2,7 +2,7 @@ module cache_offsets ( - input addr_offset core_offset, + input addr_offset core_offset, // El offset es un input pero no un output porque se mapea input word_be core_byteenable, input word core_writedata, input line core_readdata_line, @@ -10,21 +10,24 @@ module cache_offsets output line core_data_wr, core_writedata_line, - output word core_readdata, + output word core_readdata, // Readdata pasa de ser una line en el input a una word por el offset output line_be core_byteenable_line ); - //Simplificar offsets + // Simplificar offset, para que sea transparente para la cache line line_mask; + + // El byteenable se utiliza para leer o escribir en cache algo diferente a una word word be_extend, mask3, mask2, mask1, mask0; word_be be3, be2, be1, be0; assign core_writedata_line = {4{core_writedata}}; assign core_byteenable_line = {be3, be2, be1, be0}; + // Concatenar para extender a una word ([31:0]) según el valor de byteenable que es [3:0] assign be_extend = {{8{core_byteenable[3]}}, {8{core_byteenable[2]}}, {8{core_byteenable[1]}}, {8{core_byteenable[0]}}}; - assign line_mask = {mask3, mask2, mask1, mask0}; + assign line_mask = {mask3, mask2, mask1, mask0}; // Máscara para toda la línea assign core_data_wr = (core_writedata_line & line_mask) | (data_rd & ~line_mask); always_comb begin @@ -38,6 +41,7 @@ module cache_offsets be1 = 0; be0 = 0; + // Elegir la word que se va a retornar según el valor de offset unique case (core_offset) 2'b00: begin be0 = core_byteenable; diff --git a/rtl/cache/routing.sv b/rtl/cache/routing.sv index 8f744dd..aae6f51 100644 --- a/rtl/cache/routing.sv +++ b/rtl/cache/routing.sv @@ -49,9 +49,18 @@ module cache_routing } state; //Arbitrar el bus del lado de la cache + + /* Se sabe si el address es cache o no evaluando los bits de IO. + * Esto es posible porque se cumple lo siguiente: + * - La memoria tiene un tamaño que es una potencia de 2 + * - Sus direcciones inician en 0 + * Entonces si los bits de IO son distintos de 0, se sabe que no es + * una dirección cached + */ assign cached = io == 3'b000; assign cache_mem = cache_mem_read || cache_mem_write; + // Acá se divide el core_address para analizarse por separado assign {io, core_tag, core_index, core_offset} = core_address; assign core_address_line = {io, core_tag, core_index, 4'b0000}; assign core_readdata_line = cached ? data_rd : mem_readdata; diff --git a/rtl/cache/sram.sv b/rtl/cache/sram.sv index 8d68b7e..74f9e65 100644 --- a/rtl/cache/sram.sv +++ b/rtl/cache/sram.sv @@ -26,11 +26,12 @@ module cache_sram line data_file[DEPTH] /*verilator public*/; addr_tag tag_file[DEPTH] /*verilator public*/; line_state state_file[DEPTH] /*verilator public*/; - - // Hace 3 cosas: - // 1. Si se necesita escribir un dato: escribe en los tag y data files en la posición del index de escritura - // 2. Si se necesita escribir un estado: escribe en el state file en la posición del index de escritura - // 3. Cada ciclo retorna siempre lo que esté en todos los files en la posición de index de lectura + + /* 3 funciones principales: + * 1. Si se necesita escribir un dato: escribe en los tag y data files en la posición del index de escritura + * 2. Si se necesita escribir un estado: escribe en el state file en la posición del index de escritura + * 3. Cada ciclo retorna siempre lo que esté en todos los files en la posición de index de lectura + */ always_ff @(posedge clk) begin if (write_data) begin tag_file[index_wr] <= tag_wr; -- cgit v1.2.3 From dbe88c450b72913efc7831131cd92d27c9cc0b92 Mon Sep 17 00:00:00 2001 From: JulianCamacho Date: Wed, 4 Oct 2023 01:13:12 -0600 Subject: routing and beginning cache control comments --- rtl/cache/cache_control.sv | 13 ++++++++----- rtl/cache/routing.sv | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/rtl/cache/cache_control.sv b/rtl/cache/cache_control.sv index 85378d5..fb7896a 100644 --- a/rtl/cache/cache_control.sv +++ b/rtl/cache/cache_control.sv @@ -89,9 +89,11 @@ module cache_control */ assign unlock_line = !core_waitrequest; + // Replace si no coinciden las tags y el estado no es INVALID assign replace = tag_rd != core_tag && state_rd != INVALID; - assign last_hop = in_hold.ttl == `TTL_END; - assign snoop_hit = tag_rd == in_hold.tag; + assign last_hop = in_hold.ttl == `TTL_END; //Indica si es el último salto + assign snoop_hit = tag_rd == in_hold.tag; //Snoop hit si coinciden las tags + // Aceptar snoop si no es el último nodo y se tiene un mensaje válido assign accept_snoop = in_hold_valid && !last_hop && (in_hold.inval || !in_hold.reply); assign may_send = may_send_if_token_held && in_token_valid; @@ -105,7 +107,7 @@ module cache_control assign out_data_valid = out_stall || send || (in_hold_valid && !last_hop && in_data_ready); assign send_data.tag = core_tag; - assign send_data.ttl = `TTL_MAX; + assign send_data.ttl = `TTL_MAX; // Acá se inicializa el valor máximo de TTL assign send_data.data = fwd_data.data; // Esto evita muchos muxes assign send_data.read = send_read; assign send_data.index = core_index; @@ -139,11 +141,12 @@ module cache_control unique case (state) ACCEPT: begin + // Si es el último nodo en recibir el mensaje y la request no es de lectura if (last_hop && !in_hold.read) begin - end_reply = in_hold_valid; + end_reply = in_hold_valid; // Se termina el paso de ese mensaje in_data_ready = 1; end - + // Si no es el último salto y hay reply if (!last_hop && in_hold.reply) in_data_ready = 1; diff --git a/rtl/cache/routing.sv b/rtl/cache/routing.sv index aae6f51..c745cfc 100644 --- a/rtl/cache/routing.sv +++ b/rtl/cache/routing.sv @@ -37,6 +37,12 @@ module cache_routing output line_be mem_byteenable ); + /* Módulo para enrutar las operaciones a cache o memoria + * Esto porque hay escrituras que definitivamente no pueden quedar en cache + * como el caso de periféricos, para los cuales si se guarda "su valor" en + * cache y no en memoria se harían lecturas incorrectas + */ + word core_address_line; logic cached, cache_mem, transition; addr_io_region io; @@ -58,13 +64,17 @@ module cache_routing * una dirección cached */ assign cached = io == 3'b000; + // Se afirma si cache quiere hacer un read o write de memoria assign cache_mem = cache_mem_read || cache_mem_write; // Acá se divide el core_address para analizarse por separado assign {io, core_tag, core_index, core_offset} = core_address; assign core_address_line = {io, core_tag, core_index, 4'b0000}; + // Si está cached se asigna a lectura de cache, sino a lectura de memoria assign core_readdata_line = cached ? data_rd : mem_readdata; + // Se afirma si el core quiere leer/escribir a cache y efectivamente es una + // dirección de cache assign cache_core_read = core_read && cached; assign cache_core_write = core_write && cached; @@ -76,12 +86,18 @@ module cache_routing unique case (state) IDLE: + /* Transition se afirma si cache quiere hacer un read o write de + * memoria, o si el address no es cache y el core quiere leer + * o escribir a cache + */ transition = cache_mem || (!cached && (core_read || core_write)); CACHE: + // Cache le hace waitreq a memoria cache_mem_waitrequest = mem_waitrequest; BYPASS: + // Se le hace waitreq al core si la memoria también lo hace core_waitrequest = mem_waitrequest; endcase end @@ -94,6 +110,8 @@ module cache_routing end else unique case (state) IDLE: if (transition) begin + // Si cache quiere hacer una operación con memoria, se pasa + // a CACHE, sino hay que hacer BYPASS state <= cache_mem ? CACHE : BYPASS; mem_read <= cache_mem ? cache_mem_read : core_read; mem_write <= cache_mem ? cache_mem_write : core_write; @@ -109,6 +127,8 @@ module cache_routing always_ff @(posedge clk) if (transition) begin + // Si cache no quiere hacer una operación con memoria, se asignan + // las señales del core mem_address <= cache_mem ? cache_mem_address : core_address_line; mem_writedata <= cache_mem ? cache_mem_writedata : core_writedata_line; mem_byteenable <= cache_mem ? 16'hffff : core_byteenable_line; -- cgit v1.2.3 From 29832876ad224b7668ee1c2ba750e898fee347c3 Mon Sep 17 00:00:00 2001 From: Fabian Montero Date: Wed, 4 Oct 2023 17:51:02 -0600 Subject: explica estados de routing --- rtl/cache/routing.sv | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rtl/cache/routing.sv b/rtl/cache/routing.sv index c745cfc..ea30e95 100644 --- a/rtl/cache/routing.sv +++ b/rtl/cache/routing.sv @@ -78,6 +78,12 @@ module cache_routing assign cache_core_read = core_read && cached; assign cache_core_write = core_write && cached; + // Máquina de estados: + // IDLE/CACHE/BYPASS + // Bypass: el request evita pasar por caché, para que no quede escrito el + // el dato. Esto sirve para periféricos, por ejemplo. + // Cache: el request sí pasa por caché (esto sucede para todo lo que va + // para RAM. always_comb begin transition = 0; core_waitrequest = cache_core_waitrequest; -- cgit v1.2.3 From 84ac4c10f1e3ca4f779a19a1b0a2c43c5e18e37d Mon Sep 17 00:00:00 2001 From: Fabian Montero Date: Wed, 4 Oct 2023 17:57:21 -0600 Subject: explica mejor las transiciones de routing --- rtl/cache/routing.sv | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rtl/cache/routing.sv b/rtl/cache/routing.sv index ea30e95..78f1be0 100644 --- a/rtl/cache/routing.sv +++ b/rtl/cache/routing.sv @@ -82,7 +82,7 @@ module cache_routing // IDLE/CACHE/BYPASS // Bypass: el request evita pasar por caché, para que no quede escrito el // el dato. Esto sirve para periféricos, por ejemplo. - // Cache: el request sí pasa por caché (esto sucede para todo lo que va + // Cache: el request sí pasa por caché, esto sucede para todo lo que va // para RAM. always_comb begin transition = 0; @@ -117,7 +117,10 @@ module cache_routing IDLE: if (transition) begin // Si cache quiere hacer una operación con memoria, se pasa - // a CACHE, sino hay que hacer BYPASS + // a CACHE, sino hay que hacer BYPASS. Si la operación + // no es directo a memoria, se hace bypasss porque esto + // implica que el dato no tiene que quedar cacheado. (Talvez + // es algo de un periférico, etc.) state <= cache_mem ? CACHE : BYPASS; mem_read <= cache_mem ? cache_mem_read : core_read; mem_write <= cache_mem ? cache_mem_write : core_write; -- cgit v1.2.3