byteman  1.3 (Build #225)
Bitstream relocation and manipulation tool
byteman.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2022 Kristiyan Manev (University of Manchester)
3  *
4  * Licensed under the Apache License, Version 2.0(the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 #include<iostream>
18 #include<stdexcept>
19 #include<fstream>
20 
21 #include "byteman.h"
22 #include "Common/str.h"
23 #include "Common/Coords.h"
24 
25 using namespace std;
26 
27 /**************************************************************************/
35 int main(int argc, char * argv[])
36 {
37  byteman bytemanInstance;
38  string command;
39  if(argc <= 1)
40  bytemanInstance.help("", 1);//show usage and terminate with an error code
41  try {
42  bool readSTDIN = false;
43  for(int argi = 1 ; argi < argc ; argi++) {
44  if(argv[argi][0] == '-' && !command.empty()){ //new cmd and old cmd not empty
45  bytemanInstance.parse(command);
46  command.clear();
47  }
48  if(command.empty())
49  command.append(argv[argi]);
50  else
51  command.append(" ").append(argv[argi]);
52  if(command == "-stdin" || command == "-s"){
53  readSTDIN = true;
54  command.clear();
55  }
56  }
57  if(!command.empty())
58  bytemanInstance.parse(command);
59  while(readSTDIN){
60  getline(cin, command);
61  if(!cin.good())
62  return 0;
63  if(command != "" && command.at(command.find_first_not_of(" \t")) != '#'){//parse the command only if it doesnt start with '#' or if not empty
64  if(string::npos != command.find("#"))
65  command = command.substr(0, command.find("#"));//if there is a comment in the current line, remove it
66  bytemanInstance.parse(command);
67  }
68  }
69  } catch (const exception &e){
70  cout << "The program was terminated with message: \n\t'" << e.what() << "'\nWhile trying to execute command: \n\t'" << command << "'" << endl;
71  return 1;
72  }
73  return 0;
74 }
75 
77  #ifdef XS7
78  mainXS7.instanceName = "Main Xil S7";
79  tempXS7.instanceName = "Temp Xil S7";
80  #endif //XS7
81 
82  #ifdef XUS
83  mainXUS.instanceName = "Main Xil US";
84  tempXUS.instanceName = "Temp Xil US";
85  #endif //XUS
86 
87  #ifdef XUSP
88  mainXUSP.instanceName = "Main Xil US+ ";
89  tempXUSP.instanceName = "Temp Xil US+ ";
90  #endif //XUSP
91 }
93 
94 }
95 
96 void byteman::parse(string command)
97 {
98  command = str::replace(command, '=',' ');
99  command = str::replace(command, ':',' ');
100  if (command.at(0) == '-') command.erase(0, 1);
101  string params = str::findStringAndGetAllAfter(command, " ");
102  command = str::stringToLower(command);
103 
104  if(str::iff::firstStringWordIs(command, "h", "help"))//check if help first
105  help(params, 0);
106  else if(Architecture::Unknown == selectedArchitecture) //then check if architecture
107  setArchitecture(command);
108  else if(str::iff::firstStringWordIs(command, "v", "verbose")) //check the rest of commands
109  parseVerbose(params);
110  else if(str::iff::firstStringWordIs(command, "w", "warn"))
111  parseWarn(params);
112  else if(str::iff::firstStringWordIs(command, "r", "region"))
113  parseRegion(params);
114  else if(str::iff::firstStringWordIs(command, "b", "blank"))
115  parseBlank(params);
116  else if(str::iff::firstStringWordIs(command, "c", "change"))
117  parseChange(params);
118  else if(str::iff::firstStringWordIs(command, "d", "device"))
119  parseDevice(params);
120  else if(str::iff::firstStringWordIs(command, "i", "input"))
121  parseInput(params);
122  else if(str::iff::firstStringWordIs(command, "m", "merge"))
123  parseMerge(params);
124  else if(str::iff::firstStringWordIs(command, "o", "output"))
125  parseOutput(params);
126  else if(str::iff::firstStringWordIs(command, "a", "assembly"))
127  parseAssembly(params);
128  #if !defined(NDEBUG)
129  else if(str::iff::firstStringWordIs(command, "t", "test"))
130  parseTest(params);
131  #endif
132  else if(str::iff::firstStringWordIs(command, "e", "exit"))
133  exit(0);
134  else
135  throw runtime_error("Could not parse command. Consider checking out \"bytemap -help\".");
136 }
137 
138 /**************************************************************************/
147 {
148  string commandWithoutTheValidParams = "";
149  options = SelectedOptions();
150  params = str::replace(params, ',', ' ');
151  stringstream ss(params);
152  string param;
153  while (!ss.eof()) {
154  ss >> param;
155  if("main" == param || "first" == param)options.mainBufferSelected = true;
156  else if("temp" == param || "second" == param)options.tempBufferSelected = true;
157  else {
158  if(commandWithoutTheValidParams != "")
159  commandWithoutTheValidParams.append(" ");
160  commandWithoutTheValidParams.append(param);
161  }
162  param.clear();
163  }
164  if(!options.mainBufferSelected && !options.tempBufferSelected) // by default, choose the main buffer
165  options.mainBufferSelected = true;
166  return commandWithoutTheValidParams;
167 }
168 
169 void byteman::parseVerbose(string verboseCmd)
170 {
171  int verboseValue;
172  if(!str::parse::multipleInts(verboseCmd, verboseValue))verboseValue = 1; // if nothing was given, default to 1
173 
174  #ifdef XS7
175  if(Architecture::Xilinx_Series7 == selectedArchitecture){
176  mainXS7.enableLog = verboseValue;
177  tempXS7.enableLog = verboseValue;
178  }
179  #endif
180  #ifdef XUS
181  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
182  mainXUS.enableLog = verboseValue;
183  tempXUS.enableLog = verboseValue;
184  }
185  #endif
186  #ifdef XUSP
187  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
188  mainXUSP.enableLog = verboseValue;
189  tempXUSP.enableLog = verboseValue;
190  }
191  #endif
192 }
193 void byteman::parseWarn(string warnCmd)
194 {
195  int warnValue;
196  if(!str::parse::multipleInts(warnCmd, warnValue))warnValue = 1; // if nothing was given, default to 1
197 
198  #ifdef XS7
199  if(Architecture::Xilinx_Series7 == selectedArchitecture){
200  mainXS7.enableWarn = warnValue;
201  tempXS7.enableWarn = warnValue;
202  }
203  #endif
204  #ifdef XUS
205  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
206  mainXUS.enableWarn = warnValue;
207  tempXUS.enableWarn = warnValue;
208  }
209  #endif
210  #ifdef XUSP
211  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
212  mainXUSP.enableWarn = warnValue;
213  tempXUSP.enableWarn = warnValue;
214  }
215  #endif
216 }
217 void byteman::parseRegion(string regionCmd)
218 {
219  string params = str::parse::allStringWords(regionCmd);
220  Rect2D rect;
221  str::parse::multipleInts(regionCmd, rect.position.row, rect.position.col, rect.size.row, rect.size.col);
222  #ifdef XS7
223  if(Architecture::Xilinx_Series7 == selectedArchitecture){
224  mainXS7.region(params, rect);
225  tempXS7.region(params, rect);
226  }
227  #endif
228  #ifdef XUS
229  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
230  mainXUS.region(params, rect);
231  tempXUS.region(params, rect);
232  }
233  #endif
234  #ifdef XUSP
235  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
236  mainXUSP.region(params, rect);
237  tempXUSP.region(params, rect);
238  }
239  #endif
240 }
241 void byteman::parseBlank(string blankCmd)
242 {
243  string params = parseParamsAndRemoveThemFromString(blankCmd);
244  #ifdef XS7
245  if(Architecture::Xilinx_Series7 == selectedArchitecture){
246  if(options.mainBufferSelected)
247  mainXS7.blank(params);
248  if(options.tempBufferSelected)
249  tempXS7.blank(params);
250  }
251  #endif
252  #ifdef XUS
253  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
254  if(options.mainBufferSelected)
255  mainXUS.blank(params);
256  if(options.tempBufferSelected)
257  tempXUS.blank(params);
258  }
259  #endif
260  #ifdef XUSP
261  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
262  if(options.mainBufferSelected)
263  mainXUSP.blank(params);
264  if(options.tempBufferSelected)
265  tempXUSP.blank(params);
266  }
267  #endif
268 }
269 void byteman::parseChange(string changeCmd)
270 {
271  string changeParams = parseParamsAndRemoveThemFromString(changeCmd);
272  #ifdef XS7
273  if(Architecture::Xilinx_Series7 == selectedArchitecture){
274  if(options.mainBufferSelected)
275  mainXS7.change(changeParams);
276  if(options.tempBufferSelected)
277  tempXS7.change(changeParams);
278  }
279  #endif
280  #ifdef XUS
281  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
282  if(options.mainBufferSelected)
283  mainXUS.change(changeParams);
284  if(options.tempBufferSelected)
285  tempXUS.change(changeParams);
286  }
287  #endif
288  #ifdef XUSP
289  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
290  if(options.mainBufferSelected)
291  mainXUSP.change(changeParams);
292  if(options.tempBufferSelected)
293  tempXUSP.change(changeParams);
294  }
295  #endif
296 }
297 void byteman::parseDevice(string deviceCmd)
298 {
299  string deviceName = parseParamsAndRemoveThemFromString(deviceCmd);
300  #ifdef XS7
301  if(Architecture::Xilinx_Series7 == selectedArchitecture){
302  if(options.mainBufferSelected)
303  mainXS7.setDeviceByNameOrThrow(deviceName);
304  if(options.tempBufferSelected)
305  tempXS7.setDeviceByNameOrThrow(deviceName);
306  }
307  #endif
308  #ifdef XUS
309  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
310  if(options.mainBufferSelected)
311  mainXUS.setDeviceByNameOrThrow(deviceName);
312  if(options.tempBufferSelected)
313  tempXUS.setDeviceByNameOrThrow(deviceName);
314  }
315  #endif
316  #ifdef XUSP
317  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
318  if(options.mainBufferSelected)
319  mainXUSP.setDeviceByNameOrThrow(deviceName);
320  if(options.tempBufferSelected)
321  tempXUSP.setDeviceByNameOrThrow(deviceName);
322  }
323  #endif
324 }
325 void byteman::parseInput(string inputCmd)
326 {
327  string params = parseParamsAndRemoveThemFromString(inputCmd);
328  string filename = str::parse::lastStringWord(params);
329  #ifdef XS7
330  if(Architecture::Xilinx_Series7 == selectedArchitecture){
331  if(options.mainBufferSelected)
332  mainXS7.readBitstream(filename);
333  if(options.tempBufferSelected)
334  tempXS7.readBitstream(filename);
335  }
336  #endif
337  #ifdef XUS
338  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
339  if(options.mainBufferSelected)
340  mainXUS.readBitstream(filename);
341  if(options.tempBufferSelected)
342  tempXUS.readBitstream(filename);
343  }
344  #endif
345  #ifdef XUSP
346  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
347  if(options.mainBufferSelected)
348  mainXUSP.readBitstream(filename);
349  if(options.tempBufferSelected)
350  tempXUSP.readBitstream(filename);
351  }
352  #endif
353 }
354 void byteman::parseOutput(string outputCmd)
355 {
356  string params = str::parse::allStringWordsWithoutLastStringWord(outputCmd);
357  string filename = str::parse::lastStringWord(outputCmd);
358  Rect2D rect;
359  str::parse::multipleInts(outputCmd, rect.position.row, rect.position.col, rect.size.row, rect.size.col);
360  #ifdef XS7
361  if(Architecture::Xilinx_Series7 == selectedArchitecture){
362  mainXS7.writeBitstream(filename, params, rect);
363  }
364  #endif
365  #ifdef XUS
366  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
367  mainXUS.writeBitstream(filename, params, rect);
368  }
369  #endif
370  #ifdef XUSP
371  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
372  mainXUSP.writeBitstream(filename, params, rect);
373  }
374  #endif
375 }
376 void byteman::parseMerge(string mergeCmd)
377 {
378  string params = str::parse::allStringWords(mergeCmd);
379  Rect2D rect;
380  Coord2D dst;
381  str::parse::multipleInts(mergeCmd, rect.position.row, rect.position.col, rect.size.row, rect.size.col, dst.row, dst.col);
382  #ifdef XS7
383  if(Architecture::Xilinx_Series7 == selectedArchitecture){
384  mainXS7.merge(&tempXS7, params, rect, dst);
385  }
386  #endif
387  #ifdef XUS
388  if(Architecture::Xilinx_UltraScale == selectedArchitecture){
389  mainXUS.merge(&tempXUS, params, rect, dst);
390  }
391  #endif
392  #ifdef XUSP
393  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture){
394  mainXUSP.merge(&tempXUSP, params, rect, dst);
395  }
396  #endif
397 }
398 void byteman::parseAssembly(string assemblyCmd)
399 {
400  string filenameIn = str::parse::nthStringWord(assemblyCmd, 0);
401  string filenameOut = str::parse::nthStringWord(assemblyCmd, 1);
402  #ifdef XS7
403  if(Architecture::Xilinx_Series7 == selectedArchitecture)
404  mainXS7.assembler(filenameIn, filenameOut);
405  #endif
406  #ifdef XUS
407  if(Architecture::Xilinx_UltraScale == selectedArchitecture)
408  mainXUS.assembler(filenameIn, filenameOut);
409  #endif
410  #ifdef XUSP
411  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture)
412  mainXUSP.assembler(filenameIn, filenameOut);
413  #endif
414 }
415 #if !defined(NDEBUG)
416 void byteman::parseTest(string testCmd)
417 {
418  uint32_t testValue;
419  if(!str::parse::multipleUints(testCmd, testValue))
420  testValue = 0;
421 
422  testCmd = str::stringToLower(testCmd);
423  bool usableFramesOnly = false;
424  if(str::iff::stringContains(testCmd, "usableframes", "mappedframes"))
425  usableFramesOnly = true;
426 
427  bool testValueEqual = true;
428  if(str::iff::stringContains(testCmd, "notequal"))
429  testValueEqual = false;
430  #ifdef XS7
431  if(Architecture::Xilinx_Series7 == selectedArchitecture)
432  mainXS7.test(usableFramesOnly, testValueEqual, testValue);
433  #endif
434  #ifdef XUS
435  if(Architecture::Xilinx_UltraScale == selectedArchitecture)
436  mainXUS.test(usableFramesOnly, testValueEqual, testValue);
437  #endif
438  #ifdef XUSP
439  if(Architecture::Xilinx_UltraScalePlus == selectedArchitecture)
440  mainXUSP.test(usableFramesOnly, testValueEqual, testValue);
441  #endif
442 }
443 #endif
444 
445 void byteman::setArchitecture(string arch)
446 {
447  arch = str::stringToLower(arch);
448  #ifdef XUSP
449  if(str::iff::stringContains(arch, "xusp")
450  || ( str::iff::stringContains(arch, "xilinx")
451  && str::iff::stringContains(arch, "ultrascale", "us")
452  && str::iff::stringContains(arch, "plus", "+")
453  )
454  ) {
455  selectedArchitecture = Architecture::Xilinx_UltraScalePlus;
456  return;
457  }
458  #endif//XUSP
459  #ifdef XUS
460  if(str::iff::stringContains(arch, "xus")
461  || ( str::iff::stringContains(arch, "xilinx")
462  && str::iff::stringContains(arch, "ultrascale", "us")
463  )
464  ) {
465  selectedArchitecture = Architecture::Xilinx_UltraScale;
466  return;
467  }
468  #endif//XUS
469  #ifdef XS7
470  if(str::iff::stringContains(arch, "xs7")
471  || ( str::iff::stringContains(arch, "xilinx")
472  && str::iff::stringContains(arch, "series")
473  && str::iff::stringContains(arch, "7")
474  )
475  ) {
476  selectedArchitecture = Architecture::Xilinx_Series7;
477  return;
478  }
479  #endif//XS7
480  throw runtime_error(string("Unknown architecture: \"").append(arch).append("\"."));
481 }
int main(int argc, char *argv[])
Definition: byteman.cpp:35
void parseAssembly(std::string)
Definition: byteman.cpp:398
void setArchitecture(std::string)
Definition: byteman.cpp:445
void parseVerbose(std::string)
Definition: byteman.cpp:169
void parseBlank(std::string)
Definition: byteman.cpp:241
void parseMerge(std::string)
Definition: byteman.cpp:376
std::string parseParamsAndRemoveThemFromString(std::string)
Definition: byteman.cpp:146
void help(std::string, int)
Definition: help.cpp:31
void parseRegion(std::string)
Definition: byteman.cpp:217
void parseOutput(std::string)
Definition: byteman.cpp:354
virtual ~byteman()
Definition: byteman.cpp:92
void parseTest(std::string)
Definition: byteman.cpp:416
void parse(std::string)
Definition: byteman.cpp:96
void parseInput(std::string)
Definition: byteman.cpp:325
void parseDevice(std::string)
Definition: byteman.cpp:297
void parseChange(std::string)
Definition: byteman.cpp:269
byteman()
Definition: byteman.cpp:76
void parseWarn(std::string)
Definition: byteman.cpp:193
Definition: Coords.h:33
bool firstStringWordIs(std::string checkedString, std::string nextString, Rest ... restStrings)
Returns true if string checkedString's first word matches fully any of strings nextString or restStri...
Definition: iff.h:93
bool stringContains(std::string checkedString)
Returns false. End of recursion for template.
Definition: iff.h:57
std::string lastStringWord(std::string s)
Parses a string s, removes all integers and returns the last of all string words.
Definition: parse.h:81
bool multipleUints(std::stringstream &ss)
Definition: parse.h:229
std::string allStringWordsWithoutLastStringWord(std::string s)
Parses a string s, removes all integers and the last string word. Returns the rest.
Definition: parse.h:105
std::string allStringWords(std::string s)
Parses a string s, removes all integers and returns the rest.
Definition: parse.h:57
bool multipleInts(std::stringstream &ss)
Definition: parse.h:192
std::string nthStringWord(std::string s, int n)
Parses a string s, returns the n-th string word that is not an integer.
Definition: parse.h:33
std::string stringToLower(std::string str)
Replaces all uppercase characters in str with lowercase and returns the resulting string.
Definition: str.h:59
std::string replace(std::string str, char oldChar, char newChar)
Replaces all instances of oldChar in string str with newChar and returns the resulting string.
Definition: str.h:41
std::string findStringAndGetAllAfter(std::string checkedString, std::string searchString)
Finds string searchString inside checkedString and returns all to the right inside checkedString....
Definition: str.h:33
Definition: Coords.h:23
int col
Definition: Coords.h:25
int row
Definition: Coords.h:24
Definition: Coords.h:29