// Copyright 2025 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.

#include "tests/systemc/instruction_trace.h"
#include <cassert>
#include <cstdio>

constexpr uint32_t kEcallInst = 0x00000073;

void InstructionTrace::TraceInstruction(
  const std::vector<bool>& fires,
  const std::vector<uint32_t>& addrs,
  const std::vector<uint32_t>& insts,
  const std::vector<bool>& scalarWriteAddrValids,
  const std::vector<uint32_t>& scalarWriteAddrAddrs,
  const std::vector<bool>& floatWriteAddrValids,
  const std::vector<uint32_t>& floatWriteAddrAddrs,
  const std::vector<bool>& writeDataValids,
  const std::vector<uint32_t>& writeDataAddrs,
  const std::vector<uint32_t>& writeDataDatas,
  const std::vector<int>& executeRegBases
) {
  assert(fires.size() == addrs.size());
  assert(fires.size() == insts.size());
  assert(fires.size() == scalarWriteAddrValids.size());
  assert(scalarWriteAddrValids.size() == scalarWriteAddrAddrs.size());
  assert(floatWriteAddrValids.size() == floatWriteAddrAddrs.size());
  assert(writeDataValids.size() == writeDataAddrs.size());
  assert(writeDataValids.size() == writeDataDatas.size());
  assert(writeDataValids.size() == executeRegBases.size());

  // Push data about the instructions that were dispatched this cycle into
  // the retirement buffer. Newly queued instructions are marked as incomplete.
  for (size_t i = 0; i < floatWriteAddrValids.size(); ++i) {
    bool fire = fires[i];
    bool valid = floatWriteAddrValids[i];
    uint32_t inst = insts[i];
    uint32_t pc = addrs[i];
    int reg = floatWriteAddrAddrs[i] + kFloatBaseReg;
    if (fire && valid) {
      Instruction in(pc, inst, reg);
      retirement_buffer_.push_back(in);
    }
  }
  for (size_t i = 0; i < scalarWriteAddrValids.size(); ++i) {
    bool fire = fires[i];
    bool valid = scalarWriteAddrValids[i];
    uint32_t inst = insts[i];
    uint32_t pc = addrs[i];
    int reg = scalarWriteAddrAddrs[i] + kScalarBaseReg;
    if (fire && valid && (reg != 0)) {
      Instruction in(pc, inst, reg);
      retirement_buffer_.push_back(in);
    }
    if (fire && (inst == kEcallInst)) {
      Instruction in(pc, inst, kEcallBaseReg);
      retirement_buffer_.push_back(in);
    }
  }

  // Iterate over the write ports, and find the first incomplete instruction
  // that matches the write. Mark that instruction as completed, and move
  // to the next write port.
  for (size_t i = 0; i < writeDataValids.size(); ++i) {
    bool valid = writeDataValids[i];
    uint32_t addr = writeDataAddrs[i] + executeRegBases[i];
    uint32_t data = writeDataDatas[i];
    for (auto& in : retirement_buffer_) {
      if (in.completed) continue;
      if (valid && (addr == in.reg)) {
        in.data.resize(4);
        in.data[0] = (data >> 24) & 0xff;
        in.data[1] = (data >> 16) & 0xff;
        in.data[2] = (data >> 8) & 0xff;
        in.data[3] = data & 0xff;
        in.completed = true;
        break;
      }
      if (in.inst == kEcallInst) {
        in.completed = true;
        break;
      }
    }
  }

  // Iterate over the retirement buffer, moving completed instructions
  // from the front into the committed_insts_ buffer.
  // When we see an incomplete instruction, stop.
  while (!retirement_buffer_.empty()) {
    auto in = retirement_buffer_.front();
    if (!in.completed) {
      break;
    } else {
      committed_insts_.push_back(in);
      retirement_buffer_.pop_front();
    }
  }
}

void InstructionTrace::TraceInstructionRaw(uint32_t pc, uint32_t inst,
                                           uint32_t reg,
                                           const std::vector<uint8_t>& data) {
  Instruction in(pc, inst, reg);
  in.data = data;
  committed_insts_.push_back(in);
}

void InstructionTrace::PrintTrace() const {
  for (auto& inst : committed_insts_) {
    printf("0x%08x,0x%08x,0x%02x,0x", inst.pc, inst.inst, inst.reg);
    for (auto d : inst.data) {
      printf("%02x", d);
    }
    printf("\n");
  }
}
