def configure_main(self): #Pass trellis tool options to yosys and nextpnr self.edam['tool_options'] = \ {'yosys' : { 'arch' : 'ecp5', 'yosys_synth_options' : self.tool_options.get('yosys_synth_options', []), 'yosys_as_subtool' : True, 'yosys_template' : self.tool_options.get('yosys_template'), }, 'nextpnr' : { 'nextpnr_options' : self.tool_options.get('nextpnr_options', []) }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() nextpnr = Nextpnr(yosys.edam, self.work_root) nextpnr.flow_config = {'arch' : 'ecp5'} nextpnr.configure() # Write Makefile commands = self.EdaCommands() commands.commands = yosys.commands commands.commands += nextpnr.commands #Image generation depends = self.name+'.config' targets = self.name+'.bit' command = ['ecppack', '--svf', self.name+'.svf', depends, targets] commands.add(command, [targets], [depends]) commands.set_default_target(self.name+'.bit') commands.write(os.path.join(self.work_root, 'Makefile'))
def get_doc(cls, api_ver): if api_ver == 0: yosys_help = Yosys.get_doc(api_ver) icestorm_help = { 'members' : [ {'name' : 'pnr', 'type' : 'String', 'desc' : 'Select Place & Route tool. Legal values are *arachne* for Arachne-PNR, *next* for nextpnr or *none* to only perform synthesis. Default is next'}], 'lists' : [ {'name' : 'arachne_pnr_options', 'type' : 'String', 'desc' : 'Additional options for Arachnhe PNR'}, {'name' : 'nextpnr_options', 'type' : 'String', 'desc' : 'Additional options for nextpnr'}, {'name' : 'yosys_synth_options', 'type' : 'String', 'desc' : 'Additional options for the synth_ice40 command'}, ]} combined_members = icestorm_help['members'] combined_lists = icestorm_help['lists'] yosys_members = yosys_help['members'] yosys_lists = yosys_help['lists'] combined_members.extend(m for m in yosys_members if m['name'] not in [i['name'] for i in combined_members]) combined_lists.extend(l for l in yosys_lists if l['name'] not in [i['name'] for i in combined_lists]) return {'description' : "Open source toolchain for Lattice iCE40 FPGAs. Uses yosys for synthesis and arachne-pnr or nextpnr for Place & Route", 'members' : combined_members, 'lists' : combined_lists}
def configure_main(self): # Pass apicula tool options to yosys and nextpnr self.edam["tool_options"] = { "yosys": { "arch": "gowin", "output_format": "json", "yosys_synth_options": [f"-json {self.name}.json"] + self.tool_options.get("yosys_synth_options", []), "yosys_as_subtool": True, "yosys_template": self.tool_options.get("yosys_template"), }, "nextpnr": { "device": self.tool_options.get("device"), "nextpnr_options": self.tool_options.get("nextpnr_options", []), }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() nextpnr = Nextpnr(yosys.edam, self.work_root) nextpnr.flow_config = {"arch": "gowin"} nextpnr.configure() # Write Makefile commands = EdaCommands() commands.commands = yosys.commands commands.commands += nextpnr.commands # Image generation depends = self.name + ".pack" targets = self.name + ".fs" command = [ "gowin_pack", "-d", self.tool_options.get("device"), "-o", targets, depends, ] commands.add(command, [targets], [depends]) commands.set_default_target(targets) commands.write(os.path.join(self.work_root, "Makefile"))
def configure_main(self): # Pass trellis tool options to yosys and nextpnr self.edam["tool_options"] = { "yosys": { "arch": "nexus", "output_format": "json", "yosys_synth_options": self.tool_options.get("yosys_synth_options", []), "yosys_as_subtool": True, "yosys_template": self.tool_options.get("yosys_template"), }, "nextpnr": { "device": self.tool_options.get("device"), "nextpnr_options": self.tool_options.get("nextpnr_options", []), }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() nextpnr = Nextpnr(yosys.edam, self.work_root) nextpnr.flow_config = {"arch": "nexus"} nextpnr.configure() # Write Makefile commands = EdaCommands() commands.commands = yosys.commands commands.commands += nextpnr.commands # Image generation depends = self.name + ".fasm" targets = self.name + ".bit" command = ["prjoxide", "pack", depends, targets] commands.add(command, [targets], [depends]) commands.set_default_target(self.name + ".bit") commands.write(os.path.join(self.work_root, "Makefile"))
def configure_main(self): # pass mistral tool option to yosys and nextpnr self.edam["tool_options"] = { "yosys": { "arch": "intel_alm", "output_format": "json", "yosys_synth_options": self.tool_options.get("yosys_synth_options", []), "yosys_as_subtool": True, "yosys_template": self.tool_options.get("yosys_template"), }, "nextpnr": { "device": self.tool_options.get("device"), "nextpnr_options": self.tool_options.get("nextpnr_options", []), }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() nextpnr = Nextpnr(yosys.edam, self.work_root) nextpnr.flow_config = {"arch": "mistral"} nextpnr.configure() # Write Makefile commands = EdaCommands() commands.commands = yosys.commands commands.commands += nextpnr.commands # Image generation commands.set_default_target(self.name + ".rbf") commands.write(os.path.join(self.work_root, "Makefile"))
def configure_main(self): #Pass apicula tool options to yosys and nextpnr self.edam['tool_options'] = \ {'yosys' : { 'arch' : 'gowin', 'yosys_synth_options' : [f"-json {self.name}.json"] + self.tool_options.get('yosys_synth_options',[]), 'yosys_as_subtool' : True, 'yosys_template' : self.tool_options.get('yosys_template'), }, 'nextpnr' : { 'device' : self.tool_options.get('device'), 'nextpnr_options' : self.tool_options.get('nextpnr_options', []) }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() nextpnr = Nextpnr(yosys.edam, self.work_root) nextpnr.flow_config = {'arch': 'gowin'} nextpnr.configure() # Write Makefile commands = self.EdaCommands() commands.commands = yosys.commands commands.commands += nextpnr.commands #Image generation depends = self.name + '.pack' targets = self.name + '.fs' command = [ 'gowin_pack', '-d', self.tool_options.get('device'), '-o', targets, depends ] commands.add(command, [targets], [depends]) commands.set_default_target(targets) commands.write(os.path.join(self.work_root, 'Makefile'))
def get_doc(cls, api_ver): if api_ver == 0: yosys_help = Yosys.get_doc(api_ver) apicula_help = { 'members': [ { 'name': 'device', 'type': 'String', 'desc': 'Required device option for nextpnr-gowin and gowin_pack command (e.g. GW1N-LV1QN48C6/I5)' }, ], 'lists': [ { 'name': 'nextpnr_options', 'type': 'String', 'desc': 'Additional options for nextpnr' }, { 'name': 'yosys_synth_options', 'type': 'String', 'desc': 'Additional options for the synth_gowin command' }, ] } combined_members = apicula_help['members'] combined_lists = apicula_help['lists'] yosys_members = yosys_help['members'] yosys_lists = yosys_help['lists'] combined_members.extend( m for m in yosys_members if m['name'] not in [i['name'] for i in combined_members]) combined_lists.extend( l for l in yosys_lists if l['name'] not in [i['name'] for i in combined_lists]) return { 'description': "Open source toolchain for Gowin FPGAs. Uses yosys for synthesis and nextpnr for Place & Route", 'members': combined_members, 'lists': combined_lists }
def get_doc(cls, api_ver): if api_ver == 0: yosys_help = Yosys.get_doc(api_ver) trellis_help = { 'lists': [ { 'name': 'nextpnr_options', 'type': 'String', 'desc': 'Additional options for nextpnr' }, { 'name': 'yosys_synth_options', 'type': 'String', 'desc': 'Additional options for the synth_ecp5 command' }, ] } combined_members = [] combined_lists = trellis_help['lists'] yosys_members = yosys_help['members'] yosys_lists = yosys_help['lists'] combined_members.extend( m for m in yosys_members if m['name'] not in [i['name'] for i in combined_members]) combined_lists.extend( l for l in yosys_lists if l['name'] not in [i['name'] for i in combined_lists]) return { 'description': "Project Trellis enables a fully open-source flow for ECP5 FPGAs using Yosys for Verilog synthesis and nextpnr for place and route", 'members': combined_members, 'lists': combined_lists }
def configure_main(self): synth_tool = self.tool_options.get("synth", "vivado") if synth_tool == "yosys": self.edam['tool_options']['yosys'] = { 'arch' : 'xilinx', 'output_format' : 'edif', 'yosys_synth_options' : self.tool_options.get('yosys_synth_options', []), 'yosys_as_subtool' : True, } yosys = Yosys(self.edam, self.work_root) yosys.configure() self.files = yosys.edam['files'] src_files = [] incdirs = [] edif_files = [] has_vhdl2008 = False has_xci = False unused_files = [] for f in self.files: cmd = "" if f['file_type'].startswith('verilogSource'): cmd = 'read_verilog' elif f['file_type'].startswith('systemVerilogSource'): cmd = 'read_verilog -sv' elif f['file_type'] == 'tclSource': cmd = 'source' elif f['file_type'] == 'edif': cmd = 'read_edif' edif_files.append(f['name']) elif f['file_type'].startswith('vhdlSource'): cmd = 'read_vhdl' if f['file_type'] == 'vhdlSource-2008': has_vhdl2008 = True cmd += ' -vhdl2008' if f.get('logical_name'): cmd += ' -library '+f['logical_name'] elif f['file_type'] == 'xci': cmd = 'read_ip' has_xci = True elif f['file_type'] == 'xdc': cmd = 'read_xdc' elif f['file_type'] == 'SDC': cmd = 'read_xdc -unmanaged' elif f['file_type'] == 'mem': cmd = 'read_mem' if cmd: if not self._add_include_dir(f, incdirs): src_files.append(cmd + ' {' + f['name'] + '}') else: unused_files.append(f) template_vars = { 'name' : self.name, 'src_files' : '\n'.join(src_files), 'incdirs' : incdirs+['.'], 'tool_options' : self.tool_options, 'toplevel' : self.toplevel, 'vlogparam' : self.vlogparam, 'vlogdefine' : self.vlogdefine, 'generic' : self.generic, 'netlist_flow' : bool(edif_files), 'has_vhdl2008' : has_vhdl2008, 'has_xci' : has_xci, } self.render_template('vivado-project.tcl.j2', self.name+'.tcl', template_vars) jobs = self.tool_options.get('jobs', None) run_template_vars = { 'jobs' : ' -jobs ' + str(jobs) if jobs is not None else '' } self.render_template('vivado-run.tcl.j2', self.name+"_run.tcl", run_template_vars) synth_template_vars = { 'jobs' : ' -jobs ' + str(jobs) if jobs is not None else '' } self.render_template('vivado-synth.tcl.j2', self.name+"_synth.tcl", synth_template_vars) # Write Makefile commands = self.EdaCommands() vivado_command = ['vivado', '-notrace', '-mode', 'batch', '-source'] #Create project file project_file = self.name+'.xpr' tcl_file = [self.name+'.tcl'] commands.add(vivado_command+tcl_file, [project_file], tcl_file + edif_files) #Synthesis target if synth_tool == 'yosys': commands.commands += yosys.commands commands.add([], ['synth'], edif_files) else: depends = [f'{self.name}_synth.tcl', project_file] targets = [f'{self.name}.runs/synth_1/__synthesis_is_complete__'] commands.add(vivado_command+depends, targets, depends) commands.add([], ['synth'], targets) #Bitstream generation run_tcl = self.name+'_run.tcl' depends = [run_tcl, project_file] bitstream = self.name+'.bit' commands.add(vivado_command+depends, [bitstream], depends) commands.add(['vivado', project_file], ['build-gui'], [project_file]) depends = [self.name+'_pgm.tcl', bitstream] command = ['vivado', '-quiet', '-nolog', '-notrace', '-mode', 'batch', '-source', f'{self.name}_pgm.tcl', '-tclargs'] part = self.tool_options.get('part', "") command += [part] if part else [] command += [bitstream] commands.add(command, ['pgm'], depends) commands.set_default_target(bitstream) commands.write(os.path.join(self.work_root, 'Makefile')) self.render_template('vivado-program.tcl.j2', self.name+"_pgm.tcl")
def configure_main(self): (src_files, incdirs) = self._get_fileset_files() synth_out = self.name + "_synth.v" device = self.tool_options.get("device") if not device: raise RuntimeError("Missing required option 'device' for p_r") match = re.search("^CCGM1A([1-9]{1,2})$", device) if not match: raise RuntimeError("{} is not known device name".format(device)) device_number = match.groups()[0] if device_number not in ["1", "2", "4", "9", "16", "25"]: raise RuntimeError( "Rel. size {} is not unsupported".format(device_number)) ccf_file = None for f in src_files: if f.file_type == "CCF": if ccf_file: raise RuntimeError( "p_r only supports one ccf file. Found {} and {}". format(ccf_file, f.name)) else: ccf_file = f.name # Pass trellis tool options to yosys self.edam["tool_options"] = { "yosys": { "arch": "gatemate", "output_format": "verilog", "output_name": synth_out, "yosys_synth_options": self.tool_options.get("yosys_synth_options", []), "yosys_as_subtool": True, "yosys_template": self.tool_options.get("yosys_template"), }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() # Write Makefile commands = EdaCommands() commands.commands = yosys.commands # PnR & image generation targets = self.name + "_00.cfg.bit" command = [ "p_r", "-A", device_number, "-i", synth_out, "-o", self.name, "-lib", "ccag", " ".join(self.tool_options.get("p_r_options", "")), ] if ccf_file is not None: command += ["-ccf", ccf_file] commands.add(command, [targets], [synth_out]) commands.set_default_target(targets) commands.write(os.path.join(self.work_root, "Makefile"))
def configure_main(self): # Write yosys script file yosys_synth_options = self.tool_options.get('yosys_synth_options', '') #Pass icestorm tool options to yosys and nextpnr self.edam['tool_options'] = \ {'yosys' : { 'arch' : 'ice40', 'yosys_synth_options' : yosys_synth_options, 'yosys_as_subtool' : True, 'yosys_template' : self.tool_options.get('yosys_template'), }, 'nextpnr' : { 'nextpnr_options' : self.tool_options.get('nextpnr_options', []) }, } yosys = Yosys(self.edam, self.work_root) yosys.configure() pnr = self.tool_options.get('pnr', 'next') part = self.tool_options.get('part', None) if not pnr in ['arachne', 'next', 'none']: raise RuntimeError( "Invalid pnr option '{}'. Valid values are 'arachne' for Arachne-pnr, 'next' for nextpnr or 'none' to only perform synthesis" .format(pnr)) # Write Makefile commands = self.EdaCommands() commands.commands = yosys.commands if pnr == 'arachne': depends = self.name + '.blif' targets = self.name + '.asc' command = ['arachne-pnr'] command += self.tool_options.get('arachne_pnr_options', []) command += ['-p', depends, '-o', targets] commands.add(command, [depends], [targets]) set_default_target(self.name + '.bin') elif pnr == 'next': nextpnr = Nextpnr(yosys.edam, self.work_root) nextpnr.flow_config = {'arch': 'ice40'} nextpnr.configure() commands.commands += nextpnr.commands commands.set_default_target(self.name + '.bin') else: commands.set_default_target(self.name + '.json') #Image generation depends = self.name + '.asc' targets = self.name + '.bin' command = ['icepack', depends, targets] commands.add(command, [targets], [depends]) #Timing analysis depends = self.name + '.asc' targets = self.name + '.tim' command = ['icetime', '-tmd', part or '', depends, targets] commands.add(command, [targets], [depends]) commands.add([], ["timing"], [targets]) #Statistics depends = self.name + '.asc' targets = self.name + '.stat' command = ['icebox_stat', depends, targets] commands.add(command, [targets], [depends]) commands.add([], ["stats"], [targets]) commands.write(os.path.join(self.work_root, 'Makefile'))
def configure_main(self): """ Configuration is the first phase of the build. This writes the project TCL files and Makefile. It first collects all sources, IPs and constraints and then writes them to the TCL file along with the build steps. """ synth_tool = self.tool_options.get("synth", "vivado") if synth_tool == "yosys": self.edam["tool_options"]["yosys"] = { "arch": "xilinx", "output_format": "edif", "yosys_synth_options": self.tool_options.get("yosys_synth_options", []), "yosys_as_subtool": True, } yosys = Yosys(self.edam, self.work_root) yosys.configure() self.files = yosys.edam["files"] src_files = [] incdirs = [] edif_files = [] has_vhdl2008 = False has_xci = False unused_files = [] for f in self.files: cmd = "" if f["file_type"].startswith("verilogSource"): cmd = "read_verilog" elif f["file_type"].startswith("systemVerilogSource"): cmd = "read_verilog -sv" elif f["file_type"] == "tclSource": cmd = "source" elif f["file_type"] == "edif": cmd = "read_edif" edif_files.append(f["name"]) elif f["file_type"].startswith("vhdlSource"): cmd = "read_vhdl" if f["file_type"] == "vhdlSource-2008": has_vhdl2008 = True cmd += " -vhdl2008" if f.get("logical_name"): cmd += " -library " + f["logical_name"] elif f["file_type"] == "xci": cmd = "read_ip" has_xci = True elif f["file_type"] == "xdc": cmd = "read_xdc" elif f["file_type"] == "SDC": cmd = "read_xdc -unmanaged" elif f["file_type"] == "mem": cmd = "read_mem" if cmd: if not self._add_include_dir(f, incdirs): src_files.append(cmd + " {" + f["name"] + "}") else: unused_files.append(f) template_vars = { "name": self.name, "src_files": "\n".join(src_files), "incdirs": incdirs + ["."], "tool_options": self.tool_options, "toplevel": self.toplevel, "vlogparam": self.vlogparam, "vlogdefine": self.vlogdefine, "generic": self.generic, "netlist_flow": bool(edif_files), "has_vhdl2008": has_vhdl2008, "has_xci": has_xci, } self.render_template("vivado-project.tcl.j2", self.name + ".tcl", template_vars) jobs = self.tool_options.get("jobs", None) run_template_vars = { "jobs": " -jobs " + str(jobs) if jobs is not None else "" } self.render_template("vivado-run.tcl.j2", self.name + "_run.tcl", run_template_vars) synth_template_vars = { "jobs": " -jobs " + str(jobs) if jobs is not None else "" } self.render_template("vivado-synth.tcl.j2", self.name + "_synth.tcl", synth_template_vars) # Write Makefile commands = EdaCommands() vivado_command = ["vivado", "-notrace", "-mode", "batch", "-source"] # Create project file project_file = self.name + ".xpr" tcl_file = [self.name + ".tcl"] commands.add(vivado_command + tcl_file, [project_file], tcl_file + edif_files) # Synthesis target if synth_tool == "yosys": commands.commands += yosys.commands commands.add([], ["synth"], edif_files) else: depends = [f"{self.name}_synth.tcl", project_file] targets = [f"{self.name}.runs/synth_1/__synthesis_is_complete__"] commands.add(vivado_command + depends, targets, depends) commands.add([], ["synth"], targets) # Bitstream generation run_tcl = self.name + "_run.tcl" depends = [run_tcl, project_file] bitstream = self.name + ".bit" commands.add(vivado_command + depends, [bitstream], depends) commands.add(["vivado", project_file], ["build-gui"], [project_file]) depends = [self.name + "_pgm.tcl", bitstream] command = [ "vivado", "-quiet", "-nolog", "-notrace", "-mode", "batch", "-source", f"{self.name}_pgm.tcl", "-tclargs", ] part = self.tool_options.get("part", "") command += [part] if part else [] command += [bitstream] commands.add(command, ["pgm"], depends) commands.set_default_target(bitstream) commands.write(os.path.join(self.work_root, "Makefile")) self.render_template("vivado-program.tcl.j2", self.name + "_pgm.tcl")