-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtruthtable.cc
134 lines (116 loc) · 3.52 KB
/
truthtable.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "truthtable.h"
#include <cassert>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#include "tokenizer.h"
using std::istream;
using std::istringstream;
using std::ostream;
using std::string;
using std::vector;
using std::unordered_set;
using std::unordered_map;
namespace blifverifier {
TruthTable::TruthTable()
: mKind(TTKind::INPUT) { }
bool TruthTable::isValidTTEntry(const string& line, int num_entries) {
if (num_entries != static_cast<int>(line.size())) {
return false;
}
for (const auto& c : line) {
if (c != TOKENS::ZERO && c != TOKENS::ONE && c != TOKENS::NC) {
return false;
}
}
return true;
}
TruthTable::TruthTable(Tokenizer::LineTokenReader& reader,
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.
while (reader.isGood()) {
auto tokens = reader.readLine();
// TODO: clean this.
if (tokens.size() == 1 && inputs.size() == 0 &&
(tokens[0][0] == TOKENS::ZERO || tokens[0][0] == TOKENS::ONE ||
tokens[0][0] == TOKENS::NC)) {
TruthTableEntry tte("", tokens[0][0]);
addEntry(tte);
} else if (tokens.size() == 2 &&
isValidTTEntry(tokens[0], inputs.size()) &&
tokens[0].size() == inputs.size() && tokens[1].size() == 1 &&
(tokens[1][0] == TOKENS::ZERO || tokens[1][0] == TOKENS::ONE ||
tokens[1][0] == TOKENS::NC)) {
// Is a valid logic line.
TruthTableEntry tte(tokens[0], tokens[1][0]);
addEntry(tte);
} else {
// Read a non-TT line. Push it back and finish.
reader.putBack(std::move(tokens));
return;
}
}
// should never get here.
assert(false);
}
TruthTableEntry::TruthTableEntry(const std::string& inputs, char output)
: mInputs(inputs), mOutput(output) { }
char TruthTableEntry::getOutput() const {
return mOutput;
}
// 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<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 << "~";
}
// Abort if key not present.
out << nicknames.find(input_names[i])->second << " & ";
}
}
out << " -1)";
}
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 ";
}
// 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, nicknames);
out << " | ";
}
}
out << " 0); // strategy: naive\n";
}
}
void TruthTable::addInput(int input) {
assert(mKind != TTKind::INPUT);
mInputs.push_back(input);
}
void TruthTable::addEntry(const TruthTableEntry& entry) {
assert(mKind != TTKind::INPUT);
mEntries.push_back(entry);
}
const vector<int>& TruthTable::getInputs() const {
return mInputs;
}
} // namespace blifverifier