Guest Column
April 2006
Yan Chen, Marshall Crocker
MLD introduction
Mission Level Design (MLD) is a modeling and simulation platform that integrates major system-level modeling areas (architecture and function), and most simulation modeling domains in a single easy to use tool. MLD’s ability to model in multiple domains including Discrete Event (DE), Finite State Machine (FSM), three types of Dataflow (Dynamic, Synchronous, and Boolean) and Continuous Time/Discrete Event make it suitable for a wide range of modeling and simulation applications. The domains can be used individually or used together for complicated system simulation.
MLD models are defined graphically as hierarchical block diagrams. Blocks have defined inputs and outputs that are connected via visible links or via shared memories. Control and information is passed between blocks via particles (tokens) that consist of either a simple trigger particle or hierarchical data structure. Bottom level blocks contain primitives written in a form of C++ code. Higher-level blocks contain block diagrams. All blocks can be parameterized for easy “what if” analysis and to maximize block reusability. The task of building user’s blocks (library and system) in DE domain and primitive language construct are the focus of this tutorial. This tutorial assumes the user has at least read the ‘First Steps’ section of the MLD manual and has a basic understanding of the MLD platform.
MLD Simulation Design
Figure 1 shows a simulation system and library hierarchy created by the NGI group in IES. This library contains primitive definitions (e.g. RenoTCP primitive), modules, and systems (e.g. RenoTCPSystem) for simulating and evaluating network protocols and infrastructure. Based on this example, we examine the following three key points necessary for designing and implementing a simulation system using MLD:
- Requirements
- Architecture
- Implementation
Figure 1 - Reno TCP System
The first step to successfully creating and implementing a simulation system is to define the requirements and goals for the desired system. These requirements should be presented in a document that describes the purpose of the simulation system, the specific functions of the simulation, the necessary models of design, and all prerequisite system information. In our example, the Comm library serves as a general purpose library containing models necessary for performing networking simulations such as TCP performance, wireless communications, multimedia applications, routing, and so on. The details of our simulation system were generated collaboratively as a group and then recorded in a document.
Once the first version of the requirements document is complete, the next step is to design the architecture of the system based on the requirements. Architecture of a simulation system is concerned with the logical and functional relationship between primitives, modules, systems and libraries. A library is the highest level model in MLDesigner. It can be defined by different scales in terms of company (e.g. Comm Development), domain (e.g. DE Domain), role (e.g. Hosts and Network), and function (e.g. Reliable Transport and Users). A system incorporates modules or primitives from the same or different libraries in order to produce a system for executing a simulation model. Primitive is the lowest level element in MLDesigner with functionality defined using the Ptolemy language containing C++ code fragments while modules are several primtives grouped to perform a specific function. The block diagram of a primitive defines its external interface, whereas the primitive source code written in Ptolemy defines the behavior of the primitive.
The goal of architecture design is to define the logical and functional relationship between all MLD entities. The logical relationship describes the hierarchy of libraries, systems, modules, and primitives. The logical relation of the Comm Simulation library can be seen in Figure 2. The functional relationship describes how one entity uses another to accomplish a task. This relationship can be represented using "views" of the system that show different functional aspects of the model. Figure 3 is a functional representation of the Reno TCP system. In this system, the Simple User and RenoTCP primtives work together to simulate the Reno version of TCP.
Figure 2 - Logical Library Relationship
Figure 3 - RenoTCP System
The final step in simulation system design is the implementation. Implementation includes creating all libraries, systems, modules, and primitives as described by the requirements and architecture, creating any supporting data structures, and specifying the behavior of primtives through MLD primitive source code. The next sections examine in detail the specifics of definig primitives through source code.
MLD Source Code Keywords
After defining the library, system, primitive port parameters and data structures, the next step is to describe the behavior of primitive in source code. The following items can appear in a defprimitive item. We only explain the keywords appearing in the RenoTCP primitive.
-
Process control keywords: Begin and setup, cleanup and wrapup, constructor and destructor and go are processor control methods. In general, the task of MLDesigner primitive is to receive input particles and/or produce output particles. In addition, there may be side effects (reading or writing files, displaying graphs, or even updating shared data structures). As for all C++ objects, the constructor is called when the primitive is created, and the destructor is called when it is destroyed. The setup and begin methods –if any- are called every time a new simulation run is started, the go method is called each time a primitive is fired, and the wrapup and cleanup methods are called after simulation run completes.
-
Definition keywords: ccinclude and hinclude defines #include header file which will be included in PRIMITIVE_NAME.cc file, or PRIMITIVE_NAME.h file (i.e. DETCPReno.h are in DETCPReno.cc), code allows programmer to specify #define section into PRIMITIVE_NAME.cc file, protected declares extra variable members for the class, defparamater defines parameter’s type and default value through interface, input and output describes ports characteristic. Method provides a fully general way to specify an additional member function for the class of primitive, which is operated as sub-functions called in go method.
-
Shared resource keywords: Event, resource and memory are three shared resources provided in MLD. In DETCPReno.pl example, TCP design is based on asynchronous event trigger mechanism. We can add an event to the model using the tool button Add Event, and edit the event properties in an event editor window. Resource and memory definition are similar to that of event.
MLD Programming Guide
MLD go and method code are based on standard C++. Since MLD provides ports, data structures, and events, we list these specific operations and general usage as MLD programming reference.
-
Port Operation: In MLD manual section 17.4, port member functions are defined in class InDEPort and OutDEPort. PORT_NAME.before can be used to define the priority of simultaneous input port; PORT_NAME.dataNew returns a flag indicating whether the porthole has new data; PORT_NAME.get can get a particle from the porthole and return a reference of particle. PORT_NAME.put can put a particle into output port at given time stamp.
-
Queue and List Operation: In MLD manual section 13.15, MLD defines its own SequentialList and Queue operations. It can add or delete elements in the tail or header of queue and list, but it is not randomly accessible. If the operation needs to insert or delete the ith element in the queue, ListTypeR which is defined by MLD as normal list type operation should be the right way to do that. We can refer to three queues definition in DETCPReno.pl Example. To modify the element inside the list directly, we use getElementRef() instead of getElement() because getElement() returns a copy of the element inside the list and the element is not touched at all when only to modify the copy.
-
Event Operation: Event is triggered by time stamp. To schedule an event the method emitEvent(time, eventid) should be called, where the arguments represent the time at which the event will occur and the event ID which is used to identify the event. MLD keeps record of the queue of events which contains the scheduled times at which various events occurs and the location in the block diagram where the execution resumes once the event occurs. cancel(eventid) removes all entries with this id from the queue of events.
-
Create New Variable of Data Structure: The DsHandler class holds a list with all defined data structures. DsHandler::newValue(“TYPE_NAME”) can create data structure values and return reference of this value. DsHandler::newIntVector() and DsHandler::newFloatVector() can create array values. TypeRef class can instantiate a data structure (without using DsHandler) as well. TypeRef (“TYPE_NAME”) create an object that holds a reference to a TYPE_NAME data structure. But this object is destroyed automatically every time the destructor is called, that means the life time is over at the end of method.
-
Get and Set Value of Data Structure: getValue(), setValue(), getElement(), setElement() are the operations on basic type and vector. setField(), setFieldRef(), getField(), getFieldRef() are the operations on composite data type. getField() returns a copy of the element inside data structure while getFieldRef() returns a reference of the element. If we use getField() and never release it after using, memory leak happens.
-
How to avoid memory leak: It should be known exactly when a data structure must be cloned, when a data structure is a reference and whether a cloned value data structure must be released by calling die() manually. When we wan to handle the original value of data structure not the reference value (for example, methods that return data structure values, return a copy of the object inside), we need to use clone() and die() method.
-
Internal debug system: Not like other simulation software, we can’t debug MLD.pl file itself by tracing steps. MLD provides print and graph primitives to show the values of data structure variables or parameters. Referring to TCPReno system example, printDS, selectFieldDS and XMgraph are added into system for debugging. We also can add breakpoints on ports and see the data flows by turning on Textual Animation tool button.
-
External debug system: Internal debug system is definitely not enough for programmer. Here our group figures out how to debug MLD source code with external debugger. Take DETCPReno.pl as an example, the steps can refer to MLD_DEBUG file.
-
MLD with CVS: MLD was not designed with any type of built in versioning system in mind, nor was it designed to be used with an external versioning system. As a result, special steps are necessary to safely and correctly use MLD with a code versioning system. Our group set up steps to implement CVS controls MLD with referring to MLD_CVS file.
Conclusion
MLD is indeed a valuable tool for system level simulation and modeling. Its libraries contain more than 2000 design blocks and more than 400 example systems. Therefore, users can add new primitives and high level blocks, libraries, new domains and link to other tools by simply using existing blocks. As a result, MLD provides good scalability and extendibility to group design and development. By taking a methodical and detailed approach to simulation experimentation using MLD, researchers can test hypotheses in a fraction of the time it would take for anyltical analysis or real-world implementation.
Reference
- [MLD manual] MLDesign technologies, “MLDesigner Document v2.5”, 11th Nov, 2004
- [MLD_CVS] Marshall, NGI group, “Using MLD with CVS”, 24th Aug, 2005
- [MLD_DEBUG] Marshall, NGI group, “Using External Debugger with MLD”, 6th Feb, 2006
|