2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-19 08:26:30 +08:00
artiq/artiq/runtime/analyzer.c

156 lines
4.1 KiB
C

#include <system.h>
#include <generated/csr.h>
#include "log.h"
#include "analyzer.h"
#ifdef CSR_RTIO_ANALYZER_BASE
struct analyzer_header {
unsigned int sent_bytes;
unsigned long long int total_byte_count;
unsigned char overflow_occured;
unsigned char log_channel;
unsigned char dds_channel;
unsigned char padding;
} __attribute__((packed));
#define ANALYZER_BUFFER_SIZE (512*1024)
static struct analyzer_header analyzer_header;
static char analyzer_buffer[ANALYZER_BUFFER_SIZE] __attribute__((aligned(64)));
static void arm(void)
{
rtio_analyzer_message_encoder_overflow_reset_write(1);
rtio_analyzer_dma_base_address_write((unsigned int)analyzer_buffer);
rtio_analyzer_dma_last_address_write((unsigned int)analyzer_buffer + ANALYZER_BUFFER_SIZE - 1);
rtio_analyzer_dma_reset_write(1);
rtio_analyzer_dma_enable_write(1);
}
static void disarm(void)
{
rtio_analyzer_dma_enable_write(0);
while(rtio_analyzer_dma_busy_read());
flush_cpu_dcache();
flush_l2_cache();
}
void analyzer_init(void)
{
arm();
}
enum {
SEND_STATE_HEADER,
SEND_STATE_POST_POINTER, /* send from pointer to end of buffer */
SEND_STATE_PRE_POINTER, /* send from start of buffer to pointer-1 */
SEND_STATE_TERMINATE
};
static int send_state;
static int pointer;
static int wraparound;
static int offset_consumed;
static int offset_sent;
void analyzer_start(void)
{
disarm();
analyzer_header.total_byte_count = rtio_analyzer_dma_byte_count_read();
pointer = analyzer_header.total_byte_count % ANALYZER_BUFFER_SIZE;
wraparound = analyzer_header.total_byte_count >= ANALYZER_BUFFER_SIZE;
if(wraparound)
analyzer_header.sent_bytes = ANALYZER_BUFFER_SIZE;
else
analyzer_header.sent_bytes = analyzer_header.total_byte_count;
analyzer_header.overflow_occured = rtio_analyzer_message_encoder_overflow_read();
analyzer_header.log_channel = 0;
analyzer_header.dds_channel = CONFIG_RTIO_DDS_CHANNEL;
analyzer_header.padding = 0;
offset_consumed = 0;
offset_sent = 0;
send_state = SEND_STATE_HEADER;
}
void analyzer_end(void)
{
arm();
}
int analyzer_input(void *data, int length)
{
log("no input should be received by analyzer, dropping connection");
return -1;
}
void analyzer_poll(void **data, int *length)
{
switch(send_state) {
case SEND_STATE_HEADER:
*length = sizeof(struct analyzer_header) - offset_consumed;
*data = (char *)&analyzer_header + offset_consumed;
break;
case SEND_STATE_POST_POINTER:
*length = ANALYZER_BUFFER_SIZE - pointer - offset_consumed;
*data = analyzer_buffer + pointer + offset_consumed;
break;
case SEND_STATE_PRE_POINTER:
*length = pointer - offset_consumed;
*data = analyzer_buffer + offset_consumed;
break;
case SEND_STATE_TERMINATE:
*length = -1;
break;
default:
*length = 0;
break;
}
}
void analyzer_ack_consumed(int length)
{
offset_consumed += length;
}
void analyzer_ack_sent(int length)
{
offset_sent += length;
switch(send_state) {
case SEND_STATE_HEADER:
if(offset_sent >= sizeof(struct analyzer_header)) {
offset_consumed = 0;
offset_sent = 0;
if(wraparound)
send_state = SEND_STATE_POST_POINTER;
else {
if(pointer)
send_state = SEND_STATE_PRE_POINTER;
else
send_state = SEND_STATE_TERMINATE;
}
}
break;
case SEND_STATE_POST_POINTER:
if(pointer + offset_consumed >= ANALYZER_BUFFER_SIZE) {
offset_consumed = 0;
offset_sent = 0;
send_state = SEND_STATE_PRE_POINTER;
}
break;
case SEND_STATE_PRE_POINTER:
if(offset_sent >= pointer)
send_state = SEND_STATE_TERMINATE;
break;
}
}
#endif