Skip to content
Snippets Groups Projects
Commit cde48132 authored by Thomas Owen James's avatar Thomas Owen James :speech_balloon:
Browse files

Micron dma share access and cleanup

parent 4c100e76
No related branches found
No related tags found
1 merge request!55Micron dma share access and cleanup
Pipeline #5239506 passed
image: gitlab-registry.cern.ch/scouting-demonstrator/scouting-docker-images/scdaq-builder:1.0.1
image: gitlab-registry.cern.ch/scouting-demonstrator/scouting-docker-images/scdaq-builder:1.0.3
check_formatting:
stage: check
......@@ -41,4 +41,3 @@ stages:
- check
- build
- run
......@@ -71,5 +71,5 @@ session.o: session.h log.h
slice.o: slice.h
WZDmaInputFilter.o: WZDmaInputFilter.h InputFilter.h tools.h log.h
wz_dma.o: wz_dma.h
MicronDmaInputFilter.o: MicronDmaInputFilter.h libmicron/micron_dma.h
MicronDmaInputFilter.o: MicronDmaInputFilter.h
tools.o: tools.h log.h
......@@ -22,28 +22,26 @@ MicronDmaInputFilter::MicronDmaInputFilter(size_t packetBufferSize, size_t nbPac
bool loadBitFile = conf.getLoadBitFile();
int err;
processorType_ = conf.getProcessorType();
// The RunBitFile function will locate a Pico card that can run the given bit
// file, and is not already
// opened in exclusive-access mode by another program. It requests exclusive
// access to the Pico card so no other programs will try to reuse the card
// and interfere with us.
// The RunBitFile function will locate a Pico card that can run the given bit
// file, and is not already opened in exclusive-access mode by another program.
// By default it requests exclusive access to the Pico card so no other programs
// will try to reuse the card and interfere with us.
if (loadBitFile) {
LOG(DEBUG) << "Loading FPGA with '" << bitFileName << "' ...";
err = micron_run_bit_file(bitFileName.c_str(), &pico_);
} else {
err = micron_find_pico(0x852, &pico_);
//first argument sets share access to true for the pico driver,
//to allow other programs to e.g read registers
err = micron_find_pico_sb852(true, &pico_);
}
LOG(TRACE) << "Opening streams to and from the FPGA";
stream2_ = micron_create_stream(pico_, 2);
if (stream2_ < 0) {
// All functions in the Pico API return an error code. If that code is < 0,
// then you should use the PicoErrors_FullError function to decode the error
// message.
// fprintf(stderr, "%s: CreateStream error: %s\n", "bitfile",
// PicoErrors_FullError(stream1_, 0, packetBufferSize));
// then you should use the PicoErrors_FullError function to decode the error message.
throw std::runtime_error(bitFileName + ": CreateStream error: " +
micron_picoerrors_fullerror(stream2_, 0, packetBufferSize));
......@@ -53,8 +51,7 @@ MicronDmaInputFilter::MicronDmaInputFilter(size_t packetBufferSize, size_t nbPac
MicronDmaInputFilter::~MicronDmaInputFilter() {
// streams are automatically closed when the PicoDrv object is destroyed, or
// on program termination, but
// we can also close a stream manually.
// on program termination, but we can also close a stream manually.
micron_close_stream(pico_, stream2_);
LOG(TRACE) << "Destroyed Micron DMA input filter";
}
......@@ -92,54 +89,37 @@ ssize_t MicronDmaInputFilter::runMicronDAQ(char **buffer, size_t bufferSize) {
// Usually Pico streams come in two flavors: 4Byte wide, 16Byte wide
// (equivalent to 32bit, 128bit respectively) However, all calls to ReadStream
// and WriteStream must be 16Byte aligned (even for 4B wide streams) There is
// also an 'undocumented' 32Byte wide (256 bit) stream We are using that
// stream here (and in the firmware)
// also an 'undocumented' 32Byte wide (256 bit) stream.
// We are using that stream here (and in the firmware).
//
// Now allocate 32B aligned space for read and write stream buffers
//
// Similarily, the size of the call, in bytes, must also be a multiple of
// 16Bytes.
//
// err = posix_memalign((void**)&rbuf, 32, size);
// Similarily, the size of the call, in bytes, must also be a multiple of 16Bytes.
//
// NOTE: Buffer are already preallocated and aligned to 32 bytes boundaries
// As with WriteStream, a ReadStream will block until all data is returned
// from the FPGA to the host.
//
/////////////////////////////////
// Note on reading streams///////
// A user application will either have a deterministic amount of results, or a
// non-deterministic amount.
// - When a non-deterministic amount of results are expected, and given the
// When a non-deterministic amount of results are expected, and given the
// blocking nature of the ReadStream,
// a user should use the GetBytesAvailable() call to determine the amount of
// data available for retrieval.
// - When a deterministic amount of results is expected, a user can skip the
// a user should use the GetBytesAvailable() call to determine the amount of
// data available for retrieval.
// When a deterministic amount of results is expected, a user can skip the
// performance impacting
// GetBytesAvailable() call and request the full amount of results. The user
// could also call ReadStream() iteratively, without GetBytesAvailable(), in
// which case getting smaller chunks of results may allow additional
// processing of the data on the host while the FPGA generates more results.
// Either approach works, and should be kept in mind when tuning performance
// of your application.
//
//
// By calling GetBytesAvailable, one can see how much data is ready to read //
// not used for speed
// i = pico->GetBytesAvailable(stream1_, true /* reading */);
// if (i < 0){
// fprintf(stderr, "%s: GetBytesAvailable error: %s\n", "bitfile",
// PicoErrors_FullError(i, ibuf, sizeof(ibuf))); exit(-1);
// }
// Here is where we actually call ReadStream
// This reads "size" number of bytes of data from the output stream specified
// by our stream handle (e.g. 'stream') into our host buffer (rbuf) This call
// will block until it is able to read the entire "size" Bytes of data.
// GetBytesAvailable() call and request the full amount of results. The user
// could also call ReadStream() iteratively, without GetBytesAvailable(), in
// which case getting smaller chunks of results may allow additional
// processing of the data on the host while the FPGA generates more results.
// Either approach works, and should be kept in mind when tuning performance
// of your application.
////////////////////////////////
uint32_t *u32p;
uint32_t packetSize;
int err;
bool bril = true;
if (processorType_ == StreamProcessor::ProcessorType::BRIL) {
u32p = (uint32_t *)((*buffer));
......@@ -148,6 +128,10 @@ ssize_t MicronDmaInputFilter::runMicronDAQ(char **buffer, size_t bufferSize) {
packetSize = 32 * (*((uint32_t *)((*buffer) + 8)) + 2);
}
// Here is where we actually call ReadStream
// This reads "size" number of bytes of data from the output stream specified
// by our stream handle (e.g. 'stream') into our host buffer (rbuf) This call
// will block until it is able to read the entire "size" Bytes of data.
err = micron_read_stream(pico_, stream2_, *buffer, packetSize);
if (err < 0) {
......@@ -158,30 +142,8 @@ ssize_t MicronDmaInputFilter::runMicronDAQ(char **buffer, size_t bufferSize) {
return (packetSize);
}
void MicronDmaInputFilter::rwRegisters() {
// err = micron_WriteDeviceAbsolute(pico_, 8, 0, 32);
// u32p = (uint32_t*) ((*buffer));
// err = micron_ReadDeviceAbsolute(pico_, 4, *buffer, 4);
// std::cout << "reading blocked_ro count " << std::hex << *u32p << std::endl;
/*if (err < 0) {
std::cout << "err = " << err << std::endl;
throw std::runtime_error( "ReadDeviceAbsolute finished with error" );
}
*/
}
/**************************************************************************
* Entry points are here
* Overriding virtual functions
*/
// Print some additional info
void MicronDmaInputFilter::print(std::ostream &out) const {
// out
// << ", DMA errors " << stats.nbDmaErrors
// << ", oversized " << stats.nbDmaOversizedPackets
// << ", resets " << stats.nbBoardResets;
}
// Read a packet from DMA
......
......@@ -5,7 +5,7 @@
#include "InputFilter.h"
#include "config.h"
#include "libmicron/micron_dma.h"
#include <micron_dma.h>
#include "processor.h"
class MicronDmaInputFilter : public InputFilter {
......@@ -21,7 +21,6 @@ class MicronDmaInputFilter : public InputFilter {
private:
micron_private *pico_;
int stream2_;
void rwRegisters();
ssize_t runMicronDAQ(char **buffer, size_t bufferSize);
StreamProcessor::ProcessorType processorType_;
};
......
File deleted
File deleted
#
# Simple workaround creating a Micron library
#
# exit when any command fails
set -e
rm -f *.o *.a
echo "Compilling..."
g++ -Wl,--copy-dt-needed-entries -std=c++11 -fPIC -Wall -Wextra -g -rdynamic -Wno-multichar -DLINUX -DPOSIX \
-fmessage-length=0 -fdiagnostics-show-option -fms-extensions -Wno-write-strings -DOSNAME=“Linux” \
-I. -I${PICOBASE}/software/include/linux -I${PICOBASE}/software/include \
-c \
${PICOBASE}/software/source/pico_drv_linux.cpp \
${PICOBASE}/software/source/GString.cpp \
${PICOBASE}/software/source/pico_drv.cpp \
${PICOBASE}/software/source/pico_errors.cpp \
${PICOBASE}/software/source/linux/linux.cpp \
${PICOBASE}/software/source/pico_drv_swsim.cpp \
micron_dma.c
echo "Creating library..."
ar rcs libmicron.a GString.o linux.o pico_drv.o pico_drv_linux.o pico_drv_swsim.o pico_errors.o micron_dma.o
/*
* Library encapsulating Micron functions
*/
#include <picodrv.h>
#include <pico_errors.h>
#include "micron_dma.h"
int micron_run_bit_file(const char *bitFilePath, micron_private** micron)
{
//PicoDrv **drvpp
return RunBitFile(bitFilePath, (PicoDrv**) micron);
}
int micron_find_pico(uint32_t model, micron_private** micron)
{
return FindPico(model, (PicoDrv**) micron);
}
int micron_create_stream(micron_private* micron, int streamNum)
{
return ((PicoDrv*) micron)->CreateStream(streamNum);
}
void micron_close_stream(micron_private* micron, int streamHandle)
{
((PicoDrv*) micron)->CloseStream(streamHandle);
}
int micron_read_stream(micron_private* micron, int streamHandle, void *buf, int size)
{
return ((PicoDrv*) micron)->ReadStream(streamHandle, buf, size);
}
int micron_ReadDeviceAbsolute (micron_private* micron, int addr, void* buf, int numBytes)
{
return ((PicoDrv*) micron)->ReadDeviceAbsolute(addr, buf, numBytes);
}
int micron_WriteDeviceAbsolute (micron_private* micron, int addr, void* buf, int numBytes)
{
return ((PicoDrv*) micron)->WriteDeviceAbsolute(addr, buf, numBytes);
}
const char *micron_picoerrors_fullerror(int erC, char *resultP, int resultSize)
{
return PicoErrors_FullError(erC, resultP, resultSize);
}
#ifndef MICRON_DMA_H
#define MICRON_DMA_H
typedef void micron_private;
int micron_run_bit_file(const char *bitFilePath, micron_private **micron);
int micron_find_pico(uint32_t model, micron_private **micron);
int micron_ReadDeviceAbsolute(micron_private *micron, int addr, void *buf, int numBytes);
int micron_WriteDeviceAbsolute(micron_private *micron, int addr, void *buf, int numBytes);
int micron_create_stream(micron_private *micron, int streamNum);
void micron_close_stream(micron_private *micron, int streamHandle);
int micron_read_stream(micron_private *micron, int streamHandle, void *buf, int size);
const char *micron_picoerrors_fullerror(int erC, char *resultP, int resultSize);
#endif // MICRON_DMA_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment