a0ebcc4a91459cd00d75812cd8506f84aeb58497
1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Funded by NLnet http://nlnet.nl
4 """core of the python-based POWER9 simulator
6 this is part of a cycle-accurate POWER9 simulator. its primary purpose is
7 not speed, it is for both learning and educational purposes, as well as
8 a method of verifying the HDL.
12 * https://bugs.libre-soc.org/show_bug.cgi?id=424
16 from soc
.decoder
.selectable_int
import (FieldSelectableInt
, SelectableInt
,
19 from soc
.decoder
.helpers
import exts
, gtu
, ltu
, undefined
24 def swap_order(x
, nbytes
):
25 x
= x
.to_bytes(nbytes
, byteorder
='little')
26 x
= int.from_bytes(x
, byteorder
='big', signed
=False)
33 def __init__(self
, row_bytes
=8, initial_mem
=None):
35 self
.bytes_per_word
= row_bytes
36 self
.word_log2
= math
.ceil(math
.log2(row_bytes
))
37 print("Sim-Mem", initial_mem
, self
.bytes_per_word
, self
.word_log2
)
41 # different types of memory data structures recognised (for convenience)
42 if isinstance(initial_mem
, list):
43 initial_mem
= (0, initial_mem
)
44 if isinstance(initial_mem
, tuple):
45 startaddr
, mem
= initial_mem
47 for i
, val
in enumerate(mem
):
48 initial_mem
[startaddr
+ row_bytes
*i
] = (val
, row_bytes
)
50 for addr
, (val
, width
) in initial_mem
.items():
51 #val = swap_order(val, width)
52 self
.st(addr
, val
, width
, swap
=False)
54 def _get_shifter_mask(self
, wid
, remainder
):
55 shifter
= ((self
.bytes_per_word
- wid
) - remainder
) * \
57 # XXX https://bugs.libre-soc.org/show_bug.cgi?id=377
59 shifter
= remainder
* 8
60 mask
= (1 << (wid
* 8)) - 1
61 print("width,rem,shift,mask", wid
, remainder
, hex(shifter
), hex(mask
))
64 # TODO: Implement ld/st of lesser width
65 def ld(self
, address
, width
=8, swap
=True, check_in_mem
=False,
67 print("ld from addr 0x{:x} width {:d}".format(address
, width
),
68 swap
, check_in_mem
, instr_fetch
)
69 remainder
= address
& (self
.bytes_per_word
- 1)
70 address
= address
>> self
.word_log2
71 assert remainder
& (width
- 1) == 0, "Unaligned access unsupported!"
72 if address
in self
.mem
:
73 val
= self
.mem
[address
]
78 print("mem @ 0x{:x} rem {:d} : 0x{:x}".format(address
, remainder
, val
))
80 if width
!= self
.bytes_per_word
:
81 shifter
, mask
= self
._get
_shifter
_mask
(width
, remainder
)
82 print("masking", hex(val
), hex(mask
<< shifter
), shifter
)
83 val
= val
& (mask
<< shifter
)
86 val
= swap_order(val
, width
)
87 print("Read 0x{:x} from addr 0x{:x}".format(val
, address
))
90 def st(self
, addr
, v
, width
=8, swap
=True):
92 remainder
= addr
& (self
.bytes_per_word
- 1)
93 addr
= addr
>> self
.word_log2
94 print("Writing 0x{:x} to ST 0x{:x} "
95 "memaddr 0x{:x}/{:x}".format(v
, staddr
, addr
, remainder
, swap
))
96 assert remainder
& (width
- 1) == 0, "Unaligned access unsupported!"
98 v
= swap_order(v
, width
)
99 if width
!= self
.bytes_per_word
:
104 shifter
, mask
= self
._get
_shifter
_mask
(width
, remainder
)
105 val
&= ~
(mask
<< shifter
)
110 print("mem @ 0x{:x}: 0x{:x}".format(addr
, self
.mem
[addr
]))
112 def __call__(self
, addr
, sz
):
113 val
= self
.ld(addr
.value
, sz
, swap
=False)
114 print("memread", addr
, sz
, val
)
115 return SelectableInt(val
, sz
*8)
117 def memassign(self
, addr
, sz
, val
):
118 print("memassign", addr
, sz
, val
)
119 self
.st(addr
.value
, val
.value
, sz
, swap
=False)