diff options
Diffstat (limited to 'rtl')
| -rw-r--r-- | rtl/core/arm810.sv | 4 | ||||
| -rw-r--r-- | rtl/core/control/control.sv | 4 | ||||
| -rw-r--r-- | rtl/core/control/data.sv | 16 | ||||
| -rw-r--r-- | rtl/core/control/ldst/ldst.sv | 28 | ||||
| -rw-r--r-- | rtl/core/control/ldst/sizes.sv | 46 | ||||
| -rw-r--r-- | rtl/core/control/writeback.sv | 8 |
6 files changed, 93 insertions, 13 deletions
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) |
