mirror of
https://github.com/olofk/serv.git
synced 2026-03-02 01:30:24 +00:00
Initial HERV implementation
This commit is contained in:
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
width: [1, 4]
|
||||
width: [1, 4, 8]
|
||||
name: Linter
|
||||
env:
|
||||
REPO : serv
|
||||
|
||||
@@ -83,6 +83,29 @@ module serv_bufreg #(
|
||||
wire [2*W+B-2:0] muxdata = {data[W+B-1:0],data_tail};
|
||||
wire [B:0] muxout = muxdata[{1'b0,shift_amount}+:W];
|
||||
|
||||
assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;
|
||||
assign o_q = i_en ? muxout : {W{1'b0}};
|
||||
end else if (W == 8) begin : gen_lsb_w_8
|
||||
reg [1:0] lsb;
|
||||
reg [W-2:0] data_tail;
|
||||
|
||||
wire [3:0] shift_amount
|
||||
= !i_shift_op ? 4'd7 :
|
||||
i_right_shift_op ? (4'd7+{1'b0,i_shamt[2:0]}) :
|
||||
({1'b0,~i_shamt[2:0]});
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_en)
|
||||
if (i_cnt0) lsb <= q[1:0];
|
||||
if (i_en)
|
||||
data <= {i_init ? q : {W{i_sh_signed & data[31]}}, data[31:W]};
|
||||
if (i_en)
|
||||
data_tail <= data[B:1] & {B{~i_cnt_done}};
|
||||
end
|
||||
|
||||
wire [2*W+B-2:0] muxdata = {data[W+B-1:0],data_tail};
|
||||
wire [B:0] muxout = muxdata[{1'b0,shift_amount}+:W];
|
||||
|
||||
assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;
|
||||
assign o_q = i_en ? muxout : {W{1'b0}};
|
||||
end
|
||||
|
||||
@@ -65,11 +65,17 @@ module serv_bufreg2
|
||||
*/
|
||||
|
||||
wire [7:0] cnt_next;
|
||||
wire [7:0] sh_next;
|
||||
generate
|
||||
if (W == 1) begin : gen_cnt_w_eq_1
|
||||
assign cnt_next = {o_op_b, dhi[7], dhi[5:0]-6'd1};
|
||||
assign sh_next = {o_op_b, dhi[7:W]};
|
||||
end else if (W == 4) begin : gen_cnt_w_eq_4
|
||||
assign cnt_next = {o_op_b[3:2], dhi[5:0]-6'd4};
|
||||
assign sh_next = {o_op_b, dhi[7:W]};
|
||||
end else if (W == 8) begin : gen_cnt_w_eq_8
|
||||
assign cnt_next = {o_op_b[7:6], dhi[5:0]-6'd8};
|
||||
assign sh_next = o_op_b;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
@@ -77,7 +83,7 @@ module serv_bufreg2
|
||||
//Down counter mode
|
||||
cnt_next :
|
||||
//Shift reg mode
|
||||
{o_op_b, dhi[7:W]};
|
||||
sh_next;
|
||||
|
||||
assign o_sh_done = dat_shamt[5];
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ module serv_csr
|
||||
assign mstatus = ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12));
|
||||
end else if (W==4) begin : gen_mstatus_w4
|
||||
assign mstatus = {i_cnt11 | (mstatus_mie & i_cnt3), 2'b00, i_cnt12};
|
||||
end else if (W==8) begin : gen_mstatus_w8
|
||||
assign mstatus = {3'b000, i_cnt12, i_cnt11 | (mstatus_mie & i_cnt3), 3'b000};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
@@ -83,9 +85,28 @@ module serv_csr
|
||||
|
||||
wire timer_irq = i_mtip & mstatus_mie & mie_mtie;
|
||||
|
||||
generate
|
||||
if (W > 4) begin : gen_mcause_w_gt_4
|
||||
assign mcause = i_cnt0to3 ? {{W-4{1'b0}},mcause3_0} : //[3:0]
|
||||
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
|
||||
: {W{1'b0}};
|
||||
end else begin : gen_mcause_w_le_4
|
||||
assign mcause = i_cnt0to3 ? mcause3_0[B:0] : //[3:0]
|
||||
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
|
||||
: {W{1'b0}};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
wire [3:0] mcause3_0_next;
|
||||
|
||||
generate
|
||||
if (W == 1) begin : gen_mcause_next_w_eq_1
|
||||
assign mcause3_0_next = {csr_in, mcause3_0[3:1]};
|
||||
end else begin : gen_mcause_next_w_eq_4
|
||||
assign mcause3_0_next = csr_in[3:0];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign o_csr_in = csr_in;
|
||||
|
||||
@@ -109,7 +130,7 @@ module serv_csr
|
||||
These conditions are all mutually exclusive
|
||||
*/
|
||||
if ((i_trap & i_cnt_done) | i_mstatus_en & i_cnt3 & i_en | i_mret)
|
||||
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in[B]);
|
||||
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in[(W>4) ? 3 : B]);
|
||||
|
||||
/*
|
||||
Note: To save resources mstatus_mpie (mstatus bit 7) is not
|
||||
@@ -141,10 +162,10 @@ module serv_csr
|
||||
ctrl => 0000 (jump=0)
|
||||
*/
|
||||
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
|
||||
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in[B]);
|
||||
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & ((W == 1) ? mcause3_0[3] : csr_in[(W == 1) ? 0 : 2]));
|
||||
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & ((W == 1) ? mcause3_0[2] : csr_in[(W == 1) ? 0 : 1]));
|
||||
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & ((W == 1) ? mcause3_0[1] : csr_in[0]));
|
||||
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & mcause3_0_next[3]);
|
||||
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & mcause3_0_next[2]);
|
||||
mcause3_0[1] <= o_new_irq | i_e_op | (!i_trap & mcause3_0_next[1]) | (i_mem_op & i_mem_cmd);
|
||||
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & mcause3_0_next[0]);
|
||||
end
|
||||
if (i_mcause_en & i_cnt_done | i_trap)
|
||||
mcause31 <= i_trap ? o_new_irq : csr_in[B];
|
||||
|
||||
@@ -55,7 +55,7 @@ module serv_ctrl
|
||||
generate
|
||||
if (W == 1) begin : gen_plus_4_w_eq_1
|
||||
assign plus_4 = i_iscomp ? i_cnt1 : i_cnt2;
|
||||
end else if (W == 4) begin : gen_plus_4_w_eq_4
|
||||
end else if (W >= 4) begin : gen_plus_4_w_ge_4
|
||||
assign plus_4 = (i_cnt0 | i_cnt1) ? (i_iscomp ? 2 : 4) : 0;
|
||||
end
|
||||
endgenerate
|
||||
@@ -70,6 +70,8 @@ module serv_ctrl
|
||||
assign new_pc = i_trap ? (i_csr_pc & !(i_cnt0 || i_cnt1)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||
end else if (W == 4) begin : gen_new_pc_w_eq_4
|
||||
assign new_pc = i_trap ? (i_csr_pc & ((i_cnt0 || i_cnt1) ? 4'b1100 : 4'b1111)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||
end else if (W == 8) begin : gen_new_pc_w_eq_8
|
||||
assign new_pc = i_trap ? (i_csr_pc & ((i_cnt0 || i_cnt1) ? 8'b11111100 : 8'b11111111)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||
end
|
||||
end else begin : gen_no_csr
|
||||
assign new_pc = i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||
@@ -78,7 +80,14 @@ module serv_ctrl
|
||||
assign o_rd = ({W{i_utype}} & pc_plus_offset_aligned) | (pc_plus_4 & {W{i_jal_or_jalr}});
|
||||
|
||||
assign offset_a = {W{i_pc_rel}} & pc;
|
||||
assign offset_b = i_utype ? (i_imm & {W{i_cnt12to15 | i_cnt16to31}}) : i_buf;
|
||||
generate
|
||||
if (W == 8) begin : gen_offset_w_eq_8
|
||||
assign offset_b = i_utype ? (i_imm & {{4{i_cnt12to15 | i_cnt16to31}}, {4{i_cnt16to31}}}) : i_buf;
|
||||
end else begin : gen_offset_w_lt_8
|
||||
assign offset_b = i_utype ? (i_imm & {W{i_cnt12to15 | i_cnt16to31}}) : i_buf;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign {pc_plus_offset_cy,pc_plus_offset} = offset_a+offset_b+pc_plus_offset_cy_r_w;
|
||||
|
||||
generate
|
||||
|
||||
@@ -93,7 +93,7 @@ generate
|
||||
end
|
||||
|
||||
assign o_imm = i_cnt_done ? signbit : i_ctrl[0] ? imm11_7[0] : imm24_20[0];
|
||||
end else begin : gen_immdec_w_eq_4
|
||||
end else if (W == 4) begin : gen_immdec_w_eq_4
|
||||
reg [4:0] rd_addr;
|
||||
reg [4:0] rs1_addr;
|
||||
reg [4:0] rs2_addr;
|
||||
@@ -223,6 +223,150 @@ generate
|
||||
assign o_imm[1] = i_ctrl[0] ? i8 : i21;
|
||||
assign o_imm[0] = i_ctrl[0] ? i7_2 : i20_2;
|
||||
|
||||
end else begin : gen_immdec_w_eq_8
|
||||
|
||||
reg [4:0] rd_addr;
|
||||
reg [4:0] rs1_addr;
|
||||
reg [4:0] rs2_addr;
|
||||
|
||||
reg i31;
|
||||
reg i30;
|
||||
reg i29;
|
||||
reg i28;
|
||||
reg i27;
|
||||
reg i26;
|
||||
reg i25;
|
||||
reg i24;
|
||||
reg i23;
|
||||
reg i22;
|
||||
reg i21;
|
||||
reg i20;
|
||||
reg i19;
|
||||
reg i18;
|
||||
reg i17;
|
||||
reg i16;
|
||||
reg i15;
|
||||
reg i14;
|
||||
reg i13;
|
||||
reg i12;
|
||||
reg i11;
|
||||
reg i10;
|
||||
reg i9;
|
||||
reg i8;
|
||||
reg i7;
|
||||
|
||||
reg i7_2;
|
||||
reg i20_2;
|
||||
|
||||
wire signbit = i31 & !i_csr_imm_en;
|
||||
|
||||
assign o_csr_imm[7] = 1'b0;
|
||||
assign o_csr_imm[6] = 1'b0;
|
||||
assign o_csr_imm[5] = 1'b0;
|
||||
assign o_csr_imm[4] = i19;
|
||||
assign o_csr_imm[3] = i18;
|
||||
assign o_csr_imm[2] = i17;
|
||||
assign o_csr_imm[1] = i16;
|
||||
assign o_csr_imm[0] = i15;
|
||||
|
||||
assign o_rd_addr = rd_addr;
|
||||
assign o_rs1_addr = rs1_addr;
|
||||
assign o_rs2_addr = rs2_addr;
|
||||
always @(posedge i_clk) begin
|
||||
if (i_wb_en) begin
|
||||
//Common
|
||||
i31 <= i_wb_rdt[31];
|
||||
|
||||
//Bit lane 3
|
||||
i19 <= i_wb_rdt[19];
|
||||
i15 <= i_wb_rdt[15];
|
||||
i20 <= i_wb_rdt[20];
|
||||
i7 <= i_wb_rdt[7];
|
||||
i27 <= i_wb_rdt[27];
|
||||
i23 <= i_wb_rdt[23];
|
||||
i10 <= i_wb_rdt[10];
|
||||
|
||||
//Bit lane 2
|
||||
i22 <= i_wb_rdt[22];
|
||||
i9 <= i_wb_rdt[ 9];
|
||||
i26 <= i_wb_rdt[26];
|
||||
i30 <= i_wb_rdt[30];
|
||||
i14 <= i_wb_rdt[14];
|
||||
i18 <= i_wb_rdt[18];
|
||||
|
||||
//Bit lane 1
|
||||
i21 <= i_wb_rdt[21];
|
||||
i8 <= i_wb_rdt[ 8];
|
||||
i25 <= i_wb_rdt[25];
|
||||
i29 <= i_wb_rdt[29];
|
||||
i13 <= i_wb_rdt[13];
|
||||
i17 <= i_wb_rdt[17];
|
||||
|
||||
//Bit lane 0
|
||||
i11 <= i_wb_rdt[11];
|
||||
i7_2 <= i_wb_rdt[7 ];
|
||||
i20_2 <= i_wb_rdt[20];
|
||||
i24 <= i_wb_rdt[24];
|
||||
i28 <= i_wb_rdt[28];
|
||||
i12 <= i_wb_rdt[12];
|
||||
i16 <= i_wb_rdt[16];
|
||||
|
||||
rd_addr <= i_wb_rdt[11:7];
|
||||
rs1_addr <= i_wb_rdt[19:15];
|
||||
rs2_addr <= i_wb_rdt[24:20];
|
||||
end
|
||||
if (i_cnt_en) begin
|
||||
//Bit lane 6, 7
|
||||
i10 <= i_ctrl[2] ? i7 : i_ctrl[1] ? signbit : i20;
|
||||
i23 <= i_ctrl[2] ? i7 : i_ctrl[1] ? signbit : i20;
|
||||
i27 <= i_ctrl[2] ? signbit : i_ctrl[1] ? signbit : i15;
|
||||
i7 <= signbit;
|
||||
i20 <= i19;
|
||||
i15 <= i_ctrl[3] ? signbit : i23;
|
||||
i19 <= i_ctrl[3] ? signbit : i27;
|
||||
|
||||
|
||||
//Bit lane 4, 5
|
||||
i22 <= i30;
|
||||
i9 <= i30;
|
||||
i26 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i14;
|
||||
i30 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i18;
|
||||
i14 <= i_ctrl[3] ? signbit : i22;
|
||||
i18 <= i_ctrl[3] ? signbit : i26;
|
||||
|
||||
|
||||
//Bit lane 2, 3
|
||||
i21 <= i29;
|
||||
i8 <= i29;
|
||||
i25 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i13;
|
||||
i29 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i17;
|
||||
i13 <= i_ctrl[3] ? signbit : i21;
|
||||
i17 <= i_ctrl[3] ? signbit : i25;
|
||||
|
||||
|
||||
//Bit lane 0, 1
|
||||
i7_2 <= i28;
|
||||
i20_2 <= i28;
|
||||
i28 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i16;
|
||||
i16 <= i_ctrl[3] ? signbit : i24;
|
||||
i11 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i12;
|
||||
i24 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i12;
|
||||
i12 <= i_ctrl[3] ? signbit : i20_2;
|
||||
end
|
||||
end
|
||||
|
||||
assign o_imm[7] = (i_cnt_done ? signbit : (i_ctrl[0] ? i27 : i27));
|
||||
assign o_imm[3] = ((i_ctrl[0] ? i10 : i23));
|
||||
|
||||
assign o_imm[6] = i_ctrl[0] ? i26 : i26;
|
||||
assign o_imm[2] = i_ctrl[0] ? i9 : i22;
|
||||
|
||||
assign o_imm[5] = i_ctrl[0] ? i25 : i25;
|
||||
assign o_imm[1] = i_ctrl[0] ? i8 : i21;
|
||||
|
||||
assign o_imm[4] = i_ctrl[0] ? i11 : i24;
|
||||
assign o_imm[0] = i_ctrl[0] ? i7_2 : i20_2;
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
@@ -91,7 +91,13 @@ module serv_rf_ram_if
|
||||
|
||||
assign o_wen = (wtrig0 & wen0_r) | (wtrig1 & wen1_r);
|
||||
|
||||
assign wcnt = rcnt-4;
|
||||
generate
|
||||
if (W > 4) begin : gen_wcnt_w_gt_4
|
||||
assign wcnt = rcnt;
|
||||
end else begin : gen_wcnt_w_le_4
|
||||
assign wcnt = rcnt-4;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (wcnt[0]) begin
|
||||
|
||||
@@ -73,15 +73,26 @@ module serv_state
|
||||
assign o_mem_bytecnt = o_cnt[4:3];
|
||||
|
||||
assign o_cnt0to3 = (o_cnt[4:2] == 3'd0);
|
||||
assign o_cnt12to15 = (!o_cnt[4] & (o_cnt[3:2] == 2'b11));
|
||||
assign o_cnt16to31 = o_cnt[4];
|
||||
assign o_cnt0 = (o_cnt[4:2] == 3'd0) & cnt_r[0];
|
||||
assign o_cnt1 = (o_cnt[4:2] == 3'd0) & cnt_r[1];
|
||||
assign o_cnt2 = (o_cnt[4:2] == 3'd0) & cnt_r[2];
|
||||
assign o_cnt3 = (o_cnt[4:2] == 3'd0) & cnt_r[3];
|
||||
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3];
|
||||
assign o_cnt11 = (o_cnt[4:2] == 3'd2) & cnt_r[3];
|
||||
assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0];
|
||||
|
||||
generate
|
||||
if (W == 8) begin : gen_cnt_w_8
|
||||
assign o_cnt12to15 = (o_cnt[4:3] == 2'b01);
|
||||
assign o_cnt7 = o_cnt0 & o_cnt_en;
|
||||
assign o_cnt12 = o_cnt11;
|
||||
assign o_cnt_done = (o_cnt[4:3] == 2'b11) & cnt_r[3];
|
||||
end else begin : gen_cnt_w_lt_8
|
||||
assign o_cnt12to15 = (o_cnt[4:2] == 3'b011);
|
||||
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3];
|
||||
assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0];
|
||||
assign o_cnt_done = (o_cnt[4:2] == 3'b111) & cnt_r[3];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//Take branch for jump or branch instructions (opcode == 1x0xx) if
|
||||
//a) It's an unconditional branch (opcode[0] == 1)
|
||||
@@ -133,8 +144,6 @@ module serv_state
|
||||
|
||||
assign o_init = i_two_stage_op & !i_new_irq & !init_done;
|
||||
|
||||
assign o_cnt_done = (o_cnt[4:2] == 3'b111) & cnt_r[3];
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
//ibus_cyc changes on three conditions.
|
||||
//1. i_rst is asserted. Together with the async gating above, o_ibus_cyc
|
||||
@@ -209,6 +218,19 @@ module serv_state
|
||||
end
|
||||
assign cnt_r = 4'b1111;
|
||||
assign o_cnt_en = cnt_en;
|
||||
end else if (W == 8) begin : gen_cnt_w_eq_8
|
||||
reg cnt_en;
|
||||
always @(posedge i_clk) begin
|
||||
if (i_rf_ready) cnt_en <= 1; else
|
||||
if (o_cnt_done) cnt_en <= 0;
|
||||
o_cnt <= o_cnt + { 1'd0, cnt_en, 1'b0};
|
||||
if (i_rst & (RESET_STRATEGY != "NONE")) begin
|
||||
o_cnt <= 3'd0;
|
||||
cnt_en <= 1'b0;
|
||||
end
|
||||
end
|
||||
assign cnt_r = 4'b1111;
|
||||
assign o_cnt_en = cnt_en;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class serv(pluginTemplate):
|
||||
|
||||
build_serv = 'fusesoc run --target=verilator_tb --flag=mdu\
|
||||
--build --build-root=servant_test servant\
|
||||
--memsize=8388608 --compressed=1'
|
||||
--memsize=8388608 --compressed=1 --width=8'
|
||||
utils.shellCommand(build_serv).run()
|
||||
|
||||
def build(self, isa_yaml, platform_yaml):
|
||||
|
||||
Reference in New Issue
Block a user