Commit 696d7eff authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

test

parent f3c72f8e
......@@ -4,7 +4,7 @@ CFLAGS = -I. -g
CXXFLAGS = -I. -g
OBJS = wrn-lib.o fmc-lib.o list-lib.o
all: lib list-boot test-rx
all: lib list-boot list-input-test test-rx test-hash list-output-test list-dbg
lib: $(OBJS)
ar rc libwrn.a $(OBJS)
......@@ -12,11 +12,23 @@ lib: $(OBJS)
list-boot: list-boot.o $(OBJS)
${CXX} -o list-boot list-boot.o $(OBJS) -L. -lwrn -lpthread
list-dbg: list-dbg.o $(OBJS)
${CXX} -o list-dbg list-dbg.o $(OBJS) -L. -lwrn -lpthread
test-rx: test-rx.o $(OBJS)
${CXX} -o test-rx test-rx.o $(OBJS) -L. -lwrn -lpthread
test-hash: test-hash.o $(OBJS)
${CXX} -o test-hash test-hash.o $(OBJS) -L. -lwrn -lpthread
list-input-test: list-input-test.o $(OBJS)
${CXX} -o list-input-test list-input-test.o $(OBJS) -L. -lwrn -lpthread
list-output-test: list-output-test.o $(OBJS)
${CXX} -o list-output-test list-output-test.o $(OBJS) -L. -lwrn -lpthread
clean:
rm -f $(OBJS) libwrn.a test-rx
rm -f $(OBJS) libwrn.a test-rx test-hash list-boot
%.o: %.cpp
${CXX} -o $@ -c $^ $(CXXFLAGS)
\ No newline at end of file
/* A simple console for accessing the SVEC virtual UART (i.e. for communicating with the WR Core shell
from a Linux terminal. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
......
#ifndef __MQUEUE_H
#define __MQUEUE_H
#define BASE_HMQ 0x00000
#define MQUEUE_GCR ( 0x0)
#define MQUEUE_IN(slot) ( 0x4000 + (slot) * 0x400)
#define MQUEUE_OUT(slot) ( 0x8000 + (slot) * 0x400)
#define MQUEUE_CMD_CLAIM (1<<24)
#define MQUEUE_CMD_PURGE (1<<25)
#define MQUEUE_CMD_READY (1<<26)
#define MQUEUE_CMD_DISCARD (1<<27)
#define MQUEUE_SLOT_COMMAND 0
#define MQUEUE_SLOT_STATUS 4
#define MQUEUE_SLOT_DATA_START 8
#define MQUEUE_GCR_INCOMING_STATUS_MASK (0x0000ffff)
#define MQUEUE_GCR_SLOT_COUNT 0
#define MQUEUE_GCR_SLOT_STATUS 4
#define MQUEUE_GCR_IRQ_MASK 8
#define MQUEUE_GCR_IRQ_COALESCE 12
#define MQUEUE_SLOT_STATUS_FULL (1<<0)
#endif
#include <stdio.h>
#include "list-lib.h"
void list_boot_node(struct list_node *dev);
main(int argc, char *argv[])
......@@ -24,6 +25,8 @@ main(int argc, char *argv[])
list_boot_node(dev);
sleep(2);
return 0;
}
......@@ -44,6 +44,7 @@ static int rt_request ( struct list_node *node, int cpu, int command, uint32_t *
if(req_size)
memcpy(buf + 2, req, req_size * 4);
// printf("rq-s cpu %d fd %d size %d\n", cpu, node->fd_cpu_control[cpu], req_size + 2);
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, -1);
if(rsp)
......@@ -115,12 +116,12 @@ 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");
// printf("Found TDC-FD node\n");
n->n_inputs = 5;
n->n_outputs = 4;
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_control[1] = wrn_open_slot ( wrn, 1, WRN_SLOT_OUTGOING | WRN_SLOT_INCOMING );
n->fd_cpu_logging[0] = wrn_open_slot ( wrn, 2, WRN_SLOT_OUTGOING );
n->fd_cpu_logging[1] = wrn_open_slot ( wrn, 3, WRN_SLOT_OUTGOING );
break;
......@@ -140,12 +141,12 @@ int list_in_enable(struct list_node *dev, int input, int enable)
int list_in_set_dead_time ( struct list_node *dev, int input, uint64_t dead_time_ps )
{
int dead_time_cycles = dead_time_ps / 8000;
int dead_time_cycles = dead_time_ps / 16000;
if(dead_time_cycles < 10000 || dead_time_cycles > 10000000 )
if(dead_time_cycles < 5000 || dead_time_cycles > 10000000 )
return -EINVAL;
if(input < 1 || input > 5)
if(input < 1 || input > dev->n_inputs)
return -EINVAL;
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_DEAD_TIME, 2, input-1, dead_time_cycles);
......@@ -165,6 +166,9 @@ 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 )
{
if(input < 1 || input > dev->n_inputs)
return -EINVAL;
if(trig == NULL) // un-assign
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ASSIGN_TRIGGER, 5, input - 1, 0, 0, 0, 0);
else
......@@ -173,6 +177,7 @@ int list_in_assign_trigger ( struct list_node *dev, int input, struct list_id *t
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 );
}
......@@ -186,16 +191,31 @@ 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_reset_counters ( struct list_node *dev, int input )
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_RESET_COUNTERS, 1, input - 1 );
}
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 );
}
static void unbag_ts(uint32_t *buf, int offset, struct list_timestamp *ts)
{
ts->seconds = buf[offset];
ts->cycles = buf[offset + 1];
ts->frac = buf[offset + 2];
}
int list_in_get_state ( struct list_node *dev, int input, struct list_input_state *state )
{
uint32_t rsp[128], req[2];
if(input < 1 || input > dev->n_inputs)
return -EINVAL;
req[0] = input - 1;
int n = rt_request(dev, 0, ID_TDC_CMD_CHAN_GET_STATE, req, 1, rsp);
......@@ -210,23 +230,15 @@ int list_in_get_state ( struct list_node *dev, int input, struct list_input_stat
state->sent_triggers = rsp[19];
state->dead_time.seconds = 0;
state->dead_time.frac = 0;
state->dead_time.cycles = rsp[20];
state->dead_time.cycles = rsp[20] * 2;
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];
unbag_ts(rsp, 6, &state->delay);
unbag_ts(rsp, 12, &state->last);
unbag_ts(rsp, 21, &state->last_sent.ts);
state->last_sent.id.system = rsp[24];
state->last_sent.id.source_port = rsp[25];
state->last_sent.id.trigger = rsp[26];
......@@ -244,6 +256,7 @@ 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 );
}
......@@ -289,3 +302,173 @@ int list_in_read_log ( struct list_node *dev, struct list_log_entry *log, int fl
}
int list_out_trig_assign ( struct list_node *dev, struct list_trigger_handle *handle, int output, struct list_id *trig, struct list_id *condition )
{
uint32_t req[128], rsp[128];
if(output < 1 || output > dev->n_outputs)
return -EINVAL;
req[0] = output - 1;
req[4] = condition ? 1 : 0;
req[1] = trig->system;
req[2] = trig->source_port;
req[3] = trig->trigger;
if(condition)
{
req[5] = condition->system;
req[6] = condition->source_port;
req[7] = condition->trigger;
}
int n = rt_request(dev, 1, ID_FD_CMD_CHAN_ASSIGN_TRIGGER, req, 8, rsp);
if(n == 5 && rsp[0] == ID_REP_TRIGGER_HANDLE)
{
if(handle)
{
handle->channel = rsp[2];
handle->ptr_cond = rsp[3];
handle->ptr_trig = rsp[4];
}
return 0;
} else
return -1;
}
int list_out_trig_remove ( struct list_node *dev, struct list_trigger_handle *handle )
{
uint32_t req[128], rsp[128];
req[0] = handle->channel;
req[1] = handle->ptr_cond;
req[2] = handle->ptr_trig;
printf("remove: %x %x %x\n", handle->channel, handle->ptr_cond, handle->ptr_trig);
int n = rt_request(dev, 1, ID_FD_CMD_CHAN_REMOVE_TRIGGER, req, 3, rsp);
if(n == 2 && rsp[0] == ID_REP_ACK)
{
return 0;
} else
return -1;
}
int list_out_trig_get_all (struct list_node *dev, int output, struct list_output_trigger_state *triggers, int max_count)
{
int bucket;
int count = 0;
if(output < 1 || output > dev->n_outputs)
return -EINVAL;
for(bucket = 0; bucket < FD_HASH_ENTRIES; bucket++)
{
int index = 0;
while(count < max_count)
{
uint32_t req[128], rsp[128];
req[0] = bucket;
req[1] = index;
req[2] = output - 1;
int n = rt_request(dev, 1, ID_FD_CMD_READ_HASH, req, 3, rsp);
if(n != 11 && rsp[0] != ID_REP_HASH_ENTRY)
return -1;
int valid = rsp[2];
if(!valid)
break;
uint32_t state = rsp[8];
printf("%d %d %x\n", bucket, index, state);
if (state != HASH_ENT_EMPTY && !(state & HASH_ENT_CONDITIONAL))
{
struct list_output_trigger_state *current = &triggers[count];
current->handle.channel = output -1;
current->handle.ptr_cond = rsp[9];
current->handle.ptr_trig = rsp[10];
current->trigger.system = rsp[3];
current->trigger.source_port = rsp[4];
current->trigger.trigger = rsp[5];
current->delay_trig.seconds = 0;
current->delay_trig.cycles = rsp[6];
current->delay_trig.frac = rsp[7];
current->is_conditional = 0;
if(rsp[9]) // condition assigned?
{
current->is_conditional = 1;
current->condition.system = rsp[11];
current->condition.source_port = rsp[12];
current->condition.trigger = rsp[13];
current->delay_cond.seconds = 0;
current->delay_cond.cycles = rsp[14];
current->delay_cond.frac = rsp[15];
}
current->enabled = (state & HASH_ENT_DISABLED) ? 0 : 1;
count++;
}
index++;
}
}
return count;
}
int list_out_trig_set_delay ( struct list_node *dev, struct list_trigger_handle *handle, uint64_t delay_ps )
{
struct list_timestamp t = picos_to_ts(delay_ps);
return rt_requestf(dev, 1, ID_FD_CMD_CHAN_SET_DELAY, 4, handle->channel, handle->ptr_trig, t.cycles, t.frac );
}
int list_out_get_state ( struct list_node *dev, int output, struct list_output_state *state )
{
uint32_t rsp[128], req[2];
if(output < 1 || output > dev->n_outputs)
return -EINVAL;
req[0] = output - 1;
int n = rt_request(dev, 1, ID_FD_CMD_CHAN_GET_STATE, req, 1, rsp);
if(n == 28 && rsp[0] == ID_REP_STATE)
{
state->executed_pulses = rsp[3];
state->missed_pulses_late = rsp[4];
state->missed_pulses_deadtime = rsp[5];
state->missed_pulses_overflow = rsp[6];
state->total_rx_packets = rsp[27];
unbag_ts(rsp, 10, &state->last_executed.ts);
unbag_ts(rsp, 13, &state->last_enqueued.ts);
unbag_ts(rsp, 16, &state->last_programmed.ts);
return 0;
}
/* bag_id(obuf + 7, &st->last_id);
bag_timestamp(obuf + 10, &st->last_executed);
bag_timestamp(obuf + 13, &st->last_enqueued);
bag_timestamp(obuf + 16, &st->last_programmed);
obuf[19] = st->idle;
obuf[20] = st->state;
obuf[21] = st->mode;
obuf[22] = st->flags;
obuf[23] = st->log_level;
obuf[24] = st->dead_time;
obuf[25] = st->width_cycles;
obuf[26] = st->worst_latency;*/
}
\ No newline at end of file
......@@ -6,6 +6,11 @@
#include "rt/common/list-common.h"
struct list_trigger_handle {
uint32_t ptr_cond;
uint32_t ptr_trig;
int channel;
};
struct list_input_state {
int input;
......@@ -25,6 +30,39 @@ struct list_input_state {
struct list_timestamp last;
};
struct list_trigger_handle handle;
struct list_output_trigger_state {
int is_conditional;
int enabled;
struct list_id trigger;
struct list_id condition;
struct list_timestamp delay_trig;
struct list_timestamp delay_cond;
struct list_trigger_handle handle;
};
struct list_output_state {
int output;
uint32_t executed_pulses;
uint32_t missed_pulses_late;
uint32_t missed_pulses_deadtime;
uint32_t missed_pulses_overflow;
struct list_trigger_entry last_executed;
struct list_trigger_entry last_programmed;
struct list_trigger_entry last_enqueued;
uint32_t flags; ///> enum list_io_flags
uint32_t log_level; ///> enum list_log_level
int mode;
uint32_t dead_time;
uint32_t pulse_width;
struct list_timestamp worst_rx_delay;
uint32_t total_rx_packets;
};
struct list_node;
//! Open a LIST node device.
......@@ -52,6 +90,8 @@ void list_close_node ( struct list_node *node );
\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_is_enabled(struct list_node *dev, int input);
/* 3.3.1b Get/set the Trigger/System/Source Port ID. Change the IDs during operation of the node. */
......@@ -121,24 +161,31 @@ int list_in_set_timebase_offset ( struct list_node *dev, int input, uint64_t off
int list_in_get_state ( struct list_node *, int input, struct list_input_state *state );
int list_in_reset_counters ( struct list_node *dev, int input );
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_trig_assign ( struct list_node *dev, struct list_trigger_handle *handle, int output, struct list_id *trig, struct list_id *condition );
int list_out_trig_remove (struct list_node *dev, struct list_trigger_handle *handle);
int list_out_trig_get_all (struct list_node *, int output, struct list_output_trigger_state *triggers, int max_count);
int list_out_trig_set_delay ( struct list_node *, struct list_trigger_handle *handle, uint64_t delay_ps );
int list_out_trig_set_condition_delay ( struct list_node *, struct list_trigger_handle *handle, uint64_t delay_ps );
int list_out_trig_get_state ( struct list_node *, struct list_trigger_handle *handle, struct list_output_trigger_state *state );
int list_out_trig_enable ( struct list_node *, struct list_trigger_handle *handle, int enable );
int list_out_read_log ( struct list_node*, struct list_log_entry *log, int flags, int output_mask, int count );
int list_out_set_log_level ( struct list_node *, int output, uint32_t log_level);
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_get_state ( struct list_node *node, int input, int armed );
int list_out_reset_counters ( struct list_node *dev, int output );
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 );
//int list_out_wait_trigger ( struct list_node*, int output_mask, struct list_id *id );
#endif
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*.
* LHC Instability Trigger Distribution (LIST) Firmware.
*
* list-common.h: common structures and definitions
*/
#ifndef __LIST_COMMON_H
#define __LIST_COMMON_H
......@@ -7,12 +23,14 @@
#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_CONTROL 1
#define TDC_OUT_SLOT_LOGGING 2
#define FD_OUT_SLOT_LOGGING 3
#define TDC_OUT_SLOT_REMOTE 0
#define FD_IN_SLOT_REMOTE 0
#endif
......@@ -26,7 +44,6 @@
#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
......@@ -35,14 +52,33 @@
#define ID_TDC_CMD_PING 0xc
#define ID_TDC_CMD_SOFTWARE_TRIGGER 0xd
#define ID_TDC_CMD_CHAN_SET_LOG_LEVEL 0xe
#define ID_TDC_CMD_CHAN_RESET_COUNTERS 0xf
#define ID_REP_ACK 0x100
#define ID_FD_CMD_CHAN_ENABLE 0x1
#define ID_FD_CMD_CHAN_ASSIGN_TRIGGER 0x2
#define ID_FD_CMD_READ_HASH 0x3
#define ID_FD_CMD_CHAN_REMOVE_TRIGGER 0x4
#define ID_FD_CMD_CHAN_GET_STATE 0x5
#define ID_FD_CMD_CHAN_SET_DELAY 0x6
#define ID_FD_CMD_CHAN_SET_WIDTH 0x7
#define ID_FD_CMD_CHAN_SET_MODE 0x8
#define ID_FD_CMD_SOFTWARE_TRIGGER 0x9
#define ID_FD_CMD_CHAN_ARM 0xa
#define ID_REP_ACK 0x100
#define ID_REP_STATE 0x101
#define ID_REP_NACK 0x102
#define ID_REP_TRIGGER_HANDLE 0x103
#define ID_REP_HASH_ENTRY 0x104
#define TDC_NUM_CHANNELS 5
#define TDC_TRIGGER_COALESCE_LIMIT 5
#define FD_NUM_CHANNELS 4
#define FD_HASH_ENTRIES 128
#define FD_MAX_QUEUE_PULSES 16
/*!..
* This enum is used by list_in_set_trigger_mode() and list_out_set_trigger_mode() to set input/output triggering mode.
*/
......@@ -69,10 +105,18 @@ enum list_log_level {
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_EXECUTED = (1 << 4), /*!< Output only: log all triggers executed on the output */
LIST_LOG_MISSED = (1 << 5), /*!< Output only: log all triggers missed by the output */
LIST_LOG_ALL = 0xff
};
#define HASH_ENT_EMPTY 0
#define HASH_ENT_DIRECT (1<<0)
#define HASH_ENT_CONDITION (1<<1)
#define HASH_ENT_CONDITIONAL (1<<2)
#define HASH_ENT_DISABLED (1<<3)
struct list_timestamp {
int32_t seconds;
int32_t cycles;
......@@ -92,6 +136,7 @@ struct list_trigger_entry {
uint32_t seq;
};
struct list_log_entry {
uint32_t type;
uint32_t seq;
......
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __PP_PRINTF_H
#define __PP_PRINTF_H
#include <stdarg.h>
#define CONFIG_PRINT_BUFSIZE 128
#define CONFIG_PRINT_BUFSIZE 128
extern int pp_printf(const char *fmt, ...)
__attribute__((format(printf,1,2)));
......@@ -16,4 +28,4 @@ extern int pp_vsprintf(char *buf, const char *, va_list)
/* This is what we rely on for output */
extern int puts(const char *s);
#endif
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*.
* White Rabbit Node Core
*
* rt-common.c: common RT CPU functions
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
......@@ -5,12 +20,19 @@
#include "rt-mqueue.h"
#include "rt-common.h"
static int debug_slot;
void rt_set_debug_slot(int slot)
{
debug_slot = slot;
}
int puts(const char *p)
{
int i;
volatile uint32_t *buf = mq_map_out_buffer(0, 1);
volatile uint32_t *buf = mq_map_out_buffer(0, debug_slot);
mq_claim(0, 1);
mq_claim(0, debug_slot);
buf[0] = 0xdeadbeef;
for(i=0;i<127;i++,p++)
......@@ -21,24 +43,7 @@ int puts(const char *p)
break;
}
mq_send(0, 1, i + 1);
mq_send(0, debug_slot, 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
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*.
* White Rabbit Node Core
*
* rt-common.h: common WRN CPU definitions and routines
*/
#ifndef __RT_COMMON_H
#define __RT_COMMON_H
......@@ -6,9 +22,14 @@
#include "hw/wrn_cpu_lr.h"
/* Dedicated Peripheral base */
#define CPU_DP_BASE 0x200000
/* CPU Local Registers base */
#define CPU_LR_BASE 0x100000
void rt_set_debug_slot(int slot);
static inline uint32_t dp_readl ( uint32_t reg )
{
return *(volatile uint32_t *) ( reg + CPU_DP_BASE );
......@@ -39,6 +60,7 @@ static inline void gpio_clear ( int pin )
lr_writel ( (1<<pin), WRN_CPU_LR_REG_GPIO_CLEAR );
}
/* fixme: use Timing Unit */
static inline void delay(int n)
{
int i;
......
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*.
* White Rabbit Node Core
*
* rt-mqueue.h: Message Queues definitions and functions
*/
#ifndef __RT_MQUEUE_H
#define __RT_MQUEUE_H
#define REG_LR_POLL 0x100000
/* MQ Base addresses */
#define HMQ_BASE 0x40010000
#define RMQ_BASE 0x40020000
#define MQ_GCR ( 0x0)
#define MQ_IN(slot) ( 0x4000 + (slot) * 0x400)
#define MQ_OUT(slot) ( 0x8000 + (slot) * 0x400)
/* MQ Slot offsets */
#define MQ_GCR (0x0)
#define MQ_IN(slot) (0x4000 + (slot) * 0x400)
#define MQ_OUT(slot) (0x8000 + (slot) * 0x400)
#define MQ_CMD_CLAIM (1<<24)
#define MQ_CMD_PURGE (1<<25)
#define MQ_CMD_READY (1<<26)
#define MQ_CMD_DISCARD (1<<27)
/* MQ Commands */
#define MQ_CMD_CLAIM (1 << 24)
#define MQ_CMD_PURGE (1 << 25)
#define MQ_CMD_READY (1 << 26)
#define MQ_CMD_DISCARD (1 << 27)
/* MQ Registers */
#define MQ_SLOT_COMMAND 0
#define MQ_SLOT_STATUS 4
#define MQ_SLOT_DATA_START 8
......
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*.
* White Rabbit Node Core
*
* rt.h: all common stuff in a single header
*/
#ifndef __WRN_RT_H
#define __WRN_RT_H
......
......@@ -16,8 +16,6 @@ $(OUTPUT): $(LDSCRIPT) $(OBJS)
${OBJCOPY} -O binary $(OUTPUT).elf $(OUTPUT).bin
${OBJDUMP} -S $(OUTPUT).elf > disasm.S
$(SIZE) $(OUTPUT).elf
# ../genramvhd -p wrc_simulation_firmware $(OUTPUT).bin > wrc_simulation_firmware_pkg.vhd
# ../common/genraminit $(OUTPUT).bin > $(OUTPUT).ram
clean:
rm -f $(OBJS) $(OUTPUT).bin
\ No newline at end of file
/*
* This work is part of the White Rabbit Node Core project.
*
* Copyright (C) 2013-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*
* LHC Instability Trigger Distribution (LIST) Firmware
*
* rt-tdc.c: real-time CPU application for the FMC TDC mezzanine (Trigger Input)
*/
#include <string.h>
#include "rt.h"
#include "list-common.h"
#include "hw/fmctdc-direct.h"
#define DEFAULT_DEAD_TIME (80000/16)
struct tdc_channel_state {
struct list_id id;
struct list_timestamp delay;
struct list_timestamp timebase_offset;
struct list_timestamp last;
struct list_timestamp prev;
struct list_trigger_entry last_sent;
uint32_t flags;
uint32_t log_level;
......@@ -19,8 +37,7 @@ struct tdc_channel_state {
int32_t sent_pulses;
uint32_t seq;
uint32_t dead_time;
int32_t worst_latency;
};
static struct tdc_channel_state channels[TDC_NUM_CHANNELS];
......@@ -104,6 +121,15 @@ static inline void do_channel (int channel, struct list_timestamp *ts)
ts_add(ts, &ch->delay);
int delta = ts->seconds - ch->prev.seconds;
delta *= 125000000;
delta += ts->cycles - ch->prev.cycles;
if(delta < 0)
pp_printf("FUCK!");
ch->prev = *ts;
if( (ch->flags & LIST_TRIGGER_ASSIGNED ) && (ch->flags & LIST_ARMED) )
{
ch->seq++;
......@@ -145,11 +171,13 @@ static inline void do_input ()
// convert from ACAM bins (81ps) to WR time format
ts.frac = ( (meta & 0x3ffff) * 5308 ) >> 7;
#if 0
if(ts.cycles >= 125000000) // fixme: fix in hw (Eva working on the issue)
{
ts.cycles -= 125000000;
ts.seconds --;
}
#endif
ts.cycles += ts.frac >> 12;
ts.frac &= 0xfff;
......@@ -203,9 +231,6 @@ static inline void ctl_chan_enable (int seq, uint32_t *buf)
dp_writel(mask, DR_REG_CHAN_ENABLE);
//pp_printf("enable ch %d mask %x", channel, mask);
ctl_ack(seq);
}
......@@ -341,8 +366,6 @@ static inline void ctl_chan_arm (int seq, uint32_t *buf)
struct tdc_channel_state *ch = &channels[channel];
//pp_printf("arm ch %d %d", channel, buf[1]);
if(buf[1]) {
ch->flags |= LIST_ARMED;
ch->flags &= ~LIST_TRIGGERED;
......@@ -368,7 +391,6 @@ static inline void ctl_chan_assign_trigger (int seq, uint32_t *buf)
ch->id.trigger = buf[4];
ch->flags |= LIST_TRIGGER_ASSIGNED;
ch->flags &= ~LIST_LAST_VALID;
//pp_printf("assign: ch %d en %d %d %d %d", channel, buf[1], buf[2], buf[3], buf[4]);
} else {
ch->id.system = 0;
ch->id.source_port = 0;
......@@ -379,6 +401,18 @@ static inline void ctl_chan_assign_trigger (int seq, uint32_t *buf)
ctl_ack(seq);
}
static inline void ctl_chan_reset_counters (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
ch->total_pulses = 0;
ch->sent_pulses = 0;
ch->flags &= ~LIST_LAST_VALID;
ctl_ack(seq);
}
static inline void ctl_chan_set_log_level (int seq, uint32_t *buf)
{
int channel = buf[0];
......@@ -412,9 +446,9 @@ static inline void do_control()
switch(cmd)
{
_CMD(ID_TDC_CMD_CHAN_ENABLE, ctl_chan_enable)
_CMD(ID_TDC_CMD_CHAN_SET_DEAD_TIME, ctl_chan_set_dead_time)
_CMD(ID_TDC_CMD_CHAN_SET_DELAY, ctl_chan_set_delay)
_CMD(ID_TDC_CMD_CHAN_ENABLE, ctl_chan_enable)
_CMD(ID_TDC_CMD_CHAN_SET_DEAD_TIME, ctl_chan_set_dead_time)
_CMD(ID_TDC_CMD_CHAN_SET_DELAY, ctl_chan_set_delay)
_CMD(ID_TDC_CMD_CHAN_SET_TIMEBASE_OFFSET, ctl_chan_set_timebase_offset)
_CMD(ID_TDC_CMD_CHAN_GET_STATE, ctl_chan_get_state)
_CMD(ID_TDC_CMD_SOFTWARE_TRIGGER, ctl_software_trigger)
......@@ -423,6 +457,7 @@ static inline void do_control()
_CMD(ID_TDC_CMD_CHAN_ARM, ctl_chan_arm)
_CMD(ID_TDC_CMD_CHAN_SET_SEQ, ctl_chan_set_seq)
_CMD(ID_TDC_CMD_CHAN_SET_LOG_LEVEL, ctl_chan_set_log_level)
_CMD(ID_TDC_CMD_CHAN_RESET_COUNTERS, ctl_chan_reset_counters)
_CMD(ID_TDC_CMD_PING, ctl_ping)
default:
break;
......@@ -436,12 +471,14 @@ void init()
int i;
dp_writel( 0x0, DR_REG_CHAN_ENABLE);
dp_writel( 0x1, DR_REG_DEAD_TIME);
dp_writel( DEFAULT_DEAD_TIME, DR_REG_DEAD_TIME);
for(i=0;i<TDC_NUM_CHANNELS;i++)
{
memset(&channels[i], 0, sizeof(struct tdc_channel_state));
channels[i].n = i;
channels[i].mode = LIST_TRIGGER_MODE_AUTO;
channels[i].dead_time = DEFAULT_DEAD_TIME;
}
}
......@@ -449,6 +486,7 @@ void init()
main()
{
int i = 0;
rt_set_debug_slot(TDC_OUT_SLOT_CONTROL);
init();
pp_printf("RT_TDC firmware initialized.");
......
......@@ -153,9 +153,7 @@ main()
struct list_id trig = { 10, 20, 30 };
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;
......
......@@ -15,6 +15,8 @@
#include "wrn-lib.h"
#include "wrn-lib-private.h"
#define DBG(...)
#define MAX_MQUEUE_SLOTS 16
#define BASE_HMQ 0x00000
......@@ -78,7 +80,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);
DBG("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 +88,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);
DBG(" - out%d: width=%d, entries=%d\n", i, width, entries);
}
for(i =0 ; i<n_in; i++)
{
......@@ -94,7 +96,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_IN(i), MQUEUE_CMD_PURGE, MQUEUE_SLOT_COMMAND);
printf(" - in%d: width=%d, entries=%d\n", i, width, entries);
DBG(" - in%d: width=%d, entries=%d\n", i, width, entries);
}
return 0;
}
......@@ -104,14 +106,14 @@ int init_cpus(struct wrn_dev *dev)
// 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);
//DBG("init_cpus: %d CPU CBs\n", dev->cpu_count);
int i;
for(i=0;i<dev->cpu_count;i++)
{
uint32_t memsize;
wrn_writel(dev, i, BASE_CPU_CSR + WRN_CPU_CSR_REG_CORE_SEL);
memsize = wrn_readl(dev, BASE_CPU_CSR + WRN_CPU_CSR_REG_CORE_MEMSIZE);
//printf("- core %d: %d kB private memory\n", i, memsize/1024);
//DBG("- core %d: %d kB private memory\n", i, memsize/1024);
}
return 0;
}
......@@ -129,7 +131,7 @@ struct wrn_dev* wrn_open_by_lun( int lun )
dev->fmc = fmc_svec_create(lun);
dev->app_id = wrn_readl( dev, BASE_CPU_CSR + WRN_CPU_CSR_REG_APP_ID );
printf("wrn_open: application ID = 0x%08x\n", dev->app_id);
DBG("wrn_open: application ID = 0x%08x\n", dev->app_id);
init_cpus( dev );
init_hmq ( dev );
......@@ -154,9 +156,9 @@ int wrn_cpu_count( struct wrn_dev* dev)
int wrn_cpu_stop ( struct wrn_dev* dev, uint32_t mask )
{
uint32_t r = wrn_readl(dev, BASE_CPU_CSR + WRN_CPU_CSR_REG_RESET );
//printf("cpu_stop: r %x mask %x csrbase %x\n", r, mask, BASE_CPU_CSR +WRN_CPU_CSR_REG_RESET);
//DBG("cpu_stop: r %x mask %x csrbase %x\n", r, mask, BASE_CPU_CSR +WRN_CPU_CSR_REG_RESET);
r |= mask;
//printf("cpu_stop: r %x \n", r);
//DBG("cpu_stop: r %x \n", r);
wrn_writel(dev, r, BASE_CPU_CSR + WRN_CPU_CSR_REG_RESET );
return 0;
}
......@@ -164,9 +166,9 @@ int wrn_cpu_stop ( struct wrn_dev* dev, uint32_t mask )
int wrn_cpu_start ( struct wrn_dev * dev, uint32_t mask )
{
uint32_t r = wrn_readl(dev, BASE_CPU_CSR + WRN_CPU_CSR_REG_RESET );
//printf("cpu_stop: r %x mask %x csrbase %x\n", r, mask, BASE_CPU_CSR +WRN_CPU_CSR_REG_RESET);
//DBG("cpu_stop: r %x mask %x csrbase %x\n", r, mask, BASE_CPU_CSR +WRN_CPU_CSR_REG_RESET);
r &= ~mask;
//printf("cpu_start: r %x \n", r);
//DBG("cpu_start: r %x \n", r);
wrn_writel(dev, r, BASE_CPU_CSR + WRN_CPU_CSR_REG_RESET );
return 0;
}
......@@ -185,7 +187,7 @@ int wrn_cpu_load_application ( struct wrn_dev *dev, int cpu, const void *code, s
wrn_writel(dev, cpu, BASE_CPU_CSR + WRN_CPU_CSR_REG_CORE_SEL );
printf("CPU%d: loading %d bytes of LM32 code\n", cpu, code_size);
DBG("CPU%d: loading %d bytes of LM32 code\n", cpu, code_size);
uint32_t *code_c = (uint32_t *)code;
......@@ -211,14 +213,14 @@ int wrn_cpu_load_application ( struct wrn_dev *dev, int cpu, const void *code, s
word_rdbk = wrn_readl(dev, BASE_CPU_CSR + WRN_CPU_CSR_REG_UDATA) ;
if(word_rdbk != word)
{
printf("verify error: addr %x %x != %x\n", i, word_rdbk, word);
DBG("verify error: addr %x %x != %x\n", i, word_rdbk, word);
errors++;
}
}
if(errors)
{
printf("Encountered %d verification errors: errors\n");
DBG("Encountered %d verification errors: errors\n");
exit(-1);
}
// wrn_cpu_start(dev, (1<<cpu));
......@@ -267,10 +269,10 @@ 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);
/*DBG("gcr %x\n", in_stat);
if(in_stat & 1)
{
printf("Got!\n");
DBG("Got!\n");
}*/
if(in_stat & SLOT_OUT_MASK)
{
......@@ -289,7 +291,7 @@ static bool do_rx(struct wrn_dev *dev, wrn_message& msg, int& slot)
{
uint32_t rv = hmq_readl(dev, HMQ_OUT(i), MQUEUE_SLOT_DATA_START + j * 4);
msg.push_back(rv);
//printf("rv %x %x %c\n", MQUEUE_SLOT_DATA_START + j * 4, rv, (char) rv );
//DBG("rv %x %x %c\n", MQUEUE_SLOT_DATA_START + j * 4, rv, (char) rv );
}
slot = i;
hmq_writel(dev, HMQ_OUT(i), MQUEUE_CMD_DISCARD, MQUEUE_SLOT_COMMAND);
......@@ -323,12 +325,12 @@ bool tx_ready(struct wrn_dev *dev, int slot)
void do_tx(struct wrn_dev *dev, const wrn_message& msg, int slot )
{
//printf("do_tx: slot %d size %d\n", slot, msg.size());
// DBG("do_tx: slot %d size %d\n", slot, msg.size());
hmq_writel(dev, HMQ_IN(slot), MQUEUE_CMD_CLAIM, MQUEUE_SLOT_COMMAND);
for(int i=0;i<msg.size();i++)
{
//printf("%d: %x\n", i, msg[i]);
// DBG("%d: %x\n", i, msg[i]);
hmq_writel(dev, HMQ_IN(slot), msg[i], MQUEUE_SLOT_DATA_START + i * 4);
}
hmq_writel(dev, HMQ_IN(slot), MQUEUE_CMD_READY, MQUEUE_SLOT_COMMAND);
......@@ -345,19 +347,19 @@ int update_mqueues( struct wrn_dev * dev )
// outgoing path (from CPUs)
while(do_rx (dev, msg, slot) && rx_limit)
{
// printf("RxLim %d\n", rx_limit);
// DBG("RxLim %d\n", rx_limit);
rx_limit--;
got_sth = 1;
//printf("slot %d rx %d words\n", slot, msg.size());
//DBG("slot %d rx %d words\n", slot, msg.size());
for (wrn_connmap::iterator i = dev->fds.begin(); i != dev->fds.end(); ++i)
{
wrn_buffer *buf = i->second->out;
if( buf && buf->slot == slot)
{
// printf("-> queue to fd %d\n", i->first);
// DBG("-> queue to fd %d\n", i->first);
buf->lock( true );
//printf("locked\n");
//DBG("locked\n");
buf->process(msg);
buf->unlock();
......@@ -375,7 +377,7 @@ int update_mqueues( struct wrn_dev * dev )
{
buf->lock(true);
got_sth = 1;
// printf("DoTX\n");
// DBG("DoTX\n");
do_tx(dev, buf->pop(), buf->slot);
buf->unlock();
}
......@@ -433,7 +435,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);
DBG("open slot %d, fd = %d\n", slot, fd);
return fd;
}
......@@ -468,7 +470,7 @@ int wrn_recv ( struct wrn_dev *dev, int fd, uint32_t *buffer, size_t buf_size, i
if(timeout_us >= 0 && (get_tics() - t_start) >= timeout_us )
return 0;
//fprintf(stderr,"w");
//fDBG(stderr,"w");
usleep(1);
}
......@@ -506,7 +508,7 @@ void *update_thread_entry( void *data )
{
wrn_dev *dev = (wrn_dev *) data;
// fprintf(stderr,"readout thread started\n");
// DBG(stderr,"readout thread started\n");
for(;;)
{
if( !update_mqueues(dev) );
......
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