simulator

pull/1/head
panhongyang 2023-03-30 15:14:19 +08:00
parent 9635c0de3c
commit 83d6e01e3c
13 changed files with 1320 additions and 0 deletions

84
src/commands/abc/cec.hpp Normal file
View File

@ -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

72
src/commands/abc/comb.hpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -47,5 +47,8 @@
#include "commands/abc/fraig.hpp"
#include "commands/abc/&get.hpp"
#include "commands/abc/&fraig.hpp"
#include "commands/abc/comb.hpp"
#include "commands/simulator.hpp"
#include "commands/abc/cec.hpp"
ALICE_MAIN(phyLS)

View File

@ -231,6 +231,16 @@ ALICE_PRINT_STORE_STATISTICS(aig_network, os, aig) {
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) {
xmg_network xmg;