Franck Pommereau

ttc run: added let, Python expr to print and assert

Showing 1 changed file with 46 additions and 43 deletions
......@@ -179,37 +179,6 @@ class Runner (object) :
args.append(f"=> {_val(ret)}")
return (f"{F.WHITE}{event}", *args)
class AssertEnv (dict) :
def __init__ (self, ttc, *l, **k) :
super().__init__(*l, **k)
self.ttc = ttc
def __getitem__ (self, key) :
if not isinstance(key, str) :
raise TypeError(f"expected 'str' key, got {type(key).__name__!r}")
key = key.upper()
if (reg := regnum.get(key, None)) is not None :
return self.ttc.cpu.reg[reg]
elif key == "INTR" :
return list(self.ttc.cpu.intr)
elif key == "MASK" :
MR = self.ttc.cpu.reg[regnum["MR"]]
return [int(m) for m in bin(MR)[2:].rjust(16, "1")]
elif key == "CLOCK" :
return self.ttc.cpu.clock
elif key.startswith("[") and key.endswith("]") :
addr = key[1:-1]
if ":" in addr :
start, stop = addr.split(":", 1)
start = int(start or "0", 16)
stop = int(stop or "FFFF", 16)
return list(self.ttc.ram.ram[start:stop+1])
else :
return self.ttc.ram.ram[int(addr, 16)]
elif key == "SCREEN" :
return self.ttc.screen.ascii()
else :
raise KeyError(key)
class ShellRunner (Runner) :
_prompt = "ttc >>>"
prompt = f"{S.BRIGHT}{_prompt}{S.RESET_ALL} "
......@@ -223,6 +192,7 @@ class ShellRunner (Runner) :
readline.set_completer(self.complete)
self.script = self.parse_script(script)
self.interactive = interactive
self.eval_env = {}
def err (self, msg) :
if self.interactive :
super().err(msg)
......@@ -362,6 +332,36 @@ class ShellRunner (Runner) :
else :
await self.sim.ui_expect(*args)
return False
async def cmd_let (self, name:str, expr:str=None) :
"""saves a value as a name
- name: name to be assigned
- expr: value expression as a Python expression involving
- the names already assigned with let
- registers names
- the interrupt vector INTR (list of 0/1)
- the interrupt mask MASK (list of 0/1)
- the clock tick counter CLOCK
- the memory RAM (list of ints)
- the screen text SCREEN (str)
"""
if expr is None :
self.eval_env.pop(name, None)
else :
self.eval_env[name] = self.eval(expr)
def eval (self, expr, loc={}) :
try :
return int(expr, 16)
except :
env = self.eval_env.copy()
for reg, num in regnum.items() :
env[reg] = self.ttc.cpu.reg[num]
env["INTR"] = list(self.ttc.cpu.intr)
MR = self.ttc.cpu.reg[regnum["MR"]]
env["MASK"] = [int(m) for m in bin(MR)[2:].rjust(16, "1")]
env["CLOCK"] = self.ttc.cpu.clock
env["RAM"] = list(self.ttc.ram.ram)
env["SCREEN"] = self.ttc.screen.ascii()
return eval(expr, env, loc)
async def cmd_cycle (self, count:int=1) :
"""run one or more CPU cycle
- count: number of cycles to run
......@@ -437,8 +437,8 @@ class ShellRunner (Runner) :
start, stop = addr.split(":", 1)
else :
start = stop = addr
start = int(start or "0", 16)
stop = int(stop or "FFFF", 16)
start = self.eval(start or "0")
stop = self.eval(stop or "FFFF")
if start > stop :
raise ValueError
return start, stop
......@@ -460,19 +460,18 @@ class ShellRunner (Runner) :
async def cmd_assert (self, expr:str, message:str=None) :
"""check assertion
- expr: Python expression checked to be True, may include
- register names: the register's value
- intr: the interrupt vector as a list of 0/1
- mask: the interrupt mask (MR) as a list of 0/1
- clock: the clock counter
- screen: the text on screen (without colours)
- [ADDR]: the value in RAM at ADDR
- [ADDR:ADDR]: the list of values in RAM in specified range (inclusive)
- the names assigned with let
- registers names
- the interrupt vector INTR (list of 0/1)
- the interrupt mask MASK (list of 0/1)
- the clock tick counter CLOCK
- the memory RAM (list of ints)
- the screen text SCREEN
- [message]: a message to be printed if assertion fails
"""
global CLIRET
env = AssertEnv(self.ttc)
try :
ret = eval(expr, env)
ret = self.eval(expr)
except Exception as err :
print(f"{F.RED}{S.BRIGHT}assert error:{S.RESET_ALL}"
f" {F.BLUE}{expr}{F.RESET} raised",
......@@ -496,7 +495,11 @@ class ShellRunner (Runner) :
- screen: text screen
"""
for comp in component :
if (reg := comp.upper()) in regnum :
if comp in self.eval_env :
print(f"{F.GREEN}{comp}{F.RESET}"
f" = {F.BLUE}{self.eval_env[comp]}"
f"{S.RESET_ALL}")
elif (reg := comp.upper()) in regnum :
num = regnum[reg]
print(f"{F.GREEN}{reg}{F.RESET}"
f" = {F.BLUE}{_val(self.ttc.cpu.reg[num])}"
......