blob: e89cca43c31c4129188241b383dcf6ae5cc43145 [file] [log] [blame]
/*
Copyright (c) 2020 University of Maryland
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met: redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer;
redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution;
neither the name of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "HSA_Interface.h"
void print_agent_dispatch_packet(hsa_agent_dispatch_packet_t* pkt)
{
printf("Packet \t\t%p\n",
(void *)pkt);
printf("Packet 16t\t\t%p\n",
(uint16_t *)pkt);
printf("Packet 32t\t\t%p\n",
(uint32_t *)pkt);
printf("Packet void**\t\t%p\n",
(void **)pkt);
printf("%p header: \t\t%hu\n",
(void *)(&(pkt->header )),pkt->header );
printf("%p type: \t\t%hu\n",
(void *)(&(pkt->type )),pkt->type );
printf("%p reserved0: \t\t%u\n",
(void *)(&(pkt->reserved0 )),pkt->reserved0 );
printf("%p return_address: \t\t%p\n",
(void *)(&(pkt->return_address )),pkt->return_address );
printf("%p arg[0]: \t\t%lu\n",
(void *)(&(pkt->arg[0] )),pkt->arg[0] );
printf("%p arg[1]: \t\t%lu\n",
(void *)(&(pkt->arg[1] )),pkt->arg[1] );
printf("%p arg[2]: \t\t%lu\n",
(void *)(&(pkt->arg[2] )),pkt->arg[0] );
printf("%p arg[3]: \t\t%lu\n",
(void *)(&(pkt->arg[3] )),pkt->arg[1] );
printf("%p reserved2: \t\t%lu\n",
(void *)(&(pkt->reserved2 )),pkt->reserved2 );
printf("%p completion_signal: \t\t%lu\n",
(void *)(&(pkt->completion_signal )),pkt->completion_signal.handle );
fflush(stdout);
}
void agent_disp_packet_store_release(uint16_t* packet, uint16_t header) {
__atomic_store_n(packet, header, __ATOMIC_RELEASE);
}
uint16_t header(hsa_packet_type_t type) {
uint16_t header = type << HSA_PACKET_HEADER_TYPE;
header |=
HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_SCACQUIRE_FENCE_SCOPE;
header |=
HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_SCRELEASE_FENCE_SCOPE;
return header;
}
hsa_status_t get_kernel_agent(hsa_agent_t agent, void* data) {
uint32_t features = 0;
hsa_agent_get_info(agent, HSA_AGENT_INFO_FEATURE, &features);
if (features & HSA_AGENT_FEATURE_KERNEL_DISPATCH) {
// Store kernel agent in the application-provided buffer and return
hsa_agent_t* ret = (hsa_agent_t*) data;
*ret = agent;
return HSA_STATUS_INFO_BREAK;
}
// Keep iterating
return HSA_STATUS_SUCCESS;
}
void signal_wait(hsa_signal_t signal)
{
while (hsa_signal_wait_relaxed(signal, HSA_SIGNAL_CONDITION_EQ, 0,
UINT64_MAX, HSA_WAIT_STATE_ACTIVE) != 0);
// while (hsa_signal_wait_scacquire(signal, HSA_SIGNAL_CONDITION_EQ, 0,
// UINT64_MAX, HSA_WAIT_STATE_ACTIVE) != 0);
}
void initialize_agent_dispatch_packet(
hsa_agent_dispatch_packet_t* packet,
size_t header_size
)
{
// Reserved fields, private and group memory,
// and completion signal are all set to 0.
memset(((uint8_t*) packet) + header_size, 0,
sizeof(hsa_agent_dispatch_packet_t) - header_size);
}
HSA_Interface::HSA_Interface(){
printf("INFO:: Setting up HSA Interface:\n");
CHECK(hipGetDeviceProperties(&props, 0/*deviceID*/));
printf ("info: running on device %s\n", props.name); fflush(stdout);
#ifdef __HIP_PLATFORM_HCC__
printf ("info: architecture on AMD GPU device is: %d\n",
props.gcnArch); fflush(stdout);
#endif
printf ("INFO:: hsa_iterate_agents\n"); fflush(stdout);
hsa_agent_t kernel_agent;
hsa_iterate_agents(get_kernel_agent, &kernel_agent);
printf ("INFO:: hsa_queue_create\n"); fflush(stdout);
hsa_queue_create(kernel_agent, 4, HSA_QUEUE_TYPE_SINGLE,
NULL, NULL, 0, 0, &queue);
printf ("INFO:: hsa_queue_add_write_index_relaxed\n"); fflush(stdout);
hsa_queue_add_write_index_relaxed(queue, 1);
packet_id = 0;
printf("INFO:: Creating Stream\n");fflush(stdout);
stream = 0;
hipStreamCreate(&stream);
}
void HSA_Interface::steal_kernel_signal(uint32_t kid)
{
hsa_agent_dispatch_packet_t * packet =
(hsa_agent_dispatch_packet_t*) queue->base_address + packet_id;
// Populate fields in kernel dispatch packet, except for the header,
// the setup, and the completion signal fields
initialize_agent_dispatch_packet(packet,sizeof(uint16_t));
uint64_t kernel_completion_signal_addr;
packet->type = AGENT_DISPATCH_PACKET_STEAL_KERNEL_SIGNAL;
packet->return_address = &kernel_completion_signal_addr;
packet->arg[0] = kid; //This field is for the kernel id.
//Create thief packet wait signal
hsa_signal_create(1, 0, NULL, &packet->completion_signal);
agent_disp_packet_store_release((uint16_t*) packet,
header(HSA_PACKET_TYPE_AGENT_DISPATCH));
print_agent_dispatch_packet(packet);
//Send thief packet
hsa_signal_store_screlease(queue->doorbell_signal, packet_id);
signal_wait(packet->completion_signal);
printf("INFO:: Done Waiting on Thief Signal\n");
hsa_signal_t * new_signal = new hsa_signal_t;
new_signal->handle = kernel_completion_signal_addr;
m_kernel_signals.push_back(new_signal);
packet_id++;
}
void HSA_Interface::wait_kernel(uint32_t kid)
{
signal_wait(*(m_kernel_signals[kid]));
}