<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def synthesize(update_working_block=True, block=None):
 """ Lower the design to just single-bit "and", "or", and "not" gates. :param update_working_block: Boolean specifying if working block update :param block: The block you want to synthesize :return: The newly synthesized block (of type PostSynthesisBlock). Takes as input a block (default to working block) and creates a new block which is identical in function but uses only single bit gates and excludes many of the more complicated primitives. The new block should consist *almost* exclusively of the combination elements of w, &, |, ^, and ~ and sequential elements of registers (which are one bit as well). The two exceptions are for inputs/outputs (so that we can keep the same interface) which are immediately broken down into the individual bits and memories. Memories (read and write ports) which require the reassembly and disassembly of the wirevectors immediately before and after. There arethe only two places where 'c' and 's' ops should exist. The block that results from synthesis is actually of type "PostSynthesisBlock" which contains a mapping from the original inputs and outputs to the inputs and outputs of this block. This is used during simulation to map the input/outputs so that the same testbench can be used both pre and post synthesis (see documentation for Simulation for more details). """


    block_pre = working_block(block)
    block_pre.sanity_check()  # before going further, make sure that pressynth is valid
    block_in = copy_block(block_pre, update_working_block=False)

    block_out = PostSynthBlock()
    # resulting block should only have one of a restricted set of net ops
    block_out.legal_ops = set('~&|^nrwcsm@')
    wirevector_map = {}  # map from (vector,index) -> new_wire

    with set_working_block(block_out, no_sanity_check=True):
        # First, replace advanced operators with simpler ones
        for op, fun in [
                ('*', _basic_mult),
                ('+', _basic_add),
                ('-', _basic_sub),
                ('x', _basic_select),
                ('=', _basic_eq),
                ('<', _basic_lt),
                ('>', _basic_gt)]:
            net_transform(_replace_op(op, fun), block_in)

        # Next, create all of the new wires for the new block
        # from the original wires and store them in the wirevector_map
        # for reference.
        for wirevector in block_in.wirevector_subset():
            for i in range(len(wirevector)):
                new_name = '_'.join((wirevector.name, 'synth', str(i)))
                if isinstance(wirevector, Const):
                    new_val = (wirevector.val >> i) & 0x1
                    new_wirevector = Const(bitwidth=1, val=new_val)
                elif isinstance(wirevector, (Input, Output)):
                    new_wirevector = WireVector(name="tmp_" + new_name, bitwidth=1)
                else:
                    new_wirevector = wirevector.__class__(name=new_name, bitwidth=1)
                wirevector_map[(wirevector, i)] = new_wirevector

        # Now connect up the inputs and outputs to maintain the interface
        for wirevector in block_in.wirevector_subset(Input):
            input_vector = Input(name=wirevector.name, bitwidth=len(wirevector))
            for i in range(len(wirevector)):
                wirevector_map[(wirevector, i)] <<= input_vector[i]
        for wirevector in block_in.wirevector_subset(Output):
            output_vector = Output(name=wirevector.name, bitwidth=len(wirevector))
            # the "reversed" is needed because most significant bit comes first in concat
            output_bits = [wirevector_map[(wirevector, i)]
                           for i in range(len(output_vector))]
            output_vector <<= concat_list(output_bits)

        # Now that we have all the wires built and mapped, walk all the blocks
        # and map the logic to the equivalent set of primitives in the system
        out_mems = block_out.mem_map  # dictionary: PreSynth Map -> PostSynth Map
        for net in block_in.logic:
            _decompose(net, wirevector_map, out_mems, block_out)

    if update_working_block:
        set_working_block(block_out, no_sanity_check=True)
    return block_out