PLC Factory – Automating Large-Scale PLC Development

I spent this summer working at the European Spallation Source (ESS) in Lund, Sweden. My contribution was the creation of PLC Factory, a tool that automates development for programmable logic controllers (PLCs). A paper on this project is forthcoming.

The code of PLC Factory is available on the Bitbucket account of ESS. PLC Factory was developed as FOSS. Thus, I can make the code I wrote available on my private GitLab account as well.

The draft of the PLC Factory paper is likewise available on GitLab. Here is the full title information including the abstract:

PLC FACTORY: AUTOMATING ROUTINE TASKS IN LARGE-SCALE PLC SOFTWARE DEVELOPMENT

Authors:
G. Ulm, D. Brodrick, N. Levchenko, F. Bellorini

Abstract:
At the European Spallation Source in Lund, Sweden, the entire facility including all its instruments will be controlled by a large number of programmable logic controllers (PLCs). Programming PLCs, however, entails a significant amount of repetition. It is thus an error-prone and time-consuming task. Given that PLCs interface with hardware, this involves economic aspects as well, due to the fact that programming errors may cause damage to equipment. With PLC Factory, we managed to automate repetitive tasks associated with PLC programming and interfacing PLCs from EPICS. This tool is being adopted at ESS, and has shown potential for a large increase in productivity compared to the status quo. We describe PLC Factory as well as its embedded domain-specific programming language PLCF#, which it is built upon.

CodingBat: Java. Map-2

Here are my solutions to the Map-2 section on CodingBat.

word0:

public Map<String, Integer> word0(String[] strings) {
  
  Map<String, Integer> map = new HashMap<String, Integer>();
  
  for (int i = 0; i < strings.length; i++) {
    map.put(strings[i], 0);
  }
  
  return map;
}

wordLen:

public Map<String, Integer> wordLen(String[] strings) {
    
  Map<String, Integer> map = new HashMap<String, Integer>();
  
  for (int i = 0; i < strings.length; i++) {
    String tmp = strings[i];
    map.put(tmp, tmp.length());
  }
  
  return map;
}

pairs:

public Map<String, String> pairs(String[] strings) {
  
  Map<String, String> map = new HashMap<String, String>();
  
  for (int i = 0; i < strings.length; i++) {
    String tmp   = strings[i];
    String first = String.valueOf(tmp.charAt(0));
    String last  = String.valueOf(tmp.charAt(tmp.length() - 1));
    map.put(first, last);
  }
  
  return map;
}

wordCount:

public Map<String, Integer> wordCount(String[] strings) {
  
  Map<String, Integer> map = new HashMap<String, Integer>();
  
  for (int i = 0; i < strings.length; i++) {
    
    String tmp = strings[i];
    
    if (map.containsKey(tmp)) {
      int count = map.get(tmp);
      map.put(tmp, count + 1);
    } else {
      map.put(tmp, 1);
    }
    
  }
  return map;
}

firstChar:

public Map<String, String> firstChar(String[] strings) {
  
  Map<String, String> map = new HashMap<String, String>();
  
  for (int i = 0; i < strings.length; i++) {
    
    String key = String.valueOf(strings[i].charAt(0));
    
    if (map.containsKey(key)) {
      String val = map.get(key) + strings[i];
      map.put(key, val);
    } else {
      map.put(key, strings[i]);
    }
    
  }
  return map;
}

wordAppend:

public String wordAppend(String[] strings) {
 
 Map<String, Integer> map    = new HashMap<String, Integer>();
 String               result = "";
 
 for (int i = 0; i < strings.length; i++) {
   
   String key = strings[i];
   
   if (map.containsKey(key)) {
     int val = map.get(key);
     val++;
     if (val % 2 == 0) {
      result += key;
     }
     map.put(key, val);
   } else {
     map.put(key, 1);
   }
   
 }
 
 return result;
}

wordMultiple:

public Map<String, Boolean> wordMultiple(String[] strings) {
  
  Map<String, Integer> counts = new HashMap<String, Integer>();
  Map<String, Boolean> result = new HashMap<String, Boolean>();
  
  for (int i = 0; i < strings.length; i++) {
    String key = strings[i];
    
    if (counts.containsKey(key)) {
      int val = counts.get(key);
      val++;
      counts.put(key, val);
    } else {
      counts.put(key, 1);
    }
    
    result.put(key, counts.get(key) >= 2);
  }
  
  return result;
}

allSwap:

public String[] allSwap(String[] strings) {
  
  Map<String, Integer> map = new HashMap<String, Integer>();
    
  for (int i = 0; i < strings.length; i++) {
    
    String key = String.valueOf(strings[i].charAt(0));
    
    if (map.containsKey(key)) {
      
      // swap
      int    pos   = map.get(key); 
      String tmp   = strings[pos];
      strings[pos] = strings[i];
      strings[i]   = tmp ;
      
      // delete
      map.remove(key);
      
    } else {
      map.put(key, i);
    }
    
  }
  
  return strings;
}

firstSwap:

public String[] firstSwap(String[] strings) {
  
  Map<String, Integer> map = new HashMap<String, Integer>();
    
  for (int i = 0; i < strings.length; i++) {
    
    String key = String.valueOf(strings[i].charAt(0));
    
    if (map.containsKey(key)) {
      
      int val = map.get(key);
      if (val == -1) {
        continue;
      }
      
      // swap
      int    pos   = map.get(key); 
      String tmp   = strings[pos];
      strings[pos] = strings[i];
      strings[i]   = tmp ;
      
      // set a flag
      map.put(key, -1);
      
    } else {
      map.put(key, i);
    }
    
  }
  
  return strings;
}

CodingBat: Java. Map-1

Nick Parlante updated CodingBat with two new sets of Java exercises, which both focus on maps. My solutions for Map-1 are below.

mapBully:

public Map<String, String> mapBully(Map<String, String> map) {
  
  if (map.containsKey("a")) {
    String tmp = map.get("a");
    map.put("a", "");
    map.put("b", tmp);
  }
  
  return map;
}

mapShare:

public Map<String, String> mapShare(Map<String, String> map) {
  
  if (map.containsKey("a")) {
    String tmp = map.get("a");
    map.put("b", tmp);
  }
  
  map.remove("c");
      
  return map;
}

mapAB:

public Map<String, String> mapAB(Map<String, String> map) {
  
  if (map.containsKey("a") && map.containsKey("b")) {
    String tmp = map.get("a") + map.get("b");
    map.put("ab", tmp);
  }
  
  return map;
}

topping1:

public Map<String, String> topping1(Map<String, String> map) {
  
  if (map.containsKey("ice cream")) {
    map.put("ice cream", "cherry");
  }
  
  map.put("bread", "butter");
  
  return map;
}

topping2:

public Map<String, String> topping2(Map<String, String> map) {
  
  if (map.containsKey("ice cream")) {
    map.put("yogurt", map.get("ice cream"));
  }
  
  if (map.containsKey("spinach")) {
    map.put("spinach", "nuts");
  }

  return map;
}

topping3:

public Map<String, String> topping3(Map<String, String> map) {
  
  if (map.containsKey("potato")) {
    map.put("fries", map.get("potato"));
  }
  
  if (map.containsKey("salad")) {
    map.put("spinach", map.get("salad"));
  }

  return map;
  
}

Cryptographic Block Ciphers in Functional Programming: A Case Study on Feldspar and AES

Last semester I had the opportunity to do an independent research project at Chalmers. Abstract and link to the repository as well as the final report are below.

Title: Cryptographic Block Ciphers in Functional Programming: A Case Study on Feldspar and AES

Supervisor: Michal Palka

Examiner: Mary Sheeran

Abstract:
Cryptographic block ciphers are defined as mathematical functions, and thus a prime candidate for implementation in functional programming languages. We implement the block cipher Rijndael, which was selected as the block cipher used for the Advanced Encryption Standard (AES), in Cryptol, Haskell, Feldspar, and C. We analyze how well Feldspar, a language originally designed for digital signal processing, is suited to this task. We highlight relative strengths and weaknesses of Feldspar for implementing cryptographic block ciphers, and suggest possible improvements to this language.

Repository: https://gitlab.com/gregor_ulm/dat085_feldspar

Report: https://gitlab.com/gregor_ulm/dat085_feldspar/blob/master/GregorUlm.FinalReport.May31.pdf