OpenASIP  2.0
InstructionDictionary.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file InstructionDictionary.cc
26  *
27  * Implementation of a simple dictionary compressor. Warning! This
28  * compressor works correctly only when there is one instruction per
29  * MAU in the final program image. That is, the MAU of the address
30  * space should be the same as the width of the compressed
31  * instructions or wider. Otherwise jump and call addresses are
32  * invalid in the code.
33  *
34  * This compressor creates the dictionary on the level of whole instruction.
35  *
36  * @author Lasse Laasonen 2005 (lasse.laasonen-no.spam-tut.fi)
37  * @author Otto Esko 2008 (otto.esko-no.spam-tut.fi)
38  * @author Pekka Jääskeläinen 2009 (pekka.jaaskelainen-no.spam-tut.fi)
39  * @note rating: red
40  */
41 
42 #include <vector>
43 #include <string>
44 #include <iostream>
45 #include <cmath>
46 #include <boost/format.hpp>
47 
48 #include "CodeCompressor.hh"
49 #include "Program.hh"
50 #include "BinaryEncoding.hh"
51 #include "MoveSlot.hh"
52 #include "ImmediateSlotField.hh"
53 #include "ImmediateControlField.hh"
54 #include "InstructionBitVector.hh"
55 #include "NullInstruction.hh"
56 #include "AsciiImageWriter.hh"
59 #include "Binary.hh"
60 #include "TPEFProgramFactory.hh"
61 #include "MapTools.hh"
62 #include "MathTools.hh"
63 
64 using std::vector;
65 using std::string;
66 using std::endl;
70 using namespace TPEF;
71 
72 const string ENSURE_PROGRAMMABILITY = "ensure_programmability";
73 const string YES = "yes";
74 
75 /**
76  * Implements a simple instruction based dictionary compression scheme.
77  */
79 public:
80 
81  /**
82  * The constructor.
83  */
85  CodeCompressorPlugin(), compatibilityProgDone_(false),
86  dictionaryCreated_(false) {
87  }
88 
89 
90  /**
91  * Creates the compressed code and returns the bit vector of it.
92  */
93  virtual InstructionBitVector*
94  compress(const std::string& programName) {
95  try {
96  if (hasParameter(ENSURE_PROGRAMMABILITY) &&
97  parameterValue(ENSURE_PROGRAMMABILITY) == YES &&
98  !compatibilityProgDone_) {
99  ProgrammabilityValidator validator(machine());
101  Binary* compatibilityBin = validator.profile(results);
102  TPEFProgramFactory factory(*compatibilityBin, machine());
103  Program* compatibilityProg = factory.build();
104  updateDictionary(*compatibilityProg);
105  delete compatibilityBin;
106  delete compatibilityProg;
107  compatibilityProgDone_ = true;
108  }
109  } catch (const Exception& e) {
110  string errorMsg = "Unable to ensure programmability: " +
111  e.errorMessage();
112  throw InvalidData(
113  __FILE__, __LINE__, __func__, errorMsg);
114  }
115  if (!dictionaryCreated_) {
116  createDictionary();
117 
118  unsigned int compressedImemWidth =
119  MathTools::requiredBits(dictionary_.size());
120  assert(compressedImemWidth <= sizeof(long long unsigned int)*8
121  && "Compressed instruction width is too big");
122 
123  // fix imem width (mau == instruction width)
124  setImemWidth(compressedImemWidth);
125  }
126  startNewProgram(programName);
127  setAllInstructionsToStartAtBeginningOfMAU();
128  addInstructions();
129  return programBits();
130  }
131 
132  /**
133  * Generates the decompressor in VHDL.
134  *
135  * Note! The programs must be compressed by compress method before
136  * calling this method.
137  *
138  * @param stream The stream to write.
139  */
140  virtual void
141  generateDecompressor(std::ostream& stream, TCEString entityStr) {
142 
143  stream << "library ieee;" << endl;
144  stream << "use ieee.std_logic_1164.all;" << endl;
145  stream << "use ieee.std_logic_arith.all;" << endl << endl;
146 
147  stream << "package " << entityStr << "_dict_init is" << endl << endl;
148  stream << indentation(1)
149  << "type std_logic_dict_matrix is array (natural range <>) "
150  << "of std_logic_vector(" << binaryEncoding().width() - 1
151  << " downto 0);" << endl << endl;
152 
153  // write the dictionary contents
154  stream << indentation(1)
155  << "constant dict_init : std_logic_dict_matrix := (" << endl;
156  for (unsigned int i = 0; i < dictionary_.size(); i++) {
157  BitVector instr = MapTools::keyForValue<BitVector>(
158  dictionary_, i);
159  AsciiImageWriter writer(instr, instr.size());
160  stream << indentation(2) << "\"";
161  writer.writeImage(stream);
162  stream << "\"";
163  if (i+1 < dictionary_.size()) {
164  stream << "," << endl;
165  } else {
166  stream << ");" << endl;
167  }
168  }
169  stream << "end " << entityStr << "_dict_init;" << endl << endl;
170 
171  stream << "library ieee;" << endl;
172  stream << "use ieee.std_logic_1164.all;" << endl;
173  stream << "use ieee.std_logic_arith.all;" << endl;
174  stream << "use work." << entityStr << "_globals.all;" << endl;
175  stream << "use work." << entityStr << "_dict_init.all;" << endl;
176  stream << "use work." << entityStr << "_imem_mau.all;" << endl << endl;
177 
178  // write the decompressor entity
179  stream << "entity " << entityStr << "_decompressor is" << endl;
180  stream << indentation(1) << "port (" << endl;
181  stream << indentation(2) << "fetch_en : out std_logic;" << endl;
182  stream << indentation(2) << "lock : in std_logic;" << endl;
183  stream << indentation(2)
184  << "fetchblock : in std_logic_vector("
185  << "IMEMWIDTHINMAUS*IMEMMAUWIDTH-1 downto 0);" << endl;
186  stream << indentation(2)
187  << "instructionword : out std_logic_vector("
188  << "INSTRUCTIONWIDTH-1 downto 0);" << endl;
189  stream << indentation(2) << "glock : out std_logic;" << endl;
190  stream << indentation(2) << "lock_r : in std_logic;" << endl;
191  stream << indentation(2) << "clk : in std_logic;" << endl;
192  stream << indentation(2) << "rstx : in std_logic);" << endl << endl;
193  stream << "end " << entityStr << "_decompressor;" << endl << endl;
194 
195  stream << "architecture simple_dict of " << entityStr
196  << "_decompressor is" << endl << endl;
197 
198  stream << indentation(1)
199  << "subtype dict_index is integer range 0 to "
200  << "dict_init'length-1;" << endl;
201  stream << indentation(1) << "signal dict_line : dict_index;" << endl;
202  stream << indentation(1)
203  << "constant dict : std_logic_dict_matrix("
204  << "0 to dict_init'length-1) := dict_init;" << endl << endl;
205 
206  stream << "begin" << endl << endl;
207  stream << indentation(1) << "glock <= lock;" << endl;
208  stream << indentation(1) << "fetch_en <= not lock_r;" << endl;
209  stream << indentation(1)
210  << "dict_line <= conv_integer(unsigned(fetchblock("
211  << "fetchblock'length-1 downto fetchblock'length-"
212  << MathTools::requiredBits(dictionary_.size()-1)
213  << ")));" << endl << endl;
214 
215  stream << indentation(1) << "process (dict_line)" << endl;
216  stream << indentation(1) << "begin" << endl;
217  stream << indentation(2) << "instructionword <= dict(dict_line);"
218  << endl;
219  stream << indentation(1) << "end process;" << endl << endl;
220  stream << "end simple_dict;" << endl;
221  }
222 
223 
224  /**
225  * Prints the description of the plugin to the given stream.
226  *
227  * @param stream The stream.
228  */
229  virtual void
230  printDescription(std::ostream& stream) {
231  stream << "Generates the program image using instruction-based "
232  << "dictionary compression." << endl << endl
233  << "Warning! This compressor works correctly only when "
234  << "there is one instruction per MAU in the final program "
235  << "image. That is, the minimum addressable unit of the "
236  << "address space should be "
237  << "the same as the width of the compressed instructions or "
238  << "wider. Otherwise jump and call addresses are invalid in "
239  << "the code. This compressor creates the dictionary on the "
240  << "level of whole instruction." << endl << endl
241  << "Parameters accepted:" << endl
242  << "----------------------" << endl
243  << "ensure_programmability" << endl
244  << "If the value is 'yes', instructions that ensure "
245  << "programmability of the processor are added to the "
246  << "dictionary automatically." << endl;
247  }
248 
249 private:
250  /// Map type for dictionary.
251  typedef std::map<BitVector, unsigned int> Dictionary;
252 
253  /**
254  * Creates the whole dictionary
255  *
256  */
257  void
259  for (int i = 0; i < numberOfPrograms(); i++) {
260  TPEFMap::const_iterator iter = programElement(i);
261  string name = iter->first;
262  startNewProgram(name);
263  setAllInstructionsToStartAtBeginningOfMAU();
264  updateDictionary(currentProgram());
265  }
266  dictionaryCreated_ = true;
267  if (Application::verboseLevel() > 0 && dictionary_.size() > 0) {
268  std::size_t keyWidth =
269  MathTools::requiredBits(dictionary_.size() - 1);
270  std::size_t entrySize = binaryEncoding().width();
271  std::size_t entries = dictionary_.size();
273  << (boost::format(
274  "dictionary width: %d bits, entries: %d, "
275  "total size: %d bits (%d bytes)\n" )
276  % keyWidth % entries % (entries * entrySize)
277  % std::size_t(std::ceil(entries * entrySize / 8.0))).str();
278  }
279  }
280 
281  /**
282  * Adds the given instruction bits to the dictionary.
283  *
284  * @param instructionBits The instruction bits to add.
285  */
286  void
287  addToDictionary(const BitVector& instructionBits) {
288  if (!MapTools::containsKey(dictionary_, instructionBits)) {
289  unsigned int code = dictionary_.size();
290  dictionary_.insert(
291  std::pair<BitVector, unsigned int>(instructionBits, code));
292  }
293  }
294 
295 
296  /**
297  * Creates the dictionary.
298  */
299  void
301  Instruction* instruction = &program.firstInstruction();
302  while (instruction != &NullInstruction::instance()) {
303  InstructionBitVector* instructionBits = bemInstructionBits(
304  *instruction);
305  addToDictionary(*instructionBits);
306  instruction = &program.nextInstruction(*instruction);
307  }
308  }
309 
310 
311  /**
312  * Adds the compressed instructions to the program.
313  */
314  void
316  Instruction* instruction = &currentProgram().firstInstruction();
317  while (instruction != &NullInstruction::instance()) {
318  InstructionBitVector* bemBits = bemInstructionBits(*instruction);
319  unsigned int code = MapTools::valueForKey<unsigned int>(
320  dictionary_, *bemBits);
321  InstructionBitVector* compressedInstruction =
322  new InstructionBitVector();
323  static_cast<BitVector*>(compressedInstruction)->pushBack(
324  code, static_cast<int>(
325  MathTools::requiredBits(dictionary_.size() - 1)));
326  addInstruction(*instruction, compressedInstruction);
327  instruction = &currentProgram().nextInstruction(*instruction);
328 
329  }
330  }
331 
332 
333 
334  /// The dictionary.
336  /// Indicates whether the compatibility program is in dictionary.
338  /// Indicates whether the whole dictionary has been created
340 
341 };
342 
AsciiImageWriter.hh
TTAProgram::Program
Definition: Program.hh:63
ProgrammabilityValidatorResults.hh
InstructionBitVector.hh
InstructionDictionary::dictionary_
Dictionary dictionary_
The dictionary.
Definition: InstructionDictionary.cc:335
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
TTAProgram::NullInstruction
Definition: NullInstruction.hh:45
BitVector
Definition: BitVector.hh:44
ProgrammabilityValidatorResults
Definition: ProgrammabilityValidatorResults.hh:46
TPEF::Binary
Definition: Binary.hh:49
TTAProgram::Instruction
Definition: Instruction.hh:57
MapTools.hh
ImmediateSlotField.hh
CodeCompressor.hh
Application::verboseLevel
static int verboseLevel()
Definition: Application.hh:176
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
ProgrammabilityValidator::profile
TPEF::Binary * profile(ProgrammabilityValidatorResults &results)
Definition: ProgrammabilityValidator.cc:269
MoveSlot.hh
AsciiImageWriter::writeImage
virtual void writeImage(std::ostream &stream) const
Definition: AsciiImageWriter.cc:73
TTAProgram::TPEFProgramFactory
Definition: TPEFProgramFactory.hh:87
assert
#define assert(condition)
Definition: Application.hh:86
InvalidData
Definition: Exception.hh:149
InstructionDictionary::createDictionary
void createDictionary()
Definition: InstructionDictionary.cc:258
BinaryEncoding.hh
InstructionDictionary::dictionaryCreated_
bool dictionaryCreated_
Indicates whether the whole dictionary has been created.
Definition: InstructionDictionary.cc:339
InstructionDictionary::printDescription
virtual void printDescription(std::ostream &stream)
Definition: InstructionDictionary.cc:230
NullInstruction.hh
__func__
#define __func__
Definition: Application.hh:67
TTAProgram::TPEFProgramFactory::build
Program * build()
Definition: TPEFProgramFactory.cc:200
InstructionDictionary::updateDictionary
void updateDictionary(const Program &program)
Definition: InstructionDictionary.cc:300
ENSURE_PROGRAMMABILITY
const string ENSURE_PROGRAMMABILITY
Definition: InstructionDictionary.cc:72
ProgrammabilityValidator
Definition: ProgrammabilityValidator.hh:75
MathTools::requiredBits
static int requiredBits(unsigned long int number)
InstructionDictionary
Definition: InstructionDictionary.cc:78
Exception
Definition: Exception.hh:54
ProgrammabilityValidator.hh
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
ImmediateControlField.hh
InstructionDictionary::compatibilityProgDone_
bool compatibilityProgDone_
Indicates whether the compatibility program is in dictionary.
Definition: InstructionDictionary.cc:337
MapTools::containsKey
static bool containsKey(const MapType &aMap, const KeyType &aKey)
InstructionDictionary::compress
virtual InstructionBitVector * compress(const std::string &programName)
Definition: InstructionDictionary.cc:94
TPEFProgramFactory.hh
InstructionDictionary::addInstructions
void addInstructions()
Definition: InstructionDictionary.cc:315
Program.hh
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
EXPORT_CODE_COMPRESSOR
#define EXPORT_CODE_COMPRESSOR(PLUGIN_NAME__)
Definition: CodeCompressor.hh:42
YES
const string YES
Definition: InstructionDictionary.cc:73
AsciiImageWriter
Definition: AsciiImageWriter.hh:45
CodeCompressorPlugin
Definition: CodeCompressorPlugin.hh:84
TCEString
Definition: TCEString.hh:53
InstructionDictionary::InstructionDictionary
InstructionDictionary()
Definition: InstructionDictionary.cc:84
InstructionDictionary::Dictionary
std::map< BitVector, unsigned int > Dictionary
Map type for dictionary.
Definition: InstructionDictionary.cc:251
InstructionDictionary::generateDecompressor
virtual void generateDecompressor(std::ostream &stream, TCEString entityStr)
Definition: InstructionDictionary.cc:141
program
find Finds info of the inner loops in the program
Definition: InnerLoopFinder.cc:80
MathTools.hh
InstructionDictionary::addToDictionary
void addToDictionary(const BitVector &instructionBits)
Definition: InstructionDictionary.cc:287
TPEF
Definition: Assembler.hh:43
Binary.hh
InstructionBitVector
Definition: InstructionBitVector.hh:50