mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-22 04:47:56 -04:00
173 lines
No EOL
5.3 KiB
C++
173 lines
No EOL
5.3 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 "socket.h"
|
|
#include "cluster.h"
|
|
|
|
using namespace vortex;
|
|
|
|
Socket::Socket(const SimContext& ctx,
|
|
uint32_t socket_id,
|
|
Cluster* cluster,
|
|
const Arch &arch,
|
|
const DCRS &dcrs)
|
|
: SimObject(ctx, StrFormat("socket%d", socket_id))
|
|
, mem_req_ports(L1_MEM_PORTS, this)
|
|
, mem_rsp_ports(L1_MEM_PORTS, this)
|
|
, socket_id_(socket_id)
|
|
, cluster_(cluster)
|
|
, cores_(arch.socket_size())
|
|
{
|
|
auto cores_per_socket = cores_.size();
|
|
|
|
char sname[100];
|
|
snprintf(sname, 100, "%s-icaches", this->name().c_str());
|
|
icaches_ = CacheCluster::Create(sname, cores_per_socket, NUM_ICACHES, CacheSim::Config{
|
|
!ICACHE_ENABLED,
|
|
log2ceil(ICACHE_SIZE), // C
|
|
log2ceil(L1_LINE_SIZE), // L
|
|
log2ceil(sizeof(uint32_t)), // W
|
|
log2ceil(ICACHE_NUM_WAYS),// A
|
|
1, // B
|
|
XLEN, // address bits
|
|
1, // number of ports
|
|
1, // number of inputs
|
|
ICACHE_MEM_PORTS, // memory ports
|
|
false, // write-back
|
|
false, // write response
|
|
(uint8_t)arch.num_warps(), // mshr size
|
|
2, // pipeline latency
|
|
});
|
|
|
|
snprintf(sname, 100, "%s-dcaches", this->name().c_str());
|
|
dcaches_ = CacheCluster::Create(sname, cores_per_socket, NUM_DCACHES, CacheSim::Config{
|
|
!DCACHE_ENABLED,
|
|
log2ceil(DCACHE_SIZE), // C
|
|
log2ceil(L1_LINE_SIZE), // L
|
|
log2ceil(DCACHE_WORD_SIZE), // W
|
|
log2ceil(DCACHE_NUM_WAYS),// A
|
|
log2ceil(DCACHE_NUM_BANKS), // B
|
|
XLEN, // address bits
|
|
1, // number of ports
|
|
DCACHE_NUM_REQS, // number of inputs
|
|
L1_MEM_PORTS, // memory ports
|
|
DCACHE_WRITEBACK, // write-back
|
|
false, // write response
|
|
DCACHE_MSHR_SIZE, // mshr size
|
|
2, // pipeline latency
|
|
});
|
|
|
|
// find overlap
|
|
uint32_t overlap = MIN(ICACHE_MEM_PORTS, L1_MEM_PORTS);
|
|
|
|
// connect l1 caches to outgoing memory interfaces
|
|
for (uint32_t i = 0; i < L1_MEM_PORTS; ++i) {
|
|
snprintf(sname, 100, "%s-l1_arb%d", this->name().c_str(), i);
|
|
auto l1_arb = MemArbiter::Create(sname, ArbiterType::RoundRobin, 2 * overlap, overlap);
|
|
|
|
if (i < overlap) {
|
|
icaches_->MemReqPorts.at(i).bind(&l1_arb->ReqIn.at(i));
|
|
l1_arb->RspIn.at(i).bind(&icaches_->MemRspPorts.at(i));
|
|
|
|
dcaches_->MemReqPorts.at(i).bind(&l1_arb->ReqIn.at(overlap + i));
|
|
l1_arb->RspIn.at(overlap + i).bind(&dcaches_->MemRspPorts.at(i));
|
|
|
|
l1_arb->ReqOut.at(i).bind(&this->mem_req_ports.at(i));
|
|
this->mem_rsp_ports.at(i).bind(&l1_arb->RspOut.at(i));
|
|
} else {
|
|
if (L1_MEM_PORTS > ICACHE_MEM_PORTS) {
|
|
// if more dcache ports
|
|
dcaches_->MemReqPorts.at(i).bind(&this->mem_req_ports.at(i));
|
|
this->mem_rsp_ports.at(i).bind(&dcaches_->MemRspPorts.at(i));
|
|
} else {
|
|
// if more icache ports
|
|
icaches_->MemReqPorts.at(i).bind(&this->mem_req_ports.at(i));
|
|
this->mem_rsp_ports.at(i).bind(&icaches_->MemRspPorts.at(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
// create cores
|
|
for (uint32_t i = 0; i < cores_per_socket; ++i) {
|
|
uint32_t core_id = socket_id * cores_per_socket + i;
|
|
cores_.at(i) = Core::Create(core_id, this, arch, dcrs);
|
|
}
|
|
|
|
// connect cores to caches
|
|
for (uint32_t i = 0; i < cores_per_socket; ++i) {
|
|
cores_.at(i)->icache_req_ports.at(0).bind(&icaches_->CoreReqPorts.at(i).at(0));
|
|
icaches_->CoreRspPorts.at(i).at(0).bind(&cores_.at(i)->icache_rsp_ports.at(0));
|
|
|
|
for (uint32_t j = 0; j < DCACHE_NUM_REQS; ++j) {
|
|
cores_.at(i)->dcache_req_ports.at(j).bind(&dcaches_->CoreReqPorts.at(i).at(j));
|
|
dcaches_->CoreRspPorts.at(i).at(j).bind(&cores_.at(i)->dcache_rsp_ports.at(j));
|
|
}
|
|
}
|
|
}
|
|
|
|
Socket::~Socket() {
|
|
//--
|
|
}
|
|
|
|
void Socket::reset() {
|
|
//--
|
|
}
|
|
|
|
void Socket::tick() {
|
|
//--
|
|
}
|
|
|
|
void Socket::attach_ram(RAM* ram) {
|
|
for (auto core : cores_) {
|
|
core->attach_ram(ram);
|
|
}
|
|
}
|
|
|
|
#ifdef VM_ENABLE
|
|
void Socket::set_satp(uint64_t satp) {
|
|
for (auto core : cores_) {
|
|
core->set_satp(satp);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool Socket::running() const {
|
|
for (auto& core : cores_) {
|
|
if (core->running())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Socket::get_exitcode() const {
|
|
int exitcode = 0;
|
|
for (auto& core : cores_) {
|
|
exitcode |= core->get_exitcode();
|
|
}
|
|
return exitcode;
|
|
}
|
|
|
|
void Socket::barrier(uint32_t bar_id, uint32_t count, uint32_t core_id) {
|
|
cluster_->barrier(bar_id, count, socket_id_ * cores_.size() + core_id);
|
|
}
|
|
|
|
void Socket::resume(uint32_t core_index) {
|
|
cores_.at(core_index)->resume(-1);
|
|
}
|
|
|
|
Socket::PerfStats Socket::perf_stats() const {
|
|
PerfStats perf_stats;
|
|
perf_stats.icache = icaches_->perf_stats();
|
|
perf_stats.dcache = dcaches_->perf_stats();
|
|
return perf_stats;
|
|
} |