0019-haswell-NRI-Add-range-tracking-library.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. From 9fba0468e75877cbda62f5eaeef1946d6489a8f9 Mon Sep 17 00:00:00 2001
  2. From: Angel Pons <th3fanbus@gmail.com>
  3. Date: Sun, 8 May 2022 00:56:00 +0200
  4. Subject: [PATCH 19/26] haswell NRI: Add range tracking library
  5. Implement a small library used to keep track of passing ranges. This
  6. will be used by 1D training algorithms when margining some parameter.
  7. Change-Id: I8718e85165160afd7c0c8e730b5ce6c9c00f8a60
  8. Signed-off-by: Angel Pons <th3fanbus@gmail.com>
  9. ---
  10. .../intel/haswell/native_raminit/Makefile.inc | 1 +
  11. .../intel/haswell/native_raminit/ranges.c | 109 ++++++++++++++++++
  12. .../intel/haswell/native_raminit/ranges.h | 68 +++++++++++
  13. 3 files changed, 178 insertions(+)
  14. create mode 100644 src/northbridge/intel/haswell/native_raminit/ranges.c
  15. create mode 100644 src/northbridge/intel/haswell/native_raminit/ranges.h
  16. diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.inc b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
  17. index 6e1b365602..2da950771d 100644
  18. --- a/src/northbridge/intel/haswell/native_raminit/Makefile.inc
  19. +++ b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
  20. @@ -9,6 +9,7 @@ romstage-y += io_comp_control.c
  21. romstage-y += memory_map.c
  22. romstage-y += raminit_main.c
  23. romstage-y += raminit_native.c
  24. +romstage-y += ranges.c
  25. romstage-y += reut.c
  26. romstage-y += setup_wdb.c
  27. romstage-y += spd_bitmunching.c
  28. diff --git a/src/northbridge/intel/haswell/native_raminit/ranges.c b/src/northbridge/intel/haswell/native_raminit/ranges.c
  29. new file mode 100644
  30. index 0000000000..cdebc1fa66
  31. --- /dev/null
  32. +++ b/src/northbridge/intel/haswell/native_raminit/ranges.c
  33. @@ -0,0 +1,109 @@
  34. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  35. +
  36. +#include <types.h>
  37. +
  38. +#include "ranges.h"
  39. +
  40. +void linear_record_pass(
  41. + struct linear_train_data *const data,
  42. + const bool pass,
  43. + const int32_t value,
  44. + const int32_t start,
  45. + const int32_t step)
  46. +{
  47. + /* If this is the first time, initialize all values */
  48. + if (value == start) {
  49. + /*
  50. + * If value passed, create a zero-length region for the current value,
  51. + * which may be extended as long as the successive values are passing.
  52. + *
  53. + * Otherwise, create a zero-length range for the preceding value. This
  54. + * range cannot be extended by other passing values, which is desired.
  55. + */
  56. + data->current.start = start - (pass ? 0 : step);
  57. + data->current.end = data->current.start;
  58. + data->largest = data->current;
  59. + } else if (pass) {
  60. + /* If this pass is not contiguous, it belongs to a new region */
  61. + if (data->current.end != (value - step))
  62. + data->current.start = value;
  63. +
  64. + /* Update end of current region */
  65. + data->current.end = value;
  66. +
  67. + /* Update largest region */
  68. + if (range_width(data->current) > range_width(data->largest))
  69. + data->largest = data->current;
  70. + }
  71. +}
  72. +
  73. +void phase_record_pass(
  74. + struct phase_train_data *const data,
  75. + const bool pass,
  76. + const int32_t value,
  77. + const int32_t start,
  78. + const int32_t step)
  79. +{
  80. + /* If this is the first time, initialize all values */
  81. + if (value == start) {
  82. + /*
  83. + * If value passed, create a zero-length region for the current value,
  84. + * which may be extended as long as the successive values are passing.
  85. + *
  86. + * Otherwise, create a zero-length range for the preceding value. This
  87. + * range cannot be extended by other passing values, which is desired.
  88. + */
  89. + data->current.start = start - (pass ? 0 : step);
  90. + data->current.end = data->current.start;
  91. + data->largest = data->current;
  92. + data->initial = data->current;
  93. + return;
  94. + }
  95. + if (!pass)
  96. + return;
  97. +
  98. + /* Update initial region */
  99. + if (data->initial.end == (value - step))
  100. + data->initial.end = value;
  101. +
  102. + /* If this pass is not contiguous, it belongs to a new region */
  103. + if (data->current.end != (value - step))
  104. + data->current.start = value;
  105. +
  106. + /* Update end of current region */
  107. + data->current.end = value;
  108. +
  109. + /* Update largest region */
  110. + if (range_width(data->current) > range_width(data->largest))
  111. + data->largest = data->current;
  112. +}
  113. +
  114. +void phase_append_initial_to_current(
  115. + struct phase_train_data *const data,
  116. + const int32_t start,
  117. + const int32_t step)
  118. +{
  119. + /* If initial region is valid and does not overlap, append it */
  120. + if (data->initial.start == start && data->initial.end != data->current.end)
  121. + data->current.end += step + range_width(data->initial);
  122. +
  123. + /* Update largest region */
  124. + if (range_width(data->current) > range_width(data->largest))
  125. + data->largest = data->current;
  126. +}
  127. +
  128. +void phase_append_current_to_initial(
  129. + struct phase_train_data *const data,
  130. + const int32_t start,
  131. + const int32_t step)
  132. +{
  133. + /* If initial region is valid and does not overlap, append it */
  134. + if (data->initial.start == start && data->initial.end != data->current.end) {
  135. + data->initial.start -= (step + range_width(data->current));
  136. + data->current = data->initial;
  137. + }
  138. +
  139. + /* Update largest region */
  140. + if (range_width(data->current) > range_width(data->largest))
  141. + data->largest = data->current;
  142. +}
  143. diff --git a/src/northbridge/intel/haswell/native_raminit/ranges.h b/src/northbridge/intel/haswell/native_raminit/ranges.h
  144. new file mode 100644
  145. index 0000000000..235392df96
  146. --- /dev/null
  147. +++ b/src/northbridge/intel/haswell/native_raminit/ranges.h
  148. @@ -0,0 +1,68 @@
  149. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  150. +
  151. +#ifndef HASWELL_RAMINIT_RANGES_H
  152. +#define HASWELL_RAMINIT_RANGES_H
  153. +
  154. +#include <types.h>
  155. +
  156. +/*
  157. + * Many algorithms shmoo some parameter to determine the largest passing
  158. + * range. Provide a common implementation to avoid redundant boilerplate.
  159. + */
  160. +struct passing_range {
  161. + int32_t start;
  162. + int32_t end;
  163. +};
  164. +
  165. +/* Structure for linear parameters, such as roundtrip delays */
  166. +struct linear_train_data {
  167. + struct passing_range current;
  168. + struct passing_range largest;
  169. +};
  170. +
  171. +/*
  172. + * Phase ranges are "circular": the first and last indices are contiguous.
  173. + * To correctly determine the largest passing range, one has to combine
  174. + * the initial range and the current range when processing the last index.
  175. + */
  176. +struct phase_train_data {
  177. + struct passing_range initial;
  178. + struct passing_range current;
  179. + struct passing_range largest;
  180. +};
  181. +
  182. +static inline int32_t range_width(const struct passing_range range)
  183. +{
  184. + return range.end - range.start;
  185. +}
  186. +
  187. +static inline int32_t range_center(const struct passing_range range)
  188. +{
  189. + return range.start + range_width(range) / 2;
  190. +}
  191. +
  192. +void linear_record_pass(
  193. + struct linear_train_data *data,
  194. + bool pass,
  195. + int32_t value,
  196. + int32_t start,
  197. + int32_t step);
  198. +
  199. +void phase_record_pass(
  200. + struct phase_train_data *data,
  201. + bool pass,
  202. + int32_t value,
  203. + int32_t start,
  204. + int32_t step);
  205. +
  206. +void phase_append_initial_to_current(
  207. + struct phase_train_data *data,
  208. + int32_t start,
  209. + int32_t step);
  210. +
  211. +void phase_append_current_to_initial(
  212. + struct phase_train_data *data,
  213. + int32_t start,
  214. + int32_t step);
  215. +
  216. +#endif
  217. --
  218. 2.39.2