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 DmaRequestCore #6

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/DmaController.bsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import PcieTypes::*;
import DmaTypes::*;

interface DmaController#(numeric type dataWidth);

interface FifoIn#(DataStream) dataC2HPipeIn;
interface FifoIn#(DmaRequestFrame) reqC2HPipeIn;
interface FifoIn#(DmaRequestFrame) reqH2CPipeIn;
interface FifoOut#(DataStream) dataH2CPipeOut;

interface FifoIn#(DmaCsrFrame) csrC2HPipeIn;
interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host
interface FifoOut#(DmaCsrFrame) csrH2CPipeOut;

interface RawPcieRequester pcieRequester;
interface RawPcieCompleter pcieCompleter;
interface RawPcieConfiguration pcieConfig;

endinterface

module mkDmaController#() (DmaController ifc);


endmodule
121 changes: 121 additions & 0 deletions src/DmaRequestCore.bsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import FIFOF::*;
import GetPut :: *;

import SemiFifo::*;
import PcieTypes::*;
import DmaTypes::*;


typedef 4096 BUS_BOUNDARY;
typedef TAdd#(1, TLog#(BUS_BOUNDARY)) BUS_BOUNDARY_WIDTH;

typedef Bit#(BUS_BOUNDARY_WIDTH) PcieTlpMaxMaxPayloadSize;
typedef Bit#(TLog#(BUS_BOUNDARY_WIDTH)) PcieTlpSizeWidth;

typedef 128 DEFAULT_TLP_SIZE;
typedef TAdd#(1, TLog#(DEFAULT_TLP_SIZE)) DEFAULT_TLP_SIZE_WIDTH;

typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH;
typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting;

typedef struct {
DmaRequestFrame dmaRequest;
DmaMemAddr firstChunkLen;
} ChunkRequestFrame deriving(Bits, Eq);

interface ChunkCompute;
interface FifoIn#(DmaRequestFrame) dmaRequestFifoIn;
interface FifoOut#(DmaRequestFrame) chunkRequestFifoOut;
interface Put#(PcieTlpSizeSetting) setTlpMaxSize;
endinterface

module mkChunkComputer (TRXDirection direction, ChunkCompute ifc);

FIFOF#(DmaRequestFrame) inputFifo <- mkFIFOF;
FIFOF#(DmaRequestFrame) outputFifo <- mkFIFOF;
FIFOF#(ChunkRequestFrame) splitFifo <- mkFIFOF;

Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0);
Reg#(DmaMemAddr) totalLenRemainReg <- mkReg(0);
Reg#(Bool) isSplittingReg <- mkReg(False);

Reg#(DmaMemAddr) tlpMaxSize <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE)));
Reg#(PcieTlpSizeWidth) tlpMaxSizeWidth <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH)));

function Bool hasBoundary(DmaRequestFrame request);
let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH);
let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH);
return (highIdx > lowIdx);
endfunction

function DmaMemAddr getOffset(DmaRequestFrame request);
// MPS - startAddr % MPS, MPS means MRRS when the module is set to RX mode
DmaMemAddr remainderOfMps = zeroExtend(PcieTlpMaxMaxPayloadSize'(request.startAddr[tlpMaxSizeWidth-1:0]));
DmaMemAddr offsetOfMps = tlpMaxSize - remainderOfMps;
return offsetOfMps;
endfunction

rule getfirstChunkLen;
let request = inputFifo.first;
inputFifo.deq;
let offset = getOffset(request);
let firstLen = (request.length > tlpMaxSize) ? tlpMaxSize : request.length;
splitFifo.enq(ChunkRequestFrame {
dmaRequest: request,
firstChunkLen: hasBoundary(request) ? offset : firstLen
});
endrule

rule execChunkSplit;
let splitRequest = splitFifo.first;
if (isSplittingReg) begin // !isFirst
if (totalLenRemainReg <= tlpMaxSize) begin
isSplittingReg <= False;
outputFifo.enq(DmaRequestFrame {
startAddr: newChunkPtrReg,
length: totalLenRemainReg
});
splitFifo.deq;
totalLenRemainReg <= 0;
end
else begin
isSplittingReg <= True;
outputFifo.enq(DmaRequestFrame {
startAddr: newChunkPtrReg,
length: tlpMaxSize
});
newChunkPtrReg <= newChunkPtrReg + tlpMaxSize;
totalLenRemainReg <= totalLenRemainReg - tlpMaxSize;
end
end
else begin // isFirst
let remainderLength = splitRequest.dmaRequest.length - splitRequest.firstChunkLen;
Bool isSplittingNextCycle = (remainderLength > 0);
isSplittingReg <= isSplittingNextCycle;
outputFifo.enq(DmaRequestFrame {
startAddr: splitRequest.dmaRequest.startAddr,
length: splitRequest.firstChunkLen
});
if (!isSplittingNextCycle) begin
splitFifo.deq;
end
newChunkPtrReg <= splitRequest.dmaRequest.startAddr + splitRequest.firstChunkLen;
totalLenRemainReg <= remainderLength;
end
endrule

interface dmaRequestFifoIn = convertFifoToFifoIn(inputFifo);
interface chunkRequestFifoOut = convertFifoToFifoOut(outputFifo);

interface Put setTlpMaxSize;
method Action put (PcieTlpSizeSetting tlpSizeSetting);
let setting = tlpSizeSetting;
setting[valueOf(PCIE_TLP_SIZE_SETTING_WIDTH)-1] = (direction == DMA_TX) ? 0 : setting[valueOf(PCIE_TLP_SIZE_SETTING_WIDTH)-1];
DmaMemAddr defaultTlpMaxSize = fromInteger(valueOf(DEFAULT_TLP_SIZE));
tlpMaxSize <= DmaMemAddr'(defaultTlpMaxSize << setting);
PcieTlpSizeWidth defaultTlpMaxSizeWidth = fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH));
tlpMaxSizeWidth <= PcieTlpSizeWidth'(defaultTlpMaxSizeWidth + zeroExtend(setting));
endmethod
endinterface

endmodule
93 changes: 93 additions & 0 deletions test/TestDmaCore.bsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import GetPut::*;
import Randomizable::*;

import SemiFifo::*;
import PrimUtils::*;
import DmaTypes::*;
import DmaRequestCore::*;

typedef 100000 CHUNK_PER_EPOCH_TEST_NUM;
typedef 64'hFFFFFFFFFFFFFFFF MAX_ADDRESS;
typedef 16'hFFFF MAX_TEST_LENGTH;
typedef 2'b00 DEFAULT_TLP_SIZE_SETTING;
typedef 4 CHUNK_TX_TEST_SETTING_NUM;
typedef 6 CHUNK_RX_TEST_SETTING_NUM;

(* doc = "testcase" *)
module mkChunkComputerTb(Empty);

ChunkCompute dut <- mkChunkComputer(DMA_TX);

Reg#(Bool) isInitReg <- mkReg(False);
Reg#(UInt#(32)) testCntReg <- mkReg(0);
Reg#(UInt#(32)) epochCntReg <- mkReg(0);

Reg#(DmaMemAddr) lenRemainReg <- mkReg(0);

Randomize#(DmaMemAddr) startAddrRandomVal <- mkConstrainedRandomizer(0, fromInteger(valueOf(MAX_ADDRESS)-1));
Randomize#(DmaMemAddr) lengthRandomVal <- mkConstrainedRandomizer(1, fromInteger(valueOf(MAX_TEST_LENGTH)));

function Bool hasBoundary(DmaRequestFrame request);
let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH);
let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH);
return (highIdx > lowIdx);
endfunction

rule testInit if (!isInitReg);
startAddrRandomVal.cntrl.init;
lengthRandomVal.cntrl.init;
isInitReg <= True;
dut.setTlpMaxSize.put(fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING)));
$display("INFO: Start Test of mkChunkComputerTb");
$display("INFO: Set Max Payload Size to ", valueOf(DEFAULT_TLP_SIZE));
endrule

rule testInput if (isInitReg && lenRemainReg == 0);
DmaMemAddr testAddr <- startAddrRandomVal.next;
DmaMemAddr testLength <- lengthRandomVal.next;
let testEnd = testAddr + testLength - 1;
if (testEnd > testAddr && testEnd <= fromInteger(valueOf(MAX_ADDRESS))) begin
let request = DmaRequestFrame{
startAddr: testAddr,
length: testLength
};
lenRemainReg <= testLength;
dut.dmaRequestFifoIn.enq(request);
// $display("INFO: input ", fshow(request));
end
else begin
lenRemainReg <= 0;
end
endrule

rule testOutput if (isInitReg && lenRemainReg > 0);
let newRequest = dut.chunkRequestFifoOut.first;
dut.chunkRequestFifoOut.deq;
immAssert(
!hasBoundary(newRequest),
"has boundary assert @ mkChunkComputerTb",
fshow(newRequest)
);
let newRemain = lenRemainReg - newRequest.length;
lenRemainReg <= newRemain;
if (newRemain == 0) begin
if (epochCntReg < fromInteger(valueOf(CHUNK_PER_EPOCH_TEST_NUM)-1)) begin
epochCntReg <= epochCntReg + 1;
end
else begin
epochCntReg <= 0;
testCntReg <= testCntReg + 1;
if (testCntReg == fromInteger(valueOf(CHUNK_TX_TEST_SETTING_NUM)-1)) begin
$display("INFO: ChunkComputer Test End.");
$finish();
end
else begin
PcieTlpSizeSetting newSetting = fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING)) + truncate(pack(testCntReg)) + 1;
dut.setTlpMaxSize.put(newSetting);
$display("INFO: Set Max Payload Size to ", pack(fromInteger(valueOf(DEFAULT_TLP_SIZE)) << newSetting));
end
end
end
endrule

endmodule