Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Soft connections have three basic primitives, send, receive, and chain, which come in a handful of different flavors.
Send-receive pairs behave like FIFO channels, while chains operate as a broadcast primitive. Soft connections are well-typed, and endpoints with the same name but different types result in a compile-time error.
interface CONNECTION_SEND#(type t_MSG); method Action send(t_MSG data); method Bool notFull(); endinterface
CONNECTION_SEND#(UMF_PACKET) link_client_STDIO_resp <- mkConnection_Send(“rrr_client_STDIO_resp”);
This code specifies the send endpoint of a latency insensitive channel named rrr_client_STDIO_resp with the type UMF_PACKET
interface CONNECTION_RECV#(type t_MSG); method Action deq(); method Bool notEmpty(); method t_MSG receive(); endinterface
CONNECTION_RECV#(UMF_PACKET) link_client_STDIO_resp <- mkConnection_Recv("rrr_client_STDIO_resp");
This code specifies the receive endpoint of a latency insensitive channel named rrr_client_STDIO_resp with the type UMF_PACKET
interface CONNECTION_CHAIN#(type msg_T); method ActionValue#(msg_T) recvFromPrev(); method msg_T peekFromPrev(); method Bool recvNotEmpty(); method Action sendToNext(msg_T data); method Bool sendNotFull(); endinterface
CONNECTION_CHAIN#(STDIO_REQ_RING_MSG) reqChain <- mkConnectionChain("stdio_req_ring")
This code instantiate a chain endpoint on the stdio_req_ring ring. This ring has type STDIO_REQ_RING_MSG.
The primitive chain implementation requires chain endpoints to manually forward data to subsequent endpoints. To simplify the user interface, LEAP also provides several higher-level networking structures built on top of the basic chain primitive including addressable rings and token rings:
Using Soft Connections
The following example shows how to use Soft connections to create a simple Client-Server architecture. In this example, the client sends a value to the server, which increments the value and returns it to the client. Both client and server are instantiated in the top level connected application.
module [CONNECTED_MODULE] mkConnectedApplication (Empty); let client <- mkClient(); let server <- mkServer(); // Communication between client and server is implemented by LEAP. No user code required! endmodule module [CONNECTED_MODULE] mkClient (Empty); Connection_Send#(Bit#(16)) request <- mkConnection_Send("counter_request"); Connection_Recv#(Bit#(16)) response <- mkConnection_Recv("counter_response"); rule doReq; request.send(1); endrule rule doResp; let resp = response.receive(); response.deq(); $display("Did we get 2: %d", resp); $finish; endrule endmodule module [CONNECTED_MODULE] mkServer (Empty); Connection_Recv#(Bit#(16)) request <- mkConnection_Recv("counter_request"); Connection_Send#(Bit#(16)) response <- mkConnection_Send("counter_response"); rule doReq; let req = request.receive(); request.deq(); response.send(req + 1); endrule endmodule
Note that although the client and server modules are communicating, they do not have Bluespec-style, wired interfaces. This is because the implementation of the latency-insensitive communications embodied by the soft connections is chosen by LEAP. Because module communications are not directly exposed in the user program, the modularity of LEAP-based programs is greatly enhanced.
Although we have used the concrete type Bit#(16), soft connections support arbitrary polymorphic types.
Soft connections may be thought of as extending the Bluespec language with support for latency-insensitive channels. Since LEAP treats these channels as first-class language objects, while Bluespec does not, LEAP must externally augment the Bluespec compiler to handle Soft Connections. These augmentations are manifest as stages in the Build Pipeline for LEAP hardware. During regular Bluespec compilation, when a soft connections primitive is encountered, this primitive is added to a list of soft connections which is maintained by LEAP. The result of compilation of a LEAP user program is some HDL, and a complete list of the soft connections present in the design. To finish compilation, LEAP matches send and receive endpoints and joins chains, adding appropriate hardware to the design. The completely linked design may be passed to back-end synthesis tools or simulated.