simulator
parent
9635c0de3c
commit
83d6e01e3c
|
@ -0,0 +1,84 @@
|
||||||
|
/* phyLS: powerful heightened yielded Logic Synthesis
|
||||||
|
* Copyright (C) 2022 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file cec.hpp
|
||||||
|
*
|
||||||
|
* @brief performs combinational equivalence checking
|
||||||
|
*
|
||||||
|
* @author Homyoung
|
||||||
|
* @since 2022/12/14
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CEC2_HPP
|
||||||
|
#define CEC2_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/abc/abc.h"
|
||||||
|
#include "base/abci/abcVerify.c"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace mockturtle;
|
||||||
|
|
||||||
|
namespace alice {
|
||||||
|
|
||||||
|
class acec_command : public command {
|
||||||
|
public:
|
||||||
|
explicit acec_command(const environment::ptr &env)
|
||||||
|
: command(env, "performs combinational equivalence checking") {
|
||||||
|
add_option("file1, -f", filename_1, "the input file name");
|
||||||
|
add_option("file2, -b", filename_2, "the input file name");
|
||||||
|
add_flag("--verbose, -v", "print the information");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void execute() {
|
||||||
|
clock_t begin, end;
|
||||||
|
double totalTime;
|
||||||
|
|
||||||
|
begin = clock();
|
||||||
|
|
||||||
|
pabc::Abc_Ntk_t *pNtk;
|
||||||
|
int fDelete1 = 0, fDelete2 = 0;
|
||||||
|
int nArgcNew = 0;
|
||||||
|
char **pArgvNew;
|
||||||
|
int fCheck = 1, fBarBufs = 0;
|
||||||
|
|
||||||
|
pabc::Abc_Ntk_t *pNtk1 = pabc::Io_Read(
|
||||||
|
(char *)(filename_1.c_str()),
|
||||||
|
pabc::Io_ReadFileType((char *)(filename_1.c_str())), fCheck, fBarBufs);
|
||||||
|
end = clock();
|
||||||
|
pabc::Abc_Ntk_t *pNtk2 = pabc::Io_Read(
|
||||||
|
(char *)(filename_2.c_str()),
|
||||||
|
pabc::Io_ReadFileType((char *)(filename_2.c_str())), fCheck, fBarBufs);
|
||||||
|
|
||||||
|
// set defaults
|
||||||
|
int fSat = 0;
|
||||||
|
int fVerbose = 0;
|
||||||
|
int nSeconds = 20;
|
||||||
|
int nPartSize = 0;
|
||||||
|
int nConfLimit = 10000;
|
||||||
|
int nInsLimit = 0;
|
||||||
|
int fPartition = 0;
|
||||||
|
int fIgnoreNames = 0;
|
||||||
|
|
||||||
|
pabc::Abc_NtkCecFraig(pNtk1, pNtk2, nSeconds, fVerbose);
|
||||||
|
|
||||||
|
end = clock();
|
||||||
|
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
cout.setf(ios::fixed);
|
||||||
|
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string filename_1;
|
||||||
|
string filename_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
ALICE_ADD_COMMAND(acec, "Verification")
|
||||||
|
|
||||||
|
} // namespace alice
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* phyLS: powerful heightened yielded Logic Synthesis
|
||||||
|
* Copyright (C) 2023 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file comb.hpp
|
||||||
|
*
|
||||||
|
* @brief converts comb network into seq, and vice versa
|
||||||
|
*
|
||||||
|
* @author Homyoung
|
||||||
|
* @since 2023/03/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMB_HPP
|
||||||
|
#define COMB_HPP
|
||||||
|
|
||||||
|
#include "base/abc/abc.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace mockturtle;
|
||||||
|
|
||||||
|
namespace alice {
|
||||||
|
|
||||||
|
class comb_command : public command {
|
||||||
|
public:
|
||||||
|
explicit comb_command(const environment::ptr &env)
|
||||||
|
: command(env, "converts comb network into seq, and vice versa") {
|
||||||
|
add_flag(
|
||||||
|
"--convert, -c",
|
||||||
|
"converting latches to PIs/POs or removing them [default = convert]");
|
||||||
|
add_flag("--verbose, -v", "print the information");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void execute() {
|
||||||
|
clock_t begin, end;
|
||||||
|
double totalTime;
|
||||||
|
|
||||||
|
begin = clock();
|
||||||
|
|
||||||
|
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
|
||||||
|
std::cerr << "Error: Empty ABC AIG network.\n";
|
||||||
|
else {
|
||||||
|
pabc::Abc_Ntk_t *pNtk, *pNtkRes;
|
||||||
|
pNtk = store<pabc::Abc_Ntk_t *>().current();
|
||||||
|
if (pabc::Abc_NtkIsComb(pNtk))
|
||||||
|
std::cerr << "The network is already combinational.\n";
|
||||||
|
|
||||||
|
int fRemoveLatches = 0;
|
||||||
|
if (is_set("convert")) fRemoveLatches ^= 1;
|
||||||
|
|
||||||
|
pNtkRes = pabc::Abc_NtkDup(pNtk);
|
||||||
|
pabc::Abc_NtkMakeComb(pNtkRes, fRemoveLatches);
|
||||||
|
|
||||||
|
store<pabc::Abc_Ntk_t *>().extend();
|
||||||
|
store<pabc::Abc_Ntk_t *>().current() = pNtkRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = clock();
|
||||||
|
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
cout.setf(ios::fixed);
|
||||||
|
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
ALICE_ADD_COMMAND(comb, "ABC")
|
||||||
|
|
||||||
|
} // namespace alice
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* phyLS: powerful heightened yielded Logic Synthesis
|
||||||
|
* Copyright (C) 2022 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file simulator.hpp
|
||||||
|
*
|
||||||
|
* @brief Semi-tensor product based logic network simulation
|
||||||
|
*
|
||||||
|
* @author Homyoung
|
||||||
|
* @since 2023/03/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SIMULATOR_HPP
|
||||||
|
#define SIMULATOR_HPP
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "../core/simulator/lut_parser.hpp"
|
||||||
|
#include "../core/simulator/simulator.hpp"
|
||||||
|
|
||||||
|
namespace alice {
|
||||||
|
|
||||||
|
class simulator_command : public command {
|
||||||
|
public:
|
||||||
|
explicit simulator_command(const environment::ptr &env)
|
||||||
|
: command(env, "STP-based logic network simulation") {
|
||||||
|
add_option("filename,-f", filename, "name of input file");
|
||||||
|
add_flag("--verbose, -v", "verbose output");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void execute() {
|
||||||
|
std::ifstream ifs(filename);
|
||||||
|
if (!ifs.good()) std::cerr << "Can't open file " << filename << std::endl;
|
||||||
|
|
||||||
|
phyLS::CircuitGraph graph;
|
||||||
|
phyLS::LutParser parser;
|
||||||
|
|
||||||
|
if (!parser.parse(ifs, graph))
|
||||||
|
std::cerr << "Can't parse file " << filename << std::endl;
|
||||||
|
|
||||||
|
clock_t begin, end;
|
||||||
|
double totalTime = 0.0;
|
||||||
|
|
||||||
|
begin = clock();
|
||||||
|
|
||||||
|
phyLS::simulator sim(graph);
|
||||||
|
sim.simulate();
|
||||||
|
if (is_set("verbose")) sim.print_simulation_result();
|
||||||
|
|
||||||
|
end = clock();
|
||||||
|
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
std::cout.setf(ios::fixed);
|
||||||
|
std::cout << "[CPU time] " << setprecision(2) << totalTime << " s"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
ALICE_ADD_COMMAND(simulator, "Verification")
|
||||||
|
} // namespace alice
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,210 @@
|
||||||
|
#include "circuit_graph.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
Gate::Gate(Type type, line_idx output, std::vector<line_idx>&& inputs)
|
||||||
|
: m_type(type), m_inputs(inputs), m_output(output) {}
|
||||||
|
|
||||||
|
int Gate::make_gate_name(Type type) {
|
||||||
|
int lut = 0;
|
||||||
|
for (int i = 1; i < type.cols(); i++) {
|
||||||
|
lut = (lut << 1) + 1 - type(i);
|
||||||
|
}
|
||||||
|
return lut;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图的构造函数,预留一块空间
|
||||||
|
CircuitGraph::CircuitGraph() {
|
||||||
|
m_gates.reserve(5000u);
|
||||||
|
m_lines.reserve(5000u);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_idx CircuitGraph::add_input(const std::string& name) {
|
||||||
|
line_idx p_line = ensure_line(name);
|
||||||
|
if (!m_lines[p_line].is_input) {
|
||||||
|
m_lines[p_line].is_input = true;
|
||||||
|
m_inputs.push_back(p_line);
|
||||||
|
}
|
||||||
|
return p_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_idx CircuitGraph::add_output(const std::string& name) {
|
||||||
|
line_idx p_line = ensure_line(name);
|
||||||
|
if (!m_lines[p_line].is_output) {
|
||||||
|
m_lines[p_line].is_output = true;
|
||||||
|
m_outputs.push_back(p_line);
|
||||||
|
}
|
||||||
|
return p_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
gate_idx CircuitGraph::add_gate(Type type,
|
||||||
|
const std::vector<std::string>& input_names,
|
||||||
|
const std::string& output_name) {
|
||||||
|
std::vector<line_idx> inputs;
|
||||||
|
// for (size_t i = 0; i < input_names.size(); ++i)
|
||||||
|
for (int i = input_names.size() - 1; i >= 0; i--) {
|
||||||
|
line_idx p_input = ensure_line(input_names[i]);
|
||||||
|
inputs.push_back(p_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_idx p_output = ensure_line(output_name);
|
||||||
|
|
||||||
|
m_gates.emplace_back(type, p_output, std::move(inputs));
|
||||||
|
gate_idx gate = m_gates.size() - 1;
|
||||||
|
m_lines[p_output].source = gate;
|
||||||
|
m_gates.back().id() = gate;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_gates[gate].get_inputs().size(); ++i) {
|
||||||
|
m_lines[m_gates[gate].get_inputs().at(i)].connect_as_input(gate);
|
||||||
|
}
|
||||||
|
return gate;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_idx CircuitGraph::line(const std::string& name) {
|
||||||
|
auto it = m_name_to_line_idx.find(name);
|
||||||
|
|
||||||
|
if (it != m_name_to_line_idx.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
const line_idx CircuitGraph::get_line(const std::string& name) const {
|
||||||
|
auto it = m_name_to_line_idx.find(name);
|
||||||
|
|
||||||
|
if (it != m_name_to_line_idx.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return NULL_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<line_idx>& CircuitGraph::get_inputs() const {
|
||||||
|
return m_inputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<line_idx>& CircuitGraph::get_outputs() const {
|
||||||
|
return m_outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<Gate>& CircuitGraph::get_gates() const { return m_gates; }
|
||||||
|
|
||||||
|
std::vector<Gate>& CircuitGraph::get_gates() { return m_gates; }
|
||||||
|
|
||||||
|
const std::vector<Line>& CircuitGraph::get_lines() const { return m_lines; }
|
||||||
|
|
||||||
|
line_idx CircuitGraph::ensure_line(const std::string& name) {
|
||||||
|
auto it = m_name_to_line_idx.find(name);
|
||||||
|
|
||||||
|
if (it != m_name_to_line_idx.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lines.emplace_back();
|
||||||
|
Line& line = m_lines.back();
|
||||||
|
|
||||||
|
line.name = name;
|
||||||
|
line.id_line = m_lines.size() - 1;
|
||||||
|
|
||||||
|
m_name_to_line_idx[name] = m_lines.size() - 1;
|
||||||
|
|
||||||
|
return line.id_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CircuitGraph::match_logic_depth() {
|
||||||
|
for (int i = 0, num = m_outputs.size(); i < num; i++) {
|
||||||
|
int level = compute_node_depth(m_lines[m_outputs[i]].source);
|
||||||
|
if (level > max_logic_depth) max_logic_depth = level;
|
||||||
|
}
|
||||||
|
m_node_level.resize(max_logic_depth + 1);
|
||||||
|
for (int i = 0; i < m_gates.size(); i++) {
|
||||||
|
m_node_level[m_gates[i].get_level()].push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算该节点的depth = max children's depth
|
||||||
|
int CircuitGraph::compute_node_depth(const gate_idx g_id) {
|
||||||
|
Gate& gate = m_gates[g_id];
|
||||||
|
// 如果已经被计算过 直接返回
|
||||||
|
if (gate.get_level() != NO_LEVEL) return gate.get_level();
|
||||||
|
// 访问所有子节点计算
|
||||||
|
int max_depth = NO_LEVEL;
|
||||||
|
int level = -1;
|
||||||
|
for (const auto& child : gate.get_inputs()) {
|
||||||
|
if (m_lines[child].is_input) continue;
|
||||||
|
level = compute_node_depth(m_lines[child].source);
|
||||||
|
if (level > max_depth) {
|
||||||
|
max_depth = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (max_depth ==
|
||||||
|
NO_LEVEL) // 走出for循环max_depth没有改变,说明该节点所有的输入线都是input
|
||||||
|
max_depth = -1;
|
||||||
|
m_gates[g_id].level() = max_depth + 1;
|
||||||
|
return m_gates[g_id].level();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CircuitGraph::print_graph() {
|
||||||
|
// 打印INPUT
|
||||||
|
for (unsigned i = 0, length = m_inputs.size(); i < length; i++) {
|
||||||
|
std::cout << "INPUT(" << m_lines[m_inputs[i]].name << ")" << std::endl;
|
||||||
|
}
|
||||||
|
// 打印OUTPUT
|
||||||
|
for (unsigned i = 0, length = m_outputs.size(); i < length; i++) {
|
||||||
|
std::cout << "OUTPUT(" << m_lines[m_outputs[i]].name << ")" << std::endl;
|
||||||
|
}
|
||||||
|
// 打印gate
|
||||||
|
for (unsigned i = 0, length = m_gates.size(); i < length; i++) {
|
||||||
|
auto& gate = m_gates[i];
|
||||||
|
std::cout << m_lines[gate.get_output()].name << " = LUT 0x" << std::hex
|
||||||
|
<< int(gate.make_gate_name(gate.get_type())) << "(";
|
||||||
|
std::vector<std::string> inputs_name;
|
||||||
|
// for(const auto& input : gate.get_inputs())
|
||||||
|
for (int i = gate.get_inputs().size() - 1; i > -1;) {
|
||||||
|
inputs_name.push_back(m_lines[gate.get_inputs()[i]].name);
|
||||||
|
inputs_name.push_back(", ");
|
||||||
|
}
|
||||||
|
inputs_name.pop_back();
|
||||||
|
for (const auto& temp : inputs_name) std::cout << temp;
|
||||||
|
std::cout << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// //打印逻辑深度的信息
|
||||||
|
// int level = -1;
|
||||||
|
// std::cout << "*************************************" << std::endl;
|
||||||
|
// for(const auto& t1 : m_node_level)
|
||||||
|
// {
|
||||||
|
// level++;
|
||||||
|
// std::cout << "lev = " << level << " : ";
|
||||||
|
// for(const auto& t2 : t1)
|
||||||
|
// {
|
||||||
|
// std::cout << t2 << " ";
|
||||||
|
// }
|
||||||
|
// std::cout << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //遍历所有的线 打印线的前后节点信息
|
||||||
|
// for(const auto& line : m_lines)
|
||||||
|
// {
|
||||||
|
// std::cout << "*************************************" << std::endl;
|
||||||
|
// std::cout << "name: " << line.name << " ";
|
||||||
|
// if(line.is_input)
|
||||||
|
// std::cout << "input" << " /";
|
||||||
|
// if(line.is_output)
|
||||||
|
// std::cout << "output" << " /";
|
||||||
|
// if(!line.is_input)
|
||||||
|
// std::cout << "source: " << line.source << std::endl;
|
||||||
|
// if(!line.is_output)
|
||||||
|
// {
|
||||||
|
// std::cout << "destination_gates: ";
|
||||||
|
// for(const auto& gate : line.destination_gates)
|
||||||
|
// std::cout << gate << " ";
|
||||||
|
// std::cout << std::endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} // namespace phyLS
|
|
@ -0,0 +1,136 @@
|
||||||
|
#ifndef CIRCUIT_GRAPH_H
|
||||||
|
#define CIRCUIT_GRAPH_H
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <deque>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "stp_vector.hpp"
|
||||||
|
|
||||||
|
#define NULL_INDEX -1
|
||||||
|
#define NO_LEVEL -10000
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
|
||||||
|
using gate_idx = int;
|
||||||
|
using line_idx = int;
|
||||||
|
using node_level = int;
|
||||||
|
|
||||||
|
using Type = stp_vec;
|
||||||
|
class Gate;
|
||||||
|
class CircuitGraph;
|
||||||
|
|
||||||
|
struct Line {
|
||||||
|
void connect_as_input(gate_idx gate) { destination_gates.insert(gate); }
|
||||||
|
|
||||||
|
gate_idx source = NULL_INDEX; // nullptr means input port
|
||||||
|
std::set<gate_idx> destination_gates;
|
||||||
|
bool is_input = false;
|
||||||
|
bool is_output = false;
|
||||||
|
int id_line = NULL_INDEX;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Gate {
|
||||||
|
public:
|
||||||
|
Gate(Type type, line_idx output,
|
||||||
|
std::vector<line_idx> &&inputs); // 构造一般gate
|
||||||
|
|
||||||
|
Type get_type() const { return m_type; }
|
||||||
|
Type &type() { return m_type; }
|
||||||
|
|
||||||
|
const std::vector<line_idx> &get_inputs() const { return m_inputs; }
|
||||||
|
std::vector<line_idx> &inputs() { return m_inputs; }
|
||||||
|
|
||||||
|
const line_idx &get_output() const { return m_output; }
|
||||||
|
line_idx &output() { return m_output; }
|
||||||
|
|
||||||
|
const int &get_id() const { return m_id; }
|
||||||
|
int &id() { return m_id; }
|
||||||
|
|
||||||
|
const int &get_level() const { return m_level; }
|
||||||
|
int &level() { return m_level; }
|
||||||
|
|
||||||
|
bool is_input() const { return m_type.cols() == 0; }
|
||||||
|
|
||||||
|
int make_gate_name(Type type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type m_type;
|
||||||
|
int m_id = NULL_INDEX;
|
||||||
|
node_level m_level = NO_LEVEL;
|
||||||
|
std::vector<line_idx> m_inputs;
|
||||||
|
line_idx m_output = NULL_INDEX;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CircuitGraph {
|
||||||
|
public:
|
||||||
|
CircuitGraph();
|
||||||
|
|
||||||
|
line_idx add_input(const std::string &name);
|
||||||
|
line_idx add_output(const std::string &name);
|
||||||
|
gate_idx add_gate(Type type, const std::vector<std::string> &input_names,
|
||||||
|
const std::string &output_name);
|
||||||
|
|
||||||
|
const line_idx get_line(const std::string &name) const;
|
||||||
|
line_idx line(const std::string &name);
|
||||||
|
|
||||||
|
const Gate &get_gate(const gate_idx &idx) const { return m_gates[idx]; }
|
||||||
|
Gate &gate(const gate_idx &idx) { return m_gates[idx]; }
|
||||||
|
|
||||||
|
const Line &get_line(const line_idx &idx) const { return m_lines[idx]; }
|
||||||
|
Line &line(const line_idx &idx) { return m_lines[idx]; }
|
||||||
|
|
||||||
|
const std::vector<line_idx> &get_inputs() const;
|
||||||
|
std::vector<line_idx> &inputs() { return m_inputs; }
|
||||||
|
|
||||||
|
const std::vector<line_idx> &get_outputs() const;
|
||||||
|
std::vector<line_idx> &outputs() { return m_outputs; }
|
||||||
|
|
||||||
|
const std::vector<Gate> &get_gates() const;
|
||||||
|
std::vector<Gate> &get_gates();
|
||||||
|
|
||||||
|
const std::vector<Line> &get_lines() const;
|
||||||
|
std::vector<Line> &lines() { return m_lines; }
|
||||||
|
|
||||||
|
const std::vector<std::vector<gate_idx>> &get_m_node_level() const {
|
||||||
|
return m_node_level;
|
||||||
|
}
|
||||||
|
std::vector<std::vector<gate_idx>> &get_m_node_level() {
|
||||||
|
return m_node_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int &get_mld() const { return max_logic_depth; }
|
||||||
|
|
||||||
|
void match_logic_depth();
|
||||||
|
void print_graph();
|
||||||
|
|
||||||
|
private:
|
||||||
|
line_idx ensure_line(const std::string &name);
|
||||||
|
int compute_node_depth(const gate_idx g_id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Line> m_lines;
|
||||||
|
std::vector<Gate> m_gates;
|
||||||
|
|
||||||
|
std::vector<line_idx> m_inputs;
|
||||||
|
std::vector<line_idx> m_outputs;
|
||||||
|
|
||||||
|
std::vector<std::vector<gate_idx>> m_node_level;
|
||||||
|
int max_logic_depth = -1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::unordered_map<std::string, line_idx> m_name_to_line_idx;
|
||||||
|
};
|
||||||
|
} // namespace phyLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,189 @@
|
||||||
|
#include "lut_parser.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
bool LutParser::parse(std::istream& is, CircuitGraph& graph) {
|
||||||
|
const std::string flag_input = "INPUT";
|
||||||
|
const std::string flag_output = "OUTPUT";
|
||||||
|
const std::string flag_lut = "LUT";
|
||||||
|
const std::string flag_gnd = "gnd";
|
||||||
|
for (std::string line; std::getline(is, line, '\n');) {
|
||||||
|
if (line.empty()) continue;
|
||||||
|
if (line.find(flag_input) != std::string::npos) {
|
||||||
|
match_input(graph, line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.find(flag_output) != std::string::npos) {
|
||||||
|
match_output(graph, line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.find(flag_lut) != std::string::npos) {
|
||||||
|
match_gate(graph, line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LutParser::match_input(CircuitGraph& graph, const std::string& line) {
|
||||||
|
std::string input_name = m_split(line, "( )")[1];
|
||||||
|
graph.add_input(input_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LutParser::match_output(CircuitGraph& graph, const std::string& line) {
|
||||||
|
std::string output_name = m_split(line, "( )")[1];
|
||||||
|
graph.add_output(output_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LutParser::match_gate(CircuitGraph& graph, const std::string& line) {
|
||||||
|
std::vector<std::string> gate = m_split(line, ",=( )");
|
||||||
|
std::string output = gate[0];
|
||||||
|
std::string tt = gate[2];
|
||||||
|
gate.erase(gate.begin(), gate.begin() + 3);
|
||||||
|
std::vector<std::string> inputs(gate);
|
||||||
|
tt.erase(0, 2); // 删除0x
|
||||||
|
Type type = get_stp_vec(tt, inputs.size());
|
||||||
|
graph.add_gate(type, inputs, output);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stp_vec LutParser::get_stp_vec(const std::string& tt, const int& inputs_num) {
|
||||||
|
// 只有一个输入的节点(buff 或 not)
|
||||||
|
if (inputs_num == 1 && tt.size() == 1) {
|
||||||
|
stp_vec type(3);
|
||||||
|
type(0) = 2;
|
||||||
|
switch (tt[0]) {
|
||||||
|
case '0':
|
||||||
|
type(1) = 1;
|
||||||
|
type(2) = 1;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
type(1) = 1;
|
||||||
|
type(2) = 0;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
type(1) = 0;
|
||||||
|
type(2) = 1;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
type(1) = 0;
|
||||||
|
type(2) = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
stp_vec type((1 << inputs_num) + 1);
|
||||||
|
type(0) = 2;
|
||||||
|
int type_idx;
|
||||||
|
for (int i = 0, len = tt.size(); i < len; i++) {
|
||||||
|
type_idx = 4 * i + 1;
|
||||||
|
switch (tt[i]) {
|
||||||
|
case '0': // 0000 - > 1111
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case '1': // 0001 - > 1110
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case '2': // 0010 - > 1101
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case '3': // 0011 - > 1100
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case '4': // 0100 - > 1011
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case '5': // 0101 - > 1010
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case '6': // 0110 - > 1001
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case '7': // 0111 - > 1000
|
||||||
|
type(type_idx) = 1;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case '8': // 1000 - > 0111
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case '9': // 1001 - > 0110
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case 'a': // 1010 - > 0101
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case 'b': // 1011 - > 0100
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 1;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case 'c': // 1100 - > 0011
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case 'd': // 1101 - > 0010
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 1;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
case 'e': // 1110 - > 0001
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 1;
|
||||||
|
break;
|
||||||
|
case 'f': // 1111 - > 0000
|
||||||
|
type(type_idx) = 0;
|
||||||
|
type(type_idx + 1) = 0;
|
||||||
|
type(type_idx + 2) = 0;
|
||||||
|
type(type_idx + 3) = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
} // namespace phyLS
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef LUT_PARSER_HPP
|
||||||
|
#define LUT_PARSER_HPP
|
||||||
|
|
||||||
|
#include "circuit_graph.hpp"
|
||||||
|
#include "myfunction.hpp"
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
class LutParser {
|
||||||
|
public:
|
||||||
|
bool parse(std::istream& is, CircuitGraph& graph);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool match_input(CircuitGraph& graph, const std::string& line);
|
||||||
|
bool match_output(CircuitGraph& graph, const std::string& line);
|
||||||
|
bool match_gate(CircuitGraph& graph, const std::string& line);
|
||||||
|
Type get_stp_vec(const std::string& tt, const int& inputs_num);
|
||||||
|
};
|
||||||
|
} // namespace phyLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef MYFUNCTION_HPP
|
||||||
|
#define MYFUNCTION_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
static std::vector<std::string> m_split(const std::string& input,
|
||||||
|
const std::string& pred) {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
std::string temp = "";
|
||||||
|
unsigned count1 = input.size();
|
||||||
|
unsigned count2 = pred.size();
|
||||||
|
unsigned j;
|
||||||
|
for (size_t i = 0; i < count1; i++) {
|
||||||
|
for (j = 0; j < count2; j++) {
|
||||||
|
if (input[i] == pred[j]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if input[i] != pred中的任何一个 该字符加到temp上
|
||||||
|
if (j == count2)
|
||||||
|
temp += input[i];
|
||||||
|
else {
|
||||||
|
if (!temp.empty()) {
|
||||||
|
result.push_back(temp);
|
||||||
|
temp.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void seg_fault(const std::string& name, int size, int idx) {
|
||||||
|
std::cout << name << " " << size << " : " << idx << std::endl;
|
||||||
|
}
|
||||||
|
} // namespace phyLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,180 @@
|
||||||
|
#include "simulator.hpp"
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
simulator::simulator(CircuitGraph& graph) : graph(graph) {
|
||||||
|
pattern_num = 20; // 随机产生10000个仿真向量
|
||||||
|
// max_branch = int( log2(pattern_num) ); //做cut的界
|
||||||
|
max_branch = 8;
|
||||||
|
sim_info.resize(graph.get_lines().size()); // 按照lines的id记录仿真向量的信息
|
||||||
|
lines_flag.resize(graph.get_lines().size(), false); // 按照线的id给线做标记
|
||||||
|
for (const line_idx& line_id : graph.get_inputs()) {
|
||||||
|
sim_info[line_id].resize(pattern_num);
|
||||||
|
lines_flag[line_id] = true;
|
||||||
|
for (int i = 0; i < pattern_num; i++) {
|
||||||
|
sim_info[line_id][i] = rand() % 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simulator::simulate() {
|
||||||
|
// 1: 给电路划分层级
|
||||||
|
graph.match_logic_depth();
|
||||||
|
// 2: 确定电路中需要仿真的nodes
|
||||||
|
need_sim_nodes nodes = get_need_nodes();
|
||||||
|
// 3: 仿真
|
||||||
|
for (const auto& node : nodes) {
|
||||||
|
single_node_sim(node);
|
||||||
|
}
|
||||||
|
// 4: 打印结果
|
||||||
|
// print_simulation_result();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
need_sim_nodes simulator::get_need_nodes() {
|
||||||
|
need_sim_nodes nodes;
|
||||||
|
for (const auto& nodes_id : graph.get_m_node_level()) {
|
||||||
|
for (const auto& node_id : nodes_id) {
|
||||||
|
const auto& node = graph.get_gates()[node_id];
|
||||||
|
const auto& output = graph.get_lines()[node.get_output()];
|
||||||
|
// 如果是output节点或多扇出节点,则需要仿真
|
||||||
|
if (output.is_output || output.destination_gates.size() > fanout_limit) {
|
||||||
|
nodes.clear();
|
||||||
|
lines_flag[node.get_output()] = true; // 给需要仿真的节点打标记
|
||||||
|
nodes.push_back(node_id);
|
||||||
|
cut_tree(nodes);
|
||||||
|
}
|
||||||
|
nodes.push_back(node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.clear();
|
||||||
|
for (unsigned level = 0; level <= graph.get_mld(); level++) {
|
||||||
|
for (const auto& node_id : graph.get_m_node_level()[level]) {
|
||||||
|
line_idx output = graph.get_gates()[node_id].get_output();
|
||||||
|
lines_flag[output] == true;
|
||||||
|
if (lines_flag[output] == true) {
|
||||||
|
nodes.push_back(node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 广度优先遍历 cut tree
|
||||||
|
void simulator::cut_tree(need_sim_nodes& nodes) {
|
||||||
|
need_sim_nodes temp_nodes;
|
||||||
|
const auto& graph_lines = graph.get_lines();
|
||||||
|
const auto& graph_gates = graph.get_gates();
|
||||||
|
while (!nodes.empty()) {
|
||||||
|
temp_nodes.clear();
|
||||||
|
temp_nodes.push_back(nodes.front());
|
||||||
|
nodes.pop_front();
|
||||||
|
int count = 0;
|
||||||
|
while (1) {
|
||||||
|
for (const auto& input : graph_gates[temp_nodes.front()].get_inputs()) {
|
||||||
|
count++;
|
||||||
|
if (lines_flag[input] == false) {
|
||||||
|
temp_nodes.push_back(graph_lines[input].source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp_nodes.pop_front();
|
||||||
|
count--;
|
||||||
|
// 对应该两种情况 (确实是棵大树,将其化为小树 || 本就是一颗小树)
|
||||||
|
if (count > max_branch || temp_nodes.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& node_id : temp_nodes) {
|
||||||
|
lines_flag[graph_gates[node_id].get_output()] = true;
|
||||||
|
nodes.push_back(node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simulator::single_node_sim(const gate_idx node_id) {
|
||||||
|
const auto& node = graph.get_gates()[node_id];
|
||||||
|
const gate_idx& output = node.get_output();
|
||||||
|
// 1:生成矩阵链
|
||||||
|
std::map<line_idx, int> map;
|
||||||
|
m_chain matrix_chain;
|
||||||
|
get_node_matrix(node_id, matrix_chain, map);
|
||||||
|
// 2:分析矩阵链,减少变量个数
|
||||||
|
stp_logic_manage stp;
|
||||||
|
stp_vec root_stp_vec = stp.normalize_matrix(matrix_chain);
|
||||||
|
// 3:仿真
|
||||||
|
std::vector<line_idx> variable(map.size());
|
||||||
|
int inputs_number = variable.size();
|
||||||
|
for (const auto& temp : map) variable[temp.second - 1] = temp.first;
|
||||||
|
sim_info[output].resize(pattern_num);
|
||||||
|
int idx;
|
||||||
|
int bits = 1 << inputs_number;
|
||||||
|
for (int i = 0; i < pattern_num; i++) {
|
||||||
|
idx = 0;
|
||||||
|
for (int j = 0; j < inputs_number; j++) {
|
||||||
|
idx = (idx << 1) + sim_info[variable[j]][i];
|
||||||
|
}
|
||||||
|
idx = bits - idx;
|
||||||
|
sim_info[output][i] = 1 - root_stp_vec(idx);
|
||||||
|
}
|
||||||
|
lines_flag[output] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于某个cut 生成matrix chain
|
||||||
|
void simulator::get_node_matrix(const gate_idx node_id, m_chain& mc,
|
||||||
|
std::map<line_idx, int>& map) {
|
||||||
|
const auto& node = graph.get_gates()[node_id];
|
||||||
|
mc.push_back(node.get_type());
|
||||||
|
int temp;
|
||||||
|
for (const auto& line_id : node.get_inputs()) {
|
||||||
|
if (lines_flag[line_id]) // 存变量
|
||||||
|
{
|
||||||
|
if (map.find(line_id) == map.end()) {
|
||||||
|
temp = map.size() + 1;
|
||||||
|
map.emplace(line_id, map.size() + 1);
|
||||||
|
} else
|
||||||
|
temp = map.at(line_id);
|
||||||
|
mc.emplace_back(1, temp);
|
||||||
|
} else // 存lut (PIs)的lines_flag必为true 所以这种情况不可能出现source为空
|
||||||
|
{
|
||||||
|
get_node_matrix(graph.get_lines()[line_id].source, mc, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simulator::print_simulation_result() {
|
||||||
|
for (const auto& input_id : graph.get_inputs()) {
|
||||||
|
std::cout << graph.get_lines()[input_id].name << " ";
|
||||||
|
}
|
||||||
|
std::cout << ": ";
|
||||||
|
for (const auto& output_id : graph.get_outputs()) {
|
||||||
|
std::cout << graph.get_lines()[output_id].name << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
for (int i = 0; i < pattern_num; i++) {
|
||||||
|
for (const auto& input_id : graph.get_inputs()) {
|
||||||
|
std::cout << sim_info[input_id][i] << " ";
|
||||||
|
}
|
||||||
|
std::cout << ": ";
|
||||||
|
for (const auto& output_id : graph.get_outputs()) {
|
||||||
|
std::cout << sim_info[output_id][i] << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simulator::check_sim_info() {
|
||||||
|
for (int i = 0; i < sim_info.size(); i++) {
|
||||||
|
if (sim_info[i].size() != pattern_num) {
|
||||||
|
std::cout << "!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < sim_info[i].size(); j++) {
|
||||||
|
if (sim_info[i][j] != 0 && sim_info[i][j] != 1) {
|
||||||
|
std::cout << "!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "^ ^" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace phyLS
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef C_SIMLUATOR_HPP
|
||||||
|
#define C_SIMLUATOR_HPP
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "circuit_graph.hpp"
|
||||||
|
#include "myfunction.hpp"
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
|
||||||
|
using need_sim_nodes = std::deque<gate_idx>;
|
||||||
|
using line_sim_info = std::vector<u_int16_t>;
|
||||||
|
|
||||||
|
class simulator {
|
||||||
|
public:
|
||||||
|
simulator(CircuitGraph& graph);
|
||||||
|
bool simulate(); // simulate
|
||||||
|
void print_simulation_result();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_simulated(const line_idx id) {
|
||||||
|
return sim_info[id].size() == pattern_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
need_sim_nodes get_need_nodes();
|
||||||
|
void single_node_sim(const gate_idx node);
|
||||||
|
void get_node_matrix(const gate_idx node, m_chain& mc,
|
||||||
|
std::map<line_idx, int>& map);
|
||||||
|
void cut_tree(need_sim_nodes& nodes);
|
||||||
|
bool check_sim_info();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<line_sim_info> sim_info;
|
||||||
|
std::vector<int> time_interval;
|
||||||
|
std::vector<bool> lines_flag;
|
||||||
|
CircuitGraph& graph;
|
||||||
|
int pattern_num;
|
||||||
|
int max_branch;
|
||||||
|
int fanout_limit = 1;
|
||||||
|
};
|
||||||
|
} // namespace phyLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,260 @@
|
||||||
|
#ifndef STP_VECTOR_HPP
|
||||||
|
#define STP_VECTOR_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "myfunction.hpp"
|
||||||
|
|
||||||
|
namespace phyLS {
|
||||||
|
class stp_vec;
|
||||||
|
using word = unsigned;
|
||||||
|
using m_chain = std::vector<stp_vec>;
|
||||||
|
|
||||||
|
class stp_vec {
|
||||||
|
// 重载打印操作符
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const stp_vec &v) {
|
||||||
|
const unsigned length = v.cols();
|
||||||
|
for (unsigned i = 0; i < length; ++i) os << v.vec[i] << " ";
|
||||||
|
os << std::endl;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重载初始化操作符
|
||||||
|
friend std::istream &operator>>(std::istream &is, stp_vec &v) {
|
||||||
|
const unsigned length = v.cols();
|
||||||
|
for (unsigned i = 0; i < length; ++i) is >> v.vec[i];
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 各种初始化操作
|
||||||
|
stp_vec() { this->vec.clear(); }
|
||||||
|
stp_vec(unsigned cols, unsigned value = 0) { this->vec.resize(cols, value); }
|
||||||
|
stp_vec(const stp_vec &v) { this->vec = v.vec; }
|
||||||
|
stp_vec &operator=(const stp_vec &v) {
|
||||||
|
this->vec = v.vec;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重载==
|
||||||
|
bool operator==(const stp_vec &v) {
|
||||||
|
unsigned m_length = this->cols();
|
||||||
|
unsigned length = v.cols();
|
||||||
|
if (m_length != length) return false;
|
||||||
|
for (unsigned i = 0; i < length; ++i) {
|
||||||
|
if (this->vec[i] != v.vec[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 重载()
|
||||||
|
word &operator()(unsigned idx) { return vec[idx]; }
|
||||||
|
|
||||||
|
const word &operator()(unsigned idx) const { return vec[idx]; }
|
||||||
|
|
||||||
|
// 获取矩阵的列数
|
||||||
|
const unsigned cols() const { return this->vec.size(); }
|
||||||
|
|
||||||
|
// 判断是不是一个变量
|
||||||
|
bool is_variable() { return this->cols() == 1; }
|
||||||
|
|
||||||
|
// 块赋值
|
||||||
|
bool block(const stp_vec &v, int m_begin, int begin, int num) {
|
||||||
|
if (this->cols() < num || v.cols() < num) {
|
||||||
|
std::cout << "block abnormal" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < num; ++i) {
|
||||||
|
this->vec[m_begin + i] = v.vec[begin + i];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
private:
|
||||||
|
std::vector<word> vec; // 可以对比一下vector 与 deque
|
||||||
|
};
|
||||||
|
|
||||||
|
class stp_logic_manage {
|
||||||
|
public:
|
||||||
|
// 生成一个交换矩阵
|
||||||
|
stp_vec logic_swap_matrix(int m, int n) {
|
||||||
|
stp_vec result(m * n + 1);
|
||||||
|
int p, q;
|
||||||
|
result(0) = m * n;
|
||||||
|
for (int i = 0; i < m * n; i++) {
|
||||||
|
p = i / m;
|
||||||
|
q = i % m;
|
||||||
|
int j = q * n + p;
|
||||||
|
result(j + 1) = i;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 克罗内克积
|
||||||
|
stp_vec logic_kron_product(const stp_vec &v_f, const stp_vec &v_b) {
|
||||||
|
int m = v_f(0);
|
||||||
|
int n = v_f.cols() - 1;
|
||||||
|
int p = v_b(0);
|
||||||
|
int q = v_b.cols() - 1;
|
||||||
|
stp_vec result(n * q + 1);
|
||||||
|
result(0) = m * p;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int temp = v_f(i + 1) * p;
|
||||||
|
int idx = i * q + 1;
|
||||||
|
for (int j = 0; j < q; j++) {
|
||||||
|
result(idx + j) = temp + v_b(j + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 两矩阵乘法
|
||||||
|
stp_vec logic_stpm_product(const stp_vec &v_f, const stp_vec &v_b) {
|
||||||
|
int mf_row = v_f(0); // m
|
||||||
|
int mf_col = v_f.cols() - 1; // n
|
||||||
|
int mb_row = v_b(0); // p
|
||||||
|
int mb_col = v_b.cols() - 1; // q
|
||||||
|
int row, col;
|
||||||
|
stp_vec result;
|
||||||
|
if (mf_col % mb_row == 0) {
|
||||||
|
int times = mf_col / mb_row;
|
||||||
|
row = mf_row;
|
||||||
|
col = times * mb_col;
|
||||||
|
stp_vec result_matrix(col + 1);
|
||||||
|
result_matrix(0) = row;
|
||||||
|
for (int i = 1; i <= mb_col; ++i) {
|
||||||
|
result_matrix.block(v_f, 1 + times * (i - 1), times * v_b(i) + 1,
|
||||||
|
times);
|
||||||
|
}
|
||||||
|
return result_matrix;
|
||||||
|
} else if (mb_row % mf_col == 0) {
|
||||||
|
int times = mb_row / mf_col;
|
||||||
|
stp_vec i_times(times + 1);
|
||||||
|
i_times(0) = times;
|
||||||
|
// 单位矩阵的编码向量
|
||||||
|
for (int i = 1; i <= times; i++) {
|
||||||
|
i_times(i) = i - 1;
|
||||||
|
}
|
||||||
|
return logic_stpm_product(logic_kron_product(v_f, i_times), v_b);
|
||||||
|
} else {
|
||||||
|
std::cout << v_f << v_b << std::endl;
|
||||||
|
std::cout << "matrix type error!" << std::endl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 矩阵链乘法
|
||||||
|
stp_vec matrix_chain_mul(const m_chain &matrix_chain) {
|
||||||
|
if (matrix_chain.size() == 1) return matrix_chain[0];
|
||||||
|
stp_vec result;
|
||||||
|
result = logic_stpm_product(matrix_chain[0], matrix_chain[1]);
|
||||||
|
for (int i = 2; i < matrix_chain.size(); i++) {
|
||||||
|
result = logic_stpm_product(result, matrix_chain[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 化为规范型 提前给出变量的信息
|
||||||
|
stp_vec normalize_matrix(m_chain &vec_chain) {
|
||||||
|
stp_vec Mr(3);
|
||||||
|
Mr(0) = 4;
|
||||||
|
Mr(1) = 0;
|
||||||
|
Mr(2) = 3; // Reduced power matrix
|
||||||
|
stp_vec I2(3);
|
||||||
|
I2(0) = 2;
|
||||||
|
I2(1) = 0;
|
||||||
|
I2(2) = 1;
|
||||||
|
stp_vec normal_matrix;
|
||||||
|
int p_variable;
|
||||||
|
int p;
|
||||||
|
int max = 0;
|
||||||
|
for (int i = 0; i < vec_chain.size();
|
||||||
|
i++) // the max is the number of variable
|
||||||
|
{
|
||||||
|
if (vec_chain[i].is_variable() && vec_chain[i](0) > max) {
|
||||||
|
max = vec_chain[i](0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理直接就是规范型的矩阵链
|
||||||
|
if (vec_chain.size() == max + 1) return vec_chain[0];
|
||||||
|
// 常规处理
|
||||||
|
std::vector<int> idx(max + 1); // id0 is the max of idx
|
||||||
|
p_variable = vec_chain.size() - 1;
|
||||||
|
int flag;
|
||||||
|
while (p_variable >= 0) {
|
||||||
|
int flag = 0;
|
||||||
|
if (vec_chain[p_variable].is_variable()) // 1:find a variable
|
||||||
|
{
|
||||||
|
if (idx[vec_chain[p_variable](0)] == 0) {
|
||||||
|
idx[vec_chain[p_variable](0)] = idx[0] + 1;
|
||||||
|
idx[0]++;
|
||||||
|
if (p_variable == vec_chain.size() - 1) //!
|
||||||
|
{
|
||||||
|
vec_chain.pop_back();
|
||||||
|
p_variable--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (idx[vec_chain[p_variable](0)] == idx[0]) {
|
||||||
|
flag = 1;
|
||||||
|
if (p_variable == vec_chain.size() - 1) {
|
||||||
|
vec_chain.pop_back();
|
||||||
|
vec_chain.push_back(Mr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flag = 1;
|
||||||
|
vec_chain.push_back(logic_swap_matrix(
|
||||||
|
2, 1 << (idx[0] - idx[vec_chain[p_variable](0)])));
|
||||||
|
for (int i = 1; i <= max; i++) {
|
||||||
|
if (idx[i] != 0 && idx[i] > idx[vec_chain[p_variable](0)])
|
||||||
|
idx[i]--;
|
||||||
|
}
|
||||||
|
idx[vec_chain[p_variable](0)] = idx[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_chain matrix_chain1; //?
|
||||||
|
matrix_chain1.clear();
|
||||||
|
for (p = p_variable + 1; p < vec_chain.size(); p++) {
|
||||||
|
matrix_chain1.push_back(vec_chain[p]); // have no matrix
|
||||||
|
}
|
||||||
|
while (p > p_variable + 1) {
|
||||||
|
vec_chain.pop_back();
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
if (matrix_chain1.size() > 0) {
|
||||||
|
vec_chain.push_back(matrix_chain_mul(matrix_chain1));
|
||||||
|
}
|
||||||
|
if (p_variable != vec_chain.size() - 1) {
|
||||||
|
vec_chain[p_variable] =
|
||||||
|
logic_kron_product(I2, vec_chain[p_variable + 1]);
|
||||||
|
vec_chain.pop_back();
|
||||||
|
}
|
||||||
|
if (flag) vec_chain.push_back(Mr);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
p_variable--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 后续矩阵链中已经没有变量
|
||||||
|
for (int i = max; i > 0; i--) //!
|
||||||
|
{
|
||||||
|
vec_chain.push_back(logic_swap_matrix(2, 1 << (idx[0] - idx[i])));
|
||||||
|
for (int j = 1; j <= max; j++) {
|
||||||
|
if (idx[j] != 0 && idx[j] > idx[i]) idx[j]--;
|
||||||
|
}
|
||||||
|
idx[i] = max;
|
||||||
|
}
|
||||||
|
normal_matrix = matrix_chain_mul(vec_chain);
|
||||||
|
return normal_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
} // namespace phyLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -47,5 +47,8 @@
|
||||||
#include "commands/abc/fraig.hpp"
|
#include "commands/abc/fraig.hpp"
|
||||||
#include "commands/abc/&get.hpp"
|
#include "commands/abc/&get.hpp"
|
||||||
#include "commands/abc/&fraig.hpp"
|
#include "commands/abc/&fraig.hpp"
|
||||||
|
#include "commands/abc/comb.hpp"
|
||||||
|
#include "commands/simulator.hpp"
|
||||||
|
#include "commands/abc/cec.hpp"
|
||||||
|
|
||||||
ALICE_MAIN(phyLS)
|
ALICE_MAIN(phyLS)
|
|
@ -231,6 +231,16 @@ ALICE_PRINT_STORE_STATISTICS(aig_network, os, aig) {
|
||||||
|
|
||||||
ALICE_ADD_FILE_TYPE(verilog, "Verilog");
|
ALICE_ADD_FILE_TYPE(verilog, "Verilog");
|
||||||
|
|
||||||
|
ALICE_READ_FILE(aig_network, verilog, filename, cmd) {
|
||||||
|
aig_network aig;
|
||||||
|
|
||||||
|
if (lorina::read_verilog(filename, mockturtle::verilog_reader(aig)) !=
|
||||||
|
lorina::return_code::success) {
|
||||||
|
std::cout << "[w] parse error\n";
|
||||||
|
}
|
||||||
|
return aig;
|
||||||
|
}
|
||||||
|
|
||||||
ALICE_READ_FILE(xmg_network, verilog, filename, cmd) {
|
ALICE_READ_FILE(xmg_network, verilog, filename, cmd) {
|
||||||
xmg_network xmg;
|
xmg_network xmg;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue