Fix addi instruction, think a commit got lost
[soc.git] / src / soc / decoder / isa / caller.py
index 89917d9c715265c92878a61aa63ddc72bcdea920..874a06973f3666d63917ce2adcf4a11f4efc4690 100644 (file)
 from functools import wraps
+from soc.decoder.orderedset import OrderedSet
+from soc.decoder.selectable_int import SelectableInt, selectconcat
+
+def create_args(reglist, extra=None):
+    args = OrderedSet()
+    for reg in reglist:
+        args.add(reg)
+    args = list(args)
+    if extra:
+        args = [extra] + args
+    return args
+
+class Mem:
 
-class ISACaller:
     def __init__(self):
-        self.gpr = {} # TODO
-        self.mem = {} # TODO
+        self.mem = []
+        for i in range(128):
+            self.mem.append(i)
+
+    def __call__(self, addr, sz):
+        res = []
+        for s in range(sz): # TODO: big/little-end
+            res.append(SelectableInt(self.mem[addr.value + s], 8))
+        print ("memread", addr, sz, res)
+        return selectconcat(*res)
+
+    def memassign(self, addr, sz, val):
+        print ("memassign", addr, sz, val)
+        for s in range(sz):
+            byte = (val.value) >> (s*8) & 0xff # TODO: big/little-end
+            self.mem[addr.value + s] = byte
+
+
+class GPR(dict):
+    def __init__(self, decoder, regfile):
+        dict.__init__(self)
+        self.sd = decoder
+        for i in range(32):
+            self[i] = SelectableInt(regfile[i], 64)
+
+    def __call__(self, ridx):
+        return self[ridx]
+
+    def set_form(self, form):
+        self.form = form
+
+    def getz(self, rnum):
+        #rnum = rnum.value # only SelectableInt allowed
+        print("GPR getzero", rnum)
+        if rnum == 0:
+            return SelectableInt(0, 64)
+        return self[rnum]
+
+    def _get_regnum(self, attr):
+        getform = self.sd.sigforms[self.form]
+        rnum = getattr(getform, attr)
+        return rnum
+
+    def ___getitem__(self, attr):
+        print("GPR getitem", attr)
+        rnum = self._get_regnum(attr)
+        return self.regfile[rnum]
+
+    def dump(self):
+        for i in range(0, len(self), 8):
+            s = []
+            for j in range(8):
+                s.append("%08x" % self[i+j].value)
+            s = ' '.join(s)
+            print("reg", "%2d" % i, s)
+
+
+class ISACaller:
+    # decoder2 - an instance of power_decoder2
+    # regfile - a list of initial values for the registers
+    def __init__(self, decoder2, regfile):
+        self.gpr = GPR(decoder2, regfile)
+        self.mem = Mem()
         self.namespace = {'GPR': self.gpr,
                           'MEM': self.mem,
                           'memassign': self.memassign
-                         }
+                          }
+        self.decoder = decoder2
 
     def memassign(self, ea, sz, val):
-        pass
+        self.mem.memassign(ea, sz, val)
+
+    def prep_namespace(self):
+        si = yield self.decoder.SI
+        self.namespace['SI'] = SelectableInt(si, bits=16)
+
+    def call(self, name):
+        yield from self.prep_namespace()
+
+        function, read_regs, uninit_regs, write_regs = self.instrs[name]
+        input_names = create_args(read_regs | uninit_regs)
+        print(input_names)
 
-def inject(context):
+        inputs = []
+        for name in input_names:
+            regnum = yield getattr(self.decoder, name)
+            print('reading reg %d' % regnum)
+            inputs.append(self.gpr(regnum))
+        print(inputs)
+        results = function(self, *inputs)
+        print(results)
+
+        output_names = create_args(write_regs)
+        for name, output in zip(output_names, results):
+            regnum = yield getattr(self.decoder, name)
+            print('writing reg %d' % regnum)
+            self.gpr[regnum] = output.narrow(64)
+
+
+def inject():
     """ Decorator factory. """
     def variable_injector(func):
         @wraps(func)
@@ -22,6 +123,7 @@ def inject(context):
             except AttributeError:
                 func_globals = func.func_globals  # Earlier versions.
 
+            context = args[0].namespace
             saved_values = func_globals.copy()  # Shallow copy of dict.
             func_globals.update(context)
 
@@ -37,20 +139,3 @@ def inject(context):
 
     return variable_injector
 
-if __name__ == '__main__':
-    d = {'1': 1}
-    namespace = {'a': 5, 'b': 3, 'd': d}
-
-    @inject(namespace)
-    def test():
-        print (globals())
-        print('a:', a)
-        print('b:', b)
-        print('d1:', d['1'])
-        d[2] = 5
-        
-        return locals()
-
-    test()
-
-    print (namespace)