Updates to c++ library and test case
This commit is contained in:
parent
d2e3db48b3
commit
5ed7af923a
|
@ -94,7 +94,6 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
zcash_fpga& zfpga = zcash_fpga::get_instance();
|
zcash_fpga& zfpga = zcash_fpga::get_instance();
|
||||||
zfpga.init_fpga();
|
|
||||||
|
|
||||||
// Get FPGA status
|
// Get FPGA status
|
||||||
zcash_fpga::fpga_status_rpl_t status_rpl;
|
zcash_fpga::fpga_status_rpl_t status_rpl;
|
||||||
|
|
|
@ -6,6 +6,23 @@
|
||||||
|
|
||||||
#include <fpga_pci.h>
|
#include <fpga_pci.h>
|
||||||
|
|
||||||
|
zcash_fpga::zcash_fpga() {
|
||||||
|
if (zfpga.init_fpga() != 0)
|
||||||
|
printf("ERROR: Unable to initialize to FPGA!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
zcash_fpga::~zcash_fpga() {
|
||||||
|
/* clean up */
|
||||||
|
if (m_pci_bar_handle_bar0 >= 0) {
|
||||||
|
rc = fpga_pci_detach(pci_bar_handle_bar0);
|
||||||
|
if (rc) printf("ERROR: Failure while detaching bar0 from the fpga.\n");
|
||||||
|
}
|
||||||
|
if (m_pci_bar_handle_bar4 >= 0) {
|
||||||
|
rc = fpga_pci_detach(pci_bar_handle_bar4);
|
||||||
|
if (rc) printf("ERROR: Failure while detaching bar4 from the fpga.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
zcash_fpga& zcash_fpga::get_instance() {
|
zcash_fpga& zcash_fpga::get_instance() {
|
||||||
static zcash_fpga instance;
|
static zcash_fpga instance;
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -23,22 +40,22 @@ int zcash_fpga::init_fpga(int slot_id) {
|
||||||
|
|
||||||
/* initialize the fpga_pci library so we could have access to FPGA PCIe from this applications */
|
/* initialize the fpga_pci library so we could have access to FPGA PCIe from this applications */
|
||||||
rc = fpga_pci_init();
|
rc = fpga_pci_init();
|
||||||
fail_on(rc, out, "Unable to initialize the fpga_pci library");
|
fail_on(rc, out, "ERROR: Unable to initialize the fpga_pci library");
|
||||||
|
|
||||||
rc = check_afi_ready(slot_id);
|
rc = check_afi_ready(slot_id);
|
||||||
fail_on(rc, out, "AFI not ready");
|
fail_on(rc, out, "ERROR: AFI not ready");
|
||||||
|
|
||||||
// We need to attach to the FPGA BAR0 (OCL) and BAR4 (PCIS)
|
// We need to attach to the FPGA BAR0 (OCL) and BAR4 (PCIS)
|
||||||
rc = fpga_pci_attach(slot_id, FPGA_APP_PF, APP_PF_BAR0, 0, &pci_bar_handle_bar0);
|
rc = fpga_pci_attach(slot_id, FPGA_APP_PF, APP_PF_BAR0, 0, &pci_bar_handle_bar0);
|
||||||
fail_on(rc, out, "Unable to attach to the AFI BAR0 on slot id %d", slot_id);
|
fail_on(rc, out, "ERROR: Unable to attach to the AFI BAR0 on slot id %d", slot_id);
|
||||||
|
|
||||||
rc = fpga_pci_attach(slot_id, FPGA_APP_PF, APP_PF_BAR4, BURST_CAPABLE, &pci_bar_handle_bar4);
|
rc = fpga_pci_attach(slot_id, FPGA_APP_PF, APP_PF_BAR4, BURST_CAPABLE, &pci_bar_handle_bar4);
|
||||||
fail_on(rc, out, "Unable to attach to the AFI BAR4 on slot id %d", slot_id);
|
fail_on(rc, out, "ERROR: Unable to attach to the AFI BAR4 on slot id %d", slot_id);
|
||||||
|
|
||||||
// Now setup the streaming interface
|
// Now setup the streaming interface
|
||||||
|
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET, &rdata); //ISR
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET, &rdata); //ISR
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
printf("INFO: Read 0x%x from ISR register.\n", rdata);
|
printf("INFO: Read 0x%x from ISR register.\n", rdata);
|
||||||
if (rdata != 0x01D00000) {
|
if (rdata != 0x01D00000) {
|
||||||
printf("WARNING: Expected 0x01D00000.\n");
|
printf("WARNING: Expected 0x01D00000.\n");
|
||||||
|
@ -55,37 +72,72 @@ int zcash_fpga::init_fpga(int slot_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x1CULL, &rdata); //RDFO
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x1CULL, &rdata); //RDFO
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
printf("INFO: Read 0x%x from RDFO register.\n", rdata);
|
printf("INFO: Read 0x%x from RDFO register.\n", rdata);
|
||||||
if (rdata != 0x00000000) {
|
if (rdata != 0x00000000) {
|
||||||
printf("WARNING: Expected 0x00000000.\n");
|
printf("WARNING: Expected 0x00000000.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x4ULL, 0x0C000000); // Clear IER
|
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x4ULL, 0x0C000000); // Clear IER
|
||||||
fail_on(rc, out, "Unable to write to FPGA!");
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!");
|
||||||
|
|
||||||
// Check if we have AXI4 mode enabled or not
|
// Check if we have AXI4 mode enabled or not
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x44ULL, &rdata); //RDFO
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x44ULL, &rdata); //RDFO
|
||||||
fail_on(rc, out, "Unable to write to FPGA!");
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!");
|
||||||
AXI4_enabled = (1 << 31) & rdata;
|
AXI4_enabled = (1 << 31) & rdata;
|
||||||
if (AXI4_enabled)
|
if (AXI4_enabled)
|
||||||
printf("INFO: AXI4 mode is set ENABLED\n");
|
printf("INFO: AXI4 mode is set ENABLED\n");
|
||||||
else
|
else
|
||||||
printf("INFO: AXI4 mode is set DISABLED\n");
|
printf("INFO: AXI4 mode is set DISABLED\n");
|
||||||
|
|
||||||
printf("INFO: Finished initializing FPGA.\n");
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
|
// Send a Status message to FPGA to get configuration info
|
||||||
|
fpga_status_rpl_t fpga_status_rpl;
|
||||||
|
rc = get_status(fpga_status_rpl_t status_rpl);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to get FPGA status!");
|
||||||
|
|
||||||
|
|
||||||
|
printf("INFO: FPGA version: 0x%x, built on 0x%xxl\n", status_rpl.version, status_rpl.build_date);
|
||||||
|
printf("INFO: FPGA capability register: 0x%lx [ENB_VERIFY_EQUIHASH_200_9: %d, ENB_VERIFY_EQUIHASH_144_5 %d, ENB_VERIFY_SECP256K1_SIG %d, ENB_BLS12_381 %d]\n",
|
||||||
|
status_rpl.cmd_cap,
|
||||||
|
status_rpl.cmd_cap & (1 << ENB_VERIFY_EQUIHASH_200_9),
|
||||||
|
status_rpl.cmd_cap & (1 << ENB_VERIFY_EQUIHASH_144_5),
|
||||||
|
status_rpl.cmd_cap & (1 << ENB_VERIFY_SECP256K1_SIG),
|
||||||
|
status_rpl.cmd_cap & (1 << ENB_BLS12_381));
|
||||||
|
|
||||||
|
if (status_rpl.cmd_cap & (1 << ENB_BLS12_381)) {
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 0, &rdata);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
m_bls12_381_inst_axil_offset = rdata;
|
||||||
|
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 1*4, &rdata);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
m_bls12_381_data_axil_offset = rdata;
|
||||||
|
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 2*4, &rdata);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
m_bls12_381_data_size = 1 << rdata;
|
||||||
|
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 3*4, &rdata);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
m_bls12_381_inst_size = 1 << rdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("INFO: Finished initializing FPGA.\n");
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
out:
|
out:
|
||||||
|
initialized = false;
|
||||||
/* clean up */
|
/* clean up */
|
||||||
if (pci_bar_handle_bar0 >= 0) {
|
if (pci_bar_handle_bar0 >= 0) {
|
||||||
rc = fpga_pci_detach(pci_bar_handle_bar0);
|
rc = fpga_pci_detach(pci_bar_handle_bar0);
|
||||||
if (rc) printf("Failure while detaching bar0 from the fpga.\n");
|
if (rc) printf("ERROR: Failure while detaching bar0 from the fpga.\n");
|
||||||
}
|
}
|
||||||
if (pci_bar_handle_bar4 >= 0) {
|
if (pci_bar_handle_bar4 >= 0) {
|
||||||
rc = fpga_pci_detach(pci_bar_handle_bar4);
|
rc = fpga_pci_detach(pci_bar_handle_bar4);
|
||||||
if (rc) printf("Failure while detaching bar4 from the fpga.\n");
|
if (rc) printf("ERROR: Failure while detaching bar4 from the fpga.\n");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -96,31 +148,31 @@ int zcash_fpga::check_afi_ready(int slot_id) {
|
||||||
|
|
||||||
/* get local image description, contains status, vendor id, and device id. */
|
/* get local image description, contains status, vendor id, and device id. */
|
||||||
rc = fpga_mgmt_describe_local_image(slot_id, &info,0);
|
rc = fpga_mgmt_describe_local_image(slot_id, &info,0);
|
||||||
fail_on(rc, out, "Unable to get AFI information from slot %d. Are you running as root?",slot_id);
|
fail_on(rc, out, "ERROR: Unable to get AFI information from slot %d. Are you running as root?",slot_id);
|
||||||
|
|
||||||
/* check to see if the slot is ready */
|
/* check to see if the slot is ready */
|
||||||
if (info.status != FPGA_STATUS_LOADED) {
|
if (info.status != FPGA_STATUS_LOADED) {
|
||||||
rc = 1;
|
rc = 1;
|
||||||
fail_on(rc, out, "AFI in Slot %d is not in READY state !", slot_id);
|
fail_on(rc, out, "ERROR: AFI in Slot %d is not in READY state !", slot_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("AFI PCI Vendor ID: 0x%x, Device ID 0x%x\n",
|
printf("INFO: AFI PCI Vendor ID: 0x%x, Device ID 0x%x\n",
|
||||||
info.spec.map[FPGA_APP_PF].vendor_id,
|
info.spec.map[FPGA_APP_PF].vendor_id,
|
||||||
info.spec.map[FPGA_APP_PF].device_id);
|
info.spec.map[FPGA_APP_PF].device_id);
|
||||||
|
|
||||||
/* confirm that the AFI that we expect is in fact loaded */
|
/* confirm that the AFI that we expect is in fact loaded */
|
||||||
if (info.spec.map[FPGA_APP_PF].vendor_id != pci_vendor_id ||
|
if (info.spec.map[FPGA_APP_PF].vendor_id != pci_vendor_id ||
|
||||||
info.spec.map[FPGA_APP_PF].device_id != pci_device_id) {
|
info.spec.map[FPGA_APP_PF].device_id != pci_device_id) {
|
||||||
printf("AFI does not show expected PCI vendor id and device ID. If the AFI "
|
printf("INFO: AFI does not show expected PCI vendor id and device ID. If the AFI "
|
||||||
"was just loaded, it might need a rescan. Rescanning now.\n");
|
"was just loaded, it might need a rescan. Rescanning now.\n");
|
||||||
|
|
||||||
rc = fpga_pci_rescan_slot_app_pfs(slot_id);
|
rc = fpga_pci_rescan_slot_app_pfs(slot_id);
|
||||||
fail_on(rc, out, "Unable to update PF for slot %d",slot_id);
|
fail_on(rc, out, "ERROR: Unable to update PF for slot %d",slot_id);
|
||||||
/* get local image description, contains status, vendor id, and device id. */
|
/* get local image description, contains status, vendor id, and device id. */
|
||||||
rc = fpga_mgmt_describe_local_image(slot_id, &info,0);
|
rc = fpga_mgmt_describe_local_image(slot_id, &info,0);
|
||||||
fail_on(rc, out, "Unable to get AFI information from slot %d",slot_id);
|
fail_on(rc, out, "ERROR: Unable to get AFI information from slot %d",slot_id);
|
||||||
|
|
||||||
printf("AFI PCI Vendor ID: 0x%x, Device ID 0x%x\n",
|
printf("INFO: AFI PCI Vendor ID: 0x%x, Device ID 0x%x\n",
|
||||||
info.spec.map[FPGA_APP_PF].vendor_id,
|
info.spec.map[FPGA_APP_PF].vendor_id,
|
||||||
info.spec.map[FPGA_APP_PF].device_id);
|
info.spec.map[FPGA_APP_PF].device_id);
|
||||||
|
|
||||||
|
@ -128,7 +180,7 @@ int zcash_fpga::check_afi_ready(int slot_id) {
|
||||||
if (info.spec.map[FPGA_APP_PF].vendor_id != pci_vendor_id ||
|
if (info.spec.map[FPGA_APP_PF].vendor_id != pci_vendor_id ||
|
||||||
info.spec.map[FPGA_APP_PF].device_id != pci_device_id) {
|
info.spec.map[FPGA_APP_PF].device_id != pci_device_id) {
|
||||||
rc = 1;
|
rc = 1;
|
||||||
fail_on(rc, out, "The PCI vendor id and device of the loaded AFI are not "
|
fail_on(rc, out, "ERROR: The PCI vendor id and device of the loaded AFI are not "
|
||||||
"the expected values.");
|
"the expected values.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,11 +196,16 @@ int zcash_fpga::get_status(fpga_status_rpl_t& status_rpl) {
|
||||||
unsigned int timeout = 0;
|
unsigned int timeout = 0;
|
||||||
unsigned int read_len = 0;
|
unsigned int read_len = 0;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
header_t hdr;
|
header_t hdr;
|
||||||
hdr.cmd = FPGA_STATUS;
|
hdr.cmd = FPGA_STATUS;
|
||||||
hdr.len = 8;
|
hdr.len = 8;
|
||||||
rc = write_stream((char*)&hdr, sizeof(hdr));
|
rc = write_stream((char*)&hdr, sizeof(hdr));
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
|
|
||||||
// Try read reply
|
// Try read reply
|
||||||
char reply[256];
|
char reply[256];
|
||||||
|
@ -163,8 +220,6 @@ int zcash_fpga::get_status(fpga_status_rpl_t& status_rpl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
status_rpl = *(fpga_status_rpl_t*)reply;
|
status_rpl = *(fpga_status_rpl_t*)reply;
|
||||||
printf("INFO: Received FPGA reply, FPGA version: 0x%x\n", status_rpl.version); // TODO print more
|
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
out:
|
out:
|
||||||
|
@ -177,13 +232,13 @@ int zcash_fpga::write_stream(char* data, unsigned int len) {
|
||||||
unsigned int len_send = 0;
|
unsigned int len_send = 0;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
printf("INFO: FPGA not initialized!\n");
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET + 0xCULL, &rdata);
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET + 0xCULL, &rdata);
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
if (len > rdata) {
|
if (len > rdata) {
|
||||||
printf("ERROR: write_stream does not have enough space to write %d bytes! (%d free)\n", len, rdata);
|
printf("ERROR: write_stream does not have enough space to write %d bytes! (%d free)\n", len, rdata);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -196,20 +251,20 @@ int zcash_fpga::write_stream(char* data, unsigned int len) {
|
||||||
len_send += 8;
|
len_send += 8;
|
||||||
} else {
|
} else {
|
||||||
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x10ULL, *(uint32_t*)(&data[len_send])); // Reset ISR
|
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x10ULL, *(uint32_t*)(&data[len_send])); // Reset ISR
|
||||||
fail_on(rc, out, "Unable to write to FPGA!");
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!");
|
||||||
len_send += 4;
|
len_send += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x14ULL, len); // Reset ISR
|
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET+0x14ULL, len); // Reset ISR
|
||||||
fail_on(rc, out, "Unable to write to FPGA!");
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!");
|
||||||
|
|
||||||
|
|
||||||
printf("INFO: write_stream::Wrote %d bytes of data\n", len);
|
printf("INFO: write_stream::Wrote %d bytes of data\n", len);
|
||||||
|
|
||||||
// Check transmit complete bit and reset it
|
// Check transmit complete bit and reset it
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET, &rdata);
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET, &rdata);
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
if ((rdata & (1 << 27)) == 0) {
|
if ((rdata & (1 << 27)) == 0) {
|
||||||
printf("WARNING: write_stream transmit bit not set, register returned 0x%x\n", rdata);
|
printf("WARNING: write_stream transmit bit not set, register returned 0x%x\n", rdata);
|
||||||
}
|
}
|
||||||
|
@ -229,20 +284,20 @@ int zcash_fpga::read_stream(char* data, unsigned int size) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
printf("INFO: FPGA not initialized!\n");
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET, &rdata);
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET, &rdata);
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
if ((rdata & (1 << 26)) == 0) return 0; // Nothing to read
|
if ((rdata & (1 << 26)) == 0) return 0; // Nothing to read
|
||||||
|
|
||||||
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET, 0x04000000); // clear ISR
|
rc = fpga_pci_poke(pci_bar_handle_bar0, AXI_FIFO_OFFSET, 0x04000000); // clear ISR
|
||||||
fail_on(rc, out, "Unable to write to FPGA!");
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!");
|
||||||
|
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET + 0x1CULL, &rdata); //RDFO should be non-zero (slots used in FIFO)
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET + 0x1CULL, &rdata); //RDFO should be non-zero (slots used in FIFO)
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
if (rdata == 0) {
|
if (rdata == 0) {
|
||||||
printf("WARNING: Read FIFO shows data but length was 0!\n");
|
printf("WARNING: Read FIFO shows data but length was 0!\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -260,11 +315,11 @@ int zcash_fpga::read_stream(char* data, unsigned int size) {
|
||||||
while(read_len < rdata) {
|
while(read_len < rdata) {
|
||||||
if (AXI4_enabled) {
|
if (AXI4_enabled) {
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar4, 0x1000, (uint32_t*)(&data[read_len]));
|
rc = fpga_pci_peek(pci_bar_handle_bar4, 0x1000, (uint32_t*)(&data[read_len]));
|
||||||
fail_on(rc, out, "Unable to read from FPGA PCIS!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA PCIS!");
|
||||||
read_len += 8;
|
read_len += 8;
|
||||||
} else {
|
} else {
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET + 0x20ULL, (uint32_t*)(&data[read_len]));
|
rc = fpga_pci_peek(pci_bar_handle_bar0, AXI_FIFO_OFFSET + 0x20ULL, (uint32_t*)(&data[read_len]));
|
||||||
fail_on(rc, out, "Unable to read from FPGA!");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!");
|
||||||
read_len += 4;
|
read_len += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +335,11 @@ int zcash_fpga::bls12_381_write_data_slot(unsigned int id, bls12_381_slot_t slot
|
||||||
char data[48];
|
char data[48];
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
printf("INFO: FPGA not initialized!\n");
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (id >= m_bls12_381_data_size) {
|
||||||
|
printf("ERROR: Data slot id (%d) is greater than number of slots on FPGA (%d)!\n", id, m_bls12_381_data_size);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +349,8 @@ int zcash_fpga::bls12_381_write_data_slot(unsigned int id, bls12_381_slot_t slot
|
||||||
data[47] |= (slot_data.point_type << 5);
|
data[47] |= (slot_data.point_type << 5);
|
||||||
|
|
||||||
for(int i = 0; i < 48/4; i=i+4) {
|
for(int i = 0; i < 48/4; i=i+4) {
|
||||||
rc = fpga_pci_poke(pci_bar_handle_bar0, BLS12_381_OFFSET + BLS12_381_DATA_OFFSET + id*64 + i, *((uint32_t*)&data[i]));
|
rc = fpga_pci_poke(pci_bar_handle_bar0, BLS12_381_OFFSET + m_bls12_381_data_axil_offset + id*64 + i, *((uint32_t*)&data[i]));
|
||||||
fail_on(rc, out, "Unable to write to FPGA!\n");
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
|
@ -301,13 +360,17 @@ int zcash_fpga::bls12_381_write_data_slot(unsigned int id, bls12_381_slot_t slot
|
||||||
int zcash_fpga::bls12_381_read_data_slot(unsigned int id, bls12_381_slot_t& slot_data) {
|
int zcash_fpga::bls12_381_read_data_slot(unsigned int id, bls12_381_slot_t& slot_data) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
printf("INFO: FPGA not initialized!\n");
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (id >= m_bls12_381_data_size) {
|
||||||
|
printf("ERROR: Data slot id (%d) is greater than number of slots on FPGA (%d)!\n", id, m_bls12_381_data_size);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 48/4; i=i+4) {
|
for(int i = 0; i < 48/4; i=i+4) {
|
||||||
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + BLS12_381_DATA_OFFSET + id*64 + i, (uint32_t*)(&slot_data));
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + m_bls12_381_data_axil_offset + id*64 + i, (uint32_t*)(&slot_data));
|
||||||
fail_on(rc, out, "Unable to read from FPGA!\n");
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
slot_data.point_type = (point_type_t)(*((char*)&slot_data + 47) >> 5);
|
slot_data.point_type = (point_type_t)(*((char*)&slot_data + 47) >> 5);
|
||||||
|
@ -318,3 +381,129 @@ int zcash_fpga::bls12_381_read_data_slot(unsigned int id, bls12_381_slot_t& slot
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zcash_fpga::bls12_381_write_inst_slot(unsigned int id, bls12_381_inst_t inst_data) {
|
||||||
|
int rc = 0;
|
||||||
|
if (!initialized) {
|
||||||
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (id >= m_bls12_381_inst_size) {
|
||||||
|
printf("ERROR: Instance slot id (%d) is greater than number of slots on FPGA (%d)!\n", id, m_bls12_381_inst_size);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 2; i=i+1) {
|
||||||
|
rc = fpga_pci_poke(pci_bar_handle_bar0, BLS12_381_OFFSET + m_bls12_381_inst_axil_offset + id*8 + i*4, *((uint32_t*)&inst_data) + i);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zcash_fpga::bls12_381_read_inst_slot(unsigned int id, bls12_381_inst_t& inst_data) {
|
||||||
|
int rc = 0;
|
||||||
|
if (!initialized) {
|
||||||
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (id >= m_bls12_381_inst_size) {
|
||||||
|
printf("ERROR: Instance slot id (%d) is greater than number of slots on FPGA (%d)!\n", id, m_bls12_381_inst_size);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 2; i=i+1) {
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + m_bls12_381_inst_axil_offset + id*8 + i*4, ((uint32_t*)(&inst_data) + i));
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zcash_fpga::bls12_381_set_curr_inst_slot(unsigned int id) {
|
||||||
|
int rc = 0;
|
||||||
|
unsigned int prev_id;
|
||||||
|
uint32_t rdata;
|
||||||
|
if (!initialized) {
|
||||||
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (id >= m_bls12_381_inst_size) {
|
||||||
|
printf("ERROR: Instance slot id (%d) is greater than number of slots on FPGA (%d)!\n", id, m_bls12_381_inst_size);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 0x10, rdata);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
prev_id = rdata;
|
||||||
|
|
||||||
|
rc = fpga_pci_poke(pci_bar_handle_bar0, BLS12_381_OFFSET + 0x10, id);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!\n");
|
||||||
|
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 0x10, rdata);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
|
||||||
|
if (rdata != id) {
|
||||||
|
printf("ERROR: Unable to set BLS12_381 current instruction slot!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("INFO: Set BLS12_381 current instruction slot to %d (was %d)\n", id, prev_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zcash_fpga::bls12_381_get_curr_inst_slot(unsigned int& id) {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (id >= m_bls12_381_inst_size) {
|
||||||
|
printf("ERROR: Instance slot id (%d) is greater than number of slots on FPGA (%d)!\n", id, m_bls12_381_inst_size);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fpga_pci_peek(pci_bar_handle_bar0, BLS12_381_OFFSET + 0x10, id);
|
||||||
|
fail_on(rc, out, "ERROR: Unable to read from FPGA!\n");
|
||||||
|
|
||||||
|
printf("INFO: BLS12_381 current instruction slot is %d\n", id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zcash_fpga::bls12_381_reset_memory(bool inst_memory, bool data_memory) {
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t data = 0;
|
||||||
|
if (!initialized) {
|
||||||
|
printf("ERROR: FPGA not initialized!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst_memory) {
|
||||||
|
data |= 1;
|
||||||
|
printf("INFO: Resetting instruction memory\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_memory) {
|
||||||
|
data |= 1 << 1;
|
||||||
|
printf("INFO: Resetting data memory reset\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fpga_pci_poke(pci_bar_handle_bar0, BLS12_381_OFFSET, ;
|
||||||
|
fail_on(rc, out, "ERROR: Unable to write to FPGA!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,6 @@
|
||||||
|
|
||||||
#define AXI_FIFO_OFFSET UINT64_C(0x0)
|
#define AXI_FIFO_OFFSET UINT64_C(0x0)
|
||||||
#define BLS12_381_OFFSET UINT64_C(0x1000)
|
#define BLS12_381_OFFSET UINT64_C(0x1000)
|
||||||
#define BLS12_381_INST_OFFSET UINT64_C(0x1000)
|
|
||||||
#define BLS12_381_DATA_OFFSET UINT64_C(0x2000)
|
|
||||||
|
|
||||||
|
|
||||||
// These match the structs and commands defined in zcash_fpga_pkg.sv
|
// These match the structs and commands defined in zcash_fpga_pkg.sv
|
||||||
class zcash_fpga {
|
class zcash_fpga {
|
||||||
|
@ -77,6 +74,29 @@ class zcash_fpga {
|
||||||
point_type_t point_type;
|
point_type_t point_type;
|
||||||
} bls12_381_slot_t;
|
} bls12_381_slot_t;
|
||||||
|
|
||||||
|
typedef enum uint8_t {
|
||||||
|
NOOP_WAIT = 0x0,
|
||||||
|
COPY_REG = 0x1,
|
||||||
|
SEND_INTERRUPT = 0x6,
|
||||||
|
|
||||||
|
SUB_ELEMENT = 0x10,
|
||||||
|
ADD_ELEMENT = 0x11,
|
||||||
|
MUL_ELEMENT = 0x12,
|
||||||
|
INV_ELEMENT = 0x13,
|
||||||
|
|
||||||
|
POINT_MULT = 0x24,
|
||||||
|
FP_FPOINT_MULT = 0x25,
|
||||||
|
FP2_FPOINT_MULT = 0x26
|
||||||
|
} code_t;
|
||||||
|
|
||||||
|
// Instruction format
|
||||||
|
typedef struct __attribute__((__packed__)) {
|
||||||
|
code_t code;
|
||||||
|
uint16_t a;
|
||||||
|
uint16_t b;
|
||||||
|
uint16_t c;
|
||||||
|
} inst_t;
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) {
|
typedef struct __attribute__((__packed__)) {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
command_t cmd;
|
command_t cmd;
|
||||||
|
@ -110,14 +130,19 @@ class zcash_fpga {
|
||||||
} fpga_status_rpl_t;
|
} fpga_status_rpl_t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint16_t pci_vendor_id = 0x1D0F; /* Amazon PCI Vendor ID */
|
static const uint16_t s_pci_vendor_id = 0x1D0F; /* Amazon PCI Vendor ID */
|
||||||
static const uint16_t pci_device_id = 0xF000; /* PCI Device ID preassigned by Amazon for F1 applications */
|
static const uint16_t s_pci_device_id = 0xF000; /* PCI Device ID preassigned by Amazon for F1 applications */
|
||||||
|
|
||||||
pci_bar_handle_t pci_bar_handle_bar0 = PCI_BAR_HANDLE_INIT;
|
pci_bar_handle_t m_pci_bar_handle_bar0 = PCI_BAR_HANDLE_INIT;
|
||||||
pci_bar_handle_t pci_bar_handle_bar4 = PCI_BAR_HANDLE_INIT;
|
pci_bar_handle_t m_pci_bar_handle_bar4 = PCI_BAR_HANDLE_INIT;
|
||||||
|
|
||||||
bool AXI4_enabled = false;
|
unsigned int m_bls12_381_inst_axil_offset;
|
||||||
bool initialized = false;
|
unsigned int m_bls12_381_data_axil_offset;
|
||||||
|
unsigned int m_bls12_381_inst_size;
|
||||||
|
unsigned int m_bls12_381_data_size;
|
||||||
|
|
||||||
|
bool m_AXI4_enabled = false;
|
||||||
|
bool m_initialized = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static zcash_fpga& get_instance();
|
static zcash_fpga& get_instance();
|
||||||
|
@ -128,6 +153,7 @@ class zcash_fpga {
|
||||||
* This connects to the FPGA and must be called at least once
|
* This connects to the FPGA and must be called at least once
|
||||||
*/
|
*/
|
||||||
int init_fpga(int slot_id = 0);
|
int init_fpga(int slot_id = 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This sends a status request to the FPGA and waits for the reply,
|
* This sends a status request to the FPGA and waits for the reply,
|
||||||
* checking for any errors.
|
* checking for any errors.
|
||||||
|
@ -135,14 +161,25 @@ class zcash_fpga {
|
||||||
int get_status(fpga_status_rpl_t& status_rpl);
|
int get_status(fpga_status_rpl_t& status_rpl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions for writing and reading data slots in the BLS12_381 coprocessor
|
* Functions for writing and reading data/instruction slots in the BLS12_381 coprocessor
|
||||||
*/
|
*/
|
||||||
int bls12_381_write_data_slot(unsigned int id, bls12_381_slot_t slot_data);
|
int bls12_381_write_data_slot(unsigned int id, bls12_381_slot_t slot_data);
|
||||||
int bls12_381_read_data_slot(unsigned int id, bls12_381_slot_t& slot_data);
|
int bls12_381_read_data_slot(unsigned int id, bls12_381_slot_t& slot_data);
|
||||||
|
|
||||||
|
int bls12_381_write_inst_slot(unsigned int id, bls12_381_inst_t inst_data);
|
||||||
|
int bls12_381_read_inst_slot(unsigned int id, bls12_381_inst_t inst_data);
|
||||||
|
|
||||||
|
int bls12_381_set_curr_inst_slot(unsigned int id);
|
||||||
|
int bls12_381_get_curr_inst_slot(unsigned int& id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This will clear the entire memory back to the initial state (will not change instruction pointer)
|
||||||
|
*/
|
||||||
|
int bls12_381_reset_memory(bool inst_memory, bool data_memory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
zcash_fpga(){};
|
zcash_fpga();
|
||||||
~zcash_fpga(){};
|
~zcash_fpga();
|
||||||
|
|
||||||
int check_afi_ready(int slot_id);
|
int check_afi_ready(int slot_id);
|
||||||
int read_stream(char* data, unsigned int size);
|
int read_stream(char* data, unsigned int size);
|
||||||
|
|
|
@ -61,8 +61,8 @@ initial begin
|
||||||
|
|
||||||
|
|
||||||
// Run our test cases
|
// Run our test cases
|
||||||
// test_status_message();
|
test_status_message();
|
||||||
// test_block_secp256k1();
|
test_block_secp256k1();
|
||||||
test_bls12_381();
|
test_bls12_381();
|
||||||
|
|
||||||
$display("INFO: All tests passed");
|
$display("INFO: All tests passed");
|
||||||
|
@ -270,13 +270,13 @@ task test_bls12_381();
|
||||||
|
|
||||||
// Check we can read it back
|
// Check we can read it back
|
||||||
dat = 0;
|
dat = 0;
|
||||||
for(int i = 0; i < 2; i = i + 4) begin
|
for(int i = 0; i < 8; i = i + 4) begin
|
||||||
read_ocl_reg(.addr(`ZCASH_OFFSET + bls12_381_pkg::INST_AXIL_START + 3*8 + i), .rdata(rdata));
|
read_ocl_reg(.addr(`ZCASH_OFFSET + bls12_381_pkg::INST_AXIL_START + 3*8 + i), .rdata(rdata));
|
||||||
dat[i*8 +: 32] = rdata;
|
dat[i*8 +: 32] = rdata;
|
||||||
end
|
end
|
||||||
$display("INFO: Read: 0x%x", dat[48*8-1:0]);
|
$display("INFO: Read: 0x%x", dat[8*8-1:0]);
|
||||||
$display("INFO: Wrote: 0x%x", inst);
|
$display("INFO: Wrote: 0x%x", inst);
|
||||||
assert(dat[2*8-1:0] == inst) else $fatal(1, "ERROR: Writing to slot and reading gave wrong results!");
|
assert(dat[8*8-1:0] == inst) else $fatal(1, "ERROR: Writing to slot and reading gave wrong results!");
|
||||||
|
|
||||||
slot_data = '{dat:in_k, pt:SCALAR};
|
slot_data = '{dat:in_k, pt:SCALAR};
|
||||||
for(int i = 0; i < 48; i = i + 4)
|
for(int i = 0; i < 48; i = i + 4)
|
||||||
|
@ -295,6 +295,7 @@ task test_bls12_381();
|
||||||
|
|
||||||
fork
|
fork
|
||||||
begin
|
begin
|
||||||
|
stream_len = 0;
|
||||||
while(stream_len == 0) read_stream(.data(stream_data), .len(stream_len));
|
while(stream_len == 0) read_stream(.data(stream_data), .len(stream_len));
|
||||||
interrupt_rpl = stream_data;
|
interrupt_rpl = stream_data;
|
||||||
|
|
||||||
|
@ -319,7 +320,7 @@ task test_bls12_381();
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
begin
|
begin
|
||||||
repeat(10000) @(posedge tb.card.fpga.clk_main_a0);
|
repeat(100000) @(posedge tb.card.fpga.clk_main_a0);
|
||||||
$fatal(1, "ERROR: No reply received from test_bls12_381");
|
$fatal(1, "ERROR: No reply received from test_bls12_381");
|
||||||
end
|
end
|
||||||
join_any
|
join_any
|
||||||
|
|
|
@ -110,8 +110,8 @@ always_ff @ (posedge i_clk) begin
|
||||||
case(axi_lite_if.araddr)
|
case(axi_lite_if.araddr)
|
||||||
32'h0: axi_lite_if.rdata <= INST_AXIL_START;
|
32'h0: axi_lite_if.rdata <= INST_AXIL_START;
|
||||||
32'h4: axi_lite_if.rdata <= DATA_AXIL_START;
|
32'h4: axi_lite_if.rdata <= DATA_AXIL_START;
|
||||||
32'h8: axi_lite_if.rdata <= DATA_RAM_DEPTH*DATA_RAM_ALIGN_BYTE;
|
32'h8: axi_lite_if.rdata <= DATA_RAM_DEPTH;
|
||||||
32'hc: axi_lite_if.rdata <= INST_RAM_DEPTH*INST_RAM_ALIGN_BYTE;
|
32'hc: axi_lite_if.rdata <= INST_RAM_DEPTH;
|
||||||
32'h10: axi_lite_if.rdata <= curr_inst_pt;
|
32'h10: axi_lite_if.rdata <= curr_inst_pt;
|
||||||
32'h14: axi_lite_if.rdata <= last_inst_cnt;
|
32'h14: axi_lite_if.rdata <= last_inst_cnt;
|
||||||
default: axi_lite_if.rdata <= 32'hbeef;
|
default: axi_lite_if.rdata <= 32'hbeef;
|
||||||
|
|
Loading…
Reference in New Issue