// PSL thread loop static void *_psl_loop(void *ptr) { struct psl *psl = (struct psl *)ptr; struct cmd_event *event, *temp; int events, i, stopped, reset; uint8_t ack = PSLSE_DETACH; stopped = 1; pthread_mutex_lock(psl->lock); while (psl->state != PSLSE_DONE) { // idle_cycles continues to generate clock cycles for some // time after the AFU has gone idle. Eventually clocks will // not be presented to an idle AFU to keep simulation // waveforms from getting huge with no activity cycles. if (psl->state != PSLSE_IDLE) { psl->idle_cycles = PSL_IDLE_CYCLES; if (stopped) info_msg("Clocking %s", psl->name); fflush(stdout); stopped = 0; } if (psl->idle_cycles) { // Clock AFU psl_signal_afu_model(psl->afu_event); // Check for events from AFU events = psl_get_afu_events(psl->afu_event); // Error on socket if (events < 0) { warn_msg("Lost connection with AFU"); break; } // Handle events from AFU if (events > 0) _handle_afu(psl); // Drive events to AFU send_job(psl->job); send_mmio(psl->mmio); if (psl->mmio->list == NULL) psl->idle_cycles--; } else { if (!stopped) info_msg("Stopping clocks to %s", psl->name); stopped = 1; lock_delay(psl->lock); } // Skip client section if AFU descriptor hasn't been read yet if (psl->client == NULL) { lock_delay(psl->lock); continue; } // Check for event from application reset = 0; for (i = 0; i < psl->max_clients; i++) { if (psl->client[i] == NULL) continue; if ((psl->client[i]->state == CLIENT_NONE) && (psl->client[i]->idle_cycles == 0)) { put_bytes(psl->client[i]->fd, 1, &ack, psl->dbg_fp, psl->dbg_id, psl->client[i]->context); _free(psl, psl->client[i]); psl->client[i] = NULL; reset = 1; continue; } if (psl->state == PSLSE_RESET) continue; _handle_client(psl, psl->client[i]); if (psl->client[i]->idle_cycles) { psl->client[i]->idle_cycles--; } if (client_cmd(psl->cmd, psl->client[i])) { psl->client[i]->idle_cycles = PSL_IDLE_CYCLES; } } // Send reset to AFU if (reset == 1) { psl->cmd->buffer_read = NULL; event = psl->cmd->list; while (event != NULL) { if (reset) { warn_msg ("Client dropped context before AFU completed"); reset = 0; } warn_msg("Dumping command tag=0x%02x", event->tag); if (event->data) { free(event->data); } if (event->parity) { free(event->parity); } temp = event; event = event->_next; free(temp); } psl->cmd->list = NULL; info_msg("Sending reset to AFU"); add_job(psl->job, PSL_JOB_RESET, 0L); } lock_delay(psl->lock); } // Disconnect clients for (i = 0; i < psl->max_clients; i++) { if ((psl->client != NULL) && (psl->client[i] != NULL)) { // FIXME: Send warning to clients first? info_msg("Disconnecting %s context %d", psl->name, psl->client[i]->context); close_socket(&(psl->client[i]->fd)); } } // DEBUG debug_afu_drop(psl->dbg_fp, psl->dbg_id); // Disconnect from simulator, free memory and shut down thread info_msg("Disconnecting %s @ %s:%d", psl->name, psl->host, psl->port); if (psl->client) free(psl->client); if (psl->_prev) psl->_prev->_next = psl->_next; if (psl->_next) psl->_next->_prev = psl->_prev; if (psl->cmd) { free(psl->cmd); } if (psl->job) { free(psl->job); } if (psl->mmio) { free(psl->mmio); } if (psl->host) free(psl->host); if (psl->afu_event) { psl_close_afu_event(psl->afu_event); free(psl->afu_event); } if (psl->name) free(psl->name); if (*(psl->head) == psl) *(psl->head) = psl->_next; pthread_mutex_unlock(psl->lock); free(psl); pthread_exit(NULL); }
// PSL thread loop static void *_psl_loop(void *ptr) { struct psl *psl = (struct psl *)ptr; struct cmd_event *event, *temp; int events, i, stopped, reset; uint8_t ack = PSLSE_DETACH; stopped = 1; pthread_mutex_lock(psl->lock); while (psl->state != PSLSE_DONE) { // idle_cycles continues to generate clock cycles for some // time after the AFU has gone idle. Eventually clocks will // not be presented to an idle AFU to keep simulation // waveforms from getting huge with no activity cycles. if (psl->state != PSLSE_IDLE) { // if we have clients or we are in the reset state, refresh idle_cycles // so that the afu clock will not be allowed to stop to save afu event simulator cycles if ((psl->attached_clients > 0) || (psl->state == PSLSE_RESET)) { psl->idle_cycles = PSL_IDLE_CYCLES; if (stopped) info_msg("Clocking %s", psl->name); fflush(stdout); stopped = 0; } } if (psl->idle_cycles) { // Clock AFU //printf("before psl_signal_afu_model in psl_loop \n"); psl_signal_afu_model(psl->afu_event); // Check for events from AFU events = psl_get_afu_events(psl->afu_event); //printf("after psl_get_afu_events, events is 0x%3x \n", events); // Error on socket if (events < 0) { warn_msg("Lost connection with AFU"); break; } // Handle events from AFU if (events > 0) _handle_afu(psl); // Drive events to AFU send_job(psl->job); send_pe(psl->job); send_mmio(psl->mmio); if (psl->mmio->list == NULL) psl->idle_cycles--; } else { if (!stopped) info_msg("Stopping clocks to %s", psl->name); stopped = 1; lock_delay(psl->lock); } // Skip client section if AFU descriptor hasn't been read yet if (psl->client == NULL) { lock_delay(psl->lock); continue; } // Check for event from application reset = 0; for (i = 0; i < psl->max_clients; i++) { if (psl->client[i] == NULL) continue; if ((psl->client[i]->type == 'd') && (psl->client[i]->state == CLIENT_NONE) && (psl->client[i]->idle_cycles == 0)) { // this was the old way of detaching a dedicated process app/afu pair // we get the detach message, drop the client, and wait for idle cycle to get to 0 put_bytes(psl->client[i]->fd, 1, &ack, psl->dbg_fp, psl->dbg_id, psl->client[i]->context); _free(psl, psl->client[i]); psl->client[i] = NULL; // aha - this is how we only called _free once the old way // why do we not free client[i]? // because this was a short cut pointer // the *real* client point is in client_list in pslse reset = 1; // for m/s devices we need to do this differently and not send a reset... // _handle_client - creates the llcmd's to term and remove // send_pe - sends the llcmd pe's to afu one at a time // _handle_afu calls _handle_aux2 // _handle_aux2 finishes the llcmd pe's when jcack is asserted by afu // when the remove llcmd is processed, we should put_bytes, _free and set client[i] to NULL continue; } if (psl->state == PSLSE_RESET) continue; _handle_client(psl, psl->client[i]); if (psl->client[i]->idle_cycles) { psl->client[i]->idle_cycles--; } if (client_cmd(psl->cmd, psl->client[i])) { psl->client[i]->idle_cycles = PSL_IDLE_CYCLES; } } // Send reset to AFU if (reset == 1) { psl->cmd->buffer_read = NULL; event = psl->cmd->list; while (event != NULL) { if (reset) { warn_msg ("Client dropped context before AFU completed"); reset = 0; } info_msg("Dumping command tag=0x%02x", event->tag); #ifdef PSL9 info_msg("Dumping itag=0x%02x utag=0x%02x type=0x%02x state=0x%02x", event->itag, event->utag, event->type, event->state); #endif if (event->data) { free(event->data); } if (event->parity) { free(event->parity); } temp = event; event = event->_next; free(temp); } psl->cmd->list = NULL; info_msg("Sending reset to AFU"); add_job(psl->job, PSL_JOB_RESET, 0L); } lock_delay(psl->lock); } // Disconnect clients for (i = 0; i < psl->max_clients; i++) { if ((psl->client != NULL) && (psl->client[i] != NULL)) { // FIXME: Send warning to clients first? info_msg("Disconnecting %s context %d", psl->name, psl->client[i]->context); close_socket(&(psl->client[i]->fd)); } } // DEBUG debug_afu_drop(psl->dbg_fp, psl->dbg_id); // Disconnect from simulator, free memory and shut down thread info_msg("Disconnecting %s @ %s:%d", psl->name, psl->host, psl->port); if (psl->client) free(psl->client); if (psl->_prev) psl->_prev->_next = psl->_next; if (psl->_next) psl->_next->_prev = psl->_prev; if (psl->cmd) { free(psl->cmd); } if (psl->job) { free(psl->job); } if (psl->mmio) { free(psl->mmio); } if (psl->host) free(psl->host); if (psl->afu_event) { psl_close_afu_event(psl->afu_event); free(psl->afu_event); } if (psl->name) free(psl->name); if (*(psl->head) == psl) *(psl->head) = psl->_next; pthread_mutex_unlock(psl->lock); free(psl); pthread_exit(NULL); }