//=========================================================================== // Testbench johns 10-2-00 // // The Testbench module is the main driver for the Routed design. // It's job is to schedule the legs of each of the itineraries on the // appropriate dates at the appropriate times. // // It also announces arrivals of passengers at their destinations. // // The Testbench has the autonomous driver thread which server // as the master control for the simulation. Before entering its // main loop, the driver thread does two things. First it triggers // the RouteConfig module to teach all the routes to the RouteTable's // of all the hubs in the RouteMap. Passenger travel in the RouteMap // is not possible until all the hubs have have properly configured. // // Once all the routes have been taught to the RouteMap, the // calendar is advanced to day 1. This will, in turn cause // the Calendar module to announce the arrival of day 1 via the // NewDay inslave port. Once the day change has been detected, // The driver thread then enters into a loop where it schedules // any travel on the itineraries scheduled for the current day. // If no travel is scheduled, it advances the calender to the // first day on which travel is scheduled to occur. Leg's of // each itinerary are scheduled by sending the itinerary // record over the ScheduleLeg outmaster port to the Scheduler // module, which encodes it into a token and sends it to the // hardware. // // This operation continues for each leg of each itinerary until // all passengers have traveled all legs of their trip and have // finally arrived in Maui for a little R&R ! // // At that point the simulation is done - a fact which is // conveyed to the SceMiDispatcher() by signaling the Done // outmaster port. Upon receiving this notification, the // SceMiDispatcher module shuts down the SCE-MI and exits the // program. //=========================================================================== #include // For ios setw() manpulator. const Routed::Itinerary Routed::BugsesTrip[] = { /* On day, at, departs from, enroute to, */ { 2, 8, BugsBunny, Anchorage, Cupertino }, { 3, 5, BugsBunny, Cupertino, UK }, { 8, 4, BugsBunny, UK, SealBeach }, { 20, 10, BugsBunny, SealBeach, Maui }, { 0, 0, BugsBunny, Unspecified, Unspecified } }; const Routed::Itinerary Routed::DaffysTrip[] = { /* On day, at, departs from, enroute to, */ { 1, 8, DaffyDuck, Waltham, Cupertino }, { 4, 2, DaffyDuck, Cupertino, SealBeach }, { 5, 11, DaffyDuck, SealBeach, Anchorage }, { 10, 3, DaffyDuck, Anchorage, UK }, { 15, 4, DaffyDuck, UK, Cupertino }, { 22, 7, DaffyDuck, Cupertino, Maui }, { 0, 0, DaffyDuck, Unspecified, Unspecified } }; const Routed::Itinerary Routed::ElmersTrip[] = { /* On day, at, departs from, enroute to, */ { 3, 5, ElmerFudd, SealBeach, Anchorage }, { 4, 2, ElmerFudd, Anchorage, SealBeach }, { 8, 15, ElmerFudd, SealBeach, Cupertino }, { 23, 3, ElmerFudd, Cupertino, Maui }, { 0, 0, ElmerFudd, Unspecified, Unspecified } }; const Routed::Itinerary Routed::SylvestersTrip[] = { /* On day, at, departs from, enroute to, */ { 1, 1, SylvesterTheCat, Noida, SealBeach }, { 4, 2, SylvesterTheCat, SealBeach, Cupertino }, { 5, 11, SylvesterTheCat, Cupertino, UK }, { 10, 4, SylvesterTheCat, UK, SealBeach }, { 15, 9, SylvesterTheCat, SealBeach, Anchorage }, { 20, 7, SylvesterTheCat, Anchorage, Maui }, { 0, 0, SylvesterTheCat, Unspecified, Unspecified } }; static const char *passengerNames[] = { "Nobody ", "BugsBunny ", "DaffyDuck ", "ElmerFudd ", "SylvesterTheCat" }; static const char *locationNames[] = { "Unspecified", "Anchorage", "Chicago ", "Cupertino", "Dallas ", "Maui ", "Newark ", "Noida ", "SanFran ", "SealBeach", "Seattle ", "UK ", "Waltham " }; class Testbench: public sc_module { public: //------------------------------------------------------- // Abstract port declarations sc_master<> LoadRouteMap; sc_master<> Done; sc_outmaster AdvanceCalendar; sc_inslave NewDay; sc_outmaster ScheduleLeg; sc_inslave AnnounceArrival; private: SC_HAS_PROCESS(Testbench); //------------------------------------------------------- // Context declarations unsigned dNumMauiArrivals; unsigned dDayNum; const Routed::Itinerary *dItineraries[Routed::NumPassengers]; //------------------------------------------------------- // Thread declarations void driverThread(); // Autonomous "master" thread. void newDayThread() { dDayNum = NewDay; } void announceArrivalThread(); //------------------------------------------------------- // Helper declarations public: Testbench( sc_module_name name ) : sc_module(name), dNumMauiArrivals(0), dDayNum(0) { //-------------------------------------- // Thread bindings // This autonomous thread forms the main body of the TIP driver. SC_THREAD( driverThread ); sensitive << UTick; SC_SLAVE( newDayThread, NewDay ); SC_SLAVE( announceArrivalThread, AnnounceArrival ); // Initialize itinerary pointers. dItineraries[0] = Routed::BugsesTrip; dItineraries[1] = Routed::DaffysTrip; dItineraries[2] = Routed::ElmersTrip; dItineraries[3] = Routed::SylvestersTrip; } }; //--------------------------------------------------------- // ::driverThread() - Master control the simulation // // Description johnS 10-4-2000 // ----------- // This is master control driver thread. It is coded as an // autonomous System C thread which contains a main loop // that advances on the each atomic UTick clock. // // Each time the day is advanced, this thread checks the // itineraries to see if any travel is to occur this new day. // If so, the itinerary legs are sent to the scheduler and the // clock advancer is requested to perform another notification // tomorrow. // // If no itineraries have travel for this new day, the // clock advancer is requested to advance to the first day // on which at least some travel is scheduled to occur. //--------------------------------------------------------- void Testbench::driverThread(){ LoadRouteMap(); unsigned dayNum = dDayNum; AdvanceCalendar = 1; // Advance to day 1. for(;;){ wait(); // Wait for day to advance (i.e. 'NewDay' arrives. if( dayNum != dDayNum ){ unsigned date, minDate = 1000; // Check itineraries to see if any passengers are // traveling today. If so, advance calendar to tomorrow // in case next leg of itinerary is tomorrow. for( int i=0; iDateOfTravel) ){ if( date == dDayNum ){ cout << "On day " << setw(2) << dDayNum << " at " << setw(2) << dItineraries[i]->TimeOfDeparture << ":00 hrs, " << passengerNames[dItineraries[i]->PassengerID] << " departs " << locationNames[dItineraries[i]->OriginID] << " enroute to " << locationNames[dItineraries[i]->DestinationID] << endl; ScheduleLeg = dItineraries[i]++; minDate = dDayNum+1; } else if( date < minDate ) minDate = date; } } dayNum = dDayNum; AdvanceCalendar = minDate - dDayNum; } } } //--------------------------------------------------------- // ::announceArrivalThread() - Process an arrival // // Description johnS 10-4-2000 // ----------- // This thread is called when the scheduler has determined // that a passenger has arrived at a destination. A message // is output to the screen. // // Once all passengers have arrived in Maui, the simulation // is ready to terminate. //--------------------------------------------------------- void Testbench::announceArrivalThread(){ const Routed::ArrivalRecord *arrivalRecord = AnnounceArrival; cout << "On day " << setw(2) << arrivalRecord->DateOfArrival << " at " << setw(2) << arrivalRecord->TimeOfArrival << ":00 hrs,\n" << " " << passengerNames[arrivalRecord->PassengerID] << " arrives in " << locationNames[arrivalRecord->DestinationID] << " from " << locationNames[arrivalRecord->OriginID] << " after layovers in,"; for( unsigned i=0; iLayoverCount; i++ ) cout << "\n " << locationNames[arrivalRecord->LayoverIDs[i]]; cout << endl; if( arrivalRecord->DestinationID == Routed::Maui && ++dNumMauiArrivals == Routed::NumPassengers ){ cout << "Everyone has arrived in Maui. We're done. Let's party !" << endl; Done(); } }