Commit 475bc35d authored by Federico Vaga's avatar Federico Vaga

sw:rt redesign and re-organization

It compiles ... still to be tested, the HDL is not ready yet
parents c6c69f99 05f17114
......@@ -4,7 +4,6 @@
* License: GPLv3
*/
#include <mockturtle-rt-smem.h>
#include <mockturtle-framework.h>
static unsigned int iteration;
......@@ -13,31 +12,6 @@ static unsigned int period = 1000000;
static unsigned int alarm_enable;
static uint32_t alarm_iter;
enum rt_slot_name {
AC_CMD_IN = 0,
AC_CMD_OUT,
AC_DATA,
};
static struct rt_mq mq[] = {
[AC_CMD_IN] = {
.type = TRTL_HMQ,
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_INPUT,
},
[AC_CMD_OUT] = {
.type = TRTL_HMQ,
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_OUTPUT,
},
[AC_DATA] = {
.type = TRTL_HMQ,
.index = 1,
.flags = TRTL_RT_MQ_FLAGS_OUTPUT | TRTL_RT_MQ_FLAGS_CLAIM,
},
};
enum ac_variable {
AC_TIME = 0,
AC_PERIOD_UPDATE,
......@@ -45,7 +19,7 @@ enum ac_variable {
AC_ALARM_ITER,
};
static struct rt_variable variables[] = {
static struct trtl_fw_variable variables[] = {
[AC_TIME] = {
.addr = (void *)&iteration,
.mask = 0xFFFFFFFF,
......@@ -72,16 +46,13 @@ static struct rt_variable variables[] = {
},
};
static struct rt_application app = {
static struct trtl_fw_application app = {
.name = "alarm-clk",
.version = {
.fpga_id = CONFIG_FPGA_APPLICATION_ID,
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.mq = mq,
.n_mq = ARRAY_SIZE(mq),
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
......@@ -92,18 +63,18 @@ static void ac_update(void)
{
uint32_t sec, cyc;
rt_get_time(&sec, &cyc);
trtl_fw_time(&sec, &cyc);
if ((--period_c) == 0) {
period_c = period;
trtl_rt_mq_send_uint32(AC_DATA, 0x12, 1,
trtl_fw_mq_send_uint32(TRTL_HMQ, 0, 0x12, 1,
iteration);
pr_debug("Iteration %d\n\r", iteration);
}
if (alarm_enable) {
if (alarm_iter < iteration) {
trtl_rt_mq_send_uint32(AC_DATA, 0x34, 2,
trtl_fw_mq_send_uint32(TRTL_HMQ, 0, 0x34, 2,
iteration, alarm_iter);
alarm_enable = 0;
alarm_iter = 0;
......@@ -128,16 +99,12 @@ static void ac_init(void)
*/
int main()
{
rt_init(&app);
trtl_fw_init(&app);
ac_init();
while (1) {
/*
* Handle all messages incoming from slot
* AC_CMD_IN
* as actions
*/
rt_mq_action_dispatch(AC_CMD_IN);
/* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
ac_update();
}
......
......@@ -22,36 +22,11 @@ static struct dg_conf dg_conf;
static uint32_t dg_last_sample_idx;
static uint32_t dg_last_sample = 1;
enum rt_slot_name {
DG_MQ_CMD_IN = 0,
DG_MQ_CMD_OUT,
DG_MQ_DATA,
};
static struct rt_mq mq[] = {
[DG_MQ_CMD_IN] = {
.type = TRTL_HMQ,
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_INPUT,
},
[DG_MQ_CMD_OUT] = {
.type = TRTL_HMQ,
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_OUTPUT,
},
[DG_MQ_DATA] = {
.type = TRTL_HMQ,
.index = 1,
.flags = TRTL_RT_MQ_FLAGS_OUTPUT | TRTL_RT_MQ_FLAGS_CLAIM,
},
};
enum dg_variable {
DG_PERIOD_UPDATE = 0,
};
static struct rt_variable variables[] = {
static struct trtl_fw_variable variables[] = {
[DG_PERIOD_UPDATE] = {
.addr = (void *)&period,
.mask = 0xFFFFFFFF,
......@@ -65,7 +40,7 @@ enum dg_structures {
DG_CONF,
};
struct rt_buffer buffers[] = {
struct trtl_fw_buffer buffers[] = {
[DG_DATA] = {
.buf = dg_data,
.len = sizeof(dg_data),
......@@ -76,16 +51,13 @@ struct rt_buffer buffers[] = {
},
};
static struct rt_application app = {
static struct trtl_fw_application app = {
.name = "data-gen",
.version = {
.fpga_id = CONFIG_FPGA_APPLICATION_ID,
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.mq = mq,
.n_mq = ARRAY_SIZE(mq),
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
......@@ -109,7 +81,9 @@ static void generate_sample(void)
dg_last_sample_idx + 1, DG_BUF_SIZE, dg_last_sample);
dg_data[dg_last_sample_idx] = dg_last_sample;
dg_last_sample_idx = ++dg_last_sample_idx & (DG_BUF_SIZE - 1);
dg_last_sample_idx++;
dg_last_sample_idx &= (DG_BUF_SIZE - 1);
}
static void dg_update(void)
......@@ -139,16 +113,12 @@ static void dg_init(void)
*/
int main()
{
rt_init(&app);
trtl_fw_init(&app);
dg_init();
while (1) {
/*
* Handle all messages incoming from slot
* DG_MQ_CMD_IN
* as actions
*/
rt_mq_action_dispatch(DG_MQ_CMD_IN);
/* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
dg_update();
}
......
......@@ -5,7 +5,7 @@
#ifndef __FW_SVEC_COMMON_H__
#define __FW_SVEC_COMMON_H__
#include <mockturtle-rt-smem.h>
#include <mockturtle-rt.h>
#include <svec-common.h>
extern volatile int autosvec_run;
......
......@@ -15,33 +15,16 @@
#define GPIO_DDR 0x8 /* Direction Data Register */
#define GPIO_PSR 0xC /* Status Register */
enum rt_slot_name {
SVEC_CMD_IN = 0,
SVEC_CMD_OUT,
};
struct rt_mq mq[] = {
[SVEC_CMD_IN] = {
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_HMQ | TRTL_RT_MQ_FLAGS_INPUT,
},
[SVEC_CMD_OUT] = {
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_HMQ | TRTL_RT_MQ_FLAGS_OUTPUT,
},
};
static struct svec_structure svec_struct;
struct rt_buffer svec_buffers[] = {
struct trtl_fw_buffer svec_buffers[] = {
[SVEC_BUF_TEST] = {
.buf = &svec_struct,
.len = sizeof(struct svec_structure),
}
};
struct rt_variable svec_variables[] = {
struct trtl_fw_variable svec_variables[] = {
[SVEC_VAR_LEMO_STA] = {
.addr = TRTL_ADDR_DP(GPIO_PSR),
.mask = PIN_LEMO_MASK,
......@@ -85,16 +68,13 @@ struct rt_variable svec_variables[] = {
};
struct rt_application app = {
struct trtl_fw_application app = {
.name = "svec-svec",
.version = {
.fpga_id = FPGA_APPLICATION_ID,
.rt_id = RT_APPLICATION_ID,
.rt_version = RT_VERSION(1, 0),
.git_version = GIT_VERSION
},
.mq = mq,
.n_mq = 2,
.buffers = svec_buffers,
.n_buffers = ARRAY_SIZE(svec_buffers),
......@@ -119,13 +99,12 @@ static void svec_debug_interface(void)
*/
int main()
{
rt_init(&app);
trtl_fw_init(&app);
svec_debug_interface();
while (1) {
/* Handle all messages incoming from slot SVEC_HMQ_IN
as actions */
rt_mq_action_dispatch(SVEC_CMD_IN);
/* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
}
return 0;
......
......@@ -8,7 +8,7 @@
#ifndef __SVEC_COMMON_H
#define __SVEC_COMMON_H
#include <mockturtle-common.h>
#include <mockturtle.h>
/* HMQ slots used for input */
......@@ -18,7 +18,7 @@
#define SVEC_HMQ_OUT 0
/* Variable index - used only by svec-librt */
enum rt_variable_index {
enum trtl_fw_variable_index {
SVEC_VAR_LEMO_STA = 0,
SVEC_VAR_LEMO_DIR,
SVEC_VAR_LEMO_SET,
......@@ -30,14 +30,14 @@ enum rt_variable_index {
__SVEC_VAR_MAX,
};
enum rt_buffer_index {
enum trtl_fw_buffer_index {
SVEC_BUF_TEST = 0,
__SVEC_BUF_MAX,
};
/* Command and log message IDs */
enum rt_action_recv_svec {
SVEC_ID_LED_SET = __RT_ACTION_RECV_STANDARD_NUMBER,
SVEC_ID_LED_SET = 0,
SVEC_ID_LEMO_SET,
SVEC_ID_LEMO_DIR_SET,
SVEC_ID_STATE_GET,
......
......@@ -14,13 +14,6 @@
#include <libmockturtle.h>
#include <libsvec-internal.h>
static const struct trtl_proto_header hdr_tmpl = {
.rt_app_id = 0,
.slot_io = (SVEC_HMQ_IN << 4) |
(SVEC_HMQ_OUT & 0xF),
};
const char *svec_errors[] = {
"Received an invalid answer from white-rabbit-node-code CPU",
"Real-Time application does not acknowledge",
......@@ -132,7 +125,7 @@ int svec_lemo_dir_set(struct svec_node *dev, uint32_t value)
struct svec_desc *svec = (struct svec_desc *)dev;
uint32_t fields[] = {SVEC_VAR_LEMO_DIR, value};
return trtl_rt_variable_set(svec->trtl,
return trtl_fw_variable_set(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
fields, 1);
}
......@@ -143,7 +136,7 @@ int svec_lemo_set(struct svec_node *dev, uint32_t value)
uint32_t fields[] = {SVEC_VAR_LEMO_SET, value,
SVEC_VAR_LEMO_CLR, ~value};
return trtl_rt_variable_set(svec->trtl,
return trtl_fw_variable_set(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
fields, 2);
}
......@@ -185,7 +178,7 @@ int svec_led_set(struct svec_node *dev, uint32_t value, enum svec_color color)
uint32_t fields[] = {SVEC_VAR_LED_SET, real_value,
SVEC_VAR_LED_CLR, ~real_value};
return trtl_rt_variable_set(svec->trtl,
return trtl_fw_variable_set(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
fields, 2);
}
......@@ -202,7 +195,7 @@ int svec_status_get(struct svec_node *dev, struct svec_status *status)
SVEC_VAR_LEMO_DIR, 0};
int err;
err = trtl_rt_variable_get(svec->trtl,
err = trtl_fw_variable_get(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
fields, 3);
if (err)
......@@ -220,30 +213,30 @@ int svec_run_autosvec(struct svec_node *dev, uint32_t run)
struct svec_desc *svec = (struct svec_desc *)dev;
uint32_t fields[] = {SVEC_VAR_AUTO, run};
return trtl_rt_variable_set(svec->trtl,
return trtl_fw_variable_set(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
fields, 1);
}
int svec_version(struct svec_node *dev, struct trtl_rt_version *version)
int svec_version(struct svec_node *dev, struct trtl_fw_version *version)
{
struct svec_desc *svec = (struct svec_desc *)dev;
return trtl_rt_version_get(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
version);
return trtl_fw_version(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
version);
}
int svec_test_struct_get(struct svec_node *dev, struct svec_structure *test)
{
struct svec_desc *svec = (struct svec_desc *)dev;
struct trtl_structure_tlv tlv = {
.index = SVEC_BUF_TEST,
struct trtl_tlv tlv = {
.type = SVEC_BUF_TEST,
.size = sizeof(struct svec_structure),
.buf = test,
};
return trtl_rt_buffer_get(svec->trtl,
return trtl_fw_buffer_get(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
&tlv, 1);
}
......@@ -251,13 +244,13 @@ int svec_test_struct_get(struct svec_node *dev, struct svec_structure *test)
int svec_test_struct_set(struct svec_node *dev, struct svec_structure *test)
{
struct svec_desc *svec = (struct svec_desc *)dev;
struct trtl_structure_tlv tlv = {
.index = SVEC_BUF_TEST,
struct trtl_tlv tlv = {
.type = SVEC_BUF_TEST,
.size = sizeof(struct svec_structure),
.buf = test,
};
return trtl_rt_buffer_set(svec->trtl,
return trtl_fw_buffer_set(svec->trtl,
SVEC_CPU_MANUAL, SVEC_CPU_MANUAL_HMQ,
&tlv, 1);
}
......@@ -56,7 +56,7 @@ extern int svec_lemo_set(struct svec_node *dev, uint32_t value);
extern int svec_lemo_dir_set(struct svec_node *dev, uint32_t value);
extern int svec_status_get(struct svec_node *dev, struct svec_status *status);
extern int svec_run_autosvec(struct svec_node *dev, uint32_t run);
extern int svec_version(struct svec_node *dev, struct trtl_rt_version *version);
extern int svec_version(struct svec_node *dev, struct trtl_fw_version *version);
extern int svec_test_struct_set(struct svec_node *dev,
struct svec_structure *test);
extern int svec_test_struct_get(struct svec_node *dev,
......
......@@ -40,10 +40,9 @@ static void svec_print_status(struct svec_status *status)
fprintf(stdout, "\tautosvec\t%s\n", status->autosvec ? "run" : "stop");
}
static void svec_print_version(struct trtl_rt_version *version)
static void svec_print_version(struct trtl_fw_version *version)
{
fprintf(stdout, "Version:\n");
fprintf(stdout, "\tFPGA: 0x%x\n", version->fpga_id);
fprintf(stdout, "\tRT: 0x%x\n", version->rt_id);
fprintf(stdout, "\tRT Version: 0x%x\n", version->rt_version);
fprintf(stdout, "\tGit Version: 0x%x\n", version->git_version);
......@@ -68,7 +67,7 @@ int main(int argc, char *argv[])
char c, c_color = 0, autosvec = 0;
int err = 0, show_status = 0, show_version = 0, structure = 0;
enum svec_color color = SVEC_RED;
struct trtl_rt_version version;
struct trtl_fw_version version;
struct svec_structure test, test_rb;
while ((c = getopt (argc, argv, "hD:l:L:d:c:sa:vt")) != -1) {
......
#include <mockturtle-rt-serial.h>
#include <mockturtle-rt.h>
int main()
{
......
......@@ -6,32 +6,13 @@
#include <mockturtle-framework.h>
enum rt_slot_name {
HELLOFRM_CMD_IN = 0,
HELLOFRM_CMD_OUT,
};
static struct rt_mq mq[] = {
[HELLOFRM_CMD_IN] = {
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_HMQ | TRTL_RT_MQ_FLAGS_INPUT,
},
[HELLOFRM_CMD_OUT] = {
.index = 0,
.flags = TRTL_RT_MQ_FLAGS_HMQ | TRTL_RT_MQ_FLAGS_OUTPUT,
},
};
static struct rt_application app = {
static struct trtl_fw_application app = {
.name = "hellofrm",
.version = {
.fpga_id = CONFIG_FPGA_APPLICATION_ID,
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
.git_version = GIT_VERSION,
},
.mq = mq,
.n_mq = ARRAY_SIZE(mq),
};
/**
......@@ -39,15 +20,14 @@ static struct rt_application app = {
*/
int main()
{
rt_init(&app);
trtl_fw_init(&app);
while (1) {
/*
* Handle all messages incoming from slot
* HELLOFRM_CMD_IN
* Handle all messages incoming from slot 0
* as actions
*/
rt_mq_action_dispatch(HELLOFRM_CMD_IN);
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
}
return 0;
......
#ifndef __TRTL_CONFIG_ROM_H__
#define __TRTL_CONFIG_ROM_H__
#define TRTL_CONFIG_ROM_SIGNATURE 0x5452544c
#define TRTL_MAX_CPU 8 /**< Maximum number of CPU core in a bitstream */
#define TRTL_MAX_MQ_CHAN 8 /**< Maximum number of (H|R)MQ slots in a
bitstream */
#define TRTL_CONFIG_ROM_MQ_ENTRIES_SHIFT 16
#define TRTL_CONFIG_ROM_MQ_ENTRIES_MASK 0x00FF0000
#define TRTL_CONFIG_ROM_MQ_PAYLOAD_SHIFT 8
#define TRTL_CONFIG_ROM_MQ_PAYLOAD_MASK 0x0000FF00
#define TRTL_CONFIG_ROM_MQ_HEADER_SHIFT 0
#define TRTL_CONFIG_ROM_MQ_HEADER_MASK 0x000000FF
#define TRTL_CONFIG_ROM_MQ_SIZE_ENTRIES(_size) (1 << ((_size & TRTL_CONFIG_ROM_MQ_ENTRIES_MASK) >> TRTL_CONFIG_ROM_MQ_ENTRIES_SHIFT))
#define TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(_size) (1 << ((_size & TRTL_CONFIG_ROM_MQ_PAYLOAD_MASK) >> TRTL_CONFIG_ROM_MQ_PAYLOAD_SHIFT))
#define TRTL_CONFIG_ROM_MQ_SIZE_HEADER(_size) (1 << ((_size & TRTL_CONFIG_ROM_MQ_HEADER_MASK) >> TRTL_CONFIG_ROM_MQ_HEADER_SHIFT))
/**
* The synthesis configuration for a single MQ.
* Note that there is always an input and output channel for each declaration.
*/
struct trtl_config_rom_mq {
uint32_t sizes;
uint32_t endpoint_id;
};
/**
* The synthesis configuration ROM descriptor shows useful configuration
* options during synthesis.
*/
struct trtl_config_rom {
uint32_t signature; /**< we expect to see a known value */
uint32_t version; /**< Mock Turtle version */
uint32_t pad1[1];
uint32_t clock_freq;
uint32_t flags;
uint32_t app_id; /**< Application ID */
uint32_t n_cpu; /**< number of CPU */
uint32_t smem_size; /**< shared memory size */
uint32_t mem_size[TRTL_MAX_CPU]; /**< memory size for each CPU */
uint32_t n_hmq[TRTL_MAX_CPU]; /**< number of HMQ for each CPU */
uint32_t n_rmq[TRTL_MAX_CPU]; /**< number of RMQ for each CPU */
uint32_t pad2[96];
struct trtl_config_rom_mq hmq[TRTL_MAX_CPU][TRTL_MAX_MQ_CHAN];
struct trtl_config_rom_mq rmq[TRTL_MAX_CPU][TRTL_MAX_MQ_CHAN];
};
#endif
/*
* Copyright (C) 2015-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TRTL_COMMON_H__
#define __TRTL_COMMON_H__
#ifndef __KERNEL__
#include <string.h>
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof(_a[0]))
#endif
#define __TRTL_MSG_ID_MAX_USER 96
#define __TRTL_MSG_ID_MAX 128
/**
* It lists all notification's code.
*/
enum trtl_cpu_notification {
TRTL_CPU_NOTIFY_APPLICATION = 0,
__TRTL_CPU_NOTIFY_MAX,
};
/**
* List of Mock Turtle message identifiers for firmware input
*/
enum trtl_msg_id_i {
TRTL_MSG_ID_PING = __TRTL_MSG_ID_MAX_USER,
TRTL_MSG_ID_VERS_REQ,
TRTL_MSG_ID_VAR_SET,
TRTL_MSG_ID_VAR_GET,
TRTL_MSG_ID_BUF_SET,
TRTL_MSG_ID_BUF_GET,
};
/**
* List of Mock Turtle message identifiers for firmware output
*/
enum trtl_msg_id_o {
TRTL_MSG_ID_ACK = __TRTL_MSG_ID_MAX_USER,
TRTL_MSG_ID_NACK,
TRTL_MSG_ID_VERS_ANS,
TRTL_MSG_ID_DBG,
TRTL_MSG_ID_VAR_GET_ANS,
TRTL_MSG_ID_BUF_GET_ANS,
};
/**
* Synchronous. When set, the sync_id is valid and the receiver
* must answer with a message with the same sync_id
*/
#define TRTL_HMQ_HEADER_FLAG_SYNC (1 << 0)
/**
* HMQ header descriptor
*/
struct trtl_hmq_header {
/* word 0 */
uint16_t rt_app_id; /**< Real-Time application unique identifier */
uint8_t flags;
uint8_t msg_id; /**< Message identifier */
/* word 1 */
uint16_t len; /**< message-length */
uint16_t sync_id;/**< synchronous identifier */
/* word 2 */
uint32_t seq; /**< sequence number */
};
/**
* It describes the version running on the embedded CPU
*/
struct trtl_rt_version {
uint32_t fpga_id; /**< FPGA identifier expected to run the RT app */
uint32_t rt_id; /**< RT application identifier */
uint32_t rt_version; /**< RT application version*/
uint32_t git_version; /**< git commit SHA1 of the compilation time */
};
enum rt_action_standard {
RT_ACTION_RECV_PING = 0,
RT_ACTION_RECV_STRUCT_SET,
RT_ACTION_RECV_STRUCT_GET,
RT_ACTION_RECV_VERSION,
RT_ACTION_SEND_ACK,
RT_ACTION_SEND_NACK,
RT_ACTION_SEND_STRUCT_GET,
RT_ACTION_SEND_VERSION,
RT_ACTION_SEND_DEBUG,
__RT_ACTION_RECV_STANDARD_NUMBER,
};
/**< __MAX_ACTION_RECV coming from GCC on compilation */
#define MAX_ACTION_RECV (__MAX_ACTION_RECV + __RT_ACTION_RECV_STANDARD_NUMBER)
/**< __MAX_ACTION_SEND coming from GCC on compilation */
#define MAX_ACTION_SEND (__MAX_ACTION_SEND + __RT_ACTION_SEND_STANDARD_NUMBER)
/* Protocol Definition */
#define TRTL_HEAD_FLAG_REMOTE (1 << 0)
#define TRTL_HEAD_FLAG_SYNC (1 << 1)
#define TRTL_HEAD_FLAG_RPC (1 << 2)
#define TRTL_HEAD_FLAG_PERIODICAL (1 << 3)
/**
* Protocol header definition
*/
struct trtl_proto_header {
uint16_t rt_app_id; /**< Real-Time application unique identifier */
uint8_t msg_id; /**< Message identifier */
uint8_t slot_io; /**< Message Queue IO to use
(4bit Input, 4 bit output) */
uint32_t seq; /**< sequence number */
uint8_t len; /**< message data lenght */
uint8_t flags; /**< protocol flags */
uint8_t unused; /**< not used, future use */
uint8_t trans; /**< transaction descriptor - flag and seq number */
uint32_t time;
};
/**
* Data structure representing a MockTurtle packet
*/
struct mturtle_packet {
/* offset 0x00 */
volatile struct trtl_proto_header header; /**< packet header */
/* offset 0x10 */
volatile uint32_t payload[]; /**< packet payload */
};
/**
* It returns the pointer to the MockTurtle packet
* @param[in] buf buffer containing the packet
* @return pointer to the packet
*/
static inline struct mturtle_packet *rt_proto_packet_get(void *buf)
{
return (struct mturtle_packet *)buf;
}
/**
* It extracts the header from a raw message
* @param[in] raw_msg raw message
* @param[out] header the header from the message
*/
static inline struct trtl_proto_header *rt_proto_header_get(void *raw_msg)
{
return (struct trtl_proto_header *) raw_msg;
}
/**
* It embeds the header from a raw message
* @param[in] raw_msg raw message
* @param[out] header the header from the message
*/
static inline void rt_proto_header_set(void *raw_msg,
struct trtl_proto_header *header)
{
memcpy(raw_msg, header, sizeof(struct trtl_proto_header));
}
/**
* It returns the pointer where it starts the message payload
* @param[in] raw_msg raw message
* @param[out] header the header from the message
*/
static inline void *rt_proto_payload_get(void *raw_msg)
{
return ((char *)raw_msg + sizeof(struct trtl_proto_header));
}
#endif
......@@ -21,11 +21,123 @@
#define __TRTL_USER_H__
/** @file mock-turtle.h */
#include "mockturtle-common.h"
#ifndef __KERNEL__
#include <string.h>
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof(_a[0]))
#endif
#define __TRTL_MSG_ID_MAX 128
#define __TRTL_MSG_ID_MAX_TRTL 32
#define __TRTL_MSG_ID_MAX_USER (__TRTL_MSG_ID_MAX - __TRTL_MSG_ID_MAX_TRTL)
/**
* It lists all notification's code.
*/
enum trtl_cpu_notification {
TRTL_CPU_NOTIFY_APPLICATION = 0,
__TRTL_CPU_NOTIFY_MAX,
};
/**
* It enumerates the Mock Turtle message ID.
* These IDs starts after the user defined ones
*/
enum trtl_msg_id {
TRTL_MSG_ID_UNDEFINED = __TRTL_MSG_ID_MAX_USER,
TRTL_MSG_ID_ERROR,
TRTL_MSG_ID_PING,
TRTL_MSG_ID_VER,
TRTL_MSG_ID_DBG,
TRTL_MSG_ID_VAR_GET,
TRTL_MSG_ID_BUF_GET,
TRTL_MSG_ID_VAR_SET,
TRTL_MSG_ID_BUF_SET,
};
/**
* Synchronous. When set, the sync_id is valid and the receiver
* must answer with a message with the same sync_id
*/
#define TRTL_HMQ_HEADER_FLAG_SYNC (1 << 0)
/**
* Acknowledgment. When set, the sync_id is valid and it is the
* same as the sync message previously sent
*/
#define TRTL_HMQ_HEADER_FLAG_ACK (1 << 1)
/**
* Remote Procedure Call. when set the message ID will be used
* to execute a special function by the receiver
*/
#define TRTL_HMQ_HEADER_FLAG_RPC (1 << 2)
/**
* HMQ header descriptor
*/
struct trtl_hmq_header {
/* word 0 */
uint16_t rt_app_id; /**< Real-Time application unique identifier */
uint8_t flags;
uint8_t msg_id; /**< Message identifier */
/* word 1 */
uint16_t len; /**< message-length */
uint16_t sync_id;/**< synchronous identifier */
/* word 2 */
uint32_t seq; /**< sequence number (automatically set by the library) */
};
#define RT_VERSION_MAJ(_v) ((_v >> 16) & 0xFFFF)
#define RT_VERSION_MIN(_v) (_v & 0xFFFF)
#define RT_VERSION(_a, _b) (((_a & 0xFFFF) << 16) | (_b & 0xFFFF))
/**
* It describes the version running on the embedded CPU
*/
struct trtl_fw_version {
uint32_t rt_id; /**< RT application identifier */
uint32_t rt_version; /**< RT application version*/
uint32_t git_version; /**< git commit SHA1 of the compilation time */
};
/**
* Maximum number of CPU core in a bitstream
*/
#define TRTL_MAX_CPU 8
/**
* Maximum number of (H|R)MQ slots in a bitstream
*/
#define TRTL_MAX_MQ_CHAN 8
#define TRTL_MAX_CARRIER 20 /**< Maximum number of WRNC components on a
single computer*/
/**
* Maximum number of Mock Turtle components on a single computer
*/
#define TRTL_MAX_CARRIER 20
/**
* TLV used to embed buffers within a message
*/
struct trtl_tlv {
uint32_t type; /**< buffer type */
size_t size; /**< buffer size in byte */
void *buf; /**< pointer to the buffer */
};
/**
* Maximum number of notifications ID in the driver buffer
......@@ -46,22 +158,13 @@
* that you can use to access the shared memory.
*/
enum trtl_smem_modifier {
TRTL_SMEM_DIRECT = 0, /**< direct read/write of the memory */
TRTL_SMEM_ADD, /**< on write, atomic ADD to memory content */
TRTL_SMEM_SUB, /**< on write, atomic SUB to memory content */
TRTL_SMEM_OR, /**< on write, atomic OR with memory content */
TRTL_SMEM_CLR_AND, /**< on write, atomic AND with complemented memory
content */
TRTL_SMEM_XOR, /**< on write, atomic XOR with memory content */
};
/**
* Messages descriptor
*/
struct trtl_msg {
struct trtl_hmq_header hdr;
uint32_t data[TRTL_MAX_PAYLOAD_SIZE]; /**< payload very maximum size */
TRTL_SMEM_TYPE_BASE = 0, /**< no operation */
TRTL_SMEM_TYPE_ADD, /**< atomic addition */
TRTL_SMEM_TYPE_SUB, /**< atomic subtraction */
TRTL_SMEM_TYPE_SET, /**< atomic bit set */
TRTL_SMEM_TYPE_CLR, /**< atomic bit clear */
TRTL_SMEM_TYPE_FLP, /**< atomic bit flip */
TRTL_SMEM_TYPE_TST_SET, /**< atomic test and set */
};
......@@ -123,4 +226,71 @@ enum trtl_ioctl_commands {
#define TRTL_IOCTL_MSG_FILTER_CLEAN _IOW(TRTL_IOCTL_MAGIC, \
TRTL_MSG_FILTER_CLEAN, \
struct trtl_msg_filter)
/**
* Messages descriptor
*/
struct trtl_msg {
#ifdef __TRTL_FIRMWARE__
/* Only firmware */
struct trtl_hmq_header *header;
void *payload;
#else
/* library and kernel */
struct trtl_hmq_header hdr;
uint32_t data[TRTL_MAX_PAYLOAD_SIZE]; /**< payload very maximum size */
#endif
};
#define TRTL_CONFIG_ROM_MQ_ENTRIES_SHIFT 16
#define TRTL_CONFIG_ROM_MQ_ENTRIES_MASK 0x00FF0000
#define TRTL_CONFIG_ROM_MQ_PAYLOAD_SHIFT 8
#define TRTL_CONFIG_ROM_MQ_PAYLOAD_MASK 0x0000FF00
#define TRTL_CONFIG_ROM_MQ_HEADER_SHIFT 0
#define TRTL_CONFIG_ROM_MQ_HEADER_MASK 0x000000FF
#define TRTL_CONFIG_ROM_MQ_SIZE_ENTRIES(_size) (1 << ((_size & TRTL_CONFIG_ROM_MQ_ENTRIES_MASK) >> TRTL_CONFIG_ROM_MQ_ENTRIES_SHIFT))
#define TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(_size) (1 << ((_size & TRTL_CONFIG_ROM_MQ_PAYLOAD_MASK) >> TRTL_CONFIG_ROM_MQ_PAYLOAD_SHIFT))
#define TRTL_CONFIG_ROM_MQ_SIZE_HEADER(_size) (1 << ((_size & TRTL_CONFIG_ROM_MQ_HEADER_MASK) >> TRTL_CONFIG_ROM_MQ_HEADER_SHIFT))
/**
* The synthesis configuration for a single MQ.
* Note that there is always an input and output channel for each declaration.
*/
struct trtl_config_rom_mq {
uint32_t sizes;
uint32_t endpoint_id;
};
/**
* This signature must be present on all the configuration rom
*/
#define TRTL_CONFIG_ROM_SIGNATURE 0x5452544c
/**
* The synthesis configuration ROM descriptor shows useful configuration
* options during synthesis.
*/
struct trtl_config_rom {
uint32_t signature; /**< we expect to see a known value */
uint32_t version; /**< Mock Turtle version */
uint32_t pad1[1];
uint32_t clock_freq;
uint32_t flags;
uint32_t app_id; /**< Application ID */
uint32_t n_cpu; /**< number of CPU */
uint32_t smem_size; /**< shared memory size */
uint32_t mem_size[TRTL_MAX_CPU]; /**< memory size for each CPU */
uint32_t n_hmq[TRTL_MAX_CPU]; /**< number of HMQ for each CPU */
uint32_t n_rmq[TRTL_MAX_CPU]; /**< number of RMQ for each CPU */
uint32_t pad2[96];
struct trtl_config_rom_mq hmq[TRTL_MAX_CPU][TRTL_MAX_MQ_CHAN];
struct trtl_config_rom_mq rmq[TRTL_MAX_CPU][TRTL_MAX_MQ_CHAN];
};
#endif
......@@ -28,7 +28,6 @@
#include <hw/mockturtle_cpu_csr.h>
#include <hw/mockturtle_queue.h>
#include <hw/mockturtle_config.h>
#include "mockturtle-drv.h"
......@@ -198,7 +197,7 @@ static ssize_t trtl_store_smem_op(struct device *dev,
if (kstrtol(buf, 0, &val))
return -EINVAL;
if (val < TRTL_SMEM_DIRECT || val > TRTL_SMEM_ADD) {
if (val < TRTL_SMEM_TYPE_BASE || val > TRTL_SMEM_TYPE_ADD) {
dev_err(&trtl->dev, "Unsupported operation %ld\n", val);
return -EINVAL;
}
......
......@@ -15,7 +15,6 @@
#include "hw/mockturtle_addresses.h"
#include "hw/mockturtle_queue.h"
#include "hw/mockturtle_config.h"
#include "mockturtle.h"
#define MAX_MQUEUE_SLOTS (TRTL_MAX_HMQ_SLOT / 2)
......
......@@ -111,6 +111,14 @@ class TrtlMessage(Structure):
return True
class TrtlFirmwareVersion(Structure):
_fields_ = [
("id", c_uint32),
("fw-version", c_uint32),
("git-version", c_uint32),
]
class TrtlDevice(object):
"""It is a Python class that represent a Mock Turtle Device
"""
......@@ -229,7 +237,16 @@ class TrtlDevice(object):
]
self.libtrtl.trtl_hmq_flush.restype = c_int
self.libtrtl.trtl_hmq_flush.errcheck = self.errcheck
# FW PING
self.libtrtl.trtl_fw_ping.argtypes = [c_void_p, c_uint, c_uint]
self.libtrtl.trtl_fw_ping.restype = c_int
self.libtrtl.trtl_fw_ping.errcheck = self.__errcheck_int
# FW VERSION
self.libtrtl.trtl_fw_version.argtypes = [c_void_p, c_uint, c_uint,
POINTER(TrtlFirmwareVersion),
]
self.libtrtl.trtl_fw_version.restype = c_int
self.libtrtl.trtl_fw_version.errcheck = self.__errcheck_int
# self.libtrtl.trtl_hmq_filter_add.argtypes = [c_void_p]
# self.libtrtl.trtl_hmq_filter_clean.argtypes = [c_void_p]
# # Return
......@@ -326,6 +343,22 @@ class TrtlCpu(object):
self.idx_cpu,
file_path.encode())
def ping(self, idx_hmq):
"""
It pings the firmware running on the CPU
@return True if the firmware is alive, False otherwise
"""
val = self.libtrtl.trtl_fw_ping(self.trtl_dev.tkn,
self.idx_cpu, idx_hmq)
return True if val == 0 else False
def version(self):
version = TrtlFirmwareVersion()
self.libtrtl.trtl_fw_version(self.trtl_dev.tkn,
self.idx_cpu, idx_hmq,
pointer(version))
return version
class TrtlHmq(object):
"""
......
......@@ -14,6 +14,8 @@
*/
struct trtl_desc {
uint32_t devid;
uint32_t seq; /**< global sequence number for messages sent from
this instance*/
char name[TRTL_NAME_LEN]; /**< Name of the device */
char path[TRTL_PATH_LEN]; /**< path to device */
int fd_dev; /**< File Descriptor of the device */
......
This diff is collapsed.
......@@ -243,6 +243,8 @@ static struct trtl_dev *__trtl_open(const char *device)
}
}
trtl->seq = 0;
return (struct trtl_dev *)trtl;
out_hmq_fd:
......
......@@ -19,8 +19,6 @@ extern "C" {
#include <stdint.h>
#include <stdio.h>
#include <poll.h>
#include "hw/mockturtle_config.h"
#include "mockturtle-common.h"
#include "mockturtle.h"
extern const unsigned int trtl_default_timeout_ms;
......@@ -98,15 +96,6 @@ enum trtl_error_number {
};
/**
* TLV structure used to embed structures within a message
*/
struct trtl_structure_tlv {
uint32_t index; /**< structure index (type) */
void *buf; /**< pointer to the structure */
size_t size; /**< structure size in byte */
};
/**
* @file libmockturtle.c
*/
......@@ -134,8 +123,8 @@ const struct trtl_config_rom *trtl_config_get(struct trtl_dev *trtl);
* Utilities collection
* @{
*/
extern void trtl_print_header(struct trtl_proto_header *h);
extern void trtl_print_payload(struct trtl_proto_header *h, void *buf);
extern void trtl_print_header(struct trtl_msg *msg);
extern void trtl_print_payload(struct trtl_msg *msg);
extern void trtl_print_message(struct trtl_msg *msg);
extern char *trtl_strerror(int err);
/**@}*/
......@@ -224,58 +213,35 @@ extern int trtl_smem_write(struct trtl_dev *trtl, uint32_t addr, uint32_t *data,
/**@}*/
/**
* @defgroup proto Protocol management
* Set of utilities to properly handle the protocol
* @{
*/
extern void trtl_message_header_set(struct trtl_msg *msg,
struct trtl_proto_header *hdr);
extern void trtl_message_header_get(struct trtl_msg *msg,
struct trtl_proto_header *hdr);
extern void trtl_message_pack(struct trtl_msg *msg,
struct trtl_proto_header *hdr,
void *payload);
extern void trtl_message_unpack(struct trtl_msg *msg,
struct trtl_proto_header *hdr,
void *payload);
extern void trtl_message_buffer_push(struct trtl_msg *msg,
struct trtl_proto_header *hdr,
struct trtl_structure_tlv *tlv);
extern off_t trtl_message_buffer_pop(struct trtl_msg *msg, off_t offset,
struct trtl_proto_header *hdr,
struct trtl_structure_tlv *tlv);
/**@}*/
/**
* @defgroup rtmsg Real Time service messages
* Message builders for RT service messages
* @{
*/
extern int trtl_rt_version_get(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_rt_version *version);
extern int trtl_rt_ping(struct trtl_dev *trtl,
extern int trtl_fw_version(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_fw_version *version);
extern int trtl_fw_ping(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq);
extern int trtl_rt_variable_set(struct trtl_dev *trtl,
extern int trtl_fw_variable_set(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
uint32_t *var, unsigned int n_var);
extern int trtl_rt_variable_get(struct trtl_dev *trtl,
extern int trtl_fw_variable_get(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
uint32_t *var, unsigned int n_var);
extern int trtl_rt_buffer_set(struct trtl_dev *trtl,
extern int trtl_fw_buffer_set(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_structure_tlv *tlv,
struct trtl_tlv *tlv,
unsigned int n_tlv);
extern int trtl_rt_buffer_get(struct trtl_dev *trtl,
extern int trtl_fw_buffer_get(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_structure_tlv *tlv,
struct trtl_tlv *tlv,
unsigned int n_tlv);
/**@}*/
#ifdef __cplusplus
......
......@@ -16,6 +16,7 @@ AUTOCONF = $(CURDIR)/$(BUILDDIR)/include/generated/autoconf.h
CROSS_COMPILE_TARGET ?= riscv32-elf-
# FIXME the mult/div is broken, for the time being remove it completely
# -march=rv32im should be the future option
CFLAGS += -D__TRTL_FIRMWARE__
CFLAGS += -mabi=ilp32 -march=rv32i -ffunction-sections -fdata-sections
LDFLAGS += -lgcc -lc -Wl,--gc-sections
......@@ -66,10 +67,7 @@ OBJS += lib/printf.o
OBJS += lib/mockturtle-rt-common.o
OBJDIR-$(CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE) += framework
OBJS-$(CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE) += framework/mockturtle-frm-core.o
OBJS-$(CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE) += framework/mockturtle-frm-debug.o
OBJS-$(CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE) += framework/mockturtle-frm-action.o
OBJS-$(CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE) += framework/mockturtle-frm-mqueue.o
OBJS-$(CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE) += framework/mockturtle-framework.o
OBJDIR += $(OBJDIR-y)
OBJS += $(OBJS-y)
......
This diff is collapsed.
......@@ -10,13 +10,98 @@
#ifndef __TRTL_FW_FRM_H__
#define __TRTL_FW_FRM_H__
#include <inttypes.h>
#include <generated/autoconf.h>
#include "mockturtle-rt.h"
#include "mockturtle-frm-action.h"
#include "mockturtle-frm-mqueue.h"
#include "mockturtle-frm-common.h"
#include "mockturtle-frm-debug.h"
#include "mockturtle-frm-variable.h"
/**
* Action prototype type
* @param[in] msg_i input message
* @param[out] msg_o output message
* @return 0 on success. -1 on error
*
* The header for the output message is prepared by the framework.
* The header's fields that the user should touch are
*
* On error the message will be sent anyway to the host. This
* is just in case of future development.
*/
typedef int (trtl_fw_action_t)(struct trtl_msg *msg_i, struct trtl_msg *msg_o);
/**
* Variable flag. Register
*/
#define TRTL_FW_VARIABLE_FLAG_FLD (1 << 0)
/**
* Description of a variable that we want to export to the external
* world (host or network).
*/
struct trtl_fw_variable {
void *addr; /**< variable address */
uint32_t mask; /**< variable mask without offset applied */
uint8_t offset; /**< variable offset within the word */
uint32_t flags; /**< variable options */
};
/**
* Description of a buffer that we want to export to the external world
* (host or network)
*/
struct trtl_fw_buffer {
void *buf; /**< structure location */
uint32_t len; /**< data structure lenght */
/* Maybe other option later in time */
};
/**
* Real-Time Application Descriptor
*/
struct trtl_fw_application {
const char name[16]; /**< Firmware name*/
const uint32_t *fpga_id_compat; /**< list of compatible FPGA
application ID */
const unsigned int fpga_id_compat_n; /**< number of entry in
the fpga_id_compat list */
const struct trtl_fw_version version; /**< version running */
struct trtl_fw_buffer *buffers; /**< exported buffers */
unsigned int n_buffers; /**< number or exported buffers */
struct trtl_fw_variable *variables; /**< exported variables */
unsigned int n_variables; /**< number or exported variables */
trtl_fw_action_t **actions; /**< list of custum actions */
unsigned int n_actions; /**< number of custum actions */
unsigned int seq; /** sequence number reference */
const struct trtl_config_rom *cfgrom;
};
extern struct trtl_fw_application *_app;
extern int trtl_fw_init(struct trtl_fw_application *app);
extern void trtl_fw_time(uint32_t *seconds, uint32_t *cycles);
extern void trtl_fw_print_header(struct trtl_hmq_header *h);
extern void trtl_fw_print_data(uint32_t *d, unsigned int count);
extern void trtl_fw_print_message(struct trtl_msg *msg);
extern int trtl_fw_mq_send_uint32(enum trtl_mq_type type,
unsigned int idx_mq,
uint8_t msg_id,
unsigned int n,
...);
extern int trtl_fw_mq_send_buf(enum trtl_mq_type type,
unsigned int idx_mq,
uint8_t msg_id,
unsigned int n,
void *data);
extern int trtl_fw_mq_action_dispatch(enum trtl_mq_type type,
unsigned int idx_mq);
extern void trtl_fw_message_error(struct trtl_msg *msg, int err);
#endif
/**@}*/
/**
* Copyright (C) 2015-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <errno.h>
#include <inttypes.h>
#include <mockturtle-framework.h>
/**
* This is an @ref action_t function type. It fills the payload
* witht an answer for the ping message.
*/
int rt_recv_ping(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
rt_send_ack(hin, pin, hout, pout);
return 0;
}
/**
* This is an @ref action_t function type. It fills the payload with
* version information.
*/
int rt_version_getter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
uint32_t *dout = pout;
hout->msg_id = TRTL_MSG_ID_VERS_ANS;
hout->len = sizeof(struct trtl_rt_version) / 4;
memcpy(dout, (uint32_t *)&_app->version,
sizeof(struct trtl_rt_version));
return 0;
}
/**
* This is an @ref action_t function type. Accorind the message request,
* it overwrite a data structure with the one contained in the input
* payload. If the message is syncrnous it will copy back the data structure.
*/
int rt_buffer_setter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
unsigned int offset = 0, index, size;
uint32_t *din = pin;
if (!HAS_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE) {
rt_send_nack(hin, pin, hout, NULL);
return 0;
}
while (offset < hin->len) {
pr_debug("%s: offset %d/%d\n\r", __func__, offset, hin->len);
index = din[offset++];
size = din[offset++];
pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__,
index, size, _app->buffers[index].buf);
if (_app->buffers[index].len == size) {
memcpy((uint32_t *)_app->buffers[index].buf,
&din[offset], size);
} else {
pr_error("%s:%d structure %d len not correct %"PRId32" != %d\n\r",
__func__, __LINE__, index,
_app->buffers[index].len, size);
}
offset += (size / 4); /* Next TLV record */
}
/* Return back new values. Host can compare with what it sent
to spot errors */
if (hin->flags & TRTL_HEAD_FLAG_SYNC)
return rt_buffer_getter(hin, pin, hout, pout);
return 0;
}
/**
* This is an @ref action_t function type. Accorind the message request,
* it copies one of the declared data structure to the output payload.
*/
int rt_buffer_getter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
unsigned int offset = 0, index, size;
uint32_t *din = pin;
uint32_t *dout = pout;
if (!HAS_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE) {
rt_send_nack(hin, pin, hout, NULL);
return 0;
}
hout->msg_id = TRTL_MSG_ID_BUF_GET_ANS;
while (offset < hin->len) {
pr_debug("%s: offset %d/%d\n\r", __func__, offset, hin->len);
index = din[offset];
dout[offset++] = index;
size = din[offset];
dout[offset++] = size;
pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__,
index, size, _app->buffers[index].buf);
if (_app->buffers[index].len == size) {
memcpy(&dout[offset],
(uint32_t *)_app->buffers[index].buf,
size);
} else {
pr_error("%s: structure %d len not correct %"PRId32" != %d\n\r",
__func__, index, _app->buffers[index].len, size);
}
offset += (size / 4); /* Next TLV record */
}
return 0;
}
/**
* This is an @ref action_t function type. Accorind the message request,
* it writes a number of declared variables. If the message is synchronous
* it copies back the values in the output payload.
*/
int rt_variable_setter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
struct rt_variable *var;
uint32_t *din = pin, *mem, val;
int i;
if (!HAS_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE) {
pr_debug("Variable set action not supported\n\r");
rt_send_nack(hin, pin, hout, NULL);
return 0;
}
/* we always have a pair of values */
if (hin->len % 2)
rt_send_nack(hin, pin, hout, pout);
/* Write all values in the proper place */
for (i = 0; i < hin->len; i += 2) {
if (din[i] >= _app->n_variables)
continue;
var = &_app->variables[din[i]];
mem = (uint32_t *) var->addr;
val = ((din[i + 1] & var->mask) << var->offset);
if (var->flags & TRTL_RT_VARIABLE_FLAG_FLD)
*mem = (*mem & ~var->mask) | val;
else
*mem = val;
pr_debug("%s index %"PRIu32"/%d | [0x%p] = 0x%08"PRIx32" <- 0x%08"PRIx32" (0x%08"PRIx32") | index in msg (%d/%d)\n\r",
__func__,
din[i], _app->n_variables - 1,
mem, *mem, val, din[i + 1],
i + 1, hin->len - 1);
}
/* Return back new values. Host can compare with what it sent
to spot errors */
if (hin->flags & TRTL_HEAD_FLAG_SYNC)
return rt_variable_getter(hin, pin, hout, pout);
return 0;
}
/**
* This is an @ref action_t function type. Accorind the message request,
* it copies a number of declared variables.
*/
int rt_variable_getter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
struct rt_variable *var;
uint32_t *dout = pout, *din = pin, *mem, val;
int i;
if (!HAS_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE) {
pr_debug("Variable get action not supported\n\r");
rt_send_nack(hin, pin, hout, NULL);
return 0;
}
if (!hout || !pout)
return -1;
/* we always have a pair of values */
if (hin->len % 2)
return -1;
hout->msg_id = TRTL_MSG_ID_VAR_GET_ANS;
/* Write all values in the proper place */
for (i = 0; i < hout->len; i += 2) {
if (din[i] >= _app->n_variables) {
dout[i] = ~0; /* Report invalid index */
continue;
}
dout[i] = din[i];
var = &_app->variables[dout[i]];
mem = (uint32_t *) var->addr;
val = (*mem >> var->offset) & var->mask;
dout[i + 1] = val;
pr_debug("%s index %"PRIu32"d/%d | [0x%p] = 0x%08"PRIx32" -> 0x%08"PRIx32" | index in msg (%d/%d)\n\r",
__func__,
dout[i], _app->n_variables - 1,
mem, *mem, dout[i + 1],
i + 1, hin->len - 1);
}
return 0;
}
/**
* List of standard actions
*/
static action_t *trtl_actions_in[] = {
rt_recv_ping,
rt_version_getter,
rt_variable_setter,
rt_variable_getter,
rt_buffer_setter,
rt_buffer_getter,
};
/**
* It runs the action associated with the given identifier
* @param[in] id action identifier
* @param[in] msg input message for the action
* @return 0 on success. A negative value on error
*/
static inline int rt_action_run(struct trtl_proto_header *hin, void *pin)
{
action_t *action;
struct trtl_msg out_buf;
struct trtl_proto_header hout;
void *pout;
int err = 0;
if (hin->msg_id >= __TRTL_MSG_ID_MAX) {
pr_error("Invalid Message ID %d\n\r", hin->msg_id);
return -EINVAL;
}
if (hin->msg_id < __TRTL_MSG_ID_MAX_USER) {
/* User Actions */
if (hin->msg_id >= _app->n_actions ||
!_app->actions[hin->msg_id]) {
pr_error("Cannot dispatch (usr) msg_id 0x%x\n\r",
hin->msg_id);
return -EINVAL;
}
action = _app->actions[hin->msg_id];
} else {
/* Mock Turtle Standard Actions */
if (ARRAY_SIZE(trtl_actions_in) < hin->msg_id - __TRTL_MSG_ID_MAX_USER) {
pr_error("Cannot dispatch msg_id 0x%x\n\r",
hin->msg_id);
return -EINVAL;
}
action = trtl_actions_in[hin->msg_id - __TRTL_MSG_ID_MAX_USER];
}
pr_debug("Message Input\n\r");
rt_print_header(hin);
rt_print_data(pin, 8);
if (!(hin->flags & TRTL_HEAD_FLAG_SYNC)) {
/* Asynchronous message, then no output */
return action(hin, pin, NULL, NULL);
}
/* Synchronous message */
out_buf = rt_mq_claim_out(hin);
/* Do not write directly the header on the buffer because it does not
work for fields size different than 32bit */
pout = rt_proto_payload_get((void *) out_buf.data);
memcpy((uint32_t *)&hout, (uint32_t *)hin,
sizeof(struct trtl_proto_header));
err = action(hin, pin, &hout, pout);
if (err)
rt_send_nack(hin, pin, &hout, NULL);
rt_proto_header_set((void *) out_buf.data, &hout);
rt_mq_msg_send(&out_buf);
pr_debug("Message Output\n\r");
rt_print_header(&hout);
rt_print_data(pout, 8);
return err;
}
/**
* It dispatch messages coming from a given message queue.
* @param[in] mq_in MQ index within mq declaration in rt_application
* @todo provide support for remote queue
* @return 0 on success. -1 on error
*/
int rt_mq_action_dispatch(unsigned int mq_in)
{
struct trtl_proto_header *header;
unsigned int mq_in_slot = _app->mq[mq_in].index;
uint32_t *msg;
void *pin;
int err = 0;
/* HMQ control slot empty? */
if (_app->mq[mq_in].type == TRTL_HMQ) {
if (!(hmq_poll_in() & ( 1 << mq_in_slot)))
return -EAGAIN;
} else {
return -EAGAIN; /* Not used now */
}
/* Get the message from the HMQ */
msg = mq_map_in_buffer(0, mq_in_slot);
pr_debug("Incoming message\n\r");
rt_print_data(msg, 8);
header = rt_proto_header_get((void *) msg);
rt_print_header(header);
if (header->rt_app_id && header->rt_app_id != _app->version.rt_id) {
pr_error("Not for this application 0x%x\n\r", header->rt_app_id);
err = -EINVAL;
goto out;
}
if (!(header->flags & TRTL_HEAD_FLAG_RPC)) {
pr_error("%s: The message is not an RPC\n", __func__);
err = -EINVAL;
goto out;
}
pin = rt_proto_payload_get((void *) msg);
/* Run the correspondent action */
err = rt_action_run(header, pin);
if (err)
pr_error("%s: action failure err: %d\n\r", __func__, err);
out:
mq_discard(0, mq_in_slot);
return err;
}
/**
* @defgroup framework-action Framework Action
* @{
* @ingroup framework
* @brief Action (RPC)
* @copyright (C) 2015-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_FW_FRM_ACTION_H__
#define __TRTL_FW_FRM_ACTION_H__
/**
* Action prototype type
* @param[in] hin input message header
* @param[in] pin input message payload
* @param[out] hout output message header
* @param[out] pout output message payload
* @return 0 on success. -1 on error
*/
typedef int (action_t)(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
/**
* This is an @ref action_t function type. It fills the output payload
* with an acknowledged message
*/
static inline void rt_send_ack(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
hout->msg_id = TRTL_MSG_ID_ACK;
hout->len = 0;
}
/**
* This is an @ref action_t function type. It fills the output payload
* with a not-acknowledged message
*/
static inline void rt_send_nack(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout)
{
hout->msg_id = TRTL_MSG_ID_NACK;
hout->len = 0;
}
extern int rt_recv_ping(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
extern int rt_version_getter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
extern int rt_variable_setter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
extern int rt_variable_getter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
extern int rt_buffer_setter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
extern int rt_buffer_getter(struct trtl_proto_header *hin, void *pin,
struct trtl_proto_header *hout, void *pout);
extern int rt_mq_action_dispatch(unsigned int mq_in);
#endif
/**@}*/
/**
* @defgroup framework-buffer Framework Buffer
* @{
* @ingroup framework
* @brief Buffer exchange mechanism
* @copyright (C) 2015-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_FW_FRM_BUFFER_H__
#define __TRTL_FW_FRM_BUFFER_H__
/**
* Description of a buffer that we want to export to the external world
* (host or network)
*/
struct rt_buffer {
void *buf; /**< structure location */
uint32_t len; /**< data structure lenght */
/* Maybe other option later in time */
};
#endif
/**@}*/
/**
* @defgroup framework-common Framework Common Utilities
* @{
* @ingroup framework
* @brief Common Utilities
* @copyright (C) 2015-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_FW_FRM_COMMON_H__
#define __TRTL_FW_FRM_COMMON_H__
#include "mockturtle-frm-action.h"
#include "mockturtle-frm-mqueue.h"
#include "mockturtle-frm-variable.h"
#include "mockturtle-frm-buffer.h"
#define RT_VERSION_MAJ(_v) ((_v >> 16) & 0xFFFF)
#define RT_VERSION_MIN(_v) (_v & 0xFFFF)
#define RT_VERSION(_a, _b) (((_a & 0xFFFF) << 16) | (_b & 0xFFFF))
/**
* Real-Time Application Descriptor
*/
struct rt_application {
const char name[16]; /**< Firmware name*/
const uint32_t *fpga_id_compat; /**< list of compatible FPGA
application ID */
const unsigned int fpga_id_compat_n; /**< number of entry in
the fpga_id_compat list */
const struct trtl_rt_version version; /**< version running */
struct rt_mq *mq; /**< list of used MQ */
uint8_t n_mq; /**< number of available MQ */
struct rt_buffer *buffers; /**< exported buffers */
unsigned int n_buffers; /**< number or exported buffers */
struct rt_variable *variables; /**< exported variables */
unsigned int n_variables; /**< number or exported variables */
action_t **actions; /**< list of custum actions */
unsigned int n_actions; /**< number of custum actions */
};
extern struct rt_application *_app;
extern int rt_init(struct rt_application *app);
extern void rt_get_time(uint32_t *seconds, uint32_t *cycles);
#endif
/**@}*/
/**
* Copyright (C) 2015-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <stdint.h>
#include <errno.h>
#include <mockturtle-framework.h>
uint32_t msg_seq = 0;
struct rt_application *_app;
/**
* It get the current time from the internal WRNC timer
* @param[out] seconds
* @param[out] cycles
*/
void rt_get_time(uint32_t *seconds, uint32_t *cycles)
{
*seconds = lr_readl(MT_CPU_LR_REG_TAI_SEC);
*cycles = lr_readl(MT_CPU_LR_REG_TAI_CYCLES);
}
/**
* It initilizes the declared MQs
* @param[in] app application declaration
* @return 0 on success. -1 on error
*/
static inline int trtl_rt_init_mq(void)
{
int i;
for (i = 0; i < _app->n_mq; ++i) {
if (_app->mq[i].flags & TRTL_RT_MQ_FLAGS_OUTPUT) {
_app->mq[i].buf = mq_map_out_buffer(_app->mq[i].type,
_app->mq[i].index);
mq_purge(_app->mq[i].type, _app->mq[i].index);
if (_app->mq[i].flags & TRTL_RT_MQ_FLAGS_CLAIM) {
mq_claim(_app->mq[i].type, _app->mq[i].index);
}
} else {
_app->mq[i].buf = mq_map_in_buffer(_app->mq[i].type,
_app->mq[i].index);
}
}
return 0;
}
/**
* The function initializes the library and it does some compatibility check.
*
* Initialization
* - purge all the output host-message-queue
*
* compatibility checks:
* - check bitstream FPGA ID if compatibile with the application. The value in
* app->version.fpga_id will be updated with the FPGA ID from the bitstream
*
* @param[in] app application declaration
* @return 0 on success. -1 on error
*/
int rt_init(struct rt_application *app)
{
int i, err;
uint32_t *fpga_id = &app->version.fpga_id; /* in order to overwrite the const */
_app = app;
/* Validate actions */
for (i = 0; i < _app->n_actions; ++i) {
if (i > __TRTL_MSG_ID_MAX_USER) {
pr_error("Too many actions defined. Maximum '%d'\n\r",
__TRTL_MSG_ID_MAX_USER);
return -1;
}
if (_app->actions[i] == NULL) {
pr_error("Undefined action %d\n\r", i);
return -1;
}
}
pr_debug("Running application '%s'\n\r", _app->name);
/* *fpga_id = 0x1234; /\* TODO read it from the FPGA ID register *\/ */
for (i = 0; i < app->fpga_id_compat_n; i++) {
if (app->fpga_id_compat[i] == *fpga_id)
break;
}
if (app->fpga_id_compat_n && app->fpga_id_compat_n == i) {
pr_error("\tFPGA '0x%"PRIx32"' not compatible with RT app: 0x%"PRIx32" 0x%"PRIx32" (git %"PRIx32")\n\r",
_app->version.fpga_id,
_app->version.rt_id,
_app->version.rt_version,
_app->version.git_version);
return -1;
}
pr_debug("\tapp id \t'0x%"PRIx32"'\n\r",
_app->version.rt_id);
pr_debug("\tapp version\t'%"PRId32".%"PRId32"'\n\r",
RT_VERSION_MAJ(_app->version.rt_version),
RT_VERSION_MIN(_app->version.rt_version));
pr_debug("\tsource id \t'0x%"PRIx32"'\n\r",
_app->version.git_version);
err = trtl_rt_init_mq();
if (err)
return err;
#ifdef LIBRT_DEBUG
pr_debug("Exported Variables\n\r");
for (i = 0; i < _app->n_variables; ++i)
pr_debug("[%d] addr %p | mask 0x%"PRIx32" | off %d\n\r",
i,
_app->variables[i].addr,
_app->variables[i].mask,
_app->variables[i].offset);
pr_debug("Exported Buffers\n\r");
for (i = 0; i < _app->n_buffers; ++i)
pr_debug("[%d] addr %p | len %"PRId32"\n\r", i,
_app->buffers[i].buf,
_app->buffers[i].len);
#endif
return 0;
}
/**
* Copyright (C) 2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <mockturtle-framework.h>
/**
* The function can be used to send debug information to the host
* trought the HMQ
* @param[in] mq_in MQ index within mq declaration in rt_application
* @param[in] n_values number of variadic arguments
* @return 0 on success. -1 on error
*/
int rt_send_debug(int mq_in, int n_values, ...)
{
va_list ap;
struct trtl_msg out_buf;
uint32_t *buf;
struct trtl_proto_header hdr = {
.rt_app_id = _app->version.rt_id,
.msg_id = TRTL_MSG_ID_DBG,
.slot_io = _app->mq[mq_in].index & 0xF,
.seq = 0,
.len = n_values,
.flags = 0x0,
.trans = 0x0,
.time = 0x0,
};
int i;
if (!HAS_MOCKTURTLE_FRAMEWORK_DEBUG_ENABLE) {
return 0;
}
out_buf = rt_mq_claim_out(&hdr);
buf = (uint32_t *)rt_proto_payload_get(out_buf.data);
va_start(ap, n_values);
for (i = 0; i < hdr.len;++i)
buf[i] = va_arg(ap, uint32_t);
va_end(ap);
rt_proto_header_set((void *) out_buf.data, &hdr);
rt_mq_msg_send(&out_buf);
return 0;
}
/**
* It prints on the serial interface the given message header
* @param[in] h message header to print
*/
void rt_print_header(struct trtl_proto_header *h)
{
if (!HAS_MOCKTURTLE_FRAMEWORK_DEBUG_ENABLE) {
return;
}
pr_debug(" app_id 0x%x | msg_id %d | slot_io 0x%x | seq %"PRIu32"d\n\r",
h->rt_app_id, h->msg_id, h->slot_io, h->seq);
delay(1000);
pr_debug(" len %d | flags 0x%x | trans 0x%x | time %"PRIu32"d\n\r",
h->len, h->flags, h->trans, h->time);
delay(1000);
}
/**
* It prints on the serial interface a buffer
* @param[in] d buffer data
* @param[in] count number of 32bit words to show
*/
void rt_print_data(uint32_t *d, unsigned int count)
{
int i;
if (!HAS_MOCKTURTLE_FRAMEWORK_DEBUG_ENABLE) {
return;
}
for (i = 0; i < count; i++) {
pr_debug("%s: data[%d] = 0x%"PRIx32"\n\r", __func__, i , d[i]);
delay(1000);
}
}
/**
* @defgroup framework-debug Framework Debug
* @{
* @ingroup framework
* @brief Debug functions
* @copyright (C) 2015-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_FW_FRM_DEBUG_H__
#define __TRTL_FW_FRM_DEBUG_H__
#include <stdarg.h>
#include "mockturtle-common.h"
extern int rt_send_debug(int slot, int n_values, ...);
extern void rt_print_header(struct trtl_proto_header *h);
extern void rt_print_data(uint32_t *d, unsigned int count);
#endif
/**@}*/
/*
* Copyright (C) 2015-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <mockturtle-framework.h>
/**
* It sends the MQ content.
* In order to save space the function *does not* perform any
* argument validation. This means that you may crash the system
* if you provide the wrong mq_idx.
* @param[in] mq_idx MQ index within the declaration
* @param[in] count number of bytes to send
*/
void trtl_rt_mq_send(unsigned int mq_idx, unsigned int count)
{
mq_send(_app->mq[mq_idx].type, _app->mq[mq_idx].index);
if (_app->mq[mq_idx].flags & TRTL_RT_MQ_FLAGS_CLAIM) {
mq_claim(_app->mq[mq_idx].type, _app->mq[mq_idx].index);
}
}
/**
* It builds and it sends a message over MQ.
* The vargs will be copied into the payload message.
* Beware that, internally, it uses trtl_rt_mq_send().
* @param[in] mq_idx MQ index within the declaration
* @param[in] msg_id message identifier
* @param[in] n number of vargs
*/
void trtl_rt_mq_send_uint32(unsigned int mq_idx, uint8_t msg_id,
unsigned int n, ...)
{
struct trtl_proto_header hdr = {
.rt_app_id = _app->version.rt_id,
.msg_id = msg_id,
.slot_io = _app->mq[mq_idx].index & 0xF,
.seq = msg_seq++,
.len = n,
.flags = 0x0,
.trans = 0x0,
.time = 0x0,
};
void *buf = _app->mq[mq_idx].buf;
uint32_t *payload = rt_proto_payload_get(buf);
va_list ap;
int i;
va_start(ap, n);
for (i = 0; i < hdr.len;++i)
payload[i] = va_arg(ap, uint32_t);
va_end(ap);
rt_proto_header_set(buf, &hdr);
trtl_rt_mq_send(mq_idx, (sizeof(struct trtl_proto_header) / 4) +
hdr.len);
}
/**
* It builds and it sends a message over MQ.
* The buffer will be copied into the payload message.
* Beware that, internally, it uses trtl_rt_mq_send().
* @param[in] mq_idx MQ index within the declaration
* @param[in] msg_id message identifier
* @param[in] n buffer size in bytes
* @param[in] data buffer to send
*/
void trtl_rt_mq_send_buf(unsigned int mq_idx, uint8_t msg_id,
unsigned int n, void *data)
{
struct trtl_proto_header hdr = {
.rt_app_id = _app->version.rt_id,
.msg_id = msg_id,
.slot_io = _app->mq[mq_idx].index & 0xF,
.seq = msg_seq++,
.len = n / 4,
.flags = 0x0,
.trans = 0x0,
.time = 0x0,
};
void *buf = _app->mq[mq_idx].buf;
memcpy(rt_proto_payload_get(buf), data, n);
rt_proto_header_set(buf, &hdr);
trtl_rt_mq_send(mq_idx, (sizeof(struct trtl_proto_header) / 4) +
hdr.len);
}
/**
* @defgroup framework-mqueue Framework Message Queue
* @{
* @ingroup framework
* @brief Message Queues definitions and functions
* @copyright (C) 2015-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_FW_FRM_MQUEUE_H__
#define __TRTL_FW_FRM_MQUEUE_H__
extern uint32_t msg_seq;
/**
* Description of the message queue
*/
struct rt_mq {
enum trtl_mq_type type; /**< MQ type */
uint8_t index; /**< MQ gateware index */
unsigned long flags; /**< MQ flag info */
void *buf; /**< MQ buffer */
};
/**
* MQ Flag. It is RMQ
*/
#define TRTL_RT_MQ_FLAGS_RMQ (1 << 0)
/**
* MQ Flag. It is HMQ
*/
#define TRTL_RT_MQ_FLAGS_HMQ (0)
/**
* MQ Flag. It is output
*/
#define TRTL_RT_MQ_FLAGS_OUTPUT (1 << 1)
/**
* MQ Flags. On output keep claimed.
* This means that as soon as you send a message on a slot,
* the framework will claim the slot immediately.
*/
#define TRTL_RT_MQ_FLAGS_CLAIM (1 << 2)
/**
* MQ Flag. It is input
*/
#define TRTL_RT_MQ_FLAGS_INPUT (0)
/**
* It send the message associate to the given header
* @param[in] msg message to send
*/
static inline void rt_mq_msg_send(struct trtl_msg *msg)
{
struct trtl_proto_header *hdr;
hdr = rt_proto_header_get((void *)msg->data);
/* When we are not using sync messages, we use the global
sequence number */
if (!(hdr->flags & TRTL_HEAD_FLAG_SYNC))
hdr->seq = msg_seq++;
mq_send(!!(hdr->flags & TRTL_HEAD_FLAG_REMOTE),
(hdr->slot_io & 0xF));
}
extern void trtl_rt_mq_send(unsigned int mq_idx, unsigned int count);
extern void trtl_rt_mq_send_uint32(unsigned int mq_idx, uint8_t msg_id,
unsigned int n, ...);
extern void trtl_rt_mq_send_buf(unsigned int mq_idx, uint8_t msg_id,
unsigned int n, void *data);
#endif
/**@}*/
/**
* @defgroup framework-variable Framework Variable
* @{
* @ingroup framework
* @brief Variable exchange mechanism
* @copyright (C) 2015-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_FW_FRM_VARIABLE_H__
#define __TRTL_FW_FRM_VARIABLE_H__
/**
* Variable flag. Register
*/
#define TRTL_RT_VARIABLE_FLAG_FLD (1 << 0)
/**
* Description of a variable that we want to export to the external
* world (host or network).
*/
struct rt_variable {
void *addr; /**< variable address */
uint32_t mask; /**< variable mask without offset applied */
uint8_t offset; /**< variable offset within the word */
uint32_t flags; /**< variable options */
};
#endif
/**@}*/
/*
* Message assembling helper functions
*
* Copyright (C) 2013-2016 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __RT_MESSAGE_H
#define __RT_MESSAGE_H
#include <mockturtle-rt-common.h>
#ifdef MOCKTURTLE_RT
/**
* It claims an output slot. This means that you get exclusive access to
* the slot.
*/
static inline struct trtl_msg rt_mq_claim_out(struct trtl_proto_header *h)
{
struct trtl_msg b;
int remote = !!(h->flags & TRTL_HEAD_FLAG_REMOTE);
int slot = h->slot_io & 0xF;
mq_claim(remote, slot);
b.data = mq_map_out_buffer(remote, slot);
b.hdr.len = 0;
return b;
}
/**
* Obsolete. Use rt_mq_claim_out
*/
static inline struct trtl_msg hmq_msg_claim_out(int slot, int max_size)
{
struct trtl_proto_header h = {
.slot_io = (slot & 0xF),
.len = max_size,
};
return rt_mq_claim_out(&h);
}
/**
* It claims an input slot. This mean that you get exclusive access to
* the slot
*/
static inline struct trtl_msg rt_mq_claim_in(struct trtl_proto_header *h)
{
struct trtl_msg b;
int slot = (h->slot_io >> 4) & 0xF;
b.data = mq_map_in_buffer(0, slot);
b.hdr.len = h->len;
return b;
}
/**
* Obsolete. Use rt_mq_claim_in
*/
static inline struct trtl_msg hmq_msg_claim_in(int slot, int max_size)
{
struct trtl_proto_header h = {
.slot_io = (slot & 0xF) << 4,
.len = max_size,
};
return rt_mq_claim_in(&h);
}
#endif
#endif
......@@ -10,7 +10,7 @@
#include <stdint.h>
#include <string.h>
#include "mockturtle-rt-common.h"
#include "mockturtle-rt.h"
int putchar(int c)
{
......
/**
* @defgroup library-utilities Common Utilities
* @{
* @ingroup library
* @brief Common utilities
* @copyright (C) 2013-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_RT_COMMON_H
#define __TRTL_RT_COMMON_H
#include <stdint.h>
#include <stdio.h>
#include <hw/mockturtle_addresses.h>
#include "hw/mockturtle_cpu_lr.h"
#include <mockturtle-common.h>
#include "mockturtle-rt-serial.h"
struct trtl_msg {
struct trtl_hmq_header hdr;
uint32_t *data;
};
/**
* Read a 32bit word value from the given address
* @param[in] addr source address
* @return the value fromt the register
*/
static inline uint32_t readl(void *addr)
{
return *(volatile uint32_t *) (addr);
}
/**
* Write a 32bit word value to the given address
* @param[in] value value to write
* @param[in] addr destination address
*/
static inline void writel(uint32_t value, void *addr)
{
*(volatile uint32_t *) (addr) = value;
}
/**
* Read a 32bit word value from the Dedicated Peripheral address space
* @param[in] reg register offset within the Dedicated Peripheral
* @return the value fromt the register
*/
static inline uint32_t dp_readl(uint32_t reg)
{
return readl(TRTL_ADDR_DP(reg));
}
/**
* Write a 32bit word value to the Dedicated Peripheral address space
* @param[in] value value to write
* @param[in] reg register offset within the Dedicated Peripheral
*/
static inline void dp_writel(uint32_t value, uint32_t reg)
{
writel(value, TRTL_ADDR_DP(reg));
}
/**
* Read 32bit word value from the CPU Local Registers address space
* @param[in] reg register offset within the Local Registers
* @return the value fromt the register
*/
static inline uint32_t lr_readl(uint32_t reg)
{
return readl(TRTL_ADDR_LR(reg));
}
/**
* Write 32bit word value to the CPU Local Registers address space
* @param[in] value value to write
* @param[in] reg register offset within the Local Registers
*/
static inline void lr_writel(uint32_t value, uint32_t reg)
{
writel(value, TRTL_ADDR_LR(reg));
}
/**
* Set a bit in the CPU GPIO Register
* @param[in] pin GPIO pin to set
*/
static inline void gpio_set(int pin)
{
lr_writel ((1 << pin), MT_CPU_LR_REG_GPIO_SET);
}
/**
* Clear a bit in the CPU GPIO Register
* @param[in] pin GPIO pin to clear
*/
static inline void gpio_clear(int pin)
{
lr_writel ((1 << pin), MT_CPU_LR_REG_GPIO_CLEAR);
}
/**
* Wait n cycles
* @todo: use Timing Unit, compute it accoring to CPU frequency
* @param[in] n number of cycles to wait
*/
static inline void delay(int n)
{
int i;
for(i = 0; i < n; i++)
asm volatile("nop");
}
/**
* It returns a pointer to the config ROM
*/
static inline const struct trtl_config_rom *trtl_config_rom_get(void)
{
return (const struct trtl_config_rom *)(TRTL_ADDR_CONFIG_ROM_BASE);
}
/**
* It generates a notification signal (IRQ) to ask the HOST CPU
* to take some action.
*/
static inline void trtl_notify_send(enum trtl_cpu_notification id)
{
lr_writel(1, MT_CPU_LR_REG_NTF_INT);
}
#endif
/**@}*/
/**
* @defgroup library-message-queue Message Queue
* @{
* @ingroup library
* @brief Message Queues definitions and functions
* @copyright (C) 2013-2016 CERN (www.cern.ch)
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_RT_MQUEUE_H
#define __TRTL_RT_MQUEUE_H
#include <hw/mockturtle_addresses.h>
#include <hw/mockturtle_queue.h>
#include <hw/mockturtle_cpu_lr.h>
#define TRTL_MQ_SLOT_IN(slot) (TRTL_MQ_BASE_IN + ((slot) << 16))
// Outgoung slot base address, relative to BASE_HMQ
#define TRTL_MQ_SLOT_OUT(slot) (TRTL_MQ_BASE_OUT + ((slot) << 16))
/**
* List of Message Queue types
*/
enum trtl_mq_type {
TRTL_HMQ = 0, /**< Host Message Queue - Host-Firmware communication */
TRTL_RMQ, /**< Remote Message Queue - Network-Firmware communication */
};
/**
* It gets the Message Queue base address
* @param[in] type MQ type
*/
static inline void *trtl_mq_base_address(enum trtl_mq_type type)
{
return (void *)(type == TRTL_HMQ ? TRTL_ADDR_HMQ_BASE : TRTL_ADDR_RMQ_BASE);
}
/**
* It writes on a Message Queue register
* @param[in] type MQ type to use
* @param[val] value to write
* @param[reg] reg register offset
*/
static inline void mq_writel(enum trtl_mq_type type, uint32_t val, uint32_t reg)
{
*(volatile uint32_t *)(trtl_mq_base_address(type) + reg) = val;
}
/**
* @copydoc TRTL_MQ_CMD_CLAIM
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void mq_claim(enum trtl_mq_type type, int slot)
{
mq_writel(type, TRTL_MQ_CMD_CLAIM, TRTL_MQ_SLOT_OUT(slot) + TRTL_MQ_SLOT_COMMAND);
}
/**
* @copydoc TRTL_MQ_CMD_PURGE
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void mq_purge(enum trtl_mq_type type, int slot)
{
mq_writel(type, TRTL_MQ_CMD_PURGE, TRTL_MQ_SLOT_OUT(slot) + TRTL_MQ_SLOT_COMMAND);
mq_writel(type, TRTL_MQ_CMD_PURGE, TRTL_MQ_SLOT_IN(slot) + TRTL_MQ_SLOT_COMMAND);
}
/**
* @copydoc TRTL_MQ_CMD_READY
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void mq_send(enum trtl_mq_type type, int slot)
{
mq_writel(type, TRTL_MQ_CMD_READY, TRTL_MQ_SLOT_OUT(slot) + TRTL_MQ_SLOT_COMMAND);
}
/**
* @copydoc TRTL_MQ_CMD_DISCARD
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void mq_discard(enum trtl_mq_type type, int slot)
{
mq_writel(type, TRTL_MQ_CMD_DISCARD, TRTL_MQ_SLOT_IN(slot));
}
/**
* It gets the output slot data field pointer
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void *mq_map_out_buffer(enum trtl_mq_type type, int slot)
{
return (void *) (trtl_mq_base_address(type) +
TRTL_MQ_SLOT_OUT (slot) + TRTL_MQ_SLOT_DATA_START);
}
/**
* It gets the input slot data field pointer
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void *mq_map_in_buffer(enum trtl_mq_type type, int slot)
{
return (void *) (trtl_mq_base_address(type) +
TRTL_MQ_SLOT_IN (slot) + TRTL_MQ_SLOT_DATA_START);
}
/**
* It gets the output slot header field pointer
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void *mq_map_out_header(enum trtl_mq_type type, int slot)
{
return (void *) (trtl_mq_base_address(type) +
TRTL_MQ_SLOT_OUT (slot) + TRTL_MQ_SLOT_HEADER_START);
}
/**
* It gets the input slot header field pointer
* @param[in] type MQ type to use
* @param[in] slot slot number
*/
static inline void *mq_map_in_header(enum trtl_mq_type type, int slot)
{
return (void *) (trtl_mq_base_address(type) +
TRTL_MQ_SLOT_IN (slot) + TRTL_MQ_SLOT_HEADER_START);
}
/**
* It gets the current status of the input Host Message Queues
*/
static inline uint32_t hmq_poll_in(void)
{
volatile uint32_t *poll = (void *)TRTL_ADDR_LR_BASE + MT_CPU_LR_REG_HMQ_STAT;
return ((*poll & MT_CPU_LR_HMQ_STAT_IN_MASK) >> MT_CPU_LR_HMQ_STAT_IN_SHIFT);
}
/**
* It gets the current status of the output Host Message Queues
*/
static inline uint32_t hmq_poll_out(void)
{
volatile uint32_t *poll = (void *)TRTL_ADDR_LR_BASE + MT_CPU_LR_REG_HMQ_STAT;
return ((*poll & MT_CPU_LR_HMQ_STAT_OUT_MASK) >> MT_CPU_LR_HMQ_STAT_OUT_SHIFT);
}
/**
* It gets the current status of the input Remote Message Queues
*/
static inline uint32_t rmq_poll_in(void)
{
volatile uint32_t *poll = (void *)TRTL_ADDR_LR_BASE + MT_CPU_LR_REG_RMQ_STAT;
return ((*poll & MT_CPU_LR_RMQ_STAT_IN_MASK) >> MT_CPU_LR_RMQ_STAT_IN_SHIFT);
}
/**
* It gets the current status of the output Remote Message Queues
*/
static inline uint32_t rmq_poll_out(void)
{
volatile uint32_t *poll = (void *)TRTL_ADDR_LR_BASE + MT_CPU_LR_REG_RMQ_STAT;
return ((*poll & MT_CPU_LR_RMQ_STAT_OUT_MASK) >> MT_CPU_LR_RMQ_STAT_OUT_SHIFT);
}
#endif
/**@}*/
/**
* @defgroup library-serial Serial Console
* @{
* @ingroup library
* @brief Serial Console functions
* @copyright (C) 2013-2016 CERN (www.cern.ch)
* @author Alessandro Rubini <rubini@gnudd.com>
* @author Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_RT_PP_PRINTF_H
#define __TRTL_RT_PP_PRINTF_H
#include <stdarg.h>
#include <generated/autoconf.h>
/**
* Print buffer size. This means that your printf string
* should not exceed this value. If the string exceed this value
* then it will be trouncated.
*/
#define CONFIG_PRINT_BUFSIZE 128
/**
* It prints a string on the serial interface.
* Internally, it uses the puts() function.
* @param[in] fmt string format
* @param[in] ... argument according to the string format
* @return number of printed characters
*/
#if HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE == 1
extern int pp_printf(const char *fmt, ...)
__attribute__((format(printf,1,2)));
#else
static inline int pp_printf(const char *fmt, ...)
{
return 0;
}
#endif
/**
* It creates a new string according to the given format
* @param[out] s output string
* @param[in] fmt string format
* @param[in] ... argument according to the string format
* @return number of printed characters
*/
#if HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE == 1
extern int pp_sprintf(char *s, const char *fmt, ...)
__attribute__((format(printf,2,3)));
#else
static inline int pp_sprintf(char *s, const char *fmt, ...)
{
return 0;
}
#endif
/**
* It prints a string on the serial interface.
* Internally, it uses the puts() function.
* @param[in] fmt string format
* @param[in] args list of arguments according to the string format
* @return number of printed characters
*/
#if HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE
extern int pp_vprintf(const char *fmt, va_list args);
#else
static inline int pp_vprintf(const char *fmt, va_list args)
{
return 0;
}
#endif
/**
* It creates a new string according to the given format
* @param[out] buf output string
* @param[in] fmt string format
* @param[in] args list of arguments according to the string format
* @return number of printed characters
*/
#if HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE == 1
extern int pp_vsprintf(char *buf, const char *, va_list args)
__attribute__ ((format (printf, 2, 0)));
#else
static inline int pp_vsprintf(char *buf, const char *fmt, va_list args)
{
return 0;
}
#endif
/**
* It prints a string on the serial interface only when the support
* for error messages is enable.
*
* Kconfig ->CONFIG_MOCKTURTLE_LIBRARY_PRINT_DEBUG_ENABLE
*
* Internally, it uses the puts() function.
* @param[in] fmt string format
* @param[in] ... argument according to the string format
* @return number of printed characters
*/
#if (HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE == 1) && (HAS_MOCKTURTLE_LIBRARY_PRINT_DEBUG_ENABLE == 1)
extern int pr_debug(const char *fmt, ...)
__attribute__((format(printf,1,2)));
#else
static inline int pr_debug(const char *fmt, ...)
{
return 0;
}
#endif
/**
* It prints a string on the serial interface only when the support
* for error messages is enable.
*
* Kconfig -> CONFIG_MOCKTURTLE_LIBRARY_PRINT_ERROR_ENABLE
*
* Internally, it uses the puts() function.
* @param[in] fmt string format
* @param[in] ... argument according to the string format
* @return number of printed characters
*/
#if (HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE == 1) && (HAS_MOCKTURTLE_LIBRARY_PRINT_ERROR_ENABLE == 1)
extern int pr_error(const char *fmt, ...)
__attribute__((format(printf,1,2)));
#else
static inline int pr_error(const char *fmt, ...)
{
return 0;
}
#endif
extern int putchar (int c);
extern int puts(const char *p);
/**@}*/
#endif
/**
* @defgroup library-shared-memory Shared Memory Utilities
* @{
* @ingroup library
* @brief Shared Memory definitions & API
* @copyright (C) 2013-2016 CERN (www.cern.ch)
* @author Federico Vaga <federico.vaga@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __TRTL_RT_SMEM_H
#define __TRTL_RT_SMEM_H
/**
* List of supported Shared Memory access type
*/
enum trtl_smem_type {
TRTL_SMEM_TYPE_BASE = 0, /**< no operation */
TRTL_SMEM_TYPE_ADD, /**< atomic addition */
TRTL_SMEM_TYPE_SUB, /**< atomic subtraction */
TRTL_SMEM_TYPE_SET, /**< atomic bit set */
TRTL_SMEM_TYPE_CLR, /**< atomic bit clear */
TRTL_SMEM_TYPE_FLP, /**< atomic bit flip */
TRTL_SMEM_TYPE_TST_SET, /**< atomic test and set */
};
/**
* Shared Memory Size
*/
#define TRTL_SMEM_SIZE 0x10000
/**
* Shared Memory address for the
* @copydoc TRTL_SMEM_TYPE_BASE
* memory access
*/
#define TRTL_SMEM_RANGE_BASE 0x00000
/**
* It generates the SHM address range for a given SHM type
*/
#define TRTL_SMEM_TYPE_TO_RANGE(_type) \
(TRTL_SMEM_RANGE_BASE + (_type) * TRTL_SMEM_SIZE)
/**
* Shared Memory base address for the
* @copydoc TRTL_SMEM_TYPE_ADD
* memory access
*/
#define TRTL_SMEM_RANGE_ADD \
TRTL_SMEM_TYPE_TO_RANGE(TRTL_SMEM_TYPE_ADD)
/**
* Shared Memory base address for the
* @copydoc TRTL_SMEM_TYPE_SUB
* memory access
*/
#define TRTL_SMEM_RANGE_SUB \
TRTL_SMEM_TYPE_TO_RANGE(TRTL_SMEM_TYPE_SUB)
/**
* Shared Memory address for the
* @copydoc TRTL_SMEM_TYPE_SET
* memory access
*/
#define TRTL_SMEM_RANGE_SET \
TRTL_SMEM_TYPE_TO_RANGE(TRTL_SMEM_TYPE_SET)
/**
* Shared Memory address for the
* @copydoc TRTL_SMEM_TYPE_CLR
* memory access
*/
#define TRTL_SMEM_RANGE_CLEAR \
TRTL_SMEM_TYPE_TO_RANGE(TRTL_SMEM_TYPE_CLR)
/**
* Shared Memory address for the
* @copydoc TRTL_SMEM_TYPE_FLP
* memory access
*/
#define TRTL_SMEM_RANGE_FLIP \
TRTL_SMEM_TYPE_TO_RANGE(TRTL_SMEM_TYPE_FLP)
/**
* Shared Memory address for the
* @copydoc TRTL_SMEM_TYPE_TST_SET
* memory access
*/
#define TRTL_SMEM_RANGE_TEST_AND_SET \
TRTL_SMEM_TYPE_TO_RANGE(TRTL_SMEM_TYPE_TST_SET)
/**
* Compiler attribute to allocate variable on the Share Memory.
* Add this to the variable declaration to put it on the Shared Memory.
*
* SMEM int x;
*/
#define SMEM volatile __attribute__((section(".smem")))
/**
* It performs an operations on the shared memory. What the function
* performs can be summerized as:
*
* (*p) = (*p) <operation-type> x
*
* Use this function only when the operation type that you want to use
* is not supported yet by the library directly. Otherwise,
* use the other functions.
*
* @param[in] p address on the shared memory of the first operator and store location
* @param[in] x second operation argument
* @param[in] type operation type
*/
static inline void __smem_atomic_op(volatile int *p, int x,
enum trtl_smem_type type)
{
*(volatile int *)(p + (TRTL_SMEM_TYPE_TO_RANGE(type) >> 2)) = x;
}
/**
* It performs an
* @copydoc TRTL_SMEM_TYPE_ADD
*
* (*p) = (*p) + x
*
* @param[in] p address on the shared memory of the first operator and store location
* @param[in] x second operation argument
*/
static inline void smem_atomic_add(volatile int *p, int x)
{
__smem_atomic_op(p, x, TRTL_SMEM_TYPE_ADD);
}
/**
* It performs an
* @copydoc TRTL_SMEM_TYPE_SUB
*
* (*p) = (*p) - x
*
* @param[in] p address on the shared memory of the first operator and store location
* @param[in] x second operation argument
*/
static inline void smem_atomic_sub(volatile int *p, int x)
{
__smem_atomic_op(p, x, TRTL_SMEM_TYPE_SUB);
}
/**
* It performs an
* @copydoc TRTL_SMEM_TYPE_SET
*
* (*p) = (*p) | x
*
* @param[in] p address on the shared memory of the first operator and store location
* @param[in] x second operation argument
*/
static inline void smem_atomic_or(volatile int *p, int x)
{
__smem_atomic_op(p, x, TRTL_SMEM_TYPE_SET);
}
/**
* It performs an
* @copydoc TRTL_SMEM_TYPE_CLR
*
* (*p) = (*p) & (~x)
*
* @param[in] p address on the shared memory of the first operator and store location
* @param[in] x second operation argument
*/
static inline void smem_atomic_and_not(volatile int *p, int x)
{
__smem_atomic_op(p, x, TRTL_SMEM_TYPE_CLR);
}
/**
* It performs an
* @copydoc TRTL_SMEM_TYPE_FLP
*
* (*p) = (*p) ^ x
*
* @param[in] p address on the shared memory of the first operator and store location
* @param[in] x second operation argument
*/
static inline void smem_atomic_xor(int *p, int x)
{
__smem_atomic_op(p, x, TRTL_SMEM_TYPE_FLP);
}
/**
* It performs an:
* @copydoc TRTL_SMEM_TYPE_TST_SET
*
* val = (*p);
* if (val == 0) {
* (*p) = 1;
* }
* return val;
*
* This is useful to implement mutex
*
* @param[in] p address on the shared memory
* @return the value before the set
*/
static inline int smem_atomic_test_and_set(int *p)
{
/* shift right translates range in bytes into range in words */
return *(volatile int *)(p + (TRTL_SMEM_TYPE_TST_SET >> 2));
}
#endif
/**@}*/
This diff is collapsed.
......@@ -11,8 +11,7 @@
#include <stdarg.h>
#include <mockturtle-rt-common.h>
#include <mockturtle-rt-serial.h>
#include <mockturtle-rt.h>
#if HAS_MOCKTURTLE_LIBRARY_PRINT_ENABLE == 1
......
......@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
char c;
int err, n, dev_id = -1, v, i, k;
enum operations mode;
struct trtl_structure_tlv *tlv;
struct trtl_tlv *tlv;
unsigned int n_tlv, idx_cpu = 0, idx_hmq = 0;;
uint32_t *data;
......@@ -108,23 +108,23 @@ int main(int argc, char *argv[])
else
n_tlv = 1; /* Only 1 buffer on write */
tlv = calloc(n_tlv, sizeof(struct trtl_structure_tlv));
tlv = calloc(n_tlv, sizeof(struct trtl_tlv));
if (!tlv) {
fprintf(stderr, "Cannot allocate TLV descriptors\n");
exit(1);
}
for (i = optind, v = 0; v < n_tlv; i += 2, ++v) {
n = sscanf(argv[i], "%d", &tlv[v].index);
n = sscanf(argv[i], "%d", &tlv[v].type);
if (n != 1) {
fprintf(stderr,
"Invalid index: it must be a decimal number (%s)\n",
"Invalid type: it must be a decimal number (%s)\n",
argv[i]);
exit(1);
}
n = sscanf(argv[i + 1], "%zu", &tlv[v].size);
if (n != 1) {
fprintf(stderr,
"Invalid index: it must be a decimal number (%s)\n",
"Invalid size: it must be a decimal number (%s)\n",
argv[i + 1]);
exit(1);
}
......@@ -174,7 +174,7 @@ int main(int argc, char *argv[])
switch (mode) {
case OP_READ:
err = trtl_rt_buffer_get(trtl, idx_cpu, idx_hmq, tlv, n_tlv);
err = trtl_fw_buffer_get(trtl, idx_cpu, idx_hmq, tlv, n_tlv);
if (err) {
fprintf(stderr, "Cannot read buffer: %s\n",
trtl_strerror(errno));
......@@ -183,7 +183,7 @@ int main(int argc, char *argv[])
/* trtl_print_payload(&hdr, tlv); */
break;
case OP_WRITE:
err = trtl_rt_buffer_set(trtl, idx_cpu, idx_hmq, tlv, n_tlv);
err = trtl_fw_buffer_set(trtl, idx_cpu, idx_hmq, tlv, n_tlv);
break;
}
......
This diff is collapsed.
......@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
break;
case 'm':
sscanf(optarg, "%d", &mod);
if (mod > TRTL_SMEM_ADD) {
if (mod > TRTL_SMEM_TYPE_ADD) {
fprintf(stderr, "Invalid operation mode\n");
help();
exit(1);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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