Commit f3c72f8e authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

wip

parent f7d3d1d5
......@@ -4,12 +4,15 @@ CFLAGS = -I. -g
CXXFLAGS = -I. -g
OBJS = wrn-lib.o fmc-lib.o list-lib.o
all: lib test-rx
all: lib list-boot test-rx
lib: $(OBJS)
ar rc libwrn.a $(OBJS)
test-rx: test-rx.o
list-boot: list-boot.o $(OBJS)
${CXX} -o list-boot list-boot.o $(OBJS) -L. -lwrn -lpthread
test-rx: test-rx.o $(OBJS)
${CXX} -o test-rx test-rx.o $(OBJS) -L. -lwrn -lpthread
clean:
......
#include <stdio.h>
#include "list-lib.h"
void list_boot_node(struct list_node *dev);
main(int argc, char *argv[])
{
if(argc < 2)
{
printf("usage: %s <lun>\n", argv[0]);
return 0;
}
int lun = atoi(argv[1]);
printf("Booting LIST Node @ Lun %d\n", lun);
struct list_node *dev = list_open_node_by_lun(lun);
if(!dev)
{
printf("Open failed.\n");
return -1;
}
list_boot_node(dev);
return 0;
}
......@@ -6,7 +6,7 @@
#define TDC_APPLICATION "rt/tdc/rt-tdc.bin"
#define FD_APPLICATION "rt/tdc/rt-fd.bin"
#define FD_APPLICATION "rt/fd/rt-fd.bin"
#define WRN_APPID_LIST_TDC_FD 0x115790de
#define WRN_APPID_LIST_DUAL_FD 0x115790df
......@@ -18,10 +18,23 @@ struct list_node {
int n_outputs;
int fd_cpu_control[2];
int fd_cpu_logging[2];
struct wrn_dev *wrn;
};
struct list_timestamp picos_to_ts( uint64_t p )
{
struct list_timestamp t;
t.seconds = p / (1000ULL * 1000ULL * 1000ULL * 1000ULL);
p %= (1000ULL * 1000ULL * 1000ULL * 1000ULL);
t.cycles = p / 8000;
p %= 8000;
t.frac = p * 4096 / 8000;
return t;
}
static int rt_request ( struct list_node *node, int cpu, int command, uint32_t *req, int req_size, uint32_t *rsp )
{
uint32_t buf[128];
......@@ -32,7 +45,7 @@ static int rt_request ( struct list_node *node, int cpu, int command, uint32_t *
memcpy(buf + 2, req, req_size * 4);
wrn_send ( node->wrn, node->fd_cpu_control[cpu], buf, req_size + 2, 0);
int n = wrn_recv ( node->wrn, node->fd_cpu_control[cpu], buf, 128, 0);
int n = wrn_recv ( node->wrn, node->fd_cpu_control[cpu], buf, 128, -1);
if(rsp)
memcpy(rsp, buf, n * 4);
return n;
......@@ -72,6 +85,15 @@ static int check_node_running( struct list_node *dev )
#endif
// private function used by list-init, move to the driver
void list_boot_node(struct list_node *dev)
{
wrn_cpu_stop(dev->wrn, 0xff);
wrn_cpu_load_file(dev->wrn, 0, TDC_APPLICATION);
wrn_cpu_load_file(dev->wrn, 1, FD_APPLICATION);
wrn_cpu_start(dev->wrn, 0x3);
}
struct list_node* list_open_node_by_lun(int lun)
{
if ( wrn_lib_init() < 0)
......@@ -79,7 +101,6 @@ struct list_node* list_open_node_by_lun(int lun)
struct wrn_dev *wrn = wrn_open_by_lun( lun );
printf("open-node : %d %p ",lun, wrn);
if(!wrn)
return NULL;
......@@ -94,26 +115,21 @@ struct list_node* list_open_node_by_lun(int lun)
case WRN_APPID_LIST_DUAL_FD:
break;
case WRN_APPID_LIST_TDC_FD:
printf("Found TDC-FD node\n");
n->n_inputs = 5;
n->n_outputs = 4;
wrn_cpu_stop(wrn, 0xff);
wrn_cpu_load_file(wrn, 0, TDC_APPLICATION);
wrn_cpu_start(wrn, 0x1);
n->fd_cpu_control[0] = wrn_open_slot ( wrn, 0, WRN_SLOT_OUTGOING | WRN_SLOT_INCOMING );
n->fd_cpu_control[1] = wrn_open_slot ( wrn, 2, WRN_SLOT_OUTGOING | WRN_SLOT_INCOMING );
n->fd_cpu_logging[0] = wrn_open_slot ( wrn, 1, WRN_SLOT_OUTGOING );
n->fd_cpu_logging[1] = wrn_open_slot ( wrn, 3, WRN_SLOT_OUTGOING );
printf("open_slot: cpu 0 control fd %d\n", n->fd_cpu_control[0]);
break;
}
return n;
}
int list_in_enable(struct list_node *dev, int input, int enable)
{
if(input < 1 || input > 5)
......@@ -149,7 +165,10 @@ int list_in_software_trigger ( struct list_node* dev, struct list_trigger_entry
int list_in_assign_trigger ( struct list_node *dev, int input, struct list_id *trig )
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ASSIGN_TRIGGER, 4, input - 1, trig->system, trig->source_port, trig->trigger);
if(trig == NULL) // un-assign
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ASSIGN_TRIGGER, 5, input - 1, 0, 0, 0, 0);
else
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ASSIGN_TRIGGER, 5, input - 1, 1, trig->system, trig->source_port, trig->trigger);
}
int list_in_set_trigger_mode ( struct list_node *dev, int input, int mode )
......@@ -157,7 +176,116 @@ int list_in_set_trigger_mode ( struct list_node *dev, int input, int mode )
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_MODE, 2, input - 1 , mode );
}
int list_out_enable ( struct list_node *dev, int output, int enable )
{
return rt_requestf(dev, 1, ID_TDC_CMD_CHAN_SET_MODE, 2, output - 1 , enable );
}
int list_in_arm ( struct list_node *dev, int input, int armed )
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ARM, 2, input - 1, armed ? 1 : 0 );
}
int list_in_set_timebase_offset ( struct list_node *dev, int input, uint64_t offset )
{
struct list_timestamp t = picos_to_ts( offset );
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_TIMEBASE_OFFSET, 4, input - 1, t.seconds, t.cycles, t.frac );
}
int list_in_get_state ( struct list_node *dev, int input, struct list_input_state *state )
{
uint32_t rsp[128], req[2];
req[0] = input - 1;
int n = rt_request(dev, 0, ID_TDC_CMD_CHAN_GET_STATE, req, 1, rsp);
if(n == 29 && rsp[0] == ID_REP_STATE)
{
state->input = input;
state->flags = rsp[15];
state->log_level = rsp[16];
state->mode = rsp[17];
state->tagged_pulses = rsp[18];
state->sent_triggers = rsp[19];
state->dead_time.seconds = 0;
state->dead_time.frac = 0;
state->dead_time.cycles = rsp[20];
state->assigned_id.system = rsp[3];
state->assigned_id.source_port = rsp[4];
state->assigned_id.trigger = rsp[5];
state->delay.seconds = rsp[6];
state->delay.cycles = rsp[7];
state->delay.frac = rsp[8];
state->last.seconds = rsp[12];
state->last.cycles = rsp[13];
state->last.frac = rsp[14];
state->last_sent.ts.seconds = rsp[21];
state->last_sent.ts.cycles = rsp[22];
state->last_sent.ts.frac = rsp[23];
state->last_sent.id.system = rsp[24];
state->last_sent.id.source_port = rsp[25];
state->last_sent.id.trigger = rsp[26];
state->last_sent.seq = rsp[27];
state->sent_packets = rsp[28];
return 0;
} else
return -1;
}
int list_in_set_delay ( struct list_node *dev, int input, uint64_t delay_ps )
{
struct list_timestamp t = picos_to_ts(delay_ps);
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_DELAY, 4, input - 1, t.seconds, t.cycles, t.frac );
}
int list_in_set_log_level ( struct list_node *dev, int input, uint32_t log_level)
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_LOG_LEVEL, 2, input - 1, log_level );
}
int list_in_read_log ( struct list_node *dev, struct list_log_entry *log, int flags, int input_mask, int count )
{
int remaining = count;
int n_read = 0;
uint32_t buf[128];
struct list_log_entry *cur = log;
while(remaining)
{
int n = wrn_recv ( dev->wrn, dev->fd_cpu_logging[0], buf, 128, 0);
cur->type = buf[0];
cur->channel = buf[2];
if(n > 0)
{
if ((cur->type & flags) && (cur->channel & input_mask))
{
cur->seq=buf[1];
cur->id.system =buf[3];
cur->id.source_port =buf[4];
cur->id.trigger =buf[5];
cur->ts.seconds =buf[6];
cur->ts.cycles =buf[7];
cur->ts.frac =buf[8];
remaining--;
n_read++;
cur++;
}
} else
break;
}
return n_read;
}
......@@ -2,29 +2,143 @@
#define __LIST_LIB_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "rt/common/rt-common.h"
#include "rt/common/list-common.h"
struct list_input_state {
int input;
uint32_t flags; ///> enum list_io_flags
uint32_t log_level; ///> enum list_log_level
int mode;
uint32_t tagged_pulses;
uint32_t sent_triggers;
uint32_t sent_packets;
struct list_trigger_entry last_sent;
struct list_id assigned_id;
struct list_timestamp dead_time;
struct list_timestamp delay;
struct list_timestamp last;
};
struct list_node;
//! Open a LIST node device.
/*!
\param lun an integer argument to select the device or negative number to take the first one found.
\return returns an anonymous list_node structure on success. On error, NULL is returned, and errno is set appropriately.
*/
struct list_node* list_open_node_by_lun(int lun);
void list_close_node ( struct list_node *n );
//! Close a LIST node device.
/*!
\param node pointer to open node device.
*/
void list_close_node ( struct list_node *node );
/* 3.3.1a Enable/disable the input. */
//! Hardware enable/disable a LIST trigger input.
/*!
\param node pointer to open node device.
\param input index of the trigger input to enable
\param enable non-0 enables the input, 0 disables it.
*/
int list_in_enable(struct list_node *dev, int input, int enable);
int list_in_assign_trigger ( struct list_node *, int input, struct list_id *trig );
/* 3.3.1b Get/set the Trigger/System/Source Port ID. Change the IDs during operation of the node. */
//! Assign/unassign a trigger ID to a given LIST input.
/*!
\param node pointer to open node device.
\param input index of the trigger input to assign trigger to.
\param trig_id the trigger to be sent upon reception of a pulse on the given input.
passing NULL un-assigns the current trigger (the input will be tagging pulses and logging them,
but they will not be sent as triggers to the WR network).
*/
int list_in_assign_trigger ( struct list_node *, int input, struct list_id *trig_id );
/* 3.3.1d Get/set the mode: single shot or continuous. Single shot means the input will trigger on
the first incoming pulse and will ignore the subsequent pulses until re-armed. */
//! Set trigger mode for a given LIST input.
/*!
\param node pointer to open node device.
\param input index of the trigger input
\param mode triggering mode (enum list_trigger_mode). The input must be
armed by calling list_in_arm() at least once before it can send triggers.
*/
int list_in_set_trigger_mode ( struct list_node *, int input, int mode );
/* 3.3.1f Arm/re-arm the input. */
//! Arm a LIST input for triggering.
/*!
\param node pointer to open node device.
\param input index of the trigger input
\param armed non-0 arms the input, making it ready to accept/send triggers. 0 disarms the input.
*/
int list_in_arm ( struct list_node *, int input, int armed );
int list_in_check_triggered ( struct list_node *, int input );
int list_in_set_mode ( struct list_node *, int input, int mode );
int list_in_set_port_id ( struct list_node *, int input, uint32_t id);
int list_in_wait_trigger ( struct list_node*, int input_mask, struct list_id *id );
int list_in_read_raw ( struct list_node*, int input_mask, struct list_timestamp *ts, int count );
int list_in_read_log ( struct list_node*, int input_mask, struct list_input_log_entry *ts, int count );
/*
3.3.1h Log every trigger pulse sent out to the network. Each log message contains the input
number, sequence ID, trigger ID, trigger counter (since arm) and origin timestamp.
3.3.1j Log pulses coming to each physical input (within the performance limits).
*/
int list_in_read_log ( struct list_node*, struct list_log_entry *log, int flags, int input_mask, int count );
/* 3.3.1k • Software-trigger the input at a given TAI value. */
int list_in_software_trigger ( struct list_node*, struct list_trigger_entry *trigger );
int list_in_set_delay (struct list_node *, int input, uint64_t delay_ps);
int list_in_get_state ( struct list_node *, int input, struct tdc_channel_state *state );
int list_in_reset_seq_counter (struct list_node *dev, int input);
/* 3.3.1e Get/set the offset (for compensating cable delays), in 10 ps steps. */
int list_in_set_delay ( struct list_node *, int input, uint64_t delay_ps );
/* 3.3.1c Get/set the Sequence ID counter (counting up at every pulse). */
int list_in_set_seq_counter (struct list_node *dev, int input);
/* 3.3.1g Get/set the dead time (the minimum gap between input pulses, below which the TDC
ignores the subsequent pulses; limits maximum input pulse rate, 16 ns granularity) */
int list_in_set_dead_time ( struct list_node *dev, int input, uint64_t dead_time_ps );
int list_in_set_timebase_offset ( struct list_node *dev, int input, uint64_t offset );
/* 3.3.1i • Notify the host system that a trigger has been sent out to the network.
+ all "Get" commands */
int list_in_get_state ( struct list_node *, int input, struct list_input_state *state );
int list_in_set_log_level ( struct list_node *, int input, uint32_t log_level);
int list_out_enable(struct list_node *dev, int output, int enable);
int list_out_set_dead_time ( struct list_node *dev, int output, uint64_t dead_time_ps );
int list_out_add_trigger ( struct list_node *dev, int output, struct list_id *trig );
int list_out_add_conditional_trigger ( struct list_node *dev, int output, struct list_id *trig, struct list_id *condition );
int list_out_get_trigger_count ( struct list_node *dev, int output );
int list_out_set_delay ( struct list_node *, int output, uint64_t delay_ps );
int list_out_set_condition_delay ( struct list_node *, int output, uint64_t delay_ps );
int list_out_read_raw ( struct list_node*, struct list_timestamp *ts, int count );
//int list_out_read_log ( struct list_node*, int output_mask, struct list_input_log_entry *ts, int count );
int list_out_set_trigger_mode ( struct list_node *, int output, int mode );
int list_out_arm ( struct list_node *node, int input, int armed );
int list_out_get_state ( struct list_node *node, int input, int armed );
int list_out_check_triggered ( struct list_node *, int output );
int list_out_wait_trigger ( struct list_node*, int output_mask, struct list_id *id );
#endif
/*
Register definitions for slave core: WR Node CPU Local Registers
* File : wrn_cpu_lr.h
* Author : auto-generated by wbgen2 from wrn_cpu_lr.wb
* Created : Wed Apr 30 14:41:11 2014
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrn_cpu_lr.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WRN_CPU_LR_WB
#define __WBGEN2_REGDEFS_WRN_CPU_LR_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: CPU Polling Register */
/* definitions for field: HMQ Slot Status in reg: CPU Polling Register */
#define WRN_CPU_LR_POLL_HMQ_MASK WBGEN2_GEN_MASK(0, 16)
#define WRN_CPU_LR_POLL_HMQ_SHIFT 0
#define WRN_CPU_LR_POLL_HMQ_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define WRN_CPU_LR_POLL_HMQ_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for field: RMQ Slot Status in reg: CPU Polling Register */
#define WRN_CPU_LR_POLL_RMQ_MASK WBGEN2_GEN_MASK(16, 16)
#define WRN_CPU_LR_POLL_RMQ_SHIFT 16
#define WRN_CPU_LR_POLL_RMQ_W(value) WBGEN2_GEN_WRITE(value, 16, 16)
#define WRN_CPU_LR_POLL_RMQ_R(reg) WBGEN2_GEN_READ(reg, 16, 16)
/* definitions for register: CPU Status Register */
/* definitions for field: WR Link Up in reg: CPU Status Register */
#define WRN_CPU_LR_STAT_WR_LINK WBGEN2_GEN_MASK(0, 1)
/* definitions for field: WR Time OK in reg: CPU Status Register */
#define WRN_CPU_LR_STAT_WR_TIME_OK WBGEN2_GEN_MASK(1, 1)
/* definitions for register: TAI Cycles */
/* definitions for register: TAI Seconds */
/* definitions for register: Test */
/* [0x0]: REG CPU Polling Register */
#define WRN_CPU_LR_REG_POLL 0x00000000
/* [0x4]: REG CPU Status Register */
#define WRN_CPU_LR_REG_STAT 0x00000004
/* [0x8]: REG TAI Cycles */
#define WRN_CPU_LR_REG_TAI_CYCLES 0x00000008
/* [0xc]: REG TAI Seconds */
#define WRN_CPU_LR_REG_TAI_SEC 0x0000000c
/* [0x10]: REG GPIO Input */
#define WRN_CPU_LR_REG_GPIO_IN 0x00000010
/* [0x14]: REG GPIO Set */
#define WRN_CPU_LR_REG_GPIO_SET 0x00000014
/* [0x18]: REG GPIO Clear */
#define WRN_CPU_LR_REG_GPIO_CLEAR 0x00000018
#endif
#ifndef __LIST_COMMON_H
#define __LIST_COMMON_H
#ifdef WRNODE_RT
/* Mqueue slots assigned to the TDC/FD mezzanines */
#define TDC_IN_SLOT_CONTROL 0
#define TDC_OUT_SLOT_CONTROL 0
#define TDC_OUT_SLOT_LOGGING 1
#define TDC_OUT_SLOT_REMOTE 0
#define FD_IN_SLOT_CONTROL 1
#define FD_OUT_SLOT_CONTROL 2
#define FD_OUT_SLOT_LOGGING 3
#define FD_IN_SLOT_REMOTE 0
#endif
/* Command and log message IDs */
#define ID_LOG_RAW_INPUT 0x1
#define ID_LOG_SENT_TRIGGER 0x2
#define ID_TDC_CMD_CHAN_ENABLE 0x1
#define ID_TDC_CMD_CHAN_SET_DEAD_TIME 0x2
#define ID_TDC_CMD_CHAN_SET_DELAY 0x3
#define ID_TDC_CMD_CHAN_GET_STATE 0x4
#define ID_TDC_CMD_CHAN_ARM 0x5
#define ID_TDC_CMD_CHAN_DISARM 0x6
#define ID_TDC_CMD_CHAN_SET_MODE 0x7
#define ID_TDC_CMD_CHAN_SET_SEQ 0x8
#define ID_TDC_CMD_CHAN_ASSIGN_TRIGGER 0x9
#define ID_TDC_CMD_CHAN_SET_FLAGS 0xa
#define ID_TDC_CMD_CHAN_SET_TIMEBASE_OFFSET 0xb
#define ID_TDC_CMD_PING 0xc
#define ID_TDC_CMD_SOFTWARE_TRIGGER 0xd
#define ID_TDC_CMD_CHAN_SET_LOG_LEVEL 0xe
#define ID_REP_ACK 0x100
#define ID_REP_STATE 0x101
#define TDC_NUM_CHANNELS 5
#define TDC_TRIGGER_COALESCE_LIMIT 5
/*!..
* This enum is used by list_in_set_trigger_mode() and list_out_set_trigger_mode() to set input/output triggering mode.
*/
enum list_trigger_mode {
LIST_TRIGGER_MODE_SINGLE = 1, /*!< In SINGLE mode, the input/output will trigger only on the 1st pulse/trigger message after arming.*/
LIST_TRIGGER_MODE_AUTO = 2 /*!< In AUTO mode, the input/output will trigger on every pulse/trigger message.*/
};
/*!
* This enum is used in list_input_state / list_output_state structures to pass state information
*/
enum list_io_flags {
LIST_ENABLED = (1 << 0), /*!< I/O is physically enabled */
LIST_TRIGGER_ASSIGNED = (1 << 1), /*!< I/O is has a trigger assigned */
LIST_LAST_VALID = (1 << 2), /*!< I/O processed at least one pulse. It's timestamp/ID is in the "last" field. */
LIST_ARMED = (1 << 3), /*!< I/O is armed */
LIST_TRIGGERED = (1 << 4), /*!< I/O has triggered */
};
enum list_log_level {
LIST_LOG_NOTHING = 0,
LIST_LOG_RAW = (1 << 0), /*!< Input only: log all pulses coming to the TDC input */
LIST_LOG_SENT = (1 << 1), /*!< Input only: log all sent triggers */
LIST_LOG_PROMISC = (1 << 2), /*!< Output only: promiscious mode - log all trigger messages received from WR network */
LIST_LOG_FILTERED = (1 << 3), /*!< Output only: log all trigger messages that have been assigned to the output */
LIST_LOG_EXECUTED = (1 << 4), /*!< Output only: log all triggers executed on the output */
LIST_LOG_ALL = 0xff
};
struct list_timestamp {
int32_t seconds;
int32_t cycles;
int32_t frac;
};
struct list_id
{
uint32_t system;
uint32_t source_port;
uint32_t trigger;
};
struct list_trigger_entry {
struct list_timestamp ts;
struct list_id id;
uint32_t seq;
};
struct list_log_entry {
uint32_t type;
uint32_t seq;
int channel;
struct list_id id;
struct list_timestamp ts;
};
#ifdef WRNODE_RT
struct list_trigger_message {
struct rmq_message_addr hdr;
uint32_t transmit_seconds;
uint32_t transmit_cycles;
int count;
struct list_trigger_entry triggers[TDC_TRIGGER_COALESCE_LIMIT];
};
#endif
#ifdef WRNODE_RT
static inline void ts_add(struct list_timestamp *a, const struct list_timestamp *b)
{
a->frac += b->frac;
if(a->frac >= 4096)
{
a->frac -= 4096;
a->cycles ++;
}
a->cycles += b->cycles;
if(a->cycles >= 125000000)
{
a->cycles -= 125000000;
a->seconds++;
}
a->seconds += b->seconds;
}
static inline void ts_sub(struct list_timestamp *a, const struct list_timestamp *b)
{
a->frac -= b->frac;
if(a->frac < 0)
{
a->frac += 4096;
a->cycles --;
}
a->cycles -= b->cycles;
if(a->cycles < 0)
{
a->cycles += 125000000;
a->seconds--;
}
a->seconds -= b->seconds;
if(a->seconds == -1)
{
a->seconds = 0;
a->cycles -= 125000000;
}
}
#endif
#endif
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "rt-mqueue.h"
#include "rt-common.h"
int puts(const char *p)
{
int i;
volatile uint32_t *buf = mq_map_out_buffer(0, 1);
mq_claim(0, 1);
buf[0] = 0xdeadbeef;
for(i=0;i<127;i++,p++)
{
if(*p)
buf[i+1] = *p;
else
break;
}
mq_send(0, 1, i + 1);
return i;
}
/*
void ts_add(struct list_timestamp *a, struct list_timestamp *b)
{
a->frac += b->frac;
if(a->frac >= 4096)
a->cycles += 1 + b->cycles;
else
a->cycles += b->cycles;
if(a->cycle > 125 * 1000 * 1000)
a->seconds += 1 + b->seconds;
else
a->seconds += b->seconds;
}
*/
\ No newline at end of file
#ifndef __RT_COMMON_H
#define __RT_COMMON_H
#include <stdint.h>
#include <stdio.h>
#define TDC_IN_SLOT_CONTROL 0
#define TDC_OUT_SLOT_CONTROL 0
#define TDC_OUT_SLOT_LOGGING 1
#define TDC_OUT_SLOT_REMOTE 0
#include "hw/wrn_cpu_lr.h"
#define ID_TDC_LOG_RAW 0x1
#define ID_TDC_LOG_OUTGOING 0x2
#define CPU_DP_BASE 0x200000
#define CPU_LR_BASE 0x100000
#define ID_TDC_CMD_CHAN_ENABLE 0x1
#define ID_TDC_CMD_CHAN_SET_DEAD_TIME 0x2
#define ID_TDC_CMD_CHAN_SET_DELAY 0x3
#define ID_TDC_CMD_CHAN_GET_STATE 0x4
#define ID_TDC_CMD_CHAN_ARM 0x5
#define ID_TDC_CMD_CHAN_DISARM 0x6
#define ID_TDC_CMD_CHAN_SET_MODE 0x7
#define ID_TDC_CMD_CHAN_RESET_SEQ 0x8
#define ID_TDC_CMD_CHAN_ASSIGN_TRIGGER 0x9
#define ID_TDC_CMD_CHAN_SET_FLAGS 0xa
#define ID_TDC_CMD_CHAN_SET_TIMEBASE_OFFSET 0xb
#define ID_TDC_CMD_PING 0xc
#define ID_TDC_CMD_SOFTWARE_TRIGGER 0xd
#define ID_TDC_LOG_RAW_TIMESTAMP 0x102
#define ID_TDC_LOG_TRIGGER 0x103
#define ID_REP_ACK 0x100
#define ID_REP_STATE 0x101
#define TDC_NUM_CHANNELS 5
#define TDC_TRIGGER_COALESCE_LIMIT 5
#define TDC_CHAN_LOG_RAW (1<<0)
#define TDC_CHAN_LOG_TRIGGERS (1<<1)
#define TDC_CHAN_TRIGGER_ASSIGNED (1<<2)
#define TDC_CHAN_ARMED (1<<3)
#define TDC_CHAN_TRIGGERED (1<<4)
#define TDC_CHAN_ENABLED (1<<5)
#define TDC_CHAN_MODE_SINGLE 0
#define TDC_CHAN_MODE_CONTINUOUS 1
struct list_timestamp {
int32_t seconds;
int32_t cycles;
int32_t frac;
};
static inline uint32_t dp_readl ( uint32_t reg )
{
return *(volatile uint32_t *) ( reg + CPU_DP_BASE );
}
struct list_id
static inline void dp_writel ( uint32_t value, uint32_t reg )
{
uint32_t system;
uint32_t source_port;
uint32_t trigger;
};
*(volatile uint32_t *) ( reg + CPU_DP_BASE ) = value;
}
struct list_trigger_entry {
struct list_timestamp ts;
struct list_id id;
uint32_t seq;
};
static inline uint32_t lr_readl ( uint32_t reg )
{
return *(volatile uint32_t *) ( reg + CPU_LR_BASE );
}
#ifdef WRNODE_APP
struct list_trigger_message {
struct rmq_message_addr hdr;
uint32_t transmit_seconds;
uint32_t transmit_cycles;
int count;
struct list_trigger_entry triggers[TDC_TRIGGER_COALESCE_LIMIT];
};
#endif
static inline uint32_t lr_writel ( uint32_t value, uint32_t reg )
{
*(volatile uint32_t *) ( reg + CPU_LR_BASE ) = value;
}
struct tdc_channel_state {
struct list_id id;
struct list_timestamp delay;
struct list_timestamp timebase_offset;
struct list_timestamp last;
int32_t flags;
int32_t mode;
int32_t n;
int32_t total_pulses;
int32_t sent_pulses;
int32_t worst_latency;
uint32_t seq;
};
static inline void gpio_set ( int pin )
{
lr_writel ( (1<<pin), WRN_CPU_LR_REG_GPIO_SET );
}
struct tdc_channel_state_msg
static inline void gpio_clear ( int pin )
{
int seq;
struct tdc_channel_state state;
};
lr_writel ( (1<<pin), WRN_CPU_LR_REG_GPIO_CLEAR );
}
static inline void delay(int n)
{
int i;
for(i=0;i<n;i++) asm volatile("nop");
}
#endif
#ifndef __MQUEUE_H
#define __MQUEUE_H
#ifndef __RT_MQUEUE_H
#define __RT_MQUEUE_H
#define REG_LR_POLL 0x100000
......@@ -65,4 +65,9 @@ static inline uint32_t mq_poll()
return *(volatile uint32_t *) ( REG_LR_POLL );
}
static inline uint32_t rmq_poll(int slot)
{
return *(volatile uint32_t *) ( REG_LR_POLL ) & ( 1<< (16 + slot ));
}
#endif
#ifndef __WRN_RT_H
#define __WRN_RT_H
#include <stdint.h>
#include "rt-mqueue.h"
#include "rt-common.h"
#include "pp-printf.h"
#endif
/*
* vsprintf-xint: a possible free-software replacement for mprintf
*
* public domain
*/
#include <stdarg.h>
#include <stdint.h>
static const char hex[] = "0123456789abcdef";
static int number(char *out, unsigned value, int base, int lead, int wid)
{
char tmp[16];
int i = 16, ret, negative = 0;
/* No error checking at all: it is as ugly as possible */
if ((signed)value < 0 && base == 10) {
negative = 1;
value = -value;
}
while (value && i) {
tmp[--i] = hex[value % base];
value /= base;
}
if (i == 16)
tmp[--i] = '0';
if (negative && lead == ' ') {
tmp[--i] = '-';
negative = 0;
}
while (i > 16 - wid + negative)
tmp[--i] = lead;
if (negative)
tmp[--i] = '-';
ret = 16 - i;
while (i < 16)
*(out++) = tmp[i++];
return ret;
}
int pp_vsprintf(char *buf, const char *fmt, va_list args)
{
char *s, *str = buf;
int base, lead, wid;
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
*str++ = *fmt;
continue;
}
base = 10;
lead = ' ';
wid = 1;
repeat:
fmt++; /* Skip '%' initially, other stuff later */
switch(*fmt) {
case '\0':
goto ret;
case '0':
lead = '0';
goto repeat;
case '*':
/* should be precision, just eat it */
base = va_arg(args, int);
/* fall through: discard unknown stuff */
default:
if (*fmt >= '1' && *fmt <= '9')
wid = *fmt - '0';
goto repeat;
/* Special cases for conversions */
case 'c': /* char: supported */
*str++ = (unsigned char) va_arg(args, int);
break;
case 's': /* string: supported */
s = va_arg(args, char *);
while (*s)
*str++ = *s++;
break;
case 'n': /* number-thus-far: not supported */
break;
case '%': /* supported */
*str++ = '%';
break;
/* integers are more or less printed */
case 'p':
case 'x':
case 'X':
base = 16;
case 'o':
if (base == 10) /* yet unchaged */
base = 8;
case 'd':
case 'i':
case 'u':
str += number(str, va_arg(args, int), base, lead, wid);
break;
}
}
ret:
*str = '\0';
return str - buf;
}
......@@ -7,8 +7,8 @@ OBJDUMP = $(CROSS_COMPILE)objdump
OBJCOPY = $(CROSS_COMPILE)objcopy
SIZE = $(CROSS_COMPILE)size
CFLAGS = -g -Os -I. -I../common
OBJS += ../common/wrn-crt0.o ../common/vsprintf-mini.o ../common/printf.o
CFLAGS = -DWRNODE_RT -g -O3 -I. -I../common -mmultiply-enabled -mbarrel-shift-enabled
OBJS += ../common/wrn-crt0.o ../common/vsprintf-xint.o ../common/printf.o ../common/rt-common.o
LDSCRIPT = ../common/wrnode.ld
$(OUTPUT): $(LDSCRIPT) $(OBJS)
......
This diff is collapsed.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "wrn-lib.h"
#include "list-lib.h"
void decode_flags(char *buf, uint32_t flags)
{
strcpy(buf,"");
if( flags & LIST_ENABLED )
strcat(buf, "Enabled ");
if( flags & LIST_TRIGGER_ASSIGNED )
strcat(buf, "TrigAssigned ");
if( flags & LIST_LAST_VALID )
strcat(buf, "LastTimestampValid ");
if( flags & LIST_ARMED )
strcat(buf, "Armed ");
if( flags & LIST_TRIGGERED )
strcat(buf, "Triggered ");
int l = strlen(buf);
if(l)
buf[l-1] = 0;
}
void decode_mode (char *buf, int mode)
{
switch(mode)
{
case LIST_TRIGGER_MODE_AUTO:
strcpy(buf, "Auto");
break;
case LIST_TRIGGER_MODE_SINGLE:
strcpy(buf, "Single shot");
break;
default:
strcpy(buf,"?");
break;
}
}
void decode_log_level(char *buf, uint32_t flags)
{
strcpy(buf,"");
if(flags == 0)
strcpy(buf, "off");
if (flags & LIST_LOG_RAW)
strcat(buf, "Raw ");
if (flags & LIST_LOG_SENT)
strcat(buf, "Sent ");
if (flags & LIST_LOG_PROMISC)
strcat(buf, "Promiscious ");
if (flags & LIST_LOG_FILTERED)
strcat(buf, "Filtered ");
if (flags & LIST_LOG_EXECUTED)
strcat(buf, "Exceuted ");
}
void format_ts( char *buf, struct list_timestamp ts, int with_seconds )
{
uint64_t picoseconds = (uint64_t) ts.cycles * 8000 + (uint64_t)ts.frac * 8000ULL / 4096ULL;
if(with_seconds)
{
sprintf (buf, "%llu:%03llu,%03llu,%03llu ns + %3llu ps",
(long long)(ts.seconds),
(picoseconds / (1000LL * 1000 * 1000)),
(picoseconds / (1000LL * 1000) % 1000),
(picoseconds / (1000LL) % 1000),
(picoseconds % 1000LL));
} else {
sprintf (buf, "%03llu,%03llu,%03llu ns + %3llu ps",
(picoseconds / (1000LL * 1000 * 1000)),
(picoseconds / (1000LL * 1000) % 1000),
(picoseconds / (1000LL) % 1000),
(picoseconds % 1000LL));
}
}
void format_id (char *buf, struct list_id id )
{
sprintf( buf, "%04x:%04x:%08x", id.system, id.source_port,id.trigger);
}
uint64_t ts_to_picos ( struct list_timestamp ts )
{
return (uint64_t) ts.seconds * 1000LL * 1000 * 1000 * 1000
+ (uint64_t) ts.cycles * 8000ULL +
+ (uint64_t) ts.frac * 8000LL / 4096LL;
}
void dump_input_state ( struct list_input_state *state )
{
char tmp[1024], tmp2[1024];
decode_flags(tmp,state->flags);
printf("Channel %d state:\n", state->input );
printf(" - Flags: %s\n", tmp);
decode_mode(tmp,state->mode);
printf(" - Mode: %s\n", tmp );
format_ts ( tmp, state->delay, 0 );
printf(" - Delay: %s\n", tmp );
printf(" - Tagged pulses: %-10d\n", state->tagged_pulses );
printf(" - Sent triggers: %-10d\n", state->sent_triggers );
printf(" - Sent packets: %-10d\n", state->sent_packets );
format_id(tmp, state->assigned_id);
printf(" - Assigned ID: %s\n", state->flags & LIST_TRIGGER_ASSIGNED ? tmp : "none" );
if( state-> flags & LIST_LAST_VALID )
{
format_ts( tmp, state->last, 1 );
printf(" - Last input pulse: %s\n", tmp );
}
if(state->sent_triggers > 0)
{
format_ts( tmp, state->last_sent.ts, 1 );
format_id( tmp2, state->last_sent.id );
printf(" - Last sent trigger: %s, ID: %s, SeqNo %d\n", tmp, tmp2, state->last_sent.seq);
}
printf(" - Dead time: %d ns\n", ts_to_picos( state->dead_time ) / 1000 );
decode_log_level(tmp,state->log_level);
printf(" - Log level: %s\n", tmp);
}
void dump_log( struct list_log_entry *log, int n)
{
int i;
for(i=0;i<n;i++)
{
char tmp[1024];
struct list_log_entry *e = &log[i];
if(e->type == LIST_LOG_RAW)
printf("Raw ");
printf("Ch: %d ", e->channel);
format_ts(tmp, e->ts, 1);
printf("Ts: %s\n", tmp);
}
}
main()
{
struct list_node *n = list_open_node_by_lun ( 0 );
struct list_id trig = { 10, 20, 30 };
//list_in_set_dead_time(n, 1, 90 * 1000 * 1000);
list_in_enable(n, 1, 1);
list_in_assign_trigger(n, 1, &trig);
list_in_set_trigger_mode(n, 1, TDC_CHAN_MODE_CONTINUOUS);
list_in_arm(n, 1, 1);
#if 0
struct list_trigger_entry t;
t.id.system = 0x1;
t.id.source_port = 0x1;
t.id.trigger = 0x3;
t.ts.seconds = 0x4;
t.ts.cycles = 0x5;
t.ts.frac = 0x6;
t.seq = 0;
struct list_id trig2 = { 10, 20, 31 };
fprintf(stderr,"SDT\n");
list_in_set_dead_time(n, 1, 90 * 1000 * 1000);
fprintf(stderr,"STO\n");
list_in_set_timebase_offset (n, 1, 216000ULL );
int i;
for( i = 1; i <= 5; i++)
{
list_in_enable(n, i, 0);
list_in_set_delay(n, i, 1 * 1000 * 1000); // 1us delay
list_in_enable(n, i, 1);
trig.trigger = i + 123;
list_in_assign_trigger(n, i, &trig);
list_in_set_log_level(n, i, LIST_LOG_RAW);
list_in_set_trigger_mode(n, i, LIST_TRIGGER_MODE_AUTO);
list_in_arm(n, i, 1);
}
for(;;)
{
list_in_software_trigger(n, &t);
t.seq++;
usleep(10000);
printf("swT\n");
struct list_input_state state;
struct list_log_entry logbuf[128];
//list_in_get_state(n, 1, &state);
//dump_input_state(&state);
int n_ent = list_in_read_log(n, logbuf, LIST_LOG_RAW | LIST_LOG_SENT, 0xff, 12);
dump_log(logbuf, n_ent);
//sleep(1);
}
#endif
sleep(1000);
return 0;
}
......@@ -60,6 +60,11 @@ struct wrn_buffer {
msgs.pop_back();
return rv;
}
int count()
{
return msgs.size();
}
pthread_mutex_t mutex;
std::deque<wrn_message> msgs;
......
......@@ -78,7 +78,7 @@ static int init_hmq( struct wrn_dev *dev )
dev->hmq.n_in = n_in;
dev->hmq.n_out = n_out;
//printf("init_hmq: CPU->Host (outgoing) slots: %d, Host->CPU (incoming) slots: %d\n", n_out, n_in);
printf("init_hmq: CPU->Host (outgoing) slots: %d, Host->CPU (incoming) slots: %d\n", n_out, n_in);
for(i=0 ; i<n_out; i++)
{
......@@ -86,7 +86,7 @@ static int init_hmq( struct wrn_dev *dev )
width = 1 << (( slot_status >> 28) & 0xf);
entries = 1 << (( slot_status >> 2) & 0x3f);
hmq_writel(dev, HMQ_OUT(i), MQUEUE_CMD_PURGE, MQUEUE_SLOT_COMMAND);
// printf(" - out%d: width=%d, entries=%d\n", i, width, entries);
printf(" - out%d: width=%d, entries=%d\n", i, width, entries);
}
for(i =0 ; i<n_in; i++)
{
......@@ -94,14 +94,14 @@ static int init_hmq( struct wrn_dev *dev )
width = 1 << (( slot_status >> 28) & 0xf);
entries = 1 << (( slot_status >> 2) & 0x3f);
hmq_writel(dev, HMQ_IN(i), MQUEUE_CMD_PURGE, MQUEUE_SLOT_COMMAND);
//printf(" - in%d: width=%d, entries=%d\n", i, width, entries);
printf(" - in%d: width=%d, entries=%d\n", i, width, entries);
}
return 0;
}
int init_cpus(struct wrn_dev *dev)
{
wrn_writel(dev, 0xffffffff, BASE_CPU_CSR + WRN_CPU_CSR_REG_RESET);
// wrn_writel(dev, 0xffffffff, BASE_CPU_CSR + WRN_CPU_CSR_REG_RESET);
dev->cpu_count = wrn_readl(dev, BASE_CPU_CSR + WRN_CPU_CSR_REG_CORE_COUNT) & 0xf;
//printf("init_cpus: %d CPU CBs\n", dev->cpu_count);
......@@ -135,6 +135,8 @@ struct wrn_dev* wrn_open_by_lun( int lun )
init_hmq ( dev );
start_update_thread( dev );
return dev;
}
......@@ -265,7 +267,11 @@ static bool do_rx(struct wrn_dev *dev, wrn_message& msg, int& slot)
//uint32_t cnt = hmq_readl(dev, HMQ_GCR, MQUEUE_GCR_SLOT_COUNT);
// printf("gcr %x\n", in_stat);
/*printf("gcr %x\n", in_stat);
if(in_stat & 1)
{
printf("Got!\n");
}*/
if(in_stat & SLOT_OUT_MASK)
{
int i, j;
......@@ -330,14 +336,18 @@ void do_tx(struct wrn_dev *dev, const wrn_message& msg, int slot )
void update_mqueues( struct wrn_dev * dev )
int update_mqueues( struct wrn_dev * dev )
{
wrn_message msg;
int slot;
int rx_limit = 5;
int got_sth = 0;
// outgoing path (from CPUs)
while(do_rx (dev, msg, slot))
while(do_rx (dev, msg, slot) && rx_limit)
{
// printf("RxLim %d\n", rx_limit);
rx_limit--;
got_sth = 1;
//printf("slot %d rx %d words\n", slot, msg.size());
for (wrn_connmap::iterator i = dev->fds.begin(); i != dev->fds.end(); ++i)
{
......@@ -350,6 +360,7 @@ void update_mqueues( struct wrn_dev * dev )
//printf("locked\n");
buf->process(msg);
buf->unlock();
}
}
}
......@@ -363,13 +374,15 @@ void update_mqueues( struct wrn_dev * dev )
if(tx_ready(dev, buf->slot))
{
buf->lock(true);
got_sth = 1;
// printf("DoTX\n");
do_tx(dev, buf->pop(), buf->slot);
buf->unlock();
}
}
}
return got_sth;
}
......@@ -420,6 +433,7 @@ int wrn_open_slot ( struct wrn_dev *dev, int slot, int flags )
conn->in = new wrn_buffer(slot);
dev->fds[fd] = conn;
printf("open slot %d, fd = %d\n", slot, fd);
return fd;
}
......@@ -445,14 +459,18 @@ int wrn_recv ( struct wrn_dev *dev, int fd, uint32_t *buffer, size_t buf_size, i
int64_t t_start = get_tics();
if(!timeout_us && conn->out->empty())
return 0;
while(conn->out->empty())
{
if(get_tics() - t_start >= timeout_us )
if(timeout_us >= 0 && (get_tics() - t_start) >= timeout_us )
return 0;
usleep(1000);
//fprintf(stderr,"w");
usleep(1);
}
conn->out->lock(true);
......@@ -491,7 +509,7 @@ void *update_thread_entry( void *data )
// fprintf(stderr,"readout thread started\n");
for(;;)
{
update_mqueues(dev);
usleep(10000);
if( !update_mqueues(dev) );
usleep(1000);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment