Franck Pommereau

added fast execution + started exam

......@@ -6,3 +6,5 @@ __pycache__
/.python-version
*.bak
/www/ttc
/build
*.so
......
from setuptools import setup, find_packages, Extension
try:
from Cython.Build import cythonize
extensions = cythonize("ttc/vat.pyx", language_level=3)
except ImportError:
extensions = [Extension("ttc/vat.hrmx", ["ttc/vat.c"])]
setup(
packages=find_packages(where="."),
python_requires=">=3.9",
ext_modules=extensions)
from . import cpuinfo
print("from libc.stdint cimport uint16_t, uint32_t")
print()
print("ctypedef uint16_t word")
print("ctypedef uint32_t dword")
print()
print("cpdef enum regs:")
for reg in cpuinfo.regname:
print(f" {reg} = 0x{cpuinfo.regnum[reg]:X}")
print()
width = max(len(m) for m in cpuinfo.mnemo2codeop)
print("cpdef enum codeop:")
for m, c in cpuinfo.mnemo2codeop.items():
print(f" {m.upper().ljust(width)} = 0x{c.ljust(4, '0')}")
print()
print("cdef word[16] INTR = [ # i => bit i")
for i in range(16):
if i == 15:
print(f" 0b{1 << i:016b}]")
else:
print(f" 0b{1 << i:016b},")
print()
print("cdef word[16] MASK = [ # i => bits < i")
for i in range(16):
if i == 15:
print(f" 0b{('1' * i).rjust(16, '0')}]")
else:
print(f" 0b{('1' * i).rjust(16, '0')},")
print()
print("cdef word[16] NBITS = [ # i => bits <= i")
for i in range(16):
if i == 15:
print(f" 0b{('1' * (i+1)).rjust(16, '0')}]")
else:
print(f" 0b{('1' * (i+1)).rjust(16, '0')},")
print()
This diff is collapsed. Click to expand it.
......@@ -471,8 +471,8 @@ class CPU (object) :
return IP, IR
@trace("cpu.cycle")
async def cycle (self) :
await self.check_intr()
await self.clock_tick()
await self.check_intr()
IP, IR = await self.fetch()
# decode
op, args = await self.decode(IP, IR)
......
import re
import io
import random as R
import itertools as I
import functools as F
import string as S
from collections.abc import Iterable
from pathlib import Path
from .asm import asm
from .vat import TTC, AsmError
from . import words as W
class CheckError(Exception):
def __init__(self, name, message):
if name is None:
super().__init__(message)
else:
super().__init__(f"{name}: {message}")
class Func:
_builtins = {"R": R, "W": W, "I": I, "F": F, "S": S}
def __init__(self, name, args, expr, env={}):
self.name = name
self.args = tuple(args)
self.expr = expr.strip()
self._env = env
def __repr__(self):
return f"({', '.join(self.args)} => {self.expr})"
def __call__(self, *args):
env = dict(self._env)
env.update(zip(self.args, args))
return self.eval(self.expr, env)
@classmethod
def env(cls, extra={}, **more):
env = dict(cls._builtins)
env.update(extra)
env.update(more)
return env
@classmethod
def eval(cls, expr, extra={}, **more):
return eval(expr, cls.env(extra, **more))
@classmethod
def exec(cls, stmt, extra={}, **more):
exec(stmt, cls.env(more), extra)
class Source:
_pyrun = re.compile(r"\s*\#\s*\>\>\>\s*(.+)$")
_subst = re.compile(r"\{\{(.+)\}\}$")
_meta = {"func": re.compile(r"^\s*\#\s*(\w+)\s+([\w\s,]*)=>(.+)$"),
"expr": re.compile(r"^\s*\#\s*(\w+)\s*=\s*(.+)$"),
"text": re.compile(r"^\s*\#\s*(\w+)\s*:\s*(.+)$"),
"pyrun": re.compile(f"^{_pyrun.pattern}")}
def __init__(self, src, **check):
self.meta = {}
self.src = []
self.lno = {}
self.onl = {}
self._ttc = None
for lno, line in self.read(src):
for kind, rexp in self._meta.items():
if match := rexp.match(line):
break
else:
onl = len(self.src) + 1
self.lno[onl] = lno
self.onl[lno] = onl
if match := self._pyrun.search(line):
raw = line
line = line.replace(match.group(0), "")
Func.exec(match.group(1), self.meta,
src=line, raw=raw, lno=lno)
elif match := self._subst.search(line):
new = Func.eval(match.group(1),
src=line, lno=lno, **self.meta)
if isinstance(new, str):
pass
elif isinstance(new, Iterable):
new = " ".join(f"{n:X}" if isinstance(n, int)
else str(n) for n in new)
elif isinstance(new, int):
new = f"{new:X}"
else:
new = str(new)
line = line.replace(match.group(0), new)
self.src.append(line)
continue
g = match.groups()
if kind == "expr":
self.meta[g[0]] = Func.eval(g[1], **self.meta)
elif kind == "text":
self.meta[g[0]] = g[1].strip()
elif kind == "pyrun":
Func.exec(g[0], **self.meta)
elif kind == "func":
self.meta[g[0]] = Func(g[0],
[a for s in g[1].split(",")
if (a := s.strip())],
g[2],
self.meta)
if check:
self.check(**check)
def read(self, src):
if isinstance(src, io.TextIOBase):
stream = src
elif isinstance(src, Path):
stream = src.open()
elif isinstance(src, str):
try:
stream = Path(src).open()
except Exception:
stream = io.StringIO(src)
else:
raise TypeError("invalid source")
for lno, line in enumerate(stream, start=1):
yield lno, line.rstrip()
@property
def ttc(self):
if self._ttc is None:
self._ttc = TTC()
return self._ttc
def check(self, *funcs, maxsteps=1024, ttc=None):
if ttc is None:
ttc = self.ttc
if funcs:
checkers = {f: self.meta[f] for f in funcs}
else:
checkers = {k: v for k, v in self.meta.items()
if isinstance(v, Func)}
rom, err = asm({"source": "\n".join(self.src),
"pathname": "<exam>"})
if err:
raise AsmError(err)
ttc.load([v for _, v in rom], asm.lbl)
try:
ok = ttc(maxsteps=maxsteps)
except Exception as err:
raise CheckError(None, str(err))
if not ok:
raise CheckError(None, "too many steps")
for name, chk in checkers.items():
try:
ok = chk(ttc)
except Exception as err:
exc = err.__class__.__name__
raise CheckError(name, f"raised {exc}: {err}")
if not ok:
raise CheckError(name, f"failed with {ok!r}")
This diff could not be displayed because it is too large.
from libc.stdint cimport uint16_t, uint32_t
ctypedef uint16_t word
ctypedef uint32_t dword
cpdef enum regs:
R0 = 0x0
R1 = 0x1
R2 = 0x2
R3 = 0x3
R4 = 0x4
R5 = 0x5
R6 = 0x6
R7 = 0x7
R8 = 0x8
R9 = 0x9
BP = 0xA
CR = 0xB
IR = 0xC
MR = 0xD
IP = 0xE
SP = 0xF
cpdef enum codeop:
HALT = 0x0000
NOP = 0x0001
IRET = 0x0002
RET = 0x0003
CLA = 0x0004
NINTR = 0x0010
RINTR = 0x0020
CLR = 0x0030
RESET = 0x0040
SET = 0x0050
PUSH = 0x0060
POP = 0x0070
INC = 0x0080
DEC = 0x0090
RAND = 0x00A0
ZSET = 0x0100
NZSET = 0x0200
MOV = 0x0300
NOT = 0x0400
LD = 0x0500
ST = 0x0600
ADD = 0x1000
SUB = 0x2000
MUL = 0x3000
DIV = 0x4000
AND = 0x5000
OR = 0x6000
LSHIFT = 0x7000
RSHIFT = 0x8000
EQ = 0x9000
GT = 0xA000
ZMOV = 0xB000
NZMOV = 0xC000
LDI = 0xD000
STI = 0xE000
BUS = 0xF000
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
......@@ -22,4 +22,4 @@ fact:
end:
pop R1 # restore R1
pop BP # restore BP
ret # return to caller
\ No newline at end of file
ret # return to caller
......
......@@ -10,4 +10,4 @@ loop:
stop:
halt
text:
data "Hello world!" 0
\ No newline at end of file
data "Hello world!" 0
......