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

Subversion Repositories bluespec_md6

[/] [bluespec_md6/] [trunk/] [MD6Control/] [test/] [benchmarks/] [MD6Control.bsv] - Blame information for rev 7

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
 
31
//CSG Lib includes
32
import PLBMaster::*;
33
import PLBMasterDefaultParameters::*;
34
 
35
 
36
//Local Includes
37
import MD6Parameters::*;
38
import MD6Types::*;
39
import CompressionFunction::*;
40
import CompressionFunctionTypes::*;
41
import CompressionFunctionLibrary::*;
42
 
43
 
44
interface MD6Control#(numeric type engines, numeric type steps);
45
  method ActionValue#(MD6Word) wordOutput();
46
  method Action wordInput(MD6Word inWord);
47
  method ActionValue#(PLBMasterCommand) outputCommand();
48
  method Action startDecode();
49
  method Bool running();
50
  interface Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyRegister;
51
  interface Reg#(BlockAddr) sourceAddress;
52
  interface Reg#(BlockAddr) destinationAddress;
53
  interface Reg#(BlockAddr) bufferAddress;
54
  interface Reg#(Bit#(TLog#(MD6_BitSize))) bitSize;
55
 
56
endinterface
57
 
58
 
59
typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst;
60
typedef TDiv#(MD6_c,MD6WordsPerBurst) MD6BurstsPerHashStore;
61
typedef TDiv#(MD6_b,MD6WordsPerBurst) MD6BurstsPerHashLoad;
62
typedef TMul#(MD6_b,MD6_WordWidth) MD6BitsPerHashInput;
63
typedef TMul#(MD6_c,MD6_WordWidth) MD6BitsPerHashOutput;
64
 
65
 
66
typedef enum {
67
  Idle,
68
  IdleWait,
69
  LevelStart,
70
  LevelCompute
71
} ControlState deriving (Bits,Eq);
72
 
73
 
74
typedef enum {
75
    PadBlock,
76
    NoPad,
77
    AllPad // Need a seperate rule for this one, not tied externally.
78
} IncomingBlock deriving (Bits, Eq);
79
 
80
typedef enum {
81
  Normal,
82
  FinalBlock
83
} OutgoingBlock deriving (Bits, Eq);
84
 
85
module mkMD6Control (MD6Control#(engines,steps))
86
  provisos(Add#(steps,xxx,MD6_n),
87
           Add#(yyy,TLog#(steps),TLog#(MD6_n)),
88
           Add#(zzz,TLog#(steps),TLog#(MD6_b)),
89
           Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64));
90
 
91
  Vector#(engines,CompressionFunction#(steps)) md6Engines <- replicateM(mkSimpleCompressionFunction);
92
 
93
  /* These registers are externally visible.  Therefore, they must not be modified */
94
  Reg#(BlockAddr) md6SourceAddr <- mkReg(0);
95
  Reg#(BlockAddr) md6DestinationAddr <- mkReg(0);
96
  Reg#(BlockAddr) md6BufferAddr <- mkReg(0);
97
  Reg#(Bit#(TLog#(MD6_BitSize))) md6BitSize <- mkReg(0);
98
  Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyReg <- mkRegU();
99
 
100
 
101
 
102
  /* These regs are used per computation */
103
  //Reg#(MD6_BitSize) bitsRemaining <- mkReg(0);
104
  Reg#(Bit#(TLog#(MD6_BitSize))) dataBlocksRemaining <- mkReg(0);
105
  Reg#(Bit#(TDiv#(MD6_b,MD6_c))) paddingBlocksRemaining <- mkReg(0);
106
  Reg#(TreeHeight)  currentHeight <- mkReg(0);
107
  Reg#(Bit#(TLog#(MD6_b))) wordsIncoming <- mkReg(0);
108
  Reg#(Bit#(TLog#(MD6_c))) wordsOutgoing <- mkReg(0);
109
  Reg#(Bit#(TLog#(engines))) targetEngine <- mkReg(0);
110
  Reg#(ControlState) state <- mkReg(Idle);
111
  Reg#(Bit#(TAdd#(1,TLog#(MD6BurstsPerHashLoad)))) loadCount <- mkReg(0);
112
  Reg#(Bit#(TLog#(MD6BurstsPerHashStore))) storeCount <- mkReg(0);
113
  Reg#(BlockAddr) sourceAddr <- mkReg(0);
114
  Reg#(BlockAddr) destAddr <- mkReg(0);
115
  Reg#(Bool) lastCompression <- mkReg(False);
116
  Reg#(Vector#(MD6_u,Bit#(MD6_WordWidth))) identifier <- mkRegU();
117
 
118
  FIFO#(Tuple2#(IncomingBlock,Bit#(TLog#(engines)))) inTokens <- mkFIFO;
119
  FIFO#(Tuple2#(OutgoingBlock,Bit#(TLog#(engines)))) outTokens <- mkFIFO;
120
  FIFO#(Bit#(TLog#(engines))) readyEngine <- mkFIFO;
121
  FIFO#(PLBMasterCommand) plbCommand <- mkSizedFIFO(1);
122
 
123
  // This needs to be as big as an input block.
124
  Reg#(Bit#(TLog#(MD6BitsPerHashInput))) tailNonZeroBits <- mkReg(0);
125
  Reg#(Bool) waitingForPad <- mkReg(False);
126
 
127
  function Action setupLevel()
128
    provisos(Add#(steps,xxx,MD6_n),
129
           Add#(yyy,TLog#(steps),TLog#(MD6_n)),
130
           Add#(zzz,TLog#(steps),TLog#(MD6_b)),
131
           Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64));
132
    action
133
    // this is probably wrong
134
    Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize);
135
    match {.wholeBlocks, .tailBits} = currentBits;
136
    $display("Current bits: %d %d", currentBits, md6BitSize);
137
    $display("whole blocks: %d", wholeBlocks);
138
    tailNonZeroBits <= tailBits; // Probably some sizing issue here.
139
    Bit#(TDiv#(MD6_b,MD6_c)) leftoverBlocks = truncate(wholeBlocks) + ((tailBits!=0)?1:0);
140
    Bit#(TDiv#(MD6_b,MD6_c)) paddingBlocks = truncate(fromInteger(valueof(TDiv#(MD6_b,MD6_c)))-zeroExtend(leftoverBlocks));
141
    dataBlocksRemaining <= zeroExtend(wholeBlocks)+((tailBits!=0)?1:0);
142
    paddingBlocksRemaining <= paddingBlocks;
143
    $display("Padding Blocks: %d", paddingBlocks);
144
    state <= LevelCompute;
145
    if(state == Idle)
146
      begin
147
        sourceAddr <= md6SourceAddr;
148
      end
149
    else
150
      begin
151
        sourceAddr <= md6BufferAddr;
152
      end
153
    identifier <= replicate(0);
154
    // Check for last compression
155
    if(wholeBlocks <= 1)
156
      begin
157
        $display("Setting the lastCompression");
158
        destAddr <= md6DestinationAddr;
159
        lastCompression <= True;
160
      end
161
    else
162
      begin
163
        destAddr <= md6BufferAddr;
164
        lastCompression <= False;
165
      end
166
    endaction
167
  endfunction
168
 
169
  rule levelRule (state == LevelStart && !waitingForPad);
170
    currentHeight <= currentHeight+1;
171
    setupLevel();
172
  endrule
173
 
174
  rule computeRule (state == LevelCompute);
175
    if(loadCount == 0 && storeCount == 0)
176
      begin
177
        PaddingBits padding =  0;
178
        $display("Starting engine: %d", targetEngine);
179
        if(targetEngine == fromInteger(valueof(engines)-1))
180
          begin
181
            targetEngine <= 0;
182
          end
183
        else
184
          begin
185
            targetEngine <= targetEngine + 1;
186
          end
187
        // Determine pad status
188
        // We have more regular data left to go. May need to count up on this one
189
        dataBlocksRemaining <= dataBlocksRemaining - 1;
190
        if((dataBlocksRemaining > 1) || (tailNonZeroBits == 0)) // We might have a full block
191
          begin
192
            inTokens.enq(tuple2(NoPad,targetEngine));
193
          end
194
        else
195
          begin
196
            inTokens.enq(tuple2(PadBlock,targetEngine));
197
            waitingForPad <= True;
198
            // Define a block as MD6_c words.
199
            // In this case, we require some padding.
200
            padding = fromInteger(valueof(MD6_WordWidth)*valueof(MD6_b)) - zeroExtend(tailNonZeroBits);
201
            $display("tailNonZero: %d padding: %d",tailNonZeroBits,padding);
202
            // seems that tailNonZero bits is getting smashed
203
          end
204
 
205
        // Must also issue store token.
206
        $display("outToken: %d", targetEngine);
207
        if(dataBlocksRemaining == 1 && lastCompression)
208
          begin
209
            outTokens.enq(tuple2(FinalBlock,targetEngine));
210
          end
211
        else
212
          begin
213
            outTokens.enq(tuple2(Normal,targetEngine));
214
          end
215
        $display("Setting CW: r: %d, l: %d, z:%d, p:%d, keylen: %d, d: %d", valueof(MD6_r),30,(lastCompression)?1:0,
216
                                           padding,  //Padding
217
                                           valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8), // Need Byte Size....
218
                                           valueof(MD6_d));
219
 
220
        let controlWord =  makeControlWord(fromInteger(valueof(MD6_r)),
221
                                           30, // This might be wrong
222
                                           (lastCompression)?1:0,
223
                                           padding,  //Padding
224
                                           fromInteger(valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8)), // Need Byte Size....
225
                                           fromInteger(valueof(MD6_d))); // this one is in bits.
226
          // Construct identifier.
227
          Bit#(8) identLevel = currentHeight;
228
          Bit#(64) identifierFull = {identLevel,truncate(pack(identifier))};
229
          identifier <= unpack(pack(identifier) + 1);
230
          md6Engines[targetEngine].start(unpack(pack(identifierFull)), controlWord, keyReg);
231
 
232
      end
233
 
234
    if( (loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) &&
235
       (storeCount == fromInteger(valueof(MD6BurstsPerHashStore)-1)))
236
      begin
237
        loadCount <= 0;
238
        storeCount <= 0;
239
        // Check for the need to transition out of this state.
240
        // Hmm... This doesn't seem right probably only want to transition
241
        // once we're sure when we're done.
242
        $display("In unoptimized clause dataBlocksRemaining: %d", dataBlocksRemaining);
243
        // Correct as we require 1 load/1 store at least
244
        if(dataBlocksRemaining == 0)
245
          begin
246
 
247
            if(lastCompression)
248
              begin
249
                $display("Setting state idlewait");
250
                state <= IdleWait;
251
              end
252
            else
253
              begin
254
                //must fix md6BitSize here.
255
                // Probably have to fix type...
256
                Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize);
257
                Bit#(TLog#(MD6BitsPerHashOutput)) bottomZeros= 0;
258
                match {.wholeBlocks, .tailBits} = currentBits;
259
 
260
                md6BitSize <= zeroExtend({((tailBits!=0)?wholeBlocks+1:wholeBlocks), bottomZeros});
261
                state <= LevelStart;
262
               end
263
          end
264
 
265
 
266
        plbCommand.enq(tagged StorePage destAddr);
267
        destAddr <=  truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst)))));
268
        // Actually issue the store here
269
 
270
       end
271
      // This clause optimized away for default params.
272
    else if((loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) &&
273
       (storeCount < fromInteger(valueof(MD6BurstsPerHashStore)-1)))
274
      begin
275
        $display("In optimized clause");
276
        storeCount <= storeCount + 1;
277
        plbCommand.enq(tagged StorePage destAddr);
278
        destAddr <=  truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst)))));
279
      end
280
    else
281
      begin
282
        loadCount <= loadCount + 1;
283
        $display("Issue Load: %d", sourceAddr);
284
        plbCommand.enq(tagged LoadPage sourceAddr);
285
        sourceAddr <=  truncateLSB({sourceAddr,0} + (1 << (valueof(TLog#(WordsPerBurst)))));
286
      end
287
  endrule
288
 
289
 
290
  // This rule will feed output from the MD6 engine to the memory controller
291
  method ActionValue#(MD6Word) wordOutput();
292
    match {.block, .engine} = outTokens.first;
293
    if(wordsOutgoing  == fromInteger(valueof(MD6_c) - 1))
294
      begin
295
       wordsOutgoing <= 0;
296
       outTokens.deq;
297
       if(block == FinalBlock)
298
         begin
299
           state <= Idle; // At this point, we're really done...
300
         end
301
      end
302
    else
303
      begin
304
       wordsOutgoing <= wordsOutgoing + 1;
305
      end
306
    $display("outgoing word");
307
    MD6Word word <- md6Engines[engine].outputWord;
308
    return word;
309
  endmethod
310
 
311
  // This rule handles input from the outside world to the MD6 controller
312
  // This includes padding
313
  method Action wordInput(MD6Word inWord);
314
    // Must deal with zero padding at the end of the
315
    // first round.
316
 
317
    $display("inputWord called: %h", inWord);
318
    match {.blockType, .engine } = inTokens.first;
319
 
320
    if(wordsIncoming == fromInteger(valueof(MD6_b) - 1))
321
      begin
322
       wordsIncoming <= 0;
323
       if(blockType == PadBlock)
324
         begin
325
           waitingForPad <= False;
326
         end
327
       inTokens.deq;
328
      end
329
    else
330
      begin
331
       wordsIncoming <= wordsIncoming + 1;
332
      end
333
 
334
    if(blockType == PadBlock)
335
      begin
336
        $display("Padblock, tailNonZeroBits: %d", tailNonZeroBits);
337
        // Now, pad the leftover bits to zero
338
        if(tailNonZeroBits > fromInteger(valueof(MD6_WordWidth)))
339
          begin
340
            tailNonZeroBits <= tailNonZeroBits - fromInteger(valueof(MD6_WordWidth));
341
            md6Engines[engine].inputWord(inWord);
342
          end
343
        else if(tailNonZeroBits > 0)
344
          begin
345
            Bit#(TLog#(MD6_WordWidth)) shiftValue = truncate(tailNonZeroBits);
346
            Bit#(MD6_WordWidth) paddedWord = inWord & (~0 >> shiftValue);
347
            md6Engines[engine].inputWord(paddedWord);
348
            tailNonZeroBits <= 0;
349
          end
350
        else // All zeros from here.
351
          begin
352
            md6Engines[engine].inputWord(0);
353
          end
354
      end
355
    else if(blockType ==  NoPad)
356
      begin
357
        md6Engines[engine].inputWord(inWord);
358
      end
359
  endmethod
360
 
361
  method ActionValue#(PLBMasterCommand) outputCommand();
362
    plbCommand.deq;
363
    return plbCommand.first;
364
  endmethod
365
 
366
  // On the first pass only, we may have some tail non-zero bits.  we must pad these out.
367
  // All blocks must be padded to MD6_WordWidth
368
  method Action startDecode();
369
    if(state  == Idle)
370
      begin
371
        currentHeight <= 1;
372
        setupLevel();
373
      end
374
  endmethod
375
 
376
  method Bool running();
377
    return !(state == Idle);
378
  endmethod
379
 
380
  interface Reg keyRegister = keyReg;
381
  interface Reg sourceAddress = md6SourceAddr;
382
  interface Reg destinationAddress = md6DestinationAddr;
383
  interface Reg bufferAddress = md6BufferAddr;
384
  interface Reg bitSize = md6BitSize;
385
 
386
 
387
endmodule

powered by: WebSVN 2.1.0

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