Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit Trigger Distribution
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
White Rabbit Trigger Distribution
Commits
d5868bff
Commit
d5868bff
authored
Dec 12, 2018
by
Tristan Gingold
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial version of adc firmware.
parent
71424729
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
590 additions
and
0 deletions
+590
-0
Kconfig
software/firmware/adc/Kconfig
+6
-0
Makefile
software/firmware/adc/Makefile
+21
-0
mt_defconfig
software/firmware/adc/configs/mt_defconfig
+34
-0
out_queue.h
software/firmware/adc/out_queue.h
+121
-0
wrtd-adcin.c
software/firmware/adc/wrtd-adcin.c
+199
-0
wrtd-adcout.c
software/firmware/adc/wrtd-adcout.c
+99
-0
wrtd-rt-adcout.c
software/firmware/adc/wrtd-rt-adcout.c
+110
-0
No files found.
software/firmware/adc/Kconfig
0 → 100644
View file @
d5868bff
mainmenu "WRTD ADC firmware configuration"
comment "Project specific configuration"
# include Mock Turtle's Kconfig
source "Kconfig.mt"
software/firmware/adc/Makefile
0 → 100644
View file @
d5868bff
-include
Makefile.specific
OBJS
:=
wrtd-rt-adcout.o
OUTPUT
=
wrtd-rt-adcout
TRTL
?=
../../../dependencies/mock-turtle/
TRTL_SW
=
$(TRTL)
/software
EXTRA2_CFLAGS
=
# To be set by user on make line
EXTRA_CFLAGS
+=
-I
../../include
-I
../common
\
-I
../../../dependencies/fmc-adc-100m14b4cha-gw/hdl/rtl/wb_gen/
\
-Werror
$(EXTRA2_CFLAGS)
vpath
%.c
../
MEM_INIT_GEN
=
../../../dependencies/general-cores/tools/mem_init_gen.py
$(OUTPUT).bram
:
$(OUTPUT).bin
python
$(MEM_INIT_GEN)
-i
$<
>
$@
include
$(TRTL_SW)/firmware/Makefile
software/firmware/adc/configs/mt_defconfig
0 → 100644
View file @
d5868bff
#
# Automatically generated file; DO NOT EDIT.
# fmc-svec-carrier fw-01 demo configuration
#
#
# Project specific configuration
#
#
# Mock Turtle configuration
#
CONFIG_FPGA_APPLICATION_ID=0
CONFIG_RT_APPLICATION_ID=0
CONFIG_CFLAGS_OPT="-Os"
CONFIG_CFLAGS_EXTRA="-ggdb"
#
# Mock Turtle framework configuration
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
#
# Mock Turtle library configuration
#
CONFIG_MOCKTURTLE_LIBRARY_PRINT_ENABLE=y
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_DEBUG_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_ERROR_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_MESSAGE_ENABLE is not set
software/firmware/adc/out_queue.h
0 → 100644
View file @
d5868bff
/* Generic output queue.
User needs to define:
OUT_QUEUE_PREFIX: the prefix (ends with an '_')
OUT_QUEUE_SIZE: max length of the queue
OUT_QUEUE_MAXTIME: maximum time in advance.
*/
#define OUT_QUEUE_NAME(x) OUT_QUEUE_PREFIX##x
#define OUT_QUEUE_STRUCT OUT_QUEUE_NAME(out_queue)
struct
OUT_QUEUE_STRUCT
{
struct
wrtd_event
events
[
OUT_QUEUE_SIZE
];
int
head
,
tail
,
count
;
/* Last timestamp value written to output config. */
uint32_t
last_programmed_sec
;
uint32_t
last_programmed_ns
;
};
/**
* Initializes an empty pulse queue
*/
static
void
OUT_QUEUE_NAME
(
out_queue_init
)(
struct
OUT_QUEUE_STRUCT
*
p
)
{
p
->
head
=
0
;
p
->
tail
=
0
;
p
->
count
=
0
;
p
->
last_programmed_sec
=
0
;
p
->
last_programmed_ns
=
0
;
}
/**
* Requests a new entry in a pulse queue. Returns pointer to the ne
* entry or NULL if the queue is full.
*/
static
struct
wrtd_event
*
OUT_QUEUE_NAME
(
out_queue_push
)(
struct
OUT_QUEUE_STRUCT
*
p
)
{
struct
wrtd_event
*
ev
;
if
(
p
->
count
==
OUT_QUEUE_SIZE
)
return
NULL
;
ev
=
&
p
->
events
[
p
->
head
];
p
->
count
++
;
p
->
head
++
;
if
(
p
->
head
==
OUT_QUEUE_SIZE
)
p
->
head
=
0
;
return
ev
;
}
/**
* Returns non-0 if pulse queue p contains any pulses.
*/
static
inline
int
OUT_QUEUE_NAME
(
out_queue_empty
)(
struct
OUT_QUEUE_STRUCT
*
p
)
{
return
(
p
->
count
==
0
);
}
/**
* Returns the oldest entry in the pulse queue (or NULL if empty).
*/
static
struct
wrtd_event
*
OUT_QUEUE_NAME
(
out_queue_front
)(
struct
OUT_QUEUE_STRUCT
*
p
)
{
if
(
!
p
->
count
)
return
NULL
;
return
&
p
->
events
[
p
->
tail
];
}
/**
* Releases the oldest entry from the pulse queue.
*/
static
void
OUT_QUEUE_NAME
(
out_queue_pop
)(
struct
OUT_QUEUE_STRUCT
*
p
)
{
p
->
tail
++
;
if
(
p
->
tail
==
OUT_QUEUE_SIZE
)
p
->
tail
=
0
;
p
->
count
--
;
}
/**
* Checks if the timestamp of the last programmed pulse is lost because
* of timeout
*/
static
int
OUT_QUEUE_NAME
(
out_queue_check_timeout
)
(
struct
OUT_QUEUE_STRUCT
*
q
)
{
uint32_t
now_sec
;
uint32_t
now_ns
;
int
delta
;
/*
* Read the current WR time, order is important: first seconds,
* then cycles (cycles get latched on reading secs register.
*/
now_sec
=
lr_readl
(
MT_CPU_LR_REG_TAI_SEC
);
now_ns
=
lr_readl
(
MT_CPU_LR_REG_TAI_CYCLES
)
*
8
;
if
(
q
->
last_programmed_sec
>
now_sec
+
OUT_QUEUE_MAXTIME
)
{
pr_error
(
"Enqueued event very far in the future. Dropping."
);
return
0
;
}
/* Current time exceeds FD setpoint? */
delta
=
now_sec
-
q
->
last_programmed_sec
;
if
(
delta
!=
0
)
return
delta
>
0
;
delta
=
now_ns
-
q
->
last_programmed_ns
;
return
(
delta
>
0
);
}
#undef OUT_QUEUE_STRUCT
#undef OUT_QUEUE_NAME
software/firmware/adc/wrtd-adcin.c
0 → 100644
View file @
d5868bff
/*
* Copyright (C) 2013-2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <errno.h>
#include <string.h>
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#define OUT_QUEUE_MAXTIME 10
#define OUT_QUEUE_PREFIX adcin_
#define OUT_QUEUE_SIZE 4
#include "out_queue.h"
struct
wrtd_adcin_dev
{
uint32_t
io_addr
;
adcin_out_queue
queue
;
};
static
inline
int
adcin_wr_present
(
struct
wrtd_adcin_dev
*
fd
)
{
return
1
;
}
static
inline
int
adcin_wr_link_up
(
struct
wrtd_adcin_dev
*
fd
)
{
return
1
;
}
static
inline
int
adcin_wr_time_locked
(
struct
wrtd_adcin_dev
*
fd
)
{
return
1
;
}
static
inline
int
adcin_wr_time_ready
(
struct
wrtd_adcin_dev
*
fd
)
{
return
1
;
}
static
inline
int
adcin_wr_sync_timeout
(
void
)
{
return
0
;
}
static
void
adcin_wr_enable_lock
(
struct
wrtd_adcin_dev
*
fd
,
int
enable
)
{
return
;
}
static
inline
void
adcin_writel
(
struct
wrtd_adcin_dev
*
dev
,
uint32_t
value
,
uint32_t
reg
)
{
dp_writel
(
value
,
dev
->
io_addr
+
reg
);
}
static
inline
uint32_t
adcin_readl
(
struct
wrtd_adcin
*
dev
,
uint32_t
reg
)
{
return
dp_readl
(
dev
->
io_addr
+
reg
);
}
/**
* Drop the given enqueued trigger
*/
static
void
drop_trigger
(
struct
wrtd_fd_channel
*
out
,
struct
wrtd_event
*
ev
,
struct
lrt_pulse_queue
*
q
,
unsigned
reason
)
{
out
->
idle
=
1
;
if
(
pulse_queue_empty
(
q
))
return
;
/* Drop the pulse */
pulse_queue_pop
(
q
);
/* Disarm the FD output */
fd_ch_writel
(
out
,
FD_DCR_MODE
,
FD_REG_DCR
);
wrtd_log
(
WRTD_LOG_MSG_EV_DISCARDED
,
reason
,
ev
,
NULL
);
}
/**
* Output driving function. Reads pulses from the output queue,
* programs the output and updates the output statistics.
*/
static
void
adcin_output
(
struct
wrtd_adcin_dev
*
dev
)
{
struct
adcin_out_queue
*
q
=
&
dev
->
queue
;
struct
wrtd_event
*
ev
=
adcin_out_queue_front
(
q
);
uint32_t
ctrl
=
adcin_readl
(
dev
,
ALT_TRIGIN_CTRL
);
struct
wrtd_tstamp
*
ts
;
/* Check if the output has triggered */
if
(
!
dev
->
idle
)
{
#if 0
if (!wr_is_timing_ok()) {
/* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
#endif
if
(
ctrl
&
ALT_TRIGIN_CTRL_ENABLE
)
{
/* Armed but still waiting for trigger */
if
(
check_output_timeout
(
dev
))
{
/* Will never trigger. Missed. */
drop_trigger
(
dev
,
ev
,
q
,
WRTD_LOG_DISCARD_TIMEOUT
);
}
}
else
{
/* Has been triggered. */
wrtd_log
(
WRTD_LOG_MSG_EV_CONSUMED
,
WRTD_LOG_CONSUMED_DONE
,
ev
,
NULL
);
adcin_out_queue_pop
(
q
);
dev
->
idle
=
1
;
}
return
;
}
/* Output is idle: check if there's something in the queue to execute */
if
(
adcin_out_queue_empty
(
q
))
return
;
ev
=
pulse_queue_front
(
q
);
ts
=
&
ev
->
ts
;
if
(
!
wr_is_timing_ok
())
{
drop_trigger
(
out
,
ev
,
q
,
WRTD_LOG_DISCARD_NO_SYNC
);
return
;
}
/* Program the output start time */
adcin_writel
(
dev
,
ts
->
seconds
,
ALT_TRIGIN_SECONDS
+
0
);
adcin_writel
(
dev
,
ts
->
ns
/
8
,
ALT_TRIGIN_CYCLES
);
adcin_writel
(
dev
,
ALT_TRIGIN_CTRL_ENABLE
,
ALT_TRIGIN_CTRL
);
wrtd_log
(
WRTD_LOG_MSG_EV_CONSUMED
,
WRTD_LOG_CONSUMED_START
,
ev
,
NULL
);
ts_add2_ns
(
ts
,
8000
);
/*
* Store the last programmed timestamp (+ some margin) and mark
* the output as busy
*/
q
->
last_programmed_sec
=
ts
->
seconds
;
q
->
last_programmed_ns
=
ts
->
ns
;
dev
->
idle
=
0
;
}
static
void
fd_local_output
(
struct
wrtd_fd_dev
*
fd
,
struct
wrtd_event
*
ev
,
unsigned
ch
)
{
struct
wrtd_fd_channel
*
out
=
&
fd
->
channels
[
ch
];
struct
wrtd_event
*
pq_ev
;
pq_ev
=
pulse_queue_push
(
&
out
->
queue
);
if
(
!
pq_ev
)
{
/* overflow.
FIXME: stats ? */
wrtd_log
(
WRTD_LOG_MSG_EV_DISCARDED
,
WRTD_LOG_DISCARD_OVERFLOW
,
ev
,
NULL
);
return
;
}
*
pq_ev
=
*
ev
;
}
#if 0
/**
* It disable the given channel and clear its internal queue
*/
static int wrtd_out_disable(struct trtl_fw_msg *msg_i,
struct trtl_fw_msg *msg_o)
{
uint32_t ch = ((uint32_t *)msg_i->payload)[0];
pulse_queue_init(&wrtd_out_channels[ch].queue);
fd_ch_writel(&wrtd_out_channels[ch], FD_DCR_MODE, FD_REG_DCR);
msg_o->header->msg_id = msg_i->header->msg_id;
return 0;
}
#endif
static
void
wrtd_adcin_data_init
(
struct
wrtd_adcin_dev
*
dev
)
{
adcin_out_queue_init
(
&
fd
->
channels
[
i
].
queue
);
adcin
->
idle
=
1
;
}
software/firmware/adc/wrtd-adcout.c
0 → 100644
View file @
d5868bff
/*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "mockturtle-rt.h"
#define ADCOUT_NUM_CHANNELS 5
struct
wrtd_adcout_dev
{
uint32_t
io_addr
;
/* FIXME: base channel (to create the event id). */
};
static
inline
void
adcout_writel
(
const
struct
wrtd_adcout_dev
*
dev
,
uint32_t
value
,
uint32_t
reg
)
{
dp_writel
(
value
,
dev
->
io_addr
+
reg
);
}
static
inline
uint32_t
adcout_readl
(
const
struct
wrtd_adcout_dev
*
dev
,
uint32_t
reg
)
{
return
dp_readl
(
dev
->
io_addr
+
reg
);
}
static
int
adcout_init
(
struct
wrtd_adcout_dev
*
adcout
)
{
pr_debug
(
"%s: ADCout initialization complete
\n\r
"
,
__func__
);
/* Disable all channels. */
adcout_writel
(
adcout
,
0
,
ALT_TRIGOUT_CTRL
);
return
0
;
}
static
inline
int
adcout_wr_link_up
(
struct
wrtd_adcout_dev
*
adcout
)
{
return
adcout_readl
(
adcout
,
ALT_TRIGOUT_STATUS
)
&
ALT_TRIGOUT_WR_LINK
;
}
static
inline
int
adcout_wr_time_locked
(
struct
wrtd_adcout_dev
*
adcout
)
{
return
1
;
}
static
inline
int
adcout_wr_time_ready
(
struct
wrtd_adcout_dev
*
adcout
)
{
return
adcout_readl
(
adcout
,
ALT_TRIGOUT_STATUS
)
&
ALT_TRIGOUT_WR_VALID
;
}
static
inline
int
adcout_wr_sync_timeout
(
void
)
{
return
0
;
}
/**
* Handles input timestamps from all TDC channels.
*
* TODO: tdc config: base address
* first channel number (for sid)
* time offset
*/
static
void
adcout_input
(
struct
wrtd_adcout_dev
*
adcout
)
{
uint32_t
status
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_STATUS
);
uint32_t
mask
;
struct
wrtd_event
ev
;
int
i
;
/* Poll the FIFO and read the timestamp */
if
(
!
(
status
&
ALT_TRIGOUT_TS_PRESENT
))
return
;
/* FIXME: MSB word ? */
ev
.
ts
.
seconds
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_TS_MASK_SEC
+
0
);
mask
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_TS_MASK_SEC
+
4
);
ev
.
ts
.
ns
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_TS_CYCLES
)
*
8
;
ev
.
ts
.
frac
=
0
;
for
(
i
=
0
;
i
<
ADCOUT_NUM_CHANNELS
;
i
++
)
{
if
(
!
(
mask
&
((
ALT_TRIGOUT_CH1_MASK
>>
32
)
<<
i
)))
continue
;
memset
(
ev
.
id
,
0
,
WRTD_ID_LEN
);
ev
.
id
[
0
]
=
'A'
;
ev
.
id
[
1
]
=
'D'
;
ev
.
id
[
2
]
=
'C'
;
ev
.
id
[
3
]
=
'O'
;
ev
.
id
[
4
]
=
'1'
+
i
;
ev
.
flags
=
0
;
wrtd_log
(
WRTD_LOG_MSG_EV_GENERATED
,
WRTD_LOG_GENERATED_DEVICE
+
i
,
&
ev
,
NULL
);
/* Pass to wrtd. */
wrtd_route_in
(
&
ev
);
}
}
software/firmware/adc/wrtd-rt-adcout.c
0 → 100644
View file @
d5868bff
/*
* Copyright (C) 2013-2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigout.h"
#define NBR_CPUS 1
#define CPU_IDX 0
#define NBR_LOCAL_INPUTS 5
#define NBR_LOCAL_OUTPUTS 0
#define NBR_RULES 16
#define NBR_DEVICES 1
#define NBR_ALARMS 0
#define DEVICES_IO_ADDR { TRTL_ADDR_DP_BASE + 0x0000, 0, 0, 0}
#define APP_ID WRTD_APP_ADCIN_5CH
#define APP_VER RT_VERSION(2, 0)
#define APP_NAME "wrtd-adcin"
#define WRTD_NET_TX
#include "wrtd-rt-common.h"
#include "wrtd-adcout.c"
static
struct
wrtd_adcout_dev
adcout0
=
{
.
io_addr
=
0x0
,
};
static
inline
int
wr_link_up
(
void
)
{
return
adcout_wr_link_up
(
&
adcout0
);
}
static
inline
int
wr_time_locked
(
void
)
{
return
adcout_wr_time_locked
(
&
adcout0
);
}
static
inline
int
wr_time_ready
(
void
)
{
return
adcout_wr_time_ready
(
&
adcout0
);
}
static
inline
void
wr_enable_lock
(
int
enable
)
{
}
static
inline
int
wr_sync_timeout
(
void
)
{
return
0
;
}
static
void
wrtd_local_output
(
struct
wrtd_event
*
ev
,
unsigned
ch
)
{
/* No output. */
return
;
}
#ifdef SIMULATION
static
int
wrtd_i_sim_init
(
struct
wrtd_tdc_dev
*
tdc
)
{
/* TODO: preconfigure the rules. */
int
i
;
for
(
i
=
0
;
i
<
TDC_NUM_CHANNELS
;
i
++
)
{
wrtd_in_channels
[
i
].
config
.
log_level
=
WRTD_LOG_ALL
;
wrtd_in_channels
[
i
].
config
.
id
.
system
=
0
;
wrtd_in_channels
[
i
].
config
.
id
.
source_port
=
i
;
wrtd_in_channels
[
i
].
config
.
id
.
trigger
=
i
;
wrtd_in_channels
[
i
].
config
.
flags
=
WRTD_ENABLED
|
WRTD_ARMED
|
WRTD_TRIGGER_ASSIGNED
;
}
tdc_writel
(
tdc
,
0x40
,
BASE_DP_TDC_DIRECT
+
DR_REG_DEAD_TIME
);
tdc_writel
(
tdc
,
0x1f
,
BASE_DP_TDC_DIRECT
+
DR_REG_CHAN_ENABLE
);
return
0
;
}
#endif
static
int
wrtd_user_init
(
void
)
{
#ifdef SIMULATION
/* Skip WR sync and automatically generate some events when
simulating */
wrtd_i_sim_init
(
&
tdc0
);
#else
adcout_init
(
&
adcout0
);
#endif
wr_enable_lock
(
0
);
pr_debug
(
"rt-input firmware initialized.
\n\r
"
);
return
0
;
}
static
void
wrtd_io
(
void
)
{
adcout_input
(
&
adcout0
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment