Implement CSR instruction in decoder

This commit is contained in:
Florian Zaruba 2017-05-05 17:51:28 +02:00
parent b0040c754d
commit 0f80a6d211
4 changed files with 89 additions and 19 deletions

View file

@ -86,7 +86,8 @@ package ariane_pkg;
logic [63:0] result; // for unfinished instructions this field also holds the immediate
logic valid; // is the result valid
logic use_imm; // should we use the immediate as operand b?
logic use_pc; // set if we need to use the PC as operand A, PC from exception
logic use_zimm; // use zimm as operand a
logic use_pc; // set if we need to use the PC as operand a, PC from exception
exception ex; // exception has occurred
logic is_compressed; // signals a compressed instructions, we need this information at the commit stage if
// we want jump accordingly e.g.: +4, +2

View file

@ -50,6 +50,7 @@ module commit_stage (
assign waddr_a_o = commit_instr_i.rd;
assign wdata_a_o = commit_instr_i.result;
assign pc_o = commit_instr_i.pc;
// commit instruction
// write register file
always_comb begin : commit

View file

@ -30,7 +30,7 @@ module decoder (
} imm_select;
logic [63:0] imm_i_type;
logic [63:0] imm_iz_type;
logic [11:0] imm_iz_type;
logic [63:0] imm_s_type;
logic [63:0] imm_sb_type;
logic [63:0] imm_u_type;
@ -44,26 +44,90 @@ module decoder (
always_comb begin : decoder
imm_select = NOIMM;
illegal_instr = 1'b0;
instruction_o.pc = pc_i;
instruction_o.fu = NONE;
instruction_o.op = ADD;
instruction_o.rs1 = 5'b0;
instruction_o.rs2 = 5'b0;
instruction_o.rd = 5'b0;
instruction_o.use_pc = 1'b0;
instruction_o.trans_id = 5'b0;
imm_select = NOIMM;
illegal_instr = 1'b0;
instruction_o.pc = pc_i;
instruction_o.fu = NONE;
instruction_o.op = ADD;
instruction_o.rs1 = 5'b0;
instruction_o.rs2 = 5'b0;
instruction_o.rd = 5'b0;
instruction_o.use_pc = 1'b0;
instruction_o.trans_id = 5'b0;
instruction_o.is_compressed = is_compressed_i;
// TODO end
instruction_o.use_zimm = 1'b0;
if (~ex_i.valid) begin
case (instr.rtype.opcode)
OPCODE_SYSTEM: begin
// TODO: Implement
instruction_o.fu = CSR;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rd = instr.itype.rd;
unique case (instr.itype.funct3)
3'b000: begin
// TODO:
// ECALL, EBREAK, SFEBCE.VM
// MRET/SRET/URET, WFI
illegal_instr = 1'b1;
end
// atomically swaps values in the CSR and integer register
3'b001: begin// CSRRW
imm_select = IIMM;
instruction_o.op = CSR_WRITE;
end
// atomically set values in the CSR and write back to rd
3'b010: begin// CSRRS
imm_select = IIMM;
// this is just a read
if (instr.itype.rs1 == 5'b0)
instruction_o.op = CSR_READ;
else
instruction_o.op = CSR_SET;
end
// atomically clear values in the CSR and write back to rd
3'b011: begin// CSRRC
imm_select = IIMM;
// this is just a read
if (instr.itype.rs1 == 5'b0)
instruction_o.op = CSR_READ;
else
instruction_o.op = CSR_SET;
end
// use zimm and iimm
3'b101: begin// CSRRWI
instruction_o.rs1 = 5'b0;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
instruction_o.op = CSR_WRITE;
end
3'b110: begin// CSRRSI
instruction_o.rs1 = 5'b0;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
// this is just a read
if (instr.itype.rs1 == 5'b0)
instruction_o.op = CSR_READ;
else
instruction_o.op = CSR_SET;
end
3'b111: begin// CSRRCI
instruction_o.rs1 = 5'b0;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
// this is just a read
if (instr.itype.rs1 == 5'b0)
instruction_o.op = CSR_READ;
else
instruction_o.op = CSR_CLEAR;
end
default: illegal_instr = 1'b1;
endcase
end
OPCODE_FENCE: begin
// TODO: Implement
// FENCE, FENCE.I,
end
// --------------------------
@ -269,7 +333,6 @@ module decoder (
imm_sb_type = { {51 {instruction_i[31]}}, instruction_i[31], instruction_i[7], instruction_i[30:25], instruction_i[11:8], 1'b0 };
imm_u_type = { {32 {instruction_i[31]}}, instruction_i[31:12], 12'b0 }; // JAL, AUIPC, sign extended to 64 bit
imm_uj_type = { {44 {instruction_i[31]}}, instruction_i[19:12], instruction_i[20], instruction_i[30:21], 1'b0 };
// imm_z_type = { 59'b0, instruction_i[`REG_S1] };
imm_s2_type = { 59'b0, instruction_i[24:20] };
imm_bi_type = { {59{instruction_i[24]}}, instruction_i[24:20] };
imm_s3_type = { 59'b0, instruction_i[29:25] };

View file

@ -61,7 +61,7 @@ module issue_read_operands (
input logic [63:0] wdata_a_i,
input logic we_a_i
);
logic stall; // stall signal, we do not want to fetch any more entries
logic stall; // stall signal, we do not want to fetch any more entries
logic fu_busy; // functional unit is busy
logic [63:0] operand_a_regfile, operand_b_regfile; // operands coming from regfile
@ -146,9 +146,11 @@ module issue_read_operands (
// poll the scoreboard for those values
rs1_o = issue_instr_i.rs1;
rs2_o = issue_instr_i.rs2;
// 0. check that we are not using the zimm type in rs1
// as this is an immediate we do not have to wait on anything here
// 1. check if the source registers are clobberd
// 2. poll the scoreboard
if (rd_clobber_i[issue_instr_i.rs1] != NONE) begin
if (~issue_instr_i.use_zimm && rd_clobber_i[issue_instr_i.rs1] != NONE) begin
// the operand is available, forward it
if (rs1_valid_i)
forward_rs1 = 1'b1;
@ -164,8 +166,6 @@ module issue_read_operands (
else // the operand is not available -> stall
stall = 1'b1;
end
end
// Forwarding/Output MUX
always_comb begin : forwarding
@ -187,6 +187,11 @@ module issue_read_operands (
operand_a_n = issue_instr_i.pc;
end
// use the zimm as operand a
if (issue_instr_i.use_zimm) begin
// zero extend operand a
operand_a_n = {52'b0, issue_instr_i.rs1};
end
// or is it an immediate (including PC), this is not the case for a store
if (issue_instr_i.use_imm && issue_instr_i.op != SD
&& issue_instr_i.op != SW