/*
         * 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();
            }
        }
Example #2
0
        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();
        }
Example #7
0
        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);
        }