summaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-12-11 23:54:38 -0600
committerAlejandro Soto <alejandro@34project.org>2022-12-16 16:29:10 -0600
commit79e05aa7f0ccce6eb26248ddef3e928727857a9c (patch)
tree8c67d6532234dac0eace7f005638efc8441105a5 /rtl
parent0284628a47d5b4797c89f6846b9efee3f1243b94 (diff)
Implement prefetch aborts
Diffstat (limited to '')
-rw-r--r--rtl/core/arm810.sv8
-rw-r--r--rtl/core/control/control.sv3
-rw-r--r--rtl/core/control/exception.sv6
-rw-r--r--rtl/core/control/issue.sv6
-rw-r--r--rtl/core/fetch/fetch.sv4
-rw-r--r--rtl/core/fetch/prefetch.sv33
-rw-r--r--rtl/core/mmu/mmu.sv3
-rw-r--r--rtl/core/porch/porch.sv8
8 files changed, 53 insertions, 18 deletions
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv
index a0c1e0f..c820720 100644
--- a/rtl/core/arm810.sv
+++ b/rtl/core/arm810.sv
@@ -23,7 +23,7 @@ module arm810
ptr fetch_insn_pc, fetch_head, insn_addr;
word fetch_insn;
- logic fetch_nop, stall, flush, prefetch_flush, insn_start;
+ logic fetch_nop, fetch_abort, stall, flush, prefetch_flush, insn_start;
//TODO
assign prefetch_flush = halt;
@@ -34,8 +34,10 @@ module arm810
.addr(insn_addr),
.insn(fetch_insn),
.fetch(insn_start),
+ .fault(insn_fault),
.fetched(insn_ready),
.insn_pc(fetch_insn_pc),
+ .insn_abort(fetch_abort),
.fetch_data(insn_data_rd),
.porch_insn_pc(insn_pc),
.*
@@ -51,10 +53,12 @@ module arm810
ptr insn_pc;
word insn;
+ logic issue_abort;
insn_decode dec;
core_porch porch
(
+ .abort(issue_abort),
.*
);
@@ -166,7 +170,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, data_fault;
+ logic data_start, data_write, data_ready, insn_ready, data_fault, insn_fault;
logic[3:0] data_data_be;
core_mmu mmu
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv
index 8bf4976..840cf19 100644
--- a/rtl/core/control/control.sv
+++ b/rtl/core/control/control.sv
@@ -9,6 +9,7 @@ module core_control
input insn_decode dec,
input ptr insn_pc,
+ input logic issue_abort,
input psr_mode mode,
input psr_flags flags,
alu_flags,
@@ -89,7 +90,7 @@ module core_control
);
ptr pc /*verilator public*/, next_pc_visible;
- logic issue, undefined;
+ logic issue, undefined, prefetch_abort;
core_control_issue ctrl_issue
(
diff --git a/rtl/core/control/exception.sv b/rtl/core/control/exception.sv
index 2d12c0a..038cd2b 100644
--- a/rtl/core/control/exception.sv
+++ b/rtl/core/control/exception.sv
@@ -8,6 +8,7 @@ module core_control_exception
input ctrl_cycle next_cycle,
input logic high_vectors,
undefined,
+ prefetch_abort,
mem_fault,
output logic exception,
@@ -20,7 +21,7 @@ module core_control_exception
//TODO: irq, fiq, prefetch abort, swi
- assign exception = undefined || mem_fault;
+ assign exception = undefined || prefetch_abort || mem_fault;
assign exception_vector = {{16{high_vectors}}, 11'b0, vector_offset, 2'b00};
always @(posedge clk or negedge rst_n) begin
@@ -31,6 +32,9 @@ module core_control_exception
end else if(mem_fault) begin
vector_offset <= 3'b100;
exception_mode <= `MODE_ABT;
+ end else if(prefetch_abort) begin
+ vector_offset <= 3'b011;
+ exception_mode <= `MODE_ABT;
end else if(undefined) begin
vector_offset <= 3'b001;
exception_mode <= `MODE_UND;
diff --git a/rtl/core/control/issue.sv b/rtl/core/control/issue.sv
index ffdf250..23ecdcf 100644
--- a/rtl/core/control/issue.sv
+++ b/rtl/core/control/issue.sv
@@ -8,6 +8,7 @@ module core_control_issue
input insn_decode dec,
input ptr insn_pc,
+ input logic issue_abort,
input ctrl_cycle next_cycle,
input logic next_bubble,
@@ -18,6 +19,7 @@ module core_control_issue
output logic issue,
undefined,
+ prefetch_abort,
output ptr pc,
pc_visible,
next_pc_visible
@@ -34,12 +36,14 @@ module core_control_issue
pc <= 0;
undefined <= 0;
pc_visible <= 2;
+ prefetch_abort <= 0;
end else if(next_cycle.issue) begin
if(valid) begin
undefined <= dec.ctrl.undefined;
+ prefetch_abort <= issue_abort;
`ifdef VERILATOR
- if(dec.ctrl.undefined)
+ if(dec.ctrl.undefined && !issue_abort)
$display("[core] undefined insn: [0x%08x] %08x", insn_pc << 2, insn);
`endif
end
diff --git a/rtl/core/fetch/fetch.sv b/rtl/core/fetch/fetch.sv
index ba9d677..279d2c2 100644
--- a/rtl/core/fetch/fetch.sv
+++ b/rtl/core/fetch/fetch.sv
@@ -6,6 +6,7 @@ module core_fetch
input logic clk,
rst_n,
stall,
+ fault,
fetched,
explicit_branch /*verilator public*/ /*verilator forceable*/,
wr_pc,
@@ -21,7 +22,8 @@ module core_fetch
output word insn,
output ptr insn_pc,
addr,
- fetch_head
+ fetch_head,
+ output logic insn_abort
);
ptr target /*verilator public*/ /*verilator forceable*/, hold_addr;
diff --git a/rtl/core/fetch/prefetch.sv b/rtl/core/fetch/prefetch.sv
index 1b5a4c5..719ad95 100644
--- a/rtl/core/fetch/prefetch.sv
+++ b/rtl/core/fetch/prefetch.sv
@@ -7,6 +7,7 @@ module core_prefetch
rst_n,
stall,
flush,
+ fault,
fetched,
input word fetch_data,
input ptr head,
@@ -14,34 +15,43 @@ module core_prefetch
output word insn,
output ptr insn_pc,
output logic fetch,
- nop
+ nop,
+ insn_abort
);
localparam SIZE = (1 << ORDER) - 1;
ptr next_pc;
+ logic faults[SIZE];
logic[31:0] prefetch[SIZE];
logic[ORDER - 1:0] valid;
assign nop = flush ? 1 : ~|valid;
assign insn = flush ? `NOP : prefetch[0];
- assign next_pc = ~stall & |valid ? insn_pc + 1 : insn_pc;
assign fetch = !stall || ~&valid;
+ assign next_pc = ~stall & |valid ? insn_pc + 1 : insn_pc;
+ assign insn_abort = flush ? 0 : faults[0];
always_ff @(posedge clk or negedge rst_n)
if(!rst_n) begin
valid <= 0;
insn_pc <= 0;
+
+ faults[SIZE - 1] <= 0;
prefetch[SIZE - 1] <= `NOP;
end else begin
insn_pc <= flush ? head : next_pc;
- if(flush)
+ if(flush) begin
+ faults[SIZE - 1] <= 0;
prefetch[SIZE - 1] <= `NOP;
- else if(fetched && valid == SIZE - 1 + {{(ORDER - 1){1'b0}}, !stall})
+ end else if(fetched && valid == SIZE - 1 + {{(ORDER - 1){1'b0}}, !stall}) begin
+ faults[SIZE - 1] <= fault;
prefetch[SIZE - 1] <= fetch_data;
- else if(!stall)
+ end else if(!stall) begin
+ faults[SIZE - 1] <= 0;
prefetch[SIZE - 1] <= `NOP;
+ end
if(flush)
valid <= 0;
@@ -55,14 +65,19 @@ module core_prefetch
generate
for(i = 0; i < SIZE - 1; ++i) begin: prefetch_slots
always_ff @(posedge clk or negedge rst_n)
- if(!rst_n)
+ if(!rst_n) begin
+ faults[i] <= 0;
prefetch[i] <= `NOP;
- else if(flush)
+ end else if(flush) begin
+ faults[i] <= 0;
prefetch[i] <= `NOP;
- else if(fetched & (~(|i | |valid) | (valid == i + {{(ORDER - 1){1'b0}}, ~stall})))
+ end else if(fetched & (~(|i | |valid) | (valid == i + {{(ORDER - 1){1'b0}}, ~stall}))) begin
+ faults[i] <= fault;
prefetch[i] <= fetch_data;
- else if(~stall)
+ end else if(~stall) begin
+ faults[i] <= faults[i + 1];
prefetch[i] <= prefetch[i + 1];
+ end
end
endgenerate
diff --git a/rtl/core/mmu/mmu.sv b/rtl/core/mmu/mmu.sv
index 17f1e98..d22f1cd 100644
--- a/rtl/core/mmu/mmu.sv
+++ b/rtl/core/mmu/mmu.sv
@@ -26,6 +26,7 @@ module core_mmu
output logic bus_start,
bus_write,
insn_ready,
+ insn_fault,
data_ready,
data_fault,
output word insn_data_rd,
@@ -51,7 +52,7 @@ module core_mmu
.core_start(insn_start),
.core_write(0),
.core_ready(insn_ready),
- .core_fault(),
+ .core_fault(insn_fault),
.core_data_wr(0),
.core_data_be(0),
.core_data_rd(insn_data_rd),
diff --git a/rtl/core/porch/porch.sv b/rtl/core/porch/porch.sv
index 4369836..99ba9ed 100644
--- a/rtl/core/porch/porch.sv
+++ b/rtl/core/porch/porch.sv
@@ -10,13 +10,15 @@ module core_porch
input word fetch_insn,
input logic fetch_nop,
+ fetch_abort,
input ptr fetch_insn_pc,
fetch_head,
input insn_decode fetch_dec,
output word insn,
output ptr insn_pc,
- output insn_decode dec
+ output insn_decode dec,
+ output logic abort
);
logic execute, conditional, undefined, nop;
@@ -25,7 +27,7 @@ module core_porch
always_comb begin
dec = hold_dec;
dec.ctrl.nop = nop;
- dec.ctrl.execute = !flush && dec.ctrl.execute && execute && !nop;
+ dec.ctrl.execute = !flush && dec.ctrl.execute && execute && !nop && !abort;
dec.ctrl.undefined = !flush && (dec.ctrl.undefined || undefined);
dec.ctrl.conditional = !flush && (dec.ctrl.conditional || conditional);
end
@@ -39,11 +41,13 @@ module core_porch
if(!rst_n) begin
nop <= 0; // Even though it is a NOP
insn <= `NOP;
+ abort <= 0;
insn_pc <= 0;
hold_dec <= {$bits(hold_dec){1'b0}};
end else if(flush || !stall) begin
nop <= flush ? 1 : fetch_nop;
insn <= flush ? `NOP : fetch_insn;
+ abort <= flush ? 0 : fetch_abort;
insn_pc <= flush ? fetch_head : fetch_insn_pc;
hold_dec <= fetch_dec;
end