Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add B extension (Zba, Zbb, Zbs) #29

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions cores/nerv/checks.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

[options]
isa rv32i
isa rv32ib
nbus 2
csr_spec 1.12
# csr_spec 1.12

[depth]
insn 10
Expand Down
39 changes: 39 additions & 0 deletions cores/nerv/nerv.sv
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,25 @@ module nerv #(
10'b 0000000_001 /* SLLI */: begin next_wr = 1; next_rd = rs1_value << insn[24:20]; 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 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
// 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
default: illinsn = 1;
endcase
end
Expand All @@ -966,6 +985,26 @@ module nerv #(
10'b 0100000_101 /* SRA */: begin next_wr = 1; next_rd = $signed(rs1_value) >>> rs2_value[4:0]; end
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
// 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
10'b 0100000_100 /* XNOR */: begin next_wr = 1; next_rd = ~(rs1_value ^ rs2_value); end
10'b 0000101_110 /* MAX */: begin next_wr = 1; next_rd = ($signed(rs1_value) < $signed(rs2_value)) ? rs2_value : rs1_value; end
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
// 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
default: illinsn = 1;
endcase
end
Expand Down
Loading
Loading