--- /dev/null
+ship: Memory
+
+== Ports ===========================================================
+data in: inCBD
+data in: inAddr.read
+data in: inAddr.write
+data in: inAddr.readMany
+data in: inAddr.writeMany
+data in: inData
+data in: inStride
+data in: inCount
+
+data out: out
+
+== Fleeterpreter ====================================================
+ private long[] mem = new long[0];
+ public long readMem(int addr) { return mem[addr]; }
+ public void writeMem(int addr, long val) {
+ if (addr >= mem.length) {
+ long[] newmem = new long[addr * 2 + 1];
+ System.arraycopy(mem, 0, newmem, 0, mem.length);
+ mem = newmem;
+ }
+ mem[addr] = val;
+ }
+
+ public void dispatch(int addr, int size) {
+ for(int i=addr; i<addr+size; i++) {
+ Instruction instr = ((Interpreter)getFleet()).readInstruction(readMem(i));
+ ((Interpreter)getFleet()).dispatch(instr, i);
+ }
+ }
+
+ public void boot(byte[] instructions) {
+ Interpreter fleet = (Interpreter)getFleet();
+ // load the iscratch and take note of the 0-address INCBD
+ long launch = 0;
+ for(int i=0; i<instructions.length; i+=6) {
+ long word = 0;
+ for(int j=0; j<6; j++)
+ word = (word << 8) | (instructions[i+j] & 0xff);
+ writeMem(i/6, word);
+ if (i==0) launch = word;
+ }
+
+ // dispatch the 0-address INCBD
+ int base = (int)(launch >> 6);
+ base = base & ~(0xffffffff << 18);
+ int size = (int)launch;
+ size = size & ~(0xffffffff << 6);
+ dispatch(base, size);
+ }
+
+ public void service() {
+ if (box_inCBD.dataReadyForShip()) {
+ long val = box_inCBD.removeDataForShip();
+ long addr = val >> 6;
+ long size = val & 0x3f;
+ dispatch((int)addr, (int)size);
+ }
+ if (box_inAddr.dataReadyForShip() && box_out.readyForItemFromShip()) {
+ Packet packet = box_inAddr.peekPacketForShip();
+ if (packet.destination.getDestinationName().equals("read")) {
+ box_out.addDataFromShip(readMem((int)box_inAddr.removeDataForShip()));
+ } else if (packet.destination.getDestinationName().equals("write") && box_inData.dataReadyForShip()) {
+ writeMem((int)box_inAddr.removeDataForShip(),
+ box_inData.removeDataForShip());
+ box_out.addDataFromShip(0);
+ }
+ }
+ }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+`include "macros.v"
+`define BRAM_ADDR_WIDTH 14
+`define BRAM_DATA_WIDTH `DATAWIDTH
+`define BRAM_NAME dscratch_bram
+`include "bram.inc"
+
+module dscratch (clk,
+ read_addr_r, read_addr_a_, read_addr_d,
+ read_data_r_, read_data_a, read_data_d_,
+ write_addr_r, write_addr_a_, write_addr_d,
+ write_data_r, write_data_a_, write_data_d,
+ write_done_r_, write_done_a, write_done_d_
+ );
+
+ input clk;
+ `input(read_addr_r, read_addr_a, read_addr_a_, [(`DATAWIDTH-1):0], read_addr_d)
+ `output(read_data_r, read_data_r_, read_data_a, [(`DATAWIDTH-1):0], read_data_d_)
+ `defreg(read_data_d_, [(`DATAWIDTH-1):0], read_data_d)
+
+ `input(write_addr_r, write_addr_a, write_addr_a_, [(`DATAWIDTH-1):0], write_addr_d)
+ `input(write_data_r, write_data_a, write_data_a_, [(`DATAWIDTH-1):0], write_data_d)
+ `output(write_done_r, write_done_r_, write_done_a, [(`DATAWIDTH-1):0], write_done_d_)
+ `defreg(write_done_d_, [(`DATAWIDTH-1):0], write_done_d)
+
+ reg bram_we;
+ wire bram_we_;
+ assign bram_we_ = bram_we;
+ wire [(`BRAM_DATA_WIDTH-1):0] bram_read_data;
+ reg [(`BRAM_ADDR_WIDTH-1):0] bram_write_address;
+ wire [(`BRAM_ADDR_WIDTH-1):0] bram_read_address;
+ reg [(`BRAM_DATA_WIDTH-1):0] bram_write_data;
+ wire [(`BRAM_DATA_WIDTH-1):0] bram_write_data_;
+ assign bram_write_data_ = bram_write_data;
+ `BRAM_NAME mybram(clk,
+ bram_we_, bram_write_address,
+ bram_read_address, bram_write_data_,
+ not_connected, bram_read_data);
+
+ reg send_done;
+
+ reg have_read; initial have_read = 0;
+ reg read_pending; initial read_pending = 0;
+ assign bram_read_address = read_addr_d;
+
+ always @(posedge clk) begin
+ bram_we = 0;
+ if (send_done) begin
+ `onwrite(write_done_r, write_done_a)
+ send_done = 0;
+ end
+ end else begin
+ if (!write_addr_r && write_addr_a) write_addr_a = 0;
+ if (!write_data_r && write_data_a) write_data_a = 0;
+ if (write_addr_r && write_data_r) begin
+ write_addr_a = 1;
+ write_data_a = 1;
+ bram_we = 1;
+ send_done = 1;
+ bram_write_address = write_addr_d;
+ bram_write_data = write_data_d;
+ end
+ end
+
+ if (read_pending) begin
+ read_pending <= 0;
+ have_read <= 1;
+ read_data_d <= bram_read_data;
+ end else if (have_read) begin
+ `onwrite(read_data_r, read_data_a)
+ have_read <= 0;
+ end
+ end else begin
+ `onread(read_addr_r, read_addr_a)
+ // ======= Careful with the timing here! =====================
+ // We MUST capture bram_read_data on the very next clock since
+ // read_addr_d is free to change after the next clock
+ // ===========================================================
+ read_pending <= 1;
+ end
+ end
+
+ end
+
+endmodule
+
+
+== Constants ========================================================
+== TeX ==============================================================
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>