Skip to content

Commit

Permalink
M-extension support for SERV
Browse files Browse the repository at this point in the history
* modified serv(ant) for MDU
* added dependency for mdu
* M-extension for SERV
* Updated README for running RV32IM compliance tests
* waive some lint warnings related to mdu
* added mdu param for arty_a7_35t
  • Loading branch information
zeeshanrafique23 authored and olofk committed Aug 20, 2021
1 parent dbe5236 commit 6e802cb
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 52 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Run the compliance tests

cd riscv-compliance && make TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=rv32i RISCV_ISA=rv32i TARGET_SIM=$WORKSPACE/build/servant_1.1.0/verilator_tb-verilator/Vservant_sim

The above will run all tests in the rv32i test suite. Since SERV also implement the `rv32Zicsr` and `rv32Zifencei` extensions, these can also be tested by choosing any of them instead of rv32i as the `RISCV_ISA` variable.
The above will run all tests in the rv32i test suite. Since SERV also implement the `rv32im`, `rv32Zicsr` and `rv32Zifencei` extensions, these can also be tested by choosing any of them instead of rv32i as the `RISCV_ISA` variable.

## Run on hardware

Expand Down
12 changes: 11 additions & 1 deletion data/verilator_waiver.vlt
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
`verilator_config
// Bits [1:0] in i_ibus_rdt are not used at all
lint_off -rule UNUSED -file "*/serv_top.v" -lines 52
lint_off -rule UNUSED -file "*/serv_top.v" -lines 53

//Some bits in the instruction word are not used in serv_decode but it's easier
//to just send in the whole word than picking out bits
lint_off -rule UNUSED -file "*/serv_decode.v" -lines 7

//Some variables are only used when we connect an Extension with serv_decode
lint_off -rule UNUSED -file "*/serv_top.v" -lines 65
lint_off -rule UNUSED -file "*/serv_bufreg.v" -lines 10
lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8
lint_off -rule UNUSED -file "*/serv_decode.v" -lines 69
lint_off -rule UNUSED -file "*/serv_mem_if.v" -lines 23
lint_off -rule UNUSED -file "*/serv_mem_if.v" -lines 71
lint_off -rule UNUSED -file "*/serv_state.v" -lines 47
lint_off -rule UNUSED -file "*/serv_state.v" -lines 49
24 changes: 17 additions & 7 deletions rtl/serv_bufreg.v
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module serv_bufreg
(
module serv_bufreg #(
parameter [0:0] MDU = 0
)(
input wire i_clk,
//State
input wire i_cnt0,
input wire i_cnt1,
input wire i_en,
input wire i_init,
output reg [1:0] o_lsb,
input wire i_mdu_op,
output wire [1:0] o_lsb,
//Control
input wire i_rs1_en,
input wire i_imm_en,
Expand All @@ -17,11 +19,14 @@ module serv_bufreg
input wire i_imm,
output wire o_q,
//External
output wire [31:0] o_dbus_adr);
output wire [31:0] o_dbus_adr,
//Extension
output wire [31:0] o_ext_rs1);

wire c, q;
reg c_r;
reg [31:2] data;
reg [1:0] lsb;

wire clr_lsb = i_cnt0 & i_clr_lsb;

Expand All @@ -35,11 +40,16 @@ module serv_bufreg
data <= {i_init ? q : (data[31] & i_sh_signed), data[31:3]};

if (i_init ? (i_cnt0 | i_cnt1) : i_en)
o_lsb <= {i_init ? q : data[2],o_lsb[1]};

lsb <= {i_init ? q : data[2],lsb[1]};
end

assign o_q = o_lsb[0] & i_en;
assign o_q = lsb[0] & i_en;
assign o_dbus_adr = {data, 2'b00};
assign o_ext_rs1 = {o_dbus_adr[31:2],lsb};

generate
if (MDU) assign o_lsb = i_mdu_op ? 2'b00 : lsb;
else assign o_lsb = lsb;
endgenerate

endmodule
52 changes: 39 additions & 13 deletions rtl/serv_decode.v
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
`default_nettype none
module serv_decode #(
parameter [0:0] PRE_REGISTER = 1
)(
module serv_decode
#(parameter [0:0] PRE_REGISTER = 1,
parameter [0:0] MDU = 0)
(
input wire clk,
//Input
input wire [31:2] i_wb_rdt,
Expand All @@ -17,6 +18,10 @@ module serv_decode #(
output reg o_shift_op,
output reg o_slt_op,
output reg o_rd_op,
//MDU
output reg o_mdu_op,
//Extension
output reg [2:0] o_ext_funct3,
//To bufreg
output reg o_bufreg_rs1_en,
output reg o_bufreg_imm_en,
Expand Down Expand Up @@ -61,8 +66,33 @@ module serv_decode #(
reg op22;
reg op26;

reg imm25;
reg imm30;

generate
wire co_mdu_op;
wire [2:0]co_ext_funct3;
wire co_shift_op;
wire co_slt_op;
wire co_mem_word;
wire co_rd_alu_en;

if (MDU) begin
assign co_mdu_op = ((opcode == 5'b01100) & imm25);
assign co_shift_op = op_or_opimm & (funct3[1:0] == 2'b01) & !co_mdu_op;
assign co_slt_op = op_or_opimm & (funct3[2:1] == 2'b01) & !co_mdu_op;
assign co_mem_word = co_mdu_op ? co_mdu_op :funct3[1];
assign co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4] & !co_mdu_op;
end else begin
assign co_mdu_op = 1'b0;
assign co_shift_op = op_or_opimm & (funct3[1:0] == 2'b01);
assign co_slt_op = op_or_opimm & (funct3[2:1] == 2'b01);
assign co_mem_word = funct3[1];
assign co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4];
end
assign co_ext_funct3 = funct3;
endgenerate

//opcode
wire op_or_opimm = (!opcode[4] & opcode[2] & !opcode[0]);

Expand Down Expand Up @@ -109,13 +139,6 @@ module serv_decode #(
wire co_sh_right = funct3[2];
wire co_bne_or_bge = funct3[0];

//
// opcode & funct3
//

wire co_shift_op = op_or_opimm & (funct3[1:0] == 2'b01);
wire co_slt_op = op_or_opimm & (funct3[2:1] == 2'b01);

//Matches system ops except eceall/ebreak/mret
wire csr_op = opcode[4] & opcode[2] & (|funct3);

Expand Down Expand Up @@ -190,7 +213,6 @@ module serv_decode #(

wire co_mem_cmd = opcode[3];
wire co_mem_signed = ~funct3[2];
wire co_mem_word = funct3[1];
wire co_mem_half = funct3[0];

wire [1:0] co_alu_bool_op = funct3[1:0];
Expand Down Expand Up @@ -220,15 +242,14 @@ module serv_decode #(
//1 (OP_B_SOURCE_RS2) when BRANCH or OP
wire co_op_b_source = opcode[3];

wire co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4];

generate
if (PRE_REGISTER) begin

always @(posedge clk) begin
if (i_wb_en) begin
funct3 <= i_wb_rdt[14:12];
imm30 <= i_wb_rdt[30];
imm25 <= i_wb_rdt[25];
opcode <= i_wb_rdt[6:2];
op20 <= i_wb_rdt[20];
op21 <= i_wb_rdt[21];
Expand All @@ -248,6 +269,8 @@ module serv_decode #(
o_shift_op = co_shift_op;
o_slt_op = co_slt_op;
o_rd_op = co_rd_op;
o_mdu_op = co_mdu_op;
o_ext_funct3 = co_ext_funct3;
o_bufreg_rs1_en = co_bufreg_rs1_en;
o_bufreg_imm_en = co_bufreg_imm_en;
o_bufreg_clr_lsb = co_bufreg_clr_lsb;
Expand Down Expand Up @@ -285,6 +308,7 @@ module serv_decode #(
always @(*) begin
funct3 = i_wb_rdt[14:12];
imm30 = i_wb_rdt[30];
imm25 = i_wb_rdt[25];
opcode = i_wb_rdt[6:2];
op20 = i_wb_rdt[20];
op21 = i_wb_rdt[21];
Expand All @@ -304,6 +328,8 @@ module serv_decode #(
o_shift_op <= co_shift_op;
o_slt_op <= co_slt_op;
o_rd_op <= co_rd_op;
o_mdu_op <= co_mdu_op;
o_ext_funct3 <= co_ext_funct3;
o_bufreg_rs1_en <= co_bufreg_rs1_en;
o_bufreg_imm_en <= co_bufreg_imm_en;
o_bufreg_clr_lsb <= co_bufreg_clr_lsb;
Expand Down
17 changes: 15 additions & 2 deletions rtl/serv_mem_if.v
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
`default_nettype none
module serv_mem_if
#(parameter WITH_CSR = 1)
#(parameter WITH_CSR = 1,
parameter [0:0] MDU = 0)
(
input wire i_clk,
//State
Expand All @@ -18,6 +19,8 @@ module serv_mem_if
input wire i_signed,
input wire i_word,
input wire i_half,
//MDU
input wire i_mdu_op,
//Data
input wire i_op_b,
output wire o_rd,
Expand Down Expand Up @@ -58,7 +61,17 @@ module serv_mem_if
(i_bytecnt == 2'b00) |
(i_half & !i_bytecnt[1]);

assign o_rd = i_mem_op & (dat_valid ? dat_cur : signbit & i_signed);
wire mem_rd = i_mem_op & (dat_valid ? dat_cur : signbit & i_signed);

generate
if(MDU) begin
wire mdu_rd = i_mdu_op & dat_cur;
assign o_rd = mem_rd | mdu_rd;
end else begin
wire mdu_rd = 1'b0;
assign o_rd = mem_rd;
end
endgenerate

assign o_wb_sel[3] = (i_lsb == 2'b11) | i_word | (i_half & i_lsb[1]);
assign o_wb_sel[2] = (i_lsb == 2'b10) | i_word;
Expand Down
32 changes: 27 additions & 5 deletions rtl/serv_rf_top.v
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

module serv_rf_top
#(parameter RESET_PC = 32'd0,

/* Multiplication and Division Unit
This parameter enables the interface for connecting SERV and MDU
*/
parameter [0:0] MDU = 0,
/* Register signals before or after the decoder
0 : Register after the decoder. Faster but uses more resources
1 : (default) Register before the decoder. Slower but uses less resources
Expand Down Expand Up @@ -55,8 +58,17 @@ module serv_rf_top
output wire o_dbus_we ,
output wire o_dbus_cyc,
input wire [31:0] i_dbus_rdt,
input wire i_dbus_ack);

input wire i_dbus_ack,

// Extension
output wire [31:0] o_ext_rs1,
output wire [31:0] o_ext_rs2,
output wire [ 2:0] o_ext_funct3,
input wire [31:0] i_ext_rd,
input wire i_ext_ready,
// MDU
output wire o_mdu_valid);

localparam CSR_REGS = WITH_CSR*4;

wire rf_wreq;
Expand Down Expand Up @@ -120,7 +132,8 @@ module serv_rf_top
#(.RESET_PC (RESET_PC),
.PRE_REGISTER (PRE_REGISTER),
.RESET_STRATEGY (RESET_STRATEGY),
.WITH_CSR (WITH_CSR))
.WITH_CSR (WITH_CSR),
.MDU(MDU))
cpu
(
.clk (clk),
Expand Down Expand Up @@ -174,7 +187,16 @@ module serv_rf_top
.o_dbus_we (o_dbus_we),
.o_dbus_cyc (o_dbus_cyc),
.i_dbus_rdt (i_dbus_rdt),
.i_dbus_ack (i_dbus_ack));
.i_dbus_ack (i_dbus_ack),

//Extension
.o_ext_funct3 (o_ext_funct3),
.i_ext_ready (i_ext_ready),
.i_ext_rd (i_ext_rd),
.o_ext_rs1 (o_ext_rs1),
.o_ext_rs2 (o_ext_rs2),
//MDU
.o_mdu_valid (o_mdu_valid));

endmodule
`default_nettype wire
47 changes: 36 additions & 11 deletions rtl/serv_state.v
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module serv_state
#(parameter RESET_STRATEGY = "MINI",
parameter [0:0] WITH_CSR = 1)
parameter [0:0] WITH_CSR = 1,
parameter [0:0] MDU = 0)
(
input wire i_clk,
input wire i_rst,
Expand Down Expand Up @@ -41,11 +42,16 @@ module serv_state
output wire [1:0] o_mem_bytecnt,
input wire i_mem_misalign,
output reg o_cnt_done,
output wire o_bufreg_en);
output wire o_bufreg_en,
//MDU
input wire i_mdu_op,
output wire o_mdu_valid,
input wire i_mdu_ready);

reg stage_two_req;
reg init_done;
wire misalign_trap_sync;
wire two_stage_op;

reg [4:2] o_cnt;
reg [3:0] o_cnt_r;
Expand Down Expand Up @@ -74,22 +80,41 @@ module serv_state
//been calculated.
wire take_branch = i_branch_op & (!i_cond_branch | (i_alu_cmp^i_bne_or_bge));

//slt*, branch/jump, shift, load/store
wire two_stage_op = i_slt_op | i_mem_op | i_branch_op | i_shift_op;
generate
if (MDU) begin
//slt*, branch/jump, shift, load/store
assign two_stage_op = i_slt_op | i_mem_op | i_branch_op | i_shift_op | i_mdu_op;

//valid signal for mdu
assign o_mdu_valid = !o_cnt_en & init_done & i_mdu_op;

//Prepare RF for writes when everything is ready to enter stage two
// and the first stage didn't cause a misalign exception
assign o_rf_wreq = !misalign_trap_sync &
((i_shift_op & (i_sh_done | !i_sh_right) & !o_cnt_en & init_done) |
(i_mem_op & i_dbus_ack) | i_mdu_ready |
(stage_two_req & (i_slt_op | i_branch_op)));
end else begin
//slt*, branch/jump, shift, load/store
assign two_stage_op = i_slt_op | i_mem_op | i_branch_op | i_shift_op;

//valid signal for mdu turned-off
assign o_mdu_valid = 1'b0;

//Prepare RF for writes when everything is ready to enter stage two
// and the first stage didn't cause a misalign exception
assign o_rf_wreq = !misalign_trap_sync &
((i_shift_op & (i_sh_done | !i_sh_right) & !o_cnt_en & init_done) |
(i_mem_op & i_dbus_ack) | (stage_two_req & (i_slt_op | i_branch_op)));
end
endgenerate

assign o_dbus_cyc = !o_cnt_en & init_done & i_mem_op & !i_mem_misalign;

//Prepare RF for reads when a new instruction is fetched
// or when stage one caused an exception (rreq implies a write request too)
assign o_rf_rreq = i_ibus_ack | (stage_two_req & misalign_trap_sync);

//Prepare RF for writes when everything is ready to enter stage two
// and the first stage didn't cause a misalign exception
assign o_rf_wreq = !misalign_trap_sync &
((i_shift_op & (i_sh_done | !i_sh_right) & !o_cnt_en & init_done) |
(i_mem_op & i_dbus_ack) |
(stage_two_req & (i_slt_op | i_branch_op)));

assign o_rf_rd_en = i_rd_op & !o_init;

/*
Expand Down
Loading

0 comments on commit 6e802cb

Please sign in to comment.