diff --git a/migen/sim/__init__.py b/migen/sim/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/migen/sim/generic.py b/migen/sim/generic.py deleted file mode 100644 index 868719447..000000000 --- a/migen/sim/generic.py +++ /dev/null @@ -1,229 +0,0 @@ -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) - diff --git a/migen/sim/icarus.py b/migen/sim/icarus.py deleted file mode 100644 index 59dc2b7d5..000000000 --- a/migen/sim/icarus.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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() diff --git a/migen/sim/ipc.py b/migen/sim/ipc.py deleted file mode 100644 index c6124bb6c..000000000 --- a/migen/sim/ipc.py +++ /dev/null @@ -1,228 +0,0 @@ -# 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("= 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() diff --git a/migen/sim/upper.py b/migen/sim/upper.py deleted file mode 100644 index 05ba3fbc2..000000000 --- a/migen/sim/upper.py +++ /dev/null @@ -1,112 +0,0 @@ -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 diff --git a/vpi/Makefile b/vpi/Makefile deleted file mode 100644 index 5f4ed341a..000000000 --- a/vpi/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -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 diff --git a/vpi/ipc.c b/vpi/ipc.c deleted file mode 100644 index a51004165..000000000 --- a/vpi/ipc.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2012 Vermeer Manufacturing Co. - * License: GPLv3 with additional permissions (see README). - */ - -#ifdef _WIN32 -#define WINVER 0x501 -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#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; -} - diff --git a/vpi/ipc.h b/vpi/ipc.h deleted file mode 100644 index 184858eea..000000000 --- a/vpi/ipc.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 */ diff --git a/vpi/main.c b/vpi/main.c deleted file mode 100644 index 74c13fd46..000000000 --- a/vpi/main.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2012 Vermeer Manufacturing Co. - * License: GPLv3 with additional permissions (see README). - */ - -#include -#include -#include -#include - -#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> 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 -};