24 return std::make_unique<PerfTestPlugin>();
34 return std::string(
"perf_test");
39 return std::string(
"0.1");
50 description.
add(
"--perf_test",
"executes the plugin perf_test");
51 description.
add(
"--base_path",
"set base path of HAL install", {
""});
58 bool no_errors =
true;
61 std::cout <<
"comparing outputs..." << std::endl;
62 std::cout <<
"reference has " << reference_simulation->
size() <<
" and engine simulation " << engine_simulation->
size() <<
" nets" << std::endl;
78 auto signal_to_string = [](
auto v) -> std::string {
80 return std::to_string(v);
85 std::set<u32> reference_simulation_nets;
86 for (
auto it : *reference_simulation)
88 reference_simulation_nets.insert(it->id());
92 std::set<u32> engine_simulation_nets;
93 for (
auto it : *engine_simulation)
95 engine_simulation_nets.insert(it->id());
99 std::cout <<
"searching for mismatches..." << std::endl;
101 std::set<u32> unmatching_nets;
103 for (
auto it_ref : *reference_simulation)
109 std::cout <<
"error: net: " << it_ref->name().toStdString() <<
" (" << it_ref->id() <<
") in reference, but not in simulated output" << std::endl;
113 if (!it_ref->isEqual(*engine_simulation->
at(iwave_sim), tolerance))
116 unmatching_nets.insert(it_ref->id());
121 if (unmatching_nets.size() != 0)
124 std::cout <<
"error: found " << unmatching_nets.size() <<
" unmatching nets..." << std::endl;
127 std::cout <<
"printing mismatches (if any)..." << std::endl;
129 u64 earliest_mismatch = -1;
130 std::vector<u32> earliest_mismatch_nets;
131 auto update_mismatch = [&](
u64 time,
u32 net) {
132 if (time < earliest_mismatch)
134 earliest_mismatch = time;
135 earliest_mismatch_nets = {
net};
137 else if (time == earliest_mismatch)
139 earliest_mismatch_nets.push_back(
net);
143 for (
auto net_id : unmatching_nets)
145 std::vector<std::pair<u64, int>> events_a;
147 for (
auto it_sim : *reference_simulation)
149 if (it_sim->id() == net_id)
151 wave_data_a = it_sim;
156 std::vector<std::pair<u64, int>> events_b;
158 for (
auto it_sim : *engine_simulation)
160 if (it_sim->id() == net_id)
162 wave_data_b = it_sim;
167 u32 max_number_length = 0;
168 if (!events_a.empty() && !events_b.empty())
170 max_number_length = std::to_string(std::max(events_a.back().first, events_b.back().first)).size();
173 std::cout <<
"difference in net " << wave_data_a->
name().
toStdString() <<
" id=" << net_id <<
":" << std::endl;
174 std::cout <<
"reference:" << std::setfill(
' ') << std::setw(max_number_length + 5) <<
""
175 <<
"engine:" << std::endl;
177 for (
u32 i = 0, j = 0; i < events_a.size() || j < events_b.size();)
179 if (i < events_a.size() && j < events_b.size())
181 if (abs((
int)(events_a[i].first - events_b[j].first)) < tolerance)
183 if (events_a[i].second == events_b[j].second)
185 std::cout << signal_to_string(events_a[i].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_a[i].first <<
"ns";
187 std::cout << signal_to_string(events_b[j].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_b[j].first <<
"ns";
188 std::cout << std::endl;
194 update_mismatch(events_a[i].first, net_id);
195 std::cout << signal_to_string(events_a[i].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_a[i].first <<
"ns";
197 std::cout << signal_to_string(events_b[j].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_b[j].first <<
"ns";
198 std::cout <<
" <--" << std::endl;
205 if (events_a[i].first < events_b[j].first)
207 update_mismatch(events_a[i].first, net_id);
208 std::cout << signal_to_string(events_a[i].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_a[i].first <<
"ns";
210 std::cout << std::endl;
215 update_mismatch(events_b[j].first, net_id);
216 std::cout <<
" " << std::setfill(
' ') << std::setw(max_number_length) <<
""
219 std::cout << signal_to_string(events_b[j].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_b[j].first <<
"ns";
220 std::cout << std::endl;
225 else if (i < events_a.size())
227 update_mismatch(events_a[i].first, net_id);
228 std::cout << signal_to_string(events_a[i].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_a[i].first <<
"ns";
230 std::cout << std::endl;
235 update_mismatch(events_b[j].first, net_id);
236 std::cout <<
" " << std::setfill(
' ') << std::setw(max_number_length) <<
""
239 std::cout << signal_to_string(events_b[j].second) <<
" @ " << std::setfill(
' ') << std::setw(max_number_length) << events_b[j].first <<
"ns";
240 std::cout << std::endl;
244 std::cout << std::endl;
247 if (reference_simulation->
size() != engine_simulation->
size())
249 std::cout <<
"WARNING SIZE MISMATCH" << std::endl;
250 if (reference_simulation->
size() > engine_simulation->
size())
253 std::cout <<
"more nets are captured in the reference vcd file:" << std::endl;
254 std::vector<u32> mismatch;
255 std::set_difference(reference_simulation_nets.begin(), reference_simulation_nets.end(), engine_simulation_nets.begin(), engine_simulation_nets.end(), std::back_inserter(mismatch));
256 for (
auto x : mismatch)
259 std::cout <<
" " <<
x <<
" " << (iwave < 0 ?
"" : reference_simulation->
at(iwave)->name().toUtf8().data()) << std::endl;
264 std::cout <<
"more nets are captured in the engine_simulation output:" << std::endl;
265 std::vector<u32> mismatch;
266 std::set_difference(engine_simulation_nets.begin(), engine_simulation_nets.end(), reference_simulation_nets.begin(), reference_simulation_nets.end(), std::back_inserter(mismatch));
267 const char* artifical_added[] = {
"'0'",
"'1'",
nullptr};
268 for (
auto x : mismatch)
271 std::string waveName(iwave < 0 ? "" : engine_simulation->at(iwave)->
name().toUtf8().
data());
272 if (!waveName.empty())
274 bool take_it_easy =
false;
275 for (
int i = 0; artifical_added[i]; i++)
277 if (waveName == artifical_added[i])
286 std::cout <<
" " <<
x <<
" " << (iwave < 0 ?
"" : engine_simulation->
at(iwave)->name().toUtf8().data()) << std::endl;
290 if (unmatching_nets.empty())
292 std::cout <<
"everything that could be compared was correct, though!" << std::endl;
298 std::cout <<
"simulation correct!" << std::endl;
302 std::cout <<
"simulation incorrect, have fun debugging!" << std::endl;
310 std::string base_path;
321 log_error(
"perf_test",
"base_path parameter not set");
324 auto plugin = plugin_manager::get_plugin_instance<NetlistSimulatorControllerPlugin>(
"netlist_simulator_controller");
326 auto sim_ctrl_verilator = plugin->create_simulator_controller(
"tocipher_simulator");
327 auto verilator_engine = sim_ctrl_verilator->create_simulation_engine(
"verilator");
331 auto sim_ctrl_reference = plugin->create_simulator_controller(
"tocipher_reference");
334 std::string path_netlist = base_path +
"/bin/hal_plugins/test-files/toycipher/cipher_flat.vhd";
346 std::string path_vcd = base_path +
"/bin/hal_plugins/test-files/toycipher/dump.vcd";
349 log_error(
"perf_test",
"ref vcd not found");
354 sim_ctrl_reference->add_gates(nl->
get_gates());
355 sim_ctrl_reference->initialize();
356 sim_ctrl_reference->import_vcd(path_vcd, NetlistSimulatorController::FilterInputFlag::CompleteNetlist);
359 sim_ctrl_verilator->add_gates(nl->
get_gates());
361 sim_ctrl_verilator->initialize();
364 auto clk = *(nl->
get_nets([](
auto net) {
return net->get_name() ==
"CLK"; }).begin());
365 sim_ctrl_verilator->add_clock_period(clk, 10000);
367 std::set<const Net*> key_set, plaintext_set;
368 auto start = *(nl->
get_nets([](
auto net) {
return net->get_name() ==
"START"; }).begin());
370 for (
int i = 0; i < 16; i++)
372 std::string
name =
"KEY_" + std::to_string(i);
373 key_set.insert(*(nl->
get_nets([
name](
auto net) { return net->get_name() == name; }).begin()));
376 for (
int i = 0; i < 16; i++)
378 std::string
name =
"PLAINTEXT_" + std::to_string(i);
379 plaintext_set.insert(*(nl->
get_nets([
name](
auto net) { return net->get_name() == name; }).begin()));
382 int input_nets_amount = key_set.size() + plaintext_set.size();
387 if (start !=
nullptr)
396 sim_ctrl_verilator->set_input(GND, BooleanFunction::Value::ZERO);
402 sim_ctrl_verilator->set_input(VCC, BooleanFunction::Value::ONE);
409 for (
auto net : plaintext_set)
410 sim_ctrl_verilator->set_input(
net, BooleanFunction::Value::ZERO);
412 for (
auto net : key_set)
413 sim_ctrl_verilator->set_input(
net, BooleanFunction::Value::ZERO);
415 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ZERO);
416 sim_ctrl_verilator->simulate(10 * 1000);
418 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ONE);
419 sim_ctrl_verilator->simulate(10 * 1000);
421 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ZERO);
422 sim_ctrl_verilator->simulate(100 * 1000);
424 for (
auto net : plaintext_set)
425 sim_ctrl_verilator->set_input(
net, BooleanFunction::Value::ONE);
427 for (
auto net : key_set)
428 sim_ctrl_verilator->set_input(
net, BooleanFunction::Value::ONE);
430 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ZERO);
431 sim_ctrl_verilator->simulate(10 * 1000);
433 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ONE);
434 sim_ctrl_verilator->simulate(10 * 1000);
436 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ZERO);
437 sim_ctrl_verilator->simulate(100 * 1000);
439 for (
auto net : plaintext_set)
440 sim_ctrl_verilator->set_input(
net, BooleanFunction::Value::ZERO);
442 for (
auto net : key_set)
443 sim_ctrl_verilator->set_input(
net, BooleanFunction::Value::ZERO);
445 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ZERO);
447 sim_ctrl_verilator->simulate(10 * 1000);
448 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ONE);
450 sim_ctrl_verilator->simulate(10 * 1000);
451 sim_ctrl_verilator->set_input(start, BooleanFunction::Value::ZERO);
453 sim_ctrl_verilator->simulate(25 * 1000);
455 sim_ctrl_verilator->initialize();
456 sim_ctrl_verilator->run_simulation();
460 while (verilator_engine->get_state() == SimulationEngine::State::Running)
462 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
466 if (verilator_engine->get_state() == SimulationEngine::State::Failed)
474 sim_ctrl_verilator->get_results();
478 sim_ctrl_verilator->get_waveform_by_net(n);
479 sim_ctrl_reference->get_waveform_by_net(n);
487 bool equal = mParent->
cmp_sim_data(sim_ctrl_reference.get(), sim_ctrl_verilator.get());
std::vector< AbstractExtensionInterface * > m_extensions
ProgramOptions get_cli_options() const override
bool handle_cli_call(hal::Netlist *nl, hal::ProgramArguments &args) override
const std::vector< Gate * > & get_gates() const
const std::vector< Net * > & get_nets() const
const GateLibrary * get_gate_library() const
WaveDataList * get_waves() const
std::string get_version() const override
void initialize() override
std::string get_name() const override
bool cmp_sim_data(hal::NetlistSimulatorController *reference_simulation_ctrl, hal::NetlistSimulatorController *simulation_ctrl, int tolerance=200)
std::string get_parameter(const std::string &flag) const
bool is_option_set(const std::string &flag) const
bool add(const std::string &flag, const std::string &description, const std::initializer_list< std::string > ¶meters={})
std::vector< std::pair< u64, int > > get_events(u64 t0=0) const
int waveIndexByNetId(u32 id) const
#define log_error(channel,...)
bool file_exists(const std::string &filename)
std::unique_ptr< BasePluginInterface > create_plugin_instance()
This file contains various functions to create and load netlists.
const T & at(int i) const const
std::string toStdString() const const