/* Copyright Universite de Versailles Saint-Quentin en Yvelines 2009 AUTHORS: Sebastien Briais, Sid Touati This file is part of GDD. GDD is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GDD 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GDD. If not, see . */ #ifndef __GDD_OPCODE_H #define __GDD_OPCODE_H /** \file opcode.h \brief Opcode description */ #include #include /** Type of opcodes */ typedef struct { char *mnemo; int latency; int dflt_dr; SCEDA_HashMap *delta_r; SCEDA_HashMap *delta_w; } GDD_Opcode; /** Create a new opcode . @param[in] mnemo = mnemonic @param[in] latency = latency @param[in] dflt_dr = default read delay offset @return the opcode */ GDD_Opcode *GDD_opcode_create(const char *mnemo, int latency, int dflt_dr); /** Delete an opcode. @param[in] op = opcode */ void GDD_opcode_delete(GDD_Opcode *op); /** Extend delta_r function (read delay offset) of given opcode. @param[in] op = opcode @param[in] type = considered type @param[in] read = read delay offset for type @return 0 in case of success, or -1 in case of failure (e.g. if trying to redefine delta_r with another value). */ int GDD_opcode_extend_delta_r(GDD_Opcode *op, const char *type, int read); /** Extend delta_w function (write delay offset) of given opcode. @param[in] op = opcode @param[in] type = considered type @param[in] write = write delay offset for type @return 0 in case of success, or -1 in case of failure (e.g. if trying to redefine delta_r with another value). */ int GDD_opcode_extend_delta_w(GDD_Opcode *op, const char *type, int write); /** Get the value of read delay offset @param[in] op = opcode @param[in] type = considered type @return read delay offset (or default read delay offset) if type == NULL, return default read delay offset */ int GDD_opcode_delta_r(GDD_Opcode *op, const char *type); /** Get the value of write delay offset @param[in] op = opcode @param[in] type = considered type @return write delay offset (0 by default) */ int GDD_opcode_delta_w(GDD_Opcode *op, const char *type); /** Test whether an opcode is a value of given type. @param[in] op = opcode @param[in] type = type @return TRUE if op is a value of type type, FALSE otherwise */ int GDD_opcode_is_value(GDD_Opcode *op, const char *type); /** Print the description of an opcode, including its delay offsets. @param[in] stream = file stream where to print @param[in] op = opcode to print */ void GDD_opcode_fprint(FILE *stream, GDD_Opcode *op); /** Get the mnemonic of an opcode @param[in] op = opcode @return the mnemonic of op \hideinitializer */ #define GDD_opcode_mnemonic(op) ((op)->mnemo) /** Get the latency of an opcode @param[in] op = opcode @return the latency of op \hideinitializer */ #define GDD_opcode_latency(op) ((op)->latency) #endif /** \page opcode Opcodes \section opcode_intro Introduction An opcode is defined by its mnemonic and its latency. If \f$o\f$ is an opcode, we write \f$\mathop{mnemo}(o)\f$ for its mnemonic and \f$\mathop{lat}(o)\f$ for its latency. In our processor model, an opcode may also have different read or write delay offsets for each register type. A default read delay offset may be defined. If \f$t \in \mathcal{T}\f$ is a register type, we write \f$\delta_r^t(o)\f$ for the read delay offset and \f$\delta_w^t(o)\f$ for the write delay offset. If, for a given type \f$t\f$, the write delay offset is not defined, this means that the opcode does not produce a value of type \f$t\f$. Otherwise, we say, by abuse of language, that it \em is a value of type \f$t\f$. Implicitly, we assume that the following inequalities hold \f$0 \leq \delta_r^t(o) \leq \delta_w^t(o) < \mathop{lat}(o)\f$ (when defined). For convenient memory management, opcodes may be gathered into an architecture (see \ref arch). \section opcode_api API \code GDD_Opcode *GDD_opcode_create(const char *mnemo, int latency, int dflt_dr); \endcode Create a new opcode, with given mnemonic, latency and default read delay offset. \code void GDD_opcode_delete(GDD_Opcode *op); \endcode Delete an opcode. \code int GDD_opcode_extend_delta_r(GDD_Opcode *op, const char *type, int read); int GDD_opcode_extend_delta_w(GDD_Opcode *op, const char *type, int write); \endcode Define a read (resp. write) delay offset for the given register type. \code int GDD_opcode_delta_r(GDD_Opcode *op, const char *type); int GDD_opcode_delta_w(GDD_Opcode *op, const char *type); \endcode Return the read (resp. write) delay offset for the given register type. The default read delay offset is returned when delta_r is not defined on the given type. When delta_w is not defined on the given type, it returns 0. \code int GDD_opcode_is_value(GDD_Opcode *op, const char *type); \endcode Test whether the given opcode procudes a value of given type. It returns TRUE if and only if delta_w is defined on given type. \code char *GDD_opcode_mnemonic(GDD_Opcode *op); \endcode Return the mnemonic of the given opcode. \code int GDD_opcode_latency(GDD_Opcode *op); \endcode Return the latency of the given opcode. \code void GDD_opcode_fprint(FILE *stream, GDD_Opcode *op); \endcode Print the opcode on the given stream. \section opcode_example Example The following example creates an opcode for mnemonic "add" with a latency of 2 and a default read delay offset of 0. It then defines a read delay offset of 1 for register type "FR" and a write delay offset of 1 for register types "GR" and "FR". It then prints it on standard output. Finally, the opcode is deleted. \include "opcode/main.c" */