MODULE mod_handle_fmln ; { Created 2-APR-1992 MICHIGAN STATE UNIVERSITY, TRIGGER CONTROL SOFTWARE } { *************************************************************************** } INCLUDE mod_common_global_flags, mod_handle_tracing, mod_def_hardware_tables, mod_handle_registers, mod_common_hard_io, mod_tcs_io_comint_handling, {from the TRICS hardware IO library } mod_tcs_io_cbus_handling ; { *************************************************************************** } EXPORT update_fmln_threshold, {PROCEDURE load 1 threshold with new value} verify_fmln_thresholds, {PROCEDURE verify all 8 thres of 1 FMLN } zero_fmln_thresholds, {PROCEDURE initialize all 8 thresh = 0 GeV} program_fmln_momentum_lookup, {PROCEDURE program fmln Missing Pt lookup } verify_fmln_momentum_lookup ; {PROCEDURE verify fmln Missing Pt lookup } { *************************************************************************** } IMPORT framework_state, {from module MOD_COMMON_GLOBAL_FLAGS } running,{paused,} {from module MOD_COMMON_GLOBAL_FLAGS } status_type, {from module MOD_COMMON_GLOBAL_FLAGS } ok,{io_failure,}error_found, {from module MOD_COMMON_GLOBAL_FLAGS } trace_info,{trace_warn,}trace_error,{from module MOD_HANDLE_TRACING } inline_tracing, {from module MOD_HANDLE_TRACING } handle_trc_inf, {from module MOD_HANDLE_TRACING } handle_trc_err, {from module MOD_HANDLE_TRACING } fmln_card, {from module MOD_DEF_HARDWARE_TABLES } fmln_compute, {from module MOD_DEF_HARDWARE_TABLES } update_register, {from module MOD_HANDLE_REGISTER } examine_register, {from module MOD_HANDLE_REGISTER } cbus_param_list, {from module MOD_COMMON_HARD_IO } eight_bit_0_7, eight_integer_0_7, {from module MOD_COMMON_HARD_IO } array_0_255, {from module MOD_COMMON_HARD_IO } proced_tcs_pause, {from module MOD_TCS_IO_COMINT_HANDLING } proced_tcs_resume, {from module MOD_TCS_IO_COMINT_HANDLING } proced_tcs_read_fmln_cbus, {from module MOD_TCS_IO_CBUS_HANDLING } proced_tcs_write_fmln_cbus ; {from module MOD_TCS_IO_CBUS_HANDLING } { *************************************************************************** } { *************************************************************************** } CONST MUX_select_addr_gen = 128 ; dont_incr_addr_gen_on_write = 64 ; dont_incr_addr_gen_on_read = 32 ; mode_increment_addr_gen = 8 + 16 ; reset_addr_gen = 2 ; enable_addr_gen = 0 ; use_card_input = 0 ; all_channels = 255 ; no_channel = 0 ; TYPE byte = [BYTE] 0..255 ; VAR tag : VARYING_STRING(8) := 'FML/ODB%' ; square : array_0_255 ; Mispt_threshold : eight_integer_0_7 ; first_call : BOOLEAN := TRUE ; { *************************************************************************** } { *************************************************************************** } PROCEDURE update_fmln_threshold ( tagext : VARYING_STRING(8) := '' ; card :^fmln_card ; comp_num : INTEGER ; count_threshold : INTEGER ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; VAR step_status : status_type ; glob_status : status_type ; write_protect_mask : eight_bit_0_7 ; start_state : [BIT(1)] 0..1 ; through_Px_magn : INTEGER ; threshold_squared : INTEGER ; Py : INTEGER ; Py_squared : INTEGER ; addr_generated : INTEGER ; BEGIN glob_status := ok ; IF ( first_call = TRUE ) THEN init_squares ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Write FMLN comparator #' + CONVERT(STRING,comp_num) + ' Threshold = ' + CONVERT(STRING,count_threshold) ) ; IF ( count_threshold > 256 ) THEN BEGIN glob_status := error_found ; IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' FMLN Threshold overflow ' ) ; GOTO fmln_cmp_load_error ; END ELSE MisPt_Threshold[comp_num] := count_threshold ; write_protect_mask::BYTE := all_channels ; write_protect_mask.bitfield[comp_num] := 0 ; IF ( count_threshold = 0 ) THEN BEGIN zero_fmln_thresholds ( TAGEXT := tagext, CARD := card, WRITE_PROTECT_MASK := write_protect_mask, IOPAR := iopar, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; GOTO fmln_cmp_load_error ; END ; proced_tcs_pause ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.wr_protect), IOPAR := iopar, DATA := write_protect_mask::BYTE, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; reset_fmln_addr_for_write ( TAGEXT := tagext, CARD := card, IOPAR := iopar, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; threshold_squared := count_threshold * count_threshold ; start_state := 0 ; iopar^.fa := card^.write_data.fa ; {aim at proper function address} FOR Py := 0 TO ( count_threshold - 1 ) DO BEGIN Py_squared := square[Py] ; through_Px_magn := square_ge_dichotomy (threshold_squared - Py_squared) -1 ; proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} START_STATE := start_state, THROUGH_PX_MAGN := through_Px_magn ) ; END ; start_state := 1 ; through_Px_magn := 255 ; FOR Py := count_threshold TO 255 DO BEGIN proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} START_STATE := start_state, THROUGH_PX_MAGN := through_Px_magn ) ; END ; read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 256*512 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN,' + ' halfway address is ' + CONVERT(STRING,addr_generated) + ' instead of ' + CONVERT(STRING,256*512) ) ; END ; iopar^.fa := card^.write_data.fa ; {aim at proper function address} FOR Py := 256 DOWNTO count_threshold DO BEGIN proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} START_STATE := start_state, THROUGH_PX_MAGN := through_Px_magn ) ; END ; start_state := 0 ; iopar^.fa := card^.write_data.fa ; FOR Py := ( count_threshold - 1 ) DOWNTO 1 DO BEGIN Py_squared := square[Py] ; through_Px_magn := square_ge_dichotomy (threshold_squared - Py_squared) -1 ; proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} START_STATE := start_state, THROUGH_PX_MAGN := through_Px_magn ) ; END ; read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN,' + ' end address is ' + CONVERT(STRING,addr_generated) + ' instead of 0 (i.e. ' + CONVERT(STRING,2*256*512) + ')' ) ; END ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.wr_protect), IOPAR := iopar, DATA := all_channels, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.ovf_ovrule), IOPAR := iopar, DATA := no_channel, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := use_card_input, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; IF ( framework_state = running ) THEN proced_tcs_resume ; fmln_cmp_load_error: IF ( glob_status <> ok ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Writing FMLN comparator #' + CONVERT(STRING,comp_num) ) ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE zero_fmln_thresholds ( tagext : VARYING_STRING(8) := '' ; card :^fmln_card ; write_protect_mask : eight_bit_0_7 := ZERO ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; VAR step_status : status_type ; glob_status : status_type ; Py : INTEGER ; addr_generated : INTEGER ; comp_num : INTEGER ; BEGIN glob_status := ok ; IF ( write_protect_mask::BYTE = no_channel ) THEN BEGIN MisPt_Threshold := ZERO ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Zero all FMLN comparators' + ' @ cbus' + CONVERT(STRING(2),card^.cbus) + ' mba' + CONVERT(STRING(4),card^.mba) + ' ca' + CONVERT(STRING(3),card^.ca) ) ; END ELSE BEGIN FOR comp_num := 0 TO 7 DO IF ( write_protect_mask.bitfield[comp_num] = 0 ) THEN BEGIN MisPt_Threshold[comp_num] := 0 ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Zero FMLN comparator #' + CONVERT(STRING,comp_num) + ' @ cbus' + CONVERT(STRING(2),card^.cbus) + ' mba' + CONVERT(STRING(4),card^.mba) + ' ca' + CONVERT(STRING(3),card^.ca) ) ; END ; END ; proced_tcs_pause ; reset_fmln_addr_for_write ( TAGEXT := tagext, CARD := card, IOPAR := iopar, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.wr_protect), IOPAR := iopar, DATA := write_protect_mask::BYTE, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; iopar^.fa := card^.write_data.fa ; {aim at proper function address} FOR Py := 0 TO 255 DO BEGIN proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} START_STATE := 1, THROUGH_PX_MAGN := 255 ) ; END ; read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 256*512 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN,' + ' halfway address is ' + CONVERT(STRING,addr_generated) + ' instead of ' + CONVERT(STRING,256*512) ) ; END ; iopar^.fa := card^.write_data.fa ; {aim at proper function address} FOR Py := 256 DOWNTO 1 DO BEGIN proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} START_STATE := 1, THROUGH_PX_MAGN := 255 ) ; END ; read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN,' + ' end address is ' + CONVERT(STRING,addr_generated) + ' instead of 0 (i.e. ' + CONVERT(STRING,2*256*512) + ')' ) ; END ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.wr_protect), IOPAR := iopar, DATA := all_channels, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.ovf_ovrule), IOPAR := iopar, DATA := no_channel, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := use_card_input, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; IF ( framework_state = running ) THEN proced_tcs_resume ; fmln_cmp_load_error: IF ( glob_status <> ok ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Zeroing FMLN comparators' ) ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE verify_fmln_thresholds( tagext : VARYING_STRING(8) := '' ; card :^fmln_card ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; TYPE eight_status_0_7 = ARRAY [0..7] OF status_type ; VAR step_status : status_type ; glob_status : status_type ; eight_step_status : eight_status_0_7 ; eight_glob_status : eight_status_0_7 ; eight_state : eight_bit_0_7 ; eight_through : eight_integer_0_7 ; threshold_squared : eight_integer_0_7 ; start_state : [BIT(1)] 0..1 ; comp_num : INTEGER ; through_Px_magn : INTEGER ; Py : INTEGER ; Py_squared : INTEGER ; addr_generated : INTEGER ; BEGIN IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Verify all FMLN comparators' + ' @ cbus' + CONVERT(STRING(2),card^.cbus) + ' mba' + CONVERT(STRING(4),card^.mba) + ' ca' + CONVERT(STRING(3),card^.ca) ) ; glob_status := ok ; eight_glob_status := ZERO ; {ok} IF ( first_call = TRUE ) THEN init_squares ; FOR comp_num := 0 TO 7 DO threshold_squared[comp_num] := square[MisPt_Threshold[comp_num]] ; reset_fmln_addr_for_read ( TAGEXT := tagext, CARD := card, IOPAR := iopar, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.ovf_ovrule), IOPAR := iopar, DATA := all_channels, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; iopar^.fa := card^.read_thrsh.fa ; {aim at proper function address} FOR Py := 0 TO 255 DO BEGIN Py_squared := square[Py] ; proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} EIGHT_START_STATE := ADDRESS(eight_state), EIGHT_THROUGH_PX_MAGN := ADDRESS(eight_through), EIGHT_STATUS := eight_step_status ) ; FOR comp_num := 0 TO 7 DO BEGIN IF ( eight_step_status[comp_num] <> ok ) THEN BEGIN eight_glob_status[comp_num] := eight_step_status[comp_num] ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' above rule checking error were for Py=' + CONVERT(STRING,Py) ) ; END ; through_Px_magn := square_ge_dichotomy( threshold_squared[comp_num] - Py_squared ) - 1 ; IF ( through_Px_magn < 0 ) THEN BEGIN IF ( ( eight_state.bitfield[comp_num] <> 1 ) OR ( eight_through[comp_num] <> 255) ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' not all TRUE, but starts ' + CONVERT(STRING, CONVERT(BOOLEAN, eight_state.bitfield[comp_num])) + ' through Px=' + CONVERT(STRING,eight_through[comp_num]) + ' for Py=' + CONVERT(STRING,Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; END ELSE IF ( through_Px_magn < 255 ) THEN BEGIN IF ( eight_state.bitfield[comp_num] <> 0 ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' does not start TRUE at Px=0' + ' for Py=' + CONVERT(STRING,Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; IF ( through_Px_magn <> eight_through[comp_num] ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' switches at ' + CONVERT(STRING,eight_through[comp_num]) + ' instead of ' + CONVERT(STRING,through_Px_magn) + ' for Py=' + CONVERT(STRING,Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; END ELSE BEGIN { through_Px_magn >= 255 } IF ( ( eight_state.bitfield[comp_num] <> 0 ) OR ( eight_through[comp_num] <> 255) ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' not all FALSE, but starts ' + CONVERT(STRING, CONVERT(BOOLEAN, eight_state.bitfield[comp_num])) + ' through Px=' + CONVERT(STRING,eight_through[comp_num]) + ' for Py=' + CONVERT(STRING,Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; END ; {if then else else} END ;{Do on comp_num} END ;{Do on Py} read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 256*512 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Checking FMLN,' + ' halfway address is ' + CONVERT(STRING,addr_generated) + ' instead of ' + CONVERT(STRING,256*512) ) ; END ; iopar^.fa := card^.read_thrsh.fa ; {aim at proper function address} FOR Py := 256 DOWNTO 1 DO BEGIN Py_squared := square[Py] ; proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} EIGHT_START_STATE := ADDRESS(eight_state), EIGHT_THROUGH_PX_MAGN := ADDRESS(eight_through), EIGHT_STATUS := eight_step_status ) ; FOR comp_num := 0 TO 7 DO BEGIN IF ( eight_step_status[comp_num] <> ok ) THEN BEGIN eight_glob_status[comp_num] := eight_step_status[comp_num] ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' above rule checking errors were for Py=' + CONVERT(STRING,-Py) ) ; END ; through_Px_magn := square_ge_dichotomy( threshold_squared[comp_num] - Py_squared ) - 1 ; IF ( through_Px_magn < 0 ) THEN BEGIN IF ( ( eight_state.bitfield[comp_num] <> 1 ) OR ( eight_through[comp_num] <> 255) ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' not all TRUE, but starts ' + CONVERT(STRING, CONVERT(BOOLEAN, eight_state.bitfield[comp_num])) + ' through Px=' + CONVERT(STRING,eight_through[comp_num]) + ' for Py=' + CONVERT(STRING,-Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; END ELSE IF ( through_Px_magn < 255 ) THEN BEGIN IF ( eight_state.bitfield[comp_num] <> 0 ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' does not start TRUE at Px=0' + ' for Py=' + CONVERT(STRING,-Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; IF ( through_Px_magn <> eight_through[comp_num] ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' switches at ' + CONVERT(STRING,eight_through[comp_num]) + ' instead of ' + CONVERT(STRING,through_Px_magn) + ' for Py=' + CONVERT(STRING,-Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; END ELSE BEGIN { through_Px_magn >= 255 } IF ( ( eight_state.bitfield[comp_num] <> 0 ) OR ( eight_through[comp_num] <> 255) ) THEN BEGIN eight_glob_status[comp_num] := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Comp Bit #' + CONVERT(STRING,comp_num) + ' not all FALSE, but starts ' + CONVERT(STRING, CONVERT(BOOLEAN, eight_state.bitfield[comp_num])) + ' through Px=' + CONVERT(STRING,eight_through[comp_num]) + ' for Py=' + CONVERT(STRING,-Py) + ' when threshold =' + CONVERT(STRING,MisPt_Threshold[comp_num]) ) ; END ; END ; {if then else else} END ;{Do on comp_num} END ;{Do on Py} read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Checking FMLN,' + ' end address is ' + CONVERT(STRING,addr_generated) + ' instead of 0 (i.e. ' + CONVERT(STRING,2*256*512) + ')' ) ; END ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.ovf_ovrule), IOPAR := iopar, DATA := no_channel, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := use_card_input, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; FOR comp_num := 0 TO 7 DO IF ( eight_glob_status[comp_num] <> ok ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Incorrect Programming in FMLN comparator #' + CONVERT(STRING,comp_num) ) ; END ELSE handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' FMLN comparator #' + CONVERT(STRING,comp_num) + ' threshold = ' + CONVERT(STRING,MisPt_Threshold[comp_num]) + ' programming is correct' ) ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE program_fmln_momentum_lookup ( tagext : VARYING_STRING(8) := '' ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; VAR step_status : status_type ; glob_status : status_type ; through_Px_magn : INTEGER ; Py : INTEGER ; Py_squared : INTEGER ; Px : INTEGER ; addr_generated : INTEGER ; Miss_Pt_array : array_0_255 ; BEGIN IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Program FMLN Momentum Lookup ' ) ; glob_status := ok ; IF ( first_call = TRUE ) THEN init_squares ; reset_fmln_addr_for_write ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), IOPAR := iopar, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { lift write protect on all "channels" (i.e the output byte) } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.wr_protect), IOPAR := iopar, DATA := no_channel, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { take one Py at a time, and scan all the Px values, load SQRT (Px^2+Py^2) } iopar^.fa := fmln_compute.write_data.fa ; {aim at proper function address} FOR Py := 0 TO 254 DO BEGIN Py_squared := square[Py] ; {the loaded values will start saturating after a certain point ...} through_Px_magn := square_ge_dichotomy (255*255 - Py_squared) -1 ; {... compute MPt up to that point} FOR Px := 0 TO through_Px_magn DO Miss_Pt_Array[Px] := ROUND( SQRT( Py_squared + square[Px] ) ) ; proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn ) ; END ; { For Py= 255, the output saturates at 255 for all values of Px } Miss_Pt_Array[0] := 255 ; proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := 0 ) ; { check the FMLN address generator has incremented to half the address space} read_fmln_address_generator ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 256*512 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN,' + ' halfway address is ' + CONVERT(STRING,addr_generated) + ' instead of ' + CONVERT(STRING,256*512) ) ; END ; { restore function address after having read address generator} iopar^.fa := fmln_compute.write_data.fa ; {For Py= -256, the output saturates at 255 for all values of Px } proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := 0 ) ; {For Py= -255, the output saturates at 255 for all values of Px } proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := 0 ) ; {same as for positive values of Px} FOR Py := 254 DOWNTO 1 DO BEGIN Py_squared := square[Py] ; through_Px_magn := square_ge_dichotomy (255*255 - Py_squared) -1 ; FOR Px := 0 TO through_Px_magn DO Miss_Pt_Array[Px] := ROUND( SQRT( Py_squared + square[Px] ) ) ; proced_tcs_write_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn ) ; END ; { check the FMLN address generator has incremented to just rollover } read_fmln_address_generator ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN,' + ' end address is ' + CONVERT(STRING,addr_generated) + ' instead of 0 (i.e. ' + CONVERT(STRING,2*256*512) + ')' ) ; END ; { write protect all channels } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.wr_protect), IOPAR := iopar, DATA := all_channels, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { enable overflow circuitry on all channels } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.ovf_ovrule), IOPAR := iopar, DATA := no_channel, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { set card for normal operation } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.controlreg), IOPAR := iopar, DATA := use_card_input, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; fmln_lookup_load_error: IF ( glob_status <> ok ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming FMLN Momentum Lookup ' ) ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE verify_fmln_momentum_lookup ( tagext : VARYING_STRING(8) := '' ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; VAR step_status : status_type ; glob_status : status_type ; through_Px_magn : INTEGER ; Py : INTEGER ; Py_squared : INTEGER ; Px : INTEGER ; addr_generated : INTEGER ; Miss_Pt_array : array_0_255 ; Miss_Pt : INTEGER ; BEGIN IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Verify FMLN Momentum Lookup ' ) ; glob_status := ok ; IF ( first_call = TRUE ) THEN init_squares ; IF PRESENT(status) THEN status := ok ; reset_fmln_addr_for_read ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), IOPAR := iopar, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { disable the overflow circuitry from overriding the RAM output } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.ovf_ovrule), IOPAR := iopar, DATA := all_channels, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { take one Py at a time, check all the Px values for MPt= SQRT (Px^2+Py^2) } iopar^.fa := fmln_compute.read_thrsh.fa ; {aim at proper function address} FOR Py := 0 TO 254 DO BEGIN proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn, STATUS := step_status ) ; IF ( step_status <> ok ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Above Mpt rule checking errors' + ' were for Py=' + CONVERT(STRING,Py) ) ; END ; Py_squared := square[Py] ; {the loaded values started saturating after a certain point ...} {Note: we cannot easily make an exact comparison for saturation here, } {because the square root may have been rounded up to 255. } {Compare every value up to that point will also catch incorrect saturation } { IF ( through_Px_magn <> square_ge_dichotomy (255*255 - Py_squared) -1 ) } { THEN glob_status := error_found ; } {... verify the MPt up to the saturation point} FOR Px := 0 TO through_Px_magn DO BEGIN Miss_Pt := ROUND( SQRT( Py_squared + square[Px] ) ) ; IF ( Miss_Pt_Array[Px] <> Miss_Pt ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' MPt Lookup is ' + CONVERT(STRING,Miss_Pt_Array[Px]) + ' instead of ' + CONVERT(STRING,Miss_Pt) + ' for Px=' + CONVERT(STRING,Px) + ' and Py=' + CONVERT(STRING,Py) ) ; END ; END ; END ; { For Py= 255, the output should saturate at 255 for all values of Px } proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn, STATUS := step_status ) ; IF ( step_status <> ok ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Above Mpt rule checking errors' + ' were for Py=255' ) ; END ; IF ( ( through_Px_magn <> 0 ) OR ( Miss_Pt_Array[0] <> 255 ) ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Mpt lookup not all saturated' + ' for Py=255' ) ; END ; { check the FMLN address generator has incremented to half the address space} read_fmln_address_generator ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 256*512 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Verifying FMLN,' + ' halfway address is ' + CONVERT(STRING,addr_generated) + ' instead of ' + CONVERT(STRING,256*512) ) ; END ; { restore function address after having read address generator} iopar^.fa := fmln_compute.read_thrsh.fa ; {For Py= -256, the output should saturate at 255 for all values of Px } proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn, STATUS := step_status ) ; IF ( step_status <> ok ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Above Mpt rule checking errors' + ' were for Py=-256' ) ; END ; IF ( ( through_Px_magn <> 0 ) OR ( Miss_Pt_Array[0] <> 255 ) ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Mpt lookup not all saturated' + ' for Py=-256' ) ; END ; {For Py= -255, the output should saturate at 255 for all values of Px } proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn, STATUS := step_status ) ; IF ( step_status <> ok ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Above Mpt rule checking errors' + ' were for Py=-255' ) ; END ; IF ( ( through_Px_magn <> 0 ) OR ( Miss_Pt_Array[0] <> 255 ) ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Mpt lookup not all saturated' + ' for Py=-255' ) ; END ; {same as for positive values of Px} FOR Py := 254 DOWNTO 1 DO BEGIN proced_tcs_read_fmln_cbus ( PARAM := iopar, {still has correct ca,...} DATA := ADDRESS(Miss_Pt_Array), THROUGH_PX_MAGN := through_Px_magn, STATUS := step_status ) ; IF ( step_status <> ok ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Above Mpt rule checking errors' + ' were for Py=' + CONVERT(STRING,-Py) ) ; END ; Py_squared := square[Py] ; {... verify the MPt up to the saturation point} FOR Px := 0 TO through_Px_magn DO BEGIN Miss_Pt := ROUND( SQRT( Py_squared + square[Px] ) ) ; IF ( Miss_Pt_Array[Px] <> Miss_Pt ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' MPt Lookup is ' + CONVERT(STRING,Miss_Pt_Array[Px]) + ' instead of ' + CONVERT(STRING,Miss_Pt) + ' for Px=' + CONVERT(STRING,Px) + ' and Py=' + CONVERT(STRING,-Py) ) ; END ; END ; END ; { check the FMLN address generator has incremented to just rollover } read_fmln_address_generator ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN BEGIN glob_status := error_found ; handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Verifying FMLN,' + ' end address is ' + CONVERT(STRING,addr_generated) + ' instead of 0 (i.e. ' + CONVERT(STRING,2*256*512) + ')' ) ; END ; { re-enable overflow circuitry on all channels } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.ovf_ovrule), IOPAR := iopar, DATA := no_channel, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; { set card for normal operation } update_register ( TAGEXT := tagext, CARD := ADDRESS(fmln_compute), REGISTER := ADDRESS(fmln_compute.controlreg), IOPAR := iopar, DATA := use_card_input, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; fmln_lookup_load_error: IF ( glob_status <> ok ) THEN BEGIN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Verifying FMLN Momentum Lookup ' ) ; END ELSE BEGIN IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' FMLN Momentum Lookup correct' ) ; END ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE reset_fmln_addr_for_read ( tagext : VARYING_STRING(8) := '' ; card :^fmln_card ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; VAR step_status : status_type ; glob_status : status_type ; addr_generated : INTEGER ; BEGIN glob_status := ok ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := reset_addr_gen, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := MUX_select_addr_gen + mode_increment_addr_gen + dont_incr_addr_gen_on_write + enable_addr_gen, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN glob_status := error_found ; IF ( glob_status <> ok ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Resetting FMLN Address Generator' ) ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE reset_fmln_addr_for_write ( tagext : VARYING_STRING(8) := '' ; card :^fmln_card ; iopar :^cbus_param_list ; VAR status :[OPTIONAL] status_type ) ; VAR step_status : status_type ; glob_status : status_type ; addr_generated : INTEGER ; BEGIN glob_status := ok ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := reset_addr_gen, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; update_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.controlreg), IOPAR := iopar, DATA := MUX_select_addr_gen + mode_increment_addr_gen + dont_incr_addr_gen_on_read + enable_addr_gen, STATUS := step_status ) ; IF ( step_status <> ok ) THEN IF PRESENT(status) THEN glob_status := step_status ; read_fmln_address_generator ( TAGEXT := tagext, CARD := card, IOPAR := iopar, ADDR_GEN := addr_generated, STATUS := step_status ) ; IF ( step_status <> ok ) THEN glob_status := step_status ; IF ( addr_generated <> 0 ) THEN glob_status := error_found ; IF ( glob_status <> ok ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Resetting FMLN Address Generator' ) ; IF PRESENT(status) THEN status := glob_status ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE read_fmln_address_generator ( tagext : VARYING_STRING(8) := '' ; card :^fmln_card ; iopar :^cbus_param_list ; VAR addr_gen : INTEGER ; VAR status :[OPTIONAL] status_type ) ; TYPE integer_by_6bit_fields = [LONG] PACKED RECORD first_field : [POS( 0)] 0..63 ; second_field : [POS( 6)] 0..63 ; third_field : [POS(12)] 0..63 ; overflow : [POS(18)] 0..16383 ; END ; VAR address_generated : integer_by_6bit_fields ; data : byte ; BEGIN IF PRESENT(status) THEN status := ok ; address_generated::INTEGER := 0 ; examine_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.addr_gen[1]), IOPAR := iopar, DATA := data ) ; address_generated.first_field := data ; examine_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.addr_gen[2]), IOPAR := iopar, DATA := data ) ; address_generated.second_field := data ; examine_register ( TAGEXT := tagext, CARD := card, REGISTER := ADDRESS(card^.addr_gen[3]), IOPAR := iopar, DATA := data ) ; address_generated.third_field := data ; addr_gen := address_generated::INTEGER ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE init_squares ; VAR x, x_squared : INTEGER ; BEGIN x_squared := 0 ; square[0] := x_squared ; FOR x := 1 TO 255 DO BEGIN {use (n+1)^2 = n^2 + 2n + 1 = n^2 + 2(n+1) - 1} x_squared := x_squared + x + x - 1 ; square[x] := x_squared ; END ; first_call := FALSE ; END ; { *************************************************************************** } { *************************************************************************** } [INLINE] FUNCTION square_ge_dichotomy ( Px_squared : INTEGER ) : INTEGER ; VAR Px : INTEGER ; low, high : INTEGER ; BEGIN IF ( Px_squared < 128*128 ) THEN BEGIN IF ( Px_squared < 64*64 ) THEN BEGIN IF ( Px_squared < 32*32 ) THEN BEGIN IF ( Px_squared < 16*16 ) THEN BEGIN low := 0 ; high := 15 ; END ELSE BEGIN low := 16 ; high := 31 ; END ; END ELSE BEGIN IF ( Px_squared < 48*48 ) THEN BEGIN low := 32 ; high := 47 ; END ELSE BEGIN low := 48 ; high := 63 ; END ; END ; END ELSE BEGIN IF ( Px_squared <= 96*96 ) THEN BEGIN IF ( Px_squared < 80*80 ) THEN BEGIN low := 64 ; high := 79 ; END ELSE BEGIN low := 80 ; high := 95 ; END ; END ELSE BEGIN IF ( Px_squared < 112*112 ) THEN BEGIN low := 96 ; high := 111 ; END ELSE BEGIN low := 112; high := 127 ; END ; END ; END ; END ELSE BEGIN IF ( Px_squared < 192*192 ) THEN BEGIN IF ( Px_squared < 160*160 ) THEN BEGIN IF ( Px_squared < 144*144 ) THEN BEGIN low := 128 ; high := 143 ; END ELSE BEGIN low := 144 ; high := 159 ; END ; END ELSE BEGIN IF ( Px_squared < 176*176 ) THEN BEGIN low := 160 ; high := 175 ; END ELSE BEGIN low := 176 ; high := 191 ; END ; END ; END ELSE BEGIN IF ( Px_squared <= 224*224 ) THEN BEGIN IF ( Px_squared < 208*208 ) THEN BEGIN low := 192 ; high := 207 ; END ELSE BEGIN low := 208 ; high := 223 ; END ; END ELSE BEGIN IF ( Px_squared < 240*240 ) THEN BEGIN low := 224 ; high := 239 ; END ELSE BEGIN low := 240 ; high := 255 ; END ; END ; END ; END ; FOR Px := low TO high DO IF ( square[Px] >= Px_squared ) THEN GOTO done ; done: square_ge_dichotomy := Px ; END ; { *************************************************************************** } { *************************************************************************** } END.