diff options
| author | Alejandro Soto <alejandro@34project.org> | 2024-01-21 06:23:46 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2024-02-20 11:11:17 -0600 |
| commit | f3b18ead59ae02f95dabbf0a1dea40873a816975 (patch) | |
| tree | 8979e50f2a37f66a4cd27e937b480efe60d72cf7 /rtl/core/mmu | |
| parent | a8bc5a353ea997f73209b39377ee15a73e471237 (diff) | |
rtl: refactor filenames and directory hierarchy
Diffstat (limited to 'rtl/core/mmu')
| -rw-r--r-- | rtl/core/mmu/arbiter.sv | 132 | ||||
| -rw-r--r-- | rtl/core/mmu/fault.sv | 83 | ||||
| -rw-r--r-- | rtl/core/mmu/format.sv | 105 | ||||
| -rw-r--r-- | rtl/core/mmu/mmu.sv | 140 | ||||
| -rw-r--r-- | rtl/core/mmu/pagewalk.sv | 266 |
5 files changed, 0 insertions, 726 deletions
diff --git a/rtl/core/mmu/arbiter.sv b/rtl/core/mmu/arbiter.sv deleted file mode 100644 index b0da7c8..0000000 --- a/rtl/core/mmu/arbiter.sv +++ /dev/null @@ -1,132 +0,0 @@ -module core_mmu_arbiter -( - input logic clk, - rst_n, - - input logic bus_ready, - bus_ex_fail, - input word bus_data_rd, - data_data_wr, - input ptr insn_addr, - data_addr, - input logic insn_start, - data_start, - data_write, - data_ex_lock, - input logic[3:0] data_data_be, - - output word bus_data_wr, - output logic[3:0] bus_data_be, - output ptr bus_addr, - output logic bus_start, - bus_write, - bus_ex_lock, - insn_ready, - data_ready, - data_ex_fail, - output word insn_data_rd, - data_data_rd -); - - enum int unsigned - { - INSN, - DATA - } master, next_master; - - ptr hold_addr; - word hold_data_wr; - logic active, hold_ex_lock, hold_start, hold_write, hold_issue, hold_free, transition; - logic[3:0] hold_data_be; - - assign data_ex_fail = bus_ex_fail; - assign insn_data_rd = bus_data_rd; - assign data_data_rd = bus_data_rd; - - always_comb begin - next_master = master; - if(bus_ready || !active) - unique case(master) - DATA: next_master = data_start ? DATA : INSN; - INSN: next_master = !data_start && !hold_start ? INSN : DATA; - endcase - - // Causa UNOPTFLAT en Verilator con assign - transition = master != next_master; - hold_issue = transition && hold_start; - hold_free = transition || !hold_start; - - insn_ready = 0; - data_ready = 0; - - unique case(master) - INSN: insn_ready = bus_ready; - DATA: data_ready = bus_ready; - endcase - - bus_data_wr = data_data_wr; - unique case(next_master) - INSN: begin - bus_addr = insn_addr; - bus_write = 0; - bus_start = insn_start; - bus_data_be = 4'b1111; - bus_ex_lock = 0; - end - - DATA: begin - bus_addr = data_addr; - bus_write = data_write; - bus_start = data_start; - bus_data_be = data_data_be; - bus_ex_lock = data_ex_lock; - end - endcase - - if(hold_issue) begin - bus_addr = hold_addr; - bus_write = hold_write; - bus_start = 1; - bus_data_wr = hold_data_wr; - bus_data_be = hold_data_be; - bus_ex_lock = hold_ex_lock; - end - end - - always_ff @(posedge clk or negedge rst_n) - if(!rst_n) begin - master <= INSN; - active <= 0; - - hold_addr <= 30'b0; - hold_start <= 0; - hold_write <= 0; - hold_data_wr <= 0; - hold_data_be <= 0; - hold_ex_lock <= 0; - end else begin - master <= next_master; - active <= bus_start || (active && !bus_ready); - - if(hold_free) - unique case(next_master) - INSN: begin - hold_addr <= data_addr; - hold_start <= data_start; - hold_write <= data_write; - hold_data_wr <= data_data_wr; - hold_data_be <= data_data_be; - hold_ex_lock <= data_ex_lock; - end - - DATA: begin - hold_addr <= insn_addr; - hold_start <= insn_start; - hold_write <= 0; - hold_data_be <= 4'b1111; - hold_ex_lock <= 0; - end - endcase - end - -endmodule diff --git a/rtl/core/mmu/fault.sv b/rtl/core/mmu/fault.sv deleted file mode 100644 index b33cec2..0000000 --- a/rtl/core/mmu/fault.sv +++ /dev/null @@ -1,83 +0,0 @@ -`include "core/mmu/format.sv" -`include "core/uarch.sv" - -module core_mmu_fault -( - input logic valid_entry, - skip_perms, - input word mmu_dac, - input mmu_domain domain, - input logic[1:0] ap, - input logic privileged, - write, - - output logic fault, - output mmu_fault_type fault_type -); - - mmu_domain_ctrl domain_ctrl; - - always_comb begin - unique case(domain) - 4'h0: domain_ctrl = mmu_dac[1:0]; - 4'h1: domain_ctrl = mmu_dac[3:2]; - 4'h2: domain_ctrl = mmu_dac[5:4]; - 4'h3: domain_ctrl = mmu_dac[7:6]; - 4'h4: domain_ctrl = mmu_dac[9:8]; - 4'h5: domain_ctrl = mmu_dac[11:10]; - 4'h6: domain_ctrl = mmu_dac[13:12]; - 4'h7: domain_ctrl = mmu_dac[15:14]; - 4'h8: domain_ctrl = mmu_dac[17:16]; - 4'h9: domain_ctrl = mmu_dac[19:18]; - 4'ha: domain_ctrl = mmu_dac[21:20]; - 4'hb: domain_ctrl = mmu_dac[23:22]; - 4'hc: domain_ctrl = mmu_dac[25:24]; - 4'hd: domain_ctrl = mmu_dac[27:26]; - 4'he: domain_ctrl = mmu_dac[29:28]; - 4'hf: domain_ctrl = mmu_dac[31:30]; - endcase - - fault = 0; - fault_type = `MMU_FAULT_ACCESS; - - if(!valid_entry) begin - fault = 1; - fault_type = `MMU_FAULT_WALK; - end else if(!skip_perms) begin - if(!domain_ctrl.allowed) begin - fault = 1; - fault_type = `MMU_FAULT_DOMAIN; - end else if(!domain_ctrl.manager) - /* Hay una diferencia importante entre lo que dicen los - * manuales y lo que al parecer pasa realmente. Según - * el source del kernel, 0b00 debe permitir lecturas - * desde modos privilegiados (PTE_SMALL_AP_UNO_SRO), - * lo cual corresponde al caso con S = 1 en la tabla B4-1 - * del ARM ARM. Por otro lado, el kernel nunca usa su propia - * definición de CR_S. Mi única explicación para que esto - * funcione es que los cores legacy tienen S = 1 en reset - * y a nadie nunca se le ocurrió revisar eso, o tal vez - * el manual está mal. - * - * Todo esto resulta en que, si se interpretan los bits AP - * como dice el manual de ARMv6, la página inmediatamente - * posterior a tabla de vectores altos del kernel provoque - * un prefetch abort (!!!) cuando los vectores saltan a esta, - * lo cual causa un bucle infinito de aborts a la primera IRQ. - */ - unique case(ap) - 2'b00: - fault = !privileged || write; - - 2'b01: - fault = !privileged; - - 2'b10: - fault = !privileged && write; - - 2'b11: ; - endcase - end - end - -endmodule diff --git a/rtl/core/mmu/format.sv b/rtl/core/mmu/format.sv deleted file mode 100644 index 3029b83..0000000 --- a/rtl/core/mmu/format.sv +++ /dev/null @@ -1,105 +0,0 @@ -`ifndef CORE_MMU_FORMAT_SV -`define CORE_MMU_FORMAT_SV - -typedef logic[17:0] mmu_base; -typedef logic[3:0] mmu_domain; - -`define MMU_L1_INDEX [29:18] -`define MMU_L1_FAULT 2'b00 -`define MMU_L1_PAGETABLE 2'b01 -`define MMU_L1_SECTION 2'b10 - -typedef struct packed -{ - logic[31:10] field10; - logic[9:9] imp; - logic[8:5] domain; - logic[4:4] sbz; - logic[3:2] field2; - logic[1:0] typ; -} mmu_l1_entry; - -typedef struct packed -{ - logic[31:10] base; - logic[9:9] imp; - logic[8:5] domain; - logic[4:2] sbz; - logic[1:0] typ; -} mmu_l1_pagetable; - -typedef struct packed -{ - logic[31:20] base; - logic[19:15] sbz0; - logic[14:12] tex; - logic[11:10] ap; - logic[9:9] imp; - logic[8:5] domain; - logic[4:4] sbz1; - logic[3:3] c; - logic[2:2] b; - logic[1:0] typ; -} mmu_l1_section; - -`define MMU_SECTION_INDEX [17:0] - -`define MMU_L2_INDEX [17:10] -`define MMU_L2_FAULT 2'b00 -`define MMU_L2_LARGE 2'b01 -`define MMU_L2_SMALL 2'b10 -`define MMU_L2_SMALLEXT 2'b11 - -typedef struct packed -{ - logic[31:16] base; - logic[15:15] sbz; - logic[14:12] tex; - logic[11:10] ap3; - logic[9:8] ap2; - logic[7:6] ap1; - logic[5:4] ap0; - logic[3:3] c; - logic[2:2] b; - logic[1:0] typ; -} mmu_l2_large; - -typedef struct packed -{ - logic[31:12] base; - logic[11:10] ap3; - logic[9:8] ap2; - logic[7:6] ap1; - logic[5:4] ap0; - logic[3:3] c; - logic[2:2] b; - logic[1:0] typ; -} mmu_l2_small; - -typedef struct packed -{ - logic[31:12] base; - logic[11:9] sbz; - logic[8:6] tex; - logic[5:4] ap; - logic[3:3] c; - logic[2:2] b; - logic[1:0] typ; -} mmu_l2_smallext; - -`define MMU_LARGE_INDEX [13:0] -`define MMU_SMALL_INDEX [9:0] - -typedef logic[1:0] mmu_fault_type; - -`define MMU_FAULT_WALK 2'b01 -`define MMU_FAULT_DOMAIN 2'b10 -`define MMU_FAULT_ACCESS 2'b11 - -typedef struct packed -{ - logic manager, - allowed; -} mmu_domain_ctrl; - -`endif diff --git a/rtl/core/mmu/mmu.sv b/rtl/core/mmu/mmu.sv deleted file mode 100644 index 22dfc3b..0000000 --- a/rtl/core/mmu/mmu.sv +++ /dev/null @@ -1,140 +0,0 @@ -`include "core/mmu/format.sv" -`include "core/uarch.sv" - -module core_mmu -( - input logic clk, - rst_n, - - input logic privileged, - mmu_enable /*verilator public*/, - input mmu_base mmu_ttbr /*verilator public*/, - input word mmu_dac, - - input logic bus_ready, - bus_ex_fail, - input word bus_data_rd, - data_data_wr, - input ptr insn_addr, - data_addr, - input logic insn_start, - data_start, - data_write, - data_ex_lock, - data_user, - input logic[3:0] data_data_be, - - output word bus_data_wr, - output logic[3:0] bus_data_be, - output ptr bus_addr, - output logic bus_start, - bus_write, - bus_ex_lock, - insn_ready, - insn_fault, - data_ready, - data_fault, - data_ex_fail, - output word insn_data_rd, - data_data_rd, - - output logic fault_register, - fault_page, - output ptr fault_addr, - output mmu_fault_type fault_type, - output mmu_domain fault_domain -); - - ptr iphys_addr, dphys_addr; - word iphys_data_rd, dphys_data_rd, dphys_data_wr; - logic[3:0] dphys_data_be; - - logic iphys_start, dphys_start, iphys_ready, dphys_ready, dphys_write, - dphys_ex_fail, dphys_ex_lock; - - assign fault_register = data_fault; - - core_mmu_pagewalk iwalk - ( - .core_addr(insn_addr), - .core_start(insn_start), - .core_write(0), - .core_ready(insn_ready), - .core_data_wr(0), - .core_data_be(0), - .core_data_rd(insn_data_rd), - .core_ex_fail(), - .core_ex_lock(0), - - .core_fault(insn_fault), - .core_fault_addr(), - .core_fault_page(), - .core_fault_type(), - .core_fault_domain(), - - .bus_addr(iphys_addr), - .bus_start(iphys_start), - .bus_write(), - .bus_ready(iphys_ready), - .bus_data_wr(), - .bus_data_be(), - .bus_data_rd(iphys_data_rd), - .bus_ex_fail(0), - .bus_ex_lock(), - - .* - ); - - core_mmu_pagewalk dwalk - ( - .core_addr(data_addr), - .core_start(data_start), - .core_write(data_write), - .core_ready(data_ready), - .core_data_wr(data_data_wr), - .core_data_be(data_data_be), - .core_data_rd(data_data_rd), - .core_ex_fail(data_ex_fail), - .core_ex_lock(data_ex_lock), - - .core_fault(data_fault), - .core_fault_addr(fault_addr), - .core_fault_page(fault_page), - .core_fault_type(fault_type), - .core_fault_domain(fault_domain), - - .bus_addr(dphys_addr), - .bus_start(dphys_start), - .bus_write(dphys_write), - .bus_ready(dphys_ready), - .bus_data_wr(dphys_data_wr), - .bus_data_be(dphys_data_be), - .bus_data_rd(dphys_data_rd), - .bus_ex_fail(dphys_ex_fail), - .bus_ex_lock(dphys_ex_lock), - - .privileged(privileged && !data_user), - .* - ); - - core_mmu_arbiter arbiter - ( - .insn_addr(iphys_addr), - .insn_start(iphys_start), - .insn_ready(iphys_ready), - .insn_data_rd(iphys_data_rd), - - .data_addr(dphys_addr), - .data_start(dphys_start), - .data_write(dphys_write), - .data_ready(dphys_ready), - .data_data_wr(dphys_data_wr), - .data_data_be(dphys_data_be), - .data_data_rd(dphys_data_rd), - .data_ex_fail(dphys_ex_fail), - .data_ex_lock(dphys_ex_lock), - - .* - ); - -endmodule diff --git a/rtl/core/mmu/pagewalk.sv b/rtl/core/mmu/pagewalk.sv deleted file mode 100644 index 70c932c..0000000 --- a/rtl/core/mmu/pagewalk.sv +++ /dev/null @@ -1,266 +0,0 @@ -`include "core/mmu/format.sv" -`include "core/uarch.sv" - -module core_mmu_pagewalk -( - input logic clk, - rst_n, - - input logic privileged, - mmu_enable, - input mmu_base mmu_ttbr, - input word mmu_dac, - - input logic bus_ready, - bus_ex_fail, - input word bus_data_rd, - - input ptr core_addr, - input word core_data_wr, - input logic[3:0] core_data_be, - input logic core_start, - core_write, - core_ex_lock, - - output ptr bus_addr, - output word bus_data_wr, - output logic[3:0] bus_data_be, - output logic bus_start, - bus_write, - bus_ex_lock, - - output word core_data_rd, - output logic core_ready, - core_ex_fail, - core_fault, - core_fault_page, - output ptr core_fault_addr, - output mmu_fault_type core_fault_type, - output mmu_domain core_fault_domain -); - - enum int unsigned - { - IDLE, - L1, - L2, - DATA, - FAULT - } state; - - logic access_fault, valid_entry, skip_perms; - logic[1:0] ap, entry_type; - mmu_domain domain, entry_domain; - mmu_fault_type access_fault_type; - - assign entry_type = bus_data_rd[1:0]; - assign core_fault_domain = domain; - - core_mmu_fault access_check - ( - .write(hold_write), - .fault(access_fault), - .domain(entry_domain), - .fault_type(access_fault_type), - .* - ); - - mmu_l1_entry l1; - assign l1 = bus_data_rd; - - mmu_l1_pagetable pagetable; - assign pagetable = bus_data_rd; - - mmu_l1_section section; - assign section = bus_data_rd; - - mmu_l2_large ptentry_large; - assign ptentry_large = bus_data_rd; - - mmu_l2_small ptentry_small; - assign ptentry_small = bus_data_rd; - - mmu_l2_smallext ptentry_smallext; - assign ptentry_smallext = bus_data_rd; - - ptr target; - word hold_data; - logic hold_write, hold_ex_lock; - logic[3:0] hold_be; - - always_comb begin - ap = 2'bxx; - skip_perms = 0; - valid_entry = 1; - entry_domain = domain; - - unique case(state) - L1: - unique case(entry_type) - `MMU_L1_PAGETABLE: begin - ap = 2'bxx; - skip_perms = 1; - end - - `MMU_L1_SECTION: begin - ap = section.ap; - entry_domain = l1.domain; - end - - // Tiny (1KiB wtf?) pages and supersections not supported - default: - valid_entry = 0; - endcase - - L2: - unique case(entry_type) - `MMU_L2_FAULT: - valid_entry = 0; - - `MMU_L2_LARGE: - //TODO: ap3-ap2 (también en L2_SMALL) - ap = ptentry_large.ap0; - - `MMU_L2_SMALL: - ap = ptentry_small.ap0; - - `MMU_L2_SMALLEXT: - ap = ptentry_smallext.ap; - endcase - - default: - valid_entry = 1'bx; - endcase - end - - always @(posedge clk or negedge rst_n) - if(!rst_n) begin - state <= IDLE; - target <= 0; - domain <= 0; - - hold_be <= 0; - hold_data <= 0; - hold_write <= 0; - hold_ex_lock <= 0; - - bus_addr <= 0; - bus_start <= 0; - bus_write <= 0; - bus_ex_lock <= 0; - bus_data_be <= 0; - bus_data_wr <= 0; - - core_ready <= 0; - core_fault <= 0; - core_ex_fail <= 0; - core_data_rd <= 0; - core_fault_page <= 0; - core_fault_addr <= 0; - core_fault_type <= 0; - end else begin - if(bus_start) - bus_start <= 0; - - if(core_ready) - core_ready <= 0; - - if(core_fault) - core_fault <= 0; - - unique case(state) - IDLE: - if(core_start) begin - bus_start <= 1; - - if(mmu_enable) begin - target <= core_addr; - hold_be <= core_data_be; - hold_data <= core_data_wr; - hold_write <= core_write; - hold_ex_lock <= core_ex_lock; - - state <= L1; - bus_addr <= {mmu_ttbr, core_addr `MMU_L1_INDEX}; - bus_write <= 0; - bus_ex_lock <= 0; - end else begin - state <= DATA; - bus_addr <= core_addr; - bus_write <= core_write; - bus_ex_lock <= core_ex_lock; - bus_data_wr <= core_data_wr; - bus_data_be <= core_data_be; - end - end - - L1: - if(bus_ready) begin - domain <= l1.domain; - - unique case(entry_type) - `MMU_L1_PAGETABLE: begin - state <= L2; - bus_addr <= {pagetable.base, target `MMU_L2_INDEX}; - end - - `MMU_L1_SECTION: begin - state <= DATA; - bus_addr <= {section.base, target `MMU_SECTION_INDEX}; - bus_write <= hold_write; - bus_ex_lock <= hold_ex_lock; - bus_data_wr <= hold_data; - bus_data_be <= hold_be; - end - - default: ; - endcase - end - - L2: - if(bus_ready) begin - state <= DATA; - - bus_write <= hold_write; - bus_ex_lock <= hold_ex_lock; - bus_data_wr <= hold_data; - bus_data_be <= hold_be; - - unique case(entry_type) - `MMU_L2_FAULT: ; - - `MMU_L2_LARGE: - bus_addr <= {ptentry_large.base, target `MMU_LARGE_INDEX}; - - `MMU_L2_SMALL, `MMU_L2_SMALLEXT: - bus_addr <= {ptentry_small.base, target `MMU_SMALL_INDEX}; - endcase - end - - DATA: - if(bus_ready) begin - state <= IDLE; - core_ready <= 1; - core_ex_fail <= bus_ex_fail; - core_data_rd <= bus_data_rd; - end - - FAULT: begin - state <= IDLE; - core_fault <= 1; - core_ready <= 1; - core_fault_addr <= target; - end - endcase - - if((state == L1 || state == L2) && bus_ready) begin - if(access_fault) begin - state <= FAULT; - core_fault_type <= access_fault_type; - core_fault_page <= state == L2; - end else - bus_start <= 1; - end - end - -endmodule |
