From dd0c9bc29d663ab695e2c19964f23d475b8c2b22 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 9 Mar 2021 12:56:49 +0000 Subject: [PATCH] move Mem class out of ISACaller --- src/soc/decoder/isa/caller.py | 96 +------------------------ src/soc/decoder/isa/mem.py | 121 ++++++++++++++++++++++++++++++++ src/soc/decoder/isa/radixmmu.py | 13 +++- 3 files changed, 134 insertions(+), 96 deletions(-) create mode 100644 src/soc/decoder/isa/mem.py diff --git a/src/soc/decoder/isa/caller.py b/src/soc/decoder/isa/caller.py index 6235c350..dbfb492d 100644 --- a/src/soc/decoder/isa/caller.py +++ b/src/soc/decoder/isa/caller.py @@ -30,6 +30,7 @@ from soc.consts import PIb, MSRb # big-endian (PowerISA versions) from soc.decoder.power_svp64 import SVP64RM, decode_extra from soc.decoder.isa.radixmmu import RADIX +from soc.decoder.isa.mem import Mem, swap_order from collections import namedtuple import math @@ -47,12 +48,6 @@ 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 - - REG_SORT_ORDER = { # TODO (lkcl): adjust other registers that should be in a particular order # probably CA, CA32, and CR @@ -81,95 +76,6 @@ def create_args(reglist, extra=None): -class Mem: - - def __init__(self, row_bytes=8, initial_mem=None): - self.mem = {} - 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 - - # 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(): - #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, swap=True, check_in_mem=False): - print("ld from addr 0x{:x} width {:d}".format(address, width)) - remainder = address & (self.bytes_per_word - 1) - address = address >> self.word_log2 - assert remainder & (width - 1) == 0, "Unaligned access unsupported!" - if address in self.mem: - val = self.mem[address] - elif check_in_mem: - return None - else: - val = 0 - print("mem @ 0x{:x} rem {:d} : 0x{:x}".format(address, remainder, val)) - - if width != self.bytes_per_word: - shifter, mask = self._get_shifter_mask(width, remainder) - print("masking", hex(val), hex(mask << shifter), shifter) - val = val & (mask << shifter) - val >>= 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, 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, 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] - else: - val = 0 - shifter, mask = self._get_shifter_mask(width, remainder) - val &= ~(mask << shifter) - val |= v << shifter - self.mem[addr] = val - else: - self.mem[addr] = v - print("mem @ 0x{:x}: 0x{:x}".format(addr, self.mem[addr])) - - def __call__(self, addr, sz): - val = self.ld(addr.value, sz, swap=False) - print("memread", addr, sz, val) - return SelectableInt(val, sz*8) - - def memassign(self, addr, sz, val): - print("memassign", addr, sz, val) - self.st(addr.value, val.value, sz, swap=False) - - class GPR(dict): def __init__(self, decoder, isacaller, svstate, regfile): dict.__init__(self) diff --git a/src/soc/decoder/isa/mem.py b/src/soc/decoder/isa/mem.py new file mode 100644 index 00000000..723fca09 --- /dev/null +++ b/src/soc/decoder/isa/mem.py @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: LGPLv3+ +# Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton +# Funded by NLnet http://nlnet.nl +"""core of the python-based POWER9 simulator + +this is part of a cycle-accurate POWER9 simulator. its primary purpose is +not speed, it is for both learning and educational purposes, as well as +a method of verifying the HDL. + +related bugs: + +* https://bugs.libre-soc.org/show_bug.cgi?id=424 +""" + +from copy import copy +from soc.decoder.selectable_int import (FieldSelectableInt, SelectableInt, + selectconcat) + +from soc.decoder.power_enums import SPR as DEC_SPR + +from soc.decoder.helpers import exts, gtu, ltu, undefined +import math +import sys + + +def swap_order(x, nbytes): + x = x.to_bytes(nbytes, byteorder='little') + x = int.from_bytes(x, byteorder='big', signed=False) + return x + + + +class Mem: + + def __init__(self, row_bytes=8, initial_mem=None): + self.mem = {} + 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 + + # 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(): + #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, swap=True, check_in_mem=False): + print("ld from addr 0x{:x} width {:d}".format(address, width)) + remainder = address & (self.bytes_per_word - 1) + address = address >> self.word_log2 + assert remainder & (width - 1) == 0, "Unaligned access unsupported!" + if address in self.mem: + val = self.mem[address] + elif check_in_mem: + return None + else: + val = 0 + print("mem @ 0x{:x} rem {:d} : 0x{:x}".format(address, remainder, val)) + + if width != self.bytes_per_word: + shifter, mask = self._get_shifter_mask(width, remainder) + print("masking", hex(val), hex(mask << shifter), shifter) + val = val & (mask << shifter) + val >>= 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, 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, 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] + else: + val = 0 + shifter, mask = self._get_shifter_mask(width, remainder) + val &= ~(mask << shifter) + val |= v << shifter + self.mem[addr] = val + else: + self.mem[addr] = v + print("mem @ 0x{:x}: 0x{:x}".format(addr, self.mem[addr])) + + def __call__(self, addr, sz): + val = self.ld(addr.value, sz, swap=False) + print("memread", addr, sz, val) + return SelectableInt(val, sz*8) + + def memassign(self, addr, sz, val): + print("memassign", addr, sz, val) + self.st(addr.value, val.value, sz, swap=False) + + diff --git a/src/soc/decoder/isa/radixmmu.py b/src/soc/decoder/isa/radixmmu.py index 31520694..a8797870 100644 --- a/src/soc/decoder/isa/radixmmu.py +++ b/src/soc/decoder/isa/radixmmu.py @@ -18,6 +18,7 @@ from copy import copy from soc.decoder.selectable_int import (FieldSelectableInt, SelectableInt, selectconcat) from soc.decoder.helpers import exts, gtu, ltu, undefined +from soc.decoder.isa.mem import Mem import math import sys @@ -428,12 +429,22 @@ class RADIX: # very quick test of maskgen function (TODO, move to util later) if __name__ == '__main__': + # set up dummy minimal ISACaller + spr = {'DSISR': SelectableInt(0, 64), + 'DAR': SelectableInt(0, 64), + 'PIDR': SelectableInt(0, 64), + 'PRTBL': SelectableInt(0, 64) + } + class ISACaller: pass + caller = ISACaller() + caller.spr = spr + shift = SelectableInt(5, 6) mask = genmask(shift, 43) print (" mask", bin(mask.value)) mem = Mem(row_bytes=8) - mem = RADIX(mem, None) + mem = RADIX(mem, caller) # ----------------------------------------------- # |/|RTS1|/| RPDB | RTS2 | RPDS | # ----------------------------------------------- -- 2.30.2