/* * muxtree :- a tree of multiplexers. * * Muxtree is a model that builds a simple network of ssf * entities. The topology of this model is a tree: the leaves of the * tree are traffic sources and the interior nodes (including the * root) of the tree are multiplexers. Messages are generated from the * source node and travel through a series of multiplexers until it * reaches the root of the tree. Within each multiplexer, there is a * FIFO queue that has a buffer with a finite size and each message is * given a constant service time. Messages could be dropped if a * buffer overflow occurs. A detailed description of this example is * given in the SSF User's Manual. */ #ifndef __MUXTREE_H__ #define __MUXTREE_H__ #include "ssf.h" // the standard ssf header file using namespace prime::ssf; using namespace prime::rng; using namespace prime::dml; #define SECOND 1000000 // simulation time resolution: 1 microsecond = 1 tick #define TICKS2SECS(x) (double(x)/SECOND) // convert from ticks to seconds #define MUXTREE_LEVELS 3 // number of levels of multiplexers #define MUXTREE_FANIN 8 // fan-in at each multiplexer #define TRANSMISSION_DELAY ltime_t(1*SECOND) // channel delay #define SRC_ENTITY_IAT ltime_t(1*SECOND) // inter-arrival time (in seconds) #define MUX_ENTITY_BUFSIZ 6 // size of the FIFO queue #define MUX_ENTITY_MST ltime_t(1*SECOND) // mean service time (in seconds) /* * Each user message, which travels from the source node through * multiplexer nodes and ultimately to the tree root, is an ssf * event. It contains the time at which the message was created, and * the id of the source node where it was created. */ class MyMessage : public Event { public: ltime_t time; // simulation time is of ltime_t type int srcid; // id of the source node // The constructor. MyMessage(ltime_t tm, int sid) : time(tm), srcid(sid) {} // The copy constructor and the clone method are required by ssf, // so that, when the message is crossing processor boundaries, the // message will be copied implicitly by the ssf runtime system. MyMessage(const MyMessage& msg) : time(msg.time), srcid(msg.srcid) {} virtual Event* clone() { return new MyMessage(time, srcid); } // The following method is also required by ssf, so that, when the // message is crossing memory space bounaries (in a distributed // simulation environment), the message will be serialized into a // platform-independent byte array (represented by the ssf_compact // class). At the remote machine, the ssf instance will unpack // (i.e., deserialize) the byte array into a new event object using // a factory method associated with this event class. virtual ssf_compact* pack() { ssf_compact* dp = new ssf_compact; // create a new byte array dp->add_ltime(time); // serialize the time value into the array dp->add_int(srcid); // serialize the source node id into the array return dp; // return the array back to the ssf runtime system } // This is the factory method of this event object. It is required // by ssf so that the message can be copied to another ssf instance // running on a separate memory space in a distributed memory // environment. The method is static. We need to register this // factory method with the ssf runtime system using the // SSF_REGISTER_EVENT macro in the source file. static Event* create_my_message(ssf_compact* dp) { ltime_t tm; int sid; if(!dp || !dp->get_ltime(&tm) || !dp->get_int(&sid)) return 0; // return null if anything unexpected happen return new MyMessage(tm, sid); // return the newly created event object } // This macro is required by ssf. Every user-defined event class // (derived from the Event base class) must be declared using // SSF_DECLARE_EVENT in its class definition. SSF_DECLARE_EVENT(MyMessage); }; /*MyMessage*/ /* * SourceEntity is an entity class that models a traffic source. The * source nodes are at the tree leaves. Each SourceEntity object * generates messages using an exponentially distributed random * variable with a specified mean inter-arrival time. */ class SourceEntity : public Entity { public: int id; // id of the source node long nsent; // statistics: number of messages generated by this multiplexer Random rng; // the random number generator (it's a state variable) outChannel* oc; // output channel used to connect to a multiplexer // constructor. SourceEntity(int myid); }; /*SourceEntity*/ /* * EmitProcess represents a ssf process that generates messages for * the corresponding traffic source node. */ class EmitProcess : public Process { public: // The constructor. EmitProcess(SourceEntity* owner) : Process(owner) {} // The traffic source node is the owner entity of this process. SourceEntity* owner() { return (SourceEntity*)Process::owner(); } // The method is the process's starting procedure. virtual void action(); //! SSF PROCEDURE }; /*EmitProcess*/ /* * MultiplexerEntity is an entity class that models a multiplexer in * this model. Each multiplexer enques each incoming message in a FIFO * queue, serves the message in the front of the queue with a constant * service time, and then forwards it to the multiplexer at the next * level of the tree. */ class MultiplexerEntity : public Entity { public: int level; // tree level of the multiplexer int id; // id of the multiplexer (within each tree level) long nrcvd; // statistics: number of received messages long nlost; // statistics: number of messages dropped due to overflow long nsent; // statistics: number of messages sent from this multiplexer MyMessage** buf; // buffered messages are stored in a circular list int tail; // index to the tail of the buffer int head; // index to the head of the buffer int qlen; // number of messages enqueued inChannel* ic; // input channel used to receive messages (from preivous multiplexer or source node) outChannel* oc; // output channel to send messages (to the multiplexer at the next tree level) inChannel* int_ic; // internal input channel outChannel* int_oc; // internal output channel // constructor and destructor. MultiplexerEntity(int mylevel, int myid); virtual ~MultiplexerEntity(); virtual void init(); // create the source node if the multiplexer is at level 0 virtual void wrapup(); // dump statistics at the end of simulation // the starting procedure for the arrival process, which is simple. void arrive(Process*); //! SSF PROCEDURE SIMPLE // the starting procedure for the service process. void serve(Process*); //! SSF PROCEDURE }; /*MultiplexerEntity*/ #endif /*__MUXTREE_H__*/