|
Message
From: cvs at opencores.org<cvs@o...>
Date: Mon Jun 30 18:02:13 CEST 2008
Subject: [cvs-checkins] MODIFIED: cryptosorter ...
Date: 00/08/06 30:18:02 Added: cryptosorter/memocodeDesignContest2008/xup/ExternalMemory ExternalMemory.bsv ExternalMemoryTestbench.bsv ExternalMemoryTester.bsv Log: Initial checkin with actual source Revision Changes Path 1.1 cryptosorter/memocodeDesignContest2008/xup/ExternalMemory/ExternalMemory.bsv http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/xup/ExternalMemory/ExternalMemory.bsv?rev=1.1&content-type=text/x-cvsweb-markup Index: ExternalMemory.bsv =================================================================== /* Copyright (c) 2008 MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Author: Kermin Fleming */ /* This module serves as an abstraction layer for wrapping an external memory system. In particular, it emulates a parametric number of read and write virtual channels, sheilding the user module from the actual details of the underlying memory system. Thus, user modules may be implemented targeting the same "External Memory" and then used in systems with radically different memory subsystems. The module orders writes before reads. It is additionally parameterized by address width (Addr) and data width. */ import Memocode08Types::*; import Vector::*; import FIFOF::*; import Types::*; import Interfaces::*; import Parameters::*; import DebugFlags::*; import GetPut::*; module mkExternalMemory#(PLBMaster plbmaster) (ExternalMemory); FIFOF#(Bit#(TAdd#(1,TLog#(ReadPortNum)))) readRespFIFO <- mkFIFOF(); FIFOF#(Bit#(TAdd#(1,TLog#(ReadPortNum)))) writeFIFO <- mkFIFOF(); Reg#(Bit#(TLog#(RecordsPerBlock))) readRespCount <- mkReg(0); Reg#(Bit#(TLog#(RecordsPerBlock))) writeCount <- mkReg(0); Reg#(Bit#(TLog#(TAdd#(TAdd#(WritePortNum,ReadPortNum),1)))) outstandingCount <- mkReg(0); Reg#(Bit#(TLog#(TAdd#(WritePortNum,ReadPortNum)))) nextToSend <- mkReg(0); FIFOF#(Vector#(TAdd#(ReadPortNum, WritePortNum), Maybe#(PLBMasterCommand))) reqSnapshot <- mkSizedFIFOF(1); Vector#(ReadPortNum, RWire#(Addr)) readReqs <- replicateM(mkRWire); Vector#(WritePortNum, RWire#(Addr)) writeReqs <- replicateM(mkRWire); Vector#(ReadPortNum, Read) readInterfaces = newVector(); Vector#(WritePortNum, Write) writeInterfaces = newVector(); for(Integer i = 0; i < valueof(ReadPortNum); i = i + 1) begin readInterfaces[i] = interface Read; // Should we go round robin? method Action readReq(Addr addr) if(reqSnapshot.notFull()); debug(externalMemoryDebug,$display("ReadPort %d making ReadReq %h at %d", i, addr,$time)); readReqs[i].wset(addr); endmethod // May want to use some buffering here. Might help things out. method ActionValue#(Record) read() if(readRespFIFO.first() == fromInteger(i)); debug(externalMemoryDebug,$display("ReadPort %d making Read %d", i, readRespCount)); if(readRespCount + 1 == 0) begin debug(externalMemoryDebug,$display("ReadPort %d Load Complete!", i)); readRespFIFO.deq;
readRespCount <= 0;
end
else
begin
readRespCount <= readRespCount + 1;
end
Record record <- plbmaster.wordOutput.get;
return record;
endmethod
endinterface;
end
for(Integer i = 0; i < valueof(WritePortNum); i = i + 1)
begin
writeInterfaces[i] =
interface Write;
// Should we go round robin? SHould we delay as long as possible?
method Action writeReq(Addr addr) if(reqSnapshot.notFull());
debug(externalMemoryDebug,$display("WritePort %d making WriteReq %h", i, addr));
writeReqs[i].wset(addr);
endmethod
// May want to use some buffering here. Might help things out.
method Action write(Record record) if(writeFIFO.first() ==
fromInteger(i));
if(writeCount + 1 == 0)
begin
debug(externalMemoryDebug,$display("WritePort %d Load Complete!", i));
writeFIFO.deq;
writeCount <= 0;
end
else
begin
writeCount <= writeCount + 1;
end
plbmaster.wordInput.put(record);
endmethod
endinterface;
end
function checkMaybe(previous, maybeVal);
if(maybeVal matches tagged Valid .data)
begin
return True;
end
else
begin
return previous;
end
endfunction
function castStore(addrMaybe);
if(addrMaybe matches tagged Valid .addr)
begin
return tagged Valid StorePage(unpack(truncate(pack(addr))));
end
else
begin
return tagged Invalid;
end
endfunction
function castLoad(addrMaybe);
if(addrMaybe matches tagged Valid .addr)
begin
return tagged Valid LoadPage(unpack(truncate(pack(addr))));
end
else
begin
return tagged Invalid;
end
endfunction
function Maybe#(Addr) callwget(RWire#(Addr) rwire);
return rwire.wget;
endfunction
rule processReqs;
Bool shouldEnq = foldl(checkMaybe,False,append(map(callwget,writeReqs),map(callwget,readReqs)));
if(shouldEnq)
begin
debug(externalMemoryDebug,$display("Processing Reqs at %d", $time));
reqSnapshot.enq(append(map(castLoad, map(callwget,readReqs)),map(castStore,map(callwget,writeReqs))));
end
endrule
rule chooseReq;
Maybe#(Bit#(TLog#(TAdd#(WritePortNum,ReadPortNum)))) sendTarget = tagged Invalid;
for(Integer i = valueof(WritePortNum) + valueof(ReadPortNum) - 1; i >= 0; i = i - 1)
begin
if(reqSnapshot.first[i] matches tagged Valid .cmd &&& (fromInteger(i) >= nextToSend))
begin
sendTarget = tagged Valid fromInteger(i);
end
end
debug(externalMemoryDebug,$display("Sending Reqs, upto: %d, next index: %d", nextToSend, fromMaybe(-1,sendTarget)));
if(sendTarget matches tagged Valid .index &&& reqSnapshot.first[index] matches tagged Valid .cmd)
begin
plbmaster.plbMasterCommandInput.put(cmd);
if(cmd matches tagged LoadPage .addr)
begin
debug(externalMemoryDebug,$display("Issuing Load %d actual: %d", index, index));
readRespFIFO.enq(truncate(index));
end
else
begin
debug(externalMemoryDebug,$display("Issuing Store %d actual: %d", index, index-fromInteger(valueof(WritePortNum))));
writeFIFO.enq(truncate(index-fromInteger(valueof(ReadPortNum))));
end
if(index >= fromInteger(valueof(WritePortNum)+ valueof(ReadPortNum) - 1))
begin
debug(externalMemoryDebug,$display("Req Q deq, due to last request"));
reqSnapshot.deq;
nextToSend <= 0;
end
else
begin
nextToSend <= index + 1;
end
end
else
begin
debug(externalMemoryDebug,$display("Req Q deq, due to no valid requests"));
nextToSend <= 0;
reqSnapshot.deq;
end
endrule
// This is conservative...
method Bool readsPending();
return reqSnapshot.notEmpty || readRespFIFO.notEmpty;
endmethod
method Bool writesPending();
return reqSnapshot.notEmpty || writeFIFO.notEmpty;
endmethod
interface read = readInterfaces;
interface write = writeInterfaces;
endmodule
1.1 cryptosorter/memocodeDesignContest2008/xup/ExternalMemory/ExternalMemoryTestbench.bsv
http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/xup/ExternalMemory/ExternalMemoryTestbench.bsv?rev=1.1&content-type=text/x-cvsweb-markup
Index: ExternalMemoryTestbench.bsv
===================================================================
/*
Copyright (c) 2008 MIT
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Author: Kermin Fleming
*/
import ExternalMemory::*;
import Memocode08Types::*;
import Types::*;
import Interfaces::*;
import Parameters::*;
import DebugFlags::*;
import PLBMasterWires::*;
import LFSR::*;
import FIFOF::*;
import FIFO::*;
import GetPut::*;
import PLBMasterDummy::*;
typedef enum {
Initialize,
Request,
Transmit
} TesterState deriving(Bits,Eq);
module mkExternalMemoryTestbench (Empty);
Reg#(Bit#(TLog#(TDiv#(TMul#(BlockSize,WordWidth),RecordWidth)))) plbMasterCount <- mkReg(0);
FIFO#(PLBMasterCommand) plbMasterCommand <- mkFIFO();
FIFO#(Record) plbWordInput <- mkFIFO();
FIFO#(Record) plbWordOutput <- mkFIFO();
PLBMaster plbmaster;
plbmaster = interface PLBMaster;
interface Put wordInput;
method Action put(Record wordInput) if(plbMasterCommand.first matches tagged StorePage .addr);
if(zeroExtend(addr) != wordInput)
begin
$display("Store Value %h != %h", addr, wordInput);
$finish;
end
plbMasterCount <= plbMasterCount + 1;
if(plbMasterCount + 1 == 0)
begin
plbMasterCommand.deq;
end
endmethod
endinterface
interface Get wordOutput;
method ActionValue#(Record) get() if(plbMasterCommand.first matches tagged LoadPage .addr);
$display("PLBMaster Output");
plbMasterCount <= plbMasterCount + 1;
if(plbMasterCount + 1 == 0)
begin
$display("plbMaster load command dequed!");
plbMasterCommand.deq;
end
return zeroExtend(addr);
endmethod
endinterface
interface Put plbMasterCommandInput;
method Action put(PLBMasterCommand command);
$display("PLB Master got a command: %s", command matches tagged LoadPage .addr?"Load":"Store");
plbMasterCommand.enq(command);
endmethod
endinterface
interface plbMasterWires = ?;
endinterface;
ExternalMemory extMem <- mkExternalMemory(plbmaster);
rule haltAll;
Bit#(64) timeCount <- $time;
if(timeCount > 1000000100)
begin
$display("PASSED");
$finish;
end
endrule
for(Integer i = 0; i < valueof(ReadPortNum); i = i + 1)
begin
LFSR#(Bit#(16)) lfsr <- mkLFSR_16;
Reg#(TesterState) state <- mkReg(Initialize);
Reg#(Bit#(32)) counter <- mkReg(0);
FIFOF#(Bit#(16)) expectedVals <- mkFIFOF;
Reg#(Bit#(TLog#(RecordsPerBlock))) transmitCount <- mkReg(0);
rule countUp;
counter <= counter + 1;
endrule
rule init(state == Initialize);
state <= Request;
lfsr.seed(fromInteger(i+1));
endrule
rule sendRequest((state == Request) && (counter % fromInteger(32*(i+1)) == 0));
Bit#(64) timeCount <- $time;
if(timeCount < 1000000000)
begin
extMem.read[i].readReq(zeroExtend(lfsr.value));
lfsr.next();
expectedVals.enq(lfsr.value);
end
endrule
rule transmit;
transmitCount <= transmitCount + 1;
if(transmitCount + 1 == 0)
begin
expectedVals.deq;
end
Record valueTransmitted <- extMem.read[i].read;
if(valueTransmitted != zeroExtend(expectedVals.first))
begin
$display("Load Value Reader[%d] %h != %h", i, expectedVals.first, valueTransmitted);
$finish;
end
endrule
rule haltCheck (expectedVals.notEmpty);
Bit#(64) timeCount <- $time;
if(timeCount > 11000000000)
begin
$display("Writer[%d] stalled out", i);
$finish;
end
endrule
end
for(Integer i = 0; i < valueof(WritePortNum); i = i + 1)
begin
LFSR#(Bit#(16)) lfsr <- mkLFSR_16;
Reg#(TesterState) state <- mkReg(Initialize);
Reg#(Bit#(32)) counter <- mkReg(0);
FIFOF#(Bit#(16)) expectedVals <- mkFIFOF;
Reg#(Bit#(TLog#(RecordsPerBlock))) transmitCount <- mkReg(0);
rule countUp;
counter <= counter + 1;
endrule
rule init(state == Initialize);
state <= Request;
lfsr.seed(fromInteger(i+1+valueof(ReadPortNum)));
endrule
rule sendRequest((state == Request) && (counter % fromInteger(32*(i+3)) == 0));
Bit#(64) timeCount <- $time;
if(timeCount < 1000000000)
begin
extMem.write[i].writeReq(zeroExtend(lfsr.value));
lfsr.next();
expectedVals.enq(lfsr.value);
end
endrule
rule transmit;
transmitCount <= transmitCount + 1;
if(transmitCount + 1 == 0)
begin
expectedVals.deq;
end
extMem.write[i].write(zeroExtend(expectedVals.first));
endrule
rule haltCheck (expectedVals.notEmpty);
Bit#(64) timeCount <- $time;
if(timeCount > 11000000000)
begin
$display("Writer[%d] stalled out", i);
$finish;
end
endrule
end
endmodule
1.1 cryptosorter/memocodeDesignContest2008/xup/ExternalMemory/ExternalMemoryTester.bsv
http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/xup/ExternalMemory/ExternalMemoryTester.bsv?rev=1.1&content-type=text/x-cvsweb-markup
Index: ExternalMemoryTester.bsv
===================================================================
/*
Copyright (c) 2008 MIT
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Author: Kermin Fleming
*/
import ExternalMemory::*;
import Memocode08Types::*;
import Types::*;
import Interfaces::*;
import Parameters::*;
import DebugFlags::*;
import PLBMasterWires::*;
import LFSR::*;
import FIFOF::*;
import FIFO::*;
import GetPut::*;
import Vector::*;
import BRAMInitiatorWires::*;
import PLBMaster::*;
import BRAMFeeder::*;
typedef enum {
Initialize,
Request,
Transmit
} TesterState deriving(Bits,Eq);
interface ExternalMemoryTester;
interface PLBMasterWires plbMasterWires;
interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires;
endinterface
module mkExternalMemoryTester (ExternalMemoryTester);
Feeder feeder <- mkBRAMFeeder();
PLBMaster plbmaster <- mkPLBMaster;
ExternalMemory extMem <- mkExternalMemory(plbmaster);
Vector#(ReadPortNum,FIFO#(Bit#(16))) readTargets <- replicateM(mkFIFO);
Reg#(Bit#(28)) busCounter <-mkReg(0); // Need to lay off the bus for a bit
Reg#(Bool) error <- mkReg(False);
rule countUp;
busCounter <= busCounter + 1;
endrule
rule sendBackResp (busCounter == 0);
if(error)
begin
feeder.ppcMessageInput.put(1);
end
error <= False;
endrule
for(Integer i = 0; i < valueof(ReadPortNum); i = i + 1)
begin
Reg#(TesterState) state <- mkReg(Initialize);
FIFOF#(Bit#(16)) expectedVals <- mkFIFOF;
Reg#(Bit#(TLog#(RecordsPerBlock))) transmitCount <- mkReg(0);
rule init(state == Initialize);
state <= Request;
endrule
rule sendRequest;
extMem.read[i].readReq(zeroExtend(readTargets[i].first) << 4);
readTargets[i].deq();
expectedVals.enq(readTargets[i].first);
endrule
rule transmit;
transmitCount <= transmitCount + 1;
if(transmitCount + 1 == 0)
begin
expectedVals.deq;
end
Record valueTransmitted <- extMem.read[i].read;
if(valueTransmitted != zeroExtend(expectedVals.first))
begin
error <= True;
end
endrule
end
for(Integer i = 0; i < valueof(WritePortNum); i = i + 1)
begin
LFSR#(Bit#(16)) lfsr <- mkLFSR_16;
Reg#(TesterState) state <- mkReg(Initialize);
FIFOF#(Bit#(16)) expectedVals <- mkFIFOF;
Reg#(Bit#(TLog#(RecordsPerBlock))) transmitCount <- mkReg(0);
rule init(state == Initialize);
state <= Request;
lfsr.seed(fromInteger(i+1+valueof(ReadPortNum)));
endrule
rule sendRequest (busCounter[27:25] == 0);
extMem.write[i].writeReq(zeroExtend(lfsr.value)<<4); // Shift over for 16 byte alignment
lfsr.next();
expectedVals.enq(lfsr.value);
endrule
rule transmit;
transmitCount <= transmitCount + 1;
if(transmitCount + 1 == 0)
begin
expectedVals.deq;
readTargets[i].enq(expectedVals.first);
end
extMem.write[i].write(zeroExtend(expectedVals.first));
endrule
end
interface plbMasterWires = plbmaster.plbMasterWires;
interface bramInitiatorWires = feeder.bramInitiatorWires;
endmodule
|
 |