def voltage_deductions(in_pins, out_pins, logic_function, active_pin, netlist_pins): """ Setup the Supply voltage and Logic Signal as per the logic function """ in_pins = in_pins.replace(active_pin, '') + ' ' + active_pin pos_unate, pins_voltages = truths.Truths(in_pins.split(), [logic_function]).truth_table() # Setting up Power Supplies Voltages power_supplies = ['VPWR', 'VDD', 'VPB'] gnd_supplies = ['VGND', 'VNB', 'VSS'] power_str = '\n'.join([ f'V{net} {net} 0 DC {VDD}' for net in power_supplies if net in netlist_pins ]) gnd_str = '\n'.join([ f'V{net} {net} 0 DC 0' for net in gnd_supplies if net in netlist_pins ]) # Setting Up Signal Voltages active_pin_voltage = f'V{active_pin} {active_pin} 0 PULSE(0 {VDD} 0 0.01n 0.01n 50ns 100ns)' other_pins_voltage = [] for net, logic in pins_voltages.items(): if logic == 0: other_pins_voltage.append(f'V{net} {net} 0 DC 0') elif logic == 1: other_pins_voltage.append(f'V{net} {net} 0 DC {VDD}') other_pins_vol_str = '\n'.join(other_pins_voltage) power_supplies = power_str + '\n' + gnd_str signal_supplies = active_pin_voltage + '\n' + other_pins_vol_str return power_supplies, signal_supplies, pos_unate
def ngpost_timing(act_out_pin, func, signal_source, active_pin): """ Generate ngspice control commands for timing_harness""" in_pins = ' '.join(input_pins).replace(active_pin, '') + ' ' + active_pin working_func = convert_logical(func) pos_unate, pins_voltages = truths.Truths(in_pins.split(), [working_func]).truth_table() extra_alter_source = [] missing_voltage_source = [] for in_pin in pins_voltages.keys(): if pins_voltages[in_pin] == 1: voltage = power_volts else: voltage = 0 if in_pin in signal_sources.keys(): extra_alter_source.append( f'alter @{signal_sources[in_pin]}[PWL] = [ 0 {voltage} ]') else: missing_voltage_source.append(f'V{in_pin} {in_pin} 0 DC 0') extra_alter_source_str = '\n'.join(extra_alter_source) # TODO: Shift this text based template to Jinja Templates if necessary control_str = \ f"""let run = 0 \n shell rm {working_folder}/input_transition.txt shell rm {working_folder}/cell_fall.txt shell rm {working_folder}/cell_rise.txt shell rm {working_folder}/fall_transition.txt shell rm {working_folder}/rise_transition.txt foreach in_delay {input_transition_time} * Initiating Text Files in folder data echo "input_transition:$in_delay" >> {working_folder}/input_transition.txt echo "input_transition:$in_delay" >> {working_folder}/cell_fall.txt echo "input_transition:$in_delay" >> {working_folder}/cell_rise.txt echo "input_transition:$in_delay" >> {working_folder}/fall_transition.txt echo "input_transition:$in_delay" >> {working_folder}/rise_transition.txt * 1.666 to match the slew rate let actual_rtime = $in_delay*1.666 * Input Vector - Load Cap values(index2) foreach out_cap {output_caps} reset * Changing the V2 Supply Rise time as per the Input Rise Time vector alter @{signal_source}[pulse] = [ 0 {power_volts} 0 $&actual_rtime $&actual_rtime 50ns 100ns ] {extra_alter_source_str} * Changing the C1 value as per the foreach list alter CLOAD $out_cap tran 0.01n 300ns run reset * Verification of INPUT RISE TIME meas tran ts1 when v({active_pin})={float(power_volts)*0.8} RISE=1 meas tran ts2 when v({active_pin})={float(power_volts)*0.2} RISE=1 meas tran ts3 when v({active_pin})={float(power_volts)*0.8} FALL=1 meas tran ts4 when v({active_pin})={float(power_volts)*0.2} FALL=1 let RISE_IN_SLEW = (ts1-ts2)/{time_unit} let FALL_IN_SLEW = (ts4-ts3)/{time_unit} echo "actual_rise_slew:$&RISE_IN_SLEW" >> {working_folder}/input_transition.txt echo "actual_fall_slew:$&FALL_IN_SLEW" >> {working_folder}/input_transition.txt print run * Measuring Cell Fall Time @ 50% of VDD({float(power_volts)}V) meas tran tinfall when v({active_pin})={float(power_volts)*0.5} FALL=1 meas tran tofall when v({act_out_pin})={float(power_volts)*0.5} FALL=1 let cfall = (tofall-tinfall)/{time_unit} if abs(cfall)>20 meas tran tinfall when v({active_pin})={float(power_volts)*0.5} Rise=1 meas tran tofall when v({act_out_pin})={float(power_volts)*0.5} FALL=1 let cfall = abs(tofall-tinfall)/{time_unit} end print cfall echo "out_cap:$out_cap:cell_fall:$&cfall" >> {working_folder}/cell_fall.txt * Measuring Cell Rise Time @ 50% of VDD({float(power_volts)}V) meas tran tinrise when v({active_pin})={float(power_volts)*0.5} RISE=1 meas tran torise when v({act_out_pin})={float(power_volts)*0.5} RISE=1 let crise = (torise-tinrise)/{time_unit} if abs(crise)>20 meas tran tinrise when v({active_pin})={float(power_volts)*0.5} FALL=1 meas tran torise when v({act_out_pin})={float(power_volts)*0.5} RISE=1 let crise = abs(tinrise-torise)/{time_unit} end print crise echo "out_cap:$out_cap:cell_rise:$&crise" >> {working_folder}/cell_rise.txt * Measuring Fall transition Time @ 80-20% of VDD({float(power_volts)}V) meas tran ft1 when v({act_out_pin})={float(power_volts)*0.8} FALL=2 meas tran ft2 when v({act_out_pin})={float(power_volts)*0.2} FALL=2 let fall_tran = (ft2-ft1)/{time_unit} print fall_tran echo "out_cap:$out_cap:fall_transition:$&fall_tran" >> {working_folder}/fall_transition.txt * Measuring Rise transition Time @ 20-80% of VDD({float(power_volts)}V) meas tran rt1 when v({act_out_pin})={float(power_volts)*0.8} RISE=2 meas tran rt2 when v({act_out_pin})={float(power_volts)*0.2} RISE=2 let rise_tran = ((rt1-rt2)/{time_unit}) print rise_tran echo "out_cap:$out_cap:rise_transition:$&rise_tran" >> {working_folder}/rise_transition.txt let run = run + 1 * plot a y end end""" return control_str