Skip to content

Commit

Permalink
✨ Add symmetric add operation for same source FP format add/sub (open…
Browse files Browse the repository at this point in the history
…hwgroup#114)

* 🏷️ Add new operation for symmetric (same src fmt) add

* ✨ Select multi FMA addend fmt independently

* 💡 Add new operation to comment in multi FMA src

* 📝 Document new symmetric add operation
  • Loading branch information
michael-platzer committed Jun 5, 2024
1 parent de6d2ac commit 403ca74
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 38 deletions.
17 changes: 9 additions & 8 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ Enumeration of type `logic [2:0]` holding available rounding modes, encoded for
Enumeration of type `logic [3:0]` holding the FP operation.
The operation modifier `op_mod_i` can change the operation carried out.
Unless noted otherwise, the first operand `op[0]` is used for the operation.
Unless noted otherwise, `op[0]` and `op[1]` are given in source FP format and `op[2]` is given in destination FP format.

| Enumerator | Modifier | Operation |
|------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `FMADD` | `0` | Fused multiply-add (`(op[0] * op[1]) + op[2]`) |
| `FMADD` | `1` | Fused multiply-subtract (`(op[0] * op[1]) - op[2]`) |
| `FNMSUB` | `0` | Negated fused multiply-subtract (`-(op[0] * op[1]) + op[2]`) |
| `FNMSUB` | `1` | Negated fused multiply-add (`-(op[0] * op[1]) - op[2]`) |
| `ADD` | `0` | Addition (`op[1] + op[2]`) *note the operand indices* |
| `ADD` | `1` | Subtraction (`op[1] - op[2]`) *note the operand indices* |
| `ADD/ADDS` | `0` | Addition (`op[1] + op[2]`) *note the operand indices*. For `ADD`, `op[1]` is in source FP format and `op[2]` in destination FP format (default). When `ADDS` is used, both operands are in source FP format. |
| `ADD/ADDS` | `1` | Subtraction (`op[1] - op[2]`) *note the operand indices*. For `ADD`, `op[1]` is in source FP format and `op[2]` in destination FP format (default). When `ADDS` is used, both operands are in source FP format. |
| `MUL` | `0` | Multiplication (`op[0] * op[1]`) |
| `DIV` | `0` | Division (`op[0] / op[1]`) |
| `SQRT` | `0` | Square root |
Expand Down Expand Up @@ -394,12 +395,12 @@ The *operation group* is the highest level of grouping within FPnew and signifie

There are currently four operation groups in FPnew which are enumerated in `opgroup_e` as outlined in the following table:

| Enumerator | Description | Associated Operations |
|------------|-----------------------------------------------|---------------------------------------|
| `ADDMUL` | Addition and Multiplication | `FMADD`, `FNMSUB`, `ADD`, `MUL` |
| `DIVSQRT` | Division and Square Root | `DIV`, `SQRT` |
| `NONCOMP` | Non-Computational Operations like Comparisons | `SGNJ`, `MINMAX`, `CMP`, `CLASS` |
| `CONV` | Conversions | `F2I`, `I2F`, `F2F`, `CPKAB`, `CPKCD` |
| Enumerator | Description | Associated Operations |
|------------|-----------------------------------------------|-----------------------------------------|
| `ADDMUL` | Addition and Multiplication | `FMADD`, `FNMSUB`, `ADD`, `ADDS`, `MUL` |
| `DIVSQRT` | Division and Square Root | `DIV`, `SQRT` |
| `NONCOMP` | Non-Computational Operations like Comparisons | `SGNJ`, `MINMAX`, `CMP`, `CLASS` |
| `CONV` | Conversions | `F2I`, `I2F`, `F2F`, `CPKAB`, `CPKCD` |

Most architectural decisions for FPnew are made at very fine granularity.
The big exception to this is the generation of vectorial hardware which is decided at top level through the `EnableVectors` parameter.
Expand Down
26 changes: 16 additions & 10 deletions src/fpnew_fma_multi.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ module fpnew_fma_multi #(
input fpnew_pkg::roundmode_e rnd_mode_i,
input fpnew_pkg::operation_e op_i,
input logic op_mod_i,
input fpnew_pkg::fp_format_e src_fmt_i, // format of the multiplicands
input fpnew_pkg::fp_format_e dst_fmt_i, // format of the addend and result
input fpnew_pkg::fp_format_e src_fmt_i, // format of the multiplicands
input fpnew_pkg::fp_format_e src2_fmt_i, // format of the addend
input fpnew_pkg::fp_format_e dst_fmt_i, // format of the result
input TagType tag_i,
input logic mask_i,
input AuxType aux_i,
Expand Down Expand Up @@ -111,6 +112,7 @@ module fpnew_fma_multi #(
// Selected pipeline output signals as non-arrays
logic [2:0][WIDTH-1:0] operands_q;
fpnew_pkg::fp_format_e src_fmt_q;
fpnew_pkg::fp_format_e src2_fmt_q;
fpnew_pkg::fp_format_e dst_fmt_q;

// Input pipeline signals, index i holds signal after i register stages
Expand All @@ -120,6 +122,7 @@ module fpnew_fma_multi #(
fpnew_pkg::operation_e [0:NUM_INP_REGS] inp_pipe_op_q;
logic [0:NUM_INP_REGS] inp_pipe_op_mod_q;
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_src_fmt_q;
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_src2_fmt_q;
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_dst_fmt_q;
TagType [0:NUM_INP_REGS] inp_pipe_tag_q;
logic [0:NUM_INP_REGS] inp_pipe_mask_q;
Expand All @@ -135,6 +138,7 @@ module fpnew_fma_multi #(
assign inp_pipe_op_q[0] = op_i;
assign inp_pipe_op_mod_q[0] = op_mod_i;
assign inp_pipe_src_fmt_q[0] = src_fmt_i;
assign inp_pipe_src2_fmt_q[0] = src2_fmt_i;
assign inp_pipe_dst_fmt_q[0] = dst_fmt_i;
assign inp_pipe_tag_q[0] = tag_i;
assign inp_pipe_mask_q[0] = mask_i;
Expand All @@ -161,6 +165,7 @@ module fpnew_fma_multi #(
`FFL(inp_pipe_op_q[i+1], inp_pipe_op_q[i], reg_ena, fpnew_pkg::FMADD)
`FFL(inp_pipe_op_mod_q[i+1], inp_pipe_op_mod_q[i], reg_ena, '0)
`FFL(inp_pipe_src_fmt_q[i+1], inp_pipe_src_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
`FFL(inp_pipe_src2_fmt_q[i+1], inp_pipe_src2_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
`FFL(inp_pipe_dst_fmt_q[i+1], inp_pipe_dst_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
`FFL(inp_pipe_tag_q[i+1], inp_pipe_tag_q[i], reg_ena, TagType'('0))
`FFL(inp_pipe_mask_q[i+1], inp_pipe_mask_q[i], reg_ena, '0)
Expand All @@ -169,6 +174,7 @@ module fpnew_fma_multi #(
// Output stage: assign selected pipe outputs to signals for later use
assign operands_q = inp_pipe_operands_q[NUM_INP_REGS];
assign src_fmt_q = inp_pipe_src_fmt_q[NUM_INP_REGS];
assign src2_fmt_q = inp_pipe_src2_fmt_q[NUM_INP_REGS];
assign dst_fmt_q = inp_pipe_dst_fmt_q[NUM_INP_REGS];

// -----------------
Expand Down Expand Up @@ -224,20 +230,20 @@ module fpnew_fma_multi #(
// | FMADD | \c 1 | FMSUB: Invert sign of operand C
// | FNMSUB | \c 0 | FNMSUB: Invert sign of operand A
// | FNMSUB | \c 1 | FNMADD: Invert sign of operands A and C
// | ADD | \c 0 | ADD: Set operand A to +1.0
// | ADD | \c 1 | SUB: Set operand A to +1.0, invert sign of operand C
// | ADD/ADDS | \c 0 | ADD: Set operand A to +1.0
// | ADD/ADDS | \c 1 | SUB: Set operand A to +1.0, invert sign of operand C
// | MUL | \c 0 | MUL: Set operand C to +0.0 or -0.0 depending on the rounding mode
// | *others* | \c - | *invalid*
// \note \c op_mod_q always inverts the sign of the addend.
always_comb begin : op_select

// Default assignments - packing-order-agnostic
operand_a = {fmt_sign[src_fmt_q][0], fmt_exponent[src_fmt_q][0], fmt_mantissa[src_fmt_q][0]};
operand_b = {fmt_sign[src_fmt_q][1], fmt_exponent[src_fmt_q][1], fmt_mantissa[src_fmt_q][1]};
operand_c = {fmt_sign[dst_fmt_q][2], fmt_exponent[dst_fmt_q][2], fmt_mantissa[dst_fmt_q][2]};
info_a = info_q[src_fmt_q][0];
info_b = info_q[src_fmt_q][1];
info_c = info_q[dst_fmt_q][2];
operand_a = {fmt_sign[src_fmt_q ][0], fmt_exponent[src_fmt_q ][0], fmt_mantissa[src_fmt_q ][0]};
operand_b = {fmt_sign[src_fmt_q ][1], fmt_exponent[src_fmt_q ][1], fmt_mantissa[src_fmt_q ][1]};
operand_c = {fmt_sign[src2_fmt_q][2], fmt_exponent[src2_fmt_q][2], fmt_mantissa[src2_fmt_q][2]};
info_a = info_q[src_fmt_q ][0];
info_b = info_q[src_fmt_q ][1];
info_c = info_q[src2_fmt_q][2];

// op_mod_q inverts sign of operand C
operand_c.sign = operand_c.sign ^ inp_pipe_op_mod_q[NUM_INP_REGS];
Expand Down
29 changes: 15 additions & 14 deletions src/fpnew_opgroup_multifmt_slice.sv
Original file line number Diff line number Diff line change
Expand Up @@ -229,28 +229,29 @@ or set Features.FpFmtMask to support only FP32");
) i_fpnew_fma_multi (
.clk_i,
.rst_ni,
.operands_i ( local_operands ),
.operands_i ( local_operands ),
.is_boxed_i,
.rnd_mode_i,
.op_i,
.op_mod_i,
.src_fmt_i,
.src2_fmt_i ( op_i == fpnew_pkg::ADDS ? src_fmt_i : dst_fmt_i ),
.dst_fmt_i,
.tag_i,
.mask_i ( simd_mask_i[lane] ),
.aux_i ( aux_data ),
.in_valid_i ( in_valid ),
.in_ready_o ( lane_in_ready[lane] ),
.mask_i ( simd_mask_i[lane] ),
.aux_i ( aux_data ),
.in_valid_i ( in_valid ),
.in_ready_o ( lane_in_ready[lane] ),
.flush_i,
.result_o ( op_result ),
.status_o ( op_status ),
.extension_bit_o ( lane_ext_bit[lane] ),
.tag_o ( lane_tags[lane] ),
.mask_o ( lane_masks[lane] ),
.aux_o ( lane_aux[lane] ),
.out_valid_o ( out_valid ),
.out_ready_i ( out_ready ),
.busy_o ( lane_busy[lane] ),
.result_o ( op_result ),
.status_o ( op_status ),
.extension_bit_o ( lane_ext_bit[lane] ),
.tag_o ( lane_tags[lane] ),
.mask_o ( lane_masks[lane] ),
.aux_o ( lane_aux[lane] ),
.out_valid_o ( out_valid ),
.out_ready_i ( out_ready ),
.busy_o ( lane_busy[lane] ),
.reg_ena_i
);

Expand Down
13 changes: 7 additions & 6 deletions src/fpnew_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ package fpnew_pkg;
FMADD, FNMSUB, ADD, MUL, // ADDMUL operation group
DIV, SQRT, // DIVSQRT operation group
SGNJ, MINMAX, CMP, CLASSIFY, // NONCOMP operation group
F2F, F2I, I2F, CPKAB, CPKCD // CONV operation group
F2F, F2I, I2F, CPKAB, CPKCD, // CONV operation group
ADDS // ADDMUL operation group (ADDS is added here to preserve bit encoding of operations)
} operation_e;

// -------------------
Expand Down Expand Up @@ -367,11 +368,11 @@ package fpnew_pkg;
// Returns the operation group of the given operation
function automatic opgroup_e get_opgroup(operation_e op);
unique case (op)
FMADD, FNMSUB, ADD, MUL: return ADDMUL;
DIV, SQRT: return DIVSQRT;
SGNJ, MINMAX, CMP, CLASSIFY: return NONCOMP;
F2F, F2I, I2F, CPKAB, CPKCD: return CONV;
default: return NONCOMP;
FMADD, FNMSUB, ADD, ADDS, MUL: return ADDMUL;
DIV, SQRT: return DIVSQRT;
SGNJ, MINMAX, CMP, CLASSIFY: return NONCOMP;
F2F, F2I, I2F, CPKAB, CPKCD: return CONV;
default: return NONCOMP;
endcase
endfunction

Expand Down

0 comments on commit 403ca74

Please sign in to comment.