From: Luke Kenneth Casson Leighton Date: Thu, 7 May 2020 18:35:32 +0000 (+0100) Subject: move unused simulator code out the way X-Git-Tag: div_pipeline~1353 X-Git-Url: https://git.libre-soc.org/?p=soc.git;a=commitdiff_plain;h=32a529f4e7558a4da2d6d510b3be004be7ffa72d move unused simulator code out the way --- diff --git a/src/soc/simulator/internalop_sim.py b/src/soc/simulator/internalop_sim.py deleted file mode 100644 index f7a4b262..00000000 --- a/src/soc/simulator/internalop_sim.py +++ /dev/null @@ -1,196 +0,0 @@ -from soc.decoder.power_enums import (Function, Form, InternalOp, - In1Sel, In2Sel, In3Sel, OutSel, - RC, LdstLen, CryIn, get_csv, - single_bit_flags, - get_signal_name, default_values) -import math - - -class MemorySim: - def __init__(self, bytes_per_word=8): - self.mem = {} - self.bytes_per_word = bytes_per_word - self.word_log2 = math.ceil(math.log2(bytes_per_word)) - - def _get_shifter_mask(self, width, remainder): - shifter = ((self.bytes_per_word - width) - remainder) * \ - 8 # bits per byte - mask = (1 << (width * 8)) - 1 - return shifter, mask - - # TODO: Implement ld/st of lesser width - def ld(self, address, width=8): - 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] - else: - val = 0 - - if width != self.bytes_per_word: - shifter, mask = self._get_shifter_mask(width, remainder) - val = val & (mask << shifter) - val >>= shifter - print("Read {:x} from addr {:x}".format(val, address)) - return val - - def st(self, address, value, width=8): - remainder = address & (self.bytes_per_word - 1) - address = address >> self.word_log2 - assert remainder & (width - 1) == 0, "Unaligned access unsupported!" - print("Writing {:x} to addr {:x}".format(value, address)) - if width != self.bytes_per_word: - if address in self.mem: - val = self.mem[address] - else: - val = 0 - shifter, mask = self._get_shifter_mask(width, remainder) - val &= ~(mask << shifter) - val |= value << shifter - self.mem[address] = val - else: - self.mem[address] = value - - -class RegFile: - def __init__(self): - self.regfile = [0] * 32 - self.sprs = {} - - def write_reg(self, regnum, value): - all1s = (1 << 64)-1 # 64 bits worth of 1s - value &= all1s - print("Writing {:x} to reg r{}".format(value, regnum)) - self.regfile[regnum] = value - - def read_reg(self, regnum): - val = self.regfile[regnum] - print("Read {:x} from reg r{}".format(val, regnum)) - return val - - def assert_gpr(self, gpr, val): - reg_val = self.read_reg(gpr) - msg = "reg r{} got {:x}, expecting {:x}".format( - gpr, reg_val, val) - assert reg_val == val, msg - - def assert_gprs(self, gprs): - for k, v in list(gprs.items()): - self.assert_gpr(k, v) - - def set_xer(self, result, operanda, operandb): - xer = 0 - if result & 1 << 64: - xer |= XER.CA - - self.xer = xer - - -class InternalOpSimulator: - def __init__(self): - self.mem_sim = MemorySim() - self.regfile = RegFile() - - def execute_alu_op(self, op1, op2, internal_op, carry=0): - print(internal_op) - if internal_op == InternalOp.OP_ADD.value: - return op1 + op2 + carry - elif internal_op == InternalOp.OP_AND.value: - return op1 & op2 - elif internal_op == InternalOp.OP_OR.value: - return op1 | op2 - elif internal_op == InternalOp.OP_MUL_L64.value: - return op1 * op2 - else: - assert False, "Not implemented" - - def update_cr0(self, result): - if result == 0: - self.cr0 = 0b001 - elif result >> 63: - self.cr0 = 0b100 - else: - self.cr0 = 0b010 - print("update_cr0", self.cr0) - - def alu_op(self, pdecode2): - all1s = (1 << 64)-1 # 64 bits worth of 1s - internal_op = yield pdecode2.dec.op.internal_op - operand1 = 0 - operand2 = 0 - result = 0 - carry = 0 - r1_ok = yield pdecode2.e.read_reg1.ok - r2_ok = yield pdecode2.e.read_reg2.ok - r3_ok = yield pdecode2.e.read_reg3.ok - imm_ok = yield pdecode2.e.imm_data.ok - if r1_ok: - r1_sel = yield pdecode2.e.read_reg1.data - operand1 = self.regfile.read_reg(r1_sel) - elif r3_ok: - r3_sel = yield pdecode2.e.read_reg3.data - operand1 = self.regfile.read_reg(r3_sel) - if r2_ok: - r2_sel = yield pdecode2.e.read_reg2.data - operand2 = self.regfile.read_reg(r2_sel) - if imm_ok: - operand2 = yield pdecode2.e.imm_data.data - - inv_a = yield pdecode2.dec.op.inv_a - if inv_a: - operand1 = (~operand1) & all1s - - cry_in = yield pdecode2.dec.op.cry_in - if cry_in == CryIn.ONE.value: - carry = 1 - elif cry_in == CryIn.CA.value: - carry = self.carry_out - - # TODO rc_sel = yield pdecode2.dec.op.rc_sel - result = self.execute_alu_op(operand1, operand2, internal_op, - carry=carry) - - cry_out = yield pdecode2.dec.op.cry_out - rc = yield pdecode2.e.rc.data - - if rc: - self.update_cr0(result) - if cry_out == 1: - self.carry_out = (result >> 64) - print("setting carry_out", self.carry_out) - - ro_ok = yield pdecode2.e.write_reg.ok - if ro_ok: - ro_sel = yield pdecode2.e.write_reg.data - self.regfile.write_reg(ro_sel, result) - - def mem_op(self, pdecode2): - internal_op = yield pdecode2.dec.op.internal_op - addr_reg = yield pdecode2.e.read_reg1.data - addr = self.regfile.read_reg(addr_reg) - - imm_ok = yield pdecode2.e.imm_data.ok - r2_ok = yield pdecode2.e.read_reg2.ok - width = yield pdecode2.e.data_len - if imm_ok: - imm = yield pdecode2.e.imm_data.data - addr += imm - elif r2_ok: - r2_sel = yield pdecode2.e.read_reg2.data - addr += self.regfile.read_reg(r2_sel) - if internal_op == InternalOp.OP_STORE.value: - val_reg = yield pdecode2.e.read_reg3.data - val = self.regfile.read_reg(val_reg) - self.mem_sim.st(addr, val, width) - elif internal_op == InternalOp.OP_LOAD.value: - dest_reg = yield pdecode2.e.write_reg.data - val = self.mem_sim.ld(addr, width) - self.regfile.write_reg(dest_reg, val) - - def execute_op(self, pdecode2): - function = yield pdecode2.dec.op.function_unit - if function == Function.ALU.value: - yield from self.alu_op(pdecode2) - elif function == Function.LDST.value: - yield from self.mem_op(pdecode2) diff --git a/src/soc/simulator/test_sim.py b/src/soc/simulator/test_sim.py deleted file mode 100644 index 0a26380c..00000000 --- a/src/soc/simulator/test_sim.py +++ /dev/null @@ -1,140 +0,0 @@ -from nmigen import Module, Signal -from nmigen.back.pysim import Simulator, Delay -from nmigen.test.utils import FHDLTestCase -import unittest -from soc.simulator.internalop_sim import InternalOpSimulator -from soc.decoder.power_decoder import (create_pdecode) -from soc.decoder.power_enums import (Function, InternalOp, - In1Sel, In2Sel, In3Sel, - OutSel, RC, LdstLen, CryIn, - single_bit_flags, Form, SPR, - get_signal_name, get_csv) -from soc.decoder.power_decoder2 import (PowerDecode2) -from soc.simulator.program import Program -from soc.simulator.qemu import run_program - - -class Register: - def __init__(self, num): - self.num = num - - -class DecoderTestCase(FHDLTestCase): - - def run_tst(self, generator, simulator): - m = Module() - comb = m.d.comb - instruction = Signal(32) - - pdecode = create_pdecode() - - m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode) - comb += pdecode2.dec.raw_opcode_in.eq(instruction) - sim = Simulator(m) - gen = generator.generate_instructions() - - def process(): - for ins in gen: - - print("0x{:X}".format(ins & 0xffffffff)) - - # ask the decoder to decode this binary data (endian'd) - yield pdecode2.dec.bigendian.eq(0) # little / big? - yield instruction.eq(ins) # raw binary instr. - yield Delay(1e-6) - yield from simulator.execute_op(pdecode2) - - sim.add_process(process) - with sim.write_vcd("simulator.vcd", "simulator.gtkw", - traces=pdecode2.ports()): - sim.run() - - def test_example(self): - lst = ["addi 1, 0, 0x1234", - "addi 2, 0, 0x5678", - "add 3, 1, 2", - "and 4, 1, 2"] - with Program(lst) as program: - self.run_tst_program(program, [1, 2, 3, 4]) - - def test_ldst(self): - lst = ["addi 1, 0, 0x1234", - "addi 2, 0, 0x5678", - "stw 1, 0(2)", - "lwz 3, 0(2)"] - with Program(lst) as program: - self.run_tst_program(program, [1, 2, 3]) - - def test_ldst_extended(self): - lst = ["addi 1, 0, 0x1234", - "addi 2, 0, 0x5678", - "addi 4, 0, 0x40", - "stw 1, 0x40(2)", - "lwzx 3, 4, 2"] - with Program(lst) as program: - self.run_tst_program(program, [1, 2, 3]) - - def test_ldst_widths(self): - lst = [" lis 1, 0xdead", - "ori 1, 1, 0xbeef", - "addi 2, 0, 0x1000", - "std 1, 0(2)", - "lbz 1, 5(2)", - "lhz 3, 4(2)", - "lwz 4, 4(2)", - "addi 5, 0, 0x12", - "stb 5, 5(2)", - "ld 5, 0(2)"] - with Program(lst) as program: - self.run_tst_program(program, [1, 2, 3, 4, 5]) - - def test_sub(self): - lst = ["addi 1, 0, 0x1234", - "addi 2, 0, 0x5678", - "subf 3, 1, 2", - "subfic 4, 1, 0x1337", - "neg 5, 1"] - with Program(lst) as program: - self.run_tst_program(program, [1, 2, 3, 4, 5]) - - def test_add_with_carry(self): - lst = ["addi 1, 0, 5", - "neg 1, 1", - "addi 2, 0, 7", - "neg 2, 2", - "addc 3, 2, 1", - "addi 3, 3, 1" - ] - with Program(lst) as program: - self.run_tst_program(program, [1, 2, 3]) - - def test_addis(self): - lst = ["addi 1, 0, 0x0FFF", - "addis 1, 1, 0x0F" - ] - with Program(lst) as program: - self.run_tst_program(program, [1]) - - def test_mulli(self): - lst = ["addi 1, 0, 3", - "mulli 1, 1, 2" - ] - with Program(lst) as program: - self.run_tst_program(program, [1]) - - def run_tst_program(self, prog, reglist): - simulator = InternalOpSimulator() - self.run_tst(prog, simulator) - prog.reset() - with run_program(prog) as q: - qemu_register_compare(simulator, q, reglist) - - -def qemu_register_compare(simulator, qemu, regs): - for reg in regs: - qemu_val = qemu.get_register(reg) - simulator.regfile.assert_gpr(reg, qemu_val) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/unused/simulator/internalop_sim.py b/src/unused/simulator/internalop_sim.py new file mode 100644 index 00000000..f7a4b262 --- /dev/null +++ b/src/unused/simulator/internalop_sim.py @@ -0,0 +1,196 @@ +from soc.decoder.power_enums import (Function, Form, InternalOp, + In1Sel, In2Sel, In3Sel, OutSel, + RC, LdstLen, CryIn, get_csv, + single_bit_flags, + get_signal_name, default_values) +import math + + +class MemorySim: + def __init__(self, bytes_per_word=8): + self.mem = {} + self.bytes_per_word = bytes_per_word + self.word_log2 = math.ceil(math.log2(bytes_per_word)) + + def _get_shifter_mask(self, width, remainder): + shifter = ((self.bytes_per_word - width) - remainder) * \ + 8 # bits per byte + mask = (1 << (width * 8)) - 1 + return shifter, mask + + # TODO: Implement ld/st of lesser width + def ld(self, address, width=8): + 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] + else: + val = 0 + + if width != self.bytes_per_word: + shifter, mask = self._get_shifter_mask(width, remainder) + val = val & (mask << shifter) + val >>= shifter + print("Read {:x} from addr {:x}".format(val, address)) + return val + + def st(self, address, value, width=8): + remainder = address & (self.bytes_per_word - 1) + address = address >> self.word_log2 + assert remainder & (width - 1) == 0, "Unaligned access unsupported!" + print("Writing {:x} to addr {:x}".format(value, address)) + if width != self.bytes_per_word: + if address in self.mem: + val = self.mem[address] + else: + val = 0 + shifter, mask = self._get_shifter_mask(width, remainder) + val &= ~(mask << shifter) + val |= value << shifter + self.mem[address] = val + else: + self.mem[address] = value + + +class RegFile: + def __init__(self): + self.regfile = [0] * 32 + self.sprs = {} + + def write_reg(self, regnum, value): + all1s = (1 << 64)-1 # 64 bits worth of 1s + value &= all1s + print("Writing {:x} to reg r{}".format(value, regnum)) + self.regfile[regnum] = value + + def read_reg(self, regnum): + val = self.regfile[regnum] + print("Read {:x} from reg r{}".format(val, regnum)) + return val + + def assert_gpr(self, gpr, val): + reg_val = self.read_reg(gpr) + msg = "reg r{} got {:x}, expecting {:x}".format( + gpr, reg_val, val) + assert reg_val == val, msg + + def assert_gprs(self, gprs): + for k, v in list(gprs.items()): + self.assert_gpr(k, v) + + def set_xer(self, result, operanda, operandb): + xer = 0 + if result & 1 << 64: + xer |= XER.CA + + self.xer = xer + + +class InternalOpSimulator: + def __init__(self): + self.mem_sim = MemorySim() + self.regfile = RegFile() + + def execute_alu_op(self, op1, op2, internal_op, carry=0): + print(internal_op) + if internal_op == InternalOp.OP_ADD.value: + return op1 + op2 + carry + elif internal_op == InternalOp.OP_AND.value: + return op1 & op2 + elif internal_op == InternalOp.OP_OR.value: + return op1 | op2 + elif internal_op == InternalOp.OP_MUL_L64.value: + return op1 * op2 + else: + assert False, "Not implemented" + + def update_cr0(self, result): + if result == 0: + self.cr0 = 0b001 + elif result >> 63: + self.cr0 = 0b100 + else: + self.cr0 = 0b010 + print("update_cr0", self.cr0) + + def alu_op(self, pdecode2): + all1s = (1 << 64)-1 # 64 bits worth of 1s + internal_op = yield pdecode2.dec.op.internal_op + operand1 = 0 + operand2 = 0 + result = 0 + carry = 0 + r1_ok = yield pdecode2.e.read_reg1.ok + r2_ok = yield pdecode2.e.read_reg2.ok + r3_ok = yield pdecode2.e.read_reg3.ok + imm_ok = yield pdecode2.e.imm_data.ok + if r1_ok: + r1_sel = yield pdecode2.e.read_reg1.data + operand1 = self.regfile.read_reg(r1_sel) + elif r3_ok: + r3_sel = yield pdecode2.e.read_reg3.data + operand1 = self.regfile.read_reg(r3_sel) + if r2_ok: + r2_sel = yield pdecode2.e.read_reg2.data + operand2 = self.regfile.read_reg(r2_sel) + if imm_ok: + operand2 = yield pdecode2.e.imm_data.data + + inv_a = yield pdecode2.dec.op.inv_a + if inv_a: + operand1 = (~operand1) & all1s + + cry_in = yield pdecode2.dec.op.cry_in + if cry_in == CryIn.ONE.value: + carry = 1 + elif cry_in == CryIn.CA.value: + carry = self.carry_out + + # TODO rc_sel = yield pdecode2.dec.op.rc_sel + result = self.execute_alu_op(operand1, operand2, internal_op, + carry=carry) + + cry_out = yield pdecode2.dec.op.cry_out + rc = yield pdecode2.e.rc.data + + if rc: + self.update_cr0(result) + if cry_out == 1: + self.carry_out = (result >> 64) + print("setting carry_out", self.carry_out) + + ro_ok = yield pdecode2.e.write_reg.ok + if ro_ok: + ro_sel = yield pdecode2.e.write_reg.data + self.regfile.write_reg(ro_sel, result) + + def mem_op(self, pdecode2): + internal_op = yield pdecode2.dec.op.internal_op + addr_reg = yield pdecode2.e.read_reg1.data + addr = self.regfile.read_reg(addr_reg) + + imm_ok = yield pdecode2.e.imm_data.ok + r2_ok = yield pdecode2.e.read_reg2.ok + width = yield pdecode2.e.data_len + if imm_ok: + imm = yield pdecode2.e.imm_data.data + addr += imm + elif r2_ok: + r2_sel = yield pdecode2.e.read_reg2.data + addr += self.regfile.read_reg(r2_sel) + if internal_op == InternalOp.OP_STORE.value: + val_reg = yield pdecode2.e.read_reg3.data + val = self.regfile.read_reg(val_reg) + self.mem_sim.st(addr, val, width) + elif internal_op == InternalOp.OP_LOAD.value: + dest_reg = yield pdecode2.e.write_reg.data + val = self.mem_sim.ld(addr, width) + self.regfile.write_reg(dest_reg, val) + + def execute_op(self, pdecode2): + function = yield pdecode2.dec.op.function_unit + if function == Function.ALU.value: + yield from self.alu_op(pdecode2) + elif function == Function.LDST.value: + yield from self.mem_op(pdecode2) diff --git a/src/unused/simulator/test_sim.py b/src/unused/simulator/test_sim.py new file mode 100644 index 00000000..0a26380c --- /dev/null +++ b/src/unused/simulator/test_sim.py @@ -0,0 +1,140 @@ +from nmigen import Module, Signal +from nmigen.back.pysim import Simulator, Delay +from nmigen.test.utils import FHDLTestCase +import unittest +from soc.simulator.internalop_sim import InternalOpSimulator +from soc.decoder.power_decoder import (create_pdecode) +from soc.decoder.power_enums import (Function, InternalOp, + In1Sel, In2Sel, In3Sel, + OutSel, RC, LdstLen, CryIn, + single_bit_flags, Form, SPR, + get_signal_name, get_csv) +from soc.decoder.power_decoder2 import (PowerDecode2) +from soc.simulator.program import Program +from soc.simulator.qemu import run_program + + +class Register: + def __init__(self, num): + self.num = num + + +class DecoderTestCase(FHDLTestCase): + + def run_tst(self, generator, simulator): + m = Module() + comb = m.d.comb + instruction = Signal(32) + + pdecode = create_pdecode() + + m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode) + comb += pdecode2.dec.raw_opcode_in.eq(instruction) + sim = Simulator(m) + gen = generator.generate_instructions() + + def process(): + for ins in gen: + + print("0x{:X}".format(ins & 0xffffffff)) + + # ask the decoder to decode this binary data (endian'd) + yield pdecode2.dec.bigendian.eq(0) # little / big? + yield instruction.eq(ins) # raw binary instr. + yield Delay(1e-6) + yield from simulator.execute_op(pdecode2) + + sim.add_process(process) + with sim.write_vcd("simulator.vcd", "simulator.gtkw", + traces=pdecode2.ports()): + sim.run() + + def test_example(self): + lst = ["addi 1, 0, 0x1234", + "addi 2, 0, 0x5678", + "add 3, 1, 2", + "and 4, 1, 2"] + with Program(lst) as program: + self.run_tst_program(program, [1, 2, 3, 4]) + + def test_ldst(self): + lst = ["addi 1, 0, 0x1234", + "addi 2, 0, 0x5678", + "stw 1, 0(2)", + "lwz 3, 0(2)"] + with Program(lst) as program: + self.run_tst_program(program, [1, 2, 3]) + + def test_ldst_extended(self): + lst = ["addi 1, 0, 0x1234", + "addi 2, 0, 0x5678", + "addi 4, 0, 0x40", + "stw 1, 0x40(2)", + "lwzx 3, 4, 2"] + with Program(lst) as program: + self.run_tst_program(program, [1, 2, 3]) + + def test_ldst_widths(self): + lst = [" lis 1, 0xdead", + "ori 1, 1, 0xbeef", + "addi 2, 0, 0x1000", + "std 1, 0(2)", + "lbz 1, 5(2)", + "lhz 3, 4(2)", + "lwz 4, 4(2)", + "addi 5, 0, 0x12", + "stb 5, 5(2)", + "ld 5, 0(2)"] + with Program(lst) as program: + self.run_tst_program(program, [1, 2, 3, 4, 5]) + + def test_sub(self): + lst = ["addi 1, 0, 0x1234", + "addi 2, 0, 0x5678", + "subf 3, 1, 2", + "subfic 4, 1, 0x1337", + "neg 5, 1"] + with Program(lst) as program: + self.run_tst_program(program, [1, 2, 3, 4, 5]) + + def test_add_with_carry(self): + lst = ["addi 1, 0, 5", + "neg 1, 1", + "addi 2, 0, 7", + "neg 2, 2", + "addc 3, 2, 1", + "addi 3, 3, 1" + ] + with Program(lst) as program: + self.run_tst_program(program, [1, 2, 3]) + + def test_addis(self): + lst = ["addi 1, 0, 0x0FFF", + "addis 1, 1, 0x0F" + ] + with Program(lst) as program: + self.run_tst_program(program, [1]) + + def test_mulli(self): + lst = ["addi 1, 0, 3", + "mulli 1, 1, 2" + ] + with Program(lst) as program: + self.run_tst_program(program, [1]) + + def run_tst_program(self, prog, reglist): + simulator = InternalOpSimulator() + self.run_tst(prog, simulator) + prog.reset() + with run_program(prog) as q: + qemu_register_compare(simulator, q, reglist) + + +def qemu_register_compare(simulator, qemu, regs): + for reg in regs: + qemu_val = qemu.get_register(reg) + simulator.regfile.assert_gpr(reg, qemu_val) + + +if __name__ == "__main__": + unittest.main()