OpenCores
URL https://opencores.org/ocsvn/bluespec_md6/bluespec_md6/trunk

Subversion Repositories bluespec_md6

[/] [bluespec_md6/] [trunk/] [MD6Control/] [src/] [MD6Control.bsv] - Blame information for rev 9

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 kfleming
//----------------------------------------------------------------------//
2
// The MIT License
3
//
4
// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu
5
//
6
// Permission is hereby granted, free of charge, to any person
7
// obtaining a copy of this software and associated documentation
8
// files (the "Software"), to deal in the Software without
9
// restriction, including without limitation the rights to use,
10
// copy, modify, merge, publish, distribute, sublicense, and/or sell
11
// copies of the Software, and to permit persons to whom the
12
// Software is furnished to do so, subject to the following conditions:
13
//
14
// The above copyright notice and this permission notice shall be
15
// included in all copies or substantial portions of the Software.
16
//
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
// OTHER DEALINGS IN THE SOFTWARE.
25
//----------------------------------------------------------------------//
26 2 kfleming
//Global includes
27
import FIFO::*;
28
import Vector::*;
29
import GetPut::*;
30
import ConfigReg::*;
31
 
32
//CSG Lib includes
33
import PLBMaster::*;
34
import PLBMasterDefaultParameters::*;
35
 
36
 
37
//Local Includes
38
import MD6Parameters::*;
39
import MD6Types::*;
40
import MD6Library::*;
41
import CompressionFunction::*;
42
import CompressionFunctionTypes::*;
43
import CompressionFunctionLibrary::*;
44
 
45
 
46
interface MD6Control#(numeric type engines, numeric type steps);
47
  method ActionValue#(MD6Word) wordOutput();
48
  method Action wordInput(MD6Word inWord);
49
  method ActionValue#(PLBMasterCommand) outputCommand();
50
  method Action startDecode();
51
  method Bool running();
52
  interface Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyRegister;
53
  interface Reg#(BlockAddr) sourceAddress;
54
  interface Reg#(BlockAddr) destinationAddress;
55
  interface Reg#(BlockAddr) bufferAddress;
56
  interface Reg#(Bit#(TLog#(MD6_BitSize))) bitSize;
57
  interface Reg#(Bool) bigEndian;
58
  interface Reg#(DigestLength) digestLength;
59
endinterface
60
 
61
 
62
typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst;
63
typedef TDiv#(MD6_c,MD6WordsPerBurst) MD6BurstsPerHashStore;
64
typedef TDiv#(MD6_b,MD6WordsPerBurst) MD6BurstsPerHashLoad;
65
typedef TMul#(MD6_b,MD6_WordWidth) MD6BitsPerHashInput;
66
typedef TMul#(MD6_c,MD6_WordWidth) MD6BitsPerHashOutput;
67
 
68
 
69
typedef enum {
70
  Idle,
71
  IdleWait,
72
  LevelStart,
73
  LevelCompute
74
} ControlState deriving (Bits,Eq);
75
 
76
 
77
typedef enum {
78
    PadBlock,
79
    NoPad,
80
    AllPad // Need a seperate rule for this one, not tied externally.
81
} IncomingBlock deriving (Bits, Eq);
82
 
83
typedef enum {
84
  Normal,
85
  LastInLevel,
86
  FinalBlock
87
} OutgoingBlock deriving (Bits, Eq);
88
 
89
module mkMD6Control (MD6Control#(engines,steps))
90
  provisos(Add#(steps,xxx,MD6_n),
91
           Add#(yyy,TLog#(steps),TLog#(MD6_n)),
92
           Add#(zzz,TLog#(steps),TLog#(MD6_b)),
93
           Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64));
94
 
95
  Vector#(engines,CompressionFunction#(steps)) md6Engines;
96
 
97
  if(valueof(steps)<16)
98
    begin
99
      md6Engines <- replicateM(mkSimpleCompressionFunction);
100
    end
101
  else if(valueof(steps) % 16 == 0)
102
    begin
103
      md6Engines <- replicateM(mkMult16CompressionFunction);
104
    end
105
  else
106
    begin
107
      error("Unsupported Size");
108
    end
109
 
110
  /* These registers are externally visible.  Therefore, they must not be modified */
111
  Reg#(BlockAddr) md6SourceAddr <- mkRegU();
112
  Reg#(BlockAddr) md6DestinationAddr <- mkRegU();
113
  Reg#(BlockAddr) md6BufferAddr <- mkRegU();
114
  Reg#(Bit#(TLog#(MD6_BitSize))) md6BitSize <- mkRegU();
115
  Reg#(DigestLength) digestLengthReg <- mkRegU(); // Do we want to fold this across
116
                                               // The control engines themselves?
117
  Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyReg <- mkRegU();
118
  Reg#(Bool) bigEndianReg <- mkReg(False);
119
 
120
 
121
  /* These regs are used per computation */
122
  //Reg#(MD6_BitSize) bitsRemaining <- mkReg(0);
123
  Reg#(Bit#(TLog#(MD6_BitSize))) dataBlocksRemaining <- mkReg(0);
124
  Reg#(Bit#(TDiv#(MD6_b,MD6_c))) paddingBlocksRemaining <- mkReg(0);
125
  Reg#(TreeHeight)  currentHeight <- mkReg(0);
126
  Reg#(Bit#(TLog#(MD6_b))) wordsIncoming <- mkReg(0);
127
  Reg#(Bit#(TLog#(MD6_c))) wordsOutgoing <- mkReg(0);
128
  Reg#(Bit#(TLog#(engines))) targetEngine <- mkReg(0);
129
  Reg#(ControlState) state <- mkReg(Idle);
130
  Reg#(Bit#(TAdd#(1,TLog#(MD6BurstsPerHashLoad)))) loadCount <- mkReg(0);
131
  Reg#(Bit#(TLog#(MD6BurstsPerHashStore))) storeCount <- mkReg(0);
132
  Reg#(BlockAddr) sourceAddr <- mkReg(0);
133
  Reg#(BlockAddr) destAddr <- mkReg(0);
134
  Reg#(Bool) lastCompression <- mkReg(False);
135
  Reg#(Bool) issuedStart <- mkReg(False);
136
  Reg#(Vector#(MD6_u,Bit#(MD6_WordWidth))) identifier <- mkRegU();
137
 
138
  FIFO#(Tuple2#(IncomingBlock,Bit#(TLog#(engines)))) inTokens <- mkFIFO;
139
  FIFO#(Tuple2#(OutgoingBlock,Bit#(TLog#(engines)))) outTokens <- mkFIFO;
140
  FIFO#(Bit#(TLog#(engines))) readyEngine <- mkFIFO;
141
  FIFO#(PLBMasterCommand) plbCommand <- mkSizedFIFO(2); // why's this?
142
 
143
  // This needs to be as big as an input block.
144
  Reg#(Bit#(TLog#(MD6BitsPerHashInput))) tailNonZeroBits <- mkReg(0);
145
  Reg#(Bool) waitingForPad <- mkReg(False);
146
 
147
  function Action setupLevel()
148
    provisos(Add#(steps,xxx,MD6_n),
149
           Add#(yyy,TLog#(steps),TLog#(MD6_n)),
150
           Add#(zzz,TLog#(steps),TLog#(MD6_b)),
151
           Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64));
152
    action
153
    // this is probably wrong
154
    Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize);
155
    match {.wholeBlocks, .tailBits} = currentBits;
156
    $display("Current bits: %d %d", currentBits, md6BitSize);
157
    $display("whole blocks: %d", wholeBlocks);
158
    tailNonZeroBits <= tailBits; // Probably some sizing issue here.
159
    Bit#(TDiv#(MD6_b,MD6_c)) leftoverBlocks = truncate(wholeBlocks) + ((tailBits!=0)?1:0);
160
    Bit#(TDiv#(MD6_b,MD6_c)) paddingBlocks = truncate(fromInteger(valueof(TDiv#(MD6_b,MD6_c)))-zeroExtend(leftoverBlocks));
161
    dataBlocksRemaining <= zeroExtend(wholeBlocks)+((tailBits!=0)?1:0);
162
    paddingBlocksRemaining <= paddingBlocks;
163
    $display("Padding Blocks: %d", paddingBlocks);
164
    state <= LevelCompute;
165
    if(state == Idle)
166
      begin
167
        sourceAddr <= md6SourceAddr;
168
      end
169
    else
170
      begin
171
        sourceAddr <= md6BufferAddr;
172
      end
173
    identifier <= replicate(0);
174
    // Check for last compression
175
    if((wholeBlocks == 0) || ((wholeBlocks == 1) && (tailBits == 0)))
176
      begin
177
        $display("Setting the lastCompression");
178
        destAddr <= md6DestinationAddr;
179
        lastCompression <= True;
180
      end
181
    else
182
      begin
183
        destAddr <= md6BufferAddr;
184
        lastCompression <= False;
185
      end
186
    endaction
187
  endfunction
188
 
189
  rule levelRule (state == LevelStart && !waitingForPad);
190
    currentHeight <= currentHeight+1;
191
    setupLevel();
192
  endrule
193
 
194
  rule issueStart(state == LevelCompute && !issuedStart);
195
       $display("calling issue start");
196
       issuedStart <= True;
197
       PaddingBits padding =  0;
198
        $display("Starting engine: %d", targetEngine);
199
        if(targetEngine == fromInteger(valueof(engines)-1))
200
          begin
201
            targetEngine <= 0;
202
          end
203
        else
204
          begin
205
            targetEngine <= targetEngine + 1;
206
          end
207
        // Determine pad status
208
        // We have more regular data left to go. May need to count up on this one
209
        if(dataBlocksRemaining != 0)  // underflow may happen :(
210
          begin
211
            dataBlocksRemaining <= dataBlocksRemaining - 1;
212
          end
213
 
214
        if((dataBlocksRemaining > 1) || ((dataBlocksRemaining!=0) && (tailNonZeroBits == 0))) // We might have a full block
215
          begin
216
            inTokens.enq(tuple2(NoPad,targetEngine));
217
          end
218
        else
219
          begin
220
            inTokens.enq(tuple2(PadBlock,targetEngine));
221
            waitingForPad <= True;
222
            // Define a block as MD6_c words.
223
            // In this case, we require some padding.
224
            padding = fromInteger(valueof(MD6_WordWidth)*valueof(MD6_b)) - zeroExtend(tailNonZeroBits);
225
            $display("tailNonZero: %d padding: %d",tailNonZeroBits,padding);
226
            // seems that tailNonZero bits is getting smashed
227
          end
228
 
229
        // Must also issue store token.
230
        $display("outToken: %d", targetEngine);
231
        if(dataBlocksRemaining <= 1 && lastCompression)
232
          begin
233
            outTokens.enq(tuple2(FinalBlock,targetEngine));
234
          end
235
        else if(dataBlocksRemaining <= 1)
236
                  // in this case, we must wait until the level finishes processing
237
                  // to start the next one. Not necessary for
238
                  // single engine.
239
          begin
240
            outTokens.enq(tuple2(LastInLevel,targetEngine));
241
          end
242
        else
243
          begin
244
            outTokens.enq(tuple2(Normal,targetEngine));
245
          end
246
        $display("Setting CW: r: %d, l: %d, z:%d, p:%d, keylen: %d, d: %d", valueof(MD6_r),30,(lastCompression)?1:0,
247
                                           padding,  //Padding
248
                                           valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8), // Need Byte Size....
249
                                           valueof(MD6_d));
250
 
251
        // Start cutting here?
252
 
253
 
254
          Bit#(8) identLevel = currentHeight;
255
          Bit#(64) identifierFull = {identLevel,truncate(pack(identifier))};
256
          identifier <= unpack(pack(identifier) + 1);
257
 
258
          md6Engines[targetEngine].start(defaultMD6R(digestLengthReg),64,(lastCompression)?1:0,padding, fromInteger(valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8)),digestLengthReg, unpack(pack(identifierFull)), keyReg);
259
          // why call this first?  This is a problem because we cannot overlap loads/stores.
260
  endrule
261
 
262
 
263
  rule issueStoreFinal (state == LevelCompute && (loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) &&
264
                   (storeCount == fromInteger(valueof(MD6BurstsPerHashStore)-1))  && issuedStart);
265
            $display("Firiing Store Final");
266
            issuedStart <= False;
267
            loadCount <= 0;
268
            storeCount <= 0;
269
            // Check for the need to transition out of this state.
270
            // Hmm... This doesn't seem right probably only want to transition
271
            // once we're sure when we're done.
272
            $display("In unoptimized clause dataBlocksRemaining: %d", dataBlocksRemaining);
273
            // Correct as we require 1 load/1 store at least  // Need to wait on level completion?
274
            if(dataBlocksRemaining == 0)
275
              begin
276
                state <= IdleWait;
277
                if(lastCompression)
278
                  begin
279
                    $display("Setting state idlewait");
280
 
281
                  end
282
                else
283
                  begin
284
                    //must fix md6BitSize here.
285
                    // Probably have to fix type...
286
                    Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize);
287
                    Bit#(TLog#(MD6BitsPerHashOutput)) bottomZeros= 0;
288
                    match {.wholeBlocks, .tailBits} = currentBits;
289
 
290
                    md6BitSize <= zeroExtend({((tailBits!=0)?wholeBlocks+1:wholeBlocks), bottomZeros});
291
 
292
                  end
293
            end
294
 
295
 
296
            plbCommand.enq(tagged StorePage destAddr);
297
            destAddr <=  truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst)))));
298
            // Actually issue the store here
299
  endrule
300
 
301
  // This may be problematic
302
  rule issueStore (state == LevelCompute && (loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) &&
303
                   (storeCount < fromInteger(valueof(MD6BurstsPerHashStore)-1))  && issuedStart);
304
       $display("In optimized clause");
305
        storeCount <= storeCount + 1;
306
        plbCommand.enq(tagged StorePage destAddr);
307
        destAddr <=  truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst)))));
308
  endrule
309
 
310
  rule issueLoad((state == LevelCompute) && (loadCount < fromInteger(valueof(MD6BurstsPerHashLoad))));
311
    loadCount <= loadCount + 1;
312
    $display("Issue Load[%d of %d]: %d", loadCount+1, fromInteger(valueof(MD6BurstsPerHashLoad)),sourceAddr);
313
    plbCommand.enq(tagged LoadPage sourceAddr);
314
    sourceAddr <=  truncateLSB({sourceAddr,0} + (1 << (valueof(TLog#(WordsPerBurst)))));
315
  endrule
316
 
317
 
318
  // This rule will feed output from the MD6 engine to the memory controller
319
  method ActionValue#(MD6Word) wordOutput();
320
    match {.block, .engine} = outTokens.first;
321
    if(wordsOutgoing  == fromInteger(valueof(MD6_c) - 1))
322
      begin
323
       wordsOutgoing <= 0;
324
       outTokens.deq;
325
       if(block == FinalBlock)
326
         begin
327
           $display("TIMING finish: %d", $time);
328
           state <= Idle; // At this point, we're really done...
329
         end
330
       else if(block == LastInLevel)
331
         begin
332
           state <= LevelStart;
333
         end
334
      end
335
    else
336
      begin
337
       wordsOutgoing <= wordsOutgoing + 1;
338
      end
339
    $display("outgoing word");
340
 
341
    MD6Word endianCorrect <- md6Engines[engine].outputWord;
342
 
343
    MD6Word outWord;
344
 
345
    // MD6 is big endian.  If the system is little endian, we must swap.
346
    if(!bigEndianReg)
347
      begin
348
        $display("Big endian false");
349
        Vector#(TDiv#(MD6_WordWidth,8),Bit#(8)) vector = unpack(endianCorrect);
350
        outWord = pack(reverse(vector));
351
      end
352
    else
353
      begin
354
        outWord = endianCorrect;
355
      end
356
 
357
    return outWord;
358
  endmethod
359
 
360
  // This rule handles input from the outside world to the MD6 controller
361
  // This includes padding
362
  method Action wordInput(MD6Word endianCorrect);
363
    // Must deal with zero padding at the end of the
364
    // first round.
365
 
366
    MD6Word inWord;
367
 
368
    // MD6 is big endian.  If the system is little endian, we must swap.
369
    if(!bigEndianReg)
370
      begin
371
        Vector#(TDiv#(MD6_WordWidth,8),Bit#(8)) vector = unpack(endianCorrect);
372
        inWord = pack(reverse(vector));
373
      end
374
    else
375
      begin
376
        inWord = endianCorrect;
377
      end
378
 
379
    $display("inputWord called: %h", inWord);
380
    match {.blockType, .engine } = inTokens.first;
381
 
382
    if(wordsIncoming == fromInteger(valueof(MD6_b) - 1))
383
      begin
384
       wordsIncoming <= 0;
385
       if(blockType == PadBlock)
386
         begin
387
           waitingForPad <= False;
388
         end
389
       inTokens.deq;
390
      end
391
    else
392
      begin
393
       wordsIncoming <= wordsIncoming + 1;
394
      end
395
 
396
    if(blockType == PadBlock)
397
      begin
398
        $display("Padblock, tailNonZeroBits: %d", tailNonZeroBits);
399
        // Now, pad the leftover bits to zero
400
        if(tailNonZeroBits > fromInteger(valueof(MD6_WordWidth)))
401
          begin
402
            tailNonZeroBits <= tailNonZeroBits - fromInteger(valueof(MD6_WordWidth));
403
            md6Engines[engine].inputWord(inWord);
404
          end
405
        else if(tailNonZeroBits > 0)
406
          begin // Might alter this to decrease impl area
407
            Bit#(TAdd#(1,TLog#(MD6_WordWidth))) shiftValue = truncate(64-tailNonZeroBits);
408
            Bit#(MD6_WordWidth) paddedWord = inWord & (~0 << shiftValue);
409
            md6Engines[engine].inputWord(paddedWord);
410
            tailNonZeroBits <= 0;
411
          end
412
        else // All zeros from here.
413
          begin
414
            md6Engines[engine].inputWord(0);
415
          end
416
      end
417
    else if(blockType ==  NoPad)
418
      begin
419
        md6Engines[engine].inputWord(inWord);
420
      end
421
  endmethod
422
 
423
  method ActionValue#(PLBMasterCommand) outputCommand();
424
    plbCommand.deq;
425
    return plbCommand.first;
426
  endmethod
427
 
428
  // On the first pass only, we may have some tail non-zero bits.  we must pad these out.
429
  // All blocks must be padded to MD6_WordWidth
430
  method Action startDecode();
431
    if(state  == Idle)
432
      begin
433
        $display("TIMING start: %d", $time);
434
        currentHeight <= 1;
435
        setupLevel();
436
      end
437
  endmethod
438
 
439
  method Bool running();
440
    return !(state == Idle);
441
  endmethod
442
 
443
  interface Reg keyRegister = keyReg;
444
  interface Reg sourceAddress = md6SourceAddr;
445
  interface Reg destinationAddress = md6DestinationAddr;
446
  interface Reg bufferAddress = md6BufferAddr;
447
  interface Reg bitSize = md6BitSize;
448
  interface Reg bigEndian = bigEndianReg;
449
  interface Reg digestLength = digestLengthReg;
450
 
451
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.