-
Notifications
You must be signed in to change notification settings - Fork 9
/
fpu_wrap.sv
550 lines (511 loc) · 21.6 KB
/
fpu_wrap.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Stefan Mach, ETH Zurich
// Date: 12.04.2018
// Description: Wrapper for the floating-point unit
module fpu_wrap import ariane_pkg::*; (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic fpu_valid_i,
output logic fpu_ready_o,
input fu_data_t fu_data_i,
input logic [1:0] fpu_fmt_i,
input logic [2:0] fpu_rm_i,
input logic [2:0] fpu_frm_i,
input logic [6:0] fpu_prec_i,
output logic [TRANS_ID_BITS-1:0] fpu_trans_id_o,
output logic [FLEN-1:0] result_o,
output logic fpu_valid_o,
output exception_t fpu_exception_o
);
// this is a workaround
// otherwise compilation might issue an error if FLEN=0
enum logic {READY, STALL} state_q, state_d;
if (FP_PRESENT) begin : fpu_gen
logic [FLEN-1:0] operand_a_i;
logic [FLEN-1:0] operand_b_i;
logic [FLEN-1:0] operand_c_i;
assign operand_a_i = fu_data_i.operand_a[FLEN-1:0];
assign operand_b_i = fu_data_i.operand_b[FLEN-1:0];
assign operand_c_i = fu_data_i.imm[FLEN-1:0];
//-----------------------------------
// FPnew config from FPnew package
//-----------------------------------
localparam OPBITS = fpnew_pkg::OP_BITS;
localparam FMTBITS = $clog2(fpnew_pkg::NUM_FP_FORMATS);
localparam IFMTBITS = $clog2(fpnew_pkg::NUM_INT_FORMATS);
// Features (enabled formats, vectors etc.)
localparam fpnew_pkg::fpu_features_t FPU_FEATURES = '{
Width: 64,
EnableVectors: ariane_pkg::XFVEC,
EnableNanBox: 1'b1,
FpFmtMask: {RVF, RVD, XF16, XF8, XF16ALT},
IntFmtMask: {XFVEC && XF8, XFVEC && (XF16 || XF16ALT), 1'b1, 1'b1}
};
// Implementation (number of registers etc)
localparam fpnew_pkg::fpu_implementation_t FPU_IMPLEMENTATION = '{
PipeRegs: '{// FP32, FP64, FP16, FP8, FP16alt
'{LAT_COMP_FP32, LAT_COMP_FP64, LAT_COMP_FP16, LAT_COMP_FP8, LAT_COMP_FP16ALT}, // ADDMUL
'{default: LAT_DIVSQRT}, // DIVSQRT
'{default: LAT_NONCOMP}, // NONCOMP
'{default: LAT_CONV}}, // CONV
UnitTypes: '{'{default: fpnew_pkg::PARALLEL}, // ADDMUL
'{default: fpnew_pkg::MERGED}, // DIVSQRT
'{default: fpnew_pkg::PARALLEL}, // NONCOMP
'{default: fpnew_pkg::MERGED}}, // CONV
PipeConfig: fpnew_pkg::DISTRIBUTED
};
//-------------------------------------------------
// Inputs to the FPU and protocol inversion buffer
//-------------------------------------------------
logic [FLEN-1:0] operand_a_d, operand_a_q, operand_a;
logic [FLEN-1:0] operand_b_d, operand_b_q, operand_b;
logic [FLEN-1:0] operand_c_d, operand_c_q, operand_c;
logic [OPBITS-1:0] fpu_op_d, fpu_op_q, fpu_op;
logic fpu_op_mod_d, fpu_op_mod_q, fpu_op_mod;
logic [FMTBITS-1:0] fpu_srcfmt_d, fpu_srcfmt_q, fpu_srcfmt;
logic [FMTBITS-1:0] fpu_dstfmt_d, fpu_dstfmt_q, fpu_dstfmt;
logic [IFMTBITS-1:0] fpu_ifmt_d, fpu_ifmt_q, fpu_ifmt;
logic [2:0] fpu_rm_d, fpu_rm_q, fpu_rm;
logic fpu_vec_op_d, fpu_vec_op_q, fpu_vec_op;
logic [TRANS_ID_BITS-1:0] fpu_tag_d, fpu_tag_q, fpu_tag;
logic fpu_in_ready, fpu_in_valid;
logic fpu_out_ready, fpu_out_valid;
logic [4:0] fpu_status;
// FSM to handle protocol inversion
logic hold_inputs;
logic use_hold;
//-----------------------------
// Translate inputs
//-----------------------------
always_comb begin : input_translation
automatic logic vec_replication; // control honoring of replication flag
automatic logic replicate_c; // replicate operand C instead of B (for ADD/SUB)
automatic logic check_ah; // Decide for AH from RM field encoding
// Default Values
operand_a_d = operand_a_i;
operand_b_d = operand_b_i; // immediates come through this port unless used as operand
operand_c_d = operand_c_i; // immediates come through this port unless used as operand
fpu_op_d = fpnew_pkg::SGNJ; // sign injection by default
fpu_op_mod_d = 1'b0;
fpu_dstfmt_d = fpnew_pkg::FP32;
fpu_ifmt_d = fpnew_pkg::INT32;
fpu_rm_d = fpu_rm_i;
fpu_vec_op_d = fu_data_i.fu == FPU_VEC;
fpu_tag_d = fu_data_i.trans_id;
vec_replication = fpu_rm_i[0]; // replication bit is sent via rm field
replicate_c = 1'b0;
check_ah = 1'b0; // whether set scalar AH encoding from MSB of rm_i
// Scalar Rounding Modes - some ops encode inside RM but use smaller range
if (!(fpu_rm_i inside {[3'b000:3'b100]}))
fpu_rm_d = fpu_frm_i;
// Vectorial ops always consult FRM
if (fpu_vec_op_d)
fpu_rm_d = fpu_frm_i;
// Formats
unique case (fpu_fmt_i)
// FP32
2'b00: fpu_dstfmt_d = fpnew_pkg::FP32;
// FP64 or FP16ALT (vectorial)
2'b01: fpu_dstfmt_d = fpu_vec_op_d ? fpnew_pkg::FP16ALT : fpnew_pkg::FP64;
// FP16 or FP16ALT (scalar)
2'b10: begin
if (!fpu_vec_op_d && fpu_rm_i==3'b101)
fpu_dstfmt_d = fpnew_pkg::FP16ALT;
else
fpu_dstfmt_d = fpnew_pkg::FP16;
end
// FP8
default: fpu_dstfmt_d = fpnew_pkg::FP8;
endcase
// By default, set src=dst
fpu_srcfmt_d = fpu_dstfmt_d;
// Operations (this can modify the rounding mode field and format!)
unique case (fu_data_i.operator)
// Addition
FADD: begin
fpu_op_d = fpnew_pkg::ADD;
replicate_c = 1'b1; // second operand is in C
end
// Subtraction is modified ADD
FSUB: begin
fpu_op_d = fpnew_pkg::ADD;
fpu_op_mod_d = 1'b1;
replicate_c = 1'b1; // second operand is in C
end
// Multiplication
FMUL: fpu_op_d = fpnew_pkg::MUL;
// Division
FDIV: fpu_op_d = fpnew_pkg::DIV;
// Min/Max - OP is encoded in rm (000-001)
FMIN_MAX: begin
fpu_op_d = fpnew_pkg::MINMAX;
fpu_rm_d = {1'b0, fpu_rm_i[1:0]}; // mask out AH encoding bit
check_ah = 1'b1; // AH has RM MSB encoding
end
// Square Root
FSQRT: fpu_op_d = fpnew_pkg::SQRT;
// Fused Multiply Add
FMADD: fpu_op_d = fpnew_pkg::FMADD;
// Fused Multiply Subtract is modified FMADD
FMSUB: begin
fpu_op_d = fpnew_pkg::FMADD;
fpu_op_mod_d = 1'b1;
end
// Fused Negated Multiply Subtract
FNMSUB: fpu_op_d = fpnew_pkg::FNMSUB;
// Fused Negated Multiply Add is modified FNMSUB
FNMADD: begin
fpu_op_d = fpnew_pkg::FNMSUB;
fpu_op_mod_d = 1'b1;
end
// Float to Int Cast - Op encoded in lowest two imm bits or rm
FCVT_F2I: begin
fpu_op_d = fpnew_pkg::F2I;
// Vectorial Ops encoded in R bit
if (fpu_vec_op_d) begin
fpu_op_mod_d = fpu_rm_i[0];
vec_replication = 1'b0; // no replication, R bit used for op
unique case (fpu_fmt_i)
2'b00: fpu_ifmt_d = fpnew_pkg::INT32;
2'b01,
2'b10: fpu_ifmt_d = fpnew_pkg::INT16;
2'b11: fpu_ifmt_d = fpnew_pkg::INT8;
endcase
// Scalar casts encoded in imm
end else begin
fpu_op_mod_d = operand_c_i[0];
if (operand_c_i[1])
fpu_ifmt_d = fpnew_pkg::INT64;
else
fpu_ifmt_d = fpnew_pkg::INT32;
end
end
// Int to Float Cast - Op encoded in lowest two imm bits or rm
FCVT_I2F: begin
fpu_op_d = fpnew_pkg::I2F;
// Vectorial Ops encoded in R bit
if (fpu_vec_op_d) begin
fpu_op_mod_d = fpu_rm_i[0];
vec_replication = 1'b0; // no replication, R bit used for op
unique case (fpu_fmt_i)
2'b00: fpu_ifmt_d = fpnew_pkg::INT32;
2'b01,
2'b10: fpu_ifmt_d = fpnew_pkg::INT16;
2'b11: fpu_ifmt_d = fpnew_pkg::INT8;
endcase
// Scalar casts encoded in imm
end else begin
fpu_op_mod_d = operand_c_i[0];
if (operand_c_i[1])
fpu_ifmt_d = fpnew_pkg::INT64;
else
fpu_ifmt_d = fpnew_pkg::INT32;
end
end
// Float to Float Cast - Source format encoded in lowest two/three imm bits
FCVT_F2F: begin
fpu_op_d = fpnew_pkg::F2F;
// Vectorial ops encoded in lowest two imm bits
if (fpu_vec_op_d) begin
vec_replication = 1'b0; // no replication for casts (not needed)
unique case (operand_c_i[1:0])
2'b00: fpu_srcfmt_d = fpnew_pkg::FP32;
2'b01: fpu_srcfmt_d = fpnew_pkg::FP16ALT;
2'b10: fpu_srcfmt_d = fpnew_pkg::FP16;
2'b11: fpu_srcfmt_d = fpnew_pkg::FP8;
endcase
// Scalar ops encoded in lowest three imm bits
end else begin
unique case (operand_c_i[2:0])
3'b000: fpu_srcfmt_d = fpnew_pkg::FP32;
3'b001: fpu_srcfmt_d = fpnew_pkg::FP64;
3'b010: fpu_srcfmt_d = fpnew_pkg::FP16;
3'b110: fpu_srcfmt_d = fpnew_pkg::FP16ALT;
3'b011: fpu_srcfmt_d = fpnew_pkg::FP8;
endcase
end
end
// Scalar Sign Injection - op encoded in rm (000-010)
FSGNJ: begin
fpu_op_d = fpnew_pkg::SGNJ;
fpu_rm_d = {1'b0, fpu_rm_i[1:0]}; // mask out AH encoding bit
check_ah = 1'b1; // AH has RM MSB encoding
end
// Move from FPR to GPR - mapped to SGNJ-passthrough since no recoding
FMV_F2X: begin
fpu_op_d = fpnew_pkg::SGNJ;
fpu_rm_d = 3'b011; // passthrough without checking nan-box
fpu_op_mod_d = 1'b1; // no NaN-Boxing
check_ah = 1'b1; // AH has RM MSB encoding
vec_replication = 1'b0; // no replication, we set second operand
end
// Move from GPR to FPR - mapped to NOP since no recoding
FMV_X2F: begin
fpu_op_d = fpnew_pkg::SGNJ;
fpu_rm_d = 3'b011; // passthrough without checking nan-box
check_ah = 1'b1; // AH has RM MSB encoding
vec_replication = 1'b0; // no replication, we set second operand
end
// Scalar Comparisons - op encoded in rm (000-010)
FCMP: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_rm_d = {1'b0, fpu_rm_i[1:0]}; // mask out AH encoding bit
check_ah = 1'b1; // AH has RM MSB encoding
end
// Classification
FCLASS: begin
fpu_op_d = fpnew_pkg::CLASSIFY;
fpu_rm_d = {1'b0, fpu_rm_i[1:0]}; // mask out AH encoding bit - CLASS doesn't care anyways
check_ah = 1'b1; // AH has RM MSB encoding
end
// Vectorial Minimum - set up scalar encoding in rm
VFMIN: begin
fpu_op_d = fpnew_pkg::MINMAX;
fpu_rm_d = 3'b000; // min
end
// Vectorial Maximum - set up scalar encoding in rm
VFMAX: begin
fpu_op_d = fpnew_pkg::MINMAX;
fpu_rm_d = 3'b001; // max
end
// Vectorial Sign Injection - set up scalar encoding in rm
VFSGNJ: begin
fpu_op_d = fpnew_pkg::SGNJ;
fpu_rm_d = 3'b000; // sgnj
end
// Vectorial Negated Sign Injection - set up scalar encoding in rm
VFSGNJN: begin
fpu_op_d = fpnew_pkg::SGNJ;
fpu_rm_d = 3'b001; // sgnjn
end
// Vectorial Xored Sign Injection - set up scalar encoding in rm
VFSGNJX: begin
fpu_op_d = fpnew_pkg::SGNJ;
fpu_rm_d = 3'b010; // sgnjx
end
// Vectorial Equals - set up scalar encoding in rm
VFEQ: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_rm_d = 3'b010; // eq
end
// Vectorial Not Equals - set up scalar encoding in rm
VFNE: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_op_mod_d = 1'b1; // invert output
fpu_rm_d = 3'b010; // eq
end
// Vectorial Less Than - set up scalar encoding in rm
VFLT: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_rm_d = 3'b001; // lt
end
// Vectorial Greater or Equal - set up scalar encoding in rm
VFGE: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_op_mod_d = 1'b1; // invert output
fpu_rm_d = 3'b001; // lt
end
// Vectorial Less or Equal - set up scalar encoding in rm
VFLE: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_rm_d = 3'b000; // le
end
// Vectorial Greater Than - set up scalar encoding in rm
VFGT: begin
fpu_op_d = fpnew_pkg::CMP;
fpu_op_mod_d = 1'b1; // invert output
fpu_rm_d = 3'b000; // le
end
// Vectorial Convert-and-Pack from FP32, lower 4 entries
VFCPKAB_S: begin
fpu_op_d = fpnew_pkg::CPKAB;
fpu_op_mod_d = fpu_rm_i[0]; // A/B selection from R bit
vec_replication = 1'b0; // no replication, R bit used for op
fpu_srcfmt_d = fpnew_pkg::FP32; // Cast from FP32
end
// Vectorial Convert-and-Pack from FP32, upper 4 entries
VFCPKCD_S: begin
fpu_op_d = fpnew_pkg::CPKCD;
fpu_op_mod_d = fpu_rm_i[0]; // C/D selection from R bit
vec_replication = 1'b0; // no replication, R bit used for op
fpu_srcfmt_d = fpnew_pkg::FP32; // Cast from FP32
end
// Vectorial Convert-and-Pack from FP64, lower 4 entries
VFCPKAB_D: begin
fpu_op_d = fpnew_pkg::CPKAB;
fpu_op_mod_d = fpu_rm_i[0]; // A/B selection from R bit
vec_replication = 1'b0; // no replication, R bit used for op
fpu_srcfmt_d = fpnew_pkg::FP64; // Cast from FP64
end
// Vectorial Convert-and-Pack from FP64, upper 4 entries
VFCPKCD_D: begin
fpu_op_d = fpnew_pkg::CPKCD;
fpu_op_mod_d = fpu_rm_i[0]; // C/D selection from R bit
vec_replication = 1'b0; // no replication, R bit used for op
fpu_srcfmt_d = fpnew_pkg::FP64; // Cast from FP64
end
// No changes per default
default: ; //nothing
endcase
// Scalar AH encoding fixing
if (!fpu_vec_op_d && check_ah)
if (fpu_rm_i[2])
fpu_dstfmt_d = fpnew_pkg::FP16ALT;
// Replication
if (fpu_vec_op_d && vec_replication) begin
if (replicate_c) begin
unique case (fpu_dstfmt_d)
fpnew_pkg::FP32: operand_c_d = RVD ? {2{operand_c_i[31:0]}} : operand_c_i;
fpnew_pkg::FP16,
fpnew_pkg::FP16ALT: operand_c_d = RVD ? {4{operand_c_i[15:0]}} : {2{operand_c_i[15:0]}};
fpnew_pkg::FP8: operand_c_d = RVD ? {8{operand_c_i[7:0]}} : {4{operand_c_i[7:0]}};
endcase // fpu_dstfmt_d
end else begin
unique case (fpu_dstfmt_d)
fpnew_pkg::FP32: operand_b_d = RVD ? {2{operand_b_i[31:0]}} : operand_b_i;
fpnew_pkg::FP16,
fpnew_pkg::FP16ALT: operand_b_d = RVD ? {4{operand_b_i[15:0]}} : {2{operand_b_i[15:0]}};
fpnew_pkg::FP8: operand_b_d = RVD ? {8{operand_b_i[7:0]}} : {4{operand_b_i[7:0]}};
endcase // fpu_dstfmt_d
end
end
end
//---------------------------------------------------------
// Upstream protocol inversion: InValid depends on InReady
//---------------------------------------------------------
always_comb begin : p_inputFSM
// Default Values
fpu_ready_o = 1'b0;
fpu_in_valid = 1'b0;
hold_inputs = 1'b0; // hold register disabled
use_hold = 1'b0; // inputs go directly to unit
state_d = state_q; // stay in the same state
// FSM
unique case (state_q)
// Default state, ready for instructions
READY: begin
fpu_ready_o = 1'b1; // Act as if FPU ready
fpu_in_valid = fpu_valid_i; // Forward input valid to FPU
// There is a transaction but the FPU can't handle it
if (fpu_valid_i & ~fpu_in_ready) begin
fpu_ready_o = 1'b0; // No token given to Issue
hold_inputs = 1'b1; // save inputs to the holding register
state_d = STALL; // stall future incoming requests
end
end
// We're stalling the upstream (ready=0)
STALL: begin
fpu_in_valid = 1'b1; // we have data for the FPU
use_hold = 1'b1; // the data comes from the hold reg
// Wait until it's consumed
if (fpu_in_ready) begin
fpu_ready_o = 1'b1; // Give a token to issue
state_d = READY; // accept future requests
end
end
// Default: emit default values
default: ;
endcase
// Flushing will override issue and go back to idle
if (flush_i) begin
state_d = READY;
end
end
// Buffer register and FSM state holding
always_ff @(posedge clk_i or negedge rst_ni) begin : fp_hold_reg
if(~rst_ni) begin
state_q <= READY;
operand_a_q <= '0;
operand_b_q <= '0;
operand_c_q <= '0;
fpu_op_q <= '0;
fpu_op_mod_q <= '0;
fpu_srcfmt_q <= '0;
fpu_dstfmt_q <= '0;
fpu_ifmt_q <= '0;
fpu_rm_q <= '0;
fpu_vec_op_q <= '0;
fpu_tag_q <= '0;
end else begin
state_q <= state_d;
// Hold register is [TRIGGERED] by FSM
if (hold_inputs) begin
operand_a_q <= operand_a_d;
operand_b_q <= operand_b_d;
operand_c_q <= operand_c_d;
fpu_op_q <= fpu_op_d;
fpu_op_mod_q <= fpu_op_mod_d;
fpu_srcfmt_q <= fpu_srcfmt_d;
fpu_dstfmt_q <= fpu_dstfmt_d;
fpu_ifmt_q <= fpu_ifmt_d;
fpu_rm_q <= fpu_rm_d;
fpu_vec_op_q <= fpu_vec_op_d;
fpu_tag_q <= fpu_tag_d;
end
end
end
// Select FPU input data: from register if valid data in register, else directly from input
assign operand_a = use_hold ? operand_a_q : operand_a_d;
assign operand_b = use_hold ? operand_b_q : operand_b_d;
assign operand_c = use_hold ? operand_c_q : operand_c_d;
assign fpu_op = use_hold ? fpu_op_q : fpu_op_d;
assign fpu_op_mod = use_hold ? fpu_op_mod_q : fpu_op_mod_d;
assign fpu_srcfmt = use_hold ? fpu_srcfmt_q : fpu_srcfmt_d;
assign fpu_dstfmt = use_hold ? fpu_dstfmt_q : fpu_dstfmt_d;
assign fpu_ifmt = use_hold ? fpu_ifmt_q : fpu_ifmt_d;
assign fpu_rm = use_hold ? fpu_rm_q : fpu_rm_d;
assign fpu_vec_op = use_hold ? fpu_vec_op_q : fpu_vec_op_d;
assign fpu_tag = use_hold ? fpu_tag_q : fpu_tag_d;
// Consolidate operands
logic [2:0][FLEN-1:0] fpu_operands;
assign fpu_operands[0] = operand_a;
assign fpu_operands[1] = operand_b;
assign fpu_operands[2] = operand_c;
//---------------
// FPU instance
//---------------
fpnew_top #(
.Features ( FPU_FEATURES ),
.Implementation ( FPU_IMPLEMENTATION ),
.TagType ( logic [TRANS_ID_BITS-1:0] )
) i_fpnew_bulk (
.clk_i,
.rst_ni,
.operands_i ( fpu_operands ),
.rnd_mode_i ( fpnew_pkg::roundmode_e'(fpu_rm) ),
.op_i ( fpnew_pkg::operation_e'(fpu_op) ),
.op_mod_i ( fpu_op_mod ),
.src_fmt_i ( fpnew_pkg::fp_format_e'(fpu_srcfmt) ),
.dst_fmt_i ( fpnew_pkg::fp_format_e'(fpu_dstfmt) ),
.int_fmt_i ( fpnew_pkg::int_format_e'(fpu_ifmt) ),
.vectorial_op_i ( fpu_vec_op ),
.tag_i ( fpu_tag ),
.in_valid_i ( fpu_in_valid ),
.in_ready_o ( fpu_in_ready ),
.flush_i,
.result_o,
.status_o ( fpu_status ),
.tag_o ( fpu_trans_id_o ),
.out_valid_o ( fpu_out_valid ),
.out_ready_i ( fpu_out_ready ),
.busy_o ( /* unused */ )
);
// Pack status flag into exception cause, tval ignored in wb, exception is always invalid
assign fpu_exception_o.cause = {59'h0, fpu_status};
assign fpu_exception_o.valid = 1'b0;
// Donwstream write port is dedicated to FPU and always ready
assign fpu_out_ready = 1'b1;
// Downstream valid from unit
assign fpu_valid_o = fpu_out_valid;
end
endmodule