Cherry pick 1

This commit is contained in:
Flo Zaruba 2015-09-17 13:51:54 +02:00
parent 8fe67b303d
commit d274068643
2 changed files with 89 additions and 9 deletions

View file

@ -52,7 +52,7 @@ module cs_registers
output logic irq_enable_o,
output logic [31:0] epcr_o,
output logic timer_cmp_irq_o,
// Performance Counters
input logic stall_id_i, // stall ID stage
input logic is_compressed_i, // compressed instruction in ID
@ -100,6 +100,9 @@ module cs_registers
// Generic CSRs
logic [31:0] csr [0:`CSR_MAX_IDX];
logic [31:0] csr_n [0:`CSR_MAX_IDX];
// mtime - cycle count
//logic [31:0] csr_mtime_int, csr_mtime;
// CSR update logic
logic [31:0] csr_wdata_int;
@ -108,7 +111,16 @@ module cs_registers
// Interrupt control signals
logic irq_enable, irq_enable_n;
////////////////////////////////////////////
// ____ ____ ____ ____ //
// / ___/ ___|| _ \ | _ \ ___ __ _ //
// | | \___ \| |_) | | |_) / _ \/ _` | //
// | |___ ___) | _ < | _ < __/ (_| | //
// \____|____/|_| \_\ |_| \_\___|\__, | //
// |___/ //
////////////////////////////////////////////
// read logic
always_comb
@ -130,6 +142,15 @@ module cs_registers
12'hF01: csr_rdata_int = 32'h00_00_80_00;
// mhartid: unique hardware thread id
12'hF10: csr_rdata_int = {22'b0, cluster_id_i, core_id_i};
// Machine trap setup 0x300 - 0x321
// mtimecmp - machine wall-clock timer compare value
12'h321: csr_rdata_int = csr[`CSR_IDX_MTIMECMP];
// machine level timers and counters 0x701 - 0x741
// mtime - machine wall-clock time (? - actually not really wall clock??)
12'h701: csr_rdata_int = csr[`CSR_IDX_MTIME];
endcase
end
@ -138,6 +159,9 @@ module cs_registers
always_comb
begin
csr_n = csr;
//if timer interrupt occured - reset status unless it is written by the application
if (timer_cmp_irq_o == 1'b1) csr_n[`CSR_IDX_MTIME] = 32'b0;
irq_enable_n = irq_enable;
case (csr_addr_i)
@ -148,6 +172,12 @@ module cs_registers
12'h340: if (csr_we_int) csr_n[`CSR_IDX_MSCRATCH] = csr_wdata_int;
// mepc: exception program counter
12'h341: if (csr_we_int) csr_n[`CSR_IDX_MEPC] = csr_wdata_int;
// mtimecmp
12'h321: if (csr_we_int) csr_n[`CSR_IDX_MTIMECMP] = csr_wdata_int;
// mtime
12'h701: if (csr_we_int) csr_n[`CSR_IDX_MTIME] = csr_wdata_int;
endcase
end
@ -198,9 +228,11 @@ module cs_registers
else
begin
// update CSRs
csr <= csr_n;
irq_enable <= irq_enable_n;
csr <= csr_n;
// increment the timer register (mtime)
csr[`CSR_IDX_MTIME] <= csr_n[`CSR_IDX_MTIME] + 1;
irq_enable <= irq_enable_n;
// exception PC writes from exception controller get priority
if (save_pc_if_i == 1'b1)
csr[`CSR_IDX_MEPC] <= curr_pc_if_i;
@ -208,6 +240,30 @@ module cs_registers
csr[`CSR_IDX_MEPC] <= curr_pc_id_i;
end
end
////////////////////////////////////////////////
// _____ _ ____ //
// |_ _(_)_ __ ___ / ___|_ __ ___ _ __ //
// | | | | '_ ` _ \ | | | '_ ` _ \| '_ \ //
// | | | | | | | | || |___| | | | | | |_) | //
// |_| |_|_| |_| |_(_)____|_| |_| |_| .__/ //
// |_| //
// //
////////////////////////////////////////////////
// ommitting timer interrupt status register according to spec 1.7 priv instr.
// 32bit comparator
always_comb
begin
if (csr[`CSR_IDX_MTIMECMP] != 32'b0 && csr[`CSR_IDX_MTIMECMP] == csr[`CSR_IDX_MTIME])
begin
timer_cmp_irq_o = 1'b1;
end
else
begin
timer_cmp_irq_o = 1'b0;
end
end
/////////////////////////////////////////////////////////////////

View file

@ -67,10 +67,11 @@ module exc_controller
);
// Exception unit state encoding
enum logic [1:0] { ExcNone, ExcIR, ExcIllegalInsn } exc_reason;
enum logic [1:0] { ExcNone, ExcIR, ExcIRDeferred, ExcIllegalInsn } exc_reason, exc_reason_q, exc_reason_n;
// Registers
logic exc_running_p, exc_running_n;
logic new_instr_id_q;
// disable hardware loops when nops are inserted or the controller is not active
assign hwloop_enable_o = (~core_busy_i);
@ -138,6 +139,9 @@ module exc_controller
else
exc_reason = ExcIllegalInsn;
end
if (exc_reason_q != ExcNone)
exc_reason = exc_reason_q;
end
/////////////////////////////////////////////////////////////////////
@ -149,23 +153,29 @@ module exc_controller
// |_| //
/////////////////////////////////////////////////////////////////////
// exception control FSM
always_comb begin
exc_running_n = exc_running_p;
save_pc_if_o = 1'b0;
save_pc_id_o = 1'b0;
exc_pc_sel_o = 1'b0;
exc_pc_mux_o = `EXC_PC_NO_INCR;
exc_reason_n = ExcNone;
unique case (exc_reason)
// an IRQ is present, execute pending jump and then go
// to the ISR without flushing the pipeline
ExcIR: begin
if (jump_in_id_i == 2'b00 && jump_in_ex_i == 2'b00)
begin // no jump in ID
ExcIR: begin
if (((jump_in_id_i == `BRANCH_JALR || jump_in_id_i == `BRANCH_JAL) && new_instr_id_q == 1'b0)) || jump_in_ex_i == `BRANCH_COND)
begin
//wait one cycle
exc_reason_n = ExcIRDeferred;
end
else //don't wait
begin
exc_pc_sel_o = 1'b1;
save_pc_if_o = 1'b1; // save current PC
if (irq_nm_i == 1'b1) // emergency IRQ has higher priority
exc_pc_mux_o = `EXC_PC_IRQ_NM;
@ -173,8 +183,18 @@ module exc_controller
exc_pc_mux_o = `EXC_PC_IRQ;
exc_running_n = 1'b1;
// jumps in ex stage already taken
if (jump_in_id_i != `BRANCH_NONE)
save_pc_id_o = 1'b1;
else
save_pc_if_o = 1'b1;
end
end
ExcIRDeferred : begin
//
end
// Illegal instruction encountered, we directly jump to
// the ISR without flushing the pipeline
@ -195,10 +215,14 @@ module exc_controller
if ( rst_n == 1'b0 )
begin
exc_running_p <= 1'b0;
new_instr_id_q <= 1'b0;
exc_reason_q <= ExcNone;
end
else
begin
exc_running_p <= (clear_isr_running_i == 1'b1) ? 1'b0 : exc_running_n;
new_instr_id_q <= ~stall_id_i;
exc_reason_q <= exc_reason_n;
end
end