├── LICENSE ├── chisel.py ├── custom.py ├── generators.core ├── gitversion.py ├── icepll.py └── template ├── examples ├── add.v ├── constants_test.sv ├── constants_test.vhd ├── generators_chisel.core ├── generators_template_constraints.core ├── generators_template_local.core ├── generators_template_package.core ├── my_templates │ └── adder.j2 └── test_add.v ├── template_generator.py └── templates ├── constants_pkg_sv.j2 ├── constants_pkg_vhd.j2 ├── sdc.j2 └── ucf.j2 /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 fusesoc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /chisel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from fusesoc.capi2.generator import Generator 3 | import os 4 | import shutil 5 | import shlex 6 | import subprocess 7 | import tempfile 8 | 9 | 10 | class ChiselGenerator(Generator): 11 | def run(self): 12 | env = self.config.get('env', None) 13 | buildtool = self.config.get('buildtool', "mill") 14 | chiselproject = self.config.get('chiselproject', None) 15 | outputdir = self.config.get('outputdir', "generated") 16 | extraargs = self.config.get('extraargs', "") 17 | projectdir = self.config.get("projectdir", None) 18 | if buildtool == "mill" and chiselproject == None: 19 | print("The parameter 'chiselproject' must be defined.") 20 | exit(1) 21 | 22 | copy_core = self.config.get('copy_core', False) 23 | if copy_core: 24 | tmp_dir = os.path.join(tempfile.mkdtemp(), 'core') 25 | shutil.copytree(self.files_root, tmp_dir, 26 | ignore=shutil.ignore_patterns('out', 'generated')) 27 | 28 | cwd = (tmp_dir if copy_core else self.files_root) + ("/" + projectdir if projectdir else "") 29 | 30 | files = self.config['output'].get('files', []) 31 | parameters = self.config['output'].get('parameters', {}) 32 | 33 | # Find build tool, first in root dir, then ./scripts dir then in path 34 | buildcmd = [] 35 | if self._is_exe(os.path.join(cwd, buildtool)): 36 | buildcmd.append(os.path.join(cwd, buildtool)) 37 | elif self._is_exe(os.path.join(cwd, "scripts", buildtool)): 38 | buildcmd.append(os.path.join(cwd, "scripts", buildtool)) 39 | elif shutil.which(buildtool) is not None: 40 | buildcmd.append(shutil.which(buildtool)) 41 | else: 42 | print("Build tool " + buildtool + " not found") 43 | exit(1) 44 | print("Using build tool from: " + buildcmd[0]) 45 | 46 | # Define command and arguments based on build tool 47 | if buildtool == "mill": 48 | args = '-i ' + chiselproject + '.run ' + extraargs + ' --target-dir='+ outputdir 49 | elif buildtool == "sbt": 50 | args = '"run' + ' ' + extraargs + '--target-dir='+ outputdir + '"' 51 | 52 | 53 | args = shlex.split(args) 54 | 55 | # Concatenate environment variables from system + user defined 56 | d = os.environ 57 | if env: 58 | d.update(env) 59 | 60 | # Call build tool 61 | cmd = buildcmd + args 62 | if os.getenv('EDALIZE_LAUNCHER'): 63 | cmd = [os.getenv('EDALIZE_LAUNCHER')] + cmd 64 | 65 | print("Working dir:", cwd) 66 | print("Running:", " ".join(cmd)) 67 | rc = subprocess.call(cmd, env=d, cwd=cwd) 68 | 69 | if rc: 70 | exit(1) 71 | if cwd: 72 | filenames = [] 73 | for f in files: 74 | for k in f: 75 | filenames.append(k) 76 | 77 | for f in filenames: 78 | d = os.path.dirname(f) 79 | if d and not os.path.exists(d): 80 | os.makedirs(d) 81 | shutil.copy2(os.path.join(cwd, f), f) 82 | 83 | self.add_files(files) 84 | 85 | for k, v in parameters.items(): 86 | self.add_parameter(k, v) 87 | 88 | def _is_exe(self, fpath): 89 | return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 90 | 91 | 92 | g = ChiselGenerator() 93 | g.run() 94 | g.write() 95 | -------------------------------------------------------------------------------- /custom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from fusesoc.capi2.generator import Generator 3 | import os 4 | import shutil 5 | import subprocess 6 | import tempfile 7 | 8 | class CustomGenerator(Generator): 9 | def run(self): 10 | 11 | copy_core = self.config.get('copy_core', False) 12 | if copy_core: 13 | tmp_dir = os.path.join(tempfile.mkdtemp(), 'core') 14 | shutil.copytree(self.files_root, tmp_dir) 15 | 16 | cwd = None 17 | if self.config.get('run_from_core'): 18 | cwd = tmp_dir if copy_core else self.files_root 19 | 20 | files = self.config['output'].get('files', []) 21 | parameters = self.config['output'].get('parameters', {}) 22 | 23 | rc = subprocess.call(self.config['command'].split(), cwd=cwd) 24 | if rc: 25 | exit(1) 26 | if cwd: 27 | filenames = [] 28 | for f in files: 29 | for k in f: 30 | filenames.append(k) 31 | 32 | for f in filenames: 33 | d = os.path.dirname(f) 34 | if d and not os.path.exists(d): 35 | os.makedirs(d) 36 | shutil.copy2(os.path.join(cwd, f),f) 37 | 38 | self.add_files(files) 39 | 40 | for k,v in parameters.items(): 41 | self.add_parameter(k, v) 42 | 43 | g = CustomGenerator() 44 | g.run() 45 | g.write() 46 | -------------------------------------------------------------------------------- /generators.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name: fusesoc:utils:generators:0.1.7 4 | 5 | generators: 6 | custom: 7 | interpreter: python3 8 | command: custom.py 9 | description: Run custom command 10 | usage: | 11 | The custom generator allows the user to specify a custom command to run. 12 | As the custom generator doesn't know by itself what is produced by the 13 | command, the user is requrested to specify any created files and associated 14 | plusargs, defines etc in the output configuration parameter. 15 | 16 | Parameters: 17 | command (str): The command to run. Working directory for the command is 18 | determined by the copy_core and run_from_core parameters 19 | copy_core (bool): Copy the working directory to a temporary location and run 20 | the command from there 21 | run_from_core (bool): Runs command from the directory specified as files_root 22 | in the configuration file 23 | output (dict): A dictionary describing the expected output from the command. 24 | These are written to the generated .core file 25 | files (list): A list of files, specified in the same format as CAPI2 fileset 26 | files, which are expected to be generated by the command 27 | parameters (dict): A map of parameters, specified in the same format as 28 | CAPI2 parameters, which are used by the generated files 29 | 30 | gitversion: 31 | interpreter: python3 32 | command: gitversion.py 33 | description: Parse version tags from git repo 34 | usage: | 35 | The gitversion generator runs git describe to look at the tags in the current 36 | directory (or in files_root if that is defined in the input configuration file) 37 | and creates verilog defines that can be used in a core to provide accurate 38 | version information. 39 | 40 | Tags are assumed to be on the format vx.y.z which produces the following defines 41 | VERSION_MAJOR = x 42 | VERSION_MINOR = y 43 | VERSION_PATCH = z 44 | 45 | In addition to the parsed tags, the gitversion generator will also set 46 | VERSION_REV to the number of commits since the last tag and VERSION_DIRTY if 47 | it detects that there are local modifications in the repository 48 | 49 | icepll: 50 | interpreter: python3 51 | command: icepll.py 52 | description: Generate a parameterized verilog wrapper for an iCE40 PLL 53 | usage: | 54 | The icepll generator is a simple wrapper around the icepll command 55 | 56 | Parameters: 57 | freq_in (int): PLL Input Frequency (default: 12 MHz) 58 | freq_out (int) PLL Output Frequency (default: 60 MHz) 59 | filename (str): Output filename (default: pll.v) 60 | module (bool): If true, generate a verilog module which instantiates the PLL. 61 | Otherwise, the user is responsible for instantiating the PLL 62 | and the icepll generator will create a list of parameters that 63 | can be included in the parameter list of the user-instantiated 64 | component (default: false) 65 | 66 | template: 67 | interpreter: python3 68 | command: template/template_generator.py 69 | description: Generate a file from a Jinja template 70 | usage: | 71 | The template generator uses the provided YAML description to populate 72 | a Jinja template. 73 | 74 | The generator requires the following parameters: 75 | 76 | output_file: 77 | 78 | name: The file name for the rendered template 79 | type: The file type of the rendered template (vhdlSource, verilogSource, etc.) 80 | 81 | template: The file name of the template 82 | 83 | template_path (optional): The directory containing the template. 84 | 85 | If this parameter isn't specified the default is to use the 86 | calling core's directory followed by the templates 87 | directory for this generator. 88 | 89 | Examples of template usage are in the examples directory. 90 | 91 | chisel: 92 | interpreter: python3 93 | command: chisel.py 94 | description: Build Chisel HDL 95 | usage: | 96 | This generator builds chisel HDL generating Verilog output. 97 | The generator depends on the Mill or SBT build configs and require the 98 | host to have all pre-reqs like a Java Virtual Machine to build Chisel/Scala 99 | applications. 100 | The user is required to specify any created files and associated 101 | arguments and parameters. 102 | 103 | Parameters: 104 | buildtool (str): The Scala build tool to be used (Mill or SBT). 105 | Requires respective "build.sc" or "build.sbt". 106 | env (str): Environment variables to be passed to the Chisel build tool. 107 | outputdir (str): Output directory to be passed to build tool for generated 108 | verilog files from Chisel sources. Must match path used in 109 | "output: files:" section. 110 | extraargs (str): Extra arguments to be passed to the build tool. 111 | chiselproject (str): Chisel project name to be passed to the build tool. 112 | copy_core (bool): Copy the working directory to a temporary location and run 113 | the command from there 114 | output (dict): A dictionary describing the expected output from the command. 115 | These are written to the generated .core file 116 | files (list): A list of files, specified in the same format as CAPI2 fileset 117 | files, which are expected to be generated by the command 118 | parameters (dict): A map of parameters, specified in the same format as 119 | CAPI2 parameters, which are used by the generated files 120 | -------------------------------------------------------------------------------- /gitversion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from fusesoc.capi2.generator import Generator 3 | import subprocess 4 | 5 | class VersionGenerator(Generator): 6 | def run(self): 7 | verlist = subprocess.check_output(['git', 8 | 'describe', 9 | '--tags', 10 | '--dirty', 11 | '--abbrev=8', 12 | '--long'], 13 | cwd=self.files_root).decode().rstrip().split('-') 14 | dirty = verlist[-1] == 'dirty' 15 | if dirty: 16 | verlist.pop() 17 | sha = verlist.pop()[1:9] 18 | 19 | rev = verlist.pop() 20 | 21 | #Sanity checks on version 22 | if len(verlist) > 1: 23 | print("'-' is not allowed in version tag") 24 | exit(1) 25 | 26 | if not verlist[0][0] == 'v': 27 | print("Version tag must start with 'v'") 28 | exit(1) 29 | ver = verlist[0][1:].split('.') 30 | major = ver.pop(0) 31 | minor = ver.pop(0) 32 | patch = ver[0] if ver else 0 33 | 34 | params = {'VERSION_MAJOR' : major, 35 | 'VERSION_MINOR' : minor, 36 | 'VERSION_PATCH' : patch, 37 | 'VERSION_REV' : rev, 38 | } 39 | for k,v in params.items(): 40 | self.add_parameter(k, 41 | {'datatype' : 'int', 42 | 'default' : int(v), 43 | 'paramtype' : 'vlogdefine', 44 | }) 45 | self.add_parameter('VERSION_DIRTY', 46 | {'datatype' : 'bool', 47 | 'default' : dirty, 48 | 'paramtype' : 'vlogdefine'}) 49 | self.add_parameter('VERSION_SHA', 50 | {'datatype' : 'str', 51 | 'default' : str(sha), 52 | 'paramtype' : 'vlogdefine'}) 53 | 54 | vg = VersionGenerator() 55 | vg.run() 56 | vg.write() 57 | -------------------------------------------------------------------------------- /icepll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from fusesoc.capi2.generator import Generator 3 | import subprocess 4 | 5 | class IcepllGenerator(Generator): 6 | def run(self): 7 | fin = self.config.get('freq_in', 12) 8 | fout = self.config.get('freq_out', 60) 9 | module = self.config.get('module', False) 10 | filename = self.config.get('filename', 'pll.v' if module else 'pll.vh') 11 | 12 | args = ['icepll', '-f', filename, '-i', str(fin), '-o', str(fout)] 13 | if module: 14 | args.append('-m') 15 | rc = subprocess.call(args) 16 | if rc: 17 | exit(1) 18 | self.add_files([{filename : {'file_type' : 'verilogSource', 19 | 'is_include_file' : not module}}]) 20 | 21 | g = IcepllGenerator() 22 | g.run() 23 | g.write() 24 | -------------------------------------------------------------------------------- /template/examples/add.v: -------------------------------------------------------------------------------- 1 | module add #( 2 | parameter WIDTH = 16) 3 | ( 4 | input clk, 5 | input [WIDTH-1:0] a, b, 6 | output reg [WIDTH:0] c 7 | ); 8 | 9 | always @(posedge clk) 10 | c <= a + b; 11 | 12 | endmodule 13 | -------------------------------------------------------------------------------- /template/examples/constants_test.sv: -------------------------------------------------------------------------------- 1 | import constants_pkg::*; 2 | 3 | module constants_test; 4 | 5 | initial 6 | begin 7 | $display("WORD_SIZE: %d", word_size); 8 | $display("ITERATIONS: %d", iterations); 9 | $display("LOW_AREA: %d", low_area); 10 | $display("IMPL: %s", impl); 11 | $finish; 12 | end 13 | 14 | endmodule 15 | 16 | -------------------------------------------------------------------------------- /template/examples/constants_test.vhd: -------------------------------------------------------------------------------- 1 | USE work.constants_pkg.ALL; 2 | 3 | ENTITY constants_test IS 4 | END ENTITY; 5 | 6 | ARCHITECTURE test OF constants_test IS 7 | BEGIN 8 | 9 | sim : PROCESS 10 | BEGIN 11 | REPORT "WORD_SIZE: " & INTEGER'IMAGE(word_size) & LF; 12 | REPORT "ITERATIONS: " & INTEGER'IMAGE(iterations) & LF; 13 | REPORT "LOW_AREA: " & BOOLEAN'IMAGE(low_area) & LF; 14 | REPORT "IMPL: " & impl & LF; 15 | 16 | std.env.finish(0); 17 | WAIT; 18 | END PROCESS; 19 | 20 | END test ; --constants_test 21 | -------------------------------------------------------------------------------- /template/examples/generators_chisel.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name: test:demo:chiselblinky:0 4 | 5 | filesets: 6 | polarfireeval: 7 | depend: ["fusesoc:utils:generators:0.1.6"] 8 | files: 9 | - constraints/polarfire_evaluation.pdc: { file_type: PDC } 10 | 11 | generate: 12 | polarfireeval: 13 | generator: chisel 14 | parameters: 15 | buildtool: mill # Optional, set to mill as default 16 | outputdir: . # Optional, set to "generated" as default 17 | env: # Optional environment variables 18 | BOARD: polarfireeval 19 | extraargs: "-board polarfireeval" # Optional arguments to build tool 20 | chiselproject: blinky # Mandatory if using mill 21 | copy_core: true # Build from fresh directory 22 | output: 23 | files: 24 | - generated/Toplayer.v: { file_type: verilogSource } 25 | - generated/pll_polarfireeval.v: { file_type: verilogSource } 26 | 27 | targets: 28 | polarfireeval_es: 29 | default_tool: libero 30 | description: Microsemi Polarfire Evaluation Kit (ES) 31 | filesets: [polarfireeval] 32 | generate: [polarfireeval] 33 | tools: 34 | libero: 35 | family: PolarFire 36 | die: MPF300TS_ES 37 | package: FCG1152 38 | toplevel: Toplayer 39 | -------------------------------------------------------------------------------- /template/examples/generators_template_constraints.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | name: fusesoc:utils:generators_template_constraints:0.1 3 | description: Simple example of generating SDC and UCF constraints 4 | 5 | filesets: 6 | 7 | hdl: 8 | files: [add.v] 9 | file_type: verilogSource 10 | depend: ["fusesoc:utils:generators"] 11 | 12 | generate: 13 | 14 | ise_constraints: 15 | generator: template 16 | parameters: 17 | output_file: {name: add.ucf, type: UCF} 18 | template: ucf.j2 19 | clock_name: clk 20 | clock_freq: "123 MHz" 21 | 22 | quartus_constraints: 23 | generator: template 24 | parameters: 25 | output_file: {name: add.sdc, type: SDC} 26 | template: sdc.j2 27 | clock_name: clk 28 | clock_period: '"234 MHz"' 29 | input_delay: 0 30 | output_delay: 0 31 | 32 | targets: 33 | 34 | default: &default 35 | filesets: [hdl] 36 | toplevel: [add] 37 | 38 | ise: 39 | <<: *default 40 | generate: [ise_constraints] 41 | default_tool: ise 42 | tools: 43 | ise: 44 | family: spartan6l 45 | device: XC6SLX75L 46 | package: CSG484 47 | speed: "-1L" 48 | 49 | quartus: 50 | <<: *default 51 | generate: [quartus_constraints] 52 | default_tool: quartus 53 | tools: 54 | quartus: 55 | family: "Cyclone V" 56 | device: 5CEBA2F17C7 57 | -------------------------------------------------------------------------------- /template/examples/generators_template_local.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | name: fusesoc:utils:generators_template_local:0.1 3 | description: Silly example using a template from a core rather than the generator 4 | 5 | filesets: 6 | 7 | tb: 8 | files: [test_add.v] 9 | file_type: verilogSource 10 | depend: ["fusesoc:utils:generators"] 11 | 12 | generate: 13 | 14 | adder: 15 | generator: template 16 | parameters: 17 | output_file: {name: my_add.v, type: verilogSource} 18 | template: my_templates/adder.j2 19 | clock: clk 20 | adder_name: my_add 21 | 22 | targets: 23 | 24 | default: 25 | default_tool: modelsim 26 | filesets: [tb] 27 | generate: [adder] 28 | toplevel: [test_add] 29 | -------------------------------------------------------------------------------- /template/examples/generators_template_package.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | name: fusesoc:utils:generators_template_package:0.1 3 | description: Simple example of generating packages 4 | 5 | filesets: 6 | 7 | vhdl: 8 | files: [constants_test.vhd] 9 | file_type: vhdlSource-2008 10 | depend: ["fusesoc:utils:generators"] 11 | 12 | sv: 13 | files: [constants_test.sv] 14 | file_type: systemVerilogSource 15 | depend: ["fusesoc:utils:generators"] 16 | 17 | generate: 18 | 19 | constants_vhdl: 20 | generator: template 21 | position: first 22 | parameters: 23 | output_file: {name: constants_pkg.vhd, type: vhdlSource} 24 | template: constants_pkg_vhd.j2 25 | package_name: constants_pkg 26 | constants: 27 | - {name: word_size, type: POSITIVE, value: 32} 28 | - {name: iterations, type: POSITIVE, value: 100} 29 | - {name: low_area, type: BOOLEAN, value: true} 30 | - {name: impl, type: STRING, value: '"tiny"'} 31 | 32 | constants_sv: 33 | generator: template 34 | position: first 35 | parameters: 36 | output_file: {name: constants_pkg.sv, type: systemVerilogSource} 37 | template: constants_pkg_sv.j2 38 | package_name: constants_pkg 39 | constants: 40 | - {name: word_size, type: int, value: 48} 41 | - {name: iterations, type: int, value: 123} 42 | - {name: low_area, type: int, value: 0} 43 | - {name: impl, type: string, value: '"huge"'} 44 | 45 | targets: 46 | 47 | default: &default 48 | default_tool: modelsim 49 | toplevel: [constants_test] 50 | 51 | sim_vhdl: 52 | <<: *default 53 | filesets: [vhdl] 54 | generate: [constants_vhdl] 55 | 56 | sim_sv: 57 | <<: *default 58 | filesets: [sv] 59 | generate: [constants_sv] 60 | -------------------------------------------------------------------------------- /template/examples/my_templates/adder.j2: -------------------------------------------------------------------------------- 1 | {# 2 | Example of a template that's shipped with a core rather than fusesoc-generators 3 | 4 | Required varaibles: 5 | 6 | adder_name - The name of the adder module 7 | clock - The name of the clock signal 8 | #} 9 | module {{ adder_name }} #( 10 | parameter WIDTH = 16) 11 | ( 12 | input {{ clock }}, 13 | input [WIDTH-1:0] a, b, 14 | output reg [WIDTH:0] c 15 | ); 16 | 17 | always @(posedge {{ clock }}) 18 | c <= a + b; 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /template/examples/test_add.v: -------------------------------------------------------------------------------- 1 | module test_add; 2 | 3 | localparam period = 10; 4 | 5 | reg clock; 6 | reg [15:0] a, b; 7 | reg [16:0] expected; 8 | 9 | wire [16:0] c; 10 | 11 | integer errors = 0, cycle_count = 0, total_cycles = 100; 12 | 13 | my_add dut (.clk (clock), .a (a), .b (b), .c (c)); 14 | 15 | initial 16 | begin 17 | clock = 0; 18 | forever #(period/2) clock = ~clock; 19 | end 20 | 21 | // Stimulus 22 | always @(posedge clock) 23 | begin 24 | #1 25 | a = $urandom; 26 | b = $urandom; 27 | cycle_count = cycle_count + 1; 28 | end 29 | 30 | // Model 31 | always @(posedge clock) 32 | begin 33 | expected = a + b; 34 | end 35 | 36 | // Check results on the falling edge of the clock 37 | always @(negedge clock) 38 | begin 39 | 40 | if (cycle_count == total_cycles) 41 | begin 42 | $display("Finished simulation. Ran %d tests with %d errors.", cycle_count, errors); 43 | $finish; 44 | end 45 | 46 | if (c !== expected) 47 | begin 48 | errors = errors + 1; 49 | $display("Error! Got %d + %d = %d but expected %d", a, b, c, expected); 50 | end 51 | 52 | end 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /template/template_generator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from fusesoc.capi2.generator import Generator 5 | from jinja2 import Environment, FileSystemLoader 6 | 7 | class TemplateGenerator(Generator): 8 | def run(self): 9 | 10 | output_file = self.config.get('output_file') 11 | template_name = self.config.get('template') 12 | 13 | # Allow the user to specify where to look for Jinja templates, but by 14 | # default look in the core's directory or in the "templates" directory 15 | # beneath this script's location 16 | default_template_path = [self.files_root] 17 | 18 | script_dir = os.path.dirname(__file__) 19 | template_dir = os.path.join(script_dir, 'templates') 20 | 21 | default_template_path.append(template_dir) 22 | 23 | template_path = self.config.get('template_path', default_template_path) 24 | 25 | env = Environment(loader=FileSystemLoader(template_path), trim_blocks=True, lstrip_blocks=True) 26 | 27 | template = env.get_template(template_name) 28 | 29 | template.stream(self.config).dump(output_file['name']) 30 | 31 | self.add_files([{output_file['name'] : {'file_type' : output_file['type']}}]) 32 | 33 | if __name__ == '__main__': 34 | g = TemplateGenerator() 35 | g.run() 36 | g.write() 37 | -------------------------------------------------------------------------------- /template/templates/constants_pkg_sv.j2: -------------------------------------------------------------------------------- 1 | {# 2 | Render a SystemVerilog package containing constants 3 | 4 | Required varaibles: 5 | 6 | package_name - The name of the SystemVerilog package 7 | constants - A list of dicts each containing a constant's name, type, and value 8 | 9 | Example: 10 | 11 | constants_sv: 12 | generator: template 13 | position: first 14 | parameters: 15 | output_file: {name: constants_pkg.sv, type: systemVerilogSource} 16 | template: constants_pkg_sv.j2 17 | package_name: constants_pkg 18 | constants: 19 | - {name: word_size, type: int, value: 48} 20 | - {name: iterations, type: int, value: 123} 21 | - {name: low_area, type: int, value: 0} 22 | - {name: impl, type: string, value: '"huge"'} 23 | #} 24 | package {{ package_name }}; 25 | {% for c in constants %} 26 | const {{ c.type }} {{ c.name }} = {{ c.value }}; 27 | {% endfor %} 28 | endpackage 29 | -------------------------------------------------------------------------------- /template/templates/constants_pkg_vhd.j2: -------------------------------------------------------------------------------- 1 | {# 2 | Render a VHDL package containing constants 3 | 4 | Required varaibles: 5 | 6 | package_name - The name of the VHDL package 7 | constants - A list of dicts each containing a constant's name, type, and value 8 | 9 | Example: 10 | 11 | generate: 12 | 13 | constants_vhdl: 14 | generator: template 15 | position: first 16 | parameters: 17 | output_file: {name: constants_pkg.vhd, type: vhdlSource} 18 | template: constants_pkg_vhd.j2 19 | package_name: constants_pkg 20 | constants: 21 | - {name: word_size, type: POSITIVE, value: 32} 22 | - {name: iterations, type: POSITIVE, value: 100} 23 | - {name: low_area, type: BOOLEAN, value: true} 24 | - {name: impl, type: STRING, value: '"tiny"'} 25 | #} 26 | PACKAGE {{ package_name }} IS 27 | {% for c in constants %} 28 | CONSTANT {{ c.name }} : {{ c.type }} := {{ c.value }}; 29 | {% endfor %} 30 | END PACKAGE; 31 | -------------------------------------------------------------------------------- /template/templates/sdc.j2: -------------------------------------------------------------------------------- 1 | {# 2 | Render a basic Intel Quartus SDC file 3 | 4 | Variables: 5 | 6 | clock_name - Name of the clock signal (default: clk) 7 | clock_period - Quartus supports both a period in ns or a string like "375 MHz" (default: 1.0) 8 | input_delay - Value applied with set_input_delay to all inputs (default: 0) 9 | output_delay - Value applied with set_output_delay to all outputs (default: 0) 10 | -#} 11 | 12 | {% set clk = clock_name|default(clk) -%} 13 | 14 | create_clock -name {{clk}} -period {{clock_period|default(1.0)}} [get_ports {{clk}}] 15 | 16 | set_input_delay -clock {{clk}} {{input_delay|default(0)}} [all_inputs] 17 | set_output_delay -clock {{clk}} {{output_delay|default(0)}} [all_outputs] 18 | 19 | -------------------------------------------------------------------------------- /template/templates/ucf.j2: -------------------------------------------------------------------------------- 1 | {# 2 | Render a basic Xilinx ISE UCF file 3 | 4 | Variables: 5 | 6 | clock_name - Name of the clock signal (default: clk) 7 | clock_freq - Clock frequency in a string like 375 MHz (default: 500 MHz) 8 | 9 | -#} 10 | 11 | {% set clk = clock_name|default(clk) -%} 12 | 13 | 14 | NET "{{clk}}" TNM_NET = {{clk}}; 15 | TIMESPEC TS_{{clk}} = PERIOD "{{clk}}" {{clock_freq|default("500 MHz")}} HIGH 50%; 16 | 17 | --------------------------------------------------------------------------------