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

Subversion Repositories bluespec_md6

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/lib/bsv/SizedFIFO_fpga/mkSizedFIFO_fpga.bsv
0,0 → 1,91
package mkSizedFIFO_fpga;
 
import FIFO::*;
import RWire::*;
import RegFile::*;
import IFPGA_FIFO::*;
 
module mkSizedFIFO_fpga (IFPGA_FIFO#(f_type, size))
provisos(
Bits#(f_type, f_type_length),
Add#(TLog#(size), 0, lg_size),
Add#(TLog#(size), 1, lg_size_plus),
Add#(2, TLog#(size),lg_size_plus_plus),
Add#(1, lg_size_plus, lg_size_plus_plus)
);
RegFile#(Bit#(TLog#(size)), f_type) data <- mkRegFile(0, fromInteger(valueof(TSub#(size,1))));
Reg#(Bit#(lg_size_plus)) number_enqueued <- mkReg(0);
Reg#(Bit#(TLog#(size))) base_ptr <- mkReg(0);
RWire#(Bit#(0)) deque_pending <- mkRWire();
RWire#(Bit#(0)) clear_pending <- mkRWire();
RWire#(f_type) enque_pending <- mkRWire();
 
// We'll have problems with non-saturating additions, so we ought to add some checks
// Strongly Recommend power of 2 sizes to simpilfy logic.
 
rule update;
if(clear_pending.wget() matches tagged Valid .v)
begin
//clear is occuring, we drop a pending enqueue on the floor.
number_enqueued <= 0;
base_ptr <= 0;
end
else
begin
if(enque_pending.wget() matches tagged Valid .new_data)
begin
if(deque_pending.wget() matches tagged Valid .dp)
begin
// enque and deque occuring.. no change to net.
base_ptr <= (zeroExtend(base_ptr) == fromInteger(valueof(size)-1))? 0:base_ptr + 1;
Bit#(lg_size_plus_plus) offset = zeroExtend((zeroExtend(base_ptr) + number_enqueued));
data.upd((offset >= fromInteger(valueof(size)))?
truncate(offset - truncate(fromInteger(valueof(size)))):
truncate(offset),
new_data);
end
else
begin
number_enqueued <= number_enqueued + 1;
Bit#(lg_size_plus_plus) offset = zeroExtend((zeroExtend(base_ptr) + number_enqueued));
data.upd((offset >= fromInteger(valueof(size)))?
truncate(offset - truncate(fromInteger(valueof(size)))):
truncate(offset),
new_data);
end
end
else
begin
if(deque_pending.wget() matches tagged Valid .dp)
begin
//enque and deque occuring.. no change to net.
base_ptr <= (zeroExtend(base_ptr) == truncate(fromInteger(valueof(size)-1)))? 0:base_ptr + 1;
number_enqueued <= number_enqueued - 1;
end
end
end
endrule
 
interface FIFO fifo;
 
method Action enq (f_type value) if(number_enqueued < fromInteger(valueof(size)));
enque_pending.wset(value);
endmethod
 
method Action deq() if(number_enqueued > 0);
deque_pending.wset(0);
endmethod
 
method f_type first() if(number_enqueued > 0);
return data.sub(base_ptr);
endmethod
 
method Action clear();
clear_pending.wset(0);
endmethod
 
endinterface
 
endmodule
endpackage
/trunk/lib/bsv/SizedFIFO_fpga/IFPGA_FIFO.bsv
0,0 → 1,10
package IFPGA_FIFO;
 
import FIFO::*;
 
interface IFPGA_FIFO#(type f_type, numeric type size);
// Interface for memory, input generator
interface FIFO#(f_type) fifo;
endinterface
 
endpackage
/trunk/lib/bsv/Avalon/test/AvalonTester.bsv
0,0 → 1,73
import AvalonSlave::*;
import AvalonRegisterFile::*;
import StmtFSM::*;
 
 
 
module mkAvalonTester (Empty);
AvalonSlaveWires#(4,32) regs <- mkSmallAvalonRegisterFile;
 
Reg#(Bit#(4)) addr <- mkReg(0);
Reg#(Bit#(32)) data <- mkReg(0);
Reg#(Bit#(32)) expected <- mkReg(0);
Reg#(Bit#(32)) received <- mkReg(0);
Reg#(Bit#(1)) read <- mkReg(0);
Reg#(Bit#(1)) write <- mkReg(0);
 
Stmt s = seq
for(data <= 0; data < 2048; data<=data+1)
seq
action
$display("Testbench issues write");
await(regs.waitrequest==0);
write <= 1;
expected <= data;
endaction
write <= 0;
action
$display("Testbench issues read");
await(regs.waitrequest==0);
read <= 1;
endaction
while(regs.readdatavalid==0)
action
$display("Testbench awaits read resp");
read <= 0;
received <= regs.readdata;
endaction
action
read <= 0;
received <= regs.readdata;
endaction
if(received != expected)
seq
$display("Expected: %d, Received: %d", received, expected);
$finish;
endseq
else
seq
$display("Expected: %d @ %d, Received: %d", received, addr, expected);
endseq
addr <= addr + 7;
endseq
$display("PASS");
$finish;
endseq;
 
FSM fsm <- mkFSM(s);
 
rule drivePins;
regs.read(read);
regs.write(write);
regs.address(addr);
regs.writedata(data);
endrule
rule startFSM;
fsm.start;
endrule
 
endmodule
 
 
/trunk/lib/bsv/Avalon/test/AvalonRegisterFile.bsv
0,0 → 1,32
import RegFile::*;
import AvalonSlave::*;
import RegisterMapper::*;
import ClientServer::*;
import GetPut::*;
 
module mkSmallAvalonRegisterFile (AvalonSlaveWires#(4,32));
let m <- mkAvalonRegisterFile;
return m;
endmodule
 
module mkAvalonRegisterFile (AvalonSlaveWires#(addr_size,data_size));
Reset reset <- exposeCurrentReset;
Clock clock <- exposeCurrentClock;
AvalonSlave#(addr_size,data_size) avalonSlave <- mkAvalonSlave(clock, reset);
RegisterFile(Bit#(addr_size),Bit#(data_size)) regs <- mkRegFileFull();
 
rule handleReqs;
AvalonRequest#(address_width,data_width) req <- avalonSlave.busClient.request.get;
if(req.command == Write)
begin
regs.upd(req.addr,req.data);
end
else
begin
avalonSlave.busClient.response.put(regs.sub(req.addr));
end
endrule
 
return avalonSlave.slaveWires;
 
endmodule
/trunk/lib/bsv/Avalon/src/AvalonSlave.bsv
0,0 → 1,356
import FIFO::*;
import FIFOF::*;
import ClientServer::*;
import StmtFSM::*;
import GetPut::*;
import CBus::*;
import Clocks::*;
 
import Debug::*;
import CBusUtils::*;
// This import should be dragged to some other generic header file
import RegisterMapper::*;
 
 
Bool avalonDebug = False;
 
typedef struct {
Bit#(address_width) addr;
Bit#(data_width) data;
MapperCommand command;
} AvalonRequest#(numeric type address_width,
numeric type data_width) deriving (Bits,Eq);
 
 
interface AvalonSlaveWires#(numeric type address_width, numeric type data_width);
(* always_ready, always_enabled, prefix="", result="read" *)
method Action read(Bit#(1) read);
(* always_ready, always_enabled, prefix="", result="write" *)
method Action write(Bit#(1) write);
 
(* always_ready, always_enabled, prefix="", result="address" *)
method Action address(Bit#(address_width) address);
 
(* always_ready, always_enabled, prefix="", result="writedata" *)
method Action writedata(Bit#(data_width) writedata);
 
(* always_ready, always_enabled, prefix="", result="readdata" *)
method Bit#(data_width) readdata();
 
(* always_ready, always_enabled, prefix="", result="waitrequest" *)
method Bit#(1) waitrequest();
 
(* always_ready, always_enabled, prefix="", result="readdatavalid" *)
method Bit#(1) readdatavalid();
endinterface
interface AvalonSlave#(numeric type address_width, numeric type data_width);
interface AvalonSlaveWires#(address_width,data_width) slaveWires;
interface Client#(AvalonRequest#(address_width,data_width), Bit#(data_width)) busClient;
endinterface
 
module mkAvalonSlave#(Clock asicClock, Reset asicReset) (AvalonSlave#(address_width,data_width));
Clock clock <- exposeCurrentClock;
Reset reset <- exposeCurrentReset;
AvalonSlave#(address_width,data_width) m;
 
if(asicClock == clock && asicReset == reset)
begin
m <- mkAvalonSlaveSingleDomain;
end
else
begin
m <- mkAvalonSlaveDualDomain(asicClock,asicReset);
end
return m;
endmodule
 
module mkAvalonSlaveSingleDomain (AvalonSlave#(address_width,data_width));
RWire#(Bit#(1)) readInValue <- mkRWire;
RWire#(Bit#(1)) writeInValue <- mkRWire;
RWire#(Bit#(address_width)) addressInValue <- mkRWire;
RWire#(Bit#(data_width)) readdataOutValue <- mkRWire;
RWire#(Bit#(data_width)) writedataInValue <- mkRWire;
PulseWire putResponseCalled <- mkPulseWire;
 
// In avalon read/write asserted for a single cycle unless
// waitreq also asserted.
FIFOF#(AvalonRequest#(address_width,data_width)) reqFifo <- mkFIFOF;
 
rule produceRequest;
//Reads and writes are assumed not to occur simultaneously.
if(fromMaybe(0,readInValue.wget) == 1)
begin
debug(avalonDebug,$display("AvalonSlave Side Read Req addr: %h", fromMaybe(0,addressInValue.wget())));
reqFifo.enq(AvalonRequest{addr: fromMaybe(0,addressInValue.wget()),
data: ?,
command: Read});
end
else if(fromMaybe(0,writeInValue.wget) == 1)
begin
debug(avalonDebug,$display("AvalonSlave Side Write Req: addr: %h data: %h", fromMaybe(0,addressInValue.wget()), fromMaybe(0,writedataInValue.wget())));
reqFifo.enq(AvalonRequest{addr: fromMaybe(0,addressInValue.wget()),
data: fromMaybe(0,writedataInValue.wget()),
command: Write});
end
endrule
 
interface AvalonSlaveWires slaveWires;
 
method Action read(Bit#(1) readIn);
readInValue.wset(readIn);
endmethod
 
method Action write(Bit#(1) writeIn);
writeInValue.wset(writeIn);
endmethod
 
method Action address(Bit#(address_width) addressIn);
addressInValue.wset(addressIn);
endmethod
 
method Bit#(data_width) readdata();
return fromMaybe(0,readdataOutValue.wget);
endmethod
 
method Action writedata(Bit#(data_width) writedataValue);
writedataInValue.wset(writedataValue);
endmethod
 
method Bit#(1) waitrequest();
return (reqFifo.notFull)?0:1;
endmethod
 
method Bit#(1) readdatavalid();
return (putResponseCalled)?1:0;
endmethod
 
endinterface
 
 
interface Client busClient;
interface Get request;
method ActionValue#(AvalonRequest#(address_width,data_width)) get();
reqFifo.deq;
return reqFifo.first;
endmethod
endinterface
 
interface Put response;
method Action put(Bit#(data_width) data);
debug(avalonDebug,$display("Avalon Slave Resp"));
readdataOutValue.wset(data);
putResponseCalled.send;
endmethod
endinterface
endinterface
endmodule
 
 
interface AvalonSlaveDriverCBusWrapper#(numeric type address_width, numeric type data_width);
method Action putBusRequest(CBusCommand isWrite, Bit#(address_width) addr, Bit#(data_width) data);
method ActionValue#(Bit#(data_width)) getBusResponse();
endinterface
 
// This function converts a CBus request to a Avalon request. It also handles the null resp from the avalon
module mkAvalonSlaveDriverCBusWrapper#(Server#(AvalonRequest#(address_width,data_width),Bit#(data_width)) server) (AvalonSlaveDriverCBusWrapper#(address_width,data_width));
FIFO#(CBusCommand) commandFIFO <- mkSizedFIFO(50); // have to story many requests.
rule deqNullResp(commandFIFO.first == CBusUtils::Write);
commandFIFO.deq;
debug(avalonDebug,$display("Avalon CBus Wrapper Driver Null response drop"));
let data <- server.response.get;
endrule
 
method Action putBusRequest(CBusCommand isWrite, Bit#(address_width) addr, Bit#(data_width) data);
AvalonRequest#(address_width,data_width) req = AvalonRequest{addr: addr,
data: data,
command: (isWrite == Read)?Read:Write};
debug(avalonDebug,$display("Avalon CBus Wrapper Null putBusRequest addr: %h data: %h", addr, data));
server.request.put(req);
commandFIFO.enq(isWrite);
endmethod
 
method ActionValue#(Bit#(data_width)) getBusResponse() if(commandFIFO.first == CBusUtils::Read);
commandFIFO.deq;
debug(avalonDebug,$display("Avalon Cbus Wrapper returning a response"));
let data <- server.response.get;
return data;
endmethod
endmodule
 
 
 
// This is a simple driver for the Avalon slave. This might at somepoint serve as a starting point for an
// Avalon master
module mkAvalonSlaveDriver#(AvalonSlaveWires#(address_width,data_width) slaveWires) (Server#(AvalonRequest#(address_width,data_width),Bit#(data_width)));
FIFOF#(AvalonRequest#(address_width,data_width)) reqFIFO <- mkFIFOF;
FIFOF#(Bit#(data_width)) respFIFO <- mkFIFOF;
Reg#(Bit#(address_width)) addr <- mkReg(0);
Reg#(Bit#(data_width)) data <- mkReg(0);
Reg#(Bit#(1)) read <- mkReg(0);
Reg#(Bit#(1)) write <- mkReg(0);
 
rule drivePins;
slaveWires.read(read);
slaveWires.write(write);
slaveWires.address(addr);
slaveWires.writedata(data);
endrule
 
Stmt readStmt = seq
addr <= reqFIFO.first.addr;
await(slaveWires.waitrequest==0);
read <= 1;
while(slaveWires.readdatavalid==0)
action
debug(avalonDebug,$display("Avalon Master awaits read resp addr: %h ", addr));
read <= 0;
data <= slaveWires.readdata;
endaction
action
debug(avalonDebug,$display("Avalon Master Driver Read resp addr: %h data: %h", addr, slaveWires.readdata));
read <= 0;
data <= slaveWires.readdata;
endaction
action
debug(avalonDebug,$display("Avalaon Master Drive enq resp addr: %h data: %h", addr, data));
respFIFO.enq(data);
endaction
reqFIFO.deq;
endseq;
 
 
Stmt writeStmt = seq
debug(avalonDebug,$display("Avalon Master issues write: addr: %h data: %h",reqFIFO.first.addr,reqFIFO.first.data));
addr <= reqFIFO.first.addr;
data <= reqFIFO.first.data;
await(slaveWires.waitrequest==0);
write <= 1;
write <= 0;
respFIFO.enq(?);
reqFIFO.deq;
endseq;
 
FSM readFSM <- mkFSM(readStmt);
FSM writeFSM <- mkFSM(writeStmt);
 
rule startRead(readFSM.done && writeFSM.done && reqFIFO.first.command == Read);
debug(avalonDebug,$display("Avalon Master starts Read FSM: addr: %h ",reqFIFO.first.addr));
readFSM.start;
endrule
 
rule startWrite(readFSM.done && writeFSM.done && reqFIFO.first.command == Write);
debug(avalonDebug,$display("Avalon Master starts Write FSM: addr: %h data: %h",reqFIFO.first.addr,reqFIFO.first.data));
writeFSM.start;
endrule
 
interface Put request;
method Action put(AvalonRequest#(address_width,data_width) req);
reqFIFO.enq(req);
debug(avalonDebug,$display("Avalon Master receives request: addr: %h data: %h", req.addr, req.data));
endmethod
endinterface
 
interface Get response = fifoToGet(fifofToFifo(respFIFO));
endmodule
 
 
module mkAvalonSlaveDualDomain#(Clock asicClock, Reset asicReset) (AvalonSlave#(address_width,data_width));
RWire#(Bit#(1)) readInValue <- mkRWire;
RWire#(Bit#(1)) writeInValue <- mkRWire;
RWire#(Bit#(address_width)) addressInValue <- mkRWire;
RWire#(Bit#(data_width)) readdataOutValue <- mkRWire;
RWire#(Bit#(data_width)) writedataInValue <- mkRWire;
PulseWire putResponseCalled <- mkPulseWire;
// In avalon read/write asserted for a single cycle unless
// waitreq also asserted.
SyncFIFOIfc#(AvalonRequest#(address_width,data_width)) reqFIFO <- mkSyncFIFOFromCC(2,asicClock);
SyncFIFOIfc#(Bit#(data_width)) respFIFO <- mkSyncFIFOToCC(2,asicClock,asicReset);
FIFOF#(Bit#(0)) tokenFIFO <- mkSizedFIFOF(2);
 
rule produceRequest;
//Reads and writes are assumed not to occur simultaneously.
if(fromMaybe(0,readInValue.wget) == 1)
begin
debug(avalonDebug,$display("Avalon Slave Side Read Req: addr: %h", fromMaybe(0,addressInValue.wget())));
tokenFIFO.enq(?);
reqFIFO.enq(AvalonRequest{addr: fromMaybe(0,addressInValue.wget()),
data: ?,
command: Read});
end
else if(fromMaybe(0,writeInValue.wget) == 1)
begin // We are dropping data here.... need to ensure that reqFIFO has room
debug(avalonDebug,$display("DualAvalonSlave Side Write Req"));
reqFIFO.enq(AvalonRequest{addr: fromMaybe(0,addressInValue.wget()),
data: fromMaybe(0,writedataInValue.wget()),
command: Write});
end
endrule
 
rule produceResponse;
debug(avalonDebug,$display("Avalon Slave Resp"));
respFIFO.deq;
tokenFIFO.deq;
readdataOutValue.wset(respFIFO.first);
putResponseCalled.send;
endrule
 
interface AvalonSlaveWires slaveWires;
 
method Action read(Bit#(1) readIn);
readInValue.wset(readIn);
endmethod
 
method Action write(Bit#(1) writeIn);
writeInValue.wset(writeIn);
endmethod
 
method Action address(Bit#(address_width) addressIn);
addressInValue.wset(addressIn);
endmethod
 
method Bit#(data_width) readdata();
return fromMaybe(0,readdataOutValue.wget);
endmethod
 
method Action writedata(Bit#(data_width) writedataValue);
writedataInValue.wset(writedataValue);
endmethod
 
method Bit#(1) waitrequest();
return (tokenFIFO.notFull && reqFIFO.notFull)?0:1;
endmethod
 
method Bit#(1) readdatavalid();
return (putResponseCalled)?1:0;
endmethod
 
endinterface
 
interface Client busClient;
interface Get request;
method ActionValue#(AvalonRequest#(address_width,data_width)) get();
reqFIFO.deq;
return reqFIFO.first;
endmethod
endinterface
 
interface Put response;
method Action put(Bit#(data_width) data);
debug(avalonDebug,$display("Avalon Slave Resp"));
respFIFO.enq(data);
endmethod
endinterface
endinterface
 
endmodule
 
/trunk/lib/bsv/Avalon/fpga/AvalonRegisterFile.bsv
0,0 → 1,33
import RegFile::*;
import AvalonSlave::*;
import RegisterMapper::*;
import ClientServer::*;
import GetPut::*;
 
(*synthesize*)
module mkSmallAvalonRegisterFile (AvalonSlaveWires#(4,32));
let m <- mkAvalonRegisterFile;
return m;
endmodule
 
module mkAvalonRegisterFile (AvalonSlaveWires#(addr_size,data_size));
Reset reset <- exposeCurrentReset;
Clock clock <- exposeCurrentClock;
AvalonSlave#(addr_size,data_size) avalonSlave <- mkAvalonSlave(clock, reset);
RegFile#(Bit#(addr_size),Bit#(data_size)) regs <- mkRegFileFull();
 
rule handleReqs;
AvalonRequest#(addr_size,data_size) req <- avalonSlave.busClient.request.get;
if(req.command == Write)
begin
regs.upd(req.addr,req.data);
end
else
begin
avalonSlave.busClient.response.put(regs.sub(req.addr));
end
endrule
 
return avalonSlave.slaveWires;
 
endmodule
/trunk/lib/bsv/BRAM/blue_sim_model/BRAM.bsv
0,0 → 1,120
//----------------------------------------------------------------------//
// The MIT License
//
// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu
//
// 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.
//----------------------------------------------------------------------//
import FIFO::*;
import RegFile::*;
 
interface BRAM#(type idx_type, type data_type);
 
method Action read_req(idx_type idx);
 
method ActionValue#(data_type) read_resp();
 
method Action write(idx_type idx, data_type data);
endinterface
 
 
module mkBRAM#(Integer low, Integer high)
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type),
Bounded#(idx_type));
BRAM#(idx_type, data_type) m <- (valueof(data) == 0) ?
mkBRAM_Zero() :
mkBRAM_NonZero(low, high);
 
return m;
endmodule
 
module mkBRAM_NonZero#(Integer low, Integer high)
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type),
Bounded#(idx_type));
RegFile#(idx_type, data_type) arr <- mkRegFileFull();
FIFO#(data_type) outfifo <- mkSizedFIFO(8);
 
method Action read_req(idx_type idx);
outfifo.enq(arr.sub(idx));
endmethod
 
method ActionValue#(data_type) read_resp();
outfifo.deq();
return outfifo.first();
endmethod
 
method Action write(idx_type idx, data_type data);
arr.upd(idx, data);
endmethod
endmodule
 
module mkBRAM_Zero
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
FIFO#(data_type) q <- mkSizedFIFO(8);
 
method Action read_req(idx_type i);
q.enq(?);
endmethod
 
method Action write(idx_type i, data_type d);
noAction;
endmethod
 
method ActionValue#(data_type) read_resp();
q.deq();
return q.first();
endmethod
 
endmodule
 
module mkBRAM_Full
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type),
Bounded#(idx_type));
 
 
BRAM#(idx_type, data_type) br <- mkBRAM(0, valueof(TExp#(idx)) - 1);
 
return br;
 
endmodule
/trunk/lib/bsv/BRAM/BRAM.v
0,0 → 1,110
//----------------------------------------------------------------------//
// The MIT License
//
// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu
//
// 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.
//----------------------------------------------------------------------//
 
 
module BRAM(CLK, RST_N,
RD_ADDR, RD_RDY, RD_EN,
DOUT, DOUT_RDY, DOUT_EN,
WR_ADDR, WR_VAL, WR_EN);
 
// synopsys template
parameter addr_width = 1;
parameter data_width = 1;
parameter lo = 0;
parameter hi = 1;
input CLK;
input RST_N;
 
// Read Port
// req
input [addr_width - 1 : 0] RD_ADDR;
input RD_EN;
output RD_RDY;
// resp
output [data_width - 1 : 0] DOUT;
output DOUT_RDY;
input DOUT_EN;
 
// Write Port
// req
input [addr_width - 1 : 0] WR_ADDR;
input [data_width - 1 : 0] WR_VAL;
input WR_EN;
 
reg [data_width - 1 : 0] arr[lo:hi]; /*synthesis syn_ramstyle = "block_ram"*/
reg RD_REQ_MADE;
reg [data_width - 1 : 0] RAM_OUT;
reg [1:0] CTR;
FIFO2#(.width(data_width)) q(.RST_N(RST_N),
.CLK(CLK),
.D_IN(RAM_OUT),
.ENQ(RD_REQ_MADE),
.DEQ(DOUT_EN),
.CLR(1'b0),
.D_OUT(DOUT),
.FULL_N(),
.EMPTY_N(DOUT_RDY));
 
assign RD_RDY = (CTR > 0);
integer x;
 
always@(posedge CLK)
begin
 
if (!RST_N)
begin //Make simulation behavior consistent with Xilinx synthesis
// synopsys translate_off
for (x = lo; x < hi; x = x + 1)
begin
arr[x] <= 0;
end
// synopsys translate_on
CTR <= 2;
end
else
begin
RD_REQ_MADE <= RD_EN;
if (WR_EN)
arr[WR_ADDR] <= WR_VAL;
CTR <= (RD_EN) ?
(DOUT_EN) ? CTR : CTR - 1 :
(DOUT_EN) ? CTR + 1 : CTR;
RAM_OUT <= arr[RD_ADDR];
end
end // always@ (posedge CLK)
 
endmodule
/trunk/lib/bsv/BRAM/BRAM.bsv
0,0 → 1,238
//----------------------------------------------------------------------//
// The MIT License
//
// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu
//
// 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.
//----------------------------------------------------------------------//
import FIFO::*;
 
//One RAM.
interface BRAM#(type idx_type, type data_type);
 
method Action read_req(idx_type idx);
 
method ActionValue#(data_type) read_resp();
 
method Action write(idx_type idx, data_type data);
endinterface
 
 
//Two RAMs.
interface BRAM_2#(type idx_type, type data_type);
 
method Action read_req1(idx_type idx);
method Action read_req2(idx_type idx);
 
method ActionValue#(data_type) read_resp1();
method ActionValue#(data_type) read_resp2();
 
method Action write(idx_type idx, data_type data);
endinterface
 
//Three RAMs.
interface BRAM_3#(type idx_type, type data_type);
 
method Action read_req1(idx_type idx);
method Action read_req2(idx_type idx);
method Action read_req3(idx_type idx);
 
method ActionValue#(data_type) read_resp1();
method ActionValue#(data_type) read_resp2();
method ActionValue#(data_type) read_resp3();
 
method Action write(idx_type idx, data_type data);
endinterface
 
 
module mkBRAM#(Integer low, Integer high)
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
BRAM#(idx_type, data_type) m <- (valueof(data) == 0) ?
mkBRAM_Zero() :
mkBRAM_NonZero(low, high);
 
return m;
endmodule
 
import "BVI" BRAM = module mkBRAM_NonZero#(Integer low, Integer high)
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
 
default_clock clk(CLK);
 
parameter addr_width = valueof(idx);
parameter data_width = valueof(data);
parameter lo = low;
parameter hi = high;
 
method DOUT read_resp() ready(DOUT_RDY) enable(DOUT_EN);
method read_req(RD_ADDR) ready(RD_RDY) enable(RD_EN);
method write(WR_ADDR, WR_VAL) enable(WR_EN);
 
schedule read_req CF (read_resp, write);
schedule read_resp CF (read_req, write);
schedule write CF (read_req, read_resp);
schedule read_req C read_req;
schedule read_resp C read_resp;
schedule write C write;
 
endmodule
 
module mkBRAM_Zero
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
FIFO#(data_type) q <- mkLFIFO();
 
method Action read_req(idx_type i);
q.enq(?);
endmethod
 
method Action write(idx_type i, data_type d);
noAction;
endmethod
 
method ActionValue#(data_type) read_resp();
q.deq();
return q.first();
endmethod
 
endmodule
 
module mkBRAM_Full
//interface:
(BRAM#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
 
 
BRAM#(idx_type, data_type) br <- mkBRAM(0, valueof(TExp#(idx)) - 1);
 
return br;
 
endmodule
module mkBRAM_2#(Integer low, Integer high)
//interface:
(BRAM_2#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
BRAM#(idx_type, data_type) br1 <- mkBRAM(low, high);
BRAM#(idx_type, data_type) br2 <- mkBRAM(low, high);
method read_req1(idx) = br1.read_req(idx);
method read_req2(idx) = br2.read_req(idx);
 
method read_resp1() = br1.read_resp();
method read_resp2() = br2.read_resp();
 
method Action write(idx_type idx, data_type data);
br1.write(idx, data);
br2.write(idx, data);
endmethod
endmodule
 
module mkBRAM_2_Full
//interface:
(BRAM_2#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
 
 
BRAM_2#(idx_type, data_type) br <- mkBRAM_2(0, valueof(TExp#(idx)) - 1);
 
return br;
 
endmodule
 
module mkBRAM_3#(Integer low, Integer high)
//interface:
(BRAM_3#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
BRAM#(idx_type, data_type) br1 <- mkBRAM(low, high);
BRAM#(idx_type, data_type) br2 <- mkBRAM(low, high);
BRAM#(idx_type, data_type) br3 <- mkBRAM(low, high);
method read_req1(idx) = br1.read_req(idx);
method read_req2(idx) = br2.read_req(idx);
method read_req3(idx) = br3.read_req(idx);
 
method read_resp1() = br1.read_resp();
method read_resp2() = br2.read_resp();
method read_resp3() = br3.read_resp();
 
method Action write(idx_type idx, data_type data);
br1.write(idx, data);
br2.write(idx, data);
br3.write(idx, data);
endmethod
endmodule
 
 
module mkBRAM_3_Full
//interface:
(BRAM_3#(idx_type, data_type))
provisos
(Bits#(idx_type, idx),
Bits#(data_type, data),
Literal#(idx_type));
 
 
BRAM_3#(idx_type, data_type) br <- mkBRAM_3(0, valueof(TExp#(idx)) - 1);
 
return br;
 
endmodule
/trunk/lib/bsv/StreamCaptureFIFO/src/StreamCaptureFIFO.bsv
0,0 → 1,43
import FIFOF::*;
 
import BRAMFIFO::*;
 
typedef enum {
Filling,
Draining
} State deriving (Bits,Eq);
 
module mkStreamCaptureFIFOF#(Integer streamSize) (FIFOF#(data_t))
provisos(Bits#(data_t, data_sz));
 
FIFOF#(data_t) fifo <- mkBRAMFIFOF(streamSize);
Reg#(State) state <- mkReg(Filling);
rule setState (!fifo.notFull && state != Draining);
state <= Draining;
endrule
 
rule setFilling (!fifo.notEmpty && state != Filling);
state <= Filling;
endrule
 
method data_t first() if(state == Draining);
return fifo.first;
endmethod
 
method Action deq() if(state == Draining);
fifo.deq;
endmethod
 
method Action enq(data_t data) if(state == Filling);
fifo.enq(data);
endmethod
 
method notEmpty = fifo.notEmpty;
method notFull = fifo.notFull;
method Action clear;
fifo.clear;
state <= Filling;
endmethod
endmodule
/trunk/lib/bsv/Register/src/ControlReg.bsv
0,0 → 1,237
import Vector::*;
import ActionSeq::*;
import FIFOF::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import Register::*;
 
interface ControlReg#(type addr_t, type data_t);
method addr_t getAddr();
method Action write(data_t x1);
method ActionValue#(data_t) read();
endinterface
 
// function makeControlRegFromRAM(TBDRegisterMap regNum, HSTDEC_OCP_RAM_module_addr_t inc,
// FIFO#(HSTDEC_OCP_RAM_module_addr_t));
// begin
// ControlReg#(HSTDEC_OCP_RAM_addr_t, HSTDEC_OCP_RAM_data_t) cr =
// interface ControlReg
// method HSTDEC_OCP_RAM_addr_t getAddr();
// return zeroExtend(pack(regNum));
// endmethod
// method Action write(HSTDEC_OCP_RAM_data_t data);
// begin
// tbdRegs.hstRamAddr <= tbdRegs.hstRamAddr + inc;
// (determineMemory(curTBD,tbdRegs)).writeReq.put(tuple2(truncate(tbdRegs.hstRamAddr),data));
// end
// endmethod
// method ActionValue#(HSTDEC_OCP_RAM_data_t) read();
// begin
// let mem = (determineMemory(curTBD,tbdRegs));
// debugModule(hstdecDebug, $display("HSTDEC Pushing read request"));
// mem.readReq.put(truncate(tbdRegs.hstRamAddr));
// state <= Read;
// read_inc_fifo.enq(inc);
// return ?;
// end
// endmethod
// endinterface;
// return cr;
// end
 
// rule complete_read;
// let inc = read_inc_fifo.first; read_inc_fifo.deq;
// let mem = (determineMemory(curTBD,tbdRegs));
// tbdRegs.hstRamAddr <= tbdRegs.hstRamAddr + signExtend(inc);
// let data <- mem.readResp().get();
// resp_fifo.enq(data);
// endrule
// endfunction
 
 
 
// function ControlReg#(addrT, dataT) mkControlReg(addrT addr,
// function regDataT get(),
// function Action put(regDataT))
// provisos (Bits#(regDataT, regDataSz),
// Bits#(dataT, dataSz),
// Add#(regDataSz,aaa,dataSz));
// ControlReg#(addrT, dataT) cr =
// interface ControlReg;
// method addrT getAddr();
// return addr;
// endmethod
// method Action write(dataT data);
// let foo <- put(unpack(truncate(pack(data))));
// endmethod
// method ActionValue#(dataT) read();
// let data <- get();
// return unpack(zeroExtend(pack(data)));
// endmethod
// endinterface;
// return cr;
// endfunction
 
 
 
function ControlReg#(addrT, dataT) mkControlRegFromReg(addrT addr,
Reg#(dataT) r)
provisos (//Bits#(regDataT, regDataSz),
Bits#(dataT, dataSz)
//Add#(regDataSz,aaa,dataSz)
);
ControlReg#(addrT, dataT) cr =
interface ControlReg;
method addrT getAddr();
return addr;
endmethod
method Action write(dataT data);
r._write(data);
endmethod
method ActionValue#(dataT) read();
let data = r._read();
return data;
endmethod
endinterface;
return cr;
endfunction
 
function ControlReg#(addrT, dataT) mkControlRegFromGet(addrT addr,
Get#(dataT) get)
provisos (Bits#(dataT, dataSz));
ControlReg#(addrT, dataT) cr =
interface ControlReg;
method addrT getAddr();
return addr;
endmethod
method Action write(dataT data);
// no write method
endmethod
method ActionValue#(dataT) read();
let data <- get.get();
return data;
endmethod
endinterface;
return cr;
endfunction
 
function ControlReg#(addrT, dataT) mkControlRegFromGetPut(addrT addr,
Get#(dataT) get,
Put#(dataT) put)
provisos (Bits#(dataT, dataSz));
ControlReg#(addrT, dataT) cr =
interface ControlReg;
method addrT getAddr();
return addr;
endmethod
method Action write(dataT data);
put.put(data);
endmethod
method ActionValue#(dataT) read();
let data <- get.get();
return data;
endmethod
endinterface;
return cr;
endfunction
 
function ControlReg#(addrT, dataT) mkControlRegFromServer(addrT addr,
Server#(dataT, dataT) server)
provisos (Bits#(dataT, dataSz));
ControlReg#(addrT, dataT) cr =
interface ControlReg;
method addrT getAddr();
return addr;
endmethod
method Action write(dataT data);
server.request.put(data);
endmethod
method ActionValue#(dataT) read();
let data <- server.response.get();
return data;
endmethod
endinterface;
return cr;
endfunction
 
function Vector#(n, ControlReg#(addrT, dataT))
addControlReg(Vector#(n, ControlReg#(addrT, dataT)) crvec,
regNumT regNum,
ControlReg#(addrT, dataT) cr)
provisos (Bits#(regNumT, regNumSz),
Bits#(addrT, addrSz),
Bits#(dataT, ramDataSz),
Add#(regNumSz,aaa,addrSz));
crvec[zeroExtend(pack(regNum))] = cr;
return crvec;
endfunction
 
function Vector#(n, ControlReg#(addrT, dataT))
addControlRegFromReg(Vector#(n, ControlReg#(addrT, dataT)) crvec,
regNumT regNum,
Reg#(dataT) r)
provisos (Bits#(regNumT, regNumSz),
Bits#(addrT, addrSz),
Bits#(dataT, ramDataSz),
Add#(regNumSz,aaa,addrSz)
);
ControlReg#(addrT, dataT) cr =
mkControlRegFromReg(unpack(zeroExtend(pack(regNum))), r);
crvec[zeroExtend(pack(regNum))] = cr;
return crvec;
endfunction
 
function Vector#(n, ControlReg#(addrT, dataT))
addControlRegFromGet(Vector#(n, ControlReg#(addrT, dataT)) crvec,
regNumT regNum,
Get#(dataT) g)
provisos (Bits#(dataT, ramDataSz),
Bits#(regNumT, regNumSz),
Bits#(addrT, addrSz),
Add#(regNumSz,aaa,addrSz));
ControlReg#(addrT, dataT) cr =
mkControlRegFromGet(unpack(zeroExtend(pack(regNum))), g);
crvec[zeroExtend(pack(regNum))] = cr;
return crvec;
endfunction
 
function Vector#(n, ControlReg#(addrT, dataT))
addControlRegFromGetPut(Vector#(n, ControlReg#(addrT, dataT)) crvec,
regNumT regNum,
Get#(dataT) g,
Put#(dataT) p)
provisos (Bits#(dataT, ramDataSz),
Bits#(regNumT, regNumSz),
Bits#(addrT, addrSz),
Add#(regNumSz,aaa,addrSz));
ControlReg#(addrT, dataT) cr =
mkControlRegFromGetPut(unpack(zeroExtend(pack(regNum))), g, p);
crvec[pack(regNum)] = cr;
return crvec;
endfunction
 
function ControlReg#(addrT, dataT) widenControlReg(ControlReg#(nAddrT, nDataT) ncr)
provisos (Bits#(addrT, addrSz),
Bits#(dataT, dataSz),
Bits#(nAddrT, nAddrSz),
Bits#(nDataT, nDataSz),
Add#(nDataSz,ddd,dataSz),
Add#(nAddrSz,aaa,addrSz));
ControlReg#(addrT, dataT) cr =
interface ControlReg;
method addrT getAddr();
return unpack(zeroExtend(pack(ncr.getAddr())));
endmethod
method Action write(dataT data);
ncr.write(unpack(truncate(pack(data))));
endmethod
method ActionValue#(dataT) read();
let data <- ncr.read();
return unpack(zeroExtend(pack(data)));
endmethod
endinterface;
return cr;
endfunction
 
 
trunk/lib/bsv/Register/src/ControlReg.bsv Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/lib/bsv/Register/src/Register.bsv =================================================================== --- trunk/lib/bsv/Register/src/Register.bsv (nonexistent) +++ trunk/lib/bsv/Register/src/Register.bsv (revision 2) @@ -0,0 +1,476 @@ +import Vector::*; +import ActionSeq::*; +import FIFOF::*; +import FIFO::*; +import GetPut::*; +import ClientServer::*; + + + +function Tuple2#(Reg#(Bit#(aDataSz)),Reg#(Bit#(bDataSz))) splitReg(Reg#(Bit#(wDataSz)) wr) + provisos(Add#(aDataSz,bDataSz,wDataSz)); + Reg#(Bit#(aDataSz)) areg = interface Reg + method Action _write(Bit#(aDataSz) newa); + Tuple2#(Bit#(aDataSz),Bit#(bDataSz)) oldtpl = split(wr); + match { .olda, .oldb } = oldtpl; + wr <= { newa, oldb }; + endmethod + method Bit#(aDataSz) _read(); + Tuple2#(Bit#(aDataSz),Bit#(bDataSz)) oldtpl = split(wr); + match { .olda, .oldb } = oldtpl; + return olda; + endmethod + endinterface; + Reg#(Bit#(bDataSz)) breg = interface Reg + method Action _write(Bit#(bDataSz) newb); + Tuple2#(Bit#(aDataSz),Bit#(bDataSz)) oldtpl = split(wr); + match { .olda, .oldb } = oldtpl; + wr <= { olda, newb }; + endmethod + method Bit#(bDataSz) _read(); + Tuple2#(Bit#(aDataSz),Bit#(bDataSz)) oldtpl = split(wr); + match { .olda, .oldb } = oldtpl; + return oldb; + endmethod + endinterface; + return tuple2(areg,breg); +endfunction + +function Reg#(Bit#(dataSz)) invertReg(Reg#(Bit#(dataSz)) oldr); + Reg#(Bit#(dataSz)) r = interface Reg; + method Action _write(Bit#(dataSz) v); + oldr <= ~v; + endmethod + method Bit#(dataSz) _read(); + return ~oldr; + endmethod + endinterface; + return r; +endfunction + +function Reg#(dataT) mirrorReg(Reg#(dataT) areg, Reg#(dataT) breg); + Reg#(dataT) r = interface Reg; + method Action _write(dataT v); + areg <= v; + breg <= v; + endmethod + method dataT _read(); + dataT aval = areg; + dataT bval = breg; + return aval; + endmethod + endinterface; + return r; +endfunction + +function Reg#(dataT) mkZeroReg() + provisos (Literal#(dataT)); + Reg#(dataT) r = interface Reg; + method Action _write(dataT v); + endmethod + method dataT _read(); + return 0; + endmethod + endinterface; + return r; +endfunction + +function Reg#(Bit#(1)) pulsewireSendReadReg(PulseWire pulsewire, Reg#(Bit#(1)) rd); + Reg#(Bit#(1)) r = interface Reg; + method Action _write(Bit#(1) v); + if (v == 1) pulsewire.send(); + endmethod + method Bit#(1) _read(); + return rd; + endmethod + endinterface; + return r; +endfunction + +function Reg#(Bit#(1)) rwireSetReadReg(RWire#(Bit#(1)) rwire, Reg#(Bit#(1)) rd); + Reg#(Bit#(1)) r = interface Reg; + method Action _write(Bit#(1) v); + if (v == 1) rwire.wset(1); + endmethod + method Bit#(1) _read(); + return rd; + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Bit#(1)) rwireClearReadReg(RWire#(Bit#(1)) rwire, Reg#(Bit#(1)) rd); + Reg#(Bit#(1)) r = interface Reg; + method Action _write(Bit#(1) v); + if (v == 0) rwire.wset(0); + endmethod + method Bit#(1) _read(); + return ~rd; + endmethod + endinterface; + return r; +endfunction + +function Reg#(Bit#(1)) mkSetReadReg(Reg#(Bit#(1)) oldr); + Reg#(Bit#(1)) r = interface Reg; + method Action _write(Bit#(1) v); + if (v == 1) oldr <= v; + endmethod + method Bit#(1) _read(); + return oldr; + endmethod + endinterface; + return r; +endfunction +function Reg#(Bit#(1)) mkClearReadReg(Reg#(Bit#(1)) oldr); + Reg#(Bit#(1)) r = interface Reg; + method Action _write(Bit#(1) v); + if (v == 0) oldr <= v; + endmethod + method Bit#(1) _read(); + return ~oldr; + endmethod + endinterface; + return r; +endfunction + +function Reg#(dataT) constantReg(dataT v); + Reg#(dataT) r = interface Reg; + method Action _write(dataT v); + endmethod + method dataT _read(); + return v; + endmethod + endinterface; + return r; +endfunction + +function Reg#(dataT) readOnlyRegFromReg(Reg#(dataT) areg); + Reg#(dataT) r = interface Reg; + method Action _write(dataT v); + endmethod + method dataT _read(); + return areg; + endmethod + endinterface; + return r; +endfunction + +function Reg#(regType) mkRegFromActions(function regType readAction(), function Action writeAction(regType value)); + Reg#(regType) regIfc = interface Reg; + method regType _read(); + return readAction; + endmethod + + method Action _write(regType value); + writeAction(value); + endmethod + endinterface; + return regIfc; +endfunction + +function Reg#(Bit#(dataSz)) toBitsReg(Reg#(dataT) areg) + provisos(Bits#(dataT, dataSz)); + Reg#(Bit#(dataSz)) r = interface Reg; + method Action _write(Bit#(dataSz) v); + areg <= unpack(v); + endmethod + method Bit#(dataSz) _read(); + return pack(areg); + endmethod + endinterface; + return r; +endfunction + +function Reg#(dataT) fromBitsReg(Reg#(Bit#(dataSz)) areg) + provisos(Bits#(dataT, dataSz)); + Reg#(dataT) r = interface Reg; + method Action _write(dataT v); + areg <= pack(v); + endmethod + method dataT _read(); + return unpack(areg); + endmethod + endinterface; + return r; +endfunction + +function Reg#(Tuple2#(aDataT,bDataT)) zipReg(Reg#(aDataT) areg, Reg#(bDataT) breg); + Reg#(Tuple2#(aDataT,bDataT)) r = interface Reg; + method Action _write(Tuple2#(aDataT,bDataT) v); + match { .av, .bv } = v; + areg <= av; + breg <= bv; + endmethod + method Tuple2#(aDataT,bDataT) _read(); + return tuple2(areg, breg); + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Tuple3#(aDataT,bDataT,cDataT)) zipReg3(Reg#(aDataT) areg, + Reg#(bDataT) breg, + Reg#(cDataT) creg); + Reg#(Tuple3#(aDataT,bDataT,cDataT)) r = interface Reg; + method Action _write(Tuple3#(aDataT,bDataT,cDataT) v); + match { .av, .bv, .cv } = v; + areg <= av; + breg <= bv; + creg <= cv; + endmethod + method Tuple3#(aDataT,bDataT,cDataT) _read(); + return tuple3(areg, breg, creg); + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Tuple4#(aDataT,bDataT,cDataT,dDataT)) zipReg4(Reg#(aDataT) areg, + Reg#(bDataT) breg, + Reg#(cDataT) creg, + Reg#(dDataT) dreg); + Reg#(Tuple4#(aDataT,bDataT,cDataT,dDataT)) r = interface Reg; + method Action _write(Tuple4#(aDataT,bDataT,cDataT,dDataT) v); + match { .av, .bv, .cv, .dv } = v; + areg <= av; + breg <= bv; + creg <= cv; + dreg <= dv; + endmethod + method Tuple4#(aDataT,bDataT,cDataT,dDataT) _read(); + return tuple4(areg, breg, creg, dreg); + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Tuple5#(aDataT,bDataT,cDataT,dDataT,eDataT)) zipReg5(Reg#(aDataT) areg, + Reg#(bDataT) breg, + Reg#(cDataT) creg, + Reg#(dDataT) dreg, + Reg#(eDataT) ereg); + Reg#(Tuple5#(aDataT,bDataT,cDataT,dDataT,eDataT)) r = interface Reg; + method Action _write(Tuple5#(aDataT,bDataT,cDataT,dDataT,eDataT) v); + match { .av, .bv, .cv, .dv, .ev } = v; + areg <= av; + breg <= bv; + creg <= cv; + dreg <= dv; + ereg <= ev; + endmethod + method Tuple5#(aDataT,bDataT,cDataT,dDataT,eDataT) _read(); + return tuple5(areg, breg, creg, dreg, ereg); + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Tuple6#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT)) zipReg6(Reg#(aDataT) areg, + Reg#(bDataT) breg, + Reg#(cDataT) creg, + Reg#(dDataT) dreg, + Reg#(eDataT) ereg, + Reg#(fDataT) freg); + Reg#(Tuple6#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT)) r = interface Reg; + method Action _write(Tuple6#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT) v); + match { .av, .bv, .cv, .dv, .ev, .fv } = v; + areg <= av; + breg <= bv; + creg <= cv; + dreg <= dv; + ereg <= ev; + freg <= fv; + endmethod + method Tuple6#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT) _read(); + return tuple6(areg, breg, creg, dreg, ereg, freg); + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Tuple7#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT)) zipReg7(Reg#(aDataT) areg, + Reg#(bDataT) breg, + Reg#(cDataT) creg, + Reg#(dDataT) dreg, + Reg#(eDataT) ereg, + Reg#(fDataT) freg, + Reg#(gDataT) greg); + Reg#(Tuple7#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT)) r = interface Reg; + method Action _write(Tuple7#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT) v); + match { .av, .bv, .cv, .dv, .ev, .fv, .gv } = v; + areg <= av; + breg <= bv; + creg <= cv; + dreg <= dv; + ereg <= ev; + freg <= fv; + greg <= gv; + endmethod + method Tuple7#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT) _read(); + return tuple7(areg, breg, creg, dreg, ereg, freg, greg); + endmethod + endinterface; + return r; +endfunction +typedef struct { + aDataT av; bDataT bv; cDataT cv; dDataT dv; eDataT ev; fDataT fv; gDataT gv; hDataT hv; +} Zip8#(type aDataT, type bDataT, type cDataT, type dDataT, type eDataT, type fDataT, type gDataT, type hDataT) deriving (Bits,Eq); + + +function Reg#(Zip8#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT,hDataT)) zipReg8(Reg#(aDataT) areg, + Reg#(bDataT) breg, + Reg#(cDataT) creg, + Reg#(dDataT) dreg, + Reg#(eDataT) ereg, + Reg#(fDataT) freg, + Reg#(gDataT) greg, + Reg#(hDataT) hreg); + Reg#(Zip8#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT,hDataT)) r = interface Reg; + method Action _write(Zip8#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT,hDataT) v); + match tagged Zip8 { av: .av, bv: .bv, cv: .cv, dv: .dv, ev: .ev, fv: .fv, gv: .gv, hv: .hv } = v; + areg <= av; + breg <= bv; + creg <= cv; + dreg <= dv; + ereg <= ev; + freg <= fv; + greg <= gv; + hreg <= hv; + endmethod + method Zip8#(aDataT,bDataT,cDataT,dDataT,eDataT,fDataT,gDataT,hDataT) _read(); + return Zip8 { av: areg, bv: breg, cv: creg, dv: dreg, ev: ereg, fv: freg, gv: greg, hv: hreg}; + endmethod + endinterface; + return r; +endfunction + + + +function Reg#(Bool) eqReg(Reg#(dataT) areg, Reg#(dataT) breg, function Bool eq(dataT a, dataT b)) + provisos (Eq#(dataT)); + Reg#(Bool) r = interface Reg; + method Action _write(Bool v); + endmethod + method Bool _read(); + dataT aval = areg; + dataT bval = breg; + return eq(aval,bval); + endmethod + endinterface; + return r; +endfunction +function Reg#(dataT) andReg(Reg#(dataT) areg, Reg#(dataT) breg) + provisos (Bitwise#(dataT)); + Reg#(dataT) r = interface Reg; + method Action _write(dataT v); + endmethod + method dataT _read(); + dataT aval = areg; + dataT bval = breg; + return aval; + endmethod + endinterface; + return r; +endfunction + + + +function Reg#(Bit#(1)) reduceReg(Reg#(Bit#(dataSz)) areg, + function Bit#(1) foldbit(Bit#(dataSz) a)) + provisos(Add#(1,aaa,dataSz)); + Reg#(Bit#(1)) r = interface Reg; + method Action _write(dataT v); + endmethod + method Bit#(1) _read(); + Bit#(dataSz) bits = areg; + Bit#(1) r = foldbit(bits); + return r; + endmethod + endinterface; + return r; +endfunction + + +function Reg#(Bit#(dataSz)) widenRegLSB(Reg#(Bit#(nDataSz)) ncr) + provisos (Add#(nDataSz,ddd,dataSz)); + Reg#(Bit#(dataSz)) wr = + interface Reg; + method Action _write(Bit#(dataSz) data); + ncr._write(truncateLSB(data)); + endmethod + method Bit#(dataSz) _read(); + let data = ncr._read(); + return zeroExtend(data)<<(fromInteger(valueof(ddd))); + endmethod + endinterface; + return wr; +endfunction + + +function Reg#(Bit#(dataSz)) widenReg(Reg#(Bit#(nDataSz)) ncr) + provisos (Add#(nDataSz,ddd,dataSz)); + Reg#(Bit#(dataSz)) wr = + interface Reg; + method Action _write(Bit#(dataSz) data); + ncr._write(truncate(data)); + endmethod + method Bit#(dataSz) _read(); + let data = ncr._read(); + return zeroExtend(data); + endmethod + endinterface; + return wr; +endfunction + + +function Vector#(wholeRegs,Reg#(dest)) explodeRegister(Reg#(target) regTarget) + provisos(Bits#(target,targetBits), + Bits#(dest, destBits), + Div#(targetBits,destBits,wholeRegs), + Add#(targetBits, extraBits, TMul#(wholeRegs, destBits)), + Add#(otherExtraBits, destBits, TMul#(wholeRegs, destBits))); + Reg#(Bit#(TMul#(wholeRegs,destBits))) bitTarget = widenReg(toBitsReg(regTarget)); + Vector#(wholeRegs,Reg#(Bit#(destBits))) resultVec = newVector; + + for(Integer i = 0, Integer index = 0; i < valueof(TMul#(wholeRegs,destBits)) ; index = index + 1, i = i + valueof(destBits)) + begin + // perhaps cut up the reg + function Bit#(destBits) readAction(); + return bitTarget[i+valueof(destBits)-1:i]; + endfunction + + function Action writeAction(Bit#(destBits) res); + action + bitTarget[i+valueof(destBits)-1:i] <= res; // this truncate makes the type checker happy? Introduces a warning + endaction + endfunction + + resultVec[index] = mkRegFromActions(readAction,writeAction); + end + return Vector::map(fromBitsReg,resultVec); +endfunction + + +function ReadOnly#(data_t) readOnly(data_t data); + ReadOnly#(data_t) ifc = interface ReadOnly#(data_t); + method _read = data; + endinterface; + return ifc; +endfunction + +function Reg#(data_t) readOnlyToRegister(ReadOnly#(data_t) data); + Reg#(data_t) ifc = interface Reg#(data_t); + method _read = data; + method Action _write(data_t data); + $display("Read Only method has no write"); + endmethod + endinterface; + return ifc; +endfunction \ No newline at end of file
trunk/lib/bsv/Register/src/Register.bsv Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/lib/bsv/BRAMFIFO/BRAMFIFOF.v =================================================================== --- trunk/lib/bsv/BRAMFIFO/BRAMFIFOF.v (nonexistent) +++ trunk/lib/bsv/BRAMFIFO/BRAMFIFOF.v (revision 2) @@ -0,0 +1,191 @@ +//----------------------------------------------------------------------// +// The MIT License +// +// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu +// +// 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. +//----------------------------------------------------------------------// + + +/*** + * + * This module implements a parametric verilog sized fifo. This particular + * sized fifo will synthesize on to Xilinx block rams. The fifo is parametric + * in terms of both data width and the number of data stored in the fifo. + * the interface is gaurded. The fifo is not loopy. + * The methods supported by the FIFO are clear, dequeue, enqueue, notFull, + * and notEmpty + * + ***/ + + +module BRAMFIFOF(CLK, RST_N, + D_IN, CLR, DEQ, + ENQ, D_OUT, FULL_N, EMPTY_N); + + // synopsys template + parameter log_data_count = 0; + parameter data_count = 1; + parameter data_width = 1; + + input CLK; + input RST_N; + + input [data_width - 1 : 0] D_IN; + input CLR; + input DEQ; + input ENQ; + + output [data_width - 1 : 0] D_OUT; + output FULL_N; + output EMPTY_N; + + + + reg [data_width - 1 : 0] arr[0:data_count]; /*synthesis syn_ramstyle = "block_ram"*/ + + reg skid_flag; + reg [log_data_count + 2 : 0] fifo_data_count; + reg [log_data_count + 2 : 0] read_ptr; + reg [log_data_count + 2 : 0] read_ptr_current; + reg [log_data_count + 2 : 0] write_ptr; + reg [data_width - 1 : 0] skid_buffer; // this is a fast output buffer + reg [data_width - 1 : 0] RAM_OUT; + + + assign D_OUT = (skid_flag)?skid_buffer:RAM_OUT; + + assign FULL_N = !(fifo_data_count == data_count); + assign EMPTY_N = !(fifo_data_count == 0); + + integer x; + + always@(*) + begin + if(DEQ) + begin + read_ptr_current = (read_ptr == data_count)?0:(read_ptr + 1); + end + else + begin + read_ptr_current = read_ptr; + end + end + + + + always@(posedge CLK) + begin + if (!RST_N) + begin //Make simulation behavior consistent with Xilinx synthesis + // synopsys translate_off + for (x = 0; x < data_count + 1; x = x + 1) + begin + arr[x] <= 0; + end + // synopsys translate_on + fifo_data_count <= 0; + skid_buffer <= 0; + skid_flag <= 0; + read_ptr <= 0; + write_ptr <= 0; + //$display("Params: data_count: %d, log_data_count: %d, data_width: %d", data_count, log_data_count, data_width); + end + else + begin + // assign output buffer + skid_buffer <= D_IN; + + if(CLR) + begin + skid_flag <= 0; + end + else if(ENQ && ((fifo_data_count == 0) || ((fifo_data_count == 1) && DEQ))) + begin + //$display("Enque to output buffer"); + skid_flag <= 1; + end + else + begin + skid_flag <= 0; + end + + // write_ptr + if(CLR) + begin + write_ptr <= 0; + end + else if(ENQ) + begin + //$display("Enque to BRAM[%d]: %d", write_ptr,D_IN); + write_ptr <= (write_ptr == data_count)?0:(write_ptr + 1); + end + else + begin + write_ptr <= write_ptr; + end + + //read_ptr + if(CLR) + begin + read_ptr <= 0; + end + else if(DEQ) + begin + //$display("Advancing read ptr"); + read_ptr <= (read_ptr == data_count)?0:(read_ptr + 1); + end + else + begin + read_ptr <= read_ptr; + end + + // assign fifo data_count + if(CLR) + begin + fifo_data_count <= 0; + end + else if(ENQ && DEQ) + begin + fifo_data_count <= fifo_data_count; + end + else if(ENQ) + begin + fifo_data_count <= fifo_data_count + 1; + end + else if(DEQ) + begin + fifo_data_count <= fifo_data_count - 1; + end + else + begin + fifo_data_count <= fifo_data_count; + end + if(ENQ) + begin + arr[write_ptr] <= D_IN; + end + RAM_OUT <= arr[read_ptr_current]; + + end + end // always@ (posedge CLK) + +endmodule \ No newline at end of file Index: trunk/lib/bsv/BRAMFIFO/build/top.v =================================================================== --- trunk/lib/bsv/BRAMFIFO/build/top.v (nonexistent) +++ trunk/lib/bsv/BRAMFIFO/build/top.v (revision 2) @@ -0,0 +1,23 @@ +module top; + reg clk; + reg rst_n; + + mkTestBench m(.CLK(clk),.RST_N(rst_n)); + +always@(clk) + #5 clk <= ~clk; + +initial + begin + $dumpfile("dump.vcd"); + $dumpvars(4,m); + rst_n <= 0; + clk <= 0; + #50; + rst_n <= 1; + + end + + + +endmodule \ No newline at end of file Index: trunk/lib/bsv/BRAMFIFO/mkTestBench.bsv =================================================================== --- trunk/lib/bsv/BRAMFIFO/mkTestBench.bsv (nonexistent) +++ trunk/lib/bsv/BRAMFIFO/mkTestBench.bsv (revision 2) @@ -0,0 +1,98 @@ +//----------------------------------------------------------------------// +// The MIT License +// +// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu +// +// 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. +//----------------------------------------------------------------------// + +import BRAMFIFO::*; +import FIFOF::*; +import FIFO::*; + +/*** + * + * This module is a test harness for the BRAMFIFO verilog module. + * The module compares the behavior of a BRAM based sized FIFO and a + * standard sized fifo. If their behavior differs at any point during the + * long pseudo-random test bench, then a failure message is displayed. + * + ***/ + + +(* synthesize *) +module mkTest (FIFOF#(Bit#(32))); + FIFOF#(Bit#(32)) gold <- mkBRAMFIFOF(250); + FIFO#(Bit#(32)) p <- mkSizedFIFO(6); + return gold; +endmodule + + +module mkTestBench (); + Reg#(Bit#(32)) test_counter <- mkReg(0); + + rule test_counter_rl; + test_counter <= test_counter + 1; + if(test_counter > 1000000) + begin + $display("PASS"); + $finish; + end + endrule + + for(Integer i = 2; i < 4; i = i + 1) + begin + FIFO#(Bit#(32)) gold <- mkSizedFIFO(i); + FIFO#(Bit#(32)) test <- mkBRAMFIFO(i); + Reg#(Bit#(32)) counter <- mkReg(0); + + rule count; + counter <= counter + 1; + endrule + + rule enq_a(counter % fromInteger(i) == 0); + gold.enq(counter); + endrule + + rule enq_b(counter % fromInteger(i) == 0); + test.enq(counter); + endrule + + for(Integer j = 2; j < 4; j = j+1) + begin + rule deq_check(zeroExtend(counter)%fromInteger(j) == 0); + if(gold.first() != test.first()) + begin + $display("FAIL Not equal! g: %d t: %d i: %d j: %d", gold.first, test.first, i, j); + end + else + begin + $display("Match: %d i:%d j:%d", gold.first, i,j); + end + + gold.deq; + test.deq; + + endrule + end + end + +endmodule \ No newline at end of file Index: trunk/lib/bsv/BRAMFIFO/top.v =================================================================== --- trunk/lib/bsv/BRAMFIFO/top.v (nonexistent) +++ trunk/lib/bsv/BRAMFIFO/top.v (revision 2) @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------// +// The MIT License +// +// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu +// +// 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. +//----------------------------------------------------------------------// + +module top; + reg clk; + reg rst_n; + + mkTestBench m(.CLK(clk),.RST_N(rst_n)); + +always@(clk) + #5 clk <= ~clk; + +initial + begin + $dumpfile("dump.vcd"); + $dumpvars(4,m); + rst_n <= 0; + clk <= 0; + #50; + rst_n <= 1; + + end + + + +endmodule \ No newline at end of file Index: trunk/lib/bsv/BRAMFIFO/BRAMFIFO.bsv =================================================================== --- trunk/lib/bsv/BRAMFIFO/BRAMFIFO.bsv (nonexistent) +++ trunk/lib/bsv/BRAMFIFO/BRAMFIFO.bsv (revision 2) @@ -0,0 +1,163 @@ +//----------------------------------------------------------------------// +// The MIT License +// +// Copyright (c) 2008 Kermin Fleming, kfleming@mit.edu +// +// 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. +//----------------------------------------------------------------------// + +import FIFO::*; +import FIFOF::*; +import FIFOF_::*; + +/*** + * + * This module serves as a simple bluespec wrapper for + * the verilog based BRAMFIFO. The imported methods support + * the standard FIFOF and FIFO classes. It should be noted that + * the underlying verilog implementation is gaurded. + * + ***/ + + +module mkBRAMFIFO#(Integer count) (FIFO#(fifo_type)) + provisos + (Bits#(fifo_type, fifo_size)); + FIFOF#(fifo_type) fifo <- mkBRAMFIFOF(count); + + method Action enq(fifo_type data); + fifo.enq(data); + endmethod + + method Action deq(); + fifo.deq(); + endmethod + + method fifo_type first(); + return fifo.first(); + endmethod + + method Action clear(); + fifo.clear(); + endmethod + +endmodule + +module mkBRAMFIFOF#(Integer count) (FIFOF#(fifo_type)) + provisos + (Bits#(fifo_type, fifo_size)); + `ifdef BLUESIM + FIFOF#(fifo_type) fifo <- mkSizedFIFOF(count); + `else + error("How did we get here?"); + FIFOF#(fifo_type) fifo <- mkBRAMFIFOFIndirect(count); + `endif + return fifo; +endmodule + +module mkBRAMFIFOFIndirect#(Integer count) (FIFOF#(fifo_type)) + provisos + (Bits#(fifo_type, fifo_size)); + + FIFOF_#(fifo_type) fifo <- mkBRAMFIFOF_(count); + + method Action enq(fifo_type data) if(fifo.i_notFull); + fifo.enq(data); + endmethod + + method Action deq() if(fifo.i_notEmpty); + fifo.deq(); + endmethod + + method fifo_type first() if(fifo.i_notEmpty); + return fifo.first(); + endmethod + + method Bool notFull; + return fifo.notFull; + endmethod + + method Bool notEmpty; + return fifo.notEmpty; + endmethod + + method Action clear(); + fifo.clear(); + endmethod + + +endmodule + + +import "BVI" BRAMFIFOF = module mkBRAMFIFOF_#(Integer count) + //interface: + (FIFOF_#(fifo_type)) + provisos + (Bits#(fifo_type, fifo_size)); + + default_clock clk(CLK); + + parameter log_data_count = log2(count); + parameter data_count = count; + parameter data_width = valueOf(fifo_size); + + method enq((* reg *)D_IN) enable(ENQ); + method deq() enable(DEQ); + method (* reg *)D_OUT first; + method FULL_N notFull; + method FULL_N i_notFull; + method (* reg *)EMPTY_N notEmpty; + method (* reg *)EMPTY_N i_notEmpty; + method clear() enable(CLR); + + schedule deq CF (enq, i_notEmpty, i_notFull) ; + schedule enq CF (deq, first, i_notEmpty, i_notFull) ; + schedule (first, notEmpty, notFull) CF + (first, i_notEmpty, i_notFull, notEmpty, notFull) ; + schedule (i_notEmpty, i_notFull) CF + (clear, first, i_notEmpty, i_notFull, notEmpty, notFull) ; + schedule (clear, deq, enq) SBR clear ; + schedule first SB (clear, deq) ; + schedule (notEmpty, notFull) SB (clear, deq, enq) ; + + + /*schedule first SB (deq,enq,clear); + schedule first CF (first,notFull,notEmpty); + + schedule notFull SB (deq,enq,clear); + schedule notFull CF (first,notFull,notEmpty); + + schedule notEmpty SB (deq,enq,clear); + schedule notEmpty CF (first,notFull,notEmpty); + + schedule deq CF enq; + schedule deq SB clear; + schedule deq C deq; + + schedule enq CF deq; + schedule enq SB clear; + schedule enq C enq; + + schedule clear C clear;*/ + +endmodule + + Index: trunk/lib/bsv/ClientServerUtils/ClientServerUtils.bsv =================================================================== --- trunk/lib/bsv/ClientServerUtils/ClientServerUtils.bsv (nonexistent) +++ trunk/lib/bsv/ClientServerUtils/ClientServerUtils.bsv (revision 2) @@ -0,0 +1,51 @@ +import ClientServer::*; +import FIFO::*; +import GetPut::*; +import Vector::*; +import Debug::*; + +Bool clientServerDebug = False; + +module mkReplicatedServer#(Server#(req_t,resp_t) server,Integer reqDepth) (Vector#(num_servers,Server#(req_t,resp_t))); + FIFO#(Bit#(TLog#(num_servers))) numFIFO <- mkSizedFIFO(reqDepth); + Vector#(num_servers,Server#(req_t,resp_t)) interfaces = newVector(); + Reg#(Bit#(TAdd#(1,TLog#(num_servers)))) counter <- mkReg(0); + + rule roundRobin; + if(counter + 1 == fromInteger(valueof(num_servers))) + begin + counter <= 0; + end + else + begin + counter <= counter + 1; + end + endrule + + for(Integer i = 0; i < valueof(num_servers); i=i+1) + begin + interfaces[i] = interface Server; + interface Put request; + method Action put(req_t req) if(counter == fromInteger(i)); + debug(clientServerDebug,$display("Replicate Server %d Req", i)); + numFIFO.enq(fromInteger(i)); + server.request.put(req); + endmethod + endinterface + + interface Get response; + method ActionValue#(resp_t) get() if(numFIFO.first == fromInteger(i)); + begin + debug(clientServerDebug,$display("Replicate Server %d Resp",i)); + numFIFO.deq; + let data <- server.response.get; + return data; + end + endmethod + endinterface + endinterface; + end + + + return interfaces; +endmodule Index: trunk/lib/bsv/Debug/Debug.bsv =================================================================== --- trunk/lib/bsv/Debug/Debug.bsv (nonexistent) +++ trunk/lib/bsv/Debug/Debug.bsv (revision 2) @@ -0,0 +1,7 @@ +function Action debug(Bool b, Action a); + action + + if (b) a; + + endaction +endfunction \ No newline at end of file Index: trunk/lib/bsv/PLBMaster/test/PLBMasterEmulator.bsv =================================================================== --- trunk/lib/bsv/PLBMaster/test/PLBMasterEmulator.bsv (nonexistent) +++ trunk/lib/bsv/PLBMaster/test/PLBMasterEmulator.bsv (revision 2) @@ -0,0 +1,131 @@ +/* + This module is intended as an in-place model for a plb-based memory subsystem. + This code was used in Memocode 08 design project. Memory size is + given in words. */ + +// CSG lib includes +import PLBMaster::*; +import PLBMasterWires::*; +`ifdef PLB_DEFAULTS + import PLBMasterDefaultParameters::*; +`endif + +// BSC includes +import Vector::*; +import FIFO::*; +import FIFOF::*; +import GetPut::*; +import RegFile::*; + +interface PLBMasterEmulator#(numeric type memorySize); + interface PLBMaster plbmaster; +endinterface + +typedef enum { + Load, + Store, + Idle +} State deriving (Bits, Eq); + +module mkPLBMasterEmulator#(RegFile#(Bit#(TLog#(memorySize)),BusWord) memory) (PLBMasterEmulator#(memorySize)) + provisos(Add#(xxx,TLog#(memorySize),SizeOf#(BlockAddr))); + Integer lineDelay = 14; + + Reg#(Bit#(TLog#(BeatsPerBurst))) plbCount <- mkReg(0); + FIFOF#(BusWord) storeFIFO <- mkSizedFIFOF(valueof(BeatsPerBurst)); + FIFOF#(BusWord) loadFIFO <- mkSizedFIFOF(valueof(BeatsPerBurst)); + FIFOF#(PLBMasterCommand) plbLoadCommand <- mkFIFOF(); + FIFOF#(PLBMasterCommand) plbStoreCommand <- mkFIFOF(); + Reg#(Maybe#(Bit#(6))) plbDelay <- mkReg(tagged Invalid); + Reg#(State) state <- mkReg(Idle); + + //Problem in loads bypassing stores -> loads block, but no store is issued... may need to check load fifo emptiness before issuing a load. + //Might introduce such a fifo + + // Only start store if store is full + rule startStoreDelay(plbDelay matches tagged Invalid &&& plbStoreCommand.notEmpty && !storeFIFO.notFull); + state <= Store; + plbDelay <= tagged Valid fromInteger(lineDelay); + endrule + + rule startLoadDelay(plbDelay matches tagged Invalid &&& plbLoadCommand.notEmpty && !loadFIFO.notEmpty); + state <= Load; + plbDelay <= tagged Valid fromInteger(lineDelay); + endrule + + rule tickCount(plbDelay matches tagged Valid .count &&& count > 0); + plbDelay <= tagged Valid (count - 1); + if(count - 1 == 0) + begin + $display("PLB Model finished wait for %s", (state==Store)?"Store":"Load"); + end + endrule + + rule storeRule(plbStoreCommand.first matches tagged StorePage .addr &&& plbDelay matches tagged Valid .count &&& count == 0 &&& (state == Store)); + Bit#(64) wordInput = storeFIFO.first; + // The addr refers to 32 bit addresses + Bit#(TLog#(memorySize)) addrMod = truncate((addr>>1)+ zeroExtend(plbCount)); + + storeFIFO.deq; + memory.upd(addrMod,wordInput); + $display("plbMaster store count: %d, mem[%d] <= %h",plbCount, addrMod, storeFIFO.first); + plbCount <= plbCount + 1; + if(plbCount + 1 == 0) + begin + state <= Idle; + plbDelay <= tagged Invalid; + plbStoreCommand.deq; + end + endrule + + rule loadRule (plbLoadCommand.first matches tagged LoadPage .addr &&& plbDelay matches tagged Valid .count &&& count == 0 &&& (state == Load)); + plbCount <= plbCount + 1; + if(plbCount + 1 == 0) + begin + $display("plbMaster load command dequed!"); + plbLoadCommand.deq; + state <= Idle; + plbDelay <= tagged Invalid; + end + // This may not be correct. + Bit#(TLog#(memorySize)) addrMod = truncate((addr>>1) + zeroExtend(plbCount)); + $display("plbMaster load count: %d, mem[%d]: %h",plbCount, addrMod, memory.sub(addrMod)); + loadFIFO.enq(memory.sub(addrMod)); + endrule + + interface PLBMaster plbmaster; + + interface Put wordInput; + method Action put(Bit#(64) wordInput); + storeFIFO.enq(wordInput); + endmethod + endinterface + + interface Get wordOutput; + method ActionValue#(Bit#(64)) get(); + loadFIFO.deq; + return loadFIFO.first; + endmethod + endinterface + + interface Put plbMasterCommandInput; + method Action put(PLBMasterCommand command); + $display("PLB Master got a command: %s", command matches tagged LoadPage .addr?"Load":"Store"); + if(command matches tagged StorePage .addr) + begin + plbStoreCommand.enq(command); + end + else + begin + plbLoadCommand.enq(command); + end + endmethod + endinterface + + interface plbMasterWires = ?; + + endinterface + + + +endmodule \ No newline at end of file Index: trunk/lib/bsv/PLBMaster/src/PLBMaster.bsv =================================================================== --- trunk/lib/bsv/PLBMaster/src/PLBMaster.bsv (nonexistent) +++ trunk/lib/bsv/PLBMaster/src/PLBMaster.bsv (revision 2) @@ -0,0 +1,535 @@ +/* +Copyright (c) 2007 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 file implements a PLB bus master. The bus master operates on static + sized bursts. It is written in such a way that read/write bursts may be + overlapped, if the bus and target slave support such a feature. There's also + support for pipelining of read and write requests. The master is + parameterized by BeatsPerBurst (burst length) and BusWord (bus width), + which allow it to be used for various applications. +*/ + +// Global Imports +import GetPut::*; +import FIFO::*; +import RegFile::*; +import BRAMInitiatorWires::*; +import RegFile::*; +import FIFOF::*; +import Vector::*; +`ifdef PLB_DEFAULTS + import PLBMasterDefaultParameters::*; +`endif + +import PLBMasterWires::*; + +typedef Bit#(30) BlockAddr; + +interface PLBMaster; + interface Put#(Bit#(64)) wordInput; + interface Get#(Bit#(64)) wordOutput; + interface Put#(PLBMasterCommand) plbMasterCommandInput; + interface PLBMasterWires plbMasterWires; +endinterface + +typedef union tagged +{ + BlockAddr LoadPage; + BlockAddr StorePage; +} + PLBMasterCommand + deriving(Bits,Eq); + +typedef enum { + Idle, + Data, + WaitForBusy +} StateTransfer + deriving(Bits, Eq); + +typedef enum { + Idle, + RequestingLoad, + RequestingStore +} StateRequest + deriving(Bits, Eq); + +(* synthesize *) +module mkPLBMaster (PLBMaster); + Clock plbClock <- exposeCurrentClock(); + Reset plbReset <- exposeCurrentReset(); + // state for the actual magic memory hardware + FIFO#(BusWord) recordInfifo <- mkFIFO; + FIFO#(BusWord) recordOutfifo <- mkFIFO; + FIFO#(PLBMasterCommand) plbMasterCommandInfifo <- mkFIFO(); + + + // Output buffer + RegFile#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))),BusWord) storeBuffer <- mkRegFileFull(); + + + // Input buffer + RegFile#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))),BusWord) loadBuffer <- mkRegFileFull(); + + + Reg#(Bit#(24)) rowAddrOffsetLoad <- mkReg(0); + Reg#(Bit#(24)) rowAddrOffsetStore <- mkReg(0); + + Reg#(Bool) doingLoad <- mkReg(False); + Reg#(Bool) doingStore <- mkReg(False); + + Bit#(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))) zeroOffset = 0; // Words per Burst + Reg#(Bool) requestingStore <- mkReg(False); + BlockAddr addressOffset = zeroExtend({(requestingStore)?rowAddrOffsetStore:rowAddrOffsetLoad,zeroOffset}); + + + Reg#(StateRequest) stateRequest <- mkReg(Idle); + Reg#(StateTransfer) stateLoad <- mkReg(Idle); + Reg#(StateTransfer) stateStore <- mkReg(Idle); + Reg#(Bit#(1)) request <- mkReg(0); + Reg#(Bit#(1)) rnw <- mkReg(0); + + + Reg#(Bit#(TLog#(BeatsPerBurst))) loadDataCount <- mkReg(0); + Reg#(Bit#(TLog#(BeatsPerBurst))) storeDataCount <-mkReg(0);// If you change this examine mWrDBus_o + Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) loadDataCount_plus2 <- mkReg(2); + Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) storeDataCount_plus2 <-mkReg(2); + + Reg#(Bool) doAckinIdle <- mkReg(False); + + Reg#(Bit#(1)) rdBurst <- mkReg(0); + Reg#(Bit#(1)) wrBurst <- mkReg(0); + + Reg#(Bit#(1)) storeCounter <- mkReg(0); + Reg#(Bit#(1)) loadCounter <- mkReg(0); + + Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) storeBufferWritePointer <- mkReg(0); + FIFOF#(Bit#(0)) storeValid <- mkUGFIFOF;//XXX: This could be bad + Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) loadBufferReadPointer <- mkReg(0); + FIFOF#(Bit#(0)) loadValid <- mkUGFIFOF;//XXX: This could be bad + + + // Input wires + Wire#(Bit#(1)) mRst <- mkBypassWire(); + Wire#(Bit#(1)) mAddrAck <- mkBypassWire(); + Wire#(Bit#(1)) mBusy <- mkBypassWire(); + Wire#(Bit#(1)) mErr <- mkBypassWire(); + Wire#(Bit#(1)) mRdBTerm <- mkBypassWire(); + Wire#(Bit#(1)) mRdDAck <- mkBypassWire(); + Wire#(Bit#(64))mRdDBus <- mkBypassWire(); + Wire#(Bit#(3)) mRdWdAddr <- mkBypassWire(); + Wire#(Bit#(1)) mRearbitrate <- mkBypassWire(); + Wire#(Bit#(1)) mWrBTerm <- mkBypassWire(); + Wire#(Bit#(1)) mWrDAck <- mkBypassWire(); + Wire#(Bit#(1)) mSSize <- mkBypassWire(); + Wire#(Bit#(1)) sMErr <- mkBypassWire(); // on a read, during the data ack + Wire#(Bit#(1)) sMBusy <- mkBypassWire(); + + // Outputs + + + Bit#(PLBAddrSize) mABus_o = {addressOffset,2'b00}; // Our address Address Bus, we extend to compensate for word + + + Bit#(TAdd#(1,TLog#(BeatsPerBurst))) sbuf_addr = {storeCounter,storeDataCount}; + + + Bit#(64)mWrDBus_o = storeBuffer.sub(sbuf_addr); + Bit#(1) mRequest_o = request & ~mRst; // Request + Bit#(1) mBusLock_o = 1'b0 & ~mRst; // Bus lock + Bit#(1) mRdBurst_o = rdBurst & ~mRst; // read burst + Bit#(1) mWrBurst_o = wrBurst & ~mRst; // write burst + Bit#(1) mRNW_o = rnw; // Read Not Write + Bit#(1) mAbort_o = 1'b0; // Abort + Bit#(2) mPriority_o = 2'b11;// priority indicator + Bit#(1) mCompress_o = 1'b0;// compressed transfer + Bit#(1) mGuarded_o = 1'b0;// guarded transfer + Bit#(1) mOrdered_o = 1'b0;// synchronize transfer + Bit#(1) mLockErr_o = 1'b0;// lock erro + Bit#(4) mSize_o = 4'b1011; // Burst double word transfer - see PLB p.24 + Bit#(3) mType_o = 3'b000; // Memory Transfer + Bit#(8) mBE_o = 8'b00001111; // 16 word burst + Bit#(2) mMSize_o = 2'b00; + + + // precompute the next address offset. Sometimes + + + PLBMasterCommand cmd_in_first = plbMasterCommandInfifo.first(); + + let newloadDataCount = loadDataCount + 1; + let newstoreDataCount = storeDataCount + 1; + let newloadDataCount_plus2 = loadDataCount_plus2 + 1; + let newstoreDataCount_plus2 = storeDataCount_plus2 + 1; + + + rule startPageLoad(cmd_in_first matches tagged LoadPage .ba &&& !doingLoad); + $display("Start Page"); + plbMasterCommandInfifo.deq(); + $display("Load Page"); + rowAddrOffsetLoad <= truncate(ba>>(valueof(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))))); // this is the log + if (ba[3:0] != 0) + $display("ERROR:Address not 64-byte aligned"); + doingLoad <= True; + endrule + + rule startPageStore(cmd_in_first matches tagged StorePage .ba &&& !doingStore); + $display("Start Page"); + plbMasterCommandInfifo.deq(); + $display("Store Page"); + rowAddrOffsetStore <= truncate(ba>>(valueof(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))))); // this is the log + // size of burst addr + if (ba[3:0] != 0) + $display("ERROR:Address not 64-byte aligned"); + doingStore <= True; + endrule + + + rule loadPage_Idle(doingLoad && stateRequest == Idle && stateLoad == Idle && loadValid.notFull); + // We should not initiate a transfer if the wordOutfifo is not valid + requestingStore <= False; + request <= 1'b1; + stateRequest <= RequestingLoad; + rnw <= 1'b1; // We're reading + endrule + + // Store page idle is somehow running!!! + rule storePage_Idle(doingStore && stateRequest == Idle && stateStore == Idle && storeValid.notEmpty); + requestingStore <= True; + request <= 1'b1; + stateRequest <= RequestingStore; + wrBurst <= 1'b1; // Write burst is asserted with the write request + rnw <= 1'b0; // We're writing + endrule + + rule continueIdling (stateRequest == Idle && stateStore == Idle && (!(doingStore && storeValid.notEmpty) && !(doingLoad && loadValid.notFull))); // Gotta work out the complements of the stuff up above + request <= 1'b0; + requestingStore <= True; + wrBurst <= 1'b1; // Write burst is asserted with the write request + rnw <= 1'b0; // We're writing + endrule + + + rule loadPage_Requesting(doingLoad && stateRequest == RequestingLoad && stateLoad == Idle); + // We've just requested the bus and are waiting for an ack + //$display("loadPage_Requesting"); + if(mAddrAck == 1 ) + begin + stateRequest <= Idle; + // Check for error conditions + if(mRearbitrate == 1) + begin + // Got terminated by the bus + $display("Terminated by BUS @ %d",$time); + stateLoad <= Idle; + rdBurst <= 1'b0; // if we're rearbing this should be off. It may be off anyway? + request <= 1'b0; + end + else + begin + //Whew! didn't die yet.. wait for acks to come back + stateLoad <= Data; + // Not permissible to assert burst until after addrAck p. 35 + rdBurst <= 1'b1; + // Set down request, as we are not request pipelining + request <= 1'b0; + end + end + endrule + + rule loadPage_Data(doingLoad && stateLoad == Data); + if(((mRdBTerm == 1) && (loadDataCount_plus2 < (fromInteger(valueof(BeatsPerBurst))))) || (mErr == 1)) + begin + // We got terminated / Errored + rdBurst <= 1'b0; + loadDataCount <= 0; + loadDataCount_plus2 <= 2; + stateLoad <= Idle; + end + else if(mRdDAck == 1) + begin + loadDataCount <= newloadDataCount; + loadDataCount_plus2 <= newloadDataCount_plus2; + loadBuffer.upd({loadCounter,loadDataCount}, mRdDBus); + if(newloadDataCount == 0) + begin + loadCounter <= loadCounter + 1; // Flip the loadCounter + //We're now done reading... what should we do? + loadValid.enq(0); // This signifies that the data is valid Nirav could probably remove this + doingLoad <= False; + stateLoad <= Idle; + end + else if(newloadDataCount == maxBound) // YYY: ndave used to ~0 + begin + // Last read is upcoming. Need to set down the + // rdBurst signal. + rdBurst <= 1'b0; + end + end + endrule + + + + rule storePage_Requesting(doingStore && stateRequest == RequestingStore && stateStore == Idle); + // We've just requested the bus and are waiting for an ack + if(mAddrAck == 1 ) + begin + stateRequest <= Idle; + // Check for error conditions + if(mRearbitrate == 1) + begin + // Got terminated by the bus + wrBurst <= 1'b0; + request <= 1'b0; + end + else + begin + // Set down request, as we are not request pipelining + request <= 1'b0; + // We can be WrDAck'ed at this time p.29 or WrBTerm p.30 + if(mWrBTerm == 1) + begin + wrBurst <= 1'b0; + end + else if(mWrDAck == 1) + begin + storeDataCount <= newstoreDataCount; + storeDataCount_plus2 <= newstoreDataCount_plus2; + stateStore <= Data; + end + else + begin + stateStore <= Data; + end + end + end + endrule + + + rule storePage_Data(doingStore && stateStore == Data); + if((mWrBTerm == 1) && (storeDataCount_plus2 < (fromInteger(valueof(BeatsPerBurst)))) || (mErr == 1)) + begin + // We got terminated / Errored + wrBurst <= 1'b0; + storeDataCount <= 0; + storeDataCount_plus2 <= 2; + stateStore <= Idle; // Can't burst for a cycle p. 30 + end + else if(mWrDAck == 1) + begin + storeDataCount <= newstoreDataCount; + storeDataCount_plus2 <= newstoreDataCount_plus2; + if(newstoreDataCount == 0) + begin + //We're now done reading... what should we do? + // Data transfer complete + if(mBusy == 0) + begin + doingStore <= False; + stateStore <= Idle; + storeValid.deq(); + storeCounter <= storeCounter + 1; + end + else + begin + stateStore <= WaitForBusy; + end + end + else if(newstoreDataCount == maxBound) //YYY: used to be ~0 + begin + // Last read is upcoming. Need to set down the + // wrBurst signal. + wrBurst <= 1'b0; + end + end + endrule + + rule storePage_WaitForBusy(doingStore && stateStore == WaitForBusy); + if(mErr == 1) + begin + // We got terminated / Errored + wrBurst <= 1'b0; + storeDataCount <= 0; // may not be necessary + storeDataCount_plus2 <= 2; + stateStore <= Idle; // Can't burst for a cycle p. 30 + end + else if(mBusy == 0) + begin + storeCounter <= storeCounter + 1; + doingStore <= False; + stateStore <= Idle; + storeValid.deq(); + end + endrule + + /******** + /* Code For Handling Record Translation + /*******/ + + rule writeStoreData(storeValid.notFull()); + storeBufferWritePointer <= storeBufferWritePointer + 1; + + + storeBuffer.upd(storeBufferWritePointer, recordInfifo.first); + + + recordInfifo.deq; + + Bit#(TLog#(BeatsPerBurst)) bottomValue = 0; + if(truncate(storeBufferWritePointer + 1) == bottomValue) + begin + $display("Store Data finished a flight"); + storeValid.enq(0); + end + endrule + + + rule wordToRecord(loadValid.notEmpty()); + loadBufferReadPointer <= loadBufferReadPointer + 1; + Bit#(64) loadValue = loadBuffer.sub(loadBufferReadPointer); + Bit#(32) loadHigh = loadValue [63:32]; + Bit#(32) loadLow = loadValue [31:0]; + Bit#(TLog#(BeatsPerBurst)) bottomValue = 0; + if(truncate(loadBufferReadPointer + 1) == bottomValue) + begin + $display("Load Data finished a flight"); + loadValid.deq(); + end + + + recordOutfifo.enq({loadHigh,loadLow}); + + endrule + + interface Put wordInput = fifoToPut(recordInfifo); + + interface Get wordOutput = fifoToGet(recordOutfifo); + + interface Put plbMasterCommandInput = fifoToPut(plbMasterCommandInfifo); + + + interface PLBMasterWires plbMasterWires; + + method Bit#(PLBAddrSize) mABus(); // Address Bus + return mABus_o; + endmethod + method Bit#(8) mBE(); // Byte Enable + return mBE_o; + endmethod + + method Bit#(1) mRNW(); // Read Not Write + return mRNW_o; + endmethod + + method Bit#(1) mAbort(); // Abort + return mAbort_o; + endmethod + + method Bit#(1) mBusLock(); // Bus lock + return mBusLock_o; + endmethod + + method Bit#(1) mCompress(); // compressed transfer + return mCompress_o; + endmethod + + method Bit#(1) mGuarded(); // guarded transfer + return mGuarded_o; + endmethod + + method Bit#(1) mLockErr(); // lock error + return mLockErr_o; + endmethod + + method Bit#(2) mMSize(); // data bus width? + return mMSize_o; + endmethod + + method Bit#(1) mOrdered(); // synchronize transfer + return mOrdered_o; + endmethod + + method Bit#(2) mPriority(); // priority indicator + return mPriority_o; + endmethod + + method Bit#(1) mRdBurst(); // read burst + return mRdBurst_o; + endmethod + + method Bit#(1) mRequest(); // bus request + return mRequest_o; + endmethod + + method Bit#(4) mSize(); // transfer size + return mSize_o; + endmethod + + method Bit#(3) mType(); // transfer type (dma) + return mType_o; + endmethod + + method Bit#(1) mWrBurst(); // write burst + return mWrBurst_o; + endmethod + + method Bit#(64) mWrDBus(); // write data bus + return mWrDBus_o; + endmethod + + method Action plbIN( + Bit#(1) mRst_in, // PLB reset + Bit#(1) mAddrAck_in, // Addr Ack + Bit#(1) mBusy_in, // Master Busy + Bit#(1) mErr_in, // Slave Error + Bit#(1) mRdBTerm_in, // Read burst terminate signal + Bit#(1) mRdDAck_in, // Read data ack + Bit#(64)mRdDBus_in, // Read data bus + Bit#(3) mRdWdAddr_in, // Read word address + Bit#(1) mRearbitrate_in, // Rearbitrate + Bit#(1) mWrBTerm_in, // Write burst terminate + Bit#(1) mWrDAck_in, // Write data ack + Bit#(1) mSSize_in, // Slave bus size + Bit#(1) sMErr_in, // Slave error + Bit#(1) sMBusy_in); // Slave busy + mRst <= mRst_in; + mAddrAck <= mAddrAck_in; + mBusy <= mBusy_in; + mErr <= mErr_in; + mRdBTerm <= mRdBTerm_in; + mRdDAck <= mRdDAck_in; + mRdDBus <= mRdDBus_in; + mRdWdAddr <= mRdWdAddr_in; + mRearbitrate <= mRearbitrate_in; + mWrBTerm <= mWrBTerm_in; + mWrDAck <= mWrDAck_in; + mSSize <= mSSize_in; + sMErr <= sMErr_in; + sMBusy <= sMBusy_in; + endmethod + endinterface +endmodule Index: trunk/lib/bsv/PLBMaster/src/PLBMasterWires.bsv =================================================================== --- trunk/lib/bsv/PLBMaster/src/PLBMasterWires.bsv (nonexistent) +++ trunk/lib/bsv/PLBMaster/src/PLBMasterWires.bsv (revision 2) @@ -0,0 +1,142 @@ +/* +Copyright (c) 2007 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 +*/ + +// Global Imports +import GetPut::*; + +// We only use the default params if the compile flag is turned on. +`ifdef PLB_DEFAULTS +import PLBMasterDefaultParameters::*; +`endif + +`define PLB_CLK_NAME "mClk" +`define PLB_RST_NAME "mRst" +`define PLB_COMPRESS_NAME "mCompress" +`define PLB_ABUS_NAME "mABus" +`define PLB_BE_NAME "mBE" +`define PLB_RNW_NAME "mRNW" +`define PLB_ABORT_NAME "mAbort" +`define PLB_BUSLOCK_NAME "mBusLock" +`define PLB_PRESS_NAME "mpress" +`define PLB_GUARDED_NAME "mGuarded" +`define PLB_LOCKERR_NAME "mLockErr" +`define PLB_MSIZE_NAME "mMSize" +`define PLB_ORDERED_NAME "mOrdered" +`define PLB_PRIORITY_NAME "mPriority" +`define PLB_RDBURST_NAME "mRdBurst" +`define PLB_REQUEST_NAME "mRequest" +`define PLB_SIZE_NAME "mSize" +`define PLB_TYPE_NAME "mType" +`define PLB_WRBURST_NAME "mWrBurst" +`define PLB_WRDBUS_NAME "mWrDBus" +`define PLB_MADDRACK_NAME "mAddrAck" +`define PLB_MBUSY_NAME "mBusy" +`define PLB_MERR_NAME "mErr" +`define PLB_MRDBTERM_NAME "mRdBTerm" +`define PLB_MRDDACK_NAME "mRdDAck" +`define PLB_MRDDBUS_NAME "mRdDBus" +`define PLB_MRDWDADDR_NAME "mRdWdAddr" +`define PLB_MREARBITRATE_NAME "mRearbitrate" +`define PLB_MWRBTERM_NAME "mWrBTerm" +`define PLB_MWRDACK_NAME "mWrDAck" +`define PLB_MSSIZE_NAME "mSSize" +`define PLB_SMERR_NAME "sMErr" +`define PLB_SMBUSY_NAME "sMBusy" + + +interface PLBMasterWires; + + (* always_ready, prefix="", result=`PLB_ABUS_NAME *) + method Bit#(PLBAddrSize) mABus(); // Address Bus + + (* always_ready, prefix="", result=`PLB_BE_NAME *) + method Bit#(8) mBE(); // Byte Enable + + (* always_ready, prefix="", result=`PLB_RNW_NAME *) + method Bit#(1) mRNW(); // Read Not Write + + (* always_ready, prefix="", result=`PLB_ABORT_NAME *) + method Bit#(1) mAbort(); // Abort + + (* always_ready, prefix="", result=`PLB_BUSLOCK_NAME *) + method Bit#(1) mBusLock(); // Bus lock + + (* always_ready, prefix="", result=`PLB_COMPRESS_NAME *) + method Bit#(1) mCompress(); // compressed transfer + + (* always_ready, prefix="", result=`PLB_GUARDED_NAME *) + method Bit#(1) mGuarded(); // guarded transfer + + (* always_ready, prefix="", result=`PLB_LOCKERR_NAME *) + method Bit#(1) mLockErr(); // lock error + + (* always_ready, prefix="", result=`PLB_MSIZE_NAME *) + method Bit#(2) mMSize(); // data bus width? + + (* always_ready, prefix="", result=`PLB_ORDERED_NAME *) + method Bit#(1) mOrdered(); // synchronize transfer + + (* always_ready, prefix="", result=`PLB_PRIORITY_NAME *) + method Bit#(2) mPriority(); // priority indicator + + (* always_ready, prefix="", result=`PLB_RDBURST_NAME *) + method Bit#(1) mRdBurst(); // read burst + + (* always_ready, prefix="", result=`PLB_REQUEST_NAME *) + method Bit#(1) mRequest(); // bus request + + (* always_ready, prefix="", result=`PLB_SIZE_NAME *) + method Bit#(4) mSize(); // transfer size + + (* always_ready, prefix="", result=`PLB_TYPE_NAME *) + method Bit#(3) mType(); // transfer type (dma) + + (* always_ready, prefix="", result=`PLB_WRBURST_NAME *) + method Bit#(1) mWrBurst(); // write burst + + (* always_ready, prefix="", result=`PLB_WRDBUS_NAME *) + method Bit#(64) mWrDBus(); // write data bus + + (* always_ready, prefix="", always_enabled *) + method Action plbIN( + (* port=`PLB_RST_NAME *) Bit#(1) mRst, // PLB reset + (* port=`PLB_MADDRACK_NAME *) Bit#(1) mAddrAck, // Addr Ack + (* port=`PLB_MBUSY_NAME *) Bit#(1) mBusy, // Master Busy + (* port=`PLB_MERR_NAME *) Bit#(1) mErr, // Slave Error + (* port=`PLB_MRDBTERM_NAME *) Bit#(1) mRdBTerm, // Read burst terminate signal + (* port=`PLB_MRDDACK_NAME *) Bit#(1) mRdDAck, // Read data ack + (* port=`PLB_MRDDBUS_NAME *) Bit#(64)mRdDBus, // Read data bus + (* port=`PLB_MRDWDADDR_NAME *) Bit#(3) mRdWdAddr, // Read word address + (* port=`PLB_MREARBITRATE_NAME *) Bit#(1) mRearbitrate, // Rearbitrate + (* port=`PLB_MWRBTERM_NAME *) Bit#(1) mWrBTerm, // Write burst terminate + (* port=`PLB_MWRDACK_NAME *) Bit#(1) mWrDAck, // Write data ack + (* port=`PLB_MSSIZE_NAME *) Bit#(1) mSSize, // Slave bus size + (* port=`PLB_SMERR_NAME *) Bit#(1) sMErr, // Slave error + (* port=`PLB_SMBUSY_NAME *) Bit#(1) sMBusy); // Slave busy + + +endinterface Index: trunk/lib/bsv/PLBMaster/common/PLBMasterDefaultParameters.bsv =================================================================== --- trunk/lib/bsv/PLBMaster/common/PLBMasterDefaultParameters.bsv (nonexistent) +++ trunk/lib/bsv/PLBMaster/common/PLBMasterDefaultParameters.bsv (revision 2) @@ -0,0 +1,7 @@ +typedef 32 PLBAddrSize; +typedef Bit#(PLBAddrSize) PLBAddr; +typedef 2 WordsPerBeat; // PLB bandwidth +typedef 16 BurstSize; // number of beats per burst +typedef 16 BeatsPerBurst; +typedef Bit#(64) BusWord; +typedef TMul#(WordsPerBeat,BeatsPerBurst) WordsPerBurst; Index: trunk/lib/bsv/PLBMaster/fpga/plbmastertester.v =================================================================== --- trunk/lib/bsv/PLBMaster/fpga/plbmastertester.v (nonexistent) +++ trunk/lib/bsv/PLBMaster/fpga/plbmastertester.v (revision 2) @@ -0,0 +1,234 @@ +/* +Copyright (c) 2007 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: Nirav Dave +*/ + +module plbmastertester(CLK, + RST, + + plbMasterWires_mABus, + + plbMasterWires_mBE, + + plbMasterWires_mRNW, + + plbMasterWires_mAbort, + + plbMasterWires_mBusLock, + + plbMasterWires_mCompress, + + plbMasterWires_mGuarded, + + plbMasterWires_mLockErr, + + plbMasterWires_mMSize, + + plbMasterWires_mOrdered, + + plbMasterWires_mPriority, + + plbMasterWires_mRdBurst, + + plbMasterWires_mRequest, + + plbMasterWires_mSize, + + plbMasterWires_mType, + + plbMasterWires_mWrBurst, + + plbMasterWires_mWrDBus, + + plbMasterWires_mRst, + plbMasterWires_mAddrAck, + plbMasterWires_mBusy, + plbMasterWires_mErr, + plbMasterWires_mRdBTerm, + plbMasterWires_mRdDAck, + plbMasterWires_mRdDBus, + plbMasterWires_mRdWdAddr, + plbMasterWires_mRearbitrate, + plbMasterWires_mWrBTerm, + plbMasterWires_mWrDAck, + plbMasterWires_mSSize, + plbMasterWires_sMErr, + plbMasterWires_sMBusy, + bramInitiatorWires_bramRST, + bramInitiatorWires_bramAddr, + bramInitiatorWires_bramDout, + bramInitiatorWires_bramWEN, + bramInitiatorWires_bramEN, + bramInitiatorWires_bramCLK, + bramInitiatorWires_bramDin); + input CLK; + input RST; + + // value method plbMasterWires_mABus + output [31 : 0] plbMasterWires_mABus; + + // value method plbMasterWires_mBE + output [7 : 0] plbMasterWires_mBE; + + // value method plbMasterWires_mRNW + output plbMasterWires_mRNW; + + // value method plbMasterWires_mAbort + output plbMasterWires_mAbort; + + // value method plbMasterWires_mBusLock + output plbMasterWires_mBusLock; + + // value method plbMasterWires_mCompress + output plbMasterWires_mCompress; + + // value method plbMasterWires_mGuarded + output plbMasterWires_mGuarded; + + // value method plbMasterWires_mLockErr + output plbMasterWires_mLockErr; + + // value method plbMasterWires_mMSize + output [1 : 0] plbMasterWires_mMSize; + + // value method plbMasterWires_mOrdered + output plbMasterWires_mOrdered; + + // value method plbMasterWires_mPriority + output [1 : 0] plbMasterWires_mPriority; + + // value method plbMasterWires_mRdBurst + output plbMasterWires_mRdBurst; + + // value method plbMasterWires_mRequest + output plbMasterWires_mRequest; + + // value method plbMasterWires_mSize + output [3 : 0] plbMasterWires_mSize; + + // value method plbMasterWires_mType + output [2 : 0] plbMasterWires_mType; + + // value method plbMasterWires_mWrBurst + output plbMasterWires_mWrBurst; + + // value method plbMasterWires_mWrDBus + output [63 : 0] plbMasterWires_mWrDBus; + + // action method plbMasterWires_plbIN + input plbMasterWires_mRst; + input plbMasterWires_mAddrAck; + input plbMasterWires_mBusy; + input plbMasterWires_mErr; + input plbMasterWires_mRdBTerm; + input plbMasterWires_mRdDAck; + input [63 : 0] plbMasterWires_mRdDBus; + input [2 : 0] plbMasterWires_mRdWdAddr; + input plbMasterWires_mRearbitrate; + input plbMasterWires_mWrBTerm; + input plbMasterWires_mWrDAck; + input plbMasterWires_mSSize; + input plbMasterWires_sMErr; + input plbMasterWires_sMBusy; + + // action method bramTargetWires_bramIN + output [31 : 0] bramInitiatorWires_bramAddr; + output [31 : 0] bramInitiatorWires_bramDout; + output [3 : 0] bramInitiatorWires_bramWEN; + output bramInitiatorWires_bramEN; + output bramInitiatorWires_bramCLK; + output bramInitiatorWires_bramRST; + + // value method bramTargetWires_bramOUT + input [31 : 0] bramInitiatorWires_bramDin; + + wire [13:0] bramInitiatorWires_bramAddr_our; + assign bramInitiatorWires_bramAddr = {16'h00000,bramInitiatorWires_bramAddr_our, 2'b00}; + // signals for module outputs + wire [31 : 0] bramTargetWires_dinBRAM,plbMasterWires_mABus; + + wire [63 : 0] plbMasterWires_mWrDBus; + wire [7 : 0] plbMasterWires_mBE; + wire [3 : 0] plbMasterWires_mSize; + wire [2 : 0] plbMasterWires_mType; + wire [1 : 0] plbMasterWires_mMSize, plbMasterWires_mPriority; + wire plbMasterWires_mAbort, + plbMasterWires_mBusLock, + plbMasterWires_mCompress, + plbMasterWires_mGuarded, + plbMasterWires_mLockErr, + plbMasterWires_mOrdered, + plbMasterWires_mRNW, + plbMasterWires_mRdBurst, + plbMasterWires_mRequest, + plbMasterWires_mWrBurst; + +wire RST_N; +assign RST_N = ~RST; + +mkPLBMasterTester m( + .CLK(CLK), + .RST_N(RST_N), + .plbMasterWires_mABus(plbMasterWires_mABus), + .plbMasterWires_mBE(plbMasterWires_mBE), + .plbMasterWires_mRNW(plbMasterWires_mRNW), + .plbMasterWires_mAbort(plbMasterWires_mAbort), + .plbMasterWires_mBusLock(plbMasterWires_mBusLock), + .plbMasterWires_mCompress(plbMasterWires_mCompress), + .plbMasterWires_mGuarded(plbMasterWires_mGuarded), + .plbMasterWires_mLockErr(plbMasterWires_mLockErr), + .plbMasterWires_mMSize(plbMasterWires_mMSize), + .plbMasterWires_mOrdered(plbMasterWires_mOrdered), + .plbMasterWires_mPriority(plbMasterWires_mPriority), + .plbMasterWires_mRdBurst(plbMasterWires_mRdBurst), + .plbMasterWires_mRequest(plbMasterWires_mRequest), + .plbMasterWires_mSize(plbMasterWires_mSize), + .plbMasterWires_mType(plbMasterWires_mType), + .plbMasterWires_mWrBurst(plbMasterWires_mWrBurst), + .plbMasterWires_mWrDBus(plbMasterWires_mWrDBus), + .plbMasterWires_mRst(plbMasterWires_mRst), + .plbMasterWires_mAddrAck(plbMasterWires_mAddrAck), + .plbMasterWires_mBusy(plbMasterWires_mBusy), + .plbMasterWires_mErr(plbMasterWires_mErr), + .plbMasterWires_mRdBTerm(plbMasterWires_mRdBTerm), + .plbMasterWires_mRdDAck(plbMasterWires_mRdDAck), + .plbMasterWires_mRdDBus(plbMasterWires_mRdDBus), + .plbMasterWires_mRdWdAddr(plbMasterWires_mRdWdAddr), + .plbMasterWires_mRearbitrate(plbMasterWires_mRearbitrate), + .plbMasterWires_mWrBTerm(plbMasterWires_mWrBTerm), + .plbMasterWires_mWrDAck(plbMasterWires_mWrDAck), + .plbMasterWires_mSSize(plbMasterWires_mSSize), + .plbMasterWires_sMErr(plbMasterWires_sMErr), + .plbMasterWires_sMBusy(plbMasterWires_sMBusy), + .bramInitiatorWires_bramAddr(bramInitiatorWires_bramAddr_our), + .bramInitiatorWires_bramDout(bramInitiatorWires_bramDout), + .bramInitiatorWires_bramWEN(bramInitiatorWires_bramWEN), + .bramInitiatorWires_bramEN(bramInitiatorWires_bramEN), + .bramInitiatorWires_bramCLK(bramInitiatorWires_bramCLK), + .bramInitiatorWires_bramRST(bramInitiatorWires_bramRST), + .bramInitiatorWires_din(bramInitiatorWires_bramDin) + ); + +endmodule \ No newline at end of file Index: trunk/lib/bsv/PLBMaster/fpga/PLBMasterTester.bsv =================================================================== --- trunk/lib/bsv/PLBMaster/fpga/PLBMasterTester.bsv (nonexistent) +++ trunk/lib/bsv/PLBMaster/fpga/PLBMasterTester.bsv (revision 2) @@ -0,0 +1,102 @@ +/* +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 PLBMasterWires::*; +import BRAMInitiatorWires::*; +import PLBMaster::*; +import BRAMFeeder::*; +import PLBMasterDefaultParameters::*; +import FIFO::*; +import GetPut::*; + +interface PLBMasterTester; + interface PLBMasterWires plbMasterWires; + interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires; +endinterface + +typedef enum{ + Idle, + Running, + Inputing, + Outputing +} TesterState deriving (Bits,Eq); + + +module mkPLBMasterTester(PLBMasterTester); + Feeder feeder <- mkBRAMFeeder(); + PLBMaster plbMaster <- mkPLBMaster; + + Reg#(TesterState) state <- mkReg(Idle); + Reg#(BlockAddr) baseRegLoad <- mkReg(0); + Reg#(BlockAddr) baseRegStore <- mkReg(0); + Reg#(Bit#(19)) commandCount <- mkReg(0); + Reg#(Bit#(32)) commandsComplete <- mkReg(1); + FIFO#(BusWord) dataFIFO <- mkSizedFIFO(32); + Reg#(Bool) evenZero <- mkReg(True); + + rule grabInstruction(state == Idle); + PPCMessage inst <- feeder.ppcMessageOutput.get; + baseRegLoad <= truncate(pack(inst)); + baseRegStore <= truncate(pack(inst)); + state <= Running; + endrule + + rule issueCommand(state == Running); + commandCount <= commandCount + 1; + if(commandCount + 1 == 0) + begin + state <= Idle; + feeder.ppcMessageInput.put(pack(commandsComplete)); + commandsComplete <= commandsComplete + 1; + end + + if(commandCount[2] == 0) + begin + baseRegLoad <= baseRegLoad + fromInteger(valueof(TMul#(BeatsPerBurst,WordsPerBeat))); + plbMaster.plbMasterCommandInput.put(tagged LoadPage (baseRegLoad)); + end + else + begin + baseRegStore <= baseRegStore + fromInteger(valueof(TMul#(BeatsPerBurst,WordsPerBeat))); + plbMaster.plbMasterCommandInput.put(tagged StorePage (baseRegStore)); + end + endrule + + rule inputing; + BusWord data <- plbMaster.wordOutput.get; + dataFIFO.enq(data); + endrule + + rule outputing; + plbMaster.wordInput.put(unpack((~(pack(dataFIFO.first))) & (~1))); + dataFIFO.deq; + endrule + + interface plbMasterWires = plbMaster.plbMasterWires; + interface bramInitiatorWires = feeder.bramInitiatorWires; + +endmodule \ No newline at end of file Index: trunk/lib/bsv/RegisterMapper/src/RegisterMapper.bsv =================================================================== --- trunk/lib/bsv/RegisterMapper/src/RegisterMapper.bsv (nonexistent) +++ trunk/lib/bsv/RegisterMapper/src/RegisterMapper.bsv (revision 2) @@ -0,0 +1,88 @@ +/* +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 GetPut::*; +import List::*; +import Vector::*; +import FIFO::*; + + +import Register::*; + +/******* + * + * This file serves as an adapter between a register interface and another + * communication interface, perhaps a bus. We should probably put bus conversion + * shims in here, and maybe use something split phase - that is aligned with get-put + * + *******/ + + +interface RegisterMapper#(type response, type request); + method Action registerRequest(request req); + method ActionValue#(response) registerResponse(); +endinterface + +typedef enum { + Read = 0, + Write = 1 +} MapperCommand deriving (Bits,Eq); + +typedef struct { + MapperCommand command; + Bit#(TLog#(mapSize)) location; + payloadType payload; +} MapperRequest#(numeric type mapSize, type payloadType) deriving (Bits,Eq); + + +module mkRegisterMapper#(function (MapperRequest#(registerMapSize,registerType)) mapperRequestExtract(request req), + function response responseExtract(registerType resp), + Vector#(registerMapSize,Reg#(registerType)) registers) (RegisterMapper#(response, request)) + provisos (Bits#(registerType, xxx)); + + FIFO#(registerType) respFIFO <- mkFIFO; + + method Action registerRequest(request req); + + MapperRequest#(registerMapSize,registerType) mapReq = mapperRequestExtract(req); + //$display("register request called, Regs number: %d, Reg touched: %d payload: %h", valueof(registerMapSize), mapReq.location, mapReq.payload); + if(mapReq.command == Read) + begin + respFIFO.enq(registers[mapReq.location]); + end + else + begin + registers[mapReq.location] <= mapReq.payload; + end + endmethod + + method ActionValue#(response) registerResponse(); + respFIFO.deq; + return responseExtract(respFIFO.first); + endmethod + +endmodule \ No newline at end of file Index: trunk/lib/bsv/SPI/test/SPITester.bsv =================================================================== --- trunk/lib/bsv/SPI/test/SPITester.bsv (nonexistent) +++ trunk/lib/bsv/SPI/test/SPITester.bsv (revision 2) @@ -0,0 +1,83 @@ +import Vector::*; +import Clocks::*; +import FIFO::*; +import ClientServer::*; +import GetPut::*; + +import SPIMaster::*; +import SPISlave::*; +import RegisterMapper::*; + + +module mkSPITester (); + Clock clock <- exposeCurrentClock; + Reset reset <- exposeCurrentReset; + + SPIMaster#(4,Bit#(8)) spiMaster <- mkSPIMaster(8); + Reset slowReset <- mkAsyncReset(0,reset,spiMaster.wires.clock); + + Vector#(4,SPISlave#(Bit#(8))) spiSlaves <- replicateM(mkSPISlaveWriteOnly(clock, reset, clocked_by spiMaster.wires.clock, reset_by slowReset)); + + Reg#(Bool) first <- mkReg(True); + Reg#(Bit#(16)) count <- mkReg(0); + FIFO#(Bit#(16)) fifo <- mkFIFO; + Reg#(Bit#(3)) waitCount <- mkReg(~0); + + rule tickWait(waitCount != 0); + waitCount <= waitCount - 1; + endrule + + rule driveBus; + $display("Driving bus"); + Bit#(4) slaveEnables = spiMaster.wires.slaveEnables; + Bit#(1) masterOut = spiMaster.wires.outputLine; + for(Integer i = 0; i < 4; i = i + 1) + begin + spiSlaves[i].wires.inputLine(masterOut); + spiSlaves[i].wires.slaveEnable(slaveEnables[i]); + end + endrule + + for(Integer i = 0; i < 4; i = i + 1) + begin + rule checkResult (fifo.first[9:8] == fromInteger(i)) ; + let slaveIndex = fifo.first[9:8]; + let slaveData = fifo.first[7:0]; + + fifo.deq; + let masterResp <- spiMaster.server.response.get; + let slaveResp <- spiSlaves[i].client.request.get; + if(slaveResp.data != slaveData) + begin + $display("Expected: %h, Got: %h", slaveData, slaveResp.data); + $finish; + end + else + begin + $display("Result checks."); + end + endrule + end + + rule produceReq (waitCount == 0); + $display("Sending Value %b to %d", count[7:0], count[9:8]); + count <= count + 16'h6345; + if(count == 9) + begin + $display("PASS"); + $finish; + end + if(!first) + begin + fifo.enq(count); + end + else + begin + first <= False; + end + spiMaster.server.request.put(SPIMasterRequest{data: count[7:0], slave: count[9:8]}); + endrule + + + +endmodule \ No newline at end of file Index: trunk/lib/bsv/SPI/src/SPISlave.bsv =================================================================== --- trunk/lib/bsv/SPI/src/SPISlave.bsv (nonexistent) +++ trunk/lib/bsv/SPI/src/SPISlave.bsv (revision 2) @@ -0,0 +1,107 @@ +import FIFO::*; +import ClientServer::*; +import GetPut::*; +import Clocks::*; + +import RegisterMapper::*; +import FIFOUtility::*; +import Debug::*; + +Bool spiSlaveDebug = True; + + +typedef struct { + data_t data; + MapperCommand command; +} SPISlaveRequest#(type data_t) deriving (Bits,Eq); + +interface SPISlaveWires; + (* always_ready, always_enabled, prefix="", result="spi_slave_enable" *) + method Action slaveEnable(Bit#(1) enable); + (* always_ready, always_enabled, result="spi_slave_output_line" *) + method Bit#(1) outputLine(); + (* always_ready, always_enabled, result="spi_slave_input_line" *) + method Action inputLine(Bit#(1) dataIn); +endinterface + +interface SPISlave#(type data); + interface Client#(SPISlaveRequest#(data),data) client; + interface SPISlaveWires wires; +endinterface + + +typedef enum { + Data, + Cleanup +} SPIState deriving (Bits,Eq); + +module mkSPISlaveWriteOnly#(Clock fastClock, Reset fastReset) (SPISlave#(data_t)) + provisos (Bits#(data_t,data_sz), + Add#(1, TLog#(data_sz), TAdd#(1, TLog#(data_sz))) + ); + + FIFO#(SPISlaveRequest#(data_t)) outfifo <- mkFIFO(clocked_by fastClock, reset_by fastReset); + SyncFIFOIfc#(Bit#(1)) enablefifo <- mkSyncFIFOFromCC(valueof(data_sz),fastClock); + SyncFIFOIfc#(Bit#(1)) datafifo <- mkSyncFIFOFromCC(valueof(data_sz),fastClock); + + Reg#(Bit#(TLog#(data_sz))) dataCount <- mkRegA(0,clocked_by fastClock, reset_by fastReset); + Reg#(SPIState) state <- mkRegA(Data,clocked_by fastClock, reset_by fastReset); + Reg#(Bit#(data_sz)) data <- mkRegU(clocked_by fastClock, reset_by fastReset); + + + + // treat the top bit of ticks per transfer as the serial clock + // We do a state transition on serial clock 1->0 to ensure signal stability in the slave. + + + + // this will reset us in the case that the enable is cranked up + rule resetState(enablefifo.first == 1); + enablefifo.deq; + datafifo.deq; + debug(spiSlaveDebug,$display("SPI reset")); + dataCount <= 0; + endrule + + + rule dataAddr(enablefifo.first == 0); + debug(spiSlaveDebug,$display("Slaving firing data count: %d, receiving: %h", dataCount, datafifo.first)); + enablefifo.deq; + datafifo.deq; + Bit#(TAdd#(1,TLog#(data_sz))) dataPlus = zeroExtend(dataCount) + 1; + // check for impending 1->0 transition + if(dataPlus == fromInteger(valueof(data_sz))) + begin + dataCount <= 0; + let dataFinal = data; + dataFinal[dataCount] = datafifo.first; + outfifo.enq(SPISlaveRequest{data:unpack(dataFinal), command:Write}); + end + else + begin + dataCount <= truncate(dataPlus); + end + data[dataCount] <= datafifo.first; + endrule + + + interface Client client; + interface Get request = fifoToGet(outfifo); + interface Put response = ?; + endinterface + + interface SPISlaveWires wires; + + method Action slaveEnable(Bit#(1) enable); + enablefifo.enq(enable); + endmethod + + method outputLine = ?; + + method Action inputLine(Bit#(1) dataIn); + datafifo.enq(dataIn); + endmethod +endinterface + +endmodule + Index: trunk/lib/bsv/SPI/src/SPIMaster.bsv =================================================================== --- trunk/lib/bsv/SPI/src/SPIMaster.bsv (nonexistent) +++ trunk/lib/bsv/SPI/src/SPIMaster.bsv (revision 2) @@ -0,0 +1,166 @@ +import FIFO::*; +import ClientServer::*; +import GetPut::*; +import Clocks::*; + +import RegisterMapper::*; +import FIFOUtility::*; +import Debug::*; + +Bool spiMasterDebug = False; + + + +/* This module implements the SPI bus, a simple protocol. */ +typedef struct { + Bit#(TLog#(slaves)) slave; + data_t data; +} SPIMasterRequest#( numeric type slaves, + type data_t) deriving (Bits,Eq); + +interface SPIMasterWires#(numeric type slaves); + (* always_ready, always_enabled, prefix="", result="spi_slave_enable" *) + method Bit#(slaves) slaveEnables(); + (* always_ready, always_enabled, result="spi_output_line" *) + method Bit#(1) outputLine(); + (* always_ready, always_enabled, result="spi_input_line" *) + method Action inputLine(Bit#(1) dataIn); + interface Clock clock; +endinterface + +interface SPIMaster#(numeric type slaves, type data); + interface Server#(SPIMasterRequest#(slaves,data),data) server; + interface SPIMasterWires#(slaves) wires; +endinterface + + typedef enum { + Idle, + ClockWait, + Data, + Cleanup + } SPIState deriving (Bits,Eq); + + +//Need to chop + +module mkSPIMaster#(Integer divisor) (SPIMaster#(slaves,data_t)) + provisos (Bits#(data_t,data_sz), + Add#(1, TLog#(data_sz), TAdd#(1, TLog#(data_sz))) + ); + + Clock clock <- exposeCurrentClock; + Reset reset <- exposeCurrentReset; + + if(divisor < 2) + begin + error("divisor must be at least 2"); + end + + ClockDividerIfc spiClock <- mkClockDivider(divisor); + ClockDividerIfc toggleClock <- mkClockDivider(divisor/2); + + Reset toggleReset <- mkAsyncReset(1,reset,toggleClock.slowClock); // is this right? + Reset spiReset <- mkAsyncReset(1,reset,spiClock.slowClock); // is this right? + + // This could be disasterous, if we up clock during the high edge of the gated clock. toggle reg should prevent this + GatedClockIfc gatedSlowClock <- mkGatedClock(False,spiClock.slowClock, clocked_by toggleClock.slowClock, reset_by toggleReset); + + SyncFIFOIfc#(SPIMasterRequest#(slaves, data_t)) infifo <- mkSyncFIFOToSlow(2,toggleClock,toggleReset); + SyncFIFOIfc#(data_t) outfifo <- mkSyncFIFOToFast(2,toggleClock,toggleReset); + + Reg#(Bit#(TLog#(data_sz))) dataCount <- mkRegA(0,clocked_by toggleClock.slowClock, + reset_by toggleReset); + Reg#(SPIState) state <- mkRegA(Idle, clocked_by toggleClock.slowClock, + reset_by toggleReset); + + Reg#(Bit#(data_sz)) data <- mkRegU(clocked_by toggleClock.slowClock, + reset_by toggleReset); + + // toggle may not be quite right. + Reg#(Bool) toggle <- mkReg(False, clocked_by toggleClock.slowClock, reset_by toggleReset); // this reg makes sure the we are in-phase with the low edge of spiClock + + + Reg#(Bit#(slaves)) enableReg <- mkReg(~0, clocked_by toggleClock.slowClock, reset_by toggleReset); + ReadOnly#(Bit#(slaves)) enableCrossing <- mkNullCrossingWire(spiClock.slowClock,enableReg._read, clocked_by toggleClock.slowClock, reset_by toggleReset); + + Reg#(Bit#(1)) outputReg <- mkReg(~0, clocked_by toggleClock.slowClock, reset_by toggleReset); + ReadOnly#(Bit#(1)) outputCrossing <- mkNullCrossingWire(spiClock.slowClock, outputReg._read, clocked_by toggleClock.slowClock, reset_by toggleReset); + +//XXX fix me +// Reg#(Bit#(1)) inputReg <- mkReg(0,clocked_by spiClock.slowClock, reset_by spiReset); +// ReadOnly#(Bit#(1)) outputCrossing <- mkNullCrossingWire(spiClock.slowClock, inputReg.read, clocked_by spiClock.slowClock, reset_by spiReset); + + Bit#(TAdd#(1,TLog#(data_sz))) dataPlus = zeroExtend(dataCount) + 1; + + // treat the top bit of ticks per transfer as the serial clock + // We do a state transition on serial clock 1->0 to ensure signal stability in the slave. + + rule toggleTick; + toggle <= !toggle; + endrule + + rule setup(state == Idle && infifo.notEmpty && toggle); + debug(spiMasterDebug,$display("SPIMaster Setup called data: %b slave: %d",infifo.first.data ,infifo.first.slave )); + gatedSlowClock.setGateCond(True); + state <= Data; + enableReg <= ~(1<<(infifo.first.slave)); + debug(spiMasterDebug,$display("SPIMaster sending setupWait: %h", pack(infifo.first.data)[dataCount])); + outputReg <= (pack(infifo.first.data)[dataCount]); + endrule + + + rule cleanup(state == Cleanup && toggle); + outfifo.enq(unpack(data)); + state <= Idle; + enableReg <= ~0; + endrule + + + rule handleData(state == Data && toggle); + debug(spiMasterDebug,$display("SPIMaster Data called")); + if(dataPlus == fromInteger(valueof(data_sz))) + begin + debug(spiMasterDebug,$display("SPIMaster transfer done")); + dataCount <= 0; + infifo.deq; + state <= Cleanup; + gatedSlowClock.setGateCond(False); // may be too early + end + else + begin + dataCount <= truncate(dataPlus); + end + + + Bit#(TLog#(data_sz)) dataIndex = truncate(dataPlus); + outputReg <= pack(infifo.first.data)[dataIndex]; + debug(spiMasterDebug,$display("SPIMaster sending: %h", pack(infifo.first.data)[dataIndex])); + // data[dataCount] <= fromMaybe(0,inputWire.wget); + endrule + + interface Server server; + interface Put request = syncFifoToPut(infifo); + interface Get response = syncFifoToGet(outfifo); + endinterface + +interface SPIMasterWires wires; + //method slaveEnables = enableCrossing._read; + //method outputLine = outputCrossing._read; + + method Bit#(slaves) slaveEnables(); + return enableCrossing._read; + endmethod + + method Bit#(1) outputLine(); + return outputCrossing._read; + endmethod + + method Action inputLine(Bit#(1) dataIn); +// inputWire.wset(dataIn); + endmethod + + interface clock = gatedSlowClock.new_clk; +endinterface + +endmodule + Index: trunk/lib/bsv/BRAMFeeder/src/BRAMFeeder.bsv =================================================================== --- trunk/lib/bsv/BRAMFeeder/src/BRAMFeeder.bsv (nonexistent) +++ trunk/lib/bsv/BRAMFeeder/src/BRAMFeeder.bsv (revision 2) @@ -0,0 +1,224 @@ +/* +Copyright (c) 2007 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: Michael Pellauer, Nirav Dave +*/ + +import BRAM::*; +import BRAMInitiatorWires::*; +import GetPut::*; +import FIFO::*; +import FIFOF::*; +import Debug::*; + +import BRAMInitiator::*; + +//A message to the PPC +typedef Bit#(32) PPCMessage; + + +typedef enum{ + FI_Initialize, + FI_InIdle, + FI_InStartCheckRead, + FI_InStartRead, + FI_InStartTake, + FI_OutStartCheckWrite, + FI_OutStartWrite, + FI_OutStartPush, + FI_CheckLoadStore, + FI_Load, + FI_LoadTake, + FI_Store, + FI_StorePush, + FI_command +} FeederState deriving(Eq,Bits); + + +interface Feeder; + + interface Put#(PPCMessage) ppcMessageInput; + interface Get#(PPCMessage) ppcMessageOutput; + interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires; + +endinterface + +Bool feederDebug = False; + +(* synthesize *) +module mkBRAMFeeder(Feeder); + + // Data is held in 2 addr blocks. as + // Addr n : 1---------22222 <- 1 valid bit (otherwise all zero) + // 2 top bits of payload + // n+1 : 333333333333333 <- 3 rest of payload + + //State + + BRAMInitiator#(Bit#(14)) bramInit <- mkBRAMInitiator; + let bram = bramInit.bram; + + //BRAM#(Bit#(16), Bit#(32)) bram <- mkBRAM_Full(); + + FIFOF#(PPCMessage) ppcMesgQ <- mkFIFOF(); + FIFOF#(PPCMessage) ppcInstQ <- mkFIFOF(); + + let minReadPtr = 0; + let maxReadPtr = 31; + let minWritePtr = 32; + let maxWritePtr = 63; + + let ready = True; + + let debugF = debug(feederDebug); + + Reg#(Bit#(14)) readPtr <- mkReg(minReadPtr); + + Reg#(Bit#(14)) writePtr <- mkReg(minWritePtr); + + Reg#(FeederState) state <- mkReg(FI_InStartCheckRead); + + Reg#(Bit#(32)) partialRead <- mkReg(0); + + Reg#(Bit#(30)) heartbeat <- mkReg(0); + + //Every so often send a message to the PPC indicating we're still alive + + rule beat (True); + + let newheart = heartbeat + 1; + + heartbeat <= newheart; + + if (newheart == 0) + ppcMesgQ.enq(0); + + endrule + + /////////////////////////////////////////////////////////// + //Initialize + /////////////////////////////////////////////////////////// + + //Reg#(Maybe#(Bit#(14))) initReg <- mkReg(Just(0)); + + //Bool ready = !isJust(initReg); + + //rule initBRAM(initReg matches tagged Just .i); + // $display("Init"); + // bram.write(i, 0); + // initReg <= (i == maxWritePtr) ? Nothing : Just (i + 1); + //endrule + + /////////////////////////////////////////////////////////// + // In goes to FPGA, Out goes back to PPC + /////////////////////////////////////////////////////////// + + let state_tryread = (ppcInstQ.notFull ? FI_InStartCheckRead: FI_InIdle); + let state_trywrite = (ppcMesgQ.notEmpty) ? FI_OutStartCheckWrite : FI_InIdle; + + rule inStartIdle(ready && state == FI_InIdle); + if(state_tryread == FI_InIdle) + begin + state <= state_trywrite; + end + else + begin + state <= state_tryread; + end + endrule + + + rule inStartCheckRead(ready && state == FI_InStartCheckRead); + debugF($display("BRAM: StartCheckRead")); + bram.read_req(readPtr); + state <= FI_InStartRead; + endrule + + rule inStartRead(ready && state == FI_InStartRead); + + let v <- bram.read_resp(); + Bool valid = (v[31] == 1); + state <= (valid) ? FI_InStartTake : state_trywrite; + + debugF($display("BRAM: StartRead %h", v)); + if (valid) + begin + //$display("BRAM: read fstinst [%d] = %h",readPtr, v); + partialRead <= v; + bram.read_req(readPtr+1); // + end + endrule + + rule inStartTake(ready && state == FI_InStartTake); + debugF($display("BRAM: StartTake")); + let val <- bram.read_resp(); + + Bit#(63) pack_i = truncate({partialRead,val}); + + PPCMessage i = unpack(truncate(pack_i));//truncate({partialRead,val})); + + ppcInstQ.enq(i); +// $display("BRAM: read sndinst [%d] = %h",readPtr+1, val); +// $display("BRAM: got PPCMessage %h",pack_i); +// $display("Getting Inst: %h %h => %h",partialRead, val, {partialRead,val}); + bram.write(readPtr, 0); + readPtr <= (readPtr + 2 > maxReadPtr) ? minReadPtr : (readPtr + 2); + state <= state_trywrite; + endrule + + rule inStartCheckWrite(ready && state == FI_OutStartCheckWrite); + debugF($display("BRAM: StartCheckWrite")); + bram.read_req(writePtr); + state <= FI_OutStartWrite; + endrule + + rule inStartWrite(ready && state == FI_OutStartWrite); + debugF($display("BRAM: StartWrite")); + let v <- bram.read_resp(); + Bool valid = (v[31] == 0); + state <= (valid) ? FI_OutStartPush : state_tryread; + if (valid) begin + $display("BRAM: write [%d] = %h",writePtr+1, ppcMesgQ.first); + bram.write(writePtr+1, ppcMesgQ.first()); + ppcMesgQ.deq(); + end + endrule + + rule inStartPush(ready && state == FI_OutStartPush); + debugF($display("BRAM: StartPush")); + $display("BRAM: write [%d] = %h",writePtr, 32'hFFFFFFFF); + bram.write(writePtr, 32'hFFFFFFFF);//all 1s + writePtr <= (writePtr + 2 > maxWritePtr) ? minWritePtr : (writePtr + 2); + state <= state_tryread; + endrule + + //Interface + + interface ppcMessageInput = fifoToPut(fifofToFifo(ppcMesgQ)); + interface ppcMessageOutput = fifoToGet(fifofToFifo(ppcInstQ)); + + interface bramInitiatorWires = bramInit.bramInitiatorWires; + +endmodule + Index: trunk/lib/bsv/BRAMFeeder/src/BRAMInitiatorWires.bsv =================================================================== --- trunk/lib/bsv/BRAMFeeder/src/BRAMInitiatorWires.bsv (nonexistent) +++ trunk/lib/bsv/BRAMFeeder/src/BRAMInitiatorWires.bsv (revision 2) @@ -0,0 +1,50 @@ +/* +Copyright (c) 2007 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 +*/ + +interface BRAMInitiatorWires#(type idx_type); + (* always_ready, always_enabled, prefix="" *) + method Bit#(1) bramCLK(); + + (* always_ready, always_enabled, prefix="" *) + method Bit#(1) bramRST(); + + (* always_ready, always_enabled, prefix="" *) + method idx_type bramAddr(); + + (* always_ready, always_enabled, prefix="" *) + method Bit#(32) bramDout(); + + (* always_ready, always_enabled, prefix="" *) + method Action bramDin(Bit#(32) din); + + (* always_ready, always_enabled, prefix="" *) + method Bit#(4) bramWEN(); + + (* always_ready, always_enabled, prefix="" *) + method Bit#(1) bramEN(); + +endinterface Index: trunk/lib/bsv/BRAMFeeder/src/BRAMInitiator.v =================================================================== --- trunk/lib/bsv/BRAMFeeder/src/BRAMInitiator.v (nonexistent) +++ trunk/lib/bsv/BRAMFeeder/src/BRAMInitiator.v (revision 2) @@ -0,0 +1,119 @@ +/* +Copyright (c) 2007 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 +*/ + +module BRAMInitiator(CLK, RST_N, + RD_ADDR, RD_RDY, RD_EN, + DOUT, DOUT_RDY, DOUT_EN, + WR_ADDR, WR_VAL, WR_EN, + BRAM_Addr, BRAM_Dout, BRAM_Din,BRAM_Dummy_Enable, + BRAM_WEN, BRAM_EN, BRAM_RST, + BRAM_CLK); + + // synopsys template + parameter addr_width = 1; + + input CLK; + input RST_N; + + // Read Port + // req + input [addr_width -1 : 0] RD_ADDR; + input RD_EN; + output RD_RDY; + // resp + output [31 : 0] DOUT; + output DOUT_RDY; + input DOUT_EN; + + // Write Port + // req + input [addr_width - 1 : 0] WR_ADDR; + input [31 : 0] WR_VAL; + input WR_EN; + + // BRAM Wires + output [addr_width - 1 : 0] BRAM_Addr; + output [31 : 0] BRAM_Dout; + input [31 : 0] BRAM_Din; + input BRAM_Dummy_Enable; + output [3 : 0] BRAM_WEN; + output BRAM_EN; + output BRAM_RST; + output BRAM_CLK; + + + // Assignments + assign BRAM_CLK = CLK; + assign BRAM_EN = RST_N; // disable the BRAM if we are in reset + assign BRAM_RST = 1'b0; // Never reset the BRAM. + assign BRAM_Addr = (WR_EN)?(WR_ADDR):(RD_ADDR); + assign BRAM_WEN = {WR_EN,WR_EN,WR_EN,WR_EN}; + assign BRAM_Dout = WR_VAL; + + reg RD_REQ_MADE; + + reg [1:0] CTR; + + /*always@(BRAM_Din) + $display("BRAMInitiator.v BRAM_Din: %x",BRAM_Din); + */ + + FIFO2#(.width(32)) q(.RST_N(RST_N), + .CLK(CLK), + .D_IN(BRAM_Din), + .ENQ(RD_REQ_MADE), + .DEQ(DOUT_EN), + .CLR(1'b0), + .D_OUT(DOUT), + .FULL_N(), + .EMPTY_N(DOUT_RDY)); + + assign RD_RDY = (CTR > 0); + + always@(posedge CLK) + begin + if (!RST_N) + begin + CTR <= 2; + end + else + begin + /*if(RD_EN) + $display("BRAMInitiator: RD_EN"); + if(WR_EN) + $display("BRAMInitiator: WR_EN"); + */ + + RD_REQ_MADE <= RD_EN; + + CTR <= (RD_EN) ? + (DOUT_EN) ? CTR : CTR - 1 : + (DOUT_EN) ? CTR + 1 : CTR; + end + end // always@ (posedge CLK) + +endmodule \ No newline at end of file Index: trunk/lib/bsv/BRAMFeeder/src/BRAMInitiator.bsv =================================================================== --- trunk/lib/bsv/BRAMFeeder/src/BRAMInitiator.bsv (nonexistent) +++ trunk/lib/bsv/BRAMFeeder/src/BRAMInitiator.bsv (revision 2) @@ -0,0 +1,116 @@ +/* +Copyright (c) 2007 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 BRAMInitiatorWires::*; +import BRAM::*; + +interface BRAMInitiator#(type idx_type); + interface BRAM#(idx_type, Bit#(32)) bram; + interface BRAMInitiatorWires#(idx_type) bramInitiatorWires; +endinterface + +interface BRAMInitiatorFlat#(type idx_type); + method ActionValue#(Bit#(32)) read_resp(); + method Action read_req(idx_type idx); + method Action write(idx_type idx, Bit#(32) value); + method Bit#(1) bramCLK(); + method Bit#(1) bramRST(); + method idx_type bramAddr(); + method Bit#(32) bramDout(); + method Action bramDin(Bit#(32) value); + method Bit#(4) bramWEN(); + method Bit#(1) bramEN(); +endinterface + + +module mkBRAMInitiator (BRAMInitiator#(idx_type)) + provisos + (Bits#(idx_type, idx), + Literal#(idx_type)); + BRAMInitiatorFlat#(idx_type) bramFlat <- mkBRAMInitiatorFlat(); + + interface BRAM bram; + method write = bramFlat.write; + method read_req = bramFlat.read_req; + method read_resp = bramFlat.read_resp; + endinterface + + interface BRAMInitiatorWires bramInitiatorWires; + method bramCLK = bramFlat.bramCLK; + method bramRST = bramFlat.bramRST; + method bramAddr = bramFlat.bramAddr; + method bramDout = bramFlat.bramDout; + method bramDin = bramFlat.bramDin; + method bramWEN = bramFlat.bramWEN; + method bramEN = bramFlat.bramEN; + endinterface + +endmodule + + + +import "BVI" BRAMInitiator = module mkBRAMInitiatorFlat + //interface: + (BRAMInitiatorFlat#(idx_type)) + provisos + (Bits#(idx_type, idx), + Literal#(idx_type)); + + default_clock clk(CLK); + + parameter addr_width = valueof(idx); + + method DOUT read_resp() ready(DOUT_RDY) enable(DOUT_EN); + + method read_req(RD_ADDR) ready(RD_RDY) enable(RD_EN); + method write(WR_ADDR, WR_VAL) enable(WR_EN); + + method BRAM_CLK bramCLK(); + method BRAM_RST bramRST(); + method BRAM_Addr bramAddr(); + method BRAM_Dout bramDout(); + method bramDin(BRAM_Din) enable(BRAM_Dummy_Enable); + method BRAM_WEN bramWEN(); + method BRAM_EN bramEN(); + + schedule read_req CF (read_resp, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule read_resp CF (read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule write CF (read_req, read_resp, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + // All the BRAM methods are CF + schedule bramCLK CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule bramRST CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule bramAddr CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule bramDout CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule bramDin CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule bramWEN CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + schedule bramEN CF (read_resp, read_req, write, bramCLK, bramRST, bramAddr, bramDout, bramDin, bramWEN, bramEN); + + schedule read_req C read_req; + schedule read_resp C read_resp; + schedule write C write; + +endmodule \ No newline at end of file Index: trunk/lib/bsv/Stats/Min/src/Min.bsv =================================================================== --- trunk/lib/bsv/Stats/Min/src/Min.bsv (nonexistent) +++ trunk/lib/bsv/Stats/Min/src/Min.bsv (revision 2) @@ -0,0 +1,23 @@ +import Register::*; + +interface Min#(type data_t); + interface ReadOnly#(data_t) min; + method Action inputSample(data_t sample); +endinterface + +module mkMin (Min#(data_t)) + provisos (Bits#(data_t,data_sz), + Ord#(data_t), + Bounded#(data_t)); + + Reg#(data_t) result <- mkReg(maxBound); + + interface min = readOnly(result._read); + + method Action inputSample(data_t sample); + if(sample < result) + begin + result <= sample; + end + endmethod +endmodule \ No newline at end of file Index: trunk/lib/bsv/Stats/Max/src/Max.bsv =================================================================== --- trunk/lib/bsv/Stats/Max/src/Max.bsv (nonexistent) +++ trunk/lib/bsv/Stats/Max/src/Max.bsv (revision 2) @@ -0,0 +1,23 @@ +interface Max#(type data_t); + interface ReadOnly#(data_t) max; + method Action inputSample(data_t sample); +endinterface + +module mkMax (Max#(data_t)) + provisos (Bits#(data_t,data_sz), + Ord#(data_t), + Bounded#(data_t)); + + Reg#(data_t) result <- mkReg(minBound); + + interface ReadOnly max; + method _read = result._read; + endinterface + + method Action inputSample(data_t sample); + if(sample > result) + begin + result <= sample; + end + endmethod +endmodule \ No newline at end of file Index: trunk/lib/bsv/Stats/Averager/test/AveragerTest.bsv =================================================================== --- trunk/lib/bsv/Stats/Averager/test/AveragerTest.bsv (nonexistent) +++ trunk/lib/bsv/Stats/Averager/test/AveragerTest.bsv (revision 2) @@ -0,0 +1,42 @@ +import Averager::*; + + +module mkAveragerTest (); + + Averager#(Bit#(32)) average2048 <- mkAverager(2048); + Averager#(Bit#(32)) average64 <- mkAverager(64); + + Reg#(Bit#(6)) count64 <- mkReg(0); + Reg#(Bit#(11)) count2048 <- mkReg(0); + Reg#(Bit#(12)) countDown <- mkReg(~0); + Reg#(Bit#(16)) countDownFinal <- mkReg(~0); + + rule putInput; + if(countDown != 0) + begin + countDown <= countDown - 1; + end + count64 <= count64 + 1; + count2048 <= count2048 + 1; + average64.inputSample(zeroExtend(count64)); + average2048.inputSample(zeroExtend(count2048)); + endrule + + rule check(countDown == 0); + if((average64.average != 32'h1f) || + (average2048.average != 32'h3ff)) + begin + $display("FAIL: %h %h", average64.average, average2048.average); + $finish; + end + else if(countDownFinal == 0) + begin + $display("PASS"); + $finish; + end + + countDownFinal <= countDownFinal - 1; + endrule + +endmodule + Index: trunk/lib/bsv/Stats/Averager/src/Averager.bsv =================================================================== --- trunk/lib/bsv/Stats/Averager/src/Averager.bsv (nonexistent) +++ trunk/lib/bsv/Stats/Averager/src/Averager.bsv (revision 2) @@ -0,0 +1,33 @@ +import Register::*; + +interface Averager#(type data_t); + interface ReadOnly#(data_t) average; + method Action inputSample(data_t sample); +endinterface + +module mkAverager#(Integer samplesPerAverage) (Averager#(Bit#(data_sz))); + + let counter <- mkReg(0); + Reg#(Bit#(data_sz)) result <- mkReg(0); + Reg#(Bit#(data_sz)) sum <- mkReg(0); + + if(exp(2,log2(samplesPerAverage)) != samplesPerAverage) + begin + error("Averager must average power of two samples"); + end + + interface average = readOnly(result._read); + method Action inputSample(Bit#(data_sz) sample); + if(counter + 1 == fromInteger(samplesPerAverage)) + begin + result <= (sum + sample) >> fromInteger(log2(samplesPerAverage)); + sum <= 0; + counter <= 0; + end + else + begin + counter <= counter + 1; + sum <= sum + sample; + end + endmethod +endmodule \ No newline at end of file Index: trunk/lib/bsv/bscClib/CReg/CReg.bsv =================================================================== --- trunk/lib/bsv/bscClib/CReg/CReg.bsv (nonexistent) +++ trunk/lib/bsv/bscClib/CReg/CReg.bsv (revision 2) @@ -0,0 +1,35 @@ + +import "BDPI" function Action writeValue(Bit#(64) pointer, Bit#(32) value); +import "BDPI" function ActionValue#(Bit#(64)) resetInit(Bit#(32) value, String str); +import "BDPI" function Bit#(32) readValue(Bit#(64) pointer); + + +module mkCReg#(dataType initialValue, String str) (Reg#(dataType)) + provisos(Bits#(dataType, dataTypeSize), + Add#(dataTypeSize,x,32)); + Reg#(Bool) initialized <- mkReg(False); + Reg#(Bit#(64)) pointer <- mkReg(0); // 0 will def segfault + Reg#(Bool) hackReg <- mkReg(False); + + /* assume a negative reset, lalala + * the first time this function gets called, we'll + * set up a pointer. */ + rule resetRule(!initialized); + //let str <- $swriteAV("%m"); + let ptr <- resetInit(zeroExtend(pack(initialValue)), str); + pointer <= ptr; + initialized <= True; + hackReg <= True; + endrule + + method Action _write(dataType x1) if(initialized); + writeValue(pointer, zeroExtend(pack(x1))); + hackReg <= True; + endmethod + + method dataType _read() if(initialized && hackReg); + dataType retvalue = unpack(truncate(readValue(pointer))); + return retvalue; + endmethod + +endmodule \ No newline at end of file Index: trunk/lib/bsv/bscClib/CReg/CRegBaseTester.bsv =================================================================== --- trunk/lib/bsv/bscClib/CReg/CRegBaseTester.bsv (nonexistent) +++ trunk/lib/bsv/bscClib/CReg/CRegBaseTester.bsv (revision 2) @@ -0,0 +1,54 @@ +import CReg::*; + + +module mkCRegBaseTester (); + + Reg#(int) counter <- mkReg(0); + Reg#(int) validRegA <- mkReg(10); + Reg#(Bit#(5)) validRegB <- mkReg(2); + Reg#(int) testRegA <- mkCReg(10,"testRegA"); + Reg#(Bit#(5)) testRegB <- mkCReg(2,"testRegB"); + + rule count; + counter <= counter + 1; + if(counter == 100000000) + begin + $display("PASS"); + $finish; + end + endrule + + rule checkA; + if(testRegA != validRegA) + begin + $display("Reg A mismatch %d : %h vs. %h", counter, testRegA, validRegA); + $finish; + end + endrule + + rule checkB; + if(testRegB != validRegB) + begin + $display("Reg B mismatch %d : %h vs. %h", counter, testRegB, validRegB); + $finish; + end + endrule + + rule upValidA(counter % 3 == 0); + validRegA <= validRegA + counter; + endrule + + rule upTestA(counter % 3 == 0); + testRegA <= testRegA + counter; + endrule + + rule upValidB(counter % 2 == 0); + validRegB <= validRegB + truncate(pack(counter)); + endrule + + rule upTestB(counter % 2 == 0); + testRegB <= testRegB + truncate(pack(counter)); + endrule + + +endmodule \ No newline at end of file Index: trunk/lib/bsv/bscClib/CRegFile/CRegFile.bsv =================================================================== --- trunk/lib/bsv/bscClib/CRegFile/CRegFile.bsv (nonexistent) +++ trunk/lib/bsv/bscClib/CRegFile/CRegFile.bsv (revision 2) @@ -0,0 +1,39 @@ +import RegFile::*; + +import "BDPI" function Action writeValueCRegFileFull(Bit#(64) pointer, Bit#(32) index, Bit#(32) value); +import "BDPI" function ActionValue#(Bit#(64)) resetInitCRegFileFull(Bit#(32) size, String str); +import "BDPI" function Bit#(32) readValueCRegFileFull(Bit#(64) pointer, Bit#(32) index); + + +module mkCRegFileFull#(String str) (RegFile#(addrType,dataType)) + provisos(Bits#(dataType, dataTypeSize), + Add#(dataTypeSize,x,32), + Bits#(addrType, addrTypeSize), + Add#(addrTypeSize,y,32)); + + Reg#(Bool) initialized <- mkReg(False); + Reg#(Bit#(64)) pointer <- mkReg(0); // 0 will def segfault + Reg#(Bool) hackReg <- mkReg(False); + + /* assume a negative reset, lalala + * the first time this function gets called, we'll + * set up a pointer. */ + rule resetRule(!initialized); + //let str <- $swriteAV("%m"); + let ptr <- resetInitCRegFileFull(1<= 100); + let val = ram.read[0].read(counter - 100); + $display("readReq: %0d %0d %0d", counter-100, val, $time); + endrule +endmodule + +module mkBramTest(); + MultiReadMemoryServer#(2, 8, Bit#(32)) ram <- mkMultiReadBram(23); + Reg#(Bit#(8)) counter <- mkReg(0); + + rule count(True); + counter <= counter + 1; + if(counter == maxBound) + $finish(0); + endrule + + rule write(True); + ram.write(counter, zeroExtend(counter)); + $display("write: %0d %0d %0d", counter, counter, $time); + endrule + + rule readReq(counter >= 100); + ram.req[0].read(counter - 100); + $display("readReq: %0d %0d", counter-100, $time); + endrule + + rule readResp(counter >= 200); + Bit#(32) val <- ram.resp[0].read(); + $display("readResp: %0d %0d", val, $time); + endrule +endmodule Index: trunk/lib/bsv/Memory/RegFile.v =================================================================== --- trunk/lib/bsv/Memory/RegFile.v (nonexistent) +++ trunk/lib/bsv/Memory/RegFile.v (revision 2) @@ -0,0 +1,46 @@ +module RegFile +( + CLK, + RST_N, + CLK_GATE, + readReady, + readAddr, + readData, + writeReady, + writeEnable, + writeAddr, + writeData, + writeEmptyReady, + writeEmpty +); + parameter dataSize = 32; + parameter addrSize = 5; + parameter numRows = 32; + parameter resetVal = 0; + + input CLK, RST_N, CLK_GATE; + output readReady; + input [addrSize-1:0] readAddr; + output [dataSize-1:0] readData; + output writeReady; + input writeEnable; + input [addrSize-1:0] writeAddr; + input [dataSize-1:0] writeData; + output writeEmptyReady; + output writeEmpty; + + reg [dataSize-1:0] ram [numRows-1:0]; + + assign readReady = 1; + assign writeReady = 1; + assign writeEmptyReady = 1; + assign writeEmpty = 1; + + always@(posedge CLK) + begin + if(writeEnable) + ram[writeAddr] <= writeData; + end + + assign readData = ram[readAddr]; +endmodule Index: trunk/lib/bsv/Memory/Bram.v =================================================================== --- trunk/lib/bsv/Memory/Bram.v (nonexistent) +++ trunk/lib/bsv/Memory/Bram.v (revision 2) @@ -0,0 +1,81 @@ +module Bram +( + CLK, + RST_N, + CLK_GATE, + readEnable, + readAddr, + readReady, + readReqEmpty, + readReqEmptyReady, + readData, + readDataEnable, + readDataReady, + readRespEmpty, + readRespEmptyReady, + writeEnable, + writeAddr, + writeData, + writeReady, + writeEmpty, + writeEmptyReady +); + parameter dataSize = 32; + parameter addrSize = 9; + parameter numRows = 512; + parameter resetVal = 0; + + input CLK, RST_N, CLK_GATE; + input readEnable; + input [addrSize-1:0] readAddr; + output readReady; + output readReqEmpty; + output readReqEmptyReady; + output [dataSize-1:0] readData; + input readDataEnable; + output readDataReady; + output readRespEmpty; + output readRespEmptyReady; + input writeEnable; + input [addrSize-1:0] writeAddr; + input [dataSize-1:0] writeData; + output writeReady; + output writeEmpty; + output writeEmptyReady; + + reg [dataSize-1:0] readData; + + reg [dataSize-1:0] ram [numRows-1:0]; + + assign readReady = 1; + assign readDataReady = 1; + assign writeReady = 1; + + assign readReqEmpty = 1; + assign readReqEmptyReady = 1; + assign readRespEmpty = 1; + assign readRespEmptyReady = 1; + assign writeEmpty = 1; + assign writeEmptyReady = 1; + + always@(posedge CLK) + begin + if(!RST_N) + begin: reset + // synthesis translate_off + integer i; + for(i = 0; i < numRows; i=i+1) + ram[i] <= resetVal; + // synthesis translate_on + readData <= resetVal; + end + else + readData <= ram[readAddr]; + end + + always@(posedge CLK) + begin + if(writeEnable) + ram[writeAddr] <= writeData; + end +endmodule Index: trunk/lib/bsv/CBusUtils/CBusUtils.bsv =================================================================== --- trunk/lib/bsv/CBusUtils/CBusUtils.bsv (nonexistent) +++ trunk/lib/bsv/CBusUtils/CBusUtils.bsv (revision 2) @@ -0,0 +1,375 @@ +import Register::*; +import Vector::*; +import GetPut::*; +import CBus::*; +import StmtFSM::*; +import Debug::*; + +/* eventually we should refactor the CBUS get/put in terms of the wide +register r/w, since these are effectively the data payloads. We can probably also merge +r/w to form one cohesive */ + +Bool cBusDebug = False; + +/* + + This module is a CBUS mapped Put interface. + It behaves as if there is buffer space. If the user does not + check that the interface is ready, data may be dropped on the floor. + The base address is a for control information. + Subsequent addresses map the data bits in the bluespec manner. + + Read Map: + Bit 0: busy/full + + Writing a one to a bit results in activating the method. + Hardware will not check this stuff, for now. + Write Map: + Bit 0: put + +*/ + +module mkIWithCBusWideRegR#(Integer baseAddress, ReadOnly#(data_reg) register) (IWithCBus#(CBus#(size_bus_addr, size_bus_data), Empty)) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_reg,data_reg_size), + Add#(xxx, 1, size_bus_data), + Div#(data_reg_size, size_bus_data, reg_vec_size), + Add#(data_reg_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + + // need a vector of registers + Vector#(reg_vec_size,Reg#(Bit#(size_bus_data))) regVector = explodeRegister(readOnlyToRegister(register)); + + + interface CBus cbus_ifc; + method Action write(Bit#(size_bus_addr) addr, Bit#(size_bus_data) data); + noAction; + endmethod + + // for no apparent reason they or things together.. This seems like a really bad idea.. + method ActionValue#(Bit#(size_bus_data)) read(Bit#(size_bus_addr) addr); + Bit#(size_bus_data) result = 0; + + for(Integer i = 0; i < valueof(TDiv#(data_reg_size,size_bus_data)); i = i+1) + begin + if(addr == fromInteger(baseAddress + i)) + begin + result = regVector[i]; + end + end + debug(cBusDebug,$display("CBus Wide Reg Read: addr: %h data %h", addr, result)); + return result; + endmethod + endinterface + + interface Empty device_ifc = ?; +endmodule + +module [ModWithCBus#(size_bus_addr,size_bus_data)] mkCBusWideRegR#(Integer baseAddress, ReadOnly#(data_reg) register) (Empty) + provisos( + Bits#(data_reg,data_reg_size), + Add#(xxx, 1, size_bus_data), + Div#(data_reg_size, size_bus_data, reg_vec_size), + Add#(data_reg_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + + Empty returnIFC <- collectCBusIFC(mkIWithCBusWideRegR(baseAddress, register)); + return returnIFC; +endmodule + + +module mkIWithCBusPut#(Integer baseAddress, Put#(data_put) put) (IWithCBus#(CBus#(size_bus_addr, size_bus_data), Empty)) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_put,data_put_size), + Add#(xxx, 1, size_bus_data), + Div#(data_put_size, size_bus_data, reg_vec_size), + Add#(data_put_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + + // need a vector of registers + Reg#(Bool) attemptPut <- mkReg(False); + Reg#(data_put) dataContainer <- mkRegU(); + Vector#(reg_vec_size,Reg#(Bit#(size_bus_data))) regVector = explodeRegister(dataContainer); + + rule attemptGetRule(attemptPut); + debug(cBusDebug,$display("CBus Put Dumping Data: %x", dataContainer)); + put.put(dataContainer); + attemptPut <= False; + endrule + + + interface CBus cbus_ifc; + method Action write(Bit#(size_bus_addr) addr, Bit#(size_bus_data) data); + debug(cBusDebug,$display("CBus[%h] Put Write: addr: %h data: %h", baseAddress,addr, data)); + if(addr == fromInteger(baseAddress)) + begin + debug(cBusDebug,$display("CBus Put Activating attempt put")); + attemptPut <= (data[0] == 1); + end + else + begin + for(Integer i = 0; i < valueof(TDiv#(data_put_size,size_bus_data)); i = i+1) + begin + if(addr == fromInteger(baseAddress + 1 + i)) + begin + regVector[i] <= data; + end + end + end + endmethod + + + // for no apparent reason they or things together.. This seems like a really bad idea.. + method ActionValue#(Bit#(size_bus_data)) read(Bit#(size_bus_addr) addr); + Bit#(size_bus_data) result = 0; + + if(addr == fromInteger(baseAddress)) + begin + result = {fromInteger(baseAddress),((attemptPut)?1'b1:1'b0)}; + end + else + begin + for(Integer i = 0; i < valueof(TDiv#(data_put_size,size_bus_data)); i = i+1) + begin + if(addr == fromInteger(baseAddress + 1 + i)) + begin + result = regVector[i]; + end + end + end + debug(cBusDebug,$display("CBus Put Read: addr: %h data %h", addr, result)); + return result; + endmethod + endinterface + + interface Empty device_ifc = ?; +endmodule + +module [ModWithCBus#(size_bus_addr,size_bus_data)] mkCBusPut#(Integer baseAddress, Put#(data_put) put) (Empty) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_put,data_put_size), + Add#(xxx, 1, size_bus_data), + Div#(data_put_size, size_bus_data, reg_vec_size), + Add#(data_put_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + + Empty returnIFC <- collectCBusIFC(mkIWithCBusPut(baseAddress, put)); + return returnIFC; +endmodule + + + +/* + This module is a CBUS mapped Put interface. + It behaves as if there is buffer space. If the user does not + check that the interface is ready, data may be dropped on the floor. + The base address is a for control information. + Subsequent addresses map the data bits in the bluespec manner. + + Read Map: + Bit 0: busy/full + + Writing a one to a bit results in activating the method. + Hardware will not check this stuff, for now. + Write Map: + Bit 0: put + +*/ + +module mkIWithCBusGet#(Integer baseAddress, Get#(data_get) get) (IWithCBus#(CBus#(size_bus_addr, size_bus_data), Empty)) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_get,data_get_size), + Add#(xxx, 1, size_bus_data), + Div#(data_get_size, size_bus_data, reg_vec_size), + Add#(data_get_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + + // need a vector of registers + Reg#(Bool) attemptGet <- mkReg(False); + Reg#(data_get) dataContainer <- mkRegU(); + Vector#(reg_vec_size,Reg#(Bit#(size_bus_data))) regVector = explodeRegister(dataContainer); + + rule attemptGetRule(attemptGet); + let data <- get.get; + debug(cBusDebug,$display("CBus[%h] Get invoking get: data %h", baseAddress, data)); + dataContainer <= data; + attemptGet <= False; + endrule + + + interface CBus cbus_ifc; + method Action write(Bit#(size_bus_addr) addr, Bit#(size_bus_data) data); + if(addr == fromInteger(baseAddress)) + begin + debug(cBusDebug,$display("CBus[%h] enable get", baseAddress)); + attemptGet <= (data[0] == 1); + end + endmethod + + + // for no apparent reason they or things together.. This seems like a really bad idea.. + method ActionValue#(Bit#(size_bus_data)) read(Bit#(size_bus_addr) addr); + Bit#(size_bus_data) result = 0; + if(addr == fromInteger(baseAddress)) + begin + result = {fromInteger(baseAddress),((attemptGet)?1'b1:1'b0)}; + end + else + begin + for(Integer i = 0; i < valueof(TDiv#(data_get_size,size_bus_data)); i = i+1) + begin + if(addr == fromInteger(baseAddress + 1 + i)) + begin + result = regVector[i]; + end + end + end + debug(cBusDebug,$display("CBus[%h] Get Read: addr: %h data %h", baseAddress, addr, result)); + return result; + endmethod + endinterface + + interface Empty device_ifc = ?; + + +endmodule + +module [ModWithCBus#(size_bus_addr,size_bus_data)] mkCBusGet#(Integer baseAddress, Get#(data_get) get) (Empty) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_get,data_get_size), + Add#(xxx, 1, size_bus_data), + Div#(data_get_size, size_bus_data, reg_vec_size), + Add#(data_get_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + + Empty returnIFC <- collectCBusIFC(mkIWithCBusGet(baseAddress, get)); + return returnIFC; +endmodule + +typedef enum { + Read, + Write +} CBusCommand deriving (Bits,Eq); + +module mkMarshalCBusPut#(Integer baseAddr, Integer wordOffset, function Action putBusRequest(CBusCommand isWrite, Bit#(size_bus_addr) addr, Bit#(size_bus_data) data), function ActionValue#(Bit#(size_bus_data)) getBusResponse()) (Put#(data_t)) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_t,data_t_size), + Div#(data_t_size, size_bus_data, reg_vec_size), + Add#(data_t_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + Reg#(data_t) dataContainer <- mkRegU; + Reg#(Bit#(size_bus_addr)) transmitCount <- mkReg(0); + Reg#(Bool) putReady <- mkReg(False); + Vector#(reg_vec_size,Reg#(Bit#(size_bus_data))) regVector = explodeRegister(dataContainer); + + Stmt s = seq + debug(cBusDebug,$display("CBusPut[%h] Marshall begins: data: %h", baseAddr, dataContainer)); + while(!putReady) + seq + action + putBusRequest(CBusUtils::Read,fromInteger(baseAddr), ?); + debug(cBusDebug,$display("CBusPut[%h] Marshall sends putReady req: data:%h", baseAddr, dataContainer)); + endaction + action + Bit#(size_bus_data) data <- getBusResponse; + debug(cBusDebug,$display("CBusPut[%h] Marshall receives putReady: %h data:%h", baseAddr, data, dataContainer)); + putReady <= data[0] == 0; + endaction + endseq + for(transmitCount <= 0; transmitCount < fromInteger(valueof(reg_vec_size)); transmitCount <= transmitCount + 1) + seq + putBusRequest(CBusUtils::Write,fromInteger(baseAddr+wordOffset)+fromInteger(wordOffset)*transmitCount,regVector[transmitCount]); + endseq + putBusRequest(CBusUtils::Write,fromInteger(baseAddr),1); + putReady <= False; + debug(cBusDebug,$display("CBusPut[%h] Marshall completes data: %h", baseAddr, dataContainer)); + endseq; + + FSM fsm <- mkFSM(s); + + method Action put(data_t data) if(fsm.done); + debug(cBusDebug,$display("CBusPut[%h] Marshall receives data: %h", baseAddr, data)); + dataContainer <= data; + fsm.start; + endmethod +endmodule + + + + + + + + + + +// For better or worse this does a straight pull get, rather than requiring the external module to make a request +// We assume module will address words. Thus we have a word conversion factor. +module mkMarshalCBusGet#(Integer baseAddr, Integer wordOffset, function Action putBusRequest(CBusCommand isWrite, Bit#(size_bus_addr) addr, Bit#(size_bus_data) data), function ActionValue#(Bit#(size_bus_data)) getBusResponse()) (Get#(data_t)) + provisos( + //Add#(1, k, bus_data_t_size) + Bits#(data_t,data_t_size), + Div#(data_t_size, size_bus_data, reg_vec_size), + Add#(data_t_size, extra_bits, TMul#(reg_vec_size, size_bus_data)), + Add#(not_sure_of_this, size_bus_data, TMul#(reg_vec_size, size_bus_data))); + Reg#(data_t) dataContainer <- mkRegU; + Reg#(Bit#(size_bus_addr)) transmitCount <- mkReg(0); + Reg#(Bool) getReady <- mkReg(False); + Reg#(Bool) hasData <- mkReg(False); + Vector#(reg_vec_size,Reg#(Bit#(size_bus_data))) regVector = explodeRegister(dataContainer); + + + + Stmt s = seq + debug(cBusDebug,$display("Cbus SIZEINFO AddrBase: %h, data_sz: %d", baseAddr, valueof(data_t_size))); + while(!getReady) + seq + putBusRequest(CBusUtils::Read,fromInteger(baseAddr), ?); + action + Bit#(size_bus_data) data <- getBusResponse; + getReady <= data[0] == 0; + endaction + endseq + // Execute the get and then pull out the data + putBusRequest(CBusUtils::Write,fromInteger(baseAddr),1); + // Now we need to wait for this to go away before attempting to read. + getReady <= False; + while(!getReady) + seq + putBusRequest(CBusUtils::Read,fromInteger(baseAddr), ?); + action + Bit#(size_bus_data) data <- getBusResponse; + getReady <= data[0] == 0; // Wait for the 1 to get cleared... + endaction + endseq + debug(cBusDebug,$display("CBus Get Marshal sees available data")); + for(transmitCount <= 0; transmitCount < fromInteger(valueof(reg_vec_size)); transmitCount <= transmitCount + 1) + seq + putBusRequest(CBusUtils::Read,fromInteger(baseAddr+wordOffset)+fromInteger(wordOffset)*transmitCount,?); + action + Bit#(size_bus_data) data <- getBusResponse; + regVector[transmitCount] <= data; + endaction + endseq + hasData <= True; + getReady <= False; + endseq; + + FSM fsm <- mkFSM(s); + + rule kickoffMachine(!hasData && fsm.done); + fsm.start; + endrule + + method ActionValue#(data_t) get() if(hasData); + debug(cBusDebug,$display("CBusGet Marshall returns data")); + hasData <= False; + return dataContainer; + endmethod +endmodule \ No newline at end of file Index: trunk/C_implementation/gwt.c =================================================================== --- trunk/C_implementation/gwt.c (nonexistent) +++ trunk/C_implementation/gwt.c (revision 2) @@ -0,0 +1,138 @@ +/* gwt.c +** Ronald L. Rivest +** 5/14/08 +** Routines to work with differential properties of g +*/ + +#include + +#include +typedef uint64_t md6_word; +#define w 64 + +/* Useful macros: min and max */ +#define min(a,b) ((a)<(b)? (a) : (b)) +#define max(a,b) ((a)>(b)? (a) : (b)) + +md6_word g(md6_word x,int r,int ell) +{ + x = x ^ (x >> r); + x = x ^ (x << ell); + return x; +} + +md6_word ginv(md6_word x, int r,int ell) +{ + int i; + md6_word y,z,xx,yy; + y = 0; + xx = x; + for (i=0;xx!=0;i++) + { y = y ^ xx; + xx = xx << ell; + } + z = 0; + yy = y; + for (i=0;yy!=0;i++) + { z = z ^ yy; + yy = yy >> r; + } + return z; +} + +int wt(md6_word x) +{ + int i,c=0; + for (i=0;i>i) ) ; + return c; +} + +// standard shift table, for MD6 as of 6/1/08 +int Ar[16] = { 28,18,1,15,12, 5,6,22,23,10,3,13,32,10,11,4 }; +int Aell[16] = { 14,15,3,13,29,20,3, 7,15,24,9, 8, 4,19, 6,5}; + +int test1() +// print out difference tables for possibly useful r,ell pairs +{ int i,r,ell; + md6_word x; + int wt_table_g[w+1]; + int wt_table_ginv[w+1]; + if (w>16){ printf("w=%d too large!",w); return 1; } + for (r=1;r=w) continue; + + // compute difference table for g + for (i=0;i<=w;i++) wt_table_g[i] = 2*w; + for (x=0;;x++) + { + int in_wt = wt(x); + int out_wt = wt(g(x,r,ell)); + wt_table_g[in_wt] = min(wt_table_g[in_wt],out_wt); + if (x==(md6_word)(-1)) break; + } + + // compute difference table for ginv + for (i=0;i<=w;i++) wt_table_ginv[i] = 2*w; + for (x=0;;x++) + { + int in_wt = wt(x); + int out_wt = wt(ginv(x,r,ell)); + wt_table_ginv[in_wt] = min(wt_table_ginv[in_wt],out_wt); + if (x==(md6_word)(-1)) break; + } + + // print results + if (wt_table_ginv[1]>2) + { printf("r=%2d,ell=%2d ",r,ell); + for (i=0;i<=w;i++) printf("%2d ",wt_table_g[i]); + printf("\n"); + printf("r=%2d,ell=%2d ",r,ell); + for (i=0;i<=w;i++) printf("%2d ",wt_table_ginv[i]); + printf("\n\n"); + } + } + return 0; +} + +int test2() +{ + int r,ell; + md6_word x; + int gamma[w][w]; // gamma[r][ell] is min weight of ginv(x,r,ell) for + // weight-one inputs x + + printf("Table of weights of min-weight ginv outputs for ginv inputs of weight 1 (i.e. of gamma(r,ell))\n"); + printf(" ell="); + for (ell=1;ell0;x=x<<1) + gamma[r][ell] = min(gamma[r][ell],wt(ginv(x,r,ell))); + printf("%2d ",gamma[r][ell]); + if (gamma[r][ell]==2 && + ( (r != 2*ell) && + (r != ell) && + (ell != 2*r) && + (2*r+ell<=w) ) ) + printf("\nConjecture wrong! r=%d ell=%d",r,ell); + } + printf("\n"); + } + return 0; + +} + +int main() +{ + // return test1(); + return test2(); +} Index: trunk/C_implementation/md6_compress.c =================================================================== --- trunk/C_implementation/md6_compress.c (nonexistent) +++ trunk/C_implementation/md6_compress.c (revision 2) @@ -0,0 +1,444 @@ +/* File: md6_compress.c +** Author: Ronald L. Rivest +** (with optimizations by Jayant Krishnamurthy) +** Address: Room 32G-692 Stata Center +** 32 Vassar Street +** Cambridge, MA 02139 +** Email: rivest@mit.edu +** Date: 9/25/2008 +** +** (The following license is known as "The MIT License") +** +** Copyright (c) 2008 Ronald L. Rivest and Jayant Krishnamurthy +** +** 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. +** +** (end of license) +** +** This is part of the definition of the MD6 hash function. +** The files defining the md6 hash function are: +** md6.h +** md6_compress.c +** md6_mode.c +** +** The files defining the interface between MD6 and the NIST SHA-3 +** API are: +** md6_nist.h +** md6_nist.c +** The NIST SHA-3 API is defined in: +** http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf +** +** See http://groups.csail.mit.edu/cis/md6 for more information. +** +*/ + + #include +#include +#include + +#include "md6.h" + +/* Useful macros: min and max */ +#ifndef min +#define min(a,b) ((a)<(b)? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a)>(b)? (a) : (b)) +#endif + +/* Variables defining lengths of various values */ +#define w md6_w /* # bits in a word (64) */ +#define n md6_n /* # words in compression input (89) */ +#define c md6_c /* # words in compression output (16) */ +#define b md6_b /* # message words per compression input block (64) */ +#define v md6_v /* # words in control word (1) */ +#define u md6_u /* # words in unique nodeID (1) */ +#define k md6_k /* # key words per compression input block (8) */ +#define q md6_q /* # Q words per compression input block (15) */ + + + /* "Tap positions" for feedback shift-register */ + +#if (n==89) +#define t0 17 /* index for linear feedback */ +#define t1 18 /* index for first input to first and */ +#define t2 21 /* index for second input to first and */ +#define t3 31 /* index for first input to second and */ +#define t4 67 /* index for second input to second and */ +#define t5 89 /* last tap */ +#endif + + /* Loop-unrolling setup. +** +** Define macros for loop-unrolling within compression function +** These expand to: loop_body(right-shift,left-shift,step) +** These are given for word sizes 64, 32, 16, and 8, although +** only w=64 is needed for the standard MD6 definition. +** +** Also given for each word size are the constants S0 and Smask +** needed in the recurrence for round constants. +*/ + +#if (w==64) /* for standard word size */ +#define RL00 loop_body(10,11, 0) +#define RL01 loop_body( 5,24, 1) +#define RL02 loop_body(13, 9, 2) +#define RL03 loop_body(10,16, 3) +#define RL04 loop_body(11,15, 4) +#define RL05 loop_body(12, 9, 5) +#define RL06 loop_body( 2,27, 6) +#define RL07 loop_body( 7,15, 7) +#define RL08 loop_body(14, 6, 8) +#define RL09 loop_body(15, 2, 9) +#define RL10 loop_body( 7,29,10) +#define RL11 loop_body(13, 8,11) +#define RL12 loop_body(11,15,12) +#define RL13 loop_body( 7, 5,13) +#define RL14 loop_body( 6,31,14) +#define RL15 loop_body(12, 9,15) + +const md6_word S0 = (md6_word)0x0123456789abcdefULL; +const md6_word Smask = (md6_word)0x7311c2812425cfa0ULL; + +#elif (w==32) /* for variant word size */ +#define RL00 loop_body( 5, 4, 0) +#define RL01 loop_body( 3, 7, 1) +#define RL02 loop_body( 6, 7, 2) +#define RL03 loop_body( 5, 9, 3) +#define RL04 loop_body( 4,13, 4) +#define RL05 loop_body( 6, 8, 5) +#define RL06 loop_body( 7, 4, 6) +#define RL07 loop_body( 3,14, 7) +#define RL08 loop_body( 5, 7, 8) +#define RL09 loop_body( 6, 4, 9) +#define RL10 loop_body( 5, 8,10) +#define RL11 loop_body( 5,11,11) +#define RL12 loop_body( 4, 5,12) +#define RL13 loop_body( 6, 8,13) +#define RL14 loop_body( 7, 2,14) +#define RL15 loop_body( 5,11,15) + +const md6_word S0 = (md6_word)0x01234567UL; +const md6_word Smask = (md6_word)0x7311c281UL; + + /* Loop-unrolling setup (continued). +** +*/ + +#elif (w==16) /* for variant word size */ + +#define RL00 loop_body( 5, 6, 0) +#define RL01 loop_body( 4, 7, 1) +#define RL02 loop_body( 3, 2, 2) +#define RL03 loop_body( 5, 4, 3) +#define RL04 loop_body( 7, 2, 4) +#define RL05 loop_body( 5, 6, 5) +#define RL06 loop_body( 5, 3, 6) +#define RL07 loop_body( 2, 7, 7) +#define RL08 loop_body( 4, 5, 8) +#define RL09 loop_body( 3, 7, 9) +#define RL10 loop_body( 4, 6,10) +#define RL11 loop_body( 3, 5,11) +#define RL12 loop_body( 4, 5,12) +#define RL13 loop_body( 7, 6,13) +#define RL14 loop_body( 7, 4,14) +#define RL15 loop_body( 2, 3,15) + +const md6_word S0 = (md6_word)0x01234; +const md6_word Smask = (md6_word)0x7311; + +#elif (w==8) /* for variant word size */ + +#define RL00 loop_body( 3, 2, 0) +#define RL01 loop_body( 3, 4, 1) +#define RL02 loop_body( 3, 2, 2) +#define RL03 loop_body( 4, 3, 3) +#define RL04 loop_body( 3, 2, 4) +#define RL05 loop_body( 3, 2, 5) +#define RL06 loop_body( 3, 2, 6) +#define RL07 loop_body( 3, 4, 7) +#define RL08 loop_body( 2, 3, 8) +#define RL09 loop_body( 2, 3, 9) +#define RL10 loop_body( 3, 2,10) +#define RL11 loop_body( 2, 3,11) +#define RL12 loop_body( 2, 3,12) +#define RL13 loop_body( 3, 4,13) +#define RL14 loop_body( 2, 3,14) +#define RL15 loop_body( 3, 4,15) + +const md6_word S0 = (md6_word)0x01; +const md6_word Smask = (md6_word)0x73; + +#endif + + /* Main compression loop. +** +*/ + +void md6_main_compression_loop( md6_word* A , int r ) +/* +** Perform the md6 "main compression loop" on the array A. +** This is where most of the computation occurs; it is the "heart" +** of the md6 compression algorithm. +** Input: +** A input array of length t+n already set up +** with input in the first n words. +** r number of rounds to run (178); each is c steps +** Modifies: +** A A[n..r*c+n-1] filled in. +*/ +{ md6_word x, S; + int i,j; + + /* + ** main computation loop for md6 compression + */ + S = S0; + for (j = 0, i = n; j> rs); /* right-shift */ \ + A[i+step] = x ^ (x << ls); /* left-shift */ +/* ***************************************************************** */ + + /* + ** Unroll loop c=16 times. (One "round" of computation.) + ** Shift amounts are embedded in macros RLnn. + */ + RL00 RL01 RL02 RL03 RL04 RL05 RL06 RL07 + RL08 RL09 RL10 RL11 RL12 RL13 RL14 RL15 + + /* Advance round constant S to the next round constant. */ + S = (S << 1) ^ (S >> (w-1)) ^ (S & Smask); + i += 16; + } +} + + /* ``Bare'' compression routine. +** +** Compresses n-word input to c-word output. +*/ + +int md6_compress( md6_word *C, + md6_word *N, + int r, + md6_word *A + ) +/* Assumes n-word input array N has been fully set up. +** Input: +** N input array of n w-bit words (n=89) +** A working array of a = rc+n w-bit words +** A is OPTIONAL, may be given as NULL +** (then md6_compress allocates and uses its own A). +** r number of rounds +** Modifies: +** C output array of c w-bit words (c=16) +** Returns one of the following: +** MD6_SUCCESS (0) +** MD6_NULL_N +** MD6_NULL_C +** MD6_BAD_r +** MD6_OUT_OF_MEMORY +*/ +{ md6_word* A_as_given = A; + + /* check that input is sensible */ + if ( N == NULL) return MD6_NULL_N; + if ( C == NULL) return MD6_NULL_C; + if ( r<0 || r > md6_max_r) return MD6_BAD_r; + + if ( A == NULL) A = calloc(r*c+n,sizeof(md6_word)); + if ( A == NULL) return MD6_OUT_OF_MEMORY; + + memcpy( A, N, n*sizeof(md6_word) ); /* copy N to front of A */ + + md6_main_compression_loop( A, r ); /* do all the work */ + + memcpy( C, A+(r-1)*c+n, c*sizeof(md6_word) ); /* output into C */ + + if ( A_as_given == NULL ) /* zero and free A if nec. */ + { memset(A,0,(r*c+n)*sizeof(md6_word)); /* contains key info */ + free(A); + } + + return MD6_SUCCESS; +} + + /* Control words. +*/ + +md6_control_word md6_make_control_word( int r, + int L, + int z, + int p, + int keylen, + int d + ) +/* Construct control word V for given inputs. +** Input: +** r = number of rounds +** L = mode parameter (maximum tree height) +** z = 1 iff this is final compression operation +** p = number of pad bits in a block to be compressed +** keylen = number of bytes in key +** d = desired hash output length +** Does not check inputs for validity. +** Returns: +** V = constructed control word +*/ +{ md6_control_word V; + V = ( (((md6_control_word) 0) << 60) | /* reserved, width 4 bits */ + (((md6_control_word) r) << 48) | /* width 12 bits */ + (((md6_control_word) L) << 40) | /* width 8 bits */ + (((md6_control_word) z) << 36) | /* width 4 bits */ + (((md6_control_word) p) << 20) | /* width 16 bits */ + (((md6_control_word) keylen) << 12 ) | /* width 8 bits */ + (((md6_control_word) d)) ); /* width 12 bits */ + return V; +} + + /* Node ID's. +*/ + +md6_nodeID md6_make_nodeID( int ell, /* level number */ + int i /* index (0,1,2,...) within level */ + ) +/* Make "unique nodeID" U based on level ell and position i +** within level; place it at specified destination. +** Inputs: +** dest = address of where nodeID U should be placed +** ell = integer level number, 1 <= ell <= ... +** i = index within level, i = 0, 1, 2,... +** Returns +** U = constructed nodeID +*/ +{ md6_nodeID U; + U = ( (((md6_nodeID) ell) << 56) | + ((md6_nodeID) i) ); + return U; +} + + /* Assembling components of compression input. +*/ + +void md6_pack( md6_word*N, + const md6_word* Q, + md6_word* K, + int ell, int i, + int r, int L, int z, int p, int keylen, int d, + md6_word* B ) +/* Pack data before compression into n-word array N. +*/ +{ int j; + int ni; + md6_nodeID U; + md6_control_word V; + + ni = 0; + + for (j=0;jmd6_max_r) ) return MD6_BAD_r; + if ( (L<0) | (L>255) ) return MD6_BAD_L; + if ( (ell < 0) || (ell > 255) ) return MD6_BAD_ELL; + if ( (p < 0) || (p > b*w ) ) return MD6_BAD_p; + if ( (d <= 0) || (d > c*w/2) ) return MD6_BADHASHLEN; + if ( (K == NULL) ) return MD6_NULL_K; + if ( (Q == NULL) ) return MD6_NULL_Q; + + /* pack components into N for compression */ + md6_pack(N,Q,K,ell,i,r,L,z,p,keylen,d,B); + + /* call compression hook if it is defined. */ + /* -- for testing and debugging. */ + if (compression_hook != NULL) + compression_hook(C,Q,K,ell,i,r,L,z,p,keylen,d,B); + + return md6_compress(C,N,r,A); +} +/* end of md6_compress.c */ Index: trunk/C_implementation/t.exe =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/C_implementation/t.exe =================================================================== --- trunk/C_implementation/t.exe (nonexistent) +++ trunk/C_implementation/t.exe (revision 2)
trunk/C_implementation/t.exe Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/C_implementation/README_64bit.txt =================================================================== --- trunk/C_implementation/README_64bit.txt (nonexistent) +++ trunk/C_implementation/README_64bit.txt (revision 2) @@ -0,0 +1,18 @@ +Filename: README_64bit.txt +Author: Ronald L. Rivest +Date: 8/31/08 + +This directory (Optimized_32bit) contains the required "optimized +64-bit" implementation for our NIST SHA-3 submission, "MD6". + +The files included here are: + md6.h + md6_compress.c + md6_mode.c + md6_nist.h + md6_nist.c + inttypes.h + stdint.h + +These files are identical to those included in the Reference Implementation. + Index: trunk/C_implementation/t.c =================================================================== --- trunk/C_implementation/t.c (nonexistent) +++ trunk/C_implementation/t.c (revision 2) @@ -0,0 +1,613 @@ +/* + ********************************************************************** + ** md5.h -- Header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +/* typedef a 32 bit type */ +typedef unsigned long int UINT4; + +/* Data structure for MD5 (Message Digest) computation */ +typedef struct { + UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init (); +void MD5Update (); +void MD5Final (); + +/* + ********************************************************************** + ** End of md5.h ** + ******************************* (cut) ******************************** + */ + +/* + ********************************************************************** + ** md5.c ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +/* -- include the following line if the md5.h header file is separate -- */ +/* #include "md5.h" */ + +/* forward declaration */ +static void Transform (); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G and H are basic MD5 functions: selection, majority, parity */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +void MD5Init (mdContext) +MD5_CTX *mdContext; +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; +} + +void MD5Update (mdContext, inBuf, inLen) +MD5_CTX *mdContext; +unsigned char *inBuf; +unsigned int inLen; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void MD5Final (mdContext) +MD5_CTX *mdContext; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } +} + +/* Basic MD5 step. Transform buf based on in. + */ +static void Transform (buf, in) +UINT4 *buf; +UINT4 *in; +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, 3614090360); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, 3905402710); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, 606105819); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, 3250441966); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, 4118548399); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, 1200080426); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, 2821735955); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, 4249261313); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, 1770035416); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, 2336552879); /* 10 */ + FF ( c, d, a, b, in[10], S13, 4294925233); /* 11 */ + FF ( b, c, d, a, in[11], S14, 2304563134); /* 12 */ + FF ( a, b, c, d, in[12], S11, 1804603682); /* 13 */ + FF ( d, a, b, c, in[13], S12, 4254626195); /* 14 */ + FF ( c, d, a, b, in[14], S13, 2792965006); /* 15 */ + FF ( b, c, d, a, in[15], S14, 1236535329); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, 4129170786); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, 3225465664); /* 18 */ + GG ( c, d, a, b, in[11], S23, 643717713); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, 3921069994); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, 3593408605); /* 21 */ + GG ( d, a, b, c, in[10], S22, 38016083); /* 22 */ + GG ( c, d, a, b, in[15], S23, 3634488961); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, 3889429448); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, 568446438); /* 25 */ + GG ( d, a, b, c, in[14], S22, 3275163606); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, 4107603335); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, 1163531501); /* 28 */ + GG ( a, b, c, d, in[13], S21, 2850285829); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, 4243563512); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, 1735328473); /* 31 */ + GG ( b, c, d, a, in[12], S24, 2368359562); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, 4294588738); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, 2272392833); /* 34 */ + HH ( c, d, a, b, in[11], S33, 1839030562); /* 35 */ + HH ( b, c, d, a, in[14], S34, 4259657740); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, 2763975236); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, 1272893353); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, 4139469664); /* 39 */ + HH ( b, c, d, a, in[10], S34, 3200236656); /* 40 */ + HH ( a, b, c, d, in[13], S31, 681279174); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, 3936430074); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, 3572445317); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, 76029189); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, 3654602809); /* 45 */ + HH ( d, a, b, c, in[12], S32, 3873151461); /* 46 */ + HH ( c, d, a, b, in[15], S33, 530742520); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, 3299628645); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, 4096336452); /* 49 */ + II ( d, a, b, c, in[ 7], S42, 1126891415); /* 50 */ + II ( c, d, a, b, in[14], S43, 2878612391); /* 51 */ + II ( b, c, d, a, in[ 5], S44, 4237533241); /* 52 */ + II ( a, b, c, d, in[12], S41, 1700485571); /* 53 */ + II ( d, a, b, c, in[ 3], S42, 2399980690); /* 54 */ + II ( c, d, a, b, in[10], S43, 4293915773); /* 55 */ + II ( b, c, d, a, in[ 1], S44, 2240044497); /* 56 */ + II ( a, b, c, d, in[ 8], S41, 1873313359); /* 57 */ + II ( d, a, b, c, in[15], S42, 4264355552); /* 58 */ + II ( c, d, a, b, in[ 6], S43, 2734768916); /* 59 */ + II ( b, c, d, a, in[13], S44, 1309151649); /* 60 */ + II ( a, b, c, d, in[ 4], S41, 4149444226); /* 61 */ + II ( d, a, b, c, in[11], S42, 3174756917); /* 62 */ + II ( c, d, a, b, in[ 2], S43, 718787259); /* 63 */ + II ( b, c, d, a, in[ 9], S44, 3951481745); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + ********************************************************************** + ** End of md5.c ** + ******************************* (cut) ******************************** + */ + +/* + ********************************************************************** + ** md5driver.c -- sample routines to test ** + ** RSA Data Security, Inc. MD5 message digest algorithm. ** + ** Created: 2/16/90 RLR ** + ** Updated: 1/91 SRD ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +#include +#include +#include +#include + +/* -- include the following file if the file md5.h is separate -- */ +/* #include "md5.h" */ + +/* Prints message digest buffer in mdContext as 32 hexadecimal digits. + Order is from low-order byte to high-order byte of digest. + Each byte is printed with high-order hexadecimal digit first. + */ +static void MDPrint (mdContext) +MD5_CTX *mdContext; +{ + int i; + + for (i = 0; i < 16; i++) + printf ("%02x", mdContext->digest[i]); +} + +/* size of test block */ +#define TEST_BLOCK_SIZE 1000 + +/* number of blocks to process */ +#define TEST_BLOCKS 100000 + +/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */ +static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS; + +/* A time trial routine, to measure the speed of MD5. + Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE + characters. + */ +static void MDTimeTrial () +{ + MD5_CTX mdContext; + time_t endTime, startTime; + unsigned char data[TEST_BLOCK_SIZE]; + unsigned int i; + + /* initialize test data */ + for (i = 0; i < TEST_BLOCK_SIZE; i++) + data[i] = (unsigned char)(i & 0xFF); + + /* start timer */ + printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES); + time (&startTime); + + /* digest data in TEST_BLOCK_SIZE byte blocks */ + MD5Init (&mdContext); + for (i = TEST_BLOCKS; i > 0; i--) + MD5Update (&mdContext, data, TEST_BLOCK_SIZE); + MD5Final (&mdContext); + + /* stop timer, get time difference */ + time (&endTime); + MDPrint (&mdContext); + printf (" is digest of test input.\n"); + printf + ("Seconds to process test input: %ld\n", (long)(endTime-startTime)); + printf + ("Characters processed per second: %ld\n", + TEST_BYTES/(endTime-startTime)); +} + +/* Computes the message digest for string inString. + Prints out message digest, a space, the string (in quotes) and a + carriage return. + */ +static void MDString (inString) +char *inString; +{ + MD5_CTX mdContext; + unsigned int len = strlen (inString); + + MD5Init (&mdContext); + MD5Update (&mdContext, inString, len); + MD5Final (&mdContext); + MDPrint (&mdContext); + printf (" \"%s\"\n\n", inString); +} + +/* Computes the message digest for a specified file. + Prints out message digest, a space, the file name, and a carriage + return. + */ +static void MDFile (filename) +char *filename; +{ + FILE *inFile = fopen (filename, "rb"); + MD5_CTX mdContext; + int bytes; + unsigned char data[1024]; + + if (inFile == NULL) { + printf ("%s can't be opened.\n", filename); + return; + } + + MD5Init (&mdContext); + while ((bytes = fread (data, 1, 1024, inFile)) != 0) + MD5Update (&mdContext, data, bytes); + MD5Final (&mdContext); + MDPrint (&mdContext); + printf (" %s\n", filename); + fclose (inFile); +} + +/* Writes the message digest of the data from stdin onto stdout, + followed by a carriage return. + */ +static void MDFilter () +{ + MD5_CTX mdContext; + int bytes; + unsigned char data[16]; + + MD5Init (&mdContext); + while ((bytes = fread (data, 1, 16, stdin)) != 0) + MD5Update (&mdContext, data, bytes); + MD5Final (&mdContext); + MDPrint (&mdContext); + printf ("\n"); +} + +/* Runs a standard suite of test data. + */ +static void MDTestSuite () +{ + printf ("MD5 test suite results:\n\n"); + MDString (""); + MDString ("a"); + MDString ("abc"); + MDString ("message digest"); + MDString ("abcdefghijklmnopqrstuvwxyz"); + MDString + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + MDString + ("1234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890"); + /* Contents of file foo are "abc" */ + MDFile ("foo"); +} + +/* ******************************************************************** */ +/* MD6 stuff here */ +/* ******************************************************************** */ + +#define W 64 /* number of bits in a word */ +#define Db 512 /* number of bits of output */ +#define Dw (Db/W) /* number of words of output */ +#define N 4096 /* number of bits of message input per block */ +#define Nw (N/W) /* number of words of message input per block */ + +#define K 89 /* length of nonlinear feedback shift register */ +#define T (32*89) /* number of computation steps */ + +#define A0 17 /* index for linear feedback */ +#define A1 18 /* index for first input to first and */ +#define A2 21 /* index for second input to first and */ +#define A3 31 /* index for first input to second and */ +#define A4 67 /* index for second input to second and */ + +/* A time trial routine, to measure the speed of MD6. + Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE + characters. + */ + +static void MD6TimeTrial () +{ + time_t endTime, startTime; + long int i,k; + unsigned long long int temp; + unsigned long long int Z[7000]; /* buffer for computation */ + unsigned long long S[7000]; /* stage constants */ + unsigned int R[7000]; /* shift right amounts */ + unsigned int L[7000]; /* shift left amounts */ + + for (i = 0;i 0; k = k - N/(W/8)) + { + for (i = T-1; i>=0; i = i - 1) + { + temp = Z[i+K] ^ Z[i+A0] ^ ( Z[i+A1] & Z[i+A2] ) ^ ( Z[i+A3] & ~Z[i+A4] ) ; + temp = temp ^ S[i]; + temp = temp ^ (temp >> R[i]); + temp = temp ^ (temp << L[i]); + Z[i] = temp; + } + } + /* concentration phase */ + for (i = 78;i>=0;i--) + { long long int Z1, Z2, Z3; + Z1 = Z[i+8]; + Z2 = Z[i+9]; + Z3 = Z[i+10]; + Z[i] = Z[i] ^ (Z1&Z2) ^ ((~Z1)&Z3); + } + + /* stop timer, get time difference */ + time (&endTime); + printf + ("Seconds to process test input: %ld\n", (long)(endTime-startTime)); + printf + ("Characters processed per second: %ld\n", + TEST_BYTES/(endTime-startTime)); +} + +int main (argc, argv) +int argc; +char *argv[]; +{ + int i; + + /* For each command line argument in turn: + ** filename -- prints message digest and name of file + ** -sstring -- prints message digest and contents of string + ** -t -- prints time trial statistics for 1M characters + ** -u -- prints MD6 time trial stats for 1M chars + ** -x -- execute a standard suite of test data + ** (no args) -- writes messages digest of stdin onto stdout + */ + if (argc == 1) + MDFilter (); + else + for (i = 1; i < argc; i++) + if (argv[i][0] == '-' && argv[i][1] == 's') + MDString (argv[i] + 2); + else if (strcmp (argv[i], "-t") == 0) + MDTimeTrial (); + else if (strcmp (argv[i], "-u") == 0) + MD6TimeTrial (); + else if (strcmp (argv[i], "-x") == 0) + MDTestSuite (); + else MDFile (argv[i]); +} + +/* + ********************************************************************** + ** End of md5driver.c ** + ******************************* (cut) ******************************** + */ Index: trunk/C_implementation/ginv.c =================================================================== --- trunk/C_implementation/ginv.c (nonexistent) +++ trunk/C_implementation/ginv.c (revision 2) @@ -0,0 +1,103 @@ +/* ginv.c +** Ronald L. Rivest +** 5/14/08 +** Routines to work with g and ginv +*/ + +#include + +#include +typedef uint64_t md6_word; +#define w 64 + +/* Useful macros: min and max */ +#define min(a,b) ((a)<(b)? (a) : (b)) +#define max(a,b) ((a)>(b)? (a) : (b)) + +md6_word g(md6_word x,int r,int ell) +{ + x = x ^ (x >> r); + x = x ^ (x << ell); + return x; +} + +md6_word ginv(md6_word x, int r,int ell) +{ + int i; + md6_word y,z,xx,yy; + y = 0; + xx = x; + for (i=0;i> r; + } + return z; +} + +int wt(md6_word x) +{ + int i,c=0; + for (i=0;i>i); + return c; +} + +int Ar[16] = { 28,18,1,15,12,5,6,22,23,10,3,13,32,10,11,4 }; +int Aell[16] = { 14,15,3,13,29,20,3,7,15,24,9,8,4,19,6,5}; + +int main() +{ int i,i1,i2,minwt,r,ell,j; + md6_word x,y; + for (j=0;j<16;j++) + { + r = Ar[j]; + ell = Aell[j]; + printf("r=%d ell=%d: g(x,r,ell)=y ginv(y,r,ell)=x\n",r,ell); + + minwt = 64; + for (i=0;i
trunk/C_implementation/2008-02-05-SHA3-C-API.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/C_implementation/secondexample.tex =================================================================== --- trunk/C_implementation/secondexample.tex (nonexistent) +++ trunk/C_implementation/secondexample.tex (revision 2) @@ -0,0 +1,537 @@ +\begin{verbatim} +> md6sum -d224 -r5 -Kabcde12345 -B600 +-d224 +-r5 +-Kabcde12345 +-- Mon Aug 04 21:11:05 2008 +-- d = 224 (digest length in bits) +-- L = 64 (number of parallel passes) +-- r = 5 (number of rounds) +-- K = '321edcba' (key) +-- k = 10 (key length in bytes) + +MD6 compression function computation (level 1, index 0): +Input (89 words): +A[ 0] = 7311c2812425cfa0 Q[0] +A[ 1] = 6432286434aac8e7 Q[1] +A[ 2] = b60450e9ef68b7c1 Q[2] +A[ 3] = e8fb23908d9f06f1 Q[3] +A[ 4] = dd2e76cba691e5bf Q[4] +A[ 5] = 0cd0d63b2c30bc41 Q[5] +A[ 6] = 1f8ccf6823058f8a Q[6] +A[ 7] = 54e5ed5b88e3775d Q[7] +A[ 8] = 4ad12aae0a6d6031 Q[8] +A[ 9] = 3e7f16bb88222e0d Q[9] +A[ 10] = 8af8671d3fb50c2c Q[10] +A[ 11] = 995ad1178bd25c31 Q[11] +A[ 12] = c878c1dd04c4b633 Q[12] +A[ 13] = 3b72066c7a1552ac Q[13] +A[ 14] = 0d6f3522631effcb Q[14] +A[ 15] = 6162636465313233 key K[0] +A[ 16] = 3435000000000000 key K[1] +A[ 17] = 0000000000000000 key K[2] +A[ 18] = 0000000000000000 key K[3] +A[ 19] = 0000000000000000 key K[4] +A[ 20] = 0000000000000000 key K[5] +A[ 21] = 0000000000000000 key K[6] +A[ 22] = 0000000000000000 key K[7] +A[ 23] = 0100000000000000 nodeID U = (ell,i) = (1,0) +A[ 24] = 000540000000a0e0 control word V = (r,L,z,p,keylen,d) = (5,64,0,0,10,224) +A[ 25] = 1122334455667711 data B[ 0] input message word 0 +A[ 26] = 2233445566771122 data B[ 1] input message word 1 +A[ 27] = 3344556677112233 data B[ 2] input message word 2 +A[ 28] = 4455667711223344 data B[ 3] input message word 3 +A[ 29] = 5566771122334455 data B[ 4] input message word 4 +A[ 30] = 6677112233445566 data B[ 5] input message word 5 +A[ 31] = 7711223344556677 data B[ 6] input message word 6 +A[ 32] = 1122334455667711 data B[ 7] input message word 7 +A[ 33] = 2233445566771122 data B[ 8] input message word 8 +A[ 34] = 3344556677112233 data B[ 9] input message word 9 +A[ 35] = 4455667711223344 data B[10] input message word 10 +A[ 36] = 5566771122334455 data B[11] input message word 11 +A[ 37] = 6677112233445566 data B[12] input message word 12 +A[ 38] = 7711223344556677 data B[13] input message word 13 +A[ 39] = 1122334455667711 data B[14] input message word 14 +A[ 40] = 2233445566771122 data B[15] input message word 15 +A[ 41] = 3344556677112233 data B[16] input message word 16 +A[ 42] = 4455667711223344 data B[17] input message word 17 +A[ 43] = 5566771122334455 data B[18] input message word 18 +A[ 44] = 6677112233445566 data B[19] input message word 19 +A[ 45] = 7711223344556677 data B[20] input message word 20 +A[ 46] = 1122334455667711 data B[21] input message word 21 +A[ 47] = 2233445566771122 data B[22] input message word 22 +A[ 48] = 3344556677112233 data B[23] input message word 23 +A[ 49] = 4455667711223344 data B[24] input message word 24 +A[ 50] = 5566771122334455 data B[25] input message word 25 +A[ 51] = 6677112233445566 data B[26] input message word 26 +A[ 52] = 7711223344556677 data B[27] input message word 27 +A[ 53] = 1122334455667711 data B[28] input message word 28 +A[ 54] = 2233445566771122 data B[29] input message word 29 +A[ 55] = 3344556677112233 data B[30] input message word 30 +A[ 56] = 4455667711223344 data B[31] input message word 31 +A[ 57] = 5566771122334455 data B[32] input message word 32 +A[ 58] = 6677112233445566 data B[33] input message word 33 +A[ 59] = 7711223344556677 data B[34] input message word 34 +A[ 60] = 1122334455667711 data B[35] input message word 35 +A[ 61] = 2233445566771122 data B[36] input message word 36 +A[ 62] = 3344556677112233 data B[37] input message word 37 +A[ 63] = 4455667711223344 data B[38] input message word 38 +A[ 64] = 5566771122334455 data B[39] input message word 39 +A[ 65] = 6677112233445566 data B[40] input message word 40 +A[ 66] = 7711223344556677 data B[41] input message word 41 +A[ 67] = 1122334455667711 data B[42] input message word 42 +A[ 68] = 2233445566771122 data B[43] input message word 43 +A[ 69] = 3344556677112233 data B[44] input message word 44 +A[ 70] = 4455667711223344 data B[45] input message word 45 +A[ 71] = 5566771122334455 data B[46] input message word 46 +A[ 72] = 6677112233445566 data B[47] input message word 47 +A[ 73] = 7711223344556677 data B[48] input message word 48 +A[ 74] = 1122334455667711 data B[49] input message word 49 +A[ 75] = 2233445566771122 data B[50] input message word 50 +A[ 76] = 3344556677112233 data B[51] input message word 51 +A[ 77] = 4455667711223344 data B[52] input message word 52 +A[ 78] = 5566771122334455 data B[53] input message word 53 +A[ 79] = 6677112233445566 data B[54] input message word 54 +A[ 80] = 7711223344556677 data B[55] input message word 55 +A[ 81] = 1122334455667711 data B[56] input message word 56 +A[ 82] = 2233445566771122 data B[57] input message word 57 +A[ 83] = 3344556677112233 data B[58] input message word 58 +A[ 84] = 4455667711223344 data B[59] input message word 59 +A[ 85] = 5566771122334455 data B[60] input message word 60 +A[ 86] = 6677112233445566 data B[61] input message word 61 +A[ 87] = 7711223344556677 data B[62] input message word 62 +A[ 88] = 1122334455667711 data B[63] input message word 63 +Intermediate values: +A[ 89] = 023bc36dbadd897c +A[ 90] = d2927a221b06c047 +A[ 91] = c43ba671cd483453 +A[ 92] = 71fff4ac51400ece +A[ 93] = 0982eb1487ed94a0 +A[ 94] = b0db96aa5be6e25d +A[ 95] = c79104d837fa7829 +A[ 96] = 74f191fac63854c7 +A[ 97] = 555836c2482b7073 +A[ 98] = 96d1cfa2960a3635 +A[ 99] = 91f93e1e2305defb +A[ 100] = a0d6fb3db7872b00 +A[ 101] = 09b3e3efa9f46322 +A[ 102] = 4f974344be9283c2 +A[ 103] = af945d6202a52b8a +A[ 104] = 534ae6f0cc48c152 +A[ 105] = 9a1312a7cb95e823 +A[ 106] = 202d5bc69180f643 +A[ 107] = 3314055f3e8bd053 +A[ 108] = d5f43130bf23ceea +A[ 109] = 6626816602008668 +A[ 110] = 76aeea2aca773f6e +A[ 111] = 5e85d8b579246c54 +A[ 112] = 2c15d20ff9b8f8c7 +A[ 113] = b63139c71d240633 +A[ 114] = f34ac4fd12d5ff52 +A[ 115] = e6ddcdd1c15d615e +A[ 116] = 4ff6831138609787 +A[ 117] = 2d3f1ff4b46ae4d6 +A[ 118] = 0db9939d0538d1e5 +A[ 119] = 021d0b12738f57f8 +A[ 120] = 225b9b9043fc1478 +A[ 121] = 2b44b144083caec0 +A[ 122] = ec7dd9746e59215a +A[ 123] = 1b16f1dbf1ee2ca7 +A[ 124] = aff86e674d80dfc2 +A[ 125] = 500e4a1f3414f2e9 +A[ 126] = 7526f159466c0c08 +A[ 127] = 21872b0c3ff8f9e5 +A[ 128] = 9926c4c3dc26a41a +A[ 129] = 1605d8571a384095 +A[ 130] = 36108731ac38dbbe +A[ 131] = 855e83cd250610a9 +A[ 132] = e50d76ec2ffcd792 +A[ 133] = 3c25e0d2a66156b0 +A[ 134] = 5c0a179096bbd764 +A[ 135] = 69fbb852261cf3dd +A[ 136] = 464e53ab124324fd +A[ 137] = b82c23d382fe93b0 +A[ 138] = f0b2c7468873e088 +A[ 139] = 1617ffed131a1888 +A[ 140] = 4c96e83298992d59 +A[ 141] = 4572047f487d2c7f +A[ 142] = 8dd3884af1d1fa71 +A[ 143] = 4e9c5579e3a882cf +A[ 144] = e436a7a0b969237b +A[ 145] = 4c40356771ccc066 +A[ 146] = c39d8cb040a1bf0f +A[ 147] = 6d10e4a2236c9cc8 +A[ 148] = aee19ed455d9c494 +A[ 149] = 9beb541edf2cc926 +A[ 150] = 57cef68e40f3a1fe +A[ 151] = da808363958f463d +A[ 152] = dea095fbc38c581d +Output (16 words of chaining values): +A[ 153] = e86a6f805fb810ca output chaining value C[0] +A[ 154] = 991de071299831a9 output chaining value C[1] +A[ 155] = c59517fb7f5c5e74 output chaining value C[2] +A[ 156] = 0e2b5f69481c68e6 output chaining value C[3] +A[ 157] = 8ddb33a8b069b4c2 output chaining value C[4] +A[ 158] = 558b3513a0046dbd output chaining value C[5] +A[ 159] = e1dfb6726949ab7e output chaining value C[6] +A[ 160] = f48bae515e89ee94 output chaining value C[7] +A[ 161] = d31d1f87d97da302 output chaining value C[8] +A[ 162] = 5d349e9b0d69b270 output chaining value C[9] +A[ 163] = b409d2ee2c3e5577 output chaining value C[10] +A[ 164] = 997621d403cd954e output chaining value C[11] +A[ 165] = 7a353e0ef29490a3 output chaining value C[12] +A[ 166] = 716d1239dfff51dc output chaining value C[13] +A[ 167] = 59744be898cf7c0a output chaining value C[14] +A[ 168] = 07951a90e19da429 output chaining value C[15] + +MD6 compression function computation (level 1, index 1): +Input (89 words): +A[ 0] = 7311c2812425cfa0 Q[0] +A[ 1] = 6432286434aac8e7 Q[1] +A[ 2] = b60450e9ef68b7c1 Q[2] +A[ 3] = e8fb23908d9f06f1 Q[3] +A[ 4] = dd2e76cba691e5bf Q[4] +A[ 5] = 0cd0d63b2c30bc41 Q[5] +A[ 6] = 1f8ccf6823058f8a Q[6] +A[ 7] = 54e5ed5b88e3775d Q[7] +A[ 8] = 4ad12aae0a6d6031 Q[8] +A[ 9] = 3e7f16bb88222e0d Q[9] +A[ 10] = 8af8671d3fb50c2c Q[10] +A[ 11] = 995ad1178bd25c31 Q[11] +A[ 12] = c878c1dd04c4b633 Q[12] +A[ 13] = 3b72066c7a1552ac Q[13] +A[ 14] = 0d6f3522631effcb Q[14] +A[ 15] = 6162636465313233 key K[0] +A[ 16] = 3435000000000000 key K[1] +A[ 17] = 0000000000000000 key K[2] +A[ 18] = 0000000000000000 key K[3] +A[ 19] = 0000000000000000 key K[4] +A[ 20] = 0000000000000000 key K[5] +A[ 21] = 0000000000000000 key K[6] +A[ 22] = 0000000000000000 key K[7] +A[ 23] = 0100000000000001 nodeID U = (ell,i) = (1,1) +A[ 24] = 00054000d400a0e0 control word V = (r,L,z,p,keylen,d) = (5,64,0,3392,10,224) +A[ 25] = 2233445566771122 data B[ 0] input message word 64 +A[ 26] = 3344556677112233 data B[ 1] input message word 65 +A[ 27] = 4455667711223344 data B[ 2] input message word 66 +A[ 28] = 5566771122334455 data B[ 3] input message word 67 +A[ 29] = 6677112233445566 data B[ 4] input message word 68 +A[ 30] = 7711223344556677 data B[ 5] input message word 69 +A[ 31] = 1122334455667711 data B[ 6] input message word 70 +A[ 32] = 2233445566771122 data B[ 7] input message word 71 +A[ 33] = 3344556677112233 data B[ 8] input message word 72 +A[ 34] = 4455667711223344 data B[ 9] input message word 73 +A[ 35] = 5566771122334455 data B[10] input message word 74 +A[ 36] = 0000000000000000 data B[11] padding +A[ 37] = 0000000000000000 data B[12] padding +A[ 38] = 0000000000000000 data B[13] padding +A[ 39] = 0000000000000000 data B[14] padding +A[ 40] = 0000000000000000 data B[15] padding +A[ 41] = 0000000000000000 data B[16] padding +A[ 42] = 0000000000000000 data B[17] padding +A[ 43] = 0000000000000000 data B[18] padding +A[ 44] = 0000000000000000 data B[19] padding +A[ 45] = 0000000000000000 data B[20] padding +A[ 46] = 0000000000000000 data B[21] padding +A[ 47] = 0000000000000000 data B[22] padding +A[ 48] = 0000000000000000 data B[23] padding +A[ 49] = 0000000000000000 data B[24] padding +A[ 50] = 0000000000000000 data B[25] padding +A[ 51] = 0000000000000000 data B[26] padding +A[ 52] = 0000000000000000 data B[27] padding +A[ 53] = 0000000000000000 data B[28] padding +A[ 54] = 0000000000000000 data B[29] padding +A[ 55] = 0000000000000000 data B[30] padding +A[ 56] = 0000000000000000 data B[31] padding +A[ 57] = 0000000000000000 data B[32] padding +A[ 58] = 0000000000000000 data B[33] padding +A[ 59] = 0000000000000000 data B[34] padding +A[ 60] = 0000000000000000 data B[35] padding +A[ 61] = 0000000000000000 data B[36] padding +A[ 62] = 0000000000000000 data B[37] padding +A[ 63] = 0000000000000000 data B[38] padding +A[ 64] = 0000000000000000 data B[39] padding +A[ 65] = 0000000000000000 data B[40] padding +A[ 66] = 0000000000000000 data B[41] padding +A[ 67] = 0000000000000000 data B[42] padding +A[ 68] = 0000000000000000 data B[43] padding +A[ 69] = 0000000000000000 data B[44] padding +A[ 70] = 0000000000000000 data B[45] padding +A[ 71] = 0000000000000000 data B[46] padding +A[ 72] = 0000000000000000 data B[47] padding +A[ 73] = 0000000000000000 data B[48] padding +A[ 74] = 0000000000000000 data B[49] padding +A[ 75] = 0000000000000000 data B[50] padding +A[ 76] = 0000000000000000 data B[51] padding +A[ 77] = 0000000000000000 data B[52] padding +A[ 78] = 0000000000000000 data B[53] padding +A[ 79] = 0000000000000000 data B[54] padding +A[ 80] = 0000000000000000 data B[55] padding +A[ 81] = 0000000000000000 data B[56] padding +A[ 82] = 0000000000000000 data B[57] padding +A[ 83] = 0000000000000000 data B[58] padding +A[ 84] = 0000000000000000 data B[59] padding +A[ 85] = 0000000000000000 data B[60] padding +A[ 86] = 0000000000000000 data B[61] padding +A[ 87] = 0000000000000000 data B[62] padding +A[ 88] = 0000000000000000 data B[63] padding +Intermediate values: +A[ 89] = 027431e67f2b19cf +A[ 90] = 0d990f6680e90d20 +A[ 91] = f27bc123aa282635 +A[ 92] = f90ca91b7fd9c62c +A[ 93] = 85139f55bd354f15 +A[ 94] = eb6b874532011a19 +A[ 95] = 7b04461ba005d2fc +A[ 96] = c7db19c96ca9abc7 +A[ 97] = b723400f04c813c4 +A[ 98] = c22c98f63ef66335 +A[ 99] = 42a2cbb64372fc40 +A[ 100] = e52aeb1d587b9012 +A[ 101] = 9ea7a2d571275633 +A[ 102] = 7e99d0316f65addd +A[ 103] = 72f2b2f2fd1fe6ec +A[ 104] = ee030108c4c8d073 +A[ 105] = cfccf37b34add3eb +A[ 106] = f0155b54e33fa5cc +A[ 107] = b3b80e2309548fa4 +A[ 108] = b5ef06df65e727d7 +A[ 109] = ef08a1b814d205a0 +A[ 110] = 367b2caf36cc81c6 +A[ 111] = 343a0cf5b903d13e +A[ 112] = b4f9c1e7889ee19f +A[ 113] = da463fdb2c80b3cf +A[ 114] = 5e57342f3b497579 +A[ 115] = ec2a9bbbac242772 +A[ 116] = f1ece4e7901b8a58 +A[ 117] = 46a38ec4458509bc +A[ 118] = 9f023b8106000b81 +A[ 119] = bee8b8b568415c9a +A[ 120] = 0941caa98d3a8735 +A[ 121] = 1f0d393d159e88a7 +A[ 122] = fd918160425fe96e +A[ 123] = 7dc1367a2e734e1a +A[ 124] = 7f151f7a5acba9c0 +A[ 125] = 9c97a06aeb6620c2 +A[ 126] = f74ca0e2c4400541 +A[ 127] = b9a8bba23413f53c +A[ 128] = a439ca3d5839a512 +A[ 129] = d2be51693c22f741 +A[ 130] = 94c0657db84579bb +A[ 131] = a0261aaca9731c5f +A[ 132] = 4c9411c30ffbf9fa +A[ 133] = 4dcf01f6386f9b7e +A[ 134] = dbaaf2cbe4f486aa +A[ 135] = 7d5a36c9454ec7e4 +A[ 136] = f8634c771236a7dd +A[ 137] = 78c3c019f44632b1 +A[ 138] = 6cea1a934cc7ea1e +A[ 139] = fcaa77298206c0a0 +A[ 140] = 465b12166eccf1ee +A[ 141] = c07d7163bcd05dfe +A[ 142] = 841dd2066df5d2a1 +A[ 143] = db122831fc72f4b5 +A[ 144] = 08f24baf1c9d6bd8 +A[ 145] = 5eff0d4698d0fc06 +A[ 146] = 2e7d9462fae63e2c +A[ 147] = bf86d1573e7fcb05 +A[ 148] = 81b9602f09b1b144 +A[ 149] = f7d0e892806029ac +A[ 150] = ee671dbe2f9e706c +A[ 151] = 03d9c6acabf402aa +A[ 152] = 2017d423651b402b +Output (16 words of chaining values): +A[ 153] = 34e06cf8e7e380b8 output chaining value C[0] +A[ 154] = f8736f4357f99cb8 output chaining value C[1] +A[ 155] = a3e1187da8fbd4e8 output chaining value C[2] +A[ 156] = 6c11da3b93aca37a output chaining value C[3] +A[ 157] = 5fdb88a98301b016 output chaining value C[4] +A[ 158] = 5d2a34ccc621594d output chaining value C[5] +A[ 159] = d10521d7588ce414 output chaining value C[6] +A[ 160] = 5040286fe773a8c0 output chaining value C[7] +A[ 161] = fe030f559c8a0f0b output chaining value C[8] +A[ 162] = ca289a3c963dd24b output chaining value C[9] +A[ 163] = acdccf24c7a70e53 output chaining value C[10] +A[ 164] = 1f451b9a0209f583 output chaining value C[11] +A[ 165] = da56f65e3205064d output chaining value C[12] +A[ 166] = a00e879eae6d8241 output chaining value C[13] +A[ 167] = 2a2a15bc29dc56a4 output chaining value C[14] +A[ 168] = 5d8e677905657f39 output chaining value C[15] + +MD6 compression function computation (level 2, index 0): +Input (89 words): +A[ 0] = 7311c2812425cfa0 Q[0] +A[ 1] = 6432286434aac8e7 Q[1] +A[ 2] = b60450e9ef68b7c1 Q[2] +A[ 3] = e8fb23908d9f06f1 Q[3] +A[ 4] = dd2e76cba691e5bf Q[4] +A[ 5] = 0cd0d63b2c30bc41 Q[5] +A[ 6] = 1f8ccf6823058f8a Q[6] +A[ 7] = 54e5ed5b88e3775d Q[7] +A[ 8] = 4ad12aae0a6d6031 Q[8] +A[ 9] = 3e7f16bb88222e0d Q[9] +A[ 10] = 8af8671d3fb50c2c Q[10] +A[ 11] = 995ad1178bd25c31 Q[11] +A[ 12] = c878c1dd04c4b633 Q[12] +A[ 13] = 3b72066c7a1552ac Q[13] +A[ 14] = 0d6f3522631effcb Q[14] +A[ 15] = 6162636465313233 key K[0] +A[ 16] = 3435000000000000 key K[1] +A[ 17] = 0000000000000000 key K[2] +A[ 18] = 0000000000000000 key K[3] +A[ 19] = 0000000000000000 key K[4] +A[ 20] = 0000000000000000 key K[5] +A[ 21] = 0000000000000000 key K[6] +A[ 22] = 0000000000000000 key K[7] +A[ 23] = 0200000000000000 nodeID U = (ell,i) = (2,0) +A[ 24] = 000540108000a0e0 control word V = (r,L,z,p,keylen,d) = (5,64,1,2048,10,224) +A[ 25] = e86a6f805fb810ca data B[ 0] chaining from (1,0) +A[ 26] = 991de071299831a9 data B[ 1] chaining from (1,0) +A[ 27] = c59517fb7f5c5e74 data B[ 2] chaining from (1,0) +A[ 28] = 0e2b5f69481c68e6 data B[ 3] chaining from (1,0) +A[ 29] = 8ddb33a8b069b4c2 data B[ 4] chaining from (1,0) +A[ 30] = 558b3513a0046dbd data B[ 5] chaining from (1,0) +A[ 31] = e1dfb6726949ab7e data B[ 6] chaining from (1,0) +A[ 32] = f48bae515e89ee94 data B[ 7] chaining from (1,0) +A[ 33] = d31d1f87d97da302 data B[ 8] chaining from (1,0) +A[ 34] = 5d349e9b0d69b270 data B[ 9] chaining from (1,0) +A[ 35] = b409d2ee2c3e5577 data B[10] chaining from (1,0) +A[ 36] = 997621d403cd954e data B[11] chaining from (1,0) +A[ 37] = 7a353e0ef29490a3 data B[12] chaining from (1,0) +A[ 38] = 716d1239dfff51dc data B[13] chaining from (1,0) +A[ 39] = 59744be898cf7c0a data B[14] chaining from (1,0) +A[ 40] = 07951a90e19da429 data B[15] chaining from (1,0) +A[ 41] = 34e06cf8e7e380b8 data B[16] chaining from (1,1) +A[ 42] = f8736f4357f99cb8 data B[17] chaining from (1,1) +A[ 43] = a3e1187da8fbd4e8 data B[18] chaining from (1,1) +A[ 44] = 6c11da3b93aca37a data B[19] chaining from (1,1) +A[ 45] = 5fdb88a98301b016 data B[20] chaining from (1,1) +A[ 46] = 5d2a34ccc621594d data B[21] chaining from (1,1) +A[ 47] = d10521d7588ce414 data B[22] chaining from (1,1) +A[ 48] = 5040286fe773a8c0 data B[23] chaining from (1,1) +A[ 49] = fe030f559c8a0f0b data B[24] chaining from (1,1) +A[ 50] = ca289a3c963dd24b data B[25] chaining from (1,1) +A[ 51] = acdccf24c7a70e53 data B[26] chaining from (1,1) +A[ 52] = 1f451b9a0209f583 data B[27] chaining from (1,1) +A[ 53] = da56f65e3205064d data B[28] chaining from (1,1) +A[ 54] = a00e879eae6d8241 data B[29] chaining from (1,1) +A[ 55] = 2a2a15bc29dc56a4 data B[30] chaining from (1,1) +A[ 56] = 5d8e677905657f39 data B[31] chaining from (1,1) +A[ 57] = 0000000000000000 data B[32] padding +A[ 58] = 0000000000000000 data B[33] padding +A[ 59] = 0000000000000000 data B[34] padding +A[ 60] = 0000000000000000 data B[35] padding +A[ 61] = 0000000000000000 data B[36] padding +A[ 62] = 0000000000000000 data B[37] padding +A[ 63] = 0000000000000000 data B[38] padding +A[ 64] = 0000000000000000 data B[39] padding +A[ 65] = 0000000000000000 data B[40] padding +A[ 66] = 0000000000000000 data B[41] padding +A[ 67] = 0000000000000000 data B[42] padding +A[ 68] = 0000000000000000 data B[43] padding +A[ 69] = 0000000000000000 data B[44] padding +A[ 70] = 0000000000000000 data B[45] padding +A[ 71] = 0000000000000000 data B[46] padding +A[ 72] = 0000000000000000 data B[47] padding +A[ 73] = 0000000000000000 data B[48] padding +A[ 74] = 0000000000000000 data B[49] padding +A[ 75] = 0000000000000000 data B[50] padding +A[ 76] = 0000000000000000 data B[51] padding +A[ 77] = 0000000000000000 data B[52] padding +A[ 78] = 0000000000000000 data B[53] padding +A[ 79] = 0000000000000000 data B[54] padding +A[ 80] = 0000000000000000 data B[55] padding +A[ 81] = 0000000000000000 data B[56] padding +A[ 82] = 0000000000000000 data B[57] padding +A[ 83] = 0000000000000000 data B[58] padding +A[ 84] = 0000000000000000 data B[59] padding +A[ 85] = 0000000000000000 data B[60] padding +A[ 86] = 0000000000000000 data B[61] padding +A[ 87] = 0000000000000000 data B[62] padding +A[ 88] = 0000000000000000 data B[63] padding +Intermediate values: +A[ 89] = 027431e67f2b19cf +A[ 90] = 0d990f6680e90d20 +A[ 91] = f27bc123aa282635 +A[ 92] = f90ca91b7fd9c62c +A[ 93] = 85139f55bd354f15 +A[ 94] = eb6b874532011a19 +A[ 95] = 7b04461ba005d2fc +A[ 96] = c7db19c96ca9abc7 +A[ 97] = b723400f04c813c4 +A[ 98] = c22c98f63ef66335 +A[ 99] = 42a2cbb64372fc40 +A[ 100] = e52aeb1d587b9012 +A[ 101] = 9ea7a2d571275633 +A[ 102] = 7e99d0316f65addd +A[ 103] = 72f2b2f2fd1fe6ec +A[ 104] = ee030108c4c8d073 +A[ 105] = cfccf37b34add3eb +A[ 106] = f0155b54e33fa5cc +A[ 107] = b3b80e2309548fa4 +A[ 108] = b5ef06df65e727d7 +A[ 109] = ef08a1b814d205a0 +A[ 110] = 367b2caf36cc81c6 +A[ 111] = 343a0cf5b903d13e +A[ 112] = b7ffc1e7889e619e +A[ 113] = da463bde6895e3cf +A[ 114] = bd6d76d5ecb9ced7 +A[ 115] = e9211df17c1026cf +A[ 116] = b457148a6f18579b +A[ 117] = 3d0b7d88140c60ea +A[ 118] = 3a1618bc555cfd06 +A[ 119] = af18e03b8f81137f +A[ 120] = b6d883f0886927fa +A[ 121] = e381b7c523751aee +A[ 122] = a67b075ce5084a43 +A[ 123] = e21bdb4cbccfd550 +A[ 124] = 605490a2b9633ba6 +A[ 125] = 827ab3dc2455cc3e +A[ 126] = e844879b214868ab +A[ 127] = 69dee938c4137097 +A[ 128] = ac40cdbd60be47e0 +A[ 129] = f2ef6e974054c21d +A[ 130] = 7ca07eb5027eb3ba +A[ 131] = 44f906e854762107 +A[ 132] = 1ee8fa9fe001f2fb +A[ 133] = 7e59e884e26c7334 +A[ 134] = 2826f9847abcb858 +A[ 135] = df781ee5037bfa6c +A[ 136] = 7ef847fbff16a0e2 +A[ 137] = 7b9385aaadc629f9 +A[ 138] = a31a329af6d51b66 +A[ 139] = deca0d8d359124b2 +A[ 140] = aa4dcd6abdd53809 +A[ 141] = 54716fa013b20217 +A[ 142] = 540769a3c74ee7e1 +A[ 143] = 3db7182c921992a4 +A[ 144] = 09f2a43ce7a2d5f9 +A[ 145] = 7aae992259f2b683 +A[ 146] = 9a7c3b013169a03e +A[ 147] = 5d3a735c1778b352 +A[ 148] = 42d57de6de15e405 +A[ 149] = 12f0c0a26450d81e +A[ 150] = aa66aa041120fc69 +A[ 151] = 27c0ddcc71049201 +A[ 152] = 4605822c05dc18b8 +Output (16 words of chaining values): +A[ 153] = 51fe1122f4c17ec2 output chaining value C[0] +A[ 154] = a314cd812406314d output chaining value C[1] +A[ 155] = f7b08c0b30f095fe output chaining value C[2] +A[ 156] = 1ded1aee71933f09 output chaining value C[3] +A[ 157] = 2bb446cb238ed41f output chaining value C[4] +A[ 158] = 0f6460080325fe08 output chaining value C[5] +A[ 159] = 160e8b6947fcf632 output chaining value C[6] +A[ 160] = e283c3b4b88318cb output chaining value C[7] +A[ 161] = a00cab488aa9c072 output chaining value C[8] +A[ 162] = 9f2810c25189818d output chaining value C[9] +A[ 163] = 31f7f47f96cf8606 output chaining value C[10] +A[ 164] = 403f037430ec43f2 output chaining value C[11] +A[ 165] = edcbb8e5894cf059 output chaining value C[12] +A[ 166] = 8ad3288ed4bb5ac5 output chaining value C[13] +A[ 167] = df23eba0ac388a11 output chaining value C[14] +A[ 168] = b7ed2e3dd5ec5131 output chaining value C[15] + +894cf0598ad3288ed4bb5ac5df23eba0ac388a11b7ed2e3dd5ec5131 -B600 + +\end{verbatim} Index: trunk/C_implementation/README_Reference.txt =================================================================== --- trunk/C_implementation/README_Reference.txt (nonexistent) +++ trunk/C_implementation/README_Reference.txt (revision 2) @@ -0,0 +1,16 @@ +Filename: README_Reference.txt +Author: Ronald L. Rivest +Date: 8/31/08 + +This directory (Reference_Implementation) contains the +required reference implementation for our NIST SHA-3 +submission, "MD6". + +The files included here are: + md6.h + md6_compress.c + md6_mode.c + md6_nist.h + md6_nist.c + inttypes.h + stdint.h Index: trunk/C_implementation/2007-12-19-SHA3-C-API.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/C_implementation/2007-12-19-SHA3-C-API.pdf =================================================================== --- trunk/C_implementation/2007-12-19-SHA3-C-API.pdf (nonexistent) +++ trunk/C_implementation/2007-12-19-SHA3-C-API.pdf (revision 2)
trunk/C_implementation/2007-12-19-SHA3-C-API.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/C_implementation/stdint.h =================================================================== --- trunk/C_implementation/stdint.h (nonexistent) +++ trunk/C_implementation/stdint.h (revision 2) @@ -0,0 +1,222 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if (_MSC_VER < 1300) && defined(__cplusplus) + extern "C++" { +#endif +# include +#if (_MSC_VER < 1300) && defined(__cplusplus) + } +#endif + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef int intptr_t; + typedef unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] Index: trunk/C_implementation/md6sum.c =================================================================== --- trunk/C_implementation/md6sum.c (nonexistent) +++ trunk/C_implementation/md6sum.c (revision 2) @@ -0,0 +1,761 @@ +/* File: md6sum.c +** Author: Ronald L. Rivest +** Address: Room 32G-692 Stata Center +** 32 Vassar Street +** Cambridge, MA 02139 +** Email: rivest@mit.edu +** Date: 9/25/2008 +** +** (The following license is known as "The MIT License") +** +** Copyright (c) 2008 Ronald L. Rivest +** +** 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. +** +** (end of license) +** +** This is an application illustrating the use of the MD6 hash function. +** The files defining the md6 hash function are: +** md6.h +** md6_compress.c +** md6_mode.c +** +** The files defining the interface between MD6 and the NIST SHA-3 +** API are: +** md6_nist.h +** md6_nist.c +** The NIST SHA-3 API is defined in: +** http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf +** +** See http://groups.csail.mit.edu/cis/md6 for more information. +** +*/ + + #include +#include +#include +#include +#include +#include + +#include "md6.h" + + /* Cycle count routines */ + +#if defined _MSC_VER + +/* Microsoft */ +#include +#pragma intrinsic(__rdtsc) +uint64_t ticks() +{ + return __rdtsc(); +} + +#else + +/* GCC */ +#include +inline uint64_t ticks() { + /* read timestamp counter */ + uint32_t lo, hi; + asm volatile ( + "xorl %%eax,%%eax \n cpuid" + ::: "%rax", "%rbx", "%rcx", "%rdx"); + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi)); + return (uint64_t)hi << 32 | lo; +} + +#endif + + /* Constants for MD6 */ + +#define w md6_w +#define c md6_c +#define n md6_n +#define b md6_b +#define u md6_u +#define v md6_v +#define k md6_k +#define q md6_q + +/* Useful macros: min and max */ +#ifndef min +#define min(a,b) ((a)<(b)? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a)>(b)? (a) : (b)) +#endif + +/* MD6 parameters */ +int d; /* digest length */ +int L; /* mode parameter */ +int r; /* number of rounds */ +unsigned char K[100]; /* key */ +int keylen; /* key length in bytes (at most 64) */ +md6_state st; /* md6 computation state */ + +char msg[5000]; /* message to be hashed (if given with -M) */ +int msglenbytes; /* message length in bytes */ + + char help_string[] = +"md6sum [OPTIONS] file1 file2 ...\n" +"Options:\n" +"\t(option letters are case-sensitive and processed in order):\n" +"\t-bnnnn\tHash a dummy file of length nnnn bits.\n" +"\t-Bnnnn\tHash a dummy file of length nnnn bytes.\n" +"\t-c xxxx\tCheck hash from file xxxx to see if they are still valid.\n" +"\t\tHere xxxx is saved output from previous run of md6sum.\n" +"\t\tNames of files whose hash value have changed are printed.\n" +"\t-dnnn\tSet digest length d to nnn bits, 1<=nnn<=512; default is 256.\n" +"\t-h\tPrint this help information.\n" +"\t-i\tPrint input/output data for each compression function call.\n" +"\t-I\tLike -i, but also prints out all intermediate values computed.\n" +"\t-Kxxxxx\tSet MD6 key to xxxxx (length 0 to 64 bytes).\n" +"\t-Lnn\tSet MD6 mode parameter L to nn (0<=L<=64; default 64).\n" +"\t-Mxxxxx\tCompute hash of message xxxxx.\n" +"\t-rnnn\tSet MD6 number r of rounds to nn (0<=r<=255; default is 40+(d/4).\n" +"\t-snnn\tMeasure time to perform nnn MD6 initializations (nnn optional).\n" +"\t-t\tTurn on printing of elapsed times and bytes/second.\n" +"For each file given, md6sum prints a line of the form: \n" +"\thashvalue filename\n" +"If file is `-', or if no files are given, standard input is used.\n" +"Integers nnnn may use scientific notation, e.g. -B1e9 .\n" +; + + /* return integer starting at s (input presumed to end with '\n') +** (It may be expressed in exponential format e.g. 1e9.) +*/ + +uint64_t get_int(char *s) +{ long double g; + sscanf(s,"%Lg",&g); + return (uint64_t)g; +} + + /* routines to escape/unescape filenames, in case they +** contain backslash or \n 's. +*/ + +void encode(char *s, char *t) +/* input t, output s -- recode t so it all newlines and +** backslashes are escaped as \n and \\ respectively. +** Also, a leading '-' is escaped to \-. +*/ +{ if (*t && *t=='-') + { *s++ = '\\'; *s++ = '-'; t++; } + while (*t) + { if (*t=='\\') { *s++ = '\\'; *s++ = '\\'; } + else if (*t=='\n') { *s++ = '\\'; *s++ = 'n'; } + else *s++ = *t; + t++; + } + *s = 0; + return; +} + +void decode(char *s, char *t) +/* inverse of encode -- s is unescaped version of t. */ +{ while (*t) + { if (*t == '\\') + { if (*(t+1)=='\\') { *s++ = '\\'; t+=1; } + else if (*(t+1)=='n') { *s++ = '\n'; t+=1; } + else if (*(t+1)=='-') { *s++ = '-'; t+=1; } + else if (*(t+1)==0) { *s++ = '\\'; } + else { *s++ = *t; } + } + else *s++ = *t; + t++; + } + *s = 0; + return; +} + + /* timing variables and routines */ + +double start_time; +double end_time; +uint64_t start_ticks; +uint64_t end_ticks; + +void start_timer() +{ + start_time = ((double)clock())/CLOCKS_PER_SEC; + start_ticks = ticks(); +} + +void end_timer() +{ + end_time = ((double)clock())/CLOCKS_PER_SEC; + end_ticks = ticks(); +} + +int print_times = 0; + +void print_time() +{ double elapsed_time = end_time - start_time; + uint64_t elapsed_ticks = end_ticks - start_ticks; + uint64_t bytes = st.bits_processed/8; + int bits = st.bits_processed % 8; + if (!print_times) return; + printf("-- Length = "); + if (st.bits_processed==0) printf("0"); + if (bytes>0) printf("%g byte",(double)bytes); + if (bytes>1) printf("s"); + if (bytes>0 && bits>0) printf(" + "); + if (bits>0) printf("%d bit",bits); + if (bits>1) printf("s"); + printf("\n"); + printf("-- Compression calls made = %g\n",(double)st.compression_calls); + if (elapsed_time == 0.0) + printf("-- Elapsed time too short to measure...\n"); + else + { printf("-- Elapsed time = %.3f seconds.\n", elapsed_time); + printf("-- Megabytes per second = %g.\n", + (bytes/elapsed_time)/1000000.0); + printf("-- Microseconds per compression function = %g.\n", + (elapsed_time*1.0e6 / st.compression_calls )); + } + printf("-- Total clock ticks = %lld\n", + (long long int)elapsed_ticks); + if (bytes>0) + printf("-- Clock ticks / byte = %lld\n", + (long long int)(elapsed_ticks/bytes)); + printf("-- Clock ticks / compression function call = %lld\n", + (long long int)(elapsed_ticks/st.compression_calls)); +} + + /* testing and debugging */ + +/* Global variables used by compression_hook_1 */ +FILE *outFile = NULL; +int print_input_output = 0; +int print_intermediate = 0; + +void compression_hook_1(md6_word *C, + const md6_word *Q, + md6_word *K, + int ell, + int ii, + int r, + int L, + int z, + int p, + int keylen, + int d, + md6_word *B +) +{ int i; + md6_word A[5000]; + time_t now; + + md6_pack(A,Q,K,ell,ii,r,L,z,p,keylen,d,B); + + md6_main_compression_loop( A, r); + + if (ell==1 && ii==0) + { time(&now); + fprintf(outFile,"-- d = %6d (digest length in bits)\n",d); + fprintf(outFile,"-- L = %6d (number of parallel passes)\n",L); + fprintf(outFile,"-- r = %6d (number of rounds)\n",r); + /* print key out as chars, since for md6sum it is essentially + ** impossible to enter non-char keys... + */ + fprintf(outFile,"-- K = '"); + for (i=0;i>8*(7-(i%(w/8))))&0xff); + fprintf(outFile,"' (key)\n"); + fprintf(outFile,"-- k = %6d (key length in bytes)\n",keylen); + fprintf(outFile,"\n"); + } + + fprintf(outFile,"MD6 compression function computation "); + fprintf(outFile,"(level %d, index %d):\n",ell,ii); + fprintf(outFile,"Input (%d words):\n",n); + + for (i=0;i=q)&&(i0)&&(i==q+k+u-1)) + { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]); + fprintf(outFile," nodeID U = (ell,i) = (%d,%d)\n",ell,ii); + } + else if ((v>0)&&(i==q+k+u+v-1)) + { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]); + fprintf(outFile," control word V = " + "(r,L,z,p,keylen,d) = " + "(%d,%d,%d,%d,%d,%d)\n",r,L,z,p,keylen,d); + } + else if ((i>=q+k+u+v)&&(i=n) + fprintf(outFile,"padding"); + else if (ell == 1) + fprintf(outFile,"input message word %4d", + ii*(b-c)+(i-(q+k+u+v+c))); + else + fprintf(outFile, + "chaining from (%d,%d)", + ell-1, + 3*ii+(i-(q+k+u+v+c))/c); + } + } + fprintf(outFile,"\n"); + } + else if ((i>=r*c+n-c)) + { if ((i==r*c+n-c)) + fprintf(outFile,"Output (%d words of chaining values):\n",c); + fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]); + fprintf(outFile," output chaining value C[%d]\n",i-(r*c+n-c)); + } + else + { if (i==n) + { if (print_intermediate) + fprintf(outFile,"Intermediate values:\n"); + else + fprintf(outFile, + "Intermediate values A[%d..%d] omitted... " + "\n",n,r*c+n-c-1); + } + if (print_intermediate) + fprintf(outFile,"A[%4d] = " PR_MD6_WORD "\n",i,A[i]); + } + } + fprintf(outFile,"\n"); +} + + /* interface to hash routines +*/ + +void hash_init() +{ int err; + start_timer(); + if ((err=md6_full_init(&st,d,K,keylen,L,r))) + { printf("Bad MD6 parameters; can't initialize md6. " + "errcode = %d\n",err); + return; + } + if (print_input_output) + compression_hook = compression_hook_1; +} + +void hash_update(char* data, + uint64_t databitlen) +{ int err; + if ((err=md6_update(&st, + (unsigned char *)data, + databitlen))) + { printf("MD6 update error. error code: %d\n",err); + return; + } +} + +void hash_final() +{ int err; + if ((err=md6_final(&st,NULL))) + { printf("MD6 finalization error. error code: %d\n",err); + return; + } + end_timer(); +} + + void hash_filep(FILE *inFile) +{ uint64_t bytes; + char data[1024]; + if (inFile==NULL) + { printf("hash_filep has NULL input file pointer.\n"); + return; + } + hash_init(); + while ((bytes = fread (data, 1, 1024, inFile)) != 0) + hash_update(data,bytes*8); + hash_final(); +} + +void hash_stdin() +{ hash_filep(stdin); +} + +void hash_file( char *filename ) +{ FILE *inFile = fopen (filename, "rb"); + if ( inFile == NULL ) + { printf("%s can't be opened.\n", filename); + return; + } + hash_filep(inFile); + fclose(inFile); +} + +void hash_b(uint64_t bitlen) +/* Hash dummy input file of length bitlen bits. +** File (hex) repeats with period 7: +** 11 22 33 44 55 66 77 11 22 33 44 55 66 77 11 22 33 ... +*/ +{ int i; + char data[700]; /* nice if length is multiple of 7 for periodicity */ + for (i=0;i<700;i++) + data[i] = 0x11 + (char)((i % 7)*(0x11)); + hash_init(); + while (bitlen>0) + { uint64_t part_len = min(700*8,bitlen); + hash_update(data,part_len); + bitlen = bitlen - part_len; + } + hash_final(); +} + +void hash_B(uint64_t B) +/* Hash dummy input file of length B bytes. +*/ +{ hash_b(B*8); +} + + /* Routines to handle command-line options +*/ + +void optd(char *optstr) +{ /* set MD6 digest length + ** -dnn sets digest length to nn, 1 <= nn <= 512 + */ + int dopt = get_int(optstr+2); + if (dopt<1 || dopt>512) + printf("Illegal digest size option %s ignored.\n",optstr); + else + d = dopt; + r = md6_default_r(d); +} + +void opth() +{ /* print md6sum help string */ + printf(help_string); +} + +void optK(char *optstr) +{ /* set MD6 key */ + optstr += 2; + keylen = 0; + while (*optstr && keylen<64) K[keylen++] = *optstr++; + K[keylen] = 0; +} + +void optL(char *optstr) +{ /* set MD6 mode parameter + ** -Lnn where 0<=n<=64 + ** nn = 0 means fully sequential + ** nn = 64 means fully hierarchical + ** intermediate values give a blended approach + */ + int Lopt = get_int(optstr+2); + if (Lopt<0 || Lopt>64) + printf("Illegal L options %s ignored.\n",optstr); + else + L = Lopt; +} + +void optr(char *optstr) +{ /* set MD6 number of rounds + ** -rnn where 0<=r<=255 + */ + int ropt = get_int(optstr+2); + if (r<0 || r>255) + printf("Illegal r options %s ignored.\n",optstr); + else + r = ropt; + +} + +void optM(char *optstr) +{ /* hash a message given as a command-line argument */ + char *p = optstr + 2; + msglenbytes = 0; + while (*p && msglenbytes<4990) msg[msglenbytes++] = *p++; + msg[msglenbytes] = 0; + hash_init(); + hash_update(msg,msglenbytes*8); + hash_final(); +} + +void optb(char *optstr) +/* -bnnnn hash dummy file of length nnnn bits */ +{ + uint64_t bitlen = get_int(optstr+2); + hash_b(bitlen); +} + +void optB(char *optstr) +/* -Bnnnn hash dummy file of length nnnn bytes */ +{ uint64_t B = get_int(optstr+2); + hash_b(B*8); +} + +void check_line(char *line) +/* print filename if its hash doesn't agree with what's given in line +*/ +{ char *x; + char hexhashval[1000]; + int hexhashlen; + char filename[1000]; + char decfilename[1000]; + int filenamelen; + /* collect hash value */ + x = line; + hexhashlen = 0; + while (*x && *x!=' ' && hexhashlen<900) + hexhashval[hexhashlen++] = *x++; + hexhashval[hexhashlen] = 0; + if (*x != ' ') + { printf("Badly formed hash check file line: %s\n",line); + return; + } + x++; + /* collect filename and decode it */ + filenamelen = 0; + while (*x && *x != '\n' && filenamelen<900) + filename[filenamelen++] = *x++; + filename[filenamelen] = 0; + decode(decfilename,filename); + if (filename[0]=='-') + { /* handle "filenames" starting with '-' specially, + ** even though legitimate filenames may start with '-'. + */ + if (filenamelen==1) + return; /* skip standard input */ + switch( filename[1] ) + { + case 'M': optM(decfilename); break; + case 'b': optb(decfilename); break; + case 'B': optB(decfilename); break; + default: hash_file(decfilename); break; + } + } + else + { /* now compute hash of file */ + hash_file(decfilename); + } + if (strcmp(hexhashval,(char *)st.hexhashval)!=0) + printf("%s\n",decfilename); +} + +void optc(int argc, char **argv, int i) +/* Recompute hashes, and check them for current validity. +** -c file causes hashes from given file to be checked. +** (This file is e.g. output from previous run of md6sum.) +** Names of files that's don't hash the same are printed. +*/ +{ + FILE *checkfilep; + char line[1000]; + + if (i == argc-1) + { printf("md6sum error: no file given for -c option.\n"); + return; + } + checkfilep = fopen(argv[i+1],"r"); + if (checkfilep==NULL) + { printf("Hash check file %s can't be opened.\n",argv[i+1]); + return; + } + while (fgets( line, 990, checkfilep)) + { if (strlen(line)==0) continue; + line[strlen(line)-1] = 0; /* kill '\n' */ + if (line[0]=='-') /* handle md6sum option */ + { if (strlen(line)==1) + { printf("Hash check file contains illegal line with single '-'; ignored.\n"); + } + switch ( line[1] ) + { + case 'd': optd(line); break; + case 'K': optK(line); break; + case 'L': optL(line); break; + case 'r': optr(line); break; + case ' ': break; /* ignore lines starting with '- ' or '--' */ + case '-': break; + default: printf("Unrecognized md6sum option in check file: %s\n",argv[i]); + break; + }; + continue; + } + /* now handle typical line with hash value */ + check_line(line); + } + fclose(checkfilep); +} + +void optt() +/* turn on timing printout */ +{ + print_times = 1; +} + + /* Routine to print hashvalue filename line. +** Prints time_of_day first if it hasn't been printed already. +*/ + +int tod_printed = 0; + +void print_tod() +{ /* print time-of-day if it hasn't been printed yet. */ + time_t now; + if (!tod_printed) + { time(&now); + printf("-- %s",ctime(&now)); + tod_printed = 1; + } +} + +void opti() +/* turn on printing of input/output values for compression function calls */ +{ print_tod(); + print_input_output = 1; + outFile = stdout; +} + +void optI() +/* turn on printing of input/output values AND intermediate values */ +{ print_tod(); + print_input_output = 1; + print_intermediate = 1; + outFile = stdout; +} + +void opts(char *optstr) +{ uint64_t trials = get_int(optstr+2); + uint64_t i; + int err; + double elapsed_time; + uint64_t elapsed_ticks; + if (trials == 0) trials = 1; + start_timer(); + for (i=0;i
trunk/C_implementation/Assembly Optimization Tips.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/C_implementation/firstexample.tex =================================================================== --- trunk/C_implementation/firstexample.tex (nonexistent) +++ trunk/C_implementation/firstexample.tex (revision 2) @@ -0,0 +1,183 @@ +-r5 +-- Mon Aug 04 20:57:00 2008 +-- d = 256 (digest length in bits) +-- L = 64 (number of parallel passes) +-- r = 5 (number of rounds) +-- K = '' (key) +-- k = 0 (key length in bytes) + + MD6 compression function computation (level 1, index 0): +Input (89 words): +A[ 0] = 7311c2812425cfa0 Q[0] +A[ 1] = 6432286434aac8e7 Q[1] +A[ 2] = b60450e9ef68b7c1 Q[2] +A[ 3] = e8fb23908d9f06f1 Q[3] +A[ 4] = dd2e76cba691e5bf Q[4] +A[ 5] = 0cd0d63b2c30bc41 Q[5] +A[ 6] = 1f8ccf6823058f8a Q[6] +A[ 7] = 54e5ed5b88e3775d Q[7] +A[ 8] = 4ad12aae0a6d6031 Q[8] +A[ 9] = 3e7f16bb88222e0d Q[9] +A[ 10] = 8af8671d3fb50c2c Q[10] +A[ 11] = 995ad1178bd25c31 Q[11] +A[ 12] = c878c1dd04c4b633 Q[12] +A[ 13] = 3b72066c7a1552ac Q[13] +A[ 14] = 0d6f3522631effcb Q[14] +A[ 15] = 0000000000000000 key K[0] +A[ 16] = 0000000000000000 key K[1] +A[ 17] = 0000000000000000 key K[2] +A[ 18] = 0000000000000000 key K[3] +A[ 19] = 0000000000000000 key K[4] +A[ 20] = 0000000000000000 key K[5] +A[ 21] = 0000000000000000 key K[6] +A[ 22] = 0000000000000000 key K[7] +A[ 23] = 0100000000000000 nodeID U = (ell,i) = (1,0) +A[ 24] = 00054010fe800100 control word V = (r,L,z,p,keylen,d) = (5,64,1,4072,0,256) +A[ 25] = 6162630000000000 data B[ 0] input message word 0 +A[ 26] = 0000000000000000 data B[ 1] padding +A[ 27] = 0000000000000000 data B[ 2] padding +A[ 28] = 0000000000000000 data B[ 3] padding +A[ 29] = 0000000000000000 data B[ 4] padding +A[ 30] = 0000000000000000 data B[ 5] padding +A[ 31] = 0000000000000000 data B[ 6] padding +A[ 32] = 0000000000000000 data B[ 7] padding +A[ 33] = 0000000000000000 data B[ 8] padding +A[ 34] = 0000000000000000 data B[ 9] padding +A[ 35] = 0000000000000000 data B[10] padding +A[ 36] = 0000000000000000 data B[11] padding +A[ 37] = 0000000000000000 data B[12] padding +A[ 38] = 0000000000000000 data B[13] padding +A[ 39] = 0000000000000000 data B[14] padding +A[ 40] = 0000000000000000 data B[15] padding +A[ 41] = 0000000000000000 data B[16] padding +A[ 42] = 0000000000000000 data B[17] padding +A[ 43] = 0000000000000000 data B[18] padding +A[ 44] = 0000000000000000 data B[19] padding +A[ 45] = 0000000000000000 data B[20] padding +A[ 46] = 0000000000000000 data B[21] padding +A[ 47] = 0000000000000000 data B[22] padding +A[ 48] = 0000000000000000 data B[23] padding +A[ 49] = 0000000000000000 data B[24] padding +A[ 50] = 0000000000000000 data B[25] padding +A[ 51] = 0000000000000000 data B[26] padding +A[ 52] = 0000000000000000 data B[27] padding +A[ 53] = 0000000000000000 data B[28] padding +A[ 54] = 0000000000000000 data B[29] padding +A[ 55] = 0000000000000000 data B[30] padding +A[ 56] = 0000000000000000 data B[31] padding +A[ 57] = 0000000000000000 data B[32] padding +A[ 58] = 0000000000000000 data B[33] padding +A[ 59] = 0000000000000000 data B[34] padding +A[ 60] = 0000000000000000 data B[35] padding +A[ 61] = 0000000000000000 data B[36] padding +A[ 62] = 0000000000000000 data B[37] padding +A[ 63] = 0000000000000000 data B[38] padding +A[ 64] = 0000000000000000 data B[39] padding +A[ 65] = 0000000000000000 data B[40] padding +A[ 66] = 0000000000000000 data B[41] padding +A[ 67] = 0000000000000000 data B[42] padding +A[ 68] = 0000000000000000 data B[43] padding +A[ 69] = 0000000000000000 data B[44] padding +A[ 70] = 0000000000000000 data B[45] padding +A[ 71] = 0000000000000000 data B[46] padding +A[ 72] = 0000000000000000 data B[47] padding +A[ 73] = 0000000000000000 data B[48] padding +A[ 74] = 0000000000000000 data B[49] padding +A[ 75] = 0000000000000000 data B[50] padding +A[ 76] = 0000000000000000 data B[51] padding +A[ 77] = 0000000000000000 data B[52] padding +A[ 78] = 0000000000000000 data B[53] padding +A[ 79] = 0000000000000000 data B[54] padding +A[ 80] = 0000000000000000 data B[55] padding +A[ 81] = 0000000000000000 data B[56] padding +A[ 82] = 0000000000000000 data B[57] padding +A[ 83] = 0000000000000000 data B[58] padding +A[ 84] = 0000000000000000 data B[59] padding +A[ 85] = 0000000000000000 data B[60] padding +A[ 86] = 0000000000000000 data B[61] padding +A[ 87] = 0000000000000000 data B[62] padding +A[ 88] = 0000000000000000 data B[63] padding +Intermediate values: +A[ 89] = 027431e67f2b19cf +A[ 90] = 0d990f6680e90d20 +A[ 91] = f27bc123aa282635 +A[ 92] = f90ca91b7fd9c62c +A[ 93] = 85139f55bd354f15 +A[ 94] = eb6b874532011a19 +A[ 95] = 7b04461ba005d2fc +A[ 96] = c7db19c96ca9abc7 +A[ 97] = b723400f04c813c4 +A[ 98] = c22c98f63ef66335 +A[ 99] = 42a2cbb64372fc40 +A[ 100] = e52aeb1d587b9012 +A[ 101] = 9ea7a2d571275633 +A[ 102] = 7e99d0316f65addd +A[ 103] = 72f2b2f2fd1fe6ec +A[ 104] = 478df0ec797df153 +A[ 105] = 3b9efe3b34add3eb +A[ 106] = f0155b54e33fa5cc +A[ 107] = b3b80e2309548fa4 +A[ 108] = b5ef06df65e727d7 +A[ 109] = ef08a1b814d205a0 +A[ 110] = 367b2caf36cc81c6 +A[ 111] = 343a0cf5b903d13e +A[ 112] = b4f9c1e7889e619e +A[ 113] = da463bc1b64240ad +A[ 114] = 10401204b0e3df85 +A[ 115] = 4877a679f7db2705 +A[ 116] = e2ff7c19283b650d +A[ 117] = 7e20b510048c8b81 +A[ 118] = 2ec6248f95796fcd +A[ 119] = 0c87c7f9e1056f74 +A[ 120] = 5e20250caa5b4a43 +A[ 121] = 6e44865c042e3829 +A[ 122] = 9529fbc6155a6a6d +A[ 123] = c44d6a63399d5e4f +A[ 124] = 04ead78d74346144 +A[ 125] = 259b97c077a30362 +A[ 126] = d185200a80400541 +A[ 127] = b9a8bba23413f53c +A[ 128] = a439ca3d5839a512 +A[ 129] = d2be51693c027782 +A[ 130] = 94c0710d616da4c0 +A[ 131] = 55e60934532be3b6 +A[ 132] = a6e5b044f10f495d +A[ 133] = c2a4ba0dd30863e0 +A[ 134] = abfa7c9a10170f52 +A[ 135] = c55ba748fdfdcaaa +A[ 136] = 9e0f8e2fbf4645e7 +A[ 137] = 21b0d68b36a65ab3 +A[ 138] = 24e5578b36da9478 +A[ 139] = 58446db406441646 +A[ 140] = 1be8e6525fc16819 +A[ 141] = e84464fb02c603b9 +A[ 142] = a14656016a6def39 +A[ 143] = 9b2b76febbe7de1f +A[ 144] = 79eda3eb98f56b99 +A[ 145] = 0d4ce347389fbe8d +A[ 146] = 0e51deba9751e9ac +A[ 147] = a09984f7d2ed4785 +A[ 148] = b3d375606156d954 +A[ 149] = 8f7d6fb5316a6189 +A[ 150] = 1b87a1d5504f7fc3 +A[ 151] = e3d53e19846c0868 +A[ 152] = 9dfbc0507d476a7d +Output (16 words of chaining values): +A[ 153] = 2d1abe0601b2e6b0 output chaining value C[0] +A[ 154] = 61d59fd2b7310353 output chaining value C[1] +A[ 155] = ea7da28dec708ec7 output chaining value C[2] +A[ 156] = a63a99a574e40155 output chaining value C[3] +A[ 157] = 290b4fabe80104c4 output chaining value C[4] +A[ 158] = 8c6a3503cf881a99 output chaining value C[5] +A[ 159] = e370e23d1b700cc5 output chaining value C[6] +A[ 160] = 4492e78e3fe42f13 output chaining value C[7] +A[ 161] = df6c91b7eaf3f088 output chaining value C[8] +A[ 162] = aab3e19a8f63b80a output chaining value C[9] +A[ 163] = d987bdcbda2e934f output chaining value C[10] +A[ 164] = aeae805de12b0d24 output chaining value C[11] +A[ 165] = 8854c14dc284f840 output chaining value C[12] +A[ 166] = ed71ad7ba542855c output chaining value C[13] +A[ 167] = e189633e48c797a5 output chaining value C[14] +A[ 168] = 5121a746be48cec8 output chaining value C[15] + +8854c14dc284f840ed71ad7ba542855ce189633e48c797a55121a746be48cec8 -Mabc Index: trunk/C_implementation/md6_compress.s =================================================================== --- trunk/C_implementation/md6_compress.s (nonexistent) +++ trunk/C_implementation/md6_compress.s (revision 2) @@ -0,0 +1,1449 @@ +; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.42 + + TITLE C:\ron\proj\2007E_md6\rivest\C implementation\md6_compress.c + .686P + .XMM + include listing.inc + .model flat + +INCLUDELIB LIBCMT +INCLUDELIB OLDNAMES + +PUBLIC _S0 +PUBLIC _Smask +_DATA SEGMENT +COMM _compression_hook:DWORD +_DATA ENDS +CONST SEGMENT +_S0 DQ 0123456789abcdefH +_Smask DQ 7311c2812425cfa0H +CONST ENDS +PUBLIC _md6_main_compression_loop +; Function compile flags: /Ogtpy +; COMDAT _md6_main_compression_loop +_TEXT SEGMENT +tv2623 = -164 ; size = 4 +tv2611 = -164 ; size = 4 +tv2609 = -164 ; size = 4 +tv2607 = -164 ; size = 4 +tv2605 = -164 ; size = 4 +tv2603 = -164 ; size = 4 +tv2601 = -164 ; size = 4 +tv2599 = -164 ; size = 4 +tv2597 = -164 ; size = 4 +tv2595 = -164 ; size = 4 +tv2593 = -164 ; size = 4 +tv2591 = -164 ; size = 4 +tv2589 = -164 ; size = 4 +tv2587 = -164 ; size = 4 +tv2585 = -164 ; size = 4 +tv2583 = -164 ; size = 4 +tv2581 = -164 ; size = 4 +tv2579 = -164 ; size = 4 +tv2577 = -164 ; size = 4 +tv2575 = -164 ; size = 4 +tv2573 = -164 ; size = 4 +tv2571 = -164 ; size = 4 +tv2569 = -164 ; size = 4 +tv2567 = -164 ; size = 4 +tv2565 = -164 ; size = 4 +tv2563 = -164 ; size = 4 +tv2561 = -164 ; size = 4 +tv2559 = -164 ; size = 4 +tv2557 = -164 ; size = 4 +tv2555 = -164 ; size = 4 +tv2553 = -164 ; size = 4 +tv2551 = -164 ; size = 4 +tv2549 = -164 ; size = 4 +tv2619 = -160 ; size = 4 +tv2621 = -156 ; size = 4 +tv1969 = -152 ; size = 4 +_x$ = -148 ; size = 8 +_S$ = -140 ; size = 8 +tv769 = -132 ; size = 4 +tv87 = -128 ; size = 8 +tv905 = -120 ; size = 8 +tv3245 = -112 ; size = 8 +tv380 = -104 ; size = 8 +tv959 = -96 ; size = 8 +tv717 = -88 ; size = 8 +tv933 = -80 ; size = 8 +tv869 = -72 ; size = 8 +tv160 = -64 ; size = 8 +tv264 = -56 ; size = 8 +tv3268 = -48 ; size = 8 +tv185 = -40 ; size = 8 +tv3222 = -32 ; size = 8 +tv218 = -24 ; size = 8 +tv142 = -16 ; size = 8 +tv271 = -8 ; size = 8 +_A$ = 8 ; size = 4 +_r$ = 12 ; size = 4 +_md6_main_compression_loop PROC ; COMDAT +; File c:\ron\proj\2007e_md6\rivest\c implementation\md6_compress.c +; Line 197 + sub esp, 164 ; 000000a4H + push edi +; Line 204 + mov edi, DWORD PTR _r$[esp+164] + shl edi, 4 + test edi, edi + mov DWORD PTR _S$[esp+168], -1985229329 ; 89abcdefH + mov DWORD PTR _S$[esp+172], 19088743 ; 01234567H + jle $LN1@md6_main_c + mov eax, DWORD PTR _A$[esp+164] + push ebx + lea ecx, DWORD PTR [eax+712] + lea edx, DWORD PTR [eax+576] + push ebp + add edi, -1 + push esi + mov DWORD PTR tv1969[esp+180], ecx + mov DWORD PTR tv2619[esp+180], edx + mov DWORD PTR tv2621[esp+180], eax + lea esi, DWORD PTR [eax+568] + lea edx, DWORD PTR [eax+544] + lea ecx, DWORD PTR [eax+464] + shr edi, 4 + add eax, 176 ; 000000b0H + add edi, 1 + mov DWORD PTR tv769[esp+180], edi + jmp SHORT $LN3@md6_main_c +$LL8@md6_main_c: +; Line 203 + mov esi, DWORD PTR tv2623[esp+180] +$LN3@md6_main_c: +; Line 222 + mov edi, DWORD PTR [ecx+4] + and edi, DWORD PTR [eax+4] + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + mov ebp, DWORD PTR [esi+4] + and ebp, DWORD PTR [edx+4] + mov DWORD PTR tv3268[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx] + xor ebx, edi + mov edi, DWORD PTR tv3268[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 10 + shr edi, 10 ; 0000000aH + xor ebx, ebp + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 11 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 11 ; 0000000bH + xor ebp, ebx + mov DWORD PTR tv2609[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2609[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + add eax, ebx + mov DWORD PTR tv3245[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv3245[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 5 + shr edi, 5 + mov DWORD PTR tv2607[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2607[esp+180] + xor edi, ebp + mov ebp, ebx + mov DWORD PTR _x$[esp+184], edi + shld edi, ebp, 24 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 24 ; 00000018H + xor ebp, ebx + mov DWORD PTR tv2605[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2605[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + add ecx, ebx + mov DWORD PTR tv3222[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add eax, ebx + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv3222[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 13 + shr edi, 13 ; 0000000dH + mov DWORD PTR tv2603[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2603[esp+180] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 9 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 9 + xor ebp, ebx + mov DWORD PTR tv2601[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2601[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2619[esp+180], ebx + add DWORD PTR tv2621[esp+180], ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + add edi, ebx + add ecx, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+4] + and edi, DWORD PTR [eax+ebx+4] + add eax, ebx + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + mov DWORD PTR tv959[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx] + xor ebx, edi + mov edi, DWORD PTR tv959[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR [ebp+4] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 10 + xor ebx, ebp + shr edi, 10 ; 0000000aH + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 16 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 16 ; 00000010H + xor ebp, ebx + mov DWORD PTR tv2597[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2597[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + add eax, ebx + mov DWORD PTR tv87[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv87[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 11 + shr edi, 11 ; 0000000bH + xor ebx, ebp + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 15 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 15 ; 0000000fH + xor ebp, ebx + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + mov DWORD PTR tv2593[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2593[esp+180] + add eax, ebx + add ecx, ebx + add edx, ebx + add esi, ebx + add DWORD PTR tv2619[esp+180], ebx + mov DWORD PTR [edi+4], ebp + add edi, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+4] + and edi, DWORD PTR [eax+4] + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + mov ebp, DWORD PTR [esi+4] + and ebp, DWORD PTR [edx+4] + mov DWORD PTR tv933[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx] + xor ebx, edi + mov edi, DWORD PTR tv933[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 12 + shr edi, 12 ; 0000000cH + xor ebx, ebp + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 9 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 9 + xor ebp, ebx + mov DWORD PTR tv2589[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2589[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + add eax, ebx + add esi, ebx + mov DWORD PTR tv142[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx+ebx] + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv142[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR _S$[esp+180] + xor edi, DWORD PTR _S$[esp+184] + mov ebp, ebx + mov DWORD PTR _x$[esp+184], edi + shrd ebp, edi, 2 + shr edi, 2 + mov DWORD PTR tv2587[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2587[esp+180] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 27 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 27 ; 0000001bH + xor ebp, ebx + mov DWORD PTR tv2585[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2585[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + add ecx, ebx + mov DWORD PTR tv160[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add eax, ebx + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv160[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 7 + shr edi, 7 + mov DWORD PTR tv2583[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2583[esp+180] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 15 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 15 ; 0000000fH + xor ebp, ebx + mov DWORD PTR tv2581[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2581[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2619[esp+180], ebx + add DWORD PTR tv2621[esp+180], ebx +; Line 223 + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + add edi, ebx + add ecx, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+4] + and edi, DWORD PTR [eax+ebx+4] + add eax, ebx + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + mov DWORD PTR tv905[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx] + xor ebx, edi + mov edi, DWORD PTR tv905[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 14 + xor ebx, ebp + shr edi, 14 ; 0000000eH + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 6 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 6 + xor ebp, ebx + mov DWORD PTR tv2577[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2577[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + add eax, ebx + mov DWORD PTR tv380[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv380[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 15 + shr edi, 15 ; 0000000fH + xor ebx, ebp + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 2 + xor edi, DWORD PTR _x$[esp+184] + add ebp, ebp + add ebp, ebp + xor ebp, ebx + mov DWORD PTR tv2573[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov ebx, 8 + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2573[esp+180] + add eax, ebx + add ecx, ebx + mov DWORD PTR [edi+4], ebp + add edx, ebx + add edi, ebx + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+4] + and edi, DWORD PTR [eax+4] + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+4] + mov DWORD PTR tv717[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx] + add esi, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv717[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 7 + shr edi, 7 + mov DWORD PTR tv2571[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2571[esp+180] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 29 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 29 ; 0000001dH + mov DWORD PTR tv2569[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + xor ebp, ebx + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2569[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + add edi, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + add eax, ebx + add esi, ebx + mov DWORD PTR tv869[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx+ebx] + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv869[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 13 + shr edi, 13 ; 0000000dH + mov DWORD PTR tv2567[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2567[esp+180] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 8 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 8 + xor ebp, ebx + mov DWORD PTR tv2565[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2565[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + mov DWORD PTR tv264[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add eax, ebx + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv264[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 11 + shr edi, 11 ; 0000000bH + mov DWORD PTR tv2563[esp+180], edi + mov edi, DWORD PTR _x$[esp+184] + xor ebx, ebp + mov ebp, DWORD PTR tv2563[esp+180] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 15 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 15 ; 0000000fH + xor ebp, ebx + mov DWORD PTR tv2561[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2561[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + add edi, ebx + add ecx, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+4] + and edi, DWORD PTR [eax+ebx+4] + add eax, ebx + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + mov DWORD PTR tv185[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx] + xor ebx, edi + mov edi, DWORD PTR tv185[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 7 + xor ebx, ebp + shr edi, 7 + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 5 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 5 + xor ebp, ebx + mov DWORD PTR tv2557[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2557[esp+180] + mov DWORD PTR [edi+4], ebp + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+ebx+4] + add ecx, ebx + add eax, ebx + mov DWORD PTR tv218[esp+184], edi + mov edi, DWORD PTR [esi+ebx] + and edi, DWORD PTR [edx+ebx] + add esi, ebx + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv218[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 6 + shr edi, 6 + xor ebx, ebp + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 31 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 31 ; 0000001fH + xor ebp, ebx + mov DWORD PTR tv2553[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2553[esp+180] + mov ebx, 8 + mov DWORD PTR [edi+4], ebp + add eax, ebx + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add edi, ebx + mov ebp, DWORD PTR [esi+ebx+4] + and ebp, DWORD PTR [edx+ebx+4] + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR [ecx+ebx+4] + and edi, DWORD PTR [eax+4] + add ecx, ebx + add esi, ebx + mov DWORD PTR tv271[esp+184], edi + mov edi, DWORD PTR [esi] + and edi, DWORD PTR [edx+ebx] + add edx, ebx + mov ebx, DWORD PTR [ecx] + and ebx, DWORD PTR [eax] + xor ebx, edi + mov edi, DWORD PTR tv271[esp+184] + xor edi, ebp + mov ebp, DWORD PTR tv2619[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + mov ebp, DWORD PTR tv2621[esp+180] + xor edi, DWORD PTR [ebp+4] + xor ebx, DWORD PTR [ebp] + xor edi, DWORD PTR _S$[esp+184] + xor ebx, DWORD PTR _S$[esp+180] + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shrd ebp, edi, 12 + shr edi, 12 ; 0000000cH + xor ebx, ebp + mov ebp, edi + mov edi, DWORD PTR _x$[esp+184] + xor edi, ebp + mov DWORD PTR _x$[esp+184], edi + mov ebp, ebx + shld edi, ebp, 9 + xor edi, DWORD PTR _x$[esp+184] + shl ebp, 9 + xor ebp, ebx + mov DWORD PTR tv2549[esp+180], edi + mov edi, DWORD PTR tv1969[esp+180] + mov DWORD PTR [edi], ebp + mov ebp, DWORD PTR tv2549[esp+180] + mov ebx, 8 + add DWORD PTR tv2621[esp+180], ebx + add DWORD PTR tv2619[esp+180], ebx + add esi, ebx + mov DWORD PTR [edi+4], ebp + add edi, ebx + mov DWORD PTR tv2623[esp+180], esi +; Line 226 + mov esi, DWORD PTR _S$[esp+184] + add eax, ebx + add ecx, ebx + add edx, ebx + mov DWORD PTR tv1969[esp+180], edi + mov edi, DWORD PTR _S$[esp+180] + mov ebx, esi + shr esi, 31 ; 0000001fH + xor ebp, ebp + and edi, 606457760 ; 2425cfa0H + and ebx, 1930543745 ; 7311c281H + xor edi, esi + mov esi, DWORD PTR _S$[esp+180] + xor ebx, ebp + mov ebp, DWORD PTR _S$[esp+184] + shld ebp, esi, 1 + add esi, esi + xor edi, esi + xor ebx, ebp + sub DWORD PTR tv769[esp+180], 1 + mov DWORD PTR _S$[esp+180], edi + mov DWORD PTR _S$[esp+184], ebx + jne $LL8@md6_main_c + pop esi + pop ebp + pop ebx +$LN1@md6_main_c: + pop edi +; Line 229 + add esp, 164 ; 000000a4H + ret 0 +_md6_main_compression_loop ENDP +_TEXT ENDS +PUBLIC _md6_compress +EXTRN _free:PROC +EXTRN _calloc:PROC +EXTRN _memset:PROC +; Function compile flags: /Ogtpy +; COMDAT _md6_compress +_TEXT SEGMENT +_C$ = 8 ; size = 4 +_N$ = 12 ; size = 4 +_r$ = 16 ; size = 4 +_A_as_given$ = 20 ; size = 4 +_A$ = 20 ; size = 4 +_md6_compress PROC ; COMDAT +; Line 257 + push ebx + mov ebx, DWORD PTR _A$[esp] + push esi +; Line 260 + mov esi, DWORD PTR _N$[esp+4] + test esi, esi + mov DWORD PTR _A_as_given$[esp+4], ebx + jne SHORT $LN7@md6_compre + pop esi + mov eax, 9 + pop ebx +; Line 279 + ret 0 +$LN7@md6_compre: +; Line 261 + cmp DWORD PTR _C$[esp+4], 0 + jne SHORT $LN6@md6_compre + pop esi + mov eax, 15 ; 0000000fH + pop ebx +; Line 279 + ret 0 +$LN6@md6_compre: + push ebp +; Line 262 + mov ebp, DWORD PTR _r$[esp+8] + cmp ebp, 255 ; 000000ffH + ja SHORT $LN4@md6_compre +; Line 264 + test ebx, ebx + jne SHORT $LN2@md6_compre + mov eax, ebp + shl eax, 4 + add eax, 89 ; 00000059H + push 8 + push eax + call _calloc + mov ebx, eax + add esp, 8 +; Line 265 + test ebx, ebx + jne SHORT $LN2@md6_compre + pop ebp + pop esi + mov eax, 18 ; 00000012H + pop ebx +; Line 279 + ret 0 +$LN2@md6_compre: + push edi +; Line 269 + push ebp + mov ecx, 178 ; 000000b2H + mov edi, ebx + push ebx + rep movsd + call _md6_main_compression_loop +; Line 271 + mov edi, DWORD PTR _C$[esp+20] + shl ebp, 7 + add esp, 8 +; Line 273 + cmp DWORD PTR _A_as_given$[esp+12], 0 + lea esi, DWORD PTR [ebx+ebp+584] + mov ecx, 32 ; 00000020H + rep movsd + pop edi + jne SHORT $LN1@md6_compre +; Line 274 + add ebp, 712 ; 000002c8H + push ebp + push 0 + push ebx + call _memset +; Line 275 + push ebx + call _free + add esp, 16 ; 00000010H +$LN1@md6_compre: + pop ebp + pop esi +; Line 278 + xor eax, eax + pop ebx +; Line 279 + ret 0 +$LN4@md6_compre: + pop ebp + pop esi +; Line 262 + mov eax, 17 ; 00000011H + pop ebx +; Line 279 + ret 0 +_md6_compress ENDP +_TEXT ENDS +PUBLIC _md6_make_control_word +; Function compile flags: /Ogtpy +; COMDAT _md6_make_control_word +_TEXT SEGMENT +_r$ = 8 ; size = 4 +_L$ = 12 ; size = 4 +_z$ = 16 ; size = 4 +_p$ = 20 ; size = 4 +_keylen$ = 24 ; size = 4 +_d$ = 28 ; size = 4 +_md6_make_control_word PROC ; COMDAT +; Line 311 + mov eax, DWORD PTR _r$[esp-4] + cdq + shld edx, eax, 8 + shl eax, 8 + mov ecx, eax + mov eax, DWORD PTR _L$[esp-4] + push esi + mov esi, edx + cdq + or ecx, eax + mov eax, DWORD PTR _z$[esp] + or esi, edx + shld esi, ecx, 4 + shl ecx, 4 + cdq + or ecx, eax + mov eax, DWORD PTR _p$[esp] + or esi, edx + shld esi, ecx, 16 + cdq + shl ecx, 16 ; 00000010H + or ecx, eax + mov eax, DWORD PTR _keylen$[esp] + or esi, edx + shld esi, ecx, 8 + cdq + shl ecx, 8 + or ecx, eax + mov eax, DWORD PTR _d$[esp] + or esi, edx + shld esi, ecx, 12 + cdq + shl ecx, 12 ; 0000000cH + or esi, edx + or ecx, eax + mov edx, esi + mov eax, ecx + pop esi +; Line 312 + ret 0 +_md6_make_control_word ENDP +_TEXT ENDS +PUBLIC _md6_make_nodeID +; Function compile flags: /Ogtpy +; COMDAT _md6_make_nodeID +_TEXT SEGMENT +_ell$ = 8 ; size = 4 +_i$ = 12 ; size = 4 +_md6_make_nodeID PROC ; COMDAT +; Line 332 + mov eax, DWORD PTR _ell$[esp-4] + cdq + mov ecx, eax + mov eax, DWORD PTR _i$[esp-4] + cdq + push esi + xor esi, esi + shl ecx, 24 ; 00000018H + or esi, eax + or ecx, edx + mov eax, esi + mov edx, ecx + pop esi +; Line 333 + ret 0 +_md6_make_nodeID ENDP +_TEXT ENDS +PUBLIC _md6_pack +; Function compile flags: /Ogtpy +; COMDAT _md6_pack +_TEXT SEGMENT +_N$ = 8 ; size = 4 +_Q$ = 12 ; size = 4 +_K$ = 16 ; size = 4 +_ell$ = 20 ; size = 4 +_i$ = 24 ; size = 4 +_r$ = 28 ; size = 4 +_L$ = 32 ; size = 4 +_z$ = 36 ; size = 4 +_p$ = 40 ; size = 4 +_keylen$ = 44 ; size = 4 +_d$ = 48 ; size = 4 +_B$ = 52 ; size = 4 +_md6_pack PROC ; COMDAT +; Line 351 + mov ecx, DWORD PTR _N$[esp-4] +; Line 353 + mov edx, DWORD PTR _Q$[esp-4] + push esi + push edi + mov eax, ecx + sub edx, ecx + mov esi, 15 ; 0000000fH +$LL6@md6_pack: + mov edi, DWORD PTR [edx+eax] + mov DWORD PTR [eax], edi + mov edi, DWORD PTR [edx+eax+4] + mov DWORD PTR [eax+4], edi + add eax, 8 + sub esi, 1 + jne SHORT $LL6@md6_pack +; Line 355 + mov eax, DWORD PTR _K$[esp+4] + mov edx, DWORD PTR [eax] + mov DWORD PTR [ecx+120], edx + mov edx, DWORD PTR [eax+4] + mov DWORD PTR [ecx+124], edx + mov edx, DWORD PTR [eax+8] + mov DWORD PTR [ecx+128], edx + mov edx, DWORD PTR [eax+12] + mov DWORD PTR [ecx+132], edx + mov edx, DWORD PTR [eax+16] + mov DWORD PTR [ecx+136], edx + mov edx, DWORD PTR [eax+20] + mov DWORD PTR [ecx+140], edx + mov edx, DWORD PTR [eax+24] + mov DWORD PTR [ecx+144], edx + mov edx, DWORD PTR [eax+28] + mov DWORD PTR [ecx+148], edx + mov edx, DWORD PTR [eax+32] + mov DWORD PTR [ecx+152], edx + mov edx, DWORD PTR [eax+36] + mov DWORD PTR [ecx+156], edx + mov edx, DWORD PTR [eax+40] + mov DWORD PTR [ecx+160], edx + mov edx, DWORD PTR [eax+44] + mov DWORD PTR [ecx+164], edx + mov edx, DWORD PTR [eax+48] + mov DWORD PTR [ecx+168], edx + mov edx, DWORD PTR [eax+52] + mov DWORD PTR [ecx+172], edx + mov edx, DWORD PTR [eax+56] + mov DWORD PTR [ecx+176], edx + mov eax, DWORD PTR [eax+60] + mov DWORD PTR [ecx+180], eax +; Line 357 + mov eax, DWORD PTR _ell$[esp+4] + cdq + mov esi, eax + mov eax, DWORD PTR _i$[esp+4] + cdq + shl esi, 24 ; 00000018H + or esi, edx + xor edi, edi + or edi, eax +; Line 367 + mov eax, DWORD PTR _r$[esp+4] + cdq + shld edx, eax, 8 + mov DWORD PTR [ecx+188], esi + shl eax, 8 + mov DWORD PTR [ecx+184], edi + mov esi, eax + mov eax, DWORD PTR _L$[esp+4] + mov edi, edx + cdq + or esi, eax + mov eax, DWORD PTR _z$[esp+4] + or edi, edx + shld edi, esi, 4 + shl esi, 4 + cdq + or esi, eax + mov eax, DWORD PTR _p$[esp+4] + or edi, edx + shld edi, esi, 16 + shl esi, 16 ; 00000010H + cdq + or esi, eax + mov eax, DWORD PTR _keylen$[esp+4] + or edi, edx + shld edi, esi, 8 + shl esi, 8 + cdq + or esi, eax + mov eax, DWORD PTR _d$[esp+4] + or edi, edx + shld edi, esi, 12 + cdq + shl esi, 12 ; 0000000cH + or esi, eax + or edi, edx +; Line 373 + mov DWORD PTR [ecx+196], edi + mov DWORD PTR [ecx+192], esi +; Line 376 + lea edi, DWORD PTR [ecx+200] + mov esi, DWORD PTR _B$[esp+4] + mov ecx, 128 ; 00000080H + rep movsd + pop edi + pop esi +; Line 377 + ret 0 +_md6_pack ENDP +_TEXT ENDS +PUBLIC _md6_standard_compress +EXTRN __chkstk:PROC +; Function compile flags: /Ogtpy +; COMDAT _md6_standard_compress +_TEXT SEGMENT +_N$ = -40712 ; size = 712 +_A$ = -40000 ; size = 40000 +_C$ = 8 ; size = 4 +_Q$ = 12 ; size = 4 +_K$ = 16 ; size = 4 +_ell$ = 20 ; size = 4 +_i$ = 24 ; size = 4 +_r$ = 28 ; size = 4 +_L$ = 32 ; size = 4 +_z$ = 36 ; size = 4 +_p$ = 40 ; size = 4 +_keylen$ = 44 ; size = 4 +_d$ = 48 ; size = 4 +_B$ = 52 ; size = 4 +_md6_standard_compress PROC ; COMDAT +; Line 411 + mov eax, 40712 ; 00009f08H + call __chkstk +; Line 415 + cmp DWORD PTR _C$[esp+40708], 0 + jne SHORT $LN13@md6_standa + mov eax, 15 ; 0000000fH +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN13@md6_standa: +; Line 416 + cmp DWORD PTR _B$[esp+40708], 0 + jne SHORT $LN12@md6_standa + mov eax, 10 ; 0000000aH +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN12@md6_standa: +; Line 417 + xor eax, eax + push esi + mov esi, DWORD PTR _r$[esp+40712] + cmp esi, 255 ; 000000ffH + setg al + xor ecx, ecx + test esi, esi + setl cl + or eax, ecx + je SHORT $LN11@md6_standa + mov eax, 17 ; 00000011H + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN11@md6_standa: +; Line 418 + xor edx, edx + push ebx + mov ebx, DWORD PTR _L$[esp+40716] + cmp ebx, 255 ; 000000ffH + setg dl + xor eax, eax + test ebx, ebx + setl al + or edx, eax + je SHORT $LN10@md6_standa + pop ebx + mov eax, 16 ; 00000010H + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN10@md6_standa: +; Line 419 + mov ecx, DWORD PTR _ell$[esp+40716] + cmp ecx, 255 ; 000000ffH + ja $LN8@md6_standa +; Line 420 + mov edx, DWORD PTR _p$[esp+40716] + cmp edx, 4096 ; 00001000H + ja $LN6@md6_standa +; Line 421 + mov eax, DWORD PTR _d$[esp+40716] + push edi + lea edi, DWORD PTR [eax-1] + cmp edi, 511 ; 000001ffH + ja $LN4@md6_standa + push ebp +; Line 422 + mov ebp, DWORD PTR _K$[esp+40724] + test ebp, ebp + jne SHORT $LN3@md6_standa + pop ebp + pop edi + pop ebx + mov eax, 13 ; 0000000dH + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN3@md6_standa: +; Line 423 + mov edi, DWORD PTR _Q$[esp+40724] + test edi, edi + jne SHORT $LN2@md6_standa + pop ebp + pop edi + pop ebx + mov eax, 14 ; 0000000eH + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN2@md6_standa: +; Line 426 + push DWORD PTR _B$[esp+40724] + push eax + mov eax, DWORD PTR _keylen$[esp+40732] + push eax + mov eax, DWORD PTR _i$[esp+40736] + push edx + mov edx, DWORD PTR _z$[esp+40740] + push edx + push ebx + push esi + push eax + push ecx + push ebp + lea ecx, DWORD PTR _N$[esp+40768] + push edi + push ecx + call _md6_pack +; Line 430 + mov eax, DWORD PTR _compression_hook + add esp, 48 ; 00000030H + test eax, eax + je SHORT $LN16@md6_standa +; Line 431 + mov edx, DWORD PTR _B$[esp+40724] + mov ecx, DWORD PTR _d$[esp+40724] + push edx + mov edx, DWORD PTR _keylen$[esp+40728] + push ecx + mov ecx, DWORD PTR _p$[esp+40732] + push edx + mov edx, DWORD PTR _z$[esp+40736] + push ecx + mov ecx, DWORD PTR _i$[esp+40740] + push edx + mov edx, DWORD PTR _ell$[esp+40744] + push ebx + push esi + push ecx + mov ecx, DWORD PTR _C$[esp+40756] + push edx + push ebp + push edi + push ecx + call eax + add esp, 48 ; 00000030H +$LN16@md6_standa: +; Line 433 + mov ecx, DWORD PTR _C$[esp+40724] + lea edx, DWORD PTR _A$[esp+40728] + push edx + push esi + lea eax, DWORD PTR _N$[esp+40736] + push eax + push ecx + call _md6_compress + add esp, 16 ; 00000010H + pop ebp + pop edi + pop ebx + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN4@md6_standa: + pop edi + pop ebx +; Line 421 + mov eax, 2 + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN6@md6_standa: + pop ebx +; Line 420 + mov eax, 12 ; 0000000cH + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +$LN8@md6_standa: + pop ebx +; Line 419 + mov eax, 11 ; 0000000bH + pop esi +; Line 434 + add esp, 40712 ; 00009f08H + ret 0 +_md6_standard_compress ENDP +_TEXT ENDS +END Index: trunk/C_implementation/md6_nist.c =================================================================== --- trunk/C_implementation/md6_nist.c (nonexistent) +++ trunk/C_implementation/md6_nist.c (revision 2) @@ -0,0 +1,96 @@ +/* File: md6_nist.c +** Author: Ronald L. Rivest +** Address: Room 32G-692 Stata Center +** 32 Vassar Street +** Cambridge, MA 02139 +** Email: rivest@mit.edu +** Date: 9/25/2008 +** +** (The following license is known as "The MIT License") +** +** Copyright (c) 2008 Ronald L. Rivest +** +** 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. +** +** (end of license) +** +** This is part of the definition of the MD6 hash function. +** The files defining the MD6 hash function are: +** md6.h +** md6_compress.c +** md6_mode.c +** +** The files defining the interface between MD6 and the NIST SHA-3 +** API are: +** md6_nist.h +** md6_nist.c +** The NIST SHA-3 API is defined in: +** http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf +** +** See http://groups.csail.mit.edu/cis/md6 for more information. +*/ + +#include +#include "md6.h" +#include "md6_nist.h" + +HashReturn Init( hashState *state, + int hashbitlen + ) +{ int err; + if ((err = md6_init( (md6_state *) state, + hashbitlen + ))) + return err; + state->hashbitlen = hashbitlen; + return SUCCESS; +} + +HashReturn Update( hashState *state, + const BitSequence *data, + DataLength databitlen + ) +{ return md6_update( (md6_state *) state, + (unsigned char *)data, + (uint64_t) databitlen ); +} + +HashReturn Final( hashState *state, + BitSequence *hashval + ) +{ return md6_final( (md6_state *) state, + (unsigned char *) hashval + ); +} + +HashReturn Hash( int hashbitlen, + const BitSequence *data, + DataLength databitlen, + BitSequence *hashval + ) +{ int err; + md6_state state; + if ((err = Init( &state, hashbitlen ))) + return err; + if ((err = Update( &state, data, databitlen ))) + return err; + return Final( &state, hashval ); +} + + Index: trunk/C_implementation/inttypes.h =================================================================== --- trunk/C_implementation/inttypes.h (nonexistent) +++ trunk/C_implementation/inttypes.h (revision 2) @@ -0,0 +1,305 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] Index: trunk/C_implementation/gwt.exe.out.txt =================================================================== --- trunk/C_implementation/gwt.exe.out.txt (nonexistent) +++ trunk/C_implementation/gwt.exe.out.txt (revision 2) @@ -0,0 +1,65 @@ +Table of weights of min-weight ginv outputs for ginv inputs of weight 1 (i.e. of gamma(r,ell)) + ell= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 +r= 1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 +r= 2: 2 1 6 2 10 3 14 4 18 5 22 6 26 7 25 8 24 9 23 10 22 11 21 12 20 13 19 14 18 15 17 16 16 16 15 15 14 14 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 +r= 3: 3 6 1 12 15 2 20 19 3 19 18 4 18 17 5 17 16 6 16 15 7 15 14 8 14 13 9 13 12 10 12 11 11 11 10 10 10 9 9 9 8 8 8 7 7 7 6 6 6 5 5 5 4 4 4 3 3 3 2 2 2 1 1 +r= 4: 4 2 12 1 15 6 15 2 14 10 14 3 13 13 13 4 12 12 12 5 11 11 11 6 10 10 10 7 9 9 9 8 8 8 8 8 7 7 7 7 6 6 6 6 5 5 5 5 4 4 4 4 3 3 3 3 2 2 2 2 1 1 1 +r= 5: 5 10 13 13 1 12 12 12 12 2 11 11 11 11 3 10 10 10 10 4 9 9 9 9 5 8 8 8 8 6 7 7 7 7 6 6 6 6 6 5 5 5 5 5 4 4 4 4 4 3 3 3 3 3 2 2 2 2 2 1 1 1 1 +r= 6: 6 3 2 6 10 1 10 10 6 10 9 2 9 9 9 9 8 3 8 8 8 8 7 4 7 7 7 7 6 5 6 6 6 6 5 5 5 5 5 5 4 4 4 4 4 4 3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 1 +r= 7: 7 9 9 9 9 9 1 9 8 8 8 8 8 2 8 7 7 7 7 7 3 7 6 6 6 6 6 4 6 5 5 5 5 5 5 5 4 4 4 4 4 4 4 3 3 3 3 3 3 3 2 2 2 2 2 2 2 1 1 1 1 1 1 +r= 8: 8 4 8 2 8 8 8 1 7 7 7 6 7 7 7 2 6 6 6 6 6 6 6 3 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 +r= 9: 8 7 3 7 7 6 7 7 1 7 6 6 6 6 6 6 6 2 6 5 5 5 5 5 5 5 3 5 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 +r=10: 7 5 7 7 2 6 6 6 6 1 6 6 6 6 5 5 5 5 5 2 5 5 5 5 4 4 4 4 4 3 4 4 4 4 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 +r=11: 6 6 6 6 6 6 6 6 6 5 1 5 5 5 5 5 5 5 5 5 4 2 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +r=12: 6 6 4 3 5 2 5 5 5 5 5 1 5 5 5 5 4 4 4 4 4 4 4 2 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 +r=13: 5 5 5 5 5 5 5 5 5 5 5 5 1 4 4 4 4 4 4 4 4 4 4 4 4 2 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +r=14: 5 5 5 5 5 5 2 5 4 4 4 4 4 1 4 4 4 4 4 4 4 4 3 3 3 3 3 2 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=15: 5 5 5 5 3 4 4 4 4 4 4 4 4 4 1 4 4 4 4 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=16: 4 4 4 4 4 4 4 2 4 4 4 4 4 4 4 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=17: 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=18: 4 4 4 4 4 3 4 4 2 4 3 3 3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=19: 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 1 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=20: 4 4 4 4 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 1 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=21: 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=22: 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=23: 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=24: 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=25: 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=26: 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=27: 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=28: 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=29: 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=30: 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=31: 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=32: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=33: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=34: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=35: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=36: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=37: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=38: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=39: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=40: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=41: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=42: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=43: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=44: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=45: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=46: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=47: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=48: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=49: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=50: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=51: 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=52: 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=53: 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=54: 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=55: 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=56: 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=57: 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=58: 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=59: 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=60: 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=61: 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=62: 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +r=63: 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Index: trunk/C_implementation/treewalk.py =================================================================== --- trunk/C_implementation/treewalk.py (nonexistent) +++ trunk/C_implementation/treewalk.py (revision 2) @@ -0,0 +1,61 @@ +# treewalk.py +# Ronald L. Rivest +# 9/14/07 +# Compute hash of sequence D[0..n-1] +# by first applying leaf_hash to each D[i] +# and then applying combine_hash(x,y) to each +# pair to reduce number of values by two, repeatedly +# until only one value is left. (Complicated way of +# saying that we are computing up a binary tree....) +# Hash of an empty subtree (no leaves) is zero by definition. + +def H(i,k): + """ + Compute level-k hash function on D[i..i+(2**k)-1] + k = level of hash; k = 0 for leaf, parent has level = 1 + level(child) + k = Infinity for initial call. + Assume X(i) == True iff D[i] exists (i.e. i is not past EOF). + In sequential implementation, X called on non-decreasing values for i. + """ + if not X(i): + return 0 # empty subtree + if k == 0: + return leaf_hash(D[i]) # leaf + if k != Infinity: + # CILK spawn: + L = H(i,k-1) # left subtree + # CILK spawn: + R = H(i+2**(k-1),k-1) # right subtree + # CILK sync: + return combine_hash(L,R) # combine them + else: + # determine correct level k dynamically + k = 0 + L = H(i,k) + while X(i+2**k): + # now L = hash on D[i..i+2**k-1] + R = H(i+2**k,k) + L = combine_hash(L,R) + k += 1 + return L + +def leaf_hash(D): + """ Dummy leaf_hash just returns input """ + return D + +def combine_hash(L,R): + """ Dummy combine_hash just returns sum of inputs """ + return L+R + +# Global variable array D is input to be hashed +D = range(20) + +def X(i): + """ Test if D[i] exists """ + print "X",i + return i +#include +#include +#include + +#include "md6.h" + +#define w md6_w +#define c md6_c +#define n md6_n +#define b md6_b +#define u md6_u +#define v md6_v +#define k md6_k +#define q md6_q + +/* Useful macros: min and max */ +#ifndef min +#define min(a,b) ((a)<(b)? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a)>(b)? (a) : (b)) +#endif + + /* Print state. +*/ + +void md6_print_state(md6_state* st) +/* +** print out an md6_state in a nice way. +*/ +{ + int i,j; + printf("\nPrintout of md6_state:\n"); + printf(" initialized = %d\n",st->initialized); + printf(" finalized = %d\n",st->finalized); + printf(" hashbitlen = %d\n",st->hashbitlen); + printf(" Key:\n"); + for (i=0;iK[i])); + printf(" L = %d\n",st->L); + printf(" r = %d\n",st->r); + printf(" Bits processed = %lld\n",(uint64_t)st->bits_processed); + printf(" Stack top = %d\n",st->top); + printf(" N:\n"); + for (j = 0;jtop;i++) + printf("%4d %4d " PR_MD6_WORD,i,j,(md6_word)st->B[i][j]); + printf("\n"); + } + printf(" Bits on each level:\n"); + for (i=0;i<=st->top;i++) + printf(" Level %2d: %2d\n",i,st->bits[i]); + printf(" Hash Value:\n"); + for (i=0;ihashval[i]); + if (i%8==7) printf(" "); + if (i%32==31) printf("\n"); + } + printf(" Hex Hash Value:\n"); + printf(" %s\n",st->hexhashval); + printf("End of md6_state printout.\n\n"); +} + + +void md6_print_hash(md6_state *st) +/* +** print out the hash value stored in the md6 state +*/ +{ + printf("%s",st->hexhashval); +} + + +void md6_string(unsigned char *M, + int rep, + unsigned char *key, + int d) +/* +** Compute the md6 hash of a zero-terminated input byte string M +** repeated rep times. Print this hash value out with a trailing space +** and carriage return. +** Input: +** M input array of length m bytes +** rep number of times to repeat M +** key input zero-terminated key string +** d desired output hash size, in bits 1 <= d <= (c*w/2) +** (c*w/2 = 512 bits) +*/ +{ + md6_state st; + uint64_t m; + int i, keylen; + int err; + + m = strlen((char *)M); + keylen = (int)strlen((char *)key); + + /* check that input values are sensible */ + assert(( M != NULL )); + assert(( (key == NULL) || ( (0<=keylen) && (keylen <= k*(w/8))) ) ); + assert(( (1 <= d) && (d <= c*w/2) )); + + /* printf("md6_string..."); */ + + if ((err=md6_full_init(&st,d,key,keylen,md6_default_L,md6_default_r(d)))) + printf("Error code: %d\n",err); + for (i=0;i1) printf(" * %d",rep); + printf("\n"); +} + + +static void md6_file(char *filename) +/* +** compute and print out hash value for a file with given filename. +*/ +{ + FILE *inFile = fopen (filename, "rb"); + md6_state st; + uint64_t bytes; + unsigned char data[1024]; + int err; + + if (inFile == NULL) { + printf ("%s can't be opened.\n", filename); + return; + } + + if ((err=md6_init(&st,256))) + printf("Error code: %d\n",err); + while ((bytes = fread (data, 1, 1024, inFile)) != 0) + if ((err=md6_update(&st, data, bytes*8))) + printf("Error code: %d\n",err); + if ((err=md6_final(&st,NULL))) + printf("Error code: %d\n",err); + md6_print_hash(&st); + printf (" file: %s\n", filename); + fclose (inFile); +} + + +void md6_test_1(void) +/* +** run a simple set of test values +*/ +{ unsigned char *key; + int d; + + printf("------------------------------------------------------------\n"); + printf("md6_test_1: start. [simple test suite]\n"); + printf(">> string * n means string repeated n times.\n\n"); + + key = (unsigned char *)""; /* yields all-zero key */ + d = min(256,c*w/2); + printf(">> Key is all zeros.\n"); + printf(">> Hash Bit Length is %d bits.\n",d); + md6_string((unsigned char *)"",1,key,d); + md6_string((unsigned char *)"a",1,key,d); + md6_string((unsigned char *)"abc",1,key,d); + md6_string((unsigned char *)"abcdefghijklmnopqrstuvwxyz",1,key,d); + md6_string((unsigned char *)"1234567890",1000000,key,d); + printf("\n"); + + key = (unsigned char *)"abcd1234"; + d = min(256,c*w/2); + printf(">> Key is '%s'.\n",key); + printf(">> Hash Bit Length is %d bits.\n",d); + md6_string((unsigned char *)"",1,key,d); + md6_string((unsigned char *)"a",1,key,d); + md6_string((unsigned char *)"abc",1,key,d); + md6_string((unsigned char *)"abcdefghijklmnopqrstuvwxyz",1,key,d); + md6_string((unsigned char *)"1234567890",1000000,key,d); + printf("\n"); + + key = (unsigned char *)""; /* yields all-zero key */ + d = min(160,c*w/2); + printf(">> Key is all zeros.\n"); + printf(">> Hash Bit Length is %d bits.\n",d); + md6_string((unsigned char *)"",1,key,d); + md6_string((unsigned char *)"a",1,key,d); + md6_string((unsigned char *)"abc",1,key,d); + md6_string((unsigned char *)"abcdefghijklmnopqrstuvwxyz",1,key,d); + md6_string((unsigned char *)"1234567890",1000000,key,d); + printf("\n"); + + printf("md6_test_1: end.\n\n"); +} + + +/* +** rdtsc() +** returns CPU cycle counter using RDTSC intruction +** see http://en.wikipedia.org/wiki/RDTSC +** GNU Version -- see wikipedia for Microsoft Visual C++ version +** following routine is copied from Wikipedia page referenced above +* UNTESTED SO FAR... +*/ +#if 0 +extern "C" { + __inline__ uint64_t rdtsc() { + uint32_t lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + /* we cannot use "=A" since this would use %rax on x86_64 */ + return (uint64_t)hi << 32 | lo; + } +} +#endif + + + +void md6_test_2(void) +/* +** run a simple time trial +*/ +#define TEST_BLOCK_SIZE 100000 /* 10**5 bytes*/ +#define TEST_BLOCKS 1000 /* 10**3 */ +#define TEST_BYTES (TEST_BLOCKS*TEST_BLOCK_SIZE) /* 10**9 bytes */ +{ md6_state st; + double endTime, startTime; + unsigned char data[TEST_BLOCK_SIZE]; + unsigned long long int i; + unsigned int dvals[] = {160,224,256,384,512}; + int ndvals = 5; + int err; + md6_word A[md6_max_r*c+n]; + int j; + int d; + + printf("------------------------------------------------------------\n"); + printf("md6_test_2: start. [time trial]\n"); + printf(">> Key is all zeros.\n"); + printf ("Processing %lld characters...\n", (long long)TEST_BYTES); + + /* initialize test data */ + for (i = 0; i < TEST_BLOCK_SIZE; i++) + data[i] = (unsigned char)(i & 0xFF); + + for (j=0;j 0; i--) + if ((err=md6_update (&st, data, 8*TEST_BLOCK_SIZE))) + printf("Error code %d\n",err); + if ((err = md6_final(&st,NULL))) + printf("Error code: %d\n",err); + + endTime = ((double)clock())/CLOCKS_PER_SEC; + md6_print_hash(&st);printf (" is hash of test input.\n"); + printf + ("time to process test input: %.3f seconds.\n", (endTime-startTime)); + if (endTime>startTime) + printf + ("md6 bytes per second: %f\n", TEST_BYTES/(endTime-startTime)); + printf("md6 time per compression function (512 bytes) = %g microseconds.\n", + (((endTime-startTime))*1.0e6 / (4.0*TEST_BYTES/(3.0*512.0)))); + /* there are 4/3 as many c.f. operations as bytes/512, due to tree */ + + /* Now look at time just to do that many compression operations. */ + printf("Now computing time for just the compression function portions...\n"); + md6_init(&st,d); + startTime = ((double)clock())/CLOCKS_PER_SEC; + for (i=0;i<(long long)TEST_BYTES*4/(3*b*(w/8));i++) + md6_main_compression_loop(A,md6_default_r(d)); + endTime = ((double)clock())/CLOCKS_PER_SEC; + printf + ("time to process test input: %.3f seconds.\n", (endTime-startTime)); + if (endTime>startTime) + printf("md6 bytes per second: %g\n", TEST_BYTES/(endTime-startTime)); + printf("md6 time per compression function (512 bytes) = %g microseconds.\n", + (((endTime-startTime))*1.0e6 / (4.0*TEST_BYTES/(3.0*512.0)))); + } /* end of loop on j for different d's */ + + printf("md6_test_2: end.\n\n"); +} + + /* testing and debugging */ + +/* Global variables used by compression_hook_1 */ +FILE *outFile; +int hook_print_intermediate_values; + +void compression_hook_1(md6_word *C, + const md6_word *Q, + md6_word *K, + int ell, + int ii, + int r, + int L, + int z, + int p, + int keylen, + int d, + md6_word *B +) +{ int i; + // md6_word A[r*c+n]; + md6_word A[5000]; + + md6_pack(A,Q,K,ell,ii,r,L,z,p,keylen,d,B); + + md6_main_compression_loop( A, md6_default_r(d)); + + fprintf(outFile," MD6 compression function computation "); + fprintf(outFile,"(level %d, index %d):\n",ell,ii); + fprintf(outFile,"Inputs (%d words):\n",n); + for (i=0;i=q)&&(i0)&&(i==q+k+u-1)) + { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]); + fprintf(outFile," nodeID U = (ell,i) = (%d,%d)\n",ell,ii); + } + else if ((v>0)&&(i==q+k+u+v-1)) + { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]); + fprintf(outFile," control word V = " + "(r,L,z,p,keylen,d) = " + "(%d,%d,%d,%d,%d,%d)\n",r,L,z,p,keylen,d); + } + else if ((i>=q+k+u+v)&&(i=r*c+n-c)) + { if ((i==r*c+n-c)) + fprintf(outFile,"Output (%d words of chaining values):\n",c); + fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]); + fprintf(outFile," output chaining value C[%d]\n",i-(r*c+n-c)); + } + else + { if (i==n) + { if (hook_print_intermediate_values) + fprintf(outFile,"Intermediate values:\n"); + else + fprintf(outFile,"Intermediate values A[%d..%d] omitted...\n",n,r*c+n-c-1); + } + if (hook_print_intermediate_values) + fprintf(outFile,"A[%4d] = " PR_MD6_WORD "\n",i,A[i]); + } + } + fprintf(outFile,"\n"); +} + + /* Trace -- print out details of an md6 computation. +*/ + +void trace_md6 ( char* filename, + int print_intermediate_values, + char* M, + uint64_t m, + int d, + char* key, + int keylen, + int L, + int r + ) +/* +** print to file intermediate results of a hash function computation, +** for each compression function call +** M, m, d, L, r, key, keylen -- as usual +** (but assumes K is 0-terminated) +** filename = output file name +** print_intermediate_values = 1 to print non-I/O values of A +** = 0 to only print I/O values of A +*/ +{ + md6_state st; + time_t now; + int i; + int j; + + /* save switch regarding the printing of intermediate values + ** for compression_hook_1 to use later. + */ + hook_print_intermediate_values = print_intermediate_values; + + /* check that input values are sensible */ + assert(( M != NULL )); + assert(( (key == NULL) || ( (0<=keylen) && (keylen <= k*8) ) )); + assert(( (1 <= d) && (d <= c*w/2) )); + + outFile = fopen (filename, "w"); + if (outFile == NULL) + { printf( "%s can't be opened.\n", filename ); + printf( "trace_md6: aborted.\n" ); + return; + } + + fprintf(outFile,"Trace of md6 computation.\n"); + time(&now); + fprintf(outFile,"%s",ctime(&now)); + fprintf(outFile,"Filename: %s\n\n",filename); + fprintf(outFile,"d = %6d (digest length in bits)\n",d); + fprintf(outFile,"L = %6d (number of parallel passes)\n",L); + fprintf(outFile,"r = %6d (number of rounds)\n",r); + fprintf(outFile,"K = '%s' (key)\n",key); + fprintf(outFile,"k = %6d (key length in bytes)\n",keylen); + fprintf(outFile,"M = (hex) "); + for (i=0;i<18;i++) fprintf(outFile,"%02x ",M[i]); + fprintf(outFile,"...\n"); + fprintf(outFile," (input message repeats with period 7)\n"); + fprintf(outFile,"m = %6lld (message length in bits)\n",m); + fprintf(outFile," %6lld (message length in (full or partial) bytes)\n",(m+7)/8); + fprintf(outFile,"\n"); + + md6_full_init(&st,d,key,keylen,L,r); + compression_hook = compression_hook_1; /* must be done *after* init */ + md6_update(&st,M,(uint64_t)m); + md6_final(&st,NULL); + + fprintf(outFile,"Final hash value = \n"); + for (i=0; ihashval and state->hexhashval). +*/ + +extern int md6_init( md6_state *st, /* state to initialize */ + int d /* hash bit length */ + ); + +extern int md6_full_init( md6_state *st, /* state to initialize */ + int d, /* hash bit length */ + unsigned char *key, /* OK to give NULL */ + int keylen, /* (in bytes) OK to give 0 */ + int L, /* mode; OK to give md6_default_L */ + int r /* number of rounds */ + ); + +extern int md6_update( md6_state *st, /* initialized state */ + unsigned char *data, /* data portion */ + uint64_t datalen /* its length in bits */ + ); + +extern int md6_final( md6_state *st, /* initialized/updated */ + unsigned char *hashval, /* output; NULL OK */ + ); + +/* The next routines compute a hash for a message given all at once. +** The resulting hash value is returned to a specified location. +** Only one call is needed. Use md6_hash for the standard md6 hash, +** and md6_full_hash if you want to specify additional parameters. +*/ + +extern int md6_hash( int d, /* hash bit length */ + unsigned char *data, /* complete data to hash */ + uint64_t datalen /* its length in bits */ + unsigned char *hashval, /* output */ + ); + +extern int md6_full_hash( int d, /* hash bit length */ + unsigned char *data,/* complete data to hash */ + uint64_t datalen, /* its length in bits */ + unsigned char *key, /* OK to give NULL */ + int keylen, /* (in bytes) OK to give 0 */ + int L, /* mode; OK to give md6_default_L */ + int r, /* number of rounds */ + unsigned char *hashval, /* output */ + ); +#endif + + #include +#include +#include + +#include "md6.h" + +/* MD6 constants independent of mode of operation (from md6.h) */ +#define w md6_w /* # bits in a word (64) */ +#define n md6_n /* # words in compression input (89) */ +#define c md6_c /* # words in compression output (16) */ + +/* MD6 constants needed for mode of operation */ +#define q md6_q /* # words in Q (15) */ +#define k md6_k /* # words in key (aka salt) (8) */ +#define u md6_u /* # words in unique node ID (1) */ +#define v md6_v /* # words in control word (1) */ +#define b md6_b /* # data words per compression block (64) */ + +/* Useful macros: min and max */ +#ifndef min +#define min(a,b) ((a)<(b)? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a)>(b)? (a) : (b)) +#endif + +/* Default number of rounds (as a function of digest size d) */ +int md6_default_r( int d ) +{ + /* Default number of rounds is forty plus floor(d/4) */ + return 40 + (d/4); +} + + +/* MD6 Constant Vector Q +** Q = initial 960 bits of fractional part of sqrt(6) +** +** Given here for w = 64, 32, 16, and 8, although only +** w = 64 is needed for the standard version of MD6. +*/ + +#if (w==64) /* for standard version */ +/* 15 64-bit words */ +static const md6_word Q[15] = + { + 0x7311c2812425cfa0ULL, + 0x6432286434aac8e7ULL, + 0xb60450e9ef68b7c1ULL, + 0xe8fb23908d9f06f1ULL, + 0xdd2e76cba691e5bfULL, + 0x0cd0d63b2c30bc41ULL, + 0x1f8ccf6823058f8aULL, + 0x54e5ed5b88e3775dULL, + 0x4ad12aae0a6d6031ULL, + 0x3e7f16bb88222e0dULL, + 0x8af8671d3fb50c2cULL, + 0x995ad1178bd25c31ULL, + 0xc878c1dd04c4b633ULL, + 0x3b72066c7a1552acULL, + 0x0d6f3522631effcbULL, + }; +#endif + +#if (w==32) /* for variant version */ +/* 30 32-bit words */ +static const md6_word Q[30] = + { + 0x7311c281UL, 0x2425cfa0UL, + 0x64322864UL, 0x34aac8e7UL, + 0xb60450e9UL, 0xef68b7c1UL, + 0xe8fb2390UL, 0x8d9f06f1UL, + 0xdd2e76cbUL, 0xa691e5bfUL, + 0x0cd0d63bUL, 0x2c30bc41UL, + 0x1f8ccf68UL, 0x23058f8aUL, + 0x54e5ed5bUL, 0x88e3775dUL, + 0x4ad12aaeUL, 0x0a6d6031UL, + 0x3e7f16bbUL, 0x88222e0dUL, + 0x8af8671dUL, 0x3fb50c2cUL, + 0x995ad117UL, 0x8bd25c31UL, + 0xc878c1ddUL, 0x04c4b633UL, + 0x3b72066cUL, 0x7a1552acUL, + 0x0d6f3522UL, 0x631effcbUL, + }; +#endif + + /* MD6 Constant Vector Q (continued). +*/ + +#if (w==16) /* for variant version */ +/* 60 16-bit words */ +static const md6_word Q[60] = + { + 0x7311, 0xc281, 0x2425, 0xcfa0, + 0x6432, 0x2864, 0x34aa, 0xc8e7, + 0xb604, 0x50e9, 0xef68, 0xb7c1, + 0xe8fb, 0x2390, 0x8d9f, 0x06f1, + 0xdd2e, 0x76cb, 0xa691, 0xe5bf, + 0x0cd0, 0xd63b, 0x2c30, 0xbc41, + 0x1f8c, 0xcf68, 0x2305, 0x8f8a, + 0x54e5, 0xed5b, 0x88e3, 0x775d, + 0x4ad1, 0x2aae, 0x0a6d, 0x6031, + 0x3e7f, 0x16bb, 0x8822, 0x2e0d, + 0x8af8, 0x671d, 0x3fb5, 0x0c2c, + 0x995a, 0xd117, 0x8bd2, 0x5c31, + 0xc878, 0xc1dd, 0x04c4, 0xb633, + 0x3b72, 0x066c, 0x7a15, 0x52ac, + 0x0d6f, 0x3522, 0x631e, 0xffcb, + }; +#endif + +#if (w==8) /* for variant version */ +/* 120 8-bit words */ +static const md6_word Q[120] = + { + 0x73, 0x11, 0xc2, 0x81, 0x24, 0x25, 0xcf, 0xa0, + 0x64, 0x32, 0x28, 0x64, 0x34, 0xaa, 0xc8, 0xe7, + 0xb6, 0x04, 0x50, 0xe9, 0xef, 0x68, 0xb7, 0xc1, + 0xe8, 0xfb, 0x23, 0x90, 0x8d, 0x9f, 0x06, 0xf1, + 0xdd, 0x2e, 0x76, 0xcb, 0xa6, 0x91, 0xe5, 0xbf, + 0x0c, 0xd0, 0xd6, 0x3b, 0x2c, 0x30, 0xbc, 0x41, + 0x1f, 0x8c, 0xcf, 0x68, 0x23, 0x05, 0x8f, 0x8a, + 0x54, 0xe5, 0xed, 0x5b, 0x88, 0xe3, 0x77, 0x5d, + 0x4a, 0xd1, 0x2a, 0xae, 0x0a, 0x6d, 0x60, 0x31, + 0x3e, 0x7f, 0x16, 0xbb, 0x88, 0x22, 0x2e, 0x0d, + 0x8a, 0xf8, 0x67, 0x1d, 0x3f, 0xb5, 0x0c, 0x2c, + 0x99, 0x5a, 0xd1, 0x17, 0x8b, 0xd2, 0x5c, 0x31, + 0xc8, 0x78, 0xc1, 0xdd, 0x04, 0xc4, 0xb6, 0x33, + 0x3b, 0x72, 0x06, 0x6c, 0x7a, 0x15, 0x52, 0xac, + 0x0d, 0x6f, 0x35, 0x22, 0x63, 0x1e, 0xff, 0xcb, + }; +#endif + + /* Endianness. +*/ + +/* routines for dealing with byte ordering */ + +int md6_byte_order = 0; +/* md6_byte_order describes the endianness of the +** underlying machine: +** 0 = unknown +** 1 = little-endian +** 2 = big-endian +*/ + +/* Macros to detect machine byte order; these +** presume that md6_byte_order has been setup by +** md6_detect_byte_order() +*/ +#define MD6_LITTLE_ENDIAN (md6_byte_order == 1) +#define MD6_BIG_ENDIAN (md6_byte_order == 2) + +void md6_detect_byte_order( void ) +/* determine if underlying machine is little-endian or big-endian +** set global variable md6_byte_order to reflect result +** Written to work for any w. +*/ +{ md6_word x = 1 | (((md6_word)2)<<(w-8)); + unsigned char *cp = (unsigned char *)&x; + if ( *cp == 1 ) md6_byte_order = 1; /* little-endian */ + else if ( *cp == 2 ) md6_byte_order = 2; /* big-endian */ + else md6_byte_order = 0; /* unknown */ +} + +md6_word md6_byte_reverse( md6_word x ) +/* return byte-reversal of md6_word x. +** Written to work for any w, w=8,16,32,64. +*/ +{ +#define mask8 ((md6_word)0x00ff00ff00ff00ffULL) +#define mask16 ((md6_word)0x0000ffff0000ffffULL) +#if (w==64) + x = (x << 32) | (x >> 32); +#endif +#if (w >= 32) + x = ((x & mask16) << 16) | ((x & ~mask16) >> 16); +#endif +#if (w >= 16) + x = ((x & mask8) << 8) | ((x & ~mask8) >> 8); +#endif + return x; +} + +void md6_reverse_little_endian( md6_word *x, int count ) +/* Byte-reverse words x[0...count-1] if machine is little_endian */ +{ + int i; + if (MD6_LITTLE_ENDIAN) + for (i=0;i> (8-accumlen); /* right-justify it in accumulator */ + } + di = destlen/8; /* index of where next byte will go within dest */ + + /* Now process each byte of src */ + srcbytes = (srclen+7)/8; /* number of bytes (full or partial) in src */ + for (i=0;i> (8-newbits)); + accumlen += newbits; + } + /* do as many high-order bits of accum as you can (or need to) */ + while ( ( (i != srcbytes-1) & (accumlen >= 8) ) || + ( (i == srcbytes-1) & (accumlen > 0) ) ) + { int numbits = min(8,accumlen); + unsigned char bits; + bits = accum >> (accumlen - numbits); /* right justified */ + bits = bits << (8-numbits); /* left justified */ + bits &= (0xff00 >> numbits); /* mask */ + dest[di++] = bits; /* save */ + accumlen -= numbits; + } + } +} + + /* State initialization. (md6_full_init, with all parameters specified) +** +*/ + +int md6_full_init( md6_state *st, /* uninitialized state to use */ + int d, /* hash bit length */ + unsigned char *key, /* key; OK to give NULL */ + int keylen, /* keylength (bytes); OK to give 0 */ + int L, /* mode; OK to give md6_default_L */ + int r /* number of rounds */ + ) +/* Initialize md6_state +** Input: +** st md6_state to be initialized +** d desired hash bit length 1 <= d <= w*(c/2) (<=512 bits) +** key key (aka salt) for this hash computation (byte array) +** defaults to all-zero key if key==NULL or keylen==0 +** keylen length of key in bytes; 0 <= keylen <= (k*8) (<=64 bytes) +** L md6 mode parameter; 0 <= L <= 255 +** md6.h defines md6_default_L for when you want default +** r number of rounds; 0 <= r <= 255 +** Output: +** updates components of state +** returns one of the following: +** MD6_SUCCESS +** MD6_NULLSTATE +** MD6_BADKEYLEN +** MD6_BADHASHLEN +*/ +{ /* check that md6_full_init input parameters make some sense */ + if (st == NULL) return MD6_NULLSTATE; + if ( (key != NULL) && ((keylen < 0) || (keylen > k*(w/8))) ) + return MD6_BADKEYLEN; + if ( d < 1 || d > 512 || d > w*c/2 ) return MD6_BADHASHLEN; + + md6_detect_byte_order(); + memset(st,0,sizeof(md6_state)); /* clear state to zero */ + st->d = d; /* save hashbitlen */ + if (key != NULL && keylen > 0) /* if no key given, use memset zeros*/ + { memcpy(st->K,key,keylen); /* else save key (with zeros added) */ + st->keylen = keylen; + /* handle endian-ness */ /* first byte went into high end */ + md6_reverse_little_endian(st->K,k); + } + else + st->keylen = 0; + if ( (L<0) | (L>255) ) return MD6_BAD_L; + st->L = L; + if ( (r<0) | (r>255) ) return MD6_BAD_r; + st->r = r; + st->initialized = 1; + st->top = 1; + /* if SEQ mode for level 1; use IV=0 */ + /* zero bits already there by memset; */ + /* we just need to set st->bits[1] */ + if (L==0) st->bits[1] = c*w; + compression_hook = NULL; /* just to be sure default is "not set" */ + return MD6_SUCCESS; +} + + /* State initialization. (md6_init, which defaults most parameters.) +** +*/ + +int md6_init( md6_state *st, + int d + ) +/* Same as md6_full_init, but with default key, L, and r */ +{ return md6_full_init(st, + d, + NULL, + 0, + md6_default_L, + md6_default_r(d) + ); +} + + /* Data structure notes. +*/ + +/* +Here are some notes on the data structures used (inside state). + +* The variable B[] is a stack of length-b (b-64) word records, + each corresponding to a node in the tree. B[ell] corresponds + to a node at level ell. Specifically, it represents the record which, + when compressed, will yield the value at that level. (It only + contains the data payload, not the auxiliary information.) + Note that B[i] is used to store the *inputs* to the computation at + level i, not the output for the node at that level. + Thus, for example, the message input is stored in B[1], not B[0]. + +* Level 0 is not used. The message bytes are placed into B[1]. + +* top is the largest ell for which B[ell] has received data, + or is equal to 1 in case no data has been received yet at all. + +* top is never greater than L+1. If B[L+1] is + compressed, the result is put back into B[L+1] (this is SEQ). + +* bits[ell] says how many bits have been placed into + B[ell]. An invariant maintained is that of the bits in B[ell], + only the first bits[ell] may be nonzero; the following bits must be zero. + +* The B nodes may have somewhat different formats, depending on the level: + -- Level 1 node contains a variable-length bit-string, and so + 0 <= bits[1] <= b*w is all we can say. + -- Levels 2...top always receive data in c-word chunks (from + children), so for them bits[ell] is between 0 and b*w, + inclusive, but is also a multiple of cw. We can think of these + nodes as have (b/c) (i.e. 4) "slots" for chunks. + -- Level L+1 is special, in that the first c words of B are dedicated + to the "chaining variable" (or IV, for the first node on the level). + +* When the hashing is over, B[top] will contain the + final hash value, in the first or second (if top = L+1) slot. + +*/ + /* Compress one block -- compress data at a node (md6_compress_block). +*/ + +int md6_compress_block( md6_word *C, + md6_state *st, + int ell, + int z + ) +/* compress block at level ell, and put c-word result into C. +** Input: +** st current md6 computation state +** ell 0 <= ell < max_stack_height-1 +** z z = 1 if this is very last compression; else 0 +** Output: +** C c-word array to put result in +** Modifies: +** st->bits[ell] (zeroed) +** st->i_for_level[ell] (incremented) +** st->B[ell] (zeroed) +** st->compression_calls (incremented) +** Returns one of the following: +** MD6_SUCCESS +** MD6_NULLSTATE +** MD6_STATENOTINIT +** MD6_STACKUNDERFLOW +** MD6_STACKOVERFLOW +*/ +{ int p, err; + + /* check that input values are sensible */ + if ( st == NULL) return MD6_NULLSTATE; + if ( st->initialized == 0 ) return MD6_STATENOTINIT; + if ( ell < 0 ) return MD6_STACKUNDERFLOW; + if ( ell >= md6_max_stack_height-1 ) return MD6_STACKOVERFLOW; + + st->compression_calls++; + + if (ell==1) /* leaf; hashing data; reverse bytes if nec. */ + { if (ell<(st->L + 1)) /* PAR (tree) node */ + md6_reverse_little_endian(&(st->B[ell][0]),b); + else /* SEQ (sequential) node; don't reverse chaining vars */ + md6_reverse_little_endian(&(st->B[ell][c]),b-c); + } + + p = b*w - st->bits[ell]; /* number of pad bits */ + + err = + md6_standard_compress( + C, /* C */ + Q, /* Q */ + st->K, /* K */ + ell, st->i_for_level[ell], /* -> U */ + st->r, st->L, z, p, st->keylen, st->d, /* -> V */ + st->B[ell] /* B */ + ); + if (err) return err; + + st->bits[ell] = 0; /* clear bits used count this level */ + st->i_for_level[ell]++; + + memset(&(st->B[ell][0]),0,b*sizeof(md6_word)); /* clear B[ell] */ + return MD6_SUCCESS; +} + + /* Process (compress) a node and its compressible ancestors. +*/ + +int md6_process( md6_state *st, + int ell, + int final ) +/* +** Do processing of level ell (and higher, if necessary) blocks. +** +** Input: +** st md6 state that has been accumulating message bits +** and/or intermediate results +** ell level number of block to process +** final true if this routine called from md6_final +** (no more input will come) +** false if more input will be coming +** (This is not same notion as "final bit" (i.e. z) +** indicating the last compression operation.) +** Output (by side effect on state): +** Sets st->hashval to final chaining value on final compression. +** Returns one of the following: +** MD6_SUCCESS +** MD6_NULLSTATE +** MD6_STATENOTINIT +*/ +{ int err, z, next_level; + md6_word C[c]; + + /* check that input values are sensible */ + if ( st == NULL) return MD6_NULLSTATE; + if ( st->initialized == 0 ) return MD6_STATENOTINIT; + + if (!final) /* not final -- more input will be coming */ + { /* if not final and block on this level not full, nothing to do */ + if ( st->bits[ell] < b*w ) + return MD6_SUCCESS; + /* else fall through to compress this full block, + ** since more input will be coming + */ + } + else /* final -- no more input will be coming */ + { if ( ell == st->top ) + { if (ell == (st->L + 1)) /* SEQ node */ + { if ( st->bits[ell]==c*w && st->i_for_level[ell]>0 ) + return MD6_SUCCESS; + /* else (bits>cw or i==0, so fall thru to compress */ + } + else /* st->top == ell <= st->L so we are at top tree node */ + { if ( ell>1 && st->bits[ell]==c*w) + return MD6_SUCCESS; + /* else (ell==1 or bits>cw, so fall thru to compress */ + } + } + /* else (here ell < st->top so fall through to compress */ + } + + /* compress block at this level; result goes into C */ + /* first set z to 1 iff this is the very last compression */ + z = 0; if (final && (ell == st->top)) z = 1; + if ((err = md6_compress_block(C,st,ell,z))) + return err; + if (z==1) /* save final chaining value in st->hashval */ + { memcpy( st->hashval, C, md6_c*(w/8) ); + return MD6_SUCCESS; + } + + /* where should result go? To "next level" */ + next_level = min(ell+1,st->L+1); + /* Start sequential mode with IV=0 at that level if necessary + ** (All that is needed is to set bits[next_level] to c*w, + ** since the bits themselves are already zeroed, either + ** initially, or at the end of md6_compress_block.) + */ + if (next_level == st->L + 1 + && st->i_for_level[next_level]==0 + && st->bits[next_level]==0 ) + st->bits[next_level] = c*w; + /* now copy C onto next level */ + memcpy((char *)st->B[next_level] + st->bits[next_level]/8, + C, + c*(w/8)); + st->bits[next_level] += c*w; + if (next_level > st->top) st->top = next_level; + + return md6_process(st,next_level,final); +} + /* Update -- incorporate data string into hash computation. +*/ + +int md6_update( md6_state *st, + unsigned char *data, + uint64_t databitlen ) +/* Process input byte string data, updating state to reflect result +** Input: +** st already initialized state to be updated +** data byte string of length databitlen bits +** to be processed (aka "M") +** databitlen number of bits in string data (aka "m") +** Modifies: +** st updated to reflect input of data +*/ +{ unsigned int j, portion_size; + int err; + + /* check that input values are sensible */ + if ( st == NULL ) return MD6_NULLSTATE; + if ( st->initialized == 0 ) return MD6_STATENOTINIT; + if ( data == NULL ) return MD6_NULLDATA; + + j = 0; /* j = number of bits processed so far with this update */ + while (jbits[1]))); + + if ((portion_size % 8 == 0) && + (st->bits[1] % 8 == 0) && + (j % 8 == 0)) + { /* use mempy to handle easy, but most common, case */ + memcpy((char *)st->B[1] + st->bits[1]/8, + &(data[j/8]), + portion_size/8); + } + else /* handle messy case where shifting is needed */ + { append_bits((unsigned char *)st->B[1], /* dest */ + st->bits[1], /* dest current bit size */ + &(data[j/8]), /* src */ + portion_size); /* src size in bits */ + } + j += portion_size; + st->bits[1] += portion_size; + st->bits_processed += portion_size; + + /* compress level-1 block if it is now full + but we're not done yet */ + if (st->bits[1] == b*w && jhashval into hexadecimal, and +** save result in st->hexhashval +** This will be a zero-terminated string of length ceil(d/4). +** Assumes that hashval has already been "trimmed" to correct +** length. +** +** Returns one of the following: +** MD6_SUCCESS +** MD6_NULLSTATE (if input state pointer was NULL) +*/ +{ int i; + static unsigned char hex_digits[] = "0123456789abcdef"; + + /* check that input is sensible */ + if ( st == NULL ) return MD6_NULLSTATE; + + for (i=0;i<((st->d+7)/8);i++) + { st->hexhashval[2*i] + = hex_digits[ ((st->hashval[i])>>4) & 0xf ]; + st->hexhashval[2*i+1] + = hex_digits[ (st->hashval[i]) & 0xf ]; + } + + /* insert zero string termination byte at position ceil(d/4) */ + st->hexhashval[(st->d+3)/4] = 0; + return MD6_SUCCESS; +} + + /* Extract last d bits of chaining variable as hash value. +*/ + +void trim_hashval(md6_state *st) +{ /* trim hashval to desired length d bits by taking only last d bits */ + /* note that high-order bit of a byte is considered its *first* bit */ + int full_or_partial_bytes = (st->d+7)/8; + int bits = st->d % 8; /* bits in partial byte */ + int i; + + /* move relevant bytes to the front */ + for ( i=0; ihashval[i] = st->hashval[c*(w/8)-full_or_partial_bytes+i]; + + /* zero out following bytes */ + for ( i=full_or_partial_bytes; ihashval[i] = 0; + + /* shift result left by (8-bits) bit positions, per byte, if needed */ + if (bits>0) + { for ( i=0; ihashval[i] = (st->hashval[i] << (8-bits)); + if ( (i+1) < c*(w/8) ) + st->hashval[i] |= (st->hashval[i+1] >> bits); + } + } +} + + /* Final -- no more data; finish up and produce hash value. +*/ + +int md6_final( md6_state *st , unsigned char *hashval) +/* Do final processing to produce md6 hash value +** Input: +** st md6 state that has been accumulating message bits +** and/or intermediate results +** Output (by side effect on state): +** hashval If this is non-NULL, final hash value copied here. +** (NULL means don't copy.) In any case, the hash +** value remains in st->hashval. +** st->hashval this is a 64-byte array; the first st->d +** bits of which will be the desired hash value +** (with high-order bits of a byte used first), and +** remaining bits set to zero (same as hashval) +** st->hexhashval this is a 129-byte array which contains the +** zero-terminated hexadecimal version of the hash +** Returns one of the following: +** MD6_SUCCESS +** MD6_NULLSTATE +** MD6_STATENOTINIT +*/ +{ int ell, err; + + /* check that input values are sensible */ + if ( st == NULL) return MD6_NULLSTATE; + if ( st->initialized == 0 ) return MD6_STATENOTINIT; + + /* md6_final was previously called */ + if ( st->finalized == 1 ) return MD6_SUCCESS; + + /* force any processing that needs doing */ + if (st->top == 1) ell = 1; + else for (ell=1; ell<=st->top; ell++) + if (st->bits[ell]>0) break; + /* process starting at level ell, up to root */ + err = md6_process(st,ell,1); + if (err) return err; + + /* md6_process has saved final chaining value in st->hashval */ + + md6_reverse_little_endian( (md6_word*)st->hashval, c ); + if (hashval != NULL) memcpy( hashval, st->hashval, (st->d+7)/8 ); + trim_hashval( st ); + md6_compute_hex_hashval( st ); + + st->finalized = 1; + return MD6_SUCCESS; +} + + /* Routines for hashing message given "all at once". +*/ + +int md6_full_hash( int d, /* hash bit length */ + unsigned char *data,/* complete data to hash */ + uint64_t databitlen, /* its length in bits */ + unsigned char *key, /* OK to give NULL */ + int keylen, /* (in bytes) OK to give 0 */ + int L, /* mode; OK to give md6_default_L */ + int r, /* number of rounds */ + unsigned char *hashval /* output */ + ) +{ md6_state st; + int err; + + err = md6_full_init(&st,d,key,keylen,L,r); + if (err) return err; + err = md6_update(&st,data,databitlen); + if (err) return err; + md6_final(&st,hashval); + if (err) return err; + return MD6_SUCCESS; +} + +int md6_hash( int d, /* hash bit length */ + unsigned char *data, /* complete data to hash */ + uint64_t databitlen, /* its length in bits */ + unsigned char *hashval /* output */ + ) +{ int err; + + err = md6_full_hash(d,data,databitlen, + NULL,0,md6_default_L,md6_default_r(d),hashval); + if (err) return err; + return MD6_SUCCESS; +} + + +/* +** end of md6_mode.c +*/ + + Index: trunk/C_implementation/testmemcpy.c =================================================================== --- trunk/C_implementation/testmemcpy.c (nonexistent) +++ trunk/C_implementation/testmemcpy.c (revision 2) @@ -0,0 +1,45 @@ +/* testmemcpy.c +** Ronald L. Rivest +** 5/12/08 +** +** Routine to test speed of memcpy vs just a loop, for +** various size blocks to move. +** +** The cutoff for 32-bit compilation onto my laptop gives +** a cutoff of about blocksize = 16; below that the loop +** is faster; above that memcpy is faster. +*/ + +#include +#include +#include + +typedef uint64_t md6_word; + +md6_word A[8092]; +md6_word B[8092]; + +int main() +{ int blocksize; + time_t start_time, end_time; + int i,j; + int ntrials = 1000000000; + printf("ntrials = %d\n",ntrials); + for (blocksize = 1; blocksize<= 128; blocksize += blocksize) + { + printf("Blocksize = %d 64-bit words\n",blocksize); + + time(&start_time); + for (i=0;i +#endif + + /* MD6 wordsize. +** +** Define md6 wordsize md6_w, in bits. +** Note that this is the "word size" relevant to the +** definition of md6 (it defines how many bits in an +** "md6_word"); it does *not* refer to the word size +** on the platform for which this is being compiled. +*/ + +#define md6_w 64 + +/* Define "md6_word" appropriately for given value of md6_w. +** Also define PR_MD6_WORD to be the appropriate hex format string, +** using the format strings from inttypes.h . +** The term `word' in comments means an `md6_word'. +*/ + +#if (md6_w==64) /* standard md6 */ +typedef uint64_t md6_word; +#define PR_MD6_WORD "%.16" PRIx64 + +#elif (md6_w==32) /* nonstandard variant */ +typedef uint32_t md6_word; +#define PR_MD6_WORD "%.8" PRIx32 + +#elif (md6_w==16) /* nonstandard variant */ +typedef uint16_t md6_word; +#define PR_MD6_WORD "%.4" PRIx16 + +#elif (md6_w==8) /* nonstandard variant */ +typedef uint8_t md6_word; +#define PR_MD6_WORD "%.2" PRIx8 + +#endif + + /* MD6 compression function. +** +** MD6 compression function is defined in file md6_compress.c +*/ + +/* MD6 compression function constants */ + +#define md6_n 89 /* size of compression input block, in words */ +#define md6_c 16 /* size of compression output, in words */ + /* a c-word block is also called a "chunk" */ +#define md6_max_r 255 /* max allowable value for number r of rounds */ + +/* Compression function routines +** These are ``internal'' routines that need not be called for +** ordinary md6 usage. +*/ + +extern int md6_default_r( int d ); /* returns default r for given d */ + +void md6_main_compression_loop( md6_word *A, /* working array */ + int r /* number of rounds */ + ); + +int md6_compress( md6_word *C, /* output */ + md6_word *N, /* input */ + int r, /* number rounds */ + md6_word *A /* (optional) working array, may be NULL */ + ); + + +typedef uint64_t md6_control_word; /* (r,L,z,p,d) */ +md6_control_word md6_make_control_word( int r, /* number rounds */ + int L, /* parallel passes */ + int z, /* final node flag */ + int p, /* padding bits */ + int keylen, /* bytes in key */ + int d /* digest size */ + ); + +typedef uint64_t md6_nodeID; /* (ell,i) */ +md6_nodeID md6_make_nodeID( int ell, /* level number */ + int i /* index (0,1,2,...) within level */ + ); + +void md6_pack( md6_word* N, /* output */ + const md6_word* Q, /* fractional part sqrt(6) */ + md6_word* K, /* key */ + int ell, int i, /* for U */ + int r, int L, int z, int p, int keylen, int d, /* for V */ + md6_word* B /* data input */ + ); + +int md6_standard_compress( + md6_word *C, /* output */ + const md6_word *Q, /* fractional part sqrt(6) */ + md6_word *K, /* key */ + int ell, int i, /* for U */ + int r, int L, int z, int p, int keylen, int d, /* for V */ + md6_word* B /* data input */ + ); + + /* MD6 mode of operation. +** +** MD6 mode of operation is defined in file md6_mode.c +*/ + +/* MD6 constants related to standard mode of operation */ + +/* These five values give lengths of the components of compression */ +/* input block; they should sum to md6_n. */ +#define md6_q 15 /* # Q words in compression block (>=0) */ +#define md6_k 8 /* # key words per compression block (>=0) */ +#define md6_u (64/md6_w) /* # words for unique node ID (0 or 64/w) */ +#define md6_v (64/md6_w) /* # words for control word (0 or 64/w) */ +#define md6_b 64 /* # data words per compression block (>0) */ + +#define md6_default_L 64 /* large so that MD6 is fully hierarchical */ + +#define md6_max_stack_height 29 + /* max_stack_height determines the maximum number of bits that + ** can be processed by this implementation (with default L) to be: + ** (b*w) * ((b/c) ** (max_stack_height-3) + ** = 2 ** 64 for b = 64, w = 64, c = 16, and max_stack_height = 29 + ** (We lose three off the height since level 0 is unused, + ** level 1 contains the input data, and C has 0-origin indexing.) + ** The smallest workable value for md6_max_stack_height is 3. + ** (To avoid stack overflow for non-default L values, + ** we should have max_stack_height >= L + 2.) + ** (One level of storage could be saved by letting st->N[] use + ** 1-origin indexing, since st->N[0] is now unused.) + */ + + /* MD6 state. +** +** md6_state is the main data structure for the MD6 hash function. +*/ + +typedef struct { + + int d; /* desired hash bit length. 1 <= d <= 512. */ + int hashbitlen; /* hashbitlen is the same as d; for NIST API */ + + unsigned char hashval[ (md6_c/2)*(md6_w/8) ]; + /* e.g. unsigned char hashval[64]; (Assumes d<=c/2.) */ + /* contains hashval after call to md6_final */ + /* hashval appears in first floor(d/8) bytes, with */ + /* remaining (d mod 8) bits (if any) appearing in */ + /* high-order bit positions of hashval[1+floor(d/8)]. */ + + unsigned char hexhashval[(md6_c*(md6_w/8))+1]; + /* e.g. unsigned char hexhashval[129]; */ + /* zero-terminated string representing hex value of hashval */ + + int initialized; /* zero, then one after md6_init called */ + uint64_t bits_processed; /* bits processed so far */ + uint64_t compression_calls; /* compression function calls made*/ + int finalized; /* zero, then one after md6_final called */ + + md6_word K[ md6_k ]; + /* k-word (8 word) key (aka "salt") for this instance of md6 */ + int keylen; + /* number of bytes in key K. 0<=keylen<=k*(w/8) */ + + int L; + /* md6 mode specification parameter. 0 <= L <= 255 */ + /* L == 0 means purely sequential (Merkle-Damgaard) */ + /* L >= 29 means purely tree-based */ + /* Default is md6_default_L = 64 (hierarchical) */ + + int r; + /* Number of rounds. 0 <= r <= 255 */ + + int top; + /* index of block corresponding to top of stack */ + + md6_word B[ md6_max_stack_height ][ md6_b ]; + /* md6_word B[29][64] */ + /* stack of 29 64-word partial blocks waiting to be */ + /* completed and compressed. */ + /* B[1] is for compressing text data (input); */ + /* B[ell] corresponds to node at level ell in the tree. */ + + unsigned int bits[ md6_max_stack_height ]; + /* bits[ell] = */ + /* number of bits already placed in B[ell] */ + /* for 1 <= ell < max_stack_height */ + /* 0 <= bits[ell] <= b*w */ + + uint64_t i_for_level[ md6_max_stack_height ]; + /* i_for_level[ell] = */ + /* index of the node B[ ell ] on this level (0,1,...) */ + /* when it is output */ + +} md6_state; + /* MD6 main interface routines +** +** These routines are defined in md6_mode.c +*/ + +/* The next routines are used according to the pattern: +** md6_init (or md6_full_init if you use additional parameters) +** md6_update (once for each portion of the data to be hashed) +** md6_final (to finish up hash computation) +** Note: md6_final can return the hash value to a desired location, but +** hash value also remains available inside the md6_state, in both binary +** and hex formats (st->hashval and st->hexhashval). +*/ + +extern int md6_init( md6_state *st, /* state to initialize */ + int d /* hash bit length */ + ); + +extern int md6_full_init( md6_state *st, /* state to initialize */ + int d, /* hash bit length */ + unsigned char *key, /* OK to give NULL */ + int keylen, /* (in bytes) OK to give 0 */ + int L, /* mode; OK to give md6_default_L */ + int r /* number of rounds */ + ); + +extern int md6_update( md6_state *st, /* initialized state */ + unsigned char *data, /* data portion */ + uint64_t databitlen /* its length in bits */ + ); + +extern int md6_final( md6_state *st, /* initialized/updated */ + unsigned char *hashval /* output; NULL OK */ + ); + + /* MD6 main interface routines +** +** These routines are defined in md6_mode.c +** +** These routines compute a hash for a message given all at once. +** The resulting hash value is returned to a specified location. +** Only one call is needed. Use md6_hash for the standard md6 hash, +** and md6_full_hash if you want to specify additional parameters. +*/ + +extern int md6_hash( int d, /* hash bit length */ + unsigned char *data, /* complete data to hash */ + uint64_t databitlen, /* its length in bits */ + unsigned char *hashval /* output */ + ); + +extern int md6_full_hash( int d, /* hash bit length */ + unsigned char *data,/* complete data to hash */ + uint64_t databitlen, /* its length in bits */ + unsigned char *key, /* OK to give NULL */ + int keylen, /* (in bytes) OK to give 0 */ + int L, /* mode; OK to give md6_default_L */ + int r, /* number of rounds */ + unsigned char *hashval /* output */ + ); + + + /* MD6 return codes. +** +** The interface routines defined in md6_mode.c always return a +** "return code": an integer giving the status of the call. +** The codes +** SUCCESS, FAIL, and BADHASHLEN same as for NIST API +*/ + +/* SUCCESS: */ +#define MD6_SUCCESS 0 + +/* ERROR CODES: */ +#define MD6_FAIL 1 /* some other problem */ +#define MD6_BADHASHLEN 2 /* hashbitlen<1 or >512 bits */ +#define MD6_NULLSTATE 3 /* null state passed to MD6 */ +#define MD6_BADKEYLEN 4 /* key length is <0 or >512 bits */ +#define MD6_STATENOTINIT 5 /* state was never initialized */ +#define MD6_STACKUNDERFLOW 6 /* MD6 stack underflows (shouldn't happen)*/ +#define MD6_STACKOVERFLOW 7 /* MD6 stack overflow (message too long) */ +#define MD6_NULLDATA 8 /* null data pointer */ +#define MD6_NULL_N 9 /* compress: N is null */ +#define MD6_NULL_B 10 /* standard compress: null B pointer */ +#define MD6_BAD_ELL 11 /* standard compress: ell not in {0,255} */ +#define MD6_BAD_p 12 /* standard compress: p<0 or p>b*w */ +#define MD6_NULL_K 13 /* standard compress: K is null */ +#define MD6_NULL_Q 14 /* standard compress: Q is null */ +#define MD6_NULL_C 15 /* standard compress: C is null */ +#define MD6_BAD_L 16 /* standard compress: L <0 or > 255 */ + /* md6_init: L<0 or L>255 */ +#define MD6_BAD_r 17 /* compress: r<0 or r>255 */ + /* md6_init: r<0 or r>255 */ +#define MD6_OUT_OF_MEMORY 18 /* compress: storage allocation failed */ + + +/* The following code confirms that the defined MD6 constants satisfy +** some expected properties. These tests should never fail; consider +** these tests to be documentation. Failure of these tests would cause +** compilation to fail. +*/ + +#if ( (md6_w!=8) && (md6_w!=16) && (md6_w!=32) && (md6_w!=64) ) + #error "md6.h Fatal error: md6_w must be one of 8,16,32, or 64." +#elif ( md6_n<=0 ) + #error "md6.h Fatal error: md6_n must be positive." +#elif ( md6_b<=0 ) + #error "md6.h Fatal error: md6_b must be positive." +#elif ( md6_c<=0 ) + #error "md6.h Fatal error: md6_c must be positive." +#elif ( md6_v<0 ) + #error "md6.h Fatal error: md6_v must be nonnegative." +#elif ( md6_u<0 ) + #error "md6.h Fatal error: md6_u must be nonnegative." +#elif ( md6_k<0 ) + #error "md6.h Fatal error: md6_k must be nonnegative." +#elif ( md6_q<0 ) + #error "md6.h Fatal error: md6_q must be nonnegative." +#elif ( md6_b>=md6_n ) + #error "md6.h Fatal error: md6_b must be smaller than md6_n." +#elif ( md6_c>=md6_b ) + #error "md6.h Fatal error: md6_c must be smaller than md6_b." +#elif ( (md6_b%md6_c)!=0 ) + #error "md6.h Fatal error: md6_b must be a multiple of md6_c." +#elif ( md6_n != md6_b + md6_v + md6_u + md6_k + md6_q ) + #error "md6.h Fatal error: md6_n must = md6_b + md6_v + md6_u + md6_k + md6_q." +#elif ( md6_max_stack_height < 3 ) + #error "md6.h Fatal error: md6_max_stack_height must be at least 3." +#elif ( md6_r * md6_c + md6_n >= 5000 ) + /* since md6_standard_compress allocates fixed-size array A[5000] */ + #error "md6.h Fatal error: r*c+n must be < 5000." +#if 0 + /* "sizeof" doesn't work in preprocessor, these checks don't work */ + #elif ( (md6_v != 0) && (md6_v != (sizeof(md6_control_word)/(md6_w/8))) ) + #error "md6.h Fatal error: md6_v must be 0 or match md6_control_word size." + #elif ( (md6_u != 0) && (md6_u != (sizeof(md6_nodeID)/(md6_w/8))) ) + #error "md6.h Fatal error: md6_u must be 0 or match md6_nodeID size." +#endif +#endif + + +/* Debugging and testing. +*/ + +/* compression hook, if defined, points to a function that is +** called after each compression operation. +** +** compression hook must be set *after* md6_init or md6_full_init +** is called. +*/ + +void (* compression_hook)(md6_word *C, + const md6_word *Q, + md6_word *K, + int ell, + int i, + int r, + int L, + int z, + int p, + int keylen, + int d, + md6_word *N + ); + +/* end of #ifndef MD6_H_INCLUDED for multiple inclusion protection +*/ +#endif + +/* end of md6.h */ Index: trunk/C_implementation/makefile =================================================================== --- trunk/C_implementation/makefile (nonexistent) +++ trunk/C_implementation/makefile (revision 2) @@ -0,0 +1,23 @@ +# +# makefile for md6 programs + +# for GCC: +CC = gcc +CFLAGS = -Wall -O3 + +# for Microsoft VS +# CC = CL.EXE +# CFLAGS = /O2 /arch:SSE2 + +md6_test : md6_test.c md6_compress.c md6_mode.c + $(CC) $(CFLAGS) -o $@ $^ + +md6_test2 : md6_test.c md6_compress.c md6_mode.c + $(CC) -pg $(CFLAGS) -o $@ $^ + +md6sum : md6sum.c md6_compress.c md6_mode.c + $(CC) $(CFLAGS) -o $@ $^ + + + + Index: trunk/C_implementation/README_32bit.txt =================================================================== --- trunk/C_implementation/README_32bit.txt (nonexistent) +++ trunk/C_implementation/README_32bit.txt (revision 2) @@ -0,0 +1,18 @@ +Filename: README_32bit.txt +Author: Ronald L. Rivest +Date: 8/31/08 + +This directory (Optimized_32bit) contains the required "optimized +32-bit" implementation for our NIST SHA-3 submission, "MD6". + +The files included here are: + md6.h + md6_compress.c + md6_mode.c + md6_nist.h + md6_nist.c + inttypes.h + stdint.h + +These files are identical to those included in the Reference Implementation. + Index: trunk/MD6Control/test/MD6ControlTest.bsv =================================================================== --- trunk/MD6Control/test/MD6ControlTest.bsv (nonexistent) +++ trunk/MD6Control/test/MD6ControlTest.bsv (revision 2) @@ -0,0 +1,79 @@ +//BSV includes +import RegFile::*; +import Connectable::*; +import GetPut::*; +import StmtFSM::*; + +//CSG Lib includes +import PLBMaster::*; +import PLBMasterDefaultParameters::*; +import PLBMasterEmulator::*; + +//Local includes +import MD6Parameters::*; +import MD6Types::*; +import MD6Control::*; +import CompressionFunctionTypes::*; + + + + +module mkMD6ControlTest (); + RegFile#(Bit#(26),BusWord) memory <- mkRegFileFullLoad("md6Input.hex"); + PLBMasterEmulator#(TExp#(26)) plbmaster <- mkPLBMasterEmulator(memory); + MD6Control#(1,32) control <- mkMD6Control; + // Hook up the system + mkConnection(plbmaster.plbmaster.wordInput.put,control.wordOutput); + mkConnection(control.wordInput,plbmaster.plbmaster.wordOutput.get); + mkConnection(plbmaster.plbmaster.plbMasterCommandInput.put,control.outputCommand); + + + Reg#(Bit#(32)) memPtr <- mkReg(0); + + RegFile#(Bit#(1), Bit#(32)) rfileSize <- mkRegFileFullLoad("inputSize.hex"); + RegFile#(Bit#(TLog#(MD6_c)), BusWord) rfileRes <- mkRegFileFullLoad("md6Result.hex"); + Reg#(Bit#(TAdd#(TLog#(MD6_c),1))) resPtr <- mkReg(0); + + let inputSize = (((rfileSize.sub(0))/fromInteger(8*valueof(MD6_b))) + 1)*fromInteger(valueof(MD6_b)); + + + Stmt s = seq + control.keyRegister <= unpack(0); + control.digestLength <= 512; + control.sourceAddress <= 0; + $display("Offset is: %d", inputSize); + control.destinationAddress <= 2*truncate(inputSize); + control.bufferAddress <= 4*truncate(inputSize); + $display("Bits input: %d", rfileSize.sub(0)); + control.bitSize <= zeroExtend(rfileSize.sub(0)); + control.bigEndian <= True; + control.startDecode(); + await(!control.running); + delay(100); + for(resPtr <= 0; + resPtr < fromInteger(valueof(MD6_c)) - 8; //result is 512 bits I suppose + resPtr <= resPtr+1) + seq + if(rfileRes.sub(truncate(resPtr)) != memory.sub(truncate(zeroExtend(resPtr) + inputSize + 8))) + seq + $display("Offset: %d rfile: %d",zeroExtend(resPtr), rfileSize.sub(0)); + $display("FAILED at %d, %h != %h", inputSize+zeroExtend(resPtr),rfileRes.sub(truncate(resPtr)),memory.sub(truncate(zeroExtend(resPtr) + inputSize + 8))); + $finish; + endseq + else + seq + $display("Match at %d", zeroExtend(resPtr) + inputSize); + endseq + endseq + $display("PASS"); + $finish; + endseq; + + FSM fsm <- mkFSM(s); + + + rule startFSM; + fsm.start; + endrule + +endmodule \ No newline at end of file Index: trunk/MD6Control/test/encodeBits.c =================================================================== --- trunk/MD6Control/test/encodeBits.c (nonexistent) +++ trunk/MD6Control/test/encodeBits.c (revision 2) @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include"encodeBits.h" +#include"md6.h" + + +const int requiredWordCount = 1<<20; + + + +// reads the first bits bits out of the file +void md6_file(char *filename, + char *outinput, + char *outresult, + char *outsize, + long long bits) + +{ + FILE *inFile = fopen (filename, "rb"); + FILE *outInput = fopen (outinput, "wb"); + FILE *outResult = fopen (outresult, "wb"); + FILE *outSize = fopen (outsize, "wb"); + md6_state st; + uint64_t bytes; + long long bitCounter = bits; + unsigned char data[1024]; + int err,i,j,wordCount=0; + long long bitMin; + + md6_word key[md6_k]; + + printf("Bits: %d\n", bits); + + for(i=0;i= md6_w)) { + wordBuf[i] = data[md6_w/8-i-1]; + } + else{*/ + wordBuf[i] = data[i]; + } + + + + // md6_update border case uses wrong endianess + // we may cross a bit boundary here. In this case we want min of + // bitCounter/bytes*8 + bitMin = (bitCounter +#include +#include +#include +#include +#include"md6.h" +#include"encodeBits.h" + + +int main(int argc, char** argv) { + struct stat buf; + FILE *inFile; + long long bits; + + if(argc != 5) { + printf("Wrong number of args\n"); + exit(0); + } + + inFile = fopen(argv[0],"rb"); + // Must determine intput bit length... + assert(stat(argv[1],&buf) == 0); + printf("File is %lld bytes\n",buf.st_size); + + + printf("0: %s 1: %s\n",argv[0],argv[1]); + md6_file(argv[1],argv[2],argv[3],argv[4],buf.st_size*8); +} Index: trunk/MD6Control/test/md6_setbits.c =================================================================== --- trunk/MD6Control/test/md6_setbits.c (nonexistent) +++ trunk/MD6Control/test/md6_setbits.c (revision 2) @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include + +#include"md6.h" +#include"encodeBits.h" + + +int main(int argc, char** argv) { + struct stat buf; + FILE *inFile; + long long bits; + + if(argc != 6) { + printf("Wrong number of args\n"); + exit(0); + } + + bits = atoi(argv[5]); + + inFile = fopen(argv[0],"rb"); + // Must determine intput bit length... + assert(stat(argv[1],&buf) == 0); + printf("File is %d bytes\n",buf.st_size); + assert(bits < buf.st_size*8); + assert(bits < MAX_SIZE); + + + printf("0: %s 1: %s\n",argv[0],argv[1]); + md6_file(argv[1],argv[2],argv[3],argv[4],bits); +} Index: trunk/MD6Control/test/encodeBits.h =================================================================== --- trunk/MD6Control/test/encodeBits.h (nonexistent) +++ trunk/MD6Control/test/encodeBits.h (revision 2) @@ -0,0 +1,15 @@ +#ifndef ENCODE_BITS_H +#define ENCODE_BITS_H + +// The bluespec has a hardcoded maximum value... +#define MAX_SIZE (1<<(20+4)) + + +// reads the first bits bits out of the file +void md6_file(char *filename, + char *outinput, + char *outresult, + char *outsize, + long long bits); + +#endif Index: trunk/MD6Control/test/md6_random.c =================================================================== --- trunk/MD6Control/test/md6_random.c (nonexistent) +++ trunk/MD6Control/test/md6_random.c (revision 2) @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include + +#include"md6.h" +#include"encodeBits.h" + + +int main(int argc, char** argv) { + struct stat buf; + FILE *inFile; + long long size; + + if(argc != 5) { + printf("Wrong number of args\n"); + exit(0); + } + + srand(time(NULL)); + + inFile = fopen(argv[0],"rb"); + // Must determine intput bit length... + assert(stat(argv[1],&buf) == 0); + printf("File is %d bytes\n",buf.st_size); + + printf("0: %s 1: %s\n",argv[0],argv[1]); + + size = rand()%(buf.st_size*8); + + if(size > MAX_SIZE) { + size = MAX_SIZE - 1; + } + + md6_file(argv[1],argv[2],argv[3],argv[4],size); +} Index: trunk/MD6Control/test/benchmarks/Debug.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/Debug.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/Debug.bsv (revision 2) @@ -0,0 +1,7 @@ +function Action debug(Bool b, Action a); + action + + if (b) a; + + endaction +endfunction \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/CompressionFunction.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/CompressionFunction.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/CompressionFunction.bsv (revision 2) @@ -0,0 +1,233 @@ +import FIFOF::*; +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; +import CompressionFunctionLibrary::*; +import Debug::*; +import SGenerator::*; +import Vector::*; +import MD6ShiftRegister::*; + +Bool compressionDebug = True; + +interface CompressionFunction#(numeric type taps); + method Action start(Vector#(MD6_u,MD6Word) compressionIdentifierIn, Vector#(MD6_v,MD6Word) controlWordIn, Vector#(MD6_k,MD6Word) keyIn); // input all control information + method Action inputWord(MD6Word word); + method ActionValue#(MD6Word) outputWord(); + method Bit#(16) status(); +endinterface + +function MD6Word processStep(MD6Word t0, + MD6Word t1, + MD6Word t2, + MD6Word t3, + MD6Word t4, + MD6Word t5, + SGenerator sGenerator, + Bit#(TLog#(MD6_c)) step); + + ShiftFactor left = shiftIndexL(truncate(fromInteger(valueof(MD6_c) - 1) - step)); + ShiftFactor right = shiftIndexR(truncate(fromInteger(valueof(MD6_c) - 1) - step)); + + MD6Word sFactor = sGenerator.getS(); + MD6Word value = t0 ^ (t1 & t2) ^ (t3 & t4) ^ t5 ^ sFactor; + MD6Word intermediate = ((value >> right) ^ value); + return ((intermediate << left) ^ intermediate); +endfunction + +typedef enum { + Idle = 0, + LocalInitialization = 1, + LocalInitializationK = 2, + LocalInitializationU = 3, + LocalInitializationV = 4, + ExternalDataIn = 5, + Processing = 6, + AuxiliaryShift = 7, + ExternalDataOut = 8 +} CompressionState deriving (Bits,Eq); + +// TODO: I should probably support multiple digest lengths + +module mkSimpleCompressionFunction1 (CompressionFunction#(1)); + CompressionFunction#(1) compressor <- mkSimpleCompressionFunction; + return compressor; +endmodule + + +module mkSimpleCompressionFunction (CompressionFunction#(taps)) + provisos(Add#(taps,xxx,MD6_n), + Add#(yyy,TLog#(taps),TLog#(MD6_n)), + Add#(zzz,TLog#(taps),TLog#(MD6_b))); + /* The shift reg should look something like this: + -> | shift0 | shift 1 | shift 2 | shift 3 | shift 4 | -> + */ + // As a parameterization, we could extra these FIFOs as a + // seperate module which we could imeplement as a sort of + // black box. This is probably the right way to do things. + // This plus 1 may or may not work. + MD6ShiftRegister#(taps) shifter <- mkMD6ShiftRegister; + SGenerator sGenerator <- mkSGeneratorLogic; + + + // Step Number is rather special. It denotes the number of times + // that enq will be called on the fifo chain. This includes + // all init time functions + + Reg#(Round) roundNumber <- mkReg(0); + Reg#(Bit#(TLog#(MD6_n))) auxiliaryShift <- mkReg(0); + Reg#(Bit#(TLog#(MD6_c))) stepInRound <- mkReg(0); + Reg#(Bit#(TLog#(MD6_b))) externalDataCount <- mkReg(0); + Reg#(Bit#(TLog#(TSub#(MD6_n,MD6_b)))) localInitializationCount <- mkReg(0); + Reg#(CompressionState) state <- mkReg(Idle); + //Reg#(Vector#(MD6_k,MD6Word)) key <- mkReg(replicate(0)); + //Reg#(Vector#(MD6_u,MD6Word)) compressionIdentifier <- mkReg(replicate(0)); + //Reg#(Vector#(MD6_v,MD6Word)) controlWord <- mkReg(replicate(0)); + + Bit#(TLog#(TAdd#(MD6_c,1))) stepInRoundNext = zeroExtend(stepInRound) + fromInteger(valueof(taps)); + let roundNumberNext = {1'b0,roundNumber} + 1; + Bit#(TLog#(TAdd#(MD6_b,1))) externalDataCountNext = zeroExtend(externalDataCount) + 1; + Bit#(TLog#(TAdd#(TSub#(MD6_n,MD6_b),1))) localInitializationCountNext = + zeroExtend(localInitializationCount) + 1; + Bit#(TLog#(TAdd#(MD6_n,1))) auxiliaryShiftNext = zeroExtend(auxiliaryShift) + 1; + + + + rule mainShift(state == Processing); + if(stepInRoundNext == fromInteger(valueof(MD6_c))) + begin + stepInRound <= 0; + roundNumber <= truncate(roundNumberNext); + sGenerator.advanceRound(); // Need to advance round before next call of getS + if(roundNumberNext == fromInteger(valueof(MD6_r))) + begin + debug(compressionDebug,$display("Preparing to output")); + state <= ExternalDataOut; + end + end + else + begin + stepInRound <= truncate(stepInRoundNext); + end + + if((roundNumber == 0) && (stepInRound == 0)) + begin + for(Integer i = 0; i < valueof(MD6_n); i=i+1) + begin + debug(compressionDebug,$display("Starting ShiftState[%d]: %h",i, shifter.regs[i])); + end + end + + + function add(a,b); + return a+b; + endfunction + + function apply(a,b); + return a(b); + endfunction + + // The following crazy thing calculates the next state. It is vectorized + Vector#(taps,MD6Word) nextVector = zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,map(processStep,shifter.getT0),shifter.getT1),shifter.getT2),shifter.getT3),shifter.getT4),shifter.getT5),replicate(sGenerator)),zipWith(add,replicate(stepInRound),map(fromInteger,genVector))); + + /* + for(Integer i = 0; i < valueof(taps); i=i+1) + begin + debug(compressionDebug,$display("NextWordShort: %h", nextVector[i])); + debug(compressionDebug,$write("S: %h T5:%h T4:%h T3:%h T2:%h", sGenerator.getS(), shifter.getT5[i], shifter.getT4[i], shifter.getT3[i], shifter.getT2[i])); + debug(compressionDebug,$display("T1:%h T0:%h Next MD6 Word: %h", shifter.getT1[i], shifter.getT0[i], nextVector[i])); + end*/ + shifter.write(nextVector); + shifter.advance(); + endrule + + // May want to switch to InitQ -> Idle state machine order to overlap some computation potentially. + // May also want to explcitly intialize values in a state. + method Action start(Vector#(MD6_u,MD6Word) compressionIdentifierIn, Vector#(MD6_v,MD6Word) controlWordIn, Vector#(MD6_k,MD6Word) keyIn) if(state == Idle); // input all control information + state <= ExternalDataIn; + externalDataCount <= 0; + roundNumber <= 0; // Maybe put this somewhere else where its precense will be slightly more noticeable + Integer i = valueof(MD6_b); + // This stuff is in a reversed order + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(getQWord(fromInteger(j))); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_k)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(keyIn[j]); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_u)+valueof(MD6_k)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(compressionIdentifierIn[j]); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_v)+valueof(MD6_u)+valueof(MD6_k)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(controlWordIn[j]); + end + + sGenerator.resetS(); + endmethod + + + method Action inputWord(MD6Word word) if(state == ExternalDataIn); // Specific range for inputing new hash values + if(externalDataCountNext == fromInteger(valueof(MD6_b))) + begin + externalDataCount <= 0; + state <= Processing; + + for(Integer i = 0; i < valueof(MD6_n); i = i + 1) + begin + $display("Shifter[%d] = %h",i,shifter.regs[i]); + end + end + else + begin + externalDataCount <= truncate(externalDataCountNext); + end + //$display("externalDataCount: %d", externalDataCount); + // Pull same trick as in output word here. Must be careful about initialization, however, since those guys will be shifted over. + + Vector#(taps,Reg#(MD6Word)) resultVec = take(shifter.regs); + // This index is screwed up somehow. + Bit#(TLog#(taps)) index = truncate(externalDataCount); + + //We start after all of the initialization stuff + //Possible that bluespec may have issue here + Vector#(taps,Reg#(MD6Word)) inputRegs = takeAt(valueof(MD6_n)-valueof(taps),shifter.regs); + inputRegs[zeroExtend(index)]._write(word); + if(index == 0) + begin + shifter.advance; // problems here. + // this advance should occur MD6_b/taps - 1 times + end + endmethod + + + method ActionValue#(MD6Word) outputWord() if( state == ExternalDataOut ); + if(externalDataCountNext == fromInteger(valueof(MD6_c))) + begin + externalDataCount <= 0; + state <= Idle; + $display("Finished"); + end + else + begin + externalDataCount <= truncate(externalDataCountNext); + end + $display("Compression function is outputing"); + Vector#(taps,Reg#(MD6Word)) resultVec = takeAt(valueof(MD6_n)-valueof(MD6_c),shifter.regs); + // This is probably wrong now. + Bit#(TLog#(taps)) index = truncate(externalDataCount); + if(index == ~0) + begin + shifter.advance; + end + return resultVec[index]._read; + endmethod + + method Bit#(16) status(); + return zeroExtend(pack(state)); + endmethod +endmodule \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/CompressionFunctionTestbench.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/CompressionFunctionTestbench.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/CompressionFunctionTestbench.bsv (revision 2) @@ -0,0 +1,157 @@ +import LFSR::*; +import Vector::*; + +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunction::*; +import CompressionFunctionLibrary::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; + + +import "BDPI" function Action testSanityCheck(Bit#(64) md6_w_val, Bit#(64) md6_n_val, Bit#(64) md6_c_val, + Bit#(64) md6_b_val, Bit#(64) md6_v_val, Bit#(64) md6_u_val, + Bit#(64) md6_k_val, Bit#(64) md6_q_val, Bit#(64) md6_r_val); +import "BDPI" function Action writePlaintextValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeControlValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeUniqueValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeKeyValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeQValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action executeDecode(); +import "BDPI" function ActionValue#(MD6Word) readHash(Bit#(64) index); + + + +// This function will handle only the MD6 word + +typedef enum { + Initialize, + Running +} TestState deriving (Bits,Eq); + +/* +Vector#(MD6_k,MD6Word) key = replicate(0); +Vector#(MD6_u,MD6Word) identifier = replicate(0); +Round round = 0; +TreeHeight treeHeight = 0; +LastCompression lastCompression = 0; //One if last compression, else zero +PaddingBits paddingBits = 0; +KeyLength keyLength = fromInteger(valueof(MD6_k)); +DigestLength digestLength = 0; +*/ + +module mkCompressionFunctionTestbench(); + CompressionFunction#(16) compressionFunction <- mkSimpleCompressionFunction; + LFSR#(MD6Word) lfsr <- mkFeedLFSR(minBound | 9 ); // This might be random enough, maybe.. + Reg#(TestState) state <- mkReg(Initialize); + + Reg#(Bit#(TLog#(MD6_b))) externalData <- mkReg(0); + + Bit#(TLog#(TAdd#(MD6_b,1))) externalDataCountNext = zeroExtend(externalData) + 1; + + Reg#(Bool) failure <- mkReg(False); + + Reg#(Bit#(10)) testCount <- mkReg(0); + + Reg#(Vector#(MD6_k,MD6Word)) key <- mkReg(replicate(0)); + Reg#(Vector#(MD6_u,MD6Word)) identifier <- mkReg(replicate(0)); + Reg#(Round) round <- mkReg(fromInteger(valueof(MD6_r))); + Reg#(TreeHeight) treeHeight <- mkReg(0); + Reg#(LastCompression) lastCompression <- mkReg(0); + Reg#(KeyLength) keyLength <- mkReg(fromInteger(valueof(MD6_k))); + Reg#(DigestLength) digestLength <- mkReg(0); + Reg#(PaddingBits) paddingBits <- mkReg(0); + + rule initialize(state == Initialize); + lfsr.seed(~0); + state <= Running; + testSanityCheck(fromInteger(valueof(MD6_WordWidth)), fromInteger(valueof(MD6_n)), fromInteger(valueof(MD6_c)), + fromInteger(valueof(MD6_b)), fromInteger(valueof(MD6_v)), fromInteger(valueof(MD6_u)), + fromInteger(valueof(MD6_k)), fromInteger(valueof(MD6_q)), fromInteger(valueof(MD6_r))); + + + $display("Testbench Init MD6_c: %d MD6_WW: %d MD6_n: %d",valueof(MD6_c), valueof(MD6_WordWidth), valueof(MD6_n)); + $display("Testbench Taps t0: %d, t1: %d, t2: %d, t3: %d, t4: %d", determineT0, determineT1, determineT2, determineT3, determineT4); + endrule + + function sub(a,b); + return a-b; + endfunction + + rule startDecode(state == Running); + let controlWord = makeControlWord(round,treeHeight,lastCompression,paddingBits,keyLength,digestLength); + identifier <= unpack(pack(identifier) + 1); + key <= zipWith(sub,map(fromInteger,genVector),replicate(lfsr.value)); + + compressionFunction.start(identifier, + controlWord, + key); + + testCount <= testCount + 1; + if(testCount + 1 == 0) + begin + $display("PASS"); + $finish; + end + // Dump stuff into + for(Integer i = 0; i < valueof(MD6_v); i = i+1) + begin + writeUniqueValue(identifier[fromInteger(i)],fromInteger(i)); + end + for(Integer i = 0; i < valueof(MD6_u); i = i+1) + begin + writeControlValue(controlWord[fromInteger(i)],fromInteger(i)); + end + for(Integer i = 0; i < valueof(MD6_k); i = i+1) + begin + writeKeyValue(key[fromInteger(i)],fromInteger(i)); + end + for(Integer i = 0; i < valueof(MD6_q); i = i+1) + begin + $display("Writing Q value[%h]: %h", i,getQWord(fromInteger(i))); + writeQValue(getQWord(fromInteger(i)),fromInteger(i)); + end + + $display("Testbench Start"); + endrule + + rule sendInData(state == Running); + writePlaintextValue(lfsr.value, fromInteger(valueof(MD6_b)) - zeroExtend(externalData) - 1); + if(externalDataCountNext == fromInteger(valueof(MD6_b))) + begin + // Kick off something here? Is the ordering okay? + executeDecode(); + externalData <= 0; + end + else + begin + externalData <= truncate(externalDataCountNext); + end + lfsr.next(); + + compressionFunction.inputWord(lfsr.value); + endrule + + rule getOutData(state == Running); + MD6Word outWord <- compressionFunction.outputWord(); + MD6Word goldenWord <- readHash(fromInteger(valueof(MD6_c)) - zeroExtend(externalData) - 1); + if(outWord != goldenWord) + begin + $display("Failure - outWord: %h goldenWord: %h", outWord, goldenWord); + failure <= True; + end + if(externalDataCountNext == fromInteger(valueof(MD6_c))) + begin + if(failure) + begin + $finish; + end + externalData <= 0; + end + else + begin + externalData <= truncate(externalDataCountNext); + end + endrule +endmodule + Index: trunk/MD6Control/test/benchmarks/MD6Control.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/MD6Control.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/MD6Control.bsv (revision 2) @@ -0,0 +1,362 @@ +//Global includes +import FIFO::*; +import Vector::*; +import GetPut::*; + +//CSG Lib includes +import PLBMaster::*; +import PLBMasterDefaultParameters::*; + + +//Local Includes +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunction::*; +import CompressionFunctionTypes::*; +import CompressionFunctionLibrary::*; + + +interface MD6Control#(numeric type engines, numeric type steps); + method ActionValue#(MD6Word) wordOutput(); + method Action wordInput(MD6Word inWord); + method ActionValue#(PLBMasterCommand) outputCommand(); + method Action startDecode(); + method Bool running(); + interface Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyRegister; + interface Reg#(BlockAddr) sourceAddress; + interface Reg#(BlockAddr) destinationAddress; + interface Reg#(BlockAddr) bufferAddress; + interface Reg#(Bit#(TLog#(MD6_BitSize))) bitSize; + +endinterface + + +typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst; +typedef TDiv#(MD6_c,MD6WordsPerBurst) MD6BurstsPerHashStore; +typedef TDiv#(MD6_b,MD6WordsPerBurst) MD6BurstsPerHashLoad; +typedef TMul#(MD6_b,MD6_WordWidth) MD6BitsPerHashInput; +typedef TMul#(MD6_c,MD6_WordWidth) MD6BitsPerHashOutput; + + +typedef enum { + Idle, + IdleWait, + LevelStart, + LevelCompute +} ControlState deriving (Bits,Eq); + + +typedef enum { + PadBlock, + NoPad, + AllPad // Need a seperate rule for this one, not tied externally. +} IncomingBlock deriving (Bits, Eq); + +typedef enum { + Normal, + FinalBlock +} OutgoingBlock deriving (Bits, Eq); + +module mkMD6Control (MD6Control#(engines,steps)) + provisos(Add#(steps,xxx,MD6_n), + Add#(yyy,TLog#(steps),TLog#(MD6_n)), + Add#(zzz,TLog#(steps),TLog#(MD6_b)), + Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64)); + + Vector#(engines,CompressionFunction#(steps)) md6Engines <- replicateM(mkSimpleCompressionFunction); + + /* These registers are externally visible. Therefore, they must not be modified */ + Reg#(BlockAddr) md6SourceAddr <- mkReg(0); + Reg#(BlockAddr) md6DestinationAddr <- mkReg(0); + Reg#(BlockAddr) md6BufferAddr <- mkReg(0); + Reg#(Bit#(TLog#(MD6_BitSize))) md6BitSize <- mkReg(0); + Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyReg <- mkRegU(); + + + + /* These regs are used per computation */ + //Reg#(MD6_BitSize) bitsRemaining <- mkReg(0); + Reg#(Bit#(TLog#(MD6_BitSize))) dataBlocksRemaining <- mkReg(0); + Reg#(Bit#(TDiv#(MD6_b,MD6_c))) paddingBlocksRemaining <- mkReg(0); + Reg#(TreeHeight) currentHeight <- mkReg(0); + Reg#(Bit#(TLog#(MD6_b))) wordsIncoming <- mkReg(0); + Reg#(Bit#(TLog#(MD6_c))) wordsOutgoing <- mkReg(0); + Reg#(Bit#(TLog#(engines))) targetEngine <- mkReg(0); + Reg#(ControlState) state <- mkReg(Idle); + Reg#(Bit#(TAdd#(1,TLog#(MD6BurstsPerHashLoad)))) loadCount <- mkReg(0); + Reg#(Bit#(TLog#(MD6BurstsPerHashStore))) storeCount <- mkReg(0); + Reg#(BlockAddr) sourceAddr <- mkReg(0); + Reg#(BlockAddr) destAddr <- mkReg(0); + Reg#(Bool) lastCompression <- mkReg(False); + Reg#(Vector#(MD6_u,Bit#(MD6_WordWidth))) identifier <- mkRegU(); + + FIFO#(Tuple2#(IncomingBlock,Bit#(TLog#(engines)))) inTokens <- mkFIFO; + FIFO#(Tuple2#(OutgoingBlock,Bit#(TLog#(engines)))) outTokens <- mkFIFO; + FIFO#(Bit#(TLog#(engines))) readyEngine <- mkFIFO; + FIFO#(PLBMasterCommand) plbCommand <- mkSizedFIFO(1); + + // This needs to be as big as an input block. + Reg#(Bit#(TLog#(MD6BitsPerHashInput))) tailNonZeroBits <- mkReg(0); + Reg#(Bool) waitingForPad <- mkReg(False); + + function Action setupLevel() + provisos(Add#(steps,xxx,MD6_n), + Add#(yyy,TLog#(steps),TLog#(MD6_n)), + Add#(zzz,TLog#(steps),TLog#(MD6_b)), + Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64)); + action + // this is probably wrong + Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize); + match {.wholeBlocks, .tailBits} = currentBits; + $display("Current bits: %d %d", currentBits, md6BitSize); + $display("whole blocks: %d", wholeBlocks); + tailNonZeroBits <= tailBits; // Probably some sizing issue here. + Bit#(TDiv#(MD6_b,MD6_c)) leftoverBlocks = truncate(wholeBlocks) + ((tailBits!=0)?1:0); + Bit#(TDiv#(MD6_b,MD6_c)) paddingBlocks = truncate(fromInteger(valueof(TDiv#(MD6_b,MD6_c)))-zeroExtend(leftoverBlocks)); + dataBlocksRemaining <= zeroExtend(wholeBlocks)+((tailBits!=0)?1:0); + paddingBlocksRemaining <= paddingBlocks; + $display("Padding Blocks: %d", paddingBlocks); + state <= LevelCompute; + if(state == Idle) + begin + sourceAddr <= md6SourceAddr; + end + else + begin + sourceAddr <= md6BufferAddr; + end + identifier <= replicate(0); + // Check for last compression + if(wholeBlocks <= 1) + begin + $display("Setting the lastCompression"); + destAddr <= md6DestinationAddr; + lastCompression <= True; + end + else + begin + destAddr <= md6BufferAddr; + lastCompression <= False; + end + endaction + endfunction + + rule levelRule (state == LevelStart && !waitingForPad); + currentHeight <= currentHeight+1; + setupLevel(); + endrule + + rule computeRule (state == LevelCompute); + if(loadCount == 0 && storeCount == 0) + begin + PaddingBits padding = 0; + $display("Starting engine: %d", targetEngine); + if(targetEngine == fromInteger(valueof(engines)-1)) + begin + targetEngine <= 0; + end + else + begin + targetEngine <= targetEngine + 1; + end + // Determine pad status + // We have more regular data left to go. May need to count up on this one + dataBlocksRemaining <= dataBlocksRemaining - 1; + if((dataBlocksRemaining > 1) || (tailNonZeroBits == 0)) // We might have a full block + begin + inTokens.enq(tuple2(NoPad,targetEngine)); + end + else + begin + inTokens.enq(tuple2(PadBlock,targetEngine)); + waitingForPad <= True; + // Define a block as MD6_c words. + // In this case, we require some padding. + padding = fromInteger(valueof(MD6_WordWidth)*valueof(MD6_b)) - zeroExtend(tailNonZeroBits); + $display("tailNonZero: %d padding: %d",tailNonZeroBits,padding); + // seems that tailNonZero bits is getting smashed + end + + // Must also issue store token. + $display("outToken: %d", targetEngine); + if(dataBlocksRemaining == 1 && lastCompression) + begin + outTokens.enq(tuple2(FinalBlock,targetEngine)); + end + else + begin + outTokens.enq(tuple2(Normal,targetEngine)); + end + $display("Setting CW: r: %d, l: %d, z:%d, p:%d, keylen: %d, d: %d", valueof(MD6_r),30,(lastCompression)?1:0, + padding, //Padding + valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8), // Need Byte Size.... + valueof(MD6_d)); + + let controlWord = makeControlWord(fromInteger(valueof(MD6_r)), + 30, // This might be wrong + (lastCompression)?1:0, + padding, //Padding + fromInteger(valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8)), // Need Byte Size.... + fromInteger(valueof(MD6_d))); // this one is in bits. + // Construct identifier. + Bit#(8) identLevel = currentHeight; + Bit#(64) identifierFull = {identLevel,truncate(pack(identifier))}; + identifier <= unpack(pack(identifier) + 1); + md6Engines[targetEngine].start(unpack(pack(identifierFull)), controlWord, keyReg); + + end + + if( (loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) && + (storeCount == fromInteger(valueof(MD6BurstsPerHashStore)-1))) + begin + loadCount <= 0; + storeCount <= 0; + // Check for the need to transition out of this state. + // Hmm... This doesn't seem right probably only want to transition + // once we're sure when we're done. + $display("In unoptimized clause dataBlocksRemaining: %d", dataBlocksRemaining); + // Correct as we require 1 load/1 store at least + if(dataBlocksRemaining == 0) + begin + + if(lastCompression) + begin + $display("Setting state idlewait"); + state <= IdleWait; + end + else + begin + //must fix md6BitSize here. + // Probably have to fix type... + Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize); + Bit#(TLog#(MD6BitsPerHashOutput)) bottomZeros= 0; + match {.wholeBlocks, .tailBits} = currentBits; + + md6BitSize <= zeroExtend({((tailBits!=0)?wholeBlocks+1:wholeBlocks), bottomZeros}); + state <= LevelStart; + end + end + + + plbCommand.enq(tagged StorePage destAddr); + destAddr <= truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst))))); + // Actually issue the store here + + end + // This clause optimized away for default params. + else if((loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) && + (storeCount < fromInteger(valueof(MD6BurstsPerHashStore)-1))) + begin + $display("In optimized clause"); + storeCount <= storeCount + 1; + plbCommand.enq(tagged StorePage destAddr); + destAddr <= truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst))))); + end + else + begin + loadCount <= loadCount + 1; + $display("Issue Load: %d", sourceAddr); + plbCommand.enq(tagged LoadPage sourceAddr); + sourceAddr <= truncateLSB({sourceAddr,0} + (1 << (valueof(TLog#(WordsPerBurst))))); + end + endrule + + + // This rule will feed output from the MD6 engine to the memory controller + method ActionValue#(MD6Word) wordOutput(); + match {.block, .engine} = outTokens.first; + if(wordsOutgoing == fromInteger(valueof(MD6_c) - 1)) + begin + wordsOutgoing <= 0; + outTokens.deq; + if(block == FinalBlock) + begin + state <= Idle; // At this point, we're really done... + end + end + else + begin + wordsOutgoing <= wordsOutgoing + 1; + end + $display("outgoing word"); + MD6Word word <- md6Engines[engine].outputWord; + return word; + endmethod + + // This rule handles input from the outside world to the MD6 controller + // This includes padding + method Action wordInput(MD6Word inWord); + // Must deal with zero padding at the end of the + // first round. + + $display("inputWord called: %h", inWord); + match {.blockType, .engine } = inTokens.first; + + if(wordsIncoming == fromInteger(valueof(MD6_b) - 1)) + begin + wordsIncoming <= 0; + if(blockType == PadBlock) + begin + waitingForPad <= False; + end + inTokens.deq; + end + else + begin + wordsIncoming <= wordsIncoming + 1; + end + + if(blockType == PadBlock) + begin + $display("Padblock, tailNonZeroBits: %d", tailNonZeroBits); + // Now, pad the leftover bits to zero + if(tailNonZeroBits > fromInteger(valueof(MD6_WordWidth))) + begin + tailNonZeroBits <= tailNonZeroBits - fromInteger(valueof(MD6_WordWidth)); + md6Engines[engine].inputWord(inWord); + end + else if(tailNonZeroBits > 0) + begin + Bit#(TLog#(MD6_WordWidth)) shiftValue = truncate(tailNonZeroBits); + Bit#(MD6_WordWidth) paddedWord = inWord & (~0 >> shiftValue); + md6Engines[engine].inputWord(paddedWord); + tailNonZeroBits <= 0; + end + else // All zeros from here. + begin + md6Engines[engine].inputWord(0); + end + end + else if(blockType == NoPad) + begin + md6Engines[engine].inputWord(inWord); + end + endmethod + + method ActionValue#(PLBMasterCommand) outputCommand(); + plbCommand.deq; + return plbCommand.first; + endmethod + + // On the first pass only, we may have some tail non-zero bits. we must pad these out. + // All blocks must be padded to MD6_WordWidth + method Action startDecode(); + if(state == Idle) + begin + currentHeight <= 1; + setupLevel(); + end + endmethod + + method Bool running(); + return !(state == Idle); + endmethod + + interface Reg keyRegister = keyReg; + interface Reg sourceAddress = md6SourceAddr; + interface Reg destinationAddress = md6DestinationAddr; + interface Reg bufferAddress = md6BufferAddr; + interface Reg bitSize = md6BitSize; + + +endmodule \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/MD6ControlTest.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/MD6ControlTest.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/MD6ControlTest.bsv (revision 2) @@ -0,0 +1,77 @@ +//BSV includes +import RegFile::*; +import Connectable::*; +import GetPut::*; +import StmtFSM::*; + +//CSG Lib includes +import PLBMaster::*; +import PLBMasterDefaultParameters::*; +import PLBMasterEmulator::*; + +//Local includes +import MD6Parameters::*; +import MD6Types::*; +import MD6Control::*; +import CompressionFunctionTypes::*; + + + + +module mkMD6ControlTest (); + RegFile#(Bit#(20),BusWord) memory <- mkRegFileFullLoad("md6Input.hex"); + PLBMasterEmulator#(TExp#(20)) plbmaster <- mkPLBMasterEmulator(memory); + MD6Control#(1,16) control <- mkMD6Control; + // Hook up the system + mkConnection(plbmaster.plbmaster.wordInput.put,control.wordOutput); + mkConnection(control.wordInput,plbmaster.plbmaster.wordOutput.get); + mkConnection(plbmaster.plbmaster.plbMasterCommandInput.put,control.outputCommand); + + + Reg#(Bit#(32)) memPtr <- mkReg(0); + + RegFile#(Bit#(1), Bit#(32)) rfileSize <- mkRegFileFullLoad("inputSize.hex"); + RegFile#(Bit#(TLog#(MD6_c)), BusWord) rfileRes <- mkRegFileFullLoad("md6Result.hex"); + Reg#(Bit#(TAdd#(TLog#(MD6_c),1))) resPtr <- mkReg(0); + + let inputSize = (((rfileSize.sub(0))/fromInteger(valueof(MD6_b))) + 1)*fromInteger(valueof(MD6_b)); + + + Stmt s = seq + control.keyRegister <= unpack(0); + control.sourceAddress <= 0; + $display("Offset is: %d", inputSize); + control.destinationAddress <= 2*truncate(inputSize); + control.bufferAddress <= 4*truncate(inputSize); + $display("Bytes input: %d", rfileSize.sub(0)); + control.bitSize <= zeroExtend(rfileSize.sub(0)) * 8; + control.startDecode(); + await(!control.running); + delay(100); + for(resPtr <= 0; + resPtr < fromInteger(valueof(MD6_c)); + resPtr <= resPtr+1) + seq + if(rfileRes.sub(truncate(resPtr)) != memory.sub(truncate(zeroExtend(resPtr) + inputSize))) + seq + $display("Offset: %d rfile: %d",zeroExtend(resPtr), rfileSize.sub(0)); + $display("FAILED at %d, %h != %h", inputSize+zeroExtend(resPtr),rfileRes.sub(truncate(resPtr)),memory.sub(truncate(zeroExtend(resPtr) + inputSize))); + $finish; + endseq + else + seq + $display("Match at %d", zeroExtend(resPtr) + inputSize); + endseq + endseq + $display("PASS"); + $finish; + endseq; + + FSM fsm <- mkFSM(s); + + + rule startFSM; + fsm.start; + endrule + +endmodule \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/MD6ShiftRegister.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/MD6ShiftRegister.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/MD6ShiftRegister.bsv (revision 2) @@ -0,0 +1,81 @@ +import FIFOF::*; +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; +import CompressionFunctionLibrary::*; +import Debug::*; +import SGenerator::*; +import Vector::*; + +interface MD6ShiftRegister#(numeric type taps); + method Vector#(taps,MD6Word) getT0; + method Vector#(taps,MD6Word) getT1; + method Vector#(taps,MD6Word) getT2; + method Vector#(taps,MD6Word) getT3; + method Vector#(taps,MD6Word) getT4; + method Vector#(taps,MD6Word) getT5; + method Action write(Vector#(taps,MD6Word) nextValues); + method Action advance(); +// method Action advanceB(); + interface Vector#(MD6_n, Reg#(MD6Word)) regs; +endinterface + + +module mkMD6ShiftRegister (MD6ShiftRegister#(taps)) + provisos(Add#(taps,yyy,MD6_n)); + Integer historyLength = valueof(taps); + Vector#(MD6_n,Reg#(MD6Word)) t0 <- replicateM(mkReg(0)); + // we pulled out a subtraction of history length + method Vector#(taps,MD6Word) getT0; + return takeAt(determineT0,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT1; + return takeAt(determineT1,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT2; + return takeAt(determineT2,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT3; + return takeAt(determineT3,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT4; + return takeAt(determineT4,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT5; + return takeAt(determineT5,readVReg(t0)); + endmethod + + method Action write(Vector#(taps,MD6Word) nextword); + writeVReg(takeAt(valueof(MD6_n)-valueof(taps),t0),nextword); + endmethod + + method Action advance(); + for(Integer i = 0; i < valueof(MD6_n); i=i+1) + begin +// $display("Advance ShiftState[%d]: %h",i, t0[i]); + end + for(Integer i = 0; i < valueof(MD6_n)-valueof(taps); i=i+1) + begin + t0[i] <= t0[i+valueof(taps)]; + end + endmethod + +/* This may no longer be necessary + method Action advanceB(); + for(Integer i = valueof(MD6_n) - valueof(MD6_b); i < valueof(MD6_n) - valueof(taps); i=i+1) + begin + //$display("advanceB ShiftState[%d]: %h <= %h",i, t0[i+valueof(taps)],t0[i]); + t0[i+valueof(taps)] <= t0[i]; + end + endmethod +*/ + + interface regs = t0; + +endmodule \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/SGenerator.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/SGenerator.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/SGenerator.bsv (revision 2) @@ -0,0 +1,37 @@ +// CSG includes +import Debug::*; + +// Local includes +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; + +Bool sgenDebug = False; + +interface SGenerator; + method MD6Word getS(); + method Action advanceRound(); + method Action resetS(); +endinterface + + +module mkSGeneratorLogic (SGenerator); + Reg#(MD6Word) s <- mkReg(s0()); // Grab S0 from parameters + + method MD6Word getS(); + return s; + endmethod + + method Action advanceRound(); + MD6Word sRotate = (s << 1) | zeroExtend(s[valueof(MD6_WordWidth)-1]); + MD6Word nextS = sRotate ^ (s & sStar()); + s <= nextS; + debug(sgenDebug,$display("Advancing s, old s: %h, new s:%h", s, nextS)); + endmethod + + method Action resetS(); + s <= s0(); + endmethod + +endmodule Index: trunk/MD6Control/test/benchmarks/MD6Parameters.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/MD6Parameters.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/MD6Parameters.bsv (revision 2) @@ -0,0 +1,69 @@ +// The following are magic, externally defined parameters in MD6 +// Other important parameters are derived from them. +// These parameters are used at a global level + + +`ifdef BIT64 +typedef 16 MD6_c; +typedef 512 MD6_d; // Bits in final hashvalue +typedef 64 MD6_b; +typedef 178 MD6_r; + +typedef 89 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 15 MD6_q; +typedef 8 MD6_k; +typedef 1 MD6_v; +typedef 1 MD6_u; + +typedef 64 MD6_WordWidth; +`endif + +// All that appears to change for +// different word widths is the WordWidth. +// Other fields seem to get dropped. +`ifdef BIT32 +typedef 32 MD6_c; +typedef 128 MD6_b; +typedef 178 MD6_r; + +typedef 178 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 30 MD6_q; +typedef 16 MD6_k; + +typedef 2 MD6_v; +typedef 2 MD6_u; + +typedef 32 MD6_WordWidth; +`endif + +`ifdef BIT16 +typedef 64 MD6_c; +typedef 256 MD6_b; +typedef 178 MD6_r; + +typedef 178 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 30 MD6_q; +typedef 16 MD6_k; +typedef 2 MD6_v; +typedef 2 MD6_u; + +typedef 16 MD6_WordWidth; +`endif + +`ifdef BIT8 +typedef 32 MD6_c; +typedef 128 MD6_b; +typedef 178 MD6_r; + +typedef 178 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 30 MD6_q; +typedef 16 MD6_k; +typedef 2 MD6_v; +typedef 2 MD6_u; + +typedef 32 MD6_WordWidth; +`endif \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/CompressionFunctionParameters.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/CompressionFunctionParameters.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/CompressionFunctionParameters.bsv (revision 2) @@ -0,0 +1,71 @@ +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; + +// The following are magic, externally defined parameters in MD6 +// Other important parameters are derived from them. +// These parameters are used solely within the compression +// function. + +function MD6Word s0(); + return truncateLSB(64'h0123456789abcdef); +endfunction + +function MD6Word sStar(); + return truncateLSB(64'h7311c2812425cfa0); +endfunction + +// These tables are all of size 16. MD6 does not have a definition for +// Non-size 16 value of MD6_c +ShiftFactor c64ShiftR[16] = {4,11,10,32,13,3,10,23,22,6,5,12,15,1,18,28}; + +ShiftFactor c64ShiftL[16] = {5,6,19,4,8,9,24,15,7,3,20,29,13,3,15,14}; + +ShiftFactor c32ShiftR[16] = {7,13,1,8,15,3,16,13,2,3,13,9,7,10,2,4}; + +ShiftFactor c32ShiftL[16] = {15,12,3,16,10,7,5,9,4,9,16,12,11,5,1,13}; + +ShiftFactor c16ShiftR[16] = {7,4,1,7,2,1,5,7,2,1,7,1,2,7,7,8}; + +ShiftFactor c16ShiftL[16] = {3,5,2,2,4,5,3,4,6,5,4,2,3,2,6,5}; + +ShiftFactor c8ShiftR[16] = {1,1,2,1,2,3,2,3,1,3,2,2,1,1,4,2}; + +ShiftFactor c8ShiftL[16] = {3,2,4,3,3,4,1,1,2,4,4,3,4,2,3,3}; + + + + + +// This is the sqrt(6) vector value. It should probably be longer than this +Bit#(TMul#(16,64)) vectorQ = { + 64'h8b30ed2e9956c6a0, + 64'h0d6f3522631effcb, + 64'h3b72066c7a1552ac, + 64'hc878c1dd04c4b633, + 64'h995ad1178bd25c31, + 64'h8af8671d3fb50c2c, + 64'h3e7f16bb88222e0d, + 64'h4ad12aae0a6d6031, + 64'h54e5ed5b88e3775d, + 64'h1f8ccf6823058f8a, + 64'h0cd0d63b2c30bc41, + 64'hdd2e76cba691e5bf, + 64'he8fb23908d9f06f1, + 64'hb60450e9ef68b7c1, + 64'h6432286434aac8e7, + 64'h7311c2812425cfa0}; + +//This might well be enormous. +function MD6Word getQWord(Bit#(TLog#(MD6_q)) index); + Bit#(TLog#(TMul#(MD6_q,MD6_WordWidth))) baseIndex = fromInteger(valueof(MD6_WordWidth))*zeroExtend(index); + return vectorQ[(baseIndex+fromInteger(valueof(MD6_WordWidth)-1)):baseIndex]; +endfunction + +function MD6Word extractWord(Bit#(n) bitVector, Bit#(m) index) + provisos( + Add#(a,m,TAdd#(m,TLog#(MD6_WordWidth)))); + Bit#(TAdd#(m,TLog#(MD6_WordWidth))) baseIndex = fromInteger(valueof(MD6_WordWidth))*zeroExtend(index); + return bitVector[(baseIndex+fromInteger(valueof(MD6_WordWidth)-1)):baseIndex]; +endfunction + Index: trunk/MD6Control/test/benchmarks/MD6Types.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/MD6Types.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/MD6Types.bsv (revision 2) @@ -0,0 +1,13 @@ +import MD6Parameters::*; + +typedef Bit#(MD6_WordWidth) MD6Word; +typedef (TExp#(64)) MD6_BitSize; + + +typedef Bit#(12) Round; +typedef Bit#(8) TreeHeight; + +typedef Bit#(4) LastCompression; //One if last compression, else zero +typedef Bit#(16) PaddingBits; +typedef Bit#(8) KeyLength; +typedef Bit#(12) DigestLength; \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/CompressionFunctionLibrary.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/CompressionFunctionLibrary.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/CompressionFunctionLibrary.bsv (revision 2) @@ -0,0 +1,171 @@ +import Vector::*; + +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; + + +// The following are magic, externally defined parameters in MD6 +// Other important parameters are derived from them. +// These parameters are used solely within the compression +// function. + +// This set of functions determines the locations of the filter taps +// these index into the constant array given in appendix C of the spec. +// TODO: kfleming - these are currently constant functions. +function Integer determineT0(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 17; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 33; + end + else + begin + let err = error("T0 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT1(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 18; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 35; + end + else + begin + let err = error("T1 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT2(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 21; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 49; + end + else + begin + let err = error("T2 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT3(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 31; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 53; + end + else + begin + let err = error("T3 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT4(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 67; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 111; + end + else + begin + let err = error("T4 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT5(); + return 0; +endfunction + +// This function returns the shift amounts. The argument is the step +// index. + +function ShiftFactor shiftIndexR(Bit#(4) index); + if(valueof(MD6_WordWidth) == 64) + begin + return c64ShiftR[index]; + end + else if(valueof(MD6_WordWidth) == 32) + begin + return c32ShiftR[index]; + end + else if(valueof(MD6_WordWidth) == 16) + begin + return c16ShiftR[index]; + end + else if(valueof(MD6_WordWidth) == 8) + begin + return c8ShiftR[index]; + end + else + begin + return 0; + end +endfunction + +function ShiftFactor shiftIndexL(Bit#(4) index); + if(valueof(MD6_WordWidth) == 64) + begin + return c64ShiftL[index]; + end + else if(valueof(MD6_WordWidth) == 32) + begin + return c32ShiftL[index]; + end + else if(valueof(MD6_WordWidth) == 16) + begin + return c16ShiftL[index]; + end + else if(valueof(MD6_WordWidth) == 8) + begin + return c8ShiftL[index]; + end + else + begin + return 0; + end +endfunction + +function Vector#(MD6_u, MD6Word) makeControlWord(Round rounds, + TreeHeight maxTreeHeight, + LastCompression lastCompression, + PaddingBits paddingBits, + KeyLength keyLength, + DigestLength digestLength) + provisos(Bits#(MD6Word, md6_size)); + Bit#(64) controlWord = {4'b0000,rounds,maxTreeHeight,lastCompression, + paddingBits,keyLength, digestLength}; + MD6Word controlArray[valueof(MD6_u)]; + for(Integer i = 0; i < valueof(MD6_u); i = i + 1) + begin + controlArray[fromInteger(i)] = controlWord[(i+1)*valueof(md6_size)-1:i*valueof(md6_size)]; + end + Vector#(MD6_u, MD6Word) controlVector = arrayToVector(controlArray); + return controlVector; +endfunction \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/CompressionFunctionTypes.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/CompressionFunctionTypes.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/CompressionFunctionTypes.bsv (revision 2) @@ -0,0 +1,7 @@ +// This file contains types used in the compression function + +// Control Word types + + + +typedef Bit#(6) ShiftFactor; \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/ControlWord.bsv =================================================================== Index: trunk/MD6Control/test/benchmarks/MD6Engine.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/MD6Engine.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/MD6Engine.bsv (revision 2) @@ -0,0 +1,300 @@ +/* +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 is the top-level sorter module. It interfaces to the PLB bus, the + DSOCM, and the sorter core. Not much functionality, but it does have + a cycle timer, and sends periodic messages back to the PPC over the + DSOCM +*/ + +// Bluespec Lib +import FIFO::*; +import GetPut::*; +import Vector::*; +import Connectable::*; + +// CSG Lib +import PLBMasterWires::*; +import BRAMInitiatorWires::*; +import PLBMaster::*; +import BRAMFeeder::*; +import PLBMaster::*; +import PLBMasterDefaultParameters::*; + +// Local includes +import CompressionFunction::*; +import CompressionFunctionLibrary::*; +import MD6Parameters::*; +import MD6Types::*; + + +interface MD6Engine; + interface PLBMasterWires plbMasterWires; + interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires; +endinterface + +// Might consider making this size 8 at some point so that it jives with +// other parameterizations +typedef 16 InterfaceRegister; +typedef Bit#(15) RegisterTag; + +typedef enum { + Read = 0, + Write = 1 +} Command deriving (Bits,Eq); + + +typedef 7 ControlRegisters; +typedef TMul#(MD6_u,TDiv#(MD6_WordWidth,InterfaceRegister)) IdentifierRegisters; +typedef TMul#(MD6_k,TDiv#(MD6_WordWidth,InterfaceRegister)) KeyRegisters; +typedef 2 SourceRegisters; +typedef 2 DestinationRegisters; + +typedef 0 RoundRegister; +typedef 1 TreeHeightRegister; +typedef 2 LastCompressionRegister; +typedef 3 PaddingBitsRegister; +typedef 4 KeyLengthRegister; +typedef 5 DigestLengthRegister; +typedef 6 CompressionFunctionStatus; +typedef 7 KeyRegisterBase; +typedef TAdd#(ControlRegisters,KeyRegisters) IdentifierRegisterBase; +typedef TAdd#(ControlRegisters, TAdd#(KeyRegisters,IdentifierRegisters)) SourceRegisterBase; +typedef TAdd#(TAdd#(ControlRegisters,IdentifierRegisters), TAdd#(KeyRegisters,SourceRegisters)) DestinationRegisterBase; +typedef TAdd#(IdentifierRegisters,TAdd#(TAdd#(ControlRegisters,DestinationRegisters), TAdd#(KeyRegisters,SourceRegisters))) TotalRegisters; + +typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst; + +typedef 32'hC0000 MD6CommunicationConstant; + +typedef struct { + Command command; + RegisterTag regTag; + Bit#(InterfaceRegister) payload; +} IOCommand deriving (Bits,Eq); + +typedef enum { + Idle, + Load +} LoadState deriving (Bits,Eq); + +typedef enum { + Idle, + Store +} StoreState deriving (Bits,Eq); + + +(*synthesize*) +module mkCompressionFunction16 (CompressionFunction#(16)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction8 (CompressionFunction#(8)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction4 (CompressionFunction#(4)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction2 (CompressionFunction#(2)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction1 (CompressionFunction#(1)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + + +module mkMD6Engine (MD6Engine); + Feeder feeder <- mkBRAMFeeder(); + PLBMaster plbMaster <- mkPLBMaster; + CompressionFunction#(4) compressionFunction <- mkSimpleCompressionFunction; + FIFO#(PPCMessage) outputFIFO <- mkFIFO; + Vector#(TotalRegisters, Reg#(Bit#(InterfaceRegister))) interfaceRegisters <- + replicateM(mkReg(0)); + + + // Hook Control, PLBMaster and MD6 engine components together. + // This solution WILL NOT WORK for multiple Compression functions + mkConnection(plbMaster.wordInput.put, compressionFunction.outputWord); + mkConnection(compressionFunction.inputWord,plbMaster.wordOutput.get); + mkConnection(feeder.ppcMessageInput.put,(fifoToGet(outputFIFO)).get); + + Reg#(Bit#(TAdd#(1,TDiv#(MD6_b,MD6WordsPerBurst)))) loadCount <- mkReg(0); + + Reg#(Bit#(TAdd#(1,TDiv#(MD6_c,MD6WordsPerBurst)))) storeCount <- mkReg(0); + + Reg#(LoadState) loadState <- mkReg(Idle); + + Reg#(StoreState) storeState <- mkReg(Idle); + + FIFO#(IOCommand) incomingCommands <- mkFIFO; + + function IOCommand extractIOCommand(PPCMessage ppcMessage); + IOCommand command = IOCommand {command: unpack(ppcMessage[31]), + regTag: ppcMessage[30:16], + payload: ppcMessage[15:0]}; + return command; + endfunction + + // This function may require its own unit test + // It should convert interface words to MD6 Words + function Vector#(length,MD6Word) convertWords( + Vector#(TMul#(length,TDiv#(MD6_WordWidth,InterfaceRegister)),Bit#(InterfaceRegister)) inVector); + Vector#(length,MD6Word) outVector = newVector; + for(Integer totalNumber = 0; + totalNumber < valueof(length); + totalNumber = totalNumber + 1) + begin + Vector#(TDiv#(MD6_WordWidth,InterfaceRegister),Bit#(InterfaceRegister)) wordVector = newVector; + for(Integer wordsInMD6Word = 0; + wordsInMD6Word < valueof(TDiv#(MD6_WordWidth,InterfaceRegister)); + wordsInMD6Word = wordsInMD6Word + 1) + begin + wordVector[wordsInMD6Word] = inVector[totalNumber*valueof(TDiv#(MD6_WordWidth,InterfaceRegister)) + +wordsInMD6Word]; + end + outVector[totalNumber] = unpack(pack(wordVector)); // is this sane? + end + return outVector; + endfunction + + rule getCommand; + PPCMessage msg <- feeder.ppcMessageOutput.get; + IOCommand command = extractIOCommand(msg); + incomingCommands.enq(command); + endrule + + // Writing to the CompressionFunctionStatus means kickoff a compression operation + // Reading from it will grab the current status of the Compression Engine + + rule processWrite(incomingCommands.first.command == Write); + incomingCommands.deq; + + if(fromInteger(valueof(CompressionFunctionStatus)) == incomingCommands.first.regTag) + begin + // we can leave this unguarded because the properties of the compression function + // will prevent doing nasty things like confusing the order of memory accesses. + let controlWord = makeControlWord(truncate(interfaceRegisters[valueof(RoundRegister)]), + truncate(interfaceRegisters[valueof(TreeHeightRegister)]), + truncate(interfaceRegisters[valueof(LastCompressionRegister)]), + truncate(interfaceRegisters[valueof(PaddingBitsRegister)]), + truncate(interfaceRegisters[valueof(KeyLengthRegister)]), + truncate(interfaceRegisters[valueof(DigestLengthRegister)])); + + compressionFunction.start(convertWords(takeAt(valueof(IdentifierRegisterBase),readVReg(interfaceRegisters))), + controlWord, + convertWords(takeAt(valueof(KeyRegisterBase),readVReg(interfaceRegisters)))); + loadState <= Load; + loadCount <= 0; + end + else + begin + interfaceRegisters[incomingCommands.first.regTag] <= incomingCommands.first.payload; + end + endrule + + rule processRead(incomingCommands.first.command == Read); + incomingCommands.deq; + + // This is a bit ugly, and we should possibly fix it. + if(fromInteger(valueof(CompressionFunctionStatus)) == incomingCommands.first.regTag) + begin + outputFIFO.enq(fromInteger(valueof(MD6CommunicationConstant))|zeroExtend(compressionFunction.status)); + end + else + begin + outputFIFO.enq(fromInteger(valueof(MD6CommunicationConstant))|zeroExtend((interfaceRegisters[incomingCommands.first.regTag]))); + end + + endrule + + + + + // Probably should handle non-fitting burst sizes. But, don't have to + // for now. + if(valueof(TotalRegisters) != 47) + begin + error("Total Registers: %d\n",valueof(TotalRegisters)); + end + + if(valueof(MD6_b)%valueof(MD6WordsPerBurst) != 0) + begin + error("MD6_b:%d not divisible by MD6WordsPerBurst:%d",valueof(MD6_b), valueof(MD6WordsPerBurst)); + end + + if(valueof(MD6_c)%valueof(MD6WordsPerBurst) != 0) + begin + error("MD6_c:%d not divisible by MD6WordsPerBurst:%d",valueof(MD6_c), valueof(MD6WordsPerBurst)); + end + + rule issueLoads(loadState == Load); + if(loadCount + 1 == fromInteger(valueof(MD6_b)/valueof(MD6WordsPerBurst))) + begin + loadState <= Idle; + storeState <= Store; + storeCount <= 0; + end + loadCount <= loadCount + 1; + BlockAddr refAddr = truncateLSB({interfaceRegisters[valueof(SourceRegisterBase)+1], + interfaceRegisters[valueof(SourceRegisterBase)]}) + + (zeroExtend(loadCount) << (valueof(TLog#(WordsPerBurst)))); + + plbMaster.plbMasterCommandInput.put(tagged LoadPage refAddr); + endrule + + + + rule issueStores(storeState == Store); + if(storeCount + 1 == fromInteger(valueof(MD6_c)/valueof(MD6WordsPerBurst))) + begin + storeState <= Idle; + end + storeCount <= storeCount + 1; + + BlockAddr refAddr = truncateLSB({interfaceRegisters[valueof(DestinationRegisterBase)+1], + interfaceRegisters[valueof(DestinationRegisterBase)]}) + + (zeroExtend(storeCount) << (valueof(TLog#(WordsPerBurst)))); + + plbMaster.plbMasterCommandInput.put(tagged StorePage refAddr); + endrule + + interface plbMasterWires = plbMaster.plbMasterWires; + interface bramInitiatorWires = feeder.bramInitiatorWires; + +endmodule \ No newline at end of file Index: trunk/MD6Control/test/benchmarks/DataTypes.bsv =================================================================== --- trunk/MD6Control/test/benchmarks/DataTypes.bsv (nonexistent) +++ trunk/MD6Control/test/benchmarks/DataTypes.bsv (revision 2) @@ -0,0 +1 @@ +import FIFO::*; \ No newline at end of file Index: trunk/MD6Control/src/MD6Control.bsv =================================================================== --- trunk/MD6Control/src/MD6Control.bsv (nonexistent) +++ trunk/MD6Control/src/MD6Control.bsv (revision 2) @@ -0,0 +1,426 @@ +//Global includes +import FIFO::*; +import Vector::*; +import GetPut::*; +import ConfigReg::*; + +//CSG Lib includes +import PLBMaster::*; +import PLBMasterDefaultParameters::*; + + +//Local Includes +import MD6Parameters::*; +import MD6Types::*; +import MD6Library::*; +import CompressionFunction::*; +import CompressionFunctionTypes::*; +import CompressionFunctionLibrary::*; + + +interface MD6Control#(numeric type engines, numeric type steps); + method ActionValue#(MD6Word) wordOutput(); + method Action wordInput(MD6Word inWord); + method ActionValue#(PLBMasterCommand) outputCommand(); + method Action startDecode(); + method Bool running(); + interface Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyRegister; + interface Reg#(BlockAddr) sourceAddress; + interface Reg#(BlockAddr) destinationAddress; + interface Reg#(BlockAddr) bufferAddress; + interface Reg#(Bit#(TLog#(MD6_BitSize))) bitSize; + interface Reg#(Bool) bigEndian; + interface Reg#(DigestLength) digestLength; +endinterface + + +typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst; +typedef TDiv#(MD6_c,MD6WordsPerBurst) MD6BurstsPerHashStore; +typedef TDiv#(MD6_b,MD6WordsPerBurst) MD6BurstsPerHashLoad; +typedef TMul#(MD6_b,MD6_WordWidth) MD6BitsPerHashInput; +typedef TMul#(MD6_c,MD6_WordWidth) MD6BitsPerHashOutput; + + +typedef enum { + Idle, + IdleWait, + LevelStart, + LevelCompute +} ControlState deriving (Bits,Eq); + + +typedef enum { + PadBlock, + NoPad, + AllPad // Need a seperate rule for this one, not tied externally. +} IncomingBlock deriving (Bits, Eq); + +typedef enum { + Normal, + LastInLevel, + FinalBlock +} OutgoingBlock deriving (Bits, Eq); + +module mkMD6Control (MD6Control#(engines,steps)) + provisos(Add#(steps,xxx,MD6_n), + Add#(yyy,TLog#(steps),TLog#(MD6_n)), + Add#(zzz,TLog#(steps),TLog#(MD6_b)), + Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64)); + + Vector#(engines,CompressionFunction#(steps)) md6Engines; + + if(valueof(steps)<16) + begin + md6Engines <- replicateM(mkSimpleCompressionFunction); + end + else if(valueof(steps) % 16 == 0) + begin + md6Engines <- replicateM(mkMult16CompressionFunction); + end + else + begin + error("Unsupported Size"); + end + + /* These registers are externally visible. Therefore, they must not be modified */ + Reg#(BlockAddr) md6SourceAddr <- mkRegU(); + Reg#(BlockAddr) md6DestinationAddr <- mkRegU(); + Reg#(BlockAddr) md6BufferAddr <- mkRegU(); + Reg#(Bit#(TLog#(MD6_BitSize))) md6BitSize <- mkRegU(); + Reg#(DigestLength) digestLengthReg <- mkRegU(); // Do we want to fold this across + // The control engines themselves? + Reg#(Vector#(MD6_k,Bit#(MD6_WordWidth))) keyReg <- mkRegU(); + Reg#(Bool) bigEndianReg <- mkReg(False); + + + /* These regs are used per computation */ + //Reg#(MD6_BitSize) bitsRemaining <- mkReg(0); + Reg#(Bit#(TLog#(MD6_BitSize))) dataBlocksRemaining <- mkReg(0); + Reg#(Bit#(TDiv#(MD6_b,MD6_c))) paddingBlocksRemaining <- mkReg(0); + Reg#(TreeHeight) currentHeight <- mkReg(0); + Reg#(Bit#(TLog#(MD6_b))) wordsIncoming <- mkReg(0); + Reg#(Bit#(TLog#(MD6_c))) wordsOutgoing <- mkReg(0); + Reg#(Bit#(TLog#(engines))) targetEngine <- mkReg(0); + Reg#(ControlState) state <- mkReg(Idle); + Reg#(Bit#(TAdd#(1,TLog#(MD6BurstsPerHashLoad)))) loadCount <- mkReg(0); + Reg#(Bit#(TLog#(MD6BurstsPerHashStore))) storeCount <- mkReg(0); + Reg#(BlockAddr) sourceAddr <- mkReg(0); + Reg#(BlockAddr) destAddr <- mkReg(0); + Reg#(Bool) lastCompression <- mkReg(False); + Reg#(Bool) issuedStart <- mkReg(False); + Reg#(Vector#(MD6_u,Bit#(MD6_WordWidth))) identifier <- mkRegU(); + + FIFO#(Tuple2#(IncomingBlock,Bit#(TLog#(engines)))) inTokens <- mkFIFO; + FIFO#(Tuple2#(OutgoingBlock,Bit#(TLog#(engines)))) outTokens <- mkFIFO; + FIFO#(Bit#(TLog#(engines))) readyEngine <- mkFIFO; + FIFO#(PLBMasterCommand) plbCommand <- mkSizedFIFO(2); // why's this? + + // This needs to be as big as an input block. + Reg#(Bit#(TLog#(MD6BitsPerHashInput))) tailNonZeroBits <- mkReg(0); + Reg#(Bool) waitingForPad <- mkReg(False); + + function Action setupLevel() + provisos(Add#(steps,xxx,MD6_n), + Add#(yyy,TLog#(steps),TLog#(MD6_n)), + Add#(zzz,TLog#(steps),TLog#(MD6_b)), + Add#(wholeBlockBits,TLog#(MD6BitsPerHashInput),64)); + action + // this is probably wrong + Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize); + match {.wholeBlocks, .tailBits} = currentBits; + $display("Current bits: %d %d", currentBits, md6BitSize); + $display("whole blocks: %d", wholeBlocks); + tailNonZeroBits <= tailBits; // Probably some sizing issue here. + Bit#(TDiv#(MD6_b,MD6_c)) leftoverBlocks = truncate(wholeBlocks) + ((tailBits!=0)?1:0); + Bit#(TDiv#(MD6_b,MD6_c)) paddingBlocks = truncate(fromInteger(valueof(TDiv#(MD6_b,MD6_c)))-zeroExtend(leftoverBlocks)); + dataBlocksRemaining <= zeroExtend(wholeBlocks)+((tailBits!=0)?1:0); + paddingBlocksRemaining <= paddingBlocks; + $display("Padding Blocks: %d", paddingBlocks); + state <= LevelCompute; + if(state == Idle) + begin + sourceAddr <= md6SourceAddr; + end + else + begin + sourceAddr <= md6BufferAddr; + end + identifier <= replicate(0); + // Check for last compression + if((wholeBlocks == 0) || ((wholeBlocks == 1) && (tailBits == 0))) + begin + $display("Setting the lastCompression"); + destAddr <= md6DestinationAddr; + lastCompression <= True; + end + else + begin + destAddr <= md6BufferAddr; + lastCompression <= False; + end + endaction + endfunction + + rule levelRule (state == LevelStart && !waitingForPad); + currentHeight <= currentHeight+1; + setupLevel(); + endrule + + rule issueStart(state == LevelCompute && !issuedStart); + $display("calling issue start"); + issuedStart <= True; + PaddingBits padding = 0; + $display("Starting engine: %d", targetEngine); + if(targetEngine == fromInteger(valueof(engines)-1)) + begin + targetEngine <= 0; + end + else + begin + targetEngine <= targetEngine + 1; + end + // Determine pad status + // We have more regular data left to go. May need to count up on this one + if(dataBlocksRemaining != 0) // underflow may happen :( + begin + dataBlocksRemaining <= dataBlocksRemaining - 1; + end + + if((dataBlocksRemaining > 1) || ((dataBlocksRemaining!=0) && (tailNonZeroBits == 0))) // We might have a full block + begin + inTokens.enq(tuple2(NoPad,targetEngine)); + end + else + begin + inTokens.enq(tuple2(PadBlock,targetEngine)); + waitingForPad <= True; + // Define a block as MD6_c words. + // In this case, we require some padding. + padding = fromInteger(valueof(MD6_WordWidth)*valueof(MD6_b)) - zeroExtend(tailNonZeroBits); + $display("tailNonZero: %d padding: %d",tailNonZeroBits,padding); + // seems that tailNonZero bits is getting smashed + end + + // Must also issue store token. + $display("outToken: %d", targetEngine); + if(dataBlocksRemaining <= 1 && lastCompression) + begin + outTokens.enq(tuple2(FinalBlock,targetEngine)); + end + else if(dataBlocksRemaining <= 1) + // in this case, we must wait until the level finishes processing + // to start the next one. Not necessary for + // single engine. + begin + outTokens.enq(tuple2(LastInLevel,targetEngine)); + end + else + begin + outTokens.enq(tuple2(Normal,targetEngine)); + end + $display("Setting CW: r: %d, l: %d, z:%d, p:%d, keylen: %d, d: %d", valueof(MD6_r),30,(lastCompression)?1:0, + padding, //Padding + valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8), // Need Byte Size.... + valueof(MD6_d)); + + // Start cutting here? + + + Bit#(8) identLevel = currentHeight; + Bit#(64) identifierFull = {identLevel,truncate(pack(identifier))}; + identifier <= unpack(pack(identifier) + 1); + + md6Engines[targetEngine].start(defaultMD6R(digestLengthReg),64,(lastCompression)?1:0,padding, fromInteger(valueof(MD6_k)*valueof(MD6_WordWidth)/valueof(8)),digestLengthReg, unpack(pack(identifierFull)), keyReg); + // why call this first? This is a problem because we cannot overlap loads/stores. + endrule + + + rule issueStoreFinal (state == LevelCompute && (loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) && + (storeCount == fromInteger(valueof(MD6BurstsPerHashStore)-1)) && issuedStart); + $display("Firiing Store Final"); + issuedStart <= False; + loadCount <= 0; + storeCount <= 0; + // Check for the need to transition out of this state. + // Hmm... This doesn't seem right probably only want to transition + // once we're sure when we're done. + $display("In unoptimized clause dataBlocksRemaining: %d", dataBlocksRemaining); + // Correct as we require 1 load/1 store at least // Need to wait on level completion? + if(dataBlocksRemaining == 0) + begin + state <= IdleWait; + if(lastCompression) + begin + $display("Setting state idlewait"); + + end + else + begin + //must fix md6BitSize here. + // Probably have to fix type... + Tuple2#(Bit#(wholeBlockBits),Bit#(TLog#(MD6BitsPerHashInput))) currentBits = split(md6BitSize); + Bit#(TLog#(MD6BitsPerHashOutput)) bottomZeros= 0; + match {.wholeBlocks, .tailBits} = currentBits; + + md6BitSize <= zeroExtend({((tailBits!=0)?wholeBlocks+1:wholeBlocks), bottomZeros}); + + end + end + + + plbCommand.enq(tagged StorePage destAddr); + destAddr <= truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst))))); + // Actually issue the store here + endrule + + // This may be problematic + rule issueStore (state == LevelCompute && (loadCount == fromInteger(valueof(MD6BurstsPerHashLoad))) && + (storeCount < fromInteger(valueof(MD6BurstsPerHashStore)-1)) && issuedStart); + $display("In optimized clause"); + storeCount <= storeCount + 1; + plbCommand.enq(tagged StorePage destAddr); + destAddr <= truncateLSB({destAddr,0} + (1 << (valueof(TLog#(WordsPerBurst))))); + endrule + + rule issueLoad((state == LevelCompute) && (loadCount < fromInteger(valueof(MD6BurstsPerHashLoad)))); + loadCount <= loadCount + 1; + $display("Issue Load[%d of %d]: %d", loadCount+1, fromInteger(valueof(MD6BurstsPerHashLoad)),sourceAddr); + plbCommand.enq(tagged LoadPage sourceAddr); + sourceAddr <= truncateLSB({sourceAddr,0} + (1 << (valueof(TLog#(WordsPerBurst))))); + endrule + + + // This rule will feed output from the MD6 engine to the memory controller + method ActionValue#(MD6Word) wordOutput(); + match {.block, .engine} = outTokens.first; + if(wordsOutgoing == fromInteger(valueof(MD6_c) - 1)) + begin + wordsOutgoing <= 0; + outTokens.deq; + if(block == FinalBlock) + begin + $display("TIMING finish: %d", $time); + state <= Idle; // At this point, we're really done... + end + else if(block == LastInLevel) + begin + state <= LevelStart; + end + end + else + begin + wordsOutgoing <= wordsOutgoing + 1; + end + $display("outgoing word"); + + MD6Word endianCorrect <- md6Engines[engine].outputWord; + + MD6Word outWord; + + // MD6 is big endian. If the system is little endian, we must swap. + if(!bigEndianReg) + begin + $display("Big endian false"); + Vector#(TDiv#(MD6_WordWidth,8),Bit#(8)) vector = unpack(endianCorrect); + outWord = pack(reverse(vector)); + end + else + begin + outWord = endianCorrect; + end + + return outWord; + endmethod + + // This rule handles input from the outside world to the MD6 controller + // This includes padding + method Action wordInput(MD6Word endianCorrect); + // Must deal with zero padding at the end of the + // first round. + + MD6Word inWord; + + // MD6 is big endian. If the system is little endian, we must swap. + if(!bigEndianReg) + begin + Vector#(TDiv#(MD6_WordWidth,8),Bit#(8)) vector = unpack(endianCorrect); + inWord = pack(reverse(vector)); + end + else + begin + inWord = endianCorrect; + end + + $display("inputWord called: %h", inWord); + match {.blockType, .engine } = inTokens.first; + + if(wordsIncoming == fromInteger(valueof(MD6_b) - 1)) + begin + wordsIncoming <= 0; + if(blockType == PadBlock) + begin + waitingForPad <= False; + end + inTokens.deq; + end + else + begin + wordsIncoming <= wordsIncoming + 1; + end + + if(blockType == PadBlock) + begin + $display("Padblock, tailNonZeroBits: %d", tailNonZeroBits); + // Now, pad the leftover bits to zero + if(tailNonZeroBits > fromInteger(valueof(MD6_WordWidth))) + begin + tailNonZeroBits <= tailNonZeroBits - fromInteger(valueof(MD6_WordWidth)); + md6Engines[engine].inputWord(inWord); + end + else if(tailNonZeroBits > 0) + begin // Might alter this to decrease impl area + Bit#(TAdd#(1,TLog#(MD6_WordWidth))) shiftValue = truncate(64-tailNonZeroBits); + Bit#(MD6_WordWidth) paddedWord = inWord & (~0 << shiftValue); + md6Engines[engine].inputWord(paddedWord); + tailNonZeroBits <= 0; + end + else // All zeros from here. + begin + md6Engines[engine].inputWord(0); + end + end + else if(blockType == NoPad) + begin + md6Engines[engine].inputWord(inWord); + end + endmethod + + method ActionValue#(PLBMasterCommand) outputCommand(); + plbCommand.deq; + return plbCommand.first; + endmethod + + // On the first pass only, we may have some tail non-zero bits. we must pad these out. + // All blocks must be padded to MD6_WordWidth + method Action startDecode(); + if(state == Idle) + begin + $display("TIMING start: %d", $time); + currentHeight <= 1; + setupLevel(); + end + endmethod + + method Bool running(); + return !(state == Idle); + endmethod + + interface Reg keyRegister = keyReg; + interface Reg sourceAddress = md6SourceAddr; + interface Reg destinationAddress = md6DestinationAddr; + interface Reg bufferAddress = md6BufferAddr; + interface Reg bitSize = md6BitSize; + interface Reg bigEndian = bigEndianReg; + interface Reg digestLength = digestLengthReg; + +endmodule \ No newline at end of file Index: trunk/MD6Control/fpga/md6controlengine.v =================================================================== --- trunk/MD6Control/fpga/md6controlengine.v (nonexistent) +++ trunk/MD6Control/fpga/md6controlengine.v (revision 2) @@ -0,0 +1,235 @@ +/* +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 +*/ + +module md6controlengine(CLK, + RST, + plbMasterWires_mABus, + + plbMasterWires_mBE, + + plbMasterWires_mRNW, + + plbMasterWires_mAbort, + + plbMasterWires_mBusLock, + + plbMasterWires_mCompress, + + plbMasterWires_mGuarded, + + plbMasterWires_mLockErr, + + plbMasterWires_mMSize, + + plbMasterWires_mOrdered, + + plbMasterWires_mPriority, + + plbMasterWires_mRdBurst, + + plbMasterWires_mRequest, + + plbMasterWires_mSize, + + plbMasterWires_mType, + + plbMasterWires_mWrBurst, + + plbMasterWires_mWrDBus, + + plbMasterWires_mRst, + plbMasterWires_mAddrAck, + plbMasterWires_mBusy, + plbMasterWires_mErr, + plbMasterWires_mRdBTerm, + plbMasterWires_mRdDAck, + plbMasterWires_mRdDBus, + plbMasterWires_mRdWdAddr, + plbMasterWires_mRearbitrate, + plbMasterWires_mWrBTerm, + plbMasterWires_mWrDAck, + plbMasterWires_mSSize, + plbMasterWires_sMErr, + plbMasterWires_sMBusy, + bramInitiatorWires_bramRST, + bramInitiatorWires_bramAddr, + bramInitiatorWires_bramDout, + bramInitiatorWires_bramWEN, + bramInitiatorWires_bramEN, + bramInitiatorWires_bramCLK, + bramInitiatorWires_bramDin); + input CLK; + input RST; + + // value method plbMasterWires_mABus + output [31 : 0] plbMasterWires_mABus; + + // value method plbMasterWires_mBE + output [7 : 0] plbMasterWires_mBE; + + // value method plbMasterWires_mRNW + output plbMasterWires_mRNW; + + // value method plbMasterWires_mAbort + output plbMasterWires_mAbort; + + // value method plbMasterWires_mBusLock + output plbMasterWires_mBusLock; + + // value method plbMasterWires_mCompress + output plbMasterWires_mCompress; + + // value method plbMasterWires_mGuarded + output plbMasterWires_mGuarded; + + // value method plbMasterWires_mLockErr + output plbMasterWires_mLockErr; + + // value method plbMasterWires_mMSize + output [1 : 0] plbMasterWires_mMSize; + + // value method plbMasterWires_mOrdered + output plbMasterWires_mOrdered; + + // value method plbMasterWires_mPriority + output [1 : 0] plbMasterWires_mPriority; + + // value method plbMasterWires_mRdBurst + output plbMasterWires_mRdBurst; + + // value method plbMasterWires_mRequest + output plbMasterWires_mRequest; + + // value method plbMasterWires_mSize + output [3 : 0] plbMasterWires_mSize; + + // value method plbMasterWires_mType + output [2 : 0] plbMasterWires_mType; + + // value method plbMasterWires_mWrBurst + output plbMasterWires_mWrBurst; + + // value method plbMasterWires_mWrDBus + output [63 : 0] plbMasterWires_mWrDBus; + + // action method plbMasterWires_plbIN + input plbMasterWires_mRst; + input plbMasterWires_mAddrAck; + input plbMasterWires_mBusy; + input plbMasterWires_mErr; + input plbMasterWires_mRdBTerm; + input plbMasterWires_mRdDAck; + input [63 : 0] plbMasterWires_mRdDBus; + input [2 : 0] plbMasterWires_mRdWdAddr; + input plbMasterWires_mRearbitrate; + input plbMasterWires_mWrBTerm; + input plbMasterWires_mWrDAck; + input plbMasterWires_mSSize; + input plbMasterWires_sMErr; + input plbMasterWires_sMBusy; + + // action method bramTargetWires_bramIN + output [31 : 0] bramInitiatorWires_bramAddr; + output [31 : 0] bramInitiatorWires_bramDout; + output [3 : 0] bramInitiatorWires_bramWEN; + output bramInitiatorWires_bramEN; + output bramInitiatorWires_bramCLK; + output bramInitiatorWires_bramRST; + + // value method bramTargetWires_bramOUT + input [31 : 0] bramInitiatorWires_bramDin; + + wire [13:0] bramInitiatorWires_bramAddr_our; + assign bramInitiatorWires_bramAddr = {16'h0000,bramInitiatorWires_bramAddr_our, 2'b00}; + // signals for module outputs + wire [31 : 0] bramTargetWires_dinBRAM,plbMasterWires_mABus; + + wire [63 : 0] plbMasterWires_mWrDBus; + wire [7 : 0] plbMasterWires_mBE; + wire [3 : 0] plbMasterWires_mSize; + wire [2 : 0] plbMasterWires_mType; + wire [1 : 0] plbMasterWires_mMSize, plbMasterWires_mPriority; + wire plbMasterWires_mAbort, + plbMasterWires_mBusLock, + plbMasterWires_mCompress, + plbMasterWires_mGuarded, + plbMasterWires_mLockErr, + plbMasterWires_mOrdered, + plbMasterWires_mRNW, + plbMasterWires_mRdBurst, + plbMasterWires_mRequest, + plbMasterWires_mWrBurst; + +wire RST_N; +assign RST_N = ~RST; + + +mkMD6ControlEngine m( + .CLK(CLK), + .RST_N(RST_N), + + .plbMasterWires_mABus(plbMasterWires_mABus), + .plbMasterWires_mBE(plbMasterWires_mBE), + .plbMasterWires_mRNW(plbMasterWires_mRNW), + .plbMasterWires_mAbort(plbMasterWires_mAbort), + .plbMasterWires_mBusLock(plbMasterWires_mBusLock), + .plbMasterWires_mCompress(plbMasterWires_mCompress), + .plbMasterWires_mGuarded(plbMasterWires_mGuarded), + .plbMasterWires_mLockErr(plbMasterWires_mLockErr), + .plbMasterWires_mMSize(plbMasterWires_mMSize), + .plbMasterWires_mOrdered(plbMasterWires_mOrdered), + .plbMasterWires_mPriority(plbMasterWires_mPriority), + .plbMasterWires_mRdBurst(plbMasterWires_mRdBurst), + .plbMasterWires_mRequest(plbMasterWires_mRequest), + .plbMasterWires_mSize(plbMasterWires_mSize), + .plbMasterWires_mType(plbMasterWires_mType), + .plbMasterWires_mWrBurst(plbMasterWires_mWrBurst), + .plbMasterWires_mWrDBus(plbMasterWires_mWrDBus), + .plbMasterWires_mRst(plbMasterWires_mRst), + .plbMasterWires_mAddrAck(plbMasterWires_mAddrAck), + .plbMasterWires_mBusy(plbMasterWires_mBusy), + .plbMasterWires_mErr(plbMasterWires_mErr), + .plbMasterWires_mRdBTerm(plbMasterWires_mRdBTerm), + .plbMasterWires_mRdDAck(plbMasterWires_mRdDAck), + .plbMasterWires_mRdDBus(plbMasterWires_mRdDBus), + .plbMasterWires_mRdWdAddr(plbMasterWires_mRdWdAddr), + .plbMasterWires_mRearbitrate(plbMasterWires_mRearbitrate), + .plbMasterWires_mWrBTerm(plbMasterWires_mWrBTerm), + .plbMasterWires_mWrDAck(plbMasterWires_mWrDAck), + .plbMasterWires_mSSize(plbMasterWires_mSSize), + .plbMasterWires_sMErr(plbMasterWires_sMErr), + .plbMasterWires_sMBusy(plbMasterWires_sMBusy), + .bramInitiatorWires_bramAddr(bramInitiatorWires_bramAddr_our), + .bramInitiatorWires_bramDout(bramInitiatorWires_bramDout), + .bramInitiatorWires_bramWEN(bramInitiatorWires_bramWEN), + .bramInitiatorWires_bramEN(bramInitiatorWires_bramEN), + .bramInitiatorWires_bramCLK(bramInitiatorWires_bramCLK), + .bramInitiatorWires_bramRST(bramInitiatorWires_bramRST), + .bramInitiatorWires_din(bramInitiatorWires_bramDin) + ); + +endmodule \ No newline at end of file Index: trunk/MD6Control/fpga/MD6ControlEngine.bsv =================================================================== --- trunk/MD6Control/fpga/MD6ControlEngine.bsv (nonexistent) +++ trunk/MD6Control/fpga/MD6ControlEngine.bsv (revision 2) @@ -0,0 +1,140 @@ +/* +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 the top level for the MD6 control engine. + * + ****/ + +// Bluespec Lib +import FIFO::*; +import GetPut::*; +import Vector::*; +import Connectable::*; + +// CSG Lib +import PLBMasterWires::*; +import BRAMInitiatorWires::*; +import PLBMaster::*; +import BRAMFeeder::*; +import PLBMaster::*; +import PLBMasterDefaultParameters::*; +import RegisterMapper::*; +import Register::*; + +// Local includes +import MD6Control::*; +import MD6Parameters::*; +import MD6Types::*; + + +interface MD6Engine; + interface PLBMasterWires plbMasterWires; + interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires; +endinterface + + + +typedef Bit#(16) ControlReg; + +/****** + * The reg map + * 0-31 key + * 32-33 source ptr + * 34-35 destination ptr + * 36-37 buffer ptr + * 38-41 bitSize + * 42 endianess + * 43 start/status + ******/ + +typedef 16 TotalMD6ControlRegs; + + +// This might ought to be baked out into some sort of BSP +function MapperRequest#(regsSize, ControlReg) mapPPCMessageToMapperRequest(PPCMessage msg) + provisos (Add#(xxx, TLog#(regsSize), 15)); + MapperRequest#(regsSize, ControlReg) mapperRequest; + mapperRequest.command = unpack(msg[31]); + mapperRequest.location = truncate(msg[30:16]); + mapperRequest.payload = msg[15:0]; + return mapperRequest; +endfunction + +function PPCMessage mapMapperRequestToPPCMessage(ControlReg data); + return 32'hc0000 | zeroExtend(data); +endfunction + +module mkMD6ControlEngine (MD6Engine); + Feeder feeder <- mkBRAMFeeder(); + PLBMaster plbmaster <- mkPLBMaster; + MD6Control#(1,32) control <- mkMD6Control; + + /* create action-based registers */ + /* Maybe push this down? */ + function Action wrapStart(Bool bool); + action + if(!control.running()) + begin + control.startDecode(); + end + endaction + endfunction + + Reg#(Bool) startReg = mkRegFromActions(control.running,wrapStart); + + // Probably build a list and map and concat would be best? + + let regBank = append(append(append(append(append(append(append( + explodeRegister(control.keyRegister), + explodeRegister(control.sourceAddress)), + explodeRegister(control.destinationAddress)), + explodeRegister(control.bufferAddress)), + explodeRegister(control.bitSize)), + explodeRegister(control.bigEndian)), + explodeRegister(startReg)), + explodeRegister(control.digestLength)); + + RegisterMapper#(PPCMessage, + PPCMessage + ) regMapper <- mkRegisterMapper(mapPPCMessageToMapperRequest, + mapMapperRequestToPPCMessage, + regBank); + + + // Hook up the system + mkConnection(plbmaster.wordInput.put,control.wordOutput); + mkConnection(control.wordInput,plbmaster.wordOutput.get); + mkConnection(plbmaster.plbMasterCommandInput.put,control.outputCommand); + mkConnection(regMapper.registerRequest, feeder.ppcMessageOutput.get); + mkConnection(feeder.ppcMessageInput.put, regMapper.registerResponse); + + interface plbMasterWires = plbmaster.plbMasterWires; + interface bramInitiatorWires = feeder.bramInitiatorWires; + +endmodule \ No newline at end of file Index: trunk/MD6Control/fpga/MD6ControlEngineTest.bsv =================================================================== --- trunk/MD6Control/fpga/MD6ControlEngineTest.bsv (nonexistent) +++ trunk/MD6Control/fpga/MD6ControlEngineTest.bsv (revision 2) @@ -0,0 +1,224 @@ +/* +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 the top level for the MD6 control engine. + * + ****/ + +// Bluespec Lib +import FIFO::*; +import GetPut::*; +import Vector::*; +import Connectable::*; +import StmtFSM::*; +import RegFile::*; + +// CSG Lib +import PLBMasterWires::*; +import BRAMInitiatorWires::*; +import PLBMaster::*; +import BRAMFeeder::*; +import PLBMaster::*; +import PLBMasterDefaultParameters::*; +import PLBMasterEmulator::*; +import RegisterMapper::*; +import Register::*; + +// Local includes +import MD6Control::*; +import MD6Parameters::*; +import MD6Types::*; + + +typedef Bit#(16) ControlReg; + + + +typedef 16 TotalMD6ControlRegs; + + +// This might ought to be baked out into some sort of BSP +function MapperRequest#(regsSize, ControlReg) mapPPCMessageToMapperRequest(PPCMessage msg) + provisos (Add#(xxx, TLog#(regsSize), 15)); + MapperRequest#(regsSize, ControlReg) mapperRequest; + mapperRequest.command = unpack(msg[31]); + mapperRequest.location = truncate(msg[30:16]); + mapperRequest.payload = msg[15:0]; + return mapperRequest; +endfunction + +function PPCMessage mapMapperRequestToPPCMessage(ControlReg data); + return 32'hc0000000 | zeroExtend(data); +endfunction + + +module mkMD6ControlEngineTest (); + RegFile#(Bit#(26),BusWord) memory <- mkRegFileFullLoad("md6Input.hex"); + PLBMasterEmulator#(TExp#(26)) plbmaster <- mkPLBMasterEmulator(memory); + + + MD6Control#(1,48) control <- mkMD6Control; + + + + + Reg#(Bit#(32)) memPtr <- mkReg(0); + + RegFile#(Bit#(1), Bit#(32)) rfileSize <- mkRegFileFullLoad("inputSize.hex"); + RegFile#(Bit#(TLog#(MD6_c)), BusWord) rfileRes <- mkRegFileFullLoad("md6Result.hex"); + Reg#(Bit#(TAdd#(TLog#(MD6_c),1))) resPtr <- mkReg(0); + + + + + /* create action-based registers */ + /* Maybe push this down? */ + function Action wrapStart(Bool bool); + action + $display("wrapStart"); + if(!control.running()) + begin + $display("calling start decode"); + control.startDecode(); + end + endaction + endfunction + + Reg#(Bool) startReg = mkRegFromActions(control.running,wrapStart); + + // Probably build a list and map and concat would be best? + + + let regBank = append(append(append(append(append(append(append( + explodeRegister(control.keyRegister), //32 + explodeRegister(control.sourceAddress)),//2 + explodeRegister(control.destinationAddress)),//2 + explodeRegister(control.bufferAddress)), //2 + explodeRegister(control.bitSize)),//4 + explodeRegister(control.bigEndian)), // 1 + explodeRegister(startReg)), //1 + explodeRegister(control.digestLength)); //1 + RegisterMapper#(PPCMessage, + PPCMessage + ) regMapper <- mkRegisterMapper(mapPPCMessageToMapperRequest, + mapMapperRequestToPPCMessage, + regBank); + + + // Hook up the system + mkConnection(plbmaster.plbmaster.wordInput.put,control.wordOutput); + mkConnection(control.wordInput,plbmaster.plbmaster.wordOutput.get); + mkConnection(plbmaster.plbmaster.plbMasterCommandInput.put,control.outputCommand); + // mkConnection(regMapper.registerRequest, feeder.ppcMessageOutput.get); + // mkConnection(feeder.ppcMessageInput.put, regMapper.registerResponse); +/* + mapperRequest.command = unpack(msg[31]); + mapperRequest.location = truncate(msg[30:16]); + mapperRequest.payload = msg[15:0]; + */ + Bit#(32) inputSize = (((rfileSize.sub(0))/fromInteger(8*valueof(MD6_b))) + 1)*fromInteger(valueof(MD6_b)); + +/****** + * The reg map + * 0-31 key + * 32-33 source ptr + * 34-35 destination ptr + * 36-37 buffer ptr + * 38-41 bitSize + * 42 endianess + * 43 start/status + * 44 digestLength + ******/ + + + + Reg#(Bit#(7)) i <- mkReg(0); + Reg#(Bool) done <- mkReg(False); + Bit#(64) sizeValue = zeroExtend(rfileSize.sub(0)); + + Stmt s = seq + for( i <= 0; i < 32; i <= i + 1) + seq + regMapper.registerRequest({1'b1,zeroExtend(i),16'h0}); + endseq + regMapper.registerRequest({1'b1,15'd32,0}); + regMapper.registerRequest({1'b1,15'd33,0}); + regMapper.registerRequest({1'b1,15'd34,(2*inputSize)[15:0]}); + regMapper.registerRequest({1'b1,15'd35,(2*inputSize)[31:16]}); + regMapper.registerRequest({1'b1,15'd36,(4*inputSize)[15:0]}); + regMapper.registerRequest({1'b1,15'd37,(4*inputSize)[31:16]}); + $display("InputSize: %h", sizeValue); + regMapper.registerRequest({1'b1,15'd38,(sizeValue)[15:0]}); + regMapper.registerRequest({1'b1,15'd39,(sizeValue)[31:16]}); + regMapper.registerRequest({1'b1,15'd40,(sizeValue)[47:32]}); + regMapper.registerRequest({1'b1,15'd41,(sizeValue)[63:48]}); + regMapper.registerRequest({1'b1,15'd42,16'h1}); + regMapper.registerRequest({1'b1,15'd44,512}); + regMapper.registerRequest({1'b1,15'd43,16'h0}); + delay(100); + regMapper.registerRequest({1'b0,15'd43,16'h0}); + while(!done) + seq + regMapper.registerRequest({1'b0,15'd43,16'h0}); + delay(100); + action + let value <- regMapper.registerResponse(); + $display("Doness: %d",value); + done <= (value[15:0] == 0); + endaction + endseq + delay(100); + for(resPtr <= 0; + resPtr < fromInteger(valueof(MD6_c)); + resPtr <= resPtr+1) + seq + if(rfileRes.sub(truncate(resPtr)) != memory.sub(truncate(zeroExtend(resPtr) + inputSize))) + seq + $display("Offset: %d rfile: %d",zeroExtend(resPtr), rfileSize.sub(0)); + $display("FAILED at %d, %h != %h", inputSize+zeroExtend(resPtr),rfileRes.sub(truncate(resPtr)),memory.sub(truncate(zeroExtend(resPtr) + inputSize))); + $finish; + endseq + else + seq + $display("Match at %d", zeroExtend(resPtr) + inputSize); + endseq + endseq + $display("PASS"); + $finish; + endseq; + + FSM fsm <- mkFSM(s); + + + rule startFSM; + fsm.start; + endrule + + +endmodule \ No newline at end of file Index: trunk/compressionFunction/test/CompressionFunctionTestbench.bsv =================================================================== --- trunk/compressionFunction/test/CompressionFunctionTestbench.bsv (nonexistent) +++ trunk/compressionFunction/test/CompressionFunctionTestbench.bsv (revision 2) @@ -0,0 +1,162 @@ +import LFSR::*; +import Vector::*; + +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunction::*; +import CompressionFunctionLibrary::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; + + +import "BDPI" function Action testSanityCheck(Bit#(64) md6_w_val, Bit#(64) md6_n_val, Bit#(64) md6_c_val, + Bit#(64) md6_b_val, Bit#(64) md6_v_val, Bit#(64) md6_u_val, + Bit#(64) md6_k_val, Bit#(64) md6_q_val, Bit#(64) md6_r_val); +import "BDPI" function Action writePlaintextValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeControlValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeUniqueValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeKeyValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action writeQValue(MD6Word value, Bit#(64) index); +import "BDPI" function Action executeDecode(); +import "BDPI" function ActionValue#(MD6Word) readHash(Bit#(64) index); + + + +// This function will handle only the MD6 word + +typedef enum { + Initialize, + Running +} TestState deriving (Bits,Eq); + +/* +Vector#(MD6_k,MD6Word) key = replicate(0); +Vector#(MD6_u,MD6Word) identifier = replicate(0); +Round round = 0; +TreeHeight treeHeight = 0; +LastCompression lastCompression = 0; //One if last compression, else zero +PaddingBits paddingBits = 0; +KeyLength keyLength = fromInteger(valueof(MD6_k)); +DigestLength digestLength = 0; +*/ + +module mkCompressionFunctionTestbench(); + CompressionFunction#(16) compressionFunction <- mkMult16CompressionFunction; + LFSR#(MD6Word) lfsr <- mkFeedLFSR(minBound | 9 ); // This might be random enough, maybe.. + Reg#(TestState) state <- mkReg(Initialize); + + Reg#(Bit#(TLog#(MD6_b))) externalData <- mkReg(0); + + Bit#(TLog#(TAdd#(MD6_b,1))) externalDataCountNext = zeroExtend(externalData) + 1; + + Reg#(Bool) failure <- mkReg(False); + + Reg#(Bit#(10)) testCount <- mkReg(0); + + Reg#(Vector#(MD6_k,MD6Word)) key <- mkReg(replicate(0)); + Reg#(Vector#(MD6_u,MD6Word)) identifier <- mkReg(replicate(0)); + Reg#(Round) round <- mkReg(fromInteger(valueof(MD6_r))); + Reg#(TreeHeight) treeHeight <- mkReg(0); + Reg#(LastCompression) lastCompression <- mkReg(0); + Reg#(KeyLength) keyLength <- mkReg(fromInteger(valueof(MD6_k))); + Reg#(DigestLength) digestLength <- mkReg(0); + Reg#(PaddingBits) paddingBits <- mkReg(0); + + rule initialize(state == Initialize); + lfsr.seed(~0); + state <= Running; + testSanityCheck(fromInteger(valueof(MD6_WordWidth)), fromInteger(valueof(MD6_n)), fromInteger(valueof(MD6_c)), + fromInteger(valueof(MD6_b)), fromInteger(valueof(MD6_v)), fromInteger(valueof(MD6_u)), + fromInteger(valueof(MD6_k)), fromInteger(valueof(MD6_q)), fromInteger(valueof(MD6_r))); + + +// $display("Testbench Init MD6_c: %d MD6_WW: %d MD6_n: %d",valueof(MD6_c), valueof(MD6_WordWidth), valueof(MD6_n)); +// $display("Testbench Taps t0: %d, t1: %d, t2: %d, t3: %d, t4: %d", determineT0, determineT1, determineT2, determineT3, determineT4); + endrule + + function sub(a,b); + return a-b; + endfunction + + rule startDecode(state == Running); + let controlWord = makeControlWord(round,treeHeight,lastCompression,paddingBits,keyLength,digestLength); + identifier <= unpack(pack(identifier) + 1); + key <= zipWith(sub,map(fromInteger,genVector),replicate(lfsr.value)); + + compressionFunction.start(round, + treeHeight, + lastCompression, + paddingBits, + keyLength, + digestLength, + identifier, + key); + + testCount <= testCount + 1; + if(testCount + 1 == 0) + begin + $display("PASS"); + $finish; + end + // Dump stuff into + for(Integer i = 0; i < valueof(MD6_v); i = i+1) + begin + writeUniqueValue(identifier[fromInteger(i)],fromInteger(i)); + end + for(Integer i = 0; i < valueof(MD6_u); i = i+1) + begin + writeControlValue(controlWord[fromInteger(i)],fromInteger(i)); + end + for(Integer i = 0; i < valueof(MD6_k); i = i+1) + begin + writeKeyValue(key[fromInteger(i)],fromInteger(i)); + end + for(Integer i = 0; i < valueof(MD6_q); i = i+1) + begin + //$display("Writing Q value[%h]: %h", i,getQWord(fromInteger(i))); + writeQValue(getQWord(fromInteger(i)),fromInteger(i)); + end + + $display("Testbench Start"); + endrule + + rule sendInData(state == Running); + writePlaintextValue(lfsr.value, fromInteger(valueof(MD6_b)) - zeroExtend(externalData) - 1); + if(externalDataCountNext == fromInteger(valueof(MD6_b))) + begin + // Kick off something here? Is the ordering okay? + executeDecode(); + externalData <= 0; + end + else + begin + externalData <= truncate(externalDataCountNext); + end + lfsr.next(); + + compressionFunction.inputWord(lfsr.value); + endrule + + rule getOutData(state == Running); + MD6Word outWord <- compressionFunction.outputWord(); + MD6Word goldenWord <- readHash(fromInteger(valueof(MD6_c)) - zeroExtend(externalData) - 1); + if(outWord != goldenWord) + begin + $display("Failure - outWord: %h goldenWord: %h", outWord, goldenWord); + failure <= True; + end + if(externalDataCountNext == fromInteger(valueof(MD6_c))) + begin + if(failure) + begin + $finish; + end + externalData <= 0; + end + else + begin + externalData <= truncate(externalDataCountNext); + end + endrule +endmodule + Index: trunk/compressionFunction/test/CompressionFunctionTestbench.c =================================================================== --- trunk/compressionFunction/test/CompressionFunctionTestbench.c (nonexistent) +++ trunk/compressionFunction/test/CompressionFunctionTestbench.c (revision 2) @@ -0,0 +1,159 @@ +#include +#include +#include"md6.h" + + +#define COMPRESS_ROUNDS 178 +#define HASH_LENGTH md6_c +#define PLAIN_LENGTH md6_b +#define CONTROL_LENGTH md6_u +#define IDENTIFIER_LENGTH md6_v +#define KEY_LENGTH md6_k +#define Q_LENGTH md6_q + +void writePlaintextValue(md6_word value, long long index); +void writeControlValue(md6_word value, long long index); +void writeUniqueValue(md6_word value, long long index); +void writeKeyValue(md6_word value, long long index); +void writeQValue(md6_word value, long long index); +void executeDecode(); +md6_word readHash(long long index); +void testSanityCheck(long long md6_w_val, long long md6_n_val, long long md6_c_val, + long long md6_b_val, long long md6_v_val, long long md6_u_val, + long long md6_k_val, long long md6_q_val, long long md6_r_val, + long long md6_t0, long long md6_t1, long long md6_t2, + long long md6_t3, long long md6_t4); + + +md6_word plaintextArray[PLAIN_LENGTH+CONTROL_LENGTH+IDENTIFIER_LENGTH+KEY_LENGTH+Q_LENGTH]; +md6_word hashArray[HASH_LENGTH]; + +void writePlaintextValue(md6_word value, long long index) { + printf("Writing[%d]: %llx\n", CONTROL_LENGTH+IDENTIFIER_LENGTH+KEY_LENGTH+Q_LENGTH+(md6_b-index-1), value); + plaintextArray[CONTROL_LENGTH+IDENTIFIER_LENGTH+KEY_LENGTH+Q_LENGTH+(md6_b-index-1)] = value; +} + +void writeControlValue(md6_word value, long long index) { + plaintextArray[index+IDENTIFIER_LENGTH+KEY_LENGTH+Q_LENGTH] = value; +} + +void writeUniqueValue(md6_word value, long long index) { + plaintextArray[index+KEY_LENGTH+Q_LENGTH] = value; +} + +void writeKeyValue(md6_word value, long long index) { + plaintextArray[index+Q_LENGTH] = value; +} + +void writeQValue(md6_word value, long long index) { + plaintextArray[index] = value; +} + + +void executeDecode() { + md6_word plaintextArrayRev[PLAIN_LENGTH+CONTROL_LENGTH+IDENTIFIER_LENGTH+KEY_LENGTH+Q_LENGTH]; + int i; + + printf("Calling executeDecode() Size - %d\n", md6_w); + + // It so happens that md6_compress expect the array in reverse order for some reason... + + //for(i = 0; i < md6_n; i++){ + // plaintextArrayRev[md6_n - i - 1] = plaintextArray[i]; + //} + + int result = md6_compress( hashArray, + plaintextArray, + COMPRESS_ROUNDS, + NULL + ); + if(result != MD6_SUCCESS) { + printf("MD6 failed: %d, dying!\n", result); + exit(0); + } +} + +md6_word readHash(long long index) { + printf("index is : %d\n", index); + return hashArray[md6_c-index-1]; +} + +void testSanityCheck(long long md6_w_val, long long md6_n_val, long long md6_c_val, + long long md6_b_val, long long md6_v_val, long long md6_u_val, + long long md6_k_val, long long md6_q_val, long long md6_r_val, + long long md6_t0, long long md6_t1, long long md6_t2, + long long md6_t3, long long md6_t4){ + + if(md6_w_val != md6_w) { + printf("md6_w does not match: %d, %d!\n", md6_w_val, md6_w); + exit(0); + } + + if(md6_n_val != md6_n) { + printf("md6_h does not match!\n"); + exit(0); + } + + if(md6_c_val != md6_c) { + printf("md6_c does not match!\n"); + exit(0); + } + + if(md6_b_val != md6_b) { + printf("md6_b does not match!\n"); + exit(0); + } + + if(md6_v_val != md6_v) { + printf("md6_v does not match!\n"); + exit(0); + } + + if(md6_u_val != md6_u) { + printf("md6_u does not match!\n"); + exit(0); + } + + if(md6_k_val != md6_k) { + printf("md6_k does not match!\n"); + exit(0); + } + + if(md6_q_val != md6_q) { + printf("md6_q does not match!\n"); + exit(0); + } + + if(md6_r_val != 178) { + printf("md6_r does not match!\n"); + exit(0); + } + + if(md6_t0 == t0) { + printf("md6_t0 does not match!\n"); + exit(0); + } + + if(md6_t1 == t1) { + printf("md6_t1 does not match!\n"); + exit(0); + } + + if(md6_t2 == t2) { + printf("md6_t2 does not match!\n"); + exit(0); + } + + if(md6_t3 == t3) { + printf("md6_t3 does not match!\n"); + exit(0); + } + + if(md6_t4 == t4) { + printf("md6_t4 does not match!\n"); + exit(0); + } +} + + + Index: trunk/compressionFunction/src/CompressionFunction.bsv =================================================================== --- trunk/compressionFunction/src/CompressionFunction.bsv (nonexistent) +++ trunk/compressionFunction/src/CompressionFunction.bsv (revision 2) @@ -0,0 +1,568 @@ +import FIFOF::*; +import MD6Parameters::*; +import MD6Types::*; +import MD6Library::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; +import CompressionFunctionLibrary::*; +import Debug::*; +import SGenerator::*; +import Vector::*; +import MD6ShiftRegister::*; + +Bool compressionDebug = True; + +interface CompressionFunction#(numeric type taps); + method Action start(Round rounds, + TreeHeight maxTreeHeight, + LastCompression lastCompression, + PaddingBits paddingBits, + KeyLength keyLength, + DigestLength digestLenth, + Vector#(MD6_u,MD6Word) compressionIdentifierIn, + Vector#(MD6_k,MD6Word) keyIn); // input all control information + + method Action inputWord(MD6Word word); + method ActionValue#(MD6Word) outputWord(); + method Bit#(16) status(); +endinterface + +function MD6Word processStep(MD6Word t0, + MD6Word t1, + MD6Word t2, + MD6Word t3, + MD6Word t4, + MD6Word t5, + MD6Word s, + Bit#(TLog#(MD6_c)) step); + + ShiftFactor left = shiftIndexL(truncate(fromInteger(valueof(MD6_c) - 1) - step)); + ShiftFactor right = shiftIndexR(truncate(fromInteger(valueof(MD6_c) - 1) - step)); + + MD6Word sFactor = s; + MD6Word value = t0 ^ (t1 & t2) ^ (t3 & t4) ^ t5 ^ sFactor; + MD6Word intermediate = ((value >> right) ^ value); + return ((intermediate << left) ^ intermediate); +endfunction + +typedef enum { + Idle = 0, + LocalInitialization = 1, + LocalInitializationK = 2, + LocalInitializationU = 3, + LocalInitializationV = 4, + ExternalDataIn = 5, + Processing = 6, + AuxiliaryShift = 7, + ExternalDataOut = 8 +} CompressionState deriving (Bits,Eq); + +// TODO: I should probably support multiple digest lengths + +module mkSimpleCompressionFunction1 (CompressionFunction#(1)); + CompressionFunction#(1) compressor <- mkSimpleCompressionFunction; + return compressor; +endmodule + + +// This compression function works for up to one. +module mkSimpleCompressionFunction (CompressionFunction#(taps)) + provisos(Add#(taps,xxx,MD6_n), + Add#(yyy,TLog#(taps),TLog#(MD6_n)), + Add#(zzz,TLog#(taps),TLog#(MD6_b))); + /* The shift reg should look something like this: + -> | shift0 | shift 1 | shift 2 | shift 3 | shift 4 | -> + */ + // As a parameterization, we could extra these FIFOs as a + // seperate module which we could imeplement as a sort of + // black box. This is probably the right way to do things. + // This plus 1 may or may not work. + MD6ShiftRegister#(taps) shifter <- mkMD6ShiftRegister; + SGenerator#(1) sGenerator <- mkSGeneratorLogic; + + + // Step Number is rather special. It denotes the number of times + // that enq will be called on the fifo chain. This includes + // all init time functions + + Reg#(Round) roundNumber <- mkReg(0); + Reg#(Round) roundTotal <- mkReg(0); + Reg#(Bit#(TLog#(MD6_n))) auxiliaryShift <- mkReg(0); + Reg#(Bit#(TLog#(MD6_c))) stepInRound <- mkReg(0); + Reg#(Bit#(TLog#(MD6_b))) externalDataCount <- mkReg(0); + Reg#(Bit#(TLog#(TSub#(MD6_n,MD6_b)))) localInitializationCount <- mkReg(0); + Reg#(CompressionState) state <- mkReg(Idle); + //Reg#(Vector#(MD6_k,MD6Word)) key <- mkReg(replicate(0)); + //Reg#(Vector#(MD6_u,MD6Word)) compressionIdentifier <- mkReg(replicate(0)); + //Reg#(Vector#(MD6_v,MD6Word)) controlWord <- mkReg(replicate(0)); + + Bit#(TLog#(TAdd#(MD6_c,1))) stepInRoundNext = zeroExtend(stepInRound) + fromInteger(valueof(taps)); + let roundNumberNext = {1'b0,roundNumber} + 1; + Bit#(TLog#(TAdd#(MD6_b,1))) externalDataCountNext = zeroExtend(externalDataCount) + 1; + Bit#(TLog#(TAdd#(TSub#(MD6_n,MD6_b),1))) localInitializationCountNext = + zeroExtend(localInitializationCount) + 1; + Bit#(TLog#(TAdd#(MD6_n,1))) auxiliaryShiftNext = zeroExtend(auxiliaryShift) + 1; + + + + rule mainShift(state == Processing); + if(stepInRoundNext == fromInteger(valueof(MD6_c))) + begin + stepInRound <= 0; + roundNumber <= truncate(roundNumberNext); + sGenerator.advanceRound(); // Need to advance round before next call of getS + if(roundNumberNext == zeroExtend(roundTotal)) + begin + debug(compressionDebug,$display("Preparing to output")); + state <= ExternalDataOut; + end + end + else + begin + stepInRound <= truncate(stepInRoundNext); + end + + if((roundNumber == 0) && (stepInRound == 0)) + begin + for(Integer i = 0; i < valueof(MD6_n); i=i+1) + begin + debug(compressionDebug,$display("Starting ShiftState[%d]: %h",i, shifter.regs[i])); + end + end + + + function add(a,b); + return a+b; + endfunction + + function apply(a,b); + return a(b); + endfunction + + // The following crazy thing calculates the next state. It is vectorized + Vector#(taps,MD6Word) nextVector = zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,map(processStep,shifter.getT0),shifter.getT1),shifter.getT2),shifter.getT3),shifter.getT4),shifter.getT5),replicate(sGenerator.getS[0])),zipWith(add,replicate(stepInRound),map(fromInteger,genVector))); + + /* + for(Integer i = 0; i < valueof(taps); i=i+1) + begin + debug(compressionDebug,$display("NextWordShort: %h", nextVector[i])); + debug(compressionDebug,$write("S: %h T5:%h T4:%h T3:%h T2:%h", sGenerator.getS(), shifter.getT5[i], shifter.getT4[i], shifter.getT3[i], shifter.getT2[i])); + debug(compressionDebug,$display("T1:%h T0:%h Next MD6 Word: %h", shifter.getT1[i], shifter.getT0[i], nextVector[i])); + end*/ + shifter.write(nextVector); + shifter.advance(); + endrule + + // May want to switch to InitQ -> Idle state machine order to overlap some computation potentially. + // May also want to explcitly intialize values in a state. + method Action start(Round rounds, + TreeHeight maxTreeHeight, + LastCompression lastCompression, + PaddingBits paddingBits, + KeyLength keyLength, + DigestLength digestLength, + Vector#(MD6_u,MD6Word) compressionIdentifierIn, + Vector#(MD6_k,MD6Word) keyIn) if(state == Idle); // input all control information + state <= ExternalDataIn; + externalDataCount <= 0; + roundNumber <= 0; // Maybe put this somewhere else where its precense will be slightly more noticeable + + Vector#(MD6_v,MD6Word) controlWordIn = makeControlWord(rounds, + maxTreeHeight, + lastCompression, + paddingBits, + keyLength, + digestLength); + + roundTotal <= rounds;// Pull the digest size out so that we might calculate the round number + Integer i = valueof(MD6_b); + // This stuff is in a reversed order + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(getQWord(fromInteger(j))); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_k)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(keyIn[j]); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_u)+valueof(MD6_k)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(compressionIdentifierIn[j]); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_v)+valueof(MD6_u)+valueof(MD6_k)+valueof(MD6_q); i=i+1, j=j+1) + begin + shifter.regs[i]._write(controlWordIn[j]); + end + + sGenerator.resetS(); + endmethod + + + method Action inputWord(MD6Word word) if(state == ExternalDataIn); // Specific range for inputing new hash values + if(externalDataCountNext == fromInteger(valueof(MD6_b))) + begin + externalDataCount <= 0; + state <= Processing; + + for(Integer i = 0; i < valueof(MD6_n); i = i + 1) + begin + $display("Shifter[%d] = %h",i,shifter.regs[i]); + end + end + else + begin + externalDataCount <= truncate(externalDataCountNext); + end + //$display("externalDataCount: %d", externalDataCount); + // Pull same trick as in output word here. Must be careful about initialization, however, since those guys will be shifted over. + + Vector#(taps,Reg#(MD6Word)) resultVec = take(shifter.regs); + // This index is screwed up somehow. + Bit#(TLog#(taps)) index = truncate(externalDataCount); + + //We start after all of the initialization stuff + //Possible that bluespec may have issue here + Vector#(taps,Reg#(MD6Word)) inputRegs = takeAt(valueof(MD6_n)-valueof(taps),shifter.regs); + inputRegs[zeroExtend(index)]._write(word); + if(index == 0) + begin + shifter.advance; // problems here. + // this advance should occur MD6_b/taps - 1 times + end + endmethod + + + method ActionValue#(MD6Word) outputWord() if( state == ExternalDataOut ); + if(externalDataCountNext == fromInteger(valueof(MD6_c))) + begin + externalDataCount <= 0; + state <= Idle; + $display("Finished"); + end + else + begin + externalDataCount <= truncate(externalDataCountNext); + end + $display("Compression function is outputing"); + Vector#(taps,Reg#(MD6Word)) resultVec = takeAt(valueof(MD6_n)-valueof(MD6_c),shifter.regs); + // This is probably wrong now. + Bit#(TLog#(taps)) index = truncate(externalDataCount); + if(index == ~0) + begin + shifter.advance; + end + return resultVec[index]._read; + endmethod + + method Bit#(16) status(); + return zeroExtend(pack(state)); + endmethod +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// This compression function only works for size 16 multiples of taps + +module mkMult16CompressionFunction (CompressionFunction#(taps)) + provisos(Add#(taps,xxx,MD6_n), + Add#(yyy,TLog#(taps),TLog#(MD6_n)), + Add#(zzz,TLog#(taps),TLog#(MD6_b))); + /* The shift reg should look something like this: + -> | shift0 | shift 1 | shift 2 | shift 3 | shift 4 | -> + */ + // As a parameterization, we could extra these FIFOs as a + // seperate module which we could imeplement as a sort of + // black box. This is probably the right way to do things. + // This plus 1 may or may not work. + MD6ShiftRegister#(taps) shifter <- mkMD6ShiftRegister; + + + // These utility functions touch the shift register + + function Vector#(16,MD6Word) getT0(Vector#(MD6_n,MD6Word) v); + return takeAt(determineT0,v); + endfunction + + function Vector#(16,MD6Word) getT1(Vector#(MD6_n,MD6Word) v); + return takeAt(determineT1,v); + endfunction + + function Vector#(16,MD6Word) getT2(Vector#(MD6_n,MD6Word) v); + return takeAt(determineT2,v); + endfunction + + function Vector#(16,MD6Word) getT3(Vector#(MD6_n,MD6Word) v); + return takeAt(determineT3,v); + endfunction + + function Vector#(16,MD6Word) getT4(Vector#(MD6_n,MD6Word) v); + return takeAt(determineT4,v); + endfunction + + function Vector#(16,MD6Word) getT5(Vector#(MD6_n,MD6Word) v); + return takeAt(determineT5,v); + endfunction + + + // Functions that operate on the shift register. + + + // Need a new SGenerator every 16 taps... + SGenerator#(TDiv#(taps,MD6_c)) sGenerator <- mkSGeneratorLogic; + + + // Step Number is rather special. It denotes the number of times + // that enq will be called on the fifo chain. This includes + // all init time functions + + Reg#(Round) roundNumber <- mkReg(0); + Reg#(Round) roundTotal <- mkReg(0); + Reg#(Bit#(TLog#(MD6_n))) auxiliaryShift <- mkReg(0); + Reg#(Bit#(TLog#(MD6_c))) stepInRound <- mkReg(0); + Reg#(Bit#(TLog#(MD6_b))) externalDataCount <- mkReg(0); + Reg#(Bit#(TLog#(TSub#(MD6_n,MD6_b)))) localInitializationCount <- mkReg(0); + Reg#(CompressionState) state <- mkReg(Idle); + //Reg#(Vector#(MD6_k,MD6Word)) key <- mkReg(replicate(0)); + //Reg#(Vector#(MD6_u,MD6Word)) compressionIdentifier <- mkReg(replicate(0)); + //Reg#(Vector#(MD6_v,MD6Word)) controlWord <- mkReg(replicate(0)); + + //Bit#(TLog#(TAdd#(MD6_c,1))) stepInRoundNext = zeroExtend(stepInRound) + fromInteger(valueof(taps)); + let roundNumberNext = {1'b0,roundNumber} + fromInteger(valueof(taps)/16); //Not right at all + Bit#(TLog#(TAdd#(MD6_b,1))) externalDataCountNext = zeroExtend(externalDataCount) + 1; + Bit#(TLog#(TAdd#(TSub#(MD6_n,MD6_b),1))) localInitializationCountNext = + zeroExtend(localInitializationCount) + 1; + Bit#(TLog#(TAdd#(MD6_n,1))) auxiliaryShiftNext = zeroExtend(auxiliaryShift) + 1; + + + + rule mainShift(state == Processing); + roundNumber <= truncate(roundNumberNext); + sGenerator.advanceRound(); // Need to advance round before next call of getS + if(roundNumberNext >= zeroExtend(roundTotal)) + begin + debug(compressionDebug,$display("Preparing to output")); + state <= ExternalDataOut; + end + + if((roundNumber == 0)) + begin + for(Integer i = 0; i < valueof(MD6_n); i=i+1) + begin + debug(compressionDebug,$display("Starting ShiftState[%d]: %h",i, shifter.regs[i])); + end + end + + + function add(a,b); + return a+b; + endfunction + + function apply(a,b); + return a(b); + endfunction + + + Vector#(MD6_n,MD6Word) computeVector = readVReg(shifter.regs); + + // The following crazy thing calculates the next state. It is vectorized. + // The loop is bounded by T0, wherein the first feedback will occur... + for(Integer i = 0, Integer sindex = 0; i < valueof(taps); i = i + 16, sindex = sindex + 1) + begin + Vector#(16,MD6Word) nextVector = zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,zipWith(apply,map(processStep,getT0(computeVector)),getT1(computeVector)),getT2(computeVector)),getT3(computeVector)),getT4(computeVector)),getT5(computeVector)),replicate(sGenerator.getS[sindex])),zipWith(add,replicate(0),map(fromInteger,genVector))); + computeVector = takeAt(16,append(computeVector,nextVector)); + end + + + + shifter.write(takeAt(valueof(MD6_n)-valueof(taps),computeVector)); + shifter.advance(); + endrule + + + // May want to switch to InitQ -> Idle state machine order to overlap some computation potentially. + // May also want to explcitly intialize values in a state. + method Action start(Round rounds, + TreeHeight maxTreeHeight, + LastCompression lastCompression, + PaddingBits paddingBits, + KeyLength keyLength, + DigestLength digestLength, + Vector#(MD6_u,MD6Word) compressionIdentifierIn, + Vector#(MD6_k,MD6Word) keyIn) if(state == Idle); // input all control information + state <= ExternalDataIn; + externalDataCount <= 0; + roundNumber <= 0; // Maybe put this somewhere else where its precense will be slightly more noticeable + roundTotal <= rounds;// Pull the digest size out so that we might calculate the round number + + Vector#(MD6_v,MD6Word) controlWordIn = makeControlWord(rounds, + maxTreeHeight, + lastCompression, + paddingBits, + keyLength, + digestLength); + Integer offset = valueof(MD6_b)%valueof(taps); + Integer i = valueof(MD6_b)-offset; + + $display("Offset is: %d", offset); + + // This stuff is in a reversed order + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_q)-offset; i=i+1, j=j+1) + begin + shifter.regs[i]._write(getQWord(fromInteger(j))); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_k)+valueof(MD6_q) - offset; i=i+1, j=j+1) + begin + shifter.regs[i]._write(keyIn[j]); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_u)+valueof(MD6_k)+valueof(MD6_q)-offset; i=i+1, j=j+1) + begin + shifter.regs[i]._write(compressionIdentifierIn[j]); + end + for(Integer j = 0;i< valueof(MD6_b)+valueof(MD6_v)+valueof(MD6_u)+valueof(MD6_k)+valueof(MD6_q)-offset; i=i+1, j=j+1) + begin + shifter.regs[i]._write(controlWordIn[j]); + end + + sGenerator.resetS(); + endmethod + + + method Action inputWord(MD6Word word) if(state == ExternalDataIn); // Specific range for inputing new hash values + if(externalDataCountNext == fromInteger(valueof(MD6_b))) + begin + externalDataCount <= 0; + state <= Processing; + end + else + begin + externalDataCount <= truncate(externalDataCountNext); + end + + //$display("externalDataCount: %d", externalDataCount); + // Pull same trick as in output word here. Must be careful about initialization, however, since those guys will be shifted over. + + Vector#(taps,Reg#(MD6Word)) resultVec = take(shifter.regs); + // This index is screwed up somehow. + // Must subtract some offset value here. + Bit#(TLog#(taps)) index=0; + if(({1'b0,externalDataCount}+fromInteger((((valueof(taps)-valueof(MD6_b)%valueof(taps))%valueof(taps))))) >= fromInteger(valueof(taps))) + begin + index = truncate(({1'b0,externalDataCount}+fromInteger((((valueof(taps)-valueof(MD6_b)%valueof(taps))%valueof(taps)))-valueof(taps)))); + end + else + begin + index = truncate(({1'b0,externalDataCount}+fromInteger((((valueof(taps)-valueof(MD6_b)%valueof(taps))%valueof(taps)))))); + end + + + //We start after all of the initialization stuff + //Possible that bluespec may have issue here + Vector#(taps,Reg#(MD6Word)) inputRegs = takeAt(valueof(MD6_n)-valueof(taps),shifter.regs); + inputRegs[zeroExtend(index)]._write(word); + + if(index == 0) + begin + $display("Calling advance"); + shifter.advance; // problems here. + // this advance should occur MD6_b/taps - 1 times + end + endmethod + + + method ActionValue#(MD6Word) outputWord() if( state == ExternalDataOut ); + if(externalDataCountNext == fromInteger(valueof(MD6_c))) + begin + externalDataCount <= 0; + state <= Idle; + $display("Finished"); + end + else + begin + externalDataCount <= truncate(externalDataCountNext); + end + $display("Compression function is outputing"); + + // First we construct a larger vector, from which we will select 16 values for the result + Vector#(TMul#(2,MD6_n), Reg#(MD6Word)) expandedRegs = append(shifter.regs,shifter.regs); + + // Due to odd sizes, we may need an offset which is not zero... + Integer offset = 0; + + + // This one always takes the sixteen values + // Eep.. this just about kills us. Grrr.... + // Only some parameterizations will work now. for example, 48 will not work + Vector#(16,Reg#(MD6Word)) resultVec = takeAt(valueof(MD6_n)-valueof(MD6_c),shifter.regs); + + // This is probably wrong now. + Bit#(TLog#(16)) index = truncate(externalDataCount); + + return resultVec[index]._read; + endmethod + + method Bit#(16) status(); + return zeroExtend(pack(state)); + endmethod +endmodule \ No newline at end of file Index: trunk/compressionFunction/src/MD6ShiftRegister.bsv =================================================================== --- trunk/compressionFunction/src/MD6ShiftRegister.bsv (nonexistent) +++ trunk/compressionFunction/src/MD6ShiftRegister.bsv (revision 2) @@ -0,0 +1,70 @@ +import FIFOF::*; +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; +import CompressionFunctionLibrary::*; +import Debug::*; +import SGenerator::*; +import Vector::*; + +interface MD6ShiftRegister#(numeric type taps); + method Vector#(taps,MD6Word) getT0; + method Vector#(taps,MD6Word) getT1; + method Vector#(taps,MD6Word) getT2; + method Vector#(taps,MD6Word) getT3; + method Vector#(taps,MD6Word) getT4; + method Vector#(taps,MD6Word) getT5; + method Action write(Vector#(taps,MD6Word) nextValues); + method Action advance(); + interface Vector#(MD6_n, Reg#(MD6Word)) regs; +endinterface + + +module mkMD6ShiftRegister (MD6ShiftRegister#(taps)) + provisos(Add#(taps,yyy,MD6_n)); + Integer historyLength = valueof(taps); + Vector#(MD6_n,Reg#(MD6Word)) t0 <- replicateM(mkReg(0)); + // we pulled out a subtraction of history length + method Vector#(taps,MD6Word) getT0; + return takeAt(determineT0,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT1; + return takeAt(determineT1,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT2; + return takeAt(determineT2,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT3; + return takeAt(determineT3,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT4; + return takeAt(determineT4,readVReg(t0)); + endmethod + + method Vector#(taps,MD6Word) getT5; + return takeAt(determineT5,readVReg(t0)); + endmethod + + method Action write(Vector#(taps,MD6Word) nextword); + writeVReg(takeAt(valueof(MD6_n)-valueof(taps),t0),nextword); + endmethod + + method Action advance(); + for(Integer i = 0; i < valueof(MD6_n); i=i+1) + begin + //$display("Advance ShiftState[%d]: %h",i, t0[i]); + end + for(Integer i = 0; i < valueof(MD6_n)-valueof(taps); i=i+1) + begin + t0[i] <= t0[i+valueof(taps)]; + end + endmethod + + interface regs = t0; + +endmodule \ No newline at end of file Index: trunk/compressionFunction/src/SGenerator.bsv =================================================================== --- trunk/compressionFunction/src/SGenerator.bsv (nonexistent) +++ trunk/compressionFunction/src/SGenerator.bsv (revision 2) @@ -0,0 +1,72 @@ +//BSC Library includes +import Vector::*; + +// CSG includes +import Debug::*; + +// Local includes +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; + +Bool sgenDebug = False; + +interface SGenerator#(numeric type size); + method Vector#(size,MD6Word) getS(); + method Action advanceRound(); + method Action resetS(); +endinterface + + +function MD6Word advanceRoundComb(MD6Word s); + MD6Word sRotate = (s << 1) | zeroExtend(s[valueof(MD6_WordWidth)-1]); + MD6Word nextS = sRotate ^ (s & sStar()); + return nextS; +endfunction + + + + +module mkSGeneratorLogic (SGenerator#(size)); + Vector#(size,Reg#(MD6Word)) s = newVector; // Grab S0 from parameters + + function applyN(f,arg,n); + MD6Word seed = arg; + for(Integer j =0; j < n; j = j+1) + begin + seed = f(seed); + end + return seed; + endfunction + + + for(Integer i = 0; i < valueof(size); i = i+1) + begin + s[i] <- mkReg(applyN(advanceRoundComb,s0(),i)); + end + + method Vector#(size,MD6Word) getS(); + return readVReg(s); + endmethod + + method Action advanceRound(); + MD6Word seed = s[valueof(size)-1]; + $display("Calling advance Round"); + for(Integer i = 0; i < valueof(size); i = i+1) + begin + MD6Word nextSeed = advanceRoundComb(seed); + debug(sgenDebug,$display("Size: %d, Advancing s, old s: %h, new s:%h", valueof(size),s[i], nextSeed)); + s[i] <= nextSeed; // How did this work before?? + seed = nextSeed; + end + endmethod + + method Action resetS(); + for(Integer i = 0; i < valueof(size); i = i+1) + begin + s[i] <= applyN(advanceRoundComb,s0(),i); + end + endmethod + +endmodule Index: trunk/compressionFunction/src/CompressionFunctionParameters.bsv =================================================================== --- trunk/compressionFunction/src/CompressionFunctionParameters.bsv (nonexistent) +++ trunk/compressionFunction/src/CompressionFunctionParameters.bsv (revision 2) @@ -0,0 +1,71 @@ +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; + +// The following are magic, externally defined parameters in MD6 +// Other important parameters are derived from them. +// These parameters are used solely within the compression +// function. + +function MD6Word s0(); + return truncateLSB(64'h0123456789abcdef); +endfunction + +function MD6Word sStar(); + return truncateLSB(64'h7311c2812425cfa0); +endfunction + +// These tables are all of size 16. MD6 does not have a definition for +// Non-size 16 value of MD6_c +ShiftFactor c64ShiftR[16] = {12,6,7,11,13,7,15,14,7,2,12,11,10,13,5,10}; + +ShiftFactor c64ShiftL[16] = {9,31,5,15,8,29,2,6,15,27,9,15,16,9,24,11}; + +ShiftFactor c32ShiftR[16] = {7,13,1,8,15,3,16,13,2,3,13,9,7,10,2,4}; + +ShiftFactor c32ShiftL[16] = {15,12,3,16,10,7,5,9,4,9,16,12,11,5,1,13}; + +ShiftFactor c16ShiftR[16] = {7,4,1,7,2,1,5,7,2,1,7,1,2,7,7,8}; + +ShiftFactor c16ShiftL[16] = {3,5,2,2,4,5,3,4,6,5,4,2,3,2,6,5}; + +ShiftFactor c8ShiftR[16] = {1,1,2,1,2,3,2,3,1,3,2,2,1,1,4,2}; + +ShiftFactor c8ShiftL[16] = {3,2,4,3,3,4,1,1,2,4,4,3,4,2,3,3}; + + + + + +// This is the sqrt(6) vector value. It should probably be longer than this +Bit#(TMul#(16,64)) vectorQ = { + 64'h8b30ed2e9956c6a0, + 64'h0d6f3522631effcb, + 64'h3b72066c7a1552ac, + 64'hc878c1dd04c4b633, + 64'h995ad1178bd25c31, + 64'h8af8671d3fb50c2c, + 64'h3e7f16bb88222e0d, + 64'h4ad12aae0a6d6031, + 64'h54e5ed5b88e3775d, + 64'h1f8ccf6823058f8a, + 64'h0cd0d63b2c30bc41, + 64'hdd2e76cba691e5bf, + 64'he8fb23908d9f06f1, + 64'hb60450e9ef68b7c1, + 64'h6432286434aac8e7, + 64'h7311c2812425cfa0}; + +//This might well be enormous. +function MD6Word getQWord(Bit#(TLog#(MD6_q)) index); + Bit#(TLog#(TMul#(MD6_q,MD6_WordWidth))) baseIndex = fromInteger(valueof(MD6_WordWidth))*zeroExtend(index); + return vectorQ[(baseIndex+fromInteger(valueof(MD6_WordWidth)-1)):baseIndex]; +endfunction + +function MD6Word extractWord(Bit#(n) bitVector, Bit#(m) index) + provisos( + Add#(a,m,TAdd#(m,TLog#(MD6_WordWidth)))); + Bit#(TAdd#(m,TLog#(MD6_WordWidth))) baseIndex = fromInteger(valueof(MD6_WordWidth))*zeroExtend(index); + return bitVector[(baseIndex+fromInteger(valueof(MD6_WordWidth)-1)):baseIndex]; +endfunction + Index: trunk/compressionFunction/src/CompressionFunctionLibrary.bsv =================================================================== --- trunk/compressionFunction/src/CompressionFunctionLibrary.bsv (nonexistent) +++ trunk/compressionFunction/src/CompressionFunctionLibrary.bsv (revision 2) @@ -0,0 +1,171 @@ +import Vector::*; + +import MD6Parameters::*; +import MD6Types::*; +import CompressionFunctionTypes::*; +import CompressionFunctionParameters::*; + + +// The following are magic, externally defined parameters in MD6 +// Other important parameters are derived from them. +// These parameters are used solely within the compression +// function. + +// This set of functions determines the locations of the filter taps +// these index into the constant array given in appendix C of the spec. +// TODO: kfleming - these are currently constant functions. +function Integer determineT0(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 17; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 33; + end + else + begin + let err = error("T0 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT1(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 18; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 35; + end + else + begin + let err = error("T1 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT2(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 21; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 49; + end + else + begin + let err = error("T2 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT3(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 31; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 53; + end + else + begin + let err = error("T3 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT4(); + Integer returnValue = 0; + if((valueof(MD6_n) == 89) && (valueof(MD6_c) == 16)) + begin + returnValue = 67; + end + else if((valueof(MD6_n) == 178) && (valueof(MD6_c) == 32)) + begin + returnValue = 111; + end + else + begin + let err = error("T4 not defined"); + end + return valueof(MD6_n)-returnValue; +endfunction + +function Integer determineT5(); + return 0; +endfunction + +// This function returns the shift amounts. The argument is the step +// index. + +function ShiftFactor shiftIndexR(Bit#(4) index); + if(valueof(MD6_WordWidth) == 64) + begin + return c64ShiftR[index]; + end + else if(valueof(MD6_WordWidth) == 32) + begin + return c32ShiftR[index]; + end + else if(valueof(MD6_WordWidth) == 16) + begin + return c16ShiftR[index]; + end + else if(valueof(MD6_WordWidth) == 8) + begin + return c8ShiftR[index]; + end + else + begin + return 0; + end +endfunction + +function ShiftFactor shiftIndexL(Bit#(4) index); + if(valueof(MD6_WordWidth) == 64) + begin + return c64ShiftL[index]; + end + else if(valueof(MD6_WordWidth) == 32) + begin + return c32ShiftL[index]; + end + else if(valueof(MD6_WordWidth) == 16) + begin + return c16ShiftL[index]; + end + else if(valueof(MD6_WordWidth) == 8) + begin + return c8ShiftL[index]; + end + else + begin + return 0; + end +endfunction + +function Vector#(MD6_u, MD6Word) makeControlWord(Round rounds, + TreeHeight maxTreeHeight, + LastCompression lastCompression, + PaddingBits paddingBits, + KeyLength keyLength, + DigestLength digestLength) + provisos(Bits#(MD6Word, md6_size)); + Bit#(64) controlWord = {4'b0000,rounds,maxTreeHeight,lastCompression, + paddingBits,keyLength, digestLength}; + MD6Word controlArray[valueof(MD6_u)]; + for(Integer i = 0; i < valueof(MD6_u); i = i + 1) + begin + controlArray[fromInteger(i)] = controlWord[(i+1)*valueof(md6_size)-1:i*valueof(md6_size)]; + end + Vector#(MD6_u, MD6Word) controlVector = arrayToVector(controlArray); + return controlVector; +endfunction \ No newline at end of file Index: trunk/compressionFunction/src/CompressionFunctionTypes.bsv =================================================================== --- trunk/compressionFunction/src/CompressionFunctionTypes.bsv (nonexistent) +++ trunk/compressionFunction/src/CompressionFunctionTypes.bsv (revision 2) @@ -0,0 +1,7 @@ +// This file contains types used in the compression function + +// Control Word types + + + +typedef Bit#(6) ShiftFactor; \ No newline at end of file Index: trunk/compressionFunction/src/ControlWord.bsv =================================================================== Index: trunk/compressionFunction/fpga/md6engine.v =================================================================== --- trunk/compressionFunction/fpga/md6engine.v (nonexistent) +++ trunk/compressionFunction/fpga/md6engine.v (revision 2) @@ -0,0 +1,235 @@ +/* +Copyright (c) 2007 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 +*/ + +module md6engine(CLK, + RST, + plbMasterWires_mABus, + + plbMasterWires_mBE, + + plbMasterWires_mRNW, + + plbMasterWires_mAbort, + + plbMasterWires_mBusLock, + + plbMasterWires_mCompress, + + plbMasterWires_mGuarded, + + plbMasterWires_mLockErr, + + plbMasterWires_mMSize, + + plbMasterWires_mOrdered, + + plbMasterWires_mPriority, + + plbMasterWires_mRdBurst, + + plbMasterWires_mRequest, + + plbMasterWires_mSize, + + plbMasterWires_mType, + + plbMasterWires_mWrBurst, + + plbMasterWires_mWrDBus, + + plbMasterWires_mRst, + plbMasterWires_mAddrAck, + plbMasterWires_mBusy, + plbMasterWires_mErr, + plbMasterWires_mRdBTerm, + plbMasterWires_mRdDAck, + plbMasterWires_mRdDBus, + plbMasterWires_mRdWdAddr, + plbMasterWires_mRearbitrate, + plbMasterWires_mWrBTerm, + plbMasterWires_mWrDAck, + plbMasterWires_mSSize, + plbMasterWires_sMErr, + plbMasterWires_sMBusy, + bramInitiatorWires_bramRST, + bramInitiatorWires_bramAddr, + bramInitiatorWires_bramDout, + bramInitiatorWires_bramWEN, + bramInitiatorWires_bramEN, + bramInitiatorWires_bramCLK, + bramInitiatorWires_bramDin); + input CLK; + input RST; + + // value method plbMasterWires_mABus + output [31 : 0] plbMasterWires_mABus; + + // value method plbMasterWires_mBE + output [7 : 0] plbMasterWires_mBE; + + // value method plbMasterWires_mRNW + output plbMasterWires_mRNW; + + // value method plbMasterWires_mAbort + output plbMasterWires_mAbort; + + // value method plbMasterWires_mBusLock + output plbMasterWires_mBusLock; + + // value method plbMasterWires_mCompress + output plbMasterWires_mCompress; + + // value method plbMasterWires_mGuarded + output plbMasterWires_mGuarded; + + // value method plbMasterWires_mLockErr + output plbMasterWires_mLockErr; + + // value method plbMasterWires_mMSize + output [1 : 0] plbMasterWires_mMSize; + + // value method plbMasterWires_mOrdered + output plbMasterWires_mOrdered; + + // value method plbMasterWires_mPriority + output [1 : 0] plbMasterWires_mPriority; + + // value method plbMasterWires_mRdBurst + output plbMasterWires_mRdBurst; + + // value method plbMasterWires_mRequest + output plbMasterWires_mRequest; + + // value method plbMasterWires_mSize + output [3 : 0] plbMasterWires_mSize; + + // value method plbMasterWires_mType + output [2 : 0] plbMasterWires_mType; + + // value method plbMasterWires_mWrBurst + output plbMasterWires_mWrBurst; + + // value method plbMasterWires_mWrDBus + output [63 : 0] plbMasterWires_mWrDBus; + + // action method plbMasterWires_plbIN + input plbMasterWires_mRst; + input plbMasterWires_mAddrAck; + input plbMasterWires_mBusy; + input plbMasterWires_mErr; + input plbMasterWires_mRdBTerm; + input plbMasterWires_mRdDAck; + input [63 : 0] plbMasterWires_mRdDBus; + input [2 : 0] plbMasterWires_mRdWdAddr; + input plbMasterWires_mRearbitrate; + input plbMasterWires_mWrBTerm; + input plbMasterWires_mWrDAck; + input plbMasterWires_mSSize; + input plbMasterWires_sMErr; + input plbMasterWires_sMBusy; + + // action method bramTargetWires_bramIN + output [31 : 0] bramInitiatorWires_bramAddr; + output [31 : 0] bramInitiatorWires_bramDout; + output [3 : 0] bramInitiatorWires_bramWEN; + output bramInitiatorWires_bramEN; + output bramInitiatorWires_bramCLK; + output bramInitiatorWires_bramRST; + + // value method bramTargetWires_bramOUT + input [31 : 0] bramInitiatorWires_bramDin; + + wire [13:0] bramInitiatorWires_bramAddr_our; + assign bramInitiatorWires_bramAddr = {16'h0000,bramInitiatorWires_bramAddr_our, 2'b00}; + // signals for module outputs + wire [31 : 0] bramTargetWires_dinBRAM,plbMasterWires_mABus; + + wire [63 : 0] plbMasterWires_mWrDBus; + wire [7 : 0] plbMasterWires_mBE; + wire [3 : 0] plbMasterWires_mSize; + wire [2 : 0] plbMasterWires_mType; + wire [1 : 0] plbMasterWires_mMSize, plbMasterWires_mPriority; + wire plbMasterWires_mAbort, + plbMasterWires_mBusLock, + plbMasterWires_mCompress, + plbMasterWires_mGuarded, + plbMasterWires_mLockErr, + plbMasterWires_mOrdered, + plbMasterWires_mRNW, + plbMasterWires_mRdBurst, + plbMasterWires_mRequest, + plbMasterWires_mWrBurst; + +wire RST_N; +assign RST_N = ~RST; + + +mkMD6Engine m( + .CLK(CLK), + .RST_N(RST_N), + + .plbMasterWires_mABus(plbMasterWires_mABus), + .plbMasterWires_mBE(plbMasterWires_mBE), + .plbMasterWires_mRNW(plbMasterWires_mRNW), + .plbMasterWires_mAbort(plbMasterWires_mAbort), + .plbMasterWires_mBusLock(plbMasterWires_mBusLock), + .plbMasterWires_mCompress(plbMasterWires_mCompress), + .plbMasterWires_mGuarded(plbMasterWires_mGuarded), + .plbMasterWires_mLockErr(plbMasterWires_mLockErr), + .plbMasterWires_mMSize(plbMasterWires_mMSize), + .plbMasterWires_mOrdered(plbMasterWires_mOrdered), + .plbMasterWires_mPriority(plbMasterWires_mPriority), + .plbMasterWires_mRdBurst(plbMasterWires_mRdBurst), + .plbMasterWires_mRequest(plbMasterWires_mRequest), + .plbMasterWires_mSize(plbMasterWires_mSize), + .plbMasterWires_mType(plbMasterWires_mType), + .plbMasterWires_mWrBurst(plbMasterWires_mWrBurst), + .plbMasterWires_mWrDBus(plbMasterWires_mWrDBus), + .plbMasterWires_mRst(plbMasterWires_mRst), + .plbMasterWires_mAddrAck(plbMasterWires_mAddrAck), + .plbMasterWires_mBusy(plbMasterWires_mBusy), + .plbMasterWires_mErr(plbMasterWires_mErr), + .plbMasterWires_mRdBTerm(plbMasterWires_mRdBTerm), + .plbMasterWires_mRdDAck(plbMasterWires_mRdDAck), + .plbMasterWires_mRdDBus(plbMasterWires_mRdDBus), + .plbMasterWires_mRdWdAddr(plbMasterWires_mRdWdAddr), + .plbMasterWires_mRearbitrate(plbMasterWires_mRearbitrate), + .plbMasterWires_mWrBTerm(plbMasterWires_mWrBTerm), + .plbMasterWires_mWrDAck(plbMasterWires_mWrDAck), + .plbMasterWires_mSSize(plbMasterWires_mSSize), + .plbMasterWires_sMErr(plbMasterWires_sMErr), + .plbMasterWires_sMBusy(plbMasterWires_sMBusy), + .bramInitiatorWires_bramAddr(bramInitiatorWires_bramAddr_our), + .bramInitiatorWires_bramDout(bramInitiatorWires_bramDout), + .bramInitiatorWires_bramWEN(bramInitiatorWires_bramWEN), + .bramInitiatorWires_bramEN(bramInitiatorWires_bramEN), + .bramInitiatorWires_bramCLK(bramInitiatorWires_bramCLK), + .bramInitiatorWires_bramRST(bramInitiatorWires_bramRST), + .bramInitiatorWires_din(bramInitiatorWires_bramDin) + ); + +endmodule \ No newline at end of file Index: trunk/compressionFunction/fpga/MD6Engine.h =================================================================== --- trunk/compressionFunction/fpga/MD6Engine.h (nonexistent) +++ trunk/compressionFunction/fpga/MD6Engine.h (revision 2) @@ -0,0 +1,38 @@ +#ifndef MD6_ENGINE_H +#define MD6_ENGINE_H +#include"md6.h" + + +#define SHORT_WIDTH + +//#if sizeof(short) != 2 +// #error "Miss-sized short" +//#endif + +typedef enum {Read=0,Write=1,} Command; +typedef enum {RoundRegister = 0, + TreeHeightRegister = 1, + LastCompressionRegister = 2, + PaddingBitsRegister = 3, + KeyLengthRegister = 4, + DigestLengthRegister = 5, + CompressionFunctionStatus = 6, + KeyRegisterBase = 7, + IdentifierRegisterBase = KeyRegisterBase + md6_k*(md6_w/16), + SourceRegisterBase = IdentifierRegisterBase + md6_u*(md6_w/16), + DestinationRegisterBase = SourceRegisterBase + 2, + TotalRegisters = DestinationRegisterBase + 2 } RegisterAddr; + + + +/*int MD6Send(Command command, + RegisterAddr reg, + short payload); + +int MD6Receive(short * payload);*/ + +int MD6Write(RegisterAddr reg, short payload); + +int MD6Read(RegisterAddr reg, short *payload); + +#endif Index: trunk/compressionFunction/fpga/MD6Driver.c =================================================================== --- trunk/compressionFunction/fpga/MD6Driver.c (nonexistent) +++ trunk/compressionFunction/fpga/MD6Driver.c (revision 2) @@ -0,0 +1,164 @@ +#include "md6.h" +#include "MD6Engine.h" +#include "timer.h" + +#ifdef DEBUG + int writeCheck(RegisterAddr reg, short data); + int readCheck(RegisterAddr reg, short data); +#endif + +#undef DEBUG + +#define EVER ;; + +//int checkHash(md6_word *src, md6_word *dest, md6_word *uniqueID, +// md6_word *tree_height, md6_word *last_op, +// md6_word *padding_bits); +#ifdef DEBUG +inline int writeCheck(RegisterAddr reg, short data) { + short temp; + if(MD6Write(reg, data) < 0) { + xil_printf("Failed to write %s\r\n", registerAddrToString(reg)); + return -1; + } + + return readCheck(reg,data); +} +#else + int (*writeCheck) (RegisterAddr,short) = MD6Write; +#endif + +inline int readCheck(RegisterAddr reg, short data) { + short temp; + if(MD6Read(reg, &temp) < 0) { + xil_printf("Failed to read %s\r\n",registerAddrToString(reg)); + return -1; + } else if(temp != data) { + xil_printf("%s == %x, expect %x\r\n",registerAddrToString(reg),temp,data); + return -1; + } + return 0; +} + +int startHash(md6_word *src, md6_word *dest, md6_word *uniqueID, + md6_word *key, md6_word *tree_height, md6_word *last_op, + md6_word *padding_bits, md6_word *digest_length) { + short sent_value; + int spins = 0; + long long start, finish; + int i; + #ifdef DEBUG + xil_printf("src: %x dest: %x \r\n", src, dest); + #endif + sent_value = ((int)src) & 0xffff; + //Check that the compressor is turned off + // if(readChseck(CompressionFunctionStatus,0)){ + // return 0; + // } + + if(writeCheck(SourceRegisterBase, sent_value) < 0) { + return -1; + } + + sent_value = ((int)src >>16) & 0xffff; + if(writeCheck(SourceRegisterBase + 1, sent_value) < 0) { + return -1; + } + + sent_value = ((int)dest) & 0xffff; + if(writeCheck(DestinationRegisterBase, sent_value) < 0) { + return -1; + } + + sent_value = ((int)dest >>16) & 0xffff; + if(writeCheck(DestinationRegisterBase + 1, sent_value) < 0) { + return -1; + } + + // write out uniqueID + for(i = 0; i < md6_u*md6_w/16; i++) { + sent_value = ( (uniqueID[i>>2]) >> ((i&0x3)*16) ) & 0xffff; + writeCheck(IdentifierRegisterBase+i,sent_value); + } + + // write out key + for(i = 0; i < md6_k*md6_w/16; i++) { + sent_value = ( (key[i>>2]) >> ((i&0x3)*16) ) & 0xffff; + writeCheck(KeyRegisterBase+i,sent_value); + } + + sent_value = *tree_height & 0xffff; + if(writeCheck(TreeHeightRegister, sent_value) < 0) { + return -1; + } + + sent_value = *last_op & 0xffff; + if(writeCheck(LastCompressionRegister, sent_value) < 0) { + return -1; + } + + sent_value = *padding_bits & 0xffff; + if(writeCheck(PaddingBitsRegister, sent_value) < 0) { + return -1; + } + //XXXX this must be fixed at some point. + sent_value = md6_k; + if(writeCheck(KeyLengthRegister, sent_value) < 0) { + return -1; + } + + sent_value = 0; + if(writeCheck(RoundRegister, sent_value) < 0) { + return -1; + } + + sent_value = (short)*digest_length & 0xffff; + if(writeCheck(DigestLengthRegister, sent_value) < 0) { + return -1; + } + + #ifdef DEBUG + for(i = 0; i < TotalRegisters; i++) { + MD6Read(i,&sent_value); + xil_printf("Reg[%d]: %4x ", i, sent_value); + if(i%4==3) { + printf("\r\n"); + } + } + printf("\r\n"); + #endif +// md6_word *src, md6_word *dest, md6_word *uniqueID, +// md6_word *tree_height, md6_word *last_op, +// md6_word *padding_bits + // this check could possibly fail + start = ts_get_ll(); + if(MD6Write(CompressionFunctionStatus,1)<0) { + xil_printf("Failed to start Compression Function\r\n"); + return -1; + } + + + + + for(EVER) { + if(MD6Read(CompressionFunctionStatus, &sent_value) < 0) { + xil_printf("Failed to read Compression Function Status spins: %d, %d\r\n",spins,CompressionFunctionStatus); + return -1; + } + + if(sent_value == 0) { + finish = ts_get_ll(); + xil_printf("Time kernel: %d %d\r\n", (int)(finish-start),ts_elapse_ns(start,finish)); + break; + } + + spins++; + if(spins%1000000 == 0) { + xil_printf("Compression Function Timeout, status: %d", sent_value); + break; + } + } + +} + + Index: trunk/compressionFunction/fpga/MD6Engine.bsv =================================================================== --- trunk/compressionFunction/fpga/MD6Engine.bsv (nonexistent) +++ trunk/compressionFunction/fpga/MD6Engine.bsv (revision 2) @@ -0,0 +1,318 @@ +/* +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 is the top-level sorter module. It interfaces to the PLB bus, the + DSOCM, and the sorter core. Not much functionality, but it does have + a cycle timer, and sends periodic messages back to the PPC over the + DSOCM +*/ + +// Bluespec Lib +import FIFO::*; +import GetPut::*; +import Vector::*; +import Connectable::*; + +// CSG Lib +import PLBMasterWires::*; +import BRAMInitiatorWires::*; +import PLBMaster::*; +import BRAMFeeder::*; +import PLBMaster::*; +import PLBMasterDefaultParameters::*; + +// Local includes +import CompressionFunction::*; +import CompressionFunctionLibrary::*; +import MD6Parameters::*; +import MD6Types::*; + + +interface MD6Engine; + interface PLBMasterWires plbMasterWires; + interface BRAMInitiatorWires#(Bit#(14)) bramInitiatorWires; +endinterface + +// Might consider making this size 8 at some point so that it jives with +// other parameterizations +typedef 16 InterfaceRegister; +typedef Bit#(15) RegisterTag; + +typedef enum { + Read = 0, + Write = 1 +} Command deriving (Bits,Eq); + + +typedef 7 ControlRegisters; +typedef TMul#(MD6_u,TDiv#(MD6_WordWidth,InterfaceRegister)) IdentifierRegisters; +typedef TMul#(MD6_k,TDiv#(MD6_WordWidth,InterfaceRegister)) KeyRegisters; +typedef 2 SourceRegisters; +typedef 2 DestinationRegisters; + +typedef 0 RoundRegister; +typedef 1 TreeHeightRegister; +typedef 2 LastCompressionRegister; +typedef 3 PaddingBitsRegister; +typedef 4 KeyLengthRegister; +typedef 5 DigestLengthRegister; +typedef 6 CompressionFunctionStatus; +typedef 7 KeyRegisterBase; +typedef TAdd#(ControlRegisters,KeyRegisters) IdentifierRegisterBase; +typedef TAdd#(ControlRegisters, TAdd#(KeyRegisters,IdentifierRegisters)) SourceRegisterBase; +typedef TAdd#(TAdd#(ControlRegisters,IdentifierRegisters), TAdd#(KeyRegisters,SourceRegisters)) DestinationRegisterBase; +typedef TAdd#(IdentifierRegisters,TAdd#(TAdd#(ControlRegisters,DestinationRegisters), TAdd#(KeyRegisters,SourceRegisters))) TotalRegisters; + +typedef TDiv#(TMul#(SizeOf#(BusWord),BeatsPerBurst), SizeOf#(MD6Word)) MD6WordsPerBurst; + +typedef 32'hC0000 MD6CommunicationConstant; + +typedef struct { + Command command; + RegisterTag regTag; + Bit#(InterfaceRegister) payload; +} IOCommand deriving (Bits,Eq); + +typedef enum { + Idle, + Load +} LoadState deriving (Bits,Eq); + +typedef enum { + Idle, + Store +} StoreState deriving (Bits,Eq); + + +(*synthesize*) +module mkCompressionFunction64 (CompressionFunction#(64)); + let m <- mkMult16CompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction48 (CompressionFunction#(48)); + let m <- mkMult16CompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction32 (CompressionFunction#(32)); + let m <- mkMult16CompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction16 (CompressionFunction#(16)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction8 (CompressionFunction#(8)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction4 (CompressionFunction#(4)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction2 (CompressionFunction#(2)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + +(*synthesize*) +module mkCompressionFunction1 (CompressionFunction#(1)); + let m <- mkSimpleCompressionFunction; + return m; +endmodule + + +module mkMD6Engine (MD6Engine); + Feeder feeder <- mkBRAMFeeder(); + PLBMaster plbMaster <- mkPLBMaster; + CompressionFunction#(4) compressionFunction <- mkSimpleCompressionFunction; + FIFO#(PPCMessage) outputFIFO <- mkFIFO; + Vector#(TotalRegisters, Reg#(Bit#(InterfaceRegister))) interfaceRegisters <- + replicateM(mkReg(0)); + + + // Hook Control, PLBMaster and MD6 engine components together. + // This solution WILL NOT WORK for multiple Compression functions + mkConnection(plbMaster.wordInput.put, compressionFunction.outputWord); + mkConnection(compressionFunction.inputWord,plbMaster.wordOutput.get); + mkConnection(feeder.ppcMessageInput.put,(fifoToGet(outputFIFO)).get); + + Reg#(Bit#(TAdd#(1,TDiv#(MD6_b,MD6WordsPerBurst)))) loadCount <- mkReg(0); + + Reg#(Bit#(TAdd#(1,TDiv#(MD6_c,MD6WordsPerBurst)))) storeCount <- mkReg(0); + + Reg#(LoadState) loadState <- mkReg(Idle); + + Reg#(StoreState) storeState <- mkReg(Idle); + + FIFO#(IOCommand) incomingCommands <- mkFIFO; + + function IOCommand extractIOCommand(PPCMessage ppcMessage); + IOCommand command = IOCommand {command: unpack(ppcMessage[31]), + regTag: ppcMessage[30:16], + payload: ppcMessage[15:0]}; + return command; + endfunction + + // This function may require its own unit test + // It should convert interface words to MD6 Words + function Vector#(length,MD6Word) convertWords( + Vector#(TMul#(length,TDiv#(MD6_WordWidth,InterfaceRegister)),Bit#(InterfaceRegister)) inVector); + Vector#(length,MD6Word) outVector = newVector; + for(Integer totalNumber = 0; + totalNumber < valueof(length); + totalNumber = totalNumber + 1) + begin + Vector#(TDiv#(MD6_WordWidth,InterfaceRegister),Bit#(InterfaceRegister)) wordVector = newVector; + for(Integer wordsInMD6Word = 0; + wordsInMD6Word < valueof(TDiv#(MD6_WordWidth,InterfaceRegister)); + wordsInMD6Word = wordsInMD6Word + 1) + begin + wordVector[wordsInMD6Word] = inVector[totalNumber*valueof(TDiv#(MD6_WordWidth,InterfaceRegister)) + +wordsInMD6Word]; + end + outVector[totalNumber] = unpack(pack(wordVector)); // is this sane? + end + return outVector; + endfunction + + rule getCommand; + PPCMessage msg <- feeder.ppcMessageOutput.get; + IOCommand command = extractIOCommand(msg); + incomingCommands.enq(command); + endrule + + // Writing to the CompressionFunctionStatus means kickoff a compression operation + // Reading from it will grab the current status of the Compression Engine + + rule processWrite(incomingCommands.first.command == Write); + incomingCommands.deq; + + if(fromInteger(valueof(CompressionFunctionStatus)) == incomingCommands.first.regTag) + begin + // we can leave this unguarded because the properties of the compression function + // will prevent doing nasty things like confusing the order of memory accesses. + let controlWord = makeControlWord(truncate(interfaceRegisters[valueof(RoundRegister)]), + truncate(interfaceRegisters[valueof(TreeHeightRegister)]), + truncate(interfaceRegisters[valueof(LastCompressionRegister)]), + truncate(interfaceRegisters[valueof(PaddingBitsRegister)]), + truncate(interfaceRegisters[valueof(KeyLengthRegister)]), + truncate(interfaceRegisters[valueof(DigestLengthRegister)])); + + compressionFunction.start(convertWords(takeAt(valueof(IdentifierRegisterBase),readVReg(interfaceRegisters))), + controlWord, + convertWords(takeAt(valueof(KeyRegisterBase),readVReg(interfaceRegisters)))); + loadState <= Load; + loadCount <= 0; + end + else + begin + interfaceRegisters[incomingCommands.first.regTag] <= incomingCommands.first.payload; + end + endrule + + rule processRead(incomingCommands.first.command == Read); + incomingCommands.deq; + + // This is a bit ugly, and we should possibly fix it. + if(fromInteger(valueof(CompressionFunctionStatus)) == incomingCommands.first.regTag) + begin + outputFIFO.enq(fromInteger(valueof(MD6CommunicationConstant))|zeroExtend(compressionFunction.status)); + end + else + begin + outputFIFO.enq(fromInteger(valueof(MD6CommunicationConstant))|zeroExtend((interfaceRegisters[incomingCommands.first.regTag]))); + end + + endrule + + + + + // Probably should handle non-fitting burst sizes. But, don't have to + // for now. + if(valueof(TotalRegisters) != 47) + begin + error("Total Registers: %d\n",valueof(TotalRegisters)); + end + + if(valueof(MD6_b)%valueof(MD6WordsPerBurst) != 0) + begin + error("MD6_b:%d not divisible by MD6WordsPerBurst:%d",valueof(MD6_b), valueof(MD6WordsPerBurst)); + end + + if(valueof(MD6_c)%valueof(MD6WordsPerBurst) != 0) + begin + error("MD6_c:%d not divisible by MD6WordsPerBurst:%d",valueof(MD6_c), valueof(MD6WordsPerBurst)); + end + + rule issueLoads(loadState == Load); + if(loadCount + 1 == fromInteger(valueof(MD6_b)/valueof(MD6WordsPerBurst))) + begin + loadState <= Idle; + storeState <= Store; + storeCount <= 0; + end + loadCount <= loadCount + 1; + BlockAddr refAddr = truncateLSB({interfaceRegisters[valueof(SourceRegisterBase)+1], + interfaceRegisters[valueof(SourceRegisterBase)]}) + + (zeroExtend(loadCount) << (valueof(TLog#(WordsPerBurst)))); + + plbMaster.plbMasterCommandInput.put(tagged LoadPage refAddr); + endrule + + + + rule issueStores(storeState == Store); + if(storeCount + 1 == fromInteger(valueof(MD6_c)/valueof(MD6WordsPerBurst))) + begin + storeState <= Idle; + end + storeCount <= storeCount + 1; + + BlockAddr refAddr = truncateLSB({interfaceRegisters[valueof(DestinationRegisterBase)+1], + interfaceRegisters[valueof(DestinationRegisterBase)]}) + + (zeroExtend(storeCount) << (valueof(TLog#(WordsPerBurst)))); + + plbMaster.plbMasterCommandInput.put(tagged StorePage refAddr); + endrule + + interface plbMasterWires = plbMaster.plbMasterWires; + interface bramInitiatorWires = feeder.bramInitiatorWires; + +endmodule \ No newline at end of file Index: trunk/compressionFunction/fpga/MD6Driver.h =================================================================== --- trunk/compressionFunction/fpga/MD6Driver.h (nonexistent) +++ trunk/compressionFunction/fpga/MD6Driver.h (revision 2) @@ -0,0 +1,16 @@ +#ifndef MD6_ENGINE_H + +#include "md6.h" +#include "MD6Engine.h" + +int checkHash(md6_word *src, md6_word *dest, md6_word *uniqueID, + md6_word *key, md6_word *tree_height, md6_word *last_op, + md6_word *padding_bits, md6_word *digest_length); + +// this function expects src to be laid out 63:0 and writes dest 15:0 +// These will be word reversed. +int startHash(md6_word *src, md6_word *dest, md6_word *uniqueID, + md6_word *key, md6_word *tree_height, md6_word *last_op, + md6_word *padding_bits, md6_word *digest_length); + +#endif Index: trunk/compressionFunction/fpga/MD6Engine.c =================================================================== --- trunk/compressionFunction/fpga/MD6Engine.c (nonexistent) +++ trunk/compressionFunction/fpga/MD6Engine.c (revision 2) @@ -0,0 +1,65 @@ +#include "md6.h" +#include "MD6Engine.h" +#include "cLib.h" + +#define MD6CommunicationConstant 0xC0000 + +inline int MD6Send(Command command, RegisterAddr reg, short payload) { + int command_bits =(int)(((command & 0x1) << 31) | ((reg & 0x3fff) << 16) | ((payload & 0xffff) << 0)); + return putValue(command_bits); +} + +inline int MD6Receive(short *payload) { + int resp; + int value = getResponse(&resp); + if(MD6CommunicationConstant ^ (resp & 0xFFFF0000)) { + xil_printf("Communication may be corrupt\r\n"); + } + *payload = (short) resp; + return value; +} + +inline int MD6Write(RegisterAddr reg, short payload) { + return MD6Send(Write, reg, payload); +} + +inline int MD6Read(RegisterAddr reg, short *payload) { + if(MD6Send(Read, reg, 0) < 0) { + return -1; + } + return MD6Receive(payload); +} + +/*typedef enum {RoundRegister = 0, + TreeHeightRegister = 1, + LastCompressionRegister = 2, + PaddingBitsRegister = 3, + KeyLengthRegister = 4, + DigestLengthRegister = 5, + CompressionFunctionStatus = 6, + KeyRegisterBase = 7, + IdentifierRegisterBase = KeyRegisterBase + md6_k*(md6_w/16), + SourceRegisterBase = IdentifierRegisterBase + md6_u*(md6_w/16), + DestinationRegisterBase = SourceRegisterBase + 2, + TotalRegisters = DestinationRegisterBase + 2 } RegisterAddr;*/ + +char *registerAddrToString(RegisterAddr reg) { + switch(reg) { + case RoundRegister: return "RoundRegister"; + case TreeHeightRegister: return "TreeHeightRegister"; + case PaddingBitsRegister: return "PaddingBitsRegister"; + case KeyLengthRegister: return "KeyLengthRegister"; + case DigestLengthRegister: return "DigestLengthRegister"; + case KeyRegisterBase: return "KeyRegisterBase"; + case IdentifierRegisterBase: return "IdentifierRegisterBase"; + case IdentifierRegisterBase + 1: return "IdentifierRegisterBase+1"; + case IdentifierRegisterBase + 2: return "IdentifierRegisterBase+2"; + case IdentifierRegisterBase + 3: return "IdentifierRegisterBase+3"; + case CompressionFunctionStatus: return "CompressionFunctionStatus"; + case SourceRegisterBase: return "SourceRegisterBase"; + case SourceRegisterBase + 1: return "SourceRegisterBase + 1"; + case DestinationRegisterBase: return "DestinationRegisterBase"; + case DestinationRegisterBase + 1: return "DestinationRegisterBase + 1"; + default: return "Uknown Register"; + } +} \ No newline at end of file Index: trunk/common/Debug.bsv =================================================================== --- trunk/common/Debug.bsv (nonexistent) +++ trunk/common/Debug.bsv (revision 2) @@ -0,0 +1,7 @@ +function Action debug(Bool b, Action a); + action + + if (b) a; + + endaction +endfunction \ No newline at end of file Index: trunk/common/MD6Parameters.bsv =================================================================== --- trunk/common/MD6Parameters.bsv (nonexistent) +++ trunk/common/MD6Parameters.bsv (revision 2) @@ -0,0 +1,69 @@ +// The following are magic, externally defined parameters in MD6 +// Other important parameters are derived from them. +// These parameters are used at a global level + + +`ifdef BIT64 +typedef 16 MD6_c; +typedef 512 MD6_d; // Bits in final hashvalue +typedef 64 MD6_b; +typedef 178 MD6_r; + +typedef 89 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 15 MD6_q; +typedef 8 MD6_k; +typedef 1 MD6_v; +typedef 1 MD6_u; + +typedef 64 MD6_WordWidth; +`endif + +// All that appears to change for +// different word widths is the WordWidth. +// Other fields seem to get dropped. +`ifdef BIT32 +typedef 32 MD6_c; +typedef 128 MD6_b; +typedef 178 MD6_r; + +typedef 178 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 30 MD6_q; +typedef 16 MD6_k; + +typedef 2 MD6_v; +typedef 2 MD6_u; + +typedef 32 MD6_WordWidth; +`endif + +`ifdef BIT16 +typedef 64 MD6_c; +typedef 256 MD6_b; +typedef 178 MD6_r; + +typedef 178 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 30 MD6_q; +typedef 16 MD6_k; +typedef 2 MD6_v; +typedef 2 MD6_u; + +typedef 16 MD6_WordWidth; +`endif + +`ifdef BIT8 +typedef 32 MD6_c; +typedef 128 MD6_b; +typedef 178 MD6_r; + +typedef 178 MD6_n; // This can definitely be derived from other constants at + // the top level +typedef 30 MD6_q; +typedef 16 MD6_k; +typedef 2 MD6_v; +typedef 2 MD6_u; + +typedef 32 MD6_WordWidth; +`endif \ No newline at end of file Index: trunk/common/MD6Library.bsv =================================================================== --- trunk/common/MD6Library.bsv (nonexistent) +++ trunk/common/MD6Library.bsv (revision 2) @@ -0,0 +1,5 @@ +import MD6Types::*; + +function Round defaultMD6R(DigestLength length); + return 40+(length>>2); +endfunction \ No newline at end of file Index: trunk/common/MD6Types.bsv =================================================================== --- trunk/common/MD6Types.bsv (nonexistent) +++ trunk/common/MD6Types.bsv (revision 2) @@ -0,0 +1,13 @@ +import MD6Parameters::*; + +typedef Bit#(MD6_WordWidth) MD6Word; +typedef (TExp#(64)) MD6_BitSize; + + +typedef Bit#(12) Round; +typedef Bit#(8) TreeHeight; + +typedef Bit#(4) LastCompression; //One if last compression, else zero +typedef Bit#(16) PaddingBits; +typedef Bit#(8) KeyLength; +typedef Bit#(12) DigestLength; \ No newline at end of file Index: trunk/common/DataTypes.bsv =================================================================== --- trunk/common/DataTypes.bsv (nonexistent) +++ trunk/common/DataTypes.bsv (revision 2) @@ -0,0 +1 @@ +import FIFO::*; \ No newline at end of file Index: trunk/documentation/readme.txt~ =================================================================== --- trunk/documentation/readme.txt~ (nonexistent) +++ trunk/documentation/readme.txt~ (revision 2) @@ -0,0 +1,6 @@ +Some notes on using the code + +You will need to set up some environmental variables in order to +actually build the code: + + Index: trunk/documentation/readme.txt =================================================================== --- trunk/documentation/readme.txt (nonexistent) +++ trunk/documentation/readme.txt (revision 2) @@ -0,0 +1,49 @@ +Some notes on using the code + +Notes on code layout: + + C_implementation - this directory contains the golden C implementation + + common - this directory contains some definition files which are + shared among the the other directories + + compressionFunction - this directory contains the implementation + and testbenches for the compression function. + + documentation - this directory contains relevant documentation + + lib - this directory mirrors the Bluespec Board support package. + It contains useful library functionality - like bus + implementations. + + MD6Control - contains the memory controller implementations and + the full system testbenches + + toolflow - some scripts for synthesis - not really useful to the + outside world + +Building the code: + + There are many targets in the build directories - + the most useful of these are: + + MD6Verify - builds the full system verification + + MD6ControlEngine_fpga - builds an FPGA version of the control engine + + SimpleCompressionFunctionTestbench64 - a test bench for the + compression function in isolation + + +What you will need: + +Latest version of the Bluespec compiler. Visit www.bluespec.com We +may be able to provide you with one-of verilog. Please contact us if +you would like verilog. + + +Further documentation about the operation, theory, security, and +practical implementation of MD6 can be found at: + +http://groups.csail.mit.edu/cis/md6/ +

powered by: WebSVN 2.1.0

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