// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef TESTS_VERILATOR_SIM_SYSC_TB_H_
#define TESTS_VERILATOR_SIM_SYSC_TB_H_

// A SystemC baseclass for constrained random testing of Verilated RTL.
#include <systemc.h>

#include <iostream>
#include <string>

#include "tests/verilator_sim/fifo.h"
// sc_core needs to be included before verilator header
using namespace sc_core;      // NOLINT(build/namespaces)
#include "verilated_vcd_c.h"  // NOLINT(build/include_subdir): From verilator.

using sc_dt::sc_bv;

const char *vcd_path_ = "/tmp";

#define BIND(a, b) a.b(b)
#define BIND2(a, b, c) \
  BIND(a, c);          \
  BIND(b, c)

template <typename T>
struct sc_signal_vrb {
  sc_signal<bool> valid;
  sc_signal<bool> ready;
  sc_signal<T> bits;
};

template <typename T>
struct sc_in_vrb {
  sc_in<bool> valid;
  sc_out<bool> ready;
  sc_in<T> bits;

  void bind(sc_signal<bool> &v, sc_signal<bool> &r, sc_signal<T> &b) {
    valid.bind(v);
    ready.bind(r);
    bits.bind(b);
  }

  void bind(sc_signal_vrb<T> &vrb) {
    valid.bind(vrb.valid);
    ready.bind(vrb.ready);
    bits.bind(vrb.bits);
  }

  void operator()(sc_signal<bool> &v, sc_signal<bool> &r, sc_signal<T> &b) {
    bind(v, r, b);
  }

  void operator()(sc_signal_vrb<T> &vrb) { bind(vrb); }
};

template <typename T>
struct sc_out_vrb {
  sc_out<bool> valid;
  sc_in<bool> ready;
  sc_out<T> bits;

  void bind(sc_signal<bool> &v, sc_signal<bool> &r, sc_signal<T> &b) {
    valid.bind(v);
    ready.bind(r);
    bits.bind(b);
  }

  void bind(sc_signal_vrb<T> &vrb) {
    valid.bind(vrb.valid);
    ready.bind(vrb.ready);
    bits.bind(vrb.bits);
  }

  void operator()(sc_signal<bool> &v, sc_signal<bool> &r, sc_signal<T> &b) {
    bind(v, r, b);
  }

  void operator()(sc_signal_vrb<T> &vrb) { bind(vrb); }
};

// eg. struct message : base {...};
struct base {
  inline bool operator==(const base &rhs) const { return false; }

  inline friend std::ostream &operator<<(std::ostream &os, base const &v) {
    return os;
  }
};

// Base class for testbench {posedge & negedge}.
struct Sysc_tb : public sc_module {
  sc_clock clock;
  sc_signal<bool> reset;
  sc_signal<bool> resetn;

  SC_HAS_PROCESS(Sysc_tb);

  Sysc_tb(sc_module_name n, int loops, bool random = true)
      : sc_module(n),
        clock("clock", 1, SC_NS),
        reset("reset"),
        resetn("resetn"),
        random_(random),
        loops_(loops) {
    loop_ = 0;
    error_ = false;

    SC_METHOD(tb_posedge);
    sensitive << clock_.pos();

    SC_METHOD(tb_negedge);
    sensitive << clock_.neg();

    SC_METHOD(tb_stop);
    sensitive << clock_.neg();

    clock_(clock);

    // Verilated::commandArgs(argc, argv);
    tf_ = new VerilatedVcdC;
  }

  ~Sysc_tb() {
    if (error_) {
      exit(23);
    }
  }

  void start() {
    init();

    reset = 1;
    resetn = 0;
    sc_start(4.75, SC_NS);  // falling edge of clock
    reset = 0;
    resetn = 1;

    sc_start();

    if (tf_) {
      tf_->dump(sim_time_++);  // last falling edge
      tf_->close();
      delete tf_;
      tf_ = nullptr;
    }
  }

  template <typename T>
  void trace(T &design, const char *name = "") {
    if (!strlen(name)) {
      name = design.name();
    }
    std::string path = std::string(vcd_path_) + "/" + name;
    design.trace(tf_, 99);
    path += ".vcd";
    Verilated::traceEverOn(true);
    tf_->open(path.c_str());
    printf("\nInfo: default timescale unit used for tracing: 1 ps (%s)\n",
           path.c_str());
  }

  static char *get_name(char *s) {
    const int len = strlen(s);
    char *p = s;
    for (int i = 0; i < len; ++i) {
      if (s[i] == '/') {
        p = s + i + 1;
      }
    }
    return p;
  }

 protected:
  virtual void init() {}
  virtual void posedge() {}
  virtual void negedge() {}

  bool check(bool v, const char *s = "") {
    const char *KRED = "\x1B[31m";
    const char *KRST = "\033[0m";
    if (!v) {
      sc_stop();
      printf("%s", KRED);
      if (strlen(s)) {
        printf("***ERROR[%s]::VERIFY \"%s\"\n", this->name(), s);
      } else {
        printf("***ERROR[%s]::VERIFY\n", this->name());
      }
      printf("%s", KRST);
      error_ = true;
    }
    return v;
  }

  bool rand_bool() {
    // Do not allow any 'io_in_valid' controls to be set during reset.
    return !reset &&
           (!random_ || (rand() & 1));  // NOLINT(runtime/threadsafe_fn)
  }

  int rand_int(int min = 0, int max = (1 << 31)) {
    return (rand() % (max - min + 1)) + min;  // NOLINT(runtime/threadsafe_fn)
  }

  uint32_t rand_uint32(uint32_t min = 0, uint32_t max = 0xffffffffu) {
    uint32_t r = (rand() & 0xffff) |  // NOLINT(runtime/threadsafe_fn)
                 (rand() << 16);      // NOLINT(runtime/threadsafe_fn)
    if (min == 0 && max == 0xffffffff) return r;
    return (r % (max - min + 1)) + min;
  }

  uint64_t rand_uint64(uint64_t min = 0, uint64_t max = 0xffffffffffffffffull) {
    uint64_t r = rand_uint32() | (uint64_t(rand_uint32()) << 32);
    if (min == 0 && max == 0xffffffffffffffffull) return r;
    return (r % (max - min + 1)) + min;
  }

  uint32_t cycle() {
    return sim_time_ / 2;  // posedge + negedge
  }

 private:
  const bool random_;
  const int loops_;
  int loop_;
  bool error_;

  sc_in<bool> clock_;

  uint32_t sim_time_ = 0;
  VerilatedVcdC *tf_ = nullptr;

  void tb_posedge() {
    if (tf_) tf_->dump(sim_time_++);
    if (reset) return;
    posedge();
  }

  void tb_negedge() {
    if (tf_) tf_->dump(sim_time_++);
    if (reset) return;
    negedge();
  }

  void tb_stop() {
    // LessThanEqual for one more edge (end - start + 1).
    if (loop_ <= loops_) {
      loop_++;
    } else {
      printf("\nInfo: loop limit \"%d\" reached\n", loops_);
      sc_stop();
    }
  }
};

#endif  // TESTS_VERILATOR_SIM_SYSC_TB_H_
