OpenASIP 2.2
Loading...
Searching...
No Matches
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"
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
64using std::vector;
65using std::string;
66using std::endl;
70using namespace TPEF;
71
72const string ENSURE_PROGRAMMABILITY = "ensure_programmability";
73const string YES = "yes";
74
75/**
76 * Implements a simple instruction based dictionary compression scheme.
77 */
79public:
80
81 /**
82 * The constructor.
83 */
88
89
90 /**
91 * Creates the compressed code and returns the bit vector of it.
92 */
94 compress(const std::string& programName) {
95 try {
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;
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_) {
117
118 unsigned int compressedImemWidth =
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);
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++) {
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-"
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
249private:
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);
265 }
266 dictionaryCreated_ = true;
267 if (Application::verboseLevel() > 0 && dictionary_.size() > 0) {
268 std::size_t keyWidth =
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()) {
319 unsigned int code = MapTools::valueForKey<unsigned int>(
321 InstructionBitVector* compressedInstruction =
323 static_cast<BitVector*>(compressedInstruction)->pushBack(
324 code, static_cast<int>(
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
#define __func__
#define assert(condition)
#define EXPORT_CODE_COMPRESSOR(PLUGIN_NAME__)
find Finds info of the inner loops in the program
find Finds info of the inner loops in the false
const string ENSURE_PROGRAMMABILITY
const string YES
static int verboseLevel()
static std::ostream & logStream()
virtual void writeImage(std::ostream &stream) const
virtual int width(const TCEString &templateName) const
InstructionBitVector * bemBits(const TTAProgram::Program &program)
void setImemWidth(int mau, int widthInMaus=1)
TPEFMap::const_iterator programElement(int index) const
void startNewProgram(const std::string &programName)
const TTAMachine::Machine & machine() const
std::string indentation(int level)
void addInstruction(const TTAProgram::Instruction &instruction, InstructionBitVector *bits)
TTAProgram::Program & currentProgram() const
std::string parameterValue(const std::string &paramName) const
const BinaryEncoding & binaryEncoding() const
bool hasParameter(const std::string &paramName) const
InstructionBitVector * bemInstructionBits(const TTAProgram::Instruction &)
InstructionBitVector * programBits() const
std::string errorMessage() const
Definition Exception.cc:123
void addToDictionary(const BitVector &instructionBits)
virtual void generateDecompressor(std::ostream &stream, TCEString entityStr)
bool dictionaryCreated_
Indicates whether the whole dictionary has been created.
std::map< BitVector, unsigned int > Dictionary
Map type for dictionary.
Dictionary dictionary_
The dictionary.
bool compatibilityProgDone_
Indicates whether the compatibility program is in dictionary.
virtual InstructionBitVector * compress(const std::string &programName)
virtual void printDescription(std::ostream &stream)
void updateDictionary(const Program &program)
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static int requiredBits(unsigned long int number)
TPEF::Binary * profile(ProgrammabilityValidatorResults &results)
static NullInstruction & instance()
Instruction & nextInstruction(const Instruction &) const
Definition Program.cc:403
Instruction & firstInstruction() const
Definition Program.cc:353