Bill XIE has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/77058?usp=email )
Change subject: haswell NRI: Add range tracking library ......................................................................
haswell NRI: Add range tracking library
Implement a small library used to keep track of passing ranges. This will be used by 1D training algorithms when margining some parameter.
Original-Change-Id: I8718e85165160afd7c0c8e730b5ce6c9c00f8a60 Original-Signed-off-by: Angel Pons th3fanbus@gmail.com Signed-off-by: Bill XIE persmule@hardenedlinux.org Change-Id: I472df39757b8288704e20deacaacf0a544e5bc30 --- M src/northbridge/intel/haswell/native_raminit/Makefile.inc A src/northbridge/intel/haswell/native_raminit/ranges.c A src/northbridge/intel/haswell/native_raminit/ranges.h 3 files changed, 178 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/58/77058/1
diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.inc b/src/northbridge/intel/haswell/native_raminit/Makefile.inc index 6e1b365..2da9507 100644 --- a/src/northbridge/intel/haswell/native_raminit/Makefile.inc +++ b/src/northbridge/intel/haswell/native_raminit/Makefile.inc @@ -9,6 +9,7 @@ romstage-y += memory_map.c romstage-y += raminit_main.c romstage-y += raminit_native.c +romstage-y += ranges.c romstage-y += reut.c romstage-y += setup_wdb.c romstage-y += spd_bitmunching.c diff --git a/src/northbridge/intel/haswell/native_raminit/ranges.c b/src/northbridge/intel/haswell/native_raminit/ranges.c new file mode 100644 index 0000000..cdebc1f --- /dev/null +++ b/src/northbridge/intel/haswell/native_raminit/ranges.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <types.h> + +#include "ranges.h" + +void linear_record_pass( + struct linear_train_data *const data, + const bool pass, + const int32_t value, + const int32_t start, + const int32_t step) +{ + /* If this is the first time, initialize all values */ + if (value == start) { + /* + * If value passed, create a zero-length region for the current value, + * which may be extended as long as the successive values are passing. + * + * Otherwise, create a zero-length range for the preceding value. This + * range cannot be extended by other passing values, which is desired. + */ + data->current.start = start - (pass ? 0 : step); + data->current.end = data->current.start; + data->largest = data->current; + } else if (pass) { + /* If this pass is not contiguous, it belongs to a new region */ + if (data->current.end != (value - step)) + data->current.start = value; + + /* Update end of current region */ + data->current.end = value; + + /* Update largest region */ + if (range_width(data->current) > range_width(data->largest)) + data->largest = data->current; + } +} + +void phase_record_pass( + struct phase_train_data *const data, + const bool pass, + const int32_t value, + const int32_t start, + const int32_t step) +{ + /* If this is the first time, initialize all values */ + if (value == start) { + /* + * If value passed, create a zero-length region for the current value, + * which may be extended as long as the successive values are passing. + * + * Otherwise, create a zero-length range for the preceding value. This + * range cannot be extended by other passing values, which is desired. + */ + data->current.start = start - (pass ? 0 : step); + data->current.end = data->current.start; + data->largest = data->current; + data->initial = data->current; + return; + } + if (!pass) + return; + + /* Update initial region */ + if (data->initial.end == (value - step)) + data->initial.end = value; + + /* If this pass is not contiguous, it belongs to a new region */ + if (data->current.end != (value - step)) + data->current.start = value; + + /* Update end of current region */ + data->current.end = value; + + /* Update largest region */ + if (range_width(data->current) > range_width(data->largest)) + data->largest = data->current; +} + +void phase_append_initial_to_current( + struct phase_train_data *const data, + const int32_t start, + const int32_t step) +{ + /* If initial region is valid and does not overlap, append it */ + if (data->initial.start == start && data->initial.end != data->current.end) + data->current.end += step + range_width(data->initial); + + /* Update largest region */ + if (range_width(data->current) > range_width(data->largest)) + data->largest = data->current; +} + +void phase_append_current_to_initial( + struct phase_train_data *const data, + const int32_t start, + const int32_t step) +{ + /* If initial region is valid and does not overlap, append it */ + if (data->initial.start == start && data->initial.end != data->current.end) { + data->initial.start -= (step + range_width(data->current)); + data->current = data->initial; + } + + /* Update largest region */ + if (range_width(data->current) > range_width(data->largest)) + data->largest = data->current; +} diff --git a/src/northbridge/intel/haswell/native_raminit/ranges.h b/src/northbridge/intel/haswell/native_raminit/ranges.h new file mode 100644 index 0000000..235392df --- /dev/null +++ b/src/northbridge/intel/haswell/native_raminit/ranges.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef HASWELL_RAMINIT_RANGES_H +#define HASWELL_RAMINIT_RANGES_H + +#include <types.h> + +/* + * Many algorithms shmoo some parameter to determine the largest passing + * range. Provide a common implementation to avoid redundant boilerplate. + */ +struct passing_range { + int32_t start; + int32_t end; +}; + +/* Structure for linear parameters, such as roundtrip delays */ +struct linear_train_data { + struct passing_range current; + struct passing_range largest; +}; + +/* + * Phase ranges are "circular": the first and last indices are contiguous. + * To correctly determine the largest passing range, one has to combine + * the initial range and the current range when processing the last index. + */ +struct phase_train_data { + struct passing_range initial; + struct passing_range current; + struct passing_range largest; +}; + +static inline int32_t range_width(const struct passing_range range) +{ + return range.end - range.start; +} + +static inline int32_t range_center(const struct passing_range range) +{ + return range.start + range_width(range) / 2; +} + +void linear_record_pass( + struct linear_train_data *data, + bool pass, + int32_t value, + int32_t start, + int32_t step); + +void phase_record_pass( + struct phase_train_data *data, + bool pass, + int32_t value, + int32_t start, + int32_t step); + +void phase_append_initial_to_current( + struct phase_train_data *data, + int32_t start, + int32_t step); + +void phase_append_current_to_initial( + struct phase_train_data *data, + int32_t start, + int32_t step); + +#endif