X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ships%2FMemory.ship;h=2d1d6f15dbe6abc7fe5b7e02c51d47ebcdfdf943;hb=cbafca81451a452015ea365b3546c3bc0ac7bdbd;hp=135102afc0c1f20e2c829eca80bf4d0913787bad;hpb=7f4958fbb5eb13487bbfaf8411765fe997ae2ae7;p=fleet.git diff --git a/ships/Memory.ship b/ships/Memory.ship index 135102a..2d1d6f1 100644 --- a/ships/Memory.ship +++ b/ships/Memory.ship @@ -12,7 +12,25 @@ data out: out The {\tt Memory} ship represents an interface to a storage space, which can be used to read from it or write to it. This storage space -might be a fast on-chip cache, off chip DRAM, or perhaps even a disk drive. +might be a fast on-chip cache, off chip DRAM, or perhaps even a disk +drive. + +Generally, distinct {\tt Memory} ships do not access the same backing +storage, although this is not strictly prohibited. + +Each {\tt Memory} ship may have multiple {\it interfaces}, numbered +starting with {\tt 0}. Each interface may have any subset of the +following docks: {\tt inCBD}, {\tt inAddrRead}, {\tt inAddrWrite}, +{\tt inDataWrite}, and {\tt out}. If {\tt inCBD} or {\tt inAddrRead} +is present on an interface, then {\tt out} must be present as well. +If {\tt inAddrWrite} is present then {\tt inDataWrite} must be present +as well. + +Each interface serializes the operations presented to it; this means +that an interface with both read and write capabilities will not be +able to read and write concurrently. Instead, a {\tt Memory} ship +with the ability to read and write concurrently should have two +interfaces, one which is read-only and one which is write-only. There may be multiple {\tt Memory} ships which interface to the same physical storage space. An implementation of Fleet must provide @@ -44,7 +62,8 @@ inCount=size}. \subsection*{Reading} When a word is delivered to {\tt inAddrRead}, the word residing in -memory at that address is provided at {\tt out}. +memory at that address is provided at {\tt out}. The {\tt c-flag} at +the {\tt out} port is set to zero. \subsection*{Writing} @@ -52,7 +71,8 @@ When a word is delivered to {\tt inAddrWrite} and {\tt inDataWrite}, the word at {\tt inDataWrite} is written to the address specified by {\tt inAddrWrite}. Once the word is successfully committed to memory, the value {\tt inAddr+inStride} is provided at {\tt out} (that is, the -address of the next word to be written). +address of the next word to be written). The {\tt c-flag} at +the {\tt out} port is set to one. \subsection*{To Do} @@ -85,55 +105,28 @@ sequence guarantee problem mentioned in the previous paragraph. } mem[addr] = val; } - - private long stride = 0; - private long count = 0; - private long addr = 0; - private boolean writing = false; - private Queue toDispatch = new LinkedList(); + public void reset() { + super.reset(); + mem = new long[0]; + toDispatch.clear(); + } public void service() { - if (toDispatch.size() > 0) { - //if (!box_out.readyForDataFromShip()) return; - //box_out.addDataFromShip(toDispatch.remove()); - getInterpreter().dispatch(getInterpreter().readInstruction(toDispatch.remove(), getDock("out"))); + if (!box_out.readyForDataFromShip()) return; + box_out.addDataFromShip(toDispatch.remove()); } - - if (box_inCBD.dataReadyForShip() && box_out.readyForDataFromShip()) { + if (box_inCBD.dataReadyForShip()) { long val = box_inCBD.removeDataForShip(); - long addr = val >> 6; - long size = val & 0x3f; + long addr = ((Interpreter)getFleet()).CBD_OFFSET.getval(val); + long size = ((Interpreter)getFleet()).CBD_SIZE.getval(val); for(int i=0; i 0) { - if (writing) { - if (box_inDataWrite.dataReadyForShip() && box_out.readyForDataFromShip()) { - writeMem((int)addr, box_inDataWrite.removeDataForShip()); - box_out.addDataFromShip(0); - count--; - addr += stride; - } - } else { - if (box_out.readyForDataFromShip()) { - box_out.addDataFromShip(readMem((int)addr)); - count--; - addr += stride; - } - } - - } else if (box_inAddrRead.dataReadyForShip()) { - addr = box_inAddrRead.removeDataForShip(); - stride = 0; - count = 1; - writing = false; - - } else if (box_inAddrWrite.dataReadyForShip()) { - addr = box_inAddrWrite.removeDataForShip(); - stride = 0; - count = 1; - writing = true; + } else if (box_inAddrWrite.dataReadyForShip() && box_inDataWrite.dataReadyForShip() && box_out.readyForDataFromShip()) { + writeMem((int)box_inAddrWrite.removeDataForShip(), box_inDataWrite.removeDataForShip()); + box_out.addDataFromShip(0,true); + } else if (box_inAddrRead.dataReadyForShip() && box_out.readyForDataFromShip()) { + box_out.addDataFromShip(readMem((int)box_inAddrRead.removeDataForShip()),false); } } @@ -141,106 +134,112 @@ sequence guarantee problem mentioned in the previous paragraph. == FPGA ============================================================== - wire [(`DATAWIDTH-1):0] out1; - wire [(`DATAWIDTH-1):0] out2; - - reg [(`CODEBAG_SIZE_BITS-1):0] counter; - reg [(`BRAM_ADDR_WIDTH-1):0] cursor; - initial cursor = 0; - initial counter = 0; + `define BRAM_ADDR_WIDTH 14 + `define BRAM_SIZE (1<<(`BRAM_ADDR_WIDTH)) - reg write_flag; - reg dispatching_cbd; - initial write_flag = 0; - initial dispatching_cbd = 0; + reg [(`WORDWIDTH-1):0] ram [((`BRAM_SIZE)-1):0]; + reg [(`BRAM_ADDR_WIDTH-1):0] addr1; + reg [(`BRAM_ADDR_WIDTH-1):0] addr2; + reg [(`WORDWIDTH-1):0] out1; + reg [(`WORDWIDTH-1):0] out2; - wire [(`BRAM_ADDR_WIDTH-1):0] addr1; - assign addr1 = write_flag ? inAddrWrite_d[(`DATAWIDTH-1):0] : inAddrRead_d[(`DATAWIDTH-1):0]; - bram14 mybram(clk, rst, write_flag, addr1, cursor, inDataWrite_d, out1, out2); + reg out_w; + reg write_flag; + reg [(`BRAM_ADDR_WIDTH-1):0] cursor; + reg [(`CODEBAG_SIZE_BITS-1):0] counter; - assign out_d_ = dispatching_cbd ? out2 : out1; + assign out_d_ = { out_w, out1 }; + // I use "blocking assignment" here in order to facilitate BRAM inference always @(posedge clk) begin + write_flag = 0; - write_flag <= 0; - - if (!rst) begin + if (rst) begin `reset - cursor <= 0; - counter <= 0; - write_flag <= 0; - dispatching_cbd <= 0; + cursor = 0; + counter = 0; end else begin - write_flag <= 0; - - if (!inAddrRead_r && inAddrRead_a) inAddrRead_a <= 0; - if (!inDataWrite_r && inDataWrite_a) inDataWrite_a <= 0; - if (!inAddrWrite_r && inAddrWrite_a) inAddrWrite_a <= 0; - if (!inCBD_r && inCBD_a) inCBD_a <= 0; - - // assumes we never want a zero-length codebag - if ( inCBD_r && !inCBD_a && !out_r && !out_a) begin - if (!dispatching_cbd) begin - cursor <= inCBD_d[(`INSTRUCTION_WIDTH-1):(`CODEBAG_SIZE_BITS)]; - counter <= 0; - dispatching_cbd <= 1; + `cleanup + + if (counter!=0) begin + if (`out_empty) begin + `fill_out + out_w = 0; + addr1 = cursor; + cursor = cursor + 1; + counter = counter - 1; end - out_r <= 1; - end else if (inCBD_r && out_r && out_a) begin - out_r <= 0; - if (counter != inCBD_d[(`CODEBAG_SIZE_BITS-1):0]) begin - cursor <= cursor + 1; - counter <= counter + 1; - end else begin - inCBD_a <= 1; - counter <= 0; - dispatching_cbd <= 0; - end - end else if (!dispatching_cbd && out_r && out_a) begin out_r <= 0; - end else if (!dispatching_cbd && !out_r && !out_a && inAddrRead_r && !inAddrRead_a) begin - inAddrRead_a <= 1; - out_r <= 1; - - end else if (!dispatching_cbd && !out_r && !out_a && inAddrWrite_r && inDataWrite_r) begin - // timing note: it's okay to set the *_a flags here because *_d will still - // be valid on the *next* cycle, which is all we care about - inAddrWrite_a <= 1; - inDataWrite_a <= 1; - out_r <= 1; - write_flag <= 1; + + end else if (`inCBD_full) begin + cursor = inCBD_d[(`WORDWIDTH-1):(`CODEBAG_SIZE_BITS)]; + counter = inCBD_d[(`CODEBAG_SIZE_BITS-1):0]; + addr1 = cursor; + `drain_inCBD + + end else if (`out_empty && `inAddrRead_full) begin + addr1 = inAddrRead_d[(`WORDWIDTH-1):0]; + `drain_inAddrRead + `fill_out + out_w = 0; + + end else if (`out_empty && `inAddrWrite_full && `inDataWrite_full) begin + write_flag = 1; + `drain_inAddrWrite + `drain_inDataWrite + `fill_out + addr2 = inAddrWrite_d[(`WORDWIDTH-1):0]; + out_w = 1; + end end + + // this must appear at the end of the block, outside of any if..then's + if (write_flag) + ram[addr2] <= inDataWrite_d; + out1 <= ram[addr1]; + out2 <= ram[addr2]; end == Test ============================================================== +// Note: this only tests the read/write interfaces, not the inCBD interface +// FIXME: test c-flag at out dock + // expected output -#expect 12 -#expect 13 -#expect 14 +#expect 10 // ships required in order to run this code #ship debug : Debug #ship memory : Memory -// instructions not in any codebag are part of the "root codebag" -// which is dispatched when the code is loaded +memory.inAddrWrite: + set word=3; + deliver; + deliver; -memory.out: - set ilc=*; collect packet, send; +memory.inDataWrite: + set word=4; + deliver; + set word=10; + deliver; -memory.inCBD: - set word= BOB; +memory.inAddrRead: + recv token; + set word=3; deliver; -BOB: { - debug.in: - set word= 12; deliver; - set word= 13; deliver; - set word= 14; deliver; -} +memory.out: + collect; + collect; + send token to memory.inAddrRead; + collect; + send to debug.in; + +debug.in: + set ilc=*; + recv, deliver; == Constants ========================================================