--- /dev/null
+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;
+}