[J-core] Open source lattice synthesis toolchain build script.

Rob Landley rob at landley.net
Mon Nov 4 20:01:32 EST 2019

The attached script builds a fully open source VHDL toolchain from 4 github
repositories. This is how you assemble the pieces to get something that can in
_theory_ make a bitstream runnable on ICE40, but right now it's mostly useful
for sending them bug reports when our "blink one LED" hello world program throws
an internal commpiler error.

The script does the git checkout or update of 4 packages (into whatever
directory you run them into) and compiles them in sequence. The result is a
"yogh" directory (yosys+ghdl, feel free to set PREFIX= to some other directory
name) with a "bin" under it containing ghdl and yosys that know about synthesis.
Add that bin directory to your $PATH (or tell it to install into /usr/local or
some such).

The new toolchain is roughly analogous to a C compiler with ghdl instead of
clang, ghdlsynth instead of llvm, yosys instead of binutils, and then abc is the
LTO plugin binutils calls these days to do most of the optimization.

The new project is ghdlsynth, which is under very active development, and has
already resulted in a bunch changes to the other 3 projects. The bug reports
_probably_ go to ghdlsynth, but he's currently swamped so give him a month or so
to catch up.

To actually use the result, first do this:

  export PATH=~/yogh/bin:$PATH
  cd ~/j-core-ice40

That should run the simulation to the end (which runs the CPU test ROM checking
all the instructions. Printing out the c0 line means success and then it spins
an extra few seconds until we get to the 2 miliseconds of runtime the command
line argument says to stop at).

The simulation (ghdl -r at the end) wasn't the important bit, the "analysis"
(ghdl -a) and "elaboration" (ghdl -e) produced two .cf files and a .ghw file
which we use to make a bitstream. (This toolchain doesn't make .o files, it
sticks the intermediate stuff into databases for some reason. Imagine in a
compiler that couldn't read/write .o files, only .a files, but would happily add
to and replace objects in existing .a files each time it was run.)

All those -a lines told it "read these VHDL files and store the AST in the
database", and then -e says "make a schematic for this circuit". The simulator
then runs the schematic (which is still pretty abstract).

The next step the new toolchain converts the first schematic into the specific
component types we actually want to use (such as 4-input LUTs, SRAMs, and
whatever other bits of hardware we have in our FPGA libraries). I forget what
this step is called but Jeff knows.

The step after that, "place and route", fits the second schemetic into an actual
FPGA, which is really hard because you're trying to minimize the connection
lengths and you've got finite numbers of each component in specific location.
(The second schematic is sort of a ball floating in zero gravity where all the
connection lengths are zero. Place and route assigns addresses to each
component, this is _this_ cell connected by _this_ line in the routing fabric).

So, backing up: the ./ghdl_lattice.sh above did "ghdl -a" analysis of all our
vhdl source lodaing it into the database, and then requested "ghdl -e"
elaboration to create a schematic for the whole chip, and then ran the simulator
on it to confirm it worked.

All THAT part is just GHDL, and that's worked for years. Now we wanna make a

Unfortunately, this new toolchain hasn't got a chance of handling the whole
processor at once yet (I'm hoping they'll be there by the end of next year), so
we need to feed them a smaller chunk. How about _just_ the register file:

  ghdl -e register_file

(It lives in register_file.vhd but the name we fed to -e isn't the filename,
it's the object name, I.E. "entity register_file is" on line 19. We don't have
to say where it was because all those -a already loaded all the source into the
databases. If you want to do a make clean you can "rm *.cf *.ghw" but we haven't
had it get confused about new vs old stuff in forever, ghdl is pretty mature.)

Now we fire up yosys with the ghdlsim module and tell it to work on register
file. (Yes, it's got an interactive mode with its own prompt.)

  $ yosys -m ghdl
  yosys> ghdl register_file
  1. Executing GHDL.

  ******************** GHDL Bug occurred ***************************
  Please report this bug on https://github.com/ghdl/ghdl/issues
  GHDL release: 0.37-dev (v0.36-1141-g61d4cdf2) [Dunoon edition]
  Compiled with unknown compiler version
  Target: x86_64-pc-linux-gnu
  Command line:

  Exception TYPES.INTERNAL_ERROR raised
  Exception information:
  raised TYPES.INTERNAL_ERROR : synth-expr.adb:705
  ERROR: vhdl import failed.
  yosys> exit

Behold the glory of the internal compiler error we got.

Our next step is to find something small enough it can build a bitstream we can
load on the ICE40 and actually tell it's doing something. (It dies like this on
our blink-the-LED example, which is more or less the same as hooking up a scope
to a GPIO line...)

But hey: it exists! Progress!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: yogh.sh
Type: application/x-shellscript
Size: 1930 bytes
Desc: not available
URL: <http://lists.j-core.org/pipermail/j-core/attachments/20191104/f8583c46/attachment.bin>

More information about the J-core mailing list