Beispiel #1
0
void VC::UpdatePriority()
{
  if(_buffer.empty()) return;
  if(_pri_type == queue_length_based) {
    _pri = _buffer.size();
  } else if(_pri_type != none) {
    Flit * f = _buffer.front();
    if((_pri_type != local_age_based) && _priority_donation) {
      Flit * df = f;
      for(size_t i = 1; i < _buffer.size(); ++i) {
	Flit * bf = _buffer[i];
	if(bf->pri > df->pri) df = bf;
      }
      if((df != f) && (df->watch || f->watch)) {
	*gWatchOut << GetSimTime() << " | " << FullName() << " | "
		    << "Flit " << df->id
		    << " donates priority to flit " << f->id
		    << "." << endl;
      }
      f = df;
    }
    if(f->watch)
      *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		  << "Flit " << f->id
		  << " sets priority to " << f->pri
		  << "." << endl;
    _pri = f->pri;
  }
}
Beispiel #2
0
void IQRouterBase::_OutputQueuing( )
{

	for ( int output = 0; output < _outputs; ++output ) {
		for ( int t = 0; t < _output_speedup; ++t ) {
			int expanded_output = _outputs*t + output;
			Flit * f = _crossbar_pipe->Read( expanded_output );

			if ( f ) {
				_output_buffer[output].push( f );
				if(f->watch)
					*gWatchOut << GetSimTime() << " | " << FullName() << " | "
					<< "Buffering flit " << f->id
					<< " at output " << output
					<< "." << endl;
			}
		}
	}

	for ( int input = 0; input < _inputs; ++input ) {
		Credit * c = _credit_pipe->Read( input );

		if ( c ) {
			_in_cred_buffer[input].push( c );
		}
	}
}
Beispiel #3
0
  /// This is the principal constructor.
  CbirGVT::CbirGVT(DataBase *db, const string& args)
    : CbirAlgorithm(db, args) {

    string hdr = "CbirGVT::CbirGVT() : ";

    debug = 0;
    lastroundonly = false;
    
    if (db->Name().find("flickr")!=0)
      ShowError(hdr+" algorithm=gvt works only with database=flickr");

    if (debug_stages)
      cout << TimeStamp()
	   << hdr+"constructing an instance with arguments \""
	   << args << "\"" << endl;

    map<string,string> amap = SplitArgumentString(args);
    for (map<string,string>::const_iterator a=amap.begin(); a!=amap.end(); a++)
      ShowError(hdr+"key ["+a->first+"] not recognized");

    if (debug_stages)
      cout << TimeStamp()
	   << hdr+"constructed instance with FullName()=\"" << FullName()
	   << "\"" << endl;

    // After calling CbirAlgorithm::CbirAlgorithm(DataBase*) we should
    // have a valid DataBase pointer named database:

    if (false)
      cout << TimeStamp() << hdr
	   << "we are using database \"" << database->Name()
	   << "\" that contains " << database->Size() << " objects" << endl;

  }
Beispiel #4
0
void cOptMInt::Store(const char *PreStr)
{
  char b[256];
  int p=0;
  for(int i=0; i<size; i++)
    if(storage[i] || mode==0) p+=snprintf(b+p,sizeof(b)-p,mode>1 ? "%x ":"%d ",storage[i]);
  ScPlugin->SetupStore(FullName(PreStr),p>0?b:0);
}
Beispiel #5
0
void FlitChannel::WriteOutputs() {
  Channel<Flit>::WriteOutputs();
  Flit const * const & f = _output;
  if(f && f->watch) {
    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
	       << "Completed channel traversal for flit " << f->id
	       << "." << endl;
  }
}
Beispiel #6
0
void FlitChannel::ReadInputs() {
  Flit const * const & f = _input;
  if(f && f->watch) {
    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
	       << "Beginning channel traversal for flit " << f->id
	       << " with delay " << _delay
	       << "." << endl;
  }
  Channel<Flit>::ReadInputs();
}
Beispiel #7
0
uInt VdfFlow::BuildVdfsIndex(VdfsIndex* index, VdfEntryInfo* Entries, uInt BeginNum, const char* Directory)
{
    uInt result = 0;
    for(uInt i = BeginNum; ; i++)
    {
        // Make name null terminated
        for(uInt n = 63; n >= 0; n--)
        {
            if(Entries[i].Name[n] != 0x20)
            {
                if(n != 63)
                    Entries[i].Name[n + 1] = '\0';
                else
                {
                    Entries[i].Name[n] = '\0';
                    // Invalid name lengh > 64
                }
                break;
            }
        }

        AString Name(Directory);
        if(Name) Name += '\\';
        Name += Entries[i].Name;

        if(Entries[i].Type & VDF_ENTRY_DIR)
        {
            result += BuildVdfsIndex(index, Entries, Entries[i].JumpTo, Name);
        }
        else
        {
            AString FullName("\\");
            FullName += Name;
            if(!index->FullIndexes[FullName])
            {
                VdfsIndex::FileInfo* Info = index->Files.Add(new VdfsIndex::FileInfo);
                Info->Flow = this;
                Info->Name = FullName;
                Info->Offset = Entries[i].JumpTo;
                Info->Size = Entries[i].Size;
                index->FullIndexes[Info->Name] = index->Files.Size();

                uInt FileIndex = index->FileIndexes[Entries[i].Name];
                if(!FileIndex || (strcmp(FullName, index->Files[FileIndex - 1]->Name) < 0))
                    index->FileIndexes[Entries[i].Name] = index->Files.Size();

                result++;
            }
        }

        if(Entries[i].Type & VDF_ENTRY_LAST)
            break;
    }
    return result;
}
Beispiel #8
0
void IQRouterBase::_ReceiveFlits( )
{
	Flit *f;
	bufferMonitor.cycle() ;
	for ( int input = 0; input < _inputs; ++input ) {
		f = (*_input_channels)[input]->Receive();
		if ( f ) {
			++_received_flits[input];
			VC * cur_vc = _vc[input][f->vc];
			if ( cur_vc->GetState( ) == VC::idle ) {
				if ( !f->head ) {
					Error( "Received non-head flit at idle VC" );
				}
				cur_vc->SetState( VC::routing );
				_routing_vcs.push(input*_vcs+f->vc);
			}

			if(f->watch) {
				*gWatchOut << GetSimTime() << " | " << FullName() << " | "
						<< "Adding flit " << f->id
						<< " to VC " << f->vc
						<< " at input " << input
						<< " (state: " << VC::VCSTATE[cur_vc->GetState()];
				if(cur_vc->Empty()) {
					*gWatchOut << ", empty";
				} else {
					assert(cur_vc->FrontFlit());
					*gWatchOut << ", front: " << cur_vc->FrontFlit()->id;
				}
				*gWatchOut << ")." << endl;
				*gWatchOut << GetSimTime() << " | " << FullName() << " | "
						<< "Received flit " << f->id
						<< " from channel at input " << input
						<< "." << endl;
			}
			if ( !cur_vc->AddFlit( f ) ) {
				Error( "VC buffer overflow" );
			}
			bufferMonitor.write( input, f ) ;
		}
	}
}
Beispiel #9
0
void VC::SetState( eVCState s )
{
  Flit * f = FrontFlit();
  
  if(f && f->watch)
    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		<< "Changing state from " << VC::VCSTATE[_state]
		<< " to " << VC::VCSTATE[s] << "." << endl;
  
  _state = s;
}
Beispiel #10
0
void VC::Display( ostream & os ) const
{
  if ( _state != VC::idle ) {
    os << FullName() << ": "
       << " state: " << VCSTATE[_state];
    if(_state == VC::active) {
      os << " out_port: " << _out_port
	 << " out_vc: " << _out_vc;
    }
    os << " fill: " << _buffer.size();
    if(!_buffer.empty()) {
      os << " front: " << _buffer.front()->id;
    }
    os << " pri: " << _pri;
    os << endl;
  }
}
Beispiel #11
0
void IQRouterBase::_SendFlits( )
{
	Flit *f;
	for ( int output = 0; output < _outputs; ++output ) {
		if ( !_output_buffer[output].empty( ) ) {
			f = _output_buffer[output].front( );
			f->from_router = this->GetID();
			_output_buffer[output].pop( );
			++_sent_flits[output];
			if(f->watch)
				*gWatchOut << GetSimTime() << " | " << FullName() << " | "
				<< "Sending flit " << f->id
				<< " to channel at output " << output
				<< "." << endl;
		} else {
			f = 0;
		}
		if(gTrace && f){cout<<"Outport "<<output<<endl;cout<<"Stop Mark"<<endl;}
		(*_output_channels)[output]->Send( f );
	}
}
void IQRouterBaseline::_SWAlloc( )
{
    Flit        *f;
    Credit      *c;

    VC          *cur_vc;
    BufferState *dest_vc;

    int input;
    int output;
    int vc;

    int expanded_input;
    int expanded_output;

    bool        watched = false;

    bool any_nonspec_reqs = false;
    bool any_nonspec_output_reqs[_outputs*_output_speedup];
    memset(any_nonspec_output_reqs, 0, _outputs*_output_speedup*sizeof(bool));

    _sw_allocator->Clear( );
    if ( _speculative >= 2 )
        _spec_sw_allocator->Clear( );

    for ( input = 0; input < _inputs; ++input ) {
        int vc_ready_nonspec = 0;
        int vc_ready_spec = 0;
        for ( int s = 0; s < _input_speedup; ++s ) {
            expanded_input  = s*_inputs + input;

            // Arbitrate (round-robin) between multiple
            // requesting VCs at the same input (handles
            // the case when multiple VC's are requesting
            // the same output port)
            vc = _sw_rr_offset[ expanded_input ];

            for ( int v = 0; v < _vcs; ++v ) {

                // This continue acounts for the interleaving of
                // VCs when input speedup is used
                // dub: Essentially, this skips loop iterations corresponding to those
                // VCs not in the current speedup set. The skipped iterations will be
                // handled in a different iteration of the enclosing loop over 's'.
                if ( ( vc % _input_speedup ) != s ) {
                    vc = ( vc + 1 ) % _vcs;
                    continue;
                }

                cur_vc = _vc[input][vc];

                if(!cur_vc->Empty() &&
                        (cur_vc->GetStateTime() >= _sw_alloc_delay)) {

                    switch(cur_vc->GetState()) {

                    case VC::active:
                    {
                        output = cur_vc->GetOutputPort( );

                        dest_vc = _next_vcs[output];

                        if ( !dest_vc->IsFullFor( cur_vc->GetOutputVC( ) ) ) {

                            // When input_speedup > 1, the virtual channel buffers are
                            // interleaved to create multiple input ports to the switch.
                            // Similarily, the output ports are interleaved based on their
                            // originating input when output_speedup > 1.

                            assert( expanded_input == (vc%_input_speedup)*_inputs + input );
                            expanded_output =
                                (input%_output_speedup)*_outputs + output;

                            if ( ( _switch_hold_in[expanded_input] == -1 ) &&
                                    ( _switch_hold_out[expanded_output] == -1 ) ) {

                                // We could have requested this same input-output pair in a
                                // previous iteration; only replace the previous request if
                                // the current request has a higher priority (this is default
                                // behavior of the allocators).  Switch allocation priorities
                                // are strictly determined by the packet priorities.

                                Flit * f = cur_vc->FrontFlit();
                                assert(f);
                                if(f->watch) {
                                    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                               << "VC " << vc << " at input " << input
                                               << " requested output " << output
                                               << " (non-spec., exp. input: " << expanded_input
                                               << ", exp. output: " << expanded_output
                                               << ", flit: " << f->id
                                               << ", prio: " << cur_vc->GetPriority()
                                               << ")." << endl;
                                    watched = true;
                                }

                                // dub: for the old-style speculation implementation, we
                                // overload the packet priorities to prioritize
                                // non-speculative requests over speculative ones
                                if( _speculative == 1 )
                                    _sw_allocator->AddRequest(expanded_input, expanded_output,
                                                              vc, 1, 1);
                                else
                                    _sw_allocator->AddRequest(expanded_input, expanded_output,
                                                              vc, cur_vc->GetPriority( ),
                                                              cur_vc->GetPriority( ));
                                any_nonspec_reqs = true;
                                any_nonspec_output_reqs[expanded_output] = true;
                                vc_ready_nonspec++;
                            }
                        }
                    }
                    break;


                    //
                    // The following models the speculative VC allocation aspects
                    // of the pipeline. An input VC with a request in for an egress
                    // virtual channel will also speculatively bid for the switch
                    // regardless of whether the VC allocation succeeds. These
                    // speculative requests are handled in a separate allocator so
                    // as to prevent them from interfering with non-speculative bids
                    //
                    case VC::vc_spec:
                    case VC::vc_spec_grant:
                    {
                        assert( _speculative > 0 );
                        assert( expanded_input == (vc%_input_speedup)*_inputs + input );

                        const OutputSet * route_set = cur_vc->GetRouteSet( );
                        const list<OutputSet::sSetElement>* setlist = route_set ->GetSetList();
                        list<OutputSet::sSetElement>::const_iterator iset = setlist->begin( );
                        while(iset!=setlist->end( )) {
                            BufferState * dest_vc = _next_vcs[iset->output_port];
                            bool do_request = false;

                            // check if any suitable VCs are available

                            for ( int out_vc = iset->vc_start; out_vc <= iset->vc_end; ++out_vc ) {
                                int vc_prio = iset->pri;
                                if(!do_request &&
                                        ((_speculative < 3) || dest_vc->IsAvailableFor(out_vc))) {
                                    do_request = true;
                                    break;
                                }
                            }

                            if(do_request) {
                                expanded_output = (input%_output_speedup)*_outputs + iset->output_port;
                                if ( ( _switch_hold_in[expanded_input] == -1 ) &&
                                        ( _switch_hold_out[expanded_output] == -1 ) ) {

                                    Flit * f = cur_vc->FrontFlit();
                                    assert(f);
                                    if(f->watch) {
                                        *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                                   << "VC " << vc << " at input " << input
                                                   << " requested output " << iset->output_port
                                                   << " (spec., exp. input: " << expanded_input
                                                   << ", exp. output: " << expanded_output
                                                   << ", flit: " << f->id
                                                   << ", prio: " << cur_vc->GetPriority()
                                                   << ")." << endl;
                                        watched = true;
                                    }

                                    // dub: for the old-style speculation implementation, we
                                    // overload the packet priorities to prioritize non-
                                    // speculative requests over speculative ones
                                    if( _speculative == 1 )
                                        _sw_allocator->AddRequest(expanded_input, expanded_output,
                                                                  vc, 0, 0);
                                    else
                                        _spec_sw_allocator->AddRequest(expanded_input,
                                                                       expanded_output, vc,
                                                                       cur_vc->GetPriority( ),
                                                                       cur_vc->GetPriority( ));
                                    vc_ready_spec++;
                                }
                            }
                            iset++;
                        }
                    }
                    break;
                    }
                }
                vc = ( vc + 1 ) % _vcs;
            }
        }
    }

    if(watched) {
        *gWatchOut << GetSimTime() << " | " << _sw_allocator->FullName() << " | ";
        _sw_allocator->PrintRequests( gWatchOut );
        if(_speculative >= 2) {
            *gWatchOut << GetSimTime() << " | " << _spec_sw_allocator->FullName() << " | ";
            _spec_sw_allocator->PrintRequests( gWatchOut );
        }
    }

    _sw_allocator->Allocate();
    if(_speculative >= 2)
        _spec_sw_allocator->Allocate();

    // Winning flits cross the switch

    _crossbar_pipe->WriteAll( 0 );

    //////////////////////////////
    // Switch Power Modelling
    //  - Record Total Cycles
    //
    switchMonitor.cycle() ;

    for ( int input = 0; input < _inputs; ++input ) {
        c = 0;

        int vc_grant_nonspec = 0;
        int vc_grant_spec = 0;

        for ( int s = 0; s < _input_speedup; ++s ) {

            bool use_spec_grant = false;

            expanded_input  = s*_inputs + input;

            if ( _switch_hold_in[expanded_input] != -1 ) {
                assert(_switch_hold_in[expanded_input] >= 0);
                expanded_output = _switch_hold_in[expanded_input];
                vc = _switch_hold_vc[expanded_input];
                assert(vc >= 0);
                cur_vc = _vc[input][vc];

                if ( cur_vc->Empty( ) ) { // Cancel held match if VC is empty
                    expanded_output = -1;
                }
            } else {
                expanded_output = _sw_allocator->OutputAssigned( expanded_input );
                if ( ( _speculative >= 2 ) && ( expanded_output < 0 ) ) {
                    expanded_output = _spec_sw_allocator->OutputAssigned(expanded_input);
                    if ( expanded_output >= 0 ) {
                        assert(_spec_sw_allocator->InputAssigned(expanded_output) >= 0);
                        assert(_spec_sw_allocator->ReadRequest(expanded_input, expanded_output) >= 0);
                        switch ( _filter_spec_grants ) {
                        case 0:
                            if ( any_nonspec_reqs )
                                expanded_output = -1;
                            break;
                        case 1:
                            if ( any_nonspec_output_reqs[expanded_output] )
                                expanded_output = -1;
                            break;
                        case 2:
                            if ( _sw_allocator->InputAssigned(expanded_output) >= 0 )
                                expanded_output = -1;
                            break;
                        default:
                            assert(false);
                        }
                    }
                    use_spec_grant = (expanded_output >= 0);
                }
            }

            if ( expanded_output >= 0 ) {
                output = expanded_output % _outputs;

                if ( _switch_hold_in[expanded_input] == -1 ) {
                    if(use_spec_grant) {
                        assert(_spec_sw_allocator->OutputAssigned(expanded_input) >= 0);
                        assert(_spec_sw_allocator->InputAssigned(expanded_output) >= 0);
                        vc = _spec_sw_allocator->ReadRequest(expanded_input,
                                                             expanded_output);
                    } else {
                        assert(_sw_allocator->OutputAssigned(expanded_input) >= 0);
                        assert(_sw_allocator->InputAssigned(expanded_output) >= 0);
                        vc = _sw_allocator->ReadRequest(expanded_input, expanded_output);
                    }
                    assert(vc >= 0);
                    cur_vc = _vc[input][vc];
                }

                // Detect speculative switch requests which succeeded when VC
                // allocation failed and prevenet the switch from forwarding;
                // also, in case the routing function can return multiple outputs,
                // check to make sure VC allocation and speculative switch allocation
                // pick the same output port.
                if ( ( ( cur_vc->GetState() == VC::vc_spec_grant ) ||
                        ( cur_vc->GetState() == VC::active ) ) &&
                        ( cur_vc->GetOutputPort() == output ) ) {

                    if(use_spec_grant) {
                        vc_grant_spec++;
                    } else {
                        vc_grant_nonspec++;
                    }

                    if ( _hold_switch_for_packet ) {
                        _switch_hold_in[expanded_input] = expanded_output;
                        _switch_hold_vc[expanded_input] = vc;
                        _switch_hold_out[expanded_output] = expanded_input;
                    }

                    assert((cur_vc->GetState() == VC::vc_spec_grant) ||
                           (cur_vc->GetState() == VC::active));
                    assert(!cur_vc->Empty());
                    assert(cur_vc->GetOutputPort() == output);

                    dest_vc = _next_vcs[output];

                    if ( dest_vc->IsFullFor( cur_vc->GetOutputVC( ) ) )
                        continue ;

                    // Forward flit to crossbar and send credit back
                    f = cur_vc->RemoveFlit( );
                    assert(f);
                    if(f->watch) {
                        *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                   << "Output " << output
                                   << " granted to VC " << vc << " at input " << input;
                        if(cur_vc->GetState() == VC::vc_spec_grant)
                            *gWatchOut << " (spec";
                        else
                            *gWatchOut << " (non-spec";
                        *gWatchOut << ", exp. input: " << expanded_input
                                   << ", exp. output: " << expanded_output
                                   << ", flit: " << f->id << ")." << endl;
                    }

                    f->hops++;

                    //
                    // Switch Power Modelling
                    //
                    switchMonitor.traversal( input, output, f) ;
                    bufferMonitor.read(input, f) ;

                    if(f->watch)
                        *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                   << "Forwarding flit " << f->id << " through crossbar "
                                   << "(exp. input: " << expanded_input
                                   << ", exp. output: " << expanded_output
                                   << ")." << endl;

                    if ( !c ) {
                        c = _NewCredit( _vcs );
                    }

                    assert(vc == f->vc);

                    c->vc[c->vc_cnt] = f->vc;
                    c->vc_cnt++;
                    c->dest_router = f->from_router;
                    f->vc = cur_vc->GetOutputVC( );
                    dest_vc->SendingFlit( f );

                    _crossbar_pipe->Write( f, expanded_output );

                    if(f->tail) {
                        if(cur_vc->Empty()) {
                            cur_vc->SetState(VC::idle);
                        } else if(_routing_delay > 0) {
                            cur_vc->SetState(VC::routing);
                            _routing_vcs.push(input*_vcs+vc);
                        } else {
                            cur_vc->Route(_rf, this, cur_vc->FrontFlit(), input);
                            cur_vc->SetState(VC::vc_alloc);
                            _vcalloc_vcs.insert(input*_vcs+vc);
                        }
                        _switch_hold_in[expanded_input]   = -1;
                        _switch_hold_vc[expanded_input]   = -1;
                        _switch_hold_out[expanded_output] = -1;
                    } else {
                        // reset state timer for next flit
                        cur_vc->SetState(VC::active);
                    }

                    _sw_rr_offset[expanded_input] = ( vc + 1 ) % _vcs;
                } else {
                    assert(cur_vc->GetState() == VC::vc_spec);
                    Flit * f = cur_vc->FrontFlit();
                    assert(f);
                    if(f->watch)
                        *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                   << "Speculation failed at output " << output
                                   << "(exp. input: " << expanded_input
                                   << ", exp. output: " << expanded_output
                                   << ", flit: " << f->id << ")." << endl;
                }
            }
        }

        // Promote all other virtual channel grants marked as speculative to active.
        for ( int vc = 0 ; vc < _vcs ; vc++ ) {
            cur_vc = _vc[input][vc] ;
            if ( cur_vc->GetState() == VC::vc_spec_grant ) {
                cur_vc->SetState( VC::active ) ;
            }
        }

        _credit_pipe->Write( c, input );
    }
}
void ChaosRouter::_OutputAdvance( )
{
  Flit *f, *f2;
  Credit *c;
  bool advanced;
  int  mq;

  _crossbar_pipe->WriteAll( 0 );

  for ( int i = 0; i < _inputs; ++i ) {
    if ( ( ( _input_output_match[i] != -1 ) ||
	   ( _input_mq_match[i] != -1 ) ) &&
	 ( !_input_frame[i].empty( ) ) ) {
      
      advanced = false;
      f = _input_frame[i].front( );

      /*if ( ! ) {

      } else {
	cout << "Input = " << i 
	     << ", input_output_match = " << _input_output_match[i]
	     << ", input_mq_match = " << _input_mq_match[i] << endl;
	Error( "Input queue empty, but matched!" );
	}*/

      if ( _input_output_match[i] != -1 ) {
	if ( f->tail ) {
	  _output_matched[_input_output_match[i]] = false;
	}

	_crossbar_pipe->Write( f, _input_output_match[i] );
	
	if ( f->watch ) {
	  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		      << "Flit traversing crossbar from input queue " 
		      << i << " at " 
		      << FullName() << endl
		      << *f;
	}

	advanced = true;

      } else if ( !_MultiQueueFull( _input_mq_match[i] ) ) {

	mq = _input_mq_match[i];

	if ( f->head ) {
	  _rf( this, f, i, _mq_route[mq], false );
	  _mq_age[mq] = 0;

	  if ( _multi_state[mq] == empty ) {
	    _multi_state[mq] = filling;
	  } else if ( _multi_state[mq] == leaving ) {
	    _multi_state[mq] = shared;
	  } else {
	    Error( "Multi-queue received head while not empty or leaving!" );
	  }
	}
	
	if ( f->tail ) {
	  _mq_matched[mq] = false;

	  if ( _multi_state[mq] == filling ) {
	    _multi_state[mq] = full;
	  } else if ( _multi_state[mq] == cut_through ) {
	    _multi_state[mq] = leaving; 
	  } else {
	    Error( "Multi-queue received tail while not filling or cutting-through!" );
	  }
	}
	
	_multi_queue[mq].push( f );
	
	if ( f->watch ) {
	  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		      << "Flit stored in multiqueue at " 
		      << FullName() << endl
		      << "State = " << _multi_state[mq] << endl
		      << *f;
	}

	advanced = true;
      }

      if ( advanced ) {
	_input_frame[i].pop( );

	if ( f->tail ) { // last in packet, update state
	  if ( _input_state[i] == leaving ) {
	    _input_state[i] = empty;
	  } else if ( _input_state[i] == shared ) {
	    _input_state[i] = filling;
	    f2 = _input_frame[i].front( );
	    // update routes
	    _rf( this, f2, i, _input_route[i], false );
	  }
	  
	  _input_output_match[i] = -1;
	  _input_mq_match[i]     = -1;
	}
	
	c = Credit::New( );
	c->vc.insert(0);
	_credit_queue[i].push( c );
      }
    }
  }

  for ( int m = 0; m < _multi_queue_size; ++m ) {
    if ( _multi_match[m] != -1 ) {
      if ( !_multi_queue[m].empty( ) ) {
	f = _multi_queue[m].front( );
	_multi_queue[m].pop( );
      } else {
	cout << "State = " << _multi_state[m] << endl;
	Error( "Multi queue empty, but matched!" );
      }

      _crossbar_pipe->Write( f, _multi_match[m] );

      if ( f->watch ) {
	*gWatchOut << GetSimTime() << " | " << FullName() << " | "
		    << "Flit traversing crossbar from multiqueue slot "
		    << m << " at " 
		    << FullName() << endl
		    << *f;
      }

      if ( f->head ) {
	if ( _multi_state[m] == filling ) {
	  _multi_state[m] = cut_through;
	} else if ( _multi_state[m] == full ) {
	  _multi_state[m] = leaving;
	} else {
	  Error( "Multi-queue sent head while not filling or full!" );
	}
      }

      if ( f->tail ) {
	_output_matched[_multi_match[m]] = false;
	_multi_match[m] = -1;

	if ( _multi_state[m] == shared ) {
	  _multi_state[m] = filling;
	} else if ( _multi_state[m] == leaving ) {
	  _multi_state[m] = empty;
	} else {
	  cout << "State = " << _multi_state[m] << endl;
	  cout << *f;
	  Error( "Multi-queue sent tail while not leaving or shared!" );
	}
      }
    }

    _mq_age[m]++;
  }
}
bool ShaderProgram::Link()
{
    PROFILE(LinkShaderProgram);

    Release();

    if (!graphics || !graphics->IsInitialized())
    {
        LOGERROR("Can not link shader program without initialized Graphics subsystem");
        return false;
    }
    if (!vs || !ps)
    {
        LOGERROR("Shader(s) are null, can not link shader program");
        return false;
    }
    if (!vs->GLShader() || !ps->GLShader())
    {
        LOGERROR("Shaders have not been compiled, can not link shader program");
        return false;
    }

    const String& vsSourceCode = vs->Parent() ? vs->Parent()->SourceCode() : String::EMPTY;
    const String& psSourceCode = ps->Parent() ? ps->Parent()->SourceCode() : String::EMPTY;

    program = glCreateProgram();
    if (!program)
    {
        LOGERROR("Could not create shader program");
        return false;
    }

    glAttachShader(program, vs->GLShader());
    glAttachShader(program, ps->GLShader());
    glLinkProgram(program);

    int linked;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if (!linked)
    {
        int length, outLength;
        String errorString;

        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
        errorString.Resize(length);
        glGetProgramInfoLog(program, length, &outLength, &errorString[0]);
        glDeleteProgram(program);
        program = 0;

        LOGERRORF("Could not link shaders %s: %s", FullName().CString(), errorString.CString());
        return false;
    }

    LOGDEBUGF("Linked shaders %s", FullName().CString());

    glUseProgram(program);

    char nameBuffer[MAX_NAME_LENGTH];
    int numAttributes, numUniforms, numUniformBlocks, nameLength, numElements;
    GLenum type;

    attributes.Clear();

    glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttributes);
    for (int i = 0; i < numAttributes; ++i)
    {
        glGetActiveAttrib(program, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, &numElements, &type, nameBuffer);

        VertexAttribute newAttribute;
        newAttribute.name = String(nameBuffer, nameLength);
        newAttribute.semantic = SEM_POSITION;
        newAttribute.index = 0;

        for (size_t j = 0; elementSemanticNames[j]; ++j)
        {
            if (newAttribute.name.StartsWith(elementSemanticNames[j], false))
            {
                int index = NumberPostfix(newAttribute.name);
                if (index >= 0)
                    newAttribute.index = (unsigned char)index;
                break;
            }
            newAttribute.semantic = (ElementSemantic)(newAttribute.semantic + 1);
        }

        if (newAttribute.semantic == MAX_ELEMENT_SEMANTICS)
        {
            LOGWARNINGF("Found vertex attribute %s with no known semantic in shader program %s", newAttribute.name.CString(), FullName().CString());
            continue;
        }

        newAttribute.location = glGetAttribLocation(program, newAttribute.name.CString());
        attributes.Push(newAttribute);
    }

    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms);
    int numTextures = 0;
    for (int i = 0; i < numUniforms; ++i)
    {
        glGetActiveUniform(program, i, MAX_NAME_LENGTH, &nameLength, &numElements, &type, nameBuffer);

        String name(nameBuffer, nameLength);
        if (type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_SHADOW)
        {
            // Assign sampler uniforms to a texture unit according to the number appended to the sampler name
            int location = glGetUniformLocation(program, name.CString());
            int unit = NumberPostfix(name);
            // If no unit number specified, assign in appearance order starting from unit 0
            if (unit < 0)
                unit = numTextures;

            // Array samplers may have multiple elements, assign each sequentially
            if (numElements > 1)
            {
                Vector<int> units;
                for (int j = 0; j < numElements; ++j)
                    units.Push(unit++);
                glUniform1iv(location, numElements, &units[0]);
            }
            else
                glUniform1iv(location, 1, &unit);

            numTextures += numElements;
        }
    }

    glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
    for (int i = 0; i < numUniformBlocks; ++i)
    {
        glGetActiveUniformBlockName(program, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, nameBuffer);

        // Determine whether uniform block belongs to vertex or pixel shader
        String name(nameBuffer, nameLength);
        bool foundVs = vsSourceCode.Contains(name);
        bool foundPs = psSourceCode.Contains(name);
        if (foundVs && foundPs)
        {
            LOGWARNINGF("Found uniform block %s in both vertex and pixel shader in shader program %s");
            continue;
        }

        // Vertex shader constant buffer bindings occupy slots starting from zero to maximum supported, pixel shader bindings
        // from that point onward
        unsigned blockIndex = glGetUniformBlockIndex(program, name.CString());

        int bindingIndex = NumberPostfix(name);
        // If no number postfix in the name, use the block index
        if (bindingIndex < 0)
            bindingIndex = blockIndex;
        if (foundPs)
            bindingIndex += (unsigned)graphics->NumVSConstantBuffers();

        glUniformBlockBinding(program, blockIndex, bindingIndex);
    }

    return true;
}
Beispiel #15
0
// ----------------------------------------------------------------------------
// TreeNode implementation
// ----------------------------------------------------------------------------
bool RegTreeCtrl::TreeNode::OnExpand()
{
    // we add children only once
    if ( !m_aChildren.IsEmpty() )
    {
        // we've been already expanded
        return true;
    }

    if ( IsRoot() )
    {
        // we're the root key
        m_pTree->AddStdKeys();
        return true;
    }

    if ( Parent()->IsRoot() )
    {
        // we're a standard key
        m_pKey = new wxRegKey(m_strName, m_viewMode);
    }
    else
    {
        // we're a normal key
        m_pKey = new wxRegKey(*(Parent()->m_pKey), m_strName);
    }

    if ( !m_pKey->Open() )
    {
        wxLogError(wxT("The key '%s' can't be opened."), FullName());
        return false;
    }

    // if we're empty, we shouldn't be expandable at all
    bool isEmpty = true;

    // enumeration variables
    long l;
    wxString str;
    bool bCont;

    // enumerate all subkeys
    bCont = m_pKey->GetFirstKey(str, l);
#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
    while ( bCont )
    {
        m_pTree->InsertNewTreeNode(
            this,
            str,
            RegImageList::ClosedKey,
            NULL,
            m_viewMode);
        bCont = m_pKey->GetNextKey(str, l);

        // we have at least this key...
        isEmpty = false;
    }

    // enumerate all values
    bCont = m_pKey->GetFirstValue(str, l);
#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
    while ( bCont )
    {
        wxString strItem;
        if (str.empty())
            strItem = wxT("<default>");
        else
            strItem = str;
        strItem += wxT(" = ");

        // determine the appropriate icon
        RegImageList::Icon icon;
        switch ( m_pKey->GetValueType(str) )
        {
        case wxRegKey::Type_String:
        case wxRegKey::Type_Expand_String:
        case wxRegKey::Type_Multi_String:
        {
            wxString strValue;
            icon = RegImageList::TextValue;
            m_pKey->QueryValue(str, strValue);
            strItem += strValue;
        }
        break;

        case wxRegKey::Type_None:
            // @@ handle the error...
            icon = RegImageList::BinaryValue;
            break;

        case wxRegKey::Type_Dword:
        {
            long l;
            m_pKey->QueryValue(str, &l);
            strItem << l;
        }

        // fall through

        default:
            icon = RegImageList::BinaryValue;
        }

        m_pTree->InsertNewTreeNode(this, str, icon, &strItem, m_viewMode);
        bCont = m_pKey->GetNextValue(str, l);

        // we have at least this value...
        isEmpty = false;
    }

    if ( isEmpty )
    {
        // this is for the case when our last child was just deleted
        wxTreeItemId theId(Id()); // Temp variable seems necessary for BC++
        m_pTree->Collapse(theId);

        // we won't be expanded any more
        m_pTree->SetItemHasChildren(theId, false);
    }

    return true;
}
void ChaosRouter::ReadInputs( )
{
  Flit   *f;
  Credit *c;

  for ( int input = 0; input < _inputs; ++input ) { 
    f = _input_channels[input]->Receive();

    if ( f ) {
      _input_frame[input].push( f );

      if ( f->watch ) {
	*gWatchOut << GetSimTime() << " | " << FullName() << " | "
		    << "Flit arriving at " << FullName() 
		    << " on channel " << input << endl
		    << *f;
      }

      switch( _input_state[input] ) {
      case empty:
	if ( f->head ) {
	  if ( f->tail ) {
	    _input_state[input] = full;
	  } else {
	    _input_state[input] = filling;
	  }
	  _rf( this, f, input, _input_route[input], false );
	} else {
	  cout << *f;
	  Error( "Empty buffer received non-head flit!" );
	}
	break;

      case filling:
	if ( f->tail ) {
	  _input_state[input] = full;
	} else if ( f->head ) {
	  Error( "Input buffer received another head before previous tail!" );
	}
	break;
	
      case full:
	Error( "Received flit while full!" );
	break;

      case leaving:
	if ( f->head ) {
	  _input_state[input] = shared;

	  if ( f->tail ) {
	    Error( "Received single-flit packet in leaving state!" );
	  }
	} else {
	  cout << *f;
	  Error( "Received non-head flit while packet leaving!" );
	}
	break;

      case cut_through:
	if ( f->tail ) {
	  _input_state[input] = leaving;
	} 
	if ( f->head ) {
	  cout << *f;
	  Error( "Received head flit in cut through buffer!" );
	}
	break;

      case shared:
	if ( f->head ) {
	  Error( "Shared buffer received another head!" );
	} else if ( f->tail ) {
	  cout << "Input " << input << endl;
	  cout << *f;
	  Error( "Shared buffer received another tail!" );
	}
	break;
      }
    }
  }

  // Process incoming credits

  for ( int output = 0; output < _outputs; ++output ) {
    c = _output_credits[output]->Receive();
    
    if ( c ) {
      _next_queue_cnt[output]--;

      if ( _next_queue_cnt[output] < 0 ) {
	Error( "Next queue count fell below zero!" );
      }

      c->Free();
    }
  }
}
Beispiel #17
0
void IQRouterSplit::_Alloc( )
{
  bool watched = false;
  int fast_path_vcs[_inputs];
  _sw_allocator->Clear( );
  
  for(int input = 0; input < _inputs; ++input) {
    
    fast_path_vcs[input] = -1;
    
    for(int s = 0; s < _input_speedup; ++s) {
      int expanded_input  = s*_inputs + input;
      
      // Arbitrate (round-robin) between multiple requesting VCs at the same 
      // input (handles the case when multiple VC's are requesting the same 
      // output port)
      int vc = _sw_rr_offset[expanded_input];
      
      for(int v = 0; v < _vcs; ++v) {
	
	// This continue acounts for the interleaving of VCs when input speedup 
	// is used.
	// dub: Essentially, this skips loop iterations corresponding to those 
	// VCs not in the current speedup set. The skipped iterations will be 
	// handled in a different iteration of the enclosing loop over 's'.
	// dub: Furthermore, we skip this iteration if the current VC has only a
	// single, newly arrived flit.
	if(((vc % _input_speedup) != s) || _use_fast_path[input*_vcs+vc]) {
	  vc = (vc + 1) % _vcs;
	  continue;
	}
	
	VC * cur_vc = _vc[input][vc];
	
	VC::eVCState vc_state = cur_vc->GetState();
	
	if(cur_vc->FrontFlit() && cur_vc->FrontFlit()->watch) 
	  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		      << "Saw flit " << cur_vc->FrontFlit()->id
		      << " in slow path." << endl;
	
	if(!cur_vc->Empty()) {
	  
	  Flit * f = cur_vc->FrontFlit();
	  assert(f);
	  
	  if(((vc_state != VC::vc_alloc) && (vc_state != VC::active)) ||
	     (cur_vc->GetStateTime() < _sw_alloc_delay)) {
	    if(f->watch)
	      *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			  << "VC " << vc << " at input " << input 
			  << " is not ready for slow-path allocation (flit: " << f->id 
			  << ", state: " << VC::VCSTATE[vc_state] 
			  << ", state time: " << cur_vc->GetStateTime() 
			  << ")." << endl;
	    vc = (vc + 1) % _vcs;
	    continue;
	  }	    
	  
	  if(f->watch)
	    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			<< "VC " << vc << " at input " << input
			<< " is requesting slow-path allocation (flit: " << f->id 
			<< ", state: " << VC::VCSTATE[vc_state]
			<< ")." << endl;
	  
	  const OutputSet * route_set = cur_vc->GetRouteSet();
	  
	  int output = _vc_rr_offset[input*_vcs+vc];
	  
	  for(int output_index = 0; output_index < _outputs; ++output_index) {
	    
	    // in active state, we only care about our assigned output port
	    if(vc_state == VC::active) {
	      output = cur_vc->GetOutputPort();
	    }
	    
	    // When input_speedup > 1, the virtual channel buffers are 
	    // interleaved to create multiple input ports to the switch.
	    // Similarily, the output ports are interleaved based on their 
	    // originating input when output_speedup > 1.
	    
	    assert(expanded_input == (vc%_input_speedup)*_inputs+input);
	    int expanded_output = (input%_output_speedup)*_outputs + output;
	    
	    if((_switch_hold_in[expanded_input] == -1) && 
	       (_switch_hold_out[expanded_output] == -1)) {
	      
	      BufferState * dest_vc = _next_vcs[output];
	      
	      bool do_request = false;
	      int in_priority;
	      
	      // check if any suitable VCs are available and determine the 
	      // highest priority for this port
	      int vc_cnt = route_set->NumVCs(output);
	      assert(!((vc_state == VC::active) && (vc_cnt == 0)));
	      
	      for(int vc_index = 0; vc_index < vc_cnt; ++vc_index) {
		int vc_prio;
		int out_vc = route_set->GetVC(output, vc_index, &vc_prio);
		
		if((vc_state == VC::vc_alloc) &&
		   !dest_vc->IsAvailableFor(out_vc)) {
		  if(f->watch)
		    *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
				<< "VC " << out_vc << " at output "
				<< output << " is busy." << endl;
		  continue;
		} else if((vc_state == VC::active) && 
			  (out_vc != cur_vc->GetOutputVC())) {
		  continue;
		}
		
		if(dest_vc->IsFullFor(out_vc)) {
		  if(f->watch)
		    *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
				<< "VC " << out_vc << " at output "
				<< output << " has no buffers available." << endl;
		  continue;
		}
		
		if(f->watch)
		  *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			      << "VC " << out_vc << " at output "
			      << output << " is available." << endl;
		if(!do_request || (vc_prio > in_priority)) {
		  do_request = true;
		  in_priority = vc_prio;
		}
	      }
	      
	      if(do_request) {
		
		if(f->watch) {
		  *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			      << "VC " << vc << " at input "
			      << input << " requests output " << output 
			      << " (flit: " << f->id
			      << ", exp. input: " << expanded_input
			      << ", exp. output: " << expanded_output
			      << ")." << endl;
		  watched = true;
		}
		
		// We could have requested this same input-output pair in a 
		// previous iteration; only replace the previous request if the 
		// current request has a higher priority (this is default 
		// behavior of the allocators). Switch allocation priorities 
		// are strictly determined by the packet priorities.
		
		_sw_allocator->AddRequest(expanded_input, expanded_output, vc, 
					  in_priority, cur_vc->GetPriority());
		
	      }
	    }

	    // in active state, we only care about our assigned output port
	    if(vc_state == VC::active) {
	      break;
	    }
	    
	    output = (output + 1) % _outputs;
	  }
	}
	vc = (vc + 1) % _vcs;
      }
    }
    
    // dub: handle fast-path flits separately so we know all switch requests 
    // from other VCs that are on the regular path have been issued already
    for(int vc = 0; vc < _vcs; vc++) {
      
      if(_use_fast_path[input*_vcs+vc]) {
	
	VC * cur_vc = _vc[input][vc];
	
	if(cur_vc->Empty()) {
	  continue;
	}
	
	Flit * f = cur_vc->FrontFlit();
	assert(f);
	
	if(f->watch)
	  *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
		      << "Saw flit " << f->id
		      << " in fast path." << endl;
	
	VC::eVCState vc_state = cur_vc->GetState();
	
	if(((vc_state != VC::vc_alloc) && (vc_state != VC::active)) ||
	   (cur_vc->GetStateTime() < _sw_alloc_delay)) {
	  if(f->watch)
	    *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			<< "VC " << vc << " at input " << input 
			<< " is not ready for fast-path allocation (flit: " << f->id 
			<< ", state: " << VC::VCSTATE[vc_state] 
			<< ", state time: " << cur_vc->GetStateTime() 
			<< ")." << endl;
	  continue;
	}	    
	
	if(f->watch)
	  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		      << "VC " << vc << " at input " << input
		      << " is requesting fast-path allocation (flit: " << f->id 
		      << ", state: " << VC::VCSTATE[vc_state]
		      << ")." << endl;
	
	if(fast_path_vcs[input] >= 0)
	  cout << "XXX" << endl
	       << FullName() << endl
	       << "VC: " << vc << ", input: " << input << ", flit: " << f->id
	       << ", fast VC: " << fast_path_vcs[input] << ", fast flit: "
	       << _vc[input][fast_path_vcs[input]]->FrontFlit()->id << endl
	       << "XXX" << endl;
	assert(fast_path_vcs[input] < 0);
	
	fast_path_vcs[input] = vc;
	
	const OutputSet * route_set = cur_vc->GetRouteSet();
	int expanded_input = (vc%_input_speedup)*_inputs+input;
	
	for(int output = 0; output < _outputs; ++output) {
	  
	  // dub: if we're done with VC allocation, we already know our output
	  if(vc_state == VC::active) {
	    output = cur_vc->GetOutputPort();
	  }
	  
	  BufferState * dest_vc = _next_vcs[output];
	  
	  int expanded_output = (input%_output_speedup)*_outputs + output;
	  
	  if(_sw_allocator->ReadRequest(expanded_input, expanded_output) >= 0) {
	    if(f->watch)
	      *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			  << "Crossbar slot is already in use by slow path "
			  << "(exp. input: " << expanded_input
			  << ", exp. output: " << expanded_output
			  << ")." << endl;
	    if(vc_state == VC::active) {
	      break;
	    } else {
	      continue;
	    }
	  }
	  
	  bool do_request = false;
	  int in_priority;
	  
	  int vc_cnt = route_set->NumVCs(output);
	  assert((vc_state != VC::active) || (vc_cnt > 0));
	  
	  for(int vc_index = 0; vc_index < vc_cnt; ++vc_index) {
	    int vc_prio;
	    int out_vc = route_set->GetVC(output, vc_index, &vc_prio);
	    
	    if((vc_state == VC::vc_alloc) && 
	       !dest_vc->IsAvailableFor(out_vc)) {
	      if(f->watch)
		*gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			    << "VC " << out_vc << " at output "
			    << output << " is busy." << endl;
	      continue;
	    } else if((vc_state == VC::active) && 
		      (out_vc != cur_vc->GetOutputVC())) {
	      continue;
	    }
	    
	    if(dest_vc->IsFullFor(out_vc)) {
	      if(f->watch)
		*gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			    << "VC " << out_vc << " at output "
			    << output << " has no buffers available." << endl;
	      continue;
	    }
	    
	    if(f->watch)
	      *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			  << "VC " << out_vc << " at output "
			  << output << " is available." << endl;
	    if(!do_request || (vc_prio > in_priority)) {
	      do_request = true;
	      in_priority = vc_prio;
	    }	    
	  }
	  
	  if(do_request) {
	    
	    if(f->watch)
	      *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			  << "VC " << vc << " at input "
			  << input << " requests output " << output 
			  << " (flit: " << f->id
			  << ", exp. input: " << expanded_input
			  << ", exp. output: " << expanded_output
			  << ")." << endl;
	    
	    // We could have requested this same input-output pair in a 
	    // previous iteration; only replace the previous request if the 
	    // current request has a higher priority (this is default 
	    // behavior of the allocators). Switch allocation priorities 
	    // are strictly determined by the packet priorities.
	    
	    _sw_allocator->AddRequest(expanded_input, expanded_output, vc, 
				      in_priority, cur_vc->GetPriority());
	    
	  }
	  
	  if(vc_state == VC::active) {
	    break;
	  }
	}
      }
    }
  }
  
  if(watched) {
    *gWatchOut << GetSimTime() << " | " << _sw_allocator->FullName() << " | ";
    _sw_allocator->PrintRequests(gWatchOut);
  }
  
  _sw_allocator->Allocate();
  
  if(watched) {
    *gWatchOut << GetSimTime() << " | " << _sw_allocator->FullName() << " | "
		<< "Grants = [ ";
    for(int input = 0; input < _inputs; ++input)
      for(int s = 0; s < _input_speedup; ++s) {
	int expanded_input = s * _inputs + input;
	int expanded_output = _sw_allocator->OutputAssigned(expanded_input);
	if(expanded_output > -1) {
	  int output = expanded_output % _outputs;
	  int vc = _sw_allocator->ReadRequest(expanded_input, expanded_output);
	  *gWatchOut << input << " -> " << output << " (vc:" << vc << ")  ";
	}
      }
    *gWatchOut << "]." << endl;
  }
  
  // Winning flits cross the switch

  _crossbar_pipe->WriteAll(NULL);

  //////////////////////////////
  // Switch Power Modelling
  //  - Record Total Cycles
  //
  switchMonitor.cycle() ;

  for(int input = 0; input < _inputs; ++input) {
    
    Credit * c = NULL;
    
    for(int s = 0; s < _input_speedup; ++s) {
      
      int expanded_input = s*_inputs + input;
      int expanded_output;
      VC * cur_vc;
      int vc;
      int fvc = fast_path_vcs[input];
      
      if(_switch_hold_in[expanded_input] != -1) {
	assert(_switch_hold_in[expanded_input] >= 0);
	expanded_output = _switch_hold_in[expanded_input];
	vc = _switch_hold_vc[expanded_input];
	cur_vc = _vc[input][vc];
	
	if(cur_vc->Empty()) { // Cancel held match if VC is empty
	  expanded_output = -1;
	}
      } else {
	expanded_output = _sw_allocator->OutputAssigned(expanded_input);
	if(expanded_output >= 0) {
	  vc = _sw_allocator->ReadRequest(expanded_input, expanded_output);
	  cur_vc = _vc[input][vc];
	} else {
	  vc = -1;
	  cur_vc = NULL;
	}
      }
      
      if(expanded_output >= 0) {
	
	int output = expanded_output % _outputs;
	
	Flit * f = cur_vc->FrontFlit();
	assert(f);
	
	if(vc == fvc) {
	  if(f->watch)
	    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			<< "Fast-path allocation successful for VC " << vc
			<< " at input " << input << " (flit: " << f->id
			<< ")." << endl;
	} else {
	  if(f->watch)
	    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			<< "Slow-path allocation successful for VC " << vc
			<< " at input " << input << " (flit: " << f->id
			<< ")." << endl;
	  if(fvc >= 0) {
	    assert(_use_fast_path[input*_vcs+fvc]);
	    VC * fast_vc = _vc[input][fvc];
	    assert(fast_vc->FrontFlit());
	    if(fast_vc->FrontFlit()->watch)
	      cout << GetSimTime() << " | " << FullName() << " | "
		   << "Disabling fast-path allocation for VC " << fvc
		   << " at input " << input << "." << endl;
	    _use_fast_path[input*_vcs+fvc] = false;
	  }
	}
	
	BufferState * dest_vc = _next_vcs[output];
	
	switch(cur_vc->GetState()) {
	  
	case VC::vc_alloc:
	  {
	    const OutputSet * route_set = cur_vc->GetRouteSet();
	    int sel_prio = -1;
	    int sel_vc = -1;
	    int vc_cnt = route_set->NumVCs(output);
	    
	    for(int vc_index = 0; vc_index < vc_cnt; ++vc_index) {
	      int out_prio;
	      int out_vc = route_set->GetVC(output, vc_index, &out_prio);
	      if(!dest_vc->IsAvailableFor(out_vc)) {
		if(f->watch)
		  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			      << "VC " << out_vc << " at output "
			      << output << " is busy." << endl;
		continue;
	      }
	      if(dest_vc->IsFullFor(out_vc)) {
		if(f->watch)
		  *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			      << "VC " << out_vc << " at output "
			      << output << " has no buffers available." << endl;
		continue;
	      }
	      
	      if(f->watch)
		*gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			    << "VC " << out_vc << " at output "
			    << output << " is available." << endl;
	      if(out_prio > sel_prio) {
		sel_vc = out_vc;
		sel_prio = out_prio;
	      }
	    }
	    
	    if(sel_vc < 0) {
	      cout << "XXX" << endl
		   << "Flit " << f->id
		   << ", VC " << vc
		   << ", input " << input << ":" << endl
		   << "None of " << vc_cnt << " VCs at output " << output 
		   << " were suitable and available." << endl 
		   << "XXX" << endl;
	    }
	    // we should only get to this point if some VC requested 
	    // allocation
	    assert(sel_vc > -1);
	    
	    // dub: this is taken care of later on
	    //cur_vc->SetState(VC::active);
	    cur_vc->SetOutput(output, sel_vc);
	    dest_vc->TakeBuffer(sel_vc);
	    
	    _vc_rr_offset[input*_vcs+vc] = (output + 1) % _outputs;
	    
	    if(f->watch)
	      *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			  << "VC " << sel_vc << " at output " << output
			  << " granted to VC " << vc << " at input " << input
			  << " (flit: " << f->id << ")." << endl;
	  }
	  // NOTE: from here, we just fall through to the code for VC::active!
	  
	case VC::active:
	  
	  if(_hold_switch_for_packet) {
	    _switch_hold_in[expanded_input] = expanded_output;
	    _switch_hold_vc[expanded_input] = vc;
	    _switch_hold_out[expanded_output] = expanded_input;
	  }
	  
	  //assert(cur_vc->GetState() == VC::active);
	  assert(!cur_vc->Empty());
	  assert(cur_vc->GetOutputPort() == output);
	  
	  dest_vc = _next_vcs[output];
	  
	  assert(!dest_vc->IsFullFor(cur_vc->GetOutputVC()));
	  
	  // Forward flit to crossbar and send credit back
	  f = cur_vc->RemoveFlit();
	  
	  if(f->watch)
	    *gWatchOut << GetSimTime() << " | " << FullName() << " | " 
			<< "Output " << output
			<< " granted to VC " << vc << " at input " << input
			<< " (flit: " << f->id
			<< ", exp. input: " << expanded_input
			<< ", exp. output: " << expanded_output
			<< ")." << endl;
	  
	  f->hops++;
	  
	  //
	  // Switch Power Modelling
	  //
	  switchMonitor.traversal(input, output, f);
	  bufferMonitor.read(input, f);
	  
	  if(f->watch)
	    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			<< "Forwarding flit " << f->id << " through crossbar "
			<< "(exp. input: " << expanded_input
			<< ", exp. output: " << expanded_output
			<< ")." << endl;
	  
	  if (c == NULL) {
	    c = _NewCredit(_vcs);
	  }
	  
	  assert(vc == f->vc);
	  
	  c->vc[c->vc_cnt] = vc;
	  c->vc_cnt++;
	  c->dest_router = f->from_router;
	  f->vc = cur_vc->GetOutputVC();
	  dest_vc->SendingFlit(f);
	  
	  _crossbar_pipe->Write(f, expanded_output);
	  
	  if(f->tail) {
	    if(cur_vc->Empty()) {
	      cur_vc->SetState(VC::idle);
	    } else {
	      cur_vc->Route(_rf, this, cur_vc->FrontFlit(), input);
	      cur_vc->SetState(VC::vc_alloc);
	    }
	    _switch_hold_in[expanded_input] = -1;
	    _switch_hold_vc[expanded_input] = -1;
	    _switch_hold_out[expanded_output] = -1;
	  } else {
	    // reset state timer for next flit
	    cur_vc->SetState(VC::active);
	  }	  
	  
	  if(!_use_fast_path[input*_vcs+vc]) {
	    _sw_rr_offset[expanded_input] = (vc + 1) % _vcs;
	  }
	  
	  if(cur_vc->Empty() && !_use_fast_path[input*_vcs+vc]) {
	    if(f->watch)
	      *gWatchOut << GetSimTime() << " | " << FullName() << " | "
			  << "Enabling fast-path allocation for VC " << vc
			  << " at input " << input << "." << endl;
	    _use_fast_path[input*_vcs+vc] = true;
	  }
	  
	} 
      } else if((fvc >= 0) && ((fvc % _input_speedup) == s)) {
	
	assert(_use_fast_path[input*_vcs+fvc]);
	
	VC * fast_vc = _vc[input][fvc];
	Flit * f = fast_vc->FrontFlit();
	assert(f);
	
	if(f->watch)
	  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
		      << "Disabling fast-path allocation for VC " << fvc
		      << " at input " << input << "." << endl;
	_use_fast_path[input*_vcs+fvc] = false;
      }
    }    
    _credit_pipe->Write(c, input);
  }
}
Beispiel #18
0
void GPUTrafficManager::_Step()
{
  bool flits_in_flight = false;
  for(int c = 0; c < _classes; ++c) {
    flits_in_flight |= !_total_in_flight_flits[c].empty();
  }
  if(flits_in_flight && (_deadlock_timer++ >= _deadlock_warn_timeout)){
    _deadlock_timer = 0;
    cout << "WARNING: Possible network deadlock.\n";
  }
  
  vector<map<int, Flit *> > flits(_subnets);
  
  for ( int subnet = 0; subnet < _subnets; ++subnet ) {
    for ( int n = 0; n < _nodes; ++n ) {
      Flit * const f = _net[subnet]->ReadFlit( n );
      if ( f ) {
        if(f->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Ejecting flit " << f->id
          << " (packet " << f->pid << ")"
          << " from VC " << f->vc
          << "." << endl;
        }

        if(g_hpcl_comp_config.hpcl_comp_en == 0) {
          g_icnt_interface->WriteOutBuffer(subnet, n, f);
          //added by kh(030816)
          g_hpcl_network_anal->add_sample(hpcl_network_anal::NORMAL_FLIT_NO, 1);
          ///

        } else {
	  //added by kh (030816)
	  //(2.1.a) all reply flits (even write reply) are injected to decompressor for maintaining the order of flits.
	  //coming from the same vc
	  //Decompression: WRITE_REPLY should go through decomp, although no data is compressed.
	  //READ_REPLY = {f1,f2,f3,f4,f5}, WRITE_REPLY = {f6}
	  //Problematic case queue: f1,f2,f6,f3,f4,f5.
	  if(f->type == Flit::READ_REPLY || f->type == Flit::WRITE_REPLY) {	//only sm receives

	    assert(g_hpcl_global_decomp_pl_2B[n]);
	    //inject a flit to decompressor
	    hpcl_comp_pl_data* pl_data = new hpcl_comp_pl_data;
	    pl_data->add_comp_pl_data(f);
	    g_hpcl_global_decomp_pl_2B[n]->set_input_data(pl_data);

	    //added by kh (030316)
	    //set vc info to compressed flits.
	    for(int i = 0; i < f->compressed_other_flits.size(); i++) {
	      Flit* cf = f->compressed_other_flits[i];
	      assert(cf);
	      cf->vc = f->vc;
	    }
	    ///
	    //delete pl_data;

	    //added by kh (030816)
	    g_hpcl_network_anal->add_sample(hpcl_network_anal::NORMAL_FLIT_NO, 1);

	    if(f->compressed_other_flits.size() > 0) {
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::READ_REPLY_COMP_FLIT_NO, f->compressed_other_flits.size()+1);
	    } else {
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::READ_REPLY_UNCOMP_FLIT_NO, 1);
	    }
	    ///

	  } else if(f->type == Flit::CTRL_MSG) {	//(2.2.a) all ctrl flits are injected to decompressor

	    //std::cout << "f->id " << f->id << " f->src " << f->src << " f->dest " << f->dest << " node " << n << std::endl;
	    hpcl_comp_pl_data* pl_data = new hpcl_comp_pl_data;
	    pl_data->add_comp_pl_data(f);
	    g_hpcl_global_decomp_pl_2B[n]->set_input_data(pl_data);

	    //added by kh (030816)
	    g_hpcl_network_anal->add_sample(hpcl_network_anal::CTRL_FLIT_NO,1);
	    ///

	  } else {

	    g_icnt_interface->WriteOutBuffer(subnet, n, f);

	    //added by kh (030816)
	    g_hpcl_network_anal->add_sample(hpcl_network_anal::NORMAL_FLIT_NO, 1);
	    ///

	  }
	  ///
        }
      }
      

      g_icnt_interface->Transfer2BoundaryBuffer(subnet, n);
      Flit* const ejected_flit = g_icnt_interface->GetEjectedFlit(subnet, n);
      if (ejected_flit) {
        if(ejected_flit->head)
          assert(ejected_flit->dest == n);
        if(ejected_flit->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Ejected flit " << ejected_flit->id
          << " (packet " << ejected_flit->pid
          << " VC " << ejected_flit->vc << ")"
          << "from ejection buffer." << endl;
        }
        flits[subnet].insert(make_pair(n, ejected_flit));
        if((_sim_state == warming_up) || (_sim_state == running)) {
          ++_accepted_flits[ejected_flit->cl][n];
          if(ejected_flit->tail) {
            ++_accepted_packets[ejected_flit->cl][n];
          }
        }
      }
    
      // Processing the credit From the network
      Credit * const c = _net[subnet]->ReadCredit( n );
      if ( c ) {
#ifdef TRACK_FLOWS
        for(set<int>::const_iterator iter = c->vc.begin(); iter != c->vc.end(); ++iter) {
          int const vc = *iter;
          assert(!_outstanding_classes[n][subnet][vc].empty());
          int cl = _outstanding_classes[n][subnet][vc].front();
          _outstanding_classes[n][subnet][vc].pop();
          assert(_outstanding_credits[cl][subnet][n] > 0);
          --_outstanding_credits[cl][subnet][n];
        }
#endif
        _buf_states[n][subnet]->ProcessCredit(c);
        c->Free();
      }
    }
    _net[subnet]->ReadInputs( );
  }


  if(g_hpcl_comp_config.hpcl_comp_en == 1)
  {
    //added by kh (030816)
    //(2.3) Decompressor
    for(int i = 0; i < g_hpcl_global_decomp_pl_2B.size(); i++)
    {
      if(!g_hpcl_global_decomp_pl_2B[i])	continue;

      g_hpcl_global_decomp_pl_2B[i]->run(getTime()+getTotalTime());
      hpcl_comp_pl_data* comp_pl_data = g_hpcl_global_decomp_pl_2B[i]->get_output_data();
      Flit* flit = comp_pl_data->get_flit_ptr();
      if(flit) {
	int subnet = 0;
	assert(flit->const_dest == i);
	//std::cout << "Flit " << flit->id << " type " << flit->type << " is out from decomp" << std::endl;
	/*
	std::cout << GetSimTime() << "| MYEJECT | node " << i << " Flit " << flit->id << " type " << flit->type << " tail " << flit->tail << " vc " << flit->vc;
	if(flit->type == Flit::ANY_TYPE)	std::cout << " ctrl " << std::endl;
	else				std::cout << " mf " << ((mem_fetch*)flit->data)->get_request_uid() << std::endl;
	*/

	//std::cout << "Flit " << flit->id << " enc_status " << flit->m_enc_status;
	#ifdef CORRECTNESS_CHECK
	if(flit->m_enc_status == 1) {
	  std::cout << "dec_status " << flit->check_correctness() << std::endl;
	  if(flit->check_correctness() == false) {

	    printf("flit %d has incorrect decoding!\n", flit->id);

	    printf("\traw_data = ");
	    for(int k = flit->raw_data.size()-1; k >=0; k--) {
		    printf("%02x", flit->raw_data[k]);
	    }
	    printf("\n");

	    printf("\tdec_data = ");
	    for(int k = flit->decomp_data.size()-1; k >=0; k--) {
		    printf("%02x", flit->decomp_data[k]);
	    }
	    printf("\n");
	  }
	}
	#endif

	g_icnt_interface->WriteOutBuffer(subnet, i, flit);
      }

      //reset output data
      g_hpcl_global_decomp_pl_2B[i]->reset_output_data();
    }
    ///


    //added by kh (030816)
    //(1.2.c) generate/inject ctrl flit is injected to NI injection buffer
    for(int i = 0; i < g_hpcl_global_comp_pl_2B.size(); i++)
    {
      if(!g_hpcl_global_comp_pl_2B[i])	continue;
      if(g_hpcl_global_comp_pl_2B[i]->has_out_dict_ctrl_msg() == false)	continue;
      if(g_hpcl_global_comp_pl_2B[i]->get_state() == hpcl_comp_pl<unsigned short>::HPCL_COMP_RUN)	continue;

      hpcl_dict_ctrl_msg<unsigned short>* ctrl_msg = g_hpcl_global_comp_pl_2B[i]->front_out_dict_ctrl_msg();
      int packet_size = 1;	//1 flit
      Flit::FlitType packet_type = Flit::CTRL_MSG;
      void* data = NULL;
      assert(ctrl_msg->get_dest_node()>=0);
      int subnet = 0;
      int response_size = 32; 	//32bytes

      //send ctrl from MC
      int sender_device_id = -1;
      if(g_mc_placement_config.is_mc_node(i)) {
	sender_device_id = g_mc_placement_config.get_mc_node_index(i) + 56;	//56 SMs and 8 MCs
      }
      assert(sender_device_id >= 0);

      int sender_node_id = i;
      int receiver_node_id = ctrl_msg->get_dest_node();
      int receiver_device_id = g_mc_placement_config.get_sm_node_index(receiver_node_id);

      assert(sender_node_id>=0);
      assert(receiver_node_id>=0);
      if(g_icnt_interface->HasBuffer(sender_device_id, response_size)) {
	//std::cout << getTime()+getTotalTime() << " | " << " PUSH2 | " << " input " << sender_device_id << " output " << receiver_device_id << " ctrl_msg " << ctrl_msg->get_id();
	//std::cout << std::endl;
	_GeneratePacket(sender_node_id, -1, 0, getTime(), subnet, packet_size, packet_type, ctrl_msg, receiver_node_id);
	g_hpcl_global_comp_pl_2B[i]->pop_out_dict_ctrl_msg();

  //      std::cout << "ctrl_msg | id " << ctrl_msg->get_id();
  //      std::cout << " | src_node " << ctrl_msg->get_src_node();
  //      std::cout << " | dest_node " << ctrl_msg->get_dest_node();
  //      std::cout << " | word_index " << ctrl_msg->get_word_index();
  //      std::cout << " | word " << ctrl_msg->get_new_word() << std::endl;;
  //
  //      g_hpcl_global_comp_pl_2B[i]->validate_word(ctrl_msg->get_dest_node(), ctrl_msg->get_word_index(), ctrl_msg->get_new_word());
      }
    }
    ///

  }

// GPGPUSim will generate/inject packets from interconnection interface
#if 0
  if ( !_empty_network ) {
    _Inject();
  }
#endif
  
  for(int subnet = 0; subnet < _subnets; ++subnet) {
    
    for(int n = 0; n < _nodes; ++n) {
      
      Flit * f = NULL;
      
      BufferState * const dest_buf = _buf_states[n][subnet];
      
      int const last_class = _last_class[n][subnet];
      
      int class_limit = _classes;
      
      if(_hold_switch_for_packet) {
        list<Flit *> const & pp = _input_queue[subnet][n][last_class];
        if(!pp.empty() && !pp.front()->head &&
           !dest_buf->IsFullFor(pp.front()->vc)) {
          f = pp.front();
          assert(f->vc == _last_vc[n][subnet][last_class]);
          
          // if we're holding the connection, we don't need to check that class
          // again in the for loop
          --class_limit;
        }
      }
      
      for(int i = 1; i <= class_limit; ++i) {
        
        int const c = (last_class + i) % _classes;
        
        list<Flit *> const & pp = _input_queue[subnet][n][c];
        
        if(pp.empty()) {
          continue;
        }
        
        Flit * const cf = pp.front();
        assert(cf);
        assert(cf->cl == c);
        assert(cf->subnetwork == subnet);

        if(g_hpcl_comp_config.hpcl_comp_en == 1) {
	  //added by kh (030816)
	  //If compressor is busy with compressing flits of a packet,
	  //don't inject a head flit of a new packet to the busy compressor
	  //compressor is only for read reply, but write reply goes through the compressor to avoid intermixed flits from different packets
	  //Thus, the following filtering is not restricted to read reply, thus we have no flit type checking to read reply.
	  if(g_mc_placement_config.is_mc_node(n) == true && cf->head == true) {
	    if(g_hpcl_global_comp_pl_2B[n] && g_hpcl_global_comp_pl_2B[n]->get_state() == hpcl_comp_pl<unsigned short>::HPCL_COMP_RUN) {
	      f = NULL;
	      break;
	    }
	  }
	  ///
        }

        if(f && (f->pri >= cf->pri)) {
          continue;
        }
        
        //KH: routing output port is decided here.
        if(cf->head && cf->vc == -1) { // Find first available VC
          
          //std::cout << "_Step is called!!!!" << std::endl;
          //assert(1 == 0);

          OutputSet route_set;
          _rf(NULL, cf, -1, &route_set, true);
          set<OutputSet::sSetElement> const & os = route_set.GetSet();
          assert(os.size() == 1);
          OutputSet::sSetElement const & se = *os.begin();
          assert(se.output_port == -1);
          int vc_start = se.vc_start;
          int vc_end = se.vc_end;
          int vc_count = vc_end - vc_start + 1;
          if(_noq) {
            assert(_lookahead_routing);
            const FlitChannel * inject = _net[subnet]->GetInject(n);
            const Router * router = inject->GetSink();
            assert(router);
            int in_channel = inject->GetSinkPort();
            

            // NOTE: Because the lookahead is not for injection, but for the
            // first hop, we have to temporarily set cf's VC to be non-negative
            // in order to avoid seting of an assertion in the routing function.
            cf->vc = vc_start;
            _rf(router, cf, in_channel, &cf->la_route_set, false);
            cf->vc = -1;
            
            if(cf->watch) {
              *gWatchOut << GetSimTime() << " | "
              << "node" << n << " | "
              << "Generating lookahead routing info for flit " << cf->id
              << " (NOQ)." << endl;
            }
            set<OutputSet::sSetElement> const sl = cf->la_route_set.GetSet();
            assert(sl.size() == 1);
            int next_output = sl.begin()->output_port;
            vc_count /= router->NumOutputs();
            vc_start += next_output * vc_count;
            vc_end = vc_start + vc_count - 1;
            assert(vc_start >= se.vc_start && vc_start <= se.vc_end);
            assert(vc_end >= se.vc_start && vc_end <= se.vc_end);
            assert(vc_start <= vc_end);
          }
          if(cf->watch) {
            *gWatchOut << GetSimTime() << " | " << FullName() << " | "
            << "Finding output VC for flit " << cf->id
            << ":" << endl;
          }
          for(int i = 1; i <= vc_count; ++i) {
            int const lvc = _last_vc[n][subnet][c];
            int const vc =
            (lvc < vc_start || lvc > vc_end) ?
            vc_start :
            (vc_start + (lvc - vc_start + i) % vc_count);
            assert((vc >= vc_start) && (vc <= vc_end));
            if(!dest_buf->IsAvailableFor(vc)) {
              if(cf->watch) {
                *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                << "  Output VC " << vc << " is busy." << endl;
              }
            } else {
              if(dest_buf->IsFullFor(vc)) {
                if(cf->watch) {
                  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                  << "  Output VC " << vc << " is full." << endl;
                }
              } else {
                if(cf->watch) {
                  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                  << "  Selected output VC " << vc << "." << endl;
                }
                cf->vc = vc;
                break;
              }
            }
          }
        }
        
        if(cf->vc == -1) {
          if(cf->watch) {
            *gWatchOut << GetSimTime() << " | " << FullName() << " | "
            << "No output VC found for flit " << cf->id
            << "." << endl;
          }
        } else {
          if(dest_buf->IsFullFor(cf->vc)) {
            if(cf->watch) {
              *gWatchOut << GetSimTime() << " | " << FullName() << " | "
              << "Selected output VC " << cf->vc
              << " is full for flit " << cf->id
              << "." << endl;
            }
          } else {
            f = cf;
          }
        }
      }
      
      if(f) {
        
        assert(f->subnetwork == subnet);
        
        int const c = f->cl;
        
        if(f->head) {
          
          if (_lookahead_routing) {
            if(!_noq) {
              const FlitChannel * inject = _net[subnet]->GetInject(n);
              const Router * router = inject->GetSink();
              assert(router);
              int in_channel = inject->GetSinkPort();
              _rf(router, f, in_channel, &f->la_route_set, false);
              if(f->watch) {
                *gWatchOut << GetSimTime() << " | "
                << "node" << n << " | "
                << "Generating lookahead routing info for flit " << f->id
                << "." << endl;
              }
            } else if(f->watch) {
              *gWatchOut << GetSimTime() << " | "
              << "node" << n << " | "
              << "Already generated lookahead routing info for flit " << f->id
              << " (NOQ)." << endl;
            }
          } else {
            f->la_route_set.Clear();
          }
          
          dest_buf->TakeBuffer(f->vc);
          _last_vc[n][subnet][c] = f->vc;
        }
        
        _last_class[n][subnet] = c;
        
        _input_queue[subnet][n][c].pop_front();
        
#ifdef TRACK_FLOWS
        ++_outstanding_credits[c][subnet][n];
        _outstanding_classes[n][subnet][f->vc].push(c);
#endif
        

        if(g_hpcl_comp_config.hpcl_comp_en == 0) {
	  dest_buf->SendingFlit(f);
        } else {
	  //added by kh(030816)
	  //(1.1.a) send a head flit first: update buffer state
	  if(g_mc_placement_config.is_mc_node(n) == true && f->type == Flit::READ_REPLY) {
	      if(f->head)	dest_buf->SendingFlit(f);
	      //skip for other flits
	  } else {
	      dest_buf->SendingFlit(f);
	  }
	  ///
        }

        if(_pri_type == network_age_based) {
          f->pri = numeric_limits<int>::max() - _time;
          assert(f->pri >= 0);
        }
        
        if(f->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Injecting flit " << f->id
          << " into subnet " << subnet
          << " at time " << _time
          << " with priority " << f->pri
          << "." << endl;
        }
        f->itime = _time;
        
        // Pass VC "back"
        if(!_input_queue[subnet][n][c].empty() && !f->tail) {
          Flit * const nf = _input_queue[subnet][n][c].front();
          nf->vc = f->vc;
        }
        
        if((_sim_state == warming_up) || (_sim_state == running)) {
          ++_sent_flits[c][n];

          //added by kh(070215)
          ++_sent_flits_net[subnet][n];


          if(f->head) {
            ++_sent_packets[c][n];

            //added by kh(030816)
            if(f->type < Flit::ANY_TYPE) {
	      //added by kh(121715)
	      if(g_mc_placement_config.is_sm_node(n)) {
		  ((mem_fetch*)f->data)->set_status(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_SM, _time);

		  //added by kh(122815)
		  double req_queuing_lat_in_sm = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_NI_INPUT_BUF_IN_SM);
		  g_hpcl_network_anal->add_sample(hpcl_network_anal::REQ_QUEUING_LAT_IN_SM, req_queuing_lat_in_sm);
		  ///

	      } else if(g_mc_placement_config.is_mc_node(n)) {
		  ((mem_fetch*)f->data)->set_status(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_MEM, _time);
		  //added by kh(122815)
		  double rep_queuing_lat_in_mc = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_NI_INPUT_BUF_IN_MEM);
		  g_hpcl_network_anal->add_sample(hpcl_network_anal::REP_QUEUING_LAT_IN_MC, rep_queuing_lat_in_mc);
		  ///
	      }
	      ///
            }
          }
        }
        
#ifdef TRACK_FLOWS
        ++_injected_flits[c][n];
#endif
        
        if(g_hpcl_comp_config.hpcl_comp_en == 0) {

	  _net[subnet]->WriteFlit(f, n);

        } else {
	  //added by kh (021416)
	  //Compression
	  //(1.1.b) flits but a head flit are injected to the compressor
	  if(g_mc_placement_config.is_mc_node(n) == true && f->type == Flit::READ_REPLY) {

	     hpcl_comp_pl_data* pl_data = NULL;

	     //A head flit is found. It means other flits are in _input_queue now.
	     //flits move from _input_queue to compressor by force.
	     //Those flits are sent to network in different paths such that we set info for
	     //flit navigation here.
	     if(f->head == true) {
		assert(!_input_queue[subnet][n][c].empty());
		Flit * body_flit = _input_queue[subnet][n][c].front();
		_input_queue[subnet][n][c].pop_front();

		if(_pri_type == network_age_based) {
		  body_flit->pri = numeric_limits<int>::max() - _time;
		  assert(body_flit->pri >= 0);
		}
		body_flit->itime = _time;

		// Pass VC "back" for next flit
		if(!_input_queue[subnet][n][c].empty() && !body_flit->tail) {
		  Flit * const nf = _input_queue[subnet][n][c].front();
		  nf->vc = body_flit->vc;
		}

		++_sent_flits[c][n];
		++_sent_flits_net[subnet][n];

		pl_data = new hpcl_comp_pl_data;
		pl_data->add_comp_pl_data(body_flit);
		g_hpcl_global_comp_pl_2B[n]->set_input_data(pl_data);
		//delete pl_data;

		//(1.1.a)	send a head flit first
		_net[subnet]->WriteFlit(f, n);

	    } else {

		pl_data = new hpcl_comp_pl_data;
		pl_data->add_comp_pl_data(f);
		g_hpcl_global_comp_pl_2B[n]->set_input_data(pl_data);
		//delete pl_data;
	    }


	    //(1.2.a) words in a flit are pushed to a queue in a compressor
	    if(pl_data) {

		Flit* flit = pl_data->get_flit_ptr();
		assert(flit);

		//Use receiver's id as global dict index
		int global_dict_index = flit->const_dest;

		//Push words to be updated to word_queue (this is done at zero-time)
		vector<unsigned short> word_list;
		g_hpcl_global_comp_pl_2B[n]->decompose(flit->raw_data, word_list);
		for(int i = 0; i < word_list.size(); i++)
		  g_hpcl_global_comp_pl_2B[n]->push_word_to_queue(word_list[i], global_dict_index);

		delete pl_data;
	    }

	  } else if (g_mc_placement_config.is_mc_node(n) == true && f->type == Flit::CTRL_MSG) {


	      hpcl_dict_ctrl_msg<unsigned short>* ctrl_msg = (hpcl_dict_ctrl_msg<unsigned short>*)f->data;

	      /*
	      std::cout << "ctrl_msg | id " << ctrl_msg->get_id();
	      std::cout << " | src_node " << ctrl_msg->get_src_node();
	      std::cout << " | dest_node " << ctrl_msg->get_dest_node();
	      std::cout << " | word_index " << ctrl_msg->get_word_index();
	      std::cout << " | word " << ctrl_msg->get_new_word();
	      std::cout << " | n " << n;
	      std::cout << std::endl;;
	      */

	      g_hpcl_global_comp_pl_2B[n]->release_word(ctrl_msg->get_dest_node(), ctrl_msg->get_word_index(), ctrl_msg->get_new_word());
	      g_hpcl_global_comp_pl_2B[n]->validate_word(ctrl_msg->get_dest_node(), ctrl_msg->get_word_index(), ctrl_msg->get_new_word());

	      _net[subnet]->WriteFlit(f, n);

	  } else {

	      _net[subnet]->WriteFlit(f, n);
	  }
	  ///
        }
      }
    }
  }

  if(g_hpcl_comp_config.hpcl_comp_en == 1) {

    //added by kh(030816)
    //(1.3) Compression: Pipelined Compression
    for(int i = 0; i < g_hpcl_global_comp_pl_2B.size(); i++)
    {
      if(!g_hpcl_global_comp_pl_2B[i])	continue;

      //(1.2.b) words in the queue are updated to dictionary, when idle state
      //(1.2.d) ctrl msgs for words with frequency (>= threshold) are generated in compressor's run function, when idle state
      g_hpcl_global_comp_pl_2B[i]->run(getTime()+getTotalTime());
      hpcl_comp_pl_data* comp_pl_rsl = g_hpcl_global_comp_pl_2B[i]->get_output_data();
      Flit* flit = comp_pl_rsl->get_flit_ptr();
      if(flit) {
	//std::cout << "node " << i << " flit->id " << flit->id << std::endl;

	//(1.1.c) flits are injected from the compressor to an input buffer
	if(HasBufferSpace(i, flit)) {
	  SendFlitToBuffer(i, flit);		//for credit management.
	  SendFlitToNetwork(i, flit);
	  //std::cout << "\t" << " send flit " << flit->id << std::endl;

	  if(g_hpcl_global_comp_pl_2B[i]->get_comp_done() == true)
	  {
	      assert(g_hpcl_global_comp_pl_2B[i]->get_state() == hpcl_comp_pl<unsigned short>::HPCL_COMP_RUN);
	      g_hpcl_global_comp_pl_2B[i]->set_state(hpcl_comp_pl<unsigned short>::HPCL_COMP_IDLE);
	      g_hpcl_global_comp_pl_2B[i]->reset_comp_done();
	  }

	  //reset output data
	  g_hpcl_global_comp_pl_2B[i]->reset_output_data();

	} else {
	  //std::cout << "\t" << " cannot send flit " << flit->id << " due to no space!!!!!!!!!!" << std::endl;
	}
      }
    }
    ///

  }

  //Send the credit To the network
  for(int subnet = 0; subnet < _subnets; ++subnet) {
    for(int n = 0; n < _nodes; ++n) {
      map<int, Flit *>::const_iterator iter = flits[subnet].find(n);
      if(iter != flits[subnet].end()) {
        Flit * const f = iter->second;

        f->atime = _time;

        //added by kh(070715)
        if(f->tail) {

          //added by kh(030816)
	  if(f->type < Flit::ANY_TYPE) {
	    //added by kh(121715)
	    if(g_mc_placement_config.is_sm_node(n)) {
	      //std::cout << "mf's id: " << ((mem_fetch*)f->data)->get_request_uid() << ", time: " << _time << std::endl;
	      ((mem_fetch*)f->data)->set_status(TAIL_FLIT_EJECTED_FROM_EJECT_BUF_IN_SM, _time);
	      //added by kh(122815)
	      double rep_net_lat = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_MEM);
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::REP_NET_LAT, rep_net_lat);
	      ///

	    } else if(g_mc_placement_config.is_mc_node(n)) {
	      ((mem_fetch*)f->data)->set_status(TAIL_FLIT_EJECTED_FROM_EJECT_BUF_IN_MEM, _time);

	      //added by kh(122815)
	      double req_net_lat = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_SM);
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::REQ_NET_LAT, req_net_lat);
	      ///
	    }
          }
        }
        ///

        if(f->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Injecting credit for VC " << f->vc
          << " into subnet " << subnet
          << "." << endl;
        }
        

        if(g_hpcl_comp_config.hpcl_comp_en == 0) {

          Credit * const c = Credit::New();
	  c->vc.insert(f->vc);
	  _net[subnet]->WriteCredit(c, n);

        } else {
	  //added by kh(030816)
	  if(f->type == Flit::READ_REPLY) {
	      if(f->tail == false && f->m_enc_status == 1) {

	      } else {
		Credit * const c = Credit::New();
		c->vc.insert(f->vc);
		_net[subnet]->WriteCredit(c, n);
		//std::cout << "\tf->vc " << f->vc << " f->id " << f->id << std::endl;
	      }

	  } else {
	    Credit * const c = Credit::New();
	    c->vc.insert(f->vc);
	    _net[subnet]->WriteCredit(c, n);
	  }
	  ///
        }

#ifdef TRACK_FLOWS
        ++_ejected_flits[f->cl][n];
#endif
        
        _RetireFlit(f, n);
      }
    }
    flits[subnet].clear();
    // _InteralStep here
    _net[subnet]->Evaluate( );					//run router's pipeline
    _net[subnet]->WriteOutputs( );				//send flits..
  }
  
  ++_time;
  assert(_time);
  if(gTrace){
    cout<<"TIME "<<_time<<endl;
  }
  
}
Beispiel #19
0
 // Gets the parent directory of a specified subdirectory.
 TString DirectoryInfo::Parent() const
 {
     return FullName().Substring(0, _path.LastIndexOf('\\'));
 }
Beispiel #20
0
 // Gets the full path of the parent directory.
 TString FileInfo::Directory() const
 {
     return FullName().Substring(0, _path.LastIndexOf('\\'));
 }
Beispiel #21
0
namespace Ginger {

Ref * sysIsLowerCase( Ref * pc, class MachineClass * vm ) {
    if ( vm->count != 1 ) throw Ginger::Mishap( "Wrong number of arguments" );
    
    Ref r = vm->fastPeek();
    if ( IsCharacter( r ) ) {
        vm->fastPeek() = islower( CharacterToChar( r ) ) ? SYS_TRUE : SYS_FALSE;
    } else if ( IsString( r ) ) {
        Ref * str_K = RefToPtr4( r );
        char * s = reinterpret_cast< char * >( &str_K[ 1 ] );
        vm->fastPeek() = SYS_TRUE;
        while ( *s != 0 ) {
            if ( not islower( *s++ ) ) {
                vm->fastPeek() = SYS_FALSE;
                break;
            }
        }
    } else {
        throw Ginger::Mishap( "Non-character argument" ).culprit( "Argument", refToShowString( r ) );  
    } 
    
    return pc;
}
SysInfo infoIsLowerCase( 
    FullName( "isLowerCase" ), 
    Arity( 1 ), 
    Arity( 1 ), 
    sysIsLowerCase, 
    "Returns true for a lower case character or string, otherwise false" 
);

Ref * sysIsUpperCase( Ref * pc, class MachineClass * vm ) {
    if ( vm->count != 1 ) throw Ginger::Mishap( "Wrong number of arguments" );
    
    Ref r = vm->fastPeek();
    if ( IsCharacter( r ) ) {
        vm->fastPeek() = isupper( CharacterToChar( r ) ) ? SYS_TRUE : SYS_FALSE;
    } else if ( IsString( r ) ) {
        Ref * str_K = RefToPtr4( r );
        char * s = reinterpret_cast< char * >( &str_K[ 1 ] );
        vm->fastPeek() = SYS_TRUE;
        while ( *s != 0 ) {
            if ( not isupper( *s++ ) ) {
                vm->fastPeek() = SYS_FALSE;
                break;
            }
        }
    } else {
        throw Ginger::Mishap( "Non-character argument" ).culprit( "Argument", refToShowString( r ) );  
    }     
    return pc;
}
SysInfo infoIsUpperCase( 
    FullName( "isUpperCase" ), 
    Arity( 1 ), 
    Arity( 1 ), 
    sysIsUpperCase, 
    "Returns true for a upper case character or string, otherwise false" 
);

}
void IQRouterBaseline::_VCAlloc( )
{
    VC          *cur_vc;
    BufferState *dest_vc;
    int         input_and_vc;
    int         match_input;
    int         match_vc;

    Flit        *f;
    bool        watched = false;

    _vc_allocator->Clear( );


    for ( set<int>::iterator item = _vcalloc_vcs.begin(); item!=_vcalloc_vcs.end(); ++item ) {
        int vc_encode = *item;
        int input =  vc_encode/_vcs;
        int vc =vc_encode%_vcs;
        cur_vc = _vc[input][vc];
        if ( ( _speculative > 0 ) && ( cur_vc->GetState( ) == VC::vc_alloc )) {
            cur_vc->SetState( VC::vc_spec ) ;
        }
        if (  cur_vc->GetStateTime( ) >= _vc_alloc_delay  ) {
            f = cur_vc->FrontFlit( );
            if(f->watch) {
                *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                           << "VC " << vc << " at input " << input
                           << " is requesting VC allocation for flit " << f->id
                           << "." << endl;
                watched = true;
            }

            const OutputSet *route_set    = cur_vc->GetRouteSet( );
            int out_priority = cur_vc->GetPriority( );
            const list<OutputSet::sSetElement>* setlist = route_set ->GetSetList();
            //cout<<setlist->size()<<endl;
            list<OutputSet::sSetElement>::const_iterator iset = setlist->begin( );
            while(iset!=setlist->end( )) {
                BufferState *dest_vc = _next_vcs[iset->output_port];
                for ( int out_vc = iset->vc_start; out_vc <= iset->vc_end; ++out_vc ) {
                    int in_priority = iset->pri;
                    // On the input input side, a VC might request several output
                    // VCs.  These VCs can be prioritised by the routing function
                    // and this is reflected in "in_priority".  On the output,
                    // if multiple VCs are requesting the same output VC, the priority
                    // of VCs is based on the actual packet priorities, which is
                    // reflected in "out_priority".

                    //	    cout<<
                    if(dest_vc->IsAvailableFor(out_vc)) {
                        if(f->watch) {
                            *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                       << "Requesting VC " << out_vc
                                       << " at output " << iset->output_port
                                       << " with priorities " << in_priority
                                       << " and " << out_priority
                                       << "." << endl;
                        }
                        _vc_allocator->AddRequest(input*_vcs + vc, iset->output_port*_vcs + out_vc,
                                                  out_vc, in_priority, out_priority);
                    } else {
                        if(f->watch)
                            *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                                       << "VC " << out_vc << " at output " << iset->output_port
                                       << " is unavailable." << endl;
                    }
                }
                //go to the next item in the outputset
                iset++;
            }
        }

    }
    //  watched = true;
    if ( watched ) {
        *gWatchOut << GetSimTime() << " | " << _vc_allocator->FullName() << " | ";
        _vc_allocator->PrintRequests( gWatchOut );
    }

    _vc_allocator->Allocate( );

    // Winning flits get a VC

    for ( int output = 0; output < _outputs; ++output ) {
        for ( int vc = 0; vc < _vcs; ++vc ) {
            input_and_vc = _vc_allocator->InputAssigned( output*_vcs + vc );

            if ( input_and_vc != -1 ) {
                assert(input_and_vc >= 0);
                match_input = input_and_vc / _vcs;
                match_vc    = input_and_vc - match_input*_vcs;

                cur_vc  = _vc[match_input][match_vc];
                dest_vc = _next_vcs[output];

                if ( _speculative > 0 )
                    cur_vc->SetState( VC::vc_spec_grant );
                else
                    cur_vc->SetState( VC::active );
                _vcalloc_vcs.erase(match_input*_vcs+match_vc);

                cur_vc->SetOutput( output, vc );
                dest_vc->TakeBuffer( vc );

                f = cur_vc->FrontFlit( );

                if(f->watch)
                    *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                               << "Granted VC " << vc << " at output " << output
                               << " to VC " << match_vc << " at input " << match_input
                               << " (flit: " << f->id << ")." << endl;
            }
        }
    }
}
Beispiel #23
0
void cOptStr::Store(const char *PreStr)
{
  ScPlugin->SetupStore(FullName(PreStr),storage);
}