CGRA-ME
ClusteredMapper.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * The software programs comprising "CGRA-ME" and the documentation provided
3  * with them are copyright by its authors and the University of Toronto. Only
4  * non-commercial, not-for-profit use of this software is permitted without ex-
5  * plicit permission. This software is provided "as is" with no warranties or
6  * guarantees of support. See the LICENCE for more details. You should have re-
7  * ceived a copy of the full licence along with this software. If not, see
8  * <http://cgra-me.ece.utoronto.ca/license/>.
9  ******************************************************************************/
10 
11 #include <CGRA/ClusteredMapper.h>
12 #include <CGRA/Exception.h>
13 #include <CGRA/GraphAlgorithms.h>
14 #include <CGRA/MRRGProcedures.h>
17 #include <CGRA/dotparse.h>
18 
19 #include <algorithm>
20 #include <utility>
21 #include <functional>
22 #include <cmath>
23 #include <fstream>
24 
25 using std::cout;
26 using std::endl;
27 
28 AutoRegisterMapper ClusteredMapper_arm("ClusteredMapper",
29  [](std::shared_ptr<CGRA> cgra, int timelimit, const ConfigStore& args) {
30  return std::make_unique<ClusteredMapperDriver>(cgra, timelimit, args);},
31  false, // not a composite
32  "Clustered mapper.\n", { // required args
33  {"arch_id", "", ""},
34  {"initial_hfactor", 0.2, "History factor"},
35  {"initial_pfactor", 0.01, "Initial FU and routing overuse penalty"},
36  {"hfactor_factor", 1.01, "history factor increment"},
37  {"pfactor_factor", 1.07, "Multiplicative factor for overuse penalty, per iteration"},
38  {"initial_temperature_method", "", "Temperature that the anneal starts at"},
39  {"progress_dump_filename", "", "File to dump csv data status of each iteration. Empty disables."},
40  {"seed", 10, ""},
41  {"cost_function", 1, "Placement cost function could be 0 (BoundaryBox cost) or 1 (Scheduling cost)"},
42  {"swap_factor", 10, "Swaps per op node, per iteration"},
43  {"cluster", true, "Flag to set if the benchmark gets clustered or no"},
44  {"fanout_threshold", 5, "Sets the threshold of acceptable fanout"},
45  {"ram_ports", 0, "Set the number of ram ports"},
46  {"verbosity", 0, ""},
47  },
48  {} // optional arg regexes
49 );
50 
52  (std::shared_ptr<CGRA> cgra, int timelimit, const ConfigStore& args)
53  : Mapper(cgra, timelimit)
54  , l_arch_name(args.getString("arch_id"))
55  , l_rand_seed(args.getInt("seed"))
56  , l_initial_pfactor(args.getReal("initial_pfactor"))
57  , l_initial_hfactor(args.getReal("initial_hfactor"))
58  , l_p_factor_factor(args.getReal("pfactor_factor"))
59  , l_h_factor_factor(args.getReal("hfactor_factor"))
60  , l_swap_factor(args.getInt("swap_factor"))
61  , l_verbosity(args.getInt("verbosity"))
62  , l_mapper_args(args)
63  , l_cost_func(args.getInt("cost_function"))
64  , l_empty_mapping_result(cgra, 0, nullptr)
65  , l_print(0)
66  , l_cluster(args.getBool("cluster"))
67  , l_fanout_threshold(args.getInt("fanout_threshold"))
68  , l_ram_ports(args.getInt("ram_ports"))
69 { }
70 
71 Mapping ClusteredMapperDriver::mapOpGraph (std::shared_ptr<OpGraph> opgraph,
72  int II, const MRRG& mrrg,
73  std::unordered_map<std::string, std::string> fix_port) {
74  std::cout<< "SEED: " << l_rand_seed << std::endl;
75  std::cout <<"Num of ops: " << opgraph->opNodes().size();
76  PrintOnDestructionChronoSequence timing_seq("PCKM:Packing Mapper", &std::cout );
77  // Setting up the mapping
79  mrrg.initiationInterval(), opgraph);
81  const Module& top_mod = cgra->getTopLevelModule();
82  l_isElastic = top_mod.isElastic;
83 
84  if(!isAllOpsSupported(*opgraph, mrrg)) {
85  throw cgrame_mapper_error("Not all ops are supported by the architecture");
87  }
88  // Running either the elastic or the static version of the code
89  Mapping mapping_result = l_empty_mapping_result;
90  if (l_isElastic) {
91  mapping_result = mapElastic(opgraph, II, mrrg, fix_port, timing_seq);
92  } else {
93  mapping_result = mapStatic(opgraph, II, mrrg, fix_port, timing_seq);
94  }
95  mapping_result.solve_time_in_seconds = timing_seq.secondsSinceStart();
96  return mapping_result;
97 
98 }
99 
100 
101 Mapping ClusteredMapperDriver::mapStatic (std::shared_ptr<OpGraph> opgraph,
102  int II,
103  const MRRG& mrrg,
104  std::unordered_map<std::string, std::string> fix_port,
105  PrintOnDestructionChronoSequence& timing_seq) {
106  l_op_sched = new OpScheduler(*opgraph, mrrg, l_arch_name);
107  // Run the clustring algorthim to create clusters for the DFG nodes
108  TMPack am_clust(*this, &cgra->getTopLevelModule(), opgraph, mrrg, cgra->getNumRows(), cgra->getNumCols(), l_iteration_interval, l_isElastic);
109 
110  bool reschedule = true;
111 
112 
113  while (reschedule) {
115  timing_seq.tick("Schedule", 0.0);
116  for (auto& op_schedule : l_schedule) {
117  std::cout << op_schedule.first->getName() << " " << op_schedule.second << std::endl;
118  }
119  am_clust.unsetReschedule();
120  am_clust.setSchedule(l_schedule);
121  reschedule = am_clust.clusterPEs(l_cluster);
122  timing_seq.tick("TMPACK", 0.0);
124  }
125  l_clusters = am_clust.getClusters();
128 
129  std::cout << "TMPack Result" << std::endl;
130  int clusters_greater_one = 0;
131  for (int i = 0; i < l_clusters.size(); i++) {
132  std::cout << "cluster " << i << std::endl;
133  if (l_clusters[i].size() > 1) clusters_greater_one++;
134  for (auto& op : l_clusters[i]) {
135  std::cout << *op << " ";
136  std::cout << l_op_cluster_index[op] << std::endl;
137  }
138  }
139 
140  AnnealPlacer am_placer(*this, *opgraph, mrrg, fix_port, cgra->getNumRows(), cgra->getNumCols(), l_isElastic);
141  PathFinder am_router(*this, *opgraph, mrrg, l_isElastic);
142 
143  am_placer.clearPlacement();
144  am_placer.setInitialPlacement();
145  float temprature = am_placer.determineTemperature(25);
146  Mapping mapping_result = l_empty_mapping_result;
147  int i = 0;
148  while (mapping_result.getStatus() != MappingStatus::success && i < 1000) {
149  std::cout << "ITERATION: " << i << std::endl;
150  if (timelimit != 0 && timing_seq.secondsSinceStart() >= timelimit) {
151  mapping_result.setStatus(MappingStatus::timeout);
152  break;
153  }
155  l_empty_mapping_result = am_placer.placeOpGraph(temprature);
156  timing_seq.tick("Placer iteration" + std::to_string(i), 0.01);
157  if (i < 10) {
158  // printPlacementNeato(i, *opgraph, l_empty_mapping_result, l_schedule);
159  }
160  mapping_result = am_router.routeOpGraph(std::move(l_empty_mapping_result));
161  timing_seq.tick("Router iteration" + std::to_string(i), 0.01);
162  temprature = am_placer.determineTemperature(10);
163  i++;
164  }
165  timing_seq.tick("Place and route", 0.01);
166  //am_router.printCriticalPath();
167  std::cout << "[INFO] clusters greater than 1: " << clusters_greater_one << std::endl;
168  return mapping_result;
169 }
170 
171 
172 Mapping ClusteredMapperDriver::mapElastic (std::shared_ptr<OpGraph> opgraph,
173  int II,
174  const MRRG& mrrg,
175  std::unordered_map<std::string, std::string> fix_port,
177  // Run the clustring algorthim to create clusters for the DFG nodes
178  TMPack am_clust(*this, &cgra->getTopLevelModule(), opgraph, mrrg, cgra->getNumRows(), cgra->getNumCols(), II, l_isElastic);
179  am_clust.clusterPEs(l_cluster);
180  l_clusters = am_clust.getClusters();
183  std::cout << "Final Result" << std::endl;
184  for (auto& cluster : l_clusters) {
185  std::cout << "cluster" << std::endl;
186  for (auto& op : cluster) {
187  std::cout << *op << std::endl;
188  }
189  }
190 
191  AnnealPlacer am_placer(*this, *opgraph, mrrg, fix_port, cgra->getNumRows(), cgra->getNumCols(), l_isElastic);
192  PathFinder am_router(*this, *opgraph, mrrg, l_isElastic);
193 
194  am_placer.clearPlacement();
195  am_placer.setInitialPlacement();
196  float temprature = am_placer.determineTemperature(20);
197  Mapping mapping_result = l_empty_mapping_result;
198  int i = 0;
199  while (mapping_result.getStatus() != MappingStatus::success && i < 1000) {
200  std::cout << "ITERATION: " << i << std::endl;
201  if (timelimit != 0 && timing_seq.secondsSinceStart() >= timelimit) {
202  mapping_result.setStatus(MappingStatus::timeout);
203  break;
204  }
206  l_empty_mapping_result = am_placer.placeOpGraph(temprature);
207  if (i < 10) {
208  // printPlacementNeato(i, *opgraph, base.empty_mapping_result, base.schedule);
209  }
210  mapping_result = am_router.routeOpGraph(std::move(l_empty_mapping_result));
211  temprature = am_placer.determineTemperature(0.1);
212  i++;
213  }
214  return mapping_result;
215 }
216 
218  if (l_isElastic) return kUndefLatency;
219  Latency cycles_to_sink = l_schedule.at(sink) - l_schedule.at(source);
220  if (cycles_to_sink < 0) {
221  cycles_to_sink = l_iteration_interval - (std::abs(cycles_to_sink)%l_iteration_interval);
222  }
223  // If backedge and the cycles is 0
224  if (sink->getOpCode() == OpCode::PHI &&
225  source->getOpCode() != OpCode::INPUT &&
226  source->getOpCode() != OpCode::CONST &&
227  source->getOpCode() != OpCode::INPUT_PRED &&
228  cycles_to_sink == 0) {
229 
230  cycles_to_sink = l_iteration_interval - 1 + l_op_sched->getLowerBoundEdge(source->getOpCode(), sink->getOpCode());
231  }
232  if (sink == source) cycles_to_sink = l_iteration_interval;
233  if (l_isElastic) cycles_to_sink = kUndefLatency;
234  return cycles_to_sink;
235 }
236 
237 bool ClusteredMapperDriver::isAllOpsSupported(const OpGraph& opgraph, const MRRG& mrrg) {
238  const auto classes = computeNodeClassLists(mrrg);
239  for (auto op : opgraph.opNodes()) {
240  bool op_supported = false;
241  for (auto mrrg_node : classes.function_nodes) {
242  if (mrrg_node->canMapOp(op)) {
243  op_supported = true;
244  }
245  }
246  if (!op_supported) {
247  throw cgrame_error(op->getName() + " Could not be mapped");
248  return false;
249  }
250  }
251  return true;
252 }
253 
254 void ClusteredMapperDriver::printPlacementNeato(int i, const OpGraph& opgraph, Mapping placed, std::unordered_map<OpGraphOpDesc, int> sched) {
255  std::vector<std::string> colors = {"antiquewhite4", "aquamarine3", "azure3", "blue", "red", "blueviolet", "brown4", "burlywood4",
256  "cadetblue4", "chartreuse4", "chocolate4", "coral4", "cyan2", "darkgoldenrod", "crimson"};
257  int color_index = 0;
258  std::map<OpGraphOpDesc, std::string> ops_to_modules;
259  std::ofstream os{"placement_" + std::to_string(i) + ".dot"};
260  Module& topModule = this->cgra->getTopLevelModule();
261  os << "digraph " << topModule.getName() << " {\n";
262  bool set_color = false;
263  for (auto& module : topModule.submodules) {
264  if (module.first.find("pred") != std::string::npos) continue;
265  os << module.first << "[ height=.5,width=.5,fontsize=8, ";
266  os << " pos = \"" << module.second->loc.x_coord << "," << "-" << module.second->loc.y_coord << "!\"";
267  os << " ,label = \"";
268  for (auto& op : opgraph.opNodes()) {
269  MRRG::NodeDescriptor mrrg_node = placed.getSingleMapping(op);
270  Module* par = mrrg_node->parent;
271  if (par->loc.x_coord == module.second->loc.x_coord
272  && par->loc.y_coord == module.second->loc.y_coord ) {
273  set_color = true;
274  os << " \\n" << op->getName();
275  ops_to_modules.emplace(op, module.first);
276  }
277  }
278  if (set_color) {
279  os << "\"color=" << colors[color_index%colors.size()] << "]" << "\n";
280  color_index++;
281  } else {
282  os << module.first <<"\"]" << "\n";
283  }
284  set_color = false;
285  }
286 
287  for (auto& val : opgraph.valNodes()) {
288  auto src = val->input;
289  MRRG::NodeDescriptor src_mrrg_node = placed.getSingleMapping(src);
290  Module* src_par = src_mrrg_node->parent;
291  int src_x = src_par->loc.x_coord;
292  int src_y = src_par->loc.y_coord;
293  for (auto& snk : val->output) {
294  int cycles_to_sink = sched[snk] - sched[src];
295  if (cycles_to_sink < 0) {
296  cycles_to_sink = 0; // (std::abs(cycles_to_sink)%II);
297  }
298  if (src == snk) cycles_to_sink = 1;
299 
300  MRRG::NodeDescriptor snk_mrrg_node = placed.getSingleMapping(snk);
301  Module* snk_par = snk_mrrg_node->parent;
302  int snk_x = snk_par->loc.x_coord;
303  int snk_y = snk_par->loc.y_coord;
304  if (src_x != snk_x || src_y != snk_y) {
305  os << ops_to_modules[src] << "->" << ops_to_modules[snk] << "[";
306  os << "label = \"" << cycles_to_sink;
307  os << "\"color=" << colors[color_index%colors.size()] << ",fontsize=8]" << "\n";
308  color_index++;
309  }
310  }
311  }
312  os << "}\n";
313  return;
314 }
Location::x_coord
unsigned x_coord
Definition: Module.h:157
Module::submodules
std::map< std::string, Module * > submodules
Definition: Module.h:227
OpScheduler::getSchedule
std::unordered_map< const OpGraphOp *, int > getSchedule(SchedType type)
Definition: OpScheduler.cpp:643
ClusteredMapperDriver::l_op_sched
OpScheduler * l_op_sched
Definition: ClusteredMapper.h:86
CodeProfiling.h
TMPack::getClusters
std::vector< std::vector< OpGraphOpDesc > > getClusters()
Definition: ClusteredMapper.h:223
ClusteredMapperDriver::ClusteredMapperDriver
ClusteredMapperDriver(std::shared_ptr< CGRA > cgra, int timelimit, const ConfigStore &args)
Definition: ClusteredMapper.cpp:52
ClusteredMapperDriver::printPlacementNeato
void printPlacementNeato(int i, const OpGraph &opgraph, Mapping placed, std::unordered_map< OpGraphOpDesc, int > sched)
Definition: ClusteredMapper.cpp:254
OpCode::CONST
@ CONST
TMPack::extended_sched_const
std::unordered_map< opPair, int, pair_hash > extended_sched_const
Definition: ClusteredMapper.h:230
MRRG
Definition: MRRG.h:216
dotparse.h
OpCode::PHI
@ PHI
ClusteredMapperDriver::l_schedule
std::unordered_map< OpGraphOpDesc, int > l_schedule
Definition: ClusteredMapper.h:90
GraphAlgorithms.h
PathFinder::routeOpGraph
Mapping routeOpGraph(Mapping placement)
Definition: Pathfinder.cpp:51
Mapping::getSingleMapping
MRRG::NodeDescriptor getSingleMapping(OpGraph::NodeDescriptor key) const
Definition: Mapping.h:56
ClusteredMapperDriver::isAllOpsSupported
bool isAllOpsSupported(const OpGraph &opgraph, const MRRG &mrrg)
Definition: ClusteredMapper.cpp:237
AnnealPlacer::setInitialPlacement
void setInitialPlacement()
Definition: AnnealPlacer.cpp:620
Latency
int Latency
Definition: ClusteredMapper.h:35
Mapping::solve_time_in_seconds
double solve_time_in_seconds
Definition: Mapping.h:110
TMPack::getOpsNodeNames
std::unordered_map< OpGraphOpDesc, std::vector< std::string > > getOpsNodeNames()
Definition: ClusteredMapper.h:222
Mapping::getCGRA_shared
auto getCGRA_shared() const
Definition: Mapping.h:43
OpScheduler::getLowerBoundEdge
int getLowerBoundEdge(OpGraphOpCode op1, OpGraphOpCode op2)
Definition: OpScheduler.h:74
OpGraph::valNodes
auto & valNodes() const
Definition: OpGraph.h:314
AnnealPlacer::clearPlacement
void clearPlacement()
Definition: AnnealPlacer.cpp:633
AutoRegisterMapper
Special helper for registering mappers to the default mapper registry.
Definition: Mapper.h:200
ConfigStore
Definition: ConfigStore.h:76
ClusteredMapperDriver::l_arch_name
const std::string l_arch_name
Definition: ClusteredMapper.h:83
Mapping::getStatus
MappingStatus getStatus() const
Definition: Mapping.h:39
Mapper
Common interface for mappers.
Definition: Mapper.h:28
ChronoSequence::secondsSinceStart
double secondsSinceStart()
Definition: CodeProfiling.h:94
AnnealPlacer::placeOpGraph
Mapping placeOpGraph(float temp)
Definition: AnnealPlacer.cpp:640
ClusteredMapperDriver::l_op_cluster_index
std::map< OpGraphOpDesc, int > l_op_cluster_index
Definition: ClusteredMapper.h:88
OpScheduler
Definition: OpScheduler.h:39
to_string
const std::string & to_string(const OpGraphOpCode &opcode)
Definition: OpGraph.cpp:111
MRRGNode::parent
Module * parent
Definition: MRRG.h:119
Mapping
Definition: Mapping.h:31
TMPack::setSchedule
void setSchedule(std::unordered_map< OpGraphOpDesc, int > s)
Definition: ClusteredMapper.h:227
Exception.h
TMPack::clusterPEs
bool clusterPEs(bool cluster)
Definition: TMPack.cpp:683
ClusteredMapperDriver::mapElastic
Mapping mapElastic(std::shared_ptr< OpGraph > opgraph, const int II, const MRRG &mrrg, std::unordered_map< std::string, std::string > fix_port, PrintOnDestructionChronoSequence timing_seq)
Definition: ClusteredMapper.cpp:172
TMPack::unsetReschedule
void unsetReschedule()
Definition: ClusteredMapper.h:228
MappingStatus::timeout
@ timeout
ClusteredMapperDriver::mapOpGraph
Mapping mapOpGraph(std::shared_ptr< OpGraph > opgraph, const int II, const MRRG &mrrg, std::unordered_map< std::string, std::string > fix_port) override
main function to map the OpGraph to the device description
Definition: ClusteredMapper.cpp:71
OpCode::INPUT
@ INPUT
ClusteredMapperDriver::l_ops_to_node_names
std::unordered_map< OpGraphOpDesc, std::vector< std::string > > l_ops_to_node_names
Definition: ClusteredMapper.h:89
OpGraph::opNodes
auto & opNodes() const
Definition: OpGraph.h:313
UserModules.h
ClusteredMapperDriver::l_cluster
const bool l_cluster
Definition: ClusteredMapper.h:80
ClusteredMapperDriver::getCyclesToSink
const Latency getCyclesToSink(OpGraphOpDesc source, OpGraphOpDesc sink)
Definition: ClusteredMapper.cpp:217
OpCode::INPUT_PRED
@ INPUT_PRED
Module
Definition: Module.h:163
ClusteredMapperDriver::l_isElastic
bool l_isElastic
Definition: ClusteredMapper.h:81
SchedType::ASAP
@ ASAP
ClusteredMapperDriver::l_empty_mapping_result
Mapping l_empty_mapping_result
Definition: ClusteredMapper.h:91
ClusteredMapperDriver::mapStatic
Mapping mapStatic(std::shared_ptr< OpGraph > opgraph, const int II, const MRRG &mrrg, std::unordered_map< std::string, std::string > fix_port, PrintOnDestructionChronoSequence &timing_seq)
Definition: ClusteredMapper.cpp:101
PrintOnDestructionChronoSequence
Definition: CodeProfiling.h:121
ChronoSequence::tick
TickResult tick(std::string timepoint_name, double threshold=0.0, std::ostream *os=nullptr)
Definition: CodeProfiling.h:54
AnnealPlacer
Implementation of the Anneal Placer.
Definition: ClusteredMapper.h:257
ClusteredMapper_arm
AutoRegisterMapper ClusteredMapper_arm("ClusteredMapper", [](std::shared_ptr< CGRA > cgra, int timelimit, const ConfigStore &args) { return std::make_unique< ClusteredMapperDriver >(cgra, timelimit, args);}, false, "Clustered mapper.\n", { {"arch_id", "", ""}, {"initial_hfactor", 0.2, "History factor"}, {"initial_pfactor", 0.01, "Initial FU and routing overuse penalty"}, {"hfactor_factor", 1.01, "history factor increment"}, {"pfactor_factor", 1.07, "Multiplicative factor for overuse penalty, per iteration"}, {"initial_temperature_method", "", "Temperature that the anneal starts at"}, {"progress_dump_filename", "", "File to dump csv data status of each iteration. Empty disables."}, {"seed", 10, ""}, {"cost_function", 1, "Placement cost function could be 0 (BoundaryBox cost) or 1 (Scheduling cost)"}, {"swap_factor", 10, "Swaps per op node, per iteration"}, {"cluster", true, "Flag to set if the benchmark gets clustered or no"}, {"fanout_threshold", 5, "Sets the threshold of acceptable fanout"}, {"ram_ports", 0, "Set the number of ram ports"}, {"verbosity", 0, ""}, }, {})
Mapper::cgra
std::shared_ptr< CGRA > cgra
Definition: Mapper.h:45
OpGraphOp
Definition: OpGraph.h:131
MRRGNode
Definition: MRRG.h:60
OpGraphOp::getOpCode
auto getOpCode() const
Definition: OpGraph.h:156
PathFinder
Implementation of the.
Definition: ClusteredMapper.h:119
Mapping::clear
void clear()
Definition: Mapping.cpp:95
ConfigStore::getString
const std::string & getString(const std::string &key) const
Definition: ConfigStore.h:136
OpScheduler::extended_sched_const
std::unordered_map< opPair, int, pair_hash > extended_sched_const
Definition: OpScheduler.h:89
Module::getName
auto & getName() const
Definition: Module.h:247
TMPack
Definition: ClusteredMapper.h:170
Module::isElastic
bool isElastic
Definition: Module.h:236
AnnealPlacer::determineTemperature
float determineTemperature(float scale)
Definition: AnnealPlacer.cpp:454
MappingStatus::success
@ success
Module::loc
Location loc
Definition: Module.h:239
MRRG::initiationInterval
int initiationInterval() const
Definition: MRRG.h:346
MRRGProcedures.h
ClusteredMapperDriver::l_rand_seed
const int l_rand_seed
Definition: ClusteredMapper.h:71
ClusteredMapperDriver::kUndefLatency
static constexpr Latency kUndefLatency
Definition: ClusteredMapper.h:42
ClusteredMapperDriver::l_iteration_interval
int l_iteration_interval
Definition: ClusteredMapper.h:82
ConfigStore::getInt
long long getInt(const std::string &key) const
Definition: ConfigStore.h:146
cgrame_mapper_error
Definition: Exception.h:27
ClusteredMapperDriver::l_clusters
std::vector< std::vector< OpGraphOpDesc > > l_clusters
Definition: ClusteredMapper.h:87
ConfigStore::getReal
double getReal(const std::string &key) const
Definition: ConfigStore.h:156
ClusteredMapper.h
OpGraph
Definition: OpGraph.h:215
cgrame_error
Definition: Exception.h:20
TMPack::getOpClusterIndex
std::map< OpGraphOpDesc, int > getOpClusterIndex()
Definition: ClusteredMapper.h:224
Mapping::setStatus
void setStatus(MappingStatus new_status)
Definition: Mapping.h:40
computeNodeClassLists
MRRGNodeClassLists computeNodeClassLists(const MRRG &mrrg)
Definition: MRRGProcedures.cpp:169
ConfigStore::getBool
bool getBool(const std::string &key) const
Definition: ConfigStore.h:166
Mapper::timelimit
int timelimit
Definition: Mapper.h:46
Location::y_coord
unsigned y_coord
Definition: Module.h:158