torc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Spartan6Packet.hpp
Go to the documentation of this file.
1 // Torc - Copyright 2011-2013 University of Southern California. All Rights Reserved.
2 // $HeadURL$
3 // $Id$
4 
5 // This program is free software: you can redistribute it and/or modify it under the terms of the
6 // GNU General Public License as published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11 // the GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License along with this program. If
14 // not, see <http://www.gnu.org/licenses/>.
15 
16 /// \file
17 /// \brief Header for the Spartan6Packet class.
18 
19 #ifndef TORC_BITSTREAM_SPARTAN6PACKET_HPP
20 #define TORC_BITSTREAM_SPARTAN6PACKET_HPP
21 
22 #include "torc/common/Endian.hpp"
23 #include <boost/smart_ptr.hpp>
24 #include <vector>
25 #include <istream>
26 #include <iostream>
27 #include <iomanip>
28 
29 namespace torc {
30 namespace bitstream {
31 
32 namespace bitstream { class Spartan6PacketUnitTest; }
33 
34  /// \brief Bitstream packet constants for Spartan 16 bit class architectures.
36  public:
37  // enumerations
38  /// \brief Packet type enumeration.
39  /// \see packet type: UG380, v2.2, July 30, 2010, Table 5-24, 5-26
41  //
42  /// \brief Packet opcode enumeration.
43  /// \see Opcode Format: UG380, v2.2, July 30, 2010, Table 5-23
45  /// \brief Packet subfields.
46  /// \see type 1 packet format: UG380, v2.2, July 30, 2010, Table 5-24
47  /// \see type 2 packet format: UG380, v2.2, July 30, 2010, Table 5-26
48  /// \see type 2 packet format: UG380, v2.2, July 30, 2010, Table 5-27
49  enum EPacket {
50  // generic packet subfields
54  // type 1 packet subfields
56  // type 2 packet subfields
59  };
60  //
61  /// \brief Synchronization words.
62  /// \see Configuration Sequence: UG380, v2.2, July 30, 2010, Table 5-50.
71  };
72  };
73 
74  /// \brief Bitstream packet for Spartan 16 bit class architectures.
77  protected:
78  // typedefs
79  /// \brief Imported type name.
80  typedef boost::uint16_t uint16_t;
81  typedef boost::uint32_t uint32_t;
82  /// \brief Word shared array type.
83  typedef boost::shared_array<uint16_t> WordSharedArray;
84  // functions
85  void initialize(void) {
89  }
90  public:
91  //protected:
92  // members
99  int mAddress;
100  /// \brief Packet type names.
101  static const char* sPacketTypeName[ePacketTypeCount];
102  /// \brief Packet opcode names.
103  static const char* sOpcodeName[eOpcodeCount];
104  public:
105  // constructors
106  /// \brief Null constructor.
108  mOpcode(eOpcodeNOP), mAddress(0) {}
109  /// \brief Full constructor.
110  Spartan6Packet(uint16_t inHeader, uint32_t inCount, uint16_t inWord,
111  uint16_t* inWords) : mHeader(inHeader), mCount(inCount), mWord(inWord),
113  initialize();
114  }
115  /// \brief Header plus single word constructor.
116  Spartan6Packet(uint16_t inHeader, uint16_t inWord) : mHeader(inHeader), mCount(1),
117  mWord(inWord), mWords(), mType(EPacketType(0)), mOpcode(eOpcodeNOP), mAddress(0) {
118  initialize();
119  }
120  /// \brief Header only constructor.
121  Spartan6Packet(uint16_t inHeader) : mHeader(inHeader), mCount(0), mWord(0), mWords(),
123  initialize();
124  }
125  /// \brief Copy constructor.
128  initialize();
129  }
130  // functions
131  /// \brief Read a packet.
132  static Spartan6Packet read(std::istream& inStream) {
133  uint32_t count = 0;
134  uint16_t count1 = 0;
135  uint16_t count2 = 0;
136  uint16_t header = 0;
137  uint16_t word = 0;
138  uint16_t* raw_words = 0;
139  // read the header
140  inStream.read((char*) &header, sizeof(header));
141  header = ntohs(header);
142  // process synchronization packets
143  if(header == eSynchronizationDummy || header == eSynchronizationSync0
144  || header == eSynchronizationSync1 || header == eSynchronizationBusWidthSync0
146  || header == eSynchronizationBusWidthDetect1) {
147  return Spartan6Packet(header, 0, 0, 0);
148  }
149  // determine the payload length
151  switch(type) {
152  case ePacketType1:
153  count = (header & ePacketMaskType1Count) >> ePacketShiftType1Count;
154  break;
155  case ePacketType2:
156  inStream.read((char*) &count2, sizeof(count2));
157  inStream.read((char*) &count1, sizeof(count1));
158  count2 = ntohs(count2);
159  count1 = ntohs(count1);
160  count = (count2 << 16) | count1;
161  break;
162  default:
163  /// \todo we should throw an exception on invalid packet types
164  count = 0;
165  count1 = 0;
166  count2 = 0;
167  break;
168  }
169  // read the packet payload
170  // Type1 Packet
171  if(type == ePacketType1) {
172  if(count == 1) {
173  inStream.read((char*) &word, sizeof(word));
174  word = ntohs(word);
175  } else if(count > 1) {
176  raw_words = new uint16_t[count];
177  inStream.read((char*) raw_words, count << 1);
178  uint16_t* wordPtr = raw_words;
179  for(uint32_t i = 0; i < count; i++, wordPtr++) *wordPtr = ntohs(*wordPtr);
180  }
181  }
182  // Type2 Packet
183  else if(type == ePacketType2) {
184  if(count == 1) {
185  inStream.read((char*) &word, sizeof(word));
186  word = ntohs(word);
187  } else if(count > 1) {
188  raw_words = new uint16_t[count];
189  inStream.read((char*) raw_words, count << 1);
190  uint16_t* wordPtr = raw_words;
191  for(uint32_t i = 0; i < count; i++, wordPtr++) *wordPtr = ntohs(*wordPtr);
192  }
193  }
194 
195  // create and return the packet
196  return Spartan6Packet(header, count, word, raw_words);
197  }
198  /// \brief Write a packet.
199  void write(std::ostream& inStream) const {
200  uint32_t size = getWordSize();
201  for(uint32_t i = 0; i < size; i++) {
202  uint16_t word = htons(operator[](i));
203  inStream.write((char*) &word, sizeof(word));
204  // type 2 packets need to insert two count words right after the header
205  // added count information in check for non-Type 2 headers such as Sync Word 2
206  if(i == 0 && isType2() && !isSyncWord1()) {
207  word = htons(mCount >> 16);
208  inStream.write((char*) &word, sizeof(word));
209  word = htons(mCount & 0x0000ffff);
210  inStream.write((char*) &word, sizeof(word));
211  // if this was a Type 2, we've just accounted for the two extra length words,
212  // so don't try to extract them form the packet payload
213  size -= 2;
214  }
215  }
216  }
217  /// \brief Construct a type 1 write packet.
218  static Spartan6Packet makeType1Write(uint16_t inAddress, uint16_t inWord) {
219  return Spartan6Packet(makeHeader(ePacketType1, eOpcodeWrite, inAddress, 1), 1, inWord,
220  0);
221  }
222  /// \brief Construct a type 1 write packet for two words.
223  static Spartan6Packet makeType1Write32(uint16_t inAddress, uint32_t inWord) {
224  // used to send two packets after header for packets like IDCODE, FARMAJ, and CRC
225  uint16_t* words = new uint16_t[2];
226  words[0] = inWord >> 16;
227  words[1] = inWord & 0x0000ffff;
228  return Spartan6Packet(makeHeader(ePacketType1, eOpcodeWrite, inAddress, 2), 2, 0,
229  words);
230  }
231  /// \brief Construct a type 1 write packet for two words.
232  static Spartan6Packet makeType1Write(uint16_t inAddress, uint16_t inWord1,
233  uint16_t inWord2) {
234  // used to send two packets after header for packets like IDCODE, FARMAJ, and CRC
235  uint16_t* words = new uint16_t[2];
236  words[0] = inWord1;
237  words[1] = inWord2;
238  return Spartan6Packet(makeHeader(ePacketType1, eOpcodeWrite, inAddress, 2), 2, 0,
239  words);
240  }
241  /// \brief Construct a type 1 write packet for multiple words.
242  static Spartan6Packet makeType1Write(uint32_t inCount, uint16_t inAddress,
243  uint16_t* inWords) {
244  return Spartan6Packet(makeHeader(ePacketType1, eOpcodeWrite, inAddress, inCount),
245  inCount, 0, inWords);
246  }
247  /// \brief Construct a type 2 write packet.
248  static Spartan6Packet makeType2Write(uint32_t inCount, uint16_t inAddress,
249  uint16_t* inWords) {
250  return Spartan6Packet(makeHeader(ePacketType2, eOpcodeWrite, inAddress, 0), inCount, 0,
251  inWords);
252  }
253  /// \brief Construct a packet header.
254  static uint16_t makeHeader(EPacketType inType, EOpcode inOpcode, uint16_t inAddress,
255  uint32_t inCount) {
256  // type 1 packets
257  if(inType == ePacketType1) return
258  ((inType << ePacketShiftType) & ePacketMaskType) |
259  ((inOpcode << ePacketShiftOpcode) & ePacketMaskOpcode) |
262  // type 2 packets
263  else if(inType == ePacketType2) return
264  ((inType << ePacketShiftType) & ePacketMaskType) |
265  ((inOpcode << ePacketShiftOpcode) & ePacketMaskOpcode) |
267  // undefined packet types
268  else
269  /// \todo Generate an error or throw an exception on invalid packet types?
270  return 0;
271  }
272  // operators
273  uint16_t operator[] (size_t inIndex) const {
274  if(inIndex == 0) return mHeader;
275  if(inIndex == 1 && mCount == 1) return mWord;
276  if(inIndex <= mCount) return mWords[inIndex-1];
277  return 0;
278  }
279  // accessors
280  EPacketType getType(void) const { return mType; }
281  EOpcode getOpcode(void) const { return mOpcode; }
282  int getAddress(void) const { return mAddress; }
283  uint16_t getHeader(void) const { return mHeader; }
284  /// \brief Returns the number of payload words in the packet, excluding the header word.
285  uint32_t getWordCount(void) const { return mCount; }
286  /// \brief Returns the total number of words in the packet, including the header word.
287  /// \detail In the case of Type 2 packets, we also include the two implicity length words.
288  uint32_t getWordSize(void) const {
289  if(isType2() && !isSyncWord1()) return mCount + 1 + 2;
290  return mCount + 1;
291  }
292  /// brief Returns the raw packet words, including the header word.
293  const WordSharedArray getWords(void) const { return mWords; }
294  // tests
295  bool isType1(void) const { return mType == ePacketType1; }
296  bool isType2(void) const { return mType == ePacketType2; }
297  bool isNop(void) const { return mOpcode == eOpcodeNOP; }
298  bool isReserved(void) const { return mOpcode == eOpcodeReserved; }
299  bool isRead(void) const { return mOpcode == eOpcodeRead; }
300  bool isWrite(void) const { return mOpcode == eOpcodeWrite; }
301  bool isDummyWord(void) const { return mHeader == eSynchronizationDummy; }
302  bool isSyncWord0(void) const { return mHeader == eSynchronizationSync0; }
303  bool isSyncWord1(void) const { return mHeader == eSynchronizationSync1; }
306  bool isBusWidthDetectWord0(void) const
308  bool isBusWidthDetectWord1(void) const
310  };
311 
312  /// \brief Vector of Spartan 16 bit packets.
313  typedef std::vector<Spartan6Packet> Spartan6PacketVector;
314 
315 } // namespace bitstream
316 } // namespace torc
317 
318 #endif // TORC_BITSTREAM_SPARTAN6PACKET_HPP
uint16_t getHeader(void) const
static Spartan6Packet makeType1Write(uint16_t inAddress, uint16_t inWord1, uint16_t inWord2)
Construct a type 1 write packet for two words.
uint32_t getWordCount(void) const
Returns the number of payload words in the packet, excluding the header word.
bool isBusWidthDetectWord0(void) const
uint16_t operator[](size_t inIndex) const
const WordSharedArray getWords(void) const
brief Returns the raw packet words, including the header word.
Bitstream packet for Spartan 16 bit class architectures.
Spartan6Packet(uint16_t inHeader, uint16_t inWord)
Header plus single word constructor.
EPacketType getType(void) const
static uint16_t makeHeader(EPacketType inType, EOpcode inOpcode, uint16_t inAddress, uint32_t inCount)
Construct a packet header.
static Spartan6Packet makeType1Write(uint16_t inAddress, uint16_t inWord)
Construct a type 1 write packet.
Bitstream packet constants for Spartan 16 bit class architectures.
uint32_t getWordSize(void) const
Returns the total number of words in the packet, including the header word. In the case of Type 2 pa...
std::vector< Spartan6Packet > Spartan6PacketVector
Vector of Spartan 16 bit packets.
Spartan6Packet(uint16_t inHeader, uint32_t inCount, uint16_t inWord, uint16_t *inWords)
Full constructor.
static Spartan6Packet makeType2Write(uint32_t inCount, uint16_t inAddress, uint16_t *inWords)
Construct a type 2 write packet.
void write(std::ostream &inStream) const
Write a packet.
boost::shared_array< uint16_t > WordSharedArray
Word shared array type.
boost::uint16_t uint16_t
Imported type name.
static Spartan6Packet makeType1Write32(uint16_t inAddress, uint32_t inWord)
Construct a type 1 write packet for two words.
bool isBusWidthDetectWord1(void) const
Spartan6Packet(uint16_t inHeader)
Header only constructor.
Spartan6Packet(const Spartan6Packet &rhs)
Copy constructor.
friend class torc::bitstream::bitstream::Spartan6PacketUnitTest
static const char * sOpcodeName[eOpcodeCount]
Packet opcode names.
static const char * sPacketTypeName[ePacketTypeCount]
Packet type names.
Header for endian conversion.
static Spartan6Packet makeType1Write(uint32_t inCount, uint16_t inAddress, uint16_t *inWords)
Construct a type 1 write packet for multiple words.
static Spartan6Packet read(std::istream &inStream)
Read a packet.
Spartan6Packet(void)
Null constructor.