X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsoc%2Fdecoder%2Fisa%2Fcaller.py;h=51ae83c1fb11579ebcebbd40e0a043fdbbb68197;hb=d437d98d02ef2d7ac143f74a8c759cc35e0cfbed;hp=f76afdab5bc28d0200cdc847a062e4a2db9809a1;hpb=61b1e265fb5c8abf5e6f2b17a90cf10fe29c5cc6;p=soc.git diff --git a/src/soc/decoder/isa/caller.py b/src/soc/decoder/isa/caller.py index f76afdab..51ae83c1 100644 --- a/src/soc/decoder/isa/caller.py +++ b/src/soc/decoder/isa/caller.py @@ -26,6 +26,12 @@ special_sprs = { 'VRSAVE': 256} +def swap_order(x, nbytes): + x = x.to_bytes(nbytes, byteorder='little') + x = int.from_bytes(x, byteorder='big', signed=False) + return x + + def create_args(reglist, extra=None): args = OrderedSet() for reg in reglist: @@ -38,25 +44,39 @@ def create_args(reglist, extra=None): class Mem: - def __init__(self, bytes_per_word=8, initial_mem=None): + def __init__(self, row_bytes=8, initial_mem=None): self.mem = {} - self.bytes_per_word = bytes_per_word - self.word_log2 = math.ceil(math.log2(bytes_per_word)) + self.bytes_per_word = row_bytes + self.word_log2 = math.ceil(math.log2(row_bytes)) + print ("Sim-Mem", initial_mem, self.bytes_per_word, self.word_log2) if not initial_mem: return - print ("Sim-Mem", initial_mem, self.bytes_per_word) + + # different types of memory data structures recognised (for convenience) + if isinstance(initial_mem, list): + initial_mem = (0, initial_mem) + if isinstance(initial_mem, tuple): + startaddr, mem = initial_mem + initial_mem = {} + for i, val in enumerate(mem): + initial_mem[startaddr + row_bytes*i] = (val, row_bytes) + for addr, (val, width) in initial_mem.items(): - self.st(addr, val, width) + #val = swap_order(val, width) + self.st(addr, val, width, swap=False) def _get_shifter_mask(self, wid, remainder): shifter = ((self.bytes_per_word - wid) - remainder) * \ 8 # bits per byte + # XXX https://bugs.libre-soc.org/show_bug.cgi?id=377 + # BE/LE mode? + shifter = remainder * 8 mask = (1 << (wid * 8)) - 1 print ("width,rem,shift,mask", wid, remainder, hex(shifter), hex(mask)) return shifter, mask # TODO: Implement ld/st of lesser width - def ld(self, address, width=8): + def ld(self, address, width=8, swap=True): print("ld from addr 0x{:x} width {:d}".format(address, width)) remainder = address & (self.bytes_per_word - 1) address = address >> self.word_log2 @@ -72,16 +92,20 @@ class Mem: print ("masking", hex(val), hex(mask<>= shifter + if swap: + val = swap_order(val, width) print("Read 0x{:x} from addr 0x{:x}".format(val, address)) return val - def st(self, addr, v, width=8): + def st(self, addr, v, width=8, swap=True): staddr = addr remainder = addr & (self.bytes_per_word - 1) addr = addr >> self.word_log2 print("Writing 0x{:x} to ST 0x{:x} memaddr 0x{:x}/{:x}".format(v, - staddr, addr, remainder)) + staddr, addr, remainder, swap)) assert remainder & (width - 1) == 0, "Unaligned access unsupported!" + if swap: + v = swap_order(v, width) if width != self.bytes_per_word: if addr in self.mem: val = self.mem[addr] @@ -181,23 +205,48 @@ class SPR(dict): def __call__(self, ridx): return self[ridx] - - + class ISACaller: # decoder2 - an instance of power_decoder2 # regfile - a list of initial values for the registers + # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR + # respect_pc - tracks the program counter. requires initial_insns def __init__(self, decoder2, regfile, initial_sprs=None, initial_cr=0, - initial_mem=None, initial_msr=0): + initial_mem=None, initial_msr=0, + initial_insns=None, respect_pc=False, + disassembly=None): + + self.respect_pc = respect_pc if initial_sprs is None: initial_sprs = {} if initial_mem is None: initial_mem = {} + if initial_insns is None: + initial_insns = {} + assert self.respect_pc == False, "instructions required to honor pc" + + # "fake program counter" mode (for unit testing) + if not respect_pc: + if isinstance(initial_mem, tuple): + self.fake_pc = initial_mem[0] + else: + self.fake_pc = 0 + + # disassembly: we need this for now (not given from the decoder) + self.disassembly = {} + if disassembly: + for i, code in enumerate(disassembly): + self.disassembly[i*4 + self.fake_pc] = code + + # set up registers, instruction memory, data memory, PC, SPRs, MSR self.gpr = GPR(decoder2, regfile) - self.mem = Mem(bytes_per_word=8, initial_mem=initial_mem) + self.mem = Mem(row_bytes=8, initial_mem=initial_mem) + self.imem = Mem(row_bytes=4, initial_mem=initial_insns) self.pc = PC() self.spr = SPR(decoder2, initial_sprs) self.msr = SelectableInt(initial_msr, 64) # underlying reg + # TODO, needed here: # FPR (same as GPR except for FP nums) # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR) @@ -307,6 +356,7 @@ class ISACaller: imm = yield self.dec2.e.imm_data.data inputs.append(SelectableInt(imm, 64)) assert len(outputs) >= 1 + print ("handle_overflow", inputs, outputs) if len(inputs) >= 2: output = outputs[0] @@ -328,8 +378,6 @@ class ISACaller: so = so | ov self.spr['XER'][XER_bits['SO']] = so - - def handle_comparison(self, outputs): out = outputs[0] out = exts(out.value, out.bits) @@ -343,7 +391,31 @@ class ISACaller: def set_pc(self, pc_val): self.namespace['NIA'] = SelectableInt(pc_val, 64) self.pc.update(self.namespace) - + + def setup_one(self): + """set up one instruction + """ + if self.respect_pc: + pc = self.pc.CIA.value + else: + pc = self.fake_pc + ins = yield self.imem.ld(pc, 4, False) + yield self.pdecode2.dec.raw_opcode_in.eq(ins) + yield self.pdecode2.dec.bigendian.eq(0) # little / big? + self._pc + + def execute_one(self): + """execute one instruction + """ + # get the disassembly code for this instruction + code = self.disassembly[self._pc] + opname = code.split(' ')[0] + yield from call(opname) + + if not self.respect_pc: + self.fake_pc += 4 + #else: + #self.pc.CIA.value = self.pc.NIA.value def call(self, name): # TODO, asmregs is from the spec, e.g. add RT,RA,RB