Connectal Project Structure

The set of files composing the input to the Connectal toolchain is referred to as a project. A collection of out-of-tree example projects is available at https://github.com/connectal-examples. To illustrate the structure of a project, this chapter uses the example https://github.com/connectal-examples/leds, which can be executed on the Bluesim or Zynq target platforms.

Project Makefile

The top-level Makefile in the project (in our example, https://github.com/connectal-examples/leds/blob/master/Makefile) defines parameters building and executing the project. In its simplest form, it specifies the hardware and software source files, which Bluespec interfaces to use as interfaces (portals) between them, and the libraries to use for the hardware and software compilation:

INTERFACES = LedControllerRequest
BSVFILES = LedController.bsv Top.bsv
CPPFILES= testleds.cpp
include \$(CONNECTALDIR)/Makefile.connectal

BSVFILES is a list of bsv files containing interface definitions used to generate portals and module definitions used to generate HW components. Connectal bsv libraries can be used without being listed explicitly.

CPPFILES is a list of C/C++ files containing software components and main. The Connectal C/C++ libraries can be used without being listed explicitly.

INTERFACES is a list of names of BSV interfaces which may be used to communicate between the HW and SW componentsy. In addition to user-defined interfaces, there are a wide variety of interfaces defined in Connectal libraries which may be included in this list.

NUMBER_OF_MASTERS is used to designate the number of host bus masters the hardware components will instantiate. For PCIe-based platforms, this value can be set to 1, while on Zynq-based platforms values from 1 to 4 are valid.

CONNECTALDIR must be set so that the top-level Connectal makefile can be included, defining the makefile build targets for the project. This brings in the default definitions of all project build parameters as well as the Connectal hardware and software libraries. When running the toolchain on AWS, this varible is set automatically in the build environment. (See Compiling and Running Connectal Project)

Project Source

Interface Definitions

label{interface_definitions}

When generating portals, the Connectal interface compiler searches the Connectal bsv libraries and the files listed in BSVFILES for definitions of the interfaces listed in INTERFACES. If the definition of a listed interfaces is not found, an error is reported and the compilation aborts. The interfaces in this list must be composed exclusively of Action methods. Supported method argument types are Bit\#(n), Bool, Int\#(32), UInt\#(32), Float, Vector\#(t), enum, and struct.

Software

The software in a Connectal project consists of at least one C++ file which instantiates the generated portal wrappers and proxies and implements main(). The following source defines the SW component of the example, which simply toggles LEDs on the Zedboard (url{https://github.com/connectal-examples/leds/blob/master/testleds.cpp}):

#include <unistd.h>
#include "LedControllerRequest.h"
#include "GeneratedTypes.h"
int main(int argc, const char **argv)
{
  LedControllerRequestProxy *device =
    new LedControllerRequestProxy(IfcNames_LedControllerRequest);
  for (int i = 0; i < 20; i++) {
    device->setLeds(10, 10000);
    sleep(1);
    device->setLeds(5, 10000);
    sleep(1);
  }
}

The makefile listed LedControllerRequest as the only communication interface. The generated proxies and wrappers for this interface are in LedControllerRequest.h which is included, along with C++ implementations of all additional interface types in GeneratedTypes.h. Line 9 instantiates the proxy through which the software invokes the hardware methods (See also Flow Control)

To support projects that will execute software inside the linux kernel (for example, to work in conjunction with filesystems or the network stack), connectal project software can also be written in C.

Hardware

Connectal projects typically have at least one BSV file containing interface declarations and module definitions. The implementation of the interfaces and all supporting infrastructure is standard BSV. Interfaces being used as portals are subject to the type restrictions described earlier (See also Interface Declarations)

Top.bsv

In Top.bsv (https://github.com/connectal-examples/leds/blob/master/Top.bsv), the developer instantiates all hardware modules explicitly. Interfaces which can be invoked through portals need to be connected to the generated wrappers and proxies. To connect to the host processor bus, a parameterized standard interface is used, making it easy to synthesize the application for different CPUs or for simulation:

// Connectal Libraries
import CtrlMux::*;
import Portal::*;
import Leds::*;
import MemTypes::*;
import MemPortal::*;
import HostInterface::*;
import LedControllerRequest::*;
import LedController::*;

typedef enum {LedControllerRequestPortal} IfcNames deriving (Eq,Bits);

module mkConnectalTop(StdConnectalTop#(PhysAddrWidth));
   LedController ledController <- mkLedControllerRequest();
   LedControllerRequestWrapper ledControllerRequestWrapper <-
      mkLedControllerRequestWrapper(LedControllerRequestPortal,
      ledController.request);

   Vector#(1,StdPortal) portals;
   portals[0] = ledControllerRequestWrapper.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   interface leds = ledController.leds;
endmodule

Like the SW components, the HW begins by importing the generated wrappers and proxies corresponding to the interfaces listed in the project Makefile. The user-defined implementation of the LedControllerRequest interface is instantiated on line 14, and wrapped on line 15. This wrapped interface is connected to the bus using the library module mkSlaveMux on line 21 so it can be invoked from the software. At the end of the module definition, the top-level interface elements must be connected. A board-specific top-level module will include this file, instantiate mkConnectalTop and connect the interfaces to the actual peripherals. The module mkConnectalTop must be defined in a file named Top.bsv in the user project.

The Bluespec compiler generates a Verilog module from the top level BSV module, in which the methods of exposed interfaces are implemented as Verilog ports. Those ports are bound to physical pins on the FPGA using a physical constraints file. If CPU specific interface signals are needed by the design (for example, extra clocks that are generated by the PCIe core), then an optional CPU-specific HostInterface parameter to mkConnectalTop can also be used. If the design uses external pins on the FPGA, those connections are also made here by exporting a ‘Pins’ interface (hyperref[host_interface]{Section~ref{host_interface}}) and providing bindings in the constraints file.