summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conspiracion.qsf1
-rw-r--r--rtl/core/arm810.sv4
-rw-r--r--rtl/core/control/control.sv4
-rw-r--r--rtl/core/control/data.sv16
-rw-r--r--rtl/core/control/ldst/ldst.sv28
-rw-r--r--rtl/core/control/ldst/sizes.sv46
-rw-r--r--rtl/core/control/writeback.sv8
7 files changed, 94 insertions, 13 deletions
diff --git a/conspiracion.qsf b/conspiracion.qsf
index 243cb0a..c6f0f9f 100644
--- a/conspiracion.qsf
+++ b/conspiracion.qsf
@@ -208,6 +208,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/issue.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/mul.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/ldst/ldst.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/ldst/pop.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/ldst/sizes.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/select.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/stall.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/writeback.sv
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv
index eb5ebe1..ce29821 100644
--- a/rtl/core/arm810.sv
+++ b/rtl/core/arm810.sv
@@ -124,13 +124,13 @@ module arm810
.*
);
- word q_shifter;
+ word shifter_base, q_shifter;
logic c_shifter;
core_shifter #(.W(32)) shifter
(
.ctrl(shifter_ctrl),
- .base(alu_b),
+ .base(shifter_base),
.shift(shifter_shift),
.c_in(flags.c),
.q(q_shifter),
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv
index 506af2b..adfe9f7 100644
--- a/rtl/core/control/control.sv
+++ b/rtl/core/control/control.sv
@@ -43,6 +43,7 @@ module core_control
alu_b,
wr_value,
output shifter_control shifter,
+ output word shifter_base,
output logic[7:0] shifter_shift,
output ptr mem_addr,
output word mem_data_wr,
@@ -86,9 +87,10 @@ module core_control
.*
);
- word mem_offset;
+ word mem_offset, ldst_read;
logic ldst, ldst_next, ldst_writeback, pop_valid;
reg_num popped;
+ logic[1:0] ldst_shift;
core_control_ldst ctrl_ldst
(
diff --git a/rtl/core/control/data.sv b/rtl/core/control/data.sv
index 6a7ec15..5ba6b92 100644
--- a/rtl/core/control/data.sv
+++ b/rtl/core/control/data.sv
@@ -9,7 +9,9 @@ module core_control_data
input word rd_value_a,
rd_value_b,
input logic mem_ready,
- input word q_alu,
+ mem_write,
+ input word mem_data_rd,
+ q_alu,
q_shifter,
input logic c_shifter,
@@ -17,6 +19,7 @@ module core_control_data
next_cycle,
input ptr pc,
input logic ldst_next,
+ input logic[1:0] ldst_shift,
input word mem_offset,
input psr_flags flags,
@@ -25,6 +28,7 @@ module core_control_data
alu_b,
saved_base,
output shifter_control shifter,
+ output word shifter_base,
output logic[7:0] shifter_shift,
output logic c_in,
trivial_shift,
@@ -40,6 +44,8 @@ module core_control_data
always_comb begin
if(cycle.rd_indirect_shift)
shifter_shift = rd_value_b[7:0];
+ else if(cycle.transfer)
+ shifter_shift = {3'b000, ldst_shift, 3'b000};
else
shifter_shift = {2'b00, data_shift_imm};
@@ -58,6 +64,11 @@ module core_control_data
alu_b = {{20{1'b0}}, data_imm};
else
alu_b = rd_value_b;
+
+ if(cycle.transfer)
+ shifter_base = mem_write ? rd_value_b : mem_data_rd;
+ else
+ shifter_base = alu_b;
end
always_ff @(posedge clk or negedge rst_n)
@@ -92,6 +103,9 @@ module core_control_data
end else if(next_cycle.transfer) begin
if(ldst_next)
saved_base <= q_alu;
+
+ shifter.ror <= 0;
+ shifter.shr <= !mem_write;
end else if(next_cycle.exception) begin
alu <= `ALU_ADD;
data_imm <= 12'd4;
diff --git a/rtl/core/control/ldst/ldst.sv b/rtl/core/control/ldst/ldst.sv
index 12bd6b9..02f7b4a 100644
--- a/rtl/core/control/ldst/ldst.sv
+++ b/rtl/core/control/ldst/ldst.sv
@@ -10,6 +10,7 @@ module core_control_ldst
mem_ready,
input word rd_value_b,
q_alu,
+ q_shifter,
input ctrl_cycle cycle,
next_cycle,
@@ -25,16 +26,20 @@ module core_control_ldst
ldst,
ldst_next,
ldst_writeback,
+ output logic[1:0] ldst_shift,
+ output word ldst_read,
output reg_num popped
);
- logic pre, increment;
+ word base;
+ logic pre, increment, sign_extend;
reg_num popped_upper, popped_lower;
reg_list mem_regs, next_regs_upper, next_regs_lower;
+ ldst_size size;
assign popped = increment ? popped_lower : popped_upper;
assign ldst_next = !cycle.transfer || mem_ready;
- assign mem_data_wr = rd_value_b;
+ assign mem_data_wr = q_shifter;
core_control_ldst_pop pop
(
@@ -46,14 +51,26 @@ module core_control_ldst
.pop_lower(popped_lower)
);
+ core_control_ldst_sizes sizes
+ (
+ .addr(mem_addr),
+ .read(ldst_read),
+ .shift(ldst_shift),
+ .fault(), //TODO: alignment check
+ .byteenable(), //TODO
+ .*
+ );
+
always_ff @(posedge clk or negedge rst_n)
if(!rst_n) begin
pre <= 0;
ldst <= 0;
+ size <= LDST_WORD;
increment <= 0;
+ sign_extend <= 0;
ldst_writeback <= 0;
- mem_addr <= {$bits(mem_addr){1'b0}};
+ base <= {$bits(base){1'b0}};
mem_regs <= {$bits(mem_regs){1'b0}};
mem_write <= 0;
mem_start <= 0;
@@ -63,12 +80,13 @@ module core_control_ldst
if(next_cycle.issue) begin
// TODO: dec.ldst.unprivileged
- // TODO: byte/halfword sizes
if(issue)
ldst <= dec.ctrl.ldst;
pre <= dec.ldst.pre_indexed;
+ size <= dec.ldst.size;
increment <= dec.ldst.increment;
+ sign_extend <= dec.ldst.sign_extend;
ldst_writeback <= dec.ldst.writeback;
mem_regs <= dec.ldst.regs;
@@ -80,8 +98,8 @@ module core_control_ldst
end
if(ldst_next) begin
+ base <= pre ? q_alu : alu_a;
mem_regs <= increment ? next_regs_lower : next_regs_upper;
- mem_addr <= pre ? q_alu[31:2] : alu_a[31:2];
end
mem_start <= !cycle.transfer || (mem_ready && pop_valid);
diff --git a/rtl/core/control/ldst/sizes.sv b/rtl/core/control/ldst/sizes.sv
new file mode 100644
index 0000000..dff4662
--- /dev/null
+++ b/rtl/core/control/ldst/sizes.sv
@@ -0,0 +1,46 @@
+`include "core/uarch.sv"
+
+module core_control_ldst_sizes
+(
+ input word base,
+ q_shifter,
+ input ldst_size size,
+ input logic sign_extend,
+
+ output ptr addr,
+ output word read,
+ output logic[1:0] shift,
+ output logic[3:0] byteenable,
+ output logic fault
+);
+
+ assign {addr, shift} = base;
+
+ always_comb
+ unique case(size)
+ LDST_BYTE: begin
+ read = {{24{q_shifter[7] && sign_extend}}, q_shifter[7:0]};
+ fault = 0;
+
+ unique case(shift)
+ 2'b00: byteenable = 4'b0001;
+ 2'b01: byteenable = 4'b0010;
+ 2'b10: byteenable = 4'b0100;
+ 2'b11: byteenable = 4'b1000;
+ endcase
+ end
+
+ LDST_HALF: begin
+ read = {{16{q_shifter[15] && sign_extend}}, q_shifter[15:0]};
+ fault = shift[0];
+ byteenable = shift[1] ? 4'b1100 : 4'b0011;
+ end
+
+ LDST_WORD: begin
+ read = q_shifter;
+ fault = shift[1] || shift[0];
+ byteenable = 4'b1111;
+ end
+ endcase
+
+endmodule
diff --git a/rtl/core/control/writeback.sv b/rtl/core/control/writeback.sv
index 914236c..24b3ed5 100644
--- a/rtl/core/control/writeback.sv
+++ b/rtl/core/control/writeback.sv
@@ -8,7 +8,7 @@ module core_control_writeback
input insn_decode dec,
input psr_flags alu_flags,
input word q_alu,
- mem_data_rd,
+ ldst_read,
input logic mem_ready,
mem_write,
input word mul_q_hi,
@@ -61,7 +61,7 @@ module core_control_writeback
writeback = 0;
if(cycle.transfer)
- wr_value = mem_data_rd;
+ wr_value = ldst_read;
else if(cycle.base_writeback)
wr_value = saved_base;
else if(cycle.mul || cycle.mul_hi_wb)
@@ -72,9 +72,9 @@ module core_control_writeback
if(next_cycle.transfer) begin
if(mem_ready)
- wr_value = mem_data_rd;
+ wr_value = ldst_read;
end else if(next_cycle.base_writeback)
- wr_value = mem_data_rd;
+ wr_value = ldst_read;
else if(next_cycle.exception)
wr_value = vector;
else if(next_cycle.mul_hi_wb)