URL
https://opencores.org/ocsvn/openarty/openarty/trunk
Subversion Repositories openarty
Compare Revisions
- This comparison shows the changes necessary to convert path
/openarty/trunk
- from Rev 27 to Rev 28
- ↔ Reverse comparison
Rev 27 → Rev 28
/bench/cpp/uartsim.cpp
4,7 → 4,7
// |
// Project: XuLA2-LX25 SoC based upon the ZipCPU |
// |
// Purpose: |
// Purpose: To forward a Verilator simulated UART link over a TCP/IP pipe. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
44,6 → 44,7
#include <unistd.h> |
#include <arpa/inet.h> |
#include <signal.h> |
#include <ctype.h> |
|
#include "uartsim.h" |
|
72,6 → 73,8
|
memset(&my_addr, 0, sizeof(struct sockaddr_in)); // clear structure |
my_addr.sin_family = AF_INET; |
// Use *all* internet ports to this computer, allowing connections from |
// any/every one of them. |
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
my_addr.sin_port = htons(port); |
|
87,9 → 90,13
} |
|
UARTSIM::UARTSIM(const int port) { |
m_con = m_skt = -1; |
setup_listener(port); |
setup(25); |
m_conrd = m_conwr = m_skt = -1; |
if (port == 0) { |
m_conrd = STDIN_FILENO; |
m_conwr = STDOUT_FILENO; |
} else |
setup_listener(port); |
setup(25); // Set us up for (default) 8N1 w/ a baud rate of CLK/25 |
m_rx_baudcounter = 0; |
m_tx_baudcounter = 0; |
m_rx_state = RXIDLE; |
98,8 → 105,11
|
void UARTSIM::kill(void) { |
// Close any active connection |
if (m_con >= 0) close(m_con); |
if (m_conrd >= 0) close(m_conrd); |
if ((m_conwr >= 0)&&(m_conwr != m_conrd)) close(m_conwr); |
if (m_skt >= 0) close(m_skt); |
|
m_conrd = m_conwr = m_skt = -1; |
} |
|
void UARTSIM::setup(unsigned isetup) { |
114,10 → 124,10
} |
} |
|
int UARTSIM::tick(int i_tx) { |
int UARTSIM::nettick(int i_tx) { |
int o_rx = 1; |
|
if (m_con < 0) { |
if ((m_conrd < 0)&&(m_conwr<0)&&(m_skt>=0)) { |
// Can we accept a connection? |
struct pollfd pb; |
|
126,9 → 136,10
poll(&pb, 1, 0); |
|
if (pb.revents & POLLIN) { |
m_con = accept(m_skt, 0, 0); |
m_conrd = accept(m_skt, 0, 0); |
m_conwr = m_conrd; |
|
if (m_con < 0) |
if (m_conrd < 0) |
perror("Accept failed:"); |
} |
} |
141,7 → 152,7
if (m_rx_state == RXIDLE) { |
if (!i_tx) { |
m_rx_state = RXDATA; |
m_rx_baudcounter =m_baud_counts+m_baud_counts/2; |
m_rx_baudcounter =m_baud_counts+m_baud_counts/2-1; |
m_rx_baudcounter -= m_rx_changectr; |
m_rx_busy = 0; |
m_rx_data = 0; |
149,12 → 160,12
} else if (m_rx_baudcounter <= 0) { |
if (m_rx_busy >= (1<<(m_nbits+m_nparity+m_nstop-1))) { |
m_rx_state = RXIDLE; |
if (m_con > 0) { |
if (m_conwr >= 0) { |
char buf[1]; |
buf[0] = (m_rx_data >> (32-m_nbits-m_nstop-m_nparity))&0x0ff; |
if (1 != send(m_con, buf, 1, 0)) { |
close(m_con); |
m_con = -1; |
if (1 != send(m_conwr, buf, 1, 0)) { |
close(m_conwr); |
m_conrd = m_conwr = -1; |
} |
} |
} else { |
171,28 → 182,31
// stop bit |
// (possible secondary stop bit) |
m_rx_data = ((i_tx&1)<<31) | (m_rx_data>>1); |
} m_rx_baudcounter = m_baud_counts; |
} m_rx_baudcounter = m_baud_counts-1; |
} else |
m_rx_baudcounter--; |
|
if (m_tx_state == TXIDLE) { |
struct pollfd pb; |
pb.fd = m_con; |
pb.fd = m_conrd; |
pb.events = POLLIN; |
if (poll(&pb, 1, 0) < 0) |
perror("Polling error:"); |
if (pb.revents & POLLIN) { |
char buf[1]; |
if (1 == recv(m_con, buf, 1, MSG_DONTWAIT)) { |
if (1 == recv(m_conrd, buf, 1, MSG_DONTWAIT)) { |
m_tx_data = (-1<<(m_nbits+m_nparity+1)) |
// << nstart_bits |
|((buf[0]<<1)&0x01fe); |
if (m_nparity) { |
int p; |
|
// If m_nparity is set, we need to then |
// create the parity bit. |
if (m_fixdp) |
p = m_evenp; |
else { |
int p = (m_tx_data >> 1)&0x0ff; |
p = (m_tx_data >> 1)&0x0ff; |
p = p ^ (p>>4); |
p = p ^ (p>>2); |
p = p ^ (p>>1); |
204,9 → 218,112
m_tx_busy = (1<<(m_nbits+m_nparity+m_nstop+1))-1; |
m_tx_state = TXDATA; |
o_rx = 0; |
m_tx_baudcounter = m_baud_counts; |
m_tx_baudcounter = m_baud_counts-1; |
} |
} |
} else if (m_tx_baudcounter <= 0) { |
m_tx_data >>= 1; |
m_tx_busy >>= 1; |
if (!m_tx_busy) |
m_tx_state = TXIDLE; |
else |
m_tx_baudcounter = m_baud_counts-1; |
o_rx = m_tx_data&1; |
} else { |
m_tx_baudcounter--; |
o_rx = m_tx_data&1; |
} |
|
return o_rx; |
} |
|
int UARTSIM::fdtick(int i_tx) { |
int o_rx = 1; |
|
if ((!i_tx)&&(m_last_tx)) |
m_rx_changectr = 0; |
else m_rx_changectr++; |
m_last_tx = i_tx; |
|
if (m_rx_state == RXIDLE) { |
if (!i_tx) { |
m_rx_state = RXDATA; |
m_rx_baudcounter =m_baud_counts+m_baud_counts/2-1; |
m_rx_baudcounter -= m_rx_changectr; |
m_rx_busy = 0; |
m_rx_data = 0; |
} |
} else if (m_rx_baudcounter <= 0) { |
if (m_rx_busy >= (1<<(m_nbits+m_nparity+m_nstop-1))) { |
m_rx_state = RXIDLE; |
if (m_conwr >= 0) { |
char buf[1]; |
buf[0] = (m_rx_data >> (32-m_nbits-m_nstop-m_nparity))&0x0ff; |
if (1 != write(m_conwr, buf, 1)) { |
fprintf(stderr, "ERR while attempting to write out--closing output port\n"); |
perror("UARTSIM::write() "); |
m_conrd = m_conwr = -1; |
} |
} |
} else { |
m_rx_busy = (m_rx_busy << 1)|1; |
// Low order bit is transmitted first, in this |
// order: |
// Start bit (1'b1) |
// bit 0 |
// bit 1 |
// bit 2 |
// ... |
// bit N-1 |
// (possible parity bit) |
// stop bit |
// (possible secondary stop bit) |
m_rx_data = ((i_tx&1)<<31) | (m_rx_data>>1); |
} m_rx_baudcounter = m_baud_counts-1; |
} else |
m_rx_baudcounter--; |
|
if ((m_tx_state == TXIDLE)&&(m_conrd >= 0)) { |
struct pollfd pb; |
pb.fd = m_conrd; |
pb.events = POLLIN; |
if (poll(&pb, 1, 0) < 0) |
perror("Polling error:"); |
if (pb.revents & POLLIN) { |
char buf[1]; |
int nr; |
if (1==(nr = read(m_conrd, buf, 1))) { |
m_tx_data = (-1<<(m_nbits+m_nparity+1)) |
// << nstart_bits |
|((buf[0]<<1)&0x01fe); |
if (m_nparity) { |
int p; |
|
// If m_nparity is set, we need to then |
// create the parity bit. |
if (m_fixdp) |
p = m_evenp; |
else { |
p = (m_tx_data >> 1)&0x0ff; |
p = p ^ (p>>4); |
p = p ^ (p>>2); |
p = p ^ (p>>1); |
p &= 1; |
p ^= m_evenp; |
} |
m_tx_data |= (p<<(m_nbits+m_nparity)); |
} |
m_tx_busy = (1<<(m_nbits+m_nparity+m_nstop+1))-1; |
m_tx_state = TXDATA; |
o_rx = 0; |
m_tx_baudcounter = m_baud_counts-1; |
} else if (nr < 0) { |
fprintf(stderr, "ERR while attempting to read in--closing input port\n"); |
perror("UARTSIM::read() "); |
m_conrd = -1; |
} // and we really don't care if nr == 0 except that |
// the poll above is supposed to keep it from happening |
} |
} else if (m_tx_baudcounter == 0) { |
m_tx_data >>= 1; |
m_tx_busy >>= 1; |
213,7 → 330,7
if (!m_tx_busy) |
m_tx_state = TXIDLE; |
else |
m_tx_baudcounter = m_baud_counts; |
m_tx_baudcounter = m_baud_counts-1; |
o_rx = m_tx_data&1; |
} else { |
m_tx_baudcounter--; |
/bench/cpp/uartsim.h
4,8 → 4,11
// |
// Project: XuLA2-LX25 SoC based upon the ZipCPU |
// |
// Purpose: |
// Purpose: To forward a Verilator simulated UART link over a TCP/IP pipe. |
// |
// This file provides the description of the interface between the UARTSIM |
// and the rest of the world. See below for more detailed descriptions. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
54,23 → 57,74
#define RXDATA 1 |
|
class UARTSIM { |
int m_skt, m_con; |
// The file descriptors: |
// m_skt is the socket/port we are listening on |
// m_conrd is the file descriptor to read from |
// m_conwr is the file descriptor to write to |
int m_skt, m_conrd, m_conwr; |
// |
// The m_setup register is the 29'bit control register used within |
// the core. |
unsigned m_setup; |
// And the pieces of the setup register broken out. |
int m_nparity, m_fixdp, m_evenp, m_nbits, m_nstop, m_baud_counts; |
|
// UART state |
int m_rx_baudcounter, m_rx_state, m_rx_busy, |
m_rx_changectr, m_last_tx; |
int m_tx_baudcounter, m_tx_state, m_tx_busy; |
unsigned m_rx_data, m_tx_data; |
|
// setup_listener is an attempt to encapsulate all of the network |
// related setup stuff. |
void setup_listener(const int port); |
int tick(const int i_tx); |
|
// nettick() gets called if we are connected to a network, and |
int nettick(const int i_tx); |
// fdtick() if we are not. |
int fdtick(const int i_tx); |
|
// We'll use the file descriptor for the listener socket to determine |
// whether we are connected to the network or not. If not connected |
// to the network, then we assume m_conrd and m_conwr refer to |
// your more traditional file descriptors, and use them as such. |
int tick(const int i_tx) { |
if (m_skt >= 0) |
return nettick(i_tx); |
else |
return fdtick(i_tx); |
} |
|
public: |
// |
// The UARTSIM constructor takes one argument: the port on the |
// localhost to listen in on. Once started, connections may be made |
// to this port to get the output from the port. |
UARTSIM(const int port); |
|
// kill() closes any active connection and the socket. Once killed, |
// no further output will be sent to the port. |
void kill(void); |
|
// setup() busts out the bits from isetup to the various internal |
// parameters. It is ideally only called between bits at appropriate |
// transition intervals. |
void setup(unsigned isetup); |
|
// The operator() function is called on every tick. The input is the |
// the output txuart transmit wire from the device. The output is to |
// be connected to the the rxuart receive wire into the device. This |
// makes hookup and operation very simple. |
// |
// This is the most appropriate simulation entry function if the |
// setup register will never change. |
// |
int operator()(int i_tx) { |
return tick(i_tx); } |
|
// If there is a possibility that the core might change the UART setup, |
// then it makes sense to include that current setup when calling the |
// tick operator. |
int operator()(int i_tx, unsigned isetup) { |
setup(isetup); return tick(i_tx); } |
}; |