STADLS
decode.h
Go to the documentation of this file.
1 #pragma once
2 
3 #ifndef CHIP_REVISION
4 #error "Requires CHIP_REVISION"
5 #endif
6 
7 #include <limits>
8 #include <random>
9 
10 #include "fisch/vx/container.h"
11 #include "fisch/vx/container_cast.h"
12 #include "fisch/vx/fill.h"
13 #include "halco/hicann-dls/vx/capmem.h"
14 #include "halco/hicann-dls/vx/ppu.h"
15 #include "haldls/vx/common.h"
16 #include "haldls/vx/jtag.h"
17 #include "haldls/vx/traits.h"
18 #include "lola/vx/capmem.h"
19 #include "stadls/visitors.h"
20 
21 #define ID(x) x
22 #define XSTR(x) #x
23 #define STR(x) XSTR(x)
24 // clang-format off
25 #define CONCAT(w, x, y, z) STR(ID(w)ID(/)ID(x)ID(/)ID(v)ID(y)ID(/)ID(z))
26 #include CONCAT(haldls,vx,CHIP_REVISION,capmem.h)
27 // clang-format on
28 #undef ID
29 #undef XSTR
30 #undef STR
31 #undef CONCAT
32 
33 #if CHIP_REVISION == 2
34 #define CHIP_REVISION_STR v2
35 #elif CHIP_REVISION == 3
36 #define CHIP_REVISION_STR v3
37 #else
38 #error "Unknown CHIP_REVISION"
39 #endif
40 
41 namespace stadls::vx {
42 
43 namespace detail {
44 
51 template <typename T>
52 typename T::coordinate_type get_coord(T const& config)
53 {
54  using namespace halco::hicann_dls::vx;
55 
56  typename T::coordinate_type coord;
57  if constexpr (std::is_same<T, haldls::vx::PPUMemoryBlock>::value) {
58  coord = PPUMemoryBlockOnDLS(
59  PPUMemoryBlockOnPPU(
60  PPUMemoryWordOnPPU(0), PPUMemoryWordOnPPU(config.get_words().size() - 1)),
61  PPUOnDLS());
62  }
63  if constexpr (std::is_same<T, lola::vx::ExternalPPUMemoryBlock>::value) {
64  coord = ExternalPPUMemoryBlockOnFPGA(
65  ExternalPPUMemoryByteOnFPGA(0),
66  ExternalPPUMemoryByteOnFPGA(config.get_bytes().size() - 1));
67  }
68  return coord;
69 }
70 
71 
78 template <typename T>
79 size_t count_decoding_words(T const& config)
80 {
81  using namespace halco::hicann_dls::vx;
82  typedef typename haldls::vx::detail::BackendContainerTrait<T>::default_container word_type;
83  typedef std::vector<typename decltype(
84  fisch::vx::container_cast(std::declval<word_type>()))::coordinate_type>
85  addresses_type;
86  addresses_type addresses;
87 
88  auto const coord = get_coord(config);
89 
90  // get number of expected words
91  T mutable_config = config; // needed because visitor impl. might check on constness
92  haldls::vx::visit_preorder(
93  mutable_config, coord, stadls::ReadAddressVisitor<addresses_type>{addresses});
94  return addresses.size();
95 }
96 
97 } // namespace detail
98 
99 
106 template <class T>
107 inline void decode_random(std::mt19937& gen, T& config)
108 {
109  typedef typename haldls::vx::detail::BackendContainerTrait<T>::default_container word_type;
110  typedef std::vector<word_type> words_type;
111 
112  words_type words(detail::count_decoding_words(config));
113 
114  auto const coord = detail::get_coord(config);
115 
116  // randomize word content
117  for (auto& word : words) {
118  word = fisch::vx::container_cast(
119  fisch::vx::fill_random<decltype(fisch::vx::container_cast(std::declval<word_type>()))>(
120  gen));
121  }
122  // decode words into container
123  haldls::vx::visit_preorder(config, coord, stadls::DecodeVisitor<words_type>{std::move(words)});
124 }
125 
126 
132 template <class T>
133 inline void decode_ones(T& config)
134 {
135  typedef typename haldls::vx::detail::BackendContainerTrait<T>::default_container word_type;
136  typedef std::vector<word_type> words_type;
137 
138  words_type words(detail::count_decoding_words(config));
139 
140  auto const coord = detail::get_coord(config);
141 
142  // fill words
143  for (auto& word : words) {
144  word = fisch::vx::container_cast(
145  fisch::vx::fill_ones<decltype(fisch::vx::container_cast(std::declval<word_type>()))>());
146  }
147  // decode words into container
148  haldls::vx::visit_preorder(config, coord, stadls::DecodeVisitor<words_type>{std::move(words)});
149 }
150 
151 // specializations
152 
153 template <>
154 inline void decode_random(std::mt19937& gen, haldls::vx::JTAGIdCode& config)
155 {
156  // Draw a random word, to be transformed into a valid JTAG ID
157  std::uniform_int_distribution<fisch::vx::JTAGIdCode::Value::value_type> random_word(
158  std::numeric_limits<fisch::vx::JTAGIdCode::Value::value_type>::min(),
159  std::numeric_limits<fisch::vx::JTAGIdCode::Value::value_type>::max());
160 
161  // Ensure marker-bit is set to 1, thereby form a valid JTAG ID
162  auto random_jtag_id_word = random_word(gen) | 1u;
163 
164  std::array<
165  fisch::vx::word_access_type::JTAGIdCode, haldls::vx::JTAGIdCode::read_config_size_in_words>
166  data{fisch::vx::word_access_type::JTAGIdCode(random_jtag_id_word)};
167 
168  config.decode(data);
169 }
170 
171 template <>
172 inline void decode_random(
173  std::mt19937& gen, haldls::vx::CHIP_REVISION_STR::CapMemBlockConfig& config)
174 {
175  typedef haldls::vx::detail::BackendContainerTrait<
176  haldls::vx::CHIP_REVISION_STR::CapMemBlockConfig>::default_container word_type;
177  typedef std::vector<word_type> words_type;
178 
179  words_type words(detail::count_decoding_words(config));
180 
181  auto const coord = detail::get_coord(config);
182 
183  // randomize word content
184  for (auto& word : words) {
185  word = fisch::vx::container_cast(
186  fisch::vx::fill_random<decltype(fisch::vx::container_cast(std::declval<word_type>()))>(
187  gen));
188  }
189 
190  std::uniform_int_distribution<uintmax_t> hotbit_capmem_row(
191  0, halco::hicann_dls::vx::CHIP_REVISION_STR::CapMemRowOnCapMemBlock::max);
192  words.at(0) = word_type(1ul << hotbit_capmem_row(gen));
193 
194  // coordinate size is not power-of-two aligned
195  std::uniform_int_distribution<uintmax_t> capmem_column(
196  0, halco::hicann_dls::vx::CHIP_REVISION_STR::CapMemColumnOnCapMemBlock::max);
197  words.at(1) = word_type(capmem_column(gen));
198 
199  // select enums are not power-of-two aligned
200  std::uniform_int_distribution<uintmax_t> select(0, 2);
201  words.at(2) = word_type(select(gen));
202  words.at(5) = word_type(select(gen));
203 
204  std::uniform_int_distribution<uintmax_t> prescale_ramp(
205  0, haldls::vx::CHIP_REVISION_STR::CapMemBlockConfig::PrescaleRamp::max);
206  std::uniform_int_distribution<uintmax_t> prescale_pause(
207  0, haldls::vx::CHIP_REVISION_STR::CapMemBlockConfig::PrescalePause::max);
208  std::uniform_int_distribution<uintmax_t> msbs(0, 0xf);
209  std::uniform_int_distribution<uintmax_t> lsbs(0, 0xfffff);
210  words.at(6) = word_type(
211  msbs(gen) << 28 | prescale_ramp(gen) << 24 | prescale_pause(gen) << 20 | lsbs(gen));
212 
213  // decode words into container
214  haldls::vx::visit_preorder(config, coord, stadls::DecodeVisitor<words_type>{std::move(words)});
215 }
216 
217 template <>
218 inline void decode_ones(haldls::vx::CHIP_REVISION_STR::CapMemBlockConfig& /* config */)
219 {
220  throw std::runtime_error("CapMemBlockConfig can't be initialized with all ones");
221 }
222 
223 template <>
224 inline void decode_random(std::mt19937& gen, lola::vx::CHIP_REVISION_STR::CapMem& config)
225 {
226  typedef haldls::vx::detail::BackendContainerTrait<
227  lola::vx::CHIP_REVISION_STR::CapMem>::default_container word_type;
228  typedef std::vector<word_type> words_type;
229 
230  words_type words(detail::count_decoding_words(config));
231 
232  auto const coord = detail::get_coord(config);
233 
234  // randomize word content
235  for (auto& word : words) {
236  word = fisch::vx::container_cast(
237  fisch::vx::fill_random<decltype(fisch::vx::container_cast(std::declval<word_type>()))>(
238  gen));
239  }
240 
241  // overwrite CapMemBlockConfig words
242  for (size_t i = 0; auto& block : config.blocks) {
243  decode_random(gen, block);
244  words_type block_words;
245  haldls::vx::visit_preorder(
246  block, halco::hicann_dls::vx::CHIP_REVISION_STR::CapMemBlockConfigOnDLS(i),
247  stadls::EncodeVisitor<words_type>{block_words});
248  for (size_t j = 0; j < block_words.size(); ++j) {
249  words.at(i * block_words.size() + j) = block_words.at(j);
250  }
251  i++;
252  }
253 
254  // decode words into container
255  haldls::vx::visit_preorder(config, coord, stadls::DecodeVisitor<words_type>{std::move(words)});
256 }
257 
258 template <>
259 inline void decode_ones(lola::vx::CHIP_REVISION_STR::CapMem& /* config */)
260 {
261  throw std::runtime_error("CapMem can't be initialized with all ones");
262 }
263 
264 } // namespace stadls::vx
Fill the visited containers by decoding the specified configuration data.
Definition: visitors.h:132
Extract hardware configuration data for the visited containers.
Definition: visitors.h:212
T::coordinate_type get_coord(T const &config)
Get coordinate matching container, e.g.
Definition: decode.h:52
size_t count_decoding_words(T const &config)
Get number of words expected for decoding.
Definition: decode.h:79
void decode_random(std::mt19937 &gen, T &config)
Decode random data into a container.
Definition: decode.h:107
void decode_ones(T &config)
Decode data with all bits set to one into a container.
Definition: decode.h:133
Extract addresses for reading from hardware for the visited containers.
Definition: visitors.h:21