-
Notifications
You must be signed in to change notification settings - Fork 652
/
decoder.sv
1672 lines (1622 loc) · 79.4 KB
/
decoder.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
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// 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.
//
// File: issue_read_operands.sv
// Author: Florian Zaruba <zarubaf@ethz.ch>
// Date: 8.4.2017
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// Description: Issues instruction from the scoreboard and fetches the operands
// This also includes all the forwarding logic
//
module decoder
import ariane_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type branchpredict_sbe_t = logic,
parameter type exception_t = logic,
parameter type irq_ctrl_t = logic,
parameter type scoreboard_entry_t = logic,
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
) (
// Debug (async) request - SUBSYSTEM
input logic debug_req_i,
// PC from fetch stage - FRONTEND
input logic [CVA6Cfg.VLEN-1:0] pc_i,
// Is a compressed instruction - compressed_decoder
input logic is_compressed_i,
// Compressed form of instruction - FRONTEND
input logic [15:0] compressed_instr_i,
// Illegal compressed instruction - compressed_decoder
input logic is_illegal_i,
// Instruction from fetch stage - FRONTEND
input logic [31:0] instruction_i,
// Is a macro instruction - macro_decoder
input logic is_macro_instr_i,
// Is a last macro instruction - macro_decoder
input logic is_last_macro_instr_i,
// Is mvsa01/mva01s macro instruction - macro_decoder
input logic is_double_rd_macro_instr_i,
// Is a branch predict instruction - FRONTEND
input branchpredict_sbe_t branch_predict_i,
// If an exception occured in fetch stage - FRONTEND
input exception_t ex_i,
// Level sensitive (async) interrupts - SUBSYSTEM
input logic [1:0] irq_i,
// Interrupt control status - CSR_REGFILE
input irq_ctrl_t irq_ctrl_i,
// Current privilege level - CSR_REGFILE
input riscv::priv_lvl_t priv_lvl_i,
// Current virtualization mode - CSR_REGFILE
input logic v_i,
// Is debug mode - CSR_REGFILE
input logic debug_mode_i,
// Floating point extension status - CSR_REGFILE
input riscv::xs_t fs_i,
// Virtual floating point extension status - CSR_REGFILE
input riscv::xs_t vfs_i,
// Floating-point dynamic rounding mode - CSR_REGFILE
input logic [2:0] frm_i,
// Vector extension status - CSR_REGFILE
input riscv::xs_t vs_i,
// Trap virtual memory - CSR_REGFILE
input logic tvm_i,
// Timeout wait - CSR_REGFILE
input logic tw_i,
// Virtual timeout wait - CSR_REGFILE
input logic vtw_i,
// Trap sret - CSR_REGFILE
input logic tsr_i,
// Hypervisor user mode - CSR_REGFILE
input logic hu_i,
// Instruction to be added to scoreboard entry - ISSUE_STAGE
output scoreboard_entry_t instruction_o,
// Instruction - ISSUE_STAGE
output logic [31:0] orig_instr_o,
// Is a control flow instruction - ISSUE_STAGE
output logic is_control_flow_instr_o
);
logic illegal_instr;
logic illegal_instr_bm;
logic illegal_instr_zic;
logic illegal_instr_non_bm;
logic virtual_illegal_instr;
// this instruction is an environment call (ecall), it is handled like an exception
logic ecall;
// this instruction is a software break-point
logic ebreak;
// this instruction needs floating-point rounding-mode verification
logic check_fprm;
riscv::instruction_t instr;
assign instr = riscv::instruction_t'(instruction_i);
// transformed instruction
logic [31:0] tinst;
// --------------------
// Immediate select
// --------------------
enum logic [3:0] {
NOIMM,
IIMM,
SIMM,
SBIMM,
UIMM,
JIMM,
RS3
} imm_select;
logic [CVA6Cfg.XLEN-1:0] imm_i_type;
logic [CVA6Cfg.XLEN-1:0] imm_s_type;
logic [CVA6Cfg.XLEN-1:0] imm_sb_type;
logic [CVA6Cfg.XLEN-1:0] imm_u_type;
logic [CVA6Cfg.XLEN-1:0] imm_uj_type;
logic [CVA6Cfg.XLEN-1:0] imm_bi_type;
// ---------------------------------------
// Accelerator instructions' first-pass decoder
// ---------------------------------------
logic is_accel;
scoreboard_entry_t acc_instruction;
logic acc_illegal_instr;
logic acc_is_control_flow_instr;
if (CVA6Cfg.EnableAccelerator) begin : gen_accel_decoder
// This module is responsible for a light-weight decoding of accelerator instructions,
// identifying them, but also whether they read/write scalar registers.
// Accelerators are supposed to define this module.
cva6_accel_first_pass_decoder #(
.CVA6Cfg(CVA6Cfg),
.scoreboard_entry_t(scoreboard_entry_t)
) i_accel_decoder (
.instruction_i(instruction_i),
.fs_i(fs_i),
.vs_i(vs_i),
.is_accel_o(is_accel),
.instruction_o(acc_instruction),
.illegal_instr_o(acc_illegal_instr),
.is_control_flow_instr_o(acc_is_control_flow_instr)
);
end : gen_accel_decoder
else begin
assign is_accel = 1'b0;
assign acc_instruction = '0;
assign acc_illegal_instr = 1'b1; // this should never propagate
assign acc_is_control_flow_instr = 1'b0;
end
always_comb begin : decoder
imm_select = NOIMM;
is_control_flow_instr_o = 1'b0;
illegal_instr = 1'b0;
illegal_instr_non_bm = 1'b0;
illegal_instr_bm = 1'b0;
illegal_instr_zic = 1'b0;
virtual_illegal_instr = 1'b0;
instruction_o.pc = pc_i;
instruction_o.trans_id = '0;
instruction_o.fu = NONE;
instruction_o.op = ariane_pkg::ADD;
instruction_o.rs1 = '0;
instruction_o.rs2 = '0;
instruction_o.rd = '0;
instruction_o.use_pc = 1'b0;
instruction_o.is_compressed = is_compressed_i;
instruction_o.is_macro_instr = is_macro_instr_i;
instruction_o.is_last_macro_instr = is_last_macro_instr_i;
instruction_o.is_double_rd_macro_instr = is_double_rd_macro_instr_i;
instruction_o.use_zimm = 1'b0;
instruction_o.bp = branch_predict_i;
instruction_o.vfp = 1'b0;
tinst = '0;
ecall = 1'b0;
ebreak = 1'b0;
check_fprm = 1'b0;
if (~ex_i.valid) begin
case (instr.rtype.opcode)
riscv::OpcodeSystem: begin
instruction_o.fu = CSR;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rs2[4:0] = instr.rtype.rs2; //TODO: needs to be checked if better way is available
instruction_o.rd[4:0] = instr.itype.rd;
unique case (instr.itype.funct3)
3'b000: begin
// check if the RD and and RS1 fields are zero, this may be reset for the SENCE.VMA instruction
if (instr.itype.rs1 != '0 || instr.itype.rd != '0) begin
if (CVA6Cfg.RVH && v_i) begin
virtual_illegal_instr = 1'b1;
end else begin
illegal_instr = 1'b1;
end
end
// decode the immiediate field
case (instr.itype.imm)
// ECALL -> inject exception
12'b0: ecall = 1'b1;
// EBREAK -> inject exception
12'b1: ebreak = 1'b1;
// SRET
12'b1_0000_0010: begin
if (CVA6Cfg.RVS) begin
instruction_o.op = ariane_pkg::SRET;
// check privilege level, SRET can only be executed in S and M mode
// we'll just decode an illegal instruction if we are in the wrong privilege level
if (CVA6Cfg.RVU && priv_lvl_i == riscv::PRIV_LVL_U) begin
if (CVA6Cfg.RVH && v_i) begin
virtual_illegal_instr = 1'b1;
end else begin
illegal_instr = 1'b1;
end
// do not change privilege level if this is an illegal instruction
instruction_o.op = ariane_pkg::ADD;
end
// if we are in S-Mode and Trap SRET (tsr) is set -> trap on illegal instruction
if (priv_lvl_i == riscv::PRIV_LVL_S && tsr_i) begin
if (CVA6Cfg.RVH && v_i) begin
virtual_illegal_instr = 1'b1;
end else begin
illegal_instr = 1'b1;
end
// do not change privilege level if this is an illegal instruction
instruction_o.op = ariane_pkg::ADD;
end
end else begin
illegal_instr = 1'b1;
instruction_o.op = ariane_pkg::ADD;
end
end
// MRET
12'b11_0000_0010: begin
instruction_o.op = ariane_pkg::MRET;
// check privilege level, MRET can only be executed in M mode
// otherwise we decode an illegal instruction
if ((CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S) || (CVA6Cfg.RVU && priv_lvl_i == riscv::PRIV_LVL_U))
illegal_instr = 1'b1;
end
// DRET
12'b111_1011_0010: begin
instruction_o.op = ariane_pkg::DRET;
if (CVA6Cfg.DebugEn) begin
// check that we are in debug mode when executing this instruction
illegal_instr = (!debug_mode_i) ? 1'b1 : illegal_instr;
end else begin
illegal_instr = 1'b1;
end
end
// WFI
12'b1_0000_0101: begin
instruction_o.op = ariane_pkg::WFI;
// if timeout wait is set, trap on an illegal instruction in S Mode
// (after 0 cycles timeout)
if (CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S && tw_i) begin
illegal_instr = 1'b1;
instruction_o.op = ariane_pkg::ADD;
end
if (CVA6Cfg.RVH && priv_lvl_i == riscv::PRIV_LVL_S && v_i && vtw_i && !tw_i) begin
virtual_illegal_instr = 1'b1;
instruction_o.op = ariane_pkg::ADD;
end
// we don't support U mode interrupts so WFI is illegal in this context
if (CVA6Cfg.RVU && priv_lvl_i == riscv::PRIV_LVL_U) begin
if (CVA6Cfg.RVH && v_i) virtual_illegal_instr = 1'b1;
else illegal_instr = 1'b1;
instruction_o.op = ariane_pkg::ADD;
end
end
// SFENCE.VMA
default: begin
if (instr.instr[31:25] == 7'b1001) begin
// check privilege level, SFENCE.VMA can only be executed in M/S mode
// only if S mode is supported
// otherwise decode an illegal instruction
if (CVA6Cfg.RVH && v_i) begin
virtual_illegal_instr = (priv_lvl_i == riscv::PRIV_LVL_S) ? 1'b0 : 1'b1;
end else begin
illegal_instr = (CVA6Cfg.RVS && (priv_lvl_i inside {riscv::PRIV_LVL_M, riscv::PRIV_LVL_S}) && instr.itype.rd == '0) ? 1'b0 : 1'b1;
end
instruction_o.op = ariane_pkg::SFENCE_VMA;
// check TVM flag and intercept SFENCE.VMA call if necessary
if (CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S && tvm_i) begin
if (CVA6Cfg.RVH && v_i) virtual_illegal_instr = 1'b1;
else illegal_instr = 1'b1;
end
end else if (CVA6Cfg.RVH) begin
if (instr.instr[31:25] == 7'b10001) begin
// check privilege level, HFENCE.VVMA can only be executed in M/S mode
// otherwise decode an illegal instruction or virtual illegal instruction
if (v_i) begin
virtual_illegal_instr = 1'b1;
end else begin
illegal_instr = (priv_lvl_i inside {riscv::PRIV_LVL_M, riscv::PRIV_LVL_S}) ? 1'b0 : 1'b1;
end
instruction_o.op = ariane_pkg::HFENCE_VVMA;
end else if (instr.instr[31:25] == 7'b110001) begin
// check privilege level, HFENCE.GVMA can only be executed in M/S mode
// otherwise decode an illegal instruction or virtual illegal instruction
if (v_i) begin
virtual_illegal_instr = 1'b1;
end else begin
illegal_instr = (priv_lvl_i inside {riscv::PRIV_LVL_M, riscv::PRIV_LVL_S}) ? 1'b0 : 1'b1;
end
instruction_o.op = ariane_pkg::HFENCE_GVMA;
// check TVM flag and intercept HFENCE.GVMA call if necessary
if (priv_lvl_i == riscv::PRIV_LVL_S && !v_i && tvm_i) illegal_instr = 1'b1;
end else begin
illegal_instr = 1'b1;
end
end else begin
illegal_instr = 1'b1;
end
end
endcase
end
3'b100: begin
// Hypervisor load/store instructions
if (CVA6Cfg.RVH) begin
if (instr.instr[25] != 1'b0) begin
instruction_o.fu = STORE;
imm_select = NOIMM;
instruction_o.rs1[4:0] = instr.stype.rs1;
instruction_o.rs2[4:0] = instr.stype.rs2;
end else begin
instruction_o.fu = LOAD;
imm_select = NOIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
end
// Hypervisor load/store instructions when V=1 cause virtual instruction
if (v_i) virtual_illegal_instr = 1'b1;
// Hypervisor load/store instructions in U-mode when hstatus.HU=0 cause an illegal instruction trap.
else if (!hu_i && priv_lvl_i == riscv::PRIV_LVL_U) illegal_instr = 1'b1;
unique case (instr.rtype.funct7)
7'b011_0000: begin
if (instr.rtype.rs2 == 5'b0) begin
instruction_o.op = ariane_pkg::HLV_B;
end
if (instr.rtype.rs2 == 5'b1) begin
instruction_o.op = ariane_pkg::HLV_BU;
end
end
7'b011_0010: begin
if (instr.rtype.rs2 == 5'b0) begin
instruction_o.op = ariane_pkg::HLV_H;
end
if (instr.rtype.rs2 == 5'b1) begin
instruction_o.op = ariane_pkg::HLV_HU;
end
if (instr.rtype.rs2 == 5'b11) begin
instruction_o.op = ariane_pkg::HLVX_HU;
end
end
7'b011_0100: begin
if (instr.rtype.rs2 == 5'b0) begin
instruction_o.op = ariane_pkg::HLV_W;
end
if (instr.rtype.rs2 == 5'b1) begin
instruction_o.op = ariane_pkg::HLV_WU;
end
if (instr.rtype.rs2 == 5'b11) begin
instruction_o.op = ariane_pkg::HLVX_WU;
end
end
7'b011_0001: instruction_o.op = ariane_pkg::HSV_B;
7'b011_0011: instruction_o.op = ariane_pkg::HSV_H;
7'b011_0101: instruction_o.op = ariane_pkg::HSV_W;
7'b011_0110: instruction_o.op = ariane_pkg::HLV_D;
7'b011_0111: instruction_o.op = ariane_pkg::HSV_D;
default: illegal_instr = 1'b1;
endcase
tinst = {
instr.rtype.funct7,
instr.rtype.rs2,
5'b0,
instr.rtype.funct3,
instr.rtype.rd,
instr.rtype.opcode
};
end else begin
illegal_instr = 1'b1;
end
end
// atomically swaps values in the CSR and integer register
3'b001: begin // CSRRW
imm_select = IIMM;
instruction_o.op = ariane_pkg::CSR_WRITE;
end
// atomically set values in the CSR and write back to rd
3'b010: begin // CSRRS
imm_select = IIMM;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_SET;
end
// atomically clear values in the CSR and write back to rd
3'b011: begin // CSRRC
imm_select = IIMM;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_CLEAR;
end
// use zimm and iimm
3'b101: begin // CSRRWI
instruction_o.rs1[4:0] = instr.itype.rs1;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
instruction_o.op = ariane_pkg::CSR_WRITE;
end
3'b110: begin // CSRRSI
instruction_o.rs1[4:0] = instr.itype.rs1;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_SET;
end
3'b111: begin // CSRRCI
instruction_o.rs1[4:0] = instr.itype.rs1;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_CLEAR;
end
default: illegal_instr = 1'b1;
endcase
end
// Memory ordering instructions
riscv::OpcodeMiscMem: begin
instruction_o.fu = CSR;
instruction_o.rs1 = '0;
instruction_o.rs2 = '0;
instruction_o.rd = '0;
case (instr.stype.funct3)
// FENCE
// Currently implemented as a whole DCache flush boldly ignoring other things
3'b000: instruction_o.op = ariane_pkg::FENCE;
// FENCE.I
3'b001: instruction_o.op = ariane_pkg::FENCE_I;
default: illegal_instr = 1'b1;
endcase
end
// --------------------------
// Reg-Reg Operations
// --------------------------
riscv::OpcodeOp: begin
// --------------------------------------------
// Vectorial Floating-Point Reg-Reg Operations
// --------------------------------------------
if (instr.rvftype.funct2 == 2'b10) begin // Prefix 10 for all Xfvec ops
// only generate decoder if FP extensions are enabled (static)
if (CVA6Cfg.FpPresent && CVA6Cfg.XFVec && fs_i != riscv::Off && ((CVA6Cfg.RVH && (!v_i || vfs_i != riscv::Off)) || !CVA6Cfg.RVH)) begin
automatic logic allow_replication; // control honoring of replication flag
instruction_o.fu = FPU_VEC; // Same unit, but sets 'vectorial' signal
instruction_o.rs1[4:0] = instr.rvftype.rs1;
instruction_o.rs2[4:0] = instr.rvftype.rs2;
instruction_o.rd[4:0] = instr.rvftype.rd;
check_fprm = 1'b1;
allow_replication = 1'b1;
// decode vectorial FP instruction
unique case (instr.rvftype.vecfltop)
5'b00001: begin
instruction_o.op = ariane_pkg::FADD; // vfadd.vfmt - Vectorial FP Addition
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2[4:0] = instr.rvftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
end
5'b00010: begin
instruction_o.op = ariane_pkg::FSUB; // vfsub.vfmt - Vectorial FP Subtraction
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2[4:0] = instr.rvftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
end
5'b00011:
instruction_o.op = ariane_pkg::FMUL; // vfmul.vfmt - Vectorial FP Multiplication
5'b00100:
instruction_o.op = ariane_pkg::FDIV; // vfdiv.vfmt - Vectorial FP Division
5'b00101: begin
instruction_o.op = ariane_pkg::VFMIN; // vfmin.vfmt - Vectorial FP Minimum
check_fprm = 1'b0; // rounding mode irrelevant
end
5'b00110: begin
instruction_o.op = ariane_pkg::VFMAX; // vfmax.vfmt - Vectorial FP Maximum
check_fprm = 1'b0; // rounding mode irrelevant
end
5'b00111: begin
instruction_o.op = ariane_pkg::FSQRT; // vfsqrt.vfmt - Vectorial FP Square Root
allow_replication = 1'b0; // only one operand
if (instr.rvftype.rs2 != 5'b00000) illegal_instr = 1'b1; // rs2 must be 0
end
5'b01000: begin
instruction_o.op = ariane_pkg::FMADD; // vfmac.vfmt - Vectorial FP Multiply-Accumulate
imm_select = SIMM; // rd into result field (upper bits don't matter)
end
5'b01001: begin
instruction_o.op = ariane_pkg::FMSUB; // vfmre.vfmt - Vectorial FP Multiply-Reduce
imm_select = SIMM; // rd into result field (upper bits don't matter)
end
5'b01100: begin
unique case (instr.rvftype.rs2) inside // operation encoded in rs2, `inside` for matching ?
5'b00000: begin
instruction_o.rs2[4:0] = instr.rvftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
if (instr.rvftype.repl)
instruction_o.op = ariane_pkg::FMV_X2F; // vfmv.vfmt.x - GPR to FPR Move
else instruction_o.op = ariane_pkg::FMV_F2X; // vfmv.x.vfmt - FPR to GPR Move
check_fprm = 1'b0; // no rounding for moves
end
5'b00001: begin
instruction_o.op = ariane_pkg::FCLASS; // vfclass.vfmt - Vectorial FP Classify
check_fprm = 1'b0; // no rounding for classification
allow_replication = 1'b0; // R must not be set
end
5'b00010:
instruction_o.op = ariane_pkg::FCVT_F2I; // vfcvt.x.vfmt - Vectorial FP to Int Conversion
5'b00011:
instruction_o.op = ariane_pkg::FCVT_I2F; // vfcvt.vfmt.x - Vectorial Int to FP Conversion
5'b001??: begin
instruction_o.op = ariane_pkg::FCVT_F2F; // vfcvt.vfmt.vfmt - Vectorial FP to FP Conversion
instruction_o.rs2[4:0] = instr.rvftype.rd; // set rs2 = rd as target vector for conversion
imm_select = IIMM; // rs2 holds part of the intruction
// TODO CHECK R bit for valid fmt combinations
// determine source format
unique case (instr.rvftype.rs2[21:20])
// Only process instruction if corresponding extension is active (static)
2'b00: if (~CVA6Cfg.RVFVec) illegal_instr = 1'b1;
2'b01: if (~CVA6Cfg.XF16ALTVec) illegal_instr = 1'b1;
2'b10: if (~CVA6Cfg.XF16Vec) illegal_instr = 1'b1;
2'b11: if (~CVA6Cfg.XF8Vec) illegal_instr = 1'b1;
default: illegal_instr = 1'b1;
endcase
end
default: illegal_instr = 1'b1;
endcase
end
5'b01101: begin
check_fprm = 1'b0; // no rounding for sign-injection
instruction_o.op = ariane_pkg::VFSGNJ; // vfsgnj.vfmt - Vectorial FP Sign Injection
end
5'b01110: begin
check_fprm = 1'b0; // no rounding for sign-injection
instruction_o.op = ariane_pkg::VFSGNJN; // vfsgnjn.vfmt - Vectorial FP Negated Sign Injection
end
5'b01111: begin
check_fprm = 1'b0; // no rounding for sign-injection
instruction_o.op = ariane_pkg::VFSGNJX; // vfsgnjx.vfmt - Vectorial FP XORed Sign Injection
end
5'b10000: begin
check_fprm = 1'b0; // no rounding for comparisons
instruction_o.op = ariane_pkg::VFEQ; // vfeq.vfmt - Vectorial FP Equality
end
5'b10001: begin
check_fprm = 1'b0; // no rounding for comparisons
instruction_o.op = ariane_pkg::VFNE; // vfne.vfmt - Vectorial FP Non-Equality
end
5'b10010: begin
check_fprm = 1'b0; // no rounding for comparisons
instruction_o.op = ariane_pkg::VFLT; // vfle.vfmt - Vectorial FP Less Than
end
5'b10011: begin
check_fprm = 1'b0; // no rounding for comparisons
instruction_o.op = ariane_pkg::VFGE; // vfge.vfmt - Vectorial FP Greater or Equal
end
5'b10100: begin
check_fprm = 1'b0; // no rounding for comparisons
instruction_o.op = ariane_pkg::VFLE; // vfle.vfmt - Vectorial FP Less or Equal
end
5'b10101: begin
check_fprm = 1'b0; // no rounding for comparisons
instruction_o.op = ariane_pkg::VFGT; // vfgt.vfmt - Vectorial FP Greater Than
end
5'b11000: begin
instruction_o.op = ariane_pkg::VFCPKAB_S; // vfcpka/b.vfmt.s - Vectorial FP Cast-and-Pack from 2x FP32, lowest 4 entries
imm_select = SIMM; // rd into result field (upper bits don't matter)
if (~CVA6Cfg.RVF)
illegal_instr = 1'b1; // if we don't support RVF, we can't cast from FP32
// check destination format
unique case (instr.rvftype.vfmt)
// Only process instruction if corresponding extension is active and FLEN suffices (static)
2'b00: begin
if (~CVA6Cfg.RVFVec)
illegal_instr = 1'b1; // destination vector not supported
if (instr.rvftype.repl)
illegal_instr = 1'b1; // no entries 2/3 in vector of 2 fp32
end
2'b01: begin
if (~CVA6Cfg.XF16ALTVec)
illegal_instr = 1'b1; // destination vector not supported
end
2'b10: begin
if (~CVA6Cfg.XF16Vec)
illegal_instr = 1'b1; // destination vector not supported
end
2'b11: begin
if (~CVA6Cfg.XF8Vec)
illegal_instr = 1'b1; // destination vector not supported
end
default: illegal_instr = 1'b1;
endcase
end
5'b11001: begin
instruction_o.op = ariane_pkg::VFCPKCD_S; // vfcpkc/d.vfmt.s - Vectorial FP Cast-and-Pack from 2x FP32, second 4 entries
imm_select = SIMM; // rd into result field (upper bits don't matter)
if (~CVA6Cfg.RVF)
illegal_instr = 1'b1; // if we don't support RVF, we can't cast from FP32
// check destination format
unique case (instr.rvftype.vfmt)
// Only process instruction if corresponding extension is active and FLEN suffices (static)
2'b00: illegal_instr = 1'b1; // no entries 4-7 in vector of 2 FP32
2'b01: illegal_instr = 1'b1; // no entries 4-7 in vector of 4 FP16ALT
2'b10: illegal_instr = 1'b1; // no entries 4-7 in vector of 4 FP16
2'b11: begin
if (~CVA6Cfg.XF8Vec)
illegal_instr = 1'b1; // destination vector not supported
end
default: illegal_instr = 1'b1;
endcase
end
5'b11010: begin
instruction_o.op = ariane_pkg::VFCPKAB_D; // vfcpka/b.vfmt.d - Vectorial FP Cast-and-Pack from 2x FP64, lowest 4 entries
imm_select = SIMM; // rd into result field (upper bits don't matter)
if (~CVA6Cfg.RVD)
illegal_instr = 1'b1; // if we don't support RVD, we can't cast from FP64
// check destination format
unique case (instr.rvftype.vfmt)
// Only process instruction if corresponding extension is active and FLEN suffices (static)
2'b00: begin
if (~CVA6Cfg.RVFVec)
illegal_instr = 1'b1; // destination vector not supported
if (instr.rvftype.repl)
illegal_instr = 1'b1; // no entries 2/3 in vector of 2 fp32
end
2'b01: begin
if (~CVA6Cfg.XF16ALTVec)
illegal_instr = 1'b1; // destination vector not supported
end
2'b10: begin
if (~CVA6Cfg.XF16Vec)
illegal_instr = 1'b1; // destination vector not supported
end
2'b11: begin
if (~CVA6Cfg.XF8Vec)
illegal_instr = 1'b1; // destination vector not supported
end
default: illegal_instr = 1'b1;
endcase
end
5'b11011: begin
instruction_o.op = ariane_pkg::VFCPKCD_D; // vfcpka/b.vfmt.d - Vectorial FP Cast-and-Pack from 2x FP64, second 4 entries
imm_select = SIMM; // rd into result field (upper bits don't matter)
if (~CVA6Cfg.RVD)
illegal_instr = 1'b1; // if we don't support RVD, we can't cast from FP64
// check destination format
unique case (instr.rvftype.vfmt)
// Only process instruction if corresponding extension is active and FLEN suffices (static)
2'b00: illegal_instr = 1'b1; // no entries 4-7 in vector of 2 FP32
2'b01: illegal_instr = 1'b1; // no entries 4-7 in vector of 4 FP16ALT
2'b10: illegal_instr = 1'b1; // no entries 4-7 in vector of 4 FP16
2'b11: begin
if (~CVA6Cfg.XF8Vec)
illegal_instr = 1'b1; // destination vector not supported
end
default: illegal_instr = 1'b1;
endcase
end
default: illegal_instr = 1'b1;
endcase
// check format
unique case (instr.rvftype.vfmt)
// Only process instruction if corresponding extension is active (static)
2'b00: if (~CVA6Cfg.RVFVec) illegal_instr = 1'b1;
2'b01: if (~CVA6Cfg.XF16ALTVec) illegal_instr = 1'b1;
2'b10: if (~CVA6Cfg.XF16Vec) illegal_instr = 1'b1;
2'b11: if (~CVA6Cfg.XF8Vec) illegal_instr = 1'b1;
default: illegal_instr = 1'b1;
endcase
// check disallowed replication
if (~allow_replication & instr.rvftype.repl) illegal_instr = 1'b1;
// check rounding mode
if (check_fprm) begin
unique case (frm_i) inside // actual rounding mode from frm csr
[3'b000 : 3'b100]: ; //legal rounding modes
default: illegal_instr = 1'b1;
endcase
end
end else begin // No vectorial FP enabled (static)
illegal_instr = 1'b1;
end
// ---------------------------
// Integer Reg-Reg Operations
// ---------------------------
end else begin
if (CVA6Cfg.RVB) begin
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001 || ((instr.rtype.funct7 == 7'b000_0101) && !(instr.rtype.funct3[14]))) ? MULT : ALU;
end else begin
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
end
instruction_o.rs1[4:0] = instr.rtype.rs1;
instruction_o.rs2[4:0] = instr.rtype.rs2;
instruction_o.rd[4:0] = instr.rtype.rd;
unique case ({
instr.rtype.funct7, instr.rtype.funct3
})
{7'b000_0000, 3'b000} : instruction_o.op = ariane_pkg::ADD; // Add
{7'b010_0000, 3'b000} : instruction_o.op = ariane_pkg::SUB; // Sub
{7'b000_0000, 3'b010} : instruction_o.op = ariane_pkg::SLTS; // Set Lower Than
{
7'b000_0000, 3'b011
} :
instruction_o.op = ariane_pkg::SLTU; // Set Lower Than Unsigned
{7'b000_0000, 3'b100} : instruction_o.op = ariane_pkg::XORL; // Xor
{7'b000_0000, 3'b110} : instruction_o.op = ariane_pkg::ORL; // Or
{7'b000_0000, 3'b111} : instruction_o.op = ariane_pkg::ANDL; // And
{7'b000_0000, 3'b001} : instruction_o.op = ariane_pkg::SLL; // Shift Left Logical
{7'b000_0000, 3'b101} : instruction_o.op = ariane_pkg::SRL; // Shift Right Logical
{7'b010_0000, 3'b101} : instruction_o.op = ariane_pkg::SRA; // Shift Right Arithmetic
// Multiplications
{7'b000_0001, 3'b000} : instruction_o.op = ariane_pkg::MUL;
{7'b000_0001, 3'b001} : instruction_o.op = ariane_pkg::MULH;
{7'b000_0001, 3'b010} : instruction_o.op = ariane_pkg::MULHSU;
{7'b000_0001, 3'b011} : instruction_o.op = ariane_pkg::MULHU;
{7'b000_0001, 3'b100} : instruction_o.op = ariane_pkg::DIV;
{7'b000_0001, 3'b101} : instruction_o.op = ariane_pkg::DIVU;
{7'b000_0001, 3'b110} : instruction_o.op = ariane_pkg::REM;
{7'b000_0001, 3'b111} : instruction_o.op = ariane_pkg::REMU;
default: begin
illegal_instr_non_bm = 1'b1;
end
endcase
if (CVA6Cfg.RVB) begin
unique case ({
instr.rtype.funct7, instr.rtype.funct3
})
//Logical with Negate
{7'b010_0000, 3'b111} : instruction_o.op = ariane_pkg::ANDN; // Andn
{7'b010_0000, 3'b110} : instruction_o.op = ariane_pkg::ORN; // Orn
{7'b010_0000, 3'b100} : instruction_o.op = ariane_pkg::XNOR; // Xnor
//Shift and Add (Bitmanip)
{7'b001_0000, 3'b010} : instruction_o.op = ariane_pkg::SH1ADD; // Sh1add
{7'b001_0000, 3'b100} : instruction_o.op = ariane_pkg::SH2ADD; // Sh2add
{7'b001_0000, 3'b110} : instruction_o.op = ariane_pkg::SH3ADD; // Sh3add
// Integer maximum/minimum
{7'b000_0101, 3'b110} : instruction_o.op = ariane_pkg::MAX; // max
{7'b000_0101, 3'b111} : instruction_o.op = ariane_pkg::MAXU; // maxu
{7'b000_0101, 3'b100} : instruction_o.op = ariane_pkg::MIN; // min
{7'b000_0101, 3'b101} : instruction_o.op = ariane_pkg::MINU; // minu
// Single bit instructions
{7'b010_0100, 3'b001} : instruction_o.op = ariane_pkg::BCLR; // bclr
{7'b010_0100, 3'b101} : instruction_o.op = ariane_pkg::BEXT; // bext
{7'b011_0100, 3'b001} : instruction_o.op = ariane_pkg::BINV; // binv
{7'b001_0100, 3'b001} : instruction_o.op = ariane_pkg::BSET; // bset
// Carry-Less-Multiplication (clmul, clmulh, clmulr)
{7'b000_0101, 3'b001} : instruction_o.op = ariane_pkg::CLMUL; // clmul
{7'b000_0101, 3'b011} : instruction_o.op = ariane_pkg::CLMULH; // clmulh
{7'b000_0101, 3'b010} : instruction_o.op = ariane_pkg::CLMULR; // clmulr
// Bitwise Shifting
{7'b011_0000, 3'b001} : instruction_o.op = ariane_pkg::ROL; // rol
{7'b011_0000, 3'b101} : instruction_o.op = ariane_pkg::ROR; // ror
// Zero Extend Op RV32 encoding
{
7'b000_0100, 3'b100
} : begin
if (!CVA6Cfg.IS_XLEN64 && instr.instr[24:20] == 5'b00000)
instruction_o.op = ariane_pkg::ZEXTH;
else illegal_instr_bm = 1'b1;
end
default: begin
illegal_instr_bm = 1'b1;
end
endcase
end
if (CVA6Cfg.RVZiCond) begin
unique case ({
instr.rtype.funct7, instr.rtype.funct3
})
//Conditional move
{7'b000_0111, 3'b101} : instruction_o.op = ariane_pkg::CZERO_EQZ; // czero.eqz
{7'b000_0111, 3'b111} : instruction_o.op = ariane_pkg::CZERO_NEZ; // czero.nez
default: begin
illegal_instr_zic = 1'b1;
end
endcase
end
//VCS coverage on
unique case ({
CVA6Cfg.RVB, CVA6Cfg.RVZiCond
})
2'b00: illegal_instr = illegal_instr_non_bm;
2'b01: illegal_instr = illegal_instr_non_bm & illegal_instr_zic;
2'b10: illegal_instr = illegal_instr_non_bm & illegal_instr_bm;
2'b11: illegal_instr = illegal_instr_non_bm & illegal_instr_bm & illegal_instr_zic;
endcase
end
end
// --------------------------
// 32bit Reg-Reg Operations
// --------------------------
riscv::OpcodeOp32: begin
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
instruction_o.rs1[4:0] = instr.rtype.rs1;
instruction_o.rs2[4:0] = instr.rtype.rs2;
instruction_o.rd[4:0] = instr.rtype.rd;
if (CVA6Cfg.IS_XLEN64) begin
unique case ({
instr.rtype.funct7, instr.rtype.funct3
})
{7'b000_0000, 3'b000} : instruction_o.op = ariane_pkg::ADDW; // addw
{7'b010_0000, 3'b000} : instruction_o.op = ariane_pkg::SUBW; // subw
{7'b000_0000, 3'b001} : instruction_o.op = ariane_pkg::SLLW; // sllw
{7'b000_0000, 3'b101} : instruction_o.op = ariane_pkg::SRLW; // srlw
{7'b010_0000, 3'b101} : instruction_o.op = ariane_pkg::SRAW; // sraw
// Multiplications
{7'b000_0001, 3'b000} : instruction_o.op = ariane_pkg::MULW;
{7'b000_0001, 3'b100} : instruction_o.op = ariane_pkg::DIVW;
{7'b000_0001, 3'b101} : instruction_o.op = ariane_pkg::DIVUW;
{7'b000_0001, 3'b110} : instruction_o.op = ariane_pkg::REMW;
{7'b000_0001, 3'b111} : instruction_o.op = ariane_pkg::REMUW;
default: illegal_instr_non_bm = 1'b1;
endcase
if (CVA6Cfg.RVB) begin
unique case ({
instr.rtype.funct7, instr.rtype.funct3
})
// Shift with Add (Unsigned Word)
{7'b001_0000, 3'b010}: instruction_o.op = ariane_pkg::SH1ADDUW; // sh1add.uw
{7'b001_0000, 3'b100}: instruction_o.op = ariane_pkg::SH2ADDUW; // sh2add.uw
{7'b001_0000, 3'b110}: instruction_o.op = ariane_pkg::SH3ADDUW; // sh3add.uw
// Unsigned word Op's
{7'b000_0100, 3'b000}: instruction_o.op = ariane_pkg::ADDUW; // add.uw
// Bitwise Shifting
{7'b011_0000, 3'b001}: instruction_o.op = ariane_pkg::ROLW; // rolw
{7'b011_0000, 3'b101}: instruction_o.op = ariane_pkg::RORW; // rorw
// Zero Extend Op RV64 encoding
{7'b000_0100, 3'b100}:
begin
if (instr.instr[24:20] == 5'b00000)
instruction_o.op = ariane_pkg::ZEXTH;
else
illegal_instr_bm = 1'b1;
end
default: illegal_instr_bm = 1'b1;
endcase
illegal_instr = illegal_instr_non_bm & illegal_instr_bm;
end else begin
illegal_instr = illegal_instr_non_bm;
end
end else illegal_instr = 1'b1;
end
// --------------------------------
// Reg-Immediate Operations
// --------------------------------
riscv::OpcodeOpImm: begin
instruction_o.fu = ALU;
imm_select = IIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
unique case (instr.itype.funct3)
3'b000: instruction_o.op = ariane_pkg::ADD; // Add Immediate
3'b010: instruction_o.op = ariane_pkg::SLTS; // Set to one if Lower Than Immediate
3'b011:
instruction_o.op = ariane_pkg::SLTU; // Set to one if Lower Than Immediate Unsigned
3'b100: instruction_o.op = ariane_pkg::XORL; // Exclusive Or with Immediate
3'b110: instruction_o.op = ariane_pkg::ORL; // Or with Immediate
3'b111: instruction_o.op = ariane_pkg::ANDL; // And with Immediate
3'b001: begin
instruction_o.op = ariane_pkg::SLL; // Shift Left Logical by Immediate
if (instr.instr[31:26] != 6'b0) illegal_instr_non_bm = 1'b1;
if (instr.instr[25] != 1'b0 && CVA6Cfg.XLEN == 32) illegal_instr_non_bm = 1'b1;
end
3'b101: begin
if (instr.instr[31:26] == 6'b0)
instruction_o.op = ariane_pkg::SRL; // Shift Right Logical by Immediate
else if (instr.instr[31:26] == 6'b010_000)
instruction_o.op = ariane_pkg::SRA; // Shift Right Arithmetically by Immediate
else illegal_instr_non_bm = 1'b1;
if (instr.instr[25] != 1'b0 && CVA6Cfg.XLEN == 32) illegal_instr_non_bm = 1'b1;
end
endcase
if (CVA6Cfg.RVB) begin
unique case (instr.itype.funct3)
3'b001: begin
if (instr.instr[31:25] == 7'b0110000) begin
if (instr.instr[22:20] == 3'b100) instruction_o.op = ariane_pkg::SEXTB;
else if (instr.instr[22:20] == 3'b101) instruction_o.op = ariane_pkg::SEXTH;
else if (instr.instr[22:20] == 3'b010) instruction_o.op = ariane_pkg::CPOP;
else if (instr.instr[22:20] == 3'b000) instruction_o.op = ariane_pkg::CLZ;
else if (instr.instr[22:20] == 3'b001) instruction_o.op = ariane_pkg::CTZ;
end else if (instr.instr[31:26] == 6'b010010) instruction_o.op = ariane_pkg::BCLRI;
else if (instr.instr[31:26] == 6'b011010) instruction_o.op = ariane_pkg::BINVI;
else if (instr.instr[31:26] == 6'b001010) instruction_o.op = ariane_pkg::BSETI;
else illegal_instr_bm = 1'b1;
end
3'b101: begin
if (instr.instr[31:20] == 12'b001010000111) instruction_o.op = ariane_pkg::ORCB;
else if (CVA6Cfg.IS_XLEN64 && instr.instr[31:20] == 12'b011010111000)
instruction_o.op = ariane_pkg::REV8;
else if (instr.instr[31:20] == 12'b011010011000)
instruction_o.op = ariane_pkg::REV8;
else if (instr.instr[31:26] == 6'b010_010) instruction_o.op = ariane_pkg::BEXTI;
else if (instr.instr[31:26] == 6'b011_000) instruction_o.op = ariane_pkg::RORI;
else illegal_instr_bm = 1'b1;
end
default: illegal_instr_bm = 1'b1;
endcase
illegal_instr = illegal_instr_non_bm & illegal_instr_bm;
end else begin
illegal_instr = illegal_instr_non_bm;
end
end
// --------------------------------
// 32 bit Reg-Immediate Operations
// --------------------------------
riscv::OpcodeOpImm32: begin
instruction_o.fu = ALU;
imm_select = IIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
if (CVA6Cfg.IS_XLEN64) begin
unique case (instr.itype.funct3)
3'b000: instruction_o.op = ariane_pkg::ADDW; // Add Immediate
3'b001: begin
instruction_o.op = ariane_pkg::SLLW; // Shift Left Logical by Immediate
if (instr.instr[31:25] != 7'b0) illegal_instr_non_bm = 1'b1;
end
3'b101: begin
if (instr.instr[31:25] == 7'b0)
instruction_o.op = ariane_pkg::SRLW; // Shift Right Logical by Immediate
else if (instr.instr[31:25] == 7'b010_0000)
instruction_o.op = ariane_pkg::SRAW; // Shift Right Arithmetically by Immediate
else illegal_instr_non_bm = 1'b1;
end
default: illegal_instr_non_bm = 1'b1;
endcase
if (CVA6Cfg.RVB) begin
unique case (instr.itype.funct3)
3'b001: begin
if (instr.instr[31:25] == 7'b0110000) begin
if (instr.instr[21:20] == 2'b10) instruction_o.op = ariane_pkg::CPOPW;
else if (instr.instr[21:20] == 2'b00) instruction_o.op = ariane_pkg::CLZW;
else if (instr.instr[21:20] == 2'b01) instruction_o.op = ariane_pkg::CTZW;
else illegal_instr_bm = 1'b1;
end else if (instr.instr[31:26] == 6'b000010) begin
instruction_o.op = ariane_pkg::SLLIUW; // Shift Left Logic by Immediate (Unsigned Word)
end else illegal_instr_bm = 1'b1;
end
3'b101: begin
if (instr.instr[31:25] == 7'b011_0000) instruction_o.op = ariane_pkg::RORIW;
else illegal_instr_bm = 1'b1;
end
default: illegal_instr_bm = 1'b1;
endcase
illegal_instr = illegal_instr_non_bm & illegal_instr_bm;
end else begin
illegal_instr = illegal_instr_non_bm;
end
end else illegal_instr = 1'b1;
end
// --------------------------------
// LSU
// --------------------------------
riscv::OpcodeStore: begin
instruction_o.fu = STORE;
imm_select = SIMM;
instruction_o.rs1[4:0] = instr.stype.rs1;
instruction_o.rs2[4:0] = instr.stype.rs2;
// determine store size
unique case (instr.stype.funct3)
3'b000: instruction_o.op = ariane_pkg::SB;
3'b001: instruction_o.op = ariane_pkg::SH;
3'b010: instruction_o.op = ariane_pkg::SW;
3'b011:
if (CVA6Cfg.XLEN == 64) instruction_o.op = ariane_pkg::SD;
else illegal_instr = 1'b1;
default: illegal_instr = 1'b1;