Add NoC management functions to Patmos CPU

This commit is contained in:
afpr
2014-06-19 16:19:28 +01:00
parent c578cb7fb7
commit 19fca6ca36
5 changed files with 347 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
/*
Copyright 2014 Technical University of Denmark, DTU Compute.
All rights reserved.
This file is part of the time-predictable VLIW processor Patmos.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are
those of the authors and should not be interpreted as representing official
policies, either expressed or implied, of the copyright holder.
*/
/*
* Functions to initialize and use the NoC.
*
* Author: Wolfgang Puffitsch (wpuffitsch@gmail.com)
*
*/
/*
* This file has been modified by GMVIS Skysoft S.A.
*/
#include <stdio.h>
#include <bsp.h>
#include "noc.h"
// Structure to model the network interface
static struct network_interface
{
volatile int _IODEV *dma;
volatile int _IODEV *dma_p;
volatile int _IODEV *st;
} noc_interface = {
NOC_DMA_BASE, NOC_DMA_P_BASE, NOC_ST_BASE
};
// Configure network interface according to initialization information
void noc_configure(void) {
int row_size = NOC_TIMESLOTS > NOC_DMAS ? NOC_TIMESLOTS : NOC_DMAS;
int core_idx = CORE_ID * NOC_TABLES * row_size;
for (unsigned i = 0; i < NOC_TIMESLOTS; ++i) {
*(noc_interface.st+i) = noc_init_array[core_idx + i];
}
for (unsigned i = 0; i < NOC_DMAS; ++i) {
*(noc_interface.dma_p+i) = noc_init_array[core_idx + row_size + i];
}
}
// Synchronize start-up
static void noc_sync(void) {
if (CORE_ID == NOC_MASTER) {
// Wait until all slaves have configured their network interface
int done = 0;
do {
done = 1;
for (unsigned i = 0; i < MAX_CORES; i++) {
if (boot_info->slave[i].status != STATUS_NULL &&
boot_info->slave[i].status != STATUS_INITDONE) {
done = 0;
}
}
} while (!done);
// TODO: start up network
// Notify slaves that the network is started
boot_info->master.status = STATUS_INITDONE;
} else {
// Notify master that network interface is configured
boot_info->slave[CORE_ID].status = STATUS_INITDONE;
// Wait until master has started the network
while (boot_info->master.status != STATUS_INITDONE) {
/* spin */
}
}
}
// Initialize the NoC
void noc_init(void) {
/* if (CORE_ID == NOC_MASTER) puts("noc_configure"); */
noc_configure();
/* if (CORE_ID == NOC_MASTER) puts("noc_sync"); */
noc_sync();
/* if (CORE_ID == NOC_MASTER) puts("noc_done"); */
}
// Start a NoC transfer
// The addresses and the size are in double-words and relative to the
// communication SPM
int noc_dma(unsigned rcv_id,
unsigned short write_ptr,
unsigned short read_ptr,
unsigned short size) {
// Ony send if previous transfer is done
unsigned status = *(noc_interface.dma+(rcv_id<<1));
if ((status & NOC_VALID_BIT) != 0 && (status & NOC_DONE_BIT) == 0) {
return 0;
}
// Read pointer and write pointer in the dma table
*(noc_interface.dma+(rcv_id<<1)+1) = (read_ptr << 16) | write_ptr;
// DWord count and valid bit, done bit cleared
*(noc_interface.dma+(rcv_id<<1)) = (size | NOC_VALID_BIT) & ~NOC_DONE_BIT;
return 1;
}
// Convert from byte address or size to double-word address or size
#define DW(X) (((X)+7)/8)
// Transfer data via the NoC
// The addresses and the size are in bytes
void noc_send(int dst_id, volatile void _SPM *dst,
volatile void _SPM *src, size_t len) {
unsigned wp = (char *)dst - (char *)NOC_SPM_BASE;
unsigned rp = (char *)src - (char *)NOC_SPM_BASE;
while(!noc_dma(dst_id, DW(wp), DW(rp), DW(len)));
}

View File

@@ -0,0 +1,162 @@
/*
Copyright 2014 Technical University of Denmark, DTU Compute.
All rights reserved.
This file is part of the time-predictable VLIW processor Patmos.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are
those of the authors and should not be interpreted as representing official
policies, either expressed or implied, of the copyright holder.
*/
/**
* \file noc.h Definitions for libnoc.
*
* \author Wolfgang Puffitsch <wpuffitsch@gmail.com>
*
*/
/*
* This file has been modified by GMVIS Skysoft S.A.
*/
#ifndef _NOC_H_
#define _NOC_H_
#include <bsp.h>
////////////////////////////////////////////////////////////////////////////
// Definitions used for initialization of network interface
////////////////////////////////////////////////////////////////////////////
/// The CPU ID
#define CORE_ID *((_iodev_ptr_t) __PATMOS_CPU_ID_ADDR)
/// \brief The number of cores on the platform.
///
/// Defined by the application
extern const int NOC_CORES;
/// \brief The number of tables for Noc configuration.
///
/// Defined by the application
extern const int NOC_TABLES;
/// \brief The number of timeslots in the schedule.
///
/// Defined by the application
extern const int NOC_TIMESLOTS;
/// \brief The number of DMAs in the configuration.
///
/// Defined by the application
extern const int NOC_DMAS;
/// \brief The array for initialization data.
///
/// Defined by the application
extern const int noc_init_array [];
/// \brief The master core, which governs booting and startup synchronization.
///
/// Defined by the application
extern const int NOC_MASTER;
/// \brief Configure network interface according to initialization
/// information in #noc_init_array.
void noc_configure(void);
/// \brief Configure network-on-chip and synchronize all cores.
///
/// #noc_init is a static constructor and not intended to be called directly.
void noc_init(void) __attribute__((constructor,used));
////////////////////////////////////////////////////////////////////////////
// Functions for transmitting data
////////////////////////////////////////////////////////////////////////////
/// \brief Start a NoC transfer.
///
/// The addresses and the size are in double-words and relative to the
/// communication SPM base #NOC_SPM_BASE.
/// \param rcv_id The core id of the receiver.
/// \param write_ptr The address in the receiver's communication SPM,
/// in double-words, relative to #NOC_SPM_BASE.
/// \param read_ptr The address in the sender's communication SPM, in
/// double-words, relative to #NOC_SPM_BASE.
/// \param size The size of data to be transferred, in double-words.
/// \returns 1 if sending was successful, 0 otherwise.
int noc_dma(unsigned rcv_id, unsigned short write_ptr,
unsigned short read_ptr, unsigned short size);
/// \brief Transfer data via the NoC.
///
/// The addresses and the size are absolute and in bytes.
/// \param rcv_id The core id of the receiver.
/// \param dst A pointer to the destination of the transfer.
/// \param src A pointer to the source of the transfer.
/// \param size The size of data to be transferred, in bytes.
void noc_send(int rcv_id, volatile void _SPM *dst,
volatile void _SPM *src, size_t size);
////////////////////////////////////////////////////////////////////////////
// Definitions for setting up a transfer
////////////////////////////////////////////////////////////////////////////
/// The flag to mark a DMA entry as valid
#define NOC_VALID_BIT 0x08000
/// The flag to mark a DMA entry as done
#define NOC_DONE_BIT 0x04000
////////////////////////////////////////////////////////////////////////////
// Boot data definitions
////////////////////////////////////////////////////////////////////////////
#define MAX_CORES 64
#define STATUS_NULL 0
#define STATUS_BOOT 1
#define STATUS_INIT 2
#define STATUS_INITDONE 3
struct master_info_t {
volatile entrypoint_t entrypoint;
volatile int status;
};
struct slave_info_t {
volatile int status;
};
struct boot_info_t {
struct master_info_t master;
struct slave_info_t slave[MAX_CORES];
};
/* Place boot info at the beginning of the memory. Nothing else may be
placed there. */
#define boot_info ((_UNCACHED struct boot_info_t *)0x00000010)
#endif /* _NOC_H_ */

View File

@@ -21,6 +21,7 @@ noinst_PROGRAMS =
include_HEADERS += include/tcrest.h
include_HEADERS += ../../shared/include/coverhd.h
include_HEADERS += ../shared/noc/noc.h
noinst_LIBRARIES = libbspstart.a
libbspstart_a_SOURCES = ../../patmos/shared/startup/start.S
@@ -43,6 +44,8 @@ libbsp_a_SOURCES += ../shared/console/console.c
libbsp_a_SOURCES += ../shared/console/debugputs.c
# clock
libbsp_a_SOURCES += ../shared/clock/ckinit.c ../../../shared/clockdrv_shell.h
# noc
libbsp_a_SOURCES += ../shared/noc/noc.c
# timer
libbsp_a_SOURCES += ../shared/timer/timer.c

View File

@@ -35,6 +35,22 @@ extern "C" {
typedef _IODEV unsigned int volatile * const _iodev_ptr_t;
/*
* Attribute for pointers into the scratchpad memory. Use as
*
* _SPM int *p = (_SPM int *) 0x1234;
*
*/
#define _SPM __attribute__((address_space(1)))
/*
* Attribute for pointers into main memory using cache bypass. Use as
*
* _UNCACHED int *p = (_UNCACHED int *) &mydata;
*/
#define _UNCACHED __attribute__((address_space(3)))
typedef volatile int (*entrypoint_t)(void);
/*
* CPU Info Management
@@ -179,6 +195,25 @@ extern char _excunit_base; /* linker symbol giving the base address of the excep
* End of Exception Management
*/
/*
* NOC Management
*
* TODO: replace these by linker symbols
*/
/* The base address for DMA entries */
#define NOC_DMA_BASE ((volatile int _IODEV *)0xE0000000)
/* The base address for DMA routing information */
#define NOC_DMA_P_BASE ((volatile int _IODEV *)0xE1000000)
/* The base address for the slot table */
#define NOC_ST_BASE ((volatile int _IODEV *)0xE2000000)
/* The base address of the communication SPM */
#define NOC_SPM_BASE ((volatile int _SPM *)0xE8000000)
/*
* End of NOC Management
*/
#endif /* !ASM */
#ifdef __cplusplus

View File

@@ -61,6 +61,10 @@ $(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
$(PROJECT_INCLUDE)/noc.h: ../shared/noc/noc.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/noc.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/noc.h
$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT)
TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT)