diff options
Diffstat (limited to 'rtl')
| -rw-r--r-- | rtl/core/arm810.sv | 20 | ||||
| -rw-r--r-- | rtl/core/cycles.sv | 130 | ||||
| -rw-r--r-- | rtl/core/cycles/ldst/pop.sv | 56 | ||||
| -rw-r--r-- | rtl/core/decode/decode.sv | 52 | ||||
| -rw-r--r-- | rtl/core/decode/ldst/addr.sv | 14 | ||||
| -rw-r--r-- | rtl/core/decode/ldst/misc.sv | 13 | ||||
| -rw-r--r-- | rtl/core/decode/ldst/multiple.sv | 10 | ||||
| -rw-r--r-- | rtl/core/decode/ldst/single.sv | 4 | ||||
| -rw-r--r-- | rtl/core/isa.sv | 3 | ||||
| -rw-r--r-- | rtl/core/uarch.sv | 3 |
10 files changed, 261 insertions, 44 deletions
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv index d3b2c6f..975ce03 100644 --- a/rtl/core/arm810.sv +++ b/rtl/core/arm810.sv @@ -33,6 +33,7 @@ module arm810 ptr dec_branch_offset; snd_decode dec_snd; data_decode dec_data; + ldst_decode dec_ldst; core_decode decode ( @@ -44,6 +45,7 @@ module arm810 .branch_offset(dec_branch_offset), .snd_ctrl(dec_snd), .data_ctrl(dec_data), + .ldst_ctrl(dec_ldst), .* ); @@ -53,7 +55,7 @@ module arm810 psr_mode reg_mode; alu_op alu_ctrl; shifter_control shifter_ctrl; - word alu_b, wr_value; + word alu_a, alu_b, wr_value; logic[7:0] shifter_shift; core_cycles cycles @@ -61,6 +63,12 @@ module arm810 .branch(explicit_branch), .alu(alu_ctrl), .shifter(shifter_ctrl), + .mem_addr(data_addr), + .mem_start(data_start), + .mem_write(data_write), + .mem_ready(data_ready), + .mem_data_rd(data_data_rd), + .mem_data_wr(data_data_wr), .* ); @@ -93,7 +101,7 @@ module arm810 core_alu #(.W(32)) alu ( .op(alu_ctrl), - .a(rd_value_a), + .a(alu_a), .b(alu_b), .q(q_alu), .nzcv(alu_flags), @@ -114,13 +122,9 @@ module arm810 .c(c_shifter) ); - //TODO ptr data_addr; - logic data_start, data_write, data_ready; - word data_data_rd, data_data_wr; - - logic insn_ready; - word insn_data_rd; + logic data_start, data_write, data_ready, insn_ready; + word data_data_rd, data_data_wr, insn_data_rd; core_mmu mmu ( diff --git a/rtl/core/cycles.sv b/rtl/core/cycles.sv index ddaf237..c416187 100644 --- a/rtl/core/cycles.sv +++ b/rtl/core/cycles.sv @@ -10,12 +10,16 @@ module core_cycles input ptr dec_branch_offset, input snd_decode dec_snd, input data_decode dec_data, + input ldst_decode dec_ldst, input ptr fetch_insn_pc, input psr_flags flags, - input word rd_value_b, + input word rd_value_a, + rd_value_b, q_alu, q_shifter, input logic c_shifter, + mem_ready, + input word mem_data_rd, output logic stall, branch, @@ -29,31 +33,53 @@ module core_cycles pc_visible, output psr_mode reg_mode, output alu_op alu, - output word alu_b, + output word alu_a, + alu_b, wr_value, output shifter_control shifter, - output logic[7:0] shifter_shift + output logic[7:0] shifter_shift, + output ptr mem_addr, + output word mem_data_wr, + output logic mem_start, + mem_write ); enum { ISSUE, RD_INDIRECT_SHIFT, - WITH_SHIFT + WITH_SHIFT, + TRANSFER, + BASE_WRITEBACK } cycle, next_cycle; logic bubble, final_writeback, final_update_flags, + ldst, ldst_pre, ldst_increment, ldst_writeback, pop_valid, data_snd_is_imm, data_snd_shift_by_reg, trivial_shift; logic[5:0] data_shift_imm; logic[11:0] data_imm; - word saved_base; - reg_num r_shift, final_rd; + word saved_base, mem_offset; + reg_num r_shift, final_rd, popped_upper, popped_lower, popped; + reg_list mem_regs, next_regs_upper, next_regs_lower; ptr pc; assign stall = (next_cycle != ISSUE) | bubble; assign pc_visible = pc + 2; assign reg_mode = `MODE_SVC; //TODO + assign trivial_shift = shifter_shift == 0; + assign mem_data_wr = rd_value_b; + assign popped = ldst_increment ? popped_lower : popped_upper; + + core_cycles_ldst_pop ldst_pop + ( + .regs(mem_regs), + .valid(pop_valid), + .next_upper(next_regs_upper), + .next_lower(next_regs_lower), + .pop_upper(popped_upper), + .pop_lower(popped_lower) + ); always_comb begin unique case(cycle) @@ -61,10 +87,6 @@ module core_cycles default: shifter_shift = {2'b00, data_shift_imm}; endcase - trivial_shift = 1; - if(final_writeback & (shifter.shl | shifter.shr | shifter.ror)) - trivial_shift = shifter_shift == 0; - next_cycle = ISSUE; unique case(cycle) @@ -78,34 +100,54 @@ module core_cycles if(~trivial_shift) next_cycle = WITH_SHIFT; + TRANSFER: + if(!mem_ready || pop_valid) + next_cycle = TRANSFER; + else if(ldst_writeback) + next_cycle = BASE_WRITEBACK; + default: ; endcase if(bubble) next_cycle = ISSUE; + else if(next_cycle == ISSUE && ldst) + next_cycle = TRANSFER; unique case(cycle) - ISSUE: + TRANSFER: alu_a = saved_base; + default: alu_a = rd_value_a; + endcase + + unique case(cycle) + RD_INDIRECT_SHIFT, WITH_SHIFT: + alu_b = saved_base; + + TRANSFER: + alu_b = mem_offset; + + default: if(data_snd_is_imm) alu_b = {{20{1'b0}}, data_imm}; else alu_b = rd_value_b; - - RD_INDIRECT_SHIFT, WITH_SHIFT: - alu_b = saved_base; endcase end always_ff @(posedge clk) begin cycle <= next_cycle; bubble <= 0; + branch <= 0; writeback <= 0; - wr_value <= q_alu; + + unique case(cycle) + TRANSFER: wr_value <= mem_data_rd; + BASE_WRITEBACK: wr_value <= saved_base; + default: wr_value <= q_alu; + endcase unique case(next_cycle) ISSUE: begin - branch <= 0; - branch_target <= {30{1'bx}}; final_writeback <= 0; final_update_flags <= 0; @@ -135,6 +177,16 @@ module core_cycles r_shift <= dec_snd.r_shift; c_in <= flags.c; + // TODO: dec_ldst.unprivileged/user_regs + // TODO: byte/halfword sizes + ldst <= dec_ldst.enable; + ldst_pre <= dec_ldst.pre_indexed; + ldst_increment <= dec_ldst.increment; + ldst_writeback <= dec_ldst.writeback; + + mem_regs <= dec_ldst.regs; + mem_write <= !dec_ldst.load; + final_rd <= dec_data.rd; final_writeback <= dec_writeback; final_update_flags <= dec_update_flags; @@ -156,6 +208,39 @@ module core_cycles c_in <= c_shifter; saved_base <= q_shifter; end + + TRANSFER: begin + if(cycle != TRANSFER) begin + ldst <= 0; + mem_offset <= alu_b; + end + + if(mem_ready) begin + wr_value <= mem_data_rd; + writeback <= !mem_write; + end + + if(cycle != TRANSFER || mem_ready) begin + mem_regs <= ldst_increment ? next_regs_lower : next_regs_upper; + mem_addr <= ldst_pre ? q_alu[31:2] : alu_a[31:2]; + saved_base <= q_alu; + + if(pop_valid) begin + rd <= popped; + rb <= popped; + end else + rb <= final_rd; // Viene de dec_ldst.rd + end + + mem_start <= cycle != TRANSFER || (mem_ready && pop_valid); + end + + BASE_WRITEBACK: begin + rd <= final_rd; + wr_value <= mem_data_rd; + writeback <= !mem_write; + final_rd <= ra; + end endcase end @@ -170,6 +255,17 @@ module core_cycles branch_target = 30'd0; data_snd_shift_by_reg = 0; + ldst = 0; + ldst_pre = 0; + ldst_writeback = 0; + ldst_increment = 0; + + mem_addr = 30'b0; + mem_write = 0; + mem_start = 0; + mem_regs = 16'b0; + mem_offset = 0; + final_rd = 0; final_writeback = 0; end diff --git a/rtl/core/cycles/ldst/pop.sv b/rtl/core/cycles/ldst/pop.sv new file mode 100644 index 0000000..a4078d1 --- /dev/null +++ b/rtl/core/cycles/ldst/pop.sv @@ -0,0 +1,56 @@ +`include "core/uarch.sv" + +module core_cycles_ldst_pop +( + input reg_list regs, + + output logic valid, + output reg_list next_upper, + next_lower, + output reg_num pop_upper, + pop_lower +); + + assign valid = regs != 16'b0; + + always_comb begin + unique casez(regs) + 16'b???????????????1: begin pop_lower = 4'h0; next_lower = {regs[15:1], 1'b0}; end + 16'b??????????????10: begin pop_lower = 4'h1; next_lower = {regs[15:2], 2'b0}; end + 16'b?????????????100: begin pop_lower = 4'h2; next_lower = {regs[15:3], 3'b0}; end + 16'b????????????1000: begin pop_lower = 4'h3; next_lower = {regs[15:4], 4'b0}; end + 16'b???????????10000: begin pop_lower = 4'h4; next_lower = {regs[15:5], 5'b0}; end + 16'b??????????100000: begin pop_lower = 4'h5; next_lower = {regs[15:6], 6'b0}; end + 16'b?????????1000000: begin pop_lower = 4'h6; next_lower = {regs[15:7], 7'b0}; end + 16'b????????10000000: begin pop_lower = 4'h7; next_lower = {regs[15:8], 8'b0}; end + 16'b???????100000000: begin pop_lower = 4'h8; next_lower = {regs[15:9], 9'b0}; end + 16'b??????1000000000: begin pop_lower = 4'h9; next_lower = {regs[15:10], 10'b0}; end + 16'b?????10000000000: begin pop_lower = 4'ha; next_lower = {regs[15:11], 11'b0}; end + 16'b????100000000000: begin pop_lower = 4'hb; next_lower = {regs[15:12], 12'b0}; end + 16'b???1000000000000: begin pop_lower = 4'hc; next_lower = {regs[15:13], 13'b0}; end + 16'b??10000000000000: begin pop_lower = 4'hd; next_lower = {regs[15:14], 14'b0}; end + 16'b?100000000000000: begin pop_lower = 4'he; next_lower = {regs[15], 15'b0}; end + default: begin pop_lower = 4'hf; next_lower = 16'b0; end + endcase + + unique casez(regs) + 16'b1???????????????: begin pop_upper = 4'hf; next_upper = { 1'b0, regs[14:0]}; end + 16'b01??????????????: begin pop_upper = 4'he; next_upper = { 2'b0, regs[13:0]}; end + 16'b001?????????????: begin pop_upper = 4'hd; next_upper = { 3'b0, regs[12:0]}; end + 16'b0001????????????: begin pop_upper = 4'hc; next_upper = { 4'b0, regs[11:0]}; end + 16'b00001???????????: begin pop_upper = 4'hb; next_upper = { 5'b0, regs[10:0]}; end + 16'b000001??????????: begin pop_upper = 4'ha; next_upper = { 6'b0, regs[9:0]}; end + 16'b0000001?????????: begin pop_upper = 4'h9; next_upper = { 7'b0, regs[8:0]}; end + 16'b00000001????????: begin pop_upper = 4'h8; next_upper = { 8'b0, regs[7:0]}; end + 16'b000000001???????: begin pop_upper = 4'h7; next_upper = { 9'b0, regs[6:0]}; end + 16'b0000000001??????: begin pop_upper = 4'h6; next_upper = {10'b0, regs[5:0]}; end + 16'b00000000001?????: begin pop_upper = 4'h5; next_upper = {11'b0, regs[4:0]}; end + 16'b000000000001????: begin pop_upper = 4'h4; next_upper = {12'b0, regs[3:0]}; end + 16'b0000000000001???: begin pop_upper = 4'h3; next_upper = {13'b0, regs[2:0]}; end + 16'b00000000000001??: begin pop_upper = 4'h2; next_upper = {14'b0, regs[1:0]}; end + 16'b000000000000001?: begin pop_upper = 4'h1; next_upper = {15'b0, regs[0]}; end + default: begin pop_upper = 4'h0; next_upper = 16'b0; end + endcase + end + +endmodule diff --git a/rtl/core/decode/decode.sv b/rtl/core/decode/decode.sv index d14841b..16b53d4 100644 --- a/rtl/core/decode/decode.sv +++ b/rtl/core/decode/decode.sv @@ -13,12 +13,12 @@ module core_decode branch, output ptr branch_offset, output snd_decode snd_ctrl, - output data_decode data_ctrl + output data_decode data_ctrl, + output ldst_decode ldst_ctrl ); //TODO logic restore_spsr; - ldst_decode ldst_ctrl; logic cond_undefined; @@ -77,10 +77,16 @@ module core_decode ); ldst_decode ldst_misc; + logic ldst_misc_off_is_reg; + reg_num ldst_misc_off_reg; + logic[7:0] ldst_misc_off_imm; core_decode_ldst_misc group_ldst_misc ( .decode(ldst_misc), + .off_imm(ldst_misc_off_imm), + .off_reg(ldst_misc_off_reg), + .off_is_reg(ldst_misc_off_is_reg), .* ); @@ -94,6 +100,15 @@ module core_decode .* ); + ldst_decode ldst_addr; + data_decode data_ldst; + + core_decode_ldst_addr ldst2data + ( + .ldst(ldst_addr), + .alu(data_ldst) + ); + always_comb begin undefined = cond_undefined; @@ -102,10 +117,14 @@ module core_decode update_flags = 0; data_ctrl = {($bits(data_ctrl)){1'bx}}; - snd_ctrl = {($bits(snd_ctrl)){1'bx}}; - snd_ctrl.shl = 0; + snd_ctrl = {$bits(snd_ctrl){1'bx}}; + snd_ctrl.shl = 1; snd_ctrl.shr = 0; snd_ctrl.ror = 0; + snd_ctrl.is_imm = 1; + snd_ctrl.shift_imm = {$bits(snd_ctrl.shift_imm){1'b0}}; + snd_ctrl.shift_by_reg = 0; + snd_is_imm = 1'bx; snd_ror_if_imm = 1'bx; snd_shift_by_reg_if_reg = 1'bx; @@ -148,7 +167,7 @@ module core_decode snd_ctrl = snd; ldst_ctrl = ldst_single; - ldst_ctrl.enable = 1; + ldst_addr = ldst_single; undefined = undefined | snd_undefined; end @@ -157,15 +176,22 @@ module core_decode priority casez(insn `FIELD_OP) `INSN_LDRB, `INSN_LDRSB, `INSN_LDRSH, `INSN_STRH: begin ldst_ctrl = ldst_misc; - ldst_ctrl.enable = 1; + ldst_addr = ldst_misc; + + snd_ctrl.r = ldst_misc_off_reg; + snd_ctrl.imm = {4'b0, ldst_misc_off_imm}; + snd_ctrl.is_imm = !ldst_misc_off_is_reg; end - default: undefined = 1; + default: + undefined = 1; endcase `GROUP_LDST_MULT: begin ldst_ctrl = ldst_multiple; - ldst_ctrl.enable = 1; + ldst_addr = ldst_multiple; + snd_ctrl.imm = 12'd4; + restore_spsr = ldst_mult_restore_spsr; end @@ -178,6 +204,16 @@ module core_decode default: undefined = 1; endcase + unique casez(insn `FIELD_OP) + `GROUP_LDST_SINGLE, `GROUP_LDST_MISC, `GROUP_LDST_MULT: begin + ldst_ctrl.enable = 1; + data_ctrl = data_ldst; + writeback = ldst_ctrl.writeback || ldst_ctrl.load; + end + + default: ; + endcase + if(undefined) begin branch = 1'bx; writeback = 1'bx; diff --git a/rtl/core/decode/ldst/addr.sv b/rtl/core/decode/ldst/addr.sv new file mode 100644 index 0000000..4a61231 --- /dev/null +++ b/rtl/core/decode/ldst/addr.sv @@ -0,0 +1,14 @@ +`include "core/uarch.sv" + +module core_decode_ldst_addr +( + input ldst_decode ldst, + + output data_decode alu +); + + assign alu.op = ldst.increment ? `ALU_ADD : `ALU_SUB; + assign alu.rn = ldst.rn; + assign alu.rd = ldst.rd; + +endmodule diff --git a/rtl/core/decode/ldst/misc.sv b/rtl/core/decode/ldst/misc.sv index de2428f..f2fe258 100644 --- a/rtl/core/decode/ldst/misc.sv +++ b/rtl/core/decode/ldst/misc.sv @@ -5,7 +5,10 @@ module core_decode_ldst_misc ( input word insn, - output ldst_decode decode + output ldst_decode decode, + output logic off_is_reg, + output logic[7:0] off_imm, + output reg_num off_reg ); logic p, w; @@ -17,10 +20,14 @@ module core_decode_ldst_misc assign decode.increment = insn `FIELD_LDST_MISC_U; assign decode.writeback = !p || w; assign decode.sign_extend = insn `FIELD_LDST_MISC_S; - assign decode.pre_indexed = p && w; + assign decode.pre_indexed = p; assign decode.unprivileged = 0; assign decode.user_regs = 0; - assign decode.reg_list = 16'b0; + assign decode.regs = 16'b0; + + assign off_imm = {insn `FIELD_LDST_MISC_IMM_HI, insn `FIELD_LDST_MISC_IMM_LO}; + assign off_reg = insn `FIELD_LDST_MISC_RM; + assign off_is_reg = insn `FIELD_LDST_MISC_REG; assign p = insn `FIELD_LDST_MISC_P; assign w = insn `FIELD_LDST_MISC_W; diff --git a/rtl/core/decode/ldst/multiple.sv b/rtl/core/decode/ldst/multiple.sv index 24e8e5b..d286a67 100644 --- a/rtl/core/decode/ldst/multiple.sv +++ b/rtl/core/decode/ldst/multiple.sv @@ -10,7 +10,7 @@ module core_decode_ldst_multiple ); logic s, l; - logic[15:0] reg_list; + reg_list regs; assign decode.rn = insn `FIELD_LDST_MULT_RN; assign decode.size = LDST_WORD; @@ -20,13 +20,13 @@ module core_decode_ldst_multiple assign decode.sign_extend = 0; assign decode.pre_indexed = insn `FIELD_LDST_MULT_P; assign decode.unprivileged = 0; - assign decode.user_regs = s && (!l || !reg_list[`R15]); - assign decode.reg_list = reg_list; + assign decode.user_regs = s && !(l && regs[`R15]); + assign decode.regs = regs; assign s = insn `FIELD_LDST_MULT_S; assign l = insn `FIELD_LDST_LD; - assign reg_list = insn `FIELD_LDST_MULT_LIST; - assign restore_spsr = s && l && reg_list[`R15]; + assign regs = insn `FIELD_LDST_MULT_LIST; + assign restore_spsr = s && l && regs[`R15]; endmodule diff --git a/rtl/core/decode/ldst/single.sv b/rtl/core/decode/ldst/single.sv index 5bcb638..0665178 100644 --- a/rtl/core/decode/ldst/single.sv +++ b/rtl/core/decode/ldst/single.sv @@ -18,10 +18,10 @@ module core_decode_ldst_single assign decode.increment = insn `FIELD_LDST_SINGLE_U; assign decode.writeback = !p || w; assign decode.sign_extend = 0; - assign decode.pre_indexed = p && w; + assign decode.pre_indexed = p; assign decode.unprivileged = !p && w; assign decode.user_regs = 0; - assign decode.reg_list = 16'b0; + assign decode.regs = 16'b0; assign p = insn `FIELD_LDST_SINGLE_P; assign w = insn `FIELD_LDST_SINGLE_W; diff --git a/rtl/core/isa.sv b/rtl/core/isa.sv index 7298b9a..c98cfd9 100644 --- a/rtl/core/isa.sv +++ b/rtl/core/isa.sv @@ -118,8 +118,10 @@ `define INSN_STM_CUR 28'b100_?_?_0_?_0_????_???????????????? `define INSN_STM_USR 28'b100_?_?_1_0_0_????_???????????????? +`define GROUP_LDST_SINGLE 28'b01_?_?_?_?_?_?_????_????_???????????? `define GROUP_LDST_SINGLE_IMM 28'b01_0_?_?_?_?_?_????_????_???????????? `define GROUP_LDST_SINGLE_REG 28'b01_1_?_?_?_?_?_????_????_?????_??_0_???? +`define GROUP_LDST_MISC 28'b000_?_?_?_?_?_????_????_????_1_?_?_1_???? `define GROUP_LDST_MISC_IMM 28'b000_?_?_1_?_?_????_????_????_1_?_?_1_???? `define GROUP_LDST_MISC_REG 28'b000_?_?_0_?_?_????_????_0000_1_?_?_1_???? `define GROUP_LDST_MULT 28'b100_?_?_?_?_?_????_???????????????? @@ -135,6 +137,7 @@ `define FIELD_LDST_MISC_P [24] `define FIELD_LDST_MISC_U [23] +`define FIELD_LDST_MISC_REG [22] `define FIELD_LDST_MISC_W [21] `define FIELD_LDST_MISC_RN [19:16] `define FIELD_LDST_MISC_RD [15:12] diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv index 2cd6f24..bd9ed03 100644 --- a/rtl/core/uarch.sv +++ b/rtl/core/uarch.sv @@ -5,6 +5,7 @@ `define NOP 32'd0 typedef logic[3:0] reg_num; +typedef logic[15:0] reg_list; typedef logic[31:0] word; typedef logic[29:0] ptr; @@ -104,7 +105,7 @@ typedef struct packed /* P. 482: "If no bits are set, the result is UNPREDICTABLE." * Esto permite diferenciar entre ldst mĂșltiple y simple. */ - logic[15:0] reg_list; + reg_list regs; } ldst_decode; typedef struct packed |
