vortex/sim/simx/processor.cpp
tinebp 22398c991d
Some checks are pending
CI / setup (push) Waiting to run
CI / build (32) (push) Blocked by required conditions
CI / build (64) (push) Blocked by required conditions
CI / tests (cache, 32) (push) Blocked by required conditions
CI / tests (cache, 64) (push) Blocked by required conditions
CI / tests (config1, 32) (push) Blocked by required conditions
CI / tests (config1, 64) (push) Blocked by required conditions
CI / tests (config2, 32) (push) Blocked by required conditions
CI / tests (config2, 64) (push) Blocked by required conditions
CI / tests (debug, 32) (push) Blocked by required conditions
CI / tests (debug, 64) (push) Blocked by required conditions
CI / tests (opencl, 32) (push) Blocked by required conditions
CI / tests (opencl, 64) (push) Blocked by required conditions
CI / tests (regression, 32) (push) Blocked by required conditions
CI / tests (regression, 64) (push) Blocked by required conditions
CI / tests (scope, 32) (push) Blocked by required conditions
CI / tests (scope, 64) (push) Blocked by required conditions
CI / tests (stress, 32) (push) Blocked by required conditions
CI / tests (stress, 64) (push) Blocked by required conditions
CI / tests (synthesis, 32) (push) Blocked by required conditions
CI / tests (synthesis, 64) (push) Blocked by required conditions
CI / tests (vector, 32) (push) Blocked by required conditions
CI / tests (vector, 64) (push) Blocked by required conditions
CI / tests (vm, 32) (push) Blocked by required conditions
CI / tests (vm, 64) (push) Blocked by required conditions
CI / complete (push) Blocked by required conditions
ramulator memory addressing bug fix + platform memory refactoring
2025-01-26 06:28:51 -08:00

216 lines
5.6 KiB
C++

// Copyright © 2019-2023
//
// 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 "processor.h"
#include "processor_impl.h"
using namespace vortex;
ProcessorImpl::ProcessorImpl(const Arch& arch)
: arch_(arch)
, clusters_(arch.num_clusters())
{
SimPlatform::instance().initialize();
assert(PLATFORM_MEMORY_DATA_SIZE == MEM_BLOCK_SIZE);
// create memory simulator
memsim_ = MemSim::Create("dram", MemSim::Config{
PLATFORM_MEMORY_NUM_BANKS,
L3_MEM_PORTS,
MEM_BLOCK_SIZE,
MEM_CLOCK_RATIO
});
// create clusters
for (uint32_t i = 0; i < arch.num_clusters(); ++i) {
clusters_.at(i) = Cluster::Create(i, this, arch, dcrs_);
}
// create L3 cache
l3cache_ = CacheSim::Create("l3cache", CacheSim::Config{
!L3_ENABLED,
log2ceil(L3_CACHE_SIZE), // C
log2ceil(MEM_BLOCK_SIZE), // L
log2ceil(L2_LINE_SIZE), // W
log2ceil(L3_NUM_WAYS), // A
log2ceil(L3_NUM_BANKS), // B
XLEN, // address bits
1, // number of ports
L3_NUM_REQS, // request size
L3_MEM_PORTS, // memory ports
L3_WRITEBACK, // write-back
false, // write response
L3_MSHR_SIZE, // mshr size
2, // pipeline latency
}
);
// connect L3 core interfaces
for (uint32_t i = 0; i < arch.num_clusters(); ++i) {
for (uint32_t j = 0; j < L2_MEM_PORTS; ++j) {
clusters_.at(i)->mem_req_ports.at(j).bind(&l3cache_->CoreReqPorts.at(i * L2_MEM_PORTS + j));
l3cache_->CoreRspPorts.at(i * L2_MEM_PORTS + j).bind(&clusters_.at(i)->mem_rsp_ports.at(j));
}
}
// connect L3 memory interfaces
for (uint32_t i = 0; i < L3_MEM_PORTS; ++i) {
l3cache_->MemReqPorts.at(i).bind(&memsim_->MemReqPorts.at(i));
memsim_->MemRspPorts.at(i).bind(&l3cache_->MemRspPorts.at(i));
}
// set up memory profiling
for (uint32_t i = 0; i < L3_MEM_PORTS; ++i) {
memsim_->MemReqPorts.at(i).tx_callback([&](const MemReq& req, uint64_t cycle){
__unused (cycle);
perf_mem_reads_ += !req.write;
perf_mem_writes_ += req.write;
perf_mem_pending_reads_ += !req.write;
});
memsim_->MemRspPorts.at(i).tx_callback([&](const MemRsp&, uint64_t cycle){
__unused (cycle);
--perf_mem_pending_reads_;
});
}
#ifndef NDEBUG
// dump device configuration
std::cout << "CONFIGS:"
<< " num_threads=" << arch.num_threads()
<< ", num_warps=" << arch.num_warps()
<< ", num_cores=" << arch.num_cores()
<< ", num_clusters=" << arch.num_clusters()
<< ", socket_size=" << arch.socket_size()
<< ", local_mem_base=0x" << std::hex << arch.local_mem_base() << std::dec
<< ", num_barriers=" << arch.num_barriers()
<< std::endl;
#endif
// reset the device
this->reset();
}
ProcessorImpl::~ProcessorImpl() {
SimPlatform::instance().finalize();
}
void ProcessorImpl::attach_ram(RAM* ram) {
for (auto cluster : clusters_) {
cluster->attach_ram(ram);
}
}
#ifdef VM_ENABLE
void ProcessorImpl::set_satp(uint64_t satp) {
for (auto cluster : clusters_) {
cluster->set_satp(satp);
}
}
#endif
int ProcessorImpl::run() {
SimPlatform::instance().reset();
this->reset();
bool done;
int exitcode = 0;
do {
SimPlatform::instance().tick();
done = true;
for (auto cluster : clusters_) {
if (cluster->running()) {
done = false;
continue;
}
#ifdef EXT_V_ENABLE
exitcode |= cluster->get_exitcode();
#endif
}
perf_mem_latency_ += perf_mem_pending_reads_;
} while (!done);
return exitcode;
}
void ProcessorImpl::reset() {
perf_mem_reads_ = 0;
perf_mem_writes_ = 0;
perf_mem_latency_ = 0;
perf_mem_pending_reads_ = 0;
}
void ProcessorImpl::dcr_write(uint32_t addr, uint32_t value) {
dcrs_.write(addr, value);
}
ProcessorImpl::PerfStats ProcessorImpl::perf_stats() const {
ProcessorImpl::PerfStats perf;
perf.mem_reads = perf_mem_reads_;
perf.mem_writes = perf_mem_writes_;
perf.mem_latency = perf_mem_latency_;
perf.l3cache = l3cache_->perf_stats();
perf.memsim = memsim_->perf_stats();
return perf;
}
///////////////////////////////////////////////////////////////////////////////
Processor::Processor(const Arch& arch)
: impl_(new ProcessorImpl(arch))
{
#ifdef VM_ENABLE
satp_ = NULL;
#endif
}
Processor::~Processor() {
delete impl_;
#ifdef VM_ENABLE
if (satp_ != NULL)
delete satp_;
#endif
}
void Processor::attach_ram(RAM* mem) {
impl_->attach_ram(mem);
}
int Processor::run() {
return impl_->run();
}
void Processor::dcr_write(uint32_t addr, uint32_t value) {
return impl_->dcr_write(addr, value);
}
#ifdef VM_ENABLE
int16_t Processor::set_satp_by_addr(uint64_t base_addr) {
uint16_t asid = 0;
satp_ = new SATP_t (base_addr,asid);
if (satp_ == NULL)
return 1;
uint64_t satp = satp_->get_satp();
impl_->set_satp(satp);
return 0;
}
bool Processor::is_satp_unset() {
return (satp_== NULL);
}
uint8_t Processor::get_satp_mode() {
assert (satp_!=NULL);
return satp_->get_mode();
}
uint64_t Processor::get_base_ppn() {
assert (satp_!=NULL);
return satp_->get_base_ppn();
}
#endif