430 lines
16 KiB
C#
430 lines
16 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// 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();
|
||
|
}
|
||
|
}
|
||
|
}
|