tsim_device.cc 4.01 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 25 26 27 28 29 30 31 32 33
#include <vta/dpi/tsim.h>

#if VM_TRACE
#include <verilated_vcd_c.h>
#endif

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

static VTAContextHandle _ctx = nullptr;
34
static VTASimDPIFunc _sim_dpi = nullptr;
35
static VTAHostDPIFunc _host_dpi = nullptr;
36 37 38 39 40 41 42
static VTAMemDPIFunc _mem_dpi = nullptr;

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

44
void VTAHostDPI(dpi8_t* req_valid,
45 46 47 48 49 50 51
                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);
52
  (*_host_dpi)(_ctx, req_valid, req_opcode,
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
               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,
74
                VTASimDPIFunc sim_dpi,
75 76 77
                VTAHostDPIFunc host_dpi,
                VTAMemDPIFunc mem_dpi) {
  _ctx = handle;
78
  _sim_dpi = sim_dpi;
79 80 81 82
  _host_dpi = host_dpi;
  _mem_dpi = mem_dpi;
}

83 84 85 86 87 88 89

// 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);
}

90
int VTADPISim() {
91
  uint64_t trace_count = 0;
92 93
  Verilated::flushCall();
  Verilated::gotFinish(false);
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

#if VM_TRACE
  uint64_t start = 0;
#endif

  VL_TSIM_NAME* top = new VL_TSIM_NAME;

#if VM_TRACE
  Verilated::traceEverOn(true);
  VerilatedVcdC* tfp = new VerilatedVcdC;
  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
128 129
  while (!Verilated::gotFinish()) {
    top->sim_clock = 0;
130 131 132 133 134 135
    top->clock = 0;
    top->eval();
#if VM_TRACE
    if (trace_count >= start)
      tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
136
    top->sim_clock = 1;
137 138 139 140 141 142 143
    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++;
144 145 146 147 148 149 150 151
    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();
    }
152 153 154 155 156 157 158 159 160 161
  }

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

  delete top;

  return 0;
}