Add a flag to allow targeting a Kelvin w/ TCMs

- Example build for Kelvin w/ TCM:
    bazel build --build_tag_filters=-tcm-incompatible --//:link_tcm //tests/riscv-tests:all

Change-Id: Iac6d2213ce0ec773057f2a1fa67e85f3c5cdaf09
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..4ed9d4a
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,26 @@
+# Copyright 2024 Google LLC
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at#
+#     http://www.apache.org/licenses/LICENSE-2.0#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
+
+package(default_visibility = ["//visibility:public"])
+
+bool_flag(
+    name = "link_tcm",
+    build_setting_default = False,
+)
+
+config_setting(
+    name = "link_tcm_config",
+    flag_values = {
+        ":link_tcm": "True",
+    },
+)
\ No newline at end of file
diff --git a/build_tools/bazel/kelvin.bzl b/build_tools/bazel/kelvin.bzl
index 8b66f79..c29614a 100644
--- a/build_tools/bazel/kelvin.bzl
+++ b/build_tools/bazel/kelvin.bzl
@@ -223,6 +223,7 @@
       **kwargs: Agruments that will be forwarded to kelvin_binary
     """
 
+    tags = kwargs.get("tags", [])
     kelvin_elf = "{}_elf".format(name)
     kelvin_binary(
         name = kelvin_elf,
@@ -242,7 +243,7 @@
         data = [
             "{}.elf".format(kelvin_elf),
         ],
-        tags = ["iss"] + iss_test_tags,
+        tags = ["iss"] + iss_test_tags + tags,
     )
 
     hw_test = "{}_hw".format(name)
@@ -256,7 +257,7 @@
         data = [
             "{}.bin".format(kelvin_elf),
         ],
-        tags = ["systemc"] + hw_test_tags,
+        tags = ["systemc"] + hw_test_tags + tags,
     )
 
     native.test_suite(
@@ -265,6 +266,7 @@
             iss_test,
             hw_test,
         ],
+        tags = tags
     )
 
 # From @tflite-micro//tensorflow/lite/micro/build_def.bzl, and paths
diff --git a/crt/BUILD b/crt/BUILD
index 8fad457..a0c26d5 100644
--- a/crt/BUILD
+++ b/crt/BUILD
@@ -16,7 +16,10 @@
 
 filegroup(
     name = "kelvin_linker",
-    srcs = ["kelvin.ld"],
+    srcs = select({
+        "//:link_tcm_config": ["kelvin_tcm.ld"],
+        "//conditions:default": ["kelvin.ld"],
+    }),
 )
 
 cc_library(
diff --git a/crt/kelvin_tcm.ld b/crt/kelvin_tcm.ld
new file mode 100644
index 0000000..68b3276
--- /dev/null
+++ b/crt/kelvin_tcm.ld
@@ -0,0 +1,81 @@
+/* Copyright 2024 Google LLC. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+MEMORY {
+    ITCM(rx): ORIGIN = 0x00000000, LENGTH = 8K
+    DTCM(rw): ORIGIN = 0x00010000, LENGTH = 32K
+}
+
+STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x80;
+HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x80;
+
+ENTRY(_start)
+
+SECTIONS {
+    /* ITCM data here */
+    . = ORIGIN(ITCM);
+    .text : ALIGN(4) {
+        *(._init)
+        *(.text)
+        *(.text.*)
+        . = ALIGN(4);
+    } > ITCM
+
+    .init.array : ALIGN(4) {
+      __init_array_start = .;
+      *(.init_array)
+      *(.init_array.*)
+      . = ALIGN(4);
+      __init_array_end = .;
+    } > ITCM
+
+    .rodata : ALIGN(4) {
+      *(.srodata)
+      *(.srodata.*)
+      *(.rodata)
+      *(.rodata.*)
+      . = ALIGN(4);
+    } > ITCM
+
+    .data : ALIGN(4) {
+      __data_start__ = .;
+      /**
+      * This will get loaded into `gp`, and the linker will use that register for
+      * accessing data within [-2048,2047] of `__global_pointer$`.
+      *
+      * This is much cheaper (for small data) than materializing the
+      * address and loading from that (which will take one extra instruction).
+      */
+      _global_pointer = . + 0x800;
+      *(.sdata)
+      *(.sdata.*)
+      *(.data)
+      *(.data.*)
+      . = ALIGN(4);
+        __data_end__ = .;
+    } > DTCM
+
+    /* DTCM data here */
+    . = ORIGIN(DTCM);
+    .bss : ALIGN(4) {
+      __bss_start__ = .;
+      *(.sbss)
+      *(.sbss.*)
+      *(.bss)
+      *(.bss.*)
+      __bss_end__ = .;
+    } > DTCM
+
+    .heap : ALIGN(4) {
+      __heap_start__ = .;
+      . += HEAP_SIZE;
+      __heap_end__ = .;
+    } > DTCM
+
+    .stack : ALIGN(4) {
+      __stack_start__ = .;
+      . += STACK_SIZE;
+      __stack_end__ = .;
+    } > DTCM
+}
\ No newline at end of file
diff --git a/tests/riscv-tests/BUILD b/tests/riscv-tests/BUILD
index 67338f2..9a131fc 100644
--- a/tests/riscv-tests/BUILD
+++ b/tests/riscv-tests/BUILD
@@ -45,7 +45,6 @@
     "blt",
     "bltu",
     "bne",
-    "fence_i",
     "jalr",
     "jal",
     "lb",
@@ -97,6 +96,28 @@
     ],
 ) for test in RV32UI_TESTS]
 
+kelvin_test(
+    name = "rv32ui_fence_i",
+    srcs = [
+        "@riscv-tests//:isa/rv64ui/fence_i.S",
+    ],
+    # The include paths are set explicitly because riscv-tests has special
+    # include dependencies.
+    copts = [
+        "-Itests/riscv-tests",
+        "-Iexternal/riscv-tests/isa/macros/scalar",
+        "-Wno-variadic-macros",
+    ],
+    defines = [
+        "RVTEST_RV64U=RVTEST_RV32U",
+    ],
+    hw_test_size = "small",
+    deps = [
+        ":riscv_tests_base",
+    ],
+    tags = ["tcm-incompatible"],
+)
+
 RV32UM_TESTS = [
     "div",
     "divu",
@@ -176,6 +197,7 @@
         "-Wno-implicit-int",
         "-Wno-implicit-function-declaration",
     ],
+    tags = ["tcm-incompatible"],
 )
 
 kelvin_test(
@@ -200,6 +222,7 @@
         "-Wno-implicit-function-declaration",
     ],
     hw_test_size = "large",
+    tags = ["tcm-incompatible"],
 )
 
 kelvin_test(
@@ -211,6 +234,7 @@
     deps = [
         "//crt",
     ],
+    tags = ["tcm-incompatible"],
 )
 
 kelvin_test(
@@ -222,6 +246,7 @@
     deps = [
         "//crt",
     ],
+    tags = ["tcm-incompatible"],
 )
 
 kelvin_test(
@@ -233,4 +258,5 @@
     deps = [
         "//crt",
     ],
+    tags = ["tcm-incompatible"],
 )