40 #define THIS_NAME "TB"
42 #define TRACE_OFF 0x0000
43 #define TRACE_CAM 1 << 1
44 #define TRACE_CGF 1 << 2
45 #define TRACE_EAC 1 << 3
46 #define TRACE_EIT 1 << 4
47 #define TRACE_ALL 0xFFFF
49 #define DEBUG_LEVEL (TRACE_OFF)
79 string inpDAT_FileName,
80 string outDAT_GoldName,
83 map<Ip4Addr, EthAddr> &hostMap)
90 char currPath[FILENAME_MAX];
92 int inpChunks=0, outChunks=0;
93 int inpFrames=0, outFrames=0;
94 int inpBytes=0, outBytes=0;
97 ifsDAT.open(inpDAT_FileName.c_str());
99 getcwd(currPath,
sizeof(currPath));
100 printError(myName,
"Cannot open the file: %s \n\t (FYI - The current working directory is: %s) \n",
101 inpDAT_FileName.c_str(), currPath);
105 printError(myName,
"Cannot create golden files from input file \'%s\' because file is not of type \'.dat\'.\n",
106 inpDAT_FileName.c_str());
112 remove(outDAT_GoldName.c_str());
113 if (!ofsDAT.is_open()) {
117 outDAT_GoldName.c_str());
122 while ((ifsDAT.peek() != EOF) && (
ret !=
NTS_KO)) {
125 bool endOfFrame=
false;
128 while ((ifsDAT.peek() != EOF) && (!endOfFrame)) {
148 inpBytes += axisEth.
getLen();
156 printWarn(myName,
"Frame #%d is dropped because it is not a broadcast frame.\n");
164 printWarn(myName,
"Frame #%d is dropped because it is not an ARP frame.\n");
165 printInfo(myName,
" Received EtherType = 0x%4.4X\n", etherType.to_ushort());
181 printWarn(myName,
"Frame #%d is skipped because the Target Protocol Address (TPA) of the ARP-REQUEST does not match the IP address of this core.\n");
183 printIp4Addr(myName,
" Expected TPA", myIp4Address.to_uint());
204 if (ethGoldFrame.
addPayload(arpGoldPacket) ==
false) {
205 printError(myName,
"Failed to add ARP packet as payload of an ETH frame.\n");
209 printError(myName,
"Failed to write ETH frame to DAT file.\n");
214 outChunks += ethGoldFrame.
size();
215 outBytes += ethGoldFrame.
length();
240 if (ethGoldFrame.
addPayload(arpGoldPacket) ==
false) {
241 printError(myName,
"Failed to add ARP packet as payload of an ETH frame.\n");
245 printError(myName,
"Failed to write ETH frame to DAT file.\n");
250 outChunks += ethGoldFrame.
size();
251 outBytes += ethGoldFrame.
length();
259 printInfo(myName,
"Done with the creation of the golden file.\n");
260 printInfo(myName,
"\tProcessed %5d chunks in %4d frames, for a total of %6d bytes.\n",
261 inpChunks, inpFrames, inpBytes);
262 printInfo(myName,
"\tGenerated %5d chunks in %4d frames, for a total of %6d bytes.\n",
263 outChunks, outFrames, outBytes);
264 printInfo(myName,
"\tDetected a total of %4d sender host(s).\n\n",
279 stream<RtlMacLookupRequest> &siARS_MacLkpReq,
280 stream<RtlMacLookupReply> &soARS_MacLkpRep,
281 stream<RtlMacUpdateRequest> &siARS_MacUpdReq,
282 stream<RtlMacUpdateReply> &soARS_MacUpdRep)
286 static map<Ip4Addr,EthAddr> LOOKUP_TABLE;
288 static enum CamFsmStates { CAM_WAIT_4_REQ=0,
290 CAM_UPDATE_REP } camFsmState;
294 static int camUpdateIdleCnt = 0;
295 volatile static int camLookupIdleCnt = 0;
296 map<Ip4Addr,EthAddr>::const_iterator findPos;
301 switch (camFsmState) {
304 if (!siARS_MacLkpReq.empty()) {
305 siARS_MacLkpReq.read(macLkpReq);
307 camFsmState = CAM_LOOKUP_REP;
309 printInfo(myName,
"Received a MAC lookup request from ARS for key: \n");
313 else if (!siARS_MacUpdReq.empty()) {
314 siARS_MacUpdReq.read(macUpdReq);
316 camFsmState = CAM_UPDATE_REP;
318 printInfo(myName,
"Received a MAC update request from ARS for ARP binding:\n");
325 if (camLookupIdleCnt > 0) {
329 findPos = LOOKUP_TABLE.find(macLkpReq.
key);
330 if (findPos != LOOKUP_TABLE.end()) {
333 printInfo(myName,
"Result of MAC lookup = HIT \n");
339 printInfo(myName,
"Result of session lookup = NO-HIT\n");
342 camFsmState = CAM_WAIT_4_REQ;
347 if (camUpdateIdleCnt > 0) {
353 LOOKUP_TABLE[macUpdReq.
key] = macUpdReq.
value;
356 printInfo(myName,
"Successful insertion of ARP binding pair:\n");
361 LOOKUP_TABLE.erase(macUpdReq.
key);
364 printInfo(myName,
"Successful deletion of ARP binding pair:\n");
368 camFsmState = CAM_WAIT_4_REQ;
376 #if HLS_VERSION != 2017
402 stream<AxisEth> &siIPRX_Data,
404 stream<AxisEth> &soETH_Data,
406 stream<Ip4Addr> &siIPTX_MacLkpReq,
407 stream<ArpLkpReply> &soIPTX_MacLkpRep,
409 stream<RtlMacLookupRequest> &soCAM_MacLkpReq,
410 stream<RtlMacLookupReply> &siCAM_MacLkpRep,
411 stream<RtlMacUpdateRequest> &soCAM_MacUpdReq,
412 stream<RtlMacUpdateReply> &siCAM_MacUpdRep)
415 static stream<AxisRaw> ssiIPRX_Data (
"ssiIPRX_Data");
416 static stream<AxisRaw> ssoETH_Data (
"ssoETH_Data");
445 int main(
int argc,
char* argv[]) {
460 EthAddr myMacAddress = 0x010203040506;
461 Ip4Addr myIp4Address = 0x0A0CC807;
463 string ofsARS_ETH_Data_FileName =
"../../../../test/soETH_Data.dat";
464 string ofsARS_ETH_Gold_FileName =
"../../../../test/soETH_Gold.dat";
466 map<Ip4Addr,EthAddr> hostMap;
467 map<Ip4Addr,EthAddr>::iterator hostMapIter;
473 stream<AxisEth> ssIPRX_ARS_Data (
"ssIPRX_ARS_Data");
474 int nrIPRX_ARS_Chunks = 0;
475 int nrIPRX_ARS_Frames = 0;
476 int nrIPRX_ARS_Bytes = 0;
479 stream<AxisEth> ssARS_ETH_Data (
"ssARS_ETH_Data");
480 int nrARS_ETH_Chunks = 0;
481 int nrARS_ETH_Frames = 0;
482 int nrARS_ETH_Bytes = 0;
485 stream<Ip4Addr> ssIPTX_ARS_MacLkpReq (
"ssIPTX_ARS_MacLkpReq");
486 stream<ArpLkpReply> ssARS_IPTX_MacLkpRep (
"ssARS_IPTX_MacLkpRep");
489 stream<RtlMacLookupRequest> ssARS_CAM_MacLkpReq(
"ssARS_CAM_MacLkpReq");
490 stream<RtlMacLookupReply> ssCAM_ARS_MacLkpRep(
"ssCAM_ARS_MacLkpRep");
491 stream<RtlMacUpdateRequest> ssARS_CAM_MacUpdReq(
"ssARS_CAM_MacUpdReq");
492 stream<RtlMacUpdateReply> ssCAM_ARS_MacUpdRep(
"ssCAM_ARS_MacUpdRep");
498 printFatal(
THIS_NAME,
"Missing testbench parameter:\n\t Expecting an input test vector file.\n");
502 myIp4Address = param;
503 printIp4Addr(
THIS_NAME,
"The input test vector is setting the IP address of the FPGA to", myIp4Address);
509 if (feedAxisFromFile<AxisEth>(ssIPRX_ARS_Data,
"sIPRX_ARS_Data",
string(argv[1]),
510 nrIPRX_ARS_Chunks, nrIPRX_ARS_Frames, nrIPRX_ARS_Bytes)) {
512 printInfo(
THIS_NAME,
"\tGenerated %d chunks in %d frames, for a total of %d bytes.\n\n",
513 nrIPRX_ARS_Chunks, nrIPRX_ARS_Frames, nrIPRX_ARS_Bytes);
523 ofstream ofsETH_Data;
524 string ofsETH_Data_FileName =
"../../../../test/soETH_Data.dat";
525 string ofsETH_Gold_FileName =
"../../../../test/soETH_Gold.dat";
528 if (not
isDatFile(ofsETH_Data_FileName)) {
529 printFatal(
THIS_NAME,
"File \'%s\' is not of type \'DAT\'.\n", ofsETH_Data_FileName.c_str());
533 remove(ofsETH_Data_FileName.c_str());
535 if (!ofsETH_Data.is_open()) {
536 ofsETH_Data.open(ofsETH_Data_FileName.c_str(),
ofstream::out);
548 myMacAddress, myIp4Address, hostMap)) {
554 printInfo(
THIS_NAME,
"############################################################################\n");
556 printInfo(
THIS_NAME,
"############################################################################\n");
562 tbRun = (nrErr == 0) ? (nrIPRX_ARS_Chunks +
TB_GRACE_TIME) : 0;
565 #if HLS_VERSION == 2017
571 ssIPTX_ARS_MacLkpReq,
572 ssARS_IPTX_MacLkpRep,
576 ssCAM_ARS_MacUpdRep);
583 ssIPTX_ARS_MacLkpReq,
584 ssARS_IPTX_MacLkpRep,
588 ssCAM_ARS_MacUpdRep);
604 printInfo(
THIS_NAME,
"############################################################################\n");
606 printInfo(
THIS_NAME,
"############################################################################\n");
617 #if HLS_VERSION == 2017
623 ssIPTX_ARS_MacLkpReq,
624 ssARS_IPTX_MacLkpRep,
628 ssCAM_ARS_MacUpdRep);
635 ssIPTX_ARS_MacLkpReq,
636 ssARS_IPTX_MacLkpRep,
640 ssCAM_ARS_MacUpdRep);
656 printInfo(
THIS_NAME,
"############################################################################\n");
658 printInfo(
THIS_NAME,
"############################################################################\n");
665 hostMapIter = hostMap.begin();
666 while (hostMapIter != hostMap.end()) {
667 ssIPTX_ARS_MacLkpReq.write(hostMapIter->first);
672 #if HLS_VERSION == 2017
678 ssIPTX_ARS_MacLkpReq,
679 ssARS_IPTX_MacLkpRep,
683 ssCAM_ARS_MacUpdRep);
690 ssIPTX_ARS_MacLkpReq,
691 ssARS_IPTX_MacLkpRep,
695 ssCAM_ARS_MacUpdRep);
713 if (not drainAxisToFile<AxisEth>(ssARS_ETH_Data,
"ssARS_ETH_Data",
714 ofsARS_ETH_Data_FileName, nrARS_ETH_Chunks,
715 nrARS_ETH_Frames, nrARS_ETH_Bytes)) {
725 ArpLkpReply macLkpRep = ssARS_IPTX_MacLkpRep.read();
726 if (macLkpRep.
hit !=
false) {
728 printError(
THIS_NAME,
"Expecting the first MAC lookup of this testbench to be a \'NO_HIT\' flag.\n");
731 hostMapIter = hostMap.begin();
732 while (hostMapIter != hostMap.end()) {
733 ArpLkpReply macLkpRep = ssARS_IPTX_MacLkpRep.read();
734 if (macLkpRep.
hit ==
false) {
739 else if (macLkpRep.
macAddress != (hostMapIter->second)) {
748 printInfo(
THIS_NAME,
"############################################################################\n");
750 printInfo(
THIS_NAME,
"############################################################################\n");
756 int res = system((
"diff --brief -w " + std::string(ofsETH_Data_FileName) \
757 +
" " + std::string(ofsETH_Gold_FileName) +
" ").c_str());
760 ofsETH_Data_FileName.c_str(), ofsETH_Gold_FileName.c_str());
773 printError(
THIS_NAME,
"#### TEST BENCH FAILED : TOTAL NUMBER OF ERROR(S) = %2d ####\n", nrErr);
776 printInfo(
THIS_NAME,
"FYI - You may want to check for \'ERROR\' and/or \'WARNING\' alarms in the LOG file...\n\n");
779 printInfo(
THIS_NAME,
"#############################################################\n");
781 printInfo(
THIS_NAME,
"#############################################################\n");
void setTLast(tLast last)
void setTKeep(tKeep keep)
Class ARP Packet for simulation.
void setSenderProtAddr(ArpSendProtAddr spa)
void setHardwareType(ArpHwType htype)
void setTargetHwAddr(ArpTargHwAddr tha)
ArpTargProtAddr getTargetProtAddr()
void setSenderHwAddr(ArpSendHwAddr sha)
void setTargetProtAddr(ArpTargProtAddr tpa)
ArpSendProtAddr getSenderProtAddr()
void setProtocolLength(ArpProtLen plen)
ArpSendHwAddr getSenderHwAddr()
void setHardwareLength(ArpHwLen hlen)
void setOperation(ArpOper oper)
void setProtocolType(ArpProtType ptype)
void pushChunk(AxisEth ethChunk)
bool writeToDatFile(ofstream &outFileStream)
Dump this Ethernet frame as raw AxisEth chunks into a file.
void setMacDestinAddress(EthAddr addr)
EthAddr getMacDestinAddress()
bool addPayload(SimArpPacket arpPkt)
Add data payload to this frame from an ARP packet.
void setTypeLength(EthTypeLen typLen)
void setMacSourceAddress(EthAddr addr)
SimArpPacket getArpPacket()
EthAddr getMacSourceAddress()
EthTypeLen getTypeLength()
int main(int argc, char *argv[])
Main function.
void stepSim()
Increment the simulation counter.
#define TB_MAX_SIM_CYCLES
const Ip4Addr RESERVED_SENDER_PROTOCOL_ADDRESS
int createGoldenFile(string inpDAT_FileName, string outDAT_GoldName, EthAddr myMacAddress, Ip4Addr myIp4Address, map< Ip4Addr, EthAddr > &hostMap)
Create the golden reference file from an input test file.
#define CAM_LOOKUP_LATENCY
unsigned int gMaxSimCycles
void arp_top_wrap(EthAddr piMMIO_MacAddress, Ip4Addr piMMIO_Ip4Address, stream< AxisEth > &siIPRX_Data, stream< AxisEth > &soETH_Data, stream< Ip4Addr > &siIPTX_MacLkpReq, stream< ArpLkpReply > &soIPTX_MacLkpRep, stream< RtlMacLookupRequest > &soCAM_MacLkpReq, stream< RtlMacLookupReply > &siCAM_MacLkpRep, stream< RtlMacUpdateRequest > &soCAM_MacUpdReq, stream< RtlMacUpdateReply > &siCAM_MacUpdRep)
A wrapper for the Toplevel of the Address Resolution Protocol (ARP) Server.
#define CAM_UPDATE_LATENCY
void pEmulateCam(stream< RtlMacLookupRequest > &siARS_MacLkpReq, stream< RtlMacLookupReply > &soARS_MacLkpRep, stream< RtlMacUpdateRequest > &siARS_MacUpdReq, stream< RtlMacUpdateReply > &soARS_MacUpdRep)
Emulate the behavior of the Content Addressable Memory (CAM).
void arp_top(EthAddr piMMIO_MacAddress, Ip4Addr piMMIO_Ip4Address, stream< AxisRaw > &siIPRX_Data, stream< AxisRaw > &soETH_Data, stream< Ip4Addr > &siIPTX_MacLkpReq, stream< ArpLkpReply > &soIPTX_MacLkpRep, stream< RtlMacLookupRequest > &soCAM_MacLkpReq, stream< RtlMacLookupReply > &siCAM_MacLkpRep, stream< RtlMacUpdateRequest > &soCAM_MacUpdReq, stream< RtlMacUpdateReply > &siCAM_MacUpdRep)
Top of Address Resolution Protocol (ARP) Server.
bool isDatFile(string fileName)
Checks if a file has a ".dat" extension.
bool readTbParamFromFile(const string paramName, const string datFile, unsigned int ¶mVal)
Retrieve a testbench parameter from a DAT file.
bool readAxisRawFromFile(AxisRaw &axisRaw, ifstream &inpFileStream)
Retrieve an Axis raw data chunk from a file.
#define ARP_HTYPE_ETHERNET
#define printError(callerName, format,...)
A macro to print an error message.
ap_uint< 48 > ArpSendHwAddr
void printArpBindPair(const char *callerName, ArpBindPair arpBind)
Print an ARP binding pair association.
ap_uint< 32 > ArpSendProtAddr
void pAxisRawCast(hls::stream< TypeIn > &si, hls::stream< TypeOut > &so)
AxisRaw cast - Casts an AxisRaw stream to/from an AxisRaw derived class.
#define ETH_ETHERTYPE_ARP
#define ARP_HLEN_ETHERNET
#define printInfo(callerName, format,...)
A macro to print an information message.
#define ETH_BROADCAST_ADDR
void printIp4Addr(const char *callerName, const char *message, Ip4Addr ip4Addr)
Print an IPv4 address prepended with a message (used for debugging).
#define printWarn(callerName, format,...)
A macro to print a warning message.
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
void printEthAddr(const char *callerName, const char *message, EthAddr ethAddr)
Print an ETHERNET MAC address prepended with a message (for debug).
#define printFatal(callerName, format,...)
A macro to print a fatal error message and exit.