Skip to content

Commit 6606ed5

Browse files
alfredfoolofk
authored andcommitted
add support for WFI instruction
1 parent f5ddfaa commit 6606ed5

6 files changed

Lines changed: 307 additions & 6 deletions

File tree

bench/decoder_sim.v

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
`default_nettype none
2+
module decoder_sim
3+
(input wire wb_clk,
4+
input wire [31:2] wb_rdt,
5+
input wire wb_en,
6+
output wire ebreak,
7+
output wire jal_or_jalr,
8+
output wire mret,
9+
output wire wfi,
10+
output wire sh_right,
11+
output wire bne_or_bge,
12+
output wire cond_branch,
13+
output wire e_op,
14+
output wire branch_op,
15+
output wire shift_op,
16+
output wire slt_or_branch,
17+
output wire rd_op,
18+
output wire two_stage_op,
19+
output wire dbus_en,
20+
output wire mdu_op,
21+
output wire [2:0] ext_funct3,
22+
output wire bufreg_rs1_en,
23+
output wire bufreg_imm_en,
24+
output wire bufreg_clr_lsb,
25+
output wire bufreg_sh_signed,
26+
output wire ctrl_utype,
27+
output wire ctrl_pc_rel,
28+
output wire alu_sub,
29+
output wire [1:0] alu_bool_op,
30+
output wire alu_cmp_eq,
31+
output wire alu_cmp_sig,
32+
output wire [2:0] alu_rd_sel,
33+
output wire mem_signed,
34+
output wire mem_word,
35+
output wire mem_half,
36+
output wire mem_cmd,
37+
output wire csr_en,
38+
output wire [1:0] csr_addr,
39+
output wire csr_mstatus_en,
40+
output wire csr_mie_en,
41+
output wire csr_mcause_en,
42+
output wire [1:0] csr_source,
43+
output wire csr_d_sel,
44+
output wire csr_imm_en,
45+
output wire mtval_pc,
46+
output wire [3:0] immdec_ctrl,
47+
output wire [3:0] immdec_en,
48+
output wire op_b_source,
49+
output wire rd_mem_en,
50+
output wire rd_csr_en,
51+
output wire rd_alu_en
52+
);
53+
54+
// Instantiate the DUT
55+
serv_decode
56+
#(.PRE_REGISTER (1),
57+
.MDU (0))
58+
dut (
59+
.clk(wb_clk),
60+
.i_wb_rdt(wb_rdt),
61+
.i_wb_en(wb_en),
62+
// Outputs
63+
.o_sh_right(sh_right),
64+
.o_bne_or_bge(bne_or_bge),
65+
.o_cond_branch(cond_branch),
66+
.o_e_op(e_op),
67+
.o_ebreak(ebreak),
68+
.o_wfi(wfi),
69+
.o_branch_op(branch_op),
70+
.o_shift_op(shift_op),
71+
.o_rd_op(rd_op),
72+
.o_two_stage_op(two_stage_op),
73+
.o_dbus_en(dbus_en),
74+
.o_mdu_op(mdu_op),
75+
.o_ext_funct3(ext_funct3),
76+
.o_bufreg_rs1_en(bufreg_rs1_en),
77+
.o_bufreg_imm_en(bufreg_imm_en),
78+
.o_bufreg_clr_lsb(bufreg_clr_lsb),
79+
.o_bufreg_sh_signed(bufreg_sh_signed),
80+
.o_ctrl_jal_or_jalr(jal_or_jalr),
81+
.o_ctrl_utype(ctrl_utype),
82+
.o_ctrl_pc_rel(ctrl_pc_rel),
83+
.o_ctrl_mret(mret),
84+
.o_alu_sub(alu_sub),
85+
.o_alu_bool_op(alu_bool_op),
86+
.o_alu_cmp_eq(alu_cmp_eq),
87+
.o_alu_cmp_sig(alu_cmp_sig),
88+
.o_alu_rd_sel(alu_rd_sel),
89+
.o_mem_signed(mem_signed),
90+
.o_mem_word(mem_word),
91+
.o_mem_half(mem_half),
92+
.o_mem_cmd(mem_cmd),
93+
.o_csr_en(csr_en),
94+
.o_csr_addr(csr_addr),
95+
.o_csr_mstatus_en(csr_mstatus_en),
96+
.o_csr_mie_en(csr_mie_en),
97+
.o_csr_mcause_en(csr_mcause_en),
98+
.o_csr_source(csr_source),
99+
.o_csr_d_sel(csr_d_sel),
100+
.o_csr_imm_en(csr_imm_en),
101+
.o_mtval_pc(mtval_pc),
102+
.o_immdec_ctrl(immdec_ctrl),
103+
.o_immdec_en(immdec_en),
104+
.o_op_b_source(op_b_source),
105+
.o_rd_mem_en(rd_mem_en),
106+
.o_rd_csr_en(rd_csr_en),
107+
.o_rd_alu_en(rd_alu_en)
108+
);
109+
110+
endmodule

bench/decoder_tb.cpp

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#include <fcntl.h>
2+
#include <cstdint>
3+
#include <csignal>
4+
#include <iostream>
5+
#include <fstream>
6+
#include <memory>
7+
#include <ctime>
8+
#include <string>
9+
10+
#include "verilated_vcd_c.h"
11+
#include "Vdecoder_sim.h"
12+
13+
void INThandler(int signal) {
14+
std::cout << "\nCaught ctrl-c\n";
15+
std::exit(0);
16+
}
17+
18+
void test_instruction(Vdecoder_sim *top, const std::string& instr_name, uint32_t instr);
19+
void cycle(Vdecoder_sim *top);
20+
21+
int main(int argc, char** argv, char** env) {
22+
Verilated::commandArgs(argc, argv);
23+
24+
Vdecoder_sim *top = new Vdecoder_sim;
25+
std::signal(SIGINT, INThandler);
26+
27+
top->wb_clk = 0;
28+
top->wb_rdt = 0;
29+
top->wb_en = 0;
30+
31+
std::cout << "Testing decoder\n";
32+
test_instruction(top, "jalr", 0x0000006F);
33+
test_instruction(top, "mret", 0x30200073);
34+
test_instruction(top, "ebreak", 0x00100073);
35+
test_instruction(top, "wfi", 0x10500073);
36+
test_instruction(top, "add", 0x00000033);
37+
test_instruction(top, "addi", 0x00000013);
38+
test_instruction(top, "sub", 0x40000033);
39+
test_instruction(top, "and", 0x00007033);
40+
test_instruction(top, "andi", 0x00007013);
41+
test_instruction(top, "or", 0x00006033);
42+
test_instruction(top, "ori", 0x00006013);
43+
test_instruction(top, "xor", 0x00004033);
44+
test_instruction(top, "xori", 0x00004013);
45+
test_instruction(top, "sll", 0x00001033);
46+
test_instruction(top, "slli", 0x00001013);
47+
test_instruction(top, "srl", 0x00005033);
48+
test_instruction(top, "srli", 0x00005013);
49+
test_instruction(top, "sra", 0x40005033);
50+
test_instruction(top, "srai", 0x40005013);
51+
test_instruction(top, "lui", 0x00000037);
52+
test_instruction(top, "auipc", 0x00000017);
53+
test_instruction(top, "lw", 0x00002003);
54+
test_instruction(top, "lh", 0x00001003);
55+
test_instruction(top, "lhu", 0x00005003);
56+
test_instruction(top, "lb", 0x00000003);
57+
test_instruction(top, "lbu", 0x00004003);
58+
test_instruction(top, "sw", 0x00002023);
59+
test_instruction(top, "sh", 0x00001023);
60+
test_instruction(top, "sb", 0x00000023);
61+
test_instruction(top, "jal", 0x0000006F);
62+
test_instruction(top, "jalr", 0x00000067);
63+
test_instruction(top, "beq", 0x00000063);
64+
test_instruction(top, "bne", 0x00001063);
65+
test_instruction(top, "blt", 0x00004063);
66+
test_instruction(top, "bge", 0x00005063);
67+
test_instruction(top, "bltu", 0x00006063);
68+
test_instruction(top, "bgeu", 0x00007063);
69+
test_instruction(top, "slt", 0x00002033);
70+
test_instruction(top, "slti", 0x00002013);
71+
test_instruction(top, "sltu", 0x00003033);
72+
test_instruction(top, "sltiu", 0x00003013);
73+
test_instruction(top, "ecall", 0x00000073);
74+
test_instruction(top, "ebreak", 0x00100073);
75+
test_instruction(top, "fence", 0x0000000F);
76+
test_instruction(top, "fence.i", 0x0000100F);
77+
78+
test_instruction(top, "csrrw", 0x00001073);
79+
test_instruction(top, "csrrs", 0x00002073);
80+
test_instruction(top, "csrrc", 0x00003073);
81+
test_instruction(top, "csrrwi", 0x00005073);
82+
test_instruction(top, "csrrsi", 0x00006073);
83+
test_instruction(top, "csrrci", 0x00007073);
84+
return 0;
85+
}
86+
87+
void cycle(Vdecoder_sim *top) {
88+
top->eval();
89+
top->wb_clk = 0;
90+
top->eval();
91+
top->wb_clk = 1;
92+
top->eval();
93+
}
94+
95+
void test_instruction(Vdecoder_sim *top, const std::string& instr_name, uint32_t instr) {
96+
std::ofstream outfile(instr_name + ".txt");
97+
98+
std::cout << "Testing " << instr_name << "\n";
99+
outfile << "Testing " << instr_name << "\n";
100+
101+
top->wb_rdt = instr >> 2;
102+
top->wb_en = 1;
103+
cycle(top);
104+
105+
outfile << "jal_or_jalr: " << std::to_string(top->jal_or_jalr) << std::endl;
106+
outfile << "ebreak: " << std::to_string(top->ebreak) << std::endl;
107+
outfile << "mret: " << std::to_string(top->mret) << std::endl;
108+
outfile << "wfi: " << std::to_string(top->wfi) << std::endl;
109+
outfile << "sh_right: " << std::to_string(top->sh_right) << std::endl;
110+
outfile << "bne_or_bge: " << std::to_string(top->bne_or_bge) << std::endl;
111+
outfile << "cond_branch: " << std::to_string(top->cond_branch) << std::endl;
112+
outfile << "e_op: " << std::to_string(top->e_op) << std::endl;
113+
outfile << "branch_op: " << std::to_string(top->branch_op) << std::endl;
114+
outfile << "shift_op: " << std::to_string(top->shift_op) << std::endl;
115+
outfile << "slt_or_branch: " << std::to_string(top->slt_or_branch) << std::endl;
116+
outfile << "rd_op: " << std::to_string(top->rd_op) << std::endl;
117+
outfile << "two_stage_op: " << std::to_string(top->two_stage_op) << std::endl;
118+
outfile << "dbus_en: " << std::to_string(top->dbus_en) << std::endl;
119+
outfile << "mdu_op: " << std::to_string(top->mdu_op) << std::endl;
120+
outfile << "ext_funct3: " << std::to_string(top->ext_funct3) << std::endl;
121+
outfile << "bufreg_rs1_en: " << std::to_string(top->bufreg_rs1_en) << std::endl;
122+
outfile << "bufreg_imm_en: " << std::to_string(top->bufreg_imm_en) << std::endl;
123+
outfile << "bufreg_clr_lsb: " << std::to_string(top->bufreg_clr_lsb) << std::endl;
124+
outfile << "bufreg_sh_signed: " << std::to_string(top->bufreg_sh_signed) << std::endl;
125+
outfile << "ctrl_utype: " << std::to_string(top->ctrl_utype) << std::endl;
126+
outfile << "ctrl_pc_rel: " << std::to_string(top->ctrl_pc_rel) << std::endl;
127+
outfile << "alu_sub: " << std::to_string(top->alu_sub) << std::endl;
128+
outfile << "alu_bool_op: " << std::to_string(top->alu_bool_op) << std::endl;
129+
outfile << "alu_cmp_eq: " << std::to_string(top->alu_cmp_eq) << std::endl;
130+
outfile << "alu_cmp_sig: " << std::to_string(top->alu_cmp_sig) << std::endl;
131+
outfile << "alu_rd_sel: " << std::to_string(top->alu_rd_sel) << std::endl;
132+
outfile << "mem_signed: " << std::to_string(top->mem_signed) << std::endl;
133+
outfile << "mem_word: " << std::to_string(top->mem_word) << std::endl;
134+
outfile << "mem_half: " << std::to_string(top->mem_half) << std::endl;
135+
outfile << "mem_cmd: " << std::to_string(top->mem_cmd) << std::endl;
136+
outfile << "csr_en: " << std::to_string(top->csr_en) << std::endl;
137+
outfile << "csr_addr: " << std::to_string(top->csr_addr) << std::endl;
138+
outfile << "csr_mstatus_en: " << std::to_string(top->csr_mstatus_en) << std::endl;
139+
outfile << "csr_mie_en: " << std::to_string(top->csr_mie_en) << std::endl;
140+
outfile << "csr_mcause_en: " << std::to_string(top->csr_mcause_en) << std::endl;
141+
outfile << "csr_source: " << std::to_string(top->csr_source) << std::endl;
142+
outfile << "csr_d_sel: " << std::to_string(top->csr_d_sel) << std::endl;
143+
outfile << "csr_imm_en: " << std::to_string(top->csr_imm_en) << std::endl;
144+
outfile << "mtval_pc: " << std::to_string(top->mtval_pc) << std::endl;
145+
outfile << "immdec_ctrl: " << std::to_string(top->immdec_ctrl) << std::endl;
146+
outfile << "immdec_en: " << std::to_string(top->immdec_en) << std::endl;
147+
outfile << "op_b_source: " << std::to_string(top->op_b_source) << std::endl;
148+
outfile << "rd_mem_en: " << std::to_string(top->rd_mem_en) << std::endl;
149+
outfile << "rd_csr_en: " << std::to_string(top->rd_csr_en) << std::endl;
150+
outfile << "rd_alu_en: " << std::to_string(top->rd_alu_en) << std::endl;
151+
152+
assert(!(top->wfi && instr_name != "wfi"));
153+
154+
top->wb_en = 0;
155+
cycle(top);
156+
outfile.close();
157+
}

rtl/serv_debug.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ module serv_debug
182182
if (update_mcause) dbg_mcause <= dbg_csr;
183183
end
184184

185-
reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK;
185+
reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK, WFI;
186186
reg CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI;
187187
reg OTHER;
188188

@@ -228,6 +228,7 @@ module serv_debug
228228
FENCE <= 1'b0;
229229
ECALL <= 1'b0;
230230
EBREAK <= 1'b0;
231+
WFI <= 1'b0;
231232
CSRRW <= 1'b0;
232233
CSRRS <= 1'b0;
233234
CSRRC <= 1'b0;
@@ -279,6 +280,7 @@ module serv_debug
279280
32'b???????_?????_?????_000_?????_00011_11 : FENCE <= 1'b1;
280281
32'b0000000_00000_00000_000_00000_11100_11 : ECALL <= 1'b1;
281282
32'b0000000_00001_00000_000_00000_11100_11 : EBREAK <= 1'b1;
283+
32'b0001000_00010_00000_000_00000_11100_11 : WFI <= 1'b1;
282284
32'b???????_?????_?????_001_?????_11100_11 : CSRRW <= 1'b1;
283285
32'b???????_?????_?????_010_?????_11100_11 : CSRRS <= 1'b1;
284286
32'b???????_?????_?????_011_?????_11100_11 : CSRRC <= 1'b1;

rtl/serv_decode.v

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module serv_decode
1919
output reg o_cond_branch,
2020
output reg o_e_op,
2121
output reg o_ebreak,
22+
output reg o_wfi,
2223
output reg o_branch_op,
2324
output reg o_shift_op,
2425
output reg o_rd_op,
@@ -82,7 +83,7 @@ module serv_decode
8283

8384
wire co_two_stage_op =
8485
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
85-
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op;
86+
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op | o_wfi;
8687
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
8788
wire co_branch_op = opcode[4];
8889
wire co_dbus_en = ~opcode[2] & ~opcode[4];
@@ -133,20 +134,22 @@ module serv_decode
133134
wire co_sh_right = funct3[2];
134135
wire co_bne_or_bge = funct3[0];
135136

136-
//Matches system ops except ecall/ebreak/mret
137+
//Matches system ops except ecall/ebreak/mret/wfi
137138
wire csr_op = opcode[4] & opcode[2] & (|funct3);
138139

139140

140141
//op20
141-
wire co_ebreak = op20;
142+
wire co_ebreak = op20 & !op22;
143+
144+
wire co_wfi = opcode[4] & opcode[2] & op22 & !(|funct3);
142145

143146

144147
//opcode & funct3 & op21
145148

146149
wire co_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3);
147150
//Matches system opcodes except CSR accesses (funct3 == 0)
148-
//and mret (!op21)
149-
wire co_e_op = opcode[4] & opcode[2] & !op21 & !(|funct3);
151+
//and mret (!op21) and wfi (!op22)
152+
wire co_e_op = opcode[4] & opcode[2] & !op21 & !op22 & !(|funct3);
150153

151154
//opcode & funct3 & imm30
152155

@@ -261,6 +264,7 @@ module serv_decode
261264
o_two_stage_op = co_two_stage_op;
262265
o_e_op = co_e_op;
263266
o_ebreak = co_ebreak;
267+
o_wfi = co_wfi;
264268
o_branch_op = co_branch_op;
265269
o_shift_op = co_shift_op;
266270
o_rd_op = co_rd_op;
@@ -319,6 +323,7 @@ module serv_decode
319323
o_cond_branch <= co_cond_branch;
320324
o_e_op <= co_e_op;
321325
o_ebreak <= co_ebreak;
326+
o_wfi <= co_wfi;
322327
o_two_stage_op <= co_two_stage_op;
323328
o_dbus_en <= co_dbus_en;
324329
o_mtval_pc <= co_mtval_pc;

rtl/serv_top.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ module serv_top
9292
wire two_stage_op;
9393
wire e_op;
9494
wire ebreak;
95+
wire wfi;
9596
wire branch_op;
9697
wire shift_op;
9798
wire rd_op;
@@ -304,6 +305,7 @@ module serv_top
304305
.o_dbus_en (dbus_en),
305306
.o_e_op (e_op),
306307
.o_ebreak (ebreak),
308+
.o_wfi (wfi),
307309
.o_branch_op (branch_op),
308310
.o_shift_op (shift_op),
309311
.o_rd_op (rd_op),

0 commit comments

Comments
 (0)