/* * Function: SendAndCut * Description: Send the entirety of buffer and cut if the whole frame hasn't been sent. */ public static void SendAndCut(CircularFrameBuffer cfb) { var status = 0U; if (cfb.CanPop(true)) { Emu.Interrupts = 1; } else { Emu.Interrupts = 2; } Emu.debug_reg = cfb.Count; while (status <= 1) { status = SendOne(cfb, false, true, false); } if (status == 2) { Reset(); } else if (status == 3) { CutThrough(); } }
public static void WriteUDPHeader(CircularFrameBuffer cfb, UDPParser up, EthernetParserGenerator ep, IPv4ParserGenerator ip, byte ports) { Emu.Status = 0xff0; ip.Protocol = 17; ip.AssembleHeader(); //Emu.PktIn = ip.CalculateCheckSum(); //ip.HeaderChecksum = ip.CalculateCheckSum(); //ip.AssembleHeader(); ep.WriteToBuffer(cfb.PushData); ip.WriteToBuffer(cfb.PushData, 0); InterfaceFunctions.SetDestInterface(ports, cfb.PushData); cfb.PushData.Tkeep = 0xFFFFFFFF; cfb.PushData.Tlast = false; Kiwi.Pause(); cfb.Push(cfb.PushData, true); Emu.Status = 0xff1; cfb.ResetPeek(); cfb.PushData.Reset(); ip.WriteToBuffer(cfb.PushData, 1); up.WriteToBuffer(cfb.PushData, (byte)(16 + (ip.IHL - 5) * 32)); cfb.PushData.Tkeep = 0x0000003FF; cfb.PushData.Tlast = true; Kiwi.Pause(); cfb.Push(cfb.PushData); Emu.Status = 0xff2; }
/* * Function: RecvOne * Description: Receive and buffer a single segment of the ethernet frame. */ public static bool RecvOne(CircularFrameBuffer cfb, bool stop, bool wait = false) { Emu.s_axis_tready = false; Emu.Status = 1; while (wait) { wait = !Emu.s_axis_tvalid; } bool cont = !stop; if (Emu.s_axis_tvalid && cfb.CanPush()) { Emu.s_axis_tready = true; cfb.PushData.Tkeep = Emu.s_axis_tkeep; cfb.PushData.Tlast = Emu.s_axis_tlast; cfb.PushData.Tdata0 = Emu.s_axis_tdata_0; cfb.PushData.Tdata1 = Emu.s_axis_tdata_1; cfb.PushData.Tdata2 = Emu.s_axis_tdata_2; cfb.PushData.Tdata3 = Emu.s_axis_tdata_3; cfb.PushData.TuserHi = Emu.s_axis_tuser_hi; cfb.PushData.TuserLow = Emu.s_axis_tuser_low; Emu.s_axis_tready = cont; cfb.Push(cfb.PushData); Emu.Status = 2; //Kiwi.Pause(); return(true); } Emu.s_axis_tready = false; return(false); }
/* * Function: SetData * Description: Pop and set the output data to the popped contents. */ private static bool SetData(CircularFrameBuffer cfb, bool movepeek = false, bool wait = false, bool valid = true) { bool ready = Emu.m_axis_tready; if (ready || wait) { cfb.Pop(movepeek); } Emu.m_axis_tvalid = valid; Emu.m_axis_tdata_0 = cfb.PopData.Tdata0; Emu.m_axis_tdata_1 = cfb.PopData.Tdata1; Emu.m_axis_tdata_2 = cfb.PopData.Tdata2; Emu.m_axis_tdata_3 = cfb.PopData.Tdata3; Emu.m_axis_tkeep = cfb.PopData.Tkeep; Emu.m_axis_tlast = cfb.PopData.Tlast; Emu.m_axis_tuser_low = cfb.PopData.TuserLow; Emu.m_axis_tuser_hi = cfb.PopData.TuserHi; if (wait) { WaitReady(); } return(ready); }
/* * Function: RecvFrame * Description: Receive and buffer an entire Ethernet frame. */ public static uint RecvFrame(CircularFrameBuffer cfb) { // The start condition var doneReading = false; // Local variables - counters var cnt = 0U; uint psize = 0; while (!doneReading) { if (Emu.s_axis_tvalid && cfb.CanPush() && Emu.s_axis_tready) // Receive data { cfb.PushData.Tkeep = Emu.s_axis_tkeep; cfb.PushData.Tlast = Emu.s_axis_tlast; cfb.PushData.Tdata0 = Emu.s_axis_tdata_0; cfb.PushData.Tdata1 = Emu.s_axis_tdata_1; cfb.PushData.Tdata2 = Emu.s_axis_tdata_2; cfb.PushData.Tdata3 = Emu.s_axis_tdata_3; cfb.PushData.TuserHi = Emu.s_axis_tuser_hi; cfb.PushData.TuserLow = Emu.s_axis_tuser_low; Emu.s_axis_tready = !Emu.s_axis_tlast; cfb.Push(cfb.PushData); psize = cnt++; // Condition to stop receiving data doneReading = Emu.s_axis_tlast || !Emu.s_axis_tvalid; if (!cfb.CanPush()) // Buffer is full, stop receiving data { Emu.s_axis_tready = false; } } else if (!cfb.CanPush()) // Buffer is still full { Emu.s_axis_tready = false; } else if (!Emu.s_axis_tready) // Restart receiving data { Emu.s_axis_tready = true; } //Kiwi.Pause(); } Emu.PktIn++; Emu.s_axis_tready = false; return(psize); }
/* * Function: SendFrame * Description: Send the entirety of the buffered ethernet frame. */ public static void SendFrame(CircularFrameBuffer cfb) { Reset(); var status = 0U; while (status <= 1) { status = SendOne(cfb, false, true); } Reset(); }
public static void WriteIPv4EthernetHeader(CircularFrameBuffer cfb, EthernetParserGenerator ep, IPv4ParserGenerator ip, byte ports) { ip.AssembleHeader(); ep.WriteToBuffer(cfb.PushData); ip.WriteToBuffer(cfb.PushData, 0); cfb.PushData.Tkeep = 0xFFFFFFFF; cfb.PushData.Tlast = false; InterfaceFunctions.SetDestInterface(ports, cfb.PushData); cfb.Push(cfb.PushData); cfb.PushData.Reset(); ip.WriteToBuffer(cfb.PushData, 1); cfb.Push(cfb.PushData); }
/* * Function: SendOne * Description: Send a single segment of the buffered ethernet frame. */ public static uint SendOne(CircularFrameBuffer cfb, bool stop = true, bool movepeek = false, bool checkready = true) { if (cfb.CanPop(movepeek) && (!checkready || Emu.m_axis_tready)) { Emu.Status = 11; SetData(cfb, movepeek, true); var done = cfb.PopData.Tlast; Emu.Status = 3; Kiwi.Pause(); if (stop) { Reset(); } if (done) { Emu.PktOut++; Emu.Status = 12; return(2U); } Emu.Status = 13; return(0U); } Emu.Status = 14; if (stop) { Reset(); } return(3U); }
/* * Function: SendWithFCS * Description: Sends the whole buffered frame, appending the FCS at the end. */ public static bool SendWithFCS(CircularFrameBuffer cfb, crc32 crc) { bool cont = true; crc.Reset(); while (cont) { if (cfb.CanPop(true)) { if (SetData(cfb, true, false, false)) { crc.CRC_Compute(cfb.PopData); cont = !cfb.PopData.Tlast; } ; if (cfb.PopData.Tlast) { var size = (int)NumSize(cfb.PopData.Tkeep); if (size >= 24) { Emu.m_axis_tdata_3 = cfb.PopData.Tdata3 | (crc.CRC_LittleEndian() << ((size % 8) * 8)); } else if (size > 20) { Emu.m_axis_tdata_3 = cfb.PopData.Tdata3 | (crc.CRC_LittleEndian() >> ((24 - size) * 8)); Emu.m_axis_tdata_2 = cfb.PopData.Tdata2 | (crc.CRC_LittleEndian() << ((size % 8) * 8)); } else if (size >= 16) { Emu.m_axis_tdata_2 = cfb.PopData.Tdata2 | (crc.CRC_LittleEndian() >> ((size % 8) * 8)); } else if (size > 12) { Emu.m_axis_tdata_2 = cfb.PopData.Tdata2 | (crc.CRC_LittleEndian() >> ((16 - size) * 8)); Emu.m_axis_tdata_1 = cfb.PopData.Tdata1 | (crc.CRC_LittleEndian() << ((size % 8) * 8)); } else if (size >= 8) { Emu.m_axis_tdata_1 = cfb.PopData.Tdata1 | (crc.CRC_LittleEndian() << ((size % 8) * 8)); } else if (size > 4) { Emu.m_axis_tdata_1 = cfb.PopData.Tdata1 | (crc.CRC_LittleEndian() >> ((8 - size) * 8)); Emu.m_axis_tdata_0 = cfb.PopData.Tdata0 | (crc.CRC_LittleEndian() << (size * 8)); } else { Emu.m_axis_tdata_0 = cfb.PopData.Tdata0 | (crc.CRC_LittleEndian() << (size * 8)); } Emu.PktIn = (uint)size; Emu.m_axis_tkeep = Emu.m_axis_tkeep << 4 | 0xF; //Console.WriteLine($"{size}:{crc.CRC_LittleEndian():X16}"); } Emu.m_axis_tvalid = true; WaitReady(); //System.Console.WriteLine($"{Emu.m_axis_tdata_0:X16},\n{Emu.m_axis_tdata_1:X16},\n{Emu.m_axis_tdata_2:X16},\n{Emu.m_axis_tdata_3:X16}"); //Kiwi.Pause(); } else { Reset(); return(false); } } Reset(); Emu.PktOut++; return(true); }