summaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-12-11 14:48:08 -0600
committerAlejandro Soto <alejandro@34project.org>2022-12-16 16:27:20 -0600
commitff71bcd0c5425c168f111b8f4a92d0a90a6c9c31 (patch)
tree41190239b9220db09d8849afb6d6f6dbbc03f59b /rtl
parent6fee344b754464b1fd17f7c0429e6597e51dc74d (diff)
Implement data aborts
Diffstat (limited to 'rtl')
-rw-r--r--rtl/core/arm810.sv6
-rw-r--r--rtl/core/control/control.sv6
-rw-r--r--rtl/core/control/cycles.sv7
-rw-r--r--rtl/core/control/data.sv10
-rw-r--r--rtl/core/control/exception.sv48
-rw-r--r--rtl/core/control/ldst/ldst.sv3
-rw-r--r--rtl/core/control/psr.sv5
-rw-r--r--rtl/core/control/writeback.sv4
-rw-r--r--rtl/core/cp15/cp15.sv5
-rw-r--r--rtl/core/cp15/far.sv5
-rw-r--r--rtl/core/mmu/mmu.sv12
-rw-r--r--rtl/core/mmu/pagewalk.sv17
12 files changed, 94 insertions, 34 deletions
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv
index 1fd408f..bc4b5d9 100644
--- a/rtl/core/arm810.sv
+++ b/rtl/core/arm810.sv
@@ -76,6 +76,7 @@ module arm810
.mem_start(data_start),
.mem_write(data_write),
.mem_ready(data_ready),
+ .mem_fault(data_fault),
.mem_data_rd(data_data_rd),
.mem_data_wr(data_data_wr),
.mem_data_be(data_data_be),
@@ -165,7 +166,7 @@ module arm810
ptr data_addr;
word data_data_rd, data_data_wr, insn_data_rd;
- logic data_start, data_write, data_ready, insn_ready;
+ logic data_start, data_write, data_ready, insn_ready, data_fault;
logic[3:0] data_data_be;
core_mmu mmu
@@ -173,8 +174,9 @@ module arm810
.*
);
+ ptr fault_addr;
word coproc_read;
- logic coproc, high_vectors, mmu_enable;
+ logic coproc, high_vectors, mmu_enable, fault_register;
mmu_base mmu_ttbr;
coproc_decode coproc_ctrl;
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv
index 3c55507..8bf4976 100644
--- a/rtl/core/control/control.sv
+++ b/rtl/core/control/control.sv
@@ -20,6 +20,7 @@ module core_control
q_shifter,
input logic c_shifter,
mem_ready,
+ mem_fault,
input word mem_data_rd,
input logic mul_ready,
input word mul_q_hi,
@@ -147,8 +148,9 @@ module core_control
.*
);
- word vector;
- logic exception;
+ word exception_vector;
+ logic exception, exception_offset_pc;
+ psr_mode exception_mode;
core_control_exception ctrl_exc
(
diff --git a/rtl/core/control/cycles.sv b/rtl/core/control/cycles.sv
index 88e0235..5779990 100644
--- a/rtl/core/control/cycles.sv
+++ b/rtl/core/control/cycles.sv
@@ -12,6 +12,7 @@ module core_control_cycles
coproc,
exception,
mem_ready,
+ mem_fault,
mul_add,
mul_long,
mul_ready,
@@ -100,12 +101,16 @@ module core_control_cycles
ESCALATE:
next_state = EXCEPTION;
- TRANSFER:
+ TRANSFER: begin
if(!mem_ready || pop_valid)
next_state = TRANSFER;
else if(ldst_writeback)
next_state = BASE_WRITEBACK;
+ if(mem_ready && mem_fault)
+ next_state = ESCALATE;
+ end
+
MUL:
if(!mul_ready)
next_state = MUL;
diff --git a/rtl/core/control/data.sv b/rtl/core/control/data.sv
index 5ba6b92..5d34b13 100644
--- a/rtl/core/control/data.sv
+++ b/rtl/core/control/data.sv
@@ -17,11 +17,12 @@ module core_control_data
input ctrl_cycle cycle,
next_cycle,
- input ptr pc,
+ input ptr pc_visible,
input logic ldst_next,
input logic[1:0] ldst_shift,
input word mem_offset,
input psr_flags flags,
+ input logic exception_offset_pc,
output alu_op alu,
output word alu_a,
@@ -52,7 +53,7 @@ module core_control_data
if(cycle.transfer)
alu_a = saved_base;
else if(cycle.exception)
- alu_a = {pc, 2'b00};
+ alu_a = {pc_visible, 2'b00};
else
alu_a = rd_value_a;
@@ -107,8 +108,9 @@ module core_control_data
shifter.ror <= 0;
shifter.shr <= !mem_write;
end else if(next_cycle.exception) begin
- alu <= `ALU_ADD;
- data_imm <= 12'd4;
+ alu <= `ALU_SUB;
+ // Either pc_visible - 0 (pc + 8) or pc_visible - 4 (pc + 4)
+ data_imm <= {9'd0, exception_offset_pc, 2'b00};
data_snd_is_imm <= 1;
end
diff --git a/rtl/core/control/exception.sv b/rtl/core/control/exception.sv
index 3965114..2d12c0a 100644
--- a/rtl/core/control/exception.sv
+++ b/rtl/core/control/exception.sv
@@ -2,24 +2,42 @@
module core_control_exception
(
- input logic clk,
- rst_n,
-
- input logic undefined,
- high_vectors,
-
- output word vector,
- output logic exception
+ input logic clk,
+ rst_n,
+
+ input ctrl_cycle next_cycle,
+ input logic high_vectors,
+ undefined,
+ mem_fault,
+
+ output logic exception,
+ exception_offset_pc,
+ output psr_mode exception_mode,
+ output word exception_vector
);
logic[2:0] vector_offset;
- assign exception = undefined; //TODO
- assign vector = {{16{high_vectors}}, 11'b0, vector_offset, 2'b00};
-
- always_comb
- vector_offset = 3'b001; //TODO
-
- //TODO: Considerar que data abort usa + 8, no + 4
+ //TODO: irq, fiq, prefetch abort, swi
+
+ assign exception = undefined || mem_fault;
+ assign exception_vector = {{16{high_vectors}}, 11'b0, vector_offset, 2'b00};
+
+ always @(posedge clk or negedge rst_n) begin
+ if(!rst_n) begin
+ vector_offset <= 0;
+ exception_mode <= 0;
+ exception_offset_pc <= 0;
+ end else if(mem_fault) begin
+ vector_offset <= 3'b100;
+ exception_mode <= `MODE_ABT;
+ end else if(undefined) begin
+ vector_offset <= 3'b001;
+ exception_mode <= `MODE_UND;
+ end
+
+ if(next_cycle.escalate)
+ exception_offset_pc <= !mem_fault;
+ end
endmodule
diff --git a/rtl/core/control/ldst/ldst.sv b/rtl/core/control/ldst/ldst.sv
index dd5155a..027fb0a 100644
--- a/rtl/core/control/ldst/ldst.sv
+++ b/rtl/core/control/ldst/ldst.sv
@@ -77,7 +77,8 @@ module core_control_ldst
mem_start <= 0;
mem_offset <= 0;
end else begin
- mem_start <= 0;
+ if(mem_start)
+ mem_start <= 0;
if(next_cycle.issue) begin
// TODO: dec.ldst.unprivileged
diff --git a/rtl/core/control/psr.sv b/rtl/core/control/psr.sv
index 5767124..07bf4e5 100644
--- a/rtl/core/control/psr.sv
+++ b/rtl/core/control/psr.sv
@@ -10,6 +10,7 @@ module core_control_psr
spsr_rd,
alu_b,
input psr_mode mode,
+ exception_mode,
input ctrl_cycle cycle,
next_cycle,
@@ -44,8 +45,8 @@ module core_control_psr
psr_write = 1;
if(cycle.escalate)
- //TODO: otros modos, y además F (FIQ) no cambia siempre
- psr_wr = {24'b0, 3'b110, `MODE_UND};
+ //TODO: F (FIQ) no cambia siempre
+ psr_wr = {24'b0, 3'b110, exception_mode};
else if(cycle.exception)
psr_wr = exception_spsr;
else
diff --git a/rtl/core/control/writeback.sv b/rtl/core/control/writeback.sv
index 3bacb75..a7738fb 100644
--- a/rtl/core/control/writeback.sv
+++ b/rtl/core/control/writeback.sv
@@ -17,7 +17,7 @@ module core_control_writeback
input ctrl_cycle cycle,
next_cycle,
input word saved_base,
- vector,
+ exception_vector,
psr_wb,
coproc_wb,
input reg_num ra,
@@ -81,7 +81,7 @@ module core_control_writeback
end else if(next_cycle.base_writeback)
wr_value = ldst_read;
else if(next_cycle.exception)
- wr_value = vector;
+ wr_value = exception_vector;
else if(next_cycle.mul_hi_wb)
wr_value = mul_q_hi;
diff --git a/rtl/core/cp15/cp15.sv b/rtl/core/cp15/cp15.sv
index 8ddc474..bf84292 100644
--- a/rtl/core/cp15/cp15.sv
+++ b/rtl/core/cp15/cp15.sv
@@ -10,6 +10,9 @@ module core_cp15
input coproc_decode dec,
input word write,
+ input logic fault_register,
+ input ptr fault_addr,
+
output word read,
output logic high_vectors,
mmu_enable,
@@ -61,7 +64,7 @@ module core_cp15
.*
);
- core_cp15_far fsr
+ core_cp15_fsr fsr
(
.read(read_fsr),
.transfer(transfer && crn == `CP15_CRN_FSR),
diff --git a/rtl/core/cp15/far.sv b/rtl/core/cp15/far.sv
index b90dc0f..3d86151 100644
--- a/rtl/core/cp15/far.sv
+++ b/rtl/core/cp15/far.sv
@@ -11,6 +11,9 @@ module core_cp15_far
input cp_opcode op2,
input word write,
+ input logic fault_register,
+ input ptr fault_addr,
+
output word read
);
@@ -21,6 +24,8 @@ module core_cp15_far
always @(posedge clk or negedge rst_n)
if(!rst_n)
far <= 0;
+ else if(fault_register)
+ far <= {fault_addr, 2'b00};
else if(transfer && !load)
far <= write;
diff --git a/rtl/core/mmu/mmu.sv b/rtl/core/mmu/mmu.sv
index 504e447..91986db 100644
--- a/rtl/core/mmu/mmu.sv
+++ b/rtl/core/mmu/mmu.sv
@@ -26,8 +26,12 @@ module core_mmu
bus_write,
insn_ready,
data_ready,
+ data_fault,
output word insn_data_rd,
- data_data_rd
+ data_data_rd,
+
+ output logic fault_register,
+ output ptr fault_addr
);
ptr iphys_addr, dphys_addr;
@@ -35,15 +39,19 @@ module core_mmu
logic iphys_start, dphys_start, iphys_ready, dphys_ready, dphys_write;
logic[3:0] dphys_data_be;
+ 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_fault(),
.core_data_wr(0),
.core_data_be(0),
.core_data_rd(insn_data_rd),
+ .core_fault_addr(),
.bus_addr(iphys_addr),
.bus_start(iphys_start),
@@ -62,9 +70,11 @@ module core_mmu
.core_start(data_start),
.core_write(data_write),
.core_ready(data_ready),
+ .core_fault(data_fault),
.core_data_wr(data_data_wr),
.core_data_be(data_data_be),
.core_data_rd(data_data_rd),
+ .core_fault_addr(fault_addr),
.bus_addr(dphys_addr),
.bus_start(dphys_start),
diff --git a/rtl/core/mmu/pagewalk.sv b/rtl/core/mmu/pagewalk.sv
index b16ce26..be4aa8b 100644
--- a/rtl/core/mmu/pagewalk.sv
+++ b/rtl/core/mmu/pagewalk.sv
@@ -25,7 +25,9 @@ module core_mmu_pagewalk
bus_write,
output logic core_ready,
- output word core_data_rd
+ core_fault,
+ output word core_data_rd,
+ output ptr core_fault_addr
);
enum int unsigned
@@ -71,7 +73,9 @@ module core_mmu_pagewalk
bus_data_wr <= 0;
core_ready <= 0;
+ core_fault <= 0;
core_data_rd <= 0;
+ core_fault_addr <= 0;
end else begin
if(bus_start)
bus_start <= 0;
@@ -79,6 +83,9 @@ module core_mmu_pagewalk
if(core_ready)
core_ready <= 0;
+ if(core_fault)
+ core_fault <= 0;
+
unique case(state)
IDLE:
if(core_start) begin
@@ -157,8 +164,12 @@ module core_mmu_pagewalk
core_data_rd <= bus_data_rd;
end
- //TODO
- FAULT: ;
+ FAULT: begin
+ state <= IDLE;
+ core_fault <= 1;
+ core_ready <= 1;
+ core_fault_addr <= target;
+ end
endcase
end