Skip to content

Instantly share code, notes, and snippets.

@ciniml
Created February 14, 2018 15:44
Show Gist options
  • Save ciniml/d8f3e3af85e634b062e1fba63f828b21 to your computer and use it in GitHub Desktop.
Save ciniml/d8f3e3af85e634b062e1fba63f828b21 to your computer and use it in GitHub Desktop.
HLS Stream Packing
#include <hls_stream.h>
#include <ap_int.h>
#include <ap_fixed.h>
template <typename TComponentType, int TNumberOfComponents>
struct PackedComponent
{
typedef PackedComponent<TComponentType, TNumberOfComponents> SelfType;
typedef TComponentType ComponentType;
static const int NumberOfComponents = TNumberOfComponents;
static const int ComponentWidth = ComponentType::width;
static const int TotalWidth = ComponentWidth*NumberOfComponents;
ap_uint<TotalWidth> value;
ComponentType get(int index) const { return static_cast<ComponentType>(this->value.range(ComponentWidth*(index+1)-1, ComponentWidth*index)); }
void set(int index, const ComponentType& new_value) const { this->value.range(ComponentWidth*(index+1)-1, ComponentWidth*index) = new_value; }
struct ElementReference
{
int index;
SelfType& parent;
operator ComponentType() const { return this->parent.get(this->index); }
ComponentType operator=(const ComponentType& rhs) { this->parent.set(this->index, rhs); return rhs; }
ElementReference(SelfType& parent, int index) : index(index), parent(parent) {}
ElementReference& operator=(const ElementReference& rhs) { this->parent.set(this->index, static_cast<ComponentType>(rhs)); return *this; }
};
ElementReference operator[](int index) { return ElementReference(*this, index); }
ComponentType operator[](int index) const { return this->get(index); }
};
template <int NUM_COMPONENT_BITS, int NUM_PACKED_COMPONENTS>
struct PackedComponentStreamData
{
PackedComponent<ap_fixed<NUM_COMPONENT_BITS-2, 2, AP_TRN_ZERO, AP_SAT>, NUM_PACKED_COMPONENTS> data;
bool last;
};
template <int NUM_COMPONENT_BITS, int NUM_PACKED_COMPONENTS>
struct PackedComponentStream
{
typedef PackedComponentStreamData<NUM_COMPONENT_BITS, NUM_PACKED_COMPONENTS> DataType;
typedef hls::stream<DataType> StreamType;
};
extern void swap_component(PackedComponentStream<8, 4>::StreamType& input, PackedComponentStream<8, 4>::StreamType& output);
#include "swap_component.hpp"
void swap_component(PackedComponentStream<8, 4>::StreamType& input, PackedComponentStream<8, 4>::StreamType& output)
{
#pragma HLS INTERFACE axis register both port=output
#pragma HLS INTERFACE axis register both port=input
PackedComponentStream<8, 4>::DataType inputData;
PackedComponentStream<8, 4>::DataType outputData;
while(true)
{
#pragma HLS PIPELINE II=1
input >> inputData;
outputData.data[0] = inputData.data[3];
outputData.data[1] = inputData.data[2];
outputData.data[2] = inputData.data[1];
outputData.data[3] = inputData.data[0];
outputData.last = inputData.last;
output << outputData;
if( inputData.last ) break;
}
}
#include "swap_component.hpp"
#include <cstdio>
using namespace std;
int main()
{
PackedComponentStream<8, 4>::DataType data;
PackedComponentStream<8, 4>::StreamType input;
PackedComponentStream<8, 4>::StreamType output;
data.data[0] = 0x12;
data.data[1] = 0x34;
data.data[2] = 0x56;
data.data[3] = 0x78;
data.last = false;
input << data;
data.data[3] = 0x12;
data.data[2] = 0x34;
data.data[1] = 0x56;
data.data[0] = 0x78;
data.last = true;
input << data;
swap_component(input, output);
for(int i = 0; i < 2; i++ ) {
output >> data;
if( data.last != (i == 1) ) return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment