#include "Vwq_lanes64.h"
#include "verilated.h"
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <vector>
static Vwq_lanes64* top = nullptr;
static uint64_t cycles = 0;
static void tick() {
top->clk = 0;
top->eval();
top->clk = 1;
top->eval();
cycles++;
}
static void need(void* buf, size_t n) {
if (fread(buf, 1, n, stdin) != n) {
std::exit(3);
}
}
template <class T> static T get() {
T v;
need(&v, sizeof v);
return v;
}
static void put(const void* buf, size_t n) {
if (fwrite(buf, 1, n, stdout) != n) {
std::exit(4);
}
}
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
top = new Vwq_lanes64;
top->clk = 0;
top->host_we = 0;
top->start = 0;
top->report_reset = 0;
top->eval();
for (;;) {
uint8_t op;
if (fread(&op, 1, 1, stdin) != 1 || op == 0) {
break;
}
if (op == 1) {
uint64_t count = get<uint64_t>();
std::vector<uint32_t> out;
out.reserve(count * 4);
for (uint64_t k = 0; k < count; k++) {
int32_t a = get<int32_t>();
int32_t b = get<int32_t>();
top->probe_a = (uint32_t)a;
top->probe_b = (uint32_t)b;
top->eval();
uint64_t prod = top->probe_prod;
uint64_t fx = top->probe_fx;
out.push_back((uint32_t)(prod >> 32));
out.push_back((uint32_t)prod);
out.push_back((uint32_t)(fx >> 32));
out.push_back((uint32_t)fx);
}
put(out.data(), out.size() * 4);
} else if (op == 2) {
uint32_t n = get<uint32_t>();
uint32_t gates = get<uint32_t>();
if (n < 1 || n > WQ_AW) {
std::exit(5);
}
uint64_t len = 1ull << n;
cycles = 0;
for (uint64_t x = 0; x < len; x++) {
uint32_t re = (uint32_t)get<int32_t>();
uint32_t im = (uint32_t)get<int32_t>();
top->host_addr = (uint32_t)x;
top->host_wdata = ((uint64_t)im << 32) | re;
top->host_we = 1;
tick();
}
top->host_we = 0;
top->report_reset = 1;
tick();
top->report_reset = 0;
for (uint32_t g = 0; g < gates; g++) {
uint32_t w[11];
need(w, sizeof w);
top->m0 = w[0];
top->m1 = w[1];
top->m2 = w[2];
top->m3 = w[3];
top->m4 = w[4];
top->m5 = w[5];
top->m6 = w[6];
top->m7 = w[7];
top->tbit = w[8];
top->ctrl = w[9];
top->index = w[10];
top->pairs = (uint32_t)(len / 2);
top->start = 1;
tick();
top->start = 0;
while (top->busy) {
tick();
}
}
uint32_t report = top->report;
put(&report, 4);
std::vector<int32_t> state;
state.reserve(len * 2);
for (uint64_t x = 0; x < len; x++) {
top->host_addr = (uint32_t)x;
top->eval();
uint64_t v = top->host_rdata;
state.push_back((int32_t)(uint32_t)v);
state.push_back((int32_t)(uint32_t)(v >> 32));
}
put(state.data(), state.size() * 4);
put(&cycles, 8);
} else {
std::exit(2);
}
fflush(stdout);
}
top->final();
delete top;
return 0;
}