2008-11-17 18:29:00 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
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;
|
2008-11-17 18:29:00 -05:00
|
|
|
if ((n = find_node_by_name(name)) != null) {
|
2008-03-05 09:52:00 -05:00
|
|
|
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;
|
2008-11-17 18:29:00 -05:00
|
|
|
if ((n = find_node_by_name(name)) == null)
|
2008-03-05 09:52:00 -05:00
|
|
|
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();
|
2008-11-17 18:29:00 -05:00
|
|
|
while (true) {
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
line = input.ReadLine();
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
catch (Exception e) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Console.WriteLine("The file could not be read:");
|
|
|
|
Console.WriteLine(e.Message);
|
|
|
|
fatal();
|
|
|
|
}
|
|
|
|
if (line == null)
|
|
|
|
return null;
|
2008-11-17 18:29:00 -05:00
|
|
|
if (line.IndexOf('\\') == -1) {
|
2008-03-05 09:52:00 -05:00
|
|
|
str.Append(line);
|
|
|
|
return str.ToString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
str.Append(line.Replace('\\',' '));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void finalize_construct_network()
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < nodes.size(); ++i) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Gate n = node(i);
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int j = 0; j < n.fanin_names.size(); ++j) {
|
2008-03-05 09:52:00 -05:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < nodes.size(); ++i) {
|
2008-03-05 09:52:00 -05:00
|
|
|
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);
|
2008-11-17 18:29:00 -05:00
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
input = new StreamReader(filename);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
catch (Exception e) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Console.WriteLine("The file could not be read:");
|
|
|
|
Console.WriteLine(e.Message);
|
|
|
|
fatal();
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
while (true) {
|
2008-03-05 09:52:00 -05:00
|
|
|
string line = get_multiple_line(input);
|
|
|
|
if (line == null)
|
|
|
|
break;
|
|
|
|
lines.push_back(line);
|
|
|
|
if (line == ".end")
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < lines.size(); ++i) {
|
2008-03-05 09:52:00 -05:00
|
|
|
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];
|
2008-11-17 18:29:00 -05:00
|
|
|
foreach (string str in temp_tokens) {
|
|
|
|
if (str != String.Empty) {
|
2008-03-05 09:52:00 -05:00
|
|
|
tokens[tokens.Length - total_tokens] = str;
|
|
|
|
-- total_tokens;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
string first_token = tokens[0];
|
2008-11-17 18:29:00 -05:00
|
|
|
if (first_token == ".model") {
|
2008-03-05 09:52:00 -05:00
|
|
|
this.name = tokens[1];
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token == ".inputs") {
|
|
|
|
for (int k = 1; k < tokens.Length; ++k)
|
2008-03-05 09:52:00 -05:00
|
|
|
create_pi(tokens[k]);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token == ".outputs") {
|
|
|
|
for (int k = 1; k < tokens.Length; ++k)
|
2008-03-05 09:52:00 -05:00
|
|
|
create_po(tokens[k]);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token == ".latch") {
|
2008-03-05 09:52:00 -05:00
|
|
|
sharp_assert (tokens.Length == 3 || tokens.Length == 4);
|
|
|
|
ELatchDefault dft_v = ELatchDefault.LATCH_X;
|
2008-11-17 18:29:00 -05:00
|
|
|
if (tokens.Length == 4) {
|
2008-03-05 09:52:00 -05:00
|
|
|
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);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token == ".names") {
|
2008-03-05 09:52:00 -05:00
|
|
|
string [] inputs = new string [tokens.Length - 2];
|
|
|
|
sharp_assert (inputs.Length == 1 || inputs.Length == 2);
|
|
|
|
string name = tokens[tokens.Length - 1];
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int k = 1; k < tokens.Length - 1; ++k)
|
2008-03-05 09:52:00 -05:00
|
|
|
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;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((string)lines[i+1] == "1 1") {
|
2008-03-05 09:52:00 -05:00
|
|
|
warning ("A gate is a wire, sweep first ");
|
|
|
|
node.gate_type = EGateType.G_WIRE; ++ i;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((string)lines[i+1] == "0 1") {
|
2008-03-05 09:52:00 -05:00
|
|
|
node.gate_type = EGateType.G_NOT; ++ i;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((string)lines[i+1] == "11 1") {
|
2008-03-05 09:52:00 -05:00
|
|
|
node.gate_type = EGateType.G_AND_11; ++ i;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((string)lines[i+1] == "10 1") {
|
2008-03-05 09:52:00 -05:00
|
|
|
node.gate_type = EGateType.G_AND_10; ++ i;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((string)lines[i+1] == "01 1") {
|
2008-03-05 09:52:00 -05:00
|
|
|
node.gate_type = EGateType.G_AND_01; ++ i;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((string)lines[i+1] == "00 1") {
|
2008-03-05 09:52:00 -05:00
|
|
|
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;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
fatal ("Don't know gate type for " + line);
|
|
|
|
}
|
|
|
|
sharp_assert ( ((string)lines[i+1])[0] == '.');
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token == ".end") {
|
2008-03-05 09:52:00 -05:00
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token == ".wire_load_slope") {
|
2008-03-05 09:52:00 -05:00
|
|
|
warning("Warning: Ignoring " + first_token);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (first_token[0] == '.') {
|
2008-03-05 09:52:00 -05:00
|
|
|
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" );
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < primary_inputs.size(); ++i)
|
2008-03-05 09:52:00 -05:00
|
|
|
outfile.Write ( " " + node(primary_inputs[i]).name) ;
|
|
|
|
outfile.WriteLine ();
|
|
|
|
|
|
|
|
outfile.Write ( ".outputs" );
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < primary_outputs.size(); ++i)
|
2008-03-05 09:52:00 -05:00
|
|
|
outfile.Write ( " " + node(primary_outputs[i]).name) ;
|
|
|
|
outfile.WriteLine ();
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < latches.size(); ++i) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Gate n = node(latches[i]);
|
|
|
|
outfile.WriteLine ( ".latch " + node(n.fanins[0]).name + " " + n.name + " " + (int) n.latch_default );
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < combs.size(); ++i) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Gate n = node(combs[i]);
|
|
|
|
outfile.Write ( ".names");
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int j = 0; j < n.fanins.size(); ++j)
|
2008-03-05 09:52:00 -05:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|