Delete the AMO ALU. Save around 80 LCs vs original implementation, maybe enables some more savings.

This commit is contained in:
Luke Wren 2021-12-18 00:35:13 +00:00
parent 7485269ddf
commit 28b53ef7b5
11 changed files with 118 additions and 189 deletions

View File

@ -62,7 +62,7 @@ activity_led #(
);
example_soc #(
.EXTENSION_A (0),
.EXTENSION_A (1),
.EXTENSION_C (0),
.EXTENSION_M (1),
.MUL_FAST (0),

View File

@ -34,7 +34,7 @@ wire sub = !(aluop == ALUOP_ADD || (|EXTENSION_ZBA && (
)));
wire inv_op_b = sub && !(
aluop == ALUOP_AND || aluop == ALUOP_OR || aluop == ALUOP_XOR
aluop == ALUOP_AND || aluop == ALUOP_OR || aluop == ALUOP_XOR || aluop == ALUOP_RS2
);
wire [W_DATA-1:0] op_a_shifted =
@ -133,54 +133,60 @@ reg [W_DATA-1:0] bitwise;
always @ (*) begin: bitwise_ops
case (aluop[1:0])
ALUOP_AND[1:0]: bitwise = op_a & op_b_inv;
ALUOP_OR[1:0]: bitwise = op_a | op_b_inv;
default: bitwise = op_a ^ op_b_inv;
ALUOP_OR [1:0]: bitwise = op_a | op_b_inv;
ALUOP_XOR[1:0]: bitwise = op_a ^ op_b_inv;
ALUOP_RS2[1:0]: bitwise = op_b_inv;
endcase
end
wire [W_DATA-1:0] zbs_mask = {{W_DATA-1{1'b0}}, 1'b1} << op_b[W_SHAMT-1:0];
always @ (*) begin
casez ({|EXTENSION_ZBA, |EXTENSION_ZBB, |EXTENSION_ZBC, |EXTENSION_ZBS, aluop})
casez ({|EXTENSION_A, |EXTENSION_ZBA, |EXTENSION_ZBB, |EXTENSION_ZBC, |EXTENSION_ZBS, aluop})
// Base ISA
{4'bzzzz, ALUOP_ADD }: result = sum;
{4'bzzzz, ALUOP_SUB }: result = sum;
{4'bzzzz, ALUOP_LT }: result = {{W_DATA-1{1'b0}}, lt};
{4'bzzzz, ALUOP_LTU }: result = {{W_DATA-1{1'b0}}, lt};
{4'bzzzz, ALUOP_SRL }: result = shift_dout;
{4'bzzzz, ALUOP_SRA }: result = shift_dout;
{4'bzzzz, ALUOP_SLL }: result = shift_dout;
{5'bzzzzz, ALUOP_ADD }: result = sum;
{5'bzzzzz, ALUOP_SUB }: result = sum;
{5'bzzzzz, ALUOP_LT }: result = {{W_DATA-1{1'b0}}, lt};
{5'bzzzzz, ALUOP_LTU }: result = {{W_DATA-1{1'b0}}, lt};
{5'bzzzzz, ALUOP_SRL }: result = shift_dout;
{5'bzzzzz, ALUOP_SRA }: result = shift_dout;
{5'bzzzzz, ALUOP_SLL }: result = shift_dout;
// A (duplicates of Zbb)
{5'b1zzzz, ALUOP_MAX }: result = lt ? op_b : op_a;
{5'b1zzzz, ALUOP_MAXU }: result = lt ? op_b : op_a;
{5'b1zzzz, ALUOP_MIN }: result = lt ? op_a : op_b;
{5'b1zzzz, ALUOP_MINU }: result = lt ? op_a : op_b;
// Zba
{4'b1zzz, ALUOP_SH1ADD }: result = sum;
{4'b1zzz, ALUOP_SH2ADD }: result = sum;
{4'b1zzz, ALUOP_SH3ADD }: result = sum;
{5'bz1zzz, ALUOP_SH1ADD }: result = sum;
{5'bz1zzz, ALUOP_SH2ADD }: result = sum;
{5'bz1zzz, ALUOP_SH3ADD }: 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 = {{W_DATA-W_SHAMT-1{1'b0}}, ctz_clz};
{4'bz1zz, ALUOP_CTZ }: result = {{W_DATA-W_SHAMT-1{1'b0}}, ctz_clz};
{4'bz1zz, ALUOP_CPOP }: result = {{W_DATA-W_SHAMT-1{1'b0}}, 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_a[31:24]}}, {8{|op_a[23:16]}}, {8{|op_a[15:8]}}, {8{|op_a[7:0]}}};
{4'bz1zz, ALUOP_REV8 }: result = {op_a[7:0], op_a[15:8], op_a[23:16], op_a[31:24]};
{4'bz1zz, ALUOP_ROL }: result = shift_dout;
{4'bz1zz, ALUOP_ROR }: result = shift_dout;
{5'bzz1zz, ALUOP_ANDN }: result = bitwise;
{5'bzz1zz, ALUOP_ORN }: result = bitwise;
{5'bzz1zz, ALUOP_XNOR }: result = bitwise;
{5'bzz1zz, ALUOP_CLZ }: result = {{W_DATA-W_SHAMT-1{1'b0}}, ctz_clz};
{5'bzz1zz, ALUOP_CTZ }: result = {{W_DATA-W_SHAMT-1{1'b0}}, ctz_clz};
{5'bzz1zz, ALUOP_CPOP }: result = {{W_DATA-W_SHAMT-1{1'b0}}, cpop};
{5'bzz1zz, ALUOP_MAX }: result = lt ? op_b : op_a;
{5'bzz1zz, ALUOP_MAXU }: result = lt ? op_b : op_a;
{5'bzz1zz, ALUOP_MIN }: result = lt ? op_a : op_b;
{5'bzz1zz, ALUOP_MINU }: result = lt ? op_a : op_b;
{5'bzz1zz, ALUOP_SEXT_B }: result = {{W_DATA-8{op_a[7]}}, op_a[7:0]};
{5'bzz1zz, ALUOP_SEXT_H }: result = {{W_DATA-16{op_a[15]}}, op_a[15:0]};
{5'bzz1zz, ALUOP_ZEXT_H }: result = {{W_DATA-16{1'b0}}, op_a[15:0]};
{5'bzz1zz, ALUOP_ORC_B }: result = {{8{|op_a[31:24]}}, {8{|op_a[23:16]}}, {8{|op_a[15:8]}}, {8{|op_a[7:0]}}};
{5'bzz1zz, ALUOP_REV8 }: result = {op_a[7:0], op_a[15:8], op_a[23:16], op_a[31:24]};
{5'bzz1zz, ALUOP_ROL }: result = shift_dout;
{5'bzz1zz, 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];
{5'bzzz1z, ALUOP_CLMUL }: result = clmul[W_DATA-1:0];
{5'bzzz1z, ALUOP_CLMULH }: result = clmul[2*W_DATA-1:W_DATA];
{5'bzzz1z, 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]};
{5'bzzzz1, ALUOP_BCLR }: result = op_a & ~zbs_mask;
{5'bzzzz1, ALUOP_BSET }: result = op_a | zbs_mask;
{5'bzzzz1, ALUOP_BINV }: result = op_a ^ zbs_mask;
{5'bzzzz1, ALUOP_BEXT }: result = {{W_DATA-1{1'b0}}, shift_dout[0]};
default: result = bitwise;
endcase

View File

@ -1,49 +0,0 @@
/*****************************************************************************\
| Copyright (C) 2021 Luke Wren |
| SPDX-License-Identifier: Apache-2.0 |
\*****************************************************************************/
// Separate ALU for atomic memory operations
`default_nettype none
module hazard3_amo_alu #(
`include "hazard3_config.vh"
,
`include "hazard3_width_const.vh"
) (
input wire [W_MEMOP-1:0] op,
input wire [W_DATA-1:0] op_rs1, // From load
input wire [W_DATA-1:0] op_rs2, // From core
output reg [W_DATA-1:0] result
);
`include "hazard3_ops.vh"
wire sub = op != MEMOP_AMOADD_W;
wire cmp_unsigned = op == MEMOP_AMOMINU_W || op == MEMOP_AMOMAXU_W;
wire [W_DATA-1:0] sum = op_rs1 + (op_rs2 ^ {W_DATA{sub}}) + sub;
wire rs1_lessthan_rs2 =
op_rs1[W_DATA-1] == op_rs2[W_DATA-1] ? sum[W_DATA-1] :
cmp_unsigned ? op_rs2[W_DATA-1] :
op_rs1[W_DATA-1] ;
always @ (*) begin
case(op)
MEMOP_AMOADD_W: result = sum;
MEMOP_AMOXOR_W: result = op_rs1 ^ op_rs2;
MEMOP_AMOAND_W: result = op_rs1 & op_rs2;
MEMOP_AMOOR_W: result = op_rs1 | op_rs2;
MEMOP_AMOMIN_W: result = rs1_lessthan_rs2 ? op_rs1 : op_rs2;
MEMOP_AMOMAX_W: result = rs1_lessthan_rs2 ? op_rs2 : op_rs1;
MEMOP_AMOMINU_W: result = rs1_lessthan_rs2 ? op_rs1 : op_rs2;
MEMOP_AMOMAXU_W: result = rs1_lessthan_rs2 ? op_rs2 : op_rs1;
// AMOSWAP
default: result = op_rs2;
endcase
end
endmodule
`default_nettype wire

View File

@ -2,7 +2,6 @@ file hazard3_core.v
file hazard3_cpu_1port.v
file hazard3_cpu_2port.v
file arith/hazard3_alu.v
file arith/hazard3_amo_alu.v
file arith/hazard3_muldiv_seq.v
file arith/hazard3_mul_fast.v
file arith/hazard3_priority_encode.v

View File

@ -255,13 +255,15 @@ reg [W_REGADDR-1:0] xm_rs1;
reg [W_REGADDR-1:0] xm_rs2;
reg [W_REGADDR-1:0] xm_rd;
reg [W_DATA-1:0] xm_result;
reg [W_DATA-1:0] xm_store_data;
reg [1:0] xm_addr_align;
reg [W_MEMOP-1:0] xm_memop;
reg [W_EXCEPT-1:0] xm_except;
reg xm_wfi;
reg xm_delay_irq_entry;
// Registered load data, routed back through ALU. AMOs were a mistake
reg [W_DATA-1:0] mx_amo_load_data;
// ----------------------------------------------------------------------------
// Stall logic
@ -275,9 +277,7 @@ wire x_stall_on_trap = m_trap_enter_vld && !m_trap_enter_rdy ||
// sequences). Note we don't check for AMOs in stage M, because AMOs fully
// fence off on their own completion before passing down the pipe.
wire d_memop_is_amo = |EXTENSION_A && (
d_memop >= MEMOP_AMOSWAP_W && d_memop <= MEMOP_AMOMAXU_W
);
wire d_memop_is_amo = |EXTENSION_A && d_memop == MEMOP_AMO;
wire x_stall_on_exclusive_overlap = |EXTENSION_A && (
(d_memop_is_amo || d_memop == MEMOP_SC_W || d_memop == MEMOP_LR_W) &&
@ -367,7 +367,9 @@ always @ (*) begin
x_rs2_bypass = x_rdata2;
end
if (|d_alusrc_a)
if (|EXTENSION_A && x_amo_phase == 3'h2)
x_op_a = mx_amo_load_data;
else if (|d_alusrc_a)
x_op_a = d_pc;
else
x_op_a = x_rs1_bypass;
@ -459,12 +461,12 @@ always @ (posedge clk) if (rst_n) begin
assert(x_amo_phase == 3'h0);
// Error phase should never block, so it can always pass to stage 3 to raise
// excepting trap entry.
if (amo_phase == 3'h4)
if (x_amo_phase == 3'h4)
assert(!x_stall);
// Error phase is either due to a bus response, or a misaligned address.
// Neither of these are write-address-phase.
if (amo_phase == 3'h4)
assert($past(amo_phase) != 3'h2);
if (x_amo_phase == 3'h4)
assert($past(x_amo_phase) != 3'h2);
end
`endif
@ -738,7 +740,7 @@ always @ (posedge clk or negedge rst_n) begin
if (!m_stall) begin
{xm_rs1, xm_rs2, xm_rd} <= {d_rs1, d_rs2, d_rd};
// If the transfer is unaligned, make sure it is completely NOP'd on the bus
// Likewise, AMOs are handled entirely in X (well it's ambiguous; anyway different logic & stalls)
// Likewise, AMO memop logic is entirely in X, we squash the memop as it passes to M.
xm_memop <= x_unaligned_addr || d_memop_is_amo ? MEMOP_NONE : d_memop;
xm_except <= x_except;
xm_wfi <= d_wfi;
@ -764,25 +766,18 @@ always @ (posedge clk or negedge rst_n) begin
end
end
reg [W_DATA-1:0] amo_load_data;
// Datapath flops
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
xm_result <= {W_DATA{1'b0}};
xm_store_data <= {W_DATA{1'b0}};
xm_addr_align <= 2'b00;
end else if (!m_stall) begin
end else if (!m_stall || (d_memop_is_amo && x_amo_phase == 3'h2 && bus_dph_ready_d)) begin
xm_result <=
d_csr_ren ? x_csr_rdata :
|EXTENSION_A && d_memop_is_amo ? amo_load_data :
|EXTENSION_A && x_amo_phase == 3'h3 ? mx_amo_load_data :
|EXTENSION_M && d_aluop == ALUOP_MULDIV ? x_muldiv_result :
x_alu_result;
xm_store_data <= x_rs2_bypass;
xm_addr_align <= x_addr_sum[1:0];
end else if (d_memop_is_amo && x_amo_phase == 3'h1 && bus_dph_ready_d) begin
xm_store_data <= x_rs2_bypass;
end
end
@ -833,56 +828,12 @@ assign m_exception_return_addr = d_pc - (
// Load/store data handling
wire [W_DATA-1:0] m_amo_wdata;
wire m_amo_wdata_valid;
generate
if (EXTENSION_A) begin: has_amo_alu
reg [W_MEMOP-1:0] amo_memop;
reg m_amo_wdata_valid_r;
assign m_amo_wdata_valid = m_amo_wdata_valid_r;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
amo_memop <= MEMOP_NONE;
amo_load_data <= {W_DATA{1'b0}};
m_amo_wdata_valid_r <= 1'b0;
end else if (x_amo_phase == 3'h4 || (x_amo_phase == 3'h3 && bus_dph_ready_d) || m_trap_enter_soon) begin
// Higher precedence to make sure trap always clears the valid bit
m_amo_wdata_valid_r <= 1'b0;
end else if (d_memop_is_amo && x_amo_phase == 3'h1 && bus_dph_ready_d) begin
amo_memop <= d_memop;
amo_load_data <= bus_rdata_d;
m_amo_wdata_valid_r <= 1'b1;
end
end
hazard3_amo_alu #(
`include "hazard3_config_inst.vh"
) amo_alu (
.op (amo_memop),
.op_rs1(amo_load_data),
.op_rs2(xm_store_data),
.result(m_amo_wdata)
);
end else begin: no_amo_alu
assign m_amo_wdata = {W_DATA{1'b0}};
assign m_amo_wdata_valid = 1'b0;
always @ (*) amo_load_data = {W_DATA{1'b0}};
end
endgenerate
always @ (*) begin
// Local forwarding of store data
if (|mw_rd && xm_rs2 == mw_rd && !REDUCED_BYPASS) begin
m_wdata = mw_result;
end else begin
m_wdata = xm_store_data;
m_wdata = xm_result;
end
// Replicate store data to ensure appropriate byte lane is driven
case (xm_memop)
@ -890,8 +841,6 @@ always @ (*) begin
MEMOP_SB: bus_wdata_d = {4{m_wdata[7:0]}};
default: bus_wdata_d = m_wdata;
endcase
if (|EXTENSION_A && m_amo_wdata_valid)
bus_wdata_d = m_amo_wdata;
casez ({xm_memop, xm_addr_align[1:0]})
{MEMOP_LH , 2'b0z}: m_rdata_pick_sext = {{16{bus_rdata_d[15]}}, bus_rdata_d[15: 0]};
@ -923,6 +872,29 @@ always @ (*) begin
end
end
// Capture load data in read data phase of AMO. Passes back to stage X for AMO
// calculation during AMO write address phase, using the regular ALU. Then
// registered into xm_result like a regular store, to be driven out onto
// hwdata during AMO write data phase.
generate
if (EXTENSION_A) begin: has_amo_load_reg
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mx_amo_load_data <= {W_DATA{1'b0}};
end else if (d_memop_is_amo && x_amo_phase == 3'h1 && bus_dph_ready_d) begin
mx_amo_load_data <= bus_rdata_d;
end
end
end else begin: no_amo_load_reg
always @ (*) mx_amo_load_data = {W_DATA{1'b0}};
end
endgenerate
// Local monitor update.
// - Set on a load-reserved with good response from global monitor
// - Cleared by any store-conditional

View File

@ -221,9 +221,9 @@ always @ (*) begin
RV_LW: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LW; end
RV_LBU: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LBU; end
RV_LHU: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LHU; end
RV_SB: begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_SB; d_rd = X0; end
RV_SH: begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_SH; d_rd = X0; end
RV_SW: begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_SW; d_rd = X0; end
RV_SB: begin d_addr_is_regoffs = 1'b1; d_aluop = ALUOP_RS2; d_memop = MEMOP_SB; d_rd = X0; end
RV_SH: begin d_addr_is_regoffs = 1'b1; d_aluop = ALUOP_RS2; d_memop = MEMOP_SH; d_rd = X0; end
RV_SW: begin d_addr_is_regoffs = 1'b1; d_aluop = ALUOP_RS2; d_memop = MEMOP_SW; d_rd = X0; end
RV_MUL: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MUL; end else begin d_invalid_32bit = 1'b1; end
RV_MULH: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MULH; end else begin d_invalid_32bit = 1'b1; end
@ -234,17 +234,17 @@ always @ (*) begin
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_LR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_LR_W; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
RV_SC_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_SC_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOSWAP_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOSWAP_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOADD_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOADD_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOXOR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOXOR_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOAND_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOAND_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOOR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOOR_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMIN_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOMIN_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMAX_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOMAX_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMINU_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOMINU_W; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMAXU_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMOMAXU_W; end else begin d_invalid_32bit = 1'b1; end
RV_LR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_LR_W; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
RV_SC_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_SC_W; d_aluop = ALUOP_RS2; end else begin d_invalid_32bit = 1'b1; end
RV_AMOSWAP_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_RS2; end else begin d_invalid_32bit = 1'b1; end
RV_AMOADD_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_ADD; end else begin d_invalid_32bit = 1'b1; end
RV_AMOXOR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_XOR; end else begin d_invalid_32bit = 1'b1; end
RV_AMOAND_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_AND; end else begin d_invalid_32bit = 1'b1; end
RV_AMOOR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_OR; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMIN_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MIN; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMAX_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MAX; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMINU_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MINU; end else begin d_invalid_32bit = 1'b1; end
RV_AMOMAXU_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MAXU; 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

View File

@ -16,7 +16,8 @@ localparam ALUOP_SRL = 6'h09;
localparam ALUOP_SRA = 6'h0a;
localparam ALUOP_SLL = 6'h0b;
localparam ALUOP_MULDIV = 6'h0c;
// Bitmanip ALU operations:
localparam ALUOP_RS2 = 6'h0d; // differs from AND/OR/XOR in [1:0]
// Bitmanip ALU operations (some also used by AMOs):
localparam ALUOP_SH1ADD = 6'h20;
localparam ALUOP_SH2ADD = 6'h21;
localparam ALUOP_SH3ADD = 6'h22;
@ -56,27 +57,19 @@ localparam ALUSRCA_PC = 1'h1;
localparam ALUSRCB_RS2 = 1'h0;
localparam ALUSRCB_IMM = 1'h1;
localparam MEMOP_LW = 5'h00;
localparam MEMOP_LH = 5'h01;
localparam MEMOP_LB = 5'h02;
localparam MEMOP_LHU = 5'h03;
localparam MEMOP_LBU = 5'h04;
localparam MEMOP_SW = 5'h05;
localparam MEMOP_SH = 5'h06;
localparam MEMOP_SB = 5'h07;
localparam MEMOP_LW = 5'h00;
localparam MEMOP_LH = 5'h01;
localparam MEMOP_LB = 5'h02;
localparam MEMOP_LHU = 5'h03;
localparam MEMOP_LBU = 5'h04;
localparam MEMOP_SW = 5'h05;
localparam MEMOP_SH = 5'h06;
localparam MEMOP_SB = 5'h07;
localparam MEMOP_LR_W = 5'h08;
localparam MEMOP_SC_W = 5'h09;
localparam MEMOP_AMOSWAP_W = 5'h0a;
localparam MEMOP_AMOADD_W = 5'h0b;
localparam MEMOP_AMOXOR_W = 5'h0c;
localparam MEMOP_AMOAND_W = 5'h0d;
localparam MEMOP_AMOOR_W = 5'h0e;
localparam MEMOP_AMOMIN_W = 5'h0f;
localparam MEMOP_AMOMAX_W = 5'h10;
localparam MEMOP_AMOMINU_W = 5'h11;
localparam MEMOP_AMOMAXU_W = 5'h12;
localparam MEMOP_NONE = 5'h1f;
localparam MEMOP_LR_W = 5'h08;
localparam MEMOP_SC_W = 5'h09;
localparam MEMOP_AMO = 5'h0a;
localparam MEMOP_NONE = 5'h10;
localparam BCOND_NEVER = 2'h0;
localparam BCOND_ALWAYS = 2'h1;

View File

@ -1,2 +1,4 @@
#!/bin/bash
set -e
make

View File

@ -1,4 +1,6 @@
#!/bin/bash
set -e
make TEST_ARCH=C BIN_ARCH=rv32ic TESTLIST=" \
cadd-01 \
caddi16sp-01 \

View File

@ -1,4 +1,6 @@
#!/bin/bash
set -e
make TEST_ARCH=M BIN_ARCH=rv32imc TESTLIST=" \
div-01 \
divu-01 \

View File

@ -1,4 +1,6 @@
#!/bin/bash
set -e
./run_32i.sh
./run_32im.sh
./run_32ic.sh