Ejemplo n.º 1
0
static void buffer_event (int rnw, uint32_t tag, uint8_t *addr) {
	uint8_t par[2];

	if (status.psl_state==PSL_FLUSHING) {
#ifdef DEBUG
		printf ("Response FLUSHED tag=0x%02x\n", tag);
#endif /* #ifdef DEBUG */
		add_resp (tag, PSL_RESPONSE_FLUSHED);
		return;
	}

	if (!testmemaddr (addr)) {
		printf ("AFU attempted ");
		if (rnw)
			printf ("write");
		else
			printf ("read");
		printf (" to invalid address 0x%016llx\n",(long long) addr);
#ifdef DEBUG
		printf ("Response AERROR tag=0x%02x\n", tag);
#endif /* #ifdef DEBUG */
		add_resp (tag, PSL_RESPONSE_AERROR);
		status.psl_state = PSL_FLUSHING;
		return;
	}

	if (rnw) {
#ifdef DEBUG
		printf ("Buffer Read tag=0x%02x\n", tag);
#endif /* #ifdef DEBUG */
		psl_buffer_read (status.event, tag, (uint64_t) addr,
				 CACHELINE_BYTES);
	}
	else {
#ifdef DEBUG
		printf ("Buffer Write tag=0x%02x\n", tag);
#endif /* #ifdef DEBUG */
		generate_cl_parity(addr, par);
		psl_buffer_write (status.event, tag, (uint64_t) addr,
				  CACHELINE_BYTES,
				  addr, par);
		++status.credits;
#ifdef DEBUG
		printf ("Response tag=0x%02x\n", tag);
#endif /* #ifdef DEBUG */
		if (status.psl_state==PSL_NLOCK) {
#ifdef DEBUG
			printf ("Nlock response for read, tag=0x%02x\n", tag);
			fflush (stdout);
#endif /* #ifdef DEBUG */
			add_resp (tag, PSL_RESPONSE_NLOCK);
		}
		else if (!PAGED_RANDOMIZER || (rand() % PAGED_RANDOMIZER)) {
			// Inject random "Paged" response
			add_resp (tag, PSL_RESPONSE_DONE);
		}
		else {
			add_resp (tag, PSL_RESPONSE_PAGED);
			status.psl_state = PSL_FLUSHING;
		}
	}
}
Ejemplo n.º 2
0
Archivo: cmd.c Proyecto: open-cpu/pslse
// Handle randomly selected pending read by either generating early buffer
// write with bogus data, send request to client for real data or do final
// buffer write with valid data after it has been received from client.
void handle_buffer_write(struct cmd *cmd)
{
	struct cmd_event *event;
	struct client *client;
	uint8_t buffer[10];
	uint64_t *addr;
	int quadrant, byte;

	// Make sure cmd structure is valid
	if (cmd == NULL)
		return;

	// Randomly select a pending read (or none)
	event = cmd->list;
	while (event != NULL) {
		if ((event->type == CMD_READ) &&
		    (event->state != MEM_DONE) &&
		    ((event->client_state != CLIENT_VALID) ||
		     !allow_reorder(cmd->parms))) {
			break;
		}
		event = event->_next;
	}

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// After the client returns data with a call to the function
	// _handle_mem_read() issue buffer write with valid data and
	// prepare for response.
	if (event->state == MEM_RECEIVED) {
		if (psl_buffer_write(cmd->afu_event, event->tag, event->addr,
				     CACHELINE_BYTES, event->data,
				     event->parity) == PSL_SUCCESS) {
			debug_msg("%s:BUFFER WRITE tag=0x%02x", cmd->afu_name,
				  event->tag);
			for (quadrant = 0; quadrant < 4; quadrant++) {
				DPRINTF("DEBUG: Q%d 0x", quadrant);
				for (byte = 0; byte < CACHELINE_BYTES / 4;
				     byte++) {
					DPRINTF("%02x", event->data[byte]);
				}
				DPRINTF("\n");
			}
			event->resp = PSL_RESPONSE_DONE;
			event->state = MEM_DONE;
			debug_cmd_buffer_write(cmd->dbg_fp, cmd->dbg_id,
					       event->tag);
			debug_cmd_update(cmd->dbg_fp, cmd->dbg_id, event->tag,
					 event->context, event->resp);
		}
	}

	if (event->state != MEM_IDLE)
		return;

	if (!event->buffer_activity && allow_buffer(cmd->parms)) {
		// Buffer write with bogus data, but only once
		debug_cmd_buffer_write(cmd->dbg_fp, cmd->dbg_id, event->tag);
		psl_buffer_write(cmd->afu_event, event->tag, event->addr,
				 CACHELINE_BYTES, event->data, event->parity);
		event->buffer_activity = 1;
	} else if (client->mem_access == NULL) {
		// Send read request to client, set client->mem_access
		// to point to this event blocking any other memory
		// accesses to client until data is returned by call
		// to the _handle_mem_read() function.
		buffer[0] = (uint8_t) PSLSE_MEMORY_READ;
		buffer[1] = (uint8_t) event->size;
		addr = (uint64_t *) & (buffer[2]);
		*addr = htonll(event->addr);
		event->abort = &(client->abort);
		if (put_bytes(client->fd, 10, buffer, cmd->dbg_fp,
			      cmd->dbg_id, event->context) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
		}
		event->state = MEM_REQUEST;
		debug_cmd_client(cmd->dbg_fp, cmd->dbg_id, event->tag,
				 event->context);
		client->mem_access = (void *)event;
	}
}