diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-10-16 01:38:33 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-10-16 01:38:33 -0600 |
| commit | 2e6ce7931b690ccec1e41fa6847dfc1351c59d75 (patch) | |
| tree | 81759ffd1e61465a26e03414f25fbbb918308350 /rtl/core/control | |
| parent | f0b38daac3a2f987deb79fcca763f3b84b0f2b73 (diff) | |
Rename cycles as control
Diffstat (limited to 'rtl/core/control')
| -rw-r--r-- | rtl/core/control/control.sv | 279 | ||||
| -rw-r--r-- | rtl/core/control/ldst/pop.sv | 56 |
2 files changed, 335 insertions, 0 deletions
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv new file mode 100644 index 0000000..398c8c7 --- /dev/null +++ b/rtl/core/control/control.sv @@ -0,0 +1,279 @@ +`include "core/uarch.sv" + +module core_control +( + input logic clk, + dec_execute, + dec_conditional, + dec_branch, + dec_writeback, + dec_update_flags, + 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_a, + rd_value_b, + q_alu, + q_shifter, + input logic c_shifter, + mem_ready, + input word mem_data_rd, + + output logic stall, + branch, + writeback, + update_flags, + c_in, + output reg_num rd, + ra, + rb, + output ptr branch_target, + pc_visible, + output psr_mode reg_mode, + output alu_op alu, + output word alu_a, + alu_b, + wr_value, + output shifter_control shifter, + 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, + TRANSFER, + BASE_WRITEBACK + } cycle, next_cycle; + + logic bubble, next_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, 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, next_pc_visible; + + assign stall = next_cycle != ISSUE || next_bubble; + 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; + assign next_pc_visible = fetch_insn_pc + 2; + + assign next_bubble = + ((dec_update_flags || dec_conditional) && (final_update_flags || update_flags)) + || (final_writeback && (final_rd == dec_data.rn || final_rd == dec_snd.r)); + + core_control_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) + RD_INDIRECT_SHIFT: shifter_shift = rd_value_b[7:0]; + default: shifter_shift = {2'b00, data_shift_imm}; + endcase + + next_cycle = ISSUE; + + unique case(cycle) + ISSUE: + if(data_snd_shift_by_reg) + next_cycle = RD_INDIRECT_SHIFT; + else if(~trivial_shift) + next_cycle = WITH_SHIFT; + + RD_INDIRECT_SHIFT: + 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) + 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; + endcase + end + + always_ff @(posedge clk) begin + cycle <= next_cycle; + bubble <= 0; + branch <= 0; + writeback <= 0; + update_flags <= 0; + + 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 + final_writeback <= 0; + final_update_flags <= 0; + + bubble <= next_bubble; + + if(dec_execute & ~next_bubble) begin + branch <= dec_branch; + branch_target <= next_pc_visible + dec_branch_offset; + + alu <= dec_data.op; + ra <= dec_data.rn; + + data_snd_is_imm <= dec_snd.is_imm; + data_snd_shift_by_reg <= dec_snd.shift_by_reg; + data_imm <= dec_snd.imm; + data_shift_imm <= dec_snd.shift_imm; + + shifter.shr <= dec_snd.shr; + shifter.ror <= dec_snd.ror; + shifter.put_carry <= dec_snd.put_carry; + shifter.sign_extend <= dec_snd.sign_extend; + + rb <= dec_snd.r; + 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; + end + + update_flags <= final_update_flags; + writeback <= final_writeback; + rd <= final_rd; + pc <= fetch_insn_pc; + pc_visible <= next_pc_visible; + end + + RD_INDIRECT_SHIFT: begin + rb <= r_shift; + data_snd_shift_by_reg <= 0; + saved_base <= rd_value_b; + end + + WITH_SHIFT: begin + 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 + + initial begin + cycle = ISSUE; + bubble = 0; + + pc = 0; + pc_visible = 2; + + c_in = 0; + branch = 1; + writeback = 0; + 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 + +endmodule diff --git a/rtl/core/control/ldst/pop.sv b/rtl/core/control/ldst/pop.sv new file mode 100644 index 0000000..64dc04d --- /dev/null +++ b/rtl/core/control/ldst/pop.sv @@ -0,0 +1,56 @@ +`include "core/uarch.sv" + +module core_control_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 |
