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 |
/*
|
27 |
|
|
Copyright (c) 2008 MIT
|
28 |
|
|
|
29 |
|
|
Permission is hereby granted, free of charge, to any person
|
30 |
|
|
obtaining a copy of this software and associated documentation
|
31 |
|
|
files (the "Software"), to deal in the Software without
|
32 |
|
|
restriction, including without limitation the rights to use,
|
33 |
|
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
34 |
|
|
copies of the Software, and to permit persons to whom the
|
35 |
|
|
Software is furnished to do so, subject to the following
|
36 |
|
|
conditions:
|
37 |
|
|
|
38 |
|
|
The above copyright notice and this permission notice shall be
|
39 |
|
|
included in all copies or substantial portions of the Software.
|
40 |
|
|
|
41 |
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
42 |
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
43 |
|
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
44 |
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
45 |
|
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
46 |
|
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
47 |
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
48 |
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
49 |
|
|
|
50 |
|
|
Author: Kermin Fleming
|
51 |
|
|
*/
|
52 |
|
|
|
53 |
|
|
/* This is the top-level sorter module. It interfaces to the PLB bus, the
|
54 |
|
|
DSOCM, and the sorter core. Not much functionality, but it does have
|
55 |
|
|
a cycle timer, and sends periodic messages back to the PPC over the
|
56 |
|
|
DSOCM
|
57 |
|
|
*/
|
58 |
|
|
|
59 |
|
|
// Bluespec Lib
|
60 |
|
|
import FIFO::*;
|
61 |
|
|
import GetPut::*;
|
62 |
|
|
import Vector::*;
|
63 |
|
|
import Connectable::*;
|
64 |
|
|
|
65 |
|
|
// CSG Lib
|
66 |
|
|
import PLBMasterWires::*;
|
67 |
|
|
import BRAMInitiatorWires::*;
|
68 |
|
|
import PLBMaster::*;
|
69 |
|
|
import BRAMFeeder::*;
|
70 |
|
|
import PLBMaster::*;
|
71 |
|
|
import PLBMasterDefaultParameters::*;
|
72 |
|
|
|
73 |
|
|
// Local includes
|
74 |
|
|
import CompressionFunction::*;
|
75 |
|
|
import CompressionFunctionLibrary::*;
|
76 |
|
|
import MD6Parameters::*;
|
77 |
|
|
import MD6Types::*;
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
interface MD6Engine;
|
81 |
|
|
interface PLBMasterWires plbMasterWires;
|
82 |
|
|
interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires;
|
83 |
|
|
endinterface
|
84 |
|
|
|
85 |
|
|
// Might consider making this size 8 at some point so that it jives with
|
86 |
|
|
// other parameterizations
|
87 |
|
|
typedef 16 InterfaceRegister;
|
88 |
|
|
typedef Bit#(15) RegisterTag;
|
89 |
|
|
|
90 |
|
|
typedef enum {
|
91 |
|
|
Read = 0,
|
92 |
|
|
Write = 1
|
93 |
|
|
} Command deriving (Bits,Eq);
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
typedef 7 ControlRegisters;
|
97 |
|
|
typedef TMul#(MD6_u,TDiv#(MD6_WordWidth,InterfaceRegister)) IdentifierRegisters;
|
98 |
|
|
typedef TMul#(MD6_k,TDiv#(MD6_WordWidth,InterfaceRegister)) KeyRegisters;
|
99 |
|
|
typedef 2 SourceRegisters;
|
100 |
|
|
typedef 2 DestinationRegisters;
|
101 |
|
|
|
102 |
|
|
typedef 0 RoundRegister;
|
103 |
|
|
typedef 1 TreeHeightRegister;
|
104 |
|
|
typedef 2 LastCompressionRegister;
|
105 |
|
|
typedef 3 PaddingBitsRegister;
|
106 |
|
|
typedef 4 KeyLengthRegister;
|
107 |
|
|
typedef 5 DigestLengthRegister;
|
108 |
|
|
typedef 6 CompressionFunctionStatus;
|
109 |
|
|
typedef 7 KeyRegisterBase;
|
110 |
|
|
typedef TAdd#(ControlRegisters,KeyRegisters) IdentifierRegisterBase;
|
111 |
|
|
typedef TAdd#(ControlRegisters, TAdd#(KeyRegisters,IdentifierRegisters)) SourceRegisterBase;
|
112 |
|
|
typedef TAdd#(TAdd#(ControlRegisters,IdentifierRegisters), TAdd#(KeyRegisters,SourceRegisters)) DestinationRegisterBase;
|
113 |
|
|
typedef TAdd#(IdentifierRegisters,TAdd#(TAdd#(ControlRegisters,DestinationRegisters), TAdd#(KeyRegisters,SourceRegisters))) TotalRegisters;
|
114 |
|
|
|
115 |
|
|
typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst;
|
116 |
|
|
|
117 |
|
|
typedef 32'hC0000 MD6CommunicationConstant;
|
118 |
|
|
|
119 |
|
|
typedef struct {
|
120 |
|
|
Command command;
|
121 |
|
|
RegisterTag regTag;
|
122 |
|
|
Bit#(InterfaceRegister) payload;
|
123 |
|
|
} IOCommand deriving (Bits,Eq);
|
124 |
|
|
|
125 |
|
|
typedef enum {
|
126 |
|
|
Idle,
|
127 |
|
|
Load
|
128 |
|
|
} LoadState deriving (Bits,Eq);
|
129 |
|
|
|
130 |
|
|
typedef enum {
|
131 |
|
|
Idle,
|
132 |
|
|
Store
|
133 |
|
|
} StoreState deriving (Bits,Eq);
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
(*synthesize*)
|
137 |
|
|
module mkCompressionFunction16 (CompressionFunction#(16));
|
138 |
|
|
let m <- mkSimpleCompressionFunction;
|
139 |
|
|
return m;
|
140 |
|
|
endmodule
|
141 |
|
|
|
142 |
|
|
(*synthesize*)
|
143 |
|
|
module mkCompressionFunction8 (CompressionFunction#(8));
|
144 |
|
|
let m <- mkSimpleCompressionFunction;
|
145 |
|
|
return m;
|
146 |
|
|
endmodule
|
147 |
|
|
|
148 |
|
|
(*synthesize*)
|
149 |
|
|
module mkCompressionFunction4 (CompressionFunction#(4));
|
150 |
|
|
let m <- mkSimpleCompressionFunction;
|
151 |
|
|
return m;
|
152 |
|
|
endmodule
|
153 |
|
|
|
154 |
|
|
(*synthesize*)
|
155 |
|
|
module mkCompressionFunction2 (CompressionFunction#(2));
|
156 |
|
|
let m <- mkSimpleCompressionFunction;
|
157 |
|
|
return m;
|
158 |
|
|
endmodule
|
159 |
|
|
|
160 |
|
|
(*synthesize*)
|
161 |
|
|
module mkCompressionFunction1 (CompressionFunction#(1));
|
162 |
|
|
let m <- mkSimpleCompressionFunction;
|
163 |
|
|
return m;
|
164 |
|
|
endmodule
|
165 |
|
|
|
166 |
|
|
|
167 |
|
|
module mkMD6Engine (MD6Engine);
|
168 |
|
|
Feeder feeder <- mkBRAMFeeder();
|
169 |
|
|
PLBMaster plbMaster <- mkPLBMaster;
|
170 |
|
|
CompressionFunction#(4) compressionFunction <- mkSimpleCompressionFunction;
|
171 |
|
|
FIFO#(PPCMessage) outputFIFO <- mkFIFO;
|
172 |
|
|
Vector#(TotalRegisters, Reg#(Bit#(InterfaceRegister))) interfaceRegisters <-
|
173 |
|
|
replicateM(mkReg(0));
|
174 |
|
|
|
175 |
|
|
|
176 |
|
|
// Hook Control, PLBMaster and MD6 engine components together.
|
177 |
|
|
// This solution WILL NOT WORK for multiple Compression functions
|
178 |
|
|
mkConnection(plbMaster.wordInput.put, compressionFunction.outputWord);
|
179 |
|
|
mkConnection(compressionFunction.inputWord,plbMaster.wordOutput.get);
|
180 |
|
|
mkConnection(feeder.ppcMessageInput.put,(fifoToGet(outputFIFO)).get);
|
181 |
|
|
|
182 |
|
|
Reg#(Bit#(TAdd#(1,TDiv#(MD6_b,MD6WordsPerBurst)))) loadCount <- mkReg(0);
|
183 |
|
|
|
184 |
|
|
Reg#(Bit#(TAdd#(1,TDiv#(MD6_c,MD6WordsPerBurst)))) storeCount <- mkReg(0);
|
185 |
|
|
|
186 |
|
|
Reg#(LoadState) loadState <- mkReg(Idle);
|
187 |
|
|
|
188 |
|
|
Reg#(StoreState) storeState <- mkReg(Idle);
|
189 |
|
|
|
190 |
|
|
FIFO#(IOCommand) incomingCommands <- mkFIFO;
|
191 |
|
|
|
192 |
|
|
function IOCommand extractIOCommand(PPCMessage ppcMessage);
|
193 |
|
|
IOCommand command = IOCommand {command: unpack(ppcMessage[31]),
|
194 |
|
|
regTag: ppcMessage[30:16],
|
195 |
|
|
payload: ppcMessage[15:0]};
|
196 |
|
|
return command;
|
197 |
|
|
endfunction
|
198 |
|
|
|
199 |
|
|
// This function may require its own unit test
|
200 |
|
|
// It should convert interface words to MD6 Words
|
201 |
|
|
function Vector#(length,MD6Word) convertWords(
|
202 |
|
|
Vector#(TMul#(length,TDiv#(MD6_WordWidth,InterfaceRegister)),Bit#(InterfaceRegister)) inVector);
|
203 |
|
|
Vector#(length,MD6Word) outVector = newVector;
|
204 |
|
|
for(Integer totalNumber = 0;
|
205 |
|
|
totalNumber < valueof(length);
|
206 |
|
|
totalNumber = totalNumber + 1)
|
207 |
|
|
begin
|
208 |
|
|
Vector#(TDiv#(MD6_WordWidth,InterfaceRegister),Bit#(InterfaceRegister)) wordVector = newVector;
|
209 |
|
|
for(Integer wordsInMD6Word = 0;
|
210 |
|
|
wordsInMD6Word < valueof(TDiv#(MD6_WordWidth,InterfaceRegister));
|
211 |
|
|
wordsInMD6Word = wordsInMD6Word + 1)
|
212 |
|
|
begin
|
213 |
|
|
wordVector[wordsInMD6Word] = inVector[totalNumber*valueof(TDiv#(MD6_WordWidth,InterfaceRegister))
|
214 |
|
|
+wordsInMD6Word];
|
215 |
|
|
end
|
216 |
|
|
outVector[totalNumber] = unpack(pack(wordVector)); // is this sane?
|
217 |
|
|
end
|
218 |
|
|
return outVector;
|
219 |
|
|
endfunction
|
220 |
|
|
|
221 |
|
|
rule getCommand;
|
222 |
|
|
PPCMessage msg <- feeder.ppcMessageOutput.get;
|
223 |
|
|
IOCommand command = extractIOCommand(msg);
|
224 |
|
|
incomingCommands.enq(command);
|
225 |
|
|
endrule
|
226 |
|
|
|
227 |
|
|
// Writing to the CompressionFunctionStatus means kickoff a compression operation
|
228 |
|
|
// Reading from it will grab the current status of the Compression Engine
|
229 |
|
|
|
230 |
|
|
rule processWrite(incomingCommands.first.command == Write);
|
231 |
|
|
incomingCommands.deq;
|
232 |
|
|
|
233 |
|
|
if(fromInteger(valueof(CompressionFunctionStatus)) == incomingCommands.first.regTag)
|
234 |
|
|
begin
|
235 |
|
|
// we can leave this unguarded because the properties of the compression function
|
236 |
|
|
// will prevent doing nasty things like confusing the order of memory accesses.
|
237 |
|
|
let controlWord = makeControlWord(truncate(interfaceRegisters[valueof(RoundRegister)]),
|
238 |
|
|
truncate(interfaceRegisters[valueof(TreeHeightRegister)]),
|
239 |
|
|
truncate(interfaceRegisters[valueof(LastCompressionRegister)]),
|
240 |
|
|
truncate(interfaceRegisters[valueof(PaddingBitsRegister)]),
|
241 |
|
|
truncate(interfaceRegisters[valueof(KeyLengthRegister)]),
|
242 |
|
|
truncate(interfaceRegisters[valueof(DigestLengthRegister)]));
|
243 |
|
|
|
244 |
|
|
compressionFunction.start(convertWords(takeAt(valueof(IdentifierRegisterBase),readVReg(interfaceRegisters))),
|
245 |
|
|
controlWord,
|
246 |
|
|
convertWords(takeAt(valueof(KeyRegisterBase),readVReg(interfaceRegisters))));
|
247 |
|
|
loadState <= Load;
|
248 |
|
|
loadCount <= 0;
|
249 |
|
|
end
|
250 |
|
|
else
|
251 |
|
|
begin
|
252 |
|
|
interfaceRegisters[incomingCommands.first.regTag] <= incomingCommands.first.payload;
|
253 |
|
|
end
|
254 |
|
|
endrule
|
255 |
|
|
|
256 |
|
|
rule processRead(incomingCommands.first.command == Read);
|
257 |
|
|
incomingCommands.deq;
|
258 |
|
|
|
259 |
|
|
// This is a bit ugly, and we should possibly fix it.
|
260 |
|
|
if(fromInteger(valueof(CompressionFunctionStatus)) == incomingCommands.first.regTag)
|
261 |
|
|
begin
|
262 |
|
|
outputFIFO.enq(fromInteger(valueof(MD6CommunicationConstant))|zeroExtend(compressionFunction.status));
|
263 |
|
|
end
|
264 |
|
|
else
|
265 |
|
|
begin
|
266 |
|
|
outputFIFO.enq(fromInteger(valueof(MD6CommunicationConstant))|zeroExtend((interfaceRegisters[incomingCommands.first.regTag])));
|
267 |
|
|
end
|
268 |
|
|
|
269 |
|
|
endrule
|
270 |
|
|
|
271 |
|
|
|
272 |
|
|
|
273 |
|
|
|
274 |
|
|
// Probably should handle non-fitting burst sizes. But, don't have to
|
275 |
|
|
// for now.
|
276 |
|
|
if(valueof(TotalRegisters) != 47)
|
277 |
|
|
begin
|
278 |
|
|
error("Total Registers: %d\n",valueof(TotalRegisters));
|
279 |
|
|
end
|
280 |
|
|
|
281 |
|
|
if(valueof(MD6_b)%valueof(MD6WordsPerBurst) != 0)
|
282 |
|
|
begin
|
283 |
|
|
error("MD6_b:%d not divisible by MD6WordsPerBurst:%d",valueof(MD6_b), valueof(MD6WordsPerBurst));
|
284 |
|
|
end
|
285 |
|
|
|
286 |
|
|
if(valueof(MD6_c)%valueof(MD6WordsPerBurst) != 0)
|
287 |
|
|
begin
|
288 |
|
|
error("MD6_c:%d not divisible by MD6WordsPerBurst:%d",valueof(MD6_c), valueof(MD6WordsPerBurst));
|
289 |
|
|
end
|
290 |
|
|
|
291 |
|
|
rule issueLoads(loadState == Load);
|
292 |
|
|
if(loadCount + 1 == fromInteger(valueof(MD6_b)/valueof(MD6WordsPerBurst)))
|
293 |
|
|
begin
|
294 |
|
|
loadState <= Idle;
|
295 |
|
|
storeState <= Store;
|
296 |
|
|
storeCount <= 0;
|
297 |
|
|
end
|
298 |
|
|
loadCount <= loadCount + 1;
|
299 |
|
|
BlockAddr refAddr = truncateLSB({interfaceRegisters[valueof(SourceRegisterBase)+1],
|
300 |
|
|
interfaceRegisters[valueof(SourceRegisterBase)]})
|
301 |
|
|
+ (zeroExtend(loadCount) << (valueof(TLog#(WordsPerBurst))));
|
302 |
|
|
|
303 |
|
|
plbMaster.plbMasterCommandInput.put(tagged LoadPage refAddr);
|
304 |
|
|
endrule
|
305 |
|
|
|
306 |
|
|
|
307 |
|
|
|
308 |
|
|
rule issueStores(storeState == Store);
|
309 |
|
|
if(storeCount + 1 == fromInteger(valueof(MD6_c)/valueof(MD6WordsPerBurst)))
|
310 |
|
|
begin
|
311 |
|
|
storeState <= Idle;
|
312 |
|
|
end
|
313 |
|
|
storeCount <= storeCount + 1;
|
314 |
|
|
|
315 |
|
|
BlockAddr refAddr = truncateLSB({interfaceRegisters[valueof(DestinationRegisterBase)+1],
|
316 |
|
|
interfaceRegisters[valueof(DestinationRegisterBase)]})
|
317 |
|
|
+ (zeroExtend(storeCount) << (valueof(TLog#(WordsPerBurst))));
|
318 |
|
|
|
319 |
|
|
plbMaster.plbMasterCommandInput.put(tagged StorePage refAddr);
|
320 |
|
|
endrule
|
321 |
|
|
|
322 |
|
|
interface plbMasterWires = plbMaster.plbMasterWires;
|
323 |
|
|
interface bramInitiatorWires = feeder.bramInitiatorWires;
|
324 |
|
|
|
325 |
|
|
endmodule
|