package org.cellocad.MIT.dnacompiler;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.StringTokenizer;
/**
* Created by Bryan Der on 8/5/15.
*/
public class StructuralVerilogToDAG {
public static LogicCircuit createDAG(String fin_verilog) {
ArrayList<Wire> wires = new ArrayList<>();
LinkedHashMap<String, Gate> gate_map = new LinkedHashMap<>();
ArrayList<String> input_names = new ArrayList<>();
ArrayList<String> output_names = new ArrayList<>();
ArrayList<String> verilog_lines = Util.fileLines(fin_verilog);
ArrayList<String> gate_lines = new ArrayList<>();
for(String line: verilog_lines) {
if(line.startsWith("module") ) {
ArrayList<String> tokens = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(line, " \t\n\r\f,();");
while (st.hasMoreTokens()) {
tokens.add(st.nextToken());
}
boolean is_output = false;
for(String token: tokens) {
if(is_output) {
if(token.equals("input")) {
break;
}
output_names.add(token);
}
if(token.equals("output")) {
is_output = true;
}
}
boolean is_input = false;
for(String token: tokens) {
if(is_input) {
if(token.equals("output")) {
break;
}
input_names.add(token);
}
if(token.equals("input")) {
is_input = true;
}
}
}
//Wire lines?
if(line.contains("not") || line.contains("nor")) {
gate_lines.add(line);
}
}
for(String input_name: input_names) {
Gate g = new Gate();
g.Name = input_name;
g.Type = Gate.GateType.INPUT;
gate_map.put(input_name, g);
g.set_unvisited(false);
}
for(String output_name: output_names) {
Gate g = new Gate();
g.Name = output_name;
g.Type = Gate.GateType.OUTPUT;
gate_map.put(output_name, g);
}
int wire_count = 0;
for(int gi=0; gi<gate_lines.size(); ++gi) {
String line = gate_lines.get(gi);
String gate_name = "g" + (gi+1);
Integer gate_index = (gi+1);
ArrayList<String> tokens = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(line, " \t\n\r\f,()");
while (st.hasMoreTokens()) {
tokens.add(st.nextToken());
}
String gate_type = tokens.get(0);
String fanout = tokens.get(1);
ArrayList<String> fanin = new ArrayList<>();
for(int i=2; i<tokens.size()-1; ++i) {
fanin.add(tokens.get(i));
}
Gate g = new Gate();
g.Name = gate_name;
g.Index = gate_index;
//Check only not and nor?
if(gate_type.equals("not")) {
g.Type = Gate.GateType.NOT;
}
if(gate_type.equals("nor")) {
g.Type = Gate.GateType.NOR;
}
gate_map.put(g.Name, g);
for(String output_name: output_names) {
if(fanout.equals(output_name)) {
}
}
Wire prev = null;
for(int i=0; i<fanin.size(); ++i) {
String fanin_name = fanin.get(i);
Wire w = new Wire();
w.Name = fanin_name;
w.From = g;
w.Index = wire_count;
if(i==0) {
g.Outgoing = w;
}
else {
prev.Next = w;
}
prev = w;
wire_count++;
wires.add(w);
}
}
for(String output_name: output_names) {
Gate g = gate_map.get(output_name);
for(Wire w: wires) {
if(w.Name.equals(output_name)) {
g.Outgoing = w;
}
}
}
for(int gi=0; gi<gate_lines.size(); ++gi) {
String line = gate_lines.get(gi);
ArrayList<String> tokens = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(line, " \t\n\r\f,()");
while (st.hasMoreTokens()) {
tokens.add(st.nextToken());
}
String fanout_name = tokens.get(1);
String gate_name = "g" + (gi+1);
Gate g = gate_map.get(gate_name);
for(Wire w: wires) {
if(w.Name.equals(fanout_name)) {
w.To = g;
}
else {
for(String input_name: input_names) {
if(w.Name.equals(input_name)) {
w.To = gate_map.get(input_name);
}
}
for(String output_name: output_names) {
if(w.Name.equals(output_name)) {
w.From = gate_map.get(output_name);
}
}
}
}
ArrayList<String> fanin = new ArrayList<>();
for(int i=2; i<tokens.size()-1; ++i) {
fanin.add(tokens.get(i));
}
for(int i=0; i<fanin.size(); ++i) {
String fanin_name = fanin.get(i);
for(String output_name: output_names) {
if(fanin_name.equals(output_name)) {
Wire w = new Wire();
w.Name = fanin_name;
w.Index = wire_count;
w.From = g;
w.To = gate_map.get(output_name).Outgoing.To;
wire_count++;
wires.add(w);
}
}
}
}
ArrayList<Gate> gates = new ArrayList<>(gate_map.values());
for(int i=0; i<gates.size(); ++i) {
Gate g = gates.get(i);
g.Index = i;
}
LogicCircuit lc = new LogicCircuit(gates, wires);
return lc;
}
}