tsim_device.cc 4.27 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

20 21
#include <chrono>
#include <thread>
22 23 24
#include <vta/dpi/tsim.h>

#if VM_TRACE
25 26 27
#ifdef VM_TRACE_FST
#include <verilated_fst_c.h>
#else
28 29
#include <verilated_vcd_c.h>
#endif
30
#endif
31 32 33 34 35 36 37

#if VM_TRACE
#define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
#endif

static VTAContextHandle _ctx = nullptr;
38
static VTASimDPIFunc _sim_dpi = nullptr;
39
static VTAHostDPIFunc _host_dpi = nullptr;
40 41 42 43 44 45 46
static VTAMemDPIFunc _mem_dpi = nullptr;

void VTASimDPI(dpi8_t* wait,
               dpi8_t* exit) {
  assert(_sim_dpi != nullptr);
  (*_sim_dpi)(_ctx, wait, exit);
}
47

48
void VTAHostDPI(dpi8_t* req_valid,
49 50 51 52 53 54 55
                dpi8_t* req_opcode,
                dpi8_t* req_addr,
                dpi32_t* req_value,
                dpi8_t req_deq,
                dpi8_t resp_valid,
                dpi32_t resp_value) {
  assert(_host_dpi != nullptr);
56
  (*_host_dpi)(_ctx, req_valid, req_opcode,
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
               req_addr, req_value, req_deq,
               resp_valid, resp_value);
}

void VTAMemDPI(dpi8_t req_valid,
               dpi8_t req_opcode,
               dpi8_t req_len,
               dpi64_t req_addr,
               dpi8_t wr_valid,
               dpi64_t wr_value,
               dpi8_t* rd_valid,
               dpi64_t* rd_value,
               dpi8_t rd_ready) {
  assert(_mem_dpi != nullptr);
  (*_mem_dpi)(_ctx, req_valid, req_opcode, req_len,
              req_addr, wr_valid, wr_value,
              rd_valid, rd_value, rd_ready);

}

void VTADPIInit(VTAContextHandle handle,
78
                VTASimDPIFunc sim_dpi,
79 80 81
                VTAHostDPIFunc host_dpi,
                VTAMemDPIFunc mem_dpi) {
  _ctx = handle;
82
  _sim_dpi = sim_dpi;
83 84 85 86
  _host_dpi = host_dpi;
  _mem_dpi = mem_dpi;
}

87 88 89 90 91 92 93

// Override Verilator finish definition
// VL_USER_FINISH needs to be defined when compiling Verilator code
void vl_finish(const char* filename, int linenum, const char* hier) {
  Verilated::gotFinish(true);
}

94
int VTADPISim() {
95
  uint64_t trace_count = 0;
96 97
  Verilated::flushCall();
  Verilated::gotFinish(false);
98 99 100 101 102 103 104 105 106

#if VM_TRACE
  uint64_t start = 0;
#endif

  VL_TSIM_NAME* top = new VL_TSIM_NAME;

#if VM_TRACE
  Verilated::traceEverOn(true);
107 108 109
#ifdef VM_TRACE_FST
  VerilatedFstC* tfp = new VerilatedFstC;
#else
110
  VerilatedVcdC* tfp = new VerilatedVcdC;
111
#endif // VM_TRACE_FST
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
  top->trace(tfp, 99);
  tfp->open(STRINGIZE_VALUE_OF(TSIM_TRACE_FILE));
#endif

  // reset
  for (int i = 0; i < 10; i++) {
    top->reset = 1;
    top->clock = 0;
    top->eval();
#if VM_TRACE
    if (trace_count >= start)
      tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
    top->clock = 1;
    top->eval();
#if VM_TRACE
    if (trace_count >= start)
      tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
#endif
    trace_count++;
  }
  top->reset = 0;

  // start simulation
136 137
  while (!Verilated::gotFinish()) {
    top->sim_clock = 0;
138 139 140 141 142 143
    top->clock = 0;
    top->eval();
#if VM_TRACE
    if (trace_count >= start)
      tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
144
    top->sim_clock = 1;
145 146 147 148 149 150 151
    top->clock = 1;
    top->eval();
#if VM_TRACE
    if (trace_count >= start)
      tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
#endif
    trace_count++;
152
    if ((trace_count % 1000000) == 1)
153
      fprintf(stderr, "[traced %luM cycles]\n", trace_count / 1000000);
154 155 156 157 158 159 160 161
    while (top->sim_wait) {
      top->clock = 0;
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
      top->sim_clock = 0;
      top->eval();
      top->sim_clock = 1;
      top->eval();
    }
162 163 164 165 166 167 168 169 170 171
  }

#if VM_TRACE
  tfp->close();
#endif

  delete top;

  return 0;
}