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

Subversion Repositories cryptosorter

[/] [cryptosorter/] [trunk/] [memocodeDesignContest2008/] [xup/] [ExternalMemory/] [ExternalMemory.bsv] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 kfleming
/*
2
Copyright (c) 2008 MIT
3
 
4
Permission is hereby granted, free of charge, to any person
5
obtaining a copy of this software and associated documentation
6
files (the "Software"), to deal in the Software without
7
restriction, including without limitation the rights to use,
8
copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the
10
Software is furnished to do so, subject to the following
11
conditions:
12
 
13
The above copyright notice and this permission notice shall be
14
included in all copies or substantial portions of the Software.
15
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
OTHER DEALINGS IN THE SOFTWARE.
24
 
25
Author: Kermin Fleming
26
*/
27
 
28
/*  This module serves as an abstraction layer for wrapping an external memory
29
    system.  In particular, it emulates a parametric number  of
30
    read and write virtual channels, sheilding the user module from the actual
31
    details of the underlying memory system.  Thus, user modules may be
32
    implemented targeting the same "External Memory" and then used in
33
    systems with radically different memory subsystems. The module orders writes
34
    before reads. It is additionally parameterized by address width (Addr)
35
    and data width.
36
*/
37
 
38
 
39
import Memocode08Types::*;
40
import Vector::*;
41
import FIFOF::*;
42
import Types::*;
43
import Interfaces::*;
44
import Parameters::*;
45
import DebugFlags::*;
46
import GetPut::*;
47
 
48
module mkExternalMemory#(PLBMaster plbmaster) (ExternalMemory);
49
 
50
  FIFOF#(Bit#(TAdd#(1,TLog#(ReadPortNum)))) readRespFIFO <- mkFIFOF();
51
  FIFOF#(Bit#(TAdd#(1,TLog#(ReadPortNum)))) writeFIFO <- mkFIFOF();
52
 
53
  Reg#(Bit#(TLog#(RecordsPerBlock))) readRespCount  <- mkReg(0);
54
  Reg#(Bit#(TLog#(RecordsPerBlock))) writeCount <- mkReg(0);
55
  Reg#(Bit#(TLog#(TAdd#(TAdd#(WritePortNum,ReadPortNum),1))))  outstandingCount <- mkReg(0);
56
  Reg#(Bit#(TLog#(TAdd#(WritePortNum,ReadPortNum))))  nextToSend <- mkReg(0);
57
 
58
 
59
  FIFOF#(Vector#(TAdd#(ReadPortNum, WritePortNum), Maybe#(PLBMasterCommand))) reqSnapshot <- mkSizedFIFOF(1);
60
 
61
  Vector#(ReadPortNum, RWire#(Addr)) readReqs <- replicateM(mkRWire);
62
  Vector#(WritePortNum, RWire#(Addr)) writeReqs <- replicateM(mkRWire);
63
 
64
  Vector#(ReadPortNum, Read) readInterfaces = newVector();
65
  Vector#(WritePortNum, Write) writeInterfaces = newVector();
66
 
67
 
68
  for(Integer i = 0; i < valueof(ReadPortNum); i = i + 1)
69
    begin
70
      readInterfaces[i] =
71
        interface Read;
72
          // Should we go round robin?
73
          method Action readReq(Addr addr) if(reqSnapshot.notFull());
74
            debug(externalMemoryDebug,$display("ReadPort %d making ReadReq %h at %d", i, addr,$time));
75
            readReqs[i].wset(addr);
76
          endmethod
77
 
78
          // May want to use some buffering here.  Might help things out.
79
          method ActionValue#(Record) read() if(readRespFIFO.first() ==
80
                                                fromInteger(i));
81
            debug(externalMemoryDebug,$display("ReadPort %d making Read %d", i, readRespCount));
82
            if(readRespCount + 1 == 0)
83
              begin
84
                debug(externalMemoryDebug,$display("ReadPort %d Load Complete!", i));
85
                readRespFIFO.deq;
86
                readRespCount <= 0;
87
              end
88
            else
89
              begin
90
                readRespCount <= readRespCount + 1;
91
              end
92
            Record record <- plbmaster.wordOutput.get;
93
            return record;
94
          endmethod
95
        endinterface;
96
    end
97
 
98
  for(Integer i = 0; i < valueof(WritePortNum); i = i + 1)
99
    begin
100
      writeInterfaces[i] =
101
        interface Write;
102
          // Should we go round robin?  SHould we delay as long as possible?
103
          method Action writeReq(Addr addr) if(reqSnapshot.notFull());
104
            debug(externalMemoryDebug,$display("WritePort %d making WriteReq %h", i, addr));
105
            writeReqs[i].wset(addr);
106
          endmethod
107
 
108
          // May want to use some buffering here.  Might help things out.
109
          method Action write(Record record) if(writeFIFO.first() ==
110
                                                fromInteger(i));
111
            if(writeCount + 1 == 0)
112
              begin
113
                debug(externalMemoryDebug,$display("WritePort %d Load Complete!", i));
114
                writeFIFO.deq;
115
                writeCount <= 0;
116
              end
117
            else
118
              begin
119
                writeCount <= writeCount + 1;
120
              end
121
            plbmaster.wordInput.put(record);
122
          endmethod
123
        endinterface;
124
 
125
    end
126
 
127
 
128
  function checkMaybe(previous, maybeVal);
129
    if(maybeVal matches tagged Valid .data)
130
      begin
131
        return True;
132
      end
133
    else
134
      begin
135
        return previous;
136
      end
137
  endfunction
138
 
139
  function castStore(addrMaybe);
140
    if(addrMaybe matches tagged Valid .addr)
141
      begin
142
        return tagged Valid StorePage(unpack(truncate(pack(addr))));
143
      end
144
    else
145
      begin
146
        return tagged Invalid;
147
      end
148
  endfunction
149
 
150
  function castLoad(addrMaybe);
151
    if(addrMaybe matches tagged Valid .addr)
152
      begin
153
        return tagged Valid LoadPage(unpack(truncate(pack(addr))));
154
      end
155
    else
156
      begin
157
        return tagged Invalid;
158
      end
159
  endfunction
160
 
161
  function Maybe#(Addr) callwget(RWire#(Addr) rwire);
162
    return rwire.wget;
163
  endfunction
164
 
165
  rule processReqs;
166
    Bool shouldEnq = foldl(checkMaybe,False,append(map(callwget,writeReqs),map(callwget,readReqs)));
167
    if(shouldEnq)
168
      begin
169
        debug(externalMemoryDebug,$display("Processing Reqs at %d", $time));
170
        reqSnapshot.enq(append(map(castLoad, map(callwget,readReqs)),map(castStore,map(callwget,writeReqs))));
171
      end
172
  endrule
173
 
174
  rule chooseReq;
175
    Maybe#(Bit#(TLog#(TAdd#(WritePortNum,ReadPortNum)))) sendTarget = tagged Invalid;
176
    for(Integer i = valueof(WritePortNum) + valueof(ReadPortNum) - 1; i >= 0; i = i - 1)
177
      begin
178
        if(reqSnapshot.first[i] matches tagged Valid .cmd &&& (fromInteger(i) >= nextToSend))
179
          begin
180
            sendTarget = tagged Valid fromInteger(i);
181
          end
182
      end
183
 
184
    debug(externalMemoryDebug,$display("Sending Reqs, upto: %d, next index: %d", nextToSend, fromMaybe(-1,sendTarget)));
185
 
186
    if(sendTarget matches tagged Valid .index &&& reqSnapshot.first[index] matches tagged Valid .cmd)
187
      begin
188
        plbmaster.plbMasterCommandInput.put(cmd);
189
        if(cmd matches tagged LoadPage .addr)
190
          begin
191
            debug(externalMemoryDebug,$display("Issuing Load %d actual: %d", index, index));
192
            readRespFIFO.enq(truncate(index));
193
          end
194
        else
195
          begin
196
            debug(externalMemoryDebug,$display("Issuing Store %d actual: %d", index, index-fromInteger(valueof(WritePortNum))));
197
            writeFIFO.enq(truncate(index-fromInteger(valueof(ReadPortNum))));
198
          end
199
 
200
        if(index >= fromInteger(valueof(WritePortNum)+ valueof(ReadPortNum) - 1))
201
          begin
202
            debug(externalMemoryDebug,$display("Req Q deq, due to last request"));
203
            reqSnapshot.deq;
204
            nextToSend <= 0;
205
          end
206
        else
207
          begin
208
            nextToSend <= index + 1;
209
          end
210
      end
211
    else
212
      begin
213
        debug(externalMemoryDebug,$display("Req Q deq, due to no valid requests"));
214
        nextToSend <= 0;
215
        reqSnapshot.deq;
216
      end
217
 
218
  endrule
219
 
220
 
221
  // This is conservative...
222
  method Bool readsPending();
223
    return reqSnapshot.notEmpty || readRespFIFO.notEmpty;
224
  endmethod
225
 
226
  method Bool writesPending();
227
    return reqSnapshot.notEmpty || writeFIFO.notEmpty;
228
  endmethod
229
 
230
  interface  read = readInterfaces;
231
  interface  write = writeInterfaces;
232
 
233
 
234
endmodule
235
 
236
 
237
 
238
 
239
 

powered by: WebSVN 2.1.0

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