dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / HdsdModuleArchVisitor.java
diff --git a/dol/src/dol/visitor/hdsd/HdsdModuleArchVisitor.java b/dol/src/dol/visitor/hdsd/HdsdModuleArchVisitor.java
new file mode 100644 (file)
index 0000000..4b89646
--- /dev/null
@@ -0,0 +1,491 @@
+package dol.visitor.hdsd;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.Resource;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+import dol.visitor.ArchiVisitor;
+
+/**
+ * Visitor that generates the main program for one distributed simulator.
+ */
+public class HdsdModuleArchVisitor extends ArchiVisitor {
+
+    /**
+     * Constructor.
+     * @param map mapping of this code generation
+     * @param dir path of this file
+     */
+    public HdsdModuleArchVisitor(Mapping map, String dir) {
+        _map = map;
+        _dir = dir;
+        _channels = new LinkedHashSet<String>();
+        _remInChannels = new LinkedHashSet<String>();
+        _remOutChannels = new LinkedHashSet<String>();
+        _locChannels = new LinkedHashSet<String>();
+    }
+
+    /**
+     *
+     * @param x Processor that needs to be rendered
+     */
+    public void visitComponent(Processor x) {
+        
+        // get channels for this processor
+        _getChannels(x);
+        
+        try {
+            String filename = _dir + "/" + "scd_" + 
+                    x.getName() + ".cpp";
+            OutputStream file = new FileOutputStream(filename);
+            _mainPS = new CodePrintStream(file);
+
+            _mainPS.printPrefixln("#include <systemc>");
+            _mainPS.printPrefixln("#include <list>");
+
+            /* begin of profiling: standard i/o file handling routines */
+            _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+            _mainPS.printPrefixln("#include <stdio.h>");
+            _mainPS.printPrefixln("#endif");
+            /* end of profiling */
+
+            _mainPS.printPrefixln("#include \"dol_sched_if.h\"");
+            _mainPS.printPrefixln("#include \"simple_fifo.h\"");
+            _mainPS.printPrefixln("#include \"scd_logging.h\"");
+            _mainPS.printPrefixln("#include \"scd_simulator.h\"");
+            _mainPS.printPrefixln("#include \"scd_rem_fifo_in.h\"");
+            _mainPS.printPrefixln("#include \"scd_rem_fifo_out.h\"");
+            _mainPS.println();
+
+            // include process files
+            Iterator<Process> pIt = x.getProcessList().iterator();
+            Vector<String> pList = new Vector<String>();
+            while (pIt.hasNext()) {
+                Process p = pIt.next();
+                String basename = p.getBasename();
+                if (!pList.contains(basename)) {
+                    _mainPS.printPrefixln("#include \"" + p.getBasename()
+                            + "_wrapper.h\"");
+                    pList.add(basename);
+                }
+            }
+            _mainPS.println();
+            
+            // namespaces
+            _mainPS.printPrefixln("using namespace std;");
+            _mainPS.printPrefixln("using sc_core::sc_module;");
+            _mainPS.printPrefixln("using sc_core::sc_event;");
+            _mainPS.printPrefixln("using sc_core::sc_prim_channel;");
+
+
+            /* begin of profiling: global variables */
+            _mainPS.println();
+            _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+            _mainPS.printPrefixln("#define PROFILER_OUTPUT_FILENAME "
+                    + "\"profile_" + x.getName() + ".txt\"");
+            _mainPS.printPrefixln("FILE *profiler_output_file;");
+            _mainPS.printPrefixln("unsigned int profiler_event_counter;");
+            _mainPS.printPrefixln("#endif");
+            /* end of profiling */
+
+            _mainPS.println();
+            _mainPS.printPrefixln("class sc_application : public sc_module ");
+            _mainPS.printLeftBracket();
+
+            _mainPS.printPrefixln("public:");
+            _mainPS.printPrefixln("SC_HAS_PROCESS(sc_application);");
+
+            //declare processes
+            _mainPS.println();
+            pIt = x.getProcessList().iterator();
+            while (pIt.hasNext()) {
+                Process p = pIt.next();
+                _mainPS.printPrefixln(p.getBasename() + "_wrapper "
+                        + p.getName() + "_ins"+ ";");
+                _mainPS.printPrefixln("sc_event " + p.getName()
+                        + "_event;");
+            }
+            _mainPS.println();
+
+            //define the scheduler
+            _mainPS.printPrefixln("sc_event sched_event;");
+            _mainPS.printPrefixln("list<sc_event* > eventList;");
+            _mainPS.printPrefixln("list<sc_event* >::iterator iter;");
+            _mainPS.println();
+
+            //declare channels
+            _mainPS.println();
+            Iterator<String> cIt;
+            cIt = _locChannels.iterator();
+            while (cIt.hasNext())
+                _mainPS.printPrefixln("fifo " + cIt.next() + "_ins;");
+            cIt = _remInChannels.iterator();
+            while (cIt.hasNext())
+                _mainPS.printPrefixln("scd_rem_fifo_in " + cIt.next() + "_ins;");
+            cIt = _remOutChannels.iterator();
+            while (cIt.hasNext())
+                _mainPS.printPrefixln("scd_rem_fifo_out " + cIt.next() + "_ins;");
+            _mainPS.println();
+
+            // model constructor
+            _mainPS.printPrefixln("sc_application(sc_module_name name)");
+
+            // parameter of constructor (processes)
+            _mainPS.printPrefixln(":       sc_module(name),");
+            pIt = x.getProcessList().iterator();
+            while (pIt.hasNext()) {
+                Process p = pIt.next();
+                _mainPS.printPrefixln(p.getName() + "_ins(\""
+                        + p.getName() +"\"),");
+            }
+            
+            // parameter of constructor (channels)
+            cIt = _channels.iterator();
+            while (cIt.hasNext()) {
+                Channel c = _map.getPN().getChannel( cIt.next() );
+                _mainPS.printPrefix(c.getName() + "_ins(\""
+                                    + c.getName() +"\", "
+                                    + c.getSize()*c.getTokenSize()
+                                    + ")");
+                if (cIt.hasNext())
+                    _mainPS.println(",");
+                else
+                    _mainPS.println();
+            }
+            _mainPS.printLeftBracket();
+
+            //construtor content
+            //build the network
+            cIt = _channels.iterator();
+            while (cIt.hasNext())
+            {
+                Channel c = _map.getPN().getChannel(cIt.next());
+                c.accept( new HdsdModulePNVisitor(x, _mainPS) );
+            }
+            _mainPS.println();
+
+            _mainPS.println();
+
+            _mainPS.printPrefixln("SC_THREAD(thread_init);");
+            // init thread
+            _mainPS.printPrefixln("SC_THREAD(thread_sched);");
+
+            // declare concurrent non-terminating threads
+            pIt = x.getProcessList().iterator();
+            while (pIt.hasNext()) {
+                _mainPS.printPrefixln("SC_THREAD(thread_" +
+                        pIt.next().getName() + ");");
+            }
+            _mainPS.printRightBracket();
+            _mainPS.println();
+
+            //define scheduler thread
+            _mainPS.printPrefixln("void thread_init()");
+            _mainPS.printLeftBracket();
+            //init
+            pIt = x.getProcessList().iterator();
+            while (pIt.hasNext()) {
+                Process p = pIt.next();
+                _mainPS.printPrefixln(p.getName() + "_ins.initialize();");
+            }
+            _mainPS.printRightBracket();
+            _mainPS.println();
+
+
+            //different scheduling algorithm can be put here
+            _mainPS.printPrefixln("void thread_sched()");
+            _mainPS.printLeftBracket();
+            _mainPS.printPrefixln("while (1)");
+            _mainPS.printLeftBracket();
+            _mainPS.printPrefixln("for (iter=eventList.begin(); iter != "
+                    + "eventList.end(); ++iter)");
+            _mainPS.printLeftBracket();
+            _mainPS.printPrefixln("sc_event* e = (*iter);");
+            _mainPS.printPrefixln("e->notify();");
+            _mainPS.printRightBracket();
+            _mainPS.printPrefixln("eventList.clear();");
+            _mainPS.printPrefixln("wait(sched_event);");
+            _mainPS.printRightBracket();
+            _mainPS.printRightBracket();
+            _mainPS.println();
+
+            //define threads
+            pIt = x.getProcessList().iterator();
+            while (pIt.hasNext())
+                pIt.next().accept( new HdsdModulePNVisitor(x, _mainPS) );
+
+            /* begin of profiling: initialization function. */
+            /* - opens file */
+            /* - writes a list of all channels with the connected ports to the file. */
+            _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+            _mainPS.printPrefixln("void initialize_profiler()");
+            _mainPS.printLeftBracket();
+            _mainPS.printPrefixln("if ((profiler_output_file = fopen(PROFILER_OUTPUT_FILENAME,\"w\"))==NULL)");
+            _mainPS.printLeftBracket();
+            _mainPS.printPrefixln("printf(\"Unable to open profiler output file. No profiling output is written.\\n\");");
+            _mainPS.printPrefixln("return;");
+            _mainPS.printRightBracket();
+            //_mainPS.printPrefixln("printf(\"Profiling data is written to %s.\\n\", PROFILER_OUTPUT_FILENAME);");
+            _mainPS.println();
+
+            cIt = _channels.iterator();
+            while (cIt.hasNext()) {
+                String cName = cIt.next();
+                Channel ch = _map.getPN().getChannel(cName);
+                Iterator<Port> poIt = ch.getPortList().iterator();
+                String outputString = "fprintf(profiler_output_file, \"c " + ch.getName() + " " + ch.getSize();
+                String outputStringAppendix = "";
+                while (poIt.hasNext()) {
+                    Port p = poIt.next();
+                    Port peerPort = p.getPeerPort();
+                    Resource peerResource = p.getPeerResource();
+
+                    if (p.isOutPort()) {
+                        // channel.out == process.in
+                        String portAddr = null;
+                        if ( x.hasProcess(peerResource.getName()) )
+                            portAddr = "&(" + peerResource.getName()
+                            + "_ins.INPORT_" + peerPort.getBasename()
+                            + peerPort.getName().replace(
+                            peerPort.getBasename(), "").replaceAll(
+                            "_([0-9]+)", "[$1]") + ")";
+                        else
+                            portAddr = "0x00000000";
+                        outputString += " i " + peerResource.getName() + " %p";// + p.getPeerPort().getName();
+                        outputStringAppendix += "," + portAddr;
+                    } else {
+                        String portAddr = null;
+                        if ( x.hasProcess(peerResource.getName()) )
+                            portAddr = "&(" + peerResource.getName()
+                            + "_ins.OUTPORT_" + peerPort.getBasename()
+                            + peerPort.getName().replace(
+                            peerPort.getBasename(), "").replaceAll(
+                            "_([0-9]+)", "[$1]") + ")";
+                        else
+                            portAddr = "0x00000000";
+                        outputString += " o " + peerResource.getName() + " %p";// + p.getPeerPort().getName();
+                        outputStringAppendix += "," + portAddr;
+                    }
+                }
+                outputString += "\\n\"" + outputStringAppendix + ");";
+                _mainPS.printPrefixln(outputString);
+            }
+            _mainPS.printRightBracket();
+            _mainPS.printPrefixln("#endif");
+            _mainPS.println();
+            /* end of profiling */
+
+            _mainPS.printRightBracket(); // end of class
+            _mainPS.println(";");
+
+            //create and run the simulator
+            _mainPS.printPrefixln("int sc_main (int argc, char *argv[])");
+            _mainPS.printLeftBracket();
+
+            //create an instance of the application model
+            //remove potential whitespaces before using the process
+            //network name as a systemc identifier
+            _mainPS.printPrefixln("sc_application my_app_mdl(\""
+                    + x.getName().replaceAll(" ", "")  + "\");");
+
+            /* begin of profiling: initialize the profiler */
+            _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+            _mainPS.printPrefixln("my_app_mdl.initialize_profiler();");
+            _mainPS.printPrefixln("#endif");
+            _mainPS.printPrefixln();
+            /* end of profiling */
+
+            /* begin distributed simulation */
+            if (UserInterface.getInstance().getDebugFlag())
+                _mainPS.printPrefixln("scd_set_loglevel(SCD_DEBUG);");
+            else
+                _mainPS.printPrefixln("scd_set_loglevel(SCD_INFO);");
+            // simulator && master/slaves
+            Configuration opt = x.getCfg("master"); 
+            if (opt != null && opt.getValue().equals("true")) // master
+            {
+                // simulator constructor
+                _mainPS.printPrefixln("scd_simulator sim(\"" 
+                        + x.getName() + "\", \""
+                        + x.getCfg("address").getValue() + "\", "
+                        + x.getCfg("port").getValue() + ", SCD_MASTER);");
+                // register slaves
+                Iterator<Processor> iter = _map.getProcessorList().iterator();
+                while (iter.hasNext())
+                {
+                    Processor p = iter.next();
+                    opt = p.getCfg("master");
+                    if ( !(opt != null && opt.getValue().equals("true")) )
+                    {
+                        _mainPS.printPrefixln("sim.get_cont_man()."
+                                + "register_slave(\"" + p.getName()
+                                + "\");");
+                    }
+                }
+            } // end master
+            else // slave
+            {
+                // simulator constructor
+                _mainPS.printPrefixln("scd_simulator sim(\"" 
+                        + x.getName() + "\", \""
+                        + x.getCfg("address").getValue() + "\", "
+                        + x.getCfg("port").getValue() + ", SCD_SLAVE);");
+                // find and set master
+                Iterator<Processor> iter = _map.getProcessorList().iterator();
+                while (iter.hasNext())
+                {
+                    Processor p = iter.next();
+                    opt = p.getCfg("master");
+                    if (opt != null && opt.getValue().equals("true"))
+                    {
+                        _mainPS.printPrefixln("sim.get_cont_man().set_master(\""
+                                + p.getCfg("address").getValue() + "\", "
+                                + p.getCfg("port").getValue() + ");");
+                        break;
+                    }
+                }
+            } // end slave
+            
+            // register channels
+            // remote out channels
+            cIt = _remOutChannels.iterator();
+            while (cIt.hasNext())
+            {
+                String cName = cIt.next();
+                Channel c = _map.getPN().getChannel(cName);
+                Iterator<Port> poIt = c.getPortList().iterator();
+                Processor p = null;
+                while (poIt.hasNext())
+                {
+                    Port po = poIt.next();
+                    if (po.isOutPort())
+                    {
+                        Process pr = _map.getProcess(
+                                po.getPeerResource().getName() );
+                        p = pr.getProcessor();
+                    }
+                }
+                _mainPS.printPrefixln("sim.get_chan_man()."
+                        + "register_channel(\"" + cName + "\",");
+                _mainPS.printPrefixln("        my_app_mdl." + cName
+                        + "_ins, \"" + p.getCfg("address").getValue() + "\", "
+                        + p.getCfg("port").getValue() + ");");
+            }
+            // remote in channels
+            cIt = _remInChannels.iterator();
+            while (cIt.hasNext())
+            {
+                String cName = cIt.next();
+                _mainPS.printPrefixln("sim.get_chan_man().register_channel("
+                        + "\"" + cName + "\",");
+                _mainPS.printPrefixln("        my_app_mdl." + cName + "_ins);");
+            }
+            
+            // init & start
+            _mainPS.printPrefixln("bool ret = sim.init();");
+            _mainPS.printPrefixln("if (ret)");
+            _mainPS.prefixInc();
+                _mainPS.printPrefixln("ret = sim.start();");
+            _mainPS.prefixDec();
+            _mainPS.printPrefixln();
+            /* end distributed simulation */
+            
+            /* begin of profiling: close the output file */
+            _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+            _mainPS.printPrefixln("if (profiler_output_file != NULL) fclose(profiler_output_file);");
+            _mainPS.printPrefixln("#endif");
+            /* end of profiling */
+
+            _mainPS.printPrefixln("if (ret)");
+            _mainPS.prefixInc();
+            _mainPS.printPrefixln("return 0;");
+            _mainPS.prefixDec();
+            _mainPS.printPrefixln("else");
+            _mainPS.prefixInc();
+            _mainPS.printPrefixln("return 1;");
+            _mainPS.prefixDec();
+            
+            _mainPS.printRightBracket();
+
+        }
+        catch (Exception e) {
+            System.out.println("HdsdModuleVisitor: exception occured: "
+                    + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+    
+    
+    /**
+     * Retrieves all channels that have an endpoint on the specified
+     * processor and fills them into the channel sets.
+     * @param x the processor to get the channels for
+     */
+    private void _getChannels(Processor x)
+    {
+        Iterator<Channel> iter = _map.getPN().getChannelList().iterator();
+        
+        while (iter.hasNext())
+        {
+            Channel c = iter.next();
+            
+            boolean isIn = false;
+            boolean isOut = false;
+            
+            /* check if the in/out endpoint of this channel is on this
+             * processor
+             */
+            Iterator<Port> poIt = c.getPortList().iterator();
+            while (poIt.hasNext())
+            {
+                Port p = poIt.next();
+                if (x.hasProcess(p.getPeerResource().getName()))
+                {
+                    if (p.isInPort())   // inPort of channel = outport
+                        isOut = true;
+                    if (p.isOutPort()) // outPort of channel  = inport
+                        isIn = true;
+                }
+            }
+            
+            // add name to channel lists
+            if (isIn && isOut)
+            {
+                _channels.add(c.getName());
+                _locChannels.add(c.getName());
+            }
+            else if (isIn && !isOut)
+            {
+                _channels.add(c.getName());
+                _remInChannels.add(c.getName());
+            }
+            else if (!isIn && isOut)
+            {
+                _channels.add(c.getName());
+                _remOutChannels.add(c.getName());
+            }
+        }
+    } // _getChannels()
+    
+
+    protected CodePrintStream _mainPS = null;
+    protected String _dir = null;
+    protected Mapping _map = null;
+    
+    protected Set<String> _channels = null;
+    protected Set<String> _remInChannels = null;
+    protected Set<String> _remOutChannels = null;
+    protected Set<String> _locChannels = null;
+}