ci: preliminary implementation
diff --git a/.circleci/arch-deps.sh b/.circleci/arch-deps.sh
new file mode 100644
index 0000000..edb4baa
--- /dev/null
+++ b/.circleci/arch-deps.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# This script is entirely self contained, so you can cache off of its' content
+# the results stored in ICESTORM_ROOT and TRELLIS_ROOT.
+
+set -e -x -o pipefail
+
+# Parameters
+ICESTORM_ROOT=${ICESTORM_ROOT:-/usr/local/icestorm}
+TRELLIS_ROOT=${TRELLIS_ROOT:-/usr/local/trellis}
+
+# Configuration
+ICESTORM_REVISION=c02a4000f4cef8d4d9e76757f55ea4920667e1e8
+TRELLIS_REVISION=f57e0f90b9f9d95a172adf56376fa875f36a7a4e
+TRELLISDB_REVISION=ef5980c129be05aceeaea3b3c968d3102f8450b5
+
+# Instal Icestorm
+(
+    cd /tmp
+    rm -rf icestorm
+    git clone https://github.com/cliffordwolf/icestorm.git
+    cd icestorm
+    git reset --hard $ICETORM_REVISION
+    make install -j2 PREFIX=$ICESTORM_ROOT
+    rm -rf icestorm
+)
+
+# Install Trellis
+(
+    mkdir -p $TRELLIS_ROOT
+    cd $(dirname $TRELLIS_ROOT)
+    rm -rf $(basename $TRELLIS_ROOT)
+    git clone https://github.com/SymbiFlow/prjtrellis.git $(basename $TRELLIS_ROOT)
+    cd $(basename $TRELLIS_ROOT)
+
+    git reset --hard $TRELLIS_REVISION
+    git submodule update --init --recursive
+    . environment.sh
+    rm -rf database
+    git clone https://github.com/SymbiFlow/prjtrellis-db.git database
+    cd database
+    git reset --hard $TRELLISDB_REVISION
+    cd ..
+    cd libtrellis 
+    cmake .
+    make -j8
+)
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..79cb082
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,42 @@
+version: 2
+jobs:
+  build:
+    docker:
+      - image: eu.gcr.io/symbiotic-containers-public/nextpnr-ci:20180824-012428
+    steps:
+      - checkout
+      # Restore cache from arch-deps.sh
+      - restore_cache:
+          key: arch-deps-{{ checksum ".circleci/arch-deps.sh" }}
+      # Get arch deps if not found in cache
+      - run:
+          name: Install Arch dependencies
+          command: |
+            export ICESTORM_ROOT=/circleci/icestorm
+            export TRELLIS_ROOT=/circleci/trellis
+            if [ ! -e $ICESTORM_ROOT ] || [ ! -e $TRELLIS_ROOT ]; then
+              echo "Installing arch dependencies..."
+              bash .circleci/arch-deps.sh
+            fi
+      # Cache arch deps
+      - save_cache:
+          key: arch-deps-{{ checksum ".circleci/arch-deps.sh" }}
+          paths:
+            - /circleci/icestorm
+            - /circleci/trellis
+
+      # Build! We first build BBASm in parallel, then the chipdbs sequentially,
+      # then the rest in parallel. This is to not exceed the default 4G memory
+      # limit on CirclCI.
+      - run:
+          name: Build
+          command: |
+            mkdir build
+            cd build
+            cmake .. -DARCH=all -DBUILD_TESTS=ON -DCOVERAGE=ON \
+              -DTRELLIS_ROOT=/circleci/trellis \
+              -DICEBOX_ROOT=/circleci/icestorm/share/icebox
+            make -j2 bbasm
+            make -j1 ice40_chipdb
+            make -j1 ecp5_chipdb
+            make -j2
diff --git a/.circleci/env/Dockerfile b/.circleci/env/Dockerfile
new file mode 100644
index 0000000..7eb4d7d
--- /dev/null
+++ b/.circleci/env/Dockerfile
@@ -0,0 +1,8 @@
+FROM ubuntu:xenial-20180808
+
+# Install system dependencies.
+RUN set -e -x ;\
+    apt-get -y update ;\
+    apt-get -y upgrade ;\
+    apt-get -y install build-essential qtbase5-dev cmake python3-dev \
+        libboost-all-dev git pkg-config libftdi-dev lcov
diff --git a/.circleci/env/README b/.circleci/env/README
new file mode 100644
index 0000000..9733705
--- /dev/null
+++ b/.circleci/env/README
@@ -0,0 +1,31 @@
+NextPNR CI Builder Image
+========================
+
+This directory contains a Dockerfile that is used to build an environment image
+for the NextPNR Continuous Integration system.
+
+We use a custom image to speed up the build process - so that we don't have to
+`apt` install all the dependencies on a bare Ubuntu image on every CI run.
+
+Building Locally
+----------------
+
+   docker build -t nextpnr-ci .circleci/env
+
+Updating image used by CircleCI
+-------------------------------
+
+CircleCI will use whatever image is specified in `.circleci/config.yml`.
+Currently we store images in the Google Container Registry, in the
+`symbiotic-containers-public` organization. *If you update the Dockerfile, the
+image will need to be manually rebuilt and pushed by the Yosys/SymbioticEDA
+team.
+
+Here's what needs to be run:
+
+    TAG=eu.gcr.io/symbiotic-containers-public/nextpnr-ci:"$(date +%Y%m%d-%H%M%S)"
+    docker build -t "$TAG" .circleci/env
+    docker push "$TAG"
+    echo "New image: $TAG"
+
+Then update `.circleci/config.yml`.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3796c45..9ce942e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,7 +54,7 @@
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/3rdparty/sanitizers-cmake/cmake;." ${CMAKE_MODULE_PATH})
 
 if (COVERAGE)
-    include(CodeCoverage)
+        include("${CMAKE_SOURCE_DIR}/CodeCoverage.cmake")
 endif()
 
 if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS)