{"id":197998,"date":"2026-03-11T12:11:50","date_gmt":"2026-03-11T12:11:50","guid":{"rendered":"https:\/\/innovationspace.ansys.com\/knowledge\/?post_type=topic&#038;p=197998"},"modified":"2026-03-11T13:14:04","modified_gmt":"2026-03-11T13:14:04","slug":"generating-efficient-code-from-a-swan-model","status":"publish","type":"topic","link":"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/generating-efficient-code-from-a-swan-model\/","title":{"rendered":"Generating efficient code from a Swan model"},"content":{"rendered":"<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-banner.jpeg\" style=\"max-height: 700px !important\" \/><\/p>\n<h3  id=\"INTRODUCTION\">Introduction<\/h3>\n<p>In this post, we&#8217;ll take a closer look at one of the key improvements in Scade One 2026 R1: the Swan code generator. This tool converts Swan models into efficient, portable C code, and with the latest release, it&#8217;s now even better at optimizing performance of the generated code.<\/p>\n<p>In a <a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/scade-one-bridging-the-gap-between-model-based-design-and-traditional-programming\/\">previous blog post<\/a>, for the first release of Scade One, we introduced the Swan language, used for modeling in Scade One. One of the specificities of Swan compared to traditional programming languages like C\/C++ or Rust is that it is <em>declarative<\/em>. It means that a Swan model describes <em>what<\/em> to compute, using equations and a mathematical definition of the outputs. The code generator takes care of <em>how<\/em> to compute the results, translating the high-level description in the Swan model into imperative C code. In particular, the code generator needs to allocate variables and memory and decide in which order to perform the various operations. This approach makes it possible to build complex applications using a high-level language like Swan, even if you&#8217;re not a seasoned programmer, while still delivering performance that&#8217;s on par with hand-written C code.<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-generation-diagram.png\" style=\"max-height: 350px !important\" \/><br \/>\n    <em>Figure 1&#8211; Generating imperative code from a declarative model<\/em>\n<\/p>\n<p>In this blog, we&#8217;ll show various examples to illustrate how the Swan code generator generates efficient C code. These examples are also a good way to illustrate interesting use cases for the new constructs introduced in Swan. Finally, we&#8217;ll preview another new feature in 2026 R1, which enables more control over the allocation of memory in the generated code, when using external libraries like BLAS and when performance is key. <\/p>\n<h3  id=\"IMPLEMENTING-A-CONVOLUTION-ON-A-MATRIX\">Implementing a convolution on a matrix<\/h3>\n<p>Let&#8217;s start by looking at a convolution algorithm. We have already shown in a <a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/image-processing-in-scade-one-with-the-pack-operator\/\">previous blog<\/a> how to implement convolution in Swan using nested forward iterations (the new loop-like construct introduced in Swan). Here, we will use an alternative way that only makes sense in a declarative language like Swan and is very different from an imperative implementation.<\/p>\n<p>In this example, the <code>Convol2D<\/code> operator takes as input a square matrix <code>I<\/code> (of size N by N) and returns a matrix <code>C<\/code> (of size (N-2) by (N-2)), where each element is obtained by doing a weighted average of the neighbors using the coefficients in matrix <code>K<\/code>.<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-convol2d.png\" style=\"max-height: 319px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>This is done by using the <code>Pack2D<\/code> operator to create an intermediate matrix (of size (N-2) by (N-2)), where each element is the matrix of the neighbors in the input matrix I. Then, we just iterate on this matrix and apply the <code>WeightedAvg<\/code> operator on each sub-matrix. It may seem counter-intuitive to compute this huge intermediate matrix (of type <code>int32^P^P^(N-2)^(N-2)<\/code> !). It works because this matrix is never actually created in the generated code. The code generator transforms the iteration on this intermediate matrix into an iteration on the input matrix I, with the necessary index adaptations:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"color: #998;font-style: italic\">\/* Convol2D::Convol2D_8 *\/<\/span>\r\n<span style=\"color: #458;font-weight: bold\">void<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #900;font-weight: bold\">Convol2D_8_Convol2D<\/span>(\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* I *\/<\/span>\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">const<\/span><span style=\"color: #BBB\"> <\/span>array_int32_8_8<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>I,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* K *\/<\/span>\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">const<\/span><span style=\"color: #BBB\"> <\/span>array_int32_3_3<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>K,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* C *\/<\/span>array_int32_6_6<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>C)\r\n{\r\n<span style=\"color: #BBB\">\u00a0 <\/span>swan_size<span style=\"color: #BBB\"> <\/span>i1;\r\n<span style=\"color: #BBB\">\u00a0 <\/span>swan_size<span style=\"color: #BBB\"> <\/span>j1;\r\n<span style=\"color: #BBB\">\u00a0 <\/span>swan_size<span style=\"color: #BBB\"> <\/span>k1;\r\n<span style=\"color: #BBB\">\u00a0 <\/span>swan_size<span style=\"color: #BBB\"> <\/span>i11;\r\n\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">for<\/span><span style=\"color: #BBB\"> <\/span>(i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">0<\/span>;<span style=\"color: #BBB\"> <\/span>i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">&lt;<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">6<\/span>;<span style=\"color: #BBB\"> <\/span>i1<span style=\"font-weight: bold\">++<\/span>)<span style=\"color: #BBB\"> <\/span>{\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 <\/span><span style=\"font-weight: bold\">for<\/span><span style=\"color: #BBB\"> <\/span>(j1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">0<\/span>;<span style=\"color: #BBB\"> <\/span>j1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">&lt;<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">6<\/span>;<span style=\"color: #BBB\"> <\/span>j1<span style=\"font-weight: bold\">++<\/span>)<span style=\"color: #BBB\"> <\/span>{\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 \u00a0 <\/span>(<span style=\"font-weight: bold\">*<\/span>C)[i1][j1]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>swan_lit_int32(<span style=\"color: #099\">0<\/span>);\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: bold\">for<\/span><span style=\"color: #BBB\"> <\/span>(k1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">0<\/span>;<span style=\"color: #BBB\"> <\/span>k1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">&lt;<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">3<\/span>;<span style=\"color: #BBB\"> <\/span>k1<span style=\"font-weight: bold\">++<\/span>)<span style=\"color: #BBB\"> <\/span>{\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: bold\">for<\/span><span style=\"color: #BBB\"> <\/span>(i11<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">0<\/span>;<span style=\"color: #BBB\"> <\/span>i11<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">&lt;<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">3<\/span>;<span style=\"color: #BBB\"> <\/span>i11<span style=\"font-weight: bold\">++<\/span>)<span style=\"color: #BBB\"> <\/span>{\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <\/span>(<span style=\"font-weight: bold\">*<\/span>C)[i1][j1]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>(<span style=\"font-weight: bold\">*<\/span>C)[i1][j1]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>(<span style=\"font-weight: bold\">*<\/span>I)[k1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>i1][i11<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>j1]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span>(<span style=\"font-weight: bold\">*<\/span>K)[k1][i11];\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 \u00a0 \u00a0 <\/span>}\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 \u00a0 <\/span>}\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 <\/span>}\r\n<span style=\"color: #BBB\">\u00a0 <\/span>}\r\n}\r\n<\/pre>\n<\/div>\n<p>Another advantage of this approach is that the <code>Pack2D<\/code> operator can be used as a library operator, without having to know how it&#8217;s implemented (using a non-trivial combination of <code>pack<\/code> and <code>transpose<\/code>). But, in the end, the code generated from this high-level description is as efficient as a direct implementation using nested for loops in C.<\/p>\n<p><em>Did you know?<\/em> If you want to learn more about Swan, you can look at the examples provided with Scade One. The <a href=\"https:\/\/ansyshelp.ansys.com\/public\/account\/secured?returnurl=\/Views\/Secured\/ScadeOne\/v252\/en\/ScadeOne\/techdoc_en-US\/examples\/language_examples.html\">corresponding user documentation<\/a> is available for free, without any registration, on the Ansys Help website.<\/p>\n<h3  id=\"COMPUTING-A-MOVING-AVERAGE-OF-A-SIGNAL\">Computing a moving average of a signal<\/h3>\n<p>Now let&#8217;s switch to another example. The goal here is to compute the moving average of the last n values of an input flow. This is easily implemented in Swan using the temporal window operator <code>window<\/code>. It returns an array of the last n values of the input flow, where the element at index <em>i<\/em> is the input value <em>i+1<\/em> cycles ago. Then, we just compute the average of the elements by iterating on the array:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-movingavg.png\" style=\"max-height: 238px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>This example is straightforward, but it&#8217;s more interesting to look at the generated code:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"color: #998;font-style: italic\">\/* MovingAvg::MovingAvg *\/<\/span>\r\n<span style=\"color: #458;font-weight: bold\">void<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #900;font-weight: bold\">MovingAvg_MovingAvg<\/span>(\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* x *\/<\/span>swan_float32<span style=\"color: #BBB\"> <\/span>x,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* avg *\/<\/span>swan_float32<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>avg,\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC_MovingAvg_MovingAvg<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>outC)\r\n{\r\n<span style=\"color: #BBB\">\u00a0 <\/span>swan_size<span style=\"color: #BBB\"> <\/span>i1;\r\n\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">*<\/span>avg<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>swan_lit_float32(<span style=\"color: #099\">0.0<\/span>);\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">for<\/span><span style=\"color: #BBB\"> <\/span>(i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">0<\/span>;<span style=\"color: #BBB\"> <\/span>i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">&lt;<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">5<\/span>;<span style=\"color: #BBB\"> <\/span>i1<span style=\"font-weight: bold\">++<\/span>)<span style=\"color: #BBB\"> <\/span>{\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 <\/span><span style=\"font-weight: bold\">*<\/span>avg<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>avg<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>outC<span style=\"font-weight: bold\">-&gt;<\/span>window.items[(<span style=\"font-weight: bold\">-<\/span><span style=\"color: #BBB\"> <\/span>i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>(outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">4<\/span>))<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">%<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">5<\/span>];\r\n<span style=\"color: #BBB\">\u00a0 <\/span>}\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC<span style=\"font-weight: bold\">-&gt;<\/span>window.items[outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>x;\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>(outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">1<\/span>)<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">%<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">5<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>The <code>window<\/code> operator is implemented as a circular buffer: at each cycle, the current value is stored in buffer <code>window.items<\/code> at index <code>window.idx<\/code>, and the index is incremented (modulo the size of the buffer). As we have seen before, the output array of the window is never actually built. Any access or iteration on this array is transformed into an access or iteration on the circular buffer. <\/p>\n<h3  id=\"DESIGNING-DIGITAL-FILTERS-IN-SWAN\">Designing digital filters in Swan<\/h3>\n<p>The temporal <code>window<\/code> operator is also a perfect fit for implementing digital filters. Let us first consider a Finite Impulse Response (FIR) digital filter, defined by:<\/p>\n<p>$$y=\\sum_{k=0}^{N}{B\\left[k\\right]\\cdot x_{n-k}}$$<\/p>\n<p>Since <code>window<\/code> gives access to the N past values of a flow (in this formula $x_{n-1}, \\ldots, x_{n-N}$) but not to the current one ($x_{n}$), we put the term $B\\left[0\\right]\\cdot x_{n}$  out of the sum to isolate what can be computed as an iteration on the window :<\/p>\n<p>$$y=B\\left[0\\right]\\cdot x_n+\\sum_{k=1}^{N}{B\\left[k\\right]\\cdot x_{n-k}}$$<\/p>\n<p>Supposing the filter initializes with zero, the formula above can be expressed as:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-fir-filter.png\" style=\"max-height: 306px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>Note that this implementation is parametrized by the size N of the input array; this is an improvement over the Scade 6 language, where it was not possible to create such a generic implementation using only the <code>fby<\/code> operator. The code generated in this example is again very efficient:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"color: #998;font-style: italic\">\/* Filters::FIR_filter *\/<\/span>\r\n<span style=\"color: #458;font-weight: bold\">void<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #900;font-weight: bold\">FIR_filter_Filters<\/span>(\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* x *\/<\/span>swan_float32<span style=\"color: #BBB\"> <\/span>x,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* B *\/<\/span>\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">const<\/span><span style=\"color: #BBB\"> <\/span>array_float32_4<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>B,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* y *\/<\/span>swan_float32<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>y,\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC_FIR_filter_Filters<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>outC)\r\n{\r\n<span style=\"color: #BBB\">\u00a0 <\/span>swan_size<span style=\"color: #BBB\"> <\/span>i1;\r\n\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">*<\/span>y<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>(<span style=\"font-weight: bold\">*<\/span>B)[<span style=\"color: #099\">0<\/span>]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span>x;\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"font-weight: bold\">for<\/span><span style=\"color: #BBB\"> <\/span>(i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">0<\/span>;<span style=\"color: #BBB\"> <\/span>i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">&lt;<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">3<\/span>;<span style=\"color: #BBB\"> <\/span>i1<span style=\"font-weight: bold\">++<\/span>)<span style=\"color: #BBB\"> <\/span>{\r\n<span style=\"color: #BBB\">\u00a0 \u00a0 <\/span><span style=\"font-weight: bold\">*<\/span>y<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>y<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>(<span style=\"font-weight: bold\">*<\/span>B)[i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">1<\/span>]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span>outC<span style=\"font-weight: bold\">-&gt;<\/span>window.items[(<span style=\"font-weight: bold\">-<\/span><span style=\"color: #BBB\"> <\/span>i1<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span>(outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">2<\/span>))<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">%<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">3<\/span>];\r\n<span style=\"color: #BBB\">\u00a0 <\/span>}\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC<span style=\"font-weight: bold\">-&gt;<\/span>window.items[outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx]<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>x;\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">=<\/span><span style=\"color: #BBB\"> <\/span>(outC<span style=\"font-weight: bold\">-&gt;<\/span>window.idx<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">+<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">1<\/span>)<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">%<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #099\">3<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<h3  id=\"CONTROLLING-MEMORY-ALLOCATION-IN-THE-GENERATED-CODE\">Controlling memory allocation in the generated code<\/h3>\n<h5  id=\"INTRODUCING-MEMORY-CONTROL-ANNOTATIONS\">Introducing memory control annotations<\/h5>\n<p>As we have seen in the previous examples, the Swan code generator takes care of generating efficient code from Swan models. To do that, it follows a number of optimizations and heuristics. Most of the time that is enough, but for more advanced use cases, it is not. <\/p>\n<p>A new feature in Scade One 2026 R1 allows more control on memory allocated by the code generator. The idea is to add annotations to the model that correspond to constraints on the memory allocation in the generated code. These annotations guide the code generator to generate more efficient code and enable new use cases as we&#8217;ll soon see. The code generator may fail to generate code if the constraints cannot be satisfied and will then raise an error message.<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-annotations.png\" style=\"max-height: 350px !important\" \/><br \/>\n    <em>Figure 2&#8211; Using annotations to control memory in the generated code<\/em>\n<\/p>\n<p>It is important to understand that these annotations do not change the nature of the language: it is still a declarative language, and the behavior of models is the same with or without annotations.<\/p>\n<h5  id=\"USING-ANNOTATIONS-TO-LEVERAGE-EFFICIENT-LIBRARIES\">Using annotations to leverage efficient libraries<\/h5>\n<p>The first use case for these new annotations is to efficiently use existing C code, in particular libraries like <a href=\"https:\/\/en.wikipedia.org\/wiki\/Basic_Linear_Algebra_Subprograms\">BLAS<\/a>. Although Swan generated code is efficient, it will never be as efficient as such libraries, that are hand-tuned or use specific compiler or hardware features. <\/p>\n<p>Let us consider the <code>axpy<\/code> function of the BLAS library which computes a vector-scalar product and adds the result to the input vector:<\/p>\n<p>$$y := a*x + y$$<\/p>\n<p>Swan allows using such external (or imported) C code by having a Swan operator declaration with no matching definition:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"font-weight: bold\">function<\/span> saxpy&amp;lt;&amp;zwj;&amp;lt;&amp;zwj;N&amp;zwj;&amp;gt;&amp;zwj;&amp;gt;(a: <span style=\"color: #458;font-weight: bold\">float64<\/span>; x: <span style=\"color: #458;font-weight: bold\">float64<\/span><span style=\"font-weight: bold\">^<\/span>N; y: <span style=\"color: #458;font-weight: bold\">float64<\/span><span style=\"font-weight: bold\">^<\/span>N)\r\n  <span style=\"font-weight: bold\">returns<\/span> (z: <span style=\"color: #458;font-weight: bold\">float64<\/span><span style=\"font-weight: bold\">^<\/span>N);\r\n<\/pre>\n<\/div>\n<p>The expected signature of such a function (that must be implemented by the user) is:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"color: #998;font-style: italic\">\/* Imported::saxpy *\/<\/span>\r\n<span style=\"font-weight: bold\">extern<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #458;font-weight: bold\">void<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #900;font-weight: bold\">saxpy_Imported<\/span>(\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* a *\/<\/span><span style=\"color: #BBB\"> <\/span>swan_float64<span style=\"color: #BBB\"> <\/span>a,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* x *\/<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">const<\/span><span style=\"color: #BBB\"> <\/span>array_float64_100<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>x,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* y *\/<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">const<\/span><span style=\"color: #BBB\"> <\/span>array_float64_100<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>y,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* z *\/<\/span><span style=\"color: #BBB\"> <\/span>array_float64_100<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>z,\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC_saxpy_Imported<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>outC);\r\n<\/pre>\n<\/div>\n<p>The important point here is that the input arrays <code>x<\/code> and <code>y<\/code> and the output array <code>z<\/code> are separate variables. This does not correspond to the API of the BLAS function, which updates the y input in-place. Until now, there was no other solution than to write a wrapper around the BLAS call that would perform an array copy, to match the signature expected by the code generator.<\/p>\n<p>The new annotations introduced in Scade One 2026 R1 allow to constrain the code generator, so that the imported function can modify the input in-place:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"font-weight: bold\">function<\/span> blas_saxpy&amp;lt;&amp;zwj;&amp;lt;&amp;zwj;N&amp;zwj;&amp;gt;&amp;zwj;&amp;gt;(a: <span style=\"color: #458;font-weight: bold\">float64<\/span>; x: <span style=\"color: #458;font-weight: bold\">float64<\/span><span style=\"font-weight: bold\">^<\/span>N; y <span style=\"font-weight: bold\">*<\/span>: <span style=\"color: #458;font-weight: bold\">float64<\/span><span style=\"font-weight: bold\">^<\/span>N)\r\n  <span style=\"font-weight: bold\">returns<\/span> (z at y: <span style=\"color: #458;font-weight: bold\">float64<\/span><span style=\"font-weight: bold\">^<\/span>N);\r\n<\/pre>\n<\/div>\n<p>The first annotation (<code>y *<\/code>) means that there should be no dedicated memory location for <code>y<\/code>. The second one (<code>z at y<\/code>) means that <code>z<\/code> should be stored at the same location as<code> y<\/code>. The expected C signature for this annotated imported operator is:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"color: #998;font-style: italic\">\/* Blas::blas_saxpy *\/<\/span>\r\n<span style=\"font-weight: bold\">extern<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #458;font-weight: bold\">void<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #900;font-weight: bold\">blas_saxpy_Blas<\/span>(\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* a *\/<\/span><span style=\"color: #BBB\"> <\/span>swan_float64<span style=\"color: #BBB\"> <\/span>a,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* x *\/<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">const<\/span><span style=\"color: #BBB\"> <\/span>array_float64_100<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span>x,\r\n<span style=\"color: #BBB\">\u00a0 <\/span><span style=\"color: #998;font-style: italic\">\/* y *\/<\/span><span style=\"color: #BBB\"> <\/span>array_float64_100<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>y,\r\n<span style=\"color: #BBB\">\u00a0 <\/span>outC_blas_saxpy_Blas<span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">*<\/span><span style=\"color: #BBB\"> <\/span><span style=\"font-weight: bold\">restrict<\/span><span style=\"color: #BBB\"> <\/span>outC);\r\n<\/pre>\n<\/div>\n<p>We can see that the output<code> z<\/code> has disappeared: the code generator will now read the output <code>z<\/code> in the memory location storing <code>y<\/code>. Of course, using this function impacts the generated code. For instance, the code generator must remember that after calling <code>blas_saxpy<\/code>, the array used as input is overwritten, so any access to this array must be done before calling <code>blas_saxpy<\/code>.<\/p>\n<p>This is the first release of this new feature. We&#8217;ll have more use cases to show on that topic in future releases (and future blogs). Stay tuned!<\/p>\n<h3  id=\"EXPLORE-FURTHER\">Explore further<\/h3>\n<p>In this article, we have illustrated how the Swan code generator takes a high-level Swan model and turns it into efficient, portable C code. We have focused in particular on operators manipulating arrays and matrices, where the code generator avoids unnecessary copies or intermediate arrays and generates efficient index computations.  You can download the examples from <a href=\"https:\/\/github.com\/ansys\/scadeone-examples\/releases\/latest\/download\/2026-03-11-efficient-codegen.zip\">here<\/a>.<\/p>\n<p>If you&#8217;d like to learn more about Ansys Scade One, we&#8217;d love to hear from you! Get in touch on our <a href=\"https:\/\/www.ansys.com\/products\/embedded-software\/ansys-scade-one\">product page<\/a>.<\/p>\n<h3  id=\"ABOUT-THE-AUTHOR\">About the author<\/h3>\n<table style=\"max-width: 1000px;border: none !important\">\n<tr>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/03\/scade-052-author.png\" style=\"max-height: 150px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<\/td>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p><strong>C\u00e9dric Pasteur<\/strong> (<a href=\"https:\/\/www.linkedin.com\/in\/c%C3%A9dric-pasteur-9b430b25\/\">LinkedIn<\/a>) is a Senior Product Manager at Ansys. He has been working on Scade One, Ansys&#8217; latest-generation model-based embedded software development product, since its inception. He specializes in programming language theory and its application to safe embedded systems.<\/p>\n<\/td>\n<\/tr>\n<\/table>\n","protected":false},"template":"","class_list":["post-197998","topic","type-topic","status-publish","hentry","topic-tag-c","topic-tag-code","topic-tag-performance","topic-tag-scade-one","topic-tag-swan"],"aioseo_notices":[],"acf":[],"custom_fields":[{"0":{"_edit_lock":["1774542139:1769"],"_edit_last":["1769"],"_aioseo_title":[null],"_aioseo_description":[null],"_aioseo_keywords":["a:0:{}"],"_aioseo_og_title":[null],"_aioseo_og_description":[null],"_aioseo_og_article_section":[""],"_aioseo_og_article_tags":["a:0:{}"],"_aioseo_twitter_title":[null],"_aioseo_twitter_description":[null],"filter_by_optics_product":["Lumerical"],"_filter_by_optics_product":["field_64fb192ba3121"],"application_name":[""],"_application_name":["field_64a80903c8e15"],"family":[""],"_family":["field_64a809229a857"],"siebel_km_number":[""],"_siebel_km_number":["field_63ecbffce60db"],"salesforce_km_number":[""],"_salesforce_km_number":["field_63ecc018e60dc"],"km_published_date":[""],"_km_published_date":["field_64c77704499dd"],"product_version":[""],"_product_version":["field_64c776cb4fd2e"],"_bbp_forum_id":["27825"],"_bbp_topic_id":["198004"],"_bbp_author_ip":["87.190.19.71"],"_bbp_last_reply_id":["0"],"_bbp_last_active_id":["197999"],"_bbp_last_active_time":["2026-03-11 12:11:50"],"_bbp_reply_count":["0"],"_bbp_reply_count_hidden":["0"],"_bbp_voice_count":["0"],"_btv_view_count":["214"],"_bbp_likes_count":["4"]},"test":"solution"}],"_links":{"self":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/197998","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics"}],"about":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":6,"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/197998\/revisions"}],"predecessor-version":[{"id":198004,"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/197998\/revisions\/198004"}],"wp:attachment":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/media?parent=197998"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}