@@ -351,11 +351,14 @@ def _remove_unused_wires(block, keep_inputs=True):
351
351
#
352
352
353
353
354
- def synthesize (update_working_block = True , block = None ):
354
+ def synthesize (update_working_block = True , merge_io_vectors = True , block = None ):
355
355
""" Lower the design to just single-bit "and", "or", "xor", and "not" gates.
356
356
357
- :param update_working_block: Boolean specifying if working block update
358
- :param block: The block you want to synthesize
357
+ :param update_working_block: Boolean specifying if working block should
358
+ be set to the newly synthesized block.
359
+ :param merge_io_wirevectors: if False, turn all N-bit IO wirevectors
360
+ into N 1-bit IO wirevectors (i.e. don't maintain interface).
361
+ :param block: The block you want to synthesize.
359
362
:return: The newly synthesized block (of type PostSynthesisBlock).
360
363
361
364
Takes as input a block (default to working block) and creates a new
@@ -368,7 +371,10 @@ def synthesize(update_working_block=True, block=None):
368
371
the individual bits and memories (read and write ports) which
369
372
require the reassembly and disassembly of the wirevectors immediately
370
373
before and after. These are the only two places where 'c' and 's' ops
371
- should exist.
374
+ should exist. If merge_io_vectors is False, then these individual
375
+ bits are not reassembled and disassembled before and after, and so no
376
+ 'c' and 's' ops will exist. Instead, they will be named <name>[n],
377
+ where n is the bit number of original wire to which it corresponds.
372
378
373
379
The block that results from synthesis is actually of type
374
380
"PostSynthesisBlock" which contains a mapping from the original inputs
@@ -384,7 +390,9 @@ def synthesize(update_working_block=True, block=None):
384
390
385
391
block_out = PostSynthBlock ()
386
392
# resulting block should only have one of a restricted set of net ops
387
- block_out .legal_ops = set ('~&|^nrwcsm@' )
393
+ block_out .legal_ops = set ('~&|^nrwm@' )
394
+ if merge_io_vectors :
395
+ block_out .legal_ops .update (set ('cs' ))
388
396
wirevector_map = {} # map from (vector,index) -> new_wire
389
397
390
398
with set_working_block (block_out , no_sanity_check = True ):
@@ -399,6 +407,11 @@ def synthesize(update_working_block=True, block=None):
399
407
('>' , _basic_gt )]:
400
408
net_transform (_replace_op (op , fun ), block_in )
401
409
410
+ # This is a map from the cloned io wirevector created in copy_block,
411
+ # to the original io wirevector found in block_pre. We use it to create
412
+ # the block_out.io_map that is returned to the user.
413
+ orig_io_map = {temp : orig for orig , temp in block_in .io_map .items ()}
414
+
402
415
# Next, create all of the new wires for the new block
403
416
# from the original wires and store them in the wirevector_map
404
417
# for reference.
@@ -409,21 +422,31 @@ def synthesize(update_working_block=True, block=None):
409
422
new_val = (wirevector .val >> i ) & 0x1
410
423
new_wirevector = Const (bitwidth = 1 , val = new_val )
411
424
elif isinstance (wirevector , (Input , Output )):
412
- new_wirevector = WireVector (name = "tmp_" + new_name , bitwidth = 1 )
425
+ if merge_io_vectors :
426
+ new_wirevector = WireVector (name = "tmp_" + new_name , bitwidth = 1 )
427
+ else :
428
+ # Creating N 1-bit io wires for a given single N-bit io wire.
429
+ new_name = wirevector .name
430
+ if len (wirevector ) > 1 :
431
+ new_name += '[' + str (i ) + ']'
432
+ new_wirevector = wirevector .__class__ (name = new_name , bitwidth = 1 )
433
+ block_out .io_map [orig_io_map [wirevector ]] = new_wirevector
413
434
else :
414
435
new_wirevector = wirevector .__class__ (name = new_name , bitwidth = 1 )
415
436
wirevector_map [(wirevector , i )] = new_wirevector
416
437
417
438
# Now connect up the inputs and outputs to maintain the interface
418
- for wirevector in block_in .wirevector_subset (Input ):
419
- input_vector = Input (name = wirevector .name , bitwidth = len (wirevector ))
420
- for i in range (len (wirevector )):
421
- wirevector_map [(wirevector , i )] <<= input_vector [i ]
422
- for wirevector in block_in .wirevector_subset (Output ):
423
- output_vector = Output (name = wirevector .name , bitwidth = len (wirevector ))
424
- output_bits = [wirevector_map [(wirevector , i )]
425
- for i in range (len (output_vector ))]
426
- output_vector <<= concat_list (output_bits )
439
+ if merge_io_vectors :
440
+ for wirevector in block_in .wirevector_subset (Input ):
441
+ input_vector = Input (name = wirevector .name , bitwidth = len (wirevector ))
442
+ for i in range (len (wirevector )):
443
+ wirevector_map [(wirevector , i )] <<= input_vector [i ]
444
+ block_out .io_map [orig_io_map [wirevector ]] = [input_vector ]
445
+ for wirevector in block_in .wirevector_subset (Output ):
446
+ output_vector = Output (name = wirevector .name , bitwidth = len (wirevector ))
447
+ output_bits = [wirevector_map [(wirevector , i )] for i in range (len (output_vector ))]
448
+ output_vector <<= concat_list (output_bits )
449
+ block_out .io_map [orig_io_map [wirevector ]] = [output_vector ]
427
450
428
451
# Now that we have all the wires built and mapped, walk all the blocks
429
452
# and map the logic to the equivalent set of primitives in the system
0 commit comments