Skip to content

Commit

Permalink
Add FPGA firmware - single_transfer.c
Browse files Browse the repository at this point in the history
  • Loading branch information
Aba committed Nov 21, 2023
1 parent 98b40d4 commit 3b1e4c3
Showing 1 changed file with 167 additions and 0 deletions.
167 changes: 167 additions & 0 deletions deepsocflow/c/single_transfer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#include "platform.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xscugic.h"
#include <assert.h>
#include <limits.h>
#include <stdint.h>

#define printf xil_printf
#define assert_printf(v1, op, v2, optional_debug_info,...) ((v1 op v2) || (printf("ASSERT FAILED: \n CONDITION: "), printf("( " #v1 " " #op " " #v2 " )"), printf(", VALUES: ( %ld %s %ld ), ", (long int)v1, #op, (long int)v2), printf("DEBUG_INFO: " optional_debug_info), printf(" " __VA_ARGS__), printf("\n\n"), assert(v1 op v2), 0))

//static int glb_s2mm_done = 0;
static int done_pixels = 0, done_weights = 0, done_output = 0;

XAxiDma dma_pixels, dma_weights, dma_output;
XScuGic intr_controller; // Generic interrupt controller
u32 status;


#define X_BITS_L2 2
#define W_BITS_L2 2
#define X_PAD 6
#define KH_MAX 13
#define PE_ROWS 8
#define PE_COLS 24

#define N_ADD_BUF
#define WB_BYTES 92
#define W_BYTES 44
#define X_BYTES 176
#define O_WORDS 1536
#define O_WORDS_MAX 1536
#define O_BYTES_MAX 6144
#define X_BYTES_ALL 176
#define NHWC_WORDS 1536
#define Y_TYPE int16_t
#define B_TYPE int16_t
#define O_TYPE int32_t
#define B_WORDS 24
#define DATA_DIR "../vectors"
typedef struct {
volatile Y_TYPE ocm [PE_ROWS*PE_COLS];
int8_t w [W_BYTES ];
B_TYPE b [B_WORDS ]; // keep next to w. weights are loaded to w_ptr
int8_t x [X_BYTES_ALL ];
int32_t y [O_WORDS ];
int32_t nhwc [NHWC_WORDS ];
int8_t debug_tiled [O_WORDS_MAX ];
int32_t debug_nhwc [NHWC_WORDS ];
int8_t out_buffers [2 ][O_BYTES_MAX ];
int8_t add_buffers [N_ADD_BUF ][NHWC_WORDS ];
} Memory_st;
Memory_st *p_mem = (Memory_st*) 0x20000000; //XPAR_PSU_OCM_RAM_0_S_AXI_BASEADDR;

#define Y_WORDS (PE_ROWS*PE_COLS)
#define Y_BYTES (Y_WORDS*sizeof(Y_TYPE))

static void mm2s_pixels_handler(void* CallbackRef){
u32 IrqStatus = XAxiDma_IntrGetIrq(&dma_pixels, XAXIDMA_DMA_TO_DEVICE); // Read pending interrupts
XAxiDma_IntrAckIrq(&dma_pixels, IrqStatus, XAXIDMA_DMA_TO_DEVICE); // Acknowledge pending interrupts
if (!(IrqStatus & XAXIDMA_IRQ_IOC_MASK)) return;
xil_printf("pixels mm2s finished!\n");
done_pixels = 1;
}

static void mm2s_weights_handler(void* CallbackRef){
u32 IrqStatus = XAxiDma_IntrGetIrq(&dma_weights, XAXIDMA_DMA_TO_DEVICE); // Read pending interrupts
XAxiDma_IntrAckIrq(&dma_weights, IrqStatus, XAXIDMA_DMA_TO_DEVICE); // Acknowledge pending interrupts
if (!(IrqStatus & XAXIDMA_IRQ_IOC_MASK)) return;
xil_printf("weights mm2s finished!\n");
done_weights = 1;
}

static void s2mm_output_handler(void* CallbackRef){
// while(done_output);
u32 IrqStatus = XAxiDma_IntrGetIrq(&dma_output, XAXIDMA_DEVICE_TO_DMA); // Read pending interrupts
XAxiDma_IntrAckIrq(&dma_output, IrqStatus, XAXIDMA_DEVICE_TO_DMA); // Acknowledge pending interrupts
if (!(IrqStatus & XAXIDMA_IRQ_IOC_MASK)) return;
xil_printf("output s2mm finished!\n");

for (int i=0; i<Y_WORDS; i++)
xil_printf("BRAM, i:%d, value: %d\n", i, p_mem->ocm[i]);
done_output = 1;
}

static void setup_interrupt(XScuGic *p_intr_controller, u32 intr_id, Xil_InterruptHandler handler_fn, u8 priority){
XScuGic_SetPriorityTriggerType(p_intr_controller, intr_id, priority, 0x3); // set priority level, triggered by rising edge
status = XScuGic_Connect(p_intr_controller, intr_id, handler_fn, 0); assert_printf (status, ==, XST_SUCCESS, "ERROR! Failed to connect to the interrupt controller.\r\n",);
XScuGic_Enable(p_intr_controller, intr_id); // enable interrupt
}


int main() {
init_platform();
xil_printf("Store w: %p, x: %p, y:%p\n", &p_mem->w, &p_mem->x, &p_mem->ocm);
print("Starting!!!\n\r");

// Initialize Interrupt Controller
XScuGic_Config *IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
status = XScuGic_CfgInitialize(&intr_controller, IntcConfig, IntcConfig->CpuBaseAddress); assert_printf (status, ==, XST_SUCCESS, "Interrupt initialization failed",);
Xil_ExceptionInit(); // Initialize exception table
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, (void *)&intr_controller); //register the interrupt controller handler with exception table
Xil_ExceptionEnable(); // Enable non-critical exceptions


// Initialize DMA - Pixels
status = XAxiDma_CfgInitialize(&dma_pixels, XAxiDma_LookupConfigBaseAddr(XPAR_DMA_PIXELS_BASEADDR)); assert_printf (status, ==, XST_SUCCESS, "Pixels DMA initialization failed",);
// MM2S
setup_interrupt(&intr_controller, XPAR_FABRIC_DMA_PIXELS_MM2S_INTROUT_INTR, (Xil_InterruptHandler)mm2s_pixels_handler, 0xA8);
XAxiDma_IntrDisable(&dma_pixels, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrEnable (&dma_pixels, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);

// Initialize DMA - Weights
status = XAxiDma_CfgInitialize(&dma_weights, XAxiDma_LookupConfigBaseAddr(XPAR_DMA_WEIGHTS_BASEADDR)); assert_printf (status, ==, XST_SUCCESS, "Weights DMA initialization failed",);
// MM2S
setup_interrupt(&intr_controller, XPAR_FABRIC_DMA_WEIGHTS_MM2S_INTROUT_INTR, (Xil_InterruptHandler)mm2s_weights_handler, 0xAB);
XAxiDma_IntrDisable(&dma_weights, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrEnable (&dma_weights, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);

// Initialize DMA - Output
status = XAxiDma_CfgInitialize(&dma_output, XAxiDma_LookupConfigBaseAddr(XPAR_DMA_OUTPUT_BASEADDR)); assert_printf (status, ==, XST_SUCCESS, "Output DMA initialization failed",);
// S2MM
setup_interrupt(&intr_controller, XPAR_FABRIC_DMA_OUTPUT_S2MM_INTROUT_INTR, (Xil_InterruptHandler)s2mm_output_handler, 0xA0);
XAxiDma_IntrDisable(&dma_output, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrEnable (&dma_output, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA);



// ------------ DATA TRANSFER ---------------

// for (int t=0; t<1; t++){

// 1. Prepare input data
Xil_DCacheFlushRange((INTPTR)&p_mem->w, W_BYTES); // force transfer to DDR, starting addr & length
Xil_DCacheFlushRange((INTPTR)&p_mem->x, X_BYTES);

// 2. Start transfers
print("Starting DMA transfers\n\r");
status = XAxiDma_SimpleTransfer(&dma_weights, (INTPTR)&p_mem->w , W_BYTES, XAXIDMA_DMA_TO_DEVICE); assert_printf (status, ==, XST_SUCCESS, "Weights DMA transfer failed \r\n",);
while(!done_weights);
done_weights = 0;
xil_printf("Weights done: %d/100 \n", 0);

status = XAxiDma_SimpleTransfer(&dma_output , (INTPTR)&p_mem->ocm, Y_BYTES, XAXIDMA_DEVICE_TO_DMA); assert_printf (status, ==, XST_SUCCESS, "Output DMA transfer failed \r\n",);
status = XAxiDma_SimpleTransfer(&dma_pixels , (INTPTR)&p_mem->x , X_BYTES, XAXIDMA_DMA_TO_DEVICE); assert_printf (status, ==, XST_SUCCESS, "Pixels DMA transfer failed \r\n",);

// 3. Wait for interrupt callbacks to set global variables
print("Waiting to complete transfers\n\r");
while (!done_pixels | !done_output);
done_pixels = 0;
done_weights = 0;
done_output = 0;

xil_printf("Done transfer: %d/100 \n", 0);
// }

XScuGic_Disconnect(&intr_controller, XPAR_FABRIC_DMA_PIXELS_MM2S_INTROUT_INTR );
XScuGic_Disconnect(&intr_controller, XPAR_FABRIC_DMA_WEIGHTS_MM2S_INTROUT_INTR);
XScuGic_Disconnect(&intr_controller, XPAR_FABRIC_DMA_OUTPUT_S2MM_INTROUT_INTR );

cleanup_platform();
return 0;
}

0 comments on commit 3b1e4c3

Please sign in to comment.