| /* |
| * 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. |
| */ |
| |
| #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; |
| static VTAMemDPIFunc _mem_dpi = nullptr; |
| static VTAHostDPIFunc _host_dpi = nullptr; |
| |
| void VTAHostDPI(dpi8_t* exit, |
| dpi8_t* req_valid, |
| 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); |
| (*_host_dpi)(_ctx, exit, req_valid, req_opcode, |
| 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, |
| VTAHostDPIFunc host_dpi, |
| VTAMemDPIFunc mem_dpi) { |
| _ctx = handle; |
| _host_dpi = host_dpi; |
| _mem_dpi = mem_dpi; |
| } |
| |
| |
| // 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); |
| } |
| |
| int VTADPISim(uint64_t max_cycles) { |
| uint64_t trace_count = 0; |
| Verilated::flushCall(); |
| Verilated::gotFinish(false); |
| |
| #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 |
| while (!Verilated::gotFinish() && trace_count < max_cycles) { |
| 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++; |
| } |
| |
| #if VM_TRACE |
| tfp->close(); |
| #endif |
| |
| delete top; |
| |
| return 0; |
| } |