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

Subversion Repositories xulalx25soc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /xulalx25soc
    from Rev 4 to Rev 5
    Reverse comparison

Rev 4 → Rev 5

/trunk/sw/ttybus.h
0,0 → 1,124
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ttybus.h
//
// Project: XuLA2 board
//
// Purpose: This is the C++ program on the command side that will interact
// with a UART on an FPGA, to command the WISHBONE on that same
// FPGA to ... whatever we wish to command it to do.
//
// This code does not run on an FPGA, is not a test bench, neither
// is it a simulator. It is a portion of a command program
// for commanding an FPGA.
//
// This particular implementation is a complete rewrite of the
// last implementation, adding compression into the interface that
// wasn't there before.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#ifndef TTYBUS_H
#define TTYBUS_H
 
#include "llcomms.h"
#include "devbus.h"
 
#define RDBUFLN 2048
 
class TTYBUS : public DEVBUS {
public:
unsigned long m_total_nread;
private:
LLCOMMSI *m_dev;
static const unsigned MAXRDLEN, MAXWRLEN;
 
bool m_interrupt_flag, m_decode_err, m_addr_set, m_bus_err;
unsigned int m_lastaddr;
 
int m_buflen, m_rdfirst, m_rdlast;
char *m_buf, *m_rdbuf;
 
bool m_wrloaded;
int m_rdaddr, m_wraddr;
BUSW m_readtbl[1024], m_writetbl[512];
 
void init(void) {
m_interrupt_flag = false;
m_buflen = 0; m_buf = NULL;
m_addr_set = false;
bufalloc(64);
m_bus_err = false;
m_decode_err = false;
m_wrloaded = false;
 
m_rdfirst = m_rdlast = 0;
m_rdbuf = new char[RDBUFLN];
 
m_rdaddr = m_wraddr = 0;
}
 
char charenc(const int sixbitval);
unsigned chardec(const char b);
void encode(const int fbits, const BUSW v, char *buf);
unsigned decodestr(const char *buf);
int decodehex(const char hx);
void bufalloc(int len);
BUSW readword(void); // Reads a word value from the bus
void readv(const BUSW a, const int inc, const int len, BUSW *buf);
void writev(const BUSW a, const int p, const int len, const BUSW *buf);
 
int lclread(char *buf, int len);
int lclreadcode(char *buf, int len);
char *encode_address(const BUSW a);
char *readcmd(const int inc, const int len, char *buf);
public:
TTYBUS(LLCOMMSI *comms) : m_dev(comms) { init(); }
virtual ~TTYBUS(void) {
m_dev->close();
if (m_buf) delete[] m_buf; m_buf = NULL;
delete m_rdbuf; m_rdbuf = NULL;
delete m_dev;
}
 
void kill(void) { m_dev->close(); }
void close(void) { m_dev->close(); }
void writeio(const BUSW a, const BUSW v);
BUSW readio(const BUSW a);
void readi(const BUSW a, const int len, BUSW *buf);
void readz(const BUSW a, const int len, BUSW *buf);
void writei(const BUSW a, const int len, const BUSW *buf);
void writez(const BUSW a, const int len, const BUSW *buf);
bool poll(void) { return m_interrupt_flag; };
void usleep(unsigned msec); // Sleep until interrupt
void wait(void); // Sleep until interrupt
bool bus_err(void) const { return m_bus_err; };
void reset_err(void) { m_bus_err = false; }
void clear(void) { m_interrupt_flag = false; }
};
 
#endif
/trunk/sw/netusb.cpp
0,0 → 1,275
////////////////////////////////////////////////////////////////////////////////
//
// Filename: netusb.cpp
//
// Project: XuLA2 board
//
// Purpose: Forwards a XuLA2 board USB connection over a TCP socket, so
// a non-local computer can control the board.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
 
#include "port.h"
#include "usbi.h"
 
void sigstop(int v) {
fprintf(stderr, "SIGSTOP!!\n");
exit(0);
}
void sighup(int v) {
fprintf(stderr, "SIGHUP!!\n");
exit(0);
}
void sigint(int v) {
fprintf(stderr, "SIGINT!!\n");
exit(0);
}
void sigsegv(int v) {
fprintf(stderr, "SIGSEGV!!\n");
exit(0);
}
void sigbus(int v) {
fprintf(stderr, "SIGBUS!!\n");
exit(0);
}
void sigpipe(int v) {
fprintf(stderr, "SIGPIPE!!\n");
exit(0);
}
 
int setup_listener(const int port) {
int skt;
struct sockaddr_in my_addr;
 
printf("Listening on port %d\n", port);
 
skt = socket(AF_INET, SOCK_STREAM, 0);
if (skt < 0) {
perror("Could not allocate socket: ");
exit(-1);
}
 
// Set the reuse address option
{
int optv = 1, er;
er = setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, &optv, sizeof(optv));
if (er != 0) {
perror("SockOpt Err:");
exit(-1);
}
}
 
memset(&my_addr, 0, sizeof(struct sockaddr_in)); // clear structure
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
my_addr.sin_port = htons(port);
 
if (bind(skt, (struct sockaddr *)&my_addr, sizeof(my_addr))!=0) {
perror("BIND FAILED:");
exit(-1);
}
 
if (listen(skt, 1) != 0) {
perror("Listen failed:");
exit(-1);
}
 
return skt;
}
 
class LINBUFS {
public:
char m_iline[512], m_oline[512];
char m_buf[256];
int m_ilen, m_olen;
bool m_connected;
 
LINBUFS(void) {
m_ilen = 0; m_olen = 0; m_connected = false;
}
};
 
bool check_incoming(LINBUFS &lb, USBI *usbp, int confd, int timeout) {
struct pollfd p[2];
int pv, nfds;
 
if (confd >= 0) {
// Only do this if we currently have a network connection
p[0].fd = confd;
p[0].events = POLLIN | POLLRDHUP | POLLERR;
nfds = 1;
 
if ((pv=poll(p, nfds, timeout)) < 0) {
perror("Poll Failed! O/S Err:");
exit(-1);
}
if (p[0].revents & POLLIN) {
/*
else if (p[0].revents)
printf("UNKNOWN TTY EVENT: %d\n", p[0].revents);
*/
int nr = read(confd, lb.m_buf, 256);
if (nr == 0) {
lb.m_connected = false;
if (lb.m_olen > 0) {
lb.m_oline[lb.m_olen] = '\0';
printf("< %s\n", lb.m_oline);
} lb.m_olen = 0;
close(confd);
} else if (nr > 0) {
usbp->write(lb.m_buf, nr);
} for(int i=0; i<nr; i++) {
lb.m_oline[lb.m_olen++] = lb.m_buf[i];
assert(lb.m_buf[i] != '\0');
if ((lb.m_oline[lb.m_olen-1]=='\n')||(lb.m_oline[lb.m_olen-1]=='\r')||(lb.m_olen >= (int)sizeof(lb.m_oline)-1)) {
if (lb.m_olen >= (int)sizeof(lb.m_oline)-1)
lb.m_oline[lb.m_olen] = '\0';
else
lb.m_oline[lb.m_olen-1] = '\0';
if (lb.m_olen > 1)
printf("< %s\n", lb.m_oline);
lb.m_olen = 0;
}
}
} else if ((nfds>1)&&(p[1].revents)) {
printf("UNKNOWN SKT EVENT: %d\n", p[1].revents);
}
}
 
if (usbp->poll(2)) {
int nr, nrn;
 
nr = nrn = usbp->read(lb.m_buf,1,2);
while((nrn>0)&&(nr<255)&&((lb.m_buf[0]&0x80)==0)&&(lb.m_buf[0]>0x10)) {
nrn = usbp->read(&lb.m_buf[nr],1,2);
nr += nrn;
} if ((nr > 0)&&(confd >= 0)) {
// Return our result if we have a network
// connection
write(confd, lb.m_buf, nr);
} for(int i=0; i<nr; i++) {
lb.m_iline[lb.m_ilen++] = lb.m_buf[i];
if ((lb.m_iline[lb.m_ilen-1]=='\n')||(lb.m_iline[lb.m_ilen-1]=='\r')||(lb.m_ilen>=sizeof(lb.m_iline)-1)) {
if (lb.m_ilen >= sizeof(lb.m_iline)-1)
lb.m_iline[lb.m_ilen] = '\0';
else
lb.m_iline[lb.m_ilen-1] = '\0';
if (lb.m_ilen > 1)
printf("%c %s\n",
(confd>=0)?'>':'#', lb.m_iline);
lb.m_ilen = 0;
}
}
}
 
return (pv > 0);
}
 
int myaccept(int skt, int timeout) {
int con = -1;
struct pollfd p[1];
int pv;
 
p[0].fd = skt;
p[0].events = POLLIN | POLLERR;
if ((pv=poll(p, 1, timeout)) < 0) {
perror("Poll Failed! O/S Err:");
exit(-1);
} if (p[0].revents & POLLIN) {
con = accept(skt, 0, 0);
if (con < 0) {
perror("Accept failed! O/S Err:");
exit(-1);
}
} return con;
}
 
int main(int argc, char **argv) {
// First, accept a network connection
int skt = setup_listener(FPGAPORT);
USBI *usbp;
bool done = false;
 
signal(SIGSTOP, sigstop);
signal(SIGBUS, sigbus);
signal(SIGSEGV, sigsegv);
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, sigint);
signal(SIGHUP, sighup);
 
usbp = new USBI();
 
LINBUFS lb;
while(!done) {
int con;
 
// Accept a connection before going on
// Let's call poll(), so we can still read any
// tty messages even when not accepted
con = myaccept(skt, 50);
if (con >= 0) {
lb.m_connected = true;
 
/*
// Set our new socket as non-blocking
int flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
*/
 
// printf("Received a new connection\n");
}
 
// Flush any buffer within the TTY
while(check_incoming(lb, usbp, -1, 0))
;
 
// Now, process that connection until it's gone
while(lb.m_connected) {
check_incoming(lb, usbp, con, -1);
}
}
 
printf("Closing our socket\n");
close(skt);
}
 
/trunk/sw/usbi.cpp
0,0 → 1,415
////////////////////////////////////////////////////////////////////////////////
//
// Filename:
//
// Project: XuLA2 board
//
// Purpose: Creates a USB port, similar to a serial port, out of the
// XuLA2 JTAG interface S/W.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
// #include <usb.h>
 
#include <libusb.h>
 
#include "llcomms.h"
#include "usbi.h"
 
// Walk us through the JTAG Chain:
// 5-1's to go to test/reset
// 0 to go to Run-Test/Idle
// 1 to go to select-dr-scan
// 1 to go to select-ir-scan
// 0 to go to capture-ir
// 0 to go to shift-ir
// (6-bit code 0x02 through TDI to IR, while sending 0-bits to TMS)
// 1 to leave shift IR and go to exit1-ir
// 1 to go to update-ir
// 1 to go to select-dr-scan
// 0 to go to capture-dr
// 0 to go to shift-dr
#define RESET_JTAG_LEN 12
static const char RESET_TO_USER_DR[RESET_JTAG_LEN] = {
JTAG_CMD,
21, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TMS_MASK | PUT_TDI_MASK, // flags
(char)(0x0df), // TMS: Five ones, then one zero, and two ones -- low bits first
0x00, // TDI: irrelevant here
(char)0x80, // TMS: two zeros, then six zeros
0x08, // TDI: user command #1, bit reversed
0x03, // TMS: three ones, then two zeros
0x00 // TDI byte -- irrelevant here
//
// 0xc0, // TDI byte -- user command #2
// 0x40, // TDI: user command #1
// 0x0c, // TDI byte -- user command #2, bit reversed
};
 
//
// TMS:
#define TX_DR_LEN 12
static const char TX_DR_BITS[TX_DR_LEN] = {
JTAG_CMD,
48, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TDI_MASK, // flags
(char)0x0ff, 0, 0, 0, 0, 0 // Six data bytes
// module_id = 255
// 32'h(payload.length)
// payload
// module_id + payload.len + num_result_bits, length=32 + payload ???
};
 
//
// TMS:
//
#define REQ_RX_LEN 6
static const char REQ_RX_BITS[REQ_RX_LEN] = {
JTAG_CMD,
(const char)((USB_PKTLEN-REQ_RX_LEN)*8), // bits-requested
0,0,0, // Also clocks, higher order bits
GET_TDO_MASK|TDI_VAL_MASK, // flags:TDI is kept low here, so no TDI flag
// No data given, since there's no info to send or receive
// Leave the result in shift-DR mode
};
 
/*
#define RETURN_TO_RESET_LEN 7
static const char RETURN_TO_RESET[RETURN_TO_RESET_LEN] = {
JTAG_CMD,
5, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TMS_MASK, // flags
(char)0x0ff, // Five ones
};
*/
 
USBI::USBI(void) {
int config;
 
m_total_nread = 0;
 
if (0 != libusb_init(&m_usb_context)) {
fprintf(stderr, "Error initializing the USB library\n");
perror("O/S Err:");
exit(-1);
}
 
m_xula_usb_device = libusb_open_device_with_vid_pid(m_usb_context,
VENDOR_ID, PRODUCT_ID);
if (!m_xula_usb_device) {
fprintf(stderr, "Could not open XuLA device\n");
perror("O/S Err:");
 
libusb_exit(m_usb_context);
exit(-1);
}
 
if (0 != libusb_get_configuration(m_xula_usb_device, &config)) {
fprintf(stderr, "Could not get configuration\n");
perror("O/S Err:");
 
libusb_close(m_xula_usb_device);
libusb_exit(m_usb_context);
exit(-1);
}
 
if (0 != libusb_claim_interface(m_xula_usb_device, XESS_INTERFACE)) {
fprintf(stderr, "Could not claim interface\n");
perror("O/S Err:");
 
libusb_close(m_xula_usb_device);
libusb_exit(m_usb_context);
exit(-1);
}
 
unsigned char abuf[RESET_JTAG_LEN];
int actual_length = RESET_JTAG_LEN, r;
 
memcpy(abuf, RESET_TO_USER_DR, RESET_JTAG_LEN);
r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
abuf, RESET_JTAG_LEN, &actual_length, 4);
if ((r!=0)||(actual_length != RESET_JTAG_LEN)) {
// Try clearing the queue twice, then doing this
do {
r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_IN,
(unsigned char *)m_rxbuf, USB_PKTLEN, &actual_length, 20);
} while((r==0)&&(actual_length > 0));
 
r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
abuf, RESET_JTAG_LEN, &actual_length, 4);
if ((r != 0)||(actual_length != RESET_JTAG_LEN)) {
printf("Some error took place requesting RESET_TO_USER_DR\n");
printf("r = %d, actual_length = %d (vs %d requested)\n",
r, actual_length, RESET_JTAG_LEN);
perror("O/S Err");
exit(-2);
}
}
 
// Initialize our read FIFO
m_rbeg = m_rend = 0;
 
flush_read();
}
 
void USBI::close(void) {
// Release our interface
if (0 != libusb_release_interface(m_xula_usb_device, XESS_INTERFACE)) {
fprintf(stderr, "Could not release interface\n");
perror("O/S Err:");
 
libusb_close(m_xula_usb_device);
libusb_exit(m_usb_context);
exit(-1);
}
 
// And then close our device with
libusb_close(m_xula_usb_device);
 
// And just before exiting, we free our USB context
libusb_exit(m_usb_context);
}
 
void USBI::write(char *buf, int len) {
int r, actual_length;
 
if (len >= USB_PKTLEN) {
const int nv = USB_PKTLEN/2-1;
for(int pos=0; pos<len; pos+=nv)
write(&buf[pos], (len-pos>nv)?(nv):len-pos);
} else {
memset(m_txbuf, 0, len+6);
m_txbuf[0] = JTAG_CMD;
m_txbuf[1] = len * 8;
m_txbuf[2] = 0;
m_txbuf[3] = 0;
m_txbuf[4] = 0;
m_txbuf[5] = PUT_TDI_MASK | GET_TDO_MASK;
 
for(int i=0; i<len; i++)
m_txbuf[6+i] = buf[i];
r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
(unsigned char*)m_txbuf, len+6, &actual_length, 0);
if ((r!=0)||(actual_length != len+6)) {
printf("WRITE::(buf, %d) -- ERR\n", len+6);
printf("r = %d, actual_length = %d (!= %d requested)\n", r,
actual_length, len+6);
 
if (r == -7) {
r = libusb_bulk_transfer(m_xula_usb_device,
XESS_ENDPOINT_OUT,
(unsigned char*)m_txbuf, len+6,
&actual_length, 2);
if ((r!=0)||(actual_length != len+6)) {
printf("WRITE::(buf, %d) -- ERR\n", len+6);
printf("r = %d, actual_length = %d (!= %d requested)\n", r,
actual_length, len+6);
perror("O/S Err");
 
exit(-2);
}
} else {
perror("O/S Err");
exit(-2);
}
}
 
// Try to read back however many bytes we can
r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_IN,
(unsigned char*)m_rxbuf, USB_PKTLEN, &actual_length, 20);
if ((r==0)&&(actual_length > 0)) {
push_fifo(m_rxbuf, actual_length);
} else {
printf("Some error took place in receiving\n");
perror("O/S Err");
}
}
}
 
int USBI::read(char *buf, int len) {
return read(buf, len, 4);
}
 
int USBI::read(char *buf, int len, int timeout_ms) {
int left = len, nr=0;
 
// printf("USBI::read(%d) (FIFO is %d-%d)\n", len, m_rend, m_rbeg);
nr = pop_fifo(buf, left);
left -= nr;
while(left > 0) {
raw_read(left, timeout_ms);
nr = pop_fifo(buf, left);
left -= nr;
 
// printf("\tWHILE (nr = %d, LEFT = %d, len=%d)\n", nr, left, len);
if (nr == 0)
break;
}
 
// printf("READ %d characters (%d req, %d left)\n", len-left, len, left);
return len-left;
}
 
void USBI::raw_read(const int clen, int timeout_ms) {
int avail = (m_rbeg - m_rend)&(RCV_BUFMASK), actual_length;
int len = clen;
if (len > RCV_BUFMASK-avail)
len = RCV_BUFMASK-avail;
if (len > 26)
len = 26;
 
// printf("USBI::RAW-READ(%d, was %d)\n", len, clen);
memcpy(m_txbuf, REQ_RX_BITS, REQ_RX_LEN);
 
int r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
(unsigned char *)m_txbuf, REQ_RX_LEN, &actual_length,
timeout_ms);
if ((r==0)&&(actual_length == REQ_RX_LEN)) {
} else if (r == -7) {
// Nothing to read in the timeout provided
// We'll have to request this data again ... later
return;
} else {
printf("READ(WRITE,READ-REQ) -- ERR\n");
printf("r = %d, actual_length = %d (!= %d requested)\n", r,
actual_length, len+6);
perror("O/S Err");
exit(-2);
}
 
// Try to read back however many bytes we can
r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_IN,
(unsigned char *)m_rxbuf, USB_PKTLEN, &actual_length, 0);
if ((r==0)&&(actual_length > 0)) {
/*
printf("RAW-READ() -> %d Read\n", actual_length);
for(int i=0; i<actual_length; i++)
printf("%02x ", m_rxbuf[i] & 0x0ff);
printf("\n");
*/
push_fifo(m_rxbuf, actual_length);
} else if (r == -7) {
// Nothing to read in the timeout provided
// Return, adding nothing to our FIFO
} else {
printf("Some error took place in receiving\n");
perror("O/S Err");
}
 
// fprintf(stderr, "\tUSBI::RAW-READ() -- COMPLETE (%d avail)\n",
// (m_rbeg-m_rend)&(RCV_BUFMASK));
}
 
void USBI::flush_read(void) {
while(poll(4)) {
m_rbeg = m_rend = 0;
}
}
 
void USBI::push_fifo(char *buf, int len) {
char last = 0;
char *sptr = buf;
 
// printf("Pushing %d items onto FIFO (%d - %d)\n", len, m_rend, m_rbeg);
if (m_rbeg != m_rend)
last = m_rbuf[m_rend];
for(int i=0; i<len; i++) {
char v = *sptr++;
if (((v & 0x80)||((unsigned char)v < 0x10))&&(v == last)) {
// printf("\tSkipping: %02x\n", v & 0x0ff);
} else if ((unsigned char)v == 0x0ff) {
} else {
m_rbuf[m_rbeg] = v;
m_rbeg = (m_rbeg+1)&(RCV_BUFMASK);
// printf("\tPushing: %02x\n", v & 0x0ff);
} last = v;
}
}
 
int USBI::pop_fifo(char *buf, int len) {
int avail = (m_rbeg - m_rend)&(RCV_BUFMASK);
int left = len;
int nr = 0;
 
// printf("Attempting to pop %d items from FIFO (%d - %d)\n",
// len, m_rend, m_rbeg);
while((avail > 0)&&(left > 0)) {
int ln = RCV_BUFLEN-m_rend;
if (ln > left)
ln = left;
if (ln > avail)
ln = avail;
memcpy(&buf[len-left], &m_rbuf[m_rend], ln);
left -= ln;
avail -= ln;
m_rend = (m_rend + ln)&(RCV_BUFMASK);
nr += ln;
}
 
/*
if (nr > 0)
printf("\tPopped %d items, buf[0] = %02x (%d - %d)\n",
nr, buf[0], m_rend, m_rbeg);
else
printf("\tPopped nothing, %d - %d\n", m_rend, m_rbeg);
*/
return nr;
}
 
bool USBI::poll(unsigned ms) {
int avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
bool r = true;
 
// printf("POLL request\n");
 
if ((avail < 2)&&((avail<1)||(m_rbuf[m_rend]&0x80)||(m_rbuf[m_rend]<0x10))) {
raw_read(4,ms);
avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
// printf("%d availabe\n", avail);
 
char v = (m_rbuf[(m_rbeg-1)&(RCV_BUFMASK)]);
while(((v&0x80)==0)&&((unsigned)v>=0x10)&&(avail < RCV_BUFMASK-32)) {
raw_read(26,ms);
avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
}
if (avail < 1)
r = false;
else if ((avail==1)&&((m_rbuf[m_rend]&0x80)||(m_rbuf[m_rend]<0x10)))
r = false;
}
 
// printf("USBI::poll() -> %s (%d avail)\n", (r)?"true":"false", avail);
return r;
}
/trunk/sw/wbsettime.cpp
0,0 → 1,147
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbsettime.cpp
//
// Project: XuLA2 board
//
// Purpose: To give a user access, via a command line program, to set the
// real time clock within the FPGA.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <time.h>
 
#include "port.h"
#include "llcomms.h"
#include "regdefs.h"
 
DEVBUS *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
int main(int argc, char **argv) {
DEVBUS::BUSW v;
 
bool set_time = true, read_hack = false;
 
FPGAOPEN(m_fpga);
 
signal(SIGSTOP, closeup);
signal(SIGHUP, closeup);
 
 
time_t now, then;
 
// We first wait for a second change, because we don't know how
// much time this will take.
DEVBUS::BUSW clockword = 0l, dateword = 0l;
clockword = m_fpga->readio(R_CLOCK);
 
now = time(NULL);
while(time(NULL) == now)
;
 
if (set_time) {
// Now, we have one second to set the time
struct tm *tmp;
int sleepv = 0;
 
then = now+1;
tmp = localtime(&then);
clockword &= ~0x03fffff;
 
if (tmp->tm_sec != 0) {
// printf("THEN SECONDS = %d, ADDING %d\n",
// tmp->tm_sec, 60-tmp->tm_sec);
if (tmp->tm_sec < 58)
sleepv = 59 - tmp->tm_sec;
then += 60 - tmp->tm_sec;
tmp = localtime(&then);
// printf("Sleeping %d seconds (THEN->SEC = %d)\n", sleepv, tmp->tm_sec);
}
 
// printf("ORIGINAL : %02d:%02d:%02d\n", tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
// Seconds
clockword |= (((tmp->tm_sec)%10)&0x0f);
clockword |= (((tmp->tm_sec)/10)&0x0f)<< 4;
// Minutes
clockword |= (((tmp->tm_min)%10)&0x0f)<< 8;
clockword |= (((tmp->tm_min)/10)&0x0f)<<12;
// Hours
clockword |= (((tmp->tm_hour)%10)&0x0f)<<16;
clockword |= (((tmp->tm_hour)/10)&0x0f)<<20;
 
// Years
dateword = 0x00000000;
dateword |= (((tmp->tm_year+1900)/1000)&0x0f)<<28;
dateword |=((((tmp->tm_year+1900)/100 )%10)&0x0f)<<24;
dateword |=((((tmp->tm_year+1900)/10 )%10)&0x0f)<<20;
dateword |=((((tmp->tm_year+1900) )%10)&0x0f)<<16;
dateword |= (((tmp->tm_mon +1)/10)&0x0f)<<12;
dateword |= (((tmp->tm_mon +1)%10)&0x0f)<< 8;
dateword |= (((tmp->tm_mday )/10)&0x0f)<< 4;
dateword |= (((tmp->tm_mday )%10)&0x0f);
if (sleepv > 0)
sleep(sleepv);
 
while(time(NULL) < then)
;
m_fpga->writeio(R_CLOCK, clockword);
 
printf("Time set to %06x\n", clockword & 0x03fffff);
#ifdef R_DATE // If we have the date capability
m_fpga->writeio(R_DATE, dateword);
printf("Date set to %08x\n", dateword);
printf("(Now reads %08x)\n", m_fpga->readio(R_DATE));
#endif // R_DATE
 
now = then;
} if (read_hack) {
then = time(NULL) + 5;
while(time(NULL) < then)
;
clockword = m_fpga->readio(R_CLOCK);
printf("Hack : %08x\n", m_fpga->readio(R_TIMEHACK));
printf(" SUBS: %08x:%08x\n", m_fpga->readio(R_HACKHI), m_fpga->readio(R_HACKLO));
 
}
if (m_fpga->poll())
printf("FPGA was interrupted\n");
delete m_fpga;
}
 
/trunk/sw/llcomms.cpp
0,0 → 1,148
////////////////////////////////////////////////////////////////////////////////
//
// Filename: llcomms.cpp
//
// Project: XuLA2 board
//
// Purpose: This is the C++ program on the command side that will interact
// with a UART on an FPGA, both sending and receiving characters.
// Any bus interaction will call routines from this lower level
// library to accomplish the actual connection to and
// transmission to/from the board.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <assert.h>
#include <strings.h>
#include <poll.h>
#include <ctype.h>
 
#include "llcomms.h"
 
LLCOMMSI::LLCOMMSI(void) {
m_fdw = -1;
m_fdr = -1;
m_total_nread = 0l;
m_total_nwrit = 0l;
}
 
void LLCOMMSI::write(char *buf, int len) {
int nw;
nw = ::write(m_fdw, buf, len);
m_total_nwrit += nw;
assert(nw == len);
}
 
int LLCOMMSI::read(char *buf, int len) {
int nr;
nr = ::read(m_fdr, buf, len);
m_total_nread += nr;
return nr;
}
 
void LLCOMMSI::close(void) {
if(m_fdw>=0) ::close(m_fdw);
if((m_fdr>=0)&&(m_fdr != m_fdw)) ::close(m_fdr);
m_fdw = m_fdr = -1;
}
 
bool LLCOMMSI::poll(unsigned ms) {
struct pollfd fds;
 
fds.fd = m_fdr;
fds.events = POLLIN;
::poll(&fds, 1, ms);
 
if (fds.revents & POLLIN) {
return true;
} else return false;
}
 
TTYCOMMS::TTYCOMMS(const char *dev) {
m_fdr = ::open(dev, O_RDWR | O_NONBLOCK);
if (m_fdr < 0) {
printf("\n Error : Could not open %s\n", dev);
perror("O/S Err:");
exit(-1);
}
 
if (isatty(m_fdr)) {
struct termios tb;
tcgetattr(m_fdr, &tb);
cfmakeraw(&tb);
// tb.c_iflag &= (~(IXON|IXOFF));
tb.c_cflag &= (~(CRTSCTS));
tcsetattr(m_fdr, TCSANOW, &tb);
tcflow(m_fdr, TCOON);
}
 
m_fdw = m_fdr;
}
 
NETCOMMS::NETCOMMS(const char *host, const int port) {
struct sockaddr_in serv_addr;
struct hostent *hp;
 
if ((m_fdr = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Error : Could not create socket \n");
exit(-1);
}
 
memset(&serv_addr, '0', sizeof(serv_addr));
 
hp = gethostbyname(host);
if (hp == NULL) {
printf("Could not get host entity for %s\n", host);
perror("O/S Err:");
exit(-1);
}
bcopy(hp->h_addr, &serv_addr.sin_addr.s_addr, hp->h_length);
 
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
 
if (connect(m_fdr,(struct sockaddr *)&serv_addr, sizeof(serv_addr))< 0){
perror("Connect Failed Err");
exit(-1);
}
 
m_fdw = m_fdr;
}
 
/trunk/sw/usbi.h
0,0 → 1,53
#ifndef USBI_H
#define USBI_H
 
#include <libusb.h>
 
#define VENDOR_ID 0x04d8
#define PRODUCT_ID 0x0ff8c
#define XESS_INTERFACE 0
#define XESS_ENDPOINT_OUT 0x01
#define XESS_ENDPOINT_IN 0x81
#define XESS_ENDPOINT_IN 0x81
//
#define JTAG_CMD 0x4f
#define GET_TDO_MASK 0x01
#define PUT_TMS_MASK 0x02
#define TMS_VAL_MASK 0x04
#define PUT_TDI_MASK 0x08
#define TDI_VAL_MASK 0x10
//
// #define USER1_INSTR 0x02 // a SIX bit two
#define USB_PKTLEN 32
#define RCV_BUFLEN 512
#define RCV_BUFMASK (RCV_BUFLEN-1)
 
#include "llcomms.h"
 
class USBI : public LLCOMMSI { // USB Interface
private:
char m_rbuf[RCV_BUFLEN];
char m_txbuf[2*USB_PKTLEN], m_rxbuf[2*USB_PKTLEN];
int m_rbeg, m_rend;
 
libusb_context *m_usb_context;
libusb_device **m_usb_dev_list;
libusb_device_handle *m_xula_usb_device;
 
virtual int pop_fifo(char *buf, int len);
virtual void push_fifo(char *buf, int len);
virtual void raw_read(int len, int timeout_ms);
virtual void flush_read(void);
 
public:
USBI(void);
 
virtual void close(void);
virtual int read(char *buf, int len);
virtual int read(char *buf, int len, int timeout_ms);
virtual void write(char *buf, int len);
virtual bool poll(unsigned ms);
};
 
#endif // USBI_H
 
/trunk/sw/ramscope.cpp
0,0 → 1,188
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ramscope.cpp
//
// Project: XuLA2 board
//
// Purpose: To read out, and decompose, the results of the wishbone scope
// as applied to the ICAPE2 interaction.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "usbi.h"
#include "port.h"
#include "llcomms.h"
#include "regdefs.h"
 
#define WBSCOPE R_RAMSCOPE
#define WBSCOPEDATA R_RAMSCOPED
 
FPGA *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
unsigned brev(const unsigned v) {
unsigned int r, a;
a = v;
r = 0;
for(int i=0; i<8; i++) {
r <<= 1;
r |= (a&1);
a >>= 1;
} return r;
}
 
unsigned wrev(const unsigned v) {
unsigned r = brev(v&0x0ff);
r |= brev((v>>8)&0x0ff)<<8;
return r;
}
 
int main(int argc, char **argv) {
bool skipping = false;
unsigned v, lgln, scoplen;
DEVBUS::BUSW *buf;
 
FPGAOPEN(m_fpga);
 
signal(SIGSTOP, closeup);
signal(SIGHUP, closeup);
 
printf("Attempting to read address %08x\n", WBSCOPE);
v = m_fpga->readio(WBSCOPE);
if (0x60000000 != (v & 0x60000000)) {
printf("Scope is not yet ready:\n");
printf("\tRESET:\t\t%s\n", (v&0x80000000)?"Ongoing":"Complete");
printf("\tSTOPPED:\t%s\n", (v&0x40000000)?"Yes":"No");
printf("\tTRIGGERED:\t%s\n", (v&0x20000000)?"Yes":"No");
printf("\tPRIMED:\t\t%s\n", (v&0x10000000)?"Yes":"No");
printf("\tMANUAL:\t\t%s\n", (v&0x08000000)?"Yes":"No");
printf("\tDISABLED:\t%s\n", (v&0x04000000)?"Yes":"No");
printf("\tZERO:\t\t%s\n", (v&0x02000000)?"Yes":"No");
exit(0);
} else printf("SCOPD = %08x\n", v);
 
lgln = (v>>20) & 0x1f;
scoplen = (1<<lgln);
 
buf = new DEVBUS::BUSW[scoplen];
 
if (false) {
printf("Attempting vector read\n");
m_fpga->readz(WBSCOPEDATA, scoplen, buf);
 
printf("Vector read complete\n");
} else {
for(unsigned int i=0; i<scoplen; i++)
buf[i] = m_fpga->readio(WBSCOPEDATA);
}
 
for(unsigned int i=0; i<scoplen; i++) {
int cmd;
 
if ((i>0)&&(buf[i] == buf[i-1])&&
(i<scoplen-1)&&(buf[i] == buf[i+1])) {
if (!skipping)
printf(" ****\n");
skipping = true;
continue;
} skipping = false;
printf("%6d %08x:", i, buf[i]);
printf("S(%x) ", (buf[i]>>27)&0x0f);
if (buf[i] & 0x40000000)
printf("W "); else printf("R ");
printf("WB(%s%s%s%s%s",
(buf[i]&0x80000000)?"CYC":" ",
(buf[i]&0x40000000)?"STB":" ",
(buf[i]&0x20000000)?"WE":" ",
(buf[i]&0x10000000)?"ACK":" ",
(buf[i]&0x08000000)?"STL":" ");
//
if ((buf[i]&0xc8000000)==0xc0000000)
printf("*");
else
printf(" ");
printf(")-SD[%d%d%d%d,%d]",
(buf[i]&0x04000000)?1:0,
(buf[i]&0x02000000)?1:0,
(buf[i]&0x01000000)?1:0,
(buf[i]&0x00800000)?1:0,
(buf[i]&0x00600000)>>21);
cmd = (buf[i] >> 23)&0x0f;
if (buf[i]&0x00100000)
printf("<- ");
else
printf("-> ");
printf("%s", (buf[i]&0x00080000)?"P":" "); // Pending
printf("@%3x,", (buf[i]>>8)&0x07ff);
/*
printf(",%s%s%s%s%s",
(buf[i]&0x080)?"R":"-",
(buf[i]&0x040)?"P":".",
(buf[i]&0x020)?"P":".",
(buf[i]&0x010)?"P":".",
(buf[i]&0x008)?"P":".");
printf("/%x%x%x",
(buf[i]>>2)&0x01,
(buf[i]>>1)&0x01,
(buf[i]&0x01));
*/
printf("/%02x ", buf[i] & 0x0ff);
 
if (cmd & 0x8)
printf("(inactive)");
switch(cmd) {
case 0x01: printf("Refresh"); break;
case 0x02: printf("Precharge"); break;
case 0x03: printf("Activate"); break;
case 0x04: printf("Write"); break;
case 0x05: printf("Read"); break;
case 0x07: printf("NoOp"); break;
default: break;
}
 
printf("\n");
}
 
if (m_fpga->poll()) {
printf("FPGA was interrupted\n");
m_fpga->clear();
m_fpga->writeio(R_ICONTROL, SCOPEN);
}
delete m_fpga;
}
 
/trunk/sw/llcomms.h
0,0 → 1,67
////////////////////////////////////////////////////////////////////////////////
//
// Filename: llcomms.h
//
// Project: XuLA2 board
//
// Purpose: This is the C++ program on the command side that will interact
// with a UART on an FPGA, both sending and receiving characters.
// Any bus interaction will call routines from this lower level
// library to accomplish the actual connection to and
// transmission to/from the board.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#ifndef LLCOMMS_H
#define LLCOMMS_H
 
class LLCOMMSI {
protected:
int m_fdw, m_fdr;
LLCOMMSI(void);
public:
unsigned long m_total_nread, m_total_nwrit;
 
virtual ~LLCOMMSI(void) { close(); }
virtual void kill(void) { this->close(); };
virtual void close(void);
virtual void write(char *buf, int len);
virtual int read(char *buf, int len);
virtual bool poll(unsigned ms);
};
 
class TTYCOMMS : public LLCOMMSI {
public:
TTYCOMMS(const char *dev);
};
 
class NETCOMMS : public LLCOMMSI {
public:
NETCOMMS(const char *dev, const int port);
};
 
#endif
/trunk/sw/regdefs.cpp
0,0 → 1,183
////////////////////////////////////////////////////////////////////////////////
//
// Filename: regdefs.cpp
//
// Project: XuLA2 board
//
// Purpose: To give human readable names to the various registers available
// internal to the processor on the wishbone bus. This file is
// primarily used for name to number translation within wbregs.cpp.
// All names for a given register are equivalent, save only that the
// register will always be identified by its first name in any output.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include "regdefs.h"
 
const REGNAME raw_bregs[] = {
// { R_RESET, "RESET" },
// { R_STATUS, "STATUS" },
// { R_CONTROL, "CONTROL" },
{ R_VERSION, "VERSION" },
{ R_ICONTROL, "ICONTROL" },
{ R_ICONTROL, "INT" },
{ R_ICONTROL, "PIC" },
{ R_ICONTROL, "INTC" },
{ R_BUSERR, "BUSERR" },
{ R_BUSERR, "BUS" },
{ R_DATE, "DATE" },
{ R_GPIO, "GPIO" },
{ R_UART_CTRL, "UARTCTRL" },
{ R_UART_CTRL, "UART" },
{ R_PWM_INTERVAL,"PWMI" },
{ R_PWM_DATA, "PWMDATA" },
{ R_PWM_DATA, "PWM" },
{ R_UART_RX, "UART-RX" },
{ R_UART_RX, "RX" },
{ R_UART_TX, "UART-TX" },
{ R_UART_TX, "TX" },
//
{ R_SPIF_EREG, "SPIFEREG" },
{ R_SPIF_EREG, "SPIFE" },
{ R_SPIF_CREG, "SPIFCONF" },
{ R_SPIF_CREG, "SPIFC" },
{ R_SPIF_SREG, "SPIFSTAT" },
{ R_SPIF_SREG, "SPIFS" },
{ R_SPIF_IDREG, "SPIFID" },
{ R_SPIF_IDREG, "SPIFI" },
//
{ R_CLOCK, "CLOCK" },
{ R_CLOCK, "TIME" },
{ R_TIMER, "TIMER" },
{ R_STOPWATCH, "STOPWACH" },
{ R_STOPWATCH, "STOPWATCH" },
{ R_CKALARM, "CKALARM" },
{ R_CKALARM, "ALARM" },
{ R_CKSPEED, "CKSPEED" },
{ R_TIMEHACK, "TIMEHACK" },
{ R_TIMEHACK, "HACK" },
{ R_HACKHI, "HACKHI" },
{ R_HACKLO, "HACKLO" },
{ R_TIMEHACK, "HACK" },
// Scopes are defined and come and go. Be aware, therefore, not all
// of these scopes may be defined at the same time.
{ R_QSCOPE, "SCOPE" },
{ R_QSCOPE, "SCOP" },
{ R_QSCOPED, "SCOPDATA" },
{ R_QSCOPED, "SCDATA" },
{ R_CFGSCOPE, "CFGSCOPE" },
{ R_CFGSCOPE, "CFGSCOP" },
{ R_CFGSCOPED, "CFGSCOPD" },
{ R_CPUSCOPE, "CPUSCOPE" },
{ R_CPUSCOPE, "CPUSCOP" },
{ R_CPUSCOPED, "CPUSCOPD" },
{ R_RAMSCOPE, "MEMSCOPE" },
{ R_RAMSCOPE, "MEMSCOP" },
{ R_RAMSCOPED, "MEMSCOPD" },
{ R_RAMSCOPE, "RAMSCOPE" },
{ R_RAMSCOPE, "RAMSCOP" },
{ R_RAMSCOPED, "RAMSCOPD" },
//
// For working with the ICAPE interface ... if I can ever get a
// testing environment suitable to prove that it works.
//
{ R_CFG_CRC, "FPGACRC" },
{ R_CFG_FAR_MAJ, "FPGAFARH" },
{ R_CFG_FAR_MIN, "FPGAFARL" },
{ R_CFG_FDRI, "FPGAFDRI" },
{ R_CFG_FDRO, "FPGAFDRO" },
{ R_CFG_CMD, "FPGACMD" },
{ R_CFG_CTL, "FPGACTL" },
{ R_CFG_MASK, "FPGAMASK" },
{ R_CFG_STAT, "FPGASTAT" },
{ R_CFG_LOUT, "FPGALOUT" },
{ R_CFG_COR1, "FPGACOR1" },
{ R_CFG_COR2, "FPGACOR2" },
{ R_CFG_PWRDN, "FPGAPWRDN" },
{ R_CFG_FLR, "FPGAFLR" },
{ R_CFG_IDCODE, "FPGAIDCODE" },
{ R_CFG_CWDT, "FPGACWDT" },
{ R_CFG_HCOPT, "FPGAHCOPT" },
{ R_CFG_CSBO, "FPGACSBO" },
{ R_CFG_GEN1, "FPGAGEN1" },
{ R_CFG_GEN2, "FPGAGEN2" },
{ R_CFG_GEN3, "FPGAGEN3" },
{ R_CFG_GEN4, "FPGAGEN4" },
{ R_CFG_GEN5, "FPGAGEN5" },
{ R_CFG_MODE, "FPGAMODE" },
{ R_CFG_GWE, "FPGAGWE" },
{ R_CFG_GTS, "FPGAGTS" },
{ R_CFG_MFWR, "FPGAMFWR" },
{ R_CFG_CCLK, "FPGACCLK" },
{ R_CFG_SEU, "FPGASEU" },
{ R_CFG_EXP, "FPGAEXP" },
{ R_CFG_RDBK, "FPGARDBK" },
{ R_CFG_BOOTSTS, "BOOTSTS" },
{ R_CFG_EYE, "FPGAEYE" },
{ R_CFG_CBC, "FPGACBC" },
//
//
{ R_ZIPCTRL, "ZIPCTRL" },
{ R_ZIPCTRL, "ZIPC" },
{ R_ZIPCTRL, "CPU" },
{ R_ZIPCTRL, "CPUC" },
{ R_ZIPDATA, "ZIPDATA" },
{ R_ZIPDATA, "ZIPD" },
{ R_ZIPDATA, "CPUD" },
//
{ RAMBASE, "MEM" },
{ SPIFLASH, "FLASH" },
{ SDRAMBASE, "SDRAM" },
{ SDRAMBASE, "RAM" }
};
 
#define RAW_NREGS (sizeof(raw_bregs)/sizeof(bregs[0]))
 
const REGNAME *bregs = raw_bregs;
const int NREGS = RAW_NREGS;
 
unsigned addrdecode(const char *v) {
if (isalpha(v[0])) {
for(int i=0; i<NREGS; i++)
if (strcasecmp(v, bregs[i].m_name)==0)
return bregs[i].m_addr;
fprintf(stderr, "Unknown register: %s\n", v);
exit(-2);
} else
return strtoul(v, NULL, 0);
}
 
const char *addrname(const unsigned v) {
for(int i=0; i<NREGS; i++)
if (bregs[i].m_addr == v)
return bregs[i].m_name;
return NULL;
}
 
/trunk/sw/zipdbg.cpp
0,0 → 1,500
///////////////////////////////////////////////////////////////////////////////
//
// Filename: zipdbg.cpp
//
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
//
// Purpose:
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Tecnology, LLC
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////////
//
//
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
 
#include <ctype.h>
#include <ncurses.h>
 
#include "zopcodes.h"
#include "zparser.h"
#include "devbus.h"
#include "regdefs.h"
 
#include "usbi.h"
#include "port.h"
 
#define CMD_REG 0
#define CMD_DATA 1
#define CMD_HALT (1<<10)
#define CMD_STALL (1<<9)
#define CMD_STEP (1<<8)
#define CMD_INT (1<<7)
#define CMD_RESET (1<<6)
 
#define KEY_ESCAPE 27
#define KEY_RETURN 10
#define CTRL(X) ((X)&0x01f)
 
#define MAXERR 1000 // 1k cycles
 
bool gbl_err = false;
 
// No particular "parameters" need definition or redefinition here.
class ZIPPY : public DEVBUS {
typedef DEVBUS::BUSW BUSW;
DEVBUS *m_fpga;
int m_cursor;
public:
ZIPPY(DEVBUS *fpga) : m_fpga(fpga), m_cursor(0) {}
 
void kill(void) { m_fpga->kill(); }
void close(void) { m_fpga->close(); }
void writeio(const BUSW a, const BUSW v) { m_fpga->writeio(a, v); }
BUSW readio(const BUSW a) { return m_fpga->readio(a); }
void readi(const BUSW a, const int len, BUSW *buf) {
return m_fpga->readi(a, len, buf); }
void readz(const BUSW a, const int len, BUSW *buf) {
return m_fpga->readz(a, len, buf); }
void writei(const BUSW a, const int len, const BUSW *buf) {
return m_fpga->writei(a, len, buf); }
void writez(const BUSW a, const int len, const BUSW *buf) {
return m_fpga->writez(a, len, buf); }
bool poll(void) { return m_fpga->poll(); }
void usleep(unsigned ms) { m_fpga->usleep(ms); }
void wait(void) { m_fpga->wait(); }
bool bus_err(void) const { return m_fpga->bus_err(); }
void reset_err(void) { m_fpga->reset_err(); }
void clear(void) { m_fpga->clear(); }
 
void reset(void) { writeio(R_ZIPCTRL, CPU_RESET|CPU_HALT); }
void step(void) { writeio(R_ZIPCTRL, CPU_STEP); }
void go(void) { writeio(R_ZIPCTRL, CPU_GO); }
void halt(void) { writeio(R_ZIPCTRL, CPU_HALT); }
bool stalled(void) { return ((readio(R_ZIPCTRL)&CPU_STALL)==0); }
 
void showval(int y, int x, const char *lbl, unsigned int v, bool c) {
if (c)
mvprintw(y,x, ">%s> 0x%08x<", lbl, v);
else
mvprintw(y,x, " %s: 0x%08x ", lbl, v);
}
 
void dispreg(int y, int x, const char *n, unsigned int v, bool c) {
// 4,4,8,1 = 17 of 20, +2 = 18
if (c)
mvprintw(y, x, ">%s> 0x%08x<", n, v);
else
mvprintw(y, x, " %s: 0x%08x ", n, v);
}
 
void showins(int y, const char *lbl,
const int gie, const unsigned int pc) {
char line[80];
unsigned int v;
 
mvprintw(y, 0, "%s: 0x%08x", lbl, pc);
 
if (gie) attroff(A_BOLD);
else attron(A_BOLD);
 
line[0] = '\0';
try {
v= readio(pc);
zipi_to_string(v, line);
printw(" 0x%08x", v);
printw(" %-24s", &line[1]);
} catch(BUSERR b) {
printw(" 0x%08x %-24s", b.addr, "(Bus Error)");
}
attroff(A_BOLD);
}
 
unsigned int cmd_read(unsigned int a) {
int errcount = 0;
 
if (gbl_err)
return 0;
 
writeio(R_ZIPCTRL, CMD_HALT|(a&0x3f));
while(((readio(R_ZIPCTRL) & CPU_STALL) == 0)&&(errcount < MAXERR))
errcount++;
if (errcount < MAXERR)
return readio(R_ZIPDATA);
else {
gbl_err = true;
return 0;
}
}
 
void cmd_write(unsigned int a, int v) {
if (gbl_err)
return;
 
int errcount = 0;
writeio(R_ZIPCTRL, CMD_HALT|(a&0x3f));
while(((readio(R_ZIPCTRL) & CPU_STALL) == 0)&&(errcount < MAXERR))
errcount++;
if (errcount < MAXERR)
writeio(R_ZIPDATA, (unsigned int)v);
else
gbl_err = true;
}
 
void read_state(void) {
int ln= 0;
bool gie;
 
if (m_cursor < 0)
m_cursor = 0;
else if (m_cursor >= 44)
m_cursor = 43;
 
mvprintw(ln,0, "Peripherals");
mvprintw(ln,40,"%-40s", "CPU State: ");
{
unsigned int v = readio(R_ZIPCTRL);
mvprintw(ln,51, "");
if (v & 0x010000)
printw("EXT-INT ");
if ((v & 0x003000) == 0x03000)
printw("Halted ");
else if (v & 0x001000)
printw("Sleeping ");
else if (v & 0x002000)
printw("Supervisor Mod ");
if (v & 0x008000)
printw("Break-Enabled ");
if (v & 0x000080)
printw("PIC Enabled ");
} ln++;
showval(ln, 0, "PIC ", cmd_read(32+ 0), (m_cursor==0));
showval(ln,20, "WDT ", cmd_read(32+ 1), (m_cursor==1));
showval(ln,40, "WBUS", cmd_read(32+ 2), (m_cursor==2));
showval(ln,60, "PIC2", cmd_read(32+ 3), (m_cursor==3));
ln++;
showval(ln, 0, "TMRA", cmd_read(32+ 4), (m_cursor==4));
showval(ln,20, "TMRB", cmd_read(32+ 5), (m_cursor==5));
showval(ln,40, "TMRC", cmd_read(32+ 6), (m_cursor==6));
showval(ln,60, "JIF ", cmd_read(32+ 7), (m_cursor==7));
 
ln++;
showval(ln, 0, "UTSK", cmd_read(32+12), (m_cursor==8));
showval(ln,20, "UMST", cmd_read(32+13), (m_cursor==9));
showval(ln,40, "UPST", cmd_read(32+14), (m_cursor==10));
showval(ln,60, "UICT", cmd_read(32+15), (m_cursor==11));
 
ln++;
ln++;
unsigned int cc = cmd_read(14);
gie = (cc & 0x020);
if (gie)
attroff(A_BOLD);
else
attron(A_BOLD);
mvprintw(ln, 0, "Supervisor Registers");
ln++;
 
dispreg(ln, 0, "sR0 ", cmd_read(0), (m_cursor==12));
dispreg(ln,20, "sR1 ", cmd_read(1), (m_cursor==13));
dispreg(ln,40, "sR2 ", cmd_read(2), (m_cursor==14));
dispreg(ln,60, "sR3 ", cmd_read(3), (m_cursor==15)); ln++;
 
dispreg(ln, 0, "sR4 ", cmd_read(4), (m_cursor==16));
dispreg(ln,20, "sR5 ", cmd_read(5), (m_cursor==17));
dispreg(ln,40, "sR6 ", cmd_read(6), (m_cursor==18));
dispreg(ln,60, "sR7 ", cmd_read(7), (m_cursor==19)); ln++;
 
dispreg(ln, 0, "sR8 ", cmd_read( 8), (m_cursor==20));
dispreg(ln,20, "sR9 ", cmd_read( 9), (m_cursor==21));
dispreg(ln,40, "sR10", cmd_read(10), (m_cursor==22));
dispreg(ln,60, "sR11", cmd_read(11), (m_cursor==23)); ln++;
 
dispreg(ln, 0, "sR12", cmd_read(12), (m_cursor==24));
dispreg(ln,20, "sSP ", cmd_read(13), (m_cursor==25));
 
mvprintw(ln,40, "%csCC :%s%s%s%s%s%s%s%s",
(m_cursor==26)?'>':' ',
(cc & 0x100)?"TP":" ",
(cc & 0x040)?"ST":" ",
(cc & 0x020)?"IE":" ",
(cc & 0x010)?"SL":" ",
(cc&8)?"V":" ",
(cc&4)?"N":" ",
(cc&2)?"C":" ",
(cc&1)?"Z":" ");
dispreg(ln,60, "sPC ", cmd_read(15), (m_cursor==27));
ln++;
 
if (gie)
attron(A_BOLD);
else
attroff(A_BOLD);
mvprintw(ln, 0, "User Registers"); ln++;
dispreg(ln, 0, "uR0 ", cmd_read(16), (m_cursor==28));
dispreg(ln,20, "uR1 ", cmd_read(17), (m_cursor==29));
dispreg(ln,40, "uR2 ", cmd_read(18), (m_cursor==30));
dispreg(ln,60, "uR3 ", cmd_read(19), (m_cursor==31)); ln++;
 
dispreg(ln, 0, "uR4 ", cmd_read(20), (m_cursor==32));
dispreg(ln,20, "uR5 ", cmd_read(21), (m_cursor==33));
dispreg(ln,40, "uR6 ", cmd_read(22), (m_cursor==34));
dispreg(ln,60, "uR7 ", cmd_read(23), (m_cursor==35)); ln++;
 
dispreg(ln, 0, "uR8 ", cmd_read(24), (m_cursor==36));
dispreg(ln,20, "uR9 ", cmd_read(25), (m_cursor==37));
dispreg(ln,40, "uR10", cmd_read(26), (m_cursor==38));
dispreg(ln,60, "uR11", cmd_read(27), (m_cursor==39)); ln++;
 
dispreg(ln, 0, "uR12", cmd_read(28), (m_cursor==40));
dispreg(ln,20, "uSP ", cmd_read(29), (m_cursor==41));
cc = cmd_read(30);
mvprintw(ln,40, "%cuCC :%s%s%s%s%s%s%s%s",
(m_cursor == 42)?'>':' ',
(cc&0x100)?"TP":" ",
(cc&0x040)?"ST":" ",
(cc&0x020)?"IE":" ",
(cc&0x010)?"SL":" ",
(cc&8)?"V":" ",
(cc&4)?"N":" ",
(cc&2)?"C":" ",
(cc&1)?"Z":" ");
dispreg(ln,60, "uPC ", cmd_read(31), (m_cursor==43));
 
attroff(A_BOLD);
ln+=2;
 
ln+=3;
BUSW pc = cmd_read((gie)?31:15);
showins(ln, "I ", gie, pc+2); ln++;
showins(ln, "Dc", gie, pc+1); ln++;
showins(ln, "Op", gie, pc ); ln++;
showins(ln, "Al", gie, pc-1); ln++;
}
 
void cursor_up(void) {
if (m_cursor > 3)
m_cursor -= 4;
} void cursor_down(void) {
if (m_cursor < 40)
m_cursor += 4;
} void cursor_left(void) {
if (m_cursor > 0)
m_cursor--;
else m_cursor = 43;
} void cursor_right(void) {
if (m_cursor < 43)
m_cursor++;
else m_cursor = 0;
}
 
int cursor(void) { return m_cursor; }
};
 
FPGA *m_fpga;
 
void get_value(ZIPPY *zip) {
int wy, wx, ra;
int c = zip->cursor();
 
wx = (c & 0x03) * 20 + 9 + 1;
wy = (c >> 2);
if (wy >= 3+4)
wy++;
if (wy > 3)
wy += 2;
wy++;
 
if (c >= 12)
ra = c - 12;
else
ra = c + 32;
 
bool done = false;
char str[16];
int pos = 0; str[pos] = '\0';
while(!done) {
int chv = getch();
switch(chv) {
case KEY_ESCAPE:
pos = 0; str[pos] = '\0'; done = true;
break;
case KEY_RETURN: case KEY_ENTER: case KEY_UP: case KEY_DOWN:
done = true;
break;
case KEY_LEFT: case KEY_BACKSPACE:
if (pos > 0) pos--;
break;
case KEY_CLEAR:
pos = 0;
break;
case '0': case ' ': str[pos++] = '0'; break;
case '1': str[pos++] = '1'; break;
case '2': str[pos++] = '2'; break;
case '3': str[pos++] = '3'; break;
case '4': str[pos++] = '4'; break;
case '5': str[pos++] = '5'; break;
case '6': str[pos++] = '6'; break;
case '7': str[pos++] = '7'; break;
case '8': str[pos++] = '8'; break;
case '9': str[pos++] = '9'; break;
case 'A': case 'a': str[pos++] = 'A'; break;
case 'B': case 'b': str[pos++] = 'B'; break;
case 'C': case 'c': str[pos++] = 'C'; break;
case 'D': case 'd': str[pos++] = 'D'; break;
case 'E': case 'e': str[pos++] = 'E'; break;
case 'F': case 'f': str[pos++] = 'F'; break;
}
 
if (pos > 8)
pos = 8;
str[pos] = '\0';
 
attron(A_NORMAL | A_UNDERLINE);
mvprintw(wy, wx, "%-8s", str);
if (pos > 0) {
attron(A_NORMAL | A_UNDERLINE | A_BLINK);
mvprintw(wy, wx+pos-1, "%c", str[pos-1]);
}
attrset(A_NORMAL);
}
 
if (pos > 0) {
int v;
v = strtoul(str, NULL, 16);
zip->cmd_write(ra, v);
}
}
 
void on_sigint(int v) {
endwin();
 
fprintf(stderr, "Interrupted!\n");
exit(-2);
}
 
int main(int argc, char **argv) {
// FPGAOPEN(m_fpga);
ZIPPY *zip; //
 
int skp=0, port = FPGAPORT;
bool use_usb = true;
 
skp=1;
for(int argn=0; argn<argc-skp; argn++) {
if (argv[argn+skp][0] == '-') {
if (argv[argn+skp][1] == 'u')
use_usb = true;
else if (argv[argn+skp][1] == 'p') {
use_usb = false;
if (isdigit(argv[argn+skp][2]))
port = atoi(&argv[argn+skp][2]);
}
skp++; argn--;
} else
argv[argn] = argv[argn+skp];
} argc -= skp;
 
if (use_usb)
m_fpga = new FPGA(new USBI());
else
m_fpga = new FPGA(new NETCOMMS(FPGAHOST, port));
zip = new ZIPPY(m_fpga);
 
 
initscr();
raw();
noecho();
keypad(stdscr, true);
 
signal(SIGINT, on_sigint);
 
int chv;
bool done = false;
 
zip->halt();
for(int i=0; (i<5)&&(zip->stalled()); i++)
;
if (!zip->stalled())
zip->read_state();
while((!done)&&(!gbl_err)) {
chv = getch();
switch(chv) {
case 'g': case 'G':
m_fpga->writeio(R_ZIPCTRL, CPU_GO);
// We just released the CPU, so we're now done.
done = true;
break;
case 'l': case 'L': case CTRL('L'):
redrawwin(stdscr);
break;
case 'q': case 'Q': case CTRL('C'):
case KEY_CANCEL: case KEY_CLOSE: case KEY_EXIT:
case KEY_ESCAPE:
done = true;
break;
case 'r': case 'R':
zip->reset();
erase();
break;
case 's': case 'S':
zip->step();
zip->read_state();
break;
case KEY_IC: case KEY_ENTER:
get_value(zip);
break;
case KEY_UP:
zip->cursor_up();
break;
case KEY_DOWN:
zip->cursor_down();
break;
case KEY_LEFT:
zip->cursor_left();
break;
case KEY_RIGHT:
zip->cursor_right();
break;
case ERR: case KEY_CLEAR:
default:
;
}
 
if ((!done)&&(!gbl_err)) {
if (zip->stalled())
erase();
}
}
 
endwin();
 
if (gbl_err) {
printf("Killed on error: could not access bus!\n");
exit(-2);
}
}
 
/trunk/sw/cpuscope.cpp
0,0 → 1,170
//
//
// Filename: cpuscope.cpp
//
// Project: FPGA library development (Basys-3 development board)
//
// Purpose: To read out, and decompose, the results of the wishbone scope
// as applied to the ICAPE2 interaction.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
//
// Copyright: 2015
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "usbi.h"
#include "port.h"
#include "llcomms.h"
#include "regdefs.h"
 
#define WBSCOPE R_CPUSCOPE
#define WBSCOPEDATA R_CPUSCOPED
 
#include "zopcodes.h"
 
FPGA *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
unsigned brev(const unsigned v) {
unsigned int r, a;
a = v;
r = 0;
for(int i=0; i<8; i++) {
r <<= 1;
r |= (a&1);
a >>= 1;
} return r;
}
 
unsigned wrev(const unsigned v) {
unsigned r = brev(v&0x0ff);
r |= brev((v>>8)&0x0ff)<<8;
return r;
}
 
int main(int argc, char **argv) {
FPGAOPEN(m_fpga);
 
signal(SIGSTOP, closeup);
signal(SIGHUP, closeup);
 
unsigned v, lgln, scoplen;
printf("Attempting to read address %08x\n", WBSCOPE);
v = m_fpga->readio(WBSCOPE);
if (0x60000000 != (v & 0x60000000)) {
printf("Scope is not yet ready:\n");
printf("\tRESET:\t\t%s\n", (v&0x80000000)?"Ongoing":"Complete");
printf("\tSTOPPED:\t%s\n", (v&0x40000000)?"Yes":"No");
printf("\tTRIGGERED:\t%s\n", (v&0x20000000)?"Yes":"No");
printf("\tPRIMED:\t\t%s\n", (v&0x10000000)?"Yes":"No");
printf("\tMANUAL:\t\t%s\n", (v&0x08000000)?"Yes":"No");
printf("\tDISABLED:\t%s\n", (v&0x04000000)?"Yes":"No");
printf("\tZERO:\t\t%s\n", (v&0x02000000)?"Yes":"No");
exit(0);
} else printf("SCOPD = %08x\n", v);
 
lgln = (v>>20) & 0x1f;
scoplen = (1<<lgln);
 
DEVBUS::BUSW *buf;
buf = new DEVBUS::BUSW[scoplen];
 
if (false) {
printf("Attempting vector read\n");
m_fpga->readz(WBSCOPEDATA, scoplen, buf);
 
printf("Vector read complete\n");
} else {
for(unsigned int i=0; i<scoplen; i++)
buf[i] = m_fpga->readio(WBSCOPEDATA);
}
 
for(unsigned int i=0; i<scoplen; i++) {
char sbuf[64];
 
if ((i>0)&&(buf[i] == buf[i-1])&&
(i<scoplen-1)&&(buf[i] == buf[i+1]))
continue;
printf("%6d %08x:", i, buf[i]);
 
unsigned addr = (buf[i]>>24)&0x0ff;
zipi_to_string(m_fpga->readio(0x02000+addr),sbuf);
printf(" %2x %-24s", (buf[i]>>24)&0x0ff, sbuf);
printf(" %s%s%s%s%s %s%s%s",
((buf[i]>>23)&1)?"P":" ",
((buf[i]>>22)&1)?"D":" ",
((buf[i]>>21)&1)?"O":" ",
((buf[i]>>20)&1)?"A":" ",
((buf[i]>>19)&1)?"M":" ",
((buf[i]>>18)&1)?"o":" ",
((buf[i]>>17)&1)?"a":" ",
((buf[i]>>16)&1)?"m":" ");
printf(" A=%02x ", (buf[i]>>8)&0x0ff);
printf(" %s%02x ",
(((buf[i]>>16)&3)!=0)?"W->":"(w)",
(buf[i]&0x0ff));
/*
printf("%s", ((buf[i]>>31)&1)?"OpV":" ");
printf("%s", ((buf[i]>>30)&1)?"opA":" ");
printf("%s", ((buf[i]>>29)&1)?"AlV":" ");
printf("%s", ((buf[i]>>28)&1)?"AlW":" ");
printf("%s", ((buf[i]>>27)&1)?"opM":" ");
printf("%s", ((buf[i]>>26)&1)?"MmV":" ");
if (true) {
int op = (buf[i]>>22)&0x0f;
switch(op) {
case 0: printf("CMP "); break;
case 1: printf("TST "); break;
case 2: printf("MOV "); break;
case 3: printf("LDI "); break;
case 4: printf("AUX "); break;
case 5: printf("ROL "); break;
case 6: printf("LOD "); break;
case 7: printf("STO "); break;
case 8: printf("SUB "); break;
case 9: printf("AND "); break;
case 10: printf("ADD "); break;
case 11: printf(" OR "); break;
case 12: printf("XOR "); break;
case 13: printf("LSL "); break;
case 14: printf("ASR "); break;
case 15: printf("LSR "); break;
default: printf("ILL "); break;
}
} else
printf("%x", (buf[i]>>22)&0x0f);
printf(" %s", ((buf[i]>>21)&1)?"W":" ");
if ((buf[i]>>21)&1)
printf("[%X]", ((buf[i]>>17)&0x0f));
else
printf("(%x)", ((buf[i]>>17)&0x0f));
printf("D[%X]", ((buf[i]>>13)&0x0f));
printf(" r_opA=..%02x", (buf[i]>>7)&0x3f);
printf(" opA=..%02x", (buf[i]>>1)&0x3f);
printf(" ALU=..%d", buf[i]&1);
*/
 
printf("\n");
}
 
if (m_fpga->poll()) {
printf("FPGA was interrupted\n");
m_fpga->clear();
m_fpga->writeio(R_ICONTROL, SCOPEN);
}
delete m_fpga;
}
 
/trunk/sw/dumpflash.cpp
0,0 → 1,107
////////////////////////////////////////////////////////////////////////////////
//
// Filename: dumpflash.cpp
//
// Project: XuLA2 board
//
// Purpose: Read/Empty the entire contents of the flash memory to a file.
// The flash is unchanged by this process.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "port.h"
#include "regdefs.h"
 
FPGA *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
// #define DUMPMEM RAMBASE
// #define DUMPWORDS MEMWORDS
 
#define DUMPMEM SPIFLASH
#define DUMPWORDS FLASHWORDS // 1MB Flash
 
int main(int argc, char **argv) {
FILE *fp;
const int BUFLN = MEMWORDS; // 1MB Flash
FPGA::BUSW *buf = new FPGA::BUSW[BUFLN];
 
FPGAOPEN(m_fpga);
fprintf(stderr, "Before starting, nread = %ld\n",
m_fpga->m_total_nread);
 
// Start with testing the version:
printf("VERSION: %08x\n", m_fpga->readio(R_VERSION));
 
// SPI flash testing
// Enable the faster (vector) reads
bool vector_read = false;
unsigned sz;
 
if (vector_read) {
m_fpga->readi(DUMPMEM, BUFLN, buf);
} else {
for(int i=0; i<BUFLN; i++) {
buf[i] = m_fpga->readio(DUMPMEM+i);
// if (0 == (i&0x0ff))
printf("i = %02x / %04x, addr = i + %04x = %08x\n", i, BUFLN, DUMPMEM, i+DUMPMEM);
}
}
printf("\nREAD-COMPLETE\n");
 
// Now, let's find the end
sz = BUFLN-1;
while((sz>0)&&(buf[sz] == 0xffffffff))
sz--;
sz+=1;
printf("The size of the buffer is 0x%06x or %d words\n", sz, sz);
 
fp = fopen("spiftest.bin","w");
fwrite(buf, sizeof(buf[0]), sz, fp);
fclose(fp);
 
printf("The read was accomplished in %ld bytes over the UART\n",
m_fpga->m_total_nread);
 
if (m_fpga->poll())
printf("FPGA was interrupted\n");
delete m_fpga;
}
 
 
/trunk/sw/regdefs.h
0,0 → 1,197
////////////////////////////////////////////////////////////////////////////////
//
// Filename: regdefs.h
//
// Project: XuLA2 board
//
// Purpose:
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef REGDEFS_H
#define REGDEFS_H
 
// #define R_RESET 0x00000100
// #define R_STATUS 0x00000101
// #define R_CONTROL 0x00000101
#define R_VERSION 0x00000102
#define R_ICONTROL 0x00000103
#define R_BUSERR 0x00000104
#define R_DATE 0x00000105
#define R_GPIO 0x00000106
#define R_UART_CTRL 0x00000107
#define R_PWM_INTERVAL 0x00000108
#define R_PWM_DATA 0x00000109
#define R_UART_RX 0x0000010a
#define R_UART_TX 0x0000010b
#define R_SPIF_EREG 0x0000010c
#define R_SPIF_CREG 0x0000010d
#define R_SPIF_SREG 0x0000010e
#define R_SPIF_IDREG 0x0000010f
#define R_CLOCK 0x00000110
#define R_TIMER 0x00000111
#define R_STOPWATCH 0x00000112
#define R_CKALARM 0x00000113
#define R_CKSPEED 0x00000114
#define R_TIMEHACK 0x00000115
#define R_HACKHI 0x00000116
#define R_HACKLO 0x00000117
 
// GPS registers
// 0x00000114
// 0x00000115
// 0x00000116
// 0x00000117
 
// WB Scope registers wb_addr[31:3]==30'h23, i.e. 46, 8c, 118
#define R_QSCOPE 0x00000118 // Quad SPI scope ctrl
#define R_QSCOPED 0x00000119 // and data
#define R_CFGSCOPE 0x0000011a // Configuration/ICAPE scope control
#define R_CFGSCOPED 0x0000011b // and data
#define R_RAMSCOPE 0x0000011c // SDRAM scope control
#define R_RAMSCOPED 0x0000011d // and data
#define R_CPUSCOPE 0x0000011e // SDRAM scope control
#define R_CPUSCOPED 0x0000011f // and data
//
// SD Card
// 0x00000120
// 0x00000121
// 0x00000122
// 0x00000123
//
// Unused/open
// #define SOMETHING 0x00000124 -- 0x013f (28 spaces)
//
// FPGA CONFIG/ICAP REGISTERS
#define R_CFG_CRC 0x00000140
#define R_CFG_FAR_MAJ 0x00000141
#define R_CFG_FAR_MIN 0x00000142
#define R_CFG_FDRI 0x00000143
#define R_CFG_FDRO 0x00000144
#define R_CFG_CMD 0x00000145
#define R_CFG_CTL 0x00000146
#define R_CFG_MASK 0x00000147
#define R_CFG_STAT 0x00000148
#define R_CFG_LOUT 0x00000149
#define R_CFG_COR1 0x0000014a
#define R_CFG_COR2 0x0000014b
#define R_CFG_PWRDN 0x0000014c
#define R_CFG_FLR 0x0000014d
#define R_CFG_IDCODE 0x0000014e
#define R_CFG_CWDT 0x0000014f
#define R_CFG_HCOPT 0x00000150
#define R_CFG_CSBO 0x00000152
#define R_CFG_GEN1 0x00000153
#define R_CFG_GEN2 0x00000154
#define R_CFG_GEN3 0x00000155
#define R_CFG_GEN4 0x00000156
#define R_CFG_GEN5 0x00000157
#define R_CFG_MODE 0x00000158
#define R_CFG_GWE 0x00000159
#define R_CFG_GTS 0x0000015a
#define R_CFG_MFWR 0x0000015b
#define R_CFG_CCLK 0x0000015c
#define R_CFG_SEU 0x0000015d
#define R_CFG_EXP 0x0000015e
#define R_CFG_RDBK 0x0000015f
#define R_CFG_BOOTSTS 0x00000160
#define R_CFG_EYE 0x00000161
#define R_CFG_CBC 0x00000162
 
// RAM memory space
#define RAMBASE 0x00002000
#define MEMWORDS (1<<13)
// Flash memory space
#define SPIFLASH 0x00040000
#define FLASHWORDS (1<<18)
// SDRAM memory space
#define SDRAMBASE 0x00800000
// Zip CPU Control and Debug registers
#define R_ZIPCTRL 0x01000000
#define R_ZIPDATA 0x01100001
 
 
// Interrupt control constants
#define GIE 0x80000000 // Enable all interrupts
#define ISPIF_EN 0x80040004 // Enable all, enable SPI, clear SPI
#define ISPIF_DIS 0x00040000 // Disable all, disable SPI
#define ISPIF_CLR 0x00000004 // Clear SPI interrupt
#define SCOPEN 0x80080008 // Enable WBSCOPE interrupts
 
// Flash control constants
#define ERASEFLAG 0x80000000
#define DISABLEWP 0x10000000
 
#define SZPAGE 64
#define PGLEN 64
#define NPAGES 32
#define SECTORSZ (NPAGES * SZPAGE)
#define NSECTORS 256
#define SECTOROF(A) (A & (-1<<10))
#define PAGEOF(A) (A & (-1<<6))
 
#define RAMLEN 0x02000
 
// ZIP Control sequences
#define CPU_GO 0x0000
#define CPU_RESET 0x0040
#define CPU_INT 0x0080
#define CPU_STEP 0x0100
#define CPU_STALL 0x0200
#define CPU_HALT 0x0400
#define CPU_CLRCACHE 0x0800
#define CPU_sR0 (0x0000|CPU_HALT)
#define CPU_sSP (0x000d|CPU_HALT)
#define CPU_sCC (0x000e|CPU_HALT)
#define CPU_sPC (0x000f|CPU_HALT)
#define CPU_uR0 (0x0010|CPU_HALT)
#define CPU_uSP (0x001d|CPU_HALT)
#define CPU_uCC (0x001e|CPU_HALT)
#define CPU_uPC (0x001f|CPU_HALT)
 
// Scop definition/sequences
#define SCOPE_NO_RESET 0x80000000
#define SCOPE_TRIGGER (0x08000000|SCOPE_NO_RESET)
#define SCOPE_DISABLE (0x04000000)
 
typedef struct {
unsigned m_addr;
const char *m_name;
} REGNAME;
 
extern const REGNAME *bregs;
extern const int NREGS;
// #define NREGS (sizeof(bregs)/sizeof(bregs[0]))
 
extern unsigned addrdecode(const char *v);
extern const char *addrname(const unsigned v);
 
#include "ttybus.h"
// #include "portbus.h"
 
typedef TTYBUS FPGA;
 
#endif
/trunk/sw/usbtst.cpp
0,0 → 1,244
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
// #include <usb.h>
 
#include <libusb.h>
 
// /sys/bus/usb/devices/1-4/ is our device, as currently plugged in
//
// It supports
// 1 configuration
// 1 interface
// and has a product string of...
// "XuLA - XESS Micro Logic Array"
//
#define VENDOR_ID 0x04d8
#define PRODUCT_ID 0x0ff8c
#define XESS_ENDPOINT_OUT 0x01
#define XESS_ENDPOINT_IN 0x81
//
#define JTAG_CMD 0x4f
#define GET_TDO_MASK 0x01
#define PUT_TMS_MASK 0x02
#define TMS_VAL_MASK 0x04
#define PUT_TDI_MASK 0x08
#define TDI_VAL_MASK 0x10
//
#define USER1_INSTR 0x02 // a SIX bit two
 
 
bool gbl_transfer_received = false;
 
// libusbtransfer_cb_fn callback;
extern "C" {
void my_callback(libusb_transfer *tfr) {
gbl_transfer_received = true;
 
printf("Callback received!\n");
}
}
 
// All messages must be 32 bytes or less
//
 
 
// Walk us through the JTAG Chain:
// 5-1's to go to test/reset
// 0 to go to Run-Test/Idle
// 1 to go to select-dr-scan
// 1 to go to select-ir-scan
// 0 to go to capture-ir
// 0 to go to shift-ir
// (6-bit code 0x02 through TDI to IR, while sending 0-bits to TMS)
// 1 to leave shift IR and go to exit1-ir
// 1 to go to update-ir
// 1 to go to select-dr-scan
// 0 to go to capture-dr
// 0 to go to shift-dr
#define RESET_JTAG_LEN 12
const char RESET_TO_USER_DR[RESET_JTAG_LEN] = {
JTAG_CMD,
21, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TMS_MASK | PUT_TDI_MASK, // flags
(char)(0x0df), // TMS: Five ones, then one zero, and two ones -- low bits first
0x00, // TDI: irrelevant here
(char)(0x80), // TMS: two zeros, then six zeros
0x08, // TDI: user command #1, bit reversed
0x03, // TMS: three ones, then two zeros
0x00 // TDI byte -- irrelevant here
//
// 0xc0, // TDI byte -- user command #2
// 0x40, // TDI: user command #1
// 0x0c, // TDI byte -- user command #2, bit reversed
};
 
//
// TMS:
/*
#define TX_DR_LEN 12
const char TX_DR_BITS[TX_DR_LEN] = {
JTAG_CMD,
48, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TDI_MASK, // flags
(char)0x0ff, 0, 0, 0, 0, 0 // Six data bytes
// module_id = 255
// 32'h(payload.length)
// payload
// module_id + payload.len + num_result_bits, length=32 + payload ???
};
*/
 
//
// TMS:
//
#define REQ_RX_LEN 6
const char REQ_RX_BITS[REQ_RX_LEN] = {
JTAG_CMD,
(char)((32-6)*8), // bits-requested
0,0,0, // Also clocks, higher order bits
GET_TDO_MASK|TDI_VAL_MASK, // flags:TDI is kept low here, so no TDI flag
// No data given, since there's no info to send or receive
// Leave the result in shift-DR mode
};
 
#define RETURN_TO_RESET_LEN 7
const char RETURN_TO_RESET[RETURN_TO_RESET_LEN] = {
JTAG_CMD,
5, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TMS_MASK, // flags
(char)(0x0ff), // Five ones
};
 
int dec(int v) {
int br = 0;
 
/*
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
 
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
*/
br = v&0x07f;
 
if (br == ' ')
return br;
else if (isgraph(br))
return br;
else
return '.';
}
 
//
// If max packet length is 32, why do you waste 4 bytes on num_clocks?
// Why is the bit counter always from 8 to zero?
//
 
int main(int argc, char **argv) {
libusb_context *usb_context;
libusb_device_handle *xula_usb_device;
int config;
 
if (0 != libusb_init(&usb_context)) {
fprintf(stderr, "Error initializing the USB library\n");
perror("O/S Err:");
exit(-1);
}
 
xula_usb_device = libusb_open_device_with_vid_pid(usb_context,
VENDOR_ID, PRODUCT_ID);
if (!xula_usb_device) {
fprintf(stderr, "Could not open XuLA device\n");
perror("O/S Err:");
 
libusb_exit(usb_context);
exit(-1);
}
 
if (0 != libusb_get_configuration(xula_usb_device, &config)) {
fprintf(stderr, "Could not get configuration\n");
perror("O/S Err:");
 
libusb_close(xula_usb_device);
libusb_exit(usb_context);
exit(-1);
}
 
printf("Current configuration is %d\n", config);
int interface = 0;
 
if (0 != libusb_claim_interface(xula_usb_device, interface)) {
fprintf(stderr, "Could not claim interface\n");
perror("O/S Err:");
 
libusb_close(xula_usb_device);
libusb_exit(usb_context);
exit(-1);
}
 
unsigned char *abuf = new unsigned char[32];
int actual_length = 32;
memcpy(abuf, RESET_TO_USER_DR, RESET_JTAG_LEN);
int r = libusb_bulk_transfer(xula_usb_device, XESS_ENDPOINT_OUT,
abuf, RESET_JTAG_LEN, &actual_length, 20);
if ((r==0)&&(actual_length == RESET_JTAG_LEN)) {
printf("Successfully sent RESET_TO_USER_DR!\n");
} else {
printf("Some error took place requesting RESET_TO_USER_DR\n");
perror("O/S Err");
}
 
memset(abuf, 0, 32);
memcpy(abuf, REQ_RX_BITS, REQ_RX_LEN);
r = libusb_bulk_transfer(xula_usb_device, XESS_ENDPOINT_OUT,
abuf, REQ_RX_LEN, &actual_length, 20);
if ((r==0)&&(actual_length == REQ_RX_LEN)) {
printf("Successfully sent request for TDO bits!\n");
} else {
printf("Some error took place in requesting TDO bits\n");
printf("r = %d, actual_length = %d (!= %d)\n", r,
actual_length, REQ_RX_LEN);
perror("O/S Err");
}
 
r = libusb_bulk_transfer(xula_usb_device, XESS_ENDPOINT_IN,
abuf, 32, &actual_length, 20);
if ((r==0)&&(actual_length > 0)) {
printf("Successfully read %d bytes from port!\n", actual_length);
for(int i=0; i<(actual_length); i+=4)
printf("%2d: %02x %02x %02x %02x -- %c%c%c%c\n", i,
abuf[i+0], abuf[i+1], abuf[i+2], abuf[i+3],
dec(abuf[i+0]),dec(abuf[i+1]), dec(abuf[i+2]), dec(abuf[i+3]));
} else {
printf("Some error took place in receiving\n");
perror("O/S Err");
}
 
 
// Release our interface
if (0 != libusb_release_interface(xula_usb_device, interface)) {
fprintf(stderr, "Could not release interface\n");
perror("O/S Err:");
 
libusb_close(xula_usb_device);
libusb_exit(usb_context);
exit(-1);
}
 
// And then close our device with
libusb_close(xula_usb_device);
 
// And just before exiting, we free our USB context
libusb_exit(usb_context);
}
 
/trunk/sw/ziprun.cpp
0,0 → 1,210
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ziprun.cpp
//
// Project: XuLA2 board
//
// Purpose: To load a program for the ZipCPU into memory.
//
// Steps:
// 1. Halt and reset the CPU
// 2. Load memory
// 3. Clear the cache
// 4. Clear any registers
// 5. Set the PC to point to the FPGA local memory
// THIS DOES NOT START THE PROGRAM!! The CPU is left in the halt state.
// To actually start the program, execute a ./wbregs cpu 0. (Actually,
// any value between 0x0 and 0x1f will work, the difference being what
// register you will be able to inspect while the CPU is running.)
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "usbi.h"
#include "port.h"
#include "regdefs.h"
 
FPGA *m_fpga;
 
int main(int argc, char **argv) {
FILE *fp;
int nr, pos=0;
const int BUFLN = 128;
FPGA::BUSW *buf = new FPGA::BUSW[BUFLN];
int skp=0, port = FPGAPORT;
bool use_usb = true;
 
skp=1;
for(int argn=0; argn<argc-skp; argn++) {
if (argv[argn+skp][0] == '-') {
if (argv[argn+skp][1] == 'u')
use_usb = true;
else if (argv[argn+skp][1] == 'p') {
use_usb = false;
if (isdigit(argv[argn+skp][2]))
port = atoi(&argv[argn+skp][2]);
}
skp++; argn--;
} else
argv[argn] = argv[argn+skp];
} argc -= skp;
 
if (use_usb)
m_fpga = new FPGA(new USBI());
else
m_fpga = new FPGA(new NETCOMMS(FPGAHOST, port));
 
if ((argc<=0)||(access(argv[0],R_OK)!=0)) {
printf("Usage: ziprun obj-file\n");
printf("\n"
"\tziprun loads the object file into memory, resets the CPU, and leaves it\n"
"\tin a halted state ready to start running the object file.\n");
exit(-1);
}
 
// FPGAOPEN(m_fpga);
 
printf("Halting the CPU\n");
m_fpga->writeio(R_ZIPCTRL, CPU_RESET|CPU_HALT);
 
fp = fopen(argv[0], "r");
if (fp == NULL) {
fprintf(stderr, "Could not open: %s\n", argv[0]);
exit(-1);
}
 
try {
pos = RAMBASE;
while((nr=fread(buf, sizeof(FPGA::BUSW), BUFLN, fp))>0) {
// printf("Writing %4d values, pos = %08x\n", nr, pos);
m_fpga->writei(pos, nr, buf);
// printf("\tWritten\n");
pos += nr;
} printf("Successfully wrote %04x (%6d) words into memory\n",
pos-RAMBASE, pos-RAMBASE);
m_fpga->readio(R_ZIPCTRL);
 
// Do we want to zero out all other RAM addresses?
#define ZERO_RAM
#ifdef ZERO_RAM
unsigned int MAXRAM=2*RAMBASE;
for(int i=0; i<BUFLN; i++)
buf[i] = 0;
printf("***********************\n");
while(pos < (int)MAXRAM-BUFLN-1) {
m_fpga->writei(pos, BUFLN, buf);
m_fpga->readio(R_ZIPCTRL);
pos += BUFLN;
} m_fpga->writei(pos, MAXRAM-pos-1, buf);
pos += MAXRAM-pos-1;
 
m_fpga->usleep(500);
printf("Zerod rest of RAM - to %06x\n", pos);
#endif
} catch(BUSERR a) {
fprintf(stderr, "BUS Err at address 0x%08x\n", a.addr);
fprintf(stderr, "... is your program too long for this memory?\n");
m_fpga->writeio(R_ZIPCTRL, CPU_RESET|CPU_HALT|CPU_CLRCACHE);
exit(-2);
}
try {
m_fpga->readio(R_ZIPCTRL);
} catch(BUSERR a) {
fprintf(stderr, "Bus-Err? (%08x)\n", a.addr);
}
 
// Clear any buffers
printf("Clearing the cache\n");
m_fpga->writeio(R_ZIPCTRL, CPU_RESET|CPU_HALT|CPU_CLRCACHE);
 
// printf("Clearing all registers to zero, PC regs to MEMBASE\n");
// Clear all registers to zero
for(int i=0; i<32; i++) {
unsigned int v;
try {
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|i);
m_fpga->readio(R_ZIPCTRL);
} catch(BUSERR a) {
fprintf(stderr, "Bus-ERR while trying to set CPUCTRL to %x\n", CPU_HALT|i);
}
try {
if ((i&0x0f)==0x0f)
m_fpga->writeio(R_ZIPDATA, RAMBASE);
else
m_fpga->writeio(R_ZIPDATA, 0);
// printf("REG[%2x] <= %08x\n", i, ((i&0x0f)==0x0f)?RAMBASE:0);
// m_fpga->readio(R_ZIPDATA);
// printf("\t= %08x\n", m_fpga->readio(R_ZIPDATA));
} catch(BUSERR a) {
fprintf(stderr, "Bus-ERR while trying to clear reg %x\n", i);
}
} for(int i=32; i<32+16; i++) {
try {
if (i==33)
continue; // Don't start the watchdog
if (i==34)
continue; // Don't start the flash cache
if (i==39)
continue; // Jiffies don't clear, don't set the intrupt
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|i);
m_fpga->writeio(R_ZIPDATA, 0);
} catch (BUSERR a) {
fprintf(stderr, "Bus-ERR while trying to clear peripheral %d\n", i);
}
}
 
printf("Starting CPU\n");
try {
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_sCC); // Start in interrupt mode
m_fpga->writeio(R_ZIPDATA, 0x000);
printf("SCC <= 0x%08x\n", m_fpga->readio(R_ZIPDATA));
} catch (BUSERR a) {
fprintf(stderr, "Bus Err while trying to set CC register\n");
}
 
try {
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_sPC);
printf("CPU <= 0x%08x\n", m_fpga->readio(R_ZIPCTRL));
m_fpga->writeio(R_ZIPDATA, RAMBASE); // Start at the base of RAM
printf("SPC <= 0x%08x\n", m_fpga->readio(R_ZIPDATA));
} catch (BUSERR a) {
fprintf(stderr, "Bus Err while trying to set PC register\n");
}
printf("PC set to start at %08x\n", m_fpga->readio(R_ZIPDATA));
// m_fpga->writeio(R_ZIPCTRL, CPU_GO); // Release the CPU to start
 
delete m_fpga;
}
 
/trunk/sw/wbregs.cpp
0,0 → 1,122
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbregs.cpp
//
// Project: XuLA2 board
//
// Purpose: To give a user access, via a command line program, to read
// and write wishbone registers one at a time. Thus this program
// implements readio() and writeio() but nothing more.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "llcomms.h"
#include "usbi.h"
#include "port.h"
#include "regdefs.h"
 
FPGA *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
int main(int argc, char **argv) {
int skp=0, port = FPGAPORT;
bool use_usb = true;
 
skp=1;
for(int argn=0; argn<argc-skp; argn++) {
if (argv[argn+skp][0] == '-') {
if (argv[argn+skp][1] == 'u')
use_usb = true;
else if (argv[argn+skp][1] == 'p') {
use_usb = false;
if (isdigit(argv[argn+skp][2]))
port = atoi(&argv[argn+skp][2]);
}
skp++; argn--;
} else
argv[argn] = argv[argn+skp];
} argc -= skp;
 
if (use_usb)
m_fpga = new FPGA(new USBI());
else
m_fpga = new FPGA(new NETCOMMS(FPGAHOST, port));
 
signal(SIGSTOP, closeup);
signal(SIGHUP, closeup);
 
if ((argc < 1)||(argc > 2)) {
// usage();
printf("USAGE: wbregs address [value]\n");
exit(-1);
}
 
const char *nm;
unsigned address = addrdecode(argv[0]), value;
nm = addrname(address);
if (nm == NULL)
nm = "no name";
 
if (argc < 2) {
FPGA::BUSW v;
try {
unsigned char a, b, c, d;
v = m_fpga->readio(address);
a = (v>>24)&0x0ff;
b = (v>>16)&0x0ff;
c = (v>> 8)&0x0ff;
d = (v )&0x0ff;
printf("%08x (%8s) : [%c%c%c%c] %08x\n", address, nm,
isgraph(a)?a:'.', isgraph(b)?b:'.',
isgraph(c)?c:'.', isgraph(d)?d:'.', v);
} catch(BUSERR b) {
printf("%08x (%8s) : BUS-ERROR\n", address, nm);
}
} else {
value = strtoul(argv[1], NULL, 0);
m_fpga->writeio(address, value);
printf("%08x (%8s)-> %08x\n", address, nm, value);
}
 
if (m_fpga->poll())
printf("FPGA was interrupted\n");
delete m_fpga;
}
 
/trunk/sw/cfgscope.cpp
0,0 → 1,124
//
//
// Filename: cfgscope.cpp
//
// Project: FPGA library development (Basys-3 development board)
//
// Purpose: To read out, and decompose, the results of the wishbone scope
// as applied to the ICAPE2 interaction.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
//
// Copyright: 2015
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "port.h"
#include "llcomms.h"
#include "regdefs.h"
 
#define WBSCOPE R_CFGSCOPE
#define WBSCOPEDATA R_CFGSCOPED
 
FPGA *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
unsigned brev(const unsigned v) {
unsigned int r, a;
a = v;
r = 0;
for(int i=0; i<8; i++) {
r <<= 1;
r |= (a&1);
a >>= 1;
} return r;
}
 
unsigned wrev(const unsigned v) {
unsigned r = brev(v&0x0ff);
r |= brev((v>>8)&0x0ff)<<8;
return r;
}
 
int main(int argc, char **argv) {
FPGAOPEN(m_fpga);
 
signal(SIGSTOP, closeup);
signal(SIGHUP, closeup);
 
unsigned v, lgln, scoplen;
printf("Attempting to read address %08x\n", WBSCOPE);
v = m_fpga->readio(WBSCOPE);
if (0x60000000 != (v & 0x60000000)) {
printf("Scope is not yet ready:\n");
printf("\tRESET:\t\t%s\n", (v&0x80000000)?"Ongoing":"Complete");
printf("\tSTOPPED:\t%s\n", (v&0x40000000)?"Yes":"No");
printf("\tTRIGGERED:\t%s\n", (v&0x20000000)?"Yes":"No");
printf("\tPRIMED:\t\t%s\n", (v&0x10000000)?"Yes":"No");
printf("\tMANUAL:\t\t%s\n", (v&0x08000000)?"Yes":"No");
printf("\tDISABLED:\t%s\n", (v&0x04000000)?"Yes":"No");
printf("\tZERO:\t\t%s\n", (v&0x02000000)?"Yes":"No");
exit(0);
} else printf("SCOPD = %08x\n", v);
 
lgln = (v>>20) & 0x1f;
scoplen = (1<<lgln);
 
DEVBUS::BUSW *buf;
buf = new DEVBUS::BUSW[scoplen];
 
if (false) {
printf("Attempting vector read\n");
m_fpga->readz(WBSCOPEDATA, scoplen, buf);
 
printf("Vector read complete\n");
} else {
for(unsigned int i=0; i<scoplen; i++)
buf[i] = m_fpga->readio(WBSCOPEDATA);
}
 
for(unsigned int i=0; i<scoplen; i++) {
if ((i>0)&&(buf[i] == buf[i-1])&&
(i<scoplen-1)&&(buf[i] == buf[i+1]))
continue;
printf("%6d %08x:", i, buf[i]);
printf("S(%x) ", (buf[i]>>27)&0x0f);
if (buf[i] & 0x40000000)
printf("W "); else printf("R ");
printf("WB(%s%s%s%s%s)-%s%s%s%s%s",
(buf[i]&0x2000000)?"CYC":" ",
(buf[i]&0x1000000)?"STB":" ",
(buf[i]&0x0800000)?"WE":" ",
(buf[i]&0x0400000)?"ACK":" ",
(buf[i]&0x0200000)?"STL":" ",
(buf[i]&0x0100000)?"EDG":" ",
(buf[i]&0x0080000)?"CLK":" ",
(buf[i]&0x0040000)?" ":"CEn",
(buf[i]&0x0020000)?"BSY":" ",
(buf[i]&0x0010000)?" ":"WE");
if (buf[i]&0x10000)
printf("->"); // Read
else printf("<-");
printf(" %04x\n", wrev(buf[i] & 0x0ffff));
}
 
if (m_fpga->poll()) {
printf("FPGA was interrupted\n");
m_fpga->clear();
m_fpga->writeio(R_ICONTROL, SCOPEN);
}
delete m_fpga;
}
 
/trunk/sw/port.h
0,0 → 1,55
////////////////////////////////////////////////////////////////////////////////
//
// Filename: port.h
//
// Project: XuLA2 board
//
// Purpose: Defines the communication parameters necessary for communicating
// with the device.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef PORT_H
#define PORT_H
 
// #include "usbi.h"
 
// There are two ways to connect: via a serial port, and via a TCP socket
// connected to a serial port. This way, we can connect the device on one
// computer, test it, and when/if it doesn't work we can replace the device
// with the test-bench. Across the network, no one will know any better that
// anything had changed.
#define FPGAHOST "lazarus" // A random hostname,back from the grave
#define FPGATTY "/dev/ttyUSB1"
#define FPGAPORT 7239 // Just some random port number ....
 
#ifdef USBI_H
#define FPGAOPEN(V) V= new FPGA(new USBI())
#else
#define FPGAOPEN(V) V= new FPGA(new NETCOMMS(FPGAHOST, FPGAPORT))
#endif
 
#endif
/trunk/sw/ttybus.cpp
0,0 → 1,595
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ttybus.cpp
//
// Project: XuLA2 board
//
// Purpose: This is the C++ program on the command side that will interact
// with a UART on an FPGA, to command the WISHBONE on that same
// FPGA to ... whatever we wish to command it to do.
//
// This code does not run on an FPGA, is not a test bench, neither
// is it a simulator. It is a portion of a command program
// for commanding an FPGA.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <assert.h>
#include <strings.h>
#include <poll.h>
#include <ctype.h>
 
#include "ttybus.h"
 
#define TTYC_IDLE '0'
#define TTYC_BUSY '1'
#define TTYC_WRITE '2'
#define TTYC_RESET '3'
#define TTYC_INT '4'
#define TTYC_ERR '5'
 
const unsigned TTYBUS::MAXRDLEN = 1024;
const unsigned TTYBUS::MAXWRLEN = 32;
 
#define DBGPRINTF null
// #define DBGPRINTF printf
void null(...) {}
 
char TTYBUS::charenc(const int sixbitval) {
if (sixbitval < 10)
return '0' + sixbitval;
else if (sixbitval < 10+26)
return 'A' - 10 + sixbitval;
else if (sixbitval < 10+26+26)
return 'a' - 10 - 26 + sixbitval;
else if (sixbitval == 0x3e)
return '@';
else if (sixbitval == 0x3f)
return '%';
 
fprintf(stderr, "INTERNAL ERR: SIXBITVAL isn\'t!!!! sixbitval = %08x\n", sixbitval);
assert((sixbitval & (~0x03f))==0);
return 0;
}
 
unsigned TTYBUS::chardec(const char b) {
if ((b >= '0')&&(b <= '9'))
return b-'0';
else if ((b >= 'A')&&(b <= 'Z'))
return b-'A'+10;
else if ((b >= 'a')&&(b <= 'z'))
return b-'a'+36;
else if (b == '@')
return 0x03e;
else if (b == '%')
return 0x03f;
else
return 0x0100; // ERR -- invalid code
}
 
int TTYBUS::lclreadcode(char *buf, int len) {
char *sp, *dp;
int nr, ret;
 
nr = m_dev->read(buf, len);
m_total_nread += nr;
ret = nr; sp = buf; dp = buf;
for(int i=0; i<nr; i++) {
if (chardec(*sp)&(~0x3f)) {
ret--; // Skip this value, not a valid codeword
sp++;
} else {
*sp++ = *dp++;
}
} return ret;
}
 
void TTYBUS::bufalloc(int len) {
if ((m_buf)&&(m_buflen >= len))
return;
if (m_buf)
delete[] m_buf;
m_buflen = (len&(-0x3f))+0x40;
m_buf = new char[m_buflen];
}
 
void TTYBUS::encode(const int hb, const BUSW val, char *buf) {
buf[0] = charenc( (hb<<2)|((val>>30)&0x03) );
buf[1] = charenc( (val>>24)&0x3f);
buf[2] = charenc( (val>>18)&0x3f);
buf[3] = charenc( (val>>12)&0x3f);
buf[4] = charenc( (val>> 6)&0x3f);
buf[5] = charenc( (val )&0x3f);
}
 
unsigned TTYBUS::decodestr(const char *buf) {
unsigned r;
 
r = chardec(buf[0]) & 0x03;
r = (r<<6) | (chardec(buf[1]) & 0x03f);
r = (r<<6) | (chardec(buf[2]) & 0x03f);
r = (r<<6) | (chardec(buf[3]) & 0x03f);
r = (r<<6) | (chardec(buf[4]) & 0x03f);
r = (r<<6) | (chardec(buf[5]) & 0x03f);
 
return r;
}
 
int TTYBUS::decodehex(const char hx) {
if ((hx >= '0')&&(hx <= '9'))
return hx-'0';
else if ((hx >= 'A')&&(hx <= 'Z'))
return hx-'A'+10;
else if ((hx >= 'a')&&(hx <= 'z'))
return hx-'a'+10;
else
return 0;
}
 
void TTYBUS::writeio(const BUSW a, const BUSW v) {
 
writev(a, 0, 1, &v);
m_lastaddr = a; m_addr_set = true;
}
 
void TTYBUS::writev(const BUSW a, const int p, const int len, const BUSW *buf) {
char *ptr;
 
// Allocate a buffer of six bytes per word, one for addr, plus
// six more
bufalloc((len+2)*6);
 
DBGPRINTF("WRITEV(%08x,%d,#%d,0x%08x ...)\n", a, p, len, buf[0]);
// Encode the address
ptr = encode_address(a);
m_lastaddr = a; m_addr_set = true;
 
for(int i=0; i<len; i++) {
BUSW val = buf[i];
 
int caddr = 0;
// Let's try compression
for(int i=1; i<256; i++) {
unsigned tstaddr;
tstaddr = (m_wraddr - i) & 0x0ff;
if ((!m_wrloaded)&&(tstaddr > (unsigned)m_wraddr))
break;
if (m_writetbl[tstaddr] == val) {
caddr = ( m_wraddr- tstaddr ) & 0x0ff;
break;
}
}
 
if (caddr != 0)
DBGPRINTF("WR[%08x] = %08x (= TBL[%4x] <= %4x)\n", m_lastaddr, val, caddr, m_wraddr);
else
DBGPRINTF("WR[%08x] = %08x\n", m_lastaddr, val);
 
if (caddr != 0) {
*ptr++ = charenc( (((caddr>>6)&0x03)<<1) + (p?1:0) + 0x010);
*ptr++ = charenc( caddr &0x3f );
} else {
// For testing, let's start just doing this the hard way
*ptr++ = charenc( (((val>>30)&0x03)<<1) + (p?1:0) + 0x018);
*ptr++ = charenc( (val>>24)&0x3f);
*ptr++ = charenc( (val>>18)&0x3f);
*ptr++ = charenc( (val>>12)&0x3f);
*ptr++ = charenc( (val>> 6)&0x3f);
*ptr++ = charenc( (val )&0x3f);
 
m_writetbl[m_wraddr++] = val;
m_wraddr &= 0x0ff;
if (m_wraddr == 0) {
m_wrloaded = true;
}
}
 
if (p == 1) m_lastaddr++;
}
// *ptr++ = charenc(0x2e);
*ptr++ = '\n'; *ptr = '\0';
m_dev->write(m_buf, ptr-m_buf);
 
DBGPRINTF(">> %s\n", m_buf);
DBGPRINTF("WR: LAST ADDRESS LEFT AT %08x\n", m_lastaddr);
}
 
void TTYBUS::writez(const BUSW a, const int len, const BUSW *buf) {
int ln = len;
const TTYBUS::BUSW *bptr = buf;
TTYBUS::BUSW addr = a;
 
while((unsigned)ln > MAXWRLEN) {
writev(addr, 0, MAXWRLEN, bptr);
bptr += MAXWRLEN;
ln -= MAXWRLEN;
// addr += MAXWRLEN;
} if ((unsigned)ln > 0)
writev(addr, 0, ln, bptr);
}
 
void TTYBUS::writei(const BUSW a, const int len, const BUSW *buf) {
int ln = len;
const TTYBUS::BUSW *bptr = buf;
TTYBUS::BUSW addr = a;
 
while((unsigned)ln > MAXWRLEN) {
writev(addr, 1, MAXWRLEN, bptr);
bptr += MAXWRLEN;
ln -= MAXWRLEN;
addr += MAXWRLEN;
} if ((unsigned)ln > 0)
writev(addr, 1, ln, bptr);
}
 
TTYBUS::BUSW TTYBUS::readio(const TTYBUS::BUSW a) {
BUSW v;
 
// I/O reads are now the same as vector reads, but with a vector length
// of one.
try {
readv(a, 0, 1, &v);
} catch(BUSERR b) {
throw BUSERR(a);
}
 
if (m_lastaddr != a) {
DBGPRINTF("LAST-ADDR MIS-MATCH: (RCVD) %08x != %08x (XPECTED)\n", m_lastaddr, a);
m_addr_set = false;
 
exit(-3);
}
 
return v;
}
 
char *TTYBUS::encode_address(const TTYBUS::BUSW a) {
TTYBUS::BUSW addr = a;
char *ptr = m_buf;
 
if ((m_addr_set)&&(a == m_lastaddr))
return ptr;
if (m_addr_set) {
// Encode a difference address
int diffaddr = addr - m_lastaddr;
ptr = m_buf;
if ((diffaddr >= -32)&&(diffaddr < 32)) {
*ptr++ = charenc(0x09);
*ptr++ = charenc(diffaddr & 0x03f);
} else if ((diffaddr >= -2048)&&(diffaddr < 2048)) {
*ptr++ = charenc(0x0b);
*ptr++ = charenc((diffaddr>>6) & 0x03f);
*ptr++ = charenc( diffaddr & 0x03f);
} else if ((diffaddr >= -(1<<17))&&(diffaddr < (1<<17))) {
*ptr++ = charenc(0x0d);
*ptr++ = charenc((diffaddr>>12) & 0x03f);
*ptr++ = charenc((diffaddr>> 6) & 0x03f);
*ptr++ = charenc( diffaddr & 0x03f);
} else if ((diffaddr >= -(1<<23))&&(diffaddr < (1<<23))) {
*ptr++ = charenc(0x0d);
*ptr++ = charenc((diffaddr>>18) & 0x03f);
*ptr++ = charenc((diffaddr>>12) & 0x03f);
*ptr++ = charenc((diffaddr>> 6) & 0x03f);
*ptr++ = charenc( diffaddr & 0x03f);
}
*ptr = '\0';
// DBGPRINTF("DIF-ADDR: (%ld) \'%s\'\n", ptr-m_buf, m_buf);
}
 
{
// Encode an absolute (low memory) address
// Prefer absolute address encoding over differential encoding,
// when both encodings encode the same address, and when both
// encode the address in the same number of words
if ((addr <= 0x03f)&&((ptr == m_buf)||(ptr >= &m_buf[2]))) {
ptr = m_buf;
*ptr++ = charenc(0x08);
*ptr++ = charenc(addr);
} else if((addr <= 0x0fff)&&((ptr == m_buf)||(ptr >= &m_buf[3]))) {
// DBGPRINTF("Setting ADDR.3 to %08x\n", addr);
ptr = m_buf;
*ptr++ = charenc(0x0a);
*ptr++ = charenc((addr>> 6) & 0x03f);
*ptr++ = charenc( addr & 0x03f);
} else if((addr <= 0x03ffff)&&((ptr == m_buf)||(ptr >= &m_buf[4]))) {
// DBGPRINTF("Setting ADDR.4 to %08x\n", addr);
ptr = m_buf;
*ptr++ = charenc(0x0c);
*ptr++ = charenc((addr>>12) & 0x03f);
*ptr++ = charenc((addr>> 6) & 0x03f);
*ptr++ = charenc( addr & 0x03f);
} else if((addr <= 0x0ffffff)&&((ptr == m_buf)||(ptr >= &m_buf[5]))) {
// DBGPRINTF("Setting ADDR.5 to %08x\n", addr);
ptr = m_buf;
*ptr++ = charenc(0x0e);
*ptr++ = charenc((addr>>18) & 0x03f);
*ptr++ = charenc((addr>>12) & 0x03f);
*ptr++ = charenc((addr>> 6) & 0x03f);
*ptr++ = charenc( addr & 0x03f);
} else if (ptr == m_buf) { // Send our address prior to any read
ptr = m_buf;
encode(0, addr, ptr);
ptr+=6;
}
}
 
*ptr = '\0';
// DBGPRINTF("ADDR-CMD: (%ld) \'%s\'\n", ptr-m_buf, m_buf);
m_rdaddr = 0;
 
return ptr;
}
 
char *TTYBUS::readcmd(const int inc, const int len, char *buf) {
char *ptr = buf;
 
// DBGPRINTF("READCMD: LEN = %d\n", len);
assert(len < 520);
assert(len > 0);
 
if ((len < 8)||((len == 8)&&(inc))) {
*ptr++ = charenc(0x20 + (((len-1)&0x07)<<1) + (inc?1:0));
} else {
*ptr++ = charenc(0x30 + (((len-8)>>5)&0x0e) + (inc?1:0));
*ptr++ = charenc( (len-8) & 0x03f);
}
 
return ptr;
}
 
void TTYBUS::readv(const TTYBUS::BUSW a, const int inc, const int len, TTYBUS::BUSW *buf) {
const int READAHEAD = MAXRDLEN/2, READBLOCK=MAXRDLEN/2;
int cmdrd = 0, nread = 0;
// TTYBUS::BUSW addr = a;
char *ptr = m_buf;
 
if (len <= 0)
return;
// DBGPRINTF("READV(%08x,%d,#%4d)\n", a, inc, len);
 
ptr = encode_address(a);
try {
while(cmdrd < len) {
// ptr = m_buf;
do {
int nrd = len-cmdrd;
if (nrd > READBLOCK)
nrd = READBLOCK;
if (cmdrd-nread + nrd>READAHEAD+READBLOCK)
nrd = READAHEAD+READBLOCK-(cmdrd-nread);
ptr = readcmd(inc, nrd, ptr);
cmdrd += nrd;
} while((cmdrd-nread < READAHEAD+READBLOCK)&&(cmdrd< len));
 
*ptr++ = '\n'; *ptr = '\0';
m_dev->write(m_buf, (ptr-m_buf));
 
while(nread<(cmdrd-READAHEAD)) {
buf[nread++] = readword();
} ptr = m_buf;
} while(nread<len) {
buf[nread++] = readword();
}
} catch(BUSERR b) {
throw BUSERR(a+((inc)?nread:0));
}
if ((unsigned)m_lastaddr != (a+((inc)?(len):0))) {
printf("TTYBUS::READV(a=%08x,inc=%d,len=%4x,x) ERR: (Last) %08x != %08x + %08x (Expected)\n", a, inc, len, m_lastaddr, a, (inc)?(len):0);
sleep(1);
assert((int)m_lastaddr == (a+(inc)?(len):0));
exit(-3);
}
}
 
void TTYBUS::readi(const TTYBUS::BUSW a, const int len, TTYBUS::BUSW *buf) {
readv(a, 1, len, buf);
}
 
void TTYBUS::readz(const TTYBUS::BUSW a, const int len, TTYBUS::BUSW *buf) {
readv(a, 0, len, buf);
}
 
TTYBUS::BUSW TTYBUS::readword(void) {
TTYBUS::BUSW val = 0;
int nr;
unsigned sixbits;
 
// DBGPRINTF("READ-WORD()\n");
 
bool found_start = false;
do {
// Blocking read (for now)
do {
nr = lclreadcode(&m_buf[0], 1);
} while (nr < 1);
 
sixbits = chardec(m_buf[0]);
 
if (sixbits&(~0x03f)) {
// Ignore new lines, unprintables, and characters
// not a part of our code
;
} else if (sixbits < 6) {
switch(sixbits) {
case 0: break; // Idle -- ignore
case 1: break; // Idle, but the bus is busy
case 2: break; // Write acknowledgement, ignore it here
case 3:
m_bus_err = true;
throw BUSERR(0);
break;
case 4:
m_interrupt_flag = true;
break;
case 5:
m_bus_err = true;
throw BUSERR(0);
break;
}
} else if (0x08 == (sixbits & 0x3c)) { // Set 32-bit address
do {
nr += lclreadcode(&m_buf[nr], 6-nr);
} while (nr < 6);
 
val = chardec(m_buf[0]) & 0x03;
val = (val<<6) | (chardec(m_buf[1]) & 0x03f);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
val = (val<<6) | (chardec(m_buf[4]) & 0x03f);
val = (val<<6) | (chardec(m_buf[5]) & 0x03f);
 
m_addr_set = true;
m_lastaddr = val;
 
// DBGPRINTF("RCVD ADDR: 0x%08x\n", val);
} else if (0x0c == (sixbits & 0x03c)) { // Set 32-bit address,compressed
int nw = (sixbits & 0x03) + 2;
do {
nr += lclreadcode(&m_buf[nr], nw-nr);
} while (nr < nw);
 
if (nw == 2) {
val = chardec(m_buf[1]);
} else if (nw == 3) {
val = chardec(m_buf[1]);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
} else if (nw == 4) {
val = chardec(m_buf[1]);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
} else { // if (nw == 5)
val = chardec(m_buf[1]);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
val = (val<<6) | (chardec(m_buf[4]) & 0x03f);
}
 
m_addr_set = true;
m_lastaddr = val;
// DBGPRINTF("RCVD ADDR: 0x%08x (%d bytes)\n", val, nw+1);
} else
found_start = true;
} while(!found_start);
 
int rdaddr;
 
if (0x06 == (sixbits & 0x03e)) { // Tbl read, last value
rdaddr = (m_rdaddr-1)&0x03ff;
val = m_readtbl[rdaddr];
m_lastaddr += (sixbits&1);
} else if (0x10 == (sixbits & 0x030)) { // Tbl read, up to 521 into past
int idx;
do {
nr += lclreadcode(&m_buf[nr], 2-nr);
} while (nr < 2);
 
idx = (chardec(m_buf[0])>>1) & 0x07;
idx = ((idx<<6) | (chardec(m_buf[1]) & 0x03f)) + 2 + 8;
rdaddr = (m_rdaddr-idx)&0x03ff;
val = m_readtbl[rdaddr];
m_lastaddr += (sixbits&1);
} else if (0x20 == (sixbits & 0x030)) { // Tbl read, 2-9 into past
rdaddr = (m_rdaddr - (((sixbits>>1)&0x07)+2)) & 0x03ff;
val = m_readtbl[rdaddr];
m_lastaddr += (sixbits&1);
} else if (0x38 == (sixbits & 0x038)) { // Raw read
do {
nr += lclreadcode(&m_buf[nr], 6-nr);
} while (nr < 6);
 
val = (chardec(m_buf[0])>>1) & 0x03;
val = (val<<6) | (chardec(m_buf[1]) & 0x03f);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
val = (val<<6) | (chardec(m_buf[4]) & 0x03f);
val = (val<<6) | (chardec(m_buf[5]) & 0x03f);
 
m_readtbl[m_rdaddr++] = val; m_rdaddr &= 0x03ff;
m_lastaddr += (sixbits&1);
}
 
return val;
}
 
void TTYBUS::usleep(unsigned ms) {
if (m_dev->poll(ms)) {
int nr;
nr = m_dev->read(m_buf, 16);
if (nr == 0) {
// Connection closed, let it drop
DBGPRINTF("Connection closed!!\n");
m_dev->close();
exit(-1);
} for(int i=0; i<nr; i++) {
if (m_buf[i] == TTYC_INT) {
m_interrupt_flag = true;
// DBGPRINTF("!!!!!!!!!!!!!!!!! ----- INTERRUPT!\n");
} else if (m_buf[i] == TTYC_IDLE) {
// DBGPRINTF("Interface is now idle\n");
} else if (m_buf[i] == TTYC_WRITE) {
} else if (m_buf[i] == TTYC_RESET) {
// DBGPRINTF("Bus was RESET!\n");
} else if (m_buf[i] == TTYC_ERR) {
DBGPRINTF("Bus error\n");
} else if (m_buf[i] == TTYC_BUSY) {
// DBGPRINTF("Interface is ... busy ??\n");
}
// else if (m_buf[nr] == 'Q')
// else if (m_buf[nr] == 'W')
// else if (m_buf[nr] == '\n')
}
}
}
 
void TTYBUS::wait(void) {
if (m_interrupt_flag)
DBGPRINTF("INTERRUPTED PRIOR TO WAIT()\n");
do {
usleep(200);
} while(!m_interrupt_flag);
}
 
// TTYBUS: 3503421 ~= 3.3 MB, stopwatch = 1:18.5 seconds, vs 53.8 secs
// If you issue two 512 word reads at once, time drops to 41.6 secs.
// PORTBUS: 6408320 ~= 6.1 MB, ... 26% improvement, 53 seconds real time
 
/trunk/sw/txtest.cpp
0,0 → 1,256
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
// #include <usb.h>
 
#include <libusb.h>
 
// /sys/bus/usb/devices/1-4/ is our device, as currently plugged in
//
// It supports
// 1 configuration
// 1 interface
// and has a product string of...
// "XuLA - XESS Micro Logic Array"
//
#define VENDOR_ID 0x04d8
#define PRODUCT_ID 0x0ff8c
#define XESS_ENDPOINT_OUT 0x01
#define XESS_ENDPOINT_IN 0x81
//
#define JTAG_CMD 0x4f
#define GET_TDO_MASK 0x01
#define PUT_TMS_MASK 0x02
#define TMS_VAL_MASK 0x04
#define PUT_TDI_MASK 0x08
#define TDI_VAL_MASK 0x10
//
#define USER1_INSTR 0x02 // a SIX bit two
 
 
bool gbl_transfer_received = false;
 
// libusbtransfer_cb_fn callback;
extern "C" {
void my_callback(libusb_transfer *tfr) {
gbl_transfer_received = true;
 
printf("Callback received!\n");
}
}
 
// All messages must be 32 bytes or less
//
 
 
// Walk us through the JTAG Chain:
// 5-1's to go to test/reset
// 0 to go to Run-Test/Idle
// 1 to go to select-dr-scan
// 1 to go to select-ir-scan
// 0 to go to capture-ir
// 0 to go to shift-ir
// (6-bit code 0x02 through TDI to IR, while sending 0-bits to TMS)
// 1 to leave shift IR and go to exit1-ir
// 1 to go to update-ir
// 1 to go to select-dr-scan
// 0 to go to capture-dr
// 0 to go to shift-dr
#define RESET_JTAG_LEN 12
const char RESET_TO_USER_DR[RESET_JTAG_LEN] = {
JTAG_CMD,
21, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TMS_MASK | PUT_TDI_MASK, // flags
(char)(0x0df), // TMS: Five ones, then one zero, and two ones -- low bits first
0x00, // TDI: irrelevant here
(char)(0x80), // TMS: two zeros, then six zeros
0x08, // TDI: user command #1, bit reversed
0x03, // TMS: three ones, then two zeros
0x00 // TDI byte -- irrelevant here
//
// 0xc0, // TDI byte -- user command #2
// 0x40, // TDI: user command #1
// 0x0c, // TDI byte -- user command #2, bit reversed
};
 
//
// TMS:
/*
#define TX_DR_LEN 12
const char TX_DR_BITS[TX_DR_LEN] = {
JTAG_CMD,
48, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TDI_MASK, // flags
(char)0x0ff, 0, 0, 0, 0, 0 // Six data bytes
// module_id = 255
// 32'h(payload.length)
// payload
// module_id + payload.len + num_result_bits, length=32 + payload ???
};
*/
 
//
// TMS:
//
#define REQ_RX_LEN 6
const char REQ_RX_BITS[REQ_RX_LEN] = {
JTAG_CMD,
(char)((32-6)*8), // bits-requested
0,0,0, // Also clocks, higher order bits
GET_TDO_MASK|TDI_VAL_MASK, // flags:TDI is kept low here, so no TDI flag
// No data given, since there's no info to send or receive
// Leave the result in shift-DR mode
};
 
#define RETURN_TO_RESET_LEN 7
const char RETURN_TO_RESET[RETURN_TO_RESET_LEN] = {
JTAG_CMD,
5, // clocks
0,0,0, // Also clocks, higher order bits
PUT_TMS_MASK, // flags
(char)(0x0ff), // Five ones
};
 
int dec(int v) {
int br = 0;
 
/*
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
 
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
br = (br<<1)|(v&1); v>>=1;
*/
br = v&0x07f;
 
if (br == ' ')
return br;
else if (isgraph(br))
return br;
else
return '.';
}
 
//
// If max packet length is 32, why do you waste 4 bytes on num_clocks?
// Why is the bit counter always from 8 to zero?
//
 
int main(int argc, char **argv) {
libusb_context *usb_context;
libusb_device_handle *xula_usb_device;
int config;
 
if (0 != libusb_init(&usb_context)) {
fprintf(stderr, "Error initializing the USB library\n");
perror("O/S Err:");
exit(-1);
}
 
xula_usb_device = libusb_open_device_with_vid_pid(usb_context,
VENDOR_ID, PRODUCT_ID);
if (!xula_usb_device) {
fprintf(stderr, "Could not open XuLA device\n");
perror("O/S Err:");
 
libusb_exit(usb_context);
exit(-1);
}
 
if (0 != libusb_get_configuration(xula_usb_device, &config)) {
fprintf(stderr, "Could not get configuration\n");
perror("O/S Err:");
 
libusb_close(xula_usb_device);
libusb_exit(usb_context);
exit(-1);
}
 
printf("Current configuration is %d\n", config);
int interface = 0;
 
if (0 != libusb_claim_interface(xula_usb_device, interface)) {
fprintf(stderr, "Could not claim interface\n");
perror("O/S Err:");
 
libusb_close(xula_usb_device);
libusb_exit(usb_context);
exit(-1);
}
 
unsigned char *abuf = new unsigned char[32];
int actual_length = 32;
memcpy(abuf, RESET_TO_USER_DR, RESET_JTAG_LEN);
int r = libusb_bulk_transfer(xula_usb_device, XESS_ENDPOINT_OUT,
abuf, RESET_JTAG_LEN, &actual_length, 20);
if ((r==0)&&(actual_length == RESET_JTAG_LEN)) {
printf("Successfully sent RESET_TO_USER_DR!\n");
} else {
printf("Some error took place requesting RESET_TO_USER_DR\n");
perror("O/S Err");
}
 
const char hello_world[] = "Hello, World!\n";
abuf[0] = JTAG_CMD;
abuf[1] = strlen(hello_world) * 8 + 8;
abuf[2] = abuf[3] = abuf[4] = 0;
abuf[5] = PUT_TDI_MASK | GET_TDO_MASK;
strcpy((char *)&abuf[6], hello_world);
// abuf[6] = 0xff;
// abuf[7] = 0xff;
// abuf[8] = 0x00;
// abuf[9] = 0xff;
// abuf[10] = 0x01;
// abuf[11] = 0x02;
// abuf[12] = 0x04;
// abuf[13] = 0x08;
r = libusb_bulk_transfer(xula_usb_device, XESS_ENDPOINT_OUT,
abuf, strlen(hello_world)+6+1, &actual_length, 20);
if ((r==0)&&(actual_length == strlen(hello_world)+6+1)) {
printf("Successfully sent request for TDO bits!\n");
} else {
printf("Some error took place in requesting TDO bits\n");
printf("r = %d, actual_length = %d (!= %d)\n", r,
actual_length, (int)strlen(hello_world)+6);
perror("O/S Err");
}
 
r = libusb_bulk_transfer(xula_usb_device, XESS_ENDPOINT_IN,
abuf, strlen(hello_world)+1, &actual_length, 20);
if ((r==0)&&(actual_length > 0)) {
printf("Successfully read %d bytes from port!\n", actual_length);
for(int i=0; i<(actual_length); i+=4)
printf("%2d: %02x %02x %02x %02x -- %c%c%c%c\n", i,
abuf[i+0], abuf[i+1], abuf[i+2], abuf[i+3],
dec(abuf[i+0]),dec(abuf[i+1]), dec(abuf[i+2]), dec(abuf[i+3]));
} else {
printf("Some error took place in receiving\n");
perror("O/S Err");
}
 
 
// Release our interface
if (0 != libusb_release_interface(xula_usb_device, interface)) {
fprintf(stderr, "Could not release interface\n");
perror("O/S Err:");
 
libusb_close(xula_usb_device);
libusb_exit(usb_context);
exit(-1);
}
 
// And then close our device with
libusb_close(xula_usb_device);
 
// And just before exiting, we free our USB context
libusb_exit(usb_context);
}
 
/trunk/sw/dumpsdram.cpp
0,0 → 1,139
////////////////////////////////////////////////////////////////////////////////
//
// Filename: dumpsdram.cpp
//
// Project: XuLA2 board
//
// Purpose: Read local memory, dump into a file.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "usbi.h"
#include "port.h"
#include "regdefs.h"
 
FPGA *m_fpga;
 
int main(int argc, char **argv) {
FILE *fp, *fpin;
unsigned pos=0;
const int BUFLN = 127;
FPGA::BUSW *buf = new FPGA::BUSW[BUFLN],
*cmp = new FPGA::BUSW[BUFLN];
 
if (argc<=2) {
printf("Usage: dumpsdram srcfile outfile\n");
exit(-1);
}
 
FPGAOPEN(m_fpga);
 
fpin = fopen(argv[1], "rb");
if (fpin == NULL) {
fprintf(stderr, "Could not open %s\n", argv[1]);
exit(-1);
}
 
try {
int nr;
pos = SDRAMBASE;
do {
nr = BUFLN;
if (nr + pos > SDRAMBASE*2)
nr = SDRAMBASE*2 - pos;
nr = fread(buf, sizeof(FPGA::BUSW), nr, fpin);
if (nr <= 0)
break;
m_fpga->writei(pos, nr, buf);
pos += nr;
} while((nr > 0)&&(pos < 2*SDRAMBASE));
 
printf("SUCCESS::fully wrote full file to memory (pos = %08x)\n", pos);
} catch(BUSERR a) {
fprintf(stderr, "BUS Err while writing at address 0x%08x\n", a.addr);
fprintf(stderr, "... is your program too long for this memory?\n");
exit(-2);
}
 
rewind(fpin);
 
fp = fopen(argv[2], "wb");
if (fp == NULL) {
fprintf(stderr, "Could not open: %s\n", argv[2]);
exit(-1);
}
 
try {
pos = SDRAMBASE;
const unsigned int MAXRAM = SDRAMBASE*2;
do {
int nw, nr;
if (MAXRAM-pos > BUFLN)
nr = BUFLN;
else
nr = MAXRAM-pos;
m_fpga->readi(pos, nr, buf);
pos += nr;
nw = fwrite(buf, sizeof(FPGA::BUSW), nr, fp);
if (nw < nr) {
printf("Only wrote %d of %d words!\n", nw, nr);
exit(-2);
} printf("nr = %d, pos = %08x (%08x / %08x)\n", nr,
pos, SDRAMBASE, MAXRAM);
 
{int cr;
cr = fread(cmp, sizeof(FPGA::BUSW), nr, fpin);
for(int i=0; i<cr; i++)
if (cmp[i] != buf[i])
fprintf(stderr, "MISMATCH: MEM[%08x] = %08x != %08x\n",
pos-nr+i, buf[i], cmp[i]);
if (cr != nr) {
printf("Only read %d words from our input file\n", cr);
break;
}
}
} while(pos < MAXRAM);
printf("Successfully read&copied %04x (%6d) words from memory\n",
pos-SDRAMBASE, pos-SDRAMBASE);
} catch(BUSERR a) {
fprintf(stderr, "BUS Err at address 0x%08x\n", a.addr);
fprintf(stderr, "... is your program too long for this memory?\n");
exit(-2);
}
 
delete m_fpga;
}
 
/trunk/sw/Makefile
0,0 → 1,129
################################################################################
##
## Filename: Makefile
##
## Project: XuLA2 board
##
## Purpose:
##
##
## Creator: Dan Gisselquist, Ph.D.
## Gisselquist Technology, LLC
##
################################################################################
##
## Copyright (C) 2015, Gisselquist Technology, LLC
##
## This program is free software (firmware): you can redistribute it and/or
## modify it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## License: GPL, v3, as defined and found on www.gnu.org,
## http:##www.gnu.org/licenses/gpl.html
##
##
################################################################################
##
##
.PHONY: all
PROGRAMS := $(OBJDIR) usbtst wbregs netusb wbsettime dumpflash \
dumpsdram ziprun ramscope
all: $(PROGRAMS)
CXX := g++
LIBUSBINC := -I/usr/include/libusb-1.0/
LIBUSBDIR := -L/usr/lib/x86_64-linux-gnu
OBJDIR := obj-pc
ZIPD := /home/dan/work/rnd/zipcpu/trunk/sw/zasm
BUSSRCS := ttybus.cpp llcomms.cpp regdefs.cpp usbi.cpp
SOURCES := ziprun.cpp zipdbg.cpp dumpsdram.cpp wbregs.cpp netusb.cpp $(BUSSRCS)
HEADERS := llcomms.h ttybus.h devbus.h regdefs.h usbi.h
OBJECTS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(SOURCES)))
BUSOBJS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(BUSSRCS)))
CFLAGS := -g -Wall $(LIBUSBINC) -I. -I../../fpgalib/sw
LIBS := -lusb-1.0
 
all: $(PROGRAMS)
 
%.o: $(OBJDIR)/ $(OBJDIR)/%.o
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CFLAGS) -c $< -o $@
$(OBJDIR)/zipdbg.o: zipdbg.cpp
$(CXX) $(CFLAGS) -I$(ZIPD) -c $< -o $@
$(OBJDIR)/cpuscope.o: cpuscope.cpp
$(CXX) $(CFLAGS) -I$(ZIPD) -c $< -o $@
 
.PHONY: clean
clean:
rm -rf $(OBJDIR)/ $(PROGRAMS)
 
 
# wbprogram: $(OBJDIR)/wbprogram.o $(OBJDIR)/flashdrvr.o $(BUSOBJS)
# $(CXX) -g $^ -o $@
netusb: $(OBJDIR)/netusb.o $(OBJDIR)/usbi.o $(OBJDIR)/llcomms.o
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
wbsettime: $(OBJDIR)/wbsettime.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
wbregs: $(OBJDIR)/wbregs.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
dumpflash: $(OBJDIR)/dumpflash.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
cfgscope: $(OBJDIR)/cfgscope.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
ramscope: $(OBJDIR)/ramscope.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
dumpsdram: $(OBJDIR)/dumpsdram.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
ziprun: $(OBJDIR)/ziprun.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
ZIPOBJS_RAW := twoc.o zparser.o zopcodes.o
ZIPOBJS := $(addprefix $(ZIPD)/$(OBJDIR)/,$(ZIPOBJS_RAW))
zipdbg: $(OBJDIR)/zipdbg.o $(BUSOBJS) $(ZIPOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -lncurses -o $@
cpuscope: $(OBJDIR)/cpuscope.o $(BUSOBJS) $(ZIPOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
 
nothing:
@echo
 
# ziprun: $(OBJDIR)/ziprun.o $(BUSOBJS)
# $(CXX) -g $^ -o $@
# zipdbg: zipdbg.cpp $(ZIPD)/zparser.cpp $(ZIPD)/zopcodes.cpp $(ZIPD)/twoc.cpp $(BUSOBJS)
# $(CXX) -g -I../bench/cpp -I $(ZIPD)/ $^ -lncurses -o $@
 
usbtst: usbtst.cpp
$(CXX) $(CFLAGS) usbtst.cpp $(LIBS) -o usbtst
txtest: txtest.cpp
$(CXX) $(CFLAGS) txtest.cpp $(LIBS) -o txtest
 
 
define build-depends
@echo "Building dependency file(s)"
@$(CXX) $(CPPFLAGS) -MM -I$(ZIPD) $(SOURCES) > $(OBJDIR)/xdepends.txt
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
@rm $(OBJDIR)/xdepends.txt
endef
 
tags: $(SOURCES) $(HEADERS)
@echo "Generating tags"
@ctags $(SOURCES) $(HEADERS)
 
.PHONY: depends
depends: tags
$(build-depends)
 
$(OBJDIR)/depends.txt: $(OBJDIR)/ $(SOURCES) $(HEADERS)
$(build-depends)
 
$(OBJDIR)/:
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
 
# obj-pc/usbi.o: usbi.cpp
# $(CXX) $(LIBUSBINC) -I../../fpgalib/sw -c usbi.cpp -o $@
 
-include $(OBJDIR)/depends.txt
/trunk/sw/devbus.h
0,0 → 1,106
////////////////////////////////////////////////////////////////////////////////
//
// Filename: devbus.h
//
// Project: XuLA2 board
//
// Purpose: The purpose of this file is to document an interface which
// any device with a bus, whether it be implemented over a UART,
// an ethernet, or a PCI express bus, must implement. This describes
// only an interface, and not how that interface is to be accomplished.
//
// The neat part of this interface is that, if programs are designed to
// work with it, than the implementation details may be changed later
// and any program that once worked with the interface should be able
// to continue to do so. (i.e., switch from a UART controlled bus to a
// PCI express controlled bus, with minimal change to the software of
// interest.)
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#ifndef DEVBUS_H
#define DEVBUS_H
 
#include <stdio.h>
#include <unistd.h>
 
typedef unsigned int uint32;
 
class BUSERR {
public:
uint32 addr;
BUSERR(const uint32 a) : addr(a) {};
};
 
class DEVBUS {
public:
typedef uint32 BUSW;
 
virtual void kill(void) = 0;
virtual void close(void) = 0;
 
// Write a single value to a single address
virtual void writeio(const BUSW a, const BUSW v) = 0;
 
// Read a single value to a single address
virtual BUSW readio(const BUSW a) = 0;
 
// Read a series of values from values from a block of memory
virtual void readi(const BUSW a, const int len, BUSW *buf) = 0;
 
// Read a series of values from the same address in memory
virtual void readz(const BUSW a, const int len, BUSW *buf) = 0;
 
virtual void writei(const BUSW a, const int len, const BUSW *buf) = 0;
virtual void writez(const BUSW a, const int len, const BUSW *buf) = 0;
 
// Query whether or not an interrupt has taken place
virtual bool poll(void) = 0;
 
// Sleep until interrupt, but sleep no longer than msec milliseconds
virtual void usleep(unsigned msec) = 0;
 
// Sleep until an interrupt, no matter how long it takes for that
// interrupt to take place
virtual void wait(void) = 0;
 
// Query whether or not a bus error has taken place. This is somewhat
// of a misnomer, as my current bus error detection code exits any
// interface, but ... it is what it is.
virtual bool bus_err(void) const = 0;
 
// Clear any bus error condition.
virtual void reset_err(void) = 0;
 
// Clear any interrupt condition that has already been noticed by
// the interface, does not check for further interrupt
virtual void clear(void) = 0;
 
virtual ~DEVBUS(void) { };
};
 
#endif

powered by: WebSVN 2.1.0

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