Loading files
// Copyright 2019- RSD contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
//
// Complex Integer Execution stage
//
// 乗算/SIMD 命令の演算を行う
// COMPLEX_EXEC_STAGE_DEPTH 段にパイプライン化されている
//
`include "BasicMacros.sv"
import BasicTypes::*;
import OpFormatTypes::*;
import ActiveListIndexTypes::*;
module MulDivUnit(MulDivUnitIF.MulDivUnit port, RecoveryManagerIF.MulDivUnit recovery);
for (genvar i = 0; i < MULDIV_ISSUE_WIDTH; i++) begin : BlockMulUnit
// MultiplierUnit
PipelinedMultiplierUnit #(
.BIT_WIDTH(DATA_WIDTH),
.PIPELINE_DEPTH(MULDIV_STAGE_DEPTH)
) mulUnit (
.clk(port.clk),
.stall(port.stall),
.fuOpA_In(port.dataInA[i]),
.fuOpB_In(port.dataInB[i]),
.getUpper(port.mulGetUpper[i]),
.mulCode(port.mulCode[i]),
.dataOut(port.mulDataOut[i])
);
end
//
// DividerUnit
//
typedef enum logic[1:0]
{
DIVIDER_PHASE_FREE = 0, // Divider is free
DIVIDER_PHASE_RESERVED = 1, // Divider is not processing but reserved
DIVIDER_PHASE_PROCESSING = 2, // In processing
DIVIDER_PHASE_WAITING = 3 // Wait for issuing div from the replay queue
} DividerPhase;
DividerPhase regPhase [MULDIV_ISSUE_WIDTH];
DividerPhase nextPhase [MULDIV_ISSUE_WIDTH];
logic finished[MULDIV_ISSUE_WIDTH];
logic flush[MULDIV_ISSUE_WIDTH];
logic rst_divider[MULDIV_ISSUE_WIDTH];
ActiveListIndexPath regActiveListPtr[MULDIV_ISSUE_WIDTH];
ActiveListIndexPath nextActiveListPtr[MULDIV_ISSUE_WIDTH];
for (genvar i = 0; i < MULDIV_ISSUE_WIDTH; i++) begin : BlockDivUnit
DividerUnit divUnit(
.clk(port.clk),
.rst(rst_divider[i]),
.req(port.divReq[i]),
.fuOpA_In(port.dataInA[i]),
.fuOpB_In(port.dataInB[i]),
.divCode(port.divCode[i]),
.finished(finished[i]),
.dataOut(port.divDataOut[i])
);
end
always_ff @(posedge port.clk) begin
if (port.rst) begin
for (int i = 0; i < MULDIV_ISSUE_WIDTH; i++) begin
regPhase[i] <= DIVIDER_PHASE_FREE;
regActiveListPtr[i] <= 0;
end
end
else begin
regPhase <= nextPhase;
regActiveListPtr <= nextActiveListPtr;
end
end
always_comb begin
nextPhase = regPhase;
nextActiveListPtr = regActiveListPtr;
for (int i = 0; i < MULDIV_ISSUE_WIDTH; i++) begin
case (regPhase[i])
default: begin
nextPhase[i] = DIVIDER_PHASE_FREE;
end
DIVIDER_PHASE_FREE: begin
// Reserve divider and do not issue any div after that.
if (port.divAcquire[i]) begin
nextPhase[i] = DIVIDER_PHASE_RESERVED;
nextActiveListPtr[i] = port.acquireActiveListPtr[i];
end
end
DIVIDER_PHASE_RESERVED: begin
// Request to the divider
// NOT make a request when below situation
// 1) When any operands of inst. are invalid
// 2) When the divider is waiting for the instruction
// to receive the result of the divider
if (port.divReq[i]) begin
// Receive the request of div,
// so move to processing phase
nextPhase[i] = DIVIDER_PHASE_PROCESSING;
end
end
DIVIDER_PHASE_PROCESSING: begin
// Div operation has finished, so we can get result from divider
if (finished[i]) begin
nextPhase[i] = DIVIDER_PHASE_WAITING;
end
end
DIVIDER_PHASE_WAITING: begin
if (port.divRelease[i]) begin
// Divが除算器から結果を取得できたので,
// IQからのdivの発行を許可する
nextPhase[i] = DIVIDER_PHASE_FREE;
end
end
endcase // regPhase[i]
// Cancel divider allocation on pipeline flush
flush[i] = SelectiveFlushDetector(
recovery.toRecoveryPhase,
recovery.flushRangeHeadPtr,
recovery.flushRangeTailPtr,
recovery.flushAllInsns,
regActiveListPtr[i]
);
// 除算器に要求をしたdivがフラッシュされたので,除算器を解放する
if (flush[i]) begin
nextPhase[i] = DIVIDER_PHASE_FREE;
end
rst_divider[i] = port.rst | flush[i];
// 現状 acquire が issue ステージからくるので,次のサイクルの状態でフリーか
// どうかを判定する必要がある
port.divFree[i] = nextPhase[i] == DIVIDER_PHASE_FREE ? TRUE : FALSE;
port.divFinished[i] = regPhase[i] == DIVIDER_PHASE_WAITING ? TRUE : FALSE;
port.divBusy[i] = regPhase[i] == DIVIDER_PHASE_PROCESSING ? TRUE : FALSE;
port.divReserved[i] = regPhase[i] == DIVIDER_PHASE_RESERVED ? TRUE : FALSE;
end // for (int i = 0; i < MULDIV_ISSUE_WIDTH; i++) begin
end // always_comb begin
endmodule
6d2e42836This file is pinned to the selected release. Download the original to open it in your design tool.