예제 #1
0
int main(int argc, char **argv)
{
	ConfigKeeper * cfg = ConfigKeeper::inst();
	if (!cfg->processCmdLine(argc, argv))
	{
		return 1; // exit early
	}

	cout << cfg->getNodes() << " " << cfg->getNetworks() << " ";
	cout << cfg->getSysPeriodSecs() << " " << cfg->getOutfileName() << endl;

	NetGraph ng;
	ng.print();

	return 0;
}
NetGraph::NetGraph() : _ng( ConfigKeeper::inst()->getNetworks() + ConfigKeeper::inst()->getNodes())
{
    ConfigKeeper * cfg = ConfigKeeper::inst();
    // The general idea...
    // Create the proper number of networks and nodes
    unsigned long idx;

    cout << "Creating nodes and nets..." << endl;
    for ( idx = 0; idx < cfg->getNetworks(); idx++ )
    {
        _nets_nodes.push_back( new Net(idx) );
    }

    for ( ; idx < cfg->getNetworks() + cfg->getNodes(); idx++ )
    {
        _nets_nodes.push_back( new Node(idx) );
    }

    // Take the list of nodes and connect each one to at least one bus
    unsigned long nidx;
    cout << "Connecting nodes to nets..." << endl;
    if ( cfg->getNetworks() > 0 )
    {
        for (nidx = cfg->getNetworks(); nidx < cfg->getNetworks() + cfg->getNodes(); nidx++)
        {
            cout << "Network " << nidx << ": ";
            // For the vertex, select a number of nets to connect to and
            // then make a list of them
            unsigned long numnets = _rnd.chooseInt(1, cfg->getMaxNetsPerNode());
            cout << numnets << " nets " << endl;
            std::vector< long > nets = _rnd.chooseInts(0, cfg->getNetworks()-1, numnets);
            for ( unsigned long eidx = 0; eidx < numnets; eidx++ )
            {
                cout << "   connecting (" << nidx << "," << nets[eidx] << ")" << endl;
                add_edge(nidx, nets[eidx], _ng);
            }
            cout << endl;
        }
        cout << endl;
    }

    // Continue adding node/bus edges until the whole graph is connected
    /*std::vector<size_type> rank(num_vertices(_ng));
    std::vector<NetworkVertex> parent(num_vertices(_ng));
    typedef size_type* Rank;
    typedef NetworkVertex* Parent;
    disjoint_sets<Rank, Parent> ds(&rank[0], &parent[0]);

    initialize_incremental_components(_ng, ds);
    incremental_components(_ng, ds);

    // Make a single connected component
    // @todo -- come back and look at cleaning this up:
    // The graph structure isn't using the type system.
    // This will not be quite as random as it should be.

    // For now we'll check and warn
    if ( ds.count_sets() > 1)
    	cout << "The generated network is not connected!!! (" << ds.count_sets() << " comps)" << endl;

    /*while ( ds.count_sets() > 1 )
    {
    	NetworkVertex vn1 = parent[ds.count_sets()-1];
    	NetworkVertex vn2 = parent[ds.count_sets()-2];

    	NetworkVertex


    } */

    // Create a random number of tasks per processor
    cout << "Creating random tasks..." << endl;
    std::vector< double > dividers;
    dividers.push_back(1.0);
    dividers.push_back(2.0);
    dividers.push_back(4.0);
    unsigned long tidx = 0;
    // Counterintuitive syntax -- we're iterating over nodes
    for (nidx = cfg->getNetworks(); nidx < cfg->getNetworks() + cfg->getNodes(); nidx++)
    {
        unsigned long numtasks = _rnd.chooseInt(1, cfg->getMaxTasksPerNode());
        cout << "Node " << nidx << ": " << numtasks << endl;
        for ( idx = 0; idx < numtasks; idx++ )
        {
            Task t(tidx++, nidx);
            cout << "p";
            t._periodSecs = cfg->getSysPeriodSecs() / _rnd.chooseFromList(dividers);
            cout << "w";

            // Get a reasonable task exec length
            double res = cfg->getSysResolutionSecs();
            t._wcetSecs = max( t._periodSecs * _rnd.chooseDouble(cfg->getMinTaskUtil(), cfg->getMaxTaskUtil()),
                               res );
            cout << "c";
            Node * n = dynamic_cast<Node *>(_nets_nodes[nidx]);
            cout << "r";
            t._parent = n->id;
            cout << "t";
            n->_tasks.push_back(t);
            _tasks.push_back(t);

            cout << " added task " << t.id << " pd " << t._periodSecs << " et " << t._wcetSecs << " p " << t._parent << endl;
            //add_vertex(t.id, _tg);
        }
    }

    cout << "Creating subgraph structure..." << endl;
    _tg = new TaskGraph(_tasks.size());
    cout << "Creating subgraphs..." << endl;
    for ( unsigned long bidx = 0; bidx < cfg->getNetworks(); bidx++ )
    {
        _tg_subs.push_back(_tg->create_subgraph());
    }
    cout << "Finished creating subgraph structure." << endl;

    // Iterate over the buses...
    typedef graph_traits<NetworkGraph> GraphTraits;
    property_map<NetworkGraph, vertex_index_t>::type vindex = get(vertex_index, _ng);
    graph_traits<NetworkGraph>::adjacency_iterator ai;
    graph_traits<NetworkGraph>::adjacency_iterator ai_end;

    cout << "Creating task dependencies..."  << endl;
    unsigned long bidx;
    for ( bidx = 0; bidx < cfg->getNetworks(); bidx++ )
    {

        // Create a random graph between the tasks visible to that bus
        // (it could have almost any properties we want)

        //   Get the nodes for this bus
        //_tg_subs[bidx] = _tg.create_subgraph();
        for ( boost::tuples::tie(ai, ai_end) = adjacent_vertices(bidx, _ng); ai != ai_end; ++ai)
        {
            //   Get the tasks for this node
            Node * n = dynamic_cast<Node *>(_nets_nodes[vindex[*ai]]);
            for ( std::vector<Task>::iterator pT = n->_tasks.begin(); pT != n->_tasks.end(); pT++)
            {
                add_vertex( pT->id, _tg_subs[bidx] );
            }
        }

        //   Create a random graph using those tasks, and store a message length
        double p = cfg->getMsgProb();
        graph_traits<TaskGraph>::vertex_iterator vi, vi_end;
        graph_traits<TaskGraph>::vertex_iterator vi2, vi2_end;
        for ( boost::tuples::tie(vi, vi_end) = vertices(_tg_subs[bidx]); vi != vi_end; ++vi)
        {
            for ( boost::tuples::tie(vi2, vi2_end) = vertices(_tg_subs[bidx]); vi2 != vi2_end; ++vi2 )
            {
                if ( vi == vi2 )
                    continue;

                if ( _rnd.choose(p) )
                {
                    unsigned long msgln = _rnd.chooseInt(cfg->getMinMsgBytes(), cfg->getMaxMsgBytes());
                    ostringstream msgtag;
                    msgtag << bidx << "," << vindex[*vi] << "," << vindex[*vi2];
                    cout << "Adding " << msgtag.str() << " with length " << msgln << endl;
                    _tasks[vindex[*vi]]._msg_lengths[msgtag.str()] = msgln;
                    add_edge(*vi, *vi2, _tg_subs[bidx]);
                }
            }
        }
    }

    cout << "Creation finished." << endl;
}
// Output
bool NetGraph::print()
{
    cout << "Generating schedule file..." << endl;

    ConfigKeeper * cfg = ConfigKeeper::inst();
    ostringstream out;
    out << "% Schedule Generated by Tester" << endl;

    time_t tsecs;
    time( &tsecs );
    struct tm * timeinfo;
    timeinfo = localtime( &tsecs );

    char timestr[50];
    strftime(timestr, 99, "%H:%M:%S %a, %b %d, %Y", timeinfo);
    //out << "% at " << timestr << endl << endl;

    out << "Resolution " << fixed << cfg->getSysResolutionSecs() << "s" << endl << endl;

    std::vector< SystemObject * >::iterator nidx;
    for ( nidx = _nets_nodes.begin() + cfg->getNetworks(); nidx != _nets_nodes.end(); nidx++ )
    {
        Node * n = dynamic_cast< Node * >(*nidx);
        out << "Proc P" << n->id << " 100MHz 0s 0s" << endl;

        std::vector< Task >::iterator pTsk;
        for ( pTsk = n->_tasks.begin(); pTsk != n->_tasks.end(); pTsk++ )
        {
            double freq = 1.0;
            if ( (*pTsk)._periodSecs > 1.0e-12 )
            {
                freq = 1.0 / (*pTsk)._periodSecs;
            }
            out << "Comp C" << (*pTsk).id << " =" << freq << "Hz " << (*pTsk)._wcetSecs << "s" << endl;
        }

        out << endl;
    }

    unsigned long nnet, midx = 1;
    for ( nidx = _nets_nodes.begin(), nnet = 0; nnet < cfg->getNetworks(); nidx++, nnet++ )
    {
        Net * n = dynamic_cast< Net * >(*nidx);

        out << "Bus B" << n->id << " 1Mb 0s" << endl;

        // subgraph: _tg_subs[nnet]
        typedef property_map<TaskGraph, vertex_index_t>::type IndexMap;
        IndexMap index = get(vertex_index, _tg_subs[nnet]);

        graph_traits< TaskGraph >::edge_iterator ei, ei_end;
        for ( boost::tuples::tie(ei, ei_end) = edges(_tg_subs[nnet]); ei != ei_end; ++ei )
        {
            unsigned long t1idx = index[source(*ei, _tg_subs[nnet])];
            unsigned long t2idx = index[target(*ei, _tg_subs[nnet])];
            Task * t1 = &_tasks[t1idx];
            Task * t2 = &_tasks[t2idx];
            ostringstream msgtag;

            msgtag << nnet << "," << t1idx << "," << t2idx;
            std::map< std::string, unsigned long >::iterator msgln = t1->_msg_lengths.find(msgtag.str());
            // @todo: This is a bad hack -- change to eliminate the subgraph structure.  It's not what we need.
            if ( msgln != (t1->_msg_lengths).end())
            {
                cout << "Retrieving tag " << msgtag.str() << " with length " << t1->_msg_lengths[msgtag.str()] << endl;
                out << "Msg M" << midx++ << " " << t1->_msg_lengths[msgtag.str()] << "B ";
                out << "P" << t1->_parent << "/" << "C" << t1->id << " ";
                out << "P" << t2->_parent << "/" << "C" << t2->id << " " << endl;
            }
        }

        out << endl;
    }

    // Write it out to a file
    std::string filename(ConfigKeeper::inst()->getOutfileName());
    ofstream ofile( filename.c_str() );
    ofile << out.str();
    ofile.close();

    //SchedGen sg(std::string("TestDesign"));
    cout << "File generated." << endl;

    return false;
}