Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Support for Zba, Zbb, Zbc and Zbs extensions to CVA6 #878

Merged
merged 21 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
M-Ijaz-10x marked this conversation as resolved.
Show resolved Hide resolved
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