Skip to content

Commit

Permalink
Working B instructions
Browse files Browse the repository at this point in the history
In theory it's still backwards compatible with rv32, but not tested.
CSRs, memory, and probably other things are still 32 bit.  This is very much *not* a fully implemented rv64 core.  It *is* however enough to test the rv64b instructions.
This also strips out the NERV_FAULT and NERV_FAIRNESS stuff from the wrapper.
  • Loading branch information
KrystalDelusion committed Oct 13, 2024
1 parent c322618 commit 886e837
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 85 deletions.
107 changes: 70 additions & 37 deletions cores/nerv64/nerv64.sv
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,10 @@

module nerv #(
parameter [31:0] RESET_ADDR = 32'h 0000_0000,
parameter integer NUMREGS = 32
parameter integer NUMREGS = 32,
parameter Nb = 64,
parameter logNb = $clog2(Nb),
parameter NB = Nb >> 3
) (
input clock,
input reset,
Expand All @@ -316,12 +319,12 @@ module nerv #(
output reg [ 1:0] rvfi_ixl,
output reg [ 4:0] rvfi_rs1_addr,
output reg [ 4:0] rvfi_rs2_addr,
output reg [31:0] rvfi_rs1_rdata,
output reg [31:0] rvfi_rs2_rdata,
output reg [Nb - 1:0] rvfi_rs1_rdata,
output reg [Nb - 1:0] rvfi_rs2_rdata,
output reg [ 4:0] rvfi_rd_addr,
output reg [31:0] rvfi_rd_wdata,
output reg [31:0] rvfi_pc_rdata,
output reg [31:0] rvfi_pc_wdata,
output reg [Nb - 1:0] rvfi_rd_wdata,
output reg [Nb - 1:0] rvfi_pc_rdata,
output reg [Nb - 1:0] rvfi_pc_wdata,

`ifdef NERV_CSR
`define NERV_CSR_REG_MRW(NAME, ADDR, VALUE) \
Expand Down Expand Up @@ -426,10 +429,10 @@ module nerv #(
assign dmem_wdata = mem_wr_enable ? mem_wr_data : 32'h x;

// registers, instruction reg, program counter, next pc
reg [31:0] regfile [0:NUMREGS-1];
reg [Nb - 1:0] regfile [0:NUMREGS-1];
wire [31:0] insn;
reg [31:0] npc;
reg [31:0] pc;
reg [Nb - 1:0] npc;
reg [Nb - 1:0] pc;

reg [31:0] imem_addr_q;

Expand All @@ -450,8 +453,8 @@ module nerv #(
wire [6:0] insn_opcode;

// rs1 and rs2 are source for the instruction
wire [31:0] rs1_value = !insn_rs1 ? 0 : regfile[insn_rs1];
wire [31:0] rs2_value = !insn_rs2 ? 0 : regfile[insn_rs2];
wire [Nb - 1:0] rs1_value = !insn_rs1 ? 0 : regfile[insn_rs1];
wire [Nb - 1:0] rs2_value = !insn_rs2 ? 0 : regfile[insn_rs2];

// split R-type instruction - see section 2.2 of RiscV spec
assign {insn_funct7, insn_rs2, insn_rs1, insn_funct3, insn_rd, insn_opcode} = insn;
Expand All @@ -473,10 +476,13 @@ module nerv #(
wire [20:0] imm_j;
assign {imm_j[20], imm_j[10:1], imm_j[11], imm_j[19:12], imm_j[0]} = {insn[31:12], 1'b0};

wire [31:0] imm_i_sext = $signed(imm_i);
wire [31:0] imm_s_sext = $signed(imm_s);
wire [31:0] imm_b_sext = $signed(imm_b);
wire [31:0] imm_j_sext = $signed(imm_j);
wire [Nb - 1:0] imm_i_sext = $signed(imm_i);
wire [Nb - 1:0] imm_s_sext = $signed(imm_s);
wire [Nb - 1:0] imm_b_sext = $signed(imm_b);
wire [Nb - 1:0] imm_j_sext = $signed(imm_j);

wire [Nb - 1:0] sext_rs1_32 = $signed(rs1_value[31:0]);
wire [Nb - 1:0] zext_rs1_32 = {'0, rs1_value[31:0]};

// opcodes - see section 19 of RiscV spec
localparam OPCODE_LOAD = 7'b 00_000_11;
Expand Down Expand Up @@ -532,7 +538,7 @@ module nerv #(

// next write, next destination (rd) value & register
reg next_wr;
reg [31:0] next_rd;
reg [Nb - 1:0] next_rd;
reg [4:0] wr_rd;

// illegal instruction registers
Expand Down Expand Up @@ -947,28 +953,29 @@ module nerv #(
10'b zzzzzzz_100 /* XORI */: begin next_wr = 1; next_rd = rs1_value ^ imm_i_sext; end
10'b zzzzzzz_110 /* ORI */: begin next_wr = 1; next_rd = rs1_value | imm_i_sext; end
10'b zzzzzzz_111 /* ANDI */: begin next_wr = 1; next_rd = rs1_value & imm_i_sext; end
10'b 0000000_001 /* SLLI */: begin next_wr = 1; next_rd = rs1_value << insn[24:20]; end
10'b 000000z_001 /* SLLI */: begin next_wr = 1; next_rd = rs1_value << insn[20+:logNb]; end
10'b 0000000_101 /* SRLI */: begin next_wr = 1; next_rd = rs1_value >> insn[24:20]; end
10'b 0100000_101 /* SRAI */: begin next_wr = 1; next_rd = $signed(rs1_value) >>> insn[24:20]; end
// Zbb: Basic bit-manipulation
10'b 0110000_001: begin
casez (insn[24:20])
5'b 00000 /* CLZ */: begin next_wr = 1; next_rd = 0; for (int i=0; i<32; i=i+1) next_rd = rs1_value[i] ? 0 : next_rd + 1; end
5'b 00001 /* CTZ */: begin next_wr = 1; next_rd = 0; for (int i=32; i>0; i=i-1) next_rd = rs1_value[i-1] ? 0 : next_rd + 1; end
5'b 00010 /* CPOP */: begin next_wr = 1; next_rd = 0; for (int i=0; i<32; i=i+1) next_rd = next_rd + rs1_value[i]; end
5'b 00000 /* CLZ */: begin next_wr = 1; next_rd = 0; for (int i=0; i<Nb; i=i+1) next_rd = rs1_value[i] ? 0 : next_rd + 1; end
5'b 00001 /* CTZ */: begin next_wr = 1; next_rd = 0; for (int i=Nb; i>0; i=i-1) next_rd = rs1_value[i-1] ? 0 : next_rd + 1; end
5'b 00010 /* CPOP */: begin next_wr = 1; next_rd = 0; for (int i=0; i<Nb; i=i+1) next_rd = next_rd + rs1_value[i]; end
5'b 00100 /* SEXT.B */: begin next_wr = 1; next_rd = $signed(rs1_value[7:0]); end
5'b 00101 /* SEXT.H */: begin next_wr = 1; next_rd = $signed(rs1_value[15:0]); end
default: illinsn = 1;
endcase
end
10'b 0110000_101 /* RORI */: begin next_wr = 1; next_rd = rs1_value >> insn[24:20] | (rs1_value << (32 - insn[24:20])); end
10'b 0010100_101 /* ORC.B */: begin next_wr = insn[24:20] == 5'b 00111; illinsn = !next_wr; next_rd = 0; for (int i=0; i<4; i=i+1) next_rd[i*8 +: 8] = {8{|rs1_value[i*8 +: 8]}}; end
10'b 0110100_101 /* REV8 */: begin next_wr = insn[24:20] == 5'b 11000; illinsn = !next_wr; next_rd = 0; for (int i=0; i<4; i=i+1) next_rd[i*8 +: 8] = rs1_value[(4-i)*8 - 1 -: 8]; end
10'b 011000z_101 /* RORI */: begin next_wr = 1; next_rd = rs1_value >> insn[20+:logNb] | (rs1_value << (Nb - insn[20+:logNb])); end
10'b 0010100_101 /* ORC.B */: begin next_wr = insn[24:20] == 5'b 00111; illinsn = !next_wr; next_rd = 0; for (int i=0; i<NB; i=i+1) next_rd[i*8 +: 8] = {8{|rs1_value[i*8 +: 8]}}; end
10'b 0110100_101 /* REV8(32) */: begin next_wr = insn[24:20] == 5'b 11000; illinsn = !next_wr; next_rd = 0; for (int i=0; i<4; i=i+1) next_rd[i*8 +: 8] = rs1_value[(4-i)*8 - 1 -: 8]; end
10'b 0110101_101 /* REV8(64) */: begin next_wr = insn[24:20] == 5'b 11000; illinsn = !next_wr; next_rd = 0; for (int i=0; i<8; i=i+1) next_rd[i*8 +: 8] = rs1_value[(8-i)*8 - 1 -: 8]; end
// Zbs: Single-bit instructions
10'b 0100100_001 /* BCLRI */: begin next_wr = 1; next_rd = rs1_value & ~(1 << insn[24:20]); end
10'b 0100100_101 /* BEXTI */: begin next_wr = 1; next_rd = (rs1_value >> insn[24:20]) & 1; end
10'b 0110100_001 /* BINVI */: begin next_wr = 1; next_rd = rs1_value ^ (1 << insn[24:20]); end
10'b 0010100_001 /* BSETI */: begin next_wr = 1; next_rd = rs1_value | (1 << insn[24:20]); end
10'b 010010z_001 /* BCLRI */: begin next_wr = 1; next_rd = rs1_value & ~(1 << insn[20+:logNb]); end
10'b 010010z_101 /* BEXTI */: begin next_wr = 1; next_rd = (rs1_value >> insn[20+:logNb]) & 1; end
10'b 011010z_001 /* BINVI */: begin next_wr = 1; next_rd = rs1_value ^ (1 << insn[20+:logNb]); end
10'b 001010z_001 /* BSETI */: begin next_wr = 1; next_rd = rs1_value | (1 << insn[20+:logNb]); end
default: illinsn = 1;
endcase
end
Expand All @@ -987,9 +994,9 @@ module nerv #(
10'b 0000000_110 /* OR */: begin next_wr = 1; next_rd = rs1_value | rs2_value; end
10'b 0000000_111 /* AND */: begin next_wr = 1; next_rd = rs1_value & rs2_value; end
// Zba: Address generation
10'b 0010000_010 /* SH1ADD */: begin next_wr = 1; next_rd = rs2_value + {rs1_value[30:0], 1'b 0}; end
10'b 0010000_100 /* SH2ADD */: begin next_wr = 1; next_rd = rs2_value + {rs1_value[29:0], 2'b 0}; end
10'b 0010000_110 /* SH3ADD */: begin next_wr = 1; next_rd = rs2_value + {rs1_value[28:0], 3'b 0}; end
10'b 0010000_010 /* SH1ADD */: begin next_wr = 1; next_rd = rs2_value + {rs1_value[Nb - 2:0], 1'b 0}; end
10'b 0010000_100 /* SH2ADD */: begin next_wr = 1; next_rd = rs2_value + {rs1_value[Nb - 3:0], 2'b 0}; end
10'b 0010000_110 /* SH3ADD */: begin next_wr = 1; next_rd = rs2_value + {rs1_value[Nb - 4:0], 3'b 0}; end
// Zbb: Basic bit-manipulation
10'b 0100000_111 /* ANDN */: begin next_wr = 1; next_rd = rs1_value & ~rs2_value; end
10'b 0100000_110 /* ORN */: begin next_wr = 1; next_rd = rs1_value | ~rs2_value; end
Expand All @@ -998,14 +1005,40 @@ module nerv #(
10'b 0000101_111 /* MAXU */: begin next_wr = 1; next_rd = (rs1_value < rs2_value) ? rs2_value : rs1_value; end
10'b 0000101_100 /* MIN */: begin next_wr = 1; next_rd = ($signed(rs1_value) < $signed(rs2_value)) ? rs1_value : rs2_value; end
10'b 0000101_101 /* MINU */: begin next_wr = 1; next_rd = (rs1_value < rs2_value) ? rs1_value : rs2_value; end
10'b 0110000_001 /* ROL */: begin next_wr = 1; next_rd = rs1_value << rs2_value[4:0] | (rs1_value >> (32 - rs2_value[4:0])); end
10'b 0110000_101 /* ROR */: begin next_wr = 1; next_rd = rs1_value >> rs2_value[4:0] | (rs1_value << (32 - rs2_value[4:0])); end
10'b 0000100_100 /* ZEXT.H */: begin next_wr = 1; next_rd = {16'b 0, rs1_value[15:0]}; end
10'b 0110000_001 /* ROL */: begin next_wr = 1; next_rd = rs1_value << rs2_value[logNb-1:0] | (rs1_value >> (Nb - rs2_value[logNb-1:0])); end
10'b 0110000_101 /* ROR */: begin next_wr = 1; next_rd = rs1_value >> rs2_value[logNb-1:0] | (rs1_value << (Nb - rs2_value[logNb-1:0])); end
10'b 0000100_100 /* ZEXT.H(32) */: begin next_wr = 1; next_rd = {'0, rs1_value[15:0]}; end
// Zbs: Single-bit instructions
10'b 0100100_001 /* BCLR */: begin next_wr = 1; next_rd = rs1_value & ~(1 << rs2_value[4:0]); end
10'b 0100100_101 /* BEXT */: begin next_wr = 1; next_rd = (rs1_value >> rs2_value[4:0]) & 1; end
10'b 0110100_001 /* BINV */: begin next_wr = 1; next_rd = rs1_value ^ (1 << rs2_value[4:0]); end
10'b 0010100_001 /* BSET */: begin next_wr = 1; next_rd = rs1_value | (1 << rs2_value[4:0]); end
10'b 0100100_001 /* BCLR */: begin next_wr = 1; next_rd = rs1_value & ~(1 << rs2_value[logNb-1:0]); end
10'b 0100100_101 /* BEXT */: begin next_wr = 1; next_rd = (rs1_value >> rs2_value[logNb-1:0]) & 1; end
10'b 0110100_001 /* BINV */: begin next_wr = 1; next_rd = rs1_value ^ (1 << rs2_value[logNb-1:0]); end
10'b 0010100_001 /* BSET */: begin next_wr = 1; next_rd = rs1_value | (1 << rs2_value[logNb-1:0]); end
default: illinsn = 1;
endcase
end
OPCODE_OP_IMM_32: begin
casez ({insn_funct7, insn_funct3})
10'b 0110000_001: begin
casez (insn[24:20])
5'b 00000 /* CLZW */: begin next_wr = 1; next_rd = 0; for (int i=0; i<32; i=i+1) next_rd = rs1_value[i] ? 0 : next_rd + 1; end
5'b 00001 /* CTZW */: begin next_wr = 1; next_rd = 0; for (int i=32; i>0; i=i-1) next_rd = rs1_value[i-1] ? 0 : next_rd + 1; end
5'b 00010 /* CPOPW */: begin next_wr = 1; next_rd = 0; for (int i=0; i<32; i=i+1) next_rd = next_rd + rs1_value[i]; end
default: illinsn = 1;
endcase
end
10'b 0110000_101 /* RORIW */: begin next_wr = 1; next_rd = zext_rs1_32 >> insn[24:20] | (zext_rs1_32 << (32 - insn[24:20])); next_rd[Nb-1:32] = {Nb-32{next_rd[31]}}; end
10'b 000010z_001 /* SLLI.UW */: begin next_wr = 1; next_rd = zext_rs1_32 << insn[25:20]; end
endcase
end
OPCODE_OP_32: begin
case ({insn_funct7, insn_funct3})
10'b 0000100_000 /* ADD.UW */: begin next_wr = 1; next_rd = rs2_value + zext_rs1_32; end
10'b 0010000_010 /* SH1ADD.UW */: begin next_wr = 1; next_rd = rs2_value + {'0, rs1_value[31:0], 1'b 0}; end
10'b 0010000_100 /* SH2ADD.UW */: begin next_wr = 1; next_rd = rs2_value + {'0, rs1_value[31:0], 2'b 0}; end
10'b 0010000_110 /* SH3ADD.UW */: begin next_wr = 1; next_rd = rs2_value + {'0, rs1_value[31:0], 3'b 0}; end
10'b 0110000_001 /* ROLW */: begin next_wr = 1; next_rd = zext_rs1_32 << rs2_value[4:0] | (zext_rs1_32 >> (32 - rs2_value[4:0])); next_rd[Nb-1:32] = {Nb-32{next_rd[31]}}; end
10'b 0110000_101 /* RORW */: begin next_wr = 1; next_rd = zext_rs1_32 >> rs2_value[4:0] | (zext_rs1_32 << (32 - rs2_value[4:0])); next_rd[Nb-1:32] = {Nb-32{next_rd[31]}}; end
10'b 0000100_100 /* ZEXT.H(64) */: begin next_wr = 1; next_rd = {'0, rs1_value[15:0]}; end
default: illinsn = 1;
endcase
end
Expand Down
36 changes: 18 additions & 18 deletions cores/nerv64/trace.gtkw
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ rvfi_testbench.wrapper.uut.trap
@200
-
@23
rvfi_testbench.wrapper.uut.pc[31:0]
rvfi_testbench.wrapper.uut.pc[63:0]
@22
rvfi_testbench.wrapper.uut.insn[31:0]
@c00200
Expand All @@ -45,10 +45,10 @@ rvfi_testbench.wrapper.uut.insn_opcode[6:0]
@200
-
@22
rvfi_testbench.wrapper.uut.imm_b_sext[31:0]
rvfi_testbench.wrapper.uut.imm_i_sext[31:0]
rvfi_testbench.wrapper.uut.imm_j_sext[31:0]
rvfi_testbench.wrapper.uut.imm_s_sext[31:0]
rvfi_testbench.wrapper.uut.imm_b_sext[63:0]
rvfi_testbench.wrapper.uut.imm_i_sext[63:0]
rvfi_testbench.wrapper.uut.imm_j_sext[63:0]
rvfi_testbench.wrapper.uut.imm_s_sext[63:0]
@1401200
-insn_decoded
@200
Expand All @@ -64,7 +64,7 @@ rvfi_testbench.checker_inst.spec_valid
rvfi_testbench.checker_inst.rvfi_trap
@22
rvfi_testbench.checker_inst.rvfi_insn[31:0]
rvfi_testbench.wrapper.uut.rvfi_pc_rdata[31:0]
rvfi_testbench.wrapper.uut.rvfi_pc_rdata[63:0]
@c00200
-spec
@28
Expand All @@ -76,13 +76,13 @@ rvfi_testbench.checker_inst.spec_trap
rvfi_testbench.checker_inst.spec_rs1_addr[4:0]
rvfi_testbench.checker_inst.spec_rs2_addr[4:0]
rvfi_testbench.checker_inst.spec_rd_addr[4:0]
rvfi_testbench.checker_inst.spec_rd_wdata[31:0]
rvfi_testbench.checker_inst.spec_pc_wdata[31:0]
rvfi_testbench.checker_inst.spec_rd_wdata[63:0]
rvfi_testbench.checker_inst.spec_pc_wdata[63:0]
@200
-
@22
rvfi_testbench.checker_inst.spec_mem_addr[31:0]
rvfi_testbench.checker_inst.spec_mem_wdata[31:0]
rvfi_testbench.checker_inst.spec_mem_addr[63:0]
rvfi_testbench.checker_inst.spec_mem_wdata[63:0]
rvfi_testbench.checker_inst.spec_mem_rmask[3:0]
rvfi_testbench.checker_inst.spec_mem_wmask[3:0]
@1401200
Expand All @@ -103,8 +103,8 @@ rvfi_testbench.checker_inst.rvfi_insn[31:0]
@200
-
@22
rvfi_testbench.checker_inst.rvfi_pc_rdata[31:0]
rvfi_testbench.checker_inst.rvfi_pc_wdata[31:0]
rvfi_testbench.checker_inst.rvfi_pc_rdata[63:0]
rvfi_testbench.checker_inst.rvfi_pc_wdata[63:0]
@200
-
@22
Expand All @@ -114,9 +114,9 @@ rvfi_testbench.checker_inst.rvfi_rd_addr[4:0]
@200
-
@22
rvfi_testbench.checker_inst.rvfi_rs1_rdata[31:0]
rvfi_testbench.checker_inst.rvfi_rs2_rdata[31:0]
rvfi_testbench.checker_inst.rvfi_rd_wdata[31:0]
rvfi_testbench.checker_inst.rvfi_rs1_rdata[63:0]
rvfi_testbench.checker_inst.rvfi_rs2_rdata[63:0]
rvfi_testbench.checker_inst.rvfi_rd_wdata[63:0]
@200
-
@22
Expand All @@ -143,9 +143,9 @@ rvfi_testbench.checker_inst.csr_insn_rdata[31:0]
rvfi_testbench.checker_inst.csr_insn_rmask[31:0]
rvfi_testbench.checker_inst.csr_insn_wdata[31:0]
rvfi_testbench.checker_inst.csr_insn_wmask[31:0]
rvfi_testbench.checker_inst.rsval_shadow[31:0]
rvfi_testbench.checker_inst.wdata_shadow[31:0]
rvfi_testbench.checker_inst.rdata_shadow[31:0]
rvfi_testbench.checker_inst.rsval_shadow[63:0]
rvfi_testbench.checker_inst.wdata_shadow[63:0]
rvfi_testbench.checker_inst.rdata_shadow[63:0]
rvfi_testbench.checker_inst.csr_mode_shadow[1:0]
@1401200
-csr
Expand Down
32 changes: 2 additions & 30 deletions cores/nerv64/wrapper.sv
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,8 @@ module rvfi_wrapper (
(* keep *) `rvformal_rand_reg [31:0] dmem_rdata;
(* keep *) `rvformal_rand_reg [31:0] irq;

`ifdef NERV_FAULT
(* keep *) `rvformal_rand_reg imem_fault;
(* keep *) `rvformal_rand_reg dmem_fault;
`else
wire imem_fault = 0;
wire dmem_fault = 0;
`endif

(* keep *) wire trap;

Expand All @@ -61,14 +56,9 @@ module rvfi_wrapper (
.dmem_wdata (dmem_wdata),
.dmem_rdata (dmem_rdata),

`ifdef NERV_FAULT
.imem_fault (imem_fault),
.dmem_fault (dmem_fault),
`endif

.irq (irq),

`RVFI_CONN32
`RVFI_CONN
);

`ifdef RISCV_FORMAL_BUS
Expand Down Expand Up @@ -112,26 +102,16 @@ module rvfi_wrapper (
(* keep *) `rvformal_rand_reg [31:0] next_dmem_rdata;
reg [31:0] next_dmem_rdata_q;

`ifdef NERV_FAULT
(* keep *) `rvformal_rand_reg [31:0] next_dmem_fault;
reg [31:0] next_dmem_fault_q;
`endif

always @(posedge clock) begin
if (!stall) begin
next_dmem_rdata_q <= next_dmem_rdata;
`ifdef NERV_FAULT
next_dmem_fault_q <= next_dmem_fault;
`endif

end
end

always @* begin
if (!stall) begin
assume (dmem_rdata == next_dmem_rdata_q);
`ifdef NERV_FAULT
assume (dmem_fault == next_dmem_fault_q);
`endif
end
dmem_bus_addr = dmem_addr;
dmem_bus_insn = 0;
Expand All @@ -145,12 +125,4 @@ module rvfi_wrapper (
end;

`endif

`ifdef NERV_FAIRNESS
reg [2:0] stalled = 0;
always @(posedge clock) begin
stalled <= {stalled, stall};
assume (~stalled);
end
`endif
endmodule

0 comments on commit 886e837

Please sign in to comment.