41
41
import readline
42
42
import logging
43
43
import tkinter as tk
44
+ from pathlib import PurePosixPath , PureWindowsPath
45
+ import platform
44
46
readline .set_completer_delims (' \t \n ' )
45
47
histfile = ""
46
48
histfile_size = 1000
@@ -69,6 +71,16 @@ def create_project(project_dir, type: Literal["verilog", "vhdl"] = "verilog"):
69
71
shutil .copytree (f"{ fabulousRoot } /fabric_files/FABulous_project_template_{ type } /" ,
70
72
f"{ project_dir } /" , dirs_exist_ok = True )
71
73
74
+ def get_path (path ):
75
+ system = platform .system ()
76
+ # Darwin corresponds to MacOS, which also uses POSIX-style paths
77
+ if system == "Linux" or system == "Darwin" :
78
+ return PurePosixPath (path )
79
+ elif system == "Windows" :
80
+ return PureWindowsPath (path )
81
+ else :
82
+ raise NotImplementedError (f"Unsupported operating system: { system } " )
83
+
72
84
class PlaceAndRouteError (Exception ):
73
85
"""An exception to be thrown when place and route fails."""
74
86
@@ -625,7 +637,7 @@ def do_hls_create_project(self):
625
637
with open (f"{ self .projectDir } /HLS/config.tcl" , "w" ) as f :
626
638
f .write (f"source /root/legup-4.0/examples/legup.tcl\n " )
627
639
628
- name = self .projectDir . split ( '/' )[ - 1 ]
640
+ name = get_path ( self .projectDir ). name
629
641
with open (f"{ self .projectDir } /HLS/Makefile" , "w" ) as f :
630
642
f .write (f"NAME = { name } \n " )
631
643
f .write (
@@ -644,7 +656,7 @@ def do_hls_create_project(self):
644
656
os .chmod (f"./HLS/{ name } .c" , 0o666 )
645
657
646
658
def do_hls_generate_verilog (self ):
647
- name = self .projectDir . split ( '/' )[ - 1 ]
659
+ name = get_path ( self .projectDir ). name
648
660
# create folder for the generated file
649
661
if not os .path .exists (f"./HLS/generated_file" ):
650
662
os .mkdir (f"{ name } /generated_file" )
@@ -719,18 +731,11 @@ def do_synthesis_npnr(self, args):
719
731
raise TypeError (f"do_place_and_route_npnr takes exactly one argument ({ len (args )} given)" )
720
732
logger .info (
721
733
f"Running synthesis that targeting Nextpnr with design { args [0 ]} " )
722
- path , verilog_file = os .path .split (args [0 ])
723
- if len (verilog_file .split ('.' )) != 2 :
724
- logger .error (
725
- """
726
- No verilog file provided.
727
- Usage: synthesis_npnr <top_module_file>
728
- """ )
729
- return
730
-
731
- top_module_name , file_ending = verilog_file .split ('.' )
732
-
733
- if file_ending != "v" :
734
+ path = get_path (args [0 ])
735
+ parent = path .parent
736
+ verilog_file = path .name
737
+ top_module_name = path .stem
738
+ if path .suffix != ".v" :
734
739
logger .error (
735
740
"""
736
741
No verilog file provided.
@@ -740,9 +745,9 @@ def do_synthesis_npnr(self, args):
740
745
741
746
json_file = top_module_name + ".json"
742
747
runCmd = ["yosys" ,
743
- "-p" , f"synth_fabulous -top top_wrapper -json { self .projectDir } /{ path } /{ json_file } " ,
744
- f"{ self .projectDir } /{ path } /{ verilog_file } " ,
745
- f"{ self .projectDir } /{ path } /top_wrapper.v" , ]
748
+ "-p" , f"synth_fabulous -top top_wrapper -json { self .projectDir } /{ parent } /{ json_file } " ,
749
+ f"{ self .projectDir } /{ parent } /{ verilog_file } " ,
750
+ f"{ self .projectDir } /{ parent } /top_wrapper.v" , ]
746
751
try :
747
752
sp .run (runCmd , check = True )
748
753
logger .info ("Synthesis completed" )
@@ -761,18 +766,12 @@ def do_synthesis_blif(self, args):
761
766
raise TypeError (f"do_place_and_route_npnr takes exactly one argument ({ len (args )} given)" )
762
767
logger .info (
763
768
f"Running synthesis that targeting BLIF with design { args [0 ]} " )
764
- path , verilog_file = os .path .split (args [0 ])
765
- if len (verilog_file .split ('.' )) != 2 :
766
- logger .error (
767
- """
768
- No verilog file provided.
769
- Usage: synthesis_blif <top_module_file>
770
- """ )
771
- return
772
-
773
- top_module_name , file_ending = verilog_file .split ('.' )
774
769
775
- if file_ending != "v" :
770
+ path = get_path (args [0 ])
771
+ parent = path .parent
772
+ verilog_file = path .name
773
+ top_module_name = path .stem
774
+ if path .suffix != ".v" :
776
775
logger .error (
777
776
"""
778
777
No verilog file provided.
@@ -782,9 +781,9 @@ def do_synthesis_blif(self, args):
782
781
783
782
blif_file = top_module_name + ".blif"
784
783
runCmd = ["yosys" ,
785
- "-p" , f"synth_fabulous -top top_wrapper -blif { self .projectDir } /{ path } /{ blif_file } -vpr" ,
786
- f"{ self .projectDir } /{ path } /{ verilog_file } " ,
787
- f"{ self .projectDir } /{ path } /top_wrapper.v" , ]
784
+ "-p" , f"synth_fabulous -top top_wrapper -blif { self .projectDir } /{ parent } /{ blif_file } -vpr" ,
785
+ f"{ self .projectDir } /{ parent } /{ verilog_file } " ,
786
+ f"{ self .projectDir } /{ parent } /top_wrapper.v" , ]
788
787
try :
789
788
sp .run (runCmd , check = True )
790
789
logger .info ("Synthesis completed." )
@@ -807,46 +806,41 @@ def do_place_and_route_npnr(self, args):
807
806
raise TypeError (f"do_place_and_route_npnr takes exactly one argument ({ len (args )} given)" )
808
807
logger .info (
809
808
f"Running Placement and Routing with Nextpnr for design { args [0 ]} " )
810
- path , json_file = os .path .split (args [0 ])
811
- if len (json_file .split ('.' )) != 2 :
812
- logger .error (
813
- """
814
- No json file provided.
815
- Usage: place_and_route_npnr <json_file> (<json_file> is generated by Yosys. Generate it by running synthesis_npnr.)
816
- """ )
817
- return
809
+ path = get_path (args [0 ])
810
+ parent = path .parent
811
+ json_file = path .name
812
+ top_module_name = path .stem
818
813
819
- top_module_name , file_ending = json_file .split ('.' )
820
- if file_ending != "json" :
814
+ if path .suffix != ".json" :
821
815
logger .error (
822
816
"""
823
817
No json file provided.
824
818
Usage: place_and_route_npnr <json_file> (<json_file> is generated by Yosys. Generate it by running synthesis_npnr.)
825
819
""" )
826
820
return
821
+
827
822
fasm_file = top_module_name + ".fasm"
828
823
log_file = top_module_name + "_npnr_log.txt"
829
824
830
- if path == "" :
831
- path = "."
825
+ if parent == "" :
826
+ parent = "."
832
827
833
828
if not os .path .exists (f"{ self .projectDir } /.FABulous/pips.txt" ) or not os .path .exists (
834
829
f"{ self .projectDir } /.FABulous/bel.txt" ):
835
830
logger .error (
836
831
"Pips and Bel files are not found, please run model_gen_npnr first" )
837
832
raise FileNotFoundError
838
833
839
- print (self .projectDir )
840
- if os .path .exists (f"{ self .projectDir } /{ path } " ):
834
+ if os .path .exists (f"{ self .projectDir } /{ parent } " ):
841
835
# TODO rewriting the fab_arch script so no need to copy file for work around
842
- if f"{ json_file } " in os .listdir (f"{ self .projectDir } /{ path } " ):
836
+ if f"{ json_file } " in os .listdir (f"{ self .projectDir } /{ parent } " ):
843
837
runCmd = [f"FAB_ROOT={ self .projectDir } " ,
844
838
f"nextpnr-generic" ,
845
839
"--uarch" , "fabulous" ,
846
- "--json" , f"{ self .projectDir } /{ path } /{ json_file } " ,
847
- "-o" , f"fasm={ self .projectDir } /{ path } /{ fasm_file } " ,
840
+ "--json" , f"{ self .projectDir } /{ parent } /{ json_file } " ,
841
+ "-o" , f"fasm={ self .projectDir } /{ parent } /{ fasm_file } " ,
848
842
"--verbose" ,
849
- "--log" , f"{ self .projectDir } /{ path } /{ log_file } " ]
843
+ "--log" , f"{ self .projectDir } /{ parent } /{ log_file } " ]
850
844
try :
851
845
sp .run (" " .join (runCmd ), stdout = sys .stdout ,
852
846
stderr = sp .STDOUT , check = True , shell = True )
@@ -857,13 +851,13 @@ def do_place_and_route_npnr(self, args):
857
851
858
852
else :
859
853
logger .error (
860
- f"Cannot find file \" { json_file } \" in path \" ./{ path } /\" , which is generated by running Yosys with Nextpnr backend (e.g. synthesis_npnr)." )
854
+ f"Cannot find file \" { json_file } \" in path \" ./{ parent } /\" , which is generated by running Yosys with Nextpnr backend (e.g. synthesis_npnr)." )
861
855
raise FileNotFoundError
862
856
863
857
logger .info ("Placement and Routing completed" )
864
858
else :
865
859
logger .error (
866
- f"Directory { self .projectDir } /{ path } does not exist." )
860
+ f"Directory { self .projectDir } /{ parent } does not exist." )
867
861
raise FileNotFoundError
868
862
869
863
def complete_place_and_route_npnr (self , text , * ignored ):
@@ -877,7 +871,8 @@ def do_place_and_route_vpr(self, args):
877
871
raise TypeError (f"do_place_and_route_npnr takes exactly one argument ({ len (args )} given)" )
878
872
logger .info (
879
873
f"Running Placement and Routing with vpr for design { args [0 ]} " )
880
- path , blif_file = os .path .split (args [0 ])
874
+ path = get_path (args [0 ])
875
+ blif_file = path .name
881
876
882
877
if os .path .exists (f"{ self .projectDir } /user_design/{ blif_file } " ):
883
878
if not os .getenv ('VTR_ROOT' ):
@@ -914,18 +909,12 @@ def do_gen_bitStream_binary(self, args):
914
909
if len (args ) != 1 :
915
910
logger .error ("Usage: gen_bitStream_binary <fasm_file>" )
916
911
return
917
- path , fasm_file = os .path .split (args [0 ])
918
- if len (fasm_file .split ('.' )) != 2 :
919
- logger .error (
920
- """
921
- No fasm file provided.
922
- Usage: gen_bitStream_binary <fasm_file>
923
- """ )
924
- return
925
-
926
- top_module_name , file_ending = fasm_file .split ('.' )
912
+ path = get_path (args [0 ])
913
+ parent = path .parent
914
+ fasm_file = path .name
915
+ top_module_name = path .stem
927
916
928
- if file_ending != "fasm" :
917
+ if path . suffix != ". fasm" :
929
918
logger .error (
930
919
"""
931
920
No fasm file provided.
@@ -940,19 +929,19 @@ def do_gen_bitStream_binary(self, args):
940
929
"Cannot find bitStreamSpec.bin file, which is generated by running gen_bitStream_spec" )
941
930
return
942
931
943
- if not os .path .exists (f"{ self .projectDir } /{ path } /{ fasm_file } " ):
932
+ if not os .path .exists (f"{ self .projectDir } /{ parent } /{ fasm_file } " ):
944
933
logger .error (
945
- f"Cannot find { self .projectDir } /{ path } /{ fasm_file } file which is generated by running place_and_route_npnr or place_and_route_vpr. Potentially Place and Route Failed." )
934
+ f"Cannot find { self .projectDir } /{ parent } /{ fasm_file } file which is generated by running place_and_route_npnr or place_and_route_vpr. Potentially Place and Route Failed." )
946
935
return
947
936
948
937
logger .info (
949
- f"Generating Bitstream for design { self .projectDir } /{ args [ 0 ] } " )
950
- logger .info (f"Outputting to { self .projectDir } /{ path } /{ bitstream_file } " )
938
+ f"Generating Bitstream for design { self .projectDir } /{ path } " )
939
+ logger .info (f"Outputting to { self .projectDir } /{ parent } /{ bitstream_file } " )
951
940
runCmd = ["python3" , f"{ fabulousRoot } /fabric_cad/bit_gen.py" ,
952
941
"-genBitstream" ,
953
- f"{ self .projectDir } /{ path } /{ fasm_file } " ,
942
+ f"{ self .projectDir } /{ parent } /{ fasm_file } " ,
954
943
f"{ self .projectDir } /.FABulous/bitStreamSpec.bin" ,
955
- f"{ self .projectDir } /{ path } /{ bitstream_file } " ]
944
+ f"{ self .projectDir } /{ parent } /{ bitstream_file } " ]
956
945
957
946
try :
958
947
sp .run (runCmd , check = True )
@@ -979,37 +968,29 @@ def do_run_FABulous_bitstream(self, *args):
979
968
"Usage: run_FABulous_bitstream <npnr|vpr> <top_module_file>" )
980
969
return
981
970
982
- verilog_file_path = args [1 ]
983
- if len (verilog_file_path .split ('.' )) != 2 :
984
- logger .error (
985
- """
986
- No verilog file provided.
987
- Usage: run_FABulous_bitstream <npnr|vpr> <top_module_file>
988
- """ )
989
- return
990
-
991
- file_ending = verilog_file_path .split ('.' )[1 ]
971
+ verilog_file_path = get_path (args [1 ])
972
+ file_path_no_suffix = verilog_file_path .parent / verilog_file_path .stem
992
973
993
- if file_ending != "v" :
974
+ if verilog_file_path . suffix != ". v" :
994
975
logger .error (
995
976
"""
996
977
No verilog file provided.
997
978
Usage: run_FABulous_bitstream <npnr|vpr> <top_module_file>
998
979
""" )
999
980
return
1000
981
1001
- json_file_path = verilog_file_path . split ( '.' )[ 0 ] + ".json"
1002
- blif_file_path = verilog_file_path . split ( '.' )[ 0 ] + ".blif"
1003
- fasm_file_path = verilog_file_path . split ( '.' )[ 0 ] + ".fasm"
982
+ json_file_path = file_path_no_suffix . with_suffix ( ".json" )
983
+ blif_file_path = file_path_no_suffix . with_suffix ( ".blif" )
984
+ fasm_file_path = file_path_no_suffix . with_suffix ( ".fasm" )
1004
985
1005
986
if args [0 ] == "vpr" :
1006
- self .do_synthesis_blif (verilog_file_path )
1007
- self .do_place_and_route_vpr (blif_file_path )
1008
- self .do_gen_bitStream_binary (fasm_file_path )
987
+ self .do_synthesis_blif (str ( verilog_file_path ) )
988
+ self .do_place_and_route_vpr (str ( blif_file_path ) )
989
+ self .do_gen_bitStream_binary (str ( fasm_file_path ) )
1009
990
elif args [0 ] == "npnr" :
1010
- self .do_synthesis_npnr (verilog_file_path )
1011
- self .do_place_and_route_npnr (json_file_path )
1012
- self .do_gen_bitStream_binary (fasm_file_path )
991
+ self .do_synthesis_npnr (str ( verilog_file_path ) )
992
+ self .do_place_and_route_npnr (str ( json_file_path ) )
993
+ self .do_gen_bitStream_binary (str ( fasm_file_path ) )
1013
994
else :
1014
995
logger .error (
1015
996
"Usage: run_FABulous_bitstream <npnr|vpr> <top_module_file>" )
@@ -1029,21 +1010,22 @@ def do_tcl(self, args):
1029
1010
if len (args ) != 1 :
1030
1011
logger .error ("Usage: tcl <tcl_script>" )
1031
1012
return
1032
- path , name = os .path .split (args [0 ])
1033
- name = name .split ('.' )[0 ]
1034
- if not os .path .exists (args [0 ]):
1013
+ path_str = args [0 ]
1014
+ path = get_path (path_str )
1015
+ name = path .stem
1016
+ if not os .path .exists (path_str ):
1035
1017
logger .error (
1036
- f"Cannot find { args [ 0 ] } " )
1018
+ f"Cannot find { path_str } " )
1037
1019
return
1038
1020
1039
- logger .info (f"Execute TCL script { args [ 0 ] } " )
1021
+ logger .info (f"Execute TCL script { path_str } " )
1040
1022
tcl = tk .Tcl ()
1041
1023
for fun in dir (self .__class__ ):
1042
1024
if fun .startswith ("do_" ):
1043
1025
name = fun .strip ("do_" )
1044
1026
tcl .createcommand (name , getattr (self , fun ))
1045
1027
1046
- tcl .evalfile (args [ 0 ] )
1028
+ tcl .evalfile (path_str )
1047
1029
logger .info ("TCL script executed" )
1048
1030
1049
1031
def complete_tcl (self , text , * ignored ):
0 commit comments