From 88fb2adac30f6efa2805c8b3e3b3fa1b5619e7c3 Mon Sep 17 00:00:00 2001 From: Sven Stucki Date: Wed, 30 Sep 2015 18:23:42 +0200 Subject: [PATCH] Add many ALU instructions from OR10N --- alu.sv | 20 +++-- decoder.sv | 220 +++++++-------------------------------------- include/defines.sv | 2 + 3 files changed, 46 insertions(+), 196 deletions(-) diff --git a/alu.sv b/alu.sv index 1aebea0d..2fdd9241 100644 --- a/alu.sv +++ b/alu.sv @@ -284,13 +284,14 @@ module alu cmp_sign_mode[3:0] = 4'b0000; // unsigned mode // signed mode - if ((operator_i == `ALU_GTS) || - (operator_i == `ALU_GES) || - (operator_i == `ALU_LTS) || - (operator_i == `ALU_SLTS) || - (operator_i == `ALU_LES) || - (operator_i == `ALU_MAX) || - (operator_i == `ALU_MIN) || + if ((operator_i == `ALU_GTS) || + (operator_i == `ALU_GES) || + (operator_i == `ALU_LTS) || + (operator_i == `ALU_SLTS) || + (operator_i == `ALU_SLETS) || + (operator_i == `ALU_LES) || + (operator_i == `ALU_MAX) || + (operator_i == `ALU_MIN) || (operator_i == `ALU_ABS)) begin case (vector_mode_i) @@ -356,6 +357,8 @@ module alu `ALU_GES, `ALU_GEU: cmp_result = is_greater | is_equal; `ALU_LTS, `ALU_SLTS, `ALU_LTU, `ALU_SLTU: cmp_result = ~(is_greater | is_equal); + `ALU_SLETS, + `ALU_SLETU, `ALU_LES, `ALU_LEU: cmp_result = ~is_greater; default:; // nothing to do endcase //~case(operator_i) @@ -590,6 +593,9 @@ module alu // Set Lower Than Operations (result = 1, if a < b) `ALU_SLTS, `ALU_SLTU: result_o = {31'b0, cmp_result[0]}; + // Set Lower Equal Than Operations (result = 1, if a <= b) + `ALU_SLETS, `ALU_SLETU: result_o = {31'b0, cmp_result[0]}; + `ALU_FF1: result_o = {26'h0, ff1_result}; `ALU_FL1: result_o = {26'h0, fl1_result}; `ALU_CLB: result_o = {26'h0, clb_result}; diff --git a/decoder.sv b/decoder.sv index c0817a90..b7f7e337 100644 --- a/decoder.sv +++ b/decoder.sv @@ -414,23 +414,49 @@ module riscv_decoder rega_used_o = 1'b1; regb_used_o = 1'b1; + if (instr_rdata_i[28]) + regb_used_o = 1'b0; + unique case ({instr_rdata_i[31:25], instr_rdata_i[14:12]}) + // RV32I ALU operations {7'b000_0000, 3'b000}: alu_operator = `ALU_ADD; // Add {7'b010_0000, 3'b000}: alu_operator = `ALU_SUB; // Sub - {7'b000_0000, 3'b010}: alu_operator = `ALU_SLTS; // Set Lower Than {7'b000_0000, 3'b011}: alu_operator = `ALU_SLTU; // Set Lower Than Unsigned - {7'b000_0000, 3'b100}: alu_operator = `ALU_XOR; // Xor {7'b000_0000, 3'b110}: alu_operator = `ALU_OR; // Or {7'b000_0000, 3'b111}: alu_operator = `ALU_AND; // And - {7'b000_0000, 3'b001}: alu_operator = `ALU_SLL; // Shift Left Logical {7'b000_0000, 3'b101}: alu_operator = `ALU_SRL; // Shift Right Logical {7'b010_0000, 3'b101}: alu_operator = `ALU_SRA; // Shift Right Arithmetic + // supported RV32M instructions {7'b000_0001, 3'b000}: mult_en = 1'b1; // Multiplication + // PULP specific instructions + {7'b000_0010, 3'b000}: alu_operator = `ALU_AVG; // Average + {7'b000_0010, 3'b001}: alu_operator = `ALU_AVGU; // Average Unsigned + {7'b000_0010, 3'b010}: alu_operator = `ALU_SLETS; // Set Lower Equal Than + {7'b000_0010, 3'b011}: alu_operator = `ALU_SLETU; // Set Lower Equal Than Unsigned + {7'b000_0010, 3'b100}: alu_operator = `ALU_MIN; // Min + {7'b000_0010, 3'b101}: alu_operator = `ALU_MINU; // Min Unsigned + {7'b000_0010, 3'b110}: alu_operator = `ALU_MAX; // Max + {7'b000_0010, 3'b111}: alu_operator = `ALU_MAXU; // Max Unsigned + + {7'b000_0100, 3'b101}: alu_operator = `ALU_ROR; // Rotate Right + + // PULP specific instructions using only one source register + {7'b000_1000, 3'b000}: alu_operator = `ALU_FF1; // Find First 1 + {7'b000_1000, 3'b001}: alu_operator = `ALU_FL1; // Find Last 1 + {7'b000_1000, 3'b010}: alu_operator = `ALU_CLB; // Count Leading Bits + {7'b000_1000, 3'b011}: alu_operator = `ALU_CNT; // Count set bits (popcount) + {7'b000_1000, 3'b100}: alu_operator = `ALU_EXTHS; // Sign-extend Half-word + {7'b000_1000, 3'b101}: alu_operator = `ALU_EXTHZ; // Zero-extend Half-word + {7'b000_1000, 3'b110}: alu_operator = `ALU_EXTBS; // Sign-extend Byte + {7'b000_1000, 3'b111}: alu_operator = `ALU_EXTBZ; // Zero-extend Byte + + {7'b000_1010, 3'b000}: alu_operator = `ALU_ABS; // Absolute + default: begin regfile_alu_we = 1'b0; illegal_insn_o = 1'b1; @@ -438,18 +464,14 @@ module riscv_decoder endcase end - `OPCODE_PULP_OP: begin // PULP specific ALU instructions - mult_en = 1'b1; - mult_mac_en = 1'b1; - + `OPCODE_PULP_OP: begin // PULP specific ALU instructions with three source operands regfile_alu_we = 1'b1; rega_used_o = 1'b1; regb_used_o = 1'b1; + regc_used_o = 1'b1; case (instr_rdata_i[14:12]) 3'b000: begin // MAC - regc_used_o = 1'b1; - mult_en = 1'b1; mult_mac_en = 1'b1; end @@ -458,8 +480,6 @@ module riscv_decoder 3'b101, 3'b110, 3'b111: begin // MAC with subword selection - regc_used_o = 1'b1; - vector_mode_o = `VEC_MODE216; mult_sel_subword_o = instr_rdata_i[13:12]; mult_signed_mode_o = instr_rdata_i[31:30]; @@ -475,184 +495,6 @@ module riscv_decoder endcase end - /* - - `OPCODE_ALU: begin // Arithmetic Operation - rega_used_o = 1'b1; - regb_used_o = 1'b1; - - case (instr_rdata_i[9:8]) - 2'b00: begin // ALU Operation - regfile_alu_we = 1'b1; - - casex (instr_rdata_i[3:0]) - 4'b110X: begin // l.ext{b,h,w}{s,z} - alu_operator = {3'b010, instr_rdata_i[7:6], instr_rdata_i[0]}; - regb_used_o = 1'b0; // register b is not used - end - 4'b1111: begin // l.ff1 - alu_operator = `ALU_FF1; - end - endcase // casex (instr_rdata_i[3:2]) - end - - 2'b01: begin // l.fl1, l.clb, l.cnt - regfile_alu_we = 1'b1; - regb_used_o = 1'b0; - - case (instr_rdata_i[3:0]) - 4'b1101: alu_operator = `ALU_CNT; - 4'b1110: alu_operator = `ALU_CLB; - 4'b1111: alu_operator = `ALU_FL1; - - default: begin - // synopsys translate_off - $display("%t: Illegal ALU instruction received.", $time); - // synopsys translate_on - regfile_alu_we = 1'b0; // disable Write Enable for illegal instruction - illegal_insn_o = 1'b1; - end - endcase //~case(instr_rdata_i[3:0]) - end - - 2'b10: begin // Min, Max, Abs, Avg - regfile_alu_we = 1'b1; - - case (instr_rdata_i[3:0]) - 4'b0000: alu_operator = `ALU_MIN; - 4'b0001: alu_operator = `ALU_MINU; - 4'b0010: alu_operator = `ALU_MAX; - 4'b0011: alu_operator = `ALU_MAXU; - 4'b0100: alu_operator = `ALU_AVG; - 4'b0101: alu_operator = `ALU_AVGU; - - 4'b1000: begin - regb_used_o = 1'b0; - alu_operator = `ALU_ABS; - end - - default: begin - // synopsys translate_off - $display("%t: Illegal ALU instruction received.", $time); - // synopsys translate_on - regfile_alu_we = 1'b0; // disable Write Enable for illegal instruction - illegal_insn_o = 1'b1; - end - endcase //~case(instr_rdata_i[3:0]) - end - endcase; // case (instr_rdata_i[9:8]) - end - - `OPCODE_VEC: begin // vectorial alu operations - rega_used_o = 1'b1; - regfile_alu_we = 1'b1; - - if (instr_rdata_i[0] == 1'b0) // choose vector size - vector_mode_o = `VEC_MODE16; - else - vector_mode_o = `VEC_MODE8; - - if ((instr_rdata_i[7:6] == 2'b01) || (instr_rdata_i[7:6] == 2'b10)) // replicate scalar 2 or 4 times - scalar_replication_o = 1'b1; - - if (instr_rdata_i[7:6] == 2'b10) // use immediate as operand b - begin - alu_op_b_mux_sel_o = `OP_B_IMM; - immediate_mux_sel_o = `IMM_VEC; - end - else - regb_used_o = 1'b1; - - // now decode the sub opcodes - case (instr_rdata_i[5:1]) - 5'b00000: alu_operator = `ALU_ADD; - 5'b00001: alu_operator = `ALU_SUB; - 5'b00010: alu_operator = `ALU_AVG; - 5'b00011: alu_operator = `ALU_MIN; - 5'b00100: alu_operator = `ALU_MAX; - 5'b00101: alu_operator = `ALU_SRL; - 5'b00110: alu_operator = `ALU_SRA; - 5'b00111: alu_operator = `ALU_SLL; - - 5'b01000: begin // lv32.mul - regfile_alu_waddr_sel_o = 2'b01; - mult_is_running = 1'b1; - end - - 5'b01001: alu_operator = `ALU_OR; - 5'b01010: alu_operator = `ALU_XOR; - 5'b01011: alu_operator = `ALU_AND; - - 5'b01100: begin // lv32.ins - alu_operator = `ALU_INS; - scalar_replication_o = 1'b1; - end - - 5'b10000: begin // lv32.abs - regb_used_o = 1'b0; // abs does not use operand b - alu_operator = `ALU_ABS; - end - - 5'b10001: begin // lv32.ext - regb_used_o = 1'b0; - alu_operator = `ALU_EXT; - end - - default: begin // unknown instruction encountered - regfile_alu_we = 1'b0; - illegal_insn_o = 1'b1; - // synopsys translate_off - $display("%t: Unknown vector opcode 0x%h.", $time, instr_rdata_i[5:1]); - // synopsys translate_on - end - endcase // instr_rdata[5:1] - end - - `OPCODE_VCMP: begin // Vectorial comparisons, i.e. lv32.cmp_*, lv32.all_*, lv32.any_* - rega_used_o = 1'b1; - regfile_alu_we = 1'b1; - - if (instr_rdata_i[0] == 1'b0) // choose vector size - vector_mode_o = `VEC_MODE16; - else - vector_mode_o = `VEC_MODE8; - - if ((instr_rdata_i[7:6] == 2'b01) || (instr_rdata_i[7:6] == 2'b10)) // replicate scalar 2 or 4 times - scalar_replication_o = 1'b1; - - if (instr_rdata_i[7:6] == 2'b10) // use immediate as operand b - begin - alu_op_b_mux_sel_o = `OP_B_IMM; - immediate_mux_sel_o = `IMM_VEC; - end - else - regb_used_o = 1'b1; - - // now decode the sub opcodes for the ALU - case (instr_rdata_i[3:1]) - 3'b000: alu_operator = `ALU_EQ; - 3'b001: alu_operator = `ALU_NE; - 3'b010: alu_operator = `ALU_GTS; - 3'b011: alu_operator = `ALU_GES; - 3'b100: alu_operator = `ALU_LTS; - 3'b101: alu_operator = `ALU_LES; - - default: begin // unknown instruction encountered - illegal_insn_o = 1'b1; - // synopsys translate_off - $display("%t: Unknown vector opcode 0x%h.", $time, instr_rdata_i[5:1]); - // synopsys translate_on - end - endcase //~case(instr_rdata_i[3:1]) - - alu_cmp_mode_o = instr_rdata_i[5:4]; // which kind of comparison do we have here, i.e. full, any, all - - if((instr_rdata_i[5:4] == `ALU_CMP_ANY) || (instr_rdata_i[5:4] == `ALU_CMP_ALL)) - set_flag = 1'b1; // set the flag for lv32.all_* and lv32.any_* - end - - */ - //////////////////////////////////////////////// // ____ ____ _____ ____ ___ _ _ // diff --git a/include/defines.sv b/include/defines.sv index 73ed418c..d8ac9e68 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -208,6 +208,8 @@ endfunction // prettyPrintInstruction // Set Lower Than Operations `define ALU_SLTS 6'b0011_00 `define ALU_SLTU 6'b0011_01 +`define ALU_SLETS 6'b0011_10 +`define ALU_SLETU 6'b0011_11 // Extension Operations `define ALU_EXTHS 6'b010_000 `define ALU_EXTWS 6'b010_001