This list is for discussion of the design and implementation of field-programmable gate array based processors and integrated systems. It is also for discussion and community support of the XSOC Project (see http://www.fpgacpu.org/xsoc).
|
THE RIGHT TOOL FOR THE JOB To achieve near-optimal FPGA cores it is often necessary to control both technology mapping and placement of the circuit -- and to do that properly you need the right tools. (Technology mapping is the process of mapping abstract gate expressions into FPGA device resources like 4-LUTs (4-input lookup tables)). This is straightforward to do with schematics. What you see is what you get. You control technology mapping use FMAPs (4000X) or LUTs (Virtex). You control placement with RLOCs (relative location constraints). You can see liberal RLOCs and FMAPs sprinkled throughout the XSOC/xr16 schematics. The many disadvantages of schematics include that they are awkward to share, excerpt, diff, and manage with version control. And they are slow to draw (if you are fussy). I'm through designing with schematics. Mapping and placement control is also possible in structural HDLs if your HDL compiler allows the structure to be tagged with attributes that in effect generate FMAPS (LUTs) and RLOCs. FPGA Express (>=3.x) allows attributes (incl. RLOCs) but swallows FMAPs. Workarounds are awkward (see www.fpgacpu.org/usenet/rope_pushing.html). Apparently Synplicity and Exemplar give you decent control over both FMAPs and RLOCs. The attribute syntax is lamentably different across tools, of course! The schematic version of XSOC/xr16 was 25% faster and somewhat more compact than the partially-floorplanned Verilog version. C++ CIRCUIT GENERATORS When I built j32 (www3.sympatico.ca/jsgray/homebrew.htm) in 1995, I first wrote a C++ class library called CNets, which provided classes for nets, buses, and circuit primitives, and which used C++ operator overloading to provide a convenient design notation. ("Notation is a tool of thought" -- Ken Iverson.) This provided a simple and extensible text-based structural design representation (see www.fpgacpu.org/usenet/cnets.html). Indeed, all of j32, including processor, bus, serial port, simple assembler, on-chip boot ROM builder, etc. was a single manageable .cpp file. Whenever I discuss C++ and/or Java design representations, people confuse structural circuit generators with behavioral synthesizers. I attempt to explain the distinction in www.fpgacpu.org/usenet/generators.html. CNets and CNets2000 are circuit generators. In 1996 or so, I fiddled with a Java version of CNets. The allure of Java is it offers reflection, so it is easy to enumerate the members of a class. If you represent each hierarchical sheet/module of your design as a class, reflection makes it all too easy to traverse your design hierarchy. Unfortunately, Java lacks operator overloading. Where in CNets I could write net(mux) = a&~sel | b&sel; in my-JHDL I had to write mux.is(a.andnot(sel).or(b.and(sel))); which (although not terrible) I did not like. In contrast, C++'s operator overloading provides a nice notation for expressions, but requires that you somehow "introduce" each member of a class to itself and to its class. To do this, I use a set of _() macros that is not too ugly (see below). Later in 1996, I went back to C++ and designed a sketch of a new version of CNets that handled hierarchical designs properly, but I never finished it. I've picked at it over the years, but never got much traction. Back in July I again revisited CNets, producing something I'm calling CNets2000. It's very much a work in progress. I whipped up about 600 lines of new C++ code and now I can produce EDIF from a CNets2000 structural specification. For example, here is mux.h, which defines 2-input and 4-input muxes: // mux.h #include "cnets.h" module(Mux2) { // define a 2-1 mux In a, b, sel; Out o; imp(Mux2) _4(a,b,sel,o) is o = a&~sel | b&sel; endimp }; module(Mux4) { // define a 4-1 mux as a composition of three 2-1 muxes In a, b, c, d, sel1, sel2; Out o; Wire o1, o2; Mux2 m1, m2, m3; imp(Mux4) _7(a,b,c,d,sel1,sel2,o), _5(o1,o2,m1,m2,m3) is m1.a(a).b(b).sel(sel1).o(o1).rloc(0,0); m2.a(c).b(d).sel(sel1).o(o2).rloc(0,0); m3.a(o1).b(o2).sel(sel2).o(o).rloc(0,1); endimp }; // main.cpp #include "mux.h" int main() { Mux4 m("m"); m.addIOs(); cnets.edif(cout, m); return 0; } (I am especially pleased with the 'portmap' like dot-notation for specifying port-wire associations (m2.a(c).etc.) Behind the scenes, each module maps into a C++ class. Members can be In and Out port declarations, Wires, and submodules. The imp (implementation) of each module is actually its class's constructor. The implementation defines the port-wire connectivity of the submodules, as well as any other gate logic (see Mux2). This example doesn't show any registers, I'm still fiddling with them. Here is an excerpt of its output, which is approximately correct EDIF. Note that 'm.addIOs()' above has inserted IBUF and OBUFs and _i and _o nets into the design automatically: (cell Mux4 (cellType generic) (view net (viewType netlist) (interface (wire a (direction INPUT)) (wire b (direction INPUT)) (wire c (direction INPUT)) (wire d (direction INPUT)) (wire o (direction OUTPUT)) (wire sel1 (direction INPUT)) (wire sel2 (direction INPUT)) (contents (instance a_ibuf (viewRef net (cellRef IBUF))) (instance b_ibuf (viewRef net (cellRef IBUF))) (instance c_ibuf (viewRef net (cellRef IBUF))) (instance d_ibuf (viewRef net (cellRef IBUF))) (instance m1 (viewRef net (cellRef Mux2))) (instance m2 (viewRef net (cellRef Mux2))) (instance m3 (viewRef net (cellRef Mux2))) (instance o_obuf (viewRef net (cellRef OBUF))) (instance sel1_ibuf (viewRef net (cellRef IBUF))) (instance sel2_ibuf (viewRef net (cellRef IBUF))) (net a (joined (portRef a) (portRef I (instanceRef a_ibuf)))) (net a_i (joined (portRef a (instanceRef m1)) (portRef O (instanceRef a_ibuf)))) (net b (joined (portRef b) (portRef I (instanceRef b_ibuf)))) (net b_i (joined (portRef b (instanceRef m1)) (portRef O (instanceRef b_ibuf)))) (net c (joined (portRef c) (portRef I (instanceRef c_ibuf)))) (net c_i (joined (portRef a (instanceRef m2)) (portRef O (instanceRef c_ibuf)))) (net d (joined (portRef d) (portRef I (instanceRef d_ibuf)))) (net d_i (joined (portRef b (instanceRef m2)) (portRef O (instanceRef d_ibuf)))) (net o (joined (portRef o) (portRef O (instanceRef o_obuf)))) (net o1 (joined (portRef o (instanceRef m1)) (portRef a (instanceRef m3)))) (net o2 (joined (portRef o (instanceRef m2)) (portRef b (instanceRef m3)))) (net o_o (joined (portRef o (instanceRef m3)) (portRef I (instanceRef o_obuf)))) (net sel1 (joined (portRef sel1) (portRef I (instanceRef sel1_ibuf)))) (net sel1_i (joined (portRef sel (instanceRef m1)) (portRef sel (instanceRef m2)) (portRef O (instanceRef sel1_ibuf)))) (net sel2 (joined (portRef sel2) (portRef I (instanceRef sel2_ibuf)))) (net sel2_i (joined (portRef sel (instanceRef m3)) (portRef O (instanceRef sel2_ibuf)))))))) Since CNets2000 structurally models the elements of a schematic, it can do anything a schematic can do. And yet it has all the advantages of a text representation but with a modern high-level language substrate. The best thing about CNets2000 (and similar tools) is it builds a data structure of the design in memory that you can manipulate in C++. So it becomes possible to simulate it using a simple cycle-based simulator. Or emit an optimized C program that should simulate it at high speed. Or write/read designs as XML. Or massage the design (as Module::addIOs() does to insert IBUFs and OBUFs). Or directly emit it using jbits. Or ... . I don't know how far I will polish the current CNets2000, or whether I will apply it to XSOC/xr in the future. Perhaps I should open source it and move it to SourceForge.net. Questions? Comments? Jan Gray Gray Research LLC |
|
|
|
> > I don't know how far I will polish the current CNets2000, or whether I will > apply it to XSOC/xr in the future. Perhaps I should open source it and move > it to SourceForge.net. Open sourcing it sounds an excellent idea to me. But then I would say that, wouldn't I ;-) Graham http://opencollector.org |