aboutsummaryrefslogtreecommitdiffstats
path: root/tests/rpc/frontend.py
blob: 8cbec568238a7937720b603cad3d92f373530f50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def modules():
	return ["python_inv"]

def derive(module, parameters):
	assert module == r"python_inv"
	if parameters.keys() != {r"\width"}:
		raise ValueError("Invalid parameters")
	return "ilang", r"""
module \impl
	wire width {width:d} input 1 \i
	wire width {width:d} output 2 \o
	cell $neg $0
		parameter \A_SIGNED 1'0
		parameter \A_WIDTH 32'{width:b}
		parameter \Y_WIDTH 32'{width:b}
		connect \A \i
		connect \Y \o
	end
end
module \python_inv
	wire width {width:d} input 1 \i
	wire width {width:d} output 2 \o
	cell \impl $0
		connect \i \i
		connect \o \o
	end
end
""".format(width=parameters[r"\width"])

# ----------------------------------------------------------------------------

import json
import argparse
import sys, socket, os, subprocess
try:
	import msvcrt, win32pipe, win32file
except ImportError:
	msvcrt = win32pipe = win32file = None

def map_parameter(parameter):
	if parameter["type"] == "unsigned":
		return int(parameter["value"], 2)
	if parameter["type"] == "signed":
		width = len(parameter["value"])
		value = int(parameter["value"], 2)
		if value & (1 << (width - 1)):
			value = -((1 << width) - value)
		return value
	if parameter["type"] == "string":
		return parameter["value"]
	if parameter["type"] == "real":
		return float(parameter["value"])

def call(input_json):
	input = json.loads(input_json)
	if input["method"] == "modules":
		return json.dumps({"modules": modules()})
	if input["method"] == "derive":
		try:
			frontend, source = derive(input["module"],
				{name: map_parameter(value) for name, value in input["parameters"].items()})
			return json.dumps({"frontend": frontend, "source": source})
		except ValueError as e:
			return json.dumps({"error": str(e)})

def main():
	parser = argparse.ArgumentParser()
	modes = parser.add_subparsers(dest="mode")
	mode_stdio = modes.add_parser("stdio")
	if os.name == "posix":
		mode_path = modes.add_parser("unix-socket")
	if os.name == "nt":
		mode_path = modes.add_parser("named-pipe")
	mode_path.add_argument("path")
	args = parser.parse_args()

	if args.mode == "stdio":
		while True:
			input = sys.stdin.readline()
			if not input: break
			sys.stdout.write(call(input) + "\n")
			sys.stdout.flush()

	if args.mode == "unix-socket":
		sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
		sock.settimeout(30)
		sock.bind(args.path)
		try:
			sock.listen(1)
			ys_proc = subprocess.Popen(["../../yosys", "-ql", "unix.log", "-p", "connect_rpc -path {}; read_verilog design.v; hierarchy -top top; flatten; select -assert-count 1 t:$neg".format(args.path)])
			conn, addr = sock.accept()
			file = conn.makefile("rw")
			while True:
				input = file.readline()
				if not input: break
				file.write(call(input) + "\n")
				file.flush()
			ys_proc.wait(timeout=10)
			if ys_proc.returncode:
				raise subprocess.CalledProcessError(ys_proc.returncode, ys_proc.args)
		finally:
			ys_proc.kill()
			sock.close()
			os.unlink(args.path)

	if args.mode == "named-pipe":
		pipe = win32pipe.CreateNamedPipe(args.path, win32pipe.PIPE_ACCESS_DUPLEX,
		    win32pipe.PIPE_TYPE_BYTE|win32pipe.PIPE_READMODE_BYTE|win32pipe.PIPE_WAIT,
		    1, 4096, 4096, 0, None)
		win32pipe.ConnectNamedPipe(pipe, None)
		try:
			while True:
				input = b""
				while not input.endswith(b"\n"):
					result, data = win32file.ReadFile(pipe, 4096)
					assert result == 0
					input += data
					assert not b"\n" in input or input.endswith(b"\n")
				output = (call(input.decode("utf-8")) + "\n").encode("utf-8")
				length = len(output)
				while length > 0:
					result, done = win32file.WriteFile(pipe, output)
					assert result == 0
					length -= done
		except win32file.error as e:
			if e.args[0] == 109: # ERROR_BROKEN_PIPE
				pass
			else:
				raise

if __name__ == "__main__":
	main()
> ( port->driver->tx_empty(port) ) { for ( i = 0; i < port->tx_fifo_size; i++ ) { if ( port->txbufc == port->txbufp ) break; port->driver->putc( port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); } } spin_unlock(&port->tx_lock); out: local_irq_restore(flags); } static void __serial_putc(struct serial_port *port, char c) { if ( (port->txbuf != NULL) && !port->sync ) { /* Interrupt-driven (asynchronous) transmitter. */ if ( port->tx_quench ) { /* Buffer filled and we are dropping characters. */ if ( (port->txbufp - port->txbufc) > (serial_txbufsz / 2) ) return; port->tx_quench = 0; } if ( (port->txbufp - port->txbufc) == serial_txbufsz ) { if ( port->tx_log_everything ) { /* Buffer is full: we spin waiting for space to appear. */ int i; while ( !port->driver->tx_empty(port) ) cpu_relax(); for ( i = 0; i < port->tx_fifo_size; i++ ) port->driver->putc( port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c; } else { /* Buffer is full: drop chars until buffer is half empty. */ port->tx_quench = 1; } return; } if ( ((port->txbufp - port->txbufc) == 0) && port->driver->tx_empty(port) ) { /* Buffer and UART FIFO are both empty. */ port->driver->putc(port, c); } else { /* Normal case: buffer the character. */ port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c; } } else if ( port->driver->tx_empty ) { /* Synchronous finite-capacity transmitter. */ while ( !port->driver->tx_empty(port) ) cpu_relax(); port->driver->putc(port, c); } else { /* Simple synchronous transmitter. */ port->driver->putc(port, c); } } void serial_putc(int handle, char c) { struct serial_port *port; unsigned long flags; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; if ( !port->driver || !port->driver->putc ) return; spin_lock_irqsave(&port->tx_lock, flags); if ( (c == '\n') && (handle & SERHND_COOKED) ) __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00)); if ( handle & SERHND_HI ) c |= 0x80; else if ( handle & SERHND_LO ) c &= 0x7f; __serial_putc(port, c); spin_unlock_irqrestore(&port->tx_lock, flags); } void serial_puts(int handle, const char *s) { struct serial_port *port; unsigned long flags; char c; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; if ( !port->driver || !port->driver->putc ) return; spin_lock_irqsave(&port->tx_lock, flags); while ( (c = *s++) != '\0' ) { if ( (c == '\n') && (handle & SERHND_COOKED) ) __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00)); if ( handle & SERHND_HI ) c |= 0x80; else if ( handle & SERHND_LO ) c &= 0x7f; __serial_putc(port, c); } spin_unlock_irqrestore(&port->tx_lock, flags); } char serial_getc(int handle) { struct serial_port *port; char c; unsigned long flags; if ( handle == -1 ) return '\0'; port = &com[handle & SERHND_IDX]; if ( !port->driver || !port->driver->getc ) return '\0'; do { for ( ; ; ) { spin_lock_irqsave(&port->rx_lock, flags); if ( port->rxbufp != port->rxbufc ) { c = port->rxbuf[mask_serial_rxbuf_idx(port->rxbufc++)]; spin_unlock_irqrestore(&port->rx_lock, flags); break; } if ( port->driver->getc(port, &c) ) { spin_unlock_irqrestore(&port->rx_lock, flags); break; } spin_unlock_irqrestore(&port->rx_lock, flags); cpu_relax(); udelay(100); } } while ( ((handle & SERHND_LO) && (c & 0x80)) || ((handle & SERHND_HI) && !(c & 0x80)) ); return c & 0x7f; } int __init serial_parse_handle(char *conf) { int handle; if ( strncmp(conf, "com", 3) ) goto fail; switch ( conf[3] ) { case '1': handle = 0; break; case '2': handle = 1; break; default: goto fail; } if ( !com[handle].driver ) goto fail; if ( conf[4] == 'H' ) handle |= SERHND_HI; else if ( conf[4] == 'L' ) handle |= SERHND_LO; handle |= SERHND_COOKED; return handle; fail: return -1; } void __init serial_set_rx_handler(int handle, serial_rx_fn fn) { struct serial_port *port; unsigned long flags; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; spin_lock_irqsave(&port->rx_lock, flags); if ( port->rx != NULL ) goto fail; if ( handle & SERHND_LO ) { if ( port->rx_lo != NULL ) goto fail; port->rx_lo = fn; } else if ( handle & SERHND_HI ) { if ( port->rx_hi != NULL ) goto fail; port->rx_hi = fn; } else { if ( (port->rx_hi != NULL) || (port->rx_lo != NULL) ) goto fail; port->rx = fn; } spin_unlock_irqrestore(&port->rx_lock, flags); return; fail: spin_unlock_irqrestore(&port->rx_lock, flags); printk("ERROR: Conflicting receive handlers for COM%d\n", handle & SERHND_IDX); } void serial_force_unlock(int handle) { struct serial_port *port; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; spin_lock_init(&port->rx_lock); spin_lock_init(&port->tx_lock); serial_start_sync(handle); } void serial_start_sync(int handle) { struct serial_port *port; unsigned long flags; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; spin_lock_irqsave(&port->tx_lock, flags); if ( port->sync++ == 0 ) { while ( (port->txbufp - port->txbufc) != 0 ) { while ( !port->driver->tx_empty(port) ) cpu_relax(); port->driver->putc( port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); } } spin_unlock_irqrestore(&port->tx_lock, flags); } void serial_end_sync(int handle) { struct serial_port *port; unsigned long flags; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; spin_lock_irqsave(&port->tx_lock, flags); port->sync--; spin_unlock_irqrestore(&port->tx_lock, flags); } void serial_start_log_everything(int handle) { struct serial_port *port; unsigned long flags; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; spin_lock_irqsave(&port->tx_lock, flags); port->tx_log_everything++; port->tx_quench = 0; spin_unlock_irqrestore(&port->tx_lock, flags); } void serial_end_log_everything(int handle) { struct serial_port *port; unsigned long flags; if ( handle == -1 ) return; port = &com[handle & SERHND_IDX]; spin_lock_irqsave(&port->tx_lock, flags); port->tx_log_everything--; spin_unlock_irqrestore(&port->tx_lock, flags); } void __init serial_init_preirq(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) if ( com[i].driver && com[i].driver->init_preirq ) com[i].driver->init_preirq(&com[i]); } void __init serial_init_postirq(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) if ( com[i].driver && com[i].driver->init_postirq ) com[i].driver->init_postirq(&com[i]); } void __init serial_endboot(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) if ( com[i].driver && com[i].driver->endboot ) com[i].driver->endboot(&com[i]); } int __init serial_irq(int idx) { if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) && com[idx].driver && com[idx].driver->irq ) return com[idx].driver->irq(&com[idx]); return -1; } void serial_suspend(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) if ( com[i].driver && com[i].driver->suspend ) com[i].driver->suspend(&com[i]); } void serial_resume(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) if ( com[i].driver && com[i].driver->resume ) com[i].driver->resume(&com[i]); } void __init serial_register_uart(int idx, struct uart_driver *driver, void *uart) { /* Store UART-specific info. */ com[idx].driver = driver; com[idx].uart = uart; /* Default is no transmit FIFO. */ com[idx].tx_fifo_size = 1; } void __init serial_async_transmit(struct serial_port *port) { BUG_ON(!port->driver->tx_empty); if ( port->txbuf != NULL ) return; if ( serial_txbufsz < PAGE_SIZE ) serial_txbufsz = PAGE_SIZE; while ( serial_txbufsz & (serial_txbufsz - 1) ) serial_txbufsz &= serial_txbufsz - 1; port->txbuf = alloc_xenheap_pages( get_order_from_bytes(serial_txbufsz), 0); } /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */