Skip to content

Commit

Permalink
Nicknames now go by int instead of string.
Browse files Browse the repository at this point in the history
  • Loading branch information
calmofthestorm committed Apr 11, 2013
1 parent c0e3fbe commit c6cc31b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 48 deletions.
58 changes: 32 additions & 26 deletions blif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ BLIF::BLIF(istream& input)
// Need this to handle validation -- outputs are a special case but we don't
// know it when reading their truth table. Once we're done reading the file
// we can discard this, however.
unordered_set<string> outputs;
unordered_set<int> outputs;

Tokenizer::LineTokenReader reader(input);

Expand All @@ -66,10 +66,9 @@ BLIF::BLIF(istream& input)
throw DuplicateBlockError(reader.getRawLineNumber(), "inputs");
}
read_inputs = true;
int index = 0;
while (tok != tokens.end()) {
mPrimaryInputs.push_back(*tok);
mTruthTables[registerLiteral(*tok, "inputs", index++)] = TruthTable();
mTruthTables[registerLiteral(*tok)] = TruthTable();
++tok;
}
}
Expand All @@ -80,10 +79,9 @@ BLIF::BLIF(istream& input)
throw DuplicateBlockError(reader.getRawLineNumber(), "outputs");
}
read_outputs = true;
int index = 0;
while (tok != tokens.end()) {
mPrimaryOutputs.push_back(*tok);
outputs.insert(registerLiteral(*tok, "outputs", index++));
outputs.insert(registerLiteral(*tok));
++tok;
}
}
Expand All @@ -100,7 +98,7 @@ BLIF::BLIF(istream& input)
throw NamesBlockBeforeHeadersError(reader.getRawLineNumber(), "model");
}

string name = registerLiteral(*(tokens.end() - 1));
int name = registerLiteral(*(tokens.end() - 1));
if (mTruthTables.find(name) != mTruthTables.end()) {
throw DuplicateTruthTableError(reader.getRawLineNumber(),
*(tokens.end() - 1));
Expand All @@ -110,7 +108,7 @@ BLIF::BLIF(istream& input)
TruthTable::TTKind::OUTPUT :
TruthTable::TTKind::NORMAL);

vector<string> literals;
vector<int> literals;
while (tok != tokens.end() - 1) {
literals.push_back(registerLiteral(*tok++));
}
Expand Down Expand Up @@ -183,22 +181,11 @@ const std::vector<std::string>& BLIF::getPrimaryOutputs() const {
return mPrimaryOutputs;
}

string BLIF::registerLiteral(const string& lit, const string& arrayName,
int arrayIndex) {
std::ostringstream sstr;
sstr << arrayName << "[" << arrayIndex << "]";
assert(mLiterals.find(sstr.str()) == mLiterals.end());
mLiterals[lit] = sstr.str();
mLiteralsReverse[sstr.str()] = lit;
return mLiterals[lit];
}

string BLIF::registerLiteral(const string& lit) {
int BLIF::registerLiteral(const string& lit) {
if (mLiterals.find(lit) == mLiterals.end()) {
std::ostringstream sstr;
sstr << "node" << mNextLiteralIndex++;
mLiterals[lit] = sstr.str();
mLiterals[sstr.str()] = lit;
mLiterals[lit] = mNextLiteralIndex;
mLiteralsReverse[mNextLiteralIndex] = lit;
++mNextLiteralIndex;
}
return mLiterals[lit];
}
Expand All @@ -207,16 +194,35 @@ void BLIF::writeEvaluator(std::ostream& output, const string& fxn_name) const {
output << "void " << fxn_name << "(size_t inputs[numInputs],"
<< " size_t outputs[numOutputs]) {\n";

// Generate node names for each gate
std::unordered_map<int, string> nicknames;
for (const auto& gate : mLiteralsReverse) {
nicknames[gate.first] = "node" + std::to_string(gate.first); // keys only
}

// Special case primary inputs and outputs
for (decltype(mPrimaryInputs)::size_type i = 0; i < mPrimaryInputs.size(); ++i) {
assert(mLiterals.find(mPrimaryInputs[i]) != mLiterals.end());
int key = mLiterals.find(mPrimaryInputs[i])->second;
nicknames[key] = "inputs[" + std::to_string(i) + "]";
}

for (decltype(mPrimaryOutputs)::size_type i = 0; i < mPrimaryOutputs.size(); ++i) {
assert(mLiterals.find(mPrimaryOutputs[i]) != mLiterals.end());
int key = mLiterals.find(mPrimaryOutputs[i])->second;
nicknames[key] = "outputs[" + std::to_string(i) + "]";
}

// We need to write out the assignments in topologically sorted order to
// ensure that all dependencies are met. BLIF does not require the circuit
// be so sorted.
std::unordered_set<std::string> ordered;
std::unordered_set<int> ordered;
for (const auto& gate : mTruthTables) {
if (ordered.find(gate.first) == ordered.end()) {
std::stack<string> todo;
std::stack<int> todo;
todo.push(gate.first);
while (!todo.empty()) {
string top_name = todo.top();
int top_name = todo.top();
todo.pop();
// This second check is necessary if the same gate occurs twice in a
// given dependency tree. We could either index the stack with a set
Expand All @@ -237,7 +243,7 @@ void BLIF::writeEvaluator(std::ostream& output, const string& fxn_name) const {
}
if (ready) {
ordered.insert(top_name);
top.generateCode(top_name, output);
top.generateCode(top_name, output, nicknames);
}
}
}
Expand Down
11 changes: 4 additions & 7 deletions blif.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ class BLIF {
static std::vector<std::string> readLineAsTokens(std::istream& input);

// Generate a unique name for this user node (to resolve naming conflicts)
std::string registerLiteral(const std::string& lit);
std::string registerLiteral(const std::string& lit,
const std::string& arrayName,
int arrayIndex);
int registerLiteral(const std::string& lit);

// Name of the model
std::string mModel;
Expand All @@ -58,15 +55,15 @@ class BLIF {
std::vector<std::string> mPrimaryOutputs;

// Bimap from user supplied names to the ones we'll use.
std::unordered_map<std::string, std::string> mLiterals;
std::unordered_map<std::string, std::string> mLiteralsReverse;
std::unordered_map<std::string, int> mLiterals;
std::unordered_map<int, std::string> mLiteralsReverse;

// Next integer to use for unique generated names.
int mNextLiteralIndex;

// Map from node names (truth tables) to the truth tables that represent
// them.
std::unordered_map<std::string, TruthTable> mTruthTables;
std::unordered_map<int, TruthTable> mTruthTables;
};

} // namespace blifverifier
Expand Down
26 changes: 17 additions & 9 deletions truthtable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

#include "tokenizer.h"
Expand All @@ -18,6 +19,7 @@ using std::ostream;
using std::string;
using std::vector;
using std::unordered_set;
using std::unordered_map;

namespace blifverifier {

Expand All @@ -39,7 +41,7 @@ bool TruthTable::isValidTTEntry(const string& line, int num_entries) {
}

TruthTable::TruthTable(Tokenizer::LineTokenReader& reader,
vector<string>&& inputs, TTKind kind)
vector<int>&& inputs, TTKind kind)
: mInputs(inputs), mKind(kind) {
// Parse the truth table.
// Keep reading logic lines until we hit something else, and push it back.
Expand Down Expand Up @@ -78,38 +80,44 @@ char TruthTableEntry::getOutput() const {

// TODO: if BLIF truthtable contains a contradiction it will be resolved
// silently as true. This should raise an error as the file is illegal.
void TruthTableEntry::generateCode(ostream& out,
const vector<string>& input_names) const {
void TruthTableEntry::generateCode(
ostream& out,
const vector<int>& input_names,
const unordered_map<int, string>& nicknames) const {
out << "(";
for (decltype(mInputs)::size_type i = 0; i < mInputs.size(); ++i) {
if (mInputs[i] != TOKENS::NC) {
if (mInputs[i] == TOKENS::ZERO) {
out << "~";
}
out << input_names[i] << " & ";
// Abort if key not present.
out << nicknames.find(input_names[i])->second << " & ";
}
}
out << " -1)";
}

void TruthTable::generateCode(const string& name, ostream& out) const {
void TruthTable::generateCode(
int name, ostream& out,
const unordered_map<int, string>& nicknames) const {
if (mKind != TruthTable::TTKind::INPUT) {
if (mKind == TruthTable::TTKind::NORMAL) {
out << "size_t ";
}
out << name << " = ";
// Abort if key not present.
out << nicknames.find(name)->second << " = ";
out << "(";
for (const auto& entry : mEntries) {
if (entry.getOutput() == TOKENS::ONE) {
entry.generateCode(out, mInputs);
entry.generateCode(out, mInputs, nicknames);
out << " | ";
}
}
out << " 0); // strategy: naive\n";
}
}

void TruthTable::addInput(const std::string& input) {
void TruthTable::addInput(int input) {
assert(mKind != TTKind::INPUT);
mInputs.push_back(input);
}
Expand All @@ -119,7 +127,7 @@ void TruthTable::addEntry(const TruthTableEntry& entry) {
mEntries.push_back(entry);
}

const vector<string>& TruthTable::getInputs() const {
const vector<int>& TruthTable::getInputs() const {
return mInputs;
}

Expand Down
14 changes: 8 additions & 6 deletions truthtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class TruthTableEntry {

// Represents the entry as a C logic expression.
void generateCode(std::ostream& out,
const std::vector<std::string>& input_names) const;
const std::vector<int>& input_names,
const std::unordered_map<int, std::string>& nicknames) const;

private:
std::string mInputs;
Expand All @@ -50,25 +51,26 @@ class TruthTable {

TruthTable(); // Default -- primary input
TruthTable(Tokenizer::LineTokenReader& reader,
std::vector<std::string>&& inputs, TTKind kind);
std::vector<int>&& inputs, TTKind kind);

// Add an input to the truth table (not valid for inputs)
void addInput(const std::string& input);
void addInput(int input);

// Add an entry to the truth table
void addEntry(const TruthTableEntry& entry);

const std::vector<std::string>& getInputs() const;
const std::vector<int>& getInputs() const;

// Represents the entire truth table as a C logic expression.
void generateCode(const std::string& name, std::ostream& out) const;
void generateCode(int, std::ostream& out,
const std::unordered_map<int, std::string>& nicknames) const;

private:
// Verifies a truth table line.
static bool isValidTTEntry(const std::string& line, int num_entries);

// (Translated) names of the inputs to the truth table.
std::vector<std::string> mInputs;
std::vector<int> mInputs;

// All entries for the circuit that have defined output.
std::vector<TruthTableEntry> mEntries;
Expand Down

0 comments on commit c6cc31b

Please sign in to comment.