284 lines
8.3 KiB
C++
284 lines
8.3 KiB
C++
|
/*
|
||
|
* MIT License
|
||
|
*
|
||
|
* Copyright (c) 2020-2022 Peking University
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in all
|
||
|
* copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include "circuit.h"
|
||
|
#include "match.h"
|
||
|
|
||
|
vector<string> split(string str, string separator) { // split a string by the separator
|
||
|
vector<string> dest;
|
||
|
string substring;
|
||
|
string::size_type start = 0, index;
|
||
|
do {
|
||
|
index = str.find_first_of(separator, start);
|
||
|
if (index != string::npos) {
|
||
|
substring = str.substr(start, index - start);
|
||
|
dest.push_back(substring);
|
||
|
start = str.find_first_not_of(separator, index);
|
||
|
if (start == string::npos) {
|
||
|
return dest;
|
||
|
}
|
||
|
}
|
||
|
} while (index != string::npos);
|
||
|
substring = str.substr(start); // the last substring
|
||
|
dest.push_back(substring);
|
||
|
return dest;
|
||
|
}
|
||
|
|
||
|
Var::Var(string name_, bool is_in_, bool is_out_)
|
||
|
:
|
||
|
name(name_), is_in(is_in_), is_out(is_out_) {
|
||
|
depth = is_in ? 0 : -1;
|
||
|
mindep = Area = 0;
|
||
|
AreaFlow = 0;
|
||
|
}
|
||
|
|
||
|
Circuit::Circuit(string benchmark_)
|
||
|
:
|
||
|
benchmark(benchmark_) {
|
||
|
Dep = 0;
|
||
|
|
||
|
abc_res = get_abc_result();
|
||
|
|
||
|
standard_cell_map("ALL.genlib");
|
||
|
|
||
|
cout << "PI = " << input.size() << ", PO = " << output.size() << ", size = " << graph.size() << endl;
|
||
|
|
||
|
// for (auto p : graph) {
|
||
|
// cout << p.first << ' ' << p.second->depth << ' ';
|
||
|
// for (string s : p.second->pre) {
|
||
|
// cout << s << ' ' << graph[s]->depth << ' ';
|
||
|
// }
|
||
|
// cout << endl;
|
||
|
// }
|
||
|
|
||
|
// write_dot();
|
||
|
}
|
||
|
|
||
|
Circuit::~Circuit() {
|
||
|
char lut_file[256];
|
||
|
sprintf(lut_file, "%s_lut.blif", benchmark.c_str()); // lut mapping file
|
||
|
remove(lut_file);
|
||
|
|
||
|
char std_file[256];
|
||
|
sprintf(std_file, "%s_standard.blif", benchmark.c_str()); // lut mapping file
|
||
|
remove(std_file);
|
||
|
|
||
|
char abc_lut_file[256];
|
||
|
sprintf(abc_lut_file, "%s_abc_lut.blif", benchmark.c_str()); // abc lut mapping file
|
||
|
remove(abc_lut_file);
|
||
|
}
|
||
|
|
||
|
void Circuit::standard_cell_map(string lib) {
|
||
|
abc_map(benchmark, "write_blif", benchmark + "_standard.blif", lib);
|
||
|
|
||
|
ifstream fin(benchmark + "_standard.blif", ios::in);
|
||
|
if (!fin.is_open()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
string s;
|
||
|
while (fin >> s && s != ".inputs") {
|
||
|
}
|
||
|
while (fin >> s && s != ".outputs") {
|
||
|
if (s != "\\") {
|
||
|
input.push_back(s);
|
||
|
graph[s] = new Var(s, true, false);
|
||
|
}
|
||
|
}
|
||
|
while (fin >> s && s != ".gate") {
|
||
|
if (s != "\\") {
|
||
|
output.push_back(s);
|
||
|
graph[s] = new Var(s, false, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
string gate;
|
||
|
fin >> gate;
|
||
|
|
||
|
getline(fin, s);
|
||
|
vector<string> cells = split(s, " ");
|
||
|
|
||
|
string out_cell = (*cells.rbegin()).substr(2);
|
||
|
if (find(output.begin(), output.end(), out_cell) == output.end()) {
|
||
|
graph[out_cell] = new Var(out_cell, false, false);
|
||
|
}
|
||
|
cells.pop_back();
|
||
|
cells.erase(cells.begin());
|
||
|
|
||
|
for (string cell : cells) {
|
||
|
cell = cell.substr(2);
|
||
|
graph[cell]->suc.push_back(out_cell);
|
||
|
graph[out_cell]->pre.push_back(cell);
|
||
|
}
|
||
|
} while (fin >> s && s == ".gate");
|
||
|
fin.close();
|
||
|
}
|
||
|
|
||
|
void Circuit::lut_map(string lib) {
|
||
|
abc_lutpack(benchmark, "write_blif", benchmark + "_lut.blif", lib);
|
||
|
|
||
|
ifstream fin(benchmark + "_lut.blif", ios::in);
|
||
|
if (!fin.is_open()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
string s;
|
||
|
while (fin >> s && s != ".inputs") {
|
||
|
}
|
||
|
while (fin >> s && s != ".outputs") {
|
||
|
if (s != "\\") {
|
||
|
input.push_back(s);
|
||
|
graph[s] = new Var(s, true, false);
|
||
|
}
|
||
|
}
|
||
|
while (fin >> s && s != ".names") {
|
||
|
if (s != "\\") {
|
||
|
output.push_back(s);
|
||
|
graph[s] = new Var(s, false, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
if (s == ".names") {
|
||
|
getline(fin, s);
|
||
|
if (s[s.length() - 1] == '\\') {
|
||
|
string next;
|
||
|
getline(fin, next);
|
||
|
s = s.substr(0, s.length() - 1) + next.substr(1);
|
||
|
}
|
||
|
vector<string> cells = split(s.substr(1), " ");
|
||
|
|
||
|
for (string cell : cells) {
|
||
|
if (graph.find(cell) == graph.end()) {
|
||
|
graph[cell] = new Var(cell, false, false);
|
||
|
}
|
||
|
}
|
||
|
string out_cell = (*cells.rbegin());
|
||
|
cells.pop_back();
|
||
|
for (string cell : cells) {
|
||
|
graph[cell]->suc.push_back(out_cell);
|
||
|
graph[out_cell]->pre.push_back(cell);
|
||
|
}
|
||
|
}
|
||
|
} while (fin >> s && s != ".end");
|
||
|
fin.close();
|
||
|
}
|
||
|
|
||
|
pair<int, pair<int, int> > Circuit::get_abc_result() {
|
||
|
memset(abc_lut, 0, sizeof(abc_lut));
|
||
|
abc_lut_area = 0;
|
||
|
|
||
|
string s;
|
||
|
|
||
|
int area[10] = { }, delay[10] = { };
|
||
|
ifstream fin_lut("abclib/6LUT.lutlib", ios::in);
|
||
|
if (!fin_lut.is_open()) {
|
||
|
return make_pair(0, make_pair(0, 0));
|
||
|
}
|
||
|
getline(fin_lut, s);
|
||
|
getline(fin_lut, s);
|
||
|
int k;
|
||
|
while (fin_lut >> k) {
|
||
|
fin_lut >> area[k] >> delay[k];
|
||
|
}
|
||
|
fin_lut.close();
|
||
|
|
||
|
abc_lutpack(benchmark, "write_blif", benchmark + "_abc_lut.blif", "6LUT.lutlib");
|
||
|
|
||
|
ifstream fin(benchmark + "_abc_lut.blif", ios::in);
|
||
|
if (!fin.is_open()) {
|
||
|
return make_pair(0, make_pair(0, 0));
|
||
|
}
|
||
|
while (fin >> s && s != ".names") {
|
||
|
}
|
||
|
|
||
|
set<string> all_cells;
|
||
|
do {
|
||
|
if (s == ".names") {
|
||
|
getline(fin, s);
|
||
|
if (s[s.length() - 1] == '\\') {
|
||
|
string next;
|
||
|
getline(fin, next);
|
||
|
s = s.substr(0, s.length() - 1) + next.substr(1);
|
||
|
}
|
||
|
vector<string> cells = split(s.substr(1), " ");
|
||
|
for (string cell : cells){
|
||
|
all_cells.insert(cell);
|
||
|
}
|
||
|
++abc_lut[cells.size() - 1];
|
||
|
}
|
||
|
} while (fin >> s && s != ".end");
|
||
|
fin.close();
|
||
|
|
||
|
for (int i = 0; i < 10; ++i) {
|
||
|
abc_lut_area += abc_lut[i] * area[i];
|
||
|
}
|
||
|
|
||
|
int cell_number = all_cells.size();
|
||
|
for (int i = 3; i < 10; ++i) {
|
||
|
cell_number += abc_lut[i] * (i - 2);
|
||
|
}
|
||
|
|
||
|
Match *mt = new Match();
|
||
|
int r1 = abc_lut_area;
|
||
|
int r2 = abc_lut_area - mt->getMatch(benchmark + "_abc_lut.blif");
|
||
|
int r3 = mt->maxdep;
|
||
|
cout << "ABC size = " << cell_number << ", single_area = " << r1 << ", dual_area = " << r2 << ", depth = " << r3 << endl;
|
||
|
return make_pair(r1, make_pair(r2, r3));
|
||
|
}
|
||
|
|
||
|
void Circuit::write_dot() {
|
||
|
char dot_file[256];
|
||
|
sprintf(dot_file, "%s.dot", benchmark.c_str());
|
||
|
ofstream fout(dot_file, ios::out);
|
||
|
if (!fout.is_open()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fout << "digraph G {\nsize = \"7.5,10\";\ncenter = true;" << endl;
|
||
|
for (pair<string, Var*> p : graph) {
|
||
|
//for (int i = 0; i < p.first.length(); i++)
|
||
|
// if (p.first[i] != '[' && p.first[i] != ']')
|
||
|
fout << p.first;
|
||
|
if (p.second->is_in) {
|
||
|
fout << "[shape = invtriangle, color = coral, fillcolor = coral];" << endl;
|
||
|
} else if (p.second->is_out) {
|
||
|
fout << "[shape = triangle, color = coral, fillcolor = coral];" << endl;
|
||
|
} else {
|
||
|
fout << "[shape = ellipse];" << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fout << endl;
|
||
|
for (pair<string, Var*> p : graph) {
|
||
|
for (string s : p.second->pre) {
|
||
|
fout << s << " -> " << p.first << endl;
|
||
|
}
|
||
|
}
|
||
|
fout << '}' << endl;
|
||
|
|
||
|
fout.close();
|
||
|
}
|