// ---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // ---------------------------------------------------------------------------- using System.Collections; using System.Text; using System.IO; using System; //using Microsoft.Zap; namespace SharpSAT { public class NetConst { public const int PI_MASK = 1; public const int PO_MASK = (1 << 1); public const int LATCH_OUT_MASK = (1 << 2); public const int LATCH_IN_MASK = (1 << 3); public const int COMB_MASK = (1 << 4); //private NetConst() {} } public enum ELatchDefault { LATCH_0 = 0, LATCH_1 = 1, LATCH_DC = 2, LATCH_X = 3 }; public enum EGateType { G_UNKNOWN, G_NOT, //o = a' G_AND_11, //o = ab G_AND_10, //o = ab' G_AND_01, //o = a'b G_AND_00, //o = a'b' G_OR_11, //o = a+b G_OR_10, //o = a+b' G_OR_01, //o = a'+b G_OR_00, //o = a'+b' G_CONST_1, G_CONST_0, G_WIRE, }; public class Gate { public int index = -1; public EGateType gate_type = EGateType.G_UNKNOWN; public string name; public IntVector fanins = new IntVector(2); public IntVector fanouts = new IntVector(2); public int type ; public ELatchDefault latch_default ; public ObjVector fanin_names = new ObjVector(1); public bool is_PI() { return ((type & NetConst.PI_MASK) != 0); } public bool is_PO() { return ((type & NetConst.PO_MASK) != 0); } public bool is_LATCH_IN() { return ((type & NetConst.LATCH_IN_MASK) != 0); } public bool is_LATCH() { return ((type & NetConst.LATCH_OUT_MASK) != 0); } public bool is_COMB() { return ((type & NetConst.COMB_MASK) != 0); } public void set_PI() { type |= NetConst.PI_MASK; } public void set_PO() { type |= NetConst.PO_MASK; } public void set_LATCH_IN() { type |= NetConst.LATCH_IN_MASK; } public void set_LATCH() { type |= NetConst.LATCH_OUT_MASK; } public void set_COMB() { type |= NetConst.COMB_MASK; } } class NetList : SATCommon { public string name; public ObjVector nodes = new ObjVector(128); public IntVector primary_inputs = new IntVector(4); public IntVector primary_outputs = new IntVector(4); public IntVector latches = new IntVector(4); public IntVector combs = new IntVector(4); public IntVector inputs = new IntVector(4); //include PI and latch's outputs public IntVector outputs = new IntVector(4); //include PO and latch's inputs public MyHashtable name2nodeid = new MyHashtable(); public Gate node (int k) { return (Gate)nodes[k]; } Gate new_node(string name) { Gate node = new Gate(); node.name = name;; node.index = nodes.size(); nodes.push_back(node); name2nodeid[name] = node.index; return node; } Gate find_node_by_name(string name) { object o = name2nodeid[name]; if (o == null) return null; else return (Gate)nodes[(int)o]; } Gate create_pi(string name) { Gate n; if ((n = find_node_by_name(name)) != null) { sharp_assert (n.is_PI()); return n; } n = new_node(name); n.set_PI(); return n; } Gate create_po(string name) { Gate n; if ((n = find_node_by_name(name)) == null) n = new_node(name); n.set_PO(); return n; } Gate create_latch(string latch_in, string latch_out, ELatchDefault deft) { Gate n; if ((n = find_node_by_name(latch_out)) == null) n = new_node(latch_out); //int id = n.index; sharp_assert (n.fanin_names.empty()); n.fanin_names.push_back(latch_in); n.latch_default = deft; n.set_LATCH(); return n; } Gate create_comb(string name, string [] inputs) { Gate n; if ((n = find_node_by_name(name)) == null) n = new_node(name); //int id = n.index; sharp_assert (n.fanin_names.empty()); foreach (string s in inputs) n.fanin_names.push_back(s); n.set_COMB(); return n; } static string get_multiple_line (StreamReader input) { string line = null; StringBuilder str = new StringBuilder(); while (true) { try { line = input.ReadLine(); } catch (Exception e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); fatal(); } if (line == null) return null; if (line.IndexOf('\\') == -1) { str.Append(line); return str.ToString(); } else str.Append(line.Replace('\\',' ')); } } void finalize_construct_network() { for (int i = 0; i < nodes.size(); ++i) { Gate n = node(i); for (int j = 0; j < n.fanin_names.size(); ++j) { string name = (string)n.fanin_names[j]; Gate pin = find_node_by_name(name); sharp_assert (pin != null); n.fanins.push_back(pin.index); pin.fanouts.push_back(n.index); if (n.is_LATCH()) pin.set_LATCH_IN(); } } for (int i = 0; i < nodes.size(); ++i) { Gate n = node(i); if (n.is_PI()) primary_inputs.push_back(n.index); if (n.is_PI() || n.is_LATCH()) inputs.push_back(n.index); if (n.is_PO()) primary_outputs.push_back(n.index); if (n.is_PO() || n.is_LATCH_IN()) outputs.push_back(n.index); if (n.is_LATCH()) latches.push_back(n.index); if (n.is_COMB()) combs.push_back(n.index); } } public void read_blif (string filename) { StreamReader input = null; ObjVector lines = new ObjVector(128); try { input = new StreamReader(filename); } catch (Exception e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); fatal(); } while (true) { string line = get_multiple_line(input); if (line == null) break; lines.push_back(line); if (line == ".end") break; } for (int i = 0; i < lines.size(); ++i) { string line = (string)lines[i]; string [] temp_tokens = line.Split(new char[] {' ','\t'}); int total_tokens = 0; foreach (string str in temp_tokens) if (str != String.Empty) ++ total_tokens; if (total_tokens == 0) continue; string [] tokens = new string[total_tokens]; foreach (string str in temp_tokens) { if (str != String.Empty) { tokens[tokens.Length - total_tokens] = str; -- total_tokens; } } string first_token = tokens[0]; if (first_token == ".model") { this.name = tokens[1]; } else if (first_token == ".inputs") { for (int k = 1; k < tokens.Length; ++k) create_pi(tokens[k]); } else if (first_token == ".outputs") { for (int k = 1; k < tokens.Length; ++k) create_po(tokens[k]); } else if (first_token == ".latch") { sharp_assert (tokens.Length == 3 || tokens.Length == 4); ELatchDefault dft_v = ELatchDefault.LATCH_X; if (tokens.Length == 4) { string last_token = tokens[3]; sharp_assert (last_token.Length == 1); dft_v = (ELatchDefault) Int32.Parse(last_token); } create_latch(tokens[1], tokens[2], dft_v); } else if (first_token == ".names") { string [] inputs = new string [tokens.Length - 2]; sharp_assert (inputs.Length == 1 || inputs.Length == 2); string name = tokens[tokens.Length - 1]; for (int k = 1; k < tokens.Length - 1; ++k) inputs[k-1] = tokens[k]; Gate node = create_comb(name, inputs); if ((string)lines[i+1] == "1 1" && (string)lines[i+2] == "0 1" ) { node.gate_type = EGateType.G_CONST_1; i+=2; } else if ((string)lines[i+1] == "1 1") { warning ("A gate is a wire, sweep first "); node.gate_type = EGateType.G_WIRE; ++ i; } else if ((string)lines[i+1] == "0 1") { node.gate_type = EGateType.G_NOT; ++ i; } else if ((string)lines[i+1] == "11 1") { node.gate_type = EGateType.G_AND_11; ++ i; } else if ((string)lines[i+1] == "10 1") { node.gate_type = EGateType.G_AND_10; ++ i; } else if ((string)lines[i+1] == "01 1") { node.gate_type = EGateType.G_AND_01; ++ i; } else if ((string)lines[i+1] == "00 1") { node.gate_type = EGateType.G_AND_00; ++ i; } else if ((string)lines[i+1] == "0- 1" && (string)lines[i+2] == "-0 1") { node.gate_type = EGateType.G_OR_00; i+=2; } else if ((string)lines[i+1] == "0- 1" && (string)lines[i+2] == "-1 1") { node.gate_type = EGateType.G_OR_01; i+=2; } else if ((string)lines[i+1] == "1- 1" && (string)lines[i+2] == "-0 1") { node.gate_type = EGateType.G_OR_10; i+=2; } else if ((string)lines[i+1] == "1- 1" && (string)lines[i+2] == "-1 1") { node.gate_type = EGateType.G_OR_11; i+=2; } else { fatal ("Don't know gate type for " + line); } sharp_assert ( ((string)lines[i+1])[0] == '.'); } else if (first_token == ".end") { break; } else if (first_token == ".wire_load_slope") { warning("Warning: Ignoring " + first_token); } else if (first_token[0] == '.') { fatal (first_token + ": Unable to handle this keyword"); } } finalize_construct_network(); } public void write_blif(string filename) { StreamWriter outfile = new StreamWriter(filename); outfile.WriteLine ( ".model " + this.name ); outfile.Write ( ".inputs" ); for (int i = 0; i < primary_inputs.size(); ++i) outfile.Write ( " " + node(primary_inputs[i]).name) ; outfile.WriteLine (); outfile.Write ( ".outputs" ); for (int i = 0; i < primary_outputs.size(); ++i) outfile.Write ( " " + node(primary_outputs[i]).name) ; outfile.WriteLine (); for (int i = 0; i < latches.size(); ++i) { Gate n = node(latches[i]); outfile.WriteLine ( ".latch " + node(n.fanins[0]).name + " " + n.name + " " + (int) n.latch_default ); } for (int i = 0; i < combs.size(); ++i) { Gate n = node(combs[i]); outfile.Write ( ".names"); for (int j = 0; j < n.fanins.size(); ++j) outfile.Write ( " " + node(n.fanins[j]).name); outfile.WriteLine (" " + n.name ); if (n.gate_type == EGateType.G_NOT) outfile.WriteLine ( "0 1" ); else if (n.gate_type == EGateType.G_AND_11) outfile.WriteLine ( "11 1" ); else if (n.gate_type == EGateType.G_AND_10) outfile.WriteLine ( "10 1" ); else if (n.gate_type == EGateType.G_AND_01) outfile.WriteLine ( "01 1" ); else if (n.gate_type == EGateType.G_AND_00) outfile.WriteLine ( "00 1" ); else if (n.gate_type == EGateType.G_OR_11) outfile.WriteLine ( "1- 1" + '\n' + "-1 1" ); else if (n.gate_type == EGateType.G_OR_10) outfile.WriteLine ( "1- 1" + '\n' + "-0 1" ); else if (n.gate_type == EGateType.G_OR_01) outfile.WriteLine ( "0- 1" + '\n' + "-1 1" ); else if (n.gate_type == EGateType.G_OR_00) outfile.WriteLine ( "0- 1" + '\n' + "-0 1" ); // else if (n.gate_type == EGateType.G_EQUAL) // outfile.WriteLine ( "11 1" + '\n' + "00 1" ); else if (n.gate_type == EGateType.G_CONST_1) outfile.WriteLine ( "1 1" + '\n' + "0 1" ); else if (n.gate_type == EGateType.G_WIRE) outfile.WriteLine ( "1 1" + '\n' + "0 0" ); else fatal ("Unknown gate type" ); } outfile.WriteLine ( ".end" ); outfile.Close(); } } }