Bluetiles, part of Blueshell, is a Manhattan grid (mesh) interconnect for a network on chip (NoC) built using Bluespec System Verilog (BSV). The interconnect enables a large number of CPUs and other processing elements to exchange messages in the form of network packets. Each CPU may act as client or server. Find Bluetiles in the internal SVN at https://svn.cs.york.ac.uk/svn/rtslab/blueshell/

Microblaze is a Bluetile.

Scope

Bluetiles is intended to be used for CPU-CPU communications, and for sending messages between CPUs and I/O devices.

Memory accesses should generally be performed using Bluetree, a tree-like interconnect linking large numbers of CPUs to a single memory.

Introduction

Bluetiles implements a Manhattan grid interconnect. Two sorts of component are important:
  • A router. Each router has five connections - each a bidirectional 32-bit channel of type "BlueBits" (defined in Bluetiles.bsv). Four of these are named North, East, South and West and are connected to other routers (or, at the edge of the grid, nothing at all). The fifth is named Home and connects to a local component.
  • A local component. This could be a CPU, an I/O device, or a co-processor. It implements the other side of the Home connection, which allows it to send and receive messages over the network.
Each router has an address expressed in the form (x, y): these are Cartesian co-ordinates representing a grid location. The address is used when packets are routed. The router compares its own address against the destination address in a network packet, then directs the packet to one of the five interfaces accordingly.

At the top level, a Bluetiles network is defined by (1) declaring the routers, (2) declaring the connections between the routers, and (3) declaring the connections between the routers and the local components. For example, the following code defines a network of size 3 by 1, containing three routers (ba, bb, bc) and three local components (cpu, pingpong, inspector).
IfcBluetilesRouter ba <- mkBluetilesRouter(0, 0);
IfcBluetilesRouter bb <- mkBluetilesRouter(1, 0);
IfcBluetilesRouter bc <- mkBluetilesRouter(2, 0);
mkConnection(ba.east, bb.west);
mkConnection(bb.east, bc.west);
mkConnection(cpu.bluetile, ba.home);
mkConnection(pingpong.bluetile, bb.home);
mkConnection(inspector.bluetile, bc.home);

Network Protocol

The current network protocol is "Bluetiles II". The historical development and current packet format of Bluetiles II is documented here.

Port Numbers

A Bluetile component can provide multiple logical services. For instance, a memory component might provide "read" and "write". The services can be identified by different port numbers. There are 255 available numbers.

Port numbers are only assigned by convention, and in any Blueshell system you are free to invent them as you please. However, it may be helpful to respect the following:
  • Low numbered ports (e.g. < 0x10) are used for standard services (see below) which have well-defined protocols and well-defined meanings. These are used by boot loaders.
  • High-numbered ports (e.g. >= 0x80) are "dynamic" ports with meaning assigned at runtime, or locally within a particular device.
If the component at a specific location does not provide any service on a particular port, the correct response is to silently drop the packet. This is easy to implement and also means that bugs are not going to result in packet storms, where an error message triggers another error message.

Standard Services

port 0 - blackhole. Packets sent here are always dropped.

port 1 - memory read service. Implemented by boot loaders running on CPUs.
  • The payload size is exactly 1.
  • The payload word is a BT_RW_Header, as generated by the bt_make_read_write_header function. It contains the address for the read, encoded as a 24-bit value, and the number of words to be read, encoded as an 8-bit value.
  • The addresses may be within the range 00000000 to 01fffffc, or within the range 80000000 to 81fffffc. The limited range is due to the encoding used. Addresses have to be word-aligned.
  • A reply is sent containing the data.

port 2 - memory write service. Implemented by boot loaders running on CPUs.
  • The payload size is >= 2.
  • Payload word 0 is a BT_RW_Header, as generated by the bt_make_read_write_header function. It contains the address for the write, encoded as a 24-bit value, and the byte enable mask.
  • The addresses may be within the range 00000000 to 01fffffc, or within the range 80000000 to 81fffffc. The limited range is due to the encoding used. Addresses have to be word-aligned.
  • Payload words 1..size-1 give the data to write.
  • There is no reply.

port 3 - ping/pong service. Implemented by TilePingPong.bsv and by boot loaders.
  • The contents of the payload are echoed back to the sender
  • Reply - echo the payload.

port 4 - CPU boot service. Implemented by boot loaders running on CPUs.
  • Used to begin booting a CPU
  • The payload size is 1
  • The CPU boot ROM listens for a packet and jumps to the location specified in payload word 0, which is a byte address.
  • No reply.

port 5 - register for interrupts from a device. Implemented by I/O devices that may generate interrupts, such as an Ethernet interface.
  • The payload size is 2.
  • The payload should contain the header to be sent if the interrupt arrives. It must have no payload. The header should be created to specify the recipient for the interrupts.
  • No reply is sent.

port 6 - Message service. Packets sent to this service should be printed on screen.
  • Used for debugging (print(""), etc.)
  • Any payload size is acceptable. The final word can be padded with zeroes which are not printed.

port 7 - Program terminated notification.
  • Used for debugging. Indicates that a program has finished running and that, therefore, some virtual lab client should exit.
  • Any payload size is acceptable, but if the payload is not empty, the first payload word contains the return code.
  • No reply is sent.