+++ /dev/null
-import warnings
-import sys
-
-from migen.fhdl.std import *
-from migen.fhdl.structure import _Fragment
-from migen.fhdl import verilog
-from migen.sim.ipc import *
-from migen.sim import icarus
-
-
-class TopLevel:
- def __init__(self, vcd_name=None, vcd_level=1,
- top_name="top", dut_type="dut", dut_name="dut",
- cd_name="sys", clk_period=10):
- self.vcd_name = vcd_name
- self.vcd_level = vcd_level
- self.top_name = top_name
- self.dut_type = dut_type
- self.dut_name = dut_name
-
- self._cd_name = cd_name
- self._clk_period = clk_period
-
- cd = ClockDomain(self._cd_name)
- self.clock_domains = [cd]
- self.ios = {cd.clk, cd.rst}
-
- def get(self, sockaddr):
- if sys.platform == "win32":
- sockaddr = sockaddr[0] # Get the IP address only
-
- template1 = """`timescale 1ns / 1ps
-
-module {top_name}();
-
-reg {clk_name};
-reg {rst_name};
-
-initial begin
- {rst_name} <= 1'b1;
- @(posedge {clk_name});
- {rst_name} <= 1'b0;
-end
-
-always begin
- {clk_name} <= 1'b0;
- #{hclk_period};
- {clk_name} <= 1'b1;
- #{hclk_period};
-end
-
-{dut_type} {dut_name}(
- .{rst_name}({rst_name}),
- .{clk_name}({clk_name})
-);
-
-initial $migensim_connect("{sockaddr}");
-always @(posedge {clk_name}) $migensim_tick;
-"""
- template2 = """
-initial begin
- $dumpfile("{vcd_name}");
- $dumpvars({vcd_level}, {dut_name});
-end
-"""
- r = template1.format(top_name=self.top_name,
- dut_type=self.dut_type,
- dut_name=self.dut_name,
- clk_name=self._cd_name + "_clk",
- rst_name=self._cd_name + "_rst",
- hclk_period=str(self._clk_period/2),
- sockaddr=sockaddr)
- if self.vcd_name is not None:
- r += template2.format(vcd_name=self.vcd_name,
- vcd_level=str(self.vcd_level),
- dut_name=self.dut_name)
- r += "\nendmodule"
- return r
-
-
-class Simulator:
- def __init__(self, fragment, top_level=None, sim_runner=None, sockaddr="simsocket", **vopts):
- if not isinstance(fragment, _Fragment):
- fragment = fragment.get_fragment()
- if top_level is None:
- top_level = TopLevel()
- if sim_runner is None:
- sim_runner = icarus.Runner()
- self.top_level = top_level
- if sys.platform == "win32":
- sockaddr = ("127.0.0.1", 50007)
- self.ipc = Initiator(sockaddr)
- else:
- self.ipc = Initiator(sockaddr)
-
- self.sim_runner = sim_runner
-
- c_top = self.top_level.get(sockaddr)
-
- fragment = fragment + _Fragment(clock_domains=top_level.clock_domains)
- c_fragment = verilog.convert(fragment,
- ios=self.top_level.ios,
- name=self.top_level.dut_type,
- **vopts)
- self.namespace = c_fragment.ns
-
- self.cycle_counter = -1
-
- self.sim_runner = sim_runner
- self.sim_runner.start(c_top, c_fragment)
- self.ipc.accept()
- reply = self.ipc.recv()
- assert(isinstance(reply, MessageTick))
-
- self.sim_functions = fragment.sim
- self.active_sim_functions = set(f for f in fragment.sim if not hasattr(f, "passive") or not f.passive)
- self.unreferenced = {}
-
- def run(self, ncycles=None):
- counter = 0
-
- if self.active_sim_functions:
- if ncycles is None:
- def continue_simulation():
- return bool(self.active_sim_functions)
- else:
- def continue_simulation():
- return self.active_sim_functions and counter < ncycles
- else:
- if ncycles is None:
- raise ValueError("No active simulation function present - must specify ncycles to end simulation")
- def continue_simulation():
- return counter < ncycles
-
- while continue_simulation():
- self.cycle_counter += 1
- counter += 1
- self.ipc.send(MessageGo())
- reply = self.ipc.recv()
- assert(isinstance(reply, MessageTick))
-
- del_list = []
- for s in self.sim_functions:
- try:
- s(self)
- except StopSimulation:
- del_list.append(s)
- for s in del_list:
- self.sim_functions.remove(s)
- try:
- self.active_sim_functions.remove(s)
- except KeyError:
- pass
-
- def get_unreferenced(self, item, index):
- try:
- return self.unreferenced[(item, index)]
- except KeyError:
- if isinstance(item, Memory):
- try:
- init = item.init[index]
- except (TypeError, IndexError):
- init = 0
- else:
- init = item.reset
- self.unreferenced[(item, index)] = init
- return init
-
- def rd(self, item, index=0):
- try:
- name = self.top_level.top_name + "." \
- + self.top_level.dut_name + "." \
- + self.namespace.get_name(item)
- self.ipc.send(MessageRead(name, Int32(index)))
- reply = self.ipc.recv()
- assert(isinstance(reply, MessageReadReply))
- value = reply.value
- except KeyError:
- value = self.get_unreferenced(item, index)
- if isinstance(item, Memory):
- signed = False
- nbits = item.width
- else:
- signed = item.signed
- nbits = flen(item)
- value = value & (2**nbits - 1)
- if signed and (value & 2**(nbits - 1)):
- value -= 2**nbits
- return value
-
- def wr(self, item, value, index=0):
- if isinstance(item, Memory):
- nbits = item.width
- else:
- nbits = flen(item)
- if value < 0:
- value += 2**nbits
- assert(value >= 0 and value < 2**nbits)
- try:
- name = self.top_level.top_name + "." \
- + self.top_level.dut_name + "." \
- + self.namespace.get_name(item)
- self.ipc.send(MessageWrite(name, Int32(index), value))
- except KeyError:
- self.unreferenced[(item, index)] = value
-
- def __del__(self):
- if hasattr(self, "ipc"):
- warnings.warn("call Simulator.close() to clean up "
- "or use it as a contextmanager", DeprecationWarning)
- self.close()
-
- def close(self):
- self.ipc.close()
- self.sim_runner.close()
- del self.ipc
- del self.sim_runner
-
- def __enter__(self):
- return self
-
- def __exit__(self, type, value, traceback):
- self.close()
-
-
-def run_simulation(fragment, ncycles=None, vcd_name=None, **kwargs):
- with Simulator(fragment, TopLevel(vcd_name), icarus.Runner(**kwargs)) as s:
- s.run(ncycles)
-
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-import subprocess
-import os
-import time
-
-
-class Runner:
- def __init__(self, options=None, extra_files=None, top_file="migensim_top.v", dut_file="migensim_dut.v", vvp_file=None, keep_files=False):
- if extra_files is None: extra_files = []
- if vvp_file is None: vvp_file = dut_file + "vp"
- if options is None: options = []
- self.options = options
- self.extra_files = extra_files
- self.top_file = top_file
- self.dut_file = dut_file
- self.vvp_file = vvp_file
- self.data_files = []
- self.keep_files = keep_files
-
- def start(self, c_top, c_dut):
- with open(self.top_file, "w") as f:
- f.write(c_top)
- c_dut.write(self.dut_file)
- self.data_files += c_dut.data_files.keys()
- subprocess.check_call(["iverilog", "-o", self.vvp_file] + self.options + [self.top_file, self.dut_file] + self.extra_files)
- self.process = subprocess.Popen(["vvp", "-mmigensim", "-Mvpi", self.vvp_file])
-
- def close(self):
- if hasattr(self, "process"):
- self.process.terminate()
- if self.process.poll() is None:
- time.sleep(.1)
- self.process.kill()
- self.process.wait()
- if not self.keep_files:
- for f in [self.top_file, self.dut_file, self.vvp_file] + self.data_files:
- try:
- os.remove(f)
- except OSError:
- pass
- self.data_files.clear()
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-import socket
-import os
-import sys
-import struct
-
-if sys.platform == "win32":
- header_len = 2
-
-#
-# Message classes
-#
-
-class Int32(int):
- pass
-
-
-class Message:
- def __init__(self, *pvalues):
- for parameter, value in zip(self.parameters, pvalues):
- setattr(self, parameter[1], parameter[0](value))
-
- def __str__(self):
- p = []
- for parameter in self.parameters:
- p.append(parameter[1] + "=" + str(getattr(self, parameter[1])))
- if p:
- pf = " " + " ".join(p)
- else:
- pf = ""
- return "<" + self.__class__.__name__ + pf + ">"
-
-
-class MessageTick(Message):
- code = 0
- parameters = []
-
-
-class MessageGo(Message):
- code = 1
- parameters = []
-
-
-class MessageWrite(Message):
- code = 2
- parameters = [(str, "name"), (Int32, "index"), (int, "value")]
-
-
-class MessageRead(Message):
- code = 3
- parameters = [(str, "name"), (Int32, "index")]
-
-
-class MessageReadReply(Message):
- code = 4
- parameters = [(int, "value")]
-
-message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageReadReply]
-
-
-#
-# Packing
-#
-
-def _pack_int(v):
- if v == 0:
- p = [1, 0]
- else:
- p = []
- while v != 0:
- p.append(v & 0xff)
- v >>= 8
- p.insert(0, len(p))
- return p
-
-
-def _pack_str(v):
- p = [ord(c) for c in v]
- p.append(0)
- return p
-
-
-def _pack_int16(v):
- return [v & 0xff,
- (v & 0xff00) >> 8]
-
-
-def _pack_int32(v):
- return [
- v & 0xff,
- (v & 0xff00) >> 8,
- (v & 0xff0000) >> 16,
- (v & 0xff000000) >> 24
- ]
-
-
-def _pack(message):
- r = [message.code]
- for t, p in message.parameters:
- value = getattr(message, p)
- assert(isinstance(value, t))
- if t == int:
- r += _pack_int(value)
- elif t == str:
- r += _pack_str(value)
- elif t == Int32:
- r += _pack_int32(value)
- else:
- raise TypeError
- if sys.platform == "win32":
- size = _pack_int16(len(r) + header_len)
- r = size + r
- return bytes(r)
-
-
-#
-# Unpacking
-#
-
-def _unpack_int(i, nchunks=None):
- v = 0
- power = 1
- if nchunks is None:
- nchunks = next(i)
- for j in range(nchunks):
- v += power*next(i)
- power *= 256
- return v
-
-
-def _unpack_str(i):
- v = ""
- c = next(i)
- while c:
- v += chr(c)
- c = next(i)
- return v
-
-
-def _unpack(message):
- i = iter(message)
- code = next(i)
- msgclass = next(filter(lambda x: x.code == code, message_classes))
- pvalues = []
- for t, p in msgclass.parameters:
- if t == int:
- v = _unpack_int(i)
- elif t == str:
- v = _unpack_str(i)
- elif t == Int32:
- v = _unpack_int(i, 4)
- else:
- raise TypeError
- pvalues.append(v)
- return msgclass(*pvalues)
-
-
-#
-# I/O
-#
-
-class PacketTooLarge(Exception):
- pass
-
-
-class Initiator:
- def __init__(self, sockaddr):
- self.sockaddr = sockaddr
- if sys.platform == "win32":
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- else:
- self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
- self._cleanup_file()
- self.socket.bind(self.sockaddr)
- self.socket.listen(1)
-
- self.ipc_rxbuffer = bytearray()
-
- def _cleanup_file(self):
- try:
- os.remove(self.sockaddr)
- except OSError:
- pass
-
- def accept(self):
- self.conn, addr = self.socket.accept()
-
- def send(self, message):
- self.conn.send(_pack(message))
-
- def recv_packet(self, maxlen):
- if sys.platform == "win32":
- while len(self.ipc_rxbuffer) < header_len:
- self.ipc_rxbuffer += self.conn.recv(maxlen)
- packet_len = struct.unpack("<H", self.ipc_rxbuffer[:header_len])[0]
- while len(self.ipc_rxbuffer) < packet_len:
- self.ipc_rxbuffer += self.conn.recv(maxlen)
- packet = self.ipc_rxbuffer[header_len:packet_len]
- self.ipc_rxbuffer = self.ipc_rxbuffer[packet_len:]
- else:
- packet = self.conn.recv(maxlen)
- return packet
-
- def recv(self):
- maxlen = 2048
- packet = self.recv_packet(maxlen)
- if len(packet) < 1:
- return None
- if len(packet) >= maxlen:
- raise PacketTooLarge
- return _unpack(packet)
-
- def close(self):
- if hasattr(self, "conn"):
- self.conn.shutdown(socket.SHUT_RDWR)
- self.conn.close()
- if hasattr(self, "socket"):
- if sys.platform == "win32":
- # don't shutdown our socket since closing connection
- # seems to already have done it. (trigger an error
- # otherwise)
- self.socket.close()
- else:
- self.socket.shutdown(socket.SHUT_RDWR)
- self.socket.close()
- self._cleanup_file()
+++ /dev/null
-from migen.fhdl.structure import Signal, StopSimulation
-from migen.fhdl.specials import Memory
-
-
-class MemoryProxy:
- def __init__(self, simulator, obj):
- self.simulator = simulator
- self._simproxy_obj = obj
-
- def __getitem__(self, key):
- if isinstance(key, int):
- return self.simulator.rd(self._simproxy_obj, key)
- else:
- start, stop, step = key.indices(self._simproxy_obj.depth)
- return [self.simulator.rd(self._simproxy_obj, i) for i in range(start, stop, step)]
-
- def __setitem__(self, key, value):
- if isinstance(key, int):
- self.simulator.wr(self._simproxy_obj, key, value)
- else:
- start, stop, step = key.indices(self.__obj.depth)
- if len(value) != (stop - start)//step:
- raise ValueError
- for i, v in zip(range(start, stop, step), value):
- self.simulator.wr(self._simproxy_obj, i, v)
-
-
-class Proxy:
- def __init__(self, simulator, obj):
- object.__setattr__(self, "simulator", simulator)
- object.__setattr__(self, "_simproxy_obj", obj)
-
- def __process_get(self, item):
- if isinstance(item, Signal):
- return self.simulator.rd(item)
- elif isinstance(item, Memory):
- return MemoryProxy(self.simulator, item)
- else:
- return Proxy(self.simulator, item)
-
- def __getattr__(self, name):
- return self.__process_get(getattr(self._simproxy_obj, name))
-
- def __setattr__(self, name, value):
- item = getattr(self._simproxy_obj, name)
- assert(isinstance(item, Signal))
- self.simulator.wr(item, value)
-
- def __getitem__(self, key):
- return self.__process_get(self._simproxy_obj[key])
-
- def __setitem__(self, key, value):
- item = self._simproxy_obj[key]
- assert(isinstance(item, Signal))
- self.simulator.wr(item, value)
-
-
-def gen_sim(simg):
- gens = dict()
- resume_cycle = 0
-
- def do_simulation(s):
- nonlocal resume_cycle, gens
-
- if isinstance(s, Proxy):
- simulator = s.simulator
- else:
- simulator = s
-
- if simulator.cycle_counter >= resume_cycle:
- try:
- gen = gens[simulator]
- except KeyError:
- gen = simg(s)
- gens[simulator] = gen
- try:
- n = next(gen)
- except StopIteration:
- del gens[simulator]
- raise StopSimulation
- else:
- if n is None:
- n = 1
- resume_cycle = simulator.cycle_counter + n
-
- if hasattr(simg, "passive"):
- do_simulation.passive = simg.passive
-
- return do_simulation
-
-
-def proxy_sim(target, simf):
- proxies = dict()
-
- def do_simulation(simulator):
- nonlocal proxies
-
- try:
- proxy = proxies[simulator]
- except KeyError:
- proxy = Proxy(simulator, target)
- proxies[simulator] = proxy
- try:
- simf(proxy)
- except StopSimulation:
- del proxies[simulator]
- raise
-
- if hasattr(simf, "passive"):
- do_simulation.passive = simf.passive
-
- return do_simulation
+++ /dev/null
-INSTDIR = $(shell iverilog-vpi --install-dir)
-
-CFLAGS = -Wall -O2 $(CFLAGS_$@)
-VPI_CFLAGS := $(shell iverilog-vpi --cflags)
-# Define the below flags for a Windows build.
-# Make sure to run iverilog-vpi with -mingw and -ivl options if necessary!
-# i.e. iverilog-vpi -mingw=C:\msys64\mingw32 -ivl=C:\msys64\mingw32
-# MINGW_FLAGS=-lWs2_32
-
-OBJ=ipc.o main.o
-
-all: migensim.vpi
-
-%.o: %.c
- $(CC) $(CFLAGS) $(VPI_CFLAGS) -c $(INCDIRS) -o $@ $<
-
-migensim.vpi: $(OBJ)
- iverilog-vpi $(MINGW_FLAGS) --name=migensim $^
-
-install: migensim.vpi
- install -m755 -t $(INSTDIR) $^
-
-clean:
- rm -f $(OBJ)
- rm -f migensim.vpi
-
-.PHONY: install clean
+++ /dev/null
-/*
- * Copyright (C) 2012 Vermeer Manufacturing Co.
- * License: GPLv3 with additional permissions (see README).
- */
-
-#ifdef _WIN32
-#define WINVER 0x501
-#endif
-
-#include <assert.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#else
-#include <sys/socket.h>
-#include <sys/un.h>
-#endif
-
-
-#include "ipc.h"
-
-struct ipc_softc {
- int socket;
- go_handler h_go;
- write_handler h_write;
- read_handler h_read;
- void *user;
-};
-
-#define MAX_LEN 2048
-
-#ifdef _WIN32
-#define HEADER_LEN 2
-#define SOCKET_PORT "50007"
-
-unsigned char ipc_rxbuffer[2*MAX_LEN];
-int ipc_rxlen;
-#else
-#define HEADER_LEN 0
-#endif
-
-struct ipc_softc *ipc_connect(const char *sockaddr,
- go_handler h_go, write_handler h_write, read_handler h_read, void *user)
-{
- struct ipc_softc *sc;
-#ifdef _WIN32
- struct addrinfo hints, *my_addrinfo;
- WSADATA wsaData;
- ipc_rxlen = 0;
-#else
- struct sockaddr_un addr;
-#endif
-
- sc = malloc(sizeof(struct ipc_softc));
- if(!sc) return NULL;
-
- sc->h_go = h_go;
- sc->h_write = h_write;
- sc->h_read = h_read;
- sc->user = user;
-
-#ifdef _WIN32
- /* Initialize Winsock. */
- if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
- free(sc);
- return NULL;
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if(getaddrinfo(sockaddr, SOCKET_PORT, NULL, &my_addrinfo) != 0) {
- free(sc);
- return NULL;
- }
-
- sc->socket = socket(AF_INET, SOCK_STREAM, 0);
- if(sc->socket < 0) {
- free(sc);
- return NULL;
- }
-
- if(connect(sc->socket, my_addrinfo->ai_addr, my_addrinfo->ai_addrlen) != 0) {
- close(sc->socket);
- free(sc);
- return NULL;
- }
-#else
- sc->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
- if(sc->socket < 0) {
- free(sc);
- return NULL;
- }
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, sockaddr);
- if(connect(sc->socket, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
- close(sc->socket);
- free(sc);
- return NULL;
- }
-#endif
-
- return sc;
-}
-
-void ipc_destroy(struct ipc_softc *sc)
-{
- close(sc->socket);
- free(sc);
-#ifdef _WIN32
- WSACleanup();
-#endif
-}
-
-enum {
- MESSAGE_TICK = 0,
- MESSAGE_GO,
- MESSAGE_WRITE,
- MESSAGE_READ,
- MESSAGE_READ_REPLY
-};
-
-static int ipc_receive_packet(struct ipc_softc *sc, unsigned char *buffer) {
-#ifdef _WIN32
- int len;
- int packet_len;
- /* ensure we have packet header */
- while(ipc_rxlen < HEADER_LEN) {
- len = recv(sc->socket, (char *)&ipc_rxbuffer[ipc_rxlen], MAX_LEN, 0);
- if(len)
- ipc_rxlen += len;
- }
-
- /* compute packet length and ensure we have the payload */
- packet_len = (ipc_rxbuffer[1] << 8) | ipc_rxbuffer[0];
- while(ipc_rxlen < packet_len) {
- len = recv(sc->socket, (char *)&ipc_rxbuffer[ipc_rxlen], MAX_LEN, 0);
- if(len)
- ipc_rxlen += len;
- }
-
- /* copy packet to buffer */
- memcpy(buffer, ipc_rxbuffer + HEADER_LEN, packet_len - HEADER_LEN);
-
- /* prepare ipc_rxbuffer for next packet */
- ipc_rxlen = ipc_rxlen - packet_len;
- memcpy(ipc_rxbuffer, ipc_rxbuffer + packet_len, ipc_rxlen);
-
- return packet_len - HEADER_LEN;
-#else
- return recv(sc->socket, buffer, MAX_LEN, 0);
-#endif
-}
-
-/*
- * 0 -> error
- * 1 -> success
- * 2 -> graceful shutdown
- */
-int ipc_receive(struct ipc_softc *sc)
-{
- unsigned char buffer[MAX_LEN];
- ssize_t l = 0;
- int i;
-
- l = ipc_receive_packet(sc, (unsigned char *)&buffer);
- if(l == 0)
- return 2;
- if((l < 0) || (l >= MAX_LEN))
- return 0;
- i = 0;
-
- switch(buffer[i++]) {
- case MESSAGE_GO:
- assert((l - i) == 0);
-
- return sc->h_go(sc->user);
- case MESSAGE_WRITE: {
- char *name;
- int nchunks;
- unsigned char *chunks;
- unsigned int chunk_index;
-
- name = (char *)&buffer[i];
- i += strlen(name) + 1;
- assert((i+4) < l);
- chunk_index = buffer[i] | buffer[i+1] << 8 | buffer[i+2] << 16 | buffer[i+3] << 24;
- i += 4;
- nchunks = buffer[i++];
- assert(i + nchunks == l);
- chunks = (unsigned char *)&buffer[i];
-
- return sc->h_write(name, chunk_index, nchunks, chunks, sc->user);
- }
- case MESSAGE_READ: {
- char *name;
- unsigned int name_index;
-
- name = (char *)&buffer[i];
- i += strlen(name) + 1;
- assert((i+4) == l);
- name_index = buffer[i] | buffer[i+1] << 8 | buffer[i+2] << 16 | buffer[i+3] << 24;
-
- return sc->h_read(name, name_index, sc->user);
- }
- default:
- return 0;
- }
-}
-
-int ipc_tick(struct ipc_softc *sc)
-{
- ssize_t l;
- char c[HEADER_LEN + 1];
-
-#ifdef _WIN32
- c[0] = 3;
- c[1] = 0;
-#endif
- c[HEADER_LEN + 0] = MESSAGE_TICK;
- l = send(sc->socket, c, HEADER_LEN + 1, 0);
- if(l != (HEADER_LEN + 1))
- return 0;
-
- return 1;
-}
-
-int ipc_read_reply(struct ipc_softc *sc, int nchunks, const unsigned char *chunks)
-{
- int len;
- char buffer[MAX_LEN];
- ssize_t l;
-
- len = nchunks + HEADER_LEN + 2;
- assert(len < MAX_LEN);
- assert(nchunks < 256);
-
-#ifdef _WIN32
- buffer[0] = len & 0xFF;
- buffer[1] = (0xFF00 & len) >> 8;
-#endif
- buffer[HEADER_LEN + 0] = MESSAGE_READ_REPLY;
- buffer[HEADER_LEN + 1] = nchunks;
- memcpy(&buffer[HEADER_LEN + 2], chunks, nchunks);
-
- l = send(sc->socket, buffer, len, 0);
- if(l != len)
- return 0;
- return 1;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2012 Vermeer Manufacturing Co.
- * License: GPLv3 with additional permissions (see README).
- */
-
-#ifndef __IPC_H
-#define __IPC_H
-
-struct ipc_softc;
-
-typedef int(*go_handler)(void *);
-typedef int(*write_handler)(char *, int, int, const unsigned char *, void *);
-typedef int(*read_handler)(char *, int, void *);
-
-struct ipc_softc *ipc_connect(const char *sockaddr,
- go_handler h_go, write_handler h_write, read_handler h_read, void *user);
-void ipc_destroy(struct ipc_softc *sc);
-
-int ipc_receive(struct ipc_softc *sc);
-
-int ipc_tick(struct ipc_softc *sc);
-int ipc_read_reply(struct ipc_softc *sc, int nchunks, const unsigned char *value);
-
-#endif /* __IPC_H */
+++ /dev/null
-/*
- * Copyright (C) 2012 Vermeer Manufacturing Co.
- * License: GPLv3 with additional permissions (see README).
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <vpi_user.h>
-
-#include "ipc.h"
-
-struct migensim_softc {
- struct ipc_softc *ipc;
- int has_go;
-};
-
-static int h_go(void *user)
-{
- struct migensim_softc *sc = (struct migensim_softc *)user;
- sc->has_go = 1;
- return 1;
-}
-
-static s_vpi_time zero_delay = {
- .type = vpiSimTime,
- .high = 0,
- .low = 0
-};
-
-static int h_write(char *name, int index, int nchunks, const unsigned char *chunks, void *user)
-{
- vpiHandle item;
- s_vpi_vecval vector[64];
- int i;
- s_vpi_value value;
-
- item = vpi_handle_by_name(name, NULL);
- if(item == NULL) {
- fprintf(stderr, "Attempted to write non-existing signal %s\n", name);
- return 0;
- }
- if(vpi_get(vpiType, item) == vpiMemory)
- item = vpi_handle_by_index(item, index);
- else
- assert(index == 0);
-
- assert(nchunks <= 255);
- for(i=0;i<64;i++) {
- vector[i].aval = 0;
- vector[i].bval = 0;
- }
- for(i=0;i<nchunks;i++)
- vector[i/4].aval |= chunks[i] << 8*(i % 4);
-
- value.format = vpiVectorVal;
- value.value.vector = vector;
- vpi_put_value(item, &value, &zero_delay, vpiInertialDelay);
-
- return 1;
-}
-
-static int h_read(char *name, int index, void *user)
-{
- struct migensim_softc *sc = (struct migensim_softc *)user;
- vpiHandle item;
- s_vpi_value value;
- int size;
- int i;
- int nvals;
- unsigned int vals[64];
- int nchunks;
- unsigned char chunks[255];
-
- item = vpi_handle_by_name(name, NULL);
- if(item == NULL) {
- fprintf(stderr, "Attempted to read non-existing signal %s\n", name);
- return 0;
- }
- if(vpi_get(vpiType, item) == vpiMemory)
- item = vpi_handle_by_index(item, index);
- else
- assert(index == 0);
-
- value.format = vpiVectorVal;
- vpi_get_value(item, &value);
- size = vpi_get(vpiSize, item);
- nvals = (size + 31)/32;
- assert(nvals <= 64);
- for(i=0;i<nvals;i++)
- vals[i] = value.value.vector[i].aval & ~value.value.vector[i].bval;
- nchunks = (size + 7)/8;
- assert(nchunks <= 255);
- for(i=0;i<nchunks;i++) {
- switch(i % 4) {
- case 0:
- chunks[i] = vals[i/4] & 0xff;
- break;
- case 1:
- chunks[i] = (vals[i/4] & 0xff00) >> 8;
- break;
- case 2:
- chunks[i] = (vals[i/4] & 0xff0000) >> 16;
- break;
- case 3:
- chunks[i] = (vals[i/4] & 0xff000000) >> 24;
- break;
- }
- }
-
- if(!ipc_read_reply(sc->ipc, nchunks, chunks)) {
- perror("ipc_read_reply");
- return 0;
- }
-
- return 1;
-}
-
-static int process_until_go(struct migensim_softc *sc)
-{
- int r;
-
- sc->has_go = 0;
- while(!sc->has_go) {
- r = ipc_receive(sc->ipc);
- if(r != 1)
- return r;
- }
- return 1;
-}
-
-static PLI_INT32 connect_calltf(PLI_BYTE8 *user)
-{
- struct migensim_softc *sc = (struct migensim_softc *)user;
- vpiHandle sys;
- vpiHandle argv;
- vpiHandle item;
- s_vpi_value value;
-
- sys = vpi_handle(vpiSysTfCall, 0);
- argv = vpi_iterate(vpiArgument, sys);
- item = vpi_scan(argv);
- value.format = vpiStringVal;
- vpi_get_value(item, &value);
-
- sc->ipc = ipc_connect(value.value.str, h_go, h_write, h_read, sc);
- if(sc->ipc == NULL) {
- perror("ipc_connect");
- vpi_control(vpiFinish, 1);
- return 0;
- }
-
- return 0;
-}
-
-static PLI_INT32 tick_calltf(PLI_BYTE8 *user)
-{
- struct migensim_softc *sc = (struct migensim_softc *)user;
- int r;
-
- if(!ipc_tick(sc->ipc)) {
- perror("ipc_tick");
- vpi_control(vpiFinish, 1);
- ipc_destroy(sc->ipc);
- sc->ipc = NULL;
- return 0;
- }
- r = process_until_go(sc);
- if(r != 1) {
- vpi_control(vpiFinish, r == 2 ? 0 : 1);
- ipc_destroy(sc->ipc);
- sc->ipc = NULL;
- return 0;
- }
-
- return 0;
-}
-
-static struct migensim_softc sc;
-
-static void simple_register(const char *tfname, PLI_INT32 (*calltf)(PLI_BYTE8 *))
-{
- s_vpi_systf_data tf_data;
-
- tf_data.type = vpiSysTask;
- tf_data.tfname = tfname;
- tf_data.calltf = calltf;
- tf_data.compiletf = NULL;
- tf_data.sizetf = 0;
- tf_data.user_data = (void *)≻
- vpi_register_systf(&tf_data);
-}
-
-static void migensim_register()
-{
- simple_register("$migensim_connect", connect_calltf);
- simple_register("$migensim_tick", tick_calltf);
-}
-
-void (*vlog_startup_routines[])() = {
- migensim_register,
- 0
-};