Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit core collection
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
30
Issues
30
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Schedules
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 core collection
Commits
e0e3a728
Commit
e0e3a728
authored
May 12, 2014
by
Wesley W. Terpstra
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev-eca-software-queue-control' into HEAD
Tested with modelsim and quartus.
parents
5c33a4d4
a369cba9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
624 additions
and
127 deletions
+624
-127
Makefile
modules/wr_eca/Makefile
+2
-2
eca-ctl.cpp
modules/wr_eca/eca-ctl.cpp
+216
-29
eca.h
modules/wr_eca/eca.h
+58
-2
eca.vhd
modules/wr_eca/eca.vhd
+2
-0
eca_channel.vhd
modules/wr_eca/eca_channel.vhd
+6
-0
eca_pkg.vhd
modules/wr_eca/eca_pkg.vhd
+6
-2
eca_queue_channel.vhd
modules/wr_eca/eca_queue_channel.vhd
+7
-4
eca_walker.vhd
modules/wr_eca/eca_walker.vhd
+2
-0
hw-channel.cpp
modules/wr_eca/lib/hw-channel.cpp
+37
-39
hw-eca.h
modules/wr_eca/lib/hw-eca.h
+49
-30
hw-queue.cpp
modules/wr_eca/lib/hw-queue.cpp
+168
-0
probe-eca.cpp
modules/wr_eca/lib/probe-eca.cpp
+71
-19
No files found.
modules/wr_eca/Makefile
View file @
e0e3a728
...
...
@@ -2,7 +2,7 @@ PREFIX ?= /usr/local
STAGING
?=
EB
?=
no
ifeq
($(EB),no)
)
ifeq
($(EB),no)
EB_LIB
?=
-letherbone
EB_INC
?=
else
...
...
@@ -33,7 +33,7 @@ eca-ctl: eca-ctl.o libeca.a
eca-table
:
eca-table.o libeca.a
$(CXX)
$(CXXFLAGS)
-o
$@
$^
-Wl
,-rpath,
$(PREFIX)
/lib
$(EB_LIB)
libeca.a
:
lib/hw-eca.o lib/hw-stream.o lib/hw-channel.o
\
libeca.a
:
lib/hw-eca.o lib/hw-stream.o lib/hw-channel.o
lib/hw-queue.o
\
lib/load-table.o lib/store-table.o
\
lib/table.o lib/probe-eca.o
rm
-f
$@
...
...
modules/wr_eca/eca-ctl.cpp
View file @
e0e3a728
This diff is collapsed.
Click to expand it.
modules/wr_eca/eca.h
View file @
e0e3a728
...
...
@@ -28,6 +28,7 @@
#include <etherbone.h>
#include <string>
#include <vector>
#include <list>
namespace
GSI_ECA
{
...
...
@@ -52,6 +53,12 @@ struct EventEntry {
:
event
(
e
),
param
(
p
),
tef
(
t
),
time
(
i
)
{
}
};
enum
ActionStatus
{
VALID
=
0
,
CONFLICT
,
LATE
};
/* An action queued to be executed has these fields */
struct
ActionEntry
{
Event
event
;
...
...
@@ -59,9 +66,10 @@ struct ActionEntry {
Tag
tag
;
Tef
tef
;
Time
time
;
ActionStatus
status
;
ActionEntry
(
Event
e
=
0
,
Param
p
=
0
,
Tag
a
=
0
,
Tef
t
=
0
,
Time
i
=
0
)
:
event
(
e
),
param
(
p
),
tag
(
a
),
tef
(
t
),
time
(
i
)
{
}
ActionEntry
(
Event
e
=
0
,
Param
p
=
0
,
Tag
a
=
0
,
Tef
t
=
0
,
Time
i
=
0
,
ActionStatus
s
=
VALID
)
:
event
(
e
),
param
(
p
),
tag
(
a
),
tef
(
t
),
time
(
i
)
,
status
(
s
)
{
}
};
/* Software condition table entry fields */
...
...
@@ -100,6 +108,52 @@ class Table {
friend
struct
ECA
;
};
/* ======================================================================= */
/* Software interface to hardware action queues */
/* ======================================================================= */
struct
ActionQueue
{
/* ------------------------------------------------------------------- */
/* Constant hardware values */
/* ------------------------------------------------------------------- */
uint8_t
sdb_ver_major
;
uint8_t
sdb_ver_minor
;
uint32_t
sdb_version
;
uint32_t
sdb_date
;
std
::
string
sdb_name
;
uint16_t
queue_size
;
/* ------------------------------------------------------------------- */
/* Mutable hardware registers; only modify using methods below */
/* ------------------------------------------------------------------- */
bool
arrival_enable
;
/* Enable arrival interrupt delivery */
uint32_t
arrival_dest
;
/* Destination for arrival interrupt */
bool
overflow_enable
;
/* Enable overflow interrupt delivery */
uint32_t
overflow_dest
;
/* Destination for overflow interrupt */
uint32_t
queued_actions
;
/* # of actions queued to be read */
uint32_t
dropped_actions
;
/* # of actions dropped due to overflow */
/* ------------------------------------------------------------------- */
/* Access/modify the underlying hardware */
/* ------------------------------------------------------------------- */
Device
device
;
/* Device which hosts this ECA */
eb_address_t
address
;
/* Wishbone base address */
/* Reload mutable registers from hardware */
status_t
refresh
();
/* Clear all dropped counter */
status_t
reset
();
/* Hook/unhook interrupt handling */
status_t
hook_arrival
(
bool
enable
,
uint32_t
dest
);
status_t
hook_overflow
(
bool
enable
,
uint32_t
dest
);
/* Pop the next queued action from the queue */
status_t
pop
(
ActionEntry
&
queue
);
};
/* ======================================================================= */
/* Software interface to hardware action channels */
/* ======================================================================= */
...
...
@@ -110,6 +164,8 @@ struct ActionChannel {
std
::
string
name
;
/* Channel instance name */
unsigned
queue_size
;
/* Size of the inspectable queue */
std
::
list
<
ActionQueue
>
queue
;
/* Only present if an AQ is connected */
/* ------------------------------------------------------------------- */
/* Mutable hardware registers; only modify using methods below */
/* ------------------------------------------------------------------- */
...
...
modules/wr_eca/eca.vhd
View file @
e0e3a728
...
...
@@ -851,6 +851,7 @@ begin
channels
:
for
channel_idx
in
0
to
g_num_channels
-1
generate
channel
:
eca_channel
generic
map
(
g_channel_idx
=>
channel_idx
,
g_log_table_size
=>
g_log_queue_len
,
g_log_latency
=>
g_log_queue_len
,
g_log_queue_depth
=>
g_log_queue_len
+
1
)
...
...
@@ -859,6 +860,7 @@ begin
rst_n_i
=>
a_rst_n_i
,
drain_i
=>
ra0_cq_drain
(
channel_idx
),
freeze_i
=>
ra0_cq_freeze
(
channel_idx
),
eca_idx_i
=>
rc_ce_idx
,
-- crosses clock domains, but held stable
addr_i
=>
rc_cq_index
,
-- crosses clock domains, but held stable
fill_o
=>
sa_qc_fill
(
channel_idx
),
full_o
=>
sa_qw_full
(
channel_idx
),
...
...
modules/wr_eca/eca_channel.vhd
View file @
e0e3a728
...
...
@@ -65,6 +65,7 @@ use work.eca_pkg.all;
entity
eca_channel
is
generic
(
g_channel_idx
:
natural
;
g_log_table_size
:
natural
:
=
8
;
g_log_latency
:
natural
:
=
8
;
-- Must be <= g_log_table_size
g_log_queue_depth
:
natural
:
=
9
);
-- Must be > g_log_latency
...
...
@@ -73,6 +74,7 @@ entity eca_channel is
rst_n_i
:
in
std_logic
;
freeze_i
:
in
std_logic
;
-- stop action outflow and use addr_i=>inspect_o
drain_i
:
in
std_logic
;
-- stop action in+outflow and erase tables
eca_idx_i
:
in
std_logic_vector
(
7
downto
0
);
addr_i
:
in
std_logic_vector
(
g_log_table_size
-1
downto
0
);
fill_o
:
out
std_logic_vector
(
g_log_table_size
downto
0
);
full_o
:
out
std_logic
;
...
...
@@ -402,6 +404,8 @@ begin
channel_o
.
tag
<=
td_dispatch_tag
;
channel_o
.
tef
<=
td_dispatch_tef
;
channel_o
.
time
<=
td_dispatch_time
;
channel_o
.
eca_idx
<=
eca_idx_i
;
channel_o
.
chl_idx
<=
std_logic_vector
(
to_unsigned
(
g_channel_idx
,
8
));
inspect_o
.
valid
<=
td_dispatch_valid
;
inspect_o
.
conflict
<=
'0'
;
...
...
@@ -411,6 +415,8 @@ begin
inspect_o
.
tag
<=
td_dispatch_tag
;
inspect_o
.
tef
<=
td_dispatch_tef
;
inspect_o
.
time
<=
td_dispatch_time
;
inspect_o
.
eca_idx
<=
eca_idx_i
;
inspect_o
.
chl_idx
<=
std_logic_vector
(
to_unsigned
(
g_channel_idx
,
8
));
dispatch_manage_kill
<=
dispatch_valid1
;
dispatch_manage_index
<=
dispatch_index1
;
...
...
modules/wr_eca/eca_pkg.vhd
View file @
e0e3a728
...
...
@@ -64,7 +64,7 @@ package eca_pkg is
constant
c_eca_queue_sdb
:
t_sdb_device
:
=
(
abi_class
=>
x"0000"
,
-- undocumented device
abi_ver_major
=>
x"0
1
"
,
abi_ver_major
=>
x"0
2
"
,
abi_ver_minor
=>
x"00"
,
wbd_endian
=>
c_sdb_endian_big
,
wbd_width
=>
x"7"
,
-- 8/16/32-bit port granularity
...
...
@@ -75,7 +75,7 @@ package eca_pkg is
vendor_id
=>
x"0000000000000651"
,
device_id
=>
x"9bfa4560"
,
version
=>
x"00000001"
,
date
=>
x"201
31107
"
,
date
=>
x"201
40508
"
,
name
=>
"ECA_UNIT:ACTION_QUE"
)));
constant
c_event_bits
:
natural
:
=
64
;
...
...
@@ -100,6 +100,8 @@ package eca_pkg is
tag
:
t_tag
;
tef
:
t_tef
;
time
:
t_time
;
eca_idx
:
std_logic_vector
(
7
downto
0
);
chl_idx
:
std_logic_vector
(
7
downto
0
);
end
record
t_channel
;
type
t_name
is
array
(
63
downto
0
)
of
t_ascii
;
...
...
@@ -419,6 +421,7 @@ package eca_pkg is
component
eca_channel
is
generic
(
g_channel_idx
:
natural
;
g_log_table_size
:
natural
:
=
8
;
g_log_latency
:
natural
:
=
8
;
-- Must be <= g_log_table_size
g_log_queue_depth
:
natural
:
=
9
);
-- Must be > g_log_latency
...
...
@@ -427,6 +430,7 @@ package eca_pkg is
rst_n_i
:
in
std_logic
;
freeze_i
:
in
std_logic
;
-- stop action outflow and use addr_i=>inspect_o
drain_i
:
in
std_logic
;
-- stop action in+outflow and erase tables
eca_idx_i
:
in
std_logic_vector
(
7
downto
0
);
addr_i
:
in
std_logic_vector
(
g_log_table_size
-1
downto
0
);
fill_o
:
out
std_logic_vector
(
g_log_table_size
downto
0
);
full_o
:
out
std_logic
;
...
...
modules/wr_eca/eca_queue_channel.vhd
View file @
e0e3a728
--! @file eca_
gpio_
channel.vhd
--! @brief ECA-
GPIO
Adapter
--! @file eca_
queue
channel.vhd
--! @brief ECA-
Queue
Adapter
--! @author Wesley W. Terpstra <w.terpstra@gsi.de>
--!
--! Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH
...
...
@@ -17,7 +17,9 @@
--! 0x0C RW : Queue overflow interrupt address (i_master_o.adr=reg, i_master_o.dat=[0=dropped])
--! 0x10 R : Queued actions
--! 0x14 RW : Dropped actions
--! 0x18 -- reserved --
--! 0x18 R : Meta-data
--! 0x0 R : eca index
--! 0x1 R : channel index
--! 0x1C R : flags (0x1=late, 0x2=conflict)
--! 0x20 R : Event1
--! 0x24 R : Event0
...
...
@@ -412,7 +414,8 @@ begin
when
3
=>
q_slave_o
.
dat
(
rq_int_dropped
'range
)
<=
rq_int_dropped
;
when
4
=>
q_slave_o
.
dat
(
rq_queued
'range
)
<=
std_logic_vector
(
rq_queued
);
when
5
=>
q_slave_o
.
dat
(
rq_dropped
'range
)
<=
std_logic_vector
(
rq_dropped
);
when
6
=>
null
;
-- reserved
when
6
=>
q_slave_o
.
dat
(
31
downto
24
)
<=
a_channel_i
.
eca_idx
;
q_slave_o
.
dat
(
23
downto
16
)
<=
a_channel_i
.
chl_idx
;
when
7
=>
q_slave_o
.
dat
(
0
)
<=
sq_late
;
q_slave_o
.
dat
(
1
)
<=
sq_conflict
;
-- Protect clock crossing (rq_widx updates well after memory written)
...
...
modules/wr_eca/eca_walker.vhd
View file @
e0e3a728
...
...
@@ -384,6 +384,8 @@ begin
q_channel_o
(
i
)
.
tag
<=
r1_a_tag
;
q_channel_o
(
i
)
.
tef
<=
r1_a_tef
;
q_channel_o
(
i
)
.
time
<=
s1_a_action_time
;
q_channel_o
(
i
)
.
eca_idx
<=
(
others
=>
'0'
);
-- meta-data added by channel
q_channel_o
(
i
)
.
chl_idx
<=
(
others
=>
'0'
);
end
generate
;
end
rtl
;
modules/wr_eca/lib/hw-channel.cpp
View file @
e0e3a728
...
...
@@ -47,20 +47,20 @@ status_t ActionChannel::refresh() {
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
write
(
address
+
ECA
Q
_SELECT
,
EB_DATA32
,
index
<<
16
);
cycle
.
read
(
address
+
ECA
Q
_CTL
,
EB_DATA32
,
&
ctl
);
cycle
.
read
(
address
+
ECA
Q
_INT_DEST
,
EB_DATA32
,
&
d_dest
);
cycle
.
read
(
address
+
ECA
Q
_FILL
,
EB_DATA32
,
&
d_fill
);
cycle
.
read
(
address
+
ECA
Q
_VALID
,
EB_DATA32
,
&
d_valid
);
cycle
.
read
(
address
+
ECA
Q
_CONFLICT
,
EB_DATA32
,
&
d_conflict
);
cycle
.
read
(
address
+
ECA
Q
_LATE
,
EB_DATA32
,
&
d_late
);
cycle
.
write
(
address
+
ECA
C
_SELECT
,
EB_DATA32
,
index
<<
16
);
cycle
.
read
(
address
+
ECA
C
_CTL
,
EB_DATA32
,
&
ctl
);
cycle
.
read
(
address
+
ECA
C
_INT_DEST
,
EB_DATA32
,
&
d_dest
);
cycle
.
read
(
address
+
ECA
C
_FILL
,
EB_DATA32
,
&
d_fill
);
cycle
.
read
(
address
+
ECA
C
_VALID
,
EB_DATA32
,
&
d_valid
);
cycle
.
read
(
address
+
ECA
C
_CONFLICT
,
EB_DATA32
,
&
d_conflict
);
cycle
.
read
(
address
+
ECA
C
_LATE
,
EB_DATA32
,
&
d_late
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
draining
=
(
ctl
&
ECA
Q
_CTL_DRAIN
)
!=
0
;
frozen
=
(
ctl
&
ECA
Q
_CTL_FREEZE
)
!=
0
;
int_enable
=
(
ctl
&
ECA
Q
_CTL_INT_MASK
)
!=
0
;
draining
=
(
ctl
&
ECA
C
_CTL_DRAIN
)
!=
0
;
frozen
=
(
ctl
&
ECA
C
_CTL_FREEZE
)
!=
0
;
int_enable
=
(
ctl
&
ECA
C
_CTL_INT_MASK
)
!=
0
;
int_dest
=
d_dest
;
fill
=
(
d_fill
>>
16
)
&
0xFFFF
;
max_fill
=
(
d_fill
>>
0
)
&
0xFFFF
;
...
...
@@ -78,11 +78,11 @@ status_t ActionChannel::reset() {
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
write
(
address
+
ECA
Q
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
Q
_FILL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
Q
_VALID
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
Q
_CONFLICT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
Q
_LATE
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
C
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
C
_FILL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
C
_VALID
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
C
_CONFLICT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
cycle
.
write
(
address
+
ECA
C
_LATE
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
...
...
@@ -102,9 +102,9 @@ status_t ActionChannel::freeze(bool freeze) {
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
ctl
=
freeze
?
(
ECA
Q_CTL_FREEZE
)
:
(
ECAQ
_CTL_FREEZE
<<
8
);
cycle
.
write
(
address
+
ECA
Q
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
Q
_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ctl
);
ctl
=
freeze
?
(
ECA
C_CTL_FREEZE
)
:
(
ECAC
_CTL_FREEZE
<<
8
);
cycle
.
write
(
address
+
ECA
C
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
C
_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ctl
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
...
...
@@ -121,9 +121,9 @@ status_t ActionChannel::drain(bool drain) {
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
ctl
=
drain
?
(
ECA
Q_CTL_DRAIN
)
:
(
ECAQ
_CTL_DRAIN
<<
8
);
cycle
.
write
(
address
+
ECA
Q
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
Q
_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ctl
);
ctl
=
drain
?
(
ECA
C_CTL_DRAIN
)
:
(
ECAC
_CTL_DRAIN
<<
8
);
cycle
.
write
(
address
+
ECA
C
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
C
_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ctl
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
...
...
@@ -140,11 +140,11 @@ status_t ActionChannel::hook(bool enable, uint32_t dest) {
return
status
;
/* Clear the interrupt, set the address, possibly re-enable interrupt */
cycle
.
write
(
address
+
ECA
Q
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
Q_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ECAQ
_CTL_INT_MASK
<<
8
);
cycle
.
write
(
address
+
ECA
Q
_INT_DEST
,
EB_DATA32
|
EB_BIG_ENDIAN
,
dest
);
cycle
.
write
(
address
+
ECA
C
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
index
<<
16
);
cycle
.
write
(
address
+
ECA
C_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ECAC
_CTL_INT_MASK
<<
8
);
cycle
.
write
(
address
+
ECA
C
_INT_DEST
,
EB_DATA32
|
EB_BIG_ENDIAN
,
dest
);
if
(
enable
)
{
cycle
.
write
(
address
+
ECA
Q_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ECAQ
_CTL_INT_MASK
);
cycle
.
write
(
address
+
ECA
C_CTL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
ECAC
_CTL_INT_MASK
);
}
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
...
...
@@ -178,23 +178,23 @@ status_t ActionChannel::load(std::vector<ActionEntry>& table) {
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
write
(
address
+
ECA
Q
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
(
index
<<
16
)
|
i
);
cycle
.
read
(
address
+
ECA
Q
_CTL
,
EB_DATA32
,
&
ctl
);
cycle
.
write
(
address
+
ECA
C
_SELECT
,
EB_DATA32
|
EB_BIG_ENDIAN
,
(
index
<<
16
)
|
i
);
cycle
.
read
(
address
+
ECA
C
_CTL
,
EB_DATA32
,
&
ctl
);
cycle
.
read
(
address
+
ECA
Q
_EVENT1
,
EB_DATA32
,
&
event1
);
cycle
.
read
(
address
+
ECA
Q
_EVENT0
,
EB_DATA32
,
&
event0
);
cycle
.
read
(
address
+
ECA
Q
_PARAM1
,
EB_DATA32
,
&
param1
);
cycle
.
read
(
address
+
ECA
Q
_PARAM0
,
EB_DATA32
,
&
param0
);
cycle
.
read
(
address
+
ECA
Q
_TAG
,
EB_DATA32
,
&
tag
);
cycle
.
read
(
address
+
ECA
Q
_TEF
,
EB_DATA32
,
&
tef
);
cycle
.
read
(
address
+
ECA
Q
_TIME1
,
EB_DATA32
,
&
time1
);
cycle
.
read
(
address
+
ECA
Q
_TIME0
,
EB_DATA32
,
&
time0
);
cycle
.
read
(
address
+
ECA
C
_EVENT1
,
EB_DATA32
,
&
event1
);
cycle
.
read
(
address
+
ECA
C
_EVENT0
,
EB_DATA32
,
&
event0
);
cycle
.
read
(
address
+
ECA
C
_PARAM1
,
EB_DATA32
,
&
param1
);
cycle
.
read
(
address
+
ECA
C
_PARAM0
,
EB_DATA32
,
&
param0
);
cycle
.
read
(
address
+
ECA
C
_TAG
,
EB_DATA32
,
&
tag
);
cycle
.
read
(
address
+
ECA
C
_TEF
,
EB_DATA32
,
&
tef
);
cycle
.
read
(
address
+
ECA
C
_TIME1
,
EB_DATA32
,
&
time1
);
cycle
.
read
(
address
+
ECA
C
_TIME0
,
EB_DATA32
,
&
time0
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
/* Is the record invalid? */
if
(((
ctl
>>
24
)
&
ECA
Q
_STATUS_VALID
)
==
0
)
continue
;
if
(((
ctl
>>
24
)
&
ECA
C
_STATUS_VALID
)
==
0
)
continue
;
ActionEntry
ae
;
...
...
@@ -203,9 +203,7 @@ status_t ActionChannel::load(std::vector<ActionEntry>& table) {
ae
.
tag
=
tag
;
ae
.
tef
=
tef
;
ae
.
time
=
time1
;
ae
.
time
<<=
32
;
ae
.
time
+=
time0
;
/* late events have negative timestamps */
if
(((
ctl
>>
24
)
&
ECAQ_STATUS_LATE
)
==
1
)
ae
.
time
=
-
ae
.
time
;
ae
.
status
=
(((
ctl
>>
24
)
&
ECAC_STATUS_LATE
)
==
1
)
?
LATE
:
VALID
;
table
.
push_back
(
ae
);
}
...
...
modules/wr_eca/lib/hw-eca.h
View file @
e0e3a728
...
...
@@ -31,6 +31,7 @@
#define GSI_VENDOR_ID 0x651
#define ECA_DEVICE_ID 0x8752bf44U
#define ECAE_DEVICE_ID 0x8752bf45U
#define ECAQ_DEVICE_ID 0x9bfa4560U
#define ECA_FEATURE_INSPECT_TABLE 0x1
#define ECA_FEATURE_INSPECT_QUEUE 0x2
...
...
@@ -66,36 +67,54 @@
#define ECA_FREQ_2S 0x3D
#define ECA_FREQ_DIV 0x3E
#define ECAQ_STATUS_VALID 0x01
#define ECAQ_STATUS_LATE 0x02
#define ECAQ_CTL_DRAIN 0x01
#define ECAQ_CTL_FREEZE 0x02
#define ECAQ_CTL_INT_MASK 0x04
#define ECAQ_SELECT 0x40
#define ECAQ_CHANNEL 0x40
#define ECAQ_INDEX 0x42
#define ECAQ_CTL 0x44
#define ECAQ_STATUS 0x44
#define ECAQ_NAME 0x45
#define ECAQ_CTL_CLEAR 0x46
#define ECAQ_CTL_SET 0x47
#define ECAQ_INT_DEST 0x48
#define ECAQ_FILL 0x50
#define ECAQ_MAX_FILL 0x52
#define ECAQ_VALID 0x54
#define ECAQ_CONFLICT 0x58
#define ECAQ_LATE 0x5C
#define ECAQ_EVENT1 0x60
#define ECAQ_EVENT0 0x64
#define ECAQ_PARAM1 0x68
#define ECAQ_PARAM0 0x6C
#define ECAQ_TAG 0x70
#define ECAQ_TEF 0x74
#define ECAQ_TIME1 0x78
#define ECAQ_TIME0 0x7C
#define ECAC_STATUS_VALID 0x01
#define ECAC_STATUS_LATE 0x02
#define ECAC_CTL_DRAIN 0x01
#define ECAC_CTL_FREEZE 0x02
#define ECAC_CTL_INT_MASK 0x04
#define ECAC_SELECT 0x40
#define ECAC_CHANNEL 0x40
#define ECAC_INDEX 0x42
#define ECAC_CTL 0x44
#define ECAC_STATUS 0x44
#define ECAC_NAME 0x45
#define ECAC_CTL_CLEAR 0x46
#define ECAC_CTL_SET 0x47
#define ECAC_INT_DEST 0x48
#define ECAC_FILL 0x50
#define ECAC_MAX_FILL 0x52
#define ECAC_VALID 0x54
#define ECAC_CONFLICT 0x58
#define ECAC_LATE 0x5C
#define ECAC_EVENT1 0x60
#define ECAC_EVENT0 0x64
#define ECAC_PARAM1 0x68
#define ECAC_PARAM0 0x6C
#define ECAC_TAG 0x70
#define ECAC_TEF 0x74
#define ECAC_TIME1 0x78
#define ECAC_TIME0 0x7C
#define ECAQ_CTL 0x0
#define ECAQ_INT_MASK 0x4
#define ECAQ_ARRIVAL 0x8
#define ECAQ_OVERFLOW 0xC
#define ECAQ_QUEUED 0x10
#define ECAQ_DROPPED 0x14
#define ECAQ_META 0x18
#define ECAQ_FLAGS 0x1C
#define ECAQ_EVENT1 0x20
#define ECAQ_EVENT0 0x24
#define ECAQ_PARAM1 0x28
#define ECAQ_PARAM0 0x2C
#define ECAQ_TAG 0x30
#define ECAQ_TEF 0x34
#define ECAQ_TIME1 0x38
#define ECAQ_TIME0 0x3C
namespace
GSI_ECA
{
...
...
modules/wr_eca/lib/hw-queue.cpp
0 → 100644
View file @
e0e3a728
/** @file hw-queue.cpp
* @brief C++ Wrapper for the ECA Queue hardware.
* @author Wesley W. Terpstra <w.terpstra@gsi.de>
*
* Copyright (C) 2014 GSI Helmholtz Centre for Heavy Ion Research GmbH
*
* Read-write control of Queue registers.
*
*******************************************************************************
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************
*/
#define __STDC_FORMAT_MACROS
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <stdio.h>
#include <assert.h>
#include "eca.h"
#include "hw-eca.h"
namespace
GSI_ECA
{
status_t
ActionQueue
::
refresh
()
{
Cycle
cycle
;
eb_status_t
status
;
eb_data_t
d_int_mask
;
eb_data_t
d_arrival_dest
;
eb_data_t
d_overflow_dest
;
eb_data_t
d_queued
;
eb_data_t
d_dropped
;
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
read
(
address
+
ECAQ_INT_MASK
,
EB_DATA32
,
&
d_int_mask
);
cycle
.
read
(
address
+
ECAQ_ARRIVAL
,
EB_DATA32
,
&
d_arrival_dest
);
cycle
.
read
(
address
+
ECAQ_OVERFLOW
,
EB_DATA32
,
&
d_overflow_dest
);
cycle
.
read
(
address
+
ECAQ_QUEUED
,
EB_DATA32
,
&
d_queued
);
cycle
.
read
(
address
+
ECAQ_DROPPED
,
EB_DATA32
,
&
d_dropped
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
arrival_enable
=
(
d_int_mask
&
1
)
!=
0
;
overflow_enable
=
(
d_int_mask
&
2
)
!=
0
;
arrival_dest
=
d_arrival_dest
&
0xFFFFFFFF
;
overflow_dest
=
d_overflow_dest
&
0xFFFFFFFF
;
queued_actions
=
d_queued
&
0xFFFFFFFF
;
dropped_actions
=
d_dropped
&
0xFFFFFFFF
;
return
EB_OK
;
}
status_t
ActionQueue
::
reset
()
{
Cycle
cycle
;
eb_status_t
status
;
if
((
status
=
device
.
write
(
address
+
ECAQ_DROPPED
,
EB_DATA32
|
EB_BIG_ENDIAN
,
0
))
!=
EB_OK
)
return
status
;
dropped_actions
=
0
;
return
EB_OK
;
}
status_t
ActionQueue
::
hook_arrival
(
bool
enable
,
uint32_t
dest
)
{
Cycle
cycle
;
eb_status_t
status
;
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
/* Clear the interrupt, set the address, possibly re-enable interrupt */
cycle
.
write
(
address
+
ECAQ_INT_MASK
,
EB_DATA32
|
EB_BIG_ENDIAN
,
overflow_enable
?
2
:
0
);
cycle
.
write
(
address
+
ECAQ_ARRIVAL
,
EB_DATA32
|
EB_BIG_ENDIAN
,
dest
);
if
(
enable
)
{
cycle
.
write
(
address
+
ECAQ_INT_MASK
,
EB_DATA32
|
EB_BIG_ENDIAN
,
overflow_enable
?
3
:
1
);
}
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
arrival_enable
=
enable
;
arrival_dest
=
dest
;
return
EB_OK
;
}
status_t
ActionQueue
::
hook_overflow
(
bool
enable
,
uint32_t
dest
)
{
Cycle
cycle
;
eb_status_t
status
;
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
/* Clear the interrupt, set the address, possibly re-enable interrupt */
cycle
.
write
(
address
+
ECAQ_INT_MASK
,
EB_DATA32
|
EB_BIG_ENDIAN
,
arrival_enable
?
1
:
0
);
cycle
.
write
(
address
+
ECAQ_OVERFLOW
,
EB_DATA32
|
EB_BIG_ENDIAN
,
dest
);
if
(
enable
)
{
cycle
.
write
(
address
+
ECAQ_INT_MASK
,
EB_DATA32
|
EB_BIG_ENDIAN
,
arrival_enable
?
3
:
2
);
}
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
overflow_enable
=
enable
;
overflow_dest
=
dest
;
return
EB_OK
;
}
status_t
ActionQueue
::
pop
(
ActionEntry
&
queue
)
{
Cycle
cycle
;
eb_status_t
status
;
eb_data_t
queued
,
flags
;
eb_data_t
event1
,
event0
;
eb_data_t
param1
,
param0
;
eb_data_t
tag
,
tef
;
eb_data_t
time1
,
time0
;
if
(
queued_actions
==
0
)
return
EB_FAIL
;
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
read
(
address
+
ECAQ_FLAGS
,
EB_DATA32
,
&
flags
);
cycle
.
read
(
address
+
ECAQ_EVENT1
,
EB_DATA32
,
&
event1
);
cycle
.
read
(
address
+
ECAQ_EVENT0
,
EB_DATA32
,
&
event0
);
cycle
.
read
(
address
+
ECAQ_PARAM1
,
EB_DATA32
,
&
param1
);
cycle
.
read
(
address
+
ECAQ_PARAM0
,
EB_DATA32
,
&
param0
);
cycle
.
read
(
address
+
ECAQ_TAG
,
EB_DATA32
,
&
tag
);
cycle
.
read
(
address
+
ECAQ_TEF
,
EB_DATA32
,
&
tef
);
cycle
.
read
(
address
+
ECAQ_TIME1
,
EB_DATA32
,
&
time1
);
cycle
.
read
(
address
+
ECAQ_TIME0
,
EB_DATA32
,
&
time0
);
cycle
.
write
(
address
+
ECAQ_CTL
,
EB_DATA32
,
1
);
/* pop */
cycle
.
read
(
address
+
ECAQ_QUEUED
,
EB_DATA32
,
&
queued
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
queue
.
status
=
(
flags
&
2
)
!=
0
?
CONFLICT
:
(
flags
&
1
)
!=
0
?
LATE
:
VALID
;
queue
.
event
=
event1
;
queue
.
event
<<=
32
;
queue
.
event
+=
event0
;
queue
.
param
=
param1
;
queue
.
param
<<=
32
;
queue
.
param
+=
param0
;
queue
.
tag
=
tag
;
queue
.
tef
=
tef
;
queue
.
time
=
time1
;
queue
.
time
<<=
32
;
queue
.
time
+=
time0
;
queued_actions
=
queued
;
return
EB_OK
;
}
}
modules/wr_eca/lib/probe-eca.cpp
View file @
e0e3a728
...
...
@@ -39,6 +39,7 @@ struct SearchRecord {
eb_status_t
status
;
std
::
vector
<
ECA
>*
ecas
;
std
::
vector
<
EventStream
>
streams
;
std
::
vector
<
ActionQueue
>
queues
;
};
static
void
trim
(
std
::
string
&
s
)
{
...
...
@@ -63,6 +64,19 @@ void eca_sdb_search(SearchRecord* record, Device dev, const struct sdb_table* sd
case
sdb_record_device
:
{
if
(
des
->
device
.
sdb_component
.
product
.
vendor_id
==
GSI_VENDOR_ID
)
{
switch
(
des
->
device
.
sdb_component
.
product
.
device_id
)
{
case
ECAQ_DEVICE_ID
:
{
if
(
des
->
device
.
abi_ver_major
!=
2
)
break
;
ActionQueue
aq
;
aq
.
address
=
des
->
device
.
sdb_component
.
addr_first
;
aq
.
sdb_ver_major
=
des
->
device
.
abi_ver_major
;
aq
.
sdb_ver_minor
=
des
->
device
.
abi_ver_minor
;
aq
.
sdb_version
=
des
->
device
.
sdb_component
.
product
.
version
;
aq
.
sdb_date
=
des
->
device
.
sdb_component
.
product
.
date
;
aq
.
sdb_name
=
std
::
string
((
const
char
*
)
&
des
->
device
.
sdb_component
.
product
.
name
[
0
],
19
);
trim
(
aq
.
sdb_name
);
record
->
queues
.
push_back
(
aq
);
break
;
}
case
ECAE_DEVICE_ID
:
{
if
(
des
->
device
.
abi_ver_major
!=
2
)
break
;
EventStream
es
;
...
...
@@ -209,23 +223,23 @@ status_t ECA::probe(Device device, std::vector<ECA>& ecas) {
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
write
(
eca
.
address
+
ECA
Q
_SELECT
,
EB_DATA32
,
c
<<
16
);
cycle
.
write
(
eca
.
address
+
ECA
C
_SELECT
,
EB_DATA32
,
c
<<
16
);
for
(
unsigned
j
=
0
;
j
<
64
;
++
j
)
cycle
.
read
(
eca
.
address
+
ECA
Q
_CTL
,
EB_DATA32
,
&
name
[
j
]);
cycle
.
read
(
eca
.
address
+
ECA
Q
_INT_DEST
,
EB_DATA32
,
&
dest
);
cycle
.
read
(
eca
.
address
+
ECA
Q
_FILL
,
EB_DATA32
,
&
fill
);
cycle
.
read
(
eca
.
address
+
ECA
Q
_VALID
,
EB_DATA32
,
&
valid
);
cycle
.
read
(
eca
.
address
+
ECA
Q
_CONFLICT
,
EB_DATA32
,
&
conflict
);
cycle
.
read
(
eca
.
address
+
ECA
Q
_LATE
,
EB_DATA32
,
&
late
);
cycle
.
read
(
eca
.
address
+
ECA
C
_CTL
,
EB_DATA32
,
&
name
[
j
]);
cycle
.
read
(
eca
.
address
+
ECA
C
_INT_DEST
,
EB_DATA32
,
&
dest
);
cycle
.
read
(
eca
.
address
+
ECA
C
_FILL
,
EB_DATA32
,
&
fill
);
cycle
.
read
(
eca
.
address
+
ECA
C
_VALID
,
EB_DATA32
,
&
valid
);
cycle
.
read
(
eca
.
address
+
ECA
C
_CONFLICT
,
EB_DATA32
,
&
conflict
);
cycle
.
read
(
eca
.
address
+
ECA
C
_LATE
,
EB_DATA32
,
&
late
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
ac
.
name
=
eca_extract_name
(
name
);
ac
.
queue_size
=
eca
.
inspect_queue
?
eca
.
queue_size
:
0
;
ac
.
draining
=
(
name
[
0
]
&
ECA
Q
_CTL_DRAIN
)
!=
0
;
ac
.
frozen
=
(
name
[
0
]
&
ECA
Q
_CTL_FREEZE
)
!=
0
;
ac
.
int_enable
=
(
name
[
0
]
&
ECA
Q
_CTL_INT_MASK
)
!=
0
;
ac
.
draining
=
(
name
[
0
]
&
ECA
C
_CTL_DRAIN
)
!=
0
;
ac
.
frozen
=
(
name
[
0
]
&
ECA
C
_CTL_FREEZE
)
!=
0
;
ac
.
int_enable
=
(
name
[
0
]
&
ECA
C
_CTL_INT_MASK
)
!=
0
;
ac
.
int_dest
=
dest
;
ac
.
fill
=
(
fill
>>
16
)
&
0xFFFF
;
ac
.
max_fill
=
(
fill
>>
0
)
&
0xFFFF
;
...
...
@@ -238,9 +252,6 @@ status_t ECA::probe(Device device, std::vector<ECA>& ecas) {
}
/* Phase 3 -- Deduce stream relationships */
std
::
vector
<
uint8_t
>
ids
;
ids
.
resize
(
record
.
streams
.
size
());
for
(
unsigned
s
=
0
;
s
<
record
.
streams
.
size
();
++
s
)
{
EventStream
&
es
=
record
.
streams
[
s
];
...
...
@@ -248,12 +259,7 @@ status_t ECA::probe(Device device, std::vector<ECA>& ecas) {
status
=
device
.
read
(
es
.
address
,
EB_DATA32
,
&
id
);
if
(
status
!=
EB_OK
)
return
status
;
ids
[
s
]
=
id
;
}
for
(
unsigned
s
=
0
;
s
<
record
.
streams
.
size
();
++
s
)
{
EventStream
&
es
=
record
.
streams
[
s
];
uint8_t
mid
=
ids
[
s
];
uint8_t
mid
=
id
;
if
(
mid
>=
ecas
.
size
())
{
/* fprintf(stderr, "Unmatched ECA Event stream; id: %d\n", mid); */
continue
;
...
...
@@ -262,6 +268,52 @@ status_t ECA::probe(Device device, std::vector<ECA>& ecas) {
ecas
[
mid
].
streams
.
push_back
(
es
);
}
/* Phase 4 -- Deduce queue relationships */
for
(
unsigned
q
=
0
;
q
<
record
.
queues
.
size
();
++
q
)
{
eb_data_t
ctl
,
mask
;
eb_data_t
arrival
,
overflow
;
eb_data_t
queued
,
dropped
;
ActionQueue
&
aq
=
record
.
queues
[
q
];
if
((
status
=
cycle
.
open
(
device
))
!=
EB_OK
)
return
status
;
cycle
.
read
(
aq
.
address
+
ECAQ_CTL
,
EB_DATA32
,
&
ctl
);
cycle
.
read
(
aq
.
address
+
ECAQ_INT_MASK
,
EB_DATA32
,
&
mask
);
cycle
.
read
(
aq
.
address
+
ECAQ_ARRIVAL
,
EB_DATA32
,
&
arrival
);
cycle
.
read
(
aq
.
address
+
ECAQ_OVERFLOW
,
EB_DATA32
,
&
overflow
);
cycle
.
read
(
aq
.
address
+
ECAQ_QUEUED
,
EB_DATA32
,
&
queued
);
cycle
.
read
(
aq
.
address
+
ECAQ_DROPPED
,
EB_DATA32
,
&
dropped
);
cycle
.
read
(
aq
.
address
+
ECAQ_META
,
EB_DATA32
,
&
id
);
if
((
status
=
cycle
.
close
())
!=
EB_OK
)
return
status
;
uint8_t
mid
=
(
id
>>
24
)
&
0xFF
;
uint8_t
cid
=
(
id
>>
16
)
&
0xFF
;
if
(
mid
>=
ecas
.
size
()
||
cid
>=
ecas
[
mid
].
channels
.
size
())
{
/* fprintf(stderr, "Unmatched ECA Queue; id: %d idx: %d\n", mid, idx); */
continue
;
}
if
(
!
ecas
[
mid
].
channels
[
cid
].
queue
.
empty
())
{
/* fprintf(stderr, "Duplicate ECA Queue; id: %d idx: %d\n", mid, idx); */
continue
;
}
aq
.
device
=
ecas
[
mid
].
device
;
aq
.
queue_size
=
(
ctl
>>
16
)
&
0xFFFF
;
aq
.
arrival_enable
=
(
mask
&
1
)
!=
0
;
aq
.
overflow_enable
=
(
mask
&
2
)
!=
0
;
aq
.
arrival_dest
=
arrival
&
0xFFFFFFFF
;
aq
.
overflow_dest
=
overflow
&
0xFFFFFFFF
;
aq
.
queued_actions
=
queued
&
0xFFFFFFFF
;
aq
.
dropped_actions
=
dropped
&
0xFFFFFFFF
;
ecas
[
mid
].
channels
[
cid
].
queue
.
push_back
(
aq
);
}
return
EB_OK
;
}
...
...
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