merge change into files

This commit is contained in:
twk119 2022-10-10 14:28:31 +02:00
parent 8aa3edd4d2
commit fce1b702bd
4 changed files with 93 additions and 1098 deletions

View File

@ -82,217 +82,15 @@ void retrans_pointer_table( stream<pointerReq>& pointerReqFifo,
}
}
}
else if (pt_wait)
else if (pt_wait && !pt_isLocked)
{
if (!pt_isLocked)
{
pointerRspFifo.write(ptr_table[pt_req.qpn]);
pt_isLocked = true;
pt_lockedQP = pt_req.qpn;
pt_wait = false;
}
pointerRspFifo.write(ptr_table[pt_req.qpn]);
pt_isLocked = true;
pt_lockedQP = pt_req.qpn;
pt_wait = false;
}
}
/*void pointer_table( stream<retransRelease>& rx2retrans_release_upd,
stream<retransmission>& rx2retrans_req,
stream<retransmission>& timer2retrans_req, //TODO this requires psn??
stream<retransEntry>& tx2retrans_insertRequest,
stream<pointerMeta>& ptrMetaFifo)
//stream<event>& retrans2event)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
static retransPointerEntry ptr_table[MAX_QPS];
#pragma HLS RESOURCE variable=ptr_table core=RAM_T2P_BRAM
#pragma HLS DEPENDENCE variable=ptr_table inter false
retransRelease release;
//static ap_uint<16> curr;
//static ap_uint<16> newPtr;
retransEntry insert;
retransmission retrans;
retransPointerEntry ptrs;
//static retransMetaEntry meta;
if (!rx2retrans_release_upd.empty())
{
//TODO lock qpn
rx2retrans_release_upd.read(release);
ptrs = ptr_table[release.qpn];
//curr = ptrs.head;
if (ptrs.valid)
{
ptrMetaFifo.write(pointerMeta(RELEASE, ptrs));
}
}
else if (!tx2retrans_insertRequest.empty())// && !freeListFifo.empty())
{
//TODO lock qpn
newPtr = freeListFifo.read();
tx2retrans_insertRequest.read(insert);
ptrs = ptr_table[insert.qpn];
ptrMetaFifo.write(pointerMeta(INSERT, insert.qpn, ptrs));
}
else if (!rx2retrans_req.empty())
{
rx2retrans_req.read(retrans);
ptrs = ptr_table[retrans.qpn];
//curr = ptrs.head;
if (ptrs.valid)
{
ptrMetaFifo.write(pointerMeta(RX_RETRANS, retrans.psn, ptrs));
}
}
else if (!timer2retrans_req.empty())
{
timer2retrans_req.read(retrans);
//Uses always head psn
ptrs = ptr_table[retrans.qpn];
if (ptrs.valid)
{
ptrMetaFifo.write(pointerMeta(TIMER_RETRANS, ptrs));
}
}
}*/
/*void retrans_meta_table(stream<pointerMeta>& ptrMetaFifo,
stream<pointerUpdate>& pointerUpdateFifo,
stream<event>& retrans2event)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
static retransMetaEntry meta_table[META_TABLE_SIZE];
#pragma HLS RESOURCE variable=meta_table core=RAM_T2P_BRAM
#pragma HLS DEPENDENCE variable=meta_table inter false
static stream<ap_uint<16> > freeListFifo("freeListFifo");
#pragma HLS STREAM depth=META_TABLE_SIZE variable=freeListFifo
enum retransStateType {INIT, GET_META, PROCESS};
static retransStateType rt_state = INIT;
static ap_uint<16> freeListCounter = 0;
static pointerMeta ptrMeta;
static ap_uint<16> curr;
ap_uint<16> newPtr;
retransMetaEntry meta;
switch (rt_state)
{
case INIT:
freeListFifo.write(freeListCounter);
if (freeListCounter == META_TABLE_SIZE-1)
{
rt_state = GET_META;
}
freeListCounter++;
break;
case GET_META:
if (!ptrMetaFifo.empty())
{
ptrMetaFifo.read(ptrMeta);
curr = ptrMeta.entry.head;
rt_state = PROCESS;
}
break;
case PROCESS:
switch(ptrMeta.entry)
{
case INSERT:
if (!freeListFifo.empty())
{
newPtr = freeListFifo.read();
if (!ptrMeta.entry.valid)
{
//init entry
ptrMeta.entry.valid = true;
ptrMeta.entry.head = newPtr;
ptrMeta.entry.tail = newPtr;
}
else
{
meta_table[ptrMeta.entry.tail].next = newPtr;
meta_table[ptrMeta.entry.tail].isTail = false;
meta_table[newPtr] = insert;
ptrMeta.entry.tail = newPtr;
}
//Write back
pointerUpdateFifo.write(pointerUpdate(qpn, ptrMeta.entry));
//ptr_table[insert.qpn] = ptrs;
rt_state = GET_META;
}
break;
/*case RELEASE:
rt_state = MAIN;
if (ptrs.valid)
{
meta = meta_table[curr];
rt_state = RELEASE_1;
}
break;*/
/*case RELEASE:
meta = meta_table[curr];
if (!meta.valid || (meta.psn == release.latest_acked_req))
{
ptrMeta.entry.head = curr;
pointerUpdateFifo.write(qpn, ptrMeta.entry);
//ptr_table[release.qpn] = ptrs;
rt_state = GET_META;
}
else
{
if (meta.isTail)
{
ptrMeta.entry.valid = false;
ptrMeta.entry.head = curr;
pointerUpdateFifo.write(qpn, ptrMeta.entry);
//ptr_table[release.qpn] = ptrs;
rt_state = GET_META;
}
curr = meta.next;
//meta = meta_table[curr];
}
break;
/*case RETRANS_0:
rt_state = MAIN;
if (ptrs.valid)
{
meta = meta_table[curr];
rt_state = RETRANS_1;
}
break;*/
/*case RX_RETRANS:
meta = meta_table[curr];
if (!meta.valid || meta.isTail)
{
rt_state = GET_META;
}
else
{
if (meta.psn == ptrMeta.psn)
{
//Generate even
retrans2event.write(event(meta.opCode, ptrMeta.qpn, meta.vaddr, meta.length, meta.psn));
rt_state = GET_META;
}
curr = meta.next;
meta = meta_table[curr];
}
break;
case TIMER_RETRANS:
meta = meta_table[curr];
retrans2event.write(event(meta.opCode, ptrMeta.qpn, meta.vaddr, meta.length, meta.psn));
break;
}//switch entry
break;
}//switch state
}*/
void retrans_meta_table(stream<retransMetaReq>& meta_upd_req,
stream<retransMetaEntry>& meta_rsp)
//stream<bool>& stopFifo)
@ -307,157 +105,26 @@ void retrans_meta_table(stream<retransMetaReq>& meta_upd_req,
#pragma HLS RESOURCE variable=meta_table core=RAM_T2P_BRAM
#endif
#pragma HLS DEPENDENCE variable=meta_table inter false
//enum rmtFsmStateType {READ, CONTINOUS};// CONTINOUS_2, IMD};
//static rmtFsmStateType rmt_state = READ;
//static ap_uint<24> checkPsn;
//static bool prevTrigger = false;
retransMetaReq req;
//static ap_uint<16> curr_idx;
//static ap_uint<16> next_idx;
//retransMetaEntry entry;
//static bool continuousMode = false;
//static ap_uint<1> alternater = 0;
/*switch (alternater)
{
case 0:
if (continuousMode)
{
std::cout << "next_idx: " << next_idx << std::endl;
entry = meta_table[curr_idx];
bool last = false;
next_idx = entry.next;
//rmt_state = IMD; //TODO stay
if (!stopFifo.empty())
{
stopFifo.read();
last = true;
//rmt_state = READ;
continuousMode = false;
}
meta_rsp.write(retransMetaRsp(entry, last));
}
else*/ if (!meta_upd_req.empty())
{
meta_upd_req.read(req);
if (req.write)
{
meta_table[req.idx] = req.entry;
}
else if (req.append)
{
meta_table[req.idx].next = req.entry.next;
meta_table[req.idx].isTail = false;
}
else
{
//entry = meta_table[req.idx];
meta_rsp.write(meta_table[req.idx]);
//next_idx = entry.next;
/*if (req.continous)
{
continuousMode = true;
//not sure this is necessary
/*if (!entry.valid || entry.isTail)
{
next_idx = 0;
}*/
//rmt_state = CONTINOUS;
//}
}
}
/*alternater = 1;
break;
case 1:
curr_idx = entry.next;
alternater = 0;
break;
} //switch
/*switch (rmt_state)
{
case READ:
if (!meta_upd_req.empty())
{
meta_upd_req.read(req);
if (req.write)
{
meta_table[req.idx] = req.entry;
}
else if (req.append)
{
meta_table[req.idx].next = req.entry.next;
meta_table[req.idx].isTail = false;
}
else
{
entry = meta_table[req.idx];
meta_rsp.write(retransMetaRsp(entry));
next_idx = entry.next;
if (req.continous)
{
//not sure this is necessary
/*if (!entry.valid || entry.isTail)
{
next_idx = 0;
}*/
/*rmt_state = CONTINOUS;
}
}
}
break;
case CONTINOUS:
{
std::cout << "next_idx: " << next_idx << std::endl;
entry = meta_table[next_idx];
bool last = false;
next_idx = entry.next;
//rmt_state = IMD; //TODO stay
if (!stopFifo.empty())
{
stopFifo.read();
last = true;
rmt_state = READ;
}
meta_rsp.write(retransMetaRsp(entry, last));
/*isEnd = (!entry.valid || entry.psn == checkPsn || entry.isTail);
if (!entry.valid || entry.psn == checkPsn || entry.isTail)
{
//prevTrigger = true;
//rmt_state = READ;
}*/
/*}
break;
/*case IMD:
/*if (isEnd)
{
rmt_state = READ;
}
else
{
rmt_state = CONTINOUS;
}*/
/*rmt_state = CONTINOUS_2;
break;
/*case CONTINOUS_2:
if (isEnd)
{
//prevTrigger = true;
rmt_state = READ;
}
else
{
rmt_state = CONTINOUS;
}
break;*/
//}//switch
if (!meta_upd_req.empty())
{
meta_upd_req.read(req);
if (req.write)
{
meta_table[req.idx] = req.entry;
}
else if (req.append)
{
meta_table[req.idx].next = req.entry.next;
meta_table[req.idx].isTail = false;
}
else
{
meta_rsp.write(meta_table[req.idx]);
}
}
}
//TODO HLS is failing so bad with II, such that this module has a ton of states
@ -478,38 +145,18 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
/*static retransPointerEntry ptr_table[MAX_QPS];
#pragma HLS RESOURCE variable=ptr_table core=RAM_T2P_BRAM
#pragma HLS DEPENDENCE variable=ptr_table inter false*/
/*static retransMetaEntry meta_table[META_TABLE_SIZE];
#pragma HLS RESOURCE variable=meta_table core=RAM_T2P_BRAM
#pragma HLS DEPENDENCE variable=meta_table inter false*/
enum retransStateType {MAIN, INSERT, INSERT_2, RELEASE_0, RELEASE_1, RETRANS_0, RETRANS_1, RETRANS_2, TIMER_RETRANS, TIMER_RETRANS_2}; //FLUSH_META_PIPE};
enum retransStateType {MAIN, INSERT_0, INSERT_1, RELEASE_0, RELEASE_1, RETRANS_0, RETRANS_1, RETRANS_2, TIMER_RETRANS_0, TIMER_RETRANS_1}; //FLUSH_META_PIPE};
static retransStateType rt_state = MAIN;
//static ap_uint<16> freeListCounter = 0;
static retransRelease release;
static ap_uint<16> curr;
//static ap_uint<16> relCurr;
static ap_uint<16> newMetaIdx;
static retransEntry insert;
static retransmission retrans;
static retransMetaEntry meta; //TODO register needed??
static retransPointerEntry ptrMeta;
//static ap_uint<16> prevIdx;
switch (rt_state)
{
/*case INIT:
//TODO move to free handler
releaseFifo.write(freeListCounter); //TODO
if (freeListCounter == META_TABLE_SIZE-1)
{
rt_state = MAIN;
}
freeListCounter++;
break;*/
case MAIN:
if (!rx2retrans_release_upd.empty())
{
@ -522,13 +169,13 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
newMetaIdx = freeListFifo.read();
tx2retrans_insertRequest.read(insert);
pointerReqFifo.write(pointerReq(insert.qpn, true));
rt_state = INSERT;
rt_state = INSERT_0;
}
else if (!rx2retrans_req.empty())
{
rx2retrans_req.read(retrans);
std::cout << "RX Retransmit triggered!! , psn: " << std::hex << retrans.psn << std::endl;
pointerReqFifo.write(pointerReq(release.qpn));
pointerReqFifo.write(pointerReq(retrans.qpn));
rt_state = RETRANS_0;
}
else if (!timer2retrans_req.empty())
@ -537,10 +184,10 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
timer2retrans_req.read(retrans);
//Uses always head psn
pointerReqFifo.write(pointerReq(retrans.qpn));
rt_state = TIMER_RETRANS;
rt_state = TIMER_RETRANS_0;
}
break;
case INSERT:
case INSERT_0:
if (!pointerRspFifo.empty())
{
pointerRspFifo.read(ptrMeta);
@ -556,21 +203,16 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
}
else
{
//meta_table[ptrMeta.tail].next = newPtr;
//meta_table[ptrMeta.tail].isTail = false;
//Append new pointer to tail
metaReqFifo.write(retransMetaReq(ptrMeta.tail, newMetaIdx));
ptrMeta.tail = newMetaIdx;
rt_state = INSERT_2;
rt_state = INSERT_1;
}
//Write back, TODO move to insert2??
//pointerUpdFifo.write(pointerUpdate(insert.qpn, ptrMeta));
}
break;
case INSERT_2:
case INSERT_1:
metaReqFifo.write(retransMetaReq(newMetaIdx, retransMetaEntry(insert)));
pointerUpdFifo.write(pointerUpdate(insert.qpn, ptrMeta));
//meta_table[newPtr] = insert;
rt_state = MAIN;
break;
case RELEASE_0:
@ -583,7 +225,6 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
//Get continuous stream of meta entries
metaReqFifo.write(retransMetaReq(ptrMeta.head));
curr = ptrMeta.head;
//meta = meta_table[curr];
rt_state = RELEASE_1;
}
else
@ -612,8 +253,6 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
ptrMeta.head = meta.next;
ptrMeta.valid = !meta.isTail;
pointerUpdFifo.write(pointerUpdate(release.qpn, ptrMeta));
//ptr_table[release.qpn] = ptrs;
//stopFifo.write(true);
rt_state = MAIN;
}
else
@ -623,15 +262,11 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
ptrMeta.valid = false;
ptrMeta.head = curr;
pointerUpdFifo.write(pointerUpdate(release.qpn, ptrMeta));
//ptr_table[release.qpn] = ptrs;
//stopFifo.write(true);
rt_state = MAIN;
}
else
{
metaReqFifo.write(retransMetaReq(meta.next));
//rt_freeListFifo.write(curr); //TODO check correctness
//rt_state = RELEASE_2;
metaReqFifo.write(retransMetaReq(meta.next));
}
curr = meta.next;
}
@ -641,11 +276,6 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
}
}
break;
/*case RELEASE_2:
//relCurr = relMeta.next;
relMeta2 = meta_table[relCurr];
rt_state = RELEASE_1;
break;*/
case RETRANS_0:
if (!pointerRspFifo.empty())
{
@ -657,7 +287,6 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
//Get continuous stream of meta entries
metaReqFifo.write(retransMetaReq(ptrMeta.head));
curr = ptrMeta.head;
//meta = meta_table[curr];
rt_state = RETRANS_1;
}
}
@ -695,12 +324,13 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
}
}
break;
// TODO: can we simplify this state?
case RETRANS_2:
//Retransmit everything until we reach tail
if (!metaRspFifo.empty())
{
metaRspFifo.read(meta);
if (meta.valid) // && meta.psn == retrans.psn)
if (meta.valid)
{
if (!meta.isTail)
{
@ -720,16 +350,14 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
}
}
break;
case TIMER_RETRANS:
case TIMER_RETRANS_0:
if (!pointerRspFifo.empty())
{
pointerRspFifo.read(ptrMeta);
if (ptrMeta.valid)
{
metaReqFifo.write(retransMetaReq(ptrMeta.head));
rt_state = TIMER_RETRANS_2;
//meta = meta_table[ptrMeta.head];
//retrans2event.write(event(meta.opCode, retrans.qpn, meta.vaddr, meta.length, meta.psn));
rt_state = TIMER_RETRANS_1;
}
else
{
@ -737,7 +365,7 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
}
}
break;
case TIMER_RETRANS_2:
case TIMER_RETRANS_1:
if (!metaRspFifo.empty())
{
meta = metaRspFifo.read();
@ -748,16 +376,6 @@ void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
rt_state = MAIN;
}
break;
/*case FLUSH_META_PIPE:
if (!metaRspFifo.empty())
{
metaRspFifo.read(meta);
if (meta.last)
{
rt_state = MAIN;
}
}
break;*/
}//switch
}
@ -774,6 +392,7 @@ void freelist_handler( stream<ap_uint<16> >& rt_releaseFifo,
if (!rt_releaseFifo.empty())
{
rt_freeListFifo.write(rt_releaseFifo.read());
freeListCounter--; // TODO: there should be some safeguarding that freeListCounter >= 0, but that shouldn't happen?
}
else if (freeListCounter < META_TABLE_SIZE && !rt_freeListFifo.full())
{
@ -802,11 +421,8 @@ void retransmitter( stream<retransRelease>& rx2retrans_release_upd,
static stream<retransMetaReq> rt_metaReqFifo("rt_metaReqFifo");
static stream<retransMetaEntry> rt_metaRspFifo("rt_metaRspFifo");
//static stream<ap_uint<16> > rt_freeListFifo("rt_freeListFifo");
#pragma HLS STREAM depth=2 variable=rt_metaReqFifo
#pragma HLS STREAM depth=2 variable=rt_metaRspFifo
//static stream<bool> rt_stopFifo("rt_stopFifo");
//#pragma HLS STREAM depth=2 variable=rt_stopFifo
static stream<ap_uint<16> > rt_freeListFifo("rt_freeListFifo");
#pragma HLS STREAM depth=META_TABLE_SIZE variable=rt_freeListFifo

View File

@ -1,452 +0,0 @@
/************************************************
Copyright (c) 2019, Systems Group, ETH Zurich.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************/
#include "retransmitter.hpp"
#include <rocev2_config.hpp> //defines MAX_QPS
using namespace hls;
//TODO maybe introduce seperate request streams
void retrans_pointer_table( stream<pointerReq>& pointerReqFifo,
stream<pointerUpdate>& pointerUpdFifo,
stream<retransPointerEntry>& pointerRspFifo)
//stream<event>& retrans2event)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
static retransPointerEntry ptr_table[MAX_QPS];
#if defined( __VITIS_HLS__)
#pragma HLS bind_storage variable=ptr_table type=RAM_T2P impl=BRAM
#else
#pragma HLS RESOURCE variable=ptr_table core=RAM_T2P_BRAM
#endif
//#pragma HLS DEPENDENCE variable=ptr_table inter false
static ap_uint<16> pt_lockedQP;
static bool pt_isLocked = false;
static bool pt_wait = false;
static pointerReq pt_req;
pointerUpdate upd;
if (!pointerUpdFifo.empty())
{
pointerUpdFifo.read(upd);
ptr_table[upd.qpn] = upd.entry;
if (pt_lockedQP == upd.qpn)
{
pt_isLocked = false;
}
}
else if (!pointerReqFifo.empty() && !pt_wait)
{
pointerReqFifo.read(pt_req);
if (pt_req.lock && pt_isLocked)
{
pt_wait = true;
}
else
{
pointerRspFifo.write(ptr_table[pt_req.qpn]);
if (pt_req.lock)
{
pt_isLocked = true;
pt_lockedQP = pt_req.qpn;
}
}
}
else if (pt_wait && !pt_isLocked)
{
pointerRspFifo.write(ptr_table[pt_req.qpn]);
pt_isLocked = true;
pt_lockedQP = pt_req.qpn;
pt_wait = false;
}
}
void retrans_meta_table(stream<retransMetaReq>& meta_upd_req,
stream<retransMetaEntry>& meta_rsp)
//stream<bool>& stopFifo)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
static retransMetaEntry meta_table[META_TABLE_SIZE];
#if defined( __VITIS_HLS__)
#pragma HLS bind_storage variable=meta_table type=RAM_T2P impl=BRAM
#else
#pragma HLS RESOURCE variable=meta_table core=RAM_T2P_BRAM
#endif
#pragma HLS DEPENDENCE variable=meta_table inter false
retransMetaReq req;
if (!meta_upd_req.empty())
{
meta_upd_req.read(req);
if (req.write)
{
meta_table[req.idx] = req.entry;
}
else if (req.append)
{
meta_table[req.idx].next = req.entry.next;
meta_table[req.idx].isTail = false;
}
else
{
meta_rsp.write(meta_table[req.idx]);
}
}
}
//TODO HLS is failing so bad with II, such that this module has a ton of states
void process_retransmissions( stream<retransRelease>& rx2retrans_release_upd,
stream<retransmission>& rx2retrans_req,
stream<retransmission>& timer2retrans_req,
stream<retransEntry>& tx2retrans_insertRequest,
stream<pointerReq>& pointerReqFifo,
stream<pointerUpdate>& pointerUpdFifo,
stream<retransPointerEntry>& pointerRspFifo, //TODO reorder
stream<retransMetaReq>& metaReqFifo,
stream<retransMetaEntry>& metaRspFifo,
stream<ap_uint<16> >& freeListFifo,
stream<ap_uint<16> >& releaseFifo,
//stream<bool>& stopFifo,
stream<retransEvent>& retrans2event)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
enum retransStateType {MAIN, INSERT_0, INSERT_1, RELEASE_0, RELEASE_1, RETRANS_0, RETRANS_1, RETRANS_2, TIMER_RETRANS_0, TIMER_RETRANS_1}; //FLUSH_META_PIPE};
static retransStateType rt_state = MAIN;
static retransRelease release;
static ap_uint<16> curr;
static ap_uint<16> newMetaIdx;
static retransEntry insert;
static retransmission retrans;
static retransMetaEntry meta; //TODO register needed??
static retransPointerEntry ptrMeta;
switch (rt_state)
{
case MAIN:
if (!rx2retrans_release_upd.empty())
{
rx2retrans_release_upd.read(release);
pointerReqFifo.write(pointerReq(release.qpn, true));
rt_state = RELEASE_0;
}
else if (!tx2retrans_insertRequest.empty() && !freeListFifo.empty())
{
newMetaIdx = freeListFifo.read();
tx2retrans_insertRequest.read(insert);
pointerReqFifo.write(pointerReq(insert.qpn, true));
rt_state = INSERT_0;
}
else if (!rx2retrans_req.empty())
{
rx2retrans_req.read(retrans);
std::cout << "RX Retransmit triggered!! , psn: " << std::hex << retrans.psn << std::endl;
pointerReqFifo.write(pointerReq(retrans.qpn));
rt_state = RETRANS_0;
}
else if (!timer2retrans_req.empty())
{
std::cout << "TIMER Retransmit triggered!!\n";
timer2retrans_req.read(retrans);
//Uses always head psn
pointerReqFifo.write(pointerReq(retrans.qpn));
rt_state = TIMER_RETRANS_0;
}
break;
case INSERT_0:
if (!pointerRspFifo.empty())
{
pointerRspFifo.read(ptrMeta);
if (!ptrMeta.valid)
{
//init entry
ptrMeta.valid = true;
ptrMeta.head = newMetaIdx;
ptrMeta.tail = newMetaIdx;
metaReqFifo.write(retransMetaReq(newMetaIdx, retransMetaEntry(insert)));
pointerUpdFifo.write(pointerUpdate(insert.qpn, ptrMeta));
rt_state = MAIN;
}
else
{
//Append new pointer to tail
metaReqFifo.write(retransMetaReq(ptrMeta.tail, newMetaIdx));
ptrMeta.tail = newMetaIdx;
rt_state = INSERT_1;
}
}
break;
case INSERT_1:
metaReqFifo.write(retransMetaReq(newMetaIdx, retransMetaEntry(insert)));
pointerUpdFifo.write(pointerUpdate(insert.qpn, ptrMeta));
rt_state = MAIN;
break;
case RELEASE_0:
if (!pointerRspFifo.empty())
{
std::cout << "releasing: " << release.latest_acked_req << std::endl;
pointerRspFifo.read(ptrMeta);
if (ptrMeta.valid)
{
//Get continuous stream of meta entries
metaReqFifo.write(retransMetaReq(ptrMeta.head));
curr = ptrMeta.head;
rt_state = RELEASE_1;
}
else
{
std::cout << "RELEASE_0: invalid meta entry\n";
//Release lock
pointerUpdFifo.write(pointerUpdate(release.qpn, ptrMeta));
rt_state = MAIN;
}
}
break;
case RELEASE_1:
if (!metaRspFifo.empty())
{
//TODO rearrange this thing
metaRspFifo.read(meta);
//TODO this should never occur: meta.entry.valid
std::cout << "meta.psn: " << meta.psn << ", latest acked req: " << release.latest_acked_req << std::endl;
if (!meta.valid || (meta.psn == release.latest_acked_req))
{
if (meta.psn == release.latest_acked_req)
{
std::cout << "release success" << std::endl;
}
ptrMeta.head = meta.next;
ptrMeta.valid = !meta.isTail;
pointerUpdFifo.write(pointerUpdate(release.qpn, ptrMeta));
rt_state = MAIN;
}
else
{
if (meta.isTail)
{
ptrMeta.valid = false;
ptrMeta.head = curr;
pointerUpdFifo.write(pointerUpdate(release.qpn, ptrMeta));
rt_state = MAIN;
}
else
{
metaReqFifo.write(retransMetaReq(meta.next));
}
curr = meta.next;
}
if (meta.valid)
{
releaseFifo.write(curr);
}
}
break;
case RETRANS_0:
if (!pointerRspFifo.empty())
{
pointerRspFifo.read(ptrMeta);
//curr = ptrMeta.head;
rt_state = MAIN;
if (ptrMeta.valid)
{
//Get continuous stream of meta entries
metaReqFifo.write(retransMetaReq(ptrMeta.head));
curr = ptrMeta.head;
rt_state = RETRANS_1;
}
}
break;
case RETRANS_1:
//Find PSN of interest and start retransmitting
if (!metaRspFifo.empty())
{
metaRspFifo.read(meta);
if (meta.valid)
{
if (!meta.isTail)
{
metaReqFifo.write(retransMetaReq(meta.next));
}
else
{
rt_state = MAIN;
}
//Check if we should start retransmitting
if (meta.psn == retrans.psn)
{
//Generate event
std::cout << std::hex << "retransmitting opcode: " << meta.opCode << ", local addr: " << meta.localAddr << ", remote addr: " << meta.remoteAddr << ", length: " << meta.length << std::endl;
retrans2event.write(retransEvent(meta.opCode, retrans.qpn, meta.localAddr, meta.remoteAddr, meta.length, meta.psn));
if (!meta.isTail)
{
rt_state = RETRANS_2;
}
}
}
else
{
rt_state = MAIN;
}
}
break;
// TODO: can we simplify this state?
case RETRANS_2:
//Retransmit everything until we reach tail
if (!metaRspFifo.empty())
{
metaRspFifo.read(meta);
if (meta.valid)
{
if (!meta.isTail)
{
metaReqFifo.write(retransMetaReq(meta.next));
}
else
{
rt_state = MAIN;
}
//Generate event
std::cout << std::hex << "retransmitting opcode: " << meta.opCode << ", local addr: " << meta.localAddr << ", remote addr: " << meta.remoteAddr << ", length: " << meta.length << std::endl;
retrans2event.write(retransEvent(meta.opCode, retrans.qpn, meta.localAddr, meta.remoteAddr, meta.length, meta.psn));
}
else
{
rt_state = MAIN;
}
}
break;
case TIMER_RETRANS_0:
if (!pointerRspFifo.empty())
{
pointerRspFifo.read(ptrMeta);
if (ptrMeta.valid)
{
metaReqFifo.write(retransMetaReq(ptrMeta.head));
rt_state = TIMER_RETRANS_1;
}
else
{
rt_state = MAIN;
}
}
break;
case TIMER_RETRANS_1:
if (!metaRspFifo.empty())
{
meta = metaRspFifo.read();
if (meta.valid)
{
retrans2event.write(retransEvent(meta.opCode, retrans.qpn, meta.localAddr, meta.remoteAddr, meta.length, meta.psn));
}
rt_state = MAIN;
}
break;
}//switch
}
void freelist_handler( stream<ap_uint<16> >& rt_releaseFifo,
stream<ap_uint<16> >& rt_freeListFifo)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
static ap_uint<16> freeListCounter = 0;
#pragma HLS reset variable=freeListCounter
if (!rt_releaseFifo.empty())
{
rt_freeListFifo.write(rt_releaseFifo.read());
}
else if (freeListCounter < META_TABLE_SIZE && !rt_freeListFifo.full())
{
rt_freeListFifo.write(freeListCounter);
freeListCounter++; // TODO: freeListCounter never decrement?
}
}
void retransmitter( stream<retransRelease>& rx2retrans_release_upd,
stream<retransmission>& rx2retrans_req,
stream<retransmission>& timer2retrans_req,
stream<retransEntry>& tx2retrans_insertRequest,
stream<retransEvent>& retrans2event)
{
//#pragma HLS DATAFLOW
//#pragma HLS INTERFACE ap_ctrl_none register port=return
#pragma HLS INLINE
static stream<pointerReq> rt_pointerReqFifo("rt_pointerReqFifo");
static stream<pointerUpdate> rt_pointerUpdFifo("rt_pointerUpdFifo");
static stream<retransPointerEntry> rt_pointerRspFifo("rt_pointerRspFifo"); //TODO reorder
#pragma HLS STREAM depth=2 variable=rt_pointerReqFifo
#pragma HLS STREAM depth=2 variable=rt_pointerUpdFifo
#pragma HLS STREAM depth=2 variable=rt_pointerRspFifo
static stream<retransMetaReq> rt_metaReqFifo("rt_metaReqFifo");
static stream<retransMetaEntry> rt_metaRspFifo("rt_metaRspFifo");
#pragma HLS STREAM depth=2 variable=rt_metaReqFifo
#pragma HLS STREAM depth=2 variable=rt_metaRspFifo
static stream<ap_uint<16> > rt_freeListFifo("rt_freeListFifo");
#pragma HLS STREAM depth=META_TABLE_SIZE variable=rt_freeListFifo
static stream<ap_uint<16> > rt_releaseFifo("rt_releaseFifo");
#pragma HLS STREAM depth=2 variable=rt_releaseFifo
freelist_handler(rt_releaseFifo, rt_freeListFifo);
retrans_pointer_table(rt_pointerReqFifo, rt_pointerUpdFifo, rt_pointerRspFifo);
retrans_meta_table( rt_metaReqFifo,
rt_metaRspFifo);
//rt_stopFifo);
process_retransmissions(rx2retrans_release_upd,
rx2retrans_req,
timer2retrans_req,
tx2retrans_insertRequest,
rt_pointerReqFifo,
rt_pointerUpdFifo,
rt_pointerRspFifo,
rt_metaReqFifo,
rt_metaRspFifo,
rt_freeListFifo,
rt_releaseFifo,
//rt_stopFifo,
retrans2event);
}

View File

@ -56,7 +56,6 @@ void transport_timer( stream<rxTimerUpdate>& rxClearTimer_req,
#pragma HLS DEPENDENCE variable=transportTimerTable inter false
static ap_uint<16> tt_currPosition = 0;
static ap_uint<16> tt_prevPosition = 0;
static bool tt_WaitForWrite = false;
@ -69,6 +68,7 @@ void transport_timer( stream<rxTimerUpdate>& rxClearTimer_req,
if (tt_WaitForWrite)
{
// clear time in transportTimerTable, one cycle after rxClearTimer signal
if (!tt_update.stop)
{
transportTimerTable[tt_update.qpn].time = TIME_1ms;
@ -86,79 +86,70 @@ void transport_timer( stream<rxTimerUpdate>& rxClearTimer_req,
rxClearTimer_req.read(tt_update);
tt_WaitForWrite = true;
}
else
else if (!txSetTimer_req.empty())
{
// update transportTimerTable with new (timeout) time
txSetTimer_req.read(setQP);
if ((setQP - 3 < tt_currPosition) && (tt_currPosition <= setQP))
{
tt_currPosition += 5;
}
entry = transportTimerTable[setQP];
if (!entry.active)
{
switch (entry.retries)
{
case 0:
entry.time = TIME_1ms;
break;
case 1:
entry.time = TIME_5ms;
break;
// case 2:
// entry.time = TIME_10ms;
// break;
default:
entry.time = TIME_10ms;
break;
}
}
entry.active = true;
transportTimerTable[setQP] = entry;
}
else
{
// perform round robin to check whether it has timed out
checkQP = tt_currPosition;
if (!txSetTimer_req.empty())
{
txSetTimer_req.read(setQP);
checkQP = setQP;
operationSwitch = 1;
if ((setQP - 3 < tt_currPosition) && (tt_currPosition <= setQP))
{
tt_currPosition += 5;
}
}
else
{
tt_currPosition++;
if (tt_currPosition >= MAX_QPS)
{
tt_currPosition = 0;
}
operationSwitch = 0;
}
tt_currPosition++;
if (tt_currPosition >= MAX_QPS)
{
tt_currPosition = 0;
}
//Get entry from table
entry = transportTimerTable[checkQP];
switch (operationSwitch)
{
case 1:
if (!entry.active)
{
switch (entry.retries)
{
case 0:
entry.time = TIME_1ms;
break;
case 1:
entry.time = TIME_5ms;
break;
case 2:
entry.time = TIME_10ms;
break;
default:
entry.time = TIME_10ms;
break;
}
}
entry.active = true;
break;
case 0:
if (entry.active)
{
if (entry.time > 0 )
{
entry.time--;
}
else if (!timer2retrans_req.full())
{
entry.time = 0;
entry.active = false;
if (entry.active)
{
if (entry.time > 0 )
{
entry.time--;
}
else if (!timer2retrans_req.full())
{
entry.time = 0;
entry.active = false;
if (entry.retries < 4)
{
entry.retries++;
//TODO shut QP down if too many retries
timer2retrans_req.write(retransmission(checkQP));
}
}
}
if (entry.retries < 4)
{
entry.retries++;
//TODO shut QP down if too many retries
timer2retrans_req.write(retransmission(checkQP));
}
}
}//if active
break;
}//switch
//write entry back
transportTimerTable[checkQP] = entry;
tt_prevPosition = checkQP;
}
}

View File

@ -1,160 +0,0 @@
/************************************************
Copyright (c) 2019, Systems Group, ETH Zurich.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************/
#include "transport_timer.hpp"
#include <rocev2_config.hpp> //defines MAX_QPS
/*
* page 352
* One timer per QP
* Timer gets started when a WRITE (with AckReqBit) or a READ_REQ is send
* Timer gets reset everytime a valid ACK is received
* Timer is stopped when there are no more outstanding requests
* Maintain a 3-bit retry counter, decrement on timeout, clear on new ACK
*/
void transport_timer( stream<rxTimerUpdate>& rxClearTimer_req,
stream<ap_uint<24> >& txSetTimer_req,
stream<retransmission>& timer2retrans_req)
{
#pragma HLS PIPELINE II=1
#pragma HLS INLINE off
static transportTimerEntry transportTimerTable[MAX_QPS];
#if defined( __VITIS_HLS__)
#pragma HLS bind_storage variable=transportTimerTable type=RAM_T2P impl=BRAM
#pragma HLS aggregate variable=transportTimerTable compact=bit
#else
#pragma HLS RESOURCE variable=transportTimerTable core=RAM_T2P_BRAM
#pragma HLS DATA_PACK variable=transportTimerTable
#endif
#pragma HLS DEPENDENCE variable=transportTimerTable inter false
static ap_uint<16> tt_currPosition = 0;
// static ap_uint<16> tt_prevPosition = 0;
static bool tt_WaitForWrite = false;
ap_uint<16> checkQP;
static rxTimerUpdate tt_update;
ap_uint<24> setQP;
transportTimerEntry entry;
ap_uint<1> operationSwitch = 0;
if (tt_WaitForWrite)
{
// clear time in transportTimerTable, one cycle after rxClearTimer signal
if (!tt_update.stop)
{
transportTimerTable[tt_update.qpn].time = TIME_1ms;
}
else
{
transportTimerTable[tt_update.qpn].time = 0;
transportTimerTable[tt_update.qpn].active = false;
}
transportTimerTable[tt_update.qpn].retries = 0;
tt_WaitForWrite = false;
}
else if (!rxClearTimer_req.empty())
{
rxClearTimer_req.read(tt_update);
tt_WaitForWrite = true;
}
else if (!txSetTimer_req.empty())
{
// update transportTimerTable with new (timeout) time
txSetTimer_req.read(setQP);
// TODO: why?
if ((setQP - 3 < tt_currPosition) && (tt_currPosition <= setQP))
{
tt_currPosition += 5;
}
entry = transportTimerTable[setQP];
if (!entry.active)
{
switch (entry.retries)
{
case 0:
entry.time = TIME_1ms;
break;
case 1:
entry.time = TIME_5ms;
break;
// case 2:
// entry.time = TIME_10ms;
// break;
default:
entry.time = TIME_10ms;
break;
}
}
entry.active = true;
transportTimerTable[setQP] = entry;
}
else
{
// perform round robin to check whether it has timed out
checkQP = tt_currPosition;
tt_currPosition++;
if (tt_currPosition >= MAX_QPS)
{
tt_currPosition = 0;
}
//Get entry from table
entry = transportTimerTable[checkQP];
if (entry.active)
{
if (entry.time > 0 )
{
// TODO: wouldn't the time only be updated rarely? (dependent on rxClearTimer and txSetTimer)
entry.time--;
}
else if (!timer2retrans_req.full())
{
entry.time = 0;
entry.active = false;
if (entry.retries < 4)
{
entry.retries++;
//TODO shut QP down if too many retries
timer2retrans_req.write(retransmission(checkQP));
}
}
}
//write entry back
transportTimerTable[checkQP] = entry;
// TODO: what is this for?
// tt_prevPosition = checkQP;
}
}