First pass at implementing bitmanip. Breaks CXXRTL. Ooop
This commit is contained in:
parent
ed6b6a3660
commit
58c20a39d0
|
@ -18,18 +18,26 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
|
|
||||||
module hazard3_alu #(
|
module hazard3_alu #(
|
||||||
parameter W_DATA = 32
|
`include "hazard3_config.vh"
|
||||||
|
,
|
||||||
|
`include "hazard3_width_const.vh"
|
||||||
) (
|
) (
|
||||||
input wire [3:0] aluop,
|
input wire [3:0] aluop,
|
||||||
input wire [W_DATA-1:0] op_a,
|
input wire [W_DATA-1:0] op_a,
|
||||||
input wire [W_DATA-1:0] op_b,
|
input wire [W_DATA-1:0] op_b,
|
||||||
output reg [W_DATA-1:0] result,
|
output reg [W_DATA-1:0] result,
|
||||||
output wire [W_DATA-1:0] result_add, // for load/stores
|
output wire [W_DATA-1:0] result_add,
|
||||||
output wire cmp
|
output wire cmp
|
||||||
);
|
);
|
||||||
|
|
||||||
`include "hazard3_ops.vh"
|
`include "hazard3_ops.vh"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Fiddle around with add/sub, comparisons etc (all related).
|
||||||
|
|
||||||
|
// This adder is exposed directly on the result_add port, since it may be used
|
||||||
|
// for load/store addresses.
|
||||||
|
|
||||||
function msb;
|
function msb;
|
||||||
input [W_DATA-1:0] x;
|
input [W_DATA-1:0] x;
|
||||||
begin
|
begin
|
||||||
|
@ -37,59 +45,168 @@ begin
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
wire sub = aluop != ALUOP_ADD;
|
wire sub = !(aluop == ALUOP_ADD || (|EXTENSION_ZBA && (
|
||||||
wire [W_DATA-1:0] sum = op_a + (op_b ^ {W_DATA{sub}}) + sub;
|
aluop == ALUOP_ADD_SH1 || aluop == ALUOP_ADD_SH2 || aluop == ALUOP_ADD_SH3
|
||||||
|
)));
|
||||||
|
|
||||||
|
wire inv_op_b = sub || (|EXTENSION_ZBB && (
|
||||||
|
aluop == ALUOP_ANDN || aluop == ALUOP_ORN || aluop == ALUOP_XNOR
|
||||||
|
));
|
||||||
|
|
||||||
|
wire [W_DATA-1:0] op_a_shifted =
|
||||||
|
|EXTENSION_ZBA && aluop == ALUOP_ADD_SH1 ? op_a << 1 :
|
||||||
|
|EXTENSION_ZBA && aluop == ALUOP_ADD_SH2 ? op_a << 2 :
|
||||||
|
|EXTENSION_ZBA && aluop == ALUOP_ADD_SH3 ? op_a << 3 : op_a;
|
||||||
|
|
||||||
|
wire [W_DATA-1:0] op_b_inv = op_b ^ {W_DATA{inv_op_b}};
|
||||||
|
|
||||||
|
wire [W_DATA-1:0] sum = op_a_shifted + op_b_inv + sub;
|
||||||
wire [W_DATA-1:0] op_xor = op_a ^ op_b;
|
wire [W_DATA-1:0] op_xor = op_a ^ op_b;
|
||||||
|
|
||||||
|
wire cmp_is_unsigned = aluop == ALUOP_LTU ||
|
||||||
|
|EXTENSION_ZBB && aluop == ALUOP_MAXU ||
|
||||||
|
|EXTENSION_ZBB && aluop == ALUOP_MINU;
|
||||||
|
|
||||||
wire lt = msb(op_a) == msb(op_b) ? msb(sum) :
|
wire lt = msb(op_a) == msb(op_b) ? msb(sum) :
|
||||||
aluop == ALUOP_LTU ? msb(op_b) :
|
cmp_is_unsigned ? msb(op_b) :
|
||||||
msb(op_a) ;
|
msb(op_a) ;
|
||||||
|
|
||||||
assign cmp = aluop == ALUOP_SUB ? |op_xor : lt;
|
assign cmp = aluop == ALUOP_SUB ? |op_xor : lt;
|
||||||
assign result_add = sum;
|
assign result_add = sum;
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Separate units for shift, ctz etc
|
||||||
|
|
||||||
wire [W_DATA-1:0] shift_dout;
|
wire [W_DATA-1:0] shift_dout;
|
||||||
wire shift_right_nleft = aluop == ALUOP_SRL || aluop == ALUOP_SRA;
|
wire shift_right_nleft = aluop == ALUOP_SRL || aluop == ALUOP_SRA ||
|
||||||
|
|EXTENSION_ZBB && aluop == ALUOP_ROR ||
|
||||||
|
|EXTENSION_ZBS && aluop == ALUOP_BEXT;
|
||||||
|
|
||||||
wire shift_arith = aluop == ALUOP_SRA;
|
wire shift_arith = aluop == ALUOP_SRA;
|
||||||
|
wire shift_rotate = |EXTENSION_ZBB & (aluop == ALUOP_ROR || aluop == ALUOP_ROL);
|
||||||
|
|
||||||
hazard3_shift_barrel #(
|
hazard3_shift_barrel #(
|
||||||
.W_DATA(W_DATA),
|
`include "hazard3_config_inst.vh"
|
||||||
.W_SHAMT(5)
|
|
||||||
) shifter (
|
) shifter (
|
||||||
.din(op_a),
|
.din (op_a),
|
||||||
.shamt(op_b[4:0]),
|
.shamt (op_b[4:0]),
|
||||||
.right_nleft(shift_right_nleft),
|
.right_nleft (shift_right_nleft),
|
||||||
.arith(shift_arith),
|
.rotate (shift_rotate),
|
||||||
.dout(shift_dout)
|
.arith (shift_arith),
|
||||||
|
.dout (shift_dout)
|
||||||
);
|
);
|
||||||
|
|
||||||
// We can implement all bitwise ops with 1 LUT4/bit total, since each result bit
|
reg [W_DATA-1:0] op_a_rev;
|
||||||
// uses only two operand bits. Much better than feeding each into main mux tree.
|
always @ (*) begin: rev_op_a
|
||||||
|
integer i;
|
||||||
|
for (i = 0; i < W_DATA; i = i + 1) begin
|
||||||
|
op_a_rev[i] = op_a[W_DATA - 1 - i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// "leading" means starting at MSB. This is an LSB-first priority encoder, so
|
||||||
|
// ""leading" is reversed and "trailing" is not.
|
||||||
|
wire [W_DATA-1:0] ctz_search_mask = aluop == ALUOP_CLZ ? op_a_rev : op_a;
|
||||||
|
wire [W_SHAMT:0] ctz_clz;
|
||||||
|
|
||||||
|
hazard3_priority_encode #(
|
||||||
|
.W_REQ (W_DATA)
|
||||||
|
) ctz_priority_encode (
|
||||||
|
.req (ctz_search_mask),
|
||||||
|
.gnt (ctz_clz[W_SHAMT-1:0])
|
||||||
|
);
|
||||||
|
// Special case: all-zeroes returns XLEN
|
||||||
|
assign ctz_clz[W_SHAMT] = ~|op_a;
|
||||||
|
|
||||||
|
reg [W_SHAMT:0] cpop;
|
||||||
|
always @ (*) begin: cpop_count
|
||||||
|
integer i;
|
||||||
|
cpop = {W_SHAMT+1{1'b0}};
|
||||||
|
for (i = 0; i < W_DATA; i = i + 1) begin
|
||||||
|
cpop = cpop + op_a[i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg [2*W_DATA-1:0] clmul;
|
||||||
|
always @ (*) begin: clmul_mul
|
||||||
|
integer i;
|
||||||
|
clmul = {2*W_DATA{1'b0}};
|
||||||
|
for (i = 0; i < W_DATA; i = i + 1) begin
|
||||||
|
clmul = clmul ^ (({{W_DATA{1'b0}}, op_a} << i) & {2*W_DATA{op_b[i]}});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Output mux, with simple operations inline
|
||||||
|
|
||||||
|
// iCE40: We can implement all bitwise ops with 1 LUT4/bit total, since each
|
||||||
|
// result bit uses only two operand bits. Much better than feeding each into
|
||||||
|
// main mux tree. Doesn't matter for big-LUT FPGAs or for implementations with
|
||||||
|
// bitmanip extensions enabled.
|
||||||
|
|
||||||
reg [W_DATA-1:0] bitwise;
|
reg [W_DATA-1:0] bitwise;
|
||||||
|
|
||||||
always @ (*) begin: bitwise_ops
|
always @ (*) begin: bitwise_ops
|
||||||
case (aluop[1:0])
|
case (aluop[1:0])
|
||||||
ALUOP_AND[1:0]: bitwise = op_a & op_b;
|
ALUOP_AND[1:0]: bitwise = op_a & op_b_inv;
|
||||||
ALUOP_OR[1:0]: bitwise = op_a | op_b;
|
ALUOP_OR[1:0]: bitwise = op_a | op_b_inv;
|
||||||
default: bitwise = op_a ^ op_b;
|
default: bitwise = op_a ^ op_b_inv;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
wire [W_DATA-1:0] zbs_mask = {{W_DATA-1{1'b0}}, 1'b1} << op_b[W_SHAMT-1:0];
|
||||||
|
|
||||||
always @ (*) begin
|
always @ (*) begin
|
||||||
case (aluop)
|
casez ({|EXTENSION_ZBA, |EXTENSION_ZBB, EXTENSION_ZBC, |EXTENSION_ZBS, aluop})
|
||||||
ALUOP_ADD: begin result = sum; end
|
// Base ISA
|
||||||
ALUOP_SUB: begin result = sum; end
|
{4'bzzzz, ALUOP_ADD }: result = sum;
|
||||||
ALUOP_LT: begin result = {{W_DATA-1{1'b0}}, lt}; end
|
{4'bzzzz, ALUOP_SUB }: result = sum;
|
||||||
ALUOP_LTU: begin result = {{W_DATA-1{1'b0}}, lt}; end
|
{4'bzzzz, ALUOP_LT }: result = {{W_DATA-1{1'b0}}, lt};
|
||||||
ALUOP_SRL: begin result = shift_dout; end
|
{4'bzzzz, ALUOP_LTU }: result = {{W_DATA-1{1'b0}}, lt};
|
||||||
ALUOP_SRA: begin result = shift_dout; end
|
{4'bzzzz, ALUOP_SRL }: result = shift_dout;
|
||||||
ALUOP_SLL: begin result = shift_dout; end
|
{4'bzzzz, ALUOP_SRA }: result = shift_dout;
|
||||||
|
{4'bzzzz, ALUOP_SLL }: result = shift_dout;
|
||||||
|
{4'bzzzz, ALUOP_SLL }: result = shift_dout;
|
||||||
|
// Zba
|
||||||
|
{4'b1zzz, ALUOP_ADD_SH1}: result = sum;
|
||||||
|
{4'b1zzz, ALUOP_ADD_SH2}: result = sum;
|
||||||
|
{4'b1zzz, ALUOP_ADD_SH3}: result = sum;
|
||||||
|
// Zbb
|
||||||
|
{4'bz1zz, ALUOP_ANDN }: result = bitwise;
|
||||||
|
{4'bz1zz, ALUOP_ORN }: result = bitwise;
|
||||||
|
{4'bz1zz, ALUOP_XNOR }: result = bitwise;
|
||||||
|
{4'bz1zz, ALUOP_CLZ }: result = ctz_clz;
|
||||||
|
{4'bz1zz, ALUOP_CTZ }: result = ctz_clz;
|
||||||
|
{4'bz1zz, ALUOP_CPOP }: result = cpop;
|
||||||
|
{4'bz1zz, ALUOP_MAX }: result = lt ? op_b : op_a;
|
||||||
|
{4'bz1zz, ALUOP_MAXU }: result = lt ? op_b : op_a;
|
||||||
|
{4'bz1zz, ALUOP_MIN }: result = lt ? op_a : op_b;
|
||||||
|
{4'bz1zz, ALUOP_MINU }: result = lt ? op_a : op_b;
|
||||||
|
{4'bz1zz, ALUOP_SEXT_B }: result = {{W_DATA-8{op_a[7]}}, op_a[7:0]};
|
||||||
|
{4'bz1zz, ALUOP_SEXT_H }: result = {{W_DATA-16{op_a[15]}}, op_a[15:0]};
|
||||||
|
{4'bz1zz, ALUOP_ZEXT_H }: result = {{W_DATA-16{1'b0}}, op_a[15:0]};
|
||||||
|
{4'bz1zz, ALUOP_ORC_B }: result = {{8{|op[31:24]}}, {8{|op[23:16]}}, {8{|op[15:8]}}, {8{|op[7:0]}}};
|
||||||
|
{4'bz1zz, ALUOP_REV8 }: result = {op[7:0], op[15:8], op[23:16], op[31:24]};
|
||||||
|
{4'bz1zz, ALUOP_ROL }: result = shift_dout;
|
||||||
|
{4'bz1zz, ALUOP_ROR }: result = shift_dout;
|
||||||
|
// Zbc
|
||||||
|
{4'bzz1z, ALUOP_CLMUL }: result = clmul[W_DATA-1:0];
|
||||||
|
{4'bzz1z, ALUOP_CLMULH }: result = clmul[2*W_DATA-1:W_DATA];
|
||||||
|
{4'bzz1z, ALUOP_CLMULR }: result = clmul[2*W_DATA-2:W_DATA-1];
|
||||||
|
// Zbs
|
||||||
|
{4'bzzz1, ALUOP_BCLR }: result = op_a & ~zbs_mask;
|
||||||
|
{4'bzzz1, ALUOP_BSET }: result = op_a | zbs_mask;
|
||||||
|
{4'bzzz1, ALUOP_BINV }: result = op_a ^ ~zbs_mask;
|
||||||
|
{4'bzzz1, ALUOP_BEXT }: result = {{W_DATA-1{1'b0}}, shift_dout[0]};
|
||||||
|
|
||||||
default: begin result = bitwise; end
|
default: begin result = bitwise; end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Properties for base-ISA instructions
|
||||||
|
|
||||||
`ifdef FORMAL
|
`ifdef FORMAL
|
||||||
`ifndef RISCV_FORMAL
|
`ifndef RISCV_FORMAL
|
||||||
// Really we're just interested in the shifts and comparisons, as these are
|
// Really we're just interested in the shifts and comparisons, as these are
|
||||||
|
|
|
@ -22,23 +22,25 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
|
|
||||||
module hazard3_shift_barrel #(
|
module hazard3_shift_barrel #(
|
||||||
parameter W_DATA = 32,
|
`include "hazard3_config.vh"
|
||||||
parameter W_SHAMT = 5
|
,
|
||||||
|
`include "hazard3_width_const.vh"
|
||||||
) (
|
) (
|
||||||
input wire [W_DATA-1:0] din,
|
input wire [W_DATA-1:0] din,
|
||||||
input wire [W_SHAMT-1:0] shamt,
|
input wire [W_SHAMT-1:0] shamt,
|
||||||
input wire right_nleft,
|
input wire right_nleft,
|
||||||
|
input wire rotate,
|
||||||
input wire arith,
|
input wire arith,
|
||||||
output reg [W_DATA-1:0] dout
|
output reg [W_DATA-1:0] dout
|
||||||
);
|
);
|
||||||
|
|
||||||
integer i;
|
|
||||||
|
|
||||||
reg [W_DATA-1:0] din_rev;
|
reg [W_DATA-1:0] din_rev;
|
||||||
reg [W_DATA-1:0] shift_accum;
|
reg [W_DATA-1:0] shift_accum;
|
||||||
wire sext = arith && din_rev[0]; // haha
|
wire sext = arith && din_rev[0]; // haha
|
||||||
|
|
||||||
always @ (*) begin
|
always @ (*) begin: shift
|
||||||
|
integer i;
|
||||||
|
|
||||||
for (i = 0; i < W_DATA; i = i + 1)
|
for (i = 0; i < W_DATA; i = i + 1)
|
||||||
din_rev[i] = right_nleft ? din[W_DATA - 1 - i] : din[i];
|
din_rev[i] = right_nleft ? din[W_DATA - 1 - i] : din[i];
|
||||||
|
|
||||||
|
@ -46,7 +48,8 @@ always @ (*) begin
|
||||||
for (i = 0; i < W_SHAMT; i = i + 1) begin
|
for (i = 0; i < W_SHAMT; i = i + 1) begin
|
||||||
if (shamt[i]) begin
|
if (shamt[i]) begin
|
||||||
shift_accum = (shift_accum << (1 << i)) |
|
shift_accum = (shift_accum << (1 << i)) |
|
||||||
({W_DATA{sext}} & ~({W_DATA{1'b1}} << (1 << i)));
|
({W_DATA{sext}} & ~({W_DATA{1'b1}} << (1 << i))) |
|
||||||
|
({W_DATA{rotate && |EXTENSION_ZBB}} & (shift_accum >> (W_DATA - (1 << i))));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,18 @@ parameter EXTENSION_C = 1,
|
||||||
// EXTENSION_M: Support for hardware multiply/divide/modulo instructions
|
// EXTENSION_M: Support for hardware multiply/divide/modulo instructions
|
||||||
parameter EXTENSION_M = 1,
|
parameter EXTENSION_M = 1,
|
||||||
|
|
||||||
|
// EXTENSION_ZBA: Support for Zba address generation instructions
|
||||||
|
parameter EXTENSION_ZBA = 1,
|
||||||
|
|
||||||
|
// EXTENSION_ZBB: Support for Zbb basic bit manipulation instructions
|
||||||
|
parameter EXTENSION_ZBB = 1,
|
||||||
|
|
||||||
|
// EXTENSION_ZBC: Support for Zbc carry-less multiplication instructions
|
||||||
|
parameter EXTENSION_ZBC = 1,
|
||||||
|
|
||||||
|
// EXTENSION_ZBS: Support for Zbs single-bit manipulation instructions
|
||||||
|
parameter EXTENSION_ZBS = 1,
|
||||||
|
|
||||||
// CSR_M_MANDATORY: Bare minimum CSR support e.g. misa. Spec says must = 1 if
|
// CSR_M_MANDATORY: Bare minimum CSR support e.g. misa. Spec says must = 1 if
|
||||||
// CSRs are present, but I won't tell anyone.
|
// CSRs are present, but I won't tell anyone.
|
||||||
parameter CSR_M_MANDATORY = 1,
|
parameter CSR_M_MANDATORY = 1,
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
.MTVEC_INIT (MTVEC_INIT),
|
.MTVEC_INIT (MTVEC_INIT),
|
||||||
.EXTENSION_C (EXTENSION_C),
|
.EXTENSION_C (EXTENSION_C),
|
||||||
.EXTENSION_M (EXTENSION_M),
|
.EXTENSION_M (EXTENSION_M),
|
||||||
|
.EXTENSION_ZBA (EXTENSION_ZBA),
|
||||||
|
.EXTENSION_ZBB (EXTENSION_ZBB),
|
||||||
|
.EXTENSION_ZBC (EXTENSION_ZBC),
|
||||||
|
.EXTENSION_ZBS (EXTENSION_ZBS),
|
||||||
.CSR_M_MANDATORY (CSR_M_MANDATORY),
|
.CSR_M_MANDATORY (CSR_M_MANDATORY),
|
||||||
.CSR_M_TRAP (CSR_M_TRAP),
|
.CSR_M_TRAP (CSR_M_TRAP),
|
||||||
.CSR_COUNTER (CSR_COUNTER),
|
.CSR_COUNTER (CSR_COUNTER),
|
||||||
|
|
|
@ -345,7 +345,9 @@ always @ (*) begin
|
||||||
x_op_b = x_rs2_bypass;
|
x_op_b = x_rs2_bypass;
|
||||||
end
|
end
|
||||||
|
|
||||||
hazard3_alu alu (
|
hazard3_alu #(
|
||||||
|
`include "hazard3_config_inst.vh"
|
||||||
|
) alu (
|
||||||
.aluop (d_aluop),
|
.aluop (d_aluop),
|
||||||
.op_a (x_op_a),
|
.op_a (x_op_a),
|
||||||
.op_b (x_op_b),
|
.op_b (x_op_b),
|
||||||
|
|
|
@ -242,6 +242,38 @@ always @ (*) begin
|
||||||
RV_DIVU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_DIVU; end else begin d_invalid_32bit = 1'b1; end
|
RV_DIVU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_DIVU; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_REM: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REM; end else begin d_invalid_32bit = 1'b1; end
|
RV_REM: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REM; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_REMU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REMU; end else begin d_invalid_32bit = 1'b1; end
|
RV_REMU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REMU; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_SH1ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH1ADD; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_SH2ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH2ADD; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_SH3ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH3ADD; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_ANDN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ANDN; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_CLZ: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CLZ; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_CPOP: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CPOP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_CTZ: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CTZ; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_MAX: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MAX; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_MAXU: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MAXU; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_MIN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MIN; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_MINU: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MINU; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_ORC_B: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ORC_B; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_ORN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ORN; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_REV8: if (EXTENSION_ZBB) begin d_aluop = ALUOP_REV8; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_ROL: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ROL; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_ROR: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ROR; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_RORI: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ROR; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_SEXT_B: if (EXTENSION_ZBB) begin d_aluop = ALUOP_SEXT_B; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_SEXT_H: if (EXTENSION_ZBB) begin d_aluop = ALUOP_SEXT_H; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_XNOR: if (EXTENSION_ZBB) begin d_aluop = ALUOP_XNOR; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_ZEXT_H: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ZEXT_H; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_CLMUL: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMUL; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_CLMULH: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMULH; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_CLMULR: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMULR; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BCLR: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BCLR; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BCLRI: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BCLR; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BEXT: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BEXT; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BEXTI: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BEXT; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BINV: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BINV; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BINVI: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BINV; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BSET: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BSET; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
RV_BSETI: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BSET; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_FENCE: begin d_rd = X0; end // NOP
|
RV_FENCE: begin d_rd = X0; end // NOP
|
||||||
RV_FENCE_I: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_rs1 = X0; d_rs2 = X0; d_branchcond = BCOND_NZERO; d_imm[31] = 1'b1; end // FIXME this is probably busted now. Maybe implement as an exception?
|
RV_FENCE_I: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_rs1 = X0; d_rs2 = X0; d_branchcond = BCOND_NZERO; d_imm[31] = 1'b1; end // FIXME this is probably busted now. Maybe implement as an exception?
|
||||||
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
|
|
@ -1,26 +1,56 @@
|
||||||
|
|
||||||
// ALU operation selectors
|
// ALU operation selectors
|
||||||
|
|
||||||
localparam ALUOP_ADD = 4'h0;
|
localparam ALUOP_ADD = 6'h00;
|
||||||
localparam ALUOP_SUB = 4'h1;
|
localparam ALUOP_SUB = 6'h01;
|
||||||
localparam ALUOP_LT = 4'h2;
|
localparam ALUOP_LT = 6'h02;
|
||||||
localparam ALUOP_LTU = 4'h4;
|
localparam ALUOP_LTU = 6'h04;
|
||||||
localparam ALUOP_AND = 4'h6;
|
localparam ALUOP_AND = 6'h06;
|
||||||
localparam ALUOP_OR = 4'h7;
|
localparam ALUOP_OR = 6'h07;
|
||||||
localparam ALUOP_XOR = 4'h8;
|
localparam ALUOP_XOR = 6'h08;
|
||||||
localparam ALUOP_SRL = 4'h9;
|
localparam ALUOP_SRL = 6'h09;
|
||||||
localparam ALUOP_SRA = 4'ha;
|
localparam ALUOP_SRA = 6'h0a;
|
||||||
localparam ALUOP_SLL = 4'hb;
|
localparam ALUOP_SLL = 6'h0b;
|
||||||
localparam ALUOP_MULDIV = 4'hc;
|
localparam ALUOP_MULDIV = 6'h0c;
|
||||||
|
// Bitmanip ALU operations:
|
||||||
|
localparam ALUOP_SH1ADD = 6'h20;
|
||||||
|
localparam ALUOP_SH2ADD = 6'h21;
|
||||||
|
localparam ALUOP_SH3ADD = 6'h22;
|
||||||
|
localparam ALUOP_CLZ = 6'h23;
|
||||||
|
localparam ALUOP_CPOP = 6'h24;
|
||||||
|
localparam ALUOP_CTZ = 6'h25;
|
||||||
|
localparam ALUOP_ANDN = 6'h26; // Same LSBs as non-inverted
|
||||||
|
localparam ALUOP_ORN = 6'h27; // Same LSBs as non-inverted
|
||||||
|
localparam ALUOP_XNOR = 6'h28; // Same LSBs as non-inverted
|
||||||
|
localparam ALUOP_MAX = 6'h29;
|
||||||
|
localparam ALUOP_MAXU = 6'h2a;
|
||||||
|
localparam ALUOP_MIN = 6'h2b;
|
||||||
|
localparam ALUOP_MINU = 6'h2c;
|
||||||
|
localparam ALUOP_ORC_B = 6'h2d;
|
||||||
|
localparam ALUOP_REV8 = 6'h2e;
|
||||||
|
localparam ALUOP_ROL = 6'h2f;
|
||||||
|
localparam ALUOP_ROR = 6'h30;
|
||||||
|
localparam ALUOP_SEXT_B = 6'h31;
|
||||||
|
localparam ALUOP_SEXT_H = 6'h32;
|
||||||
|
localparam ALUOP_ZEXT_H = 6'h33;
|
||||||
|
|
||||||
|
localparam ALUOP_CLMUL = 6'h34;
|
||||||
|
localparam ALUOP_CLMULH = 6'h35;
|
||||||
|
localparam ALUOP_CLMULR = 6'h36;
|
||||||
|
|
||||||
|
localparam ALUOP_BCLR = 6'h37;
|
||||||
|
localparam ALUOP_BEXT = 6'h38;
|
||||||
|
localparam ALUOP_BINV = 6'h39;
|
||||||
|
localparam ALUOP_BSET = 6'h3a;
|
||||||
|
|
||||||
// Parameters to control ALU input muxes. Bypass mux paths are
|
// Parameters to control ALU input muxes. Bypass mux paths are
|
||||||
// controlled by X, so D has no parameters to choose these.
|
// controlled by X, so D has no parameters to choose these.
|
||||||
|
|
||||||
localparam ALUSRCA_RS1 = 2'h0;
|
localparam ALUSRCA_RS1 = 1'h0;
|
||||||
localparam ALUSRCA_PC = 2'h1;
|
localparam ALUSRCA_PC = 1'h1;
|
||||||
|
|
||||||
localparam ALUSRCB_RS2 = 2'h0;
|
localparam ALUSRCB_RS2 = 1'h0;
|
||||||
localparam ALUSRCB_IMM = 2'h1;
|
localparam ALUSRCB_IMM = 1'h1;
|
||||||
|
|
||||||
localparam MEMOP_LW = 4'h0;
|
localparam MEMOP_LW = 4'h0;
|
||||||
localparam MEMOP_LH = 4'h1;
|
localparam MEMOP_LH = 4'h1;
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
|
|
||||||
parameter W_REGADDR = 5,
|
parameter W_REGADDR = 5,
|
||||||
|
|
||||||
parameter W_ALUOP = 4,
|
parameter W_ALUOP = 6,
|
||||||
parameter W_ALUSRC = 2,
|
parameter W_ALUSRC = 1,
|
||||||
parameter W_MEMOP = 4,
|
parameter W_MEMOP = 4,
|
||||||
parameter W_BCOND = 2,
|
parameter W_BCOND = 2,
|
||||||
|
parameter W_SHAMT = 5,
|
||||||
|
|
||||||
parameter W_EXCEPT = 4,
|
parameter W_EXCEPT = 4,
|
||||||
parameter W_MULOP = 3
|
parameter W_MULOP = 3
|
||||||
|
|
Loading…
Reference in New Issue