1
+ # This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
2
+ # License: BSD
3
+
4
+ import os , subprocess , shutil
5
+
6
+ from migen .fhdl .structure import _Fragment
7
+ from mibuild .generic_platform import *
8
+ from mibuild import tools
9
+
10
+ def _format_constraint (c ):
11
+ if isinstance (c , Pins ):
12
+ return ("LOCATE COMP " , " SITE " + "\" " + c .identifiers [0 ] + "\" " )
13
+ elif isinstance (c , IOStandard ):
14
+ return ("IOBUF PORT " , " IO_TYPE=" + c .name )
15
+ elif isinstance (c , Misc ):
16
+ return c .misc
17
+
18
+ def _format_lpf (signame , pin , others , resname ):
19
+ fmt_c = [_format_constraint (c ) for c in ([Pins (pin )] + others )]
20
+ r = ""
21
+ for pre , suf in fmt_c :
22
+ r += pre + "\" " + signame + "\" " + suf + ";\n "
23
+ return r
24
+
25
+ def _build_lpf (named_sc , named_pc ):
26
+ r = "BLOCK RESETPATHS;\n "
27
+ r += "BLOCK ASYNCPATHS;\n "
28
+ for sig , pins , others , resname in named_sc :
29
+ if len (pins ) > 1 :
30
+ for i , p in enumerate (pins ):
31
+ r += _format_lpf (sig + "[" + str (i ) + "]" , p , others , resname )
32
+ else :
33
+ r += _format_lpf (sig , pins [0 ], others , resname )
34
+ if named_pc :
35
+ r += "\n " + "\n \n " .join (named_pc )
36
+ return r
37
+
38
+ def _build_files (device , sources , vincpaths , build_name ):
39
+ tcl = []
40
+ tcl .append ("prj_project new -name \" %s\" -impl \" implementation\" -dev %s -synthesis \" synplify\" " % (build_name , device ))
41
+ for filename , language in sources :
42
+ tcl .append ("prj_src add \" " + filename .replace ("\\ " , "/" ) + "\" " )
43
+ tcl .append ("prj_run Synthesis -impl implementation -forceOne" )
44
+ tcl .append ("prj_run Translate -impl implementation" )
45
+ tcl .append ("prj_run Map -impl implementation" )
46
+ tcl .append ("prj_run PAR -impl implementation" )
47
+ tcl .append ("prj_run Export -impl implementation -task Bitgen" )
48
+ tools .write_to_file (build_name + ".tcl" , "\n " .join (tcl ))
49
+
50
+ def _run_diamond (build_name , source , ver = None ):
51
+ if sys .platform == "win32" or sys .platform == "cygwin" :
52
+ build_script_contents = "REM Autogenerated by mibuild\n "
53
+ build_script_contents = "pnmainc " + build_name + ".tcl\n "
54
+ build_script_file = "build_" + build_name + ".bat"
55
+ tools .write_to_file (build_script_file , build_script_contents )
56
+ r = subprocess .call ([build_script_file ])
57
+ shutil .copy (os .path .join ("implementation" , build_name + "_implementation.bit" ), build_name + ".bit" )
58
+ else :
59
+ raise NotImplementedError ()
60
+
61
+ if r != 0 :
62
+ raise OSError ("Subprocess failed" )
63
+
64
+ class LatticeDiamondPlatform (GenericPlatform ):
65
+ bitstream_ext = ".bit"
66
+ def build (self , fragment , build_dir = "build" , build_name = "top" ,
67
+ diamond_path = "/opt/Diamond" , run = True ):
68
+ tools .mkdir_noerror (build_dir )
69
+ os .chdir (build_dir )
70
+
71
+ if not isinstance (fragment , _Fragment ):
72
+ fragment = fragment .get_fragment ()
73
+ self .finalize (fragment )
74
+
75
+ v_src , vns = self .get_verilog (fragment )
76
+ named_sc , named_pc = self .resolve_signals (vns )
77
+ v_file = build_name + ".v"
78
+ tools .write_to_file (v_file , v_src )
79
+ sources = self .sources + [(v_file , "verilog" )]
80
+ _build_files (self .device , sources , self .verilog_include_paths , build_name )
81
+
82
+ tools .write_to_file (build_name + ".lpf" , _build_lpf (named_sc , named_pc ))
83
+
84
+ if run :
85
+ _run_diamond (build_name , diamond_path )
86
+
87
+ os .chdir (".." )
88
+
89
+ return vns
90
+
91
+ def add_period_constraint (self , clk , period ):
92
+ # TODO: handle differential clk
93
+ self .add_platform_command ("""FREQUENCY PORT "{clk}" {freq} MHz;""" .format (freq = str (float (1 / period )* 1000 ), clk = "{clk}" ), clk = clk )
0 commit comments