\section{Yosys by example -- Synthesis} \begin{frame} \sectionpage \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Typical Phases of a Synthesis Flow} \begin{frame}{\subsecname} \begin{itemize} \item Reading and elaborating the design \item Higher-level synthesis and optimization \begin{itemize} \item Converting {\tt always}-blocks to logic and registers \item Perform coarse-grain optimizations (resource sharing, const folding, ...) \item Handling of memories and other coarse-grain blocks \item Extracting and optimizing finite state machines \end{itemize} \item Convert remaining logic to bit-level logic functions \item Perform optimizations on bit-level logic functions \item Map bit-level logic gates and registers to cell library \item Write results to output file \end{itemize} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Reading the design} \begin{frame}[fragile]{\subsecname} \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] read_verilog file1.v read_verilog -I include_dir -D enable_foo -D WIDTH=12 file2.v read_verilog -lib cell_library.v verilog_defaults -add -I include_dir read_verilog file3.v read_verilog file4.v verilog_defaults -clear verilog_defaults -push verilog_defaults -add -I include_dir read_verilog file5.v read_verilog file6.v verilog_defaults -pop \end{lstlisting} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Design elaboration} \begin{frame}[fragile]{\subsecname} During design elaboration Yosys figures out how the modules are hierarchically connected. It also re-runs the AST parts of the Verilog frontend to create all needed variations of parametric modules. \bigskip \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] # simplest form. at least this version should be used after reading all input files # hierarchy # recommended form. fails if parts of the design hierarchy are missing, removes # everything that is unreachable from the top module, and marks the top module. # hierarchy -check -top top_module \end{lstlisting} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The {\tt proc} command} \begin{frame}[fragile]{\subsecname} The Verilog frontend converts {\tt always}-blocks to RTL netlists for the expressions and ``processes'' for the control- and memory elements. \medskip The {\tt proc} command transforms this ``processes'' to netlists of RTL multiplexer and register cells. \medskip The {\tt proc} command is actually a macro-command that calls the following other commands: \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] proc_clean # remove empty branches and processes proc_rmdead # remove unreachable branches proc_init # special handling of "initial" blocks proc_arst # identify modeling of async resets proc_mux # convert decision trees to multiplexer networks proc_dff # extract registers from processes proc_clean # if all went fine, this should remove all the processes \end{lstlisting} \medskip Many commands can not operate on modules with ``processes'' in them. Usually a call to {\tt proc} is the first command in the actual synthesis procedure after design elaboration. \end{frame} \begin{frame}[fragile]{\subsecname{} -- Example 1/3} \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/proc_01.v} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/proc_01.ys} \end{columns} \hfil\includegraphics[width=8cm,trim=0 0cm 0 0cm]{PRESENTATION_ExSyn/proc_01.pdf} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 2/3} \vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm -2.5cm]{PRESENTATION_ExSyn/proc_02.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/proc_02.v} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/proc_02.ys} \end{columns} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 3/3} \vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm -1.5cm]{PRESENTATION_ExSyn/proc_03.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/proc_03.ys} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/proc_03.v} \end{columns} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The {\tt opt} command} \begin{frame}[fragile]{\subsecname} The {\tt opt} command implements a series of simple optimizations. It also is a macro command that calls other commands: \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] opt_expr # const folding and simple expression rewriting opt_merge -nomux # merging identical cells do opt_muxtree # remove never-active branches from multiplexer tree opt_reduce # consolidate trees of boolean ops to reduce functions opt_merge # merging identical cells opt_rmdff # remove/simplify registers with constant inputs opt_clean # remove unused objects (cells, wires) from design opt_expr # const folding and simple expression rewriting while [changed design] \end{lstlisting} The command {\tt clean} can be used as alias for {\tt opt\_clean}. And {\tt ;;} can be used as shortcut for {\tt clean}. For example: \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] proc; opt; memory; opt_expr;; fsm;; \end{lstlisting} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 1/4} \vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm -0.5cm]{PRESENTATION_ExSyn/opt_01.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/opt_01.ys} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/opt_01.v} \end{columns} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 2/4} \vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm 0cm]{PRESENTATION_ExSyn/opt_02.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/opt_02.ys} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/opt_02.v} \end{columns} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 3/4} \vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm -2cm]{PRESENTATION_ExSyn/opt_03.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/opt_03.ys} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/opt_03.v} \end{columns} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 4/4} \vbox to 0cm{\hskip6cm\includegraphics[width=6cm,trim=0cm 0cm 0cm -3cm]{PRESENTATION_ExSyn/opt_04.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/opt_04.v} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/opt_04.ys} \end{columns} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{When to use {\tt opt} or {\tt clean}} \begin{frame}{\subsecname} Usually it does not hurt to call {\tt opt} after each regular command in the synthesis script. But it increases the synthesis time, so it is favourable to only call {\tt opt} when an improvement can be achieved. \bigskip The designs in {\tt yosys-bigsim} are a good playground for experimenting with the effects of calling {\tt opt} in various places of the flow. \bigskip It generally is a good idea to call {\tt opt} before inherently expensive commands such as {\tt sat} or {\tt freduce}, as the possible gain is much higher in this cases as the possible loss. \bigskip The {\tt clean} command on the other hand is very fast and many commands leave a mess (dangling signal wires, etc). For example, most commands do not remove any wires or cells. They just change the connections and depend on a later call to clean to get rid of the now unused objects. So the occasional {\tt ;;} is a good idea in every synthesis script. \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The {\tt memory} command} \begin{frame}[fragile]{\subsecname} In the RTL netlist, memory reads and writes are individual cells. This makes consolidating the number of ports for a memory easier. The {\tt memory} transforms memories to an implementation. Per default that is logic for address decoders and registers. It also is a macro command that calls other commands: \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] # this merges registers into the memory read- and write cells. memory_dff # this collects all read and write cells for a memory and transforms them # into one multi-port memory cell. memory_collect # this takes the multi-port memory cell and transforms it to address decoder # logic and registers. This step is skipped if "memory" is called with -nomap. memory_map \end{lstlisting} \bigskip Usually it is preferred to use architecture-specific RAM resources for memory. For example: \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] memory -nomap; techmap -map my_memory_map.v; memory_map \end{lstlisting} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 1/2} \vbox to 0cm{\includegraphics[width=0.7\linewidth,trim=0cm 0cm 0cm -10cm]{PRESENTATION_ExSyn/memory_01.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys, frame=single]{PRESENTATION_ExSyn/memory_01.ys} \column[t]{5cm} \lstinputlisting[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=verilog]{PRESENTATION_ExSyn/memory_01.v} \end{columns} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 2/2} \vbox to 0cm{\hfill\includegraphics[width=7.5cm,trim=0cm 0cm 0cm -5cm]{PRESENTATION_ExSyn/memory_02
/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * @file    chdebug.h
 * @brief   Debug macros and structures.
 *
 * @addtogroup debug
 * @{
 */

#ifndef _CHDEBUG_H_
#define _CHDEBUG_H_

#if CH_DBG_ENABLE_ASSERTS     || CH_DBG_ENABLE_CHECKS      ||               \
    CH_DBG_ENABLE_STACK_CHECK || CH_DBG_SYSTEM_STATE_CHECK
#define CH_DBG_ENABLED              TRUE
#else
#define CH_DBG_ENABLED              FALSE
#endif

#define __QUOTE_THIS(p) #p

/*===========================================================================*/
/**
 * @name    Debug related settings
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Trace buffer entries.
 */
#ifndef CH_TRACE_BUFFER_SIZE
#define CH_TRACE_BUFFER_SIZE        64
#endif

/**
 * @brief   Fill value for thread stack area in debug mode.
 */
#ifndef CH_STACK_FILL_VALUE
#define CH_STACK_FILL_VALUE         0x55
#endif

/**
 * @brief   Fill value for thread area in debug mode.
 * @note    The chosen default value is 0xFF in order to make evident which
 *          thread fields were not initialized when inspecting the memory with
 *          a debugger. A uninitialized field is not an error in itself but it
 *          better to know it.
 */
#ifndef CH_THREAD_FILL_VALUE
#define CH_THREAD_FILL_VALUE        0xFF
#endif

/** @} */

/*===========================================================================*/
/* System state checker related code and variables.                          */
/*===========================================================================*/

#if !CH_DBG_SYSTEM_STATE_CHECK
#define dbg_check_disable()
#define dbg_check_suspend()
#define dbg_check_enable()
#define dbg_check_lock()
#define dbg_check_unlock()
#define dbg_check_lock_from_isr()
#define dbg_check_unlock_from_isr()
#define dbg_check_enter_isr()
#define dbg_check_leave_isr()
#define chDbgCheckClassI();
#define chDbgCheckClassS();
#endif

/*===========================================================================*/
/* Trace related structures and macros.                                      */
/*===========================================================================*/

#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__)
/**
 * @brief   Trace buffer record.
 */
typedef struct {
  systime_t             se_time;    /**< @brief Time of the switch event.   */
  Thread                *se_tp;     /**< @brief Switched in thread.         */
  void                  *se_wtobjp; /**< @brief Object where going to sleep.*/
  uint8_t               se_state;   /**< @brief Switched out thread state.  */
} ch_swc_event_t;

/**
 * @brief   Trace buffer header.
 */
typedef struct {
  unsigned              tb_size;    /**< @brief Trace buffer size (entries).*/
  ch_swc_event_t        *tb_ptr;    /**< @brief Pointer to the buffer front.*/
  /** @brief Ring buffer.*/
  ch_swc_event_t        tb_buffer[CH_TRACE_BUFFER_SIZE];
} ch_trace_buffer_t;

#if !defined(__DOXYGEN__)
extern ch_trace_buffer_t dbg_trace_buffer;
#endif

#endif /* CH_DBG_ENABLE_TRACE */

#if !CH_DBG_ENABLE_TRACE
/* When the trace feature is disabled this function is replaced by an empty
   macro.*/
#define dbg_trace(otp)
#endif

/*===========================================================================*/
/* Parameters checking related macros.                                       */
/*===========================================================================*/

#if CH_DBG_ENABLE_CHECKS || defined(__DOXYGEN__)
/**
 * @name    Macro Functions
 * @{
 */
/**
 * @brief   Function parameter check.
 * @details If the condition check fails then the kernel panics and halts.
 * @note    The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch
 *          is specified in @p chconf.h else the macro does nothing.
 *
 * @param[in] c         the condition to be verified to be true
 * @param[in] func      the undecorated function name
 *
 * @api
 */
#if !defined(chDbgCheck)
#define chDbgCheck(c, func) {                                           \
  if (!(c))                                                             \
    chDbgPanic(__QUOTE_THIS(func)"()");                                 \
}
#endif /* !defined(chDbgCheck) */
/** @} */
#else /* !CH_DBG_ENABLE_CHECKS */
#define chDbgCheck(c, func) {                                           \
  (void)(c), (void)__QUOTE_THIS(func)"()";                              \
}
#endif /* !CH_DBG_ENABLE_CHECKS */

/*===========================================================================*/
/* Assertions related macros.                                                */
/*===========================================================================*/

#if CH_DBG_ENABLE_ASSERTS || defined(__DOXYGEN__)
/**
 * @name    Macro Functions
 * @{
 */
/**
 * @brief   Condition assertion.
 * @details If the condition check fails then the kernel panics with the
 *          specified message and halts.
 * @note    The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS switch
 *          is specified in @p chconf.h else the macro does nothing.
 * @note    The convention for the message is the following:<br>
 *          @<function_name@>(), #@<assert_number@>
 * @note    The remark string is not currently used except for putting a
 *          comment in the code about the assertion.
 *
 * @param[in] c         the condition to be verified to be true
 * @param[in] m         the text message
 * @param[in] r         a remark string
 *
 * @api
 */
#if !defined(chDbgAssert)
#define chDbgAssert(c, m, r) {                                          \
  if (!(c))                                                             \
    chDbgPanic(m);                                                      \
}
#endif /* !defined(chDbgAssert) */
/** @} */
#else /* !CH_DBG_ENABLE_ASSERTS */
#define chDbgAssert(c, m, r) {(void)(c);}
#endif /* !CH_DBG_ENABLE_ASSERTS */

extern char *dbg_panic_msg;

/*===========================================================================*/
/* Panic related macros.                                                     */
/*===========================================================================*/

#if !CH_DBG_ENABLED
/* When the debug features are disabled this function is replaced by an empty
   macro.*/
#define chDbgPanic(msg) {}
#endif

#ifdef __cplusplus
extern "C" {
#endif
#if CH_DBG_SYSTEM_STATE_CHECK
  void dbg_check_disable(void);
  void dbg_check_suspend(void);
  void dbg_check_enable(void);
  void dbg_check_lock(void);
  void dbg_check_unlock(void);
  void dbg_check_lock_from_isr(void);
  void dbg_check_unlock_from_isr(void);
  void dbg_check_enter_isr(void);
  void dbg_check_leave_isr(void);
  void chDbgCheckClassI(void);
  void chDbgCheckClassS(void);
#endif
#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__)
  void _trace_init(void);
  void dbg_trace(Thread *otp);
#endif
#if CH_DBG_ENABLED
  void chDbgPanic(char *msg);
#endif
#ifdef __cplusplus
}
#endif

#endif /* _CHDEBUG_H_ */

/** @} */