Skip to content

Commit

Permalink
Adding Support for Zba, Zbb, Zbc and Zbs extensions to CVA6 (#878)
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Ijaz-10x authored Jul 6, 2022
1 parent 0cfa94b commit c23eed5
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 43 deletions.
127 changes: 118 additions & 9 deletions core/alu.sv
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ module alu import ariane_pkg::*;(
logic [riscv::XLEN:0] operand_b_neg;
logic [riscv::XLEN+1:0] adder_result_ext_o;
logic less; // handles both signed and unsigned forms
logic [31:0] rolw; // Rotate Left Word
logic [31:0] rorw; // Rotate Right Word
logic [31:0] orcbw, rev8w;
logic [$clog2(riscv::XLEN) :0] cpop; // Count Population
logic [$clog2(riscv::XLEN)-1 :0] lz_tz_count; // Count Leading Zeros
logic [4:0] lz_tz_wcount; // Count Leading Zeros Word
logic lz_tz_empty, lz_tz_wempty;

// bit reverse operand_a for left shifts and bit counting
generate
Expand All @@ -49,21 +56,41 @@ module alu import ariane_pkg::*;(
logic adder_z_flag;
logic [riscv::XLEN:0] adder_in_a, adder_in_b;
riscv::xlen_t adder_result;
logic [riscv::XLEN-1:0] operand_a_bitmanip, bit_indx;

always_comb begin
adder_op_b_negate = 1'b0;

unique case (fu_data_i.operator)
// ADDER OPS
EQ, NE,
SUB, SUBW: adder_op_b_negate = 1'b1;

SUB, SUBW,
ANDN, ORN, XNOR: adder_op_b_negate = 1'b1;
default: ;
endcase
end

always_comb begin
operand_a_bitmanip = fu_data_i.operand_a;

if (ariane_pkg::BITMANIP) begin
unique case (fu_data_i.operator)
SH1ADD : operand_a_bitmanip = fu_data_i.operand_a << 1;
SH2ADD : operand_a_bitmanip = fu_data_i.operand_a << 2;
SH3ADD : operand_a_bitmanip = fu_data_i.operand_a << 3;
SH1ADDUW : operand_a_bitmanip = fu_data_i.operand_a[31:0] << 1;
SH2ADDUW : operand_a_bitmanip = fu_data_i.operand_a[31:0] << 2;
SH3ADDUW : operand_a_bitmanip = fu_data_i.operand_a[31:0] << 3;
CTZ : operand_a_bitmanip = operand_a_rev;
CTZW : operand_a_bitmanip = operand_a_rev32;
ADDUW, CPOPW, CLZW : operand_a_bitmanip = fu_data_i.operand_a[31:0];
default : ;
endcase
end
end

// prepare operand a
assign adder_in_a = {fu_data_i.operand_a, 1'b1};
assign adder_in_a = {operand_a_bitmanip, 1'b1};

// prepare operand b
assign operand_b_neg = {fu_data_i.operand_b, 1'b0} ^ {riscv::XLEN+1{adder_op_b_negate}};
Expand Down Expand Up @@ -152,26 +179,61 @@ module alu import ariane_pkg::*;(

if ((fu_data_i.operator == SLTS) ||
(fu_data_i.operator == LTS) ||
(fu_data_i.operator == GES))
(fu_data_i.operator == GES) ||
(fu_data_i.operator == MAX) ||
(fu_data_i.operator == MIN))
sgn = 1'b1;

less = ($signed({sgn & fu_data_i.operand_a[riscv::XLEN-1], fu_data_i.operand_a}) < $signed({sgn & fu_data_i.operand_b[riscv::XLEN-1], fu_data_i.operand_b}));
end

if (ariane_pkg::BITMANIP) begin : gen_bitmanip
// Count Population + Count population Word

popcount #(
.INPUT_WIDTH(riscv::XLEN)
) i_cpop_count (
.data_i (operand_a_bitmanip),
.popcount_o (cpop)
);

// Count Leading/Trailing Zeros
// 64b
lzc #(
.WIDTH(riscv::XLEN),
.MODE (1)
) i_clz_64b (
.in_i (operand_a_bitmanip),
.cnt_o (lz_tz_count),
.empty_o (lz_tz_empty)
);
//32b
lzc #(
.WIDTH(32),
.MODE (1)
) i_clz_32b (
.in_i (operand_a_bitmanip[31:0]),
.cnt_o (lz_tz_wcount),
.empty_o (lz_tz_wempty)
);
end

// -----------
// Result MUX
// -----------
always_comb begin
result_o = '0;

unique case (fu_data_i.operator)
// Standard Operations
ANDL: result_o = fu_data_i.operand_a & fu_data_i.operand_b;
ORL: result_o = fu_data_i.operand_a | fu_data_i.operand_b;
XORL: result_o = fu_data_i.operand_a ^ fu_data_i.operand_b;
ANDL, ANDN: result_o = fu_data_i.operand_a & operand_b_neg[riscv::XLEN:1];
ORL, ORN : result_o = fu_data_i.operand_a | operand_b_neg[riscv::XLEN:1];
XORL, XNOR: result_o = fu_data_i.operand_a ^ operand_b_neg[riscv::XLEN:1];

// Adder Operations
ADD, SUB: result_o = adder_result;
ADD, SUB,
ADDUW,
SH1ADD, SH2ADD, SH3ADD,
SH1ADDUW, SH2ADDUW, SH3ADDUW: result_o = adder_result;
// Add word: Ignore the upper bits and sign extend to 64 bit
ADDW, SUBW: result_o = {{riscv::XLEN-32{adder_result[31]}}, adder_result[31:0]};
// Shift Operations
Expand All @@ -186,5 +248,52 @@ module alu import ariane_pkg::*;(

default: ; // default case to suppress unique warning
endcase

if (ariane_pkg::BITMANIP) begin
// Index for Bitwise Rotation
bit_indx = 1 << (fu_data_i.operand_b & (riscv::XLEN-1));
orcbw = {{8{|fu_data_i.operand_a[31:24]}}, {8{|fu_data_i.operand_a[23:16]}}, {8{|fu_data_i.operand_a[15:8]}}, {8{|fu_data_i.operand_a[7:0]}}};
rev8w = {{fu_data_i.operand_a[7:0]}, {fu_data_i.operand_a[15:8]}, {fu_data_i.operand_a[23:16]}, {fu_data_i.operand_a[31:24]}};
// rolw, roriw, rorw
rolw = ({{riscv::XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} << fu_data_i.operand_b[4:0]) | ({{riscv::XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} >> (riscv::XLEN-32-fu_data_i.operand_b[4:0]));
rorw = ({{riscv::XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} >> fu_data_i.operand_b[4:0]) | ({{riscv::XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} << (riscv::XLEN-32-fu_data_i.operand_b[4:0]));
unique case (fu_data_i.operator)
// Left Shift 32 bit unsigned
SLLIUW: result_o = {{riscv::XLEN-32{1'b0}}, fu_data_i.operand_a[31:0]} << fu_data_i.operand_b[5:0];
// Integer minimum/maximum
MAX: result_o = less ? fu_data_i.operand_b : fu_data_i.operand_a;
MAXU: result_o = less ? fu_data_i.operand_b : fu_data_i.operand_a;
MIN: result_o = ~less ? fu_data_i.operand_b : fu_data_i.operand_a;
MINU: result_o = ~less ? fu_data_i.operand_b : fu_data_i.operand_a;

// Single bit instructions operations
BCLR, BCLRI: result_o = fu_data_i.operand_a & ~bit_indx;
BEXT, BEXTI: result_o = |(fu_data_i.operand_a & bit_indx);
BINV, BINVI: result_o = fu_data_i.operand_a ^ bit_indx;
BSET, BSETI: result_o = fu_data_i.operand_a | bit_indx;

// Count Leading/Trailing Zeros
CLZ, CTZ : result_o = (lz_tz_empty) ? (lz_tz_count + 1) : lz_tz_count;
CLZW, CTZW: result_o = (lz_tz_wempty) ? 32 : lz_tz_wcount;

// Count population
CPOP, CPOPW: result_o = cpop;

// Sign and Zero Extend
SEXTB: result_o = {{riscv::XLEN-8{fu_data_i.operand_a[7]}}, fu_data_i.operand_a[7:0]};
SEXTH: result_o = {{riscv::XLEN-16{fu_data_i.operand_a[15]}}, fu_data_i.operand_a[15:0]};
ZEXTH: result_o = {{riscv::XLEN-16{1'b0}}, fu_data_i.operand_a[15:0]};

// Bitwise Rotation
ROL: result_o = (riscv::XLEN == 64) ? ((fu_data_i.operand_a << fu_data_i.operand_b[5:0]) | (fu_data_i.operand_a >> (riscv::XLEN-fu_data_i.operand_b[5:0]))) : ((fu_data_i.operand_a << fu_data_i.operand_b[4:0]) | (fu_data_i.operand_a >> (riscv::XLEN-fu_data_i.operand_b[4:0])));
ROLW: result_o = {{riscv::XLEN-32{rolw[31]}}, rolw};
ROR, RORI: result_o = (riscv::XLEN == 64) ? ((fu_data_i.operand_a >> fu_data_i.operand_b[5:0]) | (fu_data_i.operand_a << (riscv::XLEN-fu_data_i.operand_b[5:0]))) : ((fu_data_i.operand_a >> fu_data_i.operand_b[4:0]) | (fu_data_i.operand_a << (riscv::XLEN-fu_data_i.operand_b[4:0])));
RORW, RORIW: result_o = {{riscv::XLEN-32{rorw[31]}}, rorw};
ORCB: result_o = (riscv::XLEN == 64) ? ({{8{|fu_data_i.operand_a[63:56]}}, {8{|fu_data_i.operand_a[55:48]}}, {8{|fu_data_i.operand_a[47:40]}}, {8{|fu_data_i.operand_a[39:32]}}, orcbw}) : orcbw;
REV8: result_o = (riscv::XLEN == 64) ? ({rev8w , {fu_data_i.operand_a[39:32]}, {fu_data_i.operand_a[47:40]}, {fu_data_i.operand_a[55:48]}, {fu_data_i.operand_a[63:56]}}) : rev8w;

default: ; // default case to suppress unique warning
endcase
end
end
endmodule
Loading

0 comments on commit c23eed5

Please sign in to comment.