L/S output now shared with CSRs

This commit is contained in:
Eric Matthews 2019-08-28 16:58:43 -07:00
parent e4299bba99
commit 4e35ee52f6
6 changed files with 159 additions and 115 deletions

View file

@ -31,6 +31,7 @@ module csr_regs (
//GC unit
input csr_inputs_t csr_inputs,
input new_request,
input commit,
input exception_packet_t gc_exception,
output exception_packet_t csr_exception,
output logic [1:0] current_privilege,
@ -58,7 +59,7 @@ module csr_regs (
input logic interrupt,
input logic timer_interrupt,
output logic [XLEN-1:0] selected_csr,
output logic [XLEN-1:0] wb_csr,
output logic [31:0] trap_pc,
output logic [31:0] csr_mepc,
output logic [31:0] csr_sepc
@ -123,6 +124,9 @@ module csr_regs (
csr_addr_t csr_addr;
logic privilege_exception;
logic [XLEN-1:0] selected_csr;
logic [XLEN-1:0] selected_csr_r;
logic [31:0] updated_csr;
logic invalid_addr;
@ -162,10 +166,10 @@ module csr_regs (
//convert addr into packed struct form
assign csr_addr = csr_inputs.csr_addr;
assign privilege_exception = new_request && (csr_addr.privilege > privilege_level);
assign privilege_exception = new_request & (csr_addr.privilege > privilege_level);
assign supervisor_write = new_request && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == SUPERVISOR_PRIVILEGE);
assign machine_write = new_request && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == MACHINE_PRIVILEGE);
assign supervisor_write = commit && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == SUPERVISOR_PRIVILEGE);
assign machine_write = commit && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == MACHINE_PRIVILEGE);
logic illegal_instruction;
assign illegal_instruction = invalid_addr | privilege_exception;
@ -177,8 +181,8 @@ module csr_regs (
always_comb begin
case (csr_inputs.csr_op)
CSR_RW : updated_csr = csr_inputs.rs1;
CSR_RS : updated_csr = selected_csr | csr_inputs.rs1;
CSR_RC : updated_csr = selected_csr & ~csr_inputs.rs1;
CSR_RS : updated_csr = selected_csr_r | csr_inputs.rs1;
CSR_RC : updated_csr = selected_csr_r & ~csr_inputs.rs1;
default : updated_csr = csr_inputs.rs1;
endcase
end
@ -525,4 +529,10 @@ endgenerate
endcase
end
always_ff @(posedge clk) begin
selected_csr_r <= selected_csr;
end
assign wb_csr = selected_csr_r;
endmodule

View file

@ -97,6 +97,7 @@ module decode(
logic mult_div_op;
logic [NUM_WB_UNITS-1:0] new_request_for_id_gen;
logic [NUM_UNITS-1:0] new_request;
logic [WB_UNITS_WIDTH-1:0] new_request_int;
logic [NUM_UNITS-1:0] issue_ready;
@ -147,7 +148,13 @@ module decode(
assign ti.inflight_packet.rd_addr = future_rd_addr;
assign ti.inflight_packet.rd_addr_nzero = ~rd_zero;
assign ti.issued = instruction_issued & (uses_rd | new_request[LS_UNIT_WB_ID]);
one_hot_to_integer #(NUM_WB_UNITS) new_request_to_int (.*, .one_hot(new_request[NUM_WB_UNITS-1:0]), .int_out(ti.inflight_packet.unit_id));
always_comb begin
new_request_for_id_gen = new_request[NUM_WB_UNITS-1:0];
new_request_for_id_gen[LS_UNIT_WB_ID] |= new_request[GC_UNIT_ID];
end
one_hot_to_integer #(NUM_WB_UNITS) new_request_to_int (.*, .one_hot(new_request_for_id_gen), .int_out(ti.inflight_packet.unit_id));
////////////////////////////////////////////////////
//Unit Determination
assign mult_div_op = fb.instruction[25];
@ -155,7 +162,7 @@ module decode(
assign new_request[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
assign new_request[ALU_UNIT_WB_ID] = fb.alu_request;
assign new_request[LS_UNIT_WB_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
assign new_request[GC_UNIT_WB_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
assign new_request[GC_UNIT_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
generate if (USE_MUL)
assign new_request[MUL_UNIT_WB_ID] = (opcode_trim == ARITH_T) && mult_div_op && ~fn3[2];
@ -172,7 +179,7 @@ module decode(
assign issue_ready[BRANCH_UNIT_ID] = new_request[BRANCH_UNIT_ID] & branch_ex.ready;
assign issue_ready[ALU_UNIT_WB_ID] = new_request[ALU_UNIT_WB_ID] & alu_ex.ready;
assign issue_ready[LS_UNIT_WB_ID] = new_request[LS_UNIT_WB_ID] & ls_ex.ready;
assign issue_ready[GC_UNIT_WB_ID] = new_request[GC_UNIT_WB_ID] & gc_ex.ready;
assign issue_ready[GC_UNIT_ID] = new_request[GC_UNIT_ID] & gc_ex.ready;
generate if (USE_MUL)
assign issue_ready[MUL_UNIT_WB_ID] = new_request[MUL_UNIT_WB_ID] & mul_ex.ready;
endgenerate
@ -191,7 +198,7 @@ module decode(
assign issue[BRANCH_UNIT_ID] = issue_valid & operands_ready & issue_ready[BRANCH_UNIT_ID];
assign issue[ALU_UNIT_WB_ID] = issue_valid & operands_ready & issue_ready[ALU_UNIT_WB_ID];
assign issue[LS_UNIT_WB_ID] = issue_valid & load_store_operands_ready & issue_ready[LS_UNIT_WB_ID];
assign issue[GC_UNIT_WB_ID] = issue_valid & operands_ready & issue_ready[GC_UNIT_WB_ID];
assign issue[GC_UNIT_ID] = issue_valid & operands_ready & issue_ready[GC_UNIT_ID];
generate if (USE_MUL)
assign issue[MUL_UNIT_WB_ID] = issue_valid & operands_ready & issue_ready[MUL_UNIT_WB_ID];
endgenerate
@ -324,21 +331,21 @@ module decode(
assign environment_op = (opcode_trim == SYSTEM_T) && (fn3 == 0);
always_ff @(posedge clk) begin
if (issue_ready[GC_UNIT_WB_ID]) begin
if (issue_ready[GC_UNIT_ID]) begin
gc_inputs.pc <= fb.pc;
gc_inputs.instruction <= fb.instruction;
gc_inputs.rs1 <= rf_decode.rs1_data;
gc_inputs.rs2 <= rf_decode.rs2_data;
gc_inputs.rd_is_zero <= rd_zero;
gc_inputs.is_fence <= (opcode_trim == FENCE_T) && ~fn3[0];
gc_inputs.is_csr <= (opcode_trim == SYSTEM_T) && (fn3 != 0);
end
gc_inputs.is_ecall <= issue[GC_UNIT_WB_ID] && environment_op && (fb.instruction[21:20] == 0);
gc_inputs.is_ebreak <= issue[GC_UNIT_WB_ID] && environment_op && (fb.instruction[21:20] == 2'b01);
gc_inputs.is_ret <= issue[GC_UNIT_WB_ID] && environment_op && (fb.instruction[21:20] == 2'b10);
gc_inputs.is_i_fence <= issue[GC_UNIT_WB_ID] && ifence;
gc_inputs.is_csr <= (opcode_trim == SYSTEM_T) && (fn3 != 0);
gc_inputs.is_ecall <= issue[GC_UNIT_ID] && environment_op && (fb.instruction[21:20] == 0);
gc_inputs.is_ebreak <= issue[GC_UNIT_ID] && environment_op && (fb.instruction[21:20] == 2'b01);
gc_inputs.is_ret <= issue[GC_UNIT_ID] && environment_op && (fb.instruction[21:20] == 2'b10);
gc_inputs.is_i_fence <= issue[GC_UNIT_ID] && ifence;
end
assign gc_flush_required = issue[GC_UNIT_WB_ID] && (environment_op | ifence);
assign gc_flush_required = issue[GC_UNIT_ID] && (environment_op | ifence);
////////////////////////////////////////////////////
@ -405,13 +412,13 @@ module decode(
assign alu_ex.new_request_dec = issue[ALU_UNIT_WB_ID];
assign ls_ex.new_request_dec = issue[LS_UNIT_WB_ID];
assign branch_ex.new_request_dec = issue[BRANCH_UNIT_ID];
assign gc_ex.new_request_dec = issue[GC_UNIT_WB_ID];
assign gc_ex.new_request_dec = issue[GC_UNIT_ID];
always_ff @(posedge clk) begin
alu_ex.new_request <= issue[ALU_UNIT_WB_ID];
ls_ex.new_request <= issue[LS_UNIT_WB_ID];
branch_ex.new_request <= issue[BRANCH_UNIT_ID];
gc_ex.new_request <= issue[GC_UNIT_WB_ID];
gc_ex.new_request <= issue[GC_UNIT_ID];
end
assign branch_ex.instruction_id_one_hot = ti.issue_id_one_hot;
@ -443,7 +450,7 @@ module decode(
assign branch_ex.possible_issue = new_request[BRANCH_UNIT_ID] & ti.id_available;
assign alu_ex.possible_issue = new_request[ALU_UNIT_WB_ID] & ti.id_available;
assign ls_ex.possible_issue = new_request[LS_UNIT_WB_ID] & ti.id_available;
assign gc_ex.possible_issue = new_request[GC_UNIT_WB_ID] & ti.id_available;
assign gc_ex.possible_issue = new_request[GC_UNIT_ID] & ti.id_available;
////////////////////////////////////////////////////
@ -475,7 +482,7 @@ module decode(
assign tr_unit_stall = ~(|issue_ready) & issue_valid & load_store_operands_ready;
assign tr_no_id_stall = (|issue_ready) & (fb_valid & ~ti.id_available & ~gc_issue_hold & ~gc_fetch_flush) & load_store_operands_ready;
assign tr_no_instruction_stall = ~fb_valid;
assign tr_other_stall = ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall);
assign tr_other_stall = fb_valid & ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall) & ~gc_fetch_flush;
assign tr_instruction_issued_dec = instruction_issued;
assign tr_instruction_pc_dec = fb.pc;

View file

@ -55,7 +55,7 @@ module gc_unit(
input logic instruction_complete,
input logic instruction_queue_empty,
input instruction_id_t oldest_id,
unit_writeback_interface.unit gc_wb,
//unit_writeback_interface.unit gc_wb,
//External
input logic interrupt,
@ -71,7 +71,13 @@ module gc_unit(
output logic inorder,
output logic inuse_clear,
output logic [31:0] gc_fetch_pc
output logic [31:0] gc_fetch_pc,
//Write-back to Load-Store Unit
output logic[31:0] csr_rd,
output instruction_id_t csr_id,
output instruction_id_one_hot_t csr_id_done,
output logic csr_done
);
//Largest depth for TLBs
@ -82,8 +88,6 @@ module gc_unit(
logic [CLEAR_DEPTH-1:0] clear_shift_count;
logic [TLB_CLEAR_DEPTH-1:0] tlb_clear_shift_count;
////////////////////////////////////////////////////
enum {OP_ECALL, OP_EBREAK, OP_SRET, OP_MRET, OP_SFENCE, OP_FENCE, OP_FENCEI} operation;
//Instructions
//All instructions are processed only if in IDLE state, meaning there can be no exceptions caused by instructions already further in the pipeline.
//FENCE:
@ -141,7 +145,7 @@ module gc_unit(
//CSR
logic mret;
logic sret;
logic [XLEN-1:0] selected_csr;
logic [XLEN-1:0] wb_csr;
csr_inputs_t csr_inputs;
exception_packet_t gc_exception;
exception_packet_t csr_exception;
@ -151,8 +155,6 @@ module gc_unit(
logic [31:0] csr_sepc;
//Write-back handshaking
logic processing;
logic [2:0] fn3;
logic [6:0] opcode;
logic [4:0] opcode_trim;
@ -161,6 +163,9 @@ module gc_unit(
logic [4:0] rs2_addr;
logic [4:0] future_rd_addr;
instruction_id_one_hot_t id;
logic is_csr;
logic processing_csr;
//implementation
////////////////////////////////////////////////////
@ -171,60 +176,14 @@ module gc_unit(
assign fn3 = gc_inputs.instruction[14:12];
assign rs1_addr = gc_inputs.instruction[19:15];
always @(posedge clk) begin
if (rst)
state <= RST_STATE;
else
state <= next_state;
end
always_comb begin
next_state = state;
case (state)
RST_STATE : next_state = PRE_CLEAR_STATE;
PRE_CLEAR_STATE : next_state = CLEAR_STATE;
CLEAR_STATE : if (clear_shift_count[CLEAR_DEPTH-1]) next_state = IDLE_STATE;
IDLE_STATE : if (load_store_issue) next_state = LS_EXCEPTION_POSSIBLE;
TLB_CLEAR_STATE : if (tlb_clear_shift_count[TLB_CLEAR_DEPTH-1]) next_state = IDLE_STATE;
LS_EXCEPTION_POSSIBLE :
if (load_store_FIFO_emptying)
next_state = IDLE_STATE;
else if (ls_exception_valid) begin
if (ls_exception.id == oldest_id)
next_state = IQ_DISCARD;
else
next_state = IQ_DRAIN;
end
IQ_DRAIN :
if (ls_exception.id == oldest_id)
next_state = IQ_DISCARD;
IQ_DISCARD :
if (instruction_queue_empty)
next_state = IDLE_STATE;
default : next_state = RST_STATE;
endcase
end
logic ls_exception_first_cycle;
logic ls_exception_second_cycle;
assign ls_exception_first_cycle = ls_exception_valid && (state == LS_EXCEPTION_POSSIBLE);
always_ff @ (posedge clk) begin
ls_exception_second_cycle <= ls_exception_first_cycle;
end
assign gc_exception.code =
ls_exception_second_cycle ? ls_exception.code :
gc_inputs.is_ecall ? ecall_code : BREAK;
assign gc_exception.pc = ls_exception_second_cycle ? ls_exception.pc : gc_inputs.pc;
assign gc_exception.tval = ls_exception_second_cycle ? ls_exception.tval : '0;
assign gc_exception.valid = gc_inputs.is_ecall | gc_inputs.is_ebreak | ls_exception_second_cycle;
////////////////////////////////////////////////////
//GC Operation
assign is_csr = gc_ex.new_request & gc_inputs.is_csr;
assign gc_fetch_flush = branch_flush | gc_fetch_pc_override;
always_ff @ (posedge clk) begin
gc_issue_hold <= gc_ex.new_request_dec || processing || (next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD});
gc_issue_hold <= gc_ex.new_request_dec || is_csr || processing_csr || (next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD});
inuse_clear <= (next_state == CLEAR_STATE);
inorder <= 0;//(next_state inside {LS_EXCEPTION_POSSIBLE, IQ_DRAIN});
end
@ -237,14 +196,39 @@ module gc_unit(
gc_supress_writeback <= next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DISCARD} ? 1 : 0;
end
////////////////////////////////////////////////////
//GC State Machine
always @(posedge clk) begin
if (rst)
state <= RST_STATE;
else
state <= next_state;
end
always_ff @ (posedge clk) begin
second_cycle_flush <= gc_flush_required;
gc_fetch_pc_override <= gc_flush_required | second_cycle_flush | ls_exception_first_cycle;
gc_fetch_pc <=
gc_inputs.is_i_fence ? gc_inputs.pc + 4 :
gc_inputs.is_ret ? csr_mepc :
trap_pc;
gc_state ls_exception_next_state;
always_comb begin
ls_exception_next_state = state;
if (load_store_FIFO_emptying)
ls_exception_next_state = IDLE_STATE;
else if (ls_exception_valid) begin
if (ls_exception.id == oldest_id)
ls_exception_next_state = IQ_DISCARD;
else
ls_exception_next_state = IQ_DRAIN;
end
next_state = state;
case (state)
RST_STATE : next_state = PRE_CLEAR_STATE;
PRE_CLEAR_STATE : next_state = CLEAR_STATE;
CLEAR_STATE : if (clear_shift_count[CLEAR_DEPTH-1]) next_state = IDLE_STATE;
IDLE_STATE : if (load_store_issue) next_state = LS_EXCEPTION_POSSIBLE;
TLB_CLEAR_STATE : if (tlb_clear_shift_count[TLB_CLEAR_DEPTH-1]) next_state = IDLE_STATE;
LS_EXCEPTION_POSSIBLE : next_state = ls_exception_next_state;
IQ_DRAIN : if (ls_exception.id == oldest_id) next_state = IQ_DISCARD;
IQ_DISCARD : if (instruction_queue_empty) next_state = IDLE_STATE;
default : next_state = RST_STATE;
endcase
end
//CLEAR state shift reg
@ -259,12 +243,14 @@ module gc_unit(
end
////////////////////////////////////////////////////
//CSR registers
assign csr_inputs.rs1 = fn3[2] ? {27'b0, rs1_addr} : gc_inputs.rs1;
assign csr_inputs.csr_addr = gc_inputs.instruction[31:20];
assign csr_inputs.csr_op = fn3[1:0];
assign csr_inputs.rs1_is_zero = (rs1_addr == 0);
assign csr_inputs.rd_is_zero = gc_inputs.rd_is_zero;
//Exception handling
logic ls_exception_first_cycle;
logic ls_exception_second_cycle;
assign ls_exception_first_cycle = ls_exception_valid && (state == LS_EXCEPTION_POSSIBLE);
always_ff @ (posedge clk) begin
ls_exception_second_cycle <= ls_exception_first_cycle;
end
always_comb begin
case (current_privilege)
@ -275,34 +261,63 @@ module gc_unit(
endcase
end
csr_regs csr_registers (.*, .new_request(gc_inputs.is_csr & gc_ex.new_request));
assign gc_exception.code =
ls_exception_second_cycle ? ls_exception.code :
gc_inputs.is_ecall ? ecall_code : BREAK;
assign gc_exception.pc = ls_exception_second_cycle ? ls_exception.pc : gc_inputs.pc;
assign gc_exception.tval = ls_exception_second_cycle ? ls_exception.tval : '0;
assign gc_exception.valid = gc_inputs.is_ecall | gc_inputs.is_ebreak | ls_exception_second_cycle;
always_ff @ (posedge clk) begin
second_cycle_flush <= gc_flush_required;
gc_fetch_pc_override <= gc_flush_required | second_cycle_flush | ls_exception_first_cycle;
gc_fetch_pc <=
gc_inputs.is_i_fence ? gc_inputs.pc + 4 :
gc_inputs.is_ret ? csr_mepc :
trap_pc;
end
////////////////////////////////////////////////////
//CSR registers
assign csr_inputs.rs1 = fn3[2] ? {27'b0, rs1_addr} : gc_inputs.rs1;
assign csr_inputs.csr_addr = gc_inputs.instruction[31:20];
assign csr_inputs.csr_op = fn3[1:0];
assign csr_inputs.rs1_is_zero = (rs1_addr == 0);
assign csr_inputs.rd_is_zero = gc_inputs.rd_is_zero;
csr_regs csr_registers (.*, .new_request(is_csr), .commit(csr_ready_to_complete_r));
////////////////////////////////////////////////////
//Decode / Write-back Handshaking
always_ff @(posedge clk) begin
if (rst)
processing <= 0;
else if (gc_ex.new_request_dec)
processing <= 1;
else if ((state == IDLE_STATE) && instruction_queue_empty)
processing <= 0;
end
//gc_issue_hold prevents further instructions from being issued until processing returns to zero
logic csr_ready_to_complete;
logic csr_ready_to_complete_r;
//CSR reads are passed through the Load-Store unit
//A CSR write is only committed once it is the oldest instruction in the pipeline
//while processing a csr operation, gc_issue_hold prevents further instructions from being issued
assign gc_ex.ready = 1;
//Write_back
always_ff @(posedge clk) begin
id <= gc_ex.instruction_id_one_hot;
gc_wb.done_next_cycle <= id & {MAX_INFLIGHT_COUNT{(gc_ex.new_request & gc_inputs.is_csr)}};
if (rst)
processing_csr <= 0;
else if (csr_ready_to_complete)
processing_csr <= 0;
else if (is_csr)
processing_csr <= 1;
end
assign csr_ready_to_complete = (is_csr | processing_csr) && (oldest_id == csr_id);
always_ff @(posedge clk) begin
if (gc_ex.new_request) begin
gc_wb.rd <= selected_csr;
csr_ready_to_complete_r <= csr_ready_to_complete;
csr_id_done <= id & {MAX_INFLIGHT_COUNT{csr_ready_to_complete}};
if (gc_ex.new_request_dec) begin
id <= gc_ex.instruction_id_one_hot;
csr_id <= gc_ex.instruction_id;
end
end
assign csr_done = csr_ready_to_complete_r;
assign csr_rd = wb_csr;
////////////////////////////////////////////////////
//Assertions

View file

@ -46,6 +46,11 @@ module load_store_unit (
local_memory_interface.master data_bram,
input logic[31:0] csr_rd,
input instruction_id_one_hot_t csr_id_done,
input instruction_id_t csr_id,
input logic csr_done,
output logic store_committed,
output instruction_id_t store_id,
@ -328,8 +333,8 @@ module load_store_unit (
////////////////////////////////////////////////////
//Output bank
always_ff @ (posedge clk) begin
if (load_complete)
rd_bank[stage2_attr.instruction_id] <= final_load_data;
if (load_complete | csr_done)
rd_bank[csr_done ? csr_id : stage2_attr.instruction_id] <= csr_done ? csr_rd : final_load_data;
end
always_ff @ (posedge clk) begin
@ -340,11 +345,13 @@ module load_store_unit (
assign ls_wb.rd = rd_bank[ls_wb.writeback_instruction_id];
logic exception_complete;
logic ls_done;
always_ff @ (posedge clk) begin
exception_complete <= (input_fifo.valid & ls_exception_valid & stage1.load);
end
assign ls_done = load_complete | exception_complete;
assign ls_wb.done_next_cycle = stage2_attr.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{(load_complete | exception_complete)}};
assign ls_wb.done_next_cycle = csr_id_done | (stage2_attr.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{ls_done}});
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////

View file

@ -113,6 +113,11 @@ module taiga (
logic store_committed;
instruction_id_t store_id;
logic[31:0] csr_rd;
instruction_id_t csr_id;
instruction_id_one_hot_t csr_id_done;
logic csr_done;
//Branch Unit and Fetch Unit
logic branch_taken;
logic [31:0] pc_offset;
@ -189,7 +194,7 @@ module taiga (
assign dtlb.physical_address = dtlb.virtual_address;
end
endgenerate
gc_unit gc_unit_block (.*, .gc_wb(unit_wb[GC_UNIT_WB_ID]));
gc_unit gc_unit_block (.*);
generate if (USE_MUL)
mul_unit mul_unit_block (.*, .mul_wb(unit_wb[MUL_UNIT_WB_ID]));

View file

@ -184,17 +184,17 @@ package taiga_config;
////////////////////////////////////////////////////
//Write-Back Unit IDs
parameter NUM_WB_UNITS = 3 + USE_MUL + USE_DIV;
parameter NUM_WB_UNITS = 2 + USE_MUL + USE_DIV;
parameter WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
parameter NUM_UNITS = NUM_WB_UNITS + 1;
parameter NUM_UNITS = NUM_WB_UNITS + 2;
parameter ALU_UNIT_WB_ID = 0;
parameter GC_UNIT_WB_ID = 1;
parameter LS_UNIT_WB_ID = 2;
parameter LS_UNIT_WB_ID = 1;
parameter DIV_UNIT_WB_ID = LS_UNIT_WB_ID + USE_DIV;
parameter MUL_UNIT_WB_ID = DIV_UNIT_WB_ID + USE_MUL;
//Non-writeback units
parameter BRANCH_UNIT_ID = MUL_UNIT_WB_ID + 1;
parameter GC_UNIT_ID = BRANCH_UNIT_ID + 1;
////////////////////////////////////////////////////