From 2deaf0058faefb0b7dba9c419ecef372991bb0d5 Mon Sep 17 00:00:00 2001 From: gullahmed1 Date: Fri, 12 Jan 2024 18:02:38 +0500 Subject: [PATCH 1/2] Add Zcmp support --- core/Flist.cva6 | 1 + core/compressed_decoder.sv | 7 + core/id_stage.sv | 37 ++- core/zcmp_decoder.sv | 592 +++++++++++++++++++++++++++++++++++++ 4 files changed, 632 insertions(+), 5 deletions(-) create mode 100644 core/zcmp_decoder.sv diff --git a/core/Flist.cva6 b/core/Flist.cva6 index 342f053e3c..c9d5af0812 100644 --- a/core/Flist.cva6 +++ b/core/Flist.cva6 @@ -103,6 +103,7 @@ ${CVA6_REPO_DIR}/core/alu.sv ${CVA6_REPO_DIR}/core/fpu_wrap.sv ${CVA6_REPO_DIR}/core/branch_unit.sv ${CVA6_REPO_DIR}/core/compressed_decoder.sv +${CVA6_REPO_DIR}/core/zcmp_decoder.sv ${CVA6_REPO_DIR}/core/controller.sv ${CVA6_REPO_DIR}/core/csr_buffer.sv ${CVA6_REPO_DIR}/core/csr_regfile.sv diff --git a/core/compressed_decoder.sv b/core/compressed_decoder.sv index cc9c77df87..02b2edb6c6 100644 --- a/core/compressed_decoder.sv +++ b/core/compressed_decoder.sv @@ -24,6 +24,7 @@ module compressed_decoder #( ) ( input logic [31:0] instr_i, output logic [31:0] instr_o, + output logic is_push_pop_instr_o, output logic illegal_instr_o, output logic is_compressed_o ); @@ -36,6 +37,7 @@ module compressed_decoder #( instr_o = '0; is_compressed_o = 1'b1; instr_o = instr_i; + is_push_pop_instr_o = 0; // I: | imm[11:0] | rs1 | funct3 | rd | opcode | // S: | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | @@ -849,6 +851,10 @@ module compressed_decoder #( riscv::OpcodeC2Fsdsp: begin if (CVA6Cfg.FpPresent) begin + if (instr_i[12:10] == 3'b110 || instr_i[12:10] == 3'b111 || instr_i[12:10] == 3'b011) begin //is a push/pop instruction + is_push_pop_instr_o = 1; + instr_o = instr_i; + end else begin // c.fsdsp -> fsd rs2, imm(x2) instr_o = { 3'b0, @@ -861,6 +867,7 @@ module compressed_decoder #( 3'b000, riscv::OpcodeStoreFp }; + end end else begin illegal_instr_o = 1'b1; end diff --git a/core/id_stage.sv b/core/id_stage.sv index dfd8dd698f..6c86692b41 100644 --- a/core/id_stage.sv +++ b/core/id_stage.sv @@ -54,8 +54,13 @@ module id_stage #( ariane_pkg::scoreboard_entry_t decoded_instruction; logic is_illegal; + logic is_illegal_cmp; logic [31:0] instruction; + logic [31:0] compressed_instr; logic is_compressed; + logic is_compressed_cmp; + logic is_push_pop; + logic stall_instr_fetch; if (CVA6Cfg.RVC) begin // --------------------------------------------------------- @@ -65,10 +70,32 @@ module id_stage #( .CVA6Cfg(CVA6Cfg) ) compressed_decoder_i ( .instr_i (fetch_entry_i.instruction), - .instr_o (instruction), + .instr_o (compressed_instr), .illegal_instr_o(is_illegal), - .is_compressed_o(is_compressed) + .is_compressed_o(is_compressed), + .is_push_pop_instr_o(is_push_pop) ); + /*if (CVA6Cfg.CVA6ConfigZcmpExtEn) begin*/ + //sequencial decoder + zcmp_decoder #( + .CVA6Cfg(CVA6Cfg) + ) zcmp_decoder_i ( + .instr_i (compressed_instr), + .is_push_pop_instr_i (is_push_pop), + .clk_i (clk_i), + .rst_ni (rst_ni), + .instr_o (instruction), + .illegal_instr_i (is_illegal), + .is_compressed_i (is_compressed), + .illegal_instr_o (is_illegal_cmp), + .is_compressed_o (is_compressed_cmp), + .fetch_stall (stall_instr_fetch) + ); + /*end else begin + instruction = compressed_instr; + is_compressed_cmp = is_compressed; + is_illegal_cmp = is_illegal; + end*/ end else begin assign instruction = fetch_entry_i.instruction; assign is_illegal = '0; @@ -84,8 +111,8 @@ module id_stage #( .irq_ctrl_i, .irq_i, .pc_i (fetch_entry_i.address), - .is_compressed_i (is_compressed), - .is_illegal_i (is_illegal), + .is_compressed_i (is_compressed_cmp), + .is_illegal_i (is_illegal_cmp), .instruction_i (instruction), .compressed_instr_i (fetch_entry_i.instruction[15:0]), .branch_predict_i (fetch_entry_i.branch_predict), @@ -119,7 +146,7 @@ module id_stage #( // if we have a space in the register and the fetch is valid, go get it // or the issue stage is currently acknowledging an instruction, which means that we will have space // for a new instruction - if ((!issue_q.valid || issue_instr_ack_i) && fetch_entry_valid_i) begin + if ((!issue_q.valid || issue_instr_ack_i) && fetch_entry_valid_i && !stall_instr_fetch) begin fetch_entry_ready_o = 1'b1; issue_n = '{1'b1, decoded_instruction, is_control_flow_instr}; end diff --git a/core/zcmp_decoder.sv b/core/zcmp_decoder.sv new file mode 100644 index 0000000000..ab6fce43a1 --- /dev/null +++ b/core/zcmp_decoder.sv @@ -0,0 +1,592 @@ +module zcmp_decoder #( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty) + ( + input logic [31:0] instr_i, + input logic clk_i, // Clock + input logic rst_ni, // Synchronous reset + input logic is_push_pop_instr_i, + input logic illegal_instr_i, + input logic is_compressed_i, + output logic [31:0] instr_o, + output logic illegal_instr_o, + output logic is_compressed_o, + output logic fetch_stall //Wait while push/pop instructions expand +); + + // FSM States + enum logic [2:0] { + IDLE, PUSH_POP_INSTR_1, PUSH_ADDI, PUSH_POP_INSTR_2, POPRETZ_1, MOVE, INIT + } state_d, state_q; + + // Instruction Types + enum logic[2:0] { + PUSH, POP, POPRETZ, POPRET, MVA01S, MVSA01 + } zcmp_instr_type; + + // Temporary registers + logic [3:0] reg_numbers; + logic [8:0] stack_adj; + logic [4:0] xreg1; + logic [4:0] xreg2; + logic [3:0] reg_numbers_d; + logic [3:0] reg_numbers_q; + logic [4:0] store_reg_q; + logic [4:0] store_reg_d; + logic [1:0] popretz_inst_q; + logic [1:0] popretz_inst_d; + logic [11:0] offset_q; + logic [11:0] offset_d; + + riscv::itype_t itype_inst; + + always_comb begin + illegal_instr_o = 1'b0; + fetch_stall = is_push_pop_instr_i ? 1'b1 : 1'b0; + instr_o = instr_i; + is_compressed_o = is_push_pop_instr_i ? 1'b1 : is_compressed_i; + reg_numbers = '0; + stack_adj = '0; + + state_d = state_q; + offset_d = offset_q; + reg_numbers_d = reg_numbers_q; + store_reg_d = store_reg_q; + popretz_inst_d = popretz_inst_q; + + if (is_push_pop_instr_i) begin + unique case (instr_i[12:10]) + // push or pop + 3'b110: begin + unique case (instr_i[9:8]) + 2'b00: begin + zcmp_instr_type = PUSH; + end + 2'b10: begin + zcmp_instr_type = POP; + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + // popret or popretz + 3'b111: begin + unique case (instr_i[9:8]) + 2'b00: begin + zcmp_instr_type = POPRETZ; + end + 2'b10: begin + zcmp_instr_type = POPRET; + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + // mvq01s or mvsa01 + 3'b011: begin + unique case (instr_i[6:5]) + 2'b01: begin + zcmp_instr_type = MVSA01; + end + 2'b11: begin + zcmp_instr_type = MVA01S; + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + + if (zcmp_instr_type == MVSA01 || zcmp_instr_type == MVA01S) begin + if(instr_i[9:7] != instr_i[4:2]) begin + xreg1 = {instr_i[9:8] > 0, instr_i[9:8] == 0, instr_i[9:7]}; + xreg2 = {instr_i[4:3] > 0, instr_i[4:3] == 0, instr_i[4:2]}; + end else begin + illegal_instr_o = 1'b1; + end + end else begin + xreg1 = '0; + xreg2 = '0; + end + + // push/pop/popret/popretz instructions + unique case (instr_i[7:4]) + 4'b0100: reg_numbers = 1; // 4 + 4'b0101: reg_numbers = 2; // 5 + 4'b0110: reg_numbers = 3; // 6 + 4'b0111: reg_numbers = 4; // 7 + 4'b1000: reg_numbers = 5; // 8 + 4'b1001: reg_numbers = 6; // 9 + 4'b1010: reg_numbers = 7; // 10 + 4'b1011: reg_numbers = 8; // 11 + 4'b1100: reg_numbers = 9; // 12 + 4'b1101: reg_numbers = 10; // 13 + 4'b1110: reg_numbers = 11; // 14 + 4'b1111: reg_numbers = 12; // 15 + default: illegal_instr_o = 1'b1; + endcase + + if (riscv::XLEN==32) begin + unique case (instr_i[7:4]) + 4'b0100, 4'b0101, 4'b0110, 4'b0111: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 16; + 2'b01: stack_adj = 32; + 2'b10: stack_adj = 48; + 2'b11: stack_adj = 64; + endcase + end + 4'b1000, 4'b1001, 4'b1010, 4'b1011: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 32; + 2'b01: stack_adj = 48; + 2'b10: stack_adj = 64; + 2'b11: stack_adj = 80; + endcase + end + 4'b1100, 4'b1101, 4'b1110: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 48; + 2'b01: stack_adj = 64; + 2'b10: stack_adj = 80; + 2'b11: stack_adj = 96; + endcase + end + 4'b1111: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 64; + 2'b01: stack_adj = 80; + 2'b10: stack_adj = 96; + 2'b11: stack_adj = 112; + endcase + end + default: illegal_instr_o = 1'b1; + endcase + end else begin + unique case (instr_i[7:4]) + 4'b0100, 4'b0101: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 16; + 2'b01: stack_adj = 32; + 2'b10: stack_adj = 48; + 2'b11: stack_adj = 64; + endcase + end + 4'b0110, 4'b0111: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 32; + 2'b01: stack_adj = 48; + 2'b10: stack_adj = 64; + 2'b11: stack_adj = 80; + endcase + end + 4'b1000, 4'b1001: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 48; + 2'b01: stack_adj = 64; + 2'b10: stack_adj = 80; + 2'b11: stack_adj = 96; + endcase + end + 4'b1010, 4'b1011: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 64; + 2'b01: stack_adj = 80; + 2'b10: stack_adj = 96; + 2'b11: stack_adj = 112; + endcase + end + 4'b1100, 4'b1101: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 80; + 2'b01: stack_adj = 96; + 2'b10: stack_adj = 112; + 2'b11: stack_adj = 128; + endcase + end + 4'b1110: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 96; + 2'b01: stack_adj = 112; + 2'b10: stack_adj = 128; + 2'b11: stack_adj = 144; + endcase + end + 4'b1111: begin + unique case (instr_i[3:2]) + 2'b00: stack_adj = 112; + 2'b01: stack_adj = 128; + 2'b10: stack_adj = 144; + 2'b11: stack_adj = 160; + endcase + end + endcase + end + + //Take 2's compliment in case of PUSH instruction + if(zcmp_instr_type == PUSH) begin + itype_inst.imm = ~stack_adj + 1'b1; + end else begin + itype_inst.imm = stack_adj - 4; + end + end else begin + illegal_instr_o = illegal_instr_i; + end + + unique case(state_q) + IDLE: begin + if (is_push_pop_instr_i) begin + reg_numbers_d = reg_numbers; + state_d = INIT; + case (zcmp_instr_type) + PUSH: begin + offset_d = 12'hFFC; + end + POP,POPRETZ,POPRET: begin + offset_d = itype_inst.imm; + case (zcmp_instr_type) + POPRETZ: begin + popretz_inst_d = 3; + end + POPRET: begin + popretz_inst_d = 1; + end + default: begin + popretz_inst_d = 0; + end + endcase + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + // when rlist is 4, max reg is x18 i.e. 14(const) + 4 + // when rlist is 12, max reg is x27 i.e. 15(const) + 12 + if(reg_numbers == 12) begin + store_reg_d = 15 + reg_numbers; + end else begin + store_reg_d = 14 + reg_numbers; + end + end + end + INIT: begin + if(is_push_pop_instr_i && zcmp_instr_type == PUSH) begin + state_d = PUSH_POP_INSTR_1; + fetch_stall = 1; // stall inst fetch + + if (reg_numbers_q == 1) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],5'h1,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; + end else begin + instr_o = {offset_d[11:5],5'h1,5'h2,3'h2,offset_d[4:0],riscv::OpcodeStore}; + end + state_d = PUSH_ADDI; + end + + if (reg_numbers_q == 2) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],5'h8,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; + end else begin + instr_o = {offset_d[11:5],5'h8,5'h2,3'h2,offset_d[4:0],riscv::OpcodeStore}; + end + reg_numbers_d = reg_numbers_q -1; + offset_d = offset_q + 12'hFFC; // decrement offset by -4 i.e. add 2's compilment of 4 + end + + if (reg_numbers_q == 3) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],5'h9,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; + end else begin + instr_o = {offset_d[11:5],5'h9,5'h2,3'h2,offset_d[4:0],riscv::OpcodeStore}; + end + reg_numbers_d = reg_numbers_q -1; + offset_d = offset_q + 12'hFFC; + end + + if (reg_numbers_q >= 4 && reg_numbers_q <= 27) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],store_reg_q,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; + end else begin + instr_o = {offset_d[11:5],store_reg_q,5'h2,3'h2,offset_d[4:0],riscv::OpcodeStore}; + end + reg_numbers_d = reg_numbers_q - 1; + store_reg_d = store_reg_q - 1; + offset_d = offset_q + 12'hFFC; + if (reg_numbers_q == 26) begin + state_d = PUSH_POP_INSTR_2; + end + end + end + + if (is_push_pop_instr_i && (zcmp_instr_type == POP || zcmp_instr_type == POPRETZ || zcmp_instr_type == POPRET)) begin + state_d = PUSH_POP_INSTR_1; + fetch_stall = 1; // stall inst fetch + if (reg_numbers_q == 1) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],5'h1,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; + end else begin + instr_o = {offset_d[11:0],5'h2,3'h2, 5'h1,riscv::OpcodeLoad}; + end + unique case (zcmp_instr_type) + PUSH,POP,POPRET: begin + state_d = PUSH_ADDI; + end + POPRETZ: begin + state_d = POPRETZ_1; + end + endcase + end + + if (reg_numbers_q == 2) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],5'h8,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; + end else begin + instr_o = {offset_d[11:0],5'h2,3'h3, 5'h8,riscv::OpcodeLoad}; + end + reg_numbers_d = reg_numbers_q -1; + offset_d = offset_q + 12'hFFC; // decrement offset by -4 i.e. add 2's compilment of 4 + end + + if (reg_numbers_q == 3) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],5'h9,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; + end else begin + instr_o = {offset_d[11:0],5'h2,3'h3, 5'h9,riscv::OpcodeLoad}; + end + reg_numbers_d = reg_numbers_q -1; + offset_d = offset_q + 12'hFFC; + end + + if (reg_numbers_q >= 4 && reg_numbers_q <= 27) begin + if (riscv::XLEN == 64) begin + instr_o = {offset_d[11:5],store_reg_q,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; + end else begin + instr_o = {offset_d[11:0],5'h2,3'h2,store_reg_q,riscv::OpcodeLoad}; + end + reg_numbers_d = reg_numbers_q - 1; + store_reg_d = store_reg_q - 1; + offset_d = offset_q + 12'hFFC; + if (reg_numbers_q == 26) begin + state_d = PUSH_POP_INSTR_2; + end + end + end + + if (is_push_pop_instr_i && zcmp_instr_type == MVSA01) begin + fetch_stall = 1; + instr_o = {12'h0,5'hA, 3'h0,xreg1,riscv::OpcodeOpImm}; + state_d = MOVE; + end + + if (is_push_pop_instr_i && zcmp_instr_type == MVA01S) begin + fetch_stall = 1; + instr_o = {12'h0,xreg1, 3'h0,5'hA,riscv::OpcodeOpImm}; + state_d = MOVE; + end + end + + PUSH_POP_INSTR_1:begin + if (reg_numbers_q == 1) begin + if (riscv::XLEN == 64) begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5],5'h1,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h3, 5'h1,riscv::OpcodeLoad}; + end + endcase + end else begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], 5'h1, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h2, 5'h1,riscv::OpcodeLoad}; + end + endcase + end + unique case (zcmp_instr_type) + PUSH,POP,POPRET: begin + state_d = PUSH_ADDI; + end + POPRETZ: begin + state_d = POPRETZ_1; + end + endcase + end + if (reg_numbers_q == 2) begin + if (riscv::XLEN == 64) begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], 5'h8, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h3, 5'h8,riscv::OpcodeLoad}; + end + endcase + end else begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], 5'h8, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ, POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h2, 5'h8,riscv::OpcodeLoad}; + end + endcase + end + reg_numbers_d = reg_numbers_q -1; + offset_d = offset_q + 12'hFFC; // decrement offset by -4 i.e. add 2's compilment of 4 + end + if (reg_numbers_q == 3) begin + if (riscv::XLEN == 64) begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], 5'h9, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h3, 5'h9,riscv::OpcodeLoad}; + end + endcase + end else begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], 5'h9, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h2, 5'h9,riscv::OpcodeLoad}; + end + endcase + end + reg_numbers_d = reg_numbers_q -1; + offset_d = offset_q + 12'hFFC; + end + if (reg_numbers_q >= 4 && reg_numbers_q <= 27) begin + if (riscv::XLEN == 64) begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], store_reg_q, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h3,store_reg_q,riscv::OpcodeLoad}; + end + endcase + end else begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], store_reg_q,5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h2,store_reg_q,riscv::OpcodeLoad}; + end + endcase + end + reg_numbers_d = reg_numbers_q - 1; + store_reg_d = store_reg_d - 1; + offset_d = offset_d + 12'hFFC; + if (reg_numbers_q == 26) begin + state_d = PUSH_POP_INSTR_2; + end + end + end + + MOVE: begin + case (zcmp_instr_type) + MVSA01: begin + instr_o = {12'h0,5'hB, 3'h0,xreg2,riscv::OpcodeOpImm}; + end + MVA01S: begin + instr_o = {12'h0,xreg2, 3'h0,5'hB,riscv::OpcodeOpImm}; + end + endcase + fetch_stall = 0; + state_d = IDLE; + end + + PUSH_ADDI:begin + if (zcmp_instr_type == PUSH) begin + instr_o = {itype_inst.imm,5'h2, 3'h0,5'h2,riscv::OpcodeOpImm}; + end else begin + instr_o = {stack_adj,5'h2, 3'h0,5'h2,riscv::OpcodeOpImm}; + end + if (zcmp_instr_type == POPRETZ || zcmp_instr_type == POPRET) begin + state_d = POPRETZ_1; + end else begin + state_d = IDLE; + fetch_stall = 0; + end + end + + PUSH_POP_INSTR_2:begin + if (riscv::XLEN == 64) begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], store_reg_q, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h3, store_reg_q,riscv::OpcodeLoad}; + end + endcase + end else begin + case(zcmp_instr_type) + PUSH: begin + instr_o = {offset_d[11:5], store_reg_q, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; + end + POP,POPRETZ,POPRET: begin + instr_o = {offset_d[11:0],5'h2,3'h2,store_reg_q,riscv::OpcodeLoad}; + end + endcase + end + offset_d = offset_d + 12'hFFC; + state_d = PUSH_POP_INSTR_1; + end + + POPRETZ_1: begin + unique case (popretz_inst_q) + 2'b11: begin + instr_o = {20'h0,5'hA,riscv::OpcodeLui}; //lui a0, 0x0 + popretz_inst_d = popretz_inst_d - 1; + end + 2'b10: begin + instr_o = {12'h0,5'hA, 3'h0,5'hA,riscv::OpcodeOpImm}; //addi a0, a0, 0x0 + popretz_inst_d = popretz_inst_d - 1; + state_d = PUSH_ADDI; + end + 2'b01: begin + instr_o = {12'h0,5'h1,3'h0,5'h0,riscv::OpcodeJalr}; //ret - jalr x0, x1, 0 + state_d = IDLE; + fetch_stall = 0; + popretz_inst_d = popretz_inst_d - 1; + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + default: begin + state_d = IDLE; + end + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + state_q <= IDLE; + offset_q <= '0; + popretz_inst_q <= '0; + reg_numbers_q <= '0; + store_reg_q <= '0; + end else begin + state_q <= state_d; + offset_q <= offset_d; + reg_numbers_q <= reg_numbers_d; + store_reg_q <= store_reg_d; + popretz_inst_q <= popretz_inst_d; + end + end +endmodule From 237d62f23fc1764273759992deccaa711db1f30b Mon Sep 17 00:00:00 2001 From: gullahmed1 Date: Tue, 16 Jan 2024 15:58:56 +0500 Subject: [PATCH 2/2] Add Zcmp support v2 --- core/compressed_decoder.sv | 8 +- core/id_stage.sv | 6 -- core/zcmp_decoder.sv | 200 ++++++++++--------------------------- 3 files changed, 56 insertions(+), 158 deletions(-) diff --git a/core/compressed_decoder.sv b/core/compressed_decoder.sv index 02b2edb6c6..14ff0fd859 100644 --- a/core/compressed_decoder.sv +++ b/core/compressed_decoder.sv @@ -850,11 +850,10 @@ module compressed_decoder #( end riscv::OpcodeC2Fsdsp: begin - if (CVA6Cfg.FpPresent) begin - if (instr_i[12:10] == 3'b110 || instr_i[12:10] == 3'b111 || instr_i[12:10] == 3'b011) begin //is a push/pop instruction + if (instr_i[12:10] == 3'b110 || instr_i[12:10] == 3'b111 || instr_i[12:10] == 3'b011) begin //is a push/pop instruction is_push_pop_instr_o = 1; instr_o = instr_i; - end else begin + end else if (CVA6Cfg.FpPresent) begin // c.fsdsp -> fsd rs2, imm(x2) instr_o = { 3'b0, @@ -867,8 +866,7 @@ module compressed_decoder #( 3'b000, riscv::OpcodeStoreFp }; - end - end else begin + end else begin illegal_instr_o = 1'b1; end end diff --git a/core/id_stage.sv b/core/id_stage.sv index 6c86692b41..0b9bc8c561 100644 --- a/core/id_stage.sv +++ b/core/id_stage.sv @@ -75,7 +75,6 @@ module id_stage #( .is_compressed_o(is_compressed), .is_push_pop_instr_o(is_push_pop) ); - /*if (CVA6Cfg.CVA6ConfigZcmpExtEn) begin*/ //sequencial decoder zcmp_decoder #( .CVA6Cfg(CVA6Cfg) @@ -91,11 +90,6 @@ module id_stage #( .is_compressed_o (is_compressed_cmp), .fetch_stall (stall_instr_fetch) ); - /*end else begin - instruction = compressed_instr; - is_compressed_cmp = is_compressed; - is_illegal_cmp = is_illegal; - end*/ end else begin assign instruction = fetch_entry_i.instruction; assign is_illegal = '0; diff --git a/core/zcmp_decoder.sv b/core/zcmp_decoder.sv index ab6fce43a1..aefc0621ec 100644 --- a/core/zcmp_decoder.sv +++ b/core/zcmp_decoder.sv @@ -1,4 +1,4 @@ -module zcmp_decoder #( +module zcmp_decoder #( parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty) ( input logic [31:0] instr_i, @@ -15,7 +15,7 @@ module zcmp_decoder #( // FSM States enum logic [2:0] { - IDLE, PUSH_POP_INSTR_1, PUSH_ADDI, PUSH_POP_INSTR_2, POPRETZ_1, MOVE, INIT + IDLE, INIT, PUSH_ADDI, POPRETZ_1, MOVE, PUSH_POP_INSTR_2 } state_d, state_q; // Instruction Types @@ -41,7 +41,7 @@ module zcmp_decoder #( always_comb begin illegal_instr_o = 1'b0; - fetch_stall = is_push_pop_instr_i ? 1'b1 : 1'b0; + fetch_stall = 1'b0; instr_o = instr_i; is_compressed_o = is_push_pop_instr_i ? 1'b1 : is_compressed_i; reg_numbers = '0; @@ -116,18 +116,18 @@ module zcmp_decoder #( // push/pop/popret/popretz instructions unique case (instr_i[7:4]) - 4'b0100: reg_numbers = 1; // 4 - 4'b0101: reg_numbers = 2; // 5 - 4'b0110: reg_numbers = 3; // 6 - 4'b0111: reg_numbers = 4; // 7 - 4'b1000: reg_numbers = 5; // 8 - 4'b1001: reg_numbers = 6; // 9 - 4'b1010: reg_numbers = 7; // 10 - 4'b1011: reg_numbers = 8; // 11 - 4'b1100: reg_numbers = 9; // 12 - 4'b1101: reg_numbers = 10; // 13 - 4'b1110: reg_numbers = 11; // 14 - 4'b1111: reg_numbers = 12; // 15 + 4'b0100: reg_numbers = 4'b0001; // 4 + 4'b0101: reg_numbers = 4'b0010; // 5 + 4'b0110: reg_numbers = 4'b0011; // 6 + 4'b0111: reg_numbers = 4'b0100; // 7 + 4'b1000: reg_numbers = 4'b0101; // 8 + 4'b1001: reg_numbers = 4'b0110; // 9 + 4'b1010: reg_numbers = 4'b0111; // 10 + 4'b1011: reg_numbers = 4'b1000; // 11 + 4'b1100: reg_numbers = 4'b1001; // 12 + 4'b1101: reg_numbers = 4'b1010; // 13 + 4'b1110: reg_numbers = 4'b1011; // 14 + 4'b1111: reg_numbers = 4'b1100; // 15 default: illegal_instr_o = 1'b1; endcase @@ -232,7 +232,7 @@ module zcmp_decoder #( if(zcmp_instr_type == PUSH) begin itype_inst.imm = ~stack_adj + 1'b1; end else begin - itype_inst.imm = stack_adj - 4; + itype_inst.imm = stack_adj - 3'b100; end end else begin illegal_instr_o = illegal_instr_i; @@ -251,13 +251,13 @@ module zcmp_decoder #( offset_d = itype_inst.imm; case (zcmp_instr_type) POPRETZ: begin - popretz_inst_d = 3; + popretz_inst_d = 2'b11; end POPRET: begin - popretz_inst_d = 1; + popretz_inst_d = 2'b01; end default: begin - popretz_inst_d = 0; + popretz_inst_d = 'b0; end endcase end @@ -267,19 +267,19 @@ module zcmp_decoder #( endcase // when rlist is 4, max reg is x18 i.e. 14(const) + 4 // when rlist is 12, max reg is x27 i.e. 15(const) + 12 - if(reg_numbers == 12) begin - store_reg_d = 15 + reg_numbers; + if(reg_numbers == 4'b1100) begin + store_reg_d = 4'b1111 + reg_numbers; end else begin - store_reg_d = 14 + reg_numbers; + store_reg_d = 4'b1110 + reg_numbers; end end end INIT: begin if(is_push_pop_instr_i && zcmp_instr_type == PUSH) begin - state_d = PUSH_POP_INSTR_1; - fetch_stall = 1; // stall inst fetch + // state_d = PUSH_POP_INSTR_1; + fetch_stall = 1'b1; // stall inst fetch - if (reg_numbers_q == 1) begin + if (reg_numbers_q == 4'b0001) begin if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],5'h1,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; end else begin @@ -288,7 +288,7 @@ module zcmp_decoder #( state_d = PUSH_ADDI; end - if (reg_numbers_q == 2) begin + if (reg_numbers_q == 4'b0010) begin if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],5'h8,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; end else begin @@ -298,7 +298,7 @@ module zcmp_decoder #( offset_d = offset_q + 12'hFFC; // decrement offset by -4 i.e. add 2's compilment of 4 end - if (reg_numbers_q == 3) begin + if (reg_numbers_q == 4'b0011) begin if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],5'h9,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; end else begin @@ -308,23 +308,23 @@ module zcmp_decoder #( offset_d = offset_q + 12'hFFC; end - if (reg_numbers_q >= 4 && reg_numbers_q <= 27) begin + if (reg_numbers_q >= 4 && reg_numbers_q <= 12) begin if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],store_reg_q,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; end else begin - instr_o = {offset_d[11:5],store_reg_q,5'h2,3'h2,offset_d[4:0],riscv::OpcodeStore}; + instr_o = {offset_d[11:5], store_reg_q, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; end reg_numbers_d = reg_numbers_q - 1; store_reg_d = store_reg_q - 1; offset_d = offset_q + 12'hFFC; - if (reg_numbers_q == 26) begin - state_d = PUSH_POP_INSTR_2; - end + if (reg_numbers_q == 12) begin + state_d = PUSH_POP_INSTR_2; + end end end if (is_push_pop_instr_i && (zcmp_instr_type == POP || zcmp_instr_type == POPRETZ || zcmp_instr_type == POPRET)) begin - state_d = PUSH_POP_INSTR_1; + // state_d = PUSH_POP_INSTR_1; fetch_stall = 1; // stall inst fetch if (reg_numbers_q == 1) begin if (riscv::XLEN == 64) begin @@ -339,6 +339,9 @@ module zcmp_decoder #( POPRETZ: begin state_d = POPRETZ_1; end + default: begin + state_d = state_q; + end endcase end @@ -346,7 +349,7 @@ module zcmp_decoder #( if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],5'h8,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; end else begin - instr_o = {offset_d[11:0],5'h2,3'h3, 5'h8,riscv::OpcodeLoad}; + instr_o = {offset_d[11:0],5'h2,3'h2, 5'h8,riscv::OpcodeLoad}; end reg_numbers_d = reg_numbers_q -1; offset_d = offset_q + 12'hFFC; // decrement offset by -4 i.e. add 2's compilment of 4 @@ -356,13 +359,13 @@ module zcmp_decoder #( if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],5'h9,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; end else begin - instr_o = {offset_d[11:0],5'h2,3'h3, 5'h9,riscv::OpcodeLoad}; + instr_o = {offset_d[11:0],5'h2,3'h2, 5'h9,riscv::OpcodeLoad}; end reg_numbers_d = reg_numbers_q -1; offset_d = offset_q + 12'hFFC; end - if (reg_numbers_q >= 4 && reg_numbers_q <= 27) begin + if (reg_numbers_q >= 4 && reg_numbers_q <= 12) begin if (riscv::XLEN == 64) begin instr_o = {offset_d[11:5],store_reg_q,5'h2,3'h3,offset_d[4:0],riscv::OpcodeLoad}; end else begin @@ -371,9 +374,9 @@ module zcmp_decoder #( reg_numbers_d = reg_numbers_q - 1; store_reg_d = store_reg_q - 1; offset_d = offset_q + 12'hFFC; - if (reg_numbers_q == 26) begin - state_d = PUSH_POP_INSTR_2; - end + if (reg_numbers_q == 12) begin + state_d = PUSH_POP_INSTR_2; + end end end @@ -390,111 +393,6 @@ module zcmp_decoder #( end end - PUSH_POP_INSTR_1:begin - if (reg_numbers_q == 1) begin - if (riscv::XLEN == 64) begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5],5'h1,5'h2,3'h3,offset_d[4:0],riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h3, 5'h1,riscv::OpcodeLoad}; - end - endcase - end else begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], 5'h1, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h2, 5'h1,riscv::OpcodeLoad}; - end - endcase - end - unique case (zcmp_instr_type) - PUSH,POP,POPRET: begin - state_d = PUSH_ADDI; - end - POPRETZ: begin - state_d = POPRETZ_1; - end - endcase - end - if (reg_numbers_q == 2) begin - if (riscv::XLEN == 64) begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], 5'h8, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h3, 5'h8,riscv::OpcodeLoad}; - end - endcase - end else begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], 5'h8, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ, POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h2, 5'h8,riscv::OpcodeLoad}; - end - endcase - end - reg_numbers_d = reg_numbers_q -1; - offset_d = offset_q + 12'hFFC; // decrement offset by -4 i.e. add 2's compilment of 4 - end - if (reg_numbers_q == 3) begin - if (riscv::XLEN == 64) begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], 5'h9, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h3, 5'h9,riscv::OpcodeLoad}; - end - endcase - end else begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], 5'h9, 5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h2, 5'h9,riscv::OpcodeLoad}; - end - endcase - end - reg_numbers_d = reg_numbers_q -1; - offset_d = offset_q + 12'hFFC; - end - if (reg_numbers_q >= 4 && reg_numbers_q <= 27) begin - if (riscv::XLEN == 64) begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], store_reg_q, 5'h2, 3'h3, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h3,store_reg_q,riscv::OpcodeLoad}; - end - endcase - end else begin - case(zcmp_instr_type) - PUSH: begin - instr_o = {offset_d[11:5], store_reg_q,5'h2, 3'h2, offset_d[4:0], riscv::OpcodeStore}; - end - POP,POPRETZ,POPRET: begin - instr_o = {offset_d[11:0],5'h2,3'h2,store_reg_q,riscv::OpcodeLoad}; - end - endcase - end - reg_numbers_d = reg_numbers_q - 1; - store_reg_d = store_reg_d - 1; - offset_d = offset_d + 12'hFFC; - if (reg_numbers_q == 26) begin - state_d = PUSH_POP_INSTR_2; - end - end - end - MOVE: begin case (zcmp_instr_type) MVSA01: begin @@ -503,6 +401,9 @@ module zcmp_decoder #( MVA01S: begin instr_o = {12'h0,xreg2, 3'h0,5'hB,riscv::OpcodeOpImm}; end + default: begin + illegal_instr_o = 1'b1; + end endcase fetch_stall = 0; state_d = IDLE; @@ -540,10 +441,14 @@ module zcmp_decoder #( POP,POPRETZ,POPRET: begin instr_o = {offset_d[11:0],5'h2,3'h2,store_reg_q,riscv::OpcodeLoad}; end + default: begin + illegal_instr_o = 1'b1; + end endcase end - offset_d = offset_d + 12'hFFC; - state_d = PUSH_POP_INSTR_1; + offset_d = offset_q + 12'hFFC; + store_reg_d = store_reg_q - 1; + state_d = INIT; end POPRETZ_1: begin @@ -568,6 +473,7 @@ module zcmp_decoder #( end endcase end + default: begin state_d = IDLE; end @@ -589,4 +495,4 @@ module zcmp_decoder #( popretz_inst_q <= popretz_inst_d; end end -endmodule +endmodule \ No newline at end of file