|
Message
From: cvs at opencores.org<cvs@o...>
Date: Mon Jun 30 18:02:04 CEST 2008
Subject: [cvs-checkins] MODIFIED: cryptosorter ...
Date: 00/08/06 30:18:02 Added: cryptosorter/memocodeDesignContest2008/ctrl Four2OneMerger.bsv gen_test_array.c mkCtrl.bsv mkTH.sched mkTester.bsv Log: Initial checkin with actual source Revision Changes Path 1.1 cryptosorter/memocodeDesignContest2008/ctrl/Four2OneMerger.bsv http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/ctrl/Four2OneMerger.bsv?rev=1.1&content-type=text/x-cvsweb-markup Index: Four2OneMerger.bsv =================================================================== import Memocode08Types ::*; import StmtFSM ::*; import GetPut ::*; import Vector ::*; import FIFO ::*; interface Four2One; interface Vector#(4, Put#(Bit#(RecordWidth))) in; interface Get#(Bit#(RecordWidth)) out; endinterface `define Debug421 False module mkFour2One (Four2One); Vector#(4, FIFO#(Bit#(RecordWidth))) top_fifos <- replicateM(mkFIFO()); Vector#(2, FIFO#(Bit#(RecordWidth))) mid_fifos <- replicateM(mkFIFO()); Vector#(2, Reg#(Bit#(2))) l1_cnts <- replicateM(mkReg(~0)); Vector#(2, Reg#(Bit#(2))) l2_cnts <- replicateM(mkReg(2)); for(Bit#(2) i = 0; i < 2; i = i+1) rule l1_cmp (True); let b0 = (l1_cnts[i])[0:0]==1'b1; let b1 = (l1_cnts[i])[1:1]==1'b1; let in0 = top_fifos[(2*i)+0]; let in1 = top_fifos[(2*i)+1]; let out = mid_fifos[i]; let nv = ~0; if(b0&&!b1) begin in0.deq(); out.enq(in0.first()); if(`Debug421) $display("%d l1_zero", i); end else if(!b0&&b1) begin in1.deq(); out.enq(in1.first()); if(`Debug421) $display("%d l1_one", i); end else begin if (in0.first > in1.first()) begin in0.deq(); out.enq(in0.first()); nv = 2; if(`Debug421) $display("%d l1_zero (cmp)", i); end else begin in1.deq(); out.enq(in1.first()); nv = 1; if(`Debug421) $display("%d l1_one (cmp)", i); end end l1_cnts[i] <= nv; if(`Debug421) $display("%d l1_cmp nv: %x", i, nv); endrule interface in = map(fifoToPut, top_fifos); interface Get out; method ActionValue#(Bit#(RecordWidth)) get(); let b0 = (l2_cnts[0]) != 0; let b1 = (l2_cnts[1]) != 0; let in0 = mid_fifos[0]; let in1 = mid_fifos[1]; let sum = l2_cnts[0] + l2_cnts[1]; let rv = in1; let nv0 = l2_cnts[0];
let nv1 = l2_cnts[1];
if(b0&&!b1)
begin
in0.deq();
if(sum != 1)
nv0 = nv0-1;
else
begin
nv0 = 2;
nv1 = 2;
end
rv = in0;
if(`Debug421) $display("l2_zero");
end
else if(!b0&&b1)
begin
in1.deq();
if(sum != 1)
nv1 = nv1-1;
else
begin
nv0 = 2;
nv1 = 2;
end
rv = in1;
if(`Debug421) $display("l2_one");
end
else
begin
if (in0.first > in1.first())
begin
in0.deq();
nv0 = nv0-1;
rv = in0;
if(`Debug421) $display("l2_zero (cmp)");
end
else
begin
in1.deq();
nv1 = nv1-1;
rv = in1;
if(`Debug421) $display("l2_one (cmp)");
end
end
if(`Debug421) $display("l2_cmp, nv0: %d, nv1: %d, sum: %d",
nv0, nv1, sum);
l2_cnts[0] <= nv0;
l2_cnts[1] <= nv1;
return rv.first();
endmethod
endinterface
endmodule
1.1 cryptosorter/memocodeDesignContest2008/ctrl/gen_test_array.c
http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/ctrl/gen_test_array.c?rev=1.1&content-type=text/x-cvsweb-markup
Index: gen_test_array.c
===================================================================
/*
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
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "aes_core.h"
#include "recordio.h"
const unsigned char globalkey[] = {0xB0, 0x1D, 0xFA, 0xCE,
0x0D, 0xEC, 0x0D, 0xED,
0x0B, 0xA1, 0x1A, 0xDE,
0x0E, 0xFF, 0xEC, 0x70};
int main() {
long long start, stop;
int i;
FILE *sorted, *unsorted;
assert(sorted = fopen("sorted.hex","w"));
assert(unsorted = fopen("unsorted.hex","w"));
printf("Initializing database\n");
initializedb(globalkey);
printf("Sorting starts\n");
//showdb();
for(i = 0; i < MAXRECORD; i+=1) {
fprintf(unsorted,"%08x%08x%08x%08x\n", db[i].f1, db[i].f2, db[i].f3, db[i].f4 );
}
sortrecord();
// showdb();
for(i = 0; i < MAXRECORD; i+=1) {
fprintf(sorted,"%08x%08x%08x%08x\n",db[i].f1, db[i].f2, db[i].f3, db[i].f4 );
}
printf("Verifying results .. (correct = 1): ");
printf("%x\n", verifydb());
return 0;
}
1.1 cryptosorter/memocodeDesignContest2008/ctrl/mkCtrl.bsv
http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/ctrl/mkCtrl.bsv?rev=1.1&content-type=text/x-cvsweb-markup
Index: mkCtrl.bsv
===================================================================
/*
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: Myron King
*/
/***************************************************************
*
* The module mkControl is responsible for (as it's name would
* suggest) orchestrating the communication between the various
* sub-modules in the system, as well as directing their
* individual behavior. The sort tree has a complicated control
* protocol which requires that reservations be made for both
* the insertion and extraction of data. In order to avoid
* deadlock, guarantees must be made on the availability of data
* to be inserted or space for the extrated data to be buffered
* In addition, the first stage of sorting is distinct from all
* subsequent stages in that the data is organized randomly and
* no assumptions can be made about ordered sub-streams in
* memory.
*
* the module accepts commands in the form of the length of array
* to be sorted, through the doSort interface. the guarded value
* method finished() returns true upon sort completion. There is
* a debug interface msgs which can be used to extract debug
* messages.
*
* the mkTH module is for testing purposes only
*
***************************************************************/
import BRAMFIFO ::*;
import Sort ::*;
import aesCipherTop ::*;
import Memocode08Types ::*;
import ExternalMemory ::*;
import PLBMasterDummy ::*;
import Interfaces ::*;
import FIFO ::*;
import FIFOF ::*;
import EHRReg ::*;
import Vector ::*;
import SortTree64 ::*;
import RegFile ::*;
import GetPut ::*;
interface Control;
method Action doSort(Bit#(5) log_len);
method Bool finished();
interface Get#(Bit#(32)) msgs;
endinterface
typedef 64 KMerges;
typedef Bit#(TLog#(KMerges)) KMask;
typedef Bit#(TAdd#(TLog#(KMerges),1)) KMaskp1;
typedef Bit#(TLog#(RecordsPerMemRequest)) RPMRMask;
typedef Bit#(TAdd#(1,TLog#(RecordsPerMemRequest))) OBuffCap;
typedef Bit#(20) RecAddr;
`define Debug False
(* descending_urgency = "drain_sorter, write_to_mem" *)
(* descending_urgency = "read_request_a, schedule_read_request" *)
module mkControl#(ExternalMemory extMem, Clock fastClock, Reset fastReset) (Control);
/*
Bit#(5) log_sub_stream_lengths[3] = {6, 12, 18};
RecAddr num_sub_streams[13][3] = {{1, 0, 0},
{2, 1, 0},
{4, 1, 0},
{8, 1, 0},
{16, 1, 0},
{32, 1, 0},
{64, 1, 0},
{128, 2, 1},
{256, 4, 1},
{512, 8, 1},
{1024, 16, 1},
{2048, 32, 1},
{4096, 64, 1}};
*/
let sort_tree <- mkSortTree64();
Clock clk <- exposeCurrentClock;
Reset rst <- exposeCurrentReset;
AESCores#(2) aes_cores <- mkAESCoresMCD(clk,rst,clocked_by(fastClock),reset_by(fastReset));//mkAESCores();
Reg#(RecAddr) nss <- mkRegU();
Reg#(RecAddr) ssl <- mkRegU();
Reg#(RecAddr) nssl <- mkRegU();
//let ssl = (ra_one<<(log_sub_stream_lengths[iter-1]));
//let nssl = (ra_one<<(log_sub_stream_lengths[iter]));
//let nss = num_sub_streams[log_len-6][iter-1];
Reg#(RecAddr) read_req_count <- mkRegU();
Reg#(RecAddr) read_res_count <- mkRegU();
Reg#(KMask) res_count <- mkRegU();
Reg#(KMask) read_count <- mkRegU();
Reg#(Bool) read_eos <- mkRegU();
Reg#(RecAddr) write_base_addr <- mkRegU();
Reg#(RecAddr) write_req_count <- mkRegU();
Reg#(RecAddr) write_count <- mkRegU();
Reg#(Bit#(5)) log_len <- mkRegU();
Reg#(RecAddr) array_len <- mkRegU();
Reg#(Bit#(3)) iter <- mkReg(~0);
Reg#(Bool) last <- mkReg(False);
Reg#(Bool) done <- mkReg(True);
Reg#(Bool) set_next_stage <- mkReg(False);
Reg#(RecAddr) set_ptr_count <- mkRegU();
Reg#(KMask) set_count <- mkRegU();
Reg#(Bool) pending_read_req <- mkReg(False);
Reg#(KMask) pending_req_idx <- mkRegU();
Reg#(RecAddr) pending_req_new_base_ptr <- mkRegU();
Reg#(Addr) pending_req_req_addr <- mkRegU();
Reg#(RecAddr) pending_req_new_eos_left <- mkRegU();
Reg#(Bool) pending_req_need_eos <- mkRegU();
Reg#(RecAddr) pending_req_new_req_offset <- mkRegU();
Reg#(Bit#(5)) pending_req_rs_toks <- mkRegU();
Reg#(Bool) pending_req_is_fin_stage <- mkRegU();
FIFO#(Bit#(6)) pending_first_res_count <- mkFIFO();
FIFO#(RecAddr) pending_first_read_res_count <- mkFIFO();
FIFO#(Bit#(6)) pending_pending_reserve <- mkFIFO();
FIFO#(Tuple2#(KMask, Maybe#(Bit#(128)))) put_rec_fifo <- mkFIFO();
RecAddr ra_one = 1;
let kmerges = fromInteger(valueOf(KMerges));
let rpmr = fromInteger(valueOf(RecordsPerMemRequest));
let readpt = 0;
let writept = 0;
let recwid = fromInteger(valueOf(RecordWidth));
let outbuffsz = 2*rpmr;
let tok_info = sort_tree.inStream.getTokInfo();
KMask kmask = ~0;
KMaskp1 kmask1 = ~0;
RPMRMask rpmr_mask = ~0;
Bit#(32) bank_mask = fromInteger(valueOf(MemBankSelector))>>4;
RegFile#(KMask, RecAddr) base_ptrs <- mkRegFileFull();
RegFile#(KMask, RecAddr) req_offsets <- mkRegFileFull();
RegFile#(KMask, RecAddr) rsp_offsets <- mkRegFileFull();
RegFile#(KMask, RecAddr) eos_lefts <- mkRegFileFull();
Reg#(Vector#(KMerges, Bool)) finish_stage <- mkReg(replicate(False));
FIFO#(KMask) rdfifo <- mkFIFO();
FIFO#(Tuple2#(Bool,KMask)) rsfifo <- mkSizedFIFO(1);
FIFOF#(Bit#(1)) wrfifo <- mkFIFOF();
FIFO#(Bit#(1)) fsfifo <- mkFIFO();
FIFOF#(Bit#(RecordWidth)) out_buff <- mkBRAMFIFOF(2*rpmr);
Reg#(RPMRMask) out_buff_cnt <- mkReg(0);
FIFO#(Bit#(32)) msg_queue <- mkFIFO();
Reg#(int) msg_state <- mkReg(0);
Reg#(Bit#(30)) tic_counter <- mkReg(1);
Reg#(Bit#(32)) debug_read_requests <- mkReg(0);
Reg#(Bit#(32)) debug_write_requests <- mkReg(0);
Reg#(Bit#(32)) debug_drain_sorter_valid <- mkReg(0);
Reg#(Bit#(32)) debug_write_to_mem <- mkReg(0);
Reg#(Bit#(32)) debug_write_to_sort_tree <- mkReg(0);
Reg#(Bit#(32)) debug_write_eos_to_sort_tree <- mkReg(0);
Reg#(Bit#(32)) debug_write_eos_from_sort_tree <- mkReg(0);
Reg#(Bit#(32)) debug_write_eos_first <- mkReg(0);
Reg#(Bit#(32)) debug_write_eos_second <- mkReg(0);
Reg#(Bool) debug_setup_stream_stage <- mkReg(False);
rule tic_toc(True);
tic_counter <= tic_counter+1;
endrule
rule debug_stuff0 (tic_counter==0);
msg_queue.enq(debug_read_requests);
msg_state <= 1;
endrule
rule debug_stuff1 (msg_state==1);
msg_queue.enq(debug_write_requests);
msg_state <= 2;
endrule
rule debug_stuff2 (msg_state==2);
msg_queue.enq(debug_drain_sorter_valid);
msg_state <= 3;
endrule
rule debug_stuff3 (msg_state==3);
msg_queue.enq(debug_write_to_mem);
msg_state <= 4;
endrule
rule debug_stuff4 (msg_state==4);
msg_queue.enq(debug_write_to_sort_tree);
msg_state <= 5;
endrule
rule debug_stuff5 (msg_state==5);
msg_queue.enq(debug_write_eos_to_sort_tree);
msg_state <= 6;
endrule
rule debug_stuff6 (msg_state==6);
msg_queue.enq(debug_write_eos_from_sort_tree);
msg_state <= 7;
endrule
rule debug_stuff7 (msg_state==7);
msg_queue.enq(debug_write_eos_first);
msg_state <= 8;
endrule
rule debug_stuff8 (msg_state==8);
msg_queue.enq(debug_write_eos_second);
msg_state <= 9;
endrule
rule first_stage_reserve_a(!done &&
iter==0 &&
read_res_count > 0 &&
tok_info[res_count] > 1 );
res_count <= res_count - 1;
pending_first_res_count.enq(res_count);
pending_first_read_res_count.enq(truncate(read_res_count));
if(`Debug) $display("first_stage_reserve %d", res_count);
// reached the end of a 64 element block, decrement the number
// of 64 element blocks remaining
if (res_count == 0)
read_res_count <= read_res_count - 1;
endrule
rule first_stage_reserve_b (!done &&
iter==0);
// reserve 1 slot for queue res_count
// reserve 1 slot for corresponding eos
sort_tree.inStream.putDeqTok(pending_first_res_count.first(),2);
pending_first_res_count.deq();
pending_pending_reserve.enq(pending_first_res_count.first());
endrule
rule first_stage_reserve_c (!done &&
iter==0);
pending_first_read_res_count.deq();
pending_pending_reserve.deq();
// check if we've completed one burst's worth
if((truncate(pending_pending_reserve.first())&rpmr_mask) == 0)
begin
if(`Debug) $display("first_stage_reserve block: %d, idx %d",
pending_first_read_res_count.first(),
pending_pending_reserve.first());
fsfifo.enq(?);
end
endrule
// once rpmr kmerge slots have been reserved, make a burst request
rule first_stage_read_req (!done &&
iter == 0);
let new_read_req_count = read_req_count - rpmr;
fsfifo.deq(); // as long as rsfifo has something
debug_read_requests <= debug_read_requests+1;
extMem.read[readpt].readReq(zeroExtend(array_len-read_req_count)*(recwid/32));
read_req_count <= new_read_req_count;
if(`Debug) $display("first_stage_read_req %d", new_read_req_count);
endrule
// get the records returned from memory and feed the sort_tree
rule first_stage_read_resp (!done &&
iter == 0);
// enque data and eos tokens on alterntaing cycles
read_eos <= !read_eos;
if (read_eos)
begin
debug_write_eos_first <= debug_write_eos_first + 1;
put_rec_fifo.enq(tuple2(read_count, tagged Invalid));
read_count <= read_count - 1;
if(`Debug) $display("first_stage_read_resp eos %d", read_count);
end
else
begin
let a <- extMem.read[readpt].read();
let mask <- aes_cores.get_next();
put_rec_fifo.enq(tuple2(read_count, tagged Valid (a^mask)));
if(`Debug) $display("FIRST first_stage_read_resp idx %h, val %h xor %h",
read_count, a,a^mask);
end
endrule
rule drain_sorter (True);
let data <- sort_tree.getRecord();
if(isValid(data))
begin
debug_drain_sorter_valid <= debug_drain_sorter_valid+1;
out_buff.enq(unpack(fromMaybe(?, data)));
out_buff_cnt <= out_buff_cnt + 1;
if (out_buff_cnt == maxBound) // need a new write request
wrfifo.enq(?);
if(`Debug) $display("drain_sorter_finish");
end
else
begin
debug_write_eos_from_sort_tree <= debug_write_eos_from_sort_tree + 1;
// we just dequeued an end of stream token, and
// don't need to write that out to memory
if(`Debug) $display("drain_sorter_finish eos");
end
endrule
rule write_command (True);
Bit#(AddrWidth) write_addr = zeroExtend(write_base_addr - write_req_count)*(recwid/32);
wrfifo.deq();
debug_write_requests <= debug_write_requests+1;
extMem.write[writept].writeReq(write_addr);
write_req_count <= write_req_count - rpmr;
if(`Debug) $display("write_command %h",write_addr);
endrule
rule write_to_mem (True);
//TODO: we need to re-encrypt the data on the last pass!
out_buff.deq();
debug_write_to_mem <= debug_write_to_mem+1;
if(last)
begin
let mask <- aes_cores.get_next();
extMem.write[writept].write(out_buff.first()^mask);
if(`Debug) $display("LAST write_to_mem write_count %h, write_val %h xor %h",
write_count,out_buff.first(),out_buff.first()^mask);
end
else
begin
extMem.write[writept].write(out_buff.first());
if(`Debug) $display("write_to_mem write_count %h, write_val %h",
write_count,out_buff.first());
end
if(write_count == 1)
begin
write_base_addr <= write_base_addr ^ truncate(bank_mask);
write_count <= array_len;
write_req_count <= array_len;
set_next_stage <= True;
set_ptr_count <= write_base_addr; // last write this iter
set_count <= 63;
iter <= iter+1;
finish_stage <= replicate(False);
if (`Debug) $display("done array, write_base_addr=%x", write_base_addr);
ssl <= ssl << 6;
nssl <= nssl << 6;
nss <= (nss <= 64) ? 1 : (nss>>6);
end
else
write_count <= write_count - 1;
endrule
rule setup_stream_stage(!done &&
iter > 0 &&
set_next_stage );
if(!debug_setup_stream_stage)
begin
set_count <= set_count - 1;
if (set_count == 0)
set_next_stage <= False;
else
debug_setup_stream_stage <= True;
if(nss==1)
begin
done <= True;
end
else
begin
let a = rsp_offsets.sub(set_count);
let new_set_ptr_count = set_ptr_count - zeroExtend(ssl);
let chk = zeroExtend(63-set_count) >= nss;
// set_ptr_count contains an offset in # records with the
// high bit indicating a bank select. (crying out for strong typing!!!)
set_ptr_count <= new_set_ptr_count;
base_ptrs.upd(set_count, chk ? 0 : set_ptr_count);
req_offsets.upd(set_count, chk ? 0 : zeroExtend(ssl));
rsp_offsets.upd(set_count, chk ? 0 : zeroExtend(ssl));
eos_lefts.upd(set_count,(nss<kmerges) ? 1 : nss>>6); // number of substream / 64
if (`Debug) $display("%d base %x, req_offset %x, rsp_offset %x, eos_left %x",
set_count,
set_ptr_count,
(chk ? 0 : ssl),
(chk ? 0 : ssl),
((nss < kmerges) ? 1 : nss>>6));
end
if(nss<=kmerges)
last <= True;
end
else
begin
debug_setup_stream_stage <= False;
// this is OK for all but the largest size
// 12 bits
Bit#(12) eos_left = truncate(eos_lefts.sub(set_count+1));
// 12 bits
Bit#(12) bp = truncate(base_ptrs.sub(set_count+1)>>6);
// 4 bits -- 2nd stage, only about 7th bit
Bit#(4) req_off = truncate(req_offsets.sub(set_count+1)>>6);
let rv = {req_off, bp, eos_left};
//msg_queue.enq(zeroExtend(rv));
end
endrule
function Bool rdy_for_requests(Bit#(sz) x, Bool y);
return (x >= rpmr) && !y; // also check for enough for eos
endfunction
function Tuple2#(Bool,a) first_possible(Tuple2#(Bool,a) fst,
Tuple2#(Bool,a) snd);
return tpl_1(fst) ? fst : snd;
endfunction
rule schedule_read_request (!done &&
iter > 0 &&
!set_next_stage &&
!pending_read_req);
Vector#(KMerges, Bool) pred = zipWith(rdy_for_requests,
sort_tree.inStream.getTokInfo,
finish_stage);
Vector#(KMerges, KMask) idxs = genWith(fromInteger);
let vec = zip(pred, idxs);
let res = fold(first_possible,vec);
rsfifo.enq(res);
match {.bv,.idx} = res;
if (`Debug) $display("schedule_read_requests %d, %d", bv, idx);
if (`Debug) $display(" tok[%d] %d, ",idx,sort_tree.inStream.getTokInfo[idx]);
if (`Debug) $display("finish[%d] %d, ",idx,finish_stage[idx]);
endrule
// Why do they run when we are setting table?
rule read_request_a (!done && iter > 0);
rsfifo.deq();
match {.bv,.idx} = rsfifo.first();
if(bv)
begin
pending_read_req <= True;
let base_ptr = base_ptrs.sub(idx);
let new_base_ptr = base_ptr - zeroExtend(nssl);
let req_offset = req_offsets.sub(idx);
let req_addr = zeroExtend(base_ptr - req_offset)*(recwid/32);
let eos_left = eos_lefts.sub(idx);
let new_eos_left = eos_left - 1;
let need_eos = req_offset == 0;
let new_req_offset = (need_eos) ? zeroExtend(ssl) : req_offset - rpmr;
let rs_toks = (need_eos) ? 1 : rpmr;
let is_fin_stage = eos_left==1;
pending_req_idx <= idx;
pending_req_new_base_ptr <= new_base_ptr;
pending_req_req_addr <= req_addr;
pending_req_new_eos_left <= new_eos_left;
pending_req_need_eos <= need_eos;
pending_req_new_req_offset <= new_req_offset;
pending_req_rs_toks <= rs_toks;
pending_req_is_fin_stage <= is_fin_stage;
if (`Debug) $display("read_requests %d, %d", bv, idx);
end
endrule
rule read_request_b (!done && iter>0 && pending_read_req);
pending_read_req <= False;
let idx = pending_req_idx;
let new_base_ptr = pending_req_new_base_ptr;
let req_addr = pending_req_req_addr;
let new_eos_left = pending_req_new_eos_left;
let need_eos = pending_req_need_eos;
let new_req_offset = pending_req_new_req_offset;
let rs_toks = pending_req_rs_toks;
let is_fin_stage = pending_req_is_fin_stage;
if (need_eos)
begin
finish_stage <= update(finish_stage,idx,is_fin_stage);
eos_lefts.upd(idx,new_eos_left);
base_ptrs.upd(idx,new_base_ptr);
if(`Debug) $display("eos_requests %d is_last_eos %d",
idx, is_fin_stage);
end
else
begin
debug_read_requests <= debug_read_requests+1;
extMem.read[readpt].readReq(req_addr);
if(`Debug) $display("read_requests idx %d, addr %x",
idx, req_addr);
end
rdfifo.enq(idx);
req_offsets.upd(idx, new_req_offset);
sort_tree.inStream.putDeqTok(idx,rs_toks);
if(`Debug) $display("read_requests idx %d, new_req_offset %x, deqTok %d",
idx, new_req_offset, rs_toks);
endrule
rule read_resp (!done &&
iter > 0 &&
!set_next_stage);
let idx = rdfifo.first();
let rsp_offset = rsp_offsets.sub(idx);
let need_eos = rsp_offset == 0;
let new_rsp_offset = (need_eos) ? zeroExtend(ssl) : rsp_offset - 1;
RPMRMask rpmr_one = 1;
if (((truncate(rsp_offset)&rpmr_mask) == rpmr_one)||need_eos)
rdfifo.deq();
rsp_offsets.upd(idx,new_rsp_offset);
if(need_eos)
begin
debug_write_eos_second <= debug_write_eos_second + 1;
put_rec_fifo.enq(tuple2(idx, tagged Invalid));
if(`Debug) $display("read_resps eos %x", idx);
end
else
begin
let val <- extMem.read[readpt].read();
put_rec_fifo.enq(tuple2(idx, tagged Valid val));
if(`Debug) $display("read_resps idx %x val %x", idx, val);
end
endrule
rule put_rec (True);
put_rec_fifo.deq();
match {.idx, .val} = put_rec_fifo.first();
if(isValid(val))
debug_write_to_sort_tree <= debug_write_to_sort_tree+1;
else
debug_write_eos_to_sort_tree <= debug_write_eos_to_sort_tree+1;
sort_tree.inStream.putRecord(idx, val);
endrule
method Action doSort(Bit#(5) len) if (done);
$display("doSort");
RecAddr array_sz = 1<<len;
let num_blocks = array_sz>>6; // no. 64-record blocks we need for first stage = (2^len / 64)
let block_sz = 63; // 64 to go
read_res_count <= num_blocks;
res_count <= 63;
read_req_count <= array_sz;
read_count <= 63;
read_eos <= False;
write_count <= array_sz;
write_base_addr <= array_sz ^ truncate(bank_mask);
write_req_count <= array_sz;
out_buff_cnt <= 0;
log_len <= len;
iter <= 0;
done <= False;
array_len <= array_sz;
nss <= array_sz;
ssl <= 1;
nssl <= 1<<6;
aes_cores.start(len);
if(len==6)
last <= True;
else
last <= False;
endmethod
method Bool finished();
return done;
endmethod
interface msgs = fifoToGet(msg_queue);
endmodule
module mkTH ();
PLBMaster plbmaster <- mkPLBMasterDummy;
ExternalMemory extMem <- mkExternalMemory(plbmaster);
Clock clk <- exposeCurrentClock;
Reset rst <- exposeCurrentReset;
Control cnt <- mkControl(extMem, clk, rst);
Bit#(32) left_bank = (fromInteger(valueOf(MemBankSelector))>>2);
Bit#(32) right_bank = 0;
Bit#(32) bank_masks[13] = {left_bank,
right_bank,
right_bank,
right_bank,
right_bank,
right_bank,
right_bank,
left_bank,
left_bank,
left_bank,
left_bank,
left_bank,
left_bank};
String dump_file_names[13] = {"sorted_array_6.txt",
"sorted_array_7.txt",
"sorted_array_8.txt",
"sorted_array_9.txt",
"sorted_array_10.txt",
"sorted_array_11.txt",
"sorted_array_12.txt",
"sorted_array_13.txt",
"sorted_array_14.txt",
"sorted_array_15.txt",
"sorted_array_16.txt",
"sorted_array_17.txt",
"sorted_array_18.txt"};
RegFile#(Bit#(18), Record) resmem <- mkRegFileFullLoad("sorted.hex");
let recwid = fromInteger(valueOf(RecordWidth));
let rpmr = fromInteger(valueOf(RecordsPerMemRequest));
RPMRMask rpmr_msk = 0;
let log_len = `LogArrayLen; // this should be defined at the command line
let bank_mask = bank_masks[log_len-6];
let dump_file = dump_file_names[log_len-6];
Reg#(Bit#(64)) cycleCnt <- mkReg(0);
Reg#(Bit#(64)) startTime <- mkReg(0);
Reg#(Bit#(32)) count <- mkReg(0);
Reg#(int) state <- mkReg(0);
Reg#(Bool) need_req <- mkReg(True);
Reg#(Bit#(18)) output_count <- mkReg(0);
Reg#(Bit#(18)) req_count <- mkReg(0);
let fh <- mkReg(InvalidFile) ;
rule incrCycle (True);
cycleCnt <= cycleCnt + 1;
endrule
rule open_file (state == 0 );
$display("sorting an array of log_len %d", log_len);
File lfh <- $fopen( dump_file, "w" ) ;
if ( lfh == InvalidFile )
begin
$display("cannot open %s", dump_file);
$finish(0);
end
fh <= lfh;
state <= 2;
endrule
rule disp_msg (True);
let a <- cnt.msgs.get();
$display("MESSAGE from control %h",a);
endrule
rule disp_mem((state==4)&&need_req);
extMem.read[0].readReq(bank_mask|{zeroExtend(req_count),5'b00});
req_count <= req_count + 1;
if(req_count + 1 == (1<<(log_len - 2)))
begin
need_req <= False;
end
endrule
rule check(state == 4);
let data <- extMem.read[0].read();
output_count <= output_count + 1;
if(data != resmem.sub(output_count))
begin
$display("Error at %d: got %h expected %h",output_count, data, resmem.sub(output_count));
$fwrite(fh, "Error at %d: got %h expected %h",output_count, data, resmem.sub(output_count));
$finish;
end
if(output_count + 1 == (1<<log_len))
begin
$display("PASS Size %d!!!!", log_len);
$fwrite(fh, "PASS Size %d!!!!", log_len);
$finish;
end
endrule
rule start_sort(state==2);
cnt.doSort(log_len);
state <= 3;
startTime <= startTime + 1;
endrule
rule disp_orig_a((state==3)&&cnt.finished());
state <= 4;
$display("Total cycles %d",cycleCnt - startTime);
endrule
rule finish(state==5);
$finish;
endrule
endmodule
1.1 cryptosorter/memocodeDesignContest2008/ctrl/mkTH.sched
http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/ctrl/mkTH.sched?rev=1.1&content-type=text/x-cvsweb-markup
Index: mkTH.sched
===================================================================
=== Generated schedule for mkTH ===
Rule schedule
-------------
Rule: finish
Predicate: state == 32'd5
Blocking rules: (none)
Rule: disp_orig_a
Predicate: (state == 32'd3) && cnt_done
Blocking rules: (none)
Rule: start_sort
Predicate: cnt_aes_cores_commandQ.RDY_enq &&
cnt_done && cnt_aes_cores_commandQ.notFull &&
(state == 32'd2)
Blocking rules: (none)
Rule: check
Predicate: (! extMem_readRespFIFO.first) &&
plbmaster_plbMasterCommand.i_notEmpty &&
(plbmaster_plbMasterCommand.first[31:30] == 2'd1) &&
(! plbmaster_jitter2) &&
extMem_readRespFIFO.i_notEmpty &&
(state == 32'd4)
Blocking rules: (none)
Rule: disp_mem
Predicate: extMem_reqSnapshot.notFull && (state == 32'd4) && need_req
Blocking rules: (none)
Rule: disp_msg
Predicate: cnt_msg_queue.i_notEmpty
Blocking rules: (none)
Rule: open_file
Predicate: state == 32'd0
Blocking rules: (none)
Rule: incrCycle
Predicate: True
Blocking rules: (none)
Rule: cnt_put_rec
Predicate: cnt_sort_tree.RDY_inStream_putRecord && cnt_put_rec_fifo.i_notEmpty
Blocking rules: (none)
Rule: cnt_read_resp
Predicate: cnt_put_rec_fifo.i_notFull &&
cnt_rdfifo.i_notEmpty &&
((cnt_rsp_offsets.sub(cnt_rdfifo.first) == 20'd0) ||
((! extMem_readRespFIFO.first) &&
plbmaster_plbMasterCommand.i_notEmpty &&
(plbmaster_plbMasterCommand.first[31:30] == 2'd1) &&
(! plbmaster_jitter2) &&
extMem_readRespFIFO.i_notEmpty)) &&
(! cnt_done) && (! (cnt_iter == 3'd0)) && (! cnt_set_next_stage)
Blocking rules: check, cnt_write_to_mem
Rule: cnt_read_request_b
Predicate: cnt_sort_tree.RDY_inStream_putDeqTok &&
cnt_rdfifo.i_notFull &&
(cnt_pending_req_need_eos || extMem_reqSnapshot.notFull) &&
(! cnt_done) && (! (cnt_iter == 3'd0)) && cnt_pending_read_req
Blocking rules: disp_mem, cnt_read_request_a
Rule: cnt_read_request_a
Predicate: cnt_rsfifo.i_notEmpty && (! cnt_done) && (! (cnt_iter == 3'd0))
Blocking rules: (none)
Rule: cnt_schedule_read_request
Predicate: cnt_sort_tree.RDY_inStream_getTokInfo && cnt_rsfifo.i_notFull &&
(! cnt_done) && (! (cnt_iter == 3'd0)) && (! cnt_set_next_stage) &&
(! cnt_pending_read_req)
Blocking rules: (none)
Rule: cnt_setup_stream_stage
Predicate: (! cnt_done) && (! (cnt_iter == 3'd0)) && cnt_set_next_stage
Blocking rules: cnt_read_request_b, cnt_write_to_mem
Rule: cnt_write_to_mem
Predicate: (! extMem_writeFIFO.first) &&
plbmaster_plbMasterCommand.i_notEmpty &&
(! (plbmaster_plbMasterCommand.first[31:30] == 2'd0)) &&
(! (plbmaster_plbMasterCommand.first[31:30] == 2'd1)) &&
(plbmaster_jitter1 == 2'd0) &&
cnt_out_buff_fifo.i_notEmpty &&
extMem_writeFIFO.i_notEmpty &&
((! cnt_last) ||
(cnt_aes_cores_respQ.RDY_first &&
cnt_aes_cores_respQ.RDY_deq && cnt_aes_cores_respQ.notEmpty))
Blocking rules: (none)
Rule: cnt_write_command
Predicate: cnt_wrfifo.i_notEmpty && extMem_reqSnapshot.notFull
Blocking rules: (none)
Rule: cnt_drain_sorter
Predicate: cnt_sort_tree.RDY_getRecord &&
cnt_out_buff_fifo.i_notFull &&
((! (cnt_out_buff_cnt == 3'd7)) || cnt_wrfifo.i_notFull)
Blocking rules: (none)
Rule: cnt_first_stage_read_resp
Predicate: cnt_put_rec_fifo.i_notFull &&
(cnt_read_eos ||
(cnt_aes_cores_respQ.RDY_first &&
cnt_aes_cores_respQ.RDY_deq &&
(! extMem_readRespFIFO.first) &&
plbmaster_plbMasterCommand.i_notEmpty &&
(plbmaster_plbMasterCommand.first[31:30] == 2'd1) &&
(! plbmaster_jitter2) &&
cnt_aes_cores_respQ.notEmpty &&
extMem_readRespFIFO.i_notEmpty)) &&
(! cnt_done) && (cnt_iter == 3'd0)
Blocking rules: check, cnt_write_to_mem
Rule: cnt_first_stage_read_req
Predicate: extMem_reqSnapshot.notFull && cnt_fsfifo.i_notEmpty &&
(! cnt_done) && (cnt_iter == 3'd0)
Blocking rules: disp_mem
Rule: cnt_first_stage_reserve_c
Predicate: cnt_pending_first_read_res_count.i_notEmpty &&
cnt_pending_pending_reserve.i_notEmpty &&
((! (cnt_pending_pending_reserve.first[2:0] == 3'd0)) ||
cnt_fsfifo.i_notFull) &&
(! cnt_done) && (cnt_iter == 3'd0)
Blocking rules: (none)
Rule: cnt_first_stage_reserve_b
Predicate: cnt_sort_tree.RDY_inStream_putDeqTok &&
cnt_pending_first_res_count.i_notEmpty &&
cnt_pending_pending_reserve.i_notFull &&
(! cnt_done) && (cnt_iter == 3'd0)
Blocking rules: (none)
Rule: cnt_first_stage_reserve_a
Predicate: cnt_pending_first_res_count.i_notFull &&
cnt_pending_first_read_res_count.i_notFull &&
cnt_sort_tree.RDY_inStream_getTokInfo &&
(! cnt_done) && (cnt_iter == 3'd0) &&
(! (cnt_read_res_count == 20'd0)) &&
(! (((cnt_res_count == 6'd0)
? cnt_sort_tree.inStream_getTokInfo[4:0]
: ((cnt_res_count == 6'd1)
? cnt_sort_tree.inStream_getTokInfo[9:5]
: ((cnt_res_count == 6'd2)
? cnt_sort_tree.inStream_getTokInfo[14:10]
: ((cnt_res_count == 6'd3)
? cnt_sort_tree.inStream_getTokInfo[19:15]
: ((cnt_res_count == 6'd4)
? cnt_sort_tree.inStream_getTokInfo[24:20]
: ((cnt_res_count == 6'd5)
? cnt_sort_tree.inStream_getTokInfo[29:25]
: ((cnt_res_count == 6'd6)
? cnt_sort_tree.inStream_getTokInfo[34:30]
: ((cnt_res_count == 6'd7)
? cnt_sort_tree.inStream_getTokInfo[39:35]
: ((cnt_res_count == 6'd8)
? cnt_sort_tree.inStream_getTokInfo[44:40]
: ((cnt_res_count == 6'd9)
? cnt_sort_tree.inStream_getTokInfo[49:45]
: ((cnt_res_count == 6'd10)
? cnt_sort_tree.inStream_getTokInfo[54:50]
: ((cnt_res_count == 6'd11)
? cnt_sort_tree.inStream_getTokInfo[59:55]
: ((cnt_res_count == 6'd12)
? cnt_sort_tree.inStream_getTokInfo[64:60]
: ((cnt_res_count ==
6'd13)
? cnt_sort_tree.inStream_getTokInfo[69:65]
: ((x__h66583(...) ==
6'd14)
? cnt_sort_tree_inStream_getTokInfo____d1471(...)[74:70]
: (cnt_res_count_87_EQ_15___d1003(...)
? cnt_sort_tree_inStream_getTokInfo__81_BITS_79__ETC___d1341(...)
: IF_cnt_res_count_87_EQ_16_004_THEN_cnt_sort_tr_ETC___d1099(...))))))))))))))))) <=
5'd1))
Blocking rules: (none)
Rule: cnt_debug_stuff8
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd8)
Blocking rules: (none)
Rule: cnt_debug_stuff7
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd7)
Blocking rules: (none)
Rule: cnt_debug_stuff6
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd6)
Blocking rules: (none)
Rule: cnt_debug_stuff5
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd5)
Blocking rules: (none)
Rule: cnt_debug_stuff4
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd4)
Blocking rules: (none)
Rule: cnt_debug_stuff3
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd3)
Blocking rules: (none)
Rule: cnt_debug_stuff2
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd2)
Blocking rules: (none)
Rule: cnt_debug_stuff1
Predicate: cnt_msg_queue.i_notFull && (cnt_msg_state == 32'd1)
Blocking rules: (none)
Rule: cnt_debug_stuff0
Predicate: cnt_msg_queue.i_notFull && (cnt_tic_counter == 30'd0)
Blocking rules: cnt_debug_stuff1,
cnt_debug_stuff2,
cnt_debug_stuff3,
cnt_debug_stuff4,
cnt_debug_stuff5,
cnt_debug_stuff6,
cnt_debug_stuff7,
cnt_debug_stuff8
Rule: cnt_tic_toc
Predicate: True
Blocking rules: (none)
Rule: cnt_aes_cores_respRule
Predicate: cnt_aes_cores_respQ.RDY_enq &&
((cnt_aes_cores_ptr == 32'd0)
? cnt_aes_cores_cores.RDY_decrypt
: ((! (cnt_aes_cores_ptr == 32'd1)) ||
cnt_aes_cores_cores_1.RDY_decrypt)) &&
((cnt_aes_cores_ptr == 32'd0)
? cnt_aes_cores_cores.RDY_get_result
: ((! (cnt_aes_cores_ptr == 32'd1)) ||
cnt_aes_cores_cores_1.RDY_get_result)) &&
(! (cnt_aes_cores_iter == 2'd0))
Blocking rules: (none)
Rule: cnt_aes_cores_startRule
Predicate: cnt_aes_cores_cores.RDY_decrypt &&
cnt_aes_cores_cores_1.RDY_decrypt &&
cnt_aes_cores_commandQ.RDY_first &&
cnt_aes_cores_commandQ.RDY_deq &&
(cnt_aes_cores_iter == 2'd0)
Blocking rules: (none)
Rule: extMem_chooseReq
Predicate: extMem_reqSnapshot.i_notEmpty &&
((((! extMem_reqSnapshot.first[32]) || extMem_nextToSend) &&
(! extMem_reqSnapshot.first[65])) ||
(plbmaster_stall_fifo.i_notFull &&
(((extMem_reqSnapshot.first[32] && (! extMem_nextToSend))
? extMem_reqSnapshot.first[31:30] == 2'd1
: (extMem_reqSnapshot.first[64:63] == 2'd1))
? extMem_readRespFIFO.i_notFull
: extMem_writeFIFO.i_notFull)))
Blocking rules: (none)
Rule: extMem_processReqs
Predicate: ((! extMem_readReqs.whas) && (! extMem_writeReqs.whas)) ||
extMem_reqSnapshot.i_notFull
Blocking rules: (none)
Rule: plbmaster_xfer
Predicate: plbmaster_plbMasterCommand.i_notFull &&
plbmaster_stall_fifo.i_notEmpty &&
(plbmaster_stall == 5'd0)
Blocking rules: (none)
Rule: plbmaster_decr_stall
Predicate: ! (plbmaster_stall == 5'd0)
Blocking rules: (none)
Rule: plbmaster_toggle
Predicate: True
Blocking rules: (none)
Logical execution order: cnt_schedule_read_request,
cnt_read_request_a,
finish,
disp_mem,
disp_orig_a,
check,
disp_msg,
open_file,
incrCycle,
cnt_first_stage_reserve_c,
cnt_first_stage_reserve_b,
cnt_first_stage_reserve_a,
cnt_setup_stream_stage,
cnt_debug_stuff8,
cnt_read_resp,
cnt_debug_stuff7,
cnt_first_stage_read_resp,
cnt_debug_stuff6,
cnt_debug_stuff5,
cnt_debug_stuff4,
cnt_put_rec,
cnt_debug_stuff3,
cnt_debug_stuff2,
cnt_drain_sorter,
cnt_debug_stuff1,
cnt_write_command,
cnt_debug_stuff0,
cnt_read_request_b,
cnt_first_stage_read_req,
cnt_write_to_mem,
start_sort,
cnt_tic_toc,
cnt_aes_cores_respRule,
cnt_aes_cores_startRule,
extMem_chooseReq,
extMem_processReqs,
plbmaster_xfer,
plbmaster_decr_stall,
plbmaster_toggle
====================================
1.1 cryptosorter/memocodeDesignContest2008/ctrl/mkTester.bsv
http://www.opencores.org/cvsweb.shtml/cryptosorter/memocodeDesignContest2008/ctrl/mkTester.bsv?rev=1.1&content-type=text/x-cvsweb-markup
Index: mkTester.bsv
===================================================================
/*
Copyright (c) 2008 MIT
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Author: Myron King
*/
import Memocode08Types ::*;
import ExternalMemory ::*;
import PLBMasterDummy ::*;
import Interfaces ::*;
import StmtFSM ::*;
import GetPut ::*;
import Vector ::*;
import FIFO ::*;
import Four2OneMerger ::*;
typedef Bit#(TLog#(RecordsPerMemRequest)) RpmrBits;
module mkEMTB (Empty);
let recwid = fromInteger(valueOf(RecordWidth));
let rpmr = fromInteger(valueOf(RecordsPerMemRequest));
RpmrBits rpmr_msk = 0;
PLBMaster dummy <- mkPLBMasterDummy();
ExternalMemory extMem <- mkExternalMemory(dummy);
Reg#(Bit#(32)) count <- mkReg(0);
Reg#(int) state <- mkReg(0);
Reg#(Bool) need_req <- mkReg(True);
rule get_mem((state==0)&&!need_req);
RpmrBits tr = truncate(count+1);
if(truncate(count+1)==rpmr_msk)
need_req <= True;
let a <- extMem.read[0].read();
$display(a);
count <= count+1;
if(count+1==8192)
state<=1;
endrule
rule req_mem((state==0)&&need_req);
extMem.read[0].readReq(count*recwid/8);
need_req <= False;
endrule
rule fin(state==1);
$finish();
endrule
endmodule
module mk421TB (Empty);
Four2One merger <- mkFour2One();
Reg#(Bool) started <- mkReg(False);
Stmt feeder =
(seq
merger.in[0].put(0);
merger.in[1].put(0);
merger.in[2].put(0);
merger.in[3].put(0);
merger.in[0].put(1);
merger.in[1].put(2);
merger.in[2].put(3);
merger.in[3].put(4);
merger.in[0].put(4);
merger.in[1].put(3);
merger.in[2].put(2);
merger.in[3].put(1);
merger.in[0].put(4);
merger.in[1].put(3);
merger.in[2].put(1);
merger.in[3].put(2);
endseq);
FSM ffsm <- mkFSM(feeder);
rule start (!started);
$display("start merge");
ffsm.start();
started <= True;
endrule
rule get_stuff (True);
let a <- merger.out.get();
$display(a);
endrule
endmodule
|
 |