/*
         * 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();
            }
        }
        /*
         * 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);
        }