blob: 71b04d897ce12626d0d9d1544caa4d9bb2800ff2 [file] [log] [blame]
#!/usr/bin/env python
############################### blif_splicer.py ################################
#
# Generate the k largest circuits (by total # of logic blocks or occurrences
# of '.names') which can be formed by concatenating n of the MCNC 20 circuits.
# Gives an error for circuits with multiple .model sections.
#
# Author: Michael Wainberg
################################### Settings ###################################
k = 10
n = 2
blifdir = "../benchmarks/blif"
################################################################################
import os
import sys
import glob
import itertools
os.chdir(blifdir)
# Get the name of each circuit (without the '.blif') and its # of logic blocks
circuits = []
for filename in glob.glob('*.blif'):
if '+' in filename:
continue # don't use outputs from previous script runs as inputs
with open(filename) as infile:
name = os.path.splitext(filename)[0] # remove '.blif'
circuits.append((name, infile.read().count('.names')))
# Iterate over the first k combinations of n circuits in decreasing order,
# sorted by the total number of logic blocks, and stitch them together.
# Note: this could be optimized further by storing the processed version
# of each circuit after it is read in for the first time, since the largest
# circuits will likely be reused often.
nonNetChars = '0123456789\\-\n' # a valid net name can't use only these
for tupleIndex, nTuple in enumerate(sorted(itertools.combinations(circuits, n),
key=lambda item: sum(circuit[1] for circuit in item), reverse=True)):
# Parse each input blif into the following strings, which represent
# different sections of the output file.
sections = ['.inputs ', '.outputs ', '']
for circuitIndex, circuit in enumerate(nTuple):
name = circuit[0]
sectionNumber = 0 # 0 = .inputs, 1 = .outputs, 2 = body
modelFlag = False
with open(name + '.blif') as infile:
# After each circuit, replace the last newline of .inputs and
# .outputs lines with a line continuation '\' then a newline.
if circuitIndex > 0:
sections[0] = sections[0][:-1] + ' \\\n'
sections[1] = sections[1][:-1] + ' \\\n'
for line in infile:
if not line or line[0] == '\n':
continue # empty line
if line[0] == '.':
if line[1] == 'm': # .model
if modelFlag:
sys.exit('Multiple .model sections in circuit ' +
name + ': aborting')
modelFlag = True
continue
if line[1] == 'e': # .end
continue
split = line.split(' ', 1)
if line[1] == 'o': # .outputs
sectionNumber = 1
elif line[1] != 'i': # .inputs
sectionNumber = 2
sections[2] += split[0] + ' ' # copy 1st word
line = split[1] # skip 1st word
# Add this line to the appropriate section, after mangling
# each net name (one which does not contain only nonNetChars
# and is not 're') with the name of the circuit.
sections[sectionNumber] += ' '.join(name + '_' + word if word
!= 're' and any(char not in nonNetChars for char in word)
else word for word in line.split(' '))
# Write the concatenation of all sections to the output file.
# The format of the output filename is 'file1+file2+...+fileN.blif'
filename = '+'.join(circuit[0] for circuit in nTuple) + '.blif'
with open(filename, 'wb') as outfile:
outfile.write('.model top\n' + ''.join(sections) + '.end\n')
print 'Created ' + filename + '...'
if tupleIndex == k-1:
break