// credit request from our global-ring interface
        protected bool getCredit_global(Flit f, int bubble)
        {
            MyTracer.trace(f, "getCredit global", _coord);

            if (!_coord.routeL(f.bufrings_coord))
            {
                if (_creditG > bubble)
                {
                    _creditG--;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                if (_creditGL > bubble)
                {
                    _creditGL--;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        // credit request from our local-ring interface
        protected bool getCredit_local(Flit f, int bubble)
        {
            MyTracer.trace(f, "getCredit local", _coord);

            if (_coord.routeG(f.bufrings_coord))
            {
                MyTracer.trace(f, "getCredit local LG", _coord);
                //if (f.packet.ID == MyTracer.id) Console.WriteLine("credits {0} bubble {1}", _creditLG, bubble);
                if (_creditLG > bubble)
                {
                    _creditLG--;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                MyTracer.trace(f, "getCredit local L", _coord);
                if (_creditL > bubble)
                {
                    _creditL--;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        public bool doStep()
        {
            bool somethingMoved = false;

            // handle inputs

            // global input
            if (_gin.Out != null)
            {
                Flit f = _gin.Out;
                _gin.Out = null;

                MyTracer.trace(f, "IRI global input", _coord);

                somethingMoved = true;

                if (_coord.routeL(f.bufrings_coord))
                {
                    _bufGL.Enqueue(f);
                    MyTracer.trace(f,
                                   String.Format("IRI global->local transfer, queue length {0}",
                                                 _bufLG.Count), _coord);
                    Simulator.stats.bufrings_iri_enqueue_gl[_coord.level].Add();
                }
                else
                {
                    _bufG.Enqueue(f);
                    Simulator.stats.bufrings_iri_enqueue_g[_coord.level].Add();
                }
            }

            // local input
            if (_lin.Out != null)
            {
                Flit f = _lin.Out;
                _lin.Out = null;

                MyTracer.trace(f, "IRI local input", _coord);

                somethingMoved = true;

                if (_coord.routeG(f.bufrings_coord))
                {
                    _bufLG.Enqueue(f);
                    MyTracer.trace(f,
                                   String.Format("IRI local->global transfer, queue length {0}",
                                                 _bufLG.Count), _coord);
                    Simulator.stats.bufrings_iri_enqueue_lg[_coord.level].Add();
                }
                else
                {
                    _bufL.Enqueue(f);
                    Simulator.stats.bufrings_iri_enqueue_l[_coord.level].Add();
                }
            }

            // handle outputs

            // global output (on-ring traffic)
            if (_gout.In == null && _bufG.Count > 0)
            {
                Flit f = _bufG.Peek();
                if (_downstreamG.getCredit(f, 0))
                {
                    _bufG.Dequeue();
                    Simulator.stats.bufrings_iri_dequeue_g[_coord.level].Add();
                    _creditG++;
                    _gout.In       = f;
                    somethingMoved = true;
                }
            }
            // global output (transfer traffic)
            if (_gout.In == null && _bufLG.Count > 0)
            {
                Flit f = _bufLG.Peek();
                if (_downstreamG.getCredit(f, (_coord.coord.Length - _coord.level)))   // bubble flow control: black magic
                {
                    _bufLG.Dequeue();
                    Simulator.stats.bufrings_iri_dequeue_lg[_coord.level].Add();
                    _creditLG++;
                    _gout.In       = f;
                    somethingMoved = true;
                }
            }

            // local output (transfer traffic)
            if (_lout.In == null && _bufGL.Count > 0)
            {
                Flit f = _bufGL.Peek();
                if (_downstreamL.getCredit(f, 0))
                {
                    _bufGL.Dequeue();
                    Simulator.stats.bufrings_iri_dequeue_gl[_coord.level].Add();
                    _creditGL++;
                    _lout.In       = f;
                    somethingMoved = true;
                }
                else
                {
                    BufRingMultiNetwork_IRI_GlobalPort i = _downstreamL as BufRingMultiNetwork_IRI_GlobalPort;
#if DEBUG
                    Console.WriteLine("GL block at IRI {0} flit {1}.{2} cycle {3} downstream is IRI {4}",
                                      _coord, f.packet.ID, f.flitNr, Simulator.CurrentRound,
                                      (i != null) ? i._iri._coord.ToString() : "(nic)");
#endif
                }
            }

            // local output (on-ring traffic)
            if (_lout.In == null && _bufL.Count > 0)
            {
                Flit f = _bufL.Peek();
                if (_downstreamL.getCredit(f, 0))
                {
                    _bufL.Dequeue();
                    Simulator.stats.bufrings_iri_dequeue_l[_coord.level].Add();
                    _creditL++;
                    _lout.In       = f;
                    somethingMoved = true;
                }
            }

            if (_gout.In != null)
            {
                Simulator.stats.bufrings_link_traverse[_coord.level].Add();
            }
            if (_lout.In != null)
            {
                Simulator.stats.bufrings_link_traverse[_coord.level + 1].Add();
            }

            Simulator.stats.bufrings_iri_occupancy_g[_coord.level].Add(_bufG.Count);
            Simulator.stats.bufrings_iri_occupancy_l[_coord.level].Add(_bufL.Count);
            Simulator.stats.bufrings_iri_occupancy_gl[_coord.level].Add(_bufGL.Count);
            Simulator.stats.bufrings_iri_occupancy_lg[_coord.level].Add(_bufLG.Count);

            Simulator.stats.bufrings_ring_util[_coord.level].Add(_gout.In != null ? 1 : 0);

            return(somethingMoved);
        }
        public bool doStep()
        {
            bool somethingMoved = false;

            // handle input from ring
            if (_in.Out != null)
            {
                Flit f = _in.Out;
                _in.Out = null;

                MyTracer.trace(f, "NIC input", _coord);

                somethingMoved = true;

                if (f.packet.dest.ID == _router.coord.ID)
                {
                    _credits++;
                    _router.acceptFlit(f);
                }
                else
                {
                    _buf.Enqueue(f);
                    Simulator.stats.bufrings_nic_enqueue.Add();
                }
            }

            // handle through traffic
            if (_buf.Count > 0)
            {
                Flit f = _buf.Peek();
                if (_downstream.getCredit(f, 0))
                {
                    _buf.Dequeue();
                    _credits++;
                    _out.In = f;
                    Simulator.stats.bufrings_nic_dequeue.Add();
                    somethingMoved = true;
                }
            }

            // handle injections
            if (_out.In == null && _inject != null)
            {
                if (_downstream.getCredit(_inject, 2))
                {
                    _out.In = _inject;
                    _inject = null;
                    Simulator.stats.bufrings_nic_inject.Add();
                    somethingMoved = true;
                }
            }
            if (_inject != null)
            {
                Simulator.stats.bufrings_nic_starve.Add();
            }

            if (_out.In != null)
            {
                Simulator.stats.bufrings_link_traverse[Config.bufrings_levels - 1].Add();
            }

            Simulator.stats.bufrings_nic_occupancy.Add(_buf.Count);

            return(somethingMoved);
        }