Commit f7d3d1d5 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

initial commit, no documentation

parents
CC=/acc/sys/L865/cdk/gcc -m32
CXX=/acc/sys/L865/cdk/g++ -m32
CFLAGS = -I. -g
CXXFLAGS = -I. -g
OBJS = wrn-lib.o fmc-lib.o list-lib.o
all: lib test-rx
lib: $(OBJS)
ar rc libwrn.a $(OBJS)
test-rx: test-rx.o
${CXX} -o test-rx test-rx.o $(OBJS) -L. -lwrn -lpthread
clean:
rm -f $(OBJS) libwrn.a test-rx
%.o: %.cpp
${CXX} -o $@ -c $^ $(CXXFLAGS)
\ No newline at end of file
/* A simple console for accessing the SVEC virtual UART (i.e. for communicating with the WR Core shell
from a Linux terminal. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <getopt.h>
#include <errno.h>
#include "fmc-lib.h"
#include <pthread.h>
struct svec_dev {
int lun;
pthread_mutex_t lock;
};
static void svec_lock( struct svec_dev *dev )
{
pthread_mutex_lock(&dev->lock);
}
static void svec_unlock( struct svec_dev *dev )
{
pthread_mutex_unlock(&dev->lock);
}
static uint8_t generic_readb(struct fmc_dev *dev, uint64_t addr)
{
uint32_t rv = dev->readl(dev, addr & ~3);
return (rv >> (( 3 - addr & 3) * 8 )) & 0xff;
}
static uint16_t generic_readh(struct fmc_dev *dev, uint64_t addr)
{
uint16_t l = generic_readb(dev, addr + 1);
uint16_t h = generic_readb(dev, addr + 0);
return (h << 8) | l;
}
static uint64_t generic_readq(struct fmc_dev *dev, uint64_t addr)
{
uint64_t l = dev->readl(dev, addr + 4);
uint64_t h = dev->readl(dev, addr + 0);
return (h << 32) | l;
}
static uint32_t svec_readl(struct fmc_dev *dev, uint64_t addr)
{
int addr_fd, data_fd;
struct svec_dev *svec = (struct svec_dev *) dev->priv;
char str[1024];
svec_lock(svec);
sprintf(str,"/sys/bus/vme/devices/svec.%d/vme_addr", svec->lun);
addr_fd = open(str, O_RDWR);
sprintf(str,"/sys/bus/vme/devices/svec.%d/vme_data", svec->lun);
data_fd = open(str, O_RDWR);
if(addr_fd < 0 || data_fd < 0)
{
fprintf(stderr, "can't open SVEC at LUN %d: ", svec->lun);
perror("open()");
exit(-1);
}
sprintf(str,"0x%x\n", addr);
write(addr_fd, str, strlen(str) + 1);
int n = read(data_fd, str, sizeof(str));
uint32_t data;
close(addr_fd);
close(data_fd);
svec_unlock(svec);
if(n <= 0)
{
perror("read()");
exit(-1);
}
str[n] = 0;
sscanf(str, "%x", &data);
return data;
}
static void svec_writel(struct fmc_dev *dev, uint32_t data, uint64_t addr)
{
struct svec_dev *svec = (struct svec_dev *) dev->priv;
int addr_fd;
int data_fd;
char str[256];
svec_lock(svec);
sprintf(str,"/sys/bus/vme/devices/svec.%d/vme_addr", svec->lun);
addr_fd = open(str, O_RDWR);
sprintf(str,"/sys/bus/vme/devices/svec.%d/vme_data", svec->lun);
data_fd = open(str, O_RDWR);
if(addr_fd < 0 || data_fd < 0)
{
fprintf(stderr, "can't open SVEC at LUN %d: ", svec->lun);
perror("open()");
exit(-1);
}
sprintf(str,"0x%x\n", addr);
write(addr_fd, str, strlen(str) + 1);
sprintf(str,"0x%x\n", data);
write(data_fd, str, strlen(str) + 1);
close(addr_fd);
close(data_fd);
svec_unlock(svec);
}
static void *load_binary ( const char *filename, int *size )
{
FILE *f=fopen(filename,"rb");
if(!f)
return NULL;
fseek(f,0,SEEK_END);
int s = ftell(f);
rewind(f);
char *buf = malloc(s);
if(!buf)
{
fclose(f);
return NULL;
}
fread(buf,1,s,f);
*size=s;
fclose(f);
return buf;
}
static int svec_sysfs_write(struct svec_dev *svec, const char *file, char *buf, int size)
{
int fd;
char str[256];
sprintf(str,"/sys/bus/vme/devices/svec.%d/%s", svec->lun, file);
fd = open(str, O_RDWR);
int rv = write(fd, buf, size);
close(fd);
return rv;
}
static int svec_reprogram ( struct fmc_dev *dev, const char *filename )
{
struct svec_dev *svec = (struct svec_dev *) dev->priv;
int remaining;
char *buf = load_binary (filename, &remaining );
const int chunk_size = 2048;
char *p = buf;
if(!buf)
return -1;
svec_sysfs_write(svec, "firmware_cmd", "0\n", 2);
while(remaining > 0)
{
int n = remaining > chunk_size ? chunk_size : remaining;
svec_sysfs_write(svec, "firmware_blob", p, n);
remaining -= n;
p += n;
}
svec_sysfs_write(svec, "firmware_cmd", "1\n", 2);
free(buf);
return 0;
}
#define INTERCONNECT 0
#define DEVICE 1
#define BRIDGE 2
static uint32_t sdb_traverse (struct fmc_dev *dev, uint32_t base, uint32_t sdb_addr, uint64_t vendor, uint32_t device)
{
uint32_t addr = sdb_addr;
if(dev->readl(dev, addr) != 0x5344422d)
return -1;
if(dev->readb(dev, addr + 0x3f) != INTERCONNECT)
return -1;
int rec_count = dev->readh(dev, addr + 4);
int i;
for (i=0;i<rec_count;i++)
{
int t = dev->readb(dev, addr + 0x3f);
switch(t)
{
case BRIDGE:
{
uint64_t child_sdb = dev->readq(dev, addr);
uint64_t child_addr = dev->readq(dev, addr + 8);
uint32_t rv = sdb_traverse (dev, base + child_addr, base + child_sdb, vendor, device);
if(rv != -1)
return rv;
break;
}
case DEVICE:
{
uint64_t dev_addr = base + dev->readq(dev, addr + 8);
uint64_t dev_vendor = dev->readq(dev, addr + 24);
uint32_t dev_id_sdb = dev->readl(dev, addr + 32);
if(dev_vendor == vendor && dev_id_sdb == device)
return dev_addr;
break;
}
}
addr += 0x40;
}
return -1;
}
static uint32_t generic_sdb_find_device ( struct fmc_dev * dev, uint64_t vendor, uint32_t dev_id, int ordinal )
{
return sdb_traverse(dev, 0, 0, vendor, dev_id);
}
struct fmc_dev *fmc_svec_create(int lun)
{
int fd;
char str[256];
sprintf(str,"/sys/bus/vme/devices/svec.%d/vme_addr", lun);
fd = open(str, O_RDWR);
if(fd < 0)
return NULL;
struct fmc_dev *dev =malloc(sizeof(struct fmc_dev));
struct svec_dev *svec =malloc(sizeof(struct svec_dev));
dev->priv =svec;
dev->readl = svec_readl;
dev->writel = svec_writel;
dev->readb = generic_readb;
dev->readh = generic_readh;
dev->readq = generic_readq;
dev->reprogram = svec_reprogram;
dev->sdb_find_device = generic_sdb_find_device;
svec->lun = lun;
pthread_mutex_init(&svec->lock, NULL);
return dev;
}
#ifndef __FMC_LIB_H
#define __FMC_LIB_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// use DMA when reading/writing the block
#define FMC_BLK_DMA_ENABLE (1<<0)
// don't increment DMA device address (not all plaftorms)
#define FMC_BLK_DMA_NO_INCREMENT (1<<1)
//
#define FMC_IRQ_USE_VIC (1<<0)
#define FMC_PGM_PROGRAMMED 1
#define FMC_PGM_BOOTLOADER_MODE 2
#define FMC_PGM_UNPROGRAMMED -1
#define FMC_MEM_MEZZANINE_EEPROM(x)
#define FMC_MEM_CARRIER_EEPROM(x)
#define FMC_MEM_CARRIER_FLASH(x)
struct fmc_dev {
void (*writeb) ( struct fmc_dev *, uint8_t, uint64_t addr );
void (*writeh) ( struct fmc_dev *, uint16_t, uint64_t addr );
void (*writel) ( struct fmc_dev *, uint32_t, uint64_t addr );
void (*writeq) ( struct fmc_dev *, uint64_t, uint64_t addr );
uint8_t (*readb) ( struct fmc_dev *, uint64_t addr );
uint16_t (*readh) ( struct fmc_dev *, uint64_t addr );
uint32_t (*readl) ( struct fmc_dev *, uint64_t addr );
uint64_t (*readq) ( struct fmc_dev *, uint64_t addr );
int (*read_block) ( struct fmc_dev *, uint64_t addr, void *buf, size_t size, int flags );
int (*write_block) ( struct fmc_dev *, uint64_t addr, void *buf, size_t size, int flags );
int (*reprogram) ( struct fmc_dev*, const char *filename );
int (*reprogram_raw) ( struct fmc_dev*, int device, const void *buf, size_t size );
int (*is_programmed) ( struct fmc_dev * );
int (*enter_bootloader) (struct fmc_dev * );
int (*read_nv) (struct fmc_dev *, int mem, uint64_t address, void *data, size_t size );
int (*write_nv) (struct fmc_dev *, int mem, uint64_t address, void *data, size_t size );
int (*flush_nv) ( struct fmc_dev *, int mem );
uint32_t (*sdb_find_device) ( struct fmc_dev *, uint64_t vendor, uint32_t dev_id, int ordinal );
int (*enable_irq) ( struct fmc_dev *, int irq_id, int enable, int flags );
int (*wait_irq) ( struct fmc_dev *, int irq_id, int flags, int timeout_us );
void * priv;
};
struct fmc_dev *fmc_svec_create(int lun);
// path format:
// svec:slot=NUM,lun=NUM
// spec:bus=NUM,dev=NUM
// etherbone:ip=IP_ADDR,port=PORT,interface=NETWORK_CARD
// raw:base=ADDR,size=SIZE
struct fmc_dev *fmc_open( const char *path );
#ifdef __cplusplus
};
#endif
#endif
#ifndef __MQUEUE_H
#define __MQUEUE_H
#define BASE_HMQ 0x00000
#define MQUEUE_GCR ( 0x0)
#define MQUEUE_IN(slot) ( 0x4000 + (slot) * 0x400)
#define MQUEUE_OUT(slot) ( 0x8000 + (slot) * 0x400)
#define MQUEUE_CMD_CLAIM (1<<24)
#define MQUEUE_CMD_PURGE (1<<25)
#define MQUEUE_CMD_READY (1<<26)
#define MQUEUE_CMD_DISCARD (1<<27)
#define MQUEUE_SLOT_COMMAND 0
#define MQUEUE_SLOT_STATUS 4
#define MQUEUE_SLOT_DATA_START 8
#define MQUEUE_GCR_INCOMING_STATUS_MASK (0x0000ffff)
#define MQUEUE_GCR_SLOT_COUNT 0
#define MQUEUE_GCR_SLOT_STATUS 4
#define MQUEUE_GCR_IRQ_MASK 8
#define MQUEUE_GCR_IRQ_COALESCE 12
#define MQUEUE_SLOT_STATUS_FULL (1<<0)
#endif
/*
Register definitions for slave core: WR Node CPU Control/Status registers block
* File : wrn_cpu_csr.h
* Author : auto-generated by wbgen2 from wrn_cpu_csr.wb
* Created : Wed Apr 30 14:41:11 2014
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrn_cpu_csr.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WRN_CPU_CSR_WB
#define __WBGEN2_REGDEFS_WRN_CPU_CSR_WB
#include <stdint.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Application ID Register */
/* definitions for register: CPU Reset Register */
/* definitions for register: CPU Enable Register */
/* definitions for register: CPU Upload Address Register */
/* definitions for field: Address in reg: CPU Upload Address Register */
#define WRN_CPU_CSR_UADDR_ADDR_MASK WBGEN2_GEN_MASK(0, 20)
#define WRN_CPU_CSR_UADDR_ADDR_SHIFT 0
#define WRN_CPU_CSR_UADDR_ADDR_W(value) WBGEN2_GEN_WRITE(value, 0, 20)
#define WRN_CPU_CSR_UADDR_ADDR_R(reg) WBGEN2_GEN_READ(reg, 0, 20)
/* definitions for register: Core Select Register */
/* definitions for register: Core Count Register */
/* definitions for register: Core Memory Size */
/* definitions for register: CPU Upload Data Register */
/* definitions for register: CPU Debug Register */
/* definitions for field: JTAG data in reg: CPU Debug Register */
#define WRN_CPU_CSR_DEBUG_JDATA_MASK WBGEN2_GEN_MASK(0, 8)
#define WRN_CPU_CSR_DEBUG_JDATA_SHIFT 0
#define WRN_CPU_CSR_DEBUG_JDATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define WRN_CPU_CSR_DEBUG_JDATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for field: JTAG address in reg: CPU Debug Register */
#define WRN_CPU_CSR_DEBUG_JADDR_MASK WBGEN2_GEN_MASK(8, 3)
#define WRN_CPU_CSR_DEBUG_JADDR_SHIFT 8
#define WRN_CPU_CSR_DEBUG_JADDR_W(value) WBGEN2_GEN_WRITE(value, 8, 3)
#define WRN_CPU_CSR_DEBUG_JADDR_R(reg) WBGEN2_GEN_READ(reg, 8, 3)
/* definitions for field: JTAG reset in reg: CPU Debug Register */
#define WRN_CPU_CSR_DEBUG_RSTN WBGEN2_GEN_MASK(16, 1)
/* definitions for field: JTAG TCK in reg: CPU Debug Register */
#define WRN_CPU_CSR_DEBUG_TCK WBGEN2_GEN_MASK(17, 1)
/* definitions for field: JTAG Update in reg: CPU Debug Register */
#define WRN_CPU_CSR_DEBUG_UPDATE WBGEN2_GEN_MASK(18, 1)
/* [0x0]: REG Application ID Register */
#define WRN_CPU_CSR_REG_APP_ID 0x00000000
/* [0x4]: REG CPU Reset Register */
#define WRN_CPU_CSR_REG_RESET 0x00000004
/* [0x8]: REG CPU Enable Register */
#define WRN_CPU_CSR_REG_ENABLE 0x00000008
/* [0xc]: REG CPU Upload Address Register */
#define WRN_CPU_CSR_REG_UADDR 0x0000000c
/* [0x10]: REG Core Select Register */
#define WRN_CPU_CSR_REG_CORE_SEL 0x00000010
/* [0x14]: REG Core Count Register */
#define WRN_CPU_CSR_REG_CORE_COUNT 0x00000014
/* [0x18]: REG Core Memory Size */
#define WRN_CPU_CSR_REG_CORE_MEMSIZE 0x00000018
/* [0x1c]: REG CPU Upload Data Register */
#define WRN_CPU_CSR_REG_UDATA 0x0000001c
/* [0x20]: REG CPU Debug Register */
#define WRN_CPU_CSR_REG_DEBUG 0x00000020
#endif
#include <stdarg.h>
#include <errno.h>
#include "wrn-lib.h"
#include "list-lib.h"
#define TDC_APPLICATION "rt/tdc/rt-tdc.bin"
#define FD_APPLICATION "rt/tdc/rt-fd.bin"
#define WRN_APPID_LIST_TDC_FD 0x115790de
#define WRN_APPID_LIST_DUAL_FD 0x115790df
struct list_node {
uint32_t appid;
int n_inputs;
int n_outputs;
int fd_cpu_control[2];
struct wrn_dev *wrn;
};
static int rt_request ( struct list_node *node, int cpu, int command, uint32_t *req, int req_size, uint32_t *rsp )
{
uint32_t buf[128];
buf[0] = command;
buf[1] = 0;
if(req_size)
memcpy(buf + 2, req, req_size * 4);
wrn_send ( node->wrn, node->fd_cpu_control[cpu], buf, req_size + 2, 0);
int n = wrn_recv ( node->wrn, node->fd_cpu_control[cpu], buf, 128, 0);
if(rsp)
memcpy(rsp, buf, n * 4);
return n;
}
static int rt_requestf ( struct list_node *node, int cpu, int command, int n_args, ... )
{
va_list ap;
va_start( ap, n_args);
uint32_t req[128], rsp[128];
int i;
for(i = 0; i < n_args; i++ )
req[i] = va_arg(ap, uint32_t);
va_end(ap);
int n = rt_request (node, cpu, command, req, n_args, rsp);
if(n == 2 && rsp[0] == ID_REP_ACK)
return 0;
else
return -1;
}
#if 0
static int check_node_running( struct list_node *dev )
{
uint32_t rsp[2];
if ( cpu_cmd( n, 0, ID_TDC_CMD_PING, NULL, 0, rsp) == 2);
return rsp[0] == ID_TDC
}
#endif
struct list_node* list_open_node_by_lun(int lun)
{
if ( wrn_lib_init() < 0)
return NULL;
struct wrn_dev *wrn = wrn_open_by_lun( lun );
printf("open-node : %d %p ",lun, wrn);
if(!wrn)
return NULL;
uint32_t app_id = wrn_get_app_id(wrn);
struct list_node *n = malloc(sizeof(struct list_node));
n->wrn = wrn;
switch(app_id)
{
case WRN_APPID_LIST_DUAL_FD:
break;
case WRN_APPID_LIST_TDC_FD:
n->n_inputs = 5;
n->n_outputs = 4;
wrn_cpu_stop(wrn, 0xff);
wrn_cpu_load_file(wrn, 0, TDC_APPLICATION);
wrn_cpu_start(wrn, 0x1);
n->fd_cpu_control[0] = wrn_open_slot ( wrn, 0, WRN_SLOT_OUTGOING | WRN_SLOT_INCOMING );
printf("open_slot: cpu 0 control fd %d\n", n->fd_cpu_control[0]);
break;
}
return n;
}
int list_in_enable(struct list_node *dev, int input, int enable)
{
if(input < 1 || input > 5)
return -EINVAL;
return rt_requestf (dev, 0, ID_TDC_CMD_CHAN_ENABLE, 2, input - 1, enable ? 1 : 0 );
}
int list_in_set_dead_time ( struct list_node *dev, int input, uint64_t dead_time_ps )
{
int dead_time_cycles = dead_time_ps / 8000;
if(dead_time_cycles < 10000 || dead_time_cycles > 10000000 )
return -EINVAL;
if(input < 1 || input > 5)
return -EINVAL;
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_DEAD_TIME, 2, input-1, dead_time_cycles);
}
int list_in_software_trigger ( struct list_node* dev, struct list_trigger_entry *trigger )
{
uint32_t rsp[128];
int n = rt_request(dev, 0, ID_TDC_CMD_SOFTWARE_TRIGGER, (uint32_t *) trigger, sizeof(struct list_trigger_entry) / 4, rsp);
if(n == 2 && rsp[0] == ID_REP_ACK)
return 0;
else
return -1;
}
int list_in_assign_trigger ( struct list_node *dev, int input, struct list_id *trig )
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ASSIGN_TRIGGER, 4, input - 1, trig->system, trig->source_port, trig->trigger);
}
int list_in_set_trigger_mode ( struct list_node *dev, int input, int mode )
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_SET_MODE, 2, input - 1 , mode );
}
int list_in_arm ( struct list_node *dev, int input, int armed )
{
return rt_requestf(dev, 0, ID_TDC_CMD_CHAN_ARM, 2, input - 1, armed ? 1 : 0 );
}
#ifndef __LIST_LIB_H
#define __LIST_LIB_H
#include <stdio.h>
#include <stdlib.h>
#include "rt/common/rt-common.h"
struct list_node;
struct list_node* list_open_node_by_lun(int lun);
void list_close_node ( struct list_node *n );
int list_in_enable(struct list_node *dev, int input, int enable);
int list_in_assign_trigger ( struct list_node *, int input, struct list_id *trig );
int list_in_set_trigger_mode ( struct list_node *, int input, int mode );
int list_in_arm ( struct list_node *, int input, int armed );
int list_in_check_triggered ( struct list_node *, int input );
int list_in_set_mode ( struct list_node *, int input, int mode );
int list_in_set_port_id ( struct list_node *, int input, uint32_t id);
int list_in_wait_trigger ( struct list_node*, int input_mask, struct list_id *id );
int list_in_read_raw ( struct list_node*, int input_mask, struct list_timestamp *ts, int count );
int list_in_read_log ( struct list_node*, int input_mask, struct list_input_log_entry *ts, int count );
int list_in_software_trigger ( struct list_node*, struct list_trigger_entry *trigger );
int list_in_set_delay (struct list_node *, int input, uint64_t delay_ps);
int list_in_get_state ( struct list_node *, int input, struct tdc_channel_state *state );
int list_in_reset_seq_counter (struct list_node *dev, int input);
int list_in_set_dead_time ( struct list_node *dev, int input, uint64_t dead_time_ps );
#endif
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2012 GSI (www.gsi.de)
* Author: Wesley W. Terpstra <w.terpstra@gsi.de>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <string.h>
#include <stdio.h>
#include "fmc-lib.h"
#define SDB_INTERCONNET 0x00
#define SDB_DEVICE 0x01
#define SDB_BRIDGE 0x02
#define SDB_EMPTY 0xFF
typedef struct pair64 {
uint32_t high;
uint32_t low;
} pair64_t;
struct sdb_empty {
int8_t reserved[63];
uint8_t record_type;
};
struct sdb_product {
pair64_t vendor_id;
uint32_t device_id;
uint32_t version;
uint32_t date;
int8_t name[19];
uint8_t record_type;
};
struct sdb_component {
pair64_t addr_first;
pair64_t addr_last;
struct sdb_product product;
};
struct sdb_device {
uint16_t abi_class;
uint8_t abi_ver_major;
uint8_t abi_ver_minor;
uint32_t bus_specific;
struct sdb_component sdb_component;
};
struct sdb_bridge {
pair64_t sdb_child;
struct sdb_component sdb_component;
};
struct sdb_interconnect {
uint32_t sdb_magic;
uint16_t sdb_records;
uint8_t sdb_version;
uint8_t sdb_bus_type;
struct sdb_component sdb_component;
};
typedef union sdb_record {
struct sdb_empty empty;
struct sdb_device device;
struct sdb_bridge bridge;
struct sdb_interconnect interconnect;
} sdb_record_t;
static unsigned int sdb_find_device(struct fmc_dev *dev, unsigned int base, unsigned int vendor, unsigned int devid)
{
sdb_record_t *record =
int records = record->interconnect.sdb_records;
int i;
for(i = 0; i < sizeof(struct sdb_record) / 4; i++)
{
}
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE) {
unsigned char *out =
find_device_deep(dev, base +
record->bridge.sdb_component.
addr_first.low,
base +
record->bridge.sdb_child.low,
devid);
if (out)
return out;
}
if (record->empty.record_type == SDB_DEVICE &&
record->device.sdb_component.product.device_id == devid &&
record->device.sdb_component.product.vendor_id.low == vendor) {
break;
}
}
if (i == records)
return 0;
return (unsigned char *)(base +
record->device.sdb_component.addr_first.low);
}
static void print_devices_deep(unsigned int base, unsigned int sdb)
{
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
char buf[20];
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE)
print_devices_deep(base +
record->bridge.sdb_component.
addr_first.low,
base +
record->bridge.sdb_child.low);
if (record->empty.record_type != SDB_DEVICE)
continue;
memcpy(buf, record->device.sdb_component.product.name, 19);
buf[19] = 0;
mprintf("%8x:%8x 0x%8x %s\n",
record->device.sdb_component.product.vendor_id.low,
record->device.sdb_component.product.device_id,
base + record->device.sdb_component.addr_first.low,
buf);
}
}
void sdb_print_devices(void)
{
mprintf("SDB memory map:\n");
print_devices_deep(0, SDB_ADDRESS);
mprintf("---\n");
}
void sdb_find_devices(void)
{
BASE_MINIC = find_device(0xab28633a);
BASE_EP = find_device(0x650c2d4f);
BASE_SOFTPLL = find_device(0x65158dc0);
BASE_PPS_GEN = find_device(0xde0d8ced);
BASE_SYSCON = find_device(0xff07fc47);
BASE_UART = find_device(0xe2d13d04);
BASE_ONEWIRE = find_device(0x779c5443);
BASE_ETHERBONE_CFG = find_device(0x68202b22);
}
#ifndef __MQUEUE_H
#define __MQUEUE_H
#define REG_LR_POLL 0x100000
#define HMQ_BASE 0x40010000
#define RMQ_BASE 0x40020000
#define MQ_GCR ( 0x0)
#define MQ_IN(slot) ( 0x4000 + (slot) * 0x400)
#define MQ_OUT(slot) ( 0x8000 + (slot) * 0x400)
#define MQ_CMD_CLAIM (1<<24)
#define MQ_CMD_PURGE (1<<25)
#define MQ_CMD_READY (1<<26)
#define MQ_CMD_DISCARD (1<<27)
#define MQ_SLOT_COMMAND 0
#define MQ_SLOT_STATUS 4
#define MQ_SLOT_DATA_START 8
struct rmq_message_addr {
uint32_t target_ip;
uint32_t target_port;
uint32_t target_offset;
};
static inline void mq_writel( int remote, uint32_t val, uint32_t reg )
{
if(remote)
* (volatile uint32_t * ) (RMQ_BASE + reg) = val ;
else
* (volatile uint32_t * ) (HMQ_BASE + reg) = val ;
}
static inline void mq_claim (int remote, int slot)
{
mq_writel ( remote, MQ_CMD_CLAIM, MQ_OUT(slot) + MQ_SLOT_COMMAND );
}
static inline void mq_send( int remote, int slot, int count)
{
mq_writel ( remote, MQ_CMD_READY | count, MQ_OUT(slot) + MQ_SLOT_COMMAND );
}
static inline void mq_discard (int remote, int slot)
{
mq_writel ( remote, MQ_CMD_DISCARD, MQ_IN(slot) );
}
static void *mq_map_out_buffer(int remote, int slot)
{
uint32_t base = remote ? RMQ_BASE : HMQ_BASE;
return (void *) (base + MQ_OUT (slot) + MQ_SLOT_DATA_START );
}
static void *mq_map_in_buffer(int remote, int slot)
{
uint32_t base = remote ? RMQ_BASE : HMQ_BASE;
return (void *) (base + MQ_IN (slot) + MQ_SLOT_DATA_START );
}
static inline uint32_t mq_poll()
{
return *(volatile uint32_t *) ( REG_LR_POLL );
}
#endif
#include <stdarg.h>
#define CONFIG_PRINT_BUFSIZE 128
extern int pp_printf(const char *fmt, ...)
__attribute__((format(printf,1,2)));
extern int pp_sprintf(char *s, const char *fmt, ...)
__attribute__((format(printf,2,3)));
extern int pp_vprintf(const char *fmt, va_list args);
extern int pp_vsprintf(char *buf, const char *, va_list)
__attribute__ ((format (printf, 2, 0)));
/* This is what we rely on for output */
extern int puts(const char *s);
/*
* Basic printf based on vprintf based on vsprintf
*
* Alessandro Rubini for CERN, 2011 -- public domain
* (please note that the vsprintf is not public domain but GPL)
*/
#include <stdarg.h>
#include <pp-printf.h>
static char print_buf[CONFIG_PRINT_BUFSIZE];
int pp_vprintf(const char *fmt, va_list args)
{
int ret;
ret = pp_vsprintf(print_buf, fmt, args);
puts(print_buf);
return ret;
}
int pp_sprintf(char *s, const char *fmt, ...)
{
va_list args;
int ret;
va_start(args, fmt);
ret = pp_vsprintf(s, fmt, args);
va_end(args);
return ret;
}
int pp_printf(const char *fmt, ...)
{
va_list args;
int ret;
va_start(args, fmt);
ret = pp_vprintf(fmt, args);
va_end(args);
return ret;
}
#ifndef __RT_COMMON_H
#define __RT_COMMON_H
#define TDC_IN_SLOT_CONTROL 0
#define TDC_OUT_SLOT_CONTROL 0
#define TDC_OUT_SLOT_LOGGING 1
#define TDC_OUT_SLOT_REMOTE 0
#define ID_TDC_LOG_RAW 0x1
#define ID_TDC_LOG_OUTGOING 0x2
#define ID_TDC_CMD_CHAN_ENABLE 0x1
#define ID_TDC_CMD_CHAN_SET_DEAD_TIME 0x2
#define ID_TDC_CMD_CHAN_SET_DELAY 0x3
#define ID_TDC_CMD_CHAN_GET_STATE 0x4
#define ID_TDC_CMD_CHAN_ARM 0x5
#define ID_TDC_CMD_CHAN_DISARM 0x6
#define ID_TDC_CMD_CHAN_SET_MODE 0x7
#define ID_TDC_CMD_CHAN_RESET_SEQ 0x8
#define ID_TDC_CMD_CHAN_ASSIGN_TRIGGER 0x9
#define ID_TDC_CMD_CHAN_SET_FLAGS 0xa
#define ID_TDC_CMD_CHAN_SET_TIMEBASE_OFFSET 0xb
#define ID_TDC_CMD_PING 0xc
#define ID_TDC_CMD_SOFTWARE_TRIGGER 0xd
#define ID_TDC_LOG_RAW_TIMESTAMP 0x102
#define ID_TDC_LOG_TRIGGER 0x103
#define ID_REP_ACK 0x100
#define ID_REP_STATE 0x101
#define TDC_NUM_CHANNELS 5
#define TDC_TRIGGER_COALESCE_LIMIT 5
#define TDC_CHAN_LOG_RAW (1<<0)
#define TDC_CHAN_LOG_TRIGGERS (1<<1)
#define TDC_CHAN_TRIGGER_ASSIGNED (1<<2)
#define TDC_CHAN_ARMED (1<<3)
#define TDC_CHAN_TRIGGERED (1<<4)
#define TDC_CHAN_ENABLED (1<<5)
#define TDC_CHAN_MODE_SINGLE 0
#define TDC_CHAN_MODE_CONTINUOUS 1
struct list_timestamp {
int32_t seconds;
int32_t cycles;
int32_t frac;
};
struct list_id
{
uint32_t system;
uint32_t source_port;
uint32_t trigger;
};
struct list_trigger_entry {
struct list_timestamp ts;
struct list_id id;
uint32_t seq;
};
#ifdef WRNODE_APP
struct list_trigger_message {
struct rmq_message_addr hdr;
uint32_t transmit_seconds;
uint32_t transmit_cycles;
int count;
struct list_trigger_entry triggers[TDC_TRIGGER_COALESCE_LIMIT];
};
#endif
struct tdc_channel_state {
struct list_id id;
struct list_timestamp delay;
struct list_timestamp timebase_offset;
struct list_timestamp last;
int32_t flags;
int32_t mode;
int32_t n;
int32_t total_pulses;
int32_t sent_pulses;
int32_t worst_latency;
uint32_t seq;
};
struct tdc_channel_state_msg
{
int seq;
struct tdc_channel_state state;
};
#endif
#include <stdarg.h>
/*
* minimal vsprintf: only %s and hex values
* Alessandro Rubini 2010, based on code in u-boot (from older Linux)
* GNU GPL version 2.
*/
int pp_vsprintf(char *buf, const char *fmt, va_list args)
{
int i, j;
static char hex[] = "0123456789abcdef";
char *s;
char *str = buf;
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
*str++ = *fmt;
continue;
}
repeat:
fmt++; /* Skip '%' initially, other stuff later */
/* Skip the complete format string */
switch(*fmt) {
case '\0':
goto ret;
case '*':
/* should be precision, just eat it */
i = va_arg(args, int);
/* fall through: discard unknown stuff */
default:
goto repeat;
/* Special cases for conversions */
case 'c': /* char: supported */
*str++ = (unsigned char) va_arg(args, int);
break;
case 's': /* string: supported */
s = va_arg(args, char *);
while (*s)
*str++ = *s++;
break;
case 'n': /* number-thus-far: not supported */
break;
case '%': /* supported */
*str++ = '%';
break;
/* all integer (and pointer) are printed as <%08x> */
case 'o':
case 'x':
case 'X':
case 'd':
case 'i':
case 'u':
case 'p':
i = va_arg(args, int);
*str++ = '<';
for (j = 28; j >= 0; j -= 4)
*str++ = hex[(i>>j)&0xf];
*str++ = '>';
break;
}
}
ret:
*str = '\0';
return str - buf;
}
/****************************************************************************
**
** Name: crt0ram.S
**
** Description:
** Implements boot-code that calls LatticeDDInit (that calls main())
** Implements exception handlers (actually, redirectors)
**
** $Revision: $
**
** Disclaimer:
**
** This source code is intended as a design reference which
** illustrates how these types of functions can be implemented. It
** is the user's responsibility to verify their design for
** consistency and functionality through the use of formal
** verification methods. Lattice Semiconductor provides no warranty
** regarding the use or functionality of this code.
**
** --------------------------------------------------------------------
**
** Lattice Semiconductor Corporation
** 5555 NE Moore Court
** Hillsboro, OR 97214
** U.S.A
**
** TEL: 1-800-Lattice (USA and Canada)
** (503)268-8001 (other locations)
**
** web: http://www.latticesemi.com
** email: techsupport@latticesemi.com
**
** --------------------------------------------------------------------------
**
** Change History (Latest changes on top)
**
** Ver Date Description
** --------------------------------------------------------------------------
** 3.8 Apr-15-2011 Added __MICO_USER_<handler>_HANDLER__ preprocessor to
** allow customers to implement their own handlers for:
** DATA_ABORT, INST_ABORT
**
** 3.1 Jun-18-2008 Added __MICO_NO_INTERRUPTS__ preprocessor
** option to exclude invoking MicoISRHandler
** to reduce code-size in apps that don't use
** interrupts
**
** 3.0 Mar-25-2008 Added Header
**
**---------------------------------------------------------------------------
*****************************************************************************/
/*
* LatticeMico32 C startup code.
*
* 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
*/
/* From include/sys/signal.h */
#define SIGINT 2 /* interrupt */
#define SIGTRAP 5 /* trace trap */
#define SIGFPE 8 /* arithmetic exception */
#define SIGSEGV 11 /* segmentation violation */
//#define MICO32_FULL_CONTEXT_SAVE_RESTORE
/* Exception handlers - Must be 32 bytes long. */
.section .boot, "ax", @progbits
.global _start
_start:
.global _reset_handler
.type _reset_handler, @function
_reset_handler:
xor r0, r0, r0
wcsr IE, r0
wcsr IM, r0
mvhi r1, hi(_reset_handler)
ori r1, r1, lo(_reset_handler)
wcsr EBA, r1
calli _crt0
nop
.size _reset_handler, .-_reset_handler
.extern _irq_entry
.org 0xc0
.global _interrupt_handler
.type _interrupt_handler, @function
_interrupt_handler:
nop
.org 0x100
.global _crt0
.type _crt0, @function
_crt0:
/* Clear r0 */
xor r0, r0, r0
xor r1, r1, r1
xor r2, r2, r2
xor r3, r3, r3
/* Setup stack and global pointer */
mvhi sp, hi(_fstack)
ori sp, sp, lo(_fstack)
mvhi gp, hi(_gp)
ori gp, gp, lo(_gp)
mvhi r1, hi(_fbss)
ori r1, r1, lo(_fbss)
mvi r2, 0
mvhi r3, hi(_ebss)
ori r3, r3, lo(_ebss)
sub r3, r3, r1
/* calli memset */
mvi r1, 0
mvi r2, 0
mvi r3, 0
calli main
loopf:
bi loopf
OUTPUT_FORMAT("elf32-lm32")
ENTRY(_start)
MEMORY
{
ram :
ORIGIN = 0x00000000,
LENGTH = 32768 - 2048
stack :
ORIGIN = 32768 - 2048,
LENGTH = 2048
}
SECTIONS
{
.boot : { *(.boot) } > ram
.text : { *(.text .text.*) } > ram =0
.rodata : { *(.rodata .rodata.*) } > ram
.data : {
*(.data .data.*)
_gp = ALIGN(16) + 0x7ff0;
} > ram
.bss : {
_fbss = .;
*(.bss .bss.*)
*(COMMON)
_ebss = .;
} > ram
PROVIDE(_endram = ORIGIN(stack));
PROVIDE(_fstack = ORIGIN(stack) + LENGTH(stack) - 4);
}
PROVIDE(mprintf = pp_printf);
# and don't touch the rest unless you know what you're doing.
CROSS_COMPILE ?= /user/twlostow/apps/gcc-lm32/bin/lm32-elf-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJDUMP = $(CROSS_COMPILE)objdump
OBJCOPY = $(CROSS_COMPILE)objcopy
SIZE = $(CROSS_COMPILE)size
CFLAGS = -g -Os -I. -I../common
OBJS += ../common/wrn-crt0.o ../common/vsprintf-mini.o ../common/printf.o
LDSCRIPT = ../common/wrnode.ld
$(OUTPUT): $(LDSCRIPT) $(OBJS)
${CC} -o $(OUTPUT).elf -nostartfiles $(OBJS) -T $(LDSCRIPT) -lgcc -lc
${OBJCOPY} -O binary $(OUTPUT).elf $(OUTPUT).bin
${OBJDUMP} -S $(OUTPUT).elf > disasm.S
$(SIZE) $(OUTPUT).elf
# ../genramvhd -p wrc_simulation_firmware $(OUTPUT).bin > wrc_simulation_firmware_pkg.vhd
# ../common/genraminit $(OUTPUT).bin > $(OUTPUT).ram
clean:
rm -f $(OBJS) $(OUTPUT).bin
\ No newline at end of file
OBJS = rt-tdc.o
OUTPUT = rt-tdc
include ../common/wrnode.mk
/*
Register definitions for slave core: TDC Direct Readout WB Slave
* File : fmctdc-direct.h
* Author : auto-generated by wbgen2 from fmc_tdc_direct_readout_slave.wb
* Created : Thu May 15 14:23:14 2014
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fmc_tdc_direct_readout_slave.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_FMC_TDC_DIRECT_READOUT_SLAVE_WB
#define __WBGEN2_REGDEFS_FMC_TDC_DIRECT_READOUT_SLAVE_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Channel Enable Register */
/* definitions for register: Dead Time Register */
/* definitions for register: FIFO 'Readout FIFO' data output register 0 */
/* definitions for field: Seconds in reg: FIFO 'Readout FIFO' data output register 0 */
#define DR_FIFO_R0_SECONDS_MASK WBGEN2_GEN_MASK(0, 32)
#define DR_FIFO_R0_SECONDS_SHIFT 0
#define DR_FIFO_R0_SECONDS_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define DR_FIFO_R0_SECONDS_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Readout FIFO' data output register 1 */
/* definitions for field: Cycles in reg: FIFO 'Readout FIFO' data output register 1 */
#define DR_FIFO_R1_CYCLES_MASK WBGEN2_GEN_MASK(0, 32)
#define DR_FIFO_R1_CYCLES_SHIFT 0
#define DR_FIFO_R1_CYCLES_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define DR_FIFO_R1_CYCLES_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Readout FIFO' data output register 2 */
/* definitions for field: Bins in reg: FIFO 'Readout FIFO' data output register 2 */
#define DR_FIFO_R2_BINS_MASK WBGEN2_GEN_MASK(0, 18)
#define DR_FIFO_R2_BINS_SHIFT 0
#define DR_FIFO_R2_BINS_W(value) WBGEN2_GEN_WRITE(value, 0, 18)
#define DR_FIFO_R2_BINS_R(reg) WBGEN2_GEN_READ(reg, 0, 18)
/* definitions for field: Edge in reg: FIFO 'Readout FIFO' data output register 2 */
#define DR_FIFO_R2_EDGE WBGEN2_GEN_MASK(18, 1)
/* definitions for field: Channel in reg: FIFO 'Readout FIFO' data output register 2 */
#define DR_FIFO_R2_CHANNEL_MASK WBGEN2_GEN_MASK(19, 4)
#define DR_FIFO_R2_CHANNEL_SHIFT 19
#define DR_FIFO_R2_CHANNEL_W(value) WBGEN2_GEN_WRITE(value, 19, 4)
#define DR_FIFO_R2_CHANNEL_R(reg) WBGEN2_GEN_READ(reg, 19, 4)
/* definitions for register: FIFO 'Readout FIFO' control/status register */
/* definitions for field: FIFO full flag in reg: FIFO 'Readout FIFO' control/status register */
#define DR_FIFO_CSR_FULL WBGEN2_GEN_MASK(16, 1)
/* definitions for field: FIFO empty flag in reg: FIFO 'Readout FIFO' control/status register */
#define DR_FIFO_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO counter in reg: FIFO 'Readout FIFO' control/status register */
#define DR_FIFO_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 8)
#define DR_FIFO_CSR_USEDW_SHIFT 0
#define DR_FIFO_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define DR_FIFO_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* [0x0]: REG Channel Enable Register */
#define DR_REG_CHAN_ENABLE 0x00000000
/* [0x4]: REG Dead Time Register */
#define DR_REG_DEAD_TIME 0x00000004
/* [0x8]: REG FIFO 'Readout FIFO' data output register 0 */
#define DR_REG_FIFO_R0 0x00000008
/* [0xc]: REG FIFO 'Readout FIFO' data output register 1 */
#define DR_REG_FIFO_R1 0x0000000c
/* [0x10]: REG FIFO 'Readout FIFO' data output register 2 */
#define DR_REG_FIFO_R2 0x00000010
/* [0x14]: REG FIFO 'Readout FIFO' control/status register */
#define DR_REG_FIFO_CSR 0x00000014
#endif
#define WRNODE_APP
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mqueue.h"
#include "hw/fmctdc-direct.h"
#include "pp-printf.h"
#include "rt-common.h"
#define TDC_CORE_BASE 0x200000
#define CPU_LR_BASE 0x100000
static inline uint32_t tdc_readl ( uint32_t reg )
{
return *(volatile uint32_t *) ( reg + TDC_CORE_BASE );
}
static inline uint32_t lr_readl ( uint32_t reg )
{
return *(volatile uint32_t *) ( reg + CPU_LR_BASE );
}
static inline void tdc_writel ( uint32_t value, uint32_t reg )
{
*(volatile uint32_t *) ( reg + TDC_CORE_BASE ) = value;
}
int puts(const char *p)
{
int i;
volatile uint32_t *buf = mq_map_out_buffer(0, 1);
mq_claim(0, 1);
buf[0] = 0xdeadbeef;
for(i=0;i<127;i++,p++)
{
if(*p)
buf[i+1] = *p;
else
break;
}
mq_send(0, 1, i + 1);
return i;
}
static void delay(int n)
{
int i;
for(i=0;i<n;i++) asm volatile("nop");
}
struct tdc_channel_state channels[TDC_NUM_CHANNELS];
static inline void ts_add(struct list_timestamp *a, const struct list_timestamp *b)
{
a->frac += b->frac;
if(a->frac >= 4096)
{
a->frac -= 4096;
a->cycles ++;
}
a->cycles += b->cycles;
if(a->cycles >= 125000000)
{
a->cycles -= 125000000;
a->seconds++;
}
a->seconds += b->seconds;
}
static inline void ts_sub(struct list_timestamp *a, const struct list_timestamp *b)
{
a->frac -= b->frac;
if(a->frac < 0)
{
a->frac += 4096;
a->cycles --;
}
a->cycles -= b->cycles;
if(a->cycles < 0)
{
a->cycles += 125000000;
a->seconds--;
}
a->seconds -= b->seconds;
}
struct list_log_message {
int type;
int channel;
struct list_timestamp ts;
uint32_t seq;
struct list_id id;
};
static inline void log_raw_timestamp (struct tdc_channel_state *ch, struct list_timestamp *ts)
{
struct list_log_message *msg = mq_map_out_buffer(1, TDC_OUT_SLOT_LOGGING);
msg->type = ID_TDC_LOG_RAW_TIMESTAMP;
msg->channel = ch->n;
}
static inline void send_trigger (struct tdc_channel_state *ch, struct list_timestamp *ts)
{
// struct tdc_channel_state *ch = &channels[channel];
struct list_trigger_message *msg = mq_map_out_buffer(1, TDC_OUT_SLOT_REMOTE);
mq_claim(1, TDC_OUT_SLOT_REMOTE);
msg->hdr.target_ip = 0xffffffff; // broadcast
msg->hdr.target_port = 0xebd0; // port
msg->hdr.target_offset = 0x20000;// target EB slot
msg->transmit_cycles = 0; //lr_readl();
msg->transmit_seconds = 0;
msg->count = 1;
msg->triggers[0].id = ch->id;
msg->triggers[0].seq = ch->seq;
msg->triggers[0].ts = *ts;
mq_send(1, TDC_OUT_SLOT_REMOTE, 20); // fixme
}
static inline void log_sent_trigger(struct tdc_channel_state *ch, struct list_timestamp *ts)
{
uint32_t *buf = mq_map_out_buffer(0, TDC_OUT_SLOT_LOGGING);
mq_claim(0, TDC_OUT_SLOT_LOGGING);
buf[0] = ch->n;
buf[1] = ch->seq;
buf[2] = ch->id.system;
buf[3] = ch->id.source_port;
buf[4] = ch->id.trigger;
buf[5] = 0;
buf[6] = 0;
buf[7] = ts->seconds;
buf[8] = ts->cycles;
buf[9] = ts->frac;
mq_send(0, TDC_OUT_SLOT_LOGGING, 10);
}
static inline void do_channel (int channel, struct list_timestamp *ts)
{
struct tdc_channel_state *ch = &channels[channel];
ts_sub(ts, &ch->timebase_offset);
ch->last = *ts;
if( ch->flags & TDC_CHAN_LOG_RAW )
log_raw_timestamp(ch, ts);
ts_add(ts, &ch->delay);
if( (ch->flags & TDC_CHAN_TRIGGER_ASSIGNED) && (ch->flags & TDC_CHAN_ARMED) )
{
ch->seq++;
ch->flags |= TDC_CHAN_TRIGGERED;
if(ch->mode == TDC_CHAN_MODE_SINGLE)
ch->flags &= ~TDC_CHAN_ARMED;
send_trigger(ch, ts);
log_sent_trigger(channel, ts);
}
}
static inline void do_input ()
{
uint32_t fifo_sr = tdc_readl (DR_REG_FIFO_CSR);
if(! (fifo_sr & DR_FIFO_CSR_EMPTY))
{
struct list_timestamp ts;
ts.seconds = tdc_readl(DR_REG_FIFO_R0);
ts.cycles = tdc_readl(DR_REG_FIFO_R1);
int meta = tdc_readl(DR_REG_FIFO_R2);
ts.frac = (meta & 0x3ffff) * 81 * 64 / 125;
ts.cycles += ts.frac >> 12;
ts.frac &= 0x3ff;
if (ts.cycles >= 125000000)
{
ts.cycles -= 125000000;
ts.seconds ++;
}
int channel = (meta >> 19) & 0x7;
do_channel( channel, &ts );
}
};
static inline uint32_t *ctl_claim_out()
{
mq_claim(0, TDC_OUT_SLOT_CONTROL);
return mq_map_out_buffer( 0, TDC_OUT_SLOT_CONTROL );
}
static inline void ctl_ack( uint32_t seq )
{
uint32_t *buf = ctl_claim_out();
buf[0] = ID_REP_ACK;
buf[1] = seq;
mq_send(0, TDC_OUT_SLOT_CONTROL, 2);
}
static inline void ctl_chan_enable (int seq, uint32_t *buf)
{
uint32_t mask = tdc_readl(DR_REG_CHAN_ENABLE);
int channel = buf[0];
int enable = buf[1];
if(enable)
mask |= (1<<channel);
else
mask &= ~(1<<channel);
tdc_writel(mask, DR_REG_CHAN_ENABLE);
ctl_ack(seq);
}
static inline void ctl_chan_set_dead_time (int seq, uint32_t *buf)
{
//pp_printf("SDT %d", buf[0]);
ctl_ack(seq);
}
static inline void ctl_ping (int seq, uint32_t *buf)
{
ctl_ack(seq);
}
static inline void ctl_chan_set_delay (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
ch->delay.seconds = buf[1];
ch->delay.cycles = buf[2];
ch->delay.frac = buf[3];
ctl_ack(seq);
}
static inline void ctl_chan_set_timebase_offset (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
ch->timebase_offset.seconds = buf[1];
ch->timebase_offset.cycles = buf[2];
ch->timebase_offset.frac = buf[3];
ctl_ack(seq);
}
static inline void ctl_chan_get_state (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
struct tdc_channel_state_msg *msg = (struct tdc_channel_state_msg *) ctl_claim_out();
msg->seq = seq;
msg->state = *ch;
}
static inline void ctl_software_trigger (int seq, uint32_t *buf)
{
struct list_trigger_message *msg = mq_map_out_buffer(1, TDC_OUT_SLOT_REMOTE);
mq_claim(1, TDC_OUT_SLOT_REMOTE);
msg->hdr.target_ip = 0xffffffff; // broadcast
msg->hdr.target_port = 0xebd0; // port
msg->hdr.target_offset = 0x20000;// target EB slot
msg->transmit_seconds = 0;
msg->transmit_cycles = 0;
msg->count = 1;
memcpy(&msg->triggers[0], buf, sizeof(struct list_trigger_entry) );
mq_send(1, TDC_OUT_SLOT_REMOTE, sizeof(struct list_trigger_message) / 4); // fixme
ctl_ack(seq);
}
static inline void ctl_chan_set_mode (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
ch->mode = buf[1];
ch->flags &= ~TDC_CHAN_ARMED;
ctl_ack(seq);
}
static inline void ctl_chan_arm (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
if(buf[1])
ch->flags |= TDC_CHAN_ARMED;
else
ch->flags &= ~TDC_CHAN_ARMED;
ctl_ack(seq);
}
static inline void ctl_chan_assign_trigger (int seq, uint32_t *buf)
{
int channel = buf[0];
struct tdc_channel_state *ch = &channels[channel];
ch->id.system = buf[1];
ch->id.source_port = buf[2];
ch->id.trigger = buf[3];
ch->flags |= TDC_CHAN_TRIGGER_ASSIGNED;
ctl_ack(seq);
}
static inline void do_control()
{
uint32_t p = mq_poll();
if(! ( p & ( 1<< TDC_IN_SLOT_CONTROL )))
return;
uint32_t *buf = mq_map_in_buffer( 0, TDC_IN_SLOT_CONTROL );
int cmd = buf[0];
int seq = buf[1];
#define _CMD(id, func) \
case id: \
{ \
func(seq, buf + 2); \
break; \
}
switch(cmd)
{
_CMD(ID_TDC_CMD_CHAN_ENABLE, ctl_chan_enable)
_CMD(ID_TDC_CMD_CHAN_SET_DEAD_TIME, ctl_chan_set_dead_time)
_CMD(ID_TDC_CMD_CHAN_SET_DELAY, ctl_chan_set_delay)
_CMD(ID_TDC_CMD_CHAN_SET_TIMEBASE_OFFSET, ctl_chan_set_timebase_offset)
_CMD(ID_TDC_CMD_CHAN_GET_STATE, ctl_chan_get_state)
_CMD(ID_TDC_CMD_SOFTWARE_TRIGGER, ctl_software_trigger)
_CMD(ID_TDC_CMD_CHAN_ASSIGN_TRIGGER, ctl_chan_assign_trigger)
_CMD(ID_TDC_CMD_CHAN_SET_MODE, ctl_chan_set_mode)
_CMD(ID_TDC_CMD_CHAN_ARM, ctl_chan_arm)
_CMD(ID_TDC_CMD_PING, ctl_ping)
default:
break;
}
mq_discard(0, TDC_IN_SLOT_CONTROL);
}
void init()
{
int i;
tdc_writel( 0x0, DR_REG_CHAN_ENABLE);
tdc_writel( 0x1, DR_REG_DEAD_TIME);
for(i=0;i<TDC_NUM_CHANNELS;i++)
{
memset(&channels[i], 0, sizeof(struct tdc_channel_state));
channels[i].n = i;
}
}
main()
{
int i = 0;
init();
pp_printf("RT_TDC firmware initialized.");
for(;;)
{
do_input();
do_control();
}
}
\ No newline at end of file
#include "fmc-lib.h"
main(int argc, char *argv[])
{
struct fmc_dev *fmc = fmc_svec_create(0);
fmc->reprogram(fmc, argv[1]);
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include "wrn-lib.h"
#include "list-lib.h"
main()
{
struct list_node *n = list_open_node_by_lun ( 0 );
struct list_id trig = { 10, 20, 30 };
//list_in_set_dead_time(n, 1, 90 * 1000 * 1000);
list_in_enable(n, 1, 1);
list_in_assign_trigger(n, 1, &trig);
list_in_set_trigger_mode(n, 1, TDC_CHAN_MODE_CONTINUOUS);
list_in_arm(n, 1, 1);
#if 0
struct list_trigger_entry t;
t.id.system = 0x1;
t.id.source_port = 0x1;
t.id.trigger = 0x3;
t.ts.seconds = 0x4;
t.ts.cycles = 0x5;
t.ts.frac = 0x6;
t.seq = 0;
for(;;)
{
list_in_software_trigger(n, &t);
t.seq++;
usleep(10000);
printf("swT\n");
}
#endif
sleep(1000);
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include "fmc-lib.h"
#include "wrn-lib.h"
//uint32_t sdb_traverse (struct fmc_dev *dev, uint32_t base, uint32_t sdb_addr, uint32_t vendor, uint32_t device);
void monitor_hmq()
{
}
main()
{
struct wrn_dev *node = wrn_open_by_lun(0);
wrn_cpu_load_file(node, 0, "rt/tdc/rt-tdc.bin");
wrn_cpu_start(node, (1<<0));
for(;;)
{
wrn_update_mqueues(node);
usleep(10000);
}
}
#ifndef __WRN_LIB_PRIVATE_H
#define __WRN_LIB_PRIVATE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>
#include "fmc-lib.h"
#define MAX_MQUEUE_SLOTS 16
#include <vector>
#include <deque>
#include <map>
typedef std::vector<uint32_t> wrn_message;
struct wrn_mqueue_slot {
int size;
int width;
};
struct wrn_mqueue {
int n_out;
int n_in;
std::vector<wrn_mqueue_slot> in;
std::vector<wrn_mqueue_slot> out;
};
struct wrn_buffer {
int slot;
int total;
wrn_buffer(int slot);
~wrn_buffer();
bool lock(bool blocking);
void unlock();
bool process ( const wrn_message& msg )
{
msgs.push_back(msg);
}
bool push ( const wrn_message& msg)
{
msgs.push_back(msg);
}
bool empty()
{
return msgs.empty();
}
wrn_message pop()
{
wrn_message rv = msgs.back();
msgs.pop_back();
return rv;
}
pthread_mutex_t mutex;
std::deque<wrn_message> msgs;
};
struct wrn_connection {
wrn_buffer *in;
wrn_buffer *out;
int flags;
int fd;
};
typedef std::map<int, wrn_connection *> wrn_connmap;
struct wrn_dev {
int lun;
const char *path;
uint32_t base;
uint32_t app_id;
int cpu_count;
struct wrn_mqueue hmq;
struct fmc_dev *fmc;
std::map<int, wrn_connection *> fds;
pthread_t update_thread;
};
#endif
This diff is collapsed.
#ifndef __WRN_LIB_H
#define __WRN_LIB_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
struct wrn_dev;
int wrn_lib_init();
void wrn_lib_exit();
int wrn_get_node_count();
struct wrn_dev* wrn_open_by_lun( int lun );
uint32_t wrn_get_app_id( struct wrn_dev *device );
int wrn_cpu_count( struct wrn_dev* dev);
int wrn_cpu_stop ( struct wrn_dev* dev, uint32_t mask );
int wrn_cpu_start ( struct wrn_dev * dev, uint32_t mask );
int wrn_cpu_reset ( struct wrn_dev *dev, uint32_t mask );
int wrn_cpu_load_application ( struct wrn_dev *dev, int cpu, const void *code, size_t code_size );
int wrn_cpu_load_file ( struct wrn_dev *dev, int cpu, const char *filename);
#define WRN_SLOT_INCOMING (1<<0) // sending messages to the CPUs
#define WRN_SLOT_OUTGOING (1<<1) // receiving messages from the CPUs
#define WRN_SLOT_EXCLUSIVE (1<<2)
int wrn_open_slot ( struct wrn_dev *, int slot, int flags );
void wrn_close_slot ( struct wrn_dev *, int slot );
#define WRN_FILTER_OR 0
#define WRN_FILTER_AND 1
#define WRN_FILTER_COMPARE 2
#define WRN_FILTER_NOT 3
struct wrn_message_filter {
struct rule {
int op;
int word_offset;
uint32_t mask;
uint32_t value;
struct rule *next;
} *rules;
int n_rules;
};
int wrn_bind ( struct wrn_dev *, int fd, struct wrn_message_filter *flt );
int wrn_wait ( struct wrn_dev *, int fd, int timeout_us );
int wrn_recv ( struct wrn_dev *, int fd, uint32_t *buffer, size_t buf_size, int timeout_us );
int wrn_send ( struct wrn_dev *, int fd, uint32_t *buffer, size_t buf_size, int timeout_us );
//void wrn_update_mqueues( struct wrn_dev * dev );
#ifdef __cplusplus
};
#endif
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment