Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ACS
Public
VILLASframework
VILLASfpga
VILLASfpga
Commits
16297efe
Commit
16297efe
authored
May 29, 2018
by
Daniel Krebs
Browse files
update rtds2gpu HLS IP to v1.1
- better tested IP (testbenches) - detect invalid frame sizes - more status reporting
parent
2f00d736
Changes
8
Hide whitespace changes
Inline
Side-by-side
include/villas/fpga/ips/rtds2gpu.hpp
View file @
16297efe
...
...
@@ -4,6 +4,7 @@
#include <villas/fpga/ip_node.hpp>
#include "rtds2gpu/xrtds2gpu.h"
#include "rtds2gpu/register_types.hpp"
namespace
villas
{
namespace
fpga
{
...
...
@@ -17,11 +18,22 @@ public:
bool
init
();
void
dump
();
bool
start
();
bool
startOnce
(
const
MemoryBlock
&
mem
,
size_t
frameSize
);
void
dump
(
spdlog
::
level
::
level_enum
logLevel
=
spdlog
::
level
::
info
);
bool
isDone
();
bool
startOnce
(
const
MemoryBlock
&
mem
,
size_t
frameSize
,
size_t
dataOffset
,
size_t
doorbellOffset
);
bool
isFinished
();
bool
isReady
();
size_t
getMaxFrameSize
();
void
dumpDoorbell
(
uint32_t
doorbellRegister
)
const
;
private:
bool
updateStatus
();
private:
static
constexpr
const
char
*
registerMemory
=
"Reg"
;
...
...
@@ -32,6 +44,11 @@ private:
{
return
{
registerMemory
};
}
XRtds2gpu
xInstance
;
axilite_reg_status_t
status
;
size_t
maxFrameSize
;
bool
started
;
};
...
...
include/villas/fpga/ips/rtds2gpu/register_types.hpp
0 → 100644
View file @
16297efe
#ifndef REGISTER_TYPES_H
#define REGISTER_TYPES_H
#include <stdint.h>
union
axilite_reg_status_t
{
uint32_t
value
;
struct
{
uint32_t
last_seq_nr
:
16
,
last_count
:
6
,
max_frame_size
:
6
,
invalid_frame_size
:
1
,
frame_too_short
:
1
,
frame_too_long
:
1
,
is_running
:
1
;
};
};
union
reg_doorbell_t
{
uint32_t
value
;
struct
{
uint32_t
seq_nr
:
16
,
count
:
6
,
is_valid
:
1
;
};
};
#endif // REGISTER_TYPES_H
include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h
View file @
16297efe
...
...
@@ -93,11 +93,10 @@ void XRtds2gpu_Set_data_offset(XRtds2gpu *InstancePtr, u32 Data);
u32
XRtds2gpu_Get_data_offset
(
XRtds2gpu
*
InstancePtr
);
void
XRtds2gpu_Set_doorbell_offset
(
XRtds2gpu
*
InstancePtr
,
u32
Data
);
u32
XRtds2gpu_Get_doorbell_offset
(
XRtds2gpu
*
InstancePtr
);
void
XRtds2gpu_Set_status_i
(
XRtds2gpu
*
InstancePtr
,
u32
Data
);
u32
XRtds2gpu_Get_status_i
(
XRtds2gpu
*
InstancePtr
);
u32
XRtds2gpu_Get_status_o
(
XRtds2gpu
*
InstancePtr
);
void
XRtds2gpu_Set_frame_size
(
XRtds2gpu
*
InstancePtr
,
u32
Data
);
u32
XRtds2gpu_Get_frame_size
(
XRtds2gpu
*
InstancePtr
);
u32
XRtds2gpu_Get_status
(
XRtds2gpu
*
InstancePtr
);
u32
XRtds2gpu_Get_status_vld
(
XRtds2gpu
*
InstancePtr
);
void
XRtds2gpu_InterruptGlobalEnable
(
XRtds2gpu
*
InstancePtr
);
void
XRtds2gpu_InterruptGlobalDisable
(
XRtds2gpu
*
InstancePtr
);
...
...
include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h
View file @
16297efe
...
...
@@ -33,15 +33,14 @@
// 0x20 : Data signal of doorbell_offset
// bit 31~0 - doorbell_offset[31:0] (Read/Write)
// 0x24 : reserved
// 0x28 : Data signal of status_i
// bit 31~0 - status_i[31:0] (Read/Write)
// 0x2c : reserved
// 0x30 : Data signal of status_o
// bit 31~0 - status_o[31:0] (Read)
// 0x34 : reserved
// 0x38 : Data signal of frame_size
// 0x28 : Data signal of frame_size
// bit 31~0 - frame_size[31:0] (Read/Write)
// 0x3c : reserved
// 0x2c : reserved
// 0x30 : Data signal of status
// bit 31~0 - status[31:0] (Read)
// 0x34 : Control signal of status
// bit 0 - status_ap_vld (Read/COR)
// others - reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
#define XRTDS2GPU_CTRL_ADDR_AP_CTRL 0x00
...
...
@@ -54,10 +53,9 @@
#define XRTDS2GPU_CTRL_BITS_DATA_OFFSET_DATA 32
#define XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA 0x20
#define XRTDS2GPU_CTRL_BITS_DOORBELL_OFFSET_DATA 32
#define XRTDS2GPU_CTRL_ADDR_STATUS_I_DATA 0x28
#define XRTDS2GPU_CTRL_BITS_STATUS_I_DATA 32
#define XRTDS2GPU_CTRL_ADDR_STATUS_O_DATA 0x30
#define XRTDS2GPU_CTRL_BITS_STATUS_O_DATA 32
#define XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA 0x38
#define XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA 0x28
#define XRTDS2GPU_CTRL_BITS_FRAME_SIZE_DATA 32
#define XRTDS2GPU_CTRL_ADDR_STATUS_DATA 0x30
#define XRTDS2GPU_CTRL_BITS_STATUS_DATA 32
#define XRTDS2GPU_CTRL_ADDR_STATUS_CTRL 0x34
lib/CMakeLists.txt
View file @
16297efe
...
...
@@ -29,6 +29,10 @@ set(SOURCES
log_helper.c
)
# we don't have much influence on drivers generated by Xilinx, so ignore warnings
set_source_files_properties
(
ips/rtds2gpu/xrtds2gpu.c
PROPERTIES COMPILE_FLAGS -Wno-int-to-pointer-cast
)
include
(
FindPkgConfig
)
pkg_check_modules
(
JANSSON jansson
)
...
...
lib/ips/rtds2gpu/rtds2gpu.cpp
View file @
16297efe
...
...
@@ -20,44 +20,64 @@ bool Rtds2Gpu::init()
// make sure IP is stopped for now
XRtds2gpu_DisableAutoRestart
(
&
xInstance
);
dump
();
status
.
value
=
0
;
started
=
false
;
maxFrameSize
=
getMaxFrameSize
();
logger
->
info
(
"Max. frame size supported: {}"
,
maxFrameSize
);
return
true
;
}
bool
Rtds2Gpu
::
start
()
{
XRtds2gpu_Start
(
&
xInstance
);
started
=
true
;
return
true
;
}
void
Rtds2Gpu
::
dump
()
void
Rtds2Gpu
::
dump
(
spdlog
::
level
::
level_enum
logLevel
)
{
const
auto
baseaddr
=
XRtds2gpu_Get_baseaddr
(
&
xInstance
);
const
auto
data_offset
=
XRtds2gpu_Get_data_offset
(
&
xInstance
);
const
auto
doorbell_offset
=
XRtds2gpu_Get_doorbell_offset
(
&
xInstance
);
const
auto
frame_size
=
XRtds2gpu_Get_frame_size
(
&
xInstance
);
const
auto
status
=
XRtds2gpu_Get_status_o
(
&
xInstance
);
logger
->
debug
(
"Rtds2Gpu registers (IP base {:#x}):"
,
xInstance
.
Ctrl_BaseAddress
);
logger
->
debug
(
" Base address (bytes): {:#x}"
,
baseaddr
);
logger
->
debug
(
" Doorbell offset (bytes): {:#x}"
,
doorbell_offset
);
logger
->
debug
(
" Data offset (bytes): {:#x}"
,
data_offset
);
logger
->
debug
(
" Frame size (words): {:#x}"
,
frame_size
);
logger
->
debug
(
" Status: {:#x}"
,
status
);
logger
->
log
(
logLevel
,
"Rtds2Gpu registers (IP base {:#x}):"
,
xInstance
.
Ctrl_BaseAddress
);
logger
->
log
(
logLevel
,
" Base address (bytes): {:#x}"
,
baseaddr
);
logger
->
log
(
logLevel
,
" Doorbell offset (bytes): {:#x}"
,
doorbell_offset
);
logger
->
log
(
logLevel
,
" Data offset (bytes): {:#x}"
,
data_offset
);
logger
->
log
(
logLevel
,
" Frame size (words): {:#x}"
,
frame_size
);
logger
->
log
(
logLevel
,
" Status: {:#x}"
,
status
.
value
);
logger
->
log
(
logLevel
,
" Running: {}"
,
(
status
.
is_running
?
"yes"
:
"no"
));
logger
->
log
(
logLevel
,
" Frame too short: {}"
,
(
status
.
frame_too_short
?
"yes"
:
"no"
));
logger
->
log
(
logLevel
,
" Frame too long: {}"
,
(
status
.
frame_too_long
?
"yes"
:
"no"
));
logger
->
log
(
logLevel
,
" Frame size invalid: {}"
,
(
status
.
invalid_frame_size
?
"yes"
:
"no"
));
logger
->
log
(
logLevel
,
" Last count: {}"
,
status
.
last_count
);
logger
->
log
(
logLevel
,
" Last seq. number: {}"
,
status
.
last_seq_nr
);
logger
->
log
(
logLevel
,
" Max. frame size: {}"
,
status
.
max_frame_size
);
}
bool
Rtds2Gpu
::
startOnce
(
const
MemoryBlock
&
mem
,
size_t
frameSize
)
bool
Rtds2Gpu
::
startOnce
(
const
MemoryBlock
&
mem
,
size_t
frameSize
,
size_t
dataOffset
,
size_t
doorbellOffset
)
{
auto
&
mm
=
MemoryManager
::
get
();
if
(
frameSize
>
maxFrameSize
)
{
logger
->
error
(
"Requested frame size of {} exceeds max. frame size of {}"
,
frameSize
,
maxFrameSize
);
return
false
;
}
auto
translationFromIp
=
mm
.
getTranslation
(
getMasterAddrSpaceByInterface
(
axiInterface
),
mem
.
getAddrSpaceId
());
// make sure IP is stopped for now
XRtds2gpu_DisableAutoRestart
(
&
xInstance
);
// while(not XRtds2gpu_IsIdle(&xInstance) and not XRtds2gpu_IsDone(&xInstance));
// set address of memory block in HLS IP
XRtds2gpu_Set_baseaddr
(
&
xInstance
,
translationFromIp
.
getLocalAddr
(
0
));
XRtds2gpu_Set_doorbell_offset
(
&
xInstance
,
0
);
XRtds2gpu_Set_data_offset
(
&
xInstance
,
4
);
XRtds2gpu_Set_doorbell_offset
(
&
xInstance
,
doorbellOffset
);
XRtds2gpu_Set_data_offset
(
&
xInstance
,
dataOffset
);
XRtds2gpu_Set_frame_size
(
&
xInstance
,
frameSize
);
// prepare memory with all zeroes
...
...
@@ -66,15 +86,61 @@ bool Rtds2Gpu::startOnce(const MemoryBlock& mem, size_t frameSize)
memset
(
memory
,
0
,
mem
.
getSize
());
// start IP
// XRtds2gpu_EnableAutoRestart(&xInstance);
XRtds2gpu_Start
(
&
xInstance
);
return
start
();
}
bool
Rtds2Gpu
::
isFinished
()
{
if
(
started
and
isReady
())
{
started
=
false
;
if
(
not
updateStatus
())
{
throw
"IP is finished but status register invalid"
;
}
}
return
!
started
;
}
bool
Rtds2Gpu
::
isReady
()
{
// use the idle bit to indicate readiness, we don't care about the difference
// here
return
XRtds2gpu_IsIdle
(
&
xInstance
);
}
bool
Rtds2Gpu
::
updateStatus
()
{
if
(
not
XRtds2gpu_Get_status_vld
(
&
xInstance
))
return
false
;
status
.
value
=
XRtds2gpu_Get_status
(
&
xInstance
);
return
true
;
}
bool
Rtds2Gpu
::
isDone
()
size_t
Rtds2Gpu
::
getMaxFrameSize
()
{
return
XRtds2gpu_IsDone
(
&
xInstance
);
XRtds2gpu_Set_frame_size
(
&
xInstance
,
0
);
start
();
while
(
not
isFinished
());
return
status
.
max_frame_size
;
}
void
Rtds2Gpu
::
dumpDoorbell
(
uint32_t
doorbellRegister
)
const
{
auto
&
doorbell
=
reinterpret_cast
<
reg_doorbell_t
&>
(
doorbellRegister
);
logger
->
info
(
"Doorbell register: {:#08x}"
,
doorbell
.
value
);
logger
->
info
(
" Valid: {}"
,
(
doorbell
.
is_valid
?
"yes"
:
"no"
));
logger
->
info
(
" Count: {}"
,
doorbell
.
count
);
logger
->
info
(
" Seq. number: {}"
,
doorbell
.
seq_nr
);
}
Rtds2GpuFactory
::
Rtds2GpuFactory
()
:
...
...
lib/ips/rtds2gpu/xrtds2gpu.c
View file @
16297efe
...
...
@@ -127,48 +127,41 @@ u32 XRtds2gpu_Get_doorbell_offset(XRtds2gpu *InstancePtr) {
return
Data
;
}
void
XRtds2gpu_Set_
status_i
(
XRtds2gpu
*
InstancePtr
,
u32
Data
)
{
void
XRtds2gpu_Set_
frame_size
(
XRtds2gpu
*
InstancePtr
,
u32
Data
)
{
Xil_AssertVoid
(
InstancePtr
!=
NULL
);
Xil_AssertVoid
(
InstancePtr
->
IsReady
==
XIL_COMPONENT_IS_READY
);
XRtds2gpu_WriteReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_
STATUS_I
_DATA
,
Data
);
XRtds2gpu_WriteReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_
FRAME_SIZE
_DATA
,
Data
);
}
u32
XRtds2gpu_Get_
status_i
(
XRtds2gpu
*
InstancePtr
)
{
u32
XRtds2gpu_Get_
frame_size
(
XRtds2gpu
*
InstancePtr
)
{
u32
Data
;
Xil_AssertNonvoid
(
InstancePtr
!=
NULL
);
Xil_AssertNonvoid
(
InstancePtr
->
IsReady
==
XIL_COMPONENT_IS_READY
);
Data
=
XRtds2gpu_ReadReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_
STATUS_I
_DATA
);
Data
=
XRtds2gpu_ReadReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_
FRAME_SIZE
_DATA
);
return
Data
;
}
u32
XRtds2gpu_Get_status
_o
(
XRtds2gpu
*
InstancePtr
)
{
u32
XRtds2gpu_Get_status
(
XRtds2gpu
*
InstancePtr
)
{
u32
Data
;
Xil_AssertNonvoid
(
InstancePtr
!=
NULL
);
Xil_AssertNonvoid
(
InstancePtr
->
IsReady
==
XIL_COMPONENT_IS_READY
);
Data
=
XRtds2gpu_ReadReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_STATUS_
O_
DATA
);
Data
=
XRtds2gpu_ReadReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_STATUS_DATA
);
return
Data
;
}
void
XRtds2gpu_Set_frame_size
(
XRtds2gpu
*
InstancePtr
,
u32
Data
)
{
Xil_AssertVoid
(
InstancePtr
!=
NULL
);
Xil_AssertVoid
(
InstancePtr
->
IsReady
==
XIL_COMPONENT_IS_READY
);
XRtds2gpu_WriteReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA
,
Data
);
}
u32
XRtds2gpu_Get_frame_size
(
XRtds2gpu
*
InstancePtr
)
{
u32
XRtds2gpu_Get_status_vld
(
XRtds2gpu
*
InstancePtr
)
{
u32
Data
;
Xil_AssertNonvoid
(
InstancePtr
!=
NULL
);
Xil_AssertNonvoid
(
InstancePtr
->
IsReady
==
XIL_COMPONENT_IS_READY
);
Data
=
XRtds2gpu_ReadReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_
FRAME_SIZE_DATA
);
return
Data
;
Data
=
XRtds2gpu_ReadReg
(
InstancePtr
->
Ctrl_BaseAddress
,
XRTDS2GPU_CTRL_ADDR_
STATUS_CTRL
);
return
Data
&
0x1
;
}
void
XRtds2gpu_InterruptGlobalEnable
(
XRtds2gpu
*
InstancePtr
)
{
...
...
tests/rtds2gpu.cpp
View file @
16297efe
...
...
@@ -35,9 +35,12 @@
static
constexpr
size_t
SAMPLE_SIZE
=
4
;
static
constexpr
size_t
SAMPLE_COUNT
=
8
;
static
constexpr
size_t
SAMPLE_COUNT
=
16
;
static
constexpr
size_t
FRAME_SIZE
=
SAMPLE_COUNT
*
SAMPLE_SIZE
;
static
constexpr
size_t
DOORBELL_OFFSET
=
SAMPLE_COUNT
;
static
constexpr
size_t
DATA_OFFSET
=
0
;
Test
(
fpga
,
rtds2gpu
,
.
description
=
"Rtds2Gpu"
)
{
...
...
@@ -49,60 +52,55 @@ Test(fpga, rtds2gpu, .description = "Rtds2Gpu")
logger
->
info
(
"Testing {}"
,
*
ip
);
auto
rtds2gpu
=
reinterpret_cast
<
villas
::
fpga
::
ip
::
Rtds2Gpu
&>
(
*
ip
);
auto
dmaMem0
=
villas
::
HostDmaRam
::
getAllocator
(
0
).
allocate
<
char
>
(
FRAME_SIZE
+
4
);
auto
dmaMem1
=
villas
::
HostDmaRam
::
getAllocator
(
0
).
allocate
<
char
>
(
FRAME_SIZE
+
4
);
// continue;
/* Collect neccessary IPs */
auto
rtds2gpu
=
reinterpret_cast
<
villas
::
fpga
::
ip
::
Rtds2Gpu
&>
(
*
ip
);
auto
axiSwitch
=
reinterpret_cast
<
villas
::
fpga
::
ip
::
AxiStreamSwitch
*>
(
state
.
cards
.
front
()
->
lookupIp
(
villas
::
fpga
::
Vlnv
(
"xilinx.com:ip:axis_switch:"
)));
cr_assert_not_null
(
axiSwitch
);
auto
dma
=
reinterpret_cast
<
villas
::
fpga
::
ip
::
Dma
*>
(
state
.
cards
.
front
()
->
lookupIp
(
villas
::
fpga
::
Vlnv
(
"xilinx.com:ip:axi_dma:"
)));
cr_assert_not_null
(
dma
);
memset
(
&
dmaMem0
,
0x55
,
dmaMem0
.
getMemoryBlock
().
getSize
());
memset
(
&
dmaMem1
,
0x11
,
dmaMem1
.
getMemoryBlock
().
getSize
());
rtds2gpu
.
dump
(
spdlog
::
level
::
debug
);
puts
(
"Before:"
);
for
(
size_t
i
=
0
;
i
<
dmaMem0
.
getMemoryBlock
().
getSize
();
i
++
)
{
printf
(
"0x%02x "
,
dmaMem0
[
i
]);
}
puts
(
""
);
cr_assert_not_null
(
axiSwitch
,
"No AXI switch IP found"
);
cr_assert_not_null
(
dma
,
"No DMA IP found"
);
rtds2gpu
.
dump
();
cr_assert
(
axiSwitch
->
connect
(
7
,
6
));
cr_assert
(
axiSwitch
->
connect
(
6
,
7
));
/* Allocate and prepare memory */
// allocate space for all samples and doorbell register
auto
dmaMemSrc
=
villas
::
HostDmaRam
::
getAllocator
(
0
).
allocate
<
uint32_t
>
(
SAMPLE_COUNT
+
1
);
auto
dmaMemDst
=
villas
::
HostDmaRam
::
getAllocator
(
0
).
allocate
<
uint32_t
>
(
SAMPLE_COUNT
+
1
);
memset
(
&
dmaMemSrc
,
0x11
,
dmaMemSrc
.
getMemoryBlock
().
getSize
());
memset
(
&
dmaMemDst
,
0x55
,
dmaMemDst
.
getMemoryBlock
().
getSize
());
c
r_assert
(
rtds2gpu
.
startOnce
(
dmaMem0
.
getMemoryBlock
(),
SAMPLE_COUNT
),
"Preparing Rtds2Gpu IP failed"
)
;
c
onst
uint32_t
*
dataSrc
=
&
dmaMemSrc
[
DATA_OFFSET
];
const
uint32_t
*
dataDst
=
&
dmaMemDst
[
DATA_OFFSET
]
;
cr_assert
(
dma
->
write
(
dmaMem1
.
getMemoryBlock
(),
FRAME_SIZE
));
// connect DMA to Rtds2Gpu IP
// TODO: this should be done automatically
cr_assert
(
axiSwitch
->
connect
(
6
,
7
));
// cr_assert(axiSwitch->connect(6, 6)); // loopback
// cr_assert(dma->read(dmaMem1.getMemoryBlock(), FRAME_SIZE));
// cr_assert(dma->readComplete());
cr_assert
(
rtds2gpu
.
startOnce
(
dmaMemDst
.
getMemoryBlock
(),
SAMPLE_COUNT
,
DATA_OFFSET
*
4
,
DOORBELL_OFFSET
*
4
),
"Preparing Rtds2Gpu IP failed"
);
cr_assert
(
dma
->
writeComplete
());
cr_assert
(
dma
->
write
(
dmaMemSrc
.
getMemoryBlock
(),
FRAME_SIZE
),
"Starting DMA MM2S transfer failed"
);
puts
(
"After:"
);
for
(
size_t
i
=
0
;
i
<
dmaMem0
.
getMemoryBlock
().
getSize
();
i
++
)
{
printf
(
"0x%02x "
,
dmaMem0
[
i
]);
}
puts
(
""
);
cr_assert
(
dma
->
writeComplete
(),
"DMA failed"
);
while
(
not
rtds2gpu
.
isFinished
());
rtds2gpu
.
dump
();
const
uint32_t
*
doorbellDst
=
&
dmaMemDst
[
DOORBELL_OFFSET
];
rtds2gpu
.
dump
(
spdlog
::
level
::
info
);
rtds2gpu
.
dumpDoorbell
(
*
doorbellDst
);
cr_assert
(
rtds2gpu
.
isDone
()
);
cr_assert
(
memcmp
(
dataSrc
,
dataDst
,
FRAME_SIZE
)
==
0
,
"Memory not equal"
);
logger
->
info
(
TXT_GREEN
(
"Passed"
));
}
...
...
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