Overview
A System-on-Chip is the integration of a number of building blocks -- which until recently had to be implemented as separate chips -- onto a single chip. Such building blocks are called "cores" and a system with a large number of non-identical cores is a Heterogeneous Multicore System-on-Chip.

The Gannet project aims to make it easier to design such Systems-on-Chip by providing a platform.

The Gannet platform connects a set of cores over a network (called a "Network-on-Chip" (NoC) as the complete system is a single chip). The interface between the NoC and the core is a special circuit called the service manager. The service manager runs programs (written in the Gannet language) and these programs determine the way in which the cores work together to perform a task.

Below is an example of a Gannet platform SoC that captures video and transmits it over a network interface.

Depending on the available bandwidth, the raw video frames will be scaled down and MPEG compressed or encoded using a lossless codec. The system can also encrypt the video stream if required.
For more detailed background information, have a look at the Publications
Gannet Language
The aim of the Gannet project is to make it easier to design reconfigurable Systems-on-Chip. By using the Gannet platform, a System-on-Chip becomes a distributed processor for the Gannet language. The Gannet language (Gannet for short) is a functional language with features that enable full concurrency and the potential to separate control flow from data flow, as well as native support for pipelined streaming data processing, an essential feature for SoCs aimed at multimedia applications. Despite its readability and high-abstraction constructs, the language is an assembly-level language that can be readily mapped to the bytecode for the Gannet system.
Gannet is similar to Scheme in terms of syntax and language constructs. In case you don't know Scheme: every expression is of the form ( operator list-of-operands ) where every operand can again be an expression. The key difference is that in Gannet, by default all arguments of a function are evaluated in parallel. Consequently, all branches of the computational tree are traversed in parallel. For example, in
(* (+ '2 '3) (- '4 '5) (* '6 '7) )
the three argument expressions will be computed in parallel. Consequently, on a multi-core system a Gannet program will run faster than a sequential program.
As a second example consider a construct that require precedence, such as variable assignment:
(let
(assign 'v '6)
(* (read 'v) '7)
)
It is perfectly possible that the read call is evaluated before the assign call. Therefore a call will either have to wait (block) until all calls upon which it depends have returned, or the calls must be sequenced.
Gannet has no "special forms" (keywords), a very interesting feature from the language designer's perspective: no expressions are special. Instead, all language features are implemented as "services", which can be thought of as object methods. This feature makes it very simple to add or remove language constructs. However, it means that in
(if (condition) (branch1) (branch2))
both branches will be evaluated, which is in general not desirable. Gannet has a mechanism to defer evaluation, indicated by quoting the argument. Thus in
(if (condition) '(branch1) '(branch2))
only the branch corresponding to the return value of (condition) will be evaluated.
For more details on the Gannet syntax and language constructs, see Programming Gannet.
Compiler
The Gannet compiler can compile the Gannet assembly-level code into bytecode to be run on the Gannet VM or hardware, or translate the Gannet code into code for a number of reference implementations.
Garnet prototype
Garnet is a prototype for the complete Gannet system written in Ruby. It is a model for both the actual hardware archticture and the Virtual Machine. Garnet is purely a tool to research trade-offs and design decisions in the system. The source code is provided here for those who would like to study the Gannet architecture rather than the language.
Gannet VM
One branch of the Garnet prototype implements the Virtual Machine. However, a VM in Ruby is not of any practical use. The Gannet VM is a C++ port of the Garnet VM branch, obtained by automatic translation of the Ruby code. The resulting VM is small, reasonably fast and resource-efficient. It has been successfully tested on Linux on a PowerPC core embedded in a Virtex-II Pro FPGA. The source code includes a user-space driver for a fifo-buffered PLB interface. Using this driver and the examples for services provided in the source code, it is easy to add a custom hardware service to the system.
SystemC hardware model
As Gannet is intended as a platform for SoC design, a hardware model is essential. Using the Ruby and C++ codebase, we have built a cycle-approximate system-level model for the Gannet platform in the industry-standard (IEEE 1666) SystemC system-level modelling language. SystemC is implemented as a C++ library and the Gannet toolchain allows Services written in C++ or "portable" Ruby to be run integrated in the SystemC framework. This approach greatly simpifies rapid prototyping of a Gannet SoC.
Reference implementations
To make it easier to design the Gannet language and to have an unambiguous specification of the semantics of the Gannet system, a number of reference implementations have been created. Every reference implementation consists of a runtime library. The Gannet code is translated into the native code for the runtime system. All reference implementations support the concurrent evaluation semantics that is Gannet's most remarkable feature. Although Gannet is a functional language, it is possible for services to maintain state. Therefore, the operators in the Gannet code are implemented conceptually as methods of Service objects. Furthermore, every method call evaluates in its own thread.
Scheme
A very powerful reference implementation is written in Gambit Scheme. The Scheme code of the runtime library is less readable due to the use of define-syntax macros but the Gambit system allows compilation into C, making it the fastest reference implementation. As an example, consider the multiplication operation of a simple ALU service. This multiplication returns the product of its arguments:
(define (ALU)
(let (
(self (Service))
)
(service-method self 'times args
(fold * ((-> self 'ev) args) ))
self
)
)
Perl 6
Arguably the most elegant reference implementation is written in Perl 6 and uses Pugs as the interpreter. The Perl 6 syntax makes the runtime library very easy to understand:
class ALU is Service {
method mult {
my @args= self.ev(@_);
return [*] @args;
}
} # ALU
Perl 5
The Perl 5 version is aimed at those who would like to try out Gannet but don't like to install Pugs or Gambit Scheme. It does not use threads nor indeed Perl objects. The purpose of this reference implementation is to investigate how Gannet can be compiled into an imperative language. There is no runtime library for ALU operations or control constructs, but adding a service is straightforward:
sub mult {
my $res=1;
for my $v ( @_) {
$res*=$v;
}
return $res;
}