Skip to content

Commit

Permalink
Remove TestCoreSimple and TestCoreRandomized
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacob Urbanczyk committed Mar 5, 2024
1 parent 0e4f74d commit 22439d4
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 174 deletions.
8 changes: 0 additions & 8 deletions coreblocks/frontend/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ def __init__(self, gen_params: GenParams, icache: CacheInterface, cont: Method)
# ExceptionCauseRegister uses separate Transaction for it, so performace is not affected.
self.stall_exception.add_conflict(self.resume, Priority.LEFT)

# PC of the last fetched instruction. For now only used in tests.
self.pc = Signal(self.gen_params.isa.xlen)

def elaborate(self, platform):
m = TModule()

Expand Down Expand Up @@ -91,7 +88,6 @@ def stall(exception=False):
with m.If(unsafe_instr):
stall()

m.d.sync += self.pc.eq(target.addr)
m.d.comb += instr.eq(res.instr)

self.cont(m, instr=instr, pc=target.addr, access_fault=fetch_error, rvc=0)
Expand Down Expand Up @@ -138,9 +134,6 @@ def __init__(self, gen_params: GenParams, icache: CacheInterface, cont: Method)

self.perf_rvc = HwCounter("frontend.ifu.rvc", "Number of decompressed RVC instructions")

# PC of the last fetched instruction. For now only used in tests.
self.pc = Signal(self.gen_params.isa.xlen)

def elaborate(self, platform) -> TModule:
m = TModule()

Expand Down Expand Up @@ -231,7 +224,6 @@ def elaborate(self, platform) -> TModule:
m.d.sync += stalled_unsafe.eq(1)
m.d.sync += flushing.eq(1)

m.d.sync += self.pc.eq(current_pc)
with m.If(~cache_resp.error):
m.d.sync += current_pc.eq(current_pc + Mux(is_rvc, C(2, 3), C(4, 3)))

Expand Down
167 changes: 1 addition & 166 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,15 @@
from coreblocks.params.configurations import CoreConfiguration, basic_core_config, full_core_config
from coreblocks.peripherals.wishbone import WishboneBus, WishboneMemorySlave

from typing import Optional, cast
from typing import Optional
import random
import subprocess
import tempfile
from parameterized import parameterized_class
from riscvmodel.insn import (
InstructionADDI,
InstructionSLTI,
InstructionSLTIU,
InstructionXORI,
InstructionORI,
InstructionANDI,
InstructionSLLI,
InstructionSRLI,
InstructionSRAI,
InstructionLUI,
InstructionJAL,
)
from riscvmodel.model import Model
from riscvmodel.isa import Instruction, InstructionRType, get_insns
from riscvmodel.variant import RV32I


class CoreTestElaboratable(Elaboratable):
Expand Down Expand Up @@ -58,14 +46,12 @@ def elaborate(self, platform):
)
self.core = Core(gen_params=self.gen_params, wb_instr_bus=wb_instr_bus, wb_data_bus=wb_data_bus)
self.io_in = TestbenchIO(AdapterTrans(self.core.fetch_continue.method))
self.rf_write = TestbenchIO(AdapterTrans(self.core.RF.write))
self.interrupt = TestbenchIO(AdapterTrans(self.core.interrupt_controller.report_interrupt))

m.submodules.wb_mem_slave = self.wb_mem_slave
m.submodules.wb_mem_slave_data = self.wb_mem_slave_data
m.submodules.c = self.core
m.submodules.io_in = self.io_in
m.submodules.rf_write = self.rf_write
m.submodules.interrupt = self.interrupt

m.d.comb += wb_instr_bus.connect(self.wb_mem_slave.bus)
Expand All @@ -74,53 +60,19 @@ def elaborate(self, platform):
return m


def gen_riscv_add_instr(dst, src1, src2):
return 0b0110011 | dst << 7 | src1 << 15 | src2 << 20


def gen_riscv_lui_instr(dst, imm):
return 0b0110111 | dst << 7 | imm << 12


class TestCoreBase(TestCaseWithSimulator):
gen_params: GenParams
m: CoreTestElaboratable

def check_RAT_alloc(self, rat, expected_alloc_count=None): # noqa: N802
allocated = []
for i in range(self.m.gen_params.isa.reg_cnt):
allocated.append((yield rat.entries[i]))
filtered_zeros = list(filter(lambda x: x != 0, allocated))

# check if 0th register is set to 0
self.assertEqual(allocated[0], 0)
# check if there are no duplicate physical registers allocated for two different architectural registers
self.assertEqual(len(filtered_zeros), len(set(filtered_zeros)))
# check if the expected number of allocated registers matches reality
if expected_alloc_count:
self.assertEqual(len(filtered_zeros), expected_alloc_count)

def get_phys_reg_rrat(self, reg_id):
return (yield self.m.core.RRAT.entries[reg_id])

def get_phys_reg_frat(self, reg_id):
return (yield self.m.core.FRAT.entries[reg_id])

def get_arch_reg_val(self, reg_id):
return (yield self.m.core.RF.entries[(yield from self.get_phys_reg_rrat(reg_id))].reg_val)

def get_phys_reg_val(self, reg_id):
return (yield self.m.core.RF.entries[reg_id].reg_val)

def push_instr(self, opcode):
yield from self.m.io_in.call(instr=opcode)

def compare_core_states(self, sw_core):
for i in range(self.gen_params.isa.reg_cnt):
reg_val = sw_core.state.intreg.regs[i].value
unsigned_val = reg_val & 0xFFFFFFFF
self.assertEqual((yield from self.get_arch_reg_val(i)), unsigned_val)

def push_register_load_imm(self, reg_id, val):
addi_imm = signed_to_int(val & 0xFFF, 12)
lui_imm = (val & 0xFFFFF000) >> 12
Expand All @@ -132,123 +84,6 @@ def push_register_load_imm(self, reg_id, val):
yield from self.push_instr(InstructionADDI(reg_id, reg_id, addi_imm).encode())


class TestCoreSimple(TestCoreBase):
def simple_test(self):
# this test first provokes allocation of physical registers,
# then sets the values in those registers, and finally runs
# an actual computation.

# The test sets values in the reg file by hand

# provoking allocation of physical register
for i in range(self.m.gen_params.isa.reg_cnt - 1):
yield from self.push_instr(gen_riscv_add_instr(i + 1, 0, 0))

# waiting for the retirement rat to be set
for i in range(100):
yield

# checking if all registers have been allocated
yield from self.check_RAT_alloc(self.m.core.FRAT, 31)
yield from self.check_RAT_alloc(self.m.core.RRAT, 31)

# writing values to physical registers
yield from self.m.rf_write.call(reg_id=(yield from self.get_phys_reg_rrat(1)), reg_val=1)
yield from self.m.rf_write.call(reg_id=(yield from self.get_phys_reg_rrat(2)), reg_val=2)
yield from self.m.rf_write.call(reg_id=(yield from self.get_phys_reg_rrat(3)), reg_val=3)

# waiting for potential conflicts on rf_write
for i in range(10):
yield

self.assertEqual((yield from self.get_arch_reg_val(1)), 1)
self.assertEqual((yield from self.get_arch_reg_val(2)), 2)
self.assertEqual((yield from self.get_arch_reg_val(3)), 3)

# issuing actual instructions for the test
yield from self.push_instr(gen_riscv_add_instr(4, 1, 2))
yield from self.push_instr(gen_riscv_add_instr(4, 3, 4))
yield from self.push_instr(gen_riscv_lui_instr(5, 1))

# waiting for the instructions to be processed
for i in range(50):
yield

self.assertEqual((yield from self.get_arch_reg_val(1)), 1)
self.assertEqual((yield from self.get_arch_reg_val(2)), 2)
self.assertEqual((yield from self.get_arch_reg_val(3)), 3)
# 1 + 2 + 3 = 6
self.assertEqual((yield from self.get_arch_reg_val(4)), 6)
self.assertEqual((yield from self.get_arch_reg_val(5)), 1 << 12)

def test_simple(self):
self.gen_params = GenParams(basic_core_config)
m = CoreTestElaboratable(self.gen_params)
self.m = m

with self.run_simulation(m) as sim:
sim.add_sync_process(self.simple_test)


class TestCoreRandomized(TestCoreBase):
def randomized_input(self):
infloop_addr = (len(self.instr_mem) - 1) * 4
# wait for PC to go past all instruction
while (yield self.m.core.fetch.pc) != infloop_addr:
yield

# finish calculations
yield from self.tick(50)

yield from self.compare_core_states(self.software_core)

def test_randomized(self):
self.gen_params = GenParams(basic_core_config)
self.instr_count = 300
random.seed(42)

# cast is there to avoid stubbing riscvmodel
instructions = cast(list[type[Instruction]], get_insns(cls=InstructionRType, variant=RV32I))
instructions += [
InstructionADDI,
InstructionSLTI,
InstructionSLTIU,
InstructionXORI,
InstructionORI,
InstructionANDI,
InstructionSLLI,
InstructionSRLI,
InstructionSRAI,
InstructionLUI,
]

# allocate some random values for registers
init_instr_list = list(
InstructionADDI(rd=i, rs1=0, imm=random.randint(-(2**11), 2**11 - 1))
for i in range(self.gen_params.isa.reg_cnt)
)

# generate random instruction stream
instr_list = list(random.choice(instructions)() for _ in range(self.instr_count))
for instr in instr_list:
instr.randomize(RV32I)

self.software_core = Model(RV32I)
self.software_core.execute(init_instr_list)
self.software_core.execute(instr_list)

# We add JAL instruction at the end to effectively create a infinite loop at the end of the program.
all_instr = init_instr_list + instr_list + [InstructionJAL(rd=0, imm=0)]

self.instr_mem = list(map(lambda x: x.encode(), all_instr))

m = CoreTestElaboratable(self.gen_params, instr_mem=self.instr_mem)
self.m = m

with self.run_simulation(m) as sim:
sim.add_sync_process(self.randomized_input)


class TestCoreAsmSourceBase(TestCoreBase):
base_dir: str = "test/asm/"

Expand Down

0 comments on commit 22439d4

Please sign in to comment.