3. Design of a Solution
3.1 Philosophy of the Approach
4.2.4 Code Production
The scanning procedure gives a basic map of the CLB and BRAM usage. This map is then used to analyse, in greater depth, specific resources and their settings. Finally, a program is generated which describes the implementation. There are many types of resource contained within each of the basic areas, whose state has to be captured and
translated into program statements, such as multiplexors, switches, LUT arrays and routing, some of which may be to external I/O points.
The format of the Java program produced is broken into several key methods. These allow a control program to build, destroy, communicate and route a process’s physical circuit.
The main methods in the Java program are as follows:
Build(). This builds the process at a given position in a device’s matrix. An
example of this from the pulsecounter process is:
public boolean build (JBits Jbits_in, int Row_in, int Col_in) {
boolean place_ok = true;
int max_row_idx = Jbits_in.getClbRows()-1; int max_col_idx = Jbits_in.getClbColumns()-1; int max_bram_idx = (Jbits_in.getClbRows()/4)-1; if ((Row_in+row_Size)>max_row_idx) place_ok = false; if ((Col_in+col_Size)>max_col_idx) place_ok = false; if (((Row_in/4)+num_BRAM)>max_bram_idx) place_ok = false; if (place_ok) {
Jbits = Jbits_in;
jroute = new JRoute(Jbits);
jroute.getFanoutRouter().setMaxLoopCount(20000); BaseRow = Row_in; BaseCol = Col_in; pulsecntCLB041(); } return place_ok;
} // end build circuit
A bitstream is passed, together with the build row and column origin points. Various checks are implemented, such as free BRAMs (if required) and the fit of the process. If this is all right then a placement is attempted. In this example the actual building is done by the pulsecntCLB041() call, see CLB() below for details.
Destroy(). This releases all resources – multiplexors, routing, LUTs etc. for that process. For example:
public void destroy() {
NullConfig NullCLB = new NullConfig(); try {
NullCLB.nullClbLogic(Jbits,BaseRow+0,BaseCol+0); NullCLB.nullClbRoutes(Jbits,BaseRow+0,BaseCol+0); } catch (Exception ce) { System.out.println(ce); };
}
Port(). By using the port method it is possible to direct a process to connect, via physical routing, to external pads and other processes internal to the device. These can be default locations, or specified by a user. It also allows information about a port to flow back to the supervising program.
CLB() methods are called by the above mentioned build() during construction. They contain the physical implementation details for each used CLB.
BRAM() methods, when called upon, implement the described BRAM into a specified, or automatically generated, location.
Other minor methods are available for information purposes, such as to return the row and column size of the process, together with how many BRAMs are used.
From the point of view of the average user of the system, the above method details are not required. DES and the command language take care of such detail. This information is useful if the process is to be used by a Java programmer, outside of Reconnetics.
In the case of CLB areas, each resource within a CLB location is looked at and the appropriate statement is written to the file. The particular resources included in such a location are:
• Clock, chip enable, set/reset selects. • LUTs (four in total, two in each slice).
• Internal switches/muxes, such as carry select, control inputs, clock invert, chip enable invert, data input select, LUT mode selection, write enable etc.
CLB areas also contain routing. Beginning and endpoints are noted and auto-route statements generated. It is also possible to produce code for routing “templates”, rather than start/end points. This template can then be moved and placed anywhere across the device, using relative coordinates. The benefit being that a precise routing is generated, although at the expense of a larger program file. External port points are not linked but left open at this stage.
A Port() method is written in such a way that external I/O points can be connected to dynamically by the user. The signature of the port() method reveals some of the detail:
public conPort port(String portName, Pin cxPin, int mode)
By using this method, it is possible to instruct the circuit’s I/O to be connected, dynamically, to any given point on the FPGA. The different mechanisms available are accessed through instructing the Port() method with different values in mode:
DELETE (mode=0) – deletes a named route starting at portName. ROUTE (mode=1) – routes a port to a destination, stored in cxPin. DEFAULT (mode=2) – routes a port to a default connection point. INFO (mode=3) – retrieve port information.
CLOCKED (mode=4) – retrieve the clocked version of a port. NAMES (mode=5) – retrieve names of ports on this circuit.
Using these various modes it is possible to get information about any particular named port and route or unroute it. The DEFAULT mode allows a named port to be linked to its design-time point, which is useful for having a specific I/O set up installed every time for interface to external circuits, for example. INFO mode allows
data about a named port to be returned as a conPort object. This contains the port’s details, such as its width and default connections. CLOCKED mode allows a version of a port to be returned, which is always linked through a clocked register, overriding its default status, which may be a simple, straight-through connection. Finally, NAMES mode allows access to the circuit’s port names as strings. This is used for retaining labels if the circuit is recaptured, so they persist through to the new design. More details on this follow.
It is only necessary to trace output routing from a CLB since the only other place that incoming wires may be from is IOBs or BRAM, which are dealt with separately, being less numerous. Any used inputs are therefore found as a result of being traced from another CLB.
The basic “shape” of the design is kept intact, that is, the map which shows resource usage also holds the basic relational details. At the time of code production such detail is captured by producing offset row/column data between each CLB and a point of origin. The entire design can then be relocated anywhere on the surface of an FPGA, while maintaining its relational and connection constraints. This ensures that issues such as timing and gate propagation, are met, as they were when initially compiled. It is possible to override positioning data for CLBs, if necessary.
Used BRAMs are analysed and separate methods built for their construction. There are three main resource areas; settings for logic (switches, mux), data content and routing. As before, in the case of the CLBs, appropriate statements are generated to implement correct settings. Data content in the BRAM is translated into an array format, held in the method, which is downloaded at build time. Finally, statements are written for output wiring. This connects the BRAM to its owning process. It is important to note here that it is possible to position the BRAM at any BRAM location and it will still be wired to correctly. This makes it easy for a run-time system to place and route such resources in whatever way is best suited at the time.
In all the above generated code, no routing is generated that leads to external IOB positions. External I/O is scanned though, for connection points to the internal circuit. Each IOB is looked at in turn. Inputs and Outputs are checked for valid routes to
previously captured CLB positions. Tracing routes (using JBits) is a question of working through a tree of connections from source to sink(s). It is also possible to trace in reverse, which is necessary when looking at the output connections. Each net is checked for its uniqueness of connection to an I/O point and that such a link is valid (that it is a true source, for example). Each active I/O point is eventually given a port object containing its relevant details; such as start point, direction and end point(s). This data binds together the IOB, its net and the CLBs it is linked to. Obviously, the duplication of data is possible with a high number of net wires and physical routing problems; such as recursive loops. Details are checked, as noted above, for uniqueness and integrity. The information gathered here is used as default connection data, stored in the generated program.
previously captured CLB positions. Tracing routes (using JBits) is a question of working through a tree of connections from source to sink(s). It is also possible to trace in reverse, which is necessary when looking at the output connections. Each net is checked for its uniqueness of connection to an I/O point and that such a link is valid (that it is a true source, for example). Each active I/O point is eventually given a port object containing its relevant details; such as start point, direction and end point(s). This data binds together the IOB, its net and the CLBs it is linked to. Obviously, the duplication of data is possible with a high number of net wires and physical routing problems; such as recursive loops. Details are checked, as noted above, for uniqueness and integrity. The information gathered here is used as default connection data, stored in the generated program.