Merge pull request #2228 from mesonbuild/icestorm

IceStorm FPGA experiment
pull/3007/head
Jussi Pakkanen 7 years ago committed by GitHub
commit f25070ec08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      docs/markdown/Icestorm-module.md
  2. 12
      docs/markdown/snippets/fpga.md
  3. 1
      docs/sitemap.txt
  4. 2
      mesonbuild/interpreter.py
  5. 85
      mesonbuild/modules/unstable_icestorm.py
  6. 9
      test cases/fpga/1 simple/meson.build
  7. 6
      test cases/fpga/1 simple/spin.pcf
  8. 32
      test cases/fpga/1 simple/spin.v

@ -0,0 +1,27 @@
# Unstable SIMD module
This module provides is available since version 0.45.0.
**Note**: this module is unstable. It is only provided as a technology
preview. Its API may change in arbitrary ways between releases or it
might be removed from Meson altogether.
## Usage
This module provides an experimental to create FPGA bitstreams using
the [IceStorm](http://www.clifford.at/icestorm/) suite of tools.
The module exposes only one method called `project` and it is used
like this:
is.project('projname',
<verilog files>,
constraint_file : <pcf file>,
)
The input to this function is the set of Verilog files and a
constraint file. This produces output files called `projname.asc`,
`projname.blif` and `projname.bin`. In addition it creates two run
targets called `projname-time` for running timing analysis and
`projname-upload` that uploads the generated bitstream to an FPGA
devide using the `iceprog` programming executable.

@ -0,0 +1,12 @@
## Experimental FPGA support
This version adds support for generating, analysing and uploading FPGA
programs using the [IceStorm
toolchain](http://www.clifford.at/icestorm/). This support is
experimental and is currently limited to the `iCE 40` series of FPGA
chips.
FPGA generation integrates with other parts of Meson seamlessly. As an
example, [here](https://github.com/jpakkane/lm32) is an example
project that compiles a simple firmware into Verilog and combines that
with an lm32 softcore processor.

@ -30,6 +30,7 @@ index.md
Modules.md
Gnome-module.md
i18n-module.md
Icestorm-module.md
Pkgconfig-module.md
Python-3-module.md
Qt4-module.md

@ -2994,6 +2994,8 @@ different subdirectory.
def source_strings_to_files(self, sources):
results = []
mesonlib.check_direntry_issues(sources)
if not isinstance(sources, list):
sources = [sources]
for s in sources:
if isinstance(s, (mesonlib.File, GeneratedListHolder,
CustomTargetHolder, CustomTargetIndexHolder)):

@ -0,0 +1,85 @@
# Copyright 2017 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import mesonlib, compilers, mlog
from . import ExtensionModule
class IceStormModule(ExtensionModule):
def __init__(self):
super().__init__()
self.snippets.add('project')
self.yosys_bin = None
def detect_binaries(self, interpreter):
self.yosys_bin = interpreter.func_find_program(None, ['yosys'], {})
self.arachne_bin = interpreter.func_find_program(None, ['arachne-pnr'], {})
self.icepack_bin = interpreter.func_find_program(None, ['icepack'], {})
self.iceprog_bin = interpreter.func_find_program(None, ['iceprog'], {})
self.icetime_bin = interpreter.func_find_program(None, ['icetime'], {})
def project(self, interpreter, state, args, kwargs):
if not self.yosys_bin:
self.detect_binaries(interpreter)
result = []
if not len(args):
raise mesonlib.MesonException('Project requires at least one argument, which is the project name.')
proj_name = args[0]
arg_sources = args[1:]
if not isinstance(proj_name, str):
raise mesonlib.MesonException('Argument must be a string.')
kwarg_sources = kwargs.get('sources', [])
if not isinstance(kwarg_sources, list):
kwarg_sources = [kwarg_sources]
all_sources = interpreter.source_strings_to_files(interpreter.flatten(arg_sources + kwarg_sources))
if 'constraint_file' not in kwargs:
raise mesonlib.MesonException('Constraint file not specified.')
constraint_file = interpreter.source_strings_to_files(kwargs['constraint_file'])
if len(constraint_file) != 1:
raise mesonlib.MesonException('Constraint file must contain one and only one entry.')
blif_name = proj_name + '_blif'
blif_fname = proj_name + '.blif'
asc_name = proj_name + '_asc'
asc_fname = proj_name + '.asc'
bin_name = proj_name + '_bin'
bin_fname = proj_name + '.bin'
time_name = proj_name + '-time'
upload_name = proj_name + '-upload'
blif_target = interpreter.func_custom_target(None, [blif_name], {
'input': all_sources,
'output': blif_fname,
'command': [self.yosys_bin, '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@']})
asc_target = interpreter.func_custom_target(None, [asc_name], {
'input': blif_target,
'output': asc_fname,
'command': [self.arachne_bin, '-q', '-d', '1k', '-p', constraint_file, '@INPUT@', '-o', '@OUTPUT@']})
bin_target = interpreter.func_custom_target(None, [bin_name], {
'input': asc_target,
'output': bin_fname,
'command': [self.icepack_bin, '@INPUT@', '@OUTPUT@'],
'build_by_default' : True})
up_target = interpreter.func_run_target(None, [upload_name], {
'command': [self.iceprog_bin, bin_target]})
time_target = interpreter.func_run_target(None, [time_name], {
'command' : [self.icetime_bin, bin_target]})
def initialize():
return IceStormModule()

@ -0,0 +1,9 @@
project('lattice', 'c')
is = import('unstable_icestorm')
is.project('spin',
'spin.v',
constraint_file : 'spin.pcf',
)

@ -0,0 +1,6 @@
set_io LED1 99
set_io LED2 98
set_io LED3 97
set_io LED4 96
set_io LED5 95
set_io clk 21

@ -0,0 +1,32 @@
module top(input clk, output LED1, output LED2, output LED3, output LED4, output LED5);
reg ready = 0;
reg [23:0] divider;
reg [3:0] spin;
always @(posedge clk) begin
if (ready)
begin
if (divider == 6000000)
begin
divider <= 0;
spin <= {spin[2], spin[3], spin[0], spin[1]};
end
else
divider <= divider + 1;
end
else
begin
ready <= 1;
spin <= 4'b1010;
divider <= 0;
end
end
assign LED1 = spin[0];
assign LED2 = spin[1];
assign LED3 = spin[2];
assign LED4 = spin[3];
assign LED5 = 1;
endmodule
Loading…
Cancel
Save