--- /dev/null
+/* $Id: SanityCheck.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.check;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
+import dol.datamodel.architecture.ArchiResource;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Connection;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Resource;
+
+/**
+ * Check semantic correctness of process network.
+ *
+ * This class checks
+ * <ul><li>whether it is a processnetwork</li>
+ * <li>a channel only has two ports</li>
+ * <li>each channel port has only one peer port of process</li>
+ * </ul>
+ */
+public class SanityCheck {
+ /**
+ * Return the singleton instance of this class;
+ *
+ * @return the instance.
+ */
+ public final static SanityCheck getInstance() {
+ return _instance;
+ }
+
+ /**
+ * Check if the process network spec is correct
+ *
+ * @param pn processnetwork to check
+ */
+ public void checkPN(ProcessNetwork pn) {
+ try {
+ _checkNameConflict(pn);
+ _checkChannelPorts(pn);
+ _checkChannelConnection(pn);
+ }
+ catch (Exception e) {
+ System.out.println("err: " + e.getMessage());
+ //e.printStackTrace();
+ System.exit(-1);
+ }
+
+ try {
+ _checkProcessConnection(pn);
+ }
+ catch (Exception e) {
+ System.out.println("warning: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Check if the architecture spec is correct
+ *
+ * @param arch architecture to check
+ */
+ public void checkArch(Architecture arch)
+ {
+ try
+ {
+ _checkNameConflict(arch);
+ _checkNETSIM(arch);
+ _checkMaster(arch);
+ }
+ catch (Exception e)
+ {
+ System.out.println("err: " + e.getMessage());
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Check if the mapping spec is correct
+ *
+ * @param map mapping to check
+ */
+ public void checkMap(Mapping map)
+ {
+ try
+ {
+ _checkMultibind(map);
+ _checkProcessesBound(map);
+ }
+ catch (Exception e)
+ {
+ System.out.println("err: " + e.getMessage());
+ System.exit(-1);
+ }
+ }
+
+
+ /**
+ * Check name exclusiveness, including processes, channels, and
+ * connections.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkNameConflict(ProcessNetwork pn) throws Exception {
+ System.out.println("APPL: Checking resource name ...");
+
+ Vector<Resource> n = new Vector<Resource>(pn.getChannelList());
+ n.addAll(pn.getProcessList());
+ n.addAll(pn.getConnectionList());
+
+ //sort resources in n by name
+ Collections.sort(n,
+ new Comparator<Resource>()
+ {
+ public int compare(Resource resource1, Resource resource2) {
+ return resource1.getName().compareTo(resource2.getName());
+ }
+ } );
+
+ //test adjacent resources in n for equal name
+ for (int k = 0; k < n.size() - 1; k++)
+ {
+ if (((Resource) n.elementAt(k)).getName().equals(
+ ((Resource) n.elementAt(k + 1)).getName())) {
+ throw new Exception("Name conflict: " +
+ ((Resource)n.elementAt(k + 1)).getName() +
+ " appears (at least) twice.");
+ }
+ }
+ }
+
+ /**
+ * Check number of ports for every channel.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkChannelPorts(ProcessNetwork pn) throws Exception {
+ System.out.println("APPL: Checking channel ports ...");
+
+ for (Channel c : pn.getChannelList()) {
+ if (c.getPortList().size() < 2) {
+ throw new Exception("channel ports less than 2: " +
+ c.getName());
+ }
+ }
+ }
+
+ /**
+ * Check whether all processes are connected.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkProcessConnection(ProcessNetwork pn)
+ throws Exception {
+ System.out.println("APPL: Checking Process connection ...");
+
+ String result = "";
+ boolean hasUnused = false;
+ for (Process r : pn.getProcessList()) {
+ boolean flag = false;
+ for (Connection c : pn.getConnectionList()) {
+ Resource origin = c.getOrigin();
+ Resource target = c.getTarget();
+ if (r.getName().equals(origin.getName())) {
+ flag = true; break;
+ } else if (r.getName().equals(target.getName())) {
+ flag = true; break;
+ }
+ }
+ if (flag == false) {
+ hasUnused = true;
+ result += " " + r.getName();
+ }
+ }
+
+ if (hasUnused == true)
+ throw new Exception("process(es) without connection to channels:" + result);
+ }
+
+ /**
+ * Check whether there are unused channels in the processnetwork.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkChannelConnection(ProcessNetwork pn)
+ throws Exception {
+ System.out.println("APPL: Checking channel connection ...");
+
+ String result = "";
+ boolean hasUnused = false;
+ for (Channel r : pn.getChannelList()) {
+ boolean flag = false;
+ for (Connection c: pn.getConnectionList()) {
+ Resource origin = c.getOrigin();
+ Resource target = c.getTarget();
+ if (r.getName().equals(origin.getName())) {
+ flag = true; break;
+ } else if (r.getName().equals(target.getName())) {
+ flag = true; break;
+ }
+ }
+ if (flag == false) {
+ hasUnused = true;
+ result += " " + r.getName();
+ }
+ }
+
+ if (hasUnused == true)
+ throw new Exception("unused channel: " + result);
+ }
+
+
+ /**
+ * Check name exclusiveness, including both processors and memories.
+ *
+ * @param arch architecture to check
+ */
+ private void _checkNameConflict(Architecture arch) throws Exception {
+ System.out.println("ARCH: Checking resource name ...");
+ Vector<ArchiResource> n = new Vector<ArchiResource>(arch.getProcessorList());
+ n.addAll(arch.getMemoryList());
+
+ //sort resources in n by name
+ Collections.sort(n,
+ new Comparator<ArchiResource>()
+ {
+ public int compare(ArchiResource resource1, ArchiResource resource2) {
+ return resource1.getName().compareTo(resource2.getName());
+ }
+ } );
+
+ //test adjacent resources in n for equal name
+ for (int k = 0; k < n.size() - 1; k++)
+ {
+ if (((ArchiResource) n.elementAt(k)).getName().equals(
+ ((ArchiResource) n.elementAt(k + 1)).getName())) {
+ throw new Exception("Name conflict: " +
+ ((ArchiResource)n.elementAt(k + 1)).getName() +
+ " appears (at least) twice.");
+ }
+ }
+ }
+
+ /**
+ * every processor of type NETSIM must have a configuration tag with
+ * name "address" and one with name "port". these address-port pairs
+ * have to be unique
+ * @param arch
+ * @throws Exception
+ */
+ private void _checkNETSIM(Architecture arch) throws Exception
+ {
+ System.out.println("ARCH: Checking network simulators ...");
+
+ Vector<Processor> sockets = new Vector<Processor>();
+
+ for (Processor proc : arch.getProcessorList()) {
+ if ( proc.getType().equals("NETSIM") )
+ {
+ if ( proc.getCfg("address") == null
+ || proc.getCfg("port") == null )
+ {
+ throw new Exception("Processor " + proc.getName() +
+ " is of type NETSIM but address or port is missing");
+ }
+ if ( proc.getCfg("address").equals("")
+ || proc.getCfg("port").equals("") )
+ {
+ throw new Exception("Processor " + proc.getName() +
+ " has empty address or port");
+ }
+ sockets.add(proc); // add processor to socket list
+ }
+ }
+
+ /* socket comperator */
+ Comparator<Processor> sockComp = new Comparator<Processor>()
+ {
+ public int compare(Processor proc1, Processor proc2)
+ {
+ String ad1, ad2;
+ ad1 = proc1.getCfg("address").getValue();
+ ad2 = proc2.getCfg("address").getValue();
+
+ int comp = ad1.compareToIgnoreCase(ad2);
+
+ if (comp != 0)
+ {
+ return comp;
+ }
+ else
+ {
+ String p1, p2;
+ p1 = proc1.getCfg("port").getValue();
+ p2 = proc2.getCfg("port").getValue();
+
+ return p1.compareToIgnoreCase(p2);
+ }
+ }
+ };
+
+
+ /* sort sockets */
+ Collections.sort(sockets, sockComp);
+
+ /* check for uniqueness */
+ Processor proc1 = null;
+ Processor proc2 = null;
+ if (!sockets.isEmpty())
+ proc1 = sockets.get(0);
+ for (int i=1; i<sockets.size(); i++)
+ {
+ proc2 = sockets.get(i);
+ if (sockComp.compare(proc1, proc2) == 0)
+ {
+ throw new Exception("multiple processors with hostname \"" +
+ proc1.getCfg("address").getValue() +
+ "\" and port " + proc1.getCfg("port").getValue() +
+ " exist");
+ }
+ proc1 = proc2;
+ }
+ } // _checkNETSIM()
+
+
+ /**
+ * Checks that exactly one master simulator is defined if
+ * processors of type "NETSIM" exist.
+ * @param arch the architecture to check
+ * @throws Exception
+ */
+ private void _checkMaster(Architecture arch) throws Exception
+ {
+ boolean hasMaster = false;
+ boolean hasHosts = false;
+
+ for (Processor p : arch.getProcessorList()) {
+ if (p.getType().equals("NETSIM"))
+ {
+ hasHosts = true;
+ Configuration opt = p.getCfg("master");
+ if (opt != null && opt.getValue().equals("true"))
+ {
+ if (hasMaster)
+ throw new Exception("multiple master simulators"
+ + "defined");
+ else
+ hasMaster = true;
+
+ }
+ }
+ }
+
+ if (hasHosts && !hasMaster)
+ throw new Exception("no master simulator defined");
+
+ } // _checkMaster()
+
+ /**
+ * Check that software resources bind only to one hardware resource.
+ *
+ * @param map mapping to check
+ */
+ private void _checkMultibind(Mapping map) throws Exception {
+ System.out.println("MAP: Checking multiple bindings ...");
+ Vector<Process> processes = map.getProcessList();
+
+ //sort processes in n by name
+ Collections.sort(processes,
+ new Comparator<Process>()
+ {
+ public int compare(Process p1, Process p2) {
+ return p1.getName().compareTo(p2.getName());
+ }
+ } );
+
+ //test adjacent origins for equal name
+ String o1 = null;
+ String o2 = null;
+ if (!processes.isEmpty())
+ o1 = processes.get(0).getName();
+ for (int k = 1; k < processes.size(); k++)
+ {
+ o2 = processes.get(k).getName();
+ if (o1.equals(o2))
+ {
+ throw new Exception("sw resource \"" + o1 +
+ "\" has multiple bindings");
+ }
+ }
+ }
+
+ /**
+ * Checks that every process is bound to a processor.
+ * @param map the map to check
+ * @throws Exception if not all processes are bound to a processor
+ */
+ private void _checkProcessesBound(Mapping map) throws Exception
+ {
+ System.out.println("MAP: Checking that all processes have a binding ...");
+ Vector<Process> boundList = map.getProcessList();
+ Vector<Process> totalList = map.getPN().getProcessList();
+
+ if (boundList.size() != totalList.size())
+ {
+ throw new Exception("some processes are not bound to a processor");
+ }
+ }
+
+ /**
+ * singleton instance
+ */
+ private final static SanityCheck _instance = new SanityCheck();
+}