vscode自动编译调试程序
This commit is contained in:
parent
329f3a849f
commit
c8ef5ac6dd
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
*.o
|
*.o
|
||||||
*.d
|
*.d
|
||||||
.vscode
|
|
||||||
output.txt
|
output.txt
|
||||||
|
17
.vscode/c_cpp_properties.json
vendored
Normal file
17
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
34
.vscode/launch.json
vendored
Normal file
34
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
// 使用 IntelliSense 了解相关属性。
|
||||||
|
// 悬停以查看现有属性的描述。
|
||||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "(gdb) 启动",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/atpg",
|
||||||
|
"args": ["c432.bench"],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${fileDirname}",
|
||||||
|
"environment": [],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "为 gdb 启用整齐打印",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "将反汇编风格设置为 Intel",
|
||||||
|
"text": "-gdb-set disassembly-flavor intel",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preLaunchTask": "build"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
12
.vscode/tasks.json
vendored
Normal file
12
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -j 8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
12
circuit.cpp
12
circuit.cpp
@ -10,6 +10,10 @@ void Circuit::init_stems() {
|
|||||||
if(gate->outputs.size() >= 2) {
|
if(gate->outputs.size() >= 2) {
|
||||||
gate->stem = true;
|
gate->stem = true;
|
||||||
}
|
}
|
||||||
|
// gate->stem = true;
|
||||||
|
// if(rand() % 1000 <= 100) {
|
||||||
|
// gate->stem = true;
|
||||||
|
// }
|
||||||
if(gate->stem) {
|
if(gate->stem) {
|
||||||
stems.push_back(gate);
|
stems.push_back(gate);
|
||||||
}
|
}
|
||||||
@ -137,10 +141,15 @@ bool Circuit::is_valid_circuit() {
|
|||||||
int stem_total_cnt = 0;
|
int stem_total_cnt = 0;
|
||||||
int fault_total_cnt = 0;
|
int fault_total_cnt = 0;
|
||||||
|
|
||||||
|
ll fault_propagate_score = 0;
|
||||||
|
|
||||||
//printf("flip: %d, stem: %d, fault:%d\n", flip_total_weight, stem_total_weight, fault_total_weight);
|
//printf("flip: %d, stem: %d, fault:%d\n", flip_total_weight, stem_total_weight, fault_total_weight);
|
||||||
|
|
||||||
for(Gate* g : gates) {
|
for(Gate* g : gates) {
|
||||||
|
|
||||||
|
fault_propagate_score += g->fault_propagate_len[0] * fault_weight[g->id][0];
|
||||||
|
fault_propagate_score += g->fault_propagate_len[1] * fault_weight[g->id][1];
|
||||||
|
|
||||||
if(flip_need_update[g->id]) {
|
if(flip_need_update[g->id]) {
|
||||||
flip_total_weight += flip_weight[g->id];
|
flip_total_weight += flip_weight[g->id];
|
||||||
flip_total_cnt++;
|
flip_total_cnt++;
|
||||||
@ -225,6 +234,9 @@ bool Circuit::is_valid_circuit() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("%lld %lld\n", fault_propagate_score , this->fault_propagate_score);
|
||||||
|
assert(fault_propagate_score == this->fault_propagate_score);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
circuit.h
12
circuit.h
@ -61,7 +61,6 @@ bool is_valid_circuit();
|
|||||||
|
|
||||||
void init_topo_index();
|
void init_topo_index();
|
||||||
|
|
||||||
|
|
||||||
int MAX_GATE_LEVEL;
|
int MAX_GATE_LEVEL;
|
||||||
void init_gate_level();
|
void init_gate_level();
|
||||||
void init_stems();
|
void init_stems();
|
||||||
@ -94,7 +93,7 @@ int* stem_weight;
|
|||||||
int* stem_satisfied;
|
int* stem_satisfied;
|
||||||
|
|
||||||
int fault_propagate_tatal_len;
|
int fault_propagate_tatal_len;
|
||||||
int fault_propagate_score;
|
ll fault_propagate_score;
|
||||||
|
|
||||||
const int FAULT_INC = 1;
|
const int FAULT_INC = 1;
|
||||||
const int FAULT_WEIGHT_MAX = 20;
|
const int FAULT_WEIGHT_MAX = 20;
|
||||||
@ -118,4 +117,13 @@ ll ls_score();
|
|||||||
|
|
||||||
int** simulate();
|
int** simulate();
|
||||||
|
|
||||||
|
|
||||||
|
// time status
|
||||||
|
|
||||||
|
int flip_cnt = 0;
|
||||||
|
double flip_time = 0;
|
||||||
|
|
||||||
|
int update_cnt = 0;
|
||||||
|
double update_time = 0;
|
||||||
|
|
||||||
};
|
};
|
1
fault-simulator
Submodule
1
fault-simulator
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 54d48b917c1f5ab7a9ea4c8de2573b649dd73575
|
56
ls.cpp
56
ls.cpp
@ -5,6 +5,9 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
||||||
|
|
||||||
@ -21,6 +24,8 @@ bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
|||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
||||||
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
Gate* stem = nullptr;
|
Gate* stem = nullptr;
|
||||||
ll max_score = 0;
|
ll max_score = 0;
|
||||||
|
|
||||||
@ -36,7 +41,7 @@ bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
|||||||
std::swap(stems_random[i], stems_random[rand()%stems_random.size()]);
|
std::swap(stems_random[i], stems_random[rand()%stems_random.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int T = 25;
|
const int T = 50;
|
||||||
int t = 0;
|
int t = 0;
|
||||||
|
|
||||||
for(int i=0; i<stems_random.size(); i++) {
|
for(int i=0; i<stems_random.size(); i++) {
|
||||||
@ -65,6 +70,11 @@ bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
|||||||
CC[suc->id] = 1;
|
CC[suc->id] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
std::chrono::duration<double> elapsed_seconds = end - start;
|
||||||
|
flip_cnt++;
|
||||||
|
flip_time += elapsed_seconds.count();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ls_update_weight();
|
ls_update_weight();
|
||||||
|
|
||||||
@ -109,6 +119,11 @@ bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
|||||||
CC[suc->id] = 1;
|
CC[suc->id] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
std::chrono::duration<double> elapsed_seconds = end - start;
|
||||||
|
update_cnt++;
|
||||||
|
update_time += elapsed_seconds.count();
|
||||||
|
|
||||||
//printf("[UP] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %lld, stem_cnt: %lld, fault_cnt:%lld\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt);
|
//printf("[UP] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %lld, stem_cnt: %lld, fault_cnt:%lld\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,6 +146,9 @@ bool Circuit::local_search(std::unordered_set<Fault*> &faults) {
|
|||||||
|
|
||||||
printf("coverage: %.3f%%\tpattern: %d\tbefore: %d\tnow: %d\n", (double)(original_faults - faults.size()) / (original_faults) * 100, ++pattern, tmp.size(), faults.size());
|
printf("coverage: %.3f%%\tpattern: %d\tbefore: %d\tnow: %d\n", (double)(original_faults - faults.size()) / (original_faults) * 100, ++pattern, tmp.size(), faults.size());
|
||||||
|
|
||||||
|
printf("flip-cnt: %d flip-time: %.3fs update-cnt: %d update-time: %.3fs\n", flip_cnt, flip_time, update_cnt, update_time);
|
||||||
|
printf("time-per-flip: %.2fms time-per-update: %.2fms\n", flip_time / flip_cnt * 1000, update_time / update_cnt * 1000);
|
||||||
|
|
||||||
//if(tmp.size() == faults.size()) return false;
|
//if(tmp.size() == faults.size()) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -177,10 +195,12 @@ void Circuit::ls_update_weight() {
|
|||||||
|
|
||||||
if(!g->sa[0] && fault_weight[g->id][0] > 0 && (fault_weight[g->id][0] + FAULT_INC < FAULT_WEIGHT_MAX)) {
|
if(!g->sa[0] && fault_weight[g->id][0] > 0 && (fault_weight[g->id][0] + FAULT_INC < FAULT_WEIGHT_MAX)) {
|
||||||
fault_weight[g->id][0] += FAULT_INC;
|
fault_weight[g->id][0] += FAULT_INC;
|
||||||
|
fault_propagate_score += FAULT_INC * (g->fault_propagate_len[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!g->sa[1] && fault_weight[g->id][1] > 0 && (fault_weight[g->id][1] + FAULT_INC < FAULT_WEIGHT_MAX)) {
|
if(!g->sa[1] && fault_weight[g->id][1] > 0 && (fault_weight[g->id][1] + FAULT_INC < FAULT_WEIGHT_MAX)) {
|
||||||
fault_weight[g->id][1] += FAULT_INC;
|
fault_weight[g->id][1] += FAULT_INC;
|
||||||
|
fault_propagate_score += FAULT_INC * (g->fault_propagate_len[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,9 +215,11 @@ void Circuit::ls_flip(Gate* stem) {
|
|||||||
stem->value = !stem->value;
|
stem->value = !stem->value;
|
||||||
ls_block_recal(stem);
|
ls_block_recal(stem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Circuit::ls_update(Gate* stem) {
|
void Circuit::ls_update(Gate* stem) {
|
||||||
ls_block_recal(stem);
|
ls_block_recal(stem);
|
||||||
}
|
}
|
||||||
|
|
||||||
ll Circuit::ls_pick_score(Gate* stem) {
|
ll Circuit::ls_pick_score(Gate* stem) {
|
||||||
|
|
||||||
ll old_score = ls_score();
|
ll old_score = ls_score();
|
||||||
@ -215,7 +237,7 @@ ll Circuit::ls_pick_score(Gate* stem) {
|
|||||||
|
|
||||||
ll Circuit::ls_score() {
|
ll Circuit::ls_score() {
|
||||||
//ll score = - flip_total_weight - stem_total_weight + fault_total_weight + fault_propagate_tatal_len;
|
//ll score = - flip_total_weight - stem_total_weight + fault_total_weight + fault_propagate_tatal_len;
|
||||||
ll score = - flip_total_weight - stem_total_weight + 10 * fault_propagate_tatal_len;
|
ll score = - flip_total_weight - stem_total_weight + fault_propagate_score;
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,9 +246,17 @@ void Circuit::ls_init_weight(const std::unordered_set<Fault*> &faults) {
|
|||||||
stem_weight[s->id] = 1;
|
stem_weight[s->id] = 1;
|
||||||
stem_total_weight += stem_weight[s->id];
|
stem_total_weight += stem_weight[s->id];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Fault* f : faults) {
|
for(Fault* f : faults) {
|
||||||
fault_weight[f->gate->id][f->type] = 1;
|
fault_weight[f->gate->id][f->type] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int r = rand() % faults.size();
|
||||||
|
auto it = faults.begin();
|
||||||
|
std::advance(it, r);
|
||||||
|
|
||||||
|
fault_weight[(*it)->gate->id][(*it)->type] = 1000000;
|
||||||
|
|
||||||
for(Gate* s: stems) {
|
for(Gate* s: stems) {
|
||||||
flip_weight[s->id] = 1;
|
flip_weight[s->id] = 1;
|
||||||
}
|
}
|
||||||
@ -280,7 +310,7 @@ void Circuit::ls_init_data_structs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEM_INC = 0;
|
STEM_INC = 1;
|
||||||
|
|
||||||
fault_propagate_score = 0;
|
fault_propagate_score = 0;
|
||||||
|
|
||||||
@ -385,9 +415,10 @@ void Circuit::ls_block_recal(Gate* stem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::queue<Gate*> q;
|
static std::queue<Gate*> q;
|
||||||
std::unordered_map<Gate*, int> used;
|
static std::unordered_map<Gate*, int> used;
|
||||||
std::vector<Gate*> suc_stems;
|
assert(q.empty());
|
||||||
|
used.clear();
|
||||||
|
|
||||||
q.push(stem);
|
q.push(stem);
|
||||||
|
|
||||||
@ -397,7 +428,6 @@ void Circuit::ls_block_recal(Gate* stem) {
|
|||||||
used[g] = false;
|
used[g] = false;
|
||||||
for(Gate* out : g->outputs) {
|
for(Gate* out : g->outputs) {
|
||||||
if(out->stem) {
|
if(out->stem) {
|
||||||
suc_stems.push_back(out);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out->value = out->cal_value();
|
out->value = out->cal_value();
|
||||||
@ -411,20 +441,23 @@ void Circuit::ls_block_recal(Gate* stem) {
|
|||||||
assert(q.empty());
|
assert(q.empty());
|
||||||
used.clear();
|
used.clear();
|
||||||
|
|
||||||
for(Gate* stem : suc_stems) {
|
for(Gate* stem : stem->suc_stems) {
|
||||||
q.push(stem);
|
q.push(stem);
|
||||||
|
|
||||||
int fpl0 = stem->cal_propagate_len(0);
|
int fpl0 = stem->cal_propagate_len(0);
|
||||||
int fpl1 = stem->cal_propagate_len(1);
|
int fpl1 = stem->cal_propagate_len(1);
|
||||||
|
|
||||||
if(fault_weight[stem->id][0]) {
|
if(fault_weight[stem->id][0]) {
|
||||||
fault_propagate_tatal_len += fpl0 - stem->fault_propagate_len[0];
|
fault_propagate_tatal_len += (fpl0 - stem->fault_propagate_len[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fault_weight[stem->id][1]) {
|
if(fault_weight[stem->id][1]) {
|
||||||
fault_propagate_tatal_len += fpl1 - stem->fault_propagate_len[1];
|
fault_propagate_tatal_len += (fpl1 - stem->fault_propagate_len[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fault_propagate_score += (fault_weight[stem->id][0] * (fpl0 - stem->fault_propagate_len[0]));
|
||||||
|
fault_propagate_score += (fault_weight[stem->id][1] * (fpl1 - stem->fault_propagate_len[1]));
|
||||||
|
|
||||||
stem->fault_propagate_len[0] = fpl0;
|
stem->fault_propagate_len[0] = fpl0;
|
||||||
stem->fault_propagate_len[1] = fpl1;
|
stem->fault_propagate_len[1] = fpl1;
|
||||||
|
|
||||||
@ -496,6 +529,9 @@ void Circuit::ls_block_recal(Gate* stem) {
|
|||||||
fault_propagate_tatal_len += fpl1 - in->fault_propagate_len[1];
|
fault_propagate_tatal_len += fpl1 - in->fault_propagate_len[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fault_propagate_score += fault_weight[in->id][0] * (fpl0 - in->fault_propagate_len[0]);
|
||||||
|
fault_propagate_score += fault_weight[in->id][1] * (fpl1 - in->fault_propagate_len[1]);
|
||||||
|
|
||||||
in->fault_propagate_len[0] = fpl0;
|
in->fault_propagate_len[0] = fpl0;
|
||||||
in->fault_propagate_len[1] = fpl1;
|
in->fault_propagate_len[1] = fpl1;
|
||||||
|
|
||||||
|
2
makefile
2
makefile
@ -7,7 +7,7 @@
|
|||||||
#编译工具用g++,以同时支持C和C++程序,以及二者的混合编译
|
#编译工具用g++,以同时支持C和C++程序,以及二者的混合编译
|
||||||
CC=g++
|
CC=g++
|
||||||
|
|
||||||
CPPFLAGS=-O3 -std=c++17
|
CPPFLAGS=-O3 -std=c++17 -g
|
||||||
|
|
||||||
#使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表
|
#使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表
|
||||||
#sources:=main.cpp command.c
|
#sources:=main.cpp command.c
|
||||||
|
30
report/atpg-ls-动态增量-仿真.txt
Normal file
30
report/atpg-ls-动态增量-仿真.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------------
|
||||||
|
| data | fault coverage(ATPG-LS) | time(ATPG-LS) | cube(ATPG-LS) | pattern(ATPG-LS) |
|
||||||
|
| ----------------------- | ----------------------- | -------------------- | ------------- | ---------------- |
|
||||||
|
| ./benchmark/c17.bench | 100.000 | 0.035004615783691406 | 5 | 5 |
|
||||||
|
| ./benchmark/b06.bench | 100.000 | 0.07079482078552246 | 11 | 11 |
|
||||||
|
| ./benchmark/b01.bench | 100.000 | 0.09065485000610352 | 14 | 14 |
|
||||||
|
| ./benchmark/b03.bench | 100.000 | 2.3637137413024902 | 14 | 14 |
|
||||||
|
| ./benchmark/b09.bench | 100.000 | 3.8993797302246094 | 18 | 18 |
|
||||||
|
| ./benchmark/b10.bench | 100.000 | 6.369290351867676 | 29 | 29 |
|
||||||
|
| ./benchmark/b08.bench | 100.000 | 7.467808723449707 | 35 | 35 |
|
||||||
|
| ./benchmark/c880.bench | 100.000 | 50.42959809303284 | 22 | 22 |
|
||||||
|
| ./benchmark/c499.bench | 100.000 | 65.37915563583374 | 49 | 49 |
|
||||||
|
| ./benchmark/c1355.bench | 100.000 | 363.1095223426819 | 82 | 82 |
|
||||||
|
| ./benchmark/b17.bench | ERROR | 2000.0039329528809 | ERROR | ERROR |
|
||||||
|
| ./benchmark/c7552.bench | 25.531 | 2000.0044975280762 | 1 | 1 |
|
||||||
|
| ./benchmark/b20.bench | ERROR | 2000.0045347213745 | ERROR | ERROR |
|
||||||
|
| ./benchmark/b11.bench | 98.951 | 2000.0055797100067 | 47 | 47 |
|
||||||
|
| ./benchmark/c3540.bench | 93.543 | 2000.006273508072 | 63 | 63 |
|
||||||
|
| ./benchmark/c1908.bench | 95.893 | 2000.0061783790588 | 39 | 39 |
|
||||||
|
| ./benchmark/b22.bench | ERROR | 2000.0057337284088 | ERROR | ERROR |
|
||||||
|
| ./benchmark/c2670.bench | 82.328 | 2000.0055947303772 | 31 | 31 |
|
||||||
|
| ./benchmark/b21.bench | ERROR | 2000.0054640769958 | ERROR | ERROR |
|
||||||
|
| ./benchmark/c6288.bench | 92.116 | 2000.0076813697815 | 5 | 5 |
|
||||||
|
| ./benchmark/c5315.bench | 33.139 | 2000.0081040859222 | 2 | 2 |
|
||||||
|
| ./benchmark/b04.bench | 99.744 | 2000.0090584754944 | 45 | 45 |
|
||||||
|
| ./benchmark/b12.bench | 91.771 | 2000.0079457759857 | 81 | 81 |
|
||||||
|
| ./benchmark/b07.bench | 98.568 | 2000.00936460495 | 29 | 29 |
|
||||||
|
| ./benchmark/c432.bench | 99.235 | 2000.0103182792664 | 19 | 19 |
|
||||||
|
| ./benchmark/b13.bench | 98.602 | 2000.009345293045 | 32 | 32 |
|
||||||
|
---------------------------------------------------------------------------------------------------------------
|
Loading…
x
Reference in New Issue
Block a user