From 6b71c162b9fd73cefcaf121e62ea557556d61595 Mon Sep 17 00:00:00 2001
From: sts1u16 <sts1u16@ecs.soton.ac.uk>
Date: Tue, 13 Aug 2019 16:09:48 +0100
Subject: [PATCH] Update of build system to build allocated state and managed
 state simulaneously.

---
 CMakeLists.txt                              |  11 +
 aes/CMakeLists.txt                          |  26 +
 {aes128 => aes}/TI_aes_128_encr_only.c      |   0
 {aes128 => aes}/TI_aes_128_encr_only.h      |   0
 {aes128 => aes}/debug.gdb                   |   0
 {aes128 => aes}/generate-reference-output.c |   0
 {aes128 => aes}/lipsum.h                    |   0
 {aes128 => aes}/main.c                      |   0
 aes128/CMakeLists.txt                       |  30 --
 blink/CMakeLists.txt                        |  19 +-
 common.cmake                                |   9 +-
 crc32/CMakeLists.txt                        |  49 +-
 iclib/CMakeLists.txt                        |  41 +-
 iclib/common.c                              |  24 +
 iclib/common.h                              |   9 +
 iclib/config.h                              |  10 +-
 iclib/ic.c                                  |  62 +--
 iclib/memory_management.c                   | 518 ++++++++++----------
 iclib/memory_management.h                   |  12 +-
 matmul-tiled/CMakeLists.txt                 |  44 +-
 matmul/CMakeLists.txt                       |  43 +-
 21 files changed, 465 insertions(+), 442 deletions(-)
 create mode 100644 CMakeLists.txt
 create mode 100644 aes/CMakeLists.txt
 rename {aes128 => aes}/TI_aes_128_encr_only.c (100%)
 rename {aes128 => aes}/TI_aes_128_encr_only.h (100%)
 rename {aes128 => aes}/debug.gdb (100%)
 rename {aes128 => aes}/generate-reference-output.c (100%)
 rename {aes128 => aes}/lipsum.h (100%)
 rename {aes128 => aes}/main.c (100%)
 delete mode 100644 aes128/CMakeLists.txt
 create mode 100644 iclib/common.c
 create mode 100644 iclib/common.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ec1f1de
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.2)
+
+include(common.cmake)
+
+project(ic-examples)
+
+#target_compile_options(aes PUBLIC -finstrument-functions)
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+add_subdirectory(iclib)
+add_subdirectory(aes)
diff --git a/aes/CMakeLists.txt b/aes/CMakeLists.txt
new file mode 100644
index 0000000..9721b18
--- /dev/null
+++ b/aes/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.0)
+
+FOREACH(METHOD "MS" "AS")
+    set(TESTNAME "aes-${METHOD}")
+    add_executable(
+        ${TESTNAME}
+        main.c
+        TI_aes_128_encr_only.c
+        TI_aes_128_encr_only.h
+        lipsum.h
+    )
+    IF (${METHOD} STREQUAL "AS")
+        target_compile_definitions( ${TESTNAME} PUBLIC -DALLOCATEDSTATE)
+    ENDIF()
+    add_msp_upload(${TESTNAME})
+    target_link_libraries(
+        ${TESTNAME}
+        LINK_PUBLIC ic-${METHOD}
+        ${SUPPORT_LIBS})
+    set_target_properties(${TESTNAME} PROPERTIES SUFFIX ".elf")
+    add_custom_command(TARGET ${TESTNAME} POST_BUILD
+        COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${TESTNAME}>"
+        COMMENT "Invoking: msp430-elf-size")
+ENDFOREACH()
+
+
diff --git a/aes128/TI_aes_128_encr_only.c b/aes/TI_aes_128_encr_only.c
similarity index 100%
rename from aes128/TI_aes_128_encr_only.c
rename to aes/TI_aes_128_encr_only.c
diff --git a/aes128/TI_aes_128_encr_only.h b/aes/TI_aes_128_encr_only.h
similarity index 100%
rename from aes128/TI_aes_128_encr_only.h
rename to aes/TI_aes_128_encr_only.h
diff --git a/aes128/debug.gdb b/aes/debug.gdb
similarity index 100%
rename from aes128/debug.gdb
rename to aes/debug.gdb
diff --git a/aes128/generate-reference-output.c b/aes/generate-reference-output.c
similarity index 100%
rename from aes128/generate-reference-output.c
rename to aes/generate-reference-output.c
diff --git a/aes128/lipsum.h b/aes/lipsum.h
similarity index 100%
rename from aes128/lipsum.h
rename to aes/lipsum.h
diff --git a/aes128/main.c b/aes/main.c
similarity index 100%
rename from aes128/main.c
rename to aes/main.c
diff --git a/aes128/CMakeLists.txt b/aes128/CMakeLists.txt
deleted file mode 100644
index 93c7f94..0000000
--- a/aes128/CMakeLists.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-cmake_minimum_required(VERSION 3.0)
-
-include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)
-
-project(aes-MS)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-
-include_directories(${ICLIB_ROOT})
-link_directories(${ICLIB_ROOT})
-
-add_executable(
-    ${PROJECT_NAME}
-    main.c
-    TI_aes_128_encr_only.c
-    TI_aes_128_encr_only.h
-    lipsum.h
-)
-
-add_msp_upload(${PROJECT_NAME})
-
-target_link_libraries(${PROJECT_NAME}  ${SUPPORT_LIBS})
-
-set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
-
-#target_compile_options(${PROJECT_NAME} PUBLIC -finstrument-functions)
-
-add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
-    COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${PROJECT_NAME}>"
-    COMMENT "Invoking: msp430-elf-size")
diff --git a/blink/CMakeLists.txt b/blink/CMakeLists.txt
index 56c7f0c..178a3ae 100644
--- a/blink/CMakeLists.txt
+++ b/blink/CMakeLists.txt
@@ -1,21 +1,12 @@
 cmake_minimum_required(VERSION 3.0)
 
-include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)
+add_executable(blink blink.c)
+add_msp_upload(blink)
 
-project(blink)
+target_link_libraries(blink LINK_PUBLIC ic ${SUPPORT_LIBS})
 
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-
-include_directories(${ICLIB_ROOT})
-link_directories(${ICLIB_ROOT})
-
-add_executable(${PROJECT_NAME} blink.c)
-add_msp_upload(${PROJECT_NAME})
-
-target_link_libraries(${PROJECT_NAME} ic mul_none gcc c)
-
-set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
+set_target_properties(blink PROPERTIES SUFFIX ".elf")
 
 add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
-    COMMAND ${MSP430-SIZE} "$<TARGET_FILE:${PROJECT_NAME}>"
+    COMMAND ${MSP430-SIZE} "$<TARGET_FILE:blink>"
     COMMENT "Invoking: msp430-elf-size")
diff --git a/common.cmake b/common.cmake
index d6243bb..ab1c7dd 100644
--- a/common.cmake
+++ b/common.cmake
@@ -1,8 +1,5 @@
 # paths
-set(ICLIB_ROOT "${CMAKE_SOURCE_DIR}/../iclib")
-
-set(CMAKE_TOOLCHAIN_FILE
-    ${CMAKE_CURRENT_LIST_DIR}/msp430-toolchain.cmake)
+set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/msp430-toolchain.cmake)
 
 # Force compiler detection so we can set up flags
 enable_language(C ASM)
@@ -19,7 +16,7 @@ add_compile_options(
 
 # Linker scripts
 set(CMAKE_EXE_LINKER_FLAGS
-    "${CMAKE_EXE_LINKER_FLAGS} -T ${CMAKE_SOURCE_DIR}/../msp430fr5994.ld ")
+    "${CMAKE_EXE_LINKER_FLAGS} -T ${CMAKE_CURRENT_SOURCE_DIR}/msp430fr5994.ld ")
 
 # Add to search path for linker scripts (xx_symbols.ld, included by main linker script)
 link_directories(
@@ -36,4 +33,4 @@ link_libraries( # Global link flags
     )
 
 # Utility for linking targets to std libs
-set(SUPPORT_LIBS ic c gcc mul_none)
+set(SUPPORT_LIBS c gcc mul_none)
diff --git a/crc32/CMakeLists.txt b/crc32/CMakeLists.txt
index b7058b7..fa034f9 100644
--- a/crc32/CMakeLists.txt
+++ b/crc32/CMakeLists.txt
@@ -1,29 +1,26 @@
 cmake_minimum_required(VERSION 3.0)
 
-include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)
+FOREACH(METHOD "MS" "AS")
+    set(TESTNAME "crc-${METHOD}")
+    add_executable(
+        ${TESTNAME}
+        main.c
+        crc.h
+        crc_32.c
+        lipsum.h
+        sniptype.h
+    )
+    IF (${METHOD} STREQUAL "AS")
+        target_compile_definitions( ${TESTNAME} PUBLIC -DALLOCATEDSTATE)
+    ENDIF()
+    add_msp_upload(${TESTNAME})
+    target_link_libraries(
+        ${TESTNAME}
+        LINK_PUBLIC ic-${METHOD}
+        ${SUPPORT_LIBS})
+    set_target_properties(${TESTNAME} PROPERTIES SUFFIX ".elf")
+    add_custom_command(TARGET ${TESTNAME} POST_BUILD
+        COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${TESTNAME}>"
+        COMMENT "Invoking: msp430-elf-size")
+ENDFOREACH()
 
-project(crc)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-
-include_directories(${ICLIB_ROOT})
-link_directories(${ICLIB_ROOT})
-
-add_executable(
-    ${PROJECT_NAME}
-    main.c
-    crc.h
-    crc_32.c
-    lipsum.h
-    sniptype.h
-)
-
-add_msp_upload(${PROJECT_NAME})
-
-target_link_libraries(${PROJECT_NAME} ${SUPPORT_LIBS})
-
-set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
-
-add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
-    COMMAND ${MSP430-SIZE} "$<TARGET_FILE:${PROJECT_NAME}>"
-    COMMENT "Invoking: msp430-elf-size")
diff --git a/iclib/CMakeLists.txt b/iclib/CMakeLists.txt
index b7e1822..7c2f0d5 100644
--- a/iclib/CMakeLists.txt
+++ b/iclib/CMakeLists.txt
@@ -2,26 +2,29 @@ cmake_minimum_required(VERSION 3.0)
 
 include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)
 
-project(ic)
+FOREACH(METHOD "MS" "AS")
+    set(TESTNAME "ic-${METHOD}")
+    add_library(
+      ${TESTNAME}
+      ic.c
+      ic.h
+      ic.S
+      memory_management.c
+      memory_management.h
+      common.c
+      common.h
+      )
 
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+    IF (${METHOD} STREQUAL "AS")
+       target_compile_definitions( ${TESTNAME} PUBLIC -DALLOCATEDSTATE)
+   ENDIF()
 
-add_library(
-  ${CMAKE_PROJECT_NAME}
-  STATIC
-  ic.c
-  ic.h
-  ic.S
-  memory_management.c
-  memory_management.h
-  )
+    target_link_libraries(${TESTNAME} ${SUPPORT_LIBS})
 
-target_link_libraries(
-    ${CMAKE_PROJECT_NAME}
-    mul_none
-    c
-    gcc)
+    target_include_directories(${TESTNAME}  PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
 
-add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
-    COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${PROJECT_NAME}>"
-    COMMENT "Invoking: msp430-elf-size")
+    add_custom_command(TARGET ${TESTNAME} POST_BUILD
+        COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${TESTNAME}>"
+        COMMENT "Invoking: msp430-elf-size")
+
+ENDFOREACH()
diff --git a/iclib/common.c b/iclib/common.c
new file mode 100644
index 0000000..5b1d58c
--- /dev/null
+++ b/iclib/common.c
@@ -0,0 +1,24 @@
+#include "common.h"
+
+void __attribute__((naked)) fastmemcpy(uint8_t *dst, uint8_t *src, size_t len) {
+  __asm__(" push r5\n"
+          " tst r14\n" // Test for len=0
+          " jz return\n"
+          " mov #2, r5\n"   // r5 = word size
+          " xor r15, r15\n" // Clear r15
+          " mov r14, r15\n" // r15=len
+          " and #1, r15\n"  // r15 = len%2
+          " sub r15, r14\n" // r14 = len - len%2
+          "loopmemcpy:  \n"
+          " mov.w @r13+, @r12\n"
+          " add r5, r12 \n"
+          " sub r5, r14 \n"
+          " jnz loopmemcpy \n"
+          " tst r15\n"
+          " jz return\n"
+          " mov.b @r13, @r12\n" // move last byte
+          "return:\n"
+          " pop r5\n"
+          " ret\n");
+}
+
diff --git a/iclib/common.h b/iclib/common.h
new file mode 100644
index 0000000..9c745fe
--- /dev/null
+++ b/iclib/common.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * Hand-written fast version of memcpy
+ * */
+void fastmemcpy(uint8_t *dst, uint8_t *src, size_t len);
diff --git a/iclib/config.h b/iclib/config.h
index df901c8..b7a5510 100644
--- a/iclib/config.h
+++ b/iclib/config.h
@@ -24,11 +24,15 @@
 
 /* ------ Threshold Calculation ---------------------------------------------*/
 #define VMAX 3665 // 3.58 V maximum operating voltage
-#define VON 2048  // On-voltage
+#define VON 1945  // On-voltage
 
 // DVDT: 1024 x voltage delta per byte saved/restored
-#define DVDT (80 * 5) // 5
+#ifdef ALLOCATEDSTATE
+#define DVDT (33 * 5) //(33 * 5) // (60*5)
+#else
+#define DVDT (60 * 5) //(33 * 5) // (60*5)
+#endif
 
-#define V_C 205 // ~0.2 V Voltage buffer for useful compute
+#define V_C 102 // 205 // ~0.2 V Voltage buffer for useful compute
 
 #endif /* SRC_CONFIG_H_ */
diff --git a/iclib/ic.c b/iclib/ic.c
index c10b3c1..81a522a 100644
--- a/iclib/ic.c
+++ b/iclib/ic.c
@@ -1,5 +1,6 @@
 #include <msp430fr5994.h>
 
+#include "common.h"
 #include "config.h"
 #include "ic.h"
 #include "memory_management.h"
@@ -13,7 +14,7 @@ extern uint8_t __boot_stack_high;
 extern uint8_t __npdata_loadLow, __npdata_low, __npdata_high;
 
 // ------------- Globals -------------------------------------------------------
-static stackTrunk = &__stack_low;
+static uint16_t *stackTrunk = (uint16_t *)&__stack_low;
 
 // ------------- PERSISTENT VARIABLES ------------------------------------------
 #define PERSISTENT __attribute__((section(".fram_vars")))
@@ -40,7 +41,6 @@ static void adc_init(void);
 static void gpio_init(void);
 static void clock_init(void);
 static void restore(void);
-static void fastmemcpy(uint8_t *dst, uint8_t *src, size_t len);
 
 /* ------ ASM functions ---------------------------------------------------- */
 extern void suspend(uint16_t *regSnapshot);
@@ -48,7 +48,8 @@ extern void restore_registers(uint16_t *regSnapshot);
 
 /* ------ Function Declarations ---------------------------------------------*/
 
-void __attribute__((interrupt(RESET_VECTOR), naked, used)) iclib_boot() {
+void __attribute__((interrupt(RESET_VECTOR), naked, used, optimize("O0")))
+iclib_boot() {
   __set_SP_register(&__boot_stack_high); // Boot stack
   WDTCTL = WDTPW | WDTHOLD;              // Stop watchdog timer
 
@@ -66,14 +67,15 @@ void __attribute__((interrupt(RESET_VECTOR), naked, used)) iclib_boot() {
   // *!Remaining code in this function is only executed during the first
   // boot!*
   //
-  // Boot: Set SP, load data and initialize LRU
+  // First time boot: Set SP, load data and initialize LRU
   __set_SP_register(&__stack_high); // Runtime stack
   fastmemcpy(&__data_low, &__data_loadLow, &__data_high - &__data_low);
   mm_init_lru();
 
-#ifndef TRACK_MMDATA
+#ifdef ALLOCATEDSTATE
   uint16_t mmdata_size = &__mmdata_end - &__mmdata_start;
   ic_update_thresholds(mmdata_size, mmdata_size);
+  mm_restore();
 #endif
 
   int main(); // Suppress implicit decl. warning
@@ -137,15 +139,15 @@ void suspendVM(void) {
   size_t len;
 
   // mmdata
-#ifdef TRACK_MMDATA
-  // Save modified pages
-  nBytesToSave = mm_flush();
-#else
+#ifdef ALLOCATEDSTATE
   // Save entire section
   src = &__mmdata_start;
   dst = (uint8_t *)&__mmdata_loadStart;
   len = &__mmdata_end - src;
   fastmemcpy(dst, src, len);
+#else
+  // Save modified pages
+  nBytesToSave = mm_flush();
 #endif
 
   // bss
@@ -197,17 +199,8 @@ void restore(void) {
   len = &__bss_high - dst;
   fastmemcpy(dst, src, len);
 
-  // mmdata
-#ifdef TRACK_MMDATA
-  // Restore active pages only
-  mm_restoreStatic();
-#else
-  // Restore entire section
-  dst = &__mmdata_start;
-  len = &__mmdata_end - dst;
-  src = (uint8_t *)&__mmdata_loadStart;
-  fastmemcpy(dst, src, len);
-#endif
+  // Restore mmdata
+  mm_restore();
 
   // stack
 #ifdef TRACK_STACK
@@ -280,7 +273,8 @@ static void adc_init(void) {
   ADC12CTL0 |= (ADC12SC | ADC12ENC); // Enable & start conversion
 }
 
-void __attribute__((__interrupt__(ADC12_B_VECTOR))) adc12_isr(void) {
+void __attribute__((__interrupt__(ADC12_B_VECTOR), optimize("O0")))
+adc12_isr(void) {
   __disable_interrupt();
 
   switch (__even_in_range(ADC12IV, ADC12IV__ADC12RDYIFG)) {
@@ -440,34 +434,12 @@ void comparator_init() {
   // CEINT = CEIE;
 }
 
-void __attribute__((naked)) fastmemcpy(uint8_t *dst, uint8_t *src, size_t len) {
-  __asm__(" push r5\n"
-          " tst r14\n" // Test for len=0
-          " jz return\n"
-          " mov #2, r5\n"   // r5 = word size
-          " xor r15, r15\n" // Clear r15
-          " mov r14, r15\n" // r15=len
-          " and #1, r15\n"  // r15 = len%2
-          " sub r15, r14\n" // r14 = len - len%2
-          "loopmemcpy:  \n"
-          " mov.w @r13+, @r12\n"
-          " add r5, r12 \n"
-          " sub r5, r14 \n"
-          " jnz loopmemcpy \n"
-          " tst r15\n"
-          " jz return\n"
-          " mov.b @r13, @r12\n" // move last byte
-          "return:\n"
-          " pop r5\n"
-          " ret\n");
-}
-
 void __attribute__((no_instrument_function))
 __cyg_profile_func_enter(void *this_fn, void *call_site) {}
 
 void __attribute__((no_instrument_function))
 __cyg_profile_func_exit(void *this_fn, void *call_site) {
-  if (__get_SP_register() < stackTrunk) {
-    stackTrunk = __get_SP_register();
+  if ((uint16_t *)__get_SP_register() < stackTrunk) {
+    stackTrunk = (uint16_t *)_get_SP_register();
   }
 }
diff --git a/iclib/memory_management.c b/iclib/memory_management.c
index 83d0dfe..648e93b 100644
--- a/iclib/memory_management.c
+++ b/iclib/memory_management.c
@@ -3,6 +3,7 @@
 #include <stdint.h>
 #include <string.h>
 
+#include "common.h"
 #include "ic.h"
 #include "memory_management.h"
 
@@ -17,8 +18,8 @@ extern uint8_t __mmdata_end;
 extern uint8_t __mmdata_loadStart;
 
 struct LRU_candidate {
-    uint8_t pageNumber;
-    uint8_t tableIdx;
+  uint8_t pageNumber;
+  uint8_t tableIdx;
 };
 
 /**************************** Type Definitions *******************************/
@@ -30,10 +31,10 @@ struct LRU_candidate {
 #error Too many pages, increase page size or reduce memory usage
 #endif
 
-#define DUMMY_PAGE 255    //! Used for LRU table
-#define REFCNT_MASK 0x3F  //! Reference count
-#define LOADED 0x80       //! Mask to check if loaded
-#define MODIFIED 0x40     //! Mask to check if modified
+#define DUMMY_PAGE 255   //! Used for LRU table
+#define REFCNT_MASK 0x3F //! Reference count
+#define LOADED 0x80      //! Mask to check if loaded
+#define MODIFIED 0x40    //! Mask to check if modified
 
 /************************** Function Prototypes ******************************/
 static void writePageFRAM(uint8_t pageNumber);
@@ -52,116 +53,132 @@ static uint8_t lruTable[MAX_DIRTY_PAGES];
 /*************************** Function definitions ****************************/
 
 int mm_acquire(const uint8_t *memPtr, mm_mode mode) {
-    if ((&__mmdata_start > (uint8_t *)memPtr) ||
-        (&__mmdata_end < (uint8_t *)memPtr)) {
-        while (1)
-            ;  // Error: Pointer out of bounds.
-    }
-
-    uint16_t pageNumber =
-        ((uint16_t)memPtr - (uint16_t)&__mmdata_start) / PAGE_SIZE;
+#ifdef ALLOCATEDSTATE
+  return 0;
+#endif
+  if ((&__mmdata_start > (uint8_t *)memPtr) ||
+      (&__mmdata_end < (uint8_t *)memPtr)) {
+    while (1)
+      ; // Error: Pointer out of bounds.
+  }
+
+  uint16_t pageNumber =
+      ((uint16_t)memPtr - (uint16_t)&__mmdata_start) / PAGE_SIZE;
+
+  if ((attributeTable[pageNumber] & REFCNT_MASK) >= 64) {
+    while (1)
+      ; // Error: Too many references to a single page
+  }
+
+  if (mode == MM_READWRITE) { // && !(attributeTable[pageNumber] & MODIFIED)){
+    if (mm_n_dirty_pages >= MAX_DIRTY_PAGES) {
+      // Need to write back an inactive and dirty page first
+      for (int i = MAX_DIRTY_PAGES - 1; i >= 0; i--) {
+        uint8_t candidate = lruTable[i];
+        if (candidate != DUMMY_PAGE) {
+          if ((attributeTable[candidate] & REFCNT_MASK) == 0 &&
+              (attributeTable[candidate] & LOADED) &&
+              (attributeTable[candidate] & MODIFIED)) {
+            writePageFRAM(candidate);
+            clearLRU(i);
+            break;
+          }
+        }
+      }
 
-    if ((attributeTable[pageNumber] & REFCNT_MASK) >= 64) {
+      if (mm_n_dirty_pages >= MAX_DIRTY_PAGES) {
         while (1)
-            ;  // Error: Too many references to a single page
+          ; // Error: MAX_DIRTY_PAGES exceeded
+      }
     }
 
-    if (mode ==
-        MM_READWRITE) {  // && !(attributeTable[pageNumber] & MODIFIED)){
-        if (mm_n_dirty_pages >= MAX_DIRTY_PAGES) {
-            // Need to write back an inactive and dirty page first
-            for (int i = MAX_DIRTY_PAGES - 1; i >= 0; i--) {
-                uint8_t candidate = lruTable[i];
-                if (candidate != DUMMY_PAGE) {
-                    if ((attributeTable[candidate] & REFCNT_MASK) == 0 &&
-                        (attributeTable[candidate] & LOADED) &&
-                        (attributeTable[candidate] & MODIFIED)) {
-                        writePageFRAM(candidate);
-                        clearLRU(i);
-                        break;
-                    }
-                }
-            }
-
-            if (mm_n_dirty_pages >= MAX_DIRTY_PAGES) {
-                while (1)
-                    ;  // Error: MAX_DIRTY_PAGES exceeded
-            }
-        }
+    if (!(attributeTable[pageNumber] &
+          MODIFIED)) { // if page isn't already dirty
+      mm_n_dirty_pages++;
+      attributeTable[pageNumber] |= MODIFIED;
+    }
 
-        if (!(attributeTable[pageNumber] &
-              MODIFIED)) {  // if page isn't already dirty
-            mm_n_dirty_pages++;
-            attributeTable[pageNumber] |= MODIFIED;
-        }
+    // Update LRU with the new dirty page
+    addLRU(pageNumber);
+  }
 
-        // Update LRU with the new dirty page
-        addLRU(pageNumber);
-    }
+  loadPage(pageNumber);
 
-    loadPage(pageNumber);
+  if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
+    mm_n_active_pages++;
+  }
+  attributeTable[pageNumber]++;
 
-    if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
-        mm_n_active_pages++;
-    }
-    attributeTable[pageNumber]++;
-
-    // Update suspend/restore thresholds
-    static int oldPageTotal = 0;
-    if (oldPageTotal != mm_n_dirty_pages + mm_n_active_pages) {
-        ic_update_thresholds(mm_n_dirty_pages * PAGE_SIZE,
-                             mm_n_active_pages * PAGE_SIZE);
-        oldPageTotal = mm_n_dirty_pages + mm_n_active_pages;
-    }
+  // Update suspend/restore thresholds
+  static int oldPageTotal = 0;
+  if (oldPageTotal != mm_n_dirty_pages + mm_n_active_pages) {
+    ic_update_thresholds(mm_n_dirty_pages * PAGE_SIZE,
+                         mm_n_active_pages * PAGE_SIZE);
+    oldPageTotal = mm_n_dirty_pages + mm_n_active_pages;
+  }
 
-    return 0;
+  return 0;
 }
 
 int mm_release(const uint8_t *memPtr) {
-    uint16_t pageNumber =
-        ((uint16_t)memPtr - (uint16_t)&__mmdata_start) / PAGE_SIZE;
-    if ((attributeTable[pageNumber] & REFCNT_MASK) > 0) {
-        attributeTable[pageNumber]--;
-        if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
-            mm_n_active_pages--;
-        }
-    } else {
-        while (1)
-            ;  // Error: Attempt to release inactive page
+#ifdef ALLOCATEDSTATE
+  return 0;
+#endif
+  uint16_t pageNumber =
+      ((uint16_t)memPtr - (uint16_t)&__mmdata_start) / PAGE_SIZE;
+  if ((attributeTable[pageNumber] & REFCNT_MASK) > 0) {
+    attributeTable[pageNumber]--;
+    if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
+      mm_n_active_pages--;
     }
-    return 0;
+  } else {
+    while (1)
+      ; // Error: Attempt to release inactive page
+  }
+  return 0;
 }
 
-void mm_restoreStatic(void) {
-    for (int pageNumber = 0; pageNumber < NPAGES; pageNumber++) {
-        // Clear loaded pages (bits are set again when calling loadPage)
-        attributeTable[pageNumber] &= ~LOADED;
+void mm_restore(void) {
+#ifdef ALLOCATEDSTATE
+  fastmemcpy(&__mmdata_start, &__mmdata_loadStart,
+             &__mmdata_end - &__mmdata_start);
+#endif
 
-        if ((attributeTable[pageNumber] & REFCNT_MASK) > 0) {
-            loadPage(pageNumber);
-        }
+  for (int pageNumber = 0; pageNumber < NPAGES; pageNumber++) {
+    // Clear loaded pages (bits are set again when calling loadPage)
+    attributeTable[pageNumber] &= ~LOADED;
+
+    if ((attributeTable[pageNumber] & REFCNT_MASK) > 0) {
+      loadPage(pageNumber);
     }
+  }
 }
 
 unsigned mm_flush(void) {
-    unsigned pagesSaved = 0;
-
-    for (int pageNumber = 0; pageNumber < NPAGES; pageNumber++) {
-        if (mm_n_dirty_pages == 0) {
-            break;
-        } else if (attributeTable[pageNumber] & MODIFIED) {
-            writePageFRAM(pageNumber);
-            pagesSaved++;
-            if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
-                clearLRUPage(pageNumber);
-            }
-        }
+#ifdef ALLOCATEDSTATE
+  // Save entire section
+  fastmemcpy(&__mmdata_loadStart, &__mmdata_start,
+             &__mmdata_end - &__mmdata_start);
+  return (size_t)(&__mmdata_end - &__mmdata_start);
+#endif
+  unsigned pagesSaved = 0;
+
+  for (int pageNumber = 0; pageNumber < NPAGES; pageNumber++) {
+    if (mm_n_dirty_pages == 0) {
+      break;
+    } else if (attributeTable[pageNumber] & MODIFIED) {
+      writePageFRAM(pageNumber);
+      pagesSaved++;
+      if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
+        clearLRUPage(pageNumber);
+      }
     }
+  }
 
-    ic_update_thresholds(mm_n_dirty_pages * PAGE_SIZE,
-                         mm_n_active_pages * PAGE_SIZE);
+  ic_update_thresholds(mm_n_dirty_pages * PAGE_SIZE,
+                       mm_n_active_pages * PAGE_SIZE);
 
-    return pagesSaved * PAGE_SIZE;
+  return pagesSaved * PAGE_SIZE;
 }
 
 /**
@@ -169,124 +186,133 @@ unsigned mm_flush(void) {
  * @param pageNumber
  */
 static void writePageFRAM(uint8_t pageNumber) {
-    uint16_t dstStart;
-    uint16_t srcStart;
-    uint16_t pageOffset = pageNumber * PAGE_SIZE;
-    uint16_t len;
-
-    if (!(attributeTable[pageNumber] & MODIFIED)) {
-        return;
-    }
-
-    uint16_t old_gie = __get_SR_register() & GIE;
-    __disable_interrupt();  // Critical section (attributes get messed up if
-                            // interrupted)
-    srcStart = (uint16_t)&__mmdata_start + pageOffset;
-    dstStart = (uint16_t)(&__mmdata_loadStart) + pageOffset;
-    len = PAGE_SIZE;
-    if (srcStart + PAGE_SIZE > (uint16_t)&__mmdata_end) {
-        len = (uint16_t)&__mmdata_end - srcStart;
-    }
-
-    // Save page
-    memcpy((uint8_t *)dstStart, (uint8_t *)srcStart, len);
-
-    if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
-        // Page is clean
-        attributeTable[pageNumber] &= ~MODIFIED;
-        mm_n_dirty_pages--;
-    }
-    if (old_gie) {
-        __enable_interrupt();
-    }
+  uint16_t dstStart;
+  uint16_t srcStart;
+  uint16_t pageOffset = pageNumber * PAGE_SIZE;
+  uint16_t len;
+
+  if (!(attributeTable[pageNumber] & MODIFIED)) {
+    return;
+  }
+
+  uint16_t old_gie = __get_SR_register() & GIE;
+  __disable_interrupt(); // Critical section (attributes get messed up if
+                         // interrupted)
+  srcStart = (uint16_t)&__mmdata_start + pageOffset;
+  dstStart = (uint16_t)(&__mmdata_loadStart) + pageOffset;
+  len = PAGE_SIZE;
+  if (srcStart + PAGE_SIZE > (uint16_t)&__mmdata_end) {
+    len = (uint16_t)&__mmdata_end - srcStart;
+  }
+
+  // Save page
+  fastmemcpy((uint8_t *)dstStart, (uint8_t *)srcStart, len);
+
+  if ((attributeTable[pageNumber] & REFCNT_MASK) == 0) {
+    // Page is clean
+    attributeTable[pageNumber] &= ~MODIFIED;
+    mm_n_dirty_pages--;
+  }
+  if (old_gie) {
+    __enable_interrupt();
+  }
 }
 
 int mm_acquire_array(const uint8_t *memPtr, size_t len, mm_mode mode) {
-    int status = 0;
-    // Acquire each page referenced
-    const uint8_t *ptr = memPtr;
-    size_t remaining = len;
-    while (remaining > 0) {
-        status = mm_acquire(ptr, mode);
-        if (remaining > PAGE_SIZE) {
-            ptr += PAGE_SIZE;
-            remaining -= PAGE_SIZE;
-        } else {
-            ptr += remaining;
-            remaining = 0;
-        }
+#ifdef ALLOCATEDSTATE
+  return 0;
+#endif
+  int status = 0;
+  // Acquire each page referenced
+  const uint8_t *ptr = memPtr;
+  size_t remaining = len;
+  while (remaining > 0) {
+    status = mm_acquire(ptr, mode);
+    if (remaining > PAGE_SIZE) {
+      ptr += PAGE_SIZE;
+      remaining -= PAGE_SIZE;
+    } else {
+      ptr += remaining;
+      remaining = 0;
     }
-    return status;
+  }
+  return status;
 }
 
 int mm_release_array(const uint8_t *memPtr, size_t len) {
-    int status = 0;
-
-    // Error check
-    if ((memPtr > &__mmdata_end) || (memPtr < &__mmdata_start) ||
-        (memPtr + len) > &__mmdata_end) {
-        while (1)
-            ;  // Error: access out of bounds
-    }
-
-    // Release each page referenced
-    const uint8_t *ptr = memPtr;
-    size_t remaining = len;
-    while (remaining > 0) {
-        status = mm_release(ptr);
-        if (remaining > PAGE_SIZE) {
-            ptr += PAGE_SIZE;
-            remaining -= PAGE_SIZE;
-        } else {
-            ptr += remaining;
-            remaining = 0;
-        }
+#ifdef ALLOCATEDSTATE
+  return 0;
+#endif
+  int status = 0;
+
+  // Error check
+  if ((memPtr > &__mmdata_end) || (memPtr < &__mmdata_start) ||
+      (memPtr + len) > &__mmdata_end) {
+    while (1)
+      ; // Error: access out of bounds
+  }
+
+  // Release each page referenced
+  const uint8_t *ptr = memPtr;
+  size_t remaining = len;
+  while (remaining > 0) {
+    status = mm_release(ptr);
+    if (remaining > PAGE_SIZE) {
+      ptr += PAGE_SIZE;
+      remaining -= PAGE_SIZE;
+    } else {
+      ptr += remaining;
+      remaining = 0;
     }
-    return status;
+  }
+  return status;
 }
 
 size_t mm_get_n_active_pages(void) {
-    size_t nActive = 0;
-    for (int i = 0; i < NPAGES; i++) {
-        if ((attributeTable[i] & REFCNT_MASK) > 0) {
-            nActive++;
-        }
+  size_t nActive = 0;
+  for (int i = 0; i < NPAGES; i++) {
+    if ((attributeTable[i] & REFCNT_MASK) > 0) {
+      nActive++;
     }
-    return nActive;
+  }
+  return nActive;
 }
 
 size_t mm_get_n_dirty_pages(void) { return mm_n_dirty_pages; }
 
 int mm_acquire_page(const uint8_t *memPtr, size_t nElements, size_t elementSize,
                     mm_mode mode) {
-    int bytesAcquired;
-
-    // Check if first element crosses a page boundary
-    uint16_t pageNumberStart = (memPtr - &__mmdata_start) / PAGE_SIZE;
-    uint16_t pageNumberEnd =
-        (memPtr + elementSize - 1  // end address of first element
-         - &__mmdata_start         // - start address
-         ) /
-        PAGE_SIZE;
-
-    if (pageNumberStart != pageNumberEnd) {
-        // Need to load 2 pages
-        mm_acquire(memPtr, mode);
-        mm_acquire(memPtr + elementSize - 1, mode);
-        bytesAcquired = (pageNumberStart + 1) * PAGE_SIZE -
-                        (memPtr - &__mmdata_start) + PAGE_SIZE;
-    } else {
-        mm_acquire(memPtr, mode);
-        bytesAcquired =
-            (pageNumberStart + 1) * PAGE_SIZE - (memPtr - &__mmdata_start);
-    }
-
-    // Don't report acquiring more elements than requested
-    if (bytesAcquired / elementSize >= nElements) {
-        return nElements;
-    } else {
-        return bytesAcquired / elementSize;
-    }
+#ifdef ALLOCATEDSTATE
+  return nElements;
+#endif
+  int bytesAcquired;
+
+  // Check if first element crosses a page boundary
+  uint16_t pageNumberStart = (memPtr - &__mmdata_start) / PAGE_SIZE;
+  uint16_t pageNumberEnd =
+      (memPtr + elementSize - 1 // end address of first element
+       - &__mmdata_start        // - start address
+       ) /
+      PAGE_SIZE;
+
+  if (pageNumberStart != pageNumberEnd) {
+    // Need to load 2 pages
+    mm_acquire(memPtr, mode);
+    mm_acquire(memPtr + elementSize - 1, mode);
+    bytesAcquired = (pageNumberStart + 1) * PAGE_SIZE -
+                    (memPtr - &__mmdata_start) + PAGE_SIZE;
+  } else {
+    mm_acquire(memPtr, mode);
+    bytesAcquired =
+        (pageNumberStart + 1) * PAGE_SIZE - (memPtr - &__mmdata_start);
+  }
+
+  // Don't report acquiring more elements than requested
+  if (bytesAcquired / elementSize >= nElements) {
+    return nElements;
+  } else {
+    return bytesAcquired / elementSize;
+  }
 }
 
 /**
@@ -294,31 +320,31 @@ int mm_acquire_page(const uint8_t *memPtr, size_t nElements, size_t elementSize,
  * @param pageNumber
  */
 static void loadPage(uint8_t pageNumber) {
-    if (!(attributeTable[pageNumber] & LOADED)) {
-        uint8_t *srcStart;
-        uint8_t *dstStart;
-        uint16_t len;
-        uint16_t pageOffset = pageNumber * PAGE_SIZE;
-
-        dstStart = &__mmdata_start + pageOffset;      // Memory address
-        srcStart = &__mmdata_loadStart + pageOffset;  // Snapshot address
-        len = PAGE_SIZE;
-        if ((uint16_t)dstStart + PAGE_SIZE > (uint16_t)&__mmdata_end) {
-            len = (uint16_t)&__mmdata_end - (uint16_t)dstStart;
-        }
+  if (!(attributeTable[pageNumber] & LOADED)) {
+    uint8_t *srcStart;
+    uint8_t *dstStart;
+    uint16_t len;
+    uint16_t pageOffset = pageNumber * PAGE_SIZE;
 
-        memcpy((uint8_t *)dstStart, (uint8_t *)srcStart, len);
-        attributeTable[pageNumber] |= LOADED;
+    dstStart = &__mmdata_start + pageOffset;     // Memory address
+    srcStart = &__mmdata_loadStart + pageOffset; // Snapshot address
+    len = PAGE_SIZE;
+    if ((uint16_t)dstStart + PAGE_SIZE > (uint16_t)&__mmdata_end) {
+      len = (uint16_t)&__mmdata_end - (uint16_t)dstStart;
     }
+
+    fastmemcpy((uint8_t *)dstStart, (uint8_t *)srcStart, len);
+    attributeTable[pageNumber] |= LOADED;
+  }
 }
 
 /**
  * @brief Initialise LRU table with dummy pages
  */
 void mm_init_lru(void) {
-    for (int i = 0; i < MAX_DIRTY_PAGES; i++) {
-        lruTable[i] = DUMMY_PAGE;
-    }
+  for (int i = 0; i < MAX_DIRTY_PAGES; i++) {
+    lruTable[i] = DUMMY_PAGE;
+  }
 }
 
 /**
@@ -326,39 +352,39 @@ void mm_init_lru(void) {
  * @param pageNumber
  */
 static void addLRU(uint8_t pageNumber) {
-    uint8_t tmp1, tmp2;
-
-    if (pageNumber > NPAGES) {
-        while (1)
-            ;  // Error: page number out of bounds.
-    }
-
-    tmp1 = pageNumber;
-    for (int i = 0; i < MAX_DIRTY_PAGES; i++) {
-        if (lruTable[i] == pageNumber) {
-            lruTable[i] = tmp1;
-            for (int j = i + 1; j < MAX_DIRTY_PAGES; j++) {
-                if (lruTable[j] == tmp1) {
-                    lruTable[j] = DUMMY_PAGE;
-                    break;
-                }
-            }
-            break;
-        } else if (lruTable[i] == DUMMY_PAGE) {
-            lruTable[i] = tmp1;
-            for (int j = i + 1; j < MAX_DIRTY_PAGES; j++) {
-                if (lruTable[j] == tmp1) {
-                    lruTable[j] = DUMMY_PAGE;
-                    break;
-                }
-            }
-            break;
-        } else {
-            tmp2 = lruTable[i];
-            lruTable[i] = tmp1;
-            tmp1 = tmp2;
+  uint8_t tmp1, tmp2;
+
+  if (pageNumber > NPAGES) {
+    while (1)
+      ; // Error: page number out of bounds.
+  }
+
+  tmp1 = pageNumber;
+  for (int i = 0; i < MAX_DIRTY_PAGES; i++) {
+    if (lruTable[i] == pageNumber) {
+      lruTable[i] = tmp1;
+      for (int j = i + 1; j < MAX_DIRTY_PAGES; j++) {
+        if (lruTable[j] == tmp1) {
+          lruTable[j] = DUMMY_PAGE;
+          break;
+        }
+      }
+      break;
+    } else if (lruTable[i] == DUMMY_PAGE) {
+      lruTable[i] = tmp1;
+      for (int j = i + 1; j < MAX_DIRTY_PAGES; j++) {
+        if (lruTable[j] == tmp1) {
+          lruTable[j] = DUMMY_PAGE;
+          break;
         }
+      }
+      break;
+    } else {
+      tmp2 = lruTable[i];
+      lruTable[i] = tmp1;
+      tmp1 = tmp2;
     }
+  }
 }
 
 /**
@@ -372,11 +398,11 @@ static void clearLRU(uint8_t index) { lruTable[index] = DUMMY_PAGE; }
  * @param pageNumber
  */
 static void clearLRUPage(uint8_t pageNumber) {
-    for (int i = MAX_DIRTY_PAGES - 1; i >= 0; i--) {
-        if (lruTable[i] == pageNumber) {
-            lruTable[i] = DUMMY_PAGE;
-            return;
-        }
+  for (int i = MAX_DIRTY_PAGES - 1; i >= 0; i--) {
+    if (lruTable[i] == pageNumber) {
+      lruTable[i] = DUMMY_PAGE;
+      return;
     }
+  }
 }
 
diff --git a/iclib/memory_management.h b/iclib/memory_management.h
index a0d8c3a..2f8409f 100644
--- a/iclib/memory_management.h
+++ b/iclib/memory_management.h
@@ -23,14 +23,14 @@ typedef enum { MM_READONLY, MM_READWRITE } mm_mode;
  * @param Pointer to variable held in static memory
  * @parapm mm_mode access mode
  */
-int mm_acquire(const uint8_t* memPtr, mm_mode mode);
+int mm_acquire(const uint8_t *memPtr, mm_mode mode);
 
 /**
  * @brief Release a byte from managed memory.
  * @param Pointer to variable held in static memory
  * @return Status: 0=success
  */
-int mm_release(const uint8_t* memPtr);
+int mm_release(const uint8_t *memPtr);
 
 /**
  * @brief Acquire an array from static memory
@@ -39,7 +39,7 @@ int mm_release(const uint8_t* memPtr);
  * @param mm_mode access mode
  * @return
  */
-int mm_acquire_array(const uint8_t* memPtr, size_t len, mm_mode mode);
+int mm_acquire_array(const uint8_t *memPtr, size_t len, mm_mode mode);
 
 /**
  * @brief Release array
@@ -47,7 +47,7 @@ int mm_acquire_array(const uint8_t* memPtr, size_t len, mm_mode mode);
  * @param len size of array
  * @return
  */
-int mm_release_array(const uint8_t* memPtr, size_t len);
+int mm_release_array(const uint8_t *memPtr, size_t len);
 
 /**
  * @brief Aquire data from an array one page at a time. May load two pages if
@@ -57,7 +57,7 @@ int mm_release_array(const uint8_t* memPtr, size_t len);
  * @param mm_mode access mode
  * @return Number of elements acquired.
  */
-int mm_acquire_page(const uint8_t* memPtr, size_t nElements, size_t elementSize,
+int mm_acquire_page(const uint8_t *memPtr, size_t nElements, size_t elementSize,
                     mm_mode mode);
 /**
  * @brief Get the number of currently active pages
@@ -75,7 +75,7 @@ void mm_init_lru(void);
 /**
  * @brief Restore all active pages to memory from FRAM
  */
-void mm_restoreStatic(void);
+void mm_restore(void);
 
 /**
  * @brief Save all modified pages to FRAM
diff --git a/matmul-tiled/CMakeLists.txt b/matmul-tiled/CMakeLists.txt
index a56fc5c..9144a8c 100644
--- a/matmul-tiled/CMakeLists.txt
+++ b/matmul-tiled/CMakeLists.txt
@@ -1,26 +1,22 @@
 cmake_minimum_required(VERSION 3.0)
 
-include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)
-
-project(matmul-tiled)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-
-include_directories(${ICLIB_ROOT})
-link_directories(${ICLIB_ROOT})
-
-add_executable(
-    ${PROJECT_NAME}
-    main.c
-    input.h
-)
-
-add_msp_upload(${PROJECT_NAME})
-
-target_link_libraries(${PROJECT_NAME} ${SUPPORT_LIBS})
-
-set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
-
-add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
-    COMMAND ${MSP430-SIZE} "$<TARGET_FILE:${PROJECT_NAME}>"
-    COMMENT "Invoking: msp430-elf-size")
+FOREACH(METHOD "MS" "AS")
+    set(TESTNAME "matmul-tiled-${METHOD}")
+    add_executable(
+        ${TESTNAME}
+        main.c
+        input.h
+    )
+    IF (${METHOD} STREQUAL "AS")
+        target_compile_definitions( ${TESTNAME} PUBLIC -DALLOCATEDSTATE)
+    ENDIF()
+    add_msp_upload(${TESTNAME})
+    target_link_libraries(
+        ${TESTNAME}
+        LINK_PUBLIC ic-${METHOD}
+        ${SUPPORT_LIBS})
+    set_target_properties(${TESTNAME} PROPERTIES SUFFIX ".elf")
+    add_custom_command(TARGET ${TESTNAME} POST_BUILD
+        COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${TESTNAME}>"
+        COMMENT "Invoking: msp430-elf-size")
+ENDFOREACH()
diff --git a/matmul/CMakeLists.txt b/matmul/CMakeLists.txt
index e04f5a7..f393841 100644
--- a/matmul/CMakeLists.txt
+++ b/matmul/CMakeLists.txt
@@ -1,26 +1,23 @@
 cmake_minimum_required(VERSION 3.0)
 
-include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)
+FOREACH(METHOD "MS" "AS")
+    set(TESTNAME "matmul-${METHOD}")
+    add_executable(
+        ${TESTNAME}
+        main.c
+        input.h
+    )
+    IF (${METHOD} STREQUAL "AS")
+        target_compile_definitions( ${TESTNAME} PUBLIC -DALLOCATEDSTATE)
+    ENDIF()
+    add_msp_upload(${TESTNAME})
+    target_link_libraries(
+        ${TESTNAME}
+        LINK_PUBLIC ic-${METHOD}
+        ${SUPPORT_LIBS})
+    set_target_properties(${TESTNAME} PROPERTIES SUFFIX ".elf")
+    add_custom_command(TARGET ${TESTNAME} POST_BUILD
+        COMMAND ${MSP430-SIZE} -A -d "$<TARGET_FILE:${TESTNAME}>"
+        COMMENT "Invoking: msp430-elf-size")
+ENDFOREACH()
 
-project(matmul)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-
-include_directories(${ICLIB_ROOT})
-link_directories(${ICLIB_ROOT})
-
-add_executable(
-    ${PROJECT_NAME}
-    main.c
-    input.h
-)
-
-add_msp_upload(${PROJECT_NAME})
-
-target_link_libraries(${PROJECT_NAME} ${SUPPORT_LIBS})
-
-set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
-
-add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
-    COMMAND ${MSP430-SIZE} "$<TARGET_FILE:${PROJECT_NAME}>"
-    COMMENT "Invoking: msp430-elf-size")
-- 
GitLab