@@ -127,7 +127,7 @@ def input_from_blif(blif, block=None, merge_io_vectors=True, clock_name='clk', t
127
127
if isinstance (blif , six .string_types ):
128
128
blif_string = blif
129
129
else :
130
- raise PyrtlError ('input_blif expecting either open file or string' )
130
+ raise PyrtlError ('input_from_blif expecting either open file or string' )
131
131
132
132
def SKeyword (x ):
133
133
return Suppress (Keyword (x ))
@@ -947,3 +947,111 @@ def output_to_firrtl(open_file, rom_blocks=None, block=None):
947
947
pass
948
948
949
949
return 0
950
+
951
+ # -----------------------------------------------------------------
952
+ # __ __ __ __ ___ __
953
+ # | /__` / /\ /__` |__) |__ |\ | / |__|
954
+ # | .__/ \__ /~~\ .__/ |__) |___ | \| \__ | |
955
+
956
+
957
+ def input_from_iscas_bench (bench , block = None ):
958
+ ''' Import an ISCAS .bench file
959
+
960
+ :param file bench: an open ISCAS .bench file to read
961
+ :param block: block to add the imported logic (defaults to current working block)
962
+ '''
963
+
964
+ import pyparsing
965
+ import six
966
+ from pyparsing import (Word , Literal , OneOrMore , ZeroOrMore , Suppress , Group , Keyword , oneOf )
967
+
968
+ block = working_block (block )
969
+
970
+ try :
971
+ bench_string = bench .read ()
972
+ except AttributeError :
973
+ if isinstance (bench , six .string_types ):
974
+ bench_string = bench
975
+ else :
976
+ raise PyrtlError ('input_from_bench expecting either open file or string' )
977
+
978
+ def SKeyword (x ):
979
+ return Suppress (Keyword (x ))
980
+
981
+ def SLiteral (x ):
982
+ return Suppress (Literal (x ))
983
+
984
+ # NOTE: The acceptable signal characters are based on viewing the I/O names
985
+ # in the available ISCAS benchmark files, and may not be complete.
986
+ signal_start = pyparsing .alphas + pyparsing .nums + '$:[]_<>\\ /?'
987
+ signal_middle = pyparsing .alphas + pyparsing .nums + '$:[]_<>\\ /.?-'
988
+ signal_id = Word (signal_start , signal_middle )
989
+
990
+ gate_names = "AND OR NAND NOR XOR NOT BUFF DFF"
991
+
992
+ src_list = Group (signal_id + ZeroOrMore (SLiteral ("," ) + signal_id ))("src_list" )
993
+ net_def = Group (signal_id ("dst" ) + SLiteral ("=" ) + oneOf (gate_names )("gate" )
994
+ + SLiteral ("(" ) + src_list + SLiteral (")" ))("net_def" )
995
+
996
+ input_def = Group (SKeyword ("INPUT" ) + SLiteral ("(" )
997
+ + signal_id + SLiteral (")" ))("input_def" )
998
+ output_def = Group (SKeyword ("OUTPUT" ) + SLiteral ("(" )
999
+ + signal_id + SLiteral (")" ))("output_def" )
1000
+ command_def = input_def | output_def | net_def
1001
+
1002
+ commands = OneOrMore (command_def )("command_list" )
1003
+ parser = commands .ignore (pyparsing .pythonStyleComment )
1004
+
1005
+ # Begin actually reading and parsing the BENCH file
1006
+ result = parser .parseString (bench_string , parseAll = True )
1007
+
1008
+ output_to_internal = {} # dict: name -> wire
1009
+
1010
+ def twire (name ):
1011
+ """ Find or make wire named 'name' and return it. """
1012
+ w = output_to_internal .get (name )
1013
+ if w is None :
1014
+ w = block .wirevector_by_name .get (name )
1015
+ if w is None :
1016
+ w = WireVector (bitwidth = 1 , name = name )
1017
+ return w
1018
+
1019
+ for cmd in result ["command_list" ]:
1020
+ if cmd .getName () == "input_def" :
1021
+ _wire_in = Input (bitwidth = 1 , name = str (cmd [0 ]), block = block )
1022
+ elif cmd .getName () == "output_def" :
1023
+ # Create internal wire for indirection, since Outputs can't be inputs to nets in PyRTL
1024
+ wire_internal = WireVector (bitwidth = 1 , block = block )
1025
+ wire_out = Output (bitwidth = 1 , name = str (cmd [0 ]), block = block )
1026
+ wire_out <<= wire_internal
1027
+ output_to_internal [cmd [0 ]] = wire_internal
1028
+ elif cmd .getName () == "net_def" :
1029
+ srcs = cmd ["src_list" ]
1030
+ if cmd ["gate" ] == "AND" :
1031
+ dst_wire = twire (cmd ["dst" ])
1032
+ dst_wire <<= twire (srcs [0 ]) & twire (srcs [1 ])
1033
+ elif cmd ["gate" ] == "OR" :
1034
+ dst_wire = twire (cmd ["dst" ])
1035
+ dst_wire <<= twire (srcs [0 ]) | twire (srcs [1 ])
1036
+ elif cmd ["gate" ] == "NAND" :
1037
+ dst_wire = twire (cmd ["dst" ])
1038
+ dst_wire <<= twire (srcs [0 ]).nand (twire (srcs [1 ]))
1039
+ elif cmd ["gate" ] == "NOR" :
1040
+ dst_wire = twire (cmd ["dst" ])
1041
+ dst_wire <<= ~ (twire (srcs [0 ]) | twire (srcs [1 ]))
1042
+ elif cmd ["gate" ] == "XOR" :
1043
+ dst_wire = twire (cmd ["dst" ])
1044
+ dst_wire <<= twire (srcs [0 ]) ^ twire (srcs [1 ])
1045
+ elif cmd ["gate" ] == "NOT" :
1046
+ dst_wire = twire (cmd ["dst" ])
1047
+ dst_wire <<= ~ twire (srcs [0 ])
1048
+ elif cmd ["gate" ] == "BUFF" :
1049
+ dst_wire = twire (cmd ["dst" ])
1050
+ dst_wire <<= twire (srcs [0 ])
1051
+ elif cmd ["gate" ] == "DFF" :
1052
+ dst_wire = twire (cmd ["dst" ])
1053
+ reg = Register (bitwidth = 1 )
1054
+ reg .next <<= twire (srcs [0 ])
1055
+ dst_wire <<= reg
1056
+ else :
1057
+ raise PyrtlError ("Unexpected gate {%s}" % cmd ["gate" ])
0 commit comments