Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VZMQ - ZeroMQ communication with VHDL simulation in GHDL

138 views
Skip to first unread message

Wojciech M. Zabołotny"

unread,
May 24, 2018, 8:42:04 AM5/24/18
to
Sometimes I need to run a VHDL simulation which communicates
with the C or Python application exchanging data other
than simple byte stream.
The minimal solution should provide exchange of at least
"packets" or "messages" of arbitrary length.
The sources below implement "VZMQ" that allows you
to send and receive such messages to/from the simulation
running in GHDL using the ZeroMQ library (so you can
communicate with application written in any language
that supports ZMQ).
The script "runme.sh" compiles the VZMQ, starts the
GHDL simulation and opens the xterm window, that
after a few seconds runs the Python script that
exchanges messages with the GHDL simulation.
The example messages are just strings, but you may
also transmit more complex structures (However,
the ZMQ should access them as the array of bytes
and VHDL should access them as the std_logic_vector.
You need to provide the necessary
serialization/deserialization procedures.

The code is published as PUBLIC DOMAIN or under
Creative Commons CC0 license (whichever better suits
your needs).
I do not give any warranty. You use it at your own
risk.

Wojciech M. Zabolotny (wzab01<at>gmail.com)

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.15.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh26462
# Made on 2018-05-24 14:25 CEST by <wzab@wzdell>.
# Source directory was '/tmp/zmq'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 172 -rwxr--r-- runme.sh
# 2334 -rw-r--r-- vzmqc.c
# 2644 -rw-r--r-- vzmq_pkg.vhd
# 3506 -rw-r--r-- vzmq_tb.vhd
# 258 -rw-r--r-- zmqtest.py
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
if test "X$1" = "X-c"
then keep_file=''
else keep_file=true
fi
echo=echo
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=
locale_dir=
set_echo=false

for dir in $PATH
do
if test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir
set_echo=true
break ;;
esac
fi
done

if ${set_echo}
then
set_echo=false
for dir in $PATH
do
if test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
set_echo=true
break
fi
done

if ${set_echo}
then
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
fi
IFS="$save_IFS"
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'

else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and
installing GNU '\''touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
exit 1
fi
# ============= runme.sh ==============
if test -n "${keep_file}" && test -f 'runme.sh'
then
${echo} "x - SKIPPING runme.sh (file already exists)"

else
${echo} "x - extracting runme.sh (text)"
sed 's/^X//' << 'SHAR_EOF' > 'runme.sh' &&
#!/bin/sh
set -e
gcc -c vzmqc.c
ghdl -a vzmq_pkg.vhd vzmq_tb.vhd
ghdl -e -Wl,vzmqc.o -Wl,-lzmq vzmq_tb
xterm -e "sleep 5; python zmqtest.py" &
X./vzmq_tb --wave=test.ghw
X
SHAR_EOF
(set 20 18 05 24 12 31 45 'runme.sh'
eval "${shar_touch}") && \
chmod 0744 'runme.sh'
if test $? -ne 0
then ${echo} "restore of runme.sh failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'runme.sh': 'MD5 check failed'
) << \SHAR_EOF
71803dba096f59d026e27a5ac789379b runme.sh
SHAR_EOF

else
test `LC_ALL=C wc -c < 'runme.sh'` -ne 172 && \
${echo} "restoration warning: size of 'runme.sh' is not 172"
fi
fi
# ============= vzmqc.c ==============
if test -n "${keep_file}" && test -f 'vzmqc.c'
then
${echo} "x - SKIPPING vzmqc.c (file already exists)"

else
${echo} "x - extracting vzmqc.c (text)"
sed 's/^X//' << 'SHAR_EOF' > 'vzmqc.c' &&
/*
This is the C part of the VZMQ - package allowing to pass ZMQ messages
from software to the GHDL simuulation.
Code written by Wojciech M. Zabolotny (wzab01<at>gmail.com or
wzab<at>ise.pw.edu.pl)
Published as PUBLIC DOMAIN or under Creative Commons CC0 license
X */
X
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <zmq.h>
X
int zmq_smax=0, zmq_rmax=0;
void *ctx = NULL;
unsigned int mprio;
void *socket = NULL;
int rc=-1;
X
void init_zmq_server_c(const int i_zmq_smax,const int i_zmq_rmax)
{
X zmq_smax = i_zmq_smax;
X zmq_rmax = i_zmq_rmax;
X ctx = zmq_ctx_new ();
X assert (ctx);
X /* Create ZMQ_STREAM socket */
X socket = zmq_socket (ctx, ZMQ_PAIR); //When it was ZMQ_REP, I couldn't repeat call
X assert (socket);
X rc = zmq_bind (socket, "ipc://mystream2");
X assert (rc == 0);
}
X
void close_zmq_server(int ile)
{
}
X
void zmq_get_message_c(int nmax,int * nact,unsigned char *buf)
{
X int msize;
X unsigned char rbuf[zmq_rmax];
X if(nmax > zmq_rmax) {
X fprintf(stderr,"Too many bytes requested %d>%d\n",nmax,zmq_rmax);
X *nact=-1;
X return;
X }
X msize = zmq_recv (socket,rbuf,nmax, ZMQ_DONTWAIT);
X if(msize<0) {
X if(errno==EAGAIN) {
X *nact = 0;
X return;
X }
X perror("receive error ");
X fprintf(stderr,"Can't receive %d\n",msize);
X *nact=msize;
X return;
X } else {
X fprintf(stderr,"Received message of length: %d\n",msize);
X int i,j;
X for(i=0;i<msize;i++) {
X fprintf(stderr,"%c",rbuf[i]);
X for(j=0;j<8;j++)
X if(rbuf[i] & (1<<j))
X buf[i*8+j]=3;
X else
X buf[i*8+j]=2;
X }
X fprintf(stderr,"\n");
X *nact=msize;
X return;
X }
}
X
void zmq_put_message_c(int msize,int * nact,unsigned char *buf)
{
X int res=0,i,j;
X unsigned char wbuf[zmq_smax];
X //Check if the number of transmitted bytes is correct
X if(msize > zmq_smax) {
X fprintf(stderr,"Too many bytes requested %d>%d\n",msize,zmq_smax);
X *nact=-1;
X return;
X }
X //Translate the message from bit vector to bytes
X for(i=0;i<msize;i++) {
X wbuf[i] = 0;
X for(j=0;j<8;j++)
X if(buf[8*i+j]==3)
X wbuf[i] |= (1<<j);
X }
X res = zmq_send(socket,wbuf,msize, 0);
X if(res<0) {
X perror("transmit error ");
X fprintf(stderr,"Can't receive %d\n",res);
X *nact=res;
X return;
X } else {
X *nact=res;
X return;
X }
}
X
X
SHAR_EOF
(set 20 18 05 24 14 21 21 'vzmqc.c'
eval "${shar_touch}") && \
chmod 0644 'vzmqc.c'
if test $? -ne 0
then ${echo} "restore of vzmqc.c failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'vzmqc.c': 'MD5 check failed'
) << \SHAR_EOF
87bdd7492c372795944845a7b5c5f0f1 vzmqc.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'vzmqc.c'` -ne 2334 && \
${echo} "restoration warning: size of 'vzmqc.c' is not 2334"
fi
fi
# ============= vzmq_pkg.vhd ==============
if test -n "${keep_file}" && test -f 'vzmq_pkg.vhd'
then
${echo} "x - SKIPPING vzmq_pkg.vhd (file already exists)"

else
${echo} "x - extracting vzmq_pkg.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'vzmq_pkg.vhd' &&
-------------------------------------------------------------------------------
-- Title : Package vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vzmq_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-24
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016,2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
X
package vzmq is
X
X -- Maximum length of received and transmitted messages in bytes
X constant ZMQ_RCV_MAX : integer := 1000;
X constant ZMQ_SND_MAX : integer := 2000;
X
X procedure init_zmq_server (
X constant max_send : in integer;
X constant max_receive : in integer
X );
X attribute foreign of init_zmq_server : procedure is "VHPIDIRECT init_zmq_server_c";
X
X procedure zmq_get_message (
X variable nmax : in integer;
X variable nact : out integer;
X variable v1 : inout unsigned(0 to 8*ZMQ_RCV_MAX-1)
X );
X attribute foreign of zmq_get_message : procedure is "VHPIDIRECT zmq_get_message_c";
X
X procedure zmq_put_message (
X variable msize : in integer;
X variable nact : out integer;
X variable v1 : inout unsigned(0 to 8*ZMQ_SND_MAX-1)
X );
X attribute foreign of zmq_put_message : procedure is "VHPIDIRECT zmq_put_message_c";
X
end vzmq;
X
package body vzmq is
X
X procedure init_zmq_server (
X constant max_send : in integer;
X constant max_receive : in integer
X ) is
X begin
X assert false severity failure;
X end init_zmq_server;
X
X procedure zmq_get_message (
X variable nmax : in integer;
X variable nact : out integer;
X variable v1 : inout unsigned(0 to 8*ZMQ_RCV_MAX-1)
X ) is
X begin
X assert false severity failure;
X end zmq_get_message;
X
X procedure zmq_put_message (
X variable msize : in integer;
X variable nact : out integer;
X variable v1 : inout unsigned(0 to 8*ZMQ_SND_MAX-1)
X ) is
X begin
X assert false severity failure;
X end zmq_put_message;
X
end vzmq;
X
SHAR_EOF
(set 20 18 05 24 12 52 03 'vzmq_pkg.vhd'
eval "${shar_touch}") && \
chmod 0644 'vzmq_pkg.vhd'
if test $? -ne 0
then ${echo} "restore of vzmq_pkg.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'vzmq_pkg.vhd': 'MD5 check failed'
) << \SHAR_EOF
8d847724053e567b333ba1c5ac85c8ca vzmq_pkg.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'vzmq_pkg.vhd'` -ne 2644 && \
${echo} "restoration warning: size of 'vzmq_pkg.vhd' is not 2644"
fi
fi
# ============= vzmq_tb.vhd ==============
if test -n "${keep_file}" && test -f 'vzmq_tb.vhd'
then
${echo} "x - SKIPPING vzmq_tb.vhd (file already exists)"

else
${echo} "x - extracting vzmq_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'vzmq_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vhpi_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-24
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016, 2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.vzmq.all;
-------------------------------------------------------------------------------
X
entity vzmq_tb is
X
end vzmq_tb;
X
-------------------------------------------------------------------------------
X
architecture symul2 of vzmq_tb is
X
X signal sco : integer := 13254;
X signal sflag : std_logic := '0';
X
begin -- symul2
X
X process
X variable ts : integer := 5;
X variable nmax : integer := 1000;
X variable nact : integer := 0;
X variable buf : unsigned(0 to 8*ZMQ_RCV_MAX-1) := (others => '0');
X variable j : integer := 0;
X variable c : integer := 0;
X variable ln : line;
X begin
X init_zmq_server(ZMQ_SND_MAX, ZMQ_RCV_MAX);
X while true loop
X zmq_get_message(nmax, nact, buf);
X j := 0;
X c := 0;
X if nact > 0 then
X write(ln, integer'image(nact));
X writeline(OUTPUT, ln);
X for i in 0 to (8*nact)-1 loop
X c := c/2;
X if buf(i) = '1' then
X c :=c+128;
X end if;
X if j = 7 then
X write(ln, character'val(c));
X j := 0;
X c := 0;
X else
X j :=j+1;
X end if;
X end loop; -- i
X writeline(OUTPUT, ln);
X sflag <= '1';
X wait for 5 ns;
X sflag <= '0';
X wait for 5 ns;
X end if;
X end loop;
X
X end process;
X
X process(sflag)
X variable sbuf : unsigned(0 to 8*ZMQ_SND_MAX-1) := (others => '0');
X constant txt : string := "Confirmation message";
X variable cd : unsigned(7 downto 0);
X variable res : integer := 0;
X variable mlen : integer := 0;
X begin
X if rising_edge(sflag) then
X sbuf := (others => '0');
X for i in 1 to txt'length loop
X cd := to_unsigned(character'pos(txt(i)), 8);
X for j in 0 to 7 loop
X if cd(j) = '1' then
X sbuf((i-1)*8+j) := '1';
X end if;
X end loop; -- j
X end loop; -- i
X mlen := txt'length;
X report "message sent!" severity note;
X zmq_put_message(mlen, res, sbuf);
X report "returned " & integer'image(res) severity note;
X null;
X end if;
X null;
X end process;
X
end symul2;
X
-------------------------------------------------------------------------------
SHAR_EOF
(set 20 18 05 24 14 21 43 'vzmq_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'vzmq_tb.vhd'
if test $? -ne 0
then ${echo} "restore of vzmq_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'vzmq_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
b6748f1d917c60d56de015a8acd90632 vzmq_tb.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'vzmq_tb.vhd'` -ne 3506 && \
${echo} "restoration warning: size of 'vzmq_tb.vhd' is not 3506"
fi
fi
# ============= zmqtest.py ==============
if test -n "${keep_file}" && test -f 'zmqtest.py'
then
${echo} "x - SKIPPING zmqtest.py (file already exists)"

else
${echo} "x - extracting zmqtest.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'zmqtest.py' &&
#!/usr/bin/python
import zmq
import struct
ctx=zmq.Context()
s=ctx.socket(zmq.PAIR)
s.connect("ipc://mystream2")
mg1="This is the 1st message!"
s.send(mg1)
mg1="The 2nd message"
s.send(mg1)
mg1="The 3rd one"
s.send(mg1)
while True:
X m=s.recv()
X print m
X
X
X
SHAR_EOF
(set 20 18 05 24 12 12 13 'zmqtest.py'
eval "${shar_touch}") && \
chmod 0644 'zmqtest.py'
if test $? -ne 0
then ${echo} "restore of zmqtest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'zmqtest.py': 'MD5 check failed'
) << \SHAR_EOF
021cab96589714a365381c9b2483fd43 zmqtest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'zmqtest.py'` -ne 258 && \
${echo} "restoration warning: size of 'zmqtest.py' is not 258"
fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
exit 1
fi
exit 0


Wojciech M Zabołotny

unread,
May 26, 2018, 7:54:16 PM5/26/18
to
Sometimes I need to run a VHDL simulation which communicates
with the C or Python application exchanging data other
than simple byte stream.
The minimal solution should provide exchange of at least
"packets" or "messages" of arbitrary length.
The sources below implement "VZMQ" that allows you
to send and receive such messages to/from the simulation
running in GHDL using the ZeroMQ library (so you can
communicate with application written in any language
that supports ZMQ).
My previous solution provided dedicated VHDL functions
and worked via VHPI in GHDL.
However, I needed a portable solution able to work both
with GHDL and with Vivado XSIM.
Unfortunately, XSIM does not support VHPI, and the only
way to interface it with C code is via SystemVerilog
and DPI.
In XSIM t is not possible to interface SystemVerilog
functions and tasks directly with VHDL code.
Therefore, the new solution implements an IP block
vzmq, that is implemented either in VHDL (for GHDL)
or in SystemVerilog (for XSIM).
That blocks offers signals for transmitted (snd_msg)
and received (rcv_msg) messages and handshake lines:
change of state on snd_stb triggers sending of the
message, and toggling the rcv_stb triggers reception
of the message. Lines snd_ack and rcv_ack provide
confirmation of proper reception or transmission.
Lines snd_bytes transfer size of the transmitted
message. Lines rcv_bytes - the size of the received
message.
Directory "ghdl" contains implementation for the
GHDL simulator (run runme.sh to check, how it works).
Directory "dpi" contains implementation for XSIM.
Run the "build.sh" script to compile sources and
start simulation. When the simulation is started,
in another console run "python zmqtest.py".

The code is published as PUBLIC DOMAIN or under
Creative Commons CC0 license (whichever better suits
your needs).
I do not give any warranty. You use it at your own
risk.

Wojciech M. Zabolotny (wzab01<at>gmail.com)

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.15.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh07699
# Made on 2018-05-27 01:37 CEST by <wzab@wzab>.
# Source directory was '/home/wzab/biezace/VHDL/pipe_controller/mqtest/publik2'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 312 -rw-r--r-- ghdl/zmqtest.py
# 3130 -rw-r--r-- ghdl/vzmq.vhd
# 4950 -rw-r--r-- ghdl/vzmq_tb.vhd
# 181 -rwxr--r-- ghdl/runme.sh
# 2684 -rw-r--r-- ghdl/vzmq_pkg.vhd
# 2408 -rw-r--r-- ghdl/vzmqc.c
# 312 -rw-r--r-- dpi/zmqtest.py
# 4950 -rw-r--r-- dpi/vzmq_tb.vhd
# 1291 -rw-r--r-- dpi/vzmq_pkg.vhd
# 2733 -rw-r--r-- dpi/vzmqc.c
# 2308 -rw-r--r-- dpi/vzmq.sv
# 150 -rw-r--r-- dpi/build.sh
# ============= ghdl/zmqtest.py ==============
if test ! -d 'ghdl'; then
mkdir 'ghdl'
if test $? -eq 0
then ${echo} "x - created directory ghdl."
else ${echo} "x - failed to create directory ghdl."
exit 1
fi
fi
if test -n "${keep_file}" && test -f 'ghdl/zmqtest.py'
then
${echo} "x - SKIPPING ghdl/zmqtest.py (file already exists)"

else
${echo} "x - extracting ghdl/zmqtest.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl/zmqtest.py' &&
#!/usr/bin/python
import zmq
import struct
import time
ctx=zmq.Context()
s=ctx.socket(zmq.PAIR)
s.connect("ipc://mystream2")
mg1="This is the 1st message!"
s.send(mg1)
time.sleep(1)
mg1="The 2nd message"
s.send(mg1)
time.sleep(1)
mg1="The 3rd one"
s.send(mg1)
time.sleep(1)
while True:
X m=s.recv()
X print m
X
X
X
SHAR_EOF
(set 20 18 05 26 00 00 00 'ghdl/zmqtest.py'
eval "${shar_touch}") && \
chmod 0644 'ghdl/zmqtest.py'
if test $? -ne 0
then ${echo} "restore of ghdl/zmqtest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl/zmqtest.py': 'MD5 check failed'
) << \SHAR_EOF
3a90171ca14c580d93370cf467102ed1 ghdl/zmqtest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'ghdl/zmqtest.py'` -ne 312 && \
${echo} "restoration warning: size of 'ghdl/zmqtest.py' is not 312"
fi
fi
# ============= ghdl/vzmq.vhd ==============
if test ! -d 'ghdl'; then
mkdir 'ghdl'
if test $? -eq 0
then ${echo} "x - created directory ghdl."
else ${echo} "x - failed to create directory ghdl."
exit 1
fi
fi
if test -n "${keep_file}" && test -f 'ghdl/vzmq.vhd'
then
${echo} "x - SKIPPING ghdl/vzmq.vhd (file already exists)"

else
${echo} "x - extracting ghdl/vzmq.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl/vzmq.vhd' &&
-------------------------------------------------------------------------------
-- Title : Package vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vzmq_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-26
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL or XSIM simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016,2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.vzmq_pkg.all;
X
entity vzmq is
X generic (
X MAX_SND : integer := MAX_SND;
X MAX_RCV : integer := MAX_RCV);
X port (
X -- Sending interface
X snd_msg : in std_logic_vector(8*MAX_SND-1 downto 0);
X snd_stb : in std_logic;
X snd_bytes : in std_logic_vector(31 downto 0);
X snd_ack : out std_logic := '0';
X -- Receiving interface
X rcv_stb : in std_logic;
X rcv_ack : out std_logic := '0';
X rcv_msg : out std_logic_vector(8*MAX_RCV-1 downto 0);
X rcv_bytes : out std_logic_vector(31 downto 0)
X );
X
end entity vzmq;
X
architecture beh of vzmq is
X
X signal rcv_flag : std_logic := '0';
X
begin -- architecture beh
X
X -- Initialization of the ZMQ server
X process is
X begin -- process
X report "Initializing server" severity note;
X init_zmq_server(MAX_SND,MAX_RCV);
X wait;
X end process;
X
X process (snd_stb) is
X variable v_snd_bytes : integer := 0;
X variable v_act_snd : integer := 0;
X variable v_snd_msg : std_logic_vector(8*MAX_SND-1 downto 0) := (others => '0');
X begin -- process
X if snd_stb'event then
X report "send in VHDL" severity note;
X v_snd_bytes := to_integer(signed(snd_bytes));
X v_snd_msg := snd_msg;
X zmq_put_message(v_snd_bytes, v_act_snd, v_snd_msg);
X if (v_act_snd >= 0) then
X snd_ack <= '1';
X else
X snd_ack <= '0';
X end if;
X end if;
X end process;
X
X process (rcv_stb) is
X variable v_rcv_bytes : integer := 0;
X variable v_act_rcv : integer :=0 ;
X variable v_rcv_msg : std_logic_vector(8*MAX_RCV-1 downto 0) := (others => '0');
X begin -- process
X if rcv_stb'event then
X rcv_flag <= not rcv_flag;
X v_rcv_bytes := MAX_RCV;
X zmq_get_message(v_rcv_bytes, v_act_rcv, v_rcv_msg);
X rcv_msg <= v_rcv_msg;
X rcv_bytes <= std_logic_vector(to_signed(v_act_rcv,32));
X if (v_act_rcv > 0) then
X rcv_ack <= '1';
X else
X rcv_ack <= '0';
X end if;
X end if;
X end process;
X
X
end architecture beh;
X
SHAR_EOF
(set 20 18 05 26 23 29 37 'ghdl/vzmq.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl/vzmq.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl/vzmq.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl/vzmq.vhd': 'MD5 check failed'
) << \SHAR_EOF
27d4953e4265c07cb0fc7da65fc3bf3d ghdl/vzmq.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'ghdl/vzmq.vhd'` -ne 3130 && \
${echo} "restoration warning: size of 'ghdl/vzmq.vhd' is not 3130"
fi
fi
# ============= ghdl/vzmq_tb.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl/vzmq_tb.vhd'
then
${echo} "x - SKIPPING ghdl/vzmq_tb.vhd (file already exists)"

else
${echo} "x - extracting ghdl/vzmq_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl/vzmq_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vhpi_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-26
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL or XSIM simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016, 2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.vzmq_pkg.all;
-------------------------------------------------------------------------------
X
entity vzmq_tb is
X
end vzmq_tb;
X
-------------------------------------------------------------------------------
X
architecture symul2 of vzmq_tb is
X
X signal sco : integer := 13254;
X signal sflag : std_logic := '0';
X
X component vzmq
X generic (
X MAX_SND : integer := 16384;
X MAX_RCV : integer := 16384
X );
X port
X ( --Sending interface
X snd_msg : in std_logic_vector(8*MAX_SND-1 downto 0);
X snd_stb : in std_logic;
X snd_bytes : in std_logic_vector(31 downto 0);
X snd_ack : out std_logic;
X --Receiving interface
X rcv_stb : in std_logic;
X rcv_ack : out std_logic;
X rcv_msg : out std_logic_vector(8*MAX_RCV-1 downto 0);
X rcv_bytes : out std_logic_vector(31 downto 0)
X );
X end component;
X
X signal snd_msg : std_logic_vector(8*MAX_SND-1 downto 0) := (others => '0');
X signal snd_stb : std_logic := '0';
X signal snd_bytes : std_logic_vector(31 downto 0) := (others => '0');
X signal snd_ack : std_logic := '0';
X signal rcv_stb : std_logic := '0';
X signal rcv_ack : std_logic := '0';
X signal rcv_msg : std_logic_vector(8*MAX_RCV-1 downto 0) := (others => '0');
X signal rcv_bytes : std_logic_vector(31 downto 0) := (others => '0');
X
begin -- symul2
X
X vzmq_1 : vzmq
X generic map (
X MAX_SND => MAX_SND,
X MAX_RCV => MAX_RCV)
X port map (
X snd_msg => snd_msg,
X snd_stb => snd_stb,
X snd_bytes => snd_bytes,
X snd_ack => snd_ack,
X rcv_stb => rcv_stb,
X rcv_ack => rcv_ack,
X rcv_msg => rcv_msg,
X rcv_bytes => rcv_bytes);
X
X -- Receiving process
X process
X variable i, j : integer;
X variable c : integer;
X variable ln : line;
X variable nbytes : integer;
X begin
X while true loop
X wait for 1 ns;
X sflag <= '0';
X rcv_stb <= not rcv_stb;
X wait for 1 ns;
X if rcv_ack = '1' then
X report "message received!" severity note;
X sflag <= '1';
X nbytes := to_integer(signed(rcv_bytes));
X j := 0;
X c := 0;
X if nbytes > 0 then
X write(ln, integer'image(nbytes));
X writeline(OUTPUT, ln);
X for i in 0 to (8*nbytes)-1 loop
X c := c*2;
X if rcv_msg(i) = '1' then
X c := c+1;
X end if;
X if j = 7 then
X write(ln, character'val(c));
X j := 0;
X c := 0;
X else
X j := j+1;
X end if;
X end loop; -- i
X writeline(OUTPUT, ln);
X end if;
X end if;
X end loop;
X end process;
X
X process(sflag)
X constant txt : string := "Confirmation message";
X variable cd : unsigned(7 downto 0);
X variable res : integer := 0;
X variable mlen : integer := 0;
X begin
X if rising_edge(sflag) then
X snd_msg <= (others => '0');
X for i in 1 to txt'length loop
X cd := to_unsigned(character'pos(txt(i)), 8);
X for j in 0 to 7 loop
X if cd(j) = '1' then
X --snd_msg(8*(MAX_SND-i)+j) <= '1';
X snd_msg(8*(i-1)+7-j) <= '1';
X end if;
X end loop; -- j
X end loop; -- i
X snd_bytes <= std_logic_vector(to_unsigned(txt'length, 32));
X report "message sent!" severity note;
X snd_stb <= not snd_stb;
X --report "returned " & integer'image(res) severity note;
X null;
X end if;
X null;
X end process;
X
end symul2;
X
-------------------------------------------------------------------------------
SHAR_EOF
(set 20 18 05 26 23 29 31 'ghdl/vzmq_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl/vzmq_tb.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl/vzmq_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl/vzmq_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
066512de69d7282d72e52fcd8ab37b5d ghdl/vzmq_tb.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'ghdl/vzmq_tb.vhd'` -ne 4950 && \
${echo} "restoration warning: size of 'ghdl/vzmq_tb.vhd' is not 4950"
fi
fi
# ============= ghdl/runme.sh ==============
if test -n "${keep_file}" && test -f 'ghdl/runme.sh'
then
${echo} "x - SKIPPING ghdl/runme.sh (file already exists)"

else
${echo} "x - extracting ghdl/runme.sh (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl/runme.sh' &&
#!/bin/sh
set -e
gcc -c vzmqc.c
ghdl -a vzmq_pkg.vhd vzmq.vhd vzmq_tb.vhd
ghdl -e -Wl,vzmqc.o -Wl,-lzmq vzmq_tb
xterm -e "sleep 1; python zmqtest.py" &
X./vzmq_tb --wave=test.ghw
X
SHAR_EOF
(set 20 18 05 26 20 31 02 'ghdl/runme.sh'
eval "${shar_touch}") && \
chmod 0744 'ghdl/runme.sh'
if test $? -ne 0
then ${echo} "restore of ghdl/runme.sh failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl/runme.sh': 'MD5 check failed'
) << \SHAR_EOF
c6caf368454c278dc0210b657572b059 ghdl/runme.sh
SHAR_EOF

else
test `LC_ALL=C wc -c < 'ghdl/runme.sh'` -ne 181 && \
${echo} "restoration warning: size of 'ghdl/runme.sh' is not 181"
fi
fi
# ============= ghdl/vzmq_pkg.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl/vzmq_pkg.vhd'
then
${echo} "x - SKIPPING ghdl/vzmq_pkg.vhd (file already exists)"

else
${echo} "x - extracting ghdl/vzmq_pkg.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl/vzmq_pkg.vhd' &&
-------------------------------------------------------------------------------
-- Title : Package vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vzmq_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-26
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016,2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
X
package vzmq_pkg is
X
X -- Maximum length of received and transmitted messages in bytes
X constant MAX_SND : integer := 1000;
X constant MAX_RCV : integer := 2000;
X
X procedure init_zmq_server (
X constant max_send : in integer;
X constant max_receive : in integer
X );
X attribute foreign of init_zmq_server : procedure is "VHPIDIRECT init_zmq_server_c";
X
X procedure zmq_get_message (
X variable nmax : in integer;
X variable nact : out integer;
X variable v1 : inout std_logic_vector(8*MAX_RCV-1 downto 0)
X );
X attribute foreign of zmq_get_message : procedure is "VHPIDIRECT zmq_get_message_c";
X
X procedure zmq_put_message (
X variable msize : in integer;
X variable nact : out integer;
X variable v1 : inout std_logic_vector(8*MAX_SND-1 downto 0)
X );
X attribute foreign of zmq_put_message : procedure is "VHPIDIRECT zmq_put_message_c";
X
end vzmq_pkg;
X
package body vzmq_pkg is
X
X procedure init_zmq_server (
X constant max_send : in integer;
X constant max_receive : in integer
X ) is
X begin
X assert false severity failure;
X end init_zmq_server;
X
X procedure zmq_get_message (
X variable nmax : in integer;
X variable nact : out integer;
X variable v1 : inout std_logic_vector(8*MAX_RCV-1 downto 0)
X ) is
X begin
X assert false severity failure;
X end zmq_get_message;
X
X procedure zmq_put_message (
X variable msize : in integer;
X variable nact : out integer;
X variable v1 : inout std_logic_vector(8*MAX_SND-1 downto 0)
X ) is
X begin
X assert false severity failure;
X end zmq_put_message;
X
end vzmq_pkg;
X
SHAR_EOF
(set 20 18 05 26 23 29 22 'ghdl/vzmq_pkg.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl/vzmq_pkg.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl/vzmq_pkg.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl/vzmq_pkg.vhd': 'MD5 check failed'
) << \SHAR_EOF
aaabef83059db12aa7846b34afef7a83 ghdl/vzmq_pkg.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'ghdl/vzmq_pkg.vhd'` -ne 2684 && \
${echo} "restoration warning: size of 'ghdl/vzmq_pkg.vhd' is not 2684"
fi
fi
# ============= ghdl/vzmqc.c ==============
if test -n "${keep_file}" && test -f 'ghdl/vzmqc.c'
then
${echo} "x - SKIPPING ghdl/vzmqc.c (file already exists)"

else
${echo} "x - extracting ghdl/vzmqc.c (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl/vzmqc.c' &&
/*
This is the C part of the VZMQ - package allowing to pass ZMQ messages
from software to the GHDL simuulation.
Code written by Wojciech M. Zabolotny (wzab01<at>gmail.com or
wzab<at>ise.pw.edu.pl)
Published as PUBLIC DOMAIN or under Creative Commons CC0 license
X */
X
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <zmq.h>
X
static int zmq_smax=0, zmq_rmax=0;
static void *ctx = NULL;
static unsigned int mprio;
static void *socket = NULL;
static int rc=-1;
X buf[(zmq_rmax-i-1)*8+j]=3;
X else
X buf[(zmq_rmax-i-1)*8+j]=2;
X }
X fprintf(stderr,"\n");
X *nact=msize;
X return;
X }
}
X
void zmq_put_message_c(int msize,int * nact,unsigned char *buf)
{
X int res=0,i,j;
X unsigned char wbuf[zmq_smax];
X //Check if the number of transmitted bytes is correct
X if(msize > zmq_smax) {
X fprintf(stderr,"Too many bytes requested %d>%d\n",msize,zmq_smax);
X *nact=-1;
X return;
X }
X //Translate the message from bit vector to bytes
X for(i=0;i<msize;i++) {
X wbuf[i] = 0;
X for(j=0;j<8;j++)
X if(buf[(zmq_smax-i-1)*8+j]==3)
X wbuf[i] |= (1<<j);
X }
X res = zmq_send(socket,wbuf,msize, 0);
X if(res<0) {
X perror("transmit error ");
X fprintf(stderr,"Can't receive %d\n",res);
X *nact=res;
X return;
X } else {
X *nact=res;
X return;
X }
}
X
X
SHAR_EOF
(set 20 18 05 26 23 30 12 'ghdl/vzmqc.c'
eval "${shar_touch}") && \
chmod 0644 'ghdl/vzmqc.c'
if test $? -ne 0
then ${echo} "restore of ghdl/vzmqc.c failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl/vzmqc.c': 'MD5 check failed'
) << \SHAR_EOF
2fbbab58e7569cdcab30a433b040d807 ghdl/vzmqc.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'ghdl/vzmqc.c'` -ne 2408 && \
${echo} "restoration warning: size of 'ghdl/vzmqc.c' is not 2408"
fi
fi
# ============= dpi/zmqtest.py ==============
if test ! -d 'dpi'; then
mkdir 'dpi'
if test $? -eq 0
then ${echo} "x - created directory dpi."
else ${echo} "x - failed to create directory dpi."
exit 1
fi
fi
if test -n "${keep_file}" && test -f 'dpi/zmqtest.py'
then
${echo} "x - SKIPPING dpi/zmqtest.py (file already exists)"

else
${echo} "x - extracting dpi/zmqtest.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'dpi/zmqtest.py' &&
#!/usr/bin/python
import zmq
import struct
import time
ctx=zmq.Context()
s=ctx.socket(zmq.PAIR)
s.connect("ipc://mystream2")
mg1="This is the 1st message!"
s.send(mg1)
time.sleep(1)
mg1="The 2nd message"
s.send(mg1)
time.sleep(1)
mg1="The 3rd one"
s.send(mg1)
time.sleep(1)
while True:
X m=s.recv()
X print m
X
X
X
SHAR_EOF
(set 20 18 05 26 00 00 00 'dpi/zmqtest.py'
eval "${shar_touch}") && \
chmod 0644 'dpi/zmqtest.py'
if test $? -ne 0
then ${echo} "restore of dpi/zmqtest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'dpi/zmqtest.py': 'MD5 check failed'
) << \SHAR_EOF
3a90171ca14c580d93370cf467102ed1 dpi/zmqtest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'dpi/zmqtest.py'` -ne 312 && \
${echo} "restoration warning: size of 'dpi/zmqtest.py' is not 312"
fi
fi
# ============= dpi/vzmq_tb.vhd ==============
if test ! -d 'dpi'; then
mkdir 'dpi'
if test $? -eq 0
then ${echo} "x - created directory dpi."
else ${echo} "x - failed to create directory dpi."
exit 1
fi
fi
if test -n "${keep_file}" && test -f 'dpi/vzmq_tb.vhd'
then
${echo} "x - SKIPPING dpi/vzmq_tb.vhd (file already exists)"

else
${echo} "x - extracting dpi/vzmq_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'dpi/vzmq_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vhpi_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-26
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL or XSIM simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016, 2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.vzmq_pkg.all;
-------------------------------------------------------------------------------
X
entity vzmq_tb is
X
end vzmq_tb;
X
-------------------------------------------------------------------------------
X
architecture symul2 of vzmq_tb is
X
X signal sco : integer := 13254;
X signal sflag : std_logic := '0';
X
X component vzmq
X generic (
X MAX_SND : integer := 16384;
X MAX_RCV : integer := 16384
X );
X port
X ( --Sending interface
X snd_msg : in std_logic_vector(8*MAX_SND-1 downto 0);
X snd_stb : in std_logic;
X snd_bytes : in std_logic_vector(31 downto 0);
X snd_ack : out std_logic;
X --Receiving interface
X rcv_stb : in std_logic;
X rcv_ack : out std_logic;
X rcv_msg : out std_logic_vector(8*MAX_RCV-1 downto 0);
X rcv_bytes : out std_logic_vector(31 downto 0)
X );
X end component;
X
X signal snd_msg : std_logic_vector(8*MAX_SND-1 downto 0) := (others => '0');
X signal snd_stb : std_logic := '0';
X signal snd_bytes : std_logic_vector(31 downto 0) := (others => '0');
X signal snd_ack : std_logic := '0';
X signal rcv_stb : std_logic := '0';
X signal rcv_ack : std_logic := '0';
X signal rcv_msg : std_logic_vector(8*MAX_RCV-1 downto 0) := (others => '0');
X signal rcv_bytes : std_logic_vector(31 downto 0) := (others => '0');
X
begin -- symul2
X
X vzmq_1 : vzmq
X generic map (
X MAX_SND => MAX_SND,
X MAX_RCV => MAX_RCV)
X port map (
X snd_msg => snd_msg,
X snd_stb => snd_stb,
X snd_bytes => snd_bytes,
X snd_ack => snd_ack,
X rcv_stb => rcv_stb,
X rcv_ack => rcv_ack,
X rcv_msg => rcv_msg,
X rcv_bytes => rcv_bytes);
X
X -- Receiving process
X process
X variable i, j : integer;
X variable c : integer;
X variable ln : line;
X variable nbytes : integer;
X begin
X while true loop
X wait for 1 ns;
X sflag <= '0';
X rcv_stb <= not rcv_stb;
X wait for 1 ns;
X if rcv_ack = '1' then
X report "message received!" severity note;
X sflag <= '1';
X nbytes := to_integer(signed(rcv_bytes));
X j := 0;
X c := 0;
X if nbytes > 0 then
X write(ln, integer'image(nbytes));
X writeline(OUTPUT, ln);
X for i in 0 to (8*nbytes)-1 loop
X c := c*2;
X if rcv_msg(i) = '1' then
X c := c+1;
X end if;
X if j = 7 then
X write(ln, character'val(c));
X j := 0;
X c := 0;
X else
X j := j+1;
X end if;
X end loop; -- i
X writeline(OUTPUT, ln);
X end if;
X end if;
X end loop;
X end process;
X
X process(sflag)
X constant txt : string := "Confirmation message";
X variable cd : unsigned(7 downto 0);
X variable res : integer := 0;
X variable mlen : integer := 0;
X begin
X if rising_edge(sflag) then
X snd_msg <= (others => '0');
X for i in 1 to txt'length loop
X cd := to_unsigned(character'pos(txt(i)), 8);
X for j in 0 to 7 loop
X if cd(j) = '1' then
X --snd_msg(8*(MAX_SND-i)+j) <= '1';
X snd_msg(8*(i-1)+7-j) <= '1';
X end if;
X end loop; -- j
X end loop; -- i
X snd_bytes <= std_logic_vector(to_unsigned(txt'length, 32));
X report "message sent!" severity note;
X snd_stb <= not snd_stb;
X --report "returned " & integer'image(res) severity note;
X null;
X end if;
X null;
X end process;
X
end symul2;
X
-------------------------------------------------------------------------------
SHAR_EOF
(set 20 18 05 26 23 29 31 'dpi/vzmq_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'dpi/vzmq_tb.vhd'
if test $? -ne 0
then ${echo} "restore of dpi/vzmq_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'dpi/vzmq_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
066512de69d7282d72e52fcd8ab37b5d dpi/vzmq_tb.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'dpi/vzmq_tb.vhd'` -ne 4950 && \
${echo} "restoration warning: size of 'dpi/vzmq_tb.vhd' is not 4950"
fi
fi
# ============= dpi/vzmq_pkg.vhd ==============
if test -n "${keep_file}" && test -f 'dpi/vzmq_pkg.vhd'
then
${echo} "x - SKIPPING dpi/vzmq_pkg.vhd (file already exists)"

else
${echo} "x - extracting dpi/vzmq_pkg.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'dpi/vzmq_pkg.vhd' &&
-------------------------------------------------------------------------------
-- Title : Package vzmq
-- Project :
-------------------------------------------------------------------------------
-- File : vzmq_tb.vhd
-- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
-- Company : Institute of Electronic Systems
-- License : Public Domain or Creative Commons CC0
-- Created : 2018-05-20
-- Last update: 2018-05-26
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: vzmq - package for passing ZMQ messages to GHDL simulation
-------------------------------------------------------------------------------
-- Copyright (c) 2016,2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2018-05-20 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
X
package vzmq_pkg is
X
X -- Maximum length of received and transmitted messages in bytes
X constant MAX_SND : integer := 1000;
X constant MAX_RCV : integer := 2000;
X
end vzmq_pkg;
X
SHAR_EOF
(set 20 18 05 26 23 25 46 'dpi/vzmq_pkg.vhd'
eval "${shar_touch}") && \
chmod 0644 'dpi/vzmq_pkg.vhd'
if test $? -ne 0
then ${echo} "restore of dpi/vzmq_pkg.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'dpi/vzmq_pkg.vhd': 'MD5 check failed'
) << \SHAR_EOF
0a8ce7294e114525cb997ed387fcd375 dpi/vzmq_pkg.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'dpi/vzmq_pkg.vhd'` -ne 1291 && \
${echo} "restoration warning: size of 'dpi/vzmq_pkg.vhd' is not 1291"
fi
fi
# ============= dpi/vzmqc.c ==============
if test -n "${keep_file}" && test -f 'dpi/vzmqc.c'
then
${echo} "x - SKIPPING dpi/vzmqc.c (file already exists)"

else
${echo} "x - extracting dpi/vzmqc.c (text)"
sed 's/^X//' << 'SHAR_EOF' > 'dpi/vzmqc.c' &&
/*
X This is the C part of the VZMQ - package allowing to pass ZMQ messages
X from software to the GHDL or XSIM simuulation.
X Code written by Wojciech M. Zabolotny (wzab01<at>gmail.com or
X wzab<at>ise.pw.edu.pl)
X Published as PUBLIC DOMAIN or under Creative Commons CC0 license
*/
X
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <zmq.h>
#include "vzmq.h"
X
static int zmq_smax=0, zmq_rmax=0;
static void *ctx = NULL;
static unsigned int mprio;
static void *socket = NULL;
static int rc=-1;
DPI_LINKER_DECL DPI_DLLESPEC
void init_zmq_server_c(int i_zmq_smax,int i_zmq_rmax)
{
X zmq_smax = i_zmq_smax;
X zmq_rmax = i_zmq_rmax;
X ctx = zmq_ctx_new ();
X assert (ctx);
X /* Create ZMQ_STREAM socket */
X socket = zmq_socket (ctx, ZMQ_PAIR); //When it was ZMQ_REP, I couldn't repeat call
X assert (socket);
X rc = zmq_bind (socket, "ipc://mystream2");
X assert (rc == 0);
}
X
void close_zmq_server(int ile)
{
}
X
DPI_LINKER_DECL DPI_DLLESPEC int
zmq_get_message_c(int nmax,int * nact,svLogicVecVal buf[])
{
X //svBitVecVal * buf=(svBitVecVal *) vbuf;
X int msize;
X unsigned char rbuf[zmq_rmax];
X if(nmax > zmq_rmax) {
X fprintf(stderr,"Too many bytes requested %d>%d\n",nmax,zmq_rmax);
X *nact=-1;
X return 0;
X }
X msize = zmq_recv (socket,rbuf,nmax, ZMQ_DONTWAIT);
X if(msize<0) {
X if(errno==EAGAIN) {
X //fprintf(stderr,"No data %d\n",msize);
X *nact = 0;
X return 0;
X }
X perror("receive error ");
X fprintf(stderr,"Can't receive %d\n",msize);
X *nact=msize;
X return 0;
X } else {
X fprintf(stderr,"Received message of length: %d\n",msize);
X int i,j,k;
X for(i=0;i<msize;i++) {
X k=8*i;
X fprintf(stderr,"%c",rbuf[i]);
X for(j=0;j<8;j++) {
X if(rbuf[i] & (1<<j))
X svPutBitselLogic(buf,k+7-j,sv_1);
X else
X svPutBitselLogic(buf,k+7-j,sv_0);
X }
X }
X fprintf(stderr,"\n");
X *nact=msize;
X return 0;
X }
}
X
DPI_LINKER_DECL DPI_DLLESPEC int
zmq_put_message_c(int msize,int * nact,const svLogicVecVal buf[])
{
X //svBitVecVal * buf=(svBitVecVal *) vbuf;
X int res=0,i,j,k;
X unsigned char wbuf[zmq_smax];
X //Check if the number of transmitted bytes is correct
X if(msize > zmq_smax) {
X fprintf(stderr,"Too many bytes requested %d>%d\n",msize,zmq_smax);
X *nact=-1;
X return 0;
X }
X //Translate the message from bit vector to bytes
X for(i=0;i<msize;i++) {
X k=8*i;
X wbuf[i] = 0;
X for(j=0;j<8;j++)
X if(svGetBitselLogic(buf,k+7-j)==sv_1)
X wbuf[i] |= (1<<j);
X }
X res = zmq_send(socket,wbuf,msize, 0);
X if(res<0) {
X perror("transmit error ");
X fprintf(stderr,"Can't receive %d\n",res);
X *nact=res;
X return 0;
X } else {
X *nact=res;
X return 0;
X }
}
X
X
SHAR_EOF
(set 20 18 05 27 01 31 37 'dpi/vzmqc.c'
eval "${shar_touch}") && \
chmod 0644 'dpi/vzmqc.c'
if test $? -ne 0
then ${echo} "restore of dpi/vzmqc.c failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'dpi/vzmqc.c': 'MD5 check failed'
) << \SHAR_EOF
c0f353b9d354161812766f8b109fee58 dpi/vzmqc.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'dpi/vzmqc.c'` -ne 2733 && \
${echo} "restoration warning: size of 'dpi/vzmqc.c' is not 2733"
fi
fi
# ============= dpi/vzmq.sv ==============
if test -n "${keep_file}" && test -f 'dpi/vzmq.sv'
then
${echo} "x - SKIPPING dpi/vzmq.sv (file already exists)"

else
${echo} "x - extracting dpi/vzmq.sv (text)"
sed 's/^X//' << 'SHAR_EOF' > 'dpi/vzmq.sv' &&
/*-------------------------------------------------------------------------------
X -- Title : Package vzmq
X -- Project :
X -------------------------------------------------------------------------------
X -- File : vzmq_tb.vhd
X -- Author : Wojciech M. Zabolotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl
X -- Company : Institute of Electronic Systems
X -- License : Public Domain or Creative Commons CC0
X -- Created : 2018-05-20
X -- Last update: 2018-05-24
X -- Platform :
X -- Standard : VHDL'93
X -------------------------------------------------------------------------------
X -- Description: vzmq - package for passing ZMQ messages to GHDL or XSIM simulation
X -------------------------------------------------------------------------------
X -- Copyright (c) 2016,2018
X -------------------------------------------------------------------------------
X -- Revisions :
X -- Date Version Author Description
X -- 2018-05-20 1.0 wzab Created
X -------------------------------------------------------------------------------
X */
module vzmq # (parameter MAX_SND=16384, MAX_RCV=16384)
X ( //Sending interface
X input logic [8*MAX_SND-1:0] snd_msg,
X input logic snd_stb,
X input logic [31:0] snd_bytes,
X output logic snd_ack,
X //Receiving interface
X input logic rcv_stb,
X output logic rcv_ack,
X output logic [8*MAX_RCV-1:0] rcv_msg ,
X output logic [31:0] rcv_bytes
X );
X
X import "DPI-C" function void init_zmq_server_c(int max_send, int max_receive);
X import "DPI-C" task zmq_get_message_c (input int nmax,
X output int nact, inout logic [8*MAX_RCV-1:0] v1);
X import "DPI-C" task zmq_put_message_c (input int msize, output int nact,
X input logic [8*MAX_SND-1:0] v1);
X
X integer act_snd;
X integer act_rcv;
X
X
X
X initial begin
X init_zmq_server_c(MAX_SND,MAX_RCV);
X end
X
X always @ (snd_stb) begin
X //$displayh(snd_msg,";");
X zmq_put_message_c(snd_bytes,act_snd,snd_msg);
X if (act_snd >= 0)
X snd_ack <= 1;
X else
X snd_ack <= 0;
X end
X
X always @ (rcv_stb) begin
X zmq_get_message_c(MAX_RCV,act_rcv,rcv_msg);
X rcv_bytes <= act_rcv;
X if (act_rcv > 0)
X rcv_ack <= 1;
X else
X rcv_ack <= 0;
X end
X
endmodule
SHAR_EOF
(set 20 18 05 27 01 30 49 'dpi/vzmq.sv'
eval "${shar_touch}") && \
chmod 0644 'dpi/vzmq.sv'
if test $? -ne 0
then ${echo} "restore of dpi/vzmq.sv failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'dpi/vzmq.sv': 'MD5 check failed'
) << \SHAR_EOF
8514b8c3fc4c89e0ffb3a2c16d04e533 dpi/vzmq.sv
SHAR_EOF

else
test `LC_ALL=C wc -c < 'dpi/vzmq.sv'` -ne 2308 && \
${echo} "restoration warning: size of 'dpi/vzmq.sv' is not 2308"
fi
fi
# ============= dpi/build.sh ==============
if test -n "${keep_file}" && test -f 'dpi/build.sh'
then
${echo} "x - SKIPPING dpi/build.sh (file already exists)"

else
${echo} "x - extracting dpi/build.sh (text)"
sed 's/^X//' << 'SHAR_EOF' > 'dpi/build.sh' &&
xelab --dpiheader vzmq.h -svlog vzmq.sv
xsc --gcc_link_options lzmq vzmqc.c
xelab -svlog vzmq.sv -sv_lib dpi -vhdl vzmq_pkg.vhd -vhdl vzmq_tb.vhd -R
SHAR_EOF
(set 20 18 05 26 23 34 00 'dpi/build.sh'
eval "${shar_touch}") && \
chmod 0644 'dpi/build.sh'
if test $? -ne 0
then ${echo} "restore of dpi/build.sh failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'dpi/build.sh': 'MD5 check failed'
) << \SHAR_EOF
c1d5067be54eeeabd0e930c01fa73528 dpi/build.sh
SHAR_EOF

else
test `LC_ALL=C wc -c < 'dpi/build.sh'` -ne 150 && \
${echo} "restoration warning: size of 'dpi/build.sh' is not 150"
0 new messages