import random import cocotb from cocotb.triggers import FallingEdge,RisingEdge,ClockCycles import cocotb.log from cpu import RiskV from defsParser import Regs from cocotb.result import TestSuccess from tests.common_functions.test_functions import * from tests.bitbang.bitbang_functions import * from caravel import GPIO_MODE from cocotb.binary import BinaryValue from tests.housekeeping.housekeeping_spi.spi_access_functions import * reg = Regs() caravel_clock = 0 user_clock = 0 core_clock = 0 @cocotb.test() @repot_test async def clock_redirect(dut): caravelEnv,clock = await test_configure(dut,timeout_cycles=264012) cpu = RiskV(dut) cpu.cpu_force_reset() cpu.cpu_release_reset() # calculate core clock await cocotb.start(calculate_clk_period(dut.uut.clock,"core clock")) await ClockCycles(caravelEnv.clk,110) cocotb.log.info(f"[TEST] core clock requency = {round(1000000/core_clock,2)} MHz period = {core_clock}ps") await wait_reg1(cpu,caravelEnv,0xAa) # check clk redirect working #user clock clock_name = "user clock" await write_reg_spi(caravelEnv,0x1b,0x0) # disable user clock output redirect await cocotb.start(calculate_clk_period(dut.bin14_monitor,clock_name)) await ClockCycles(caravelEnv.clk,110) if user_clock != 0: cocotb.log.error(f"[TEST] Error: {clock_name} is directed while clk2_output_dest is disabled") else: cocotb.log.info(f"[TEST] Pass: {clock_name} has not directed when reg clk2_output_dest is disabled") await write_reg_spi(caravelEnv,0x1b,0x4) # enable user clock output redirect await cocotb.start(calculate_clk_period(dut.bin14_monitor,clock_name)) await ClockCycles(caravelEnv.clk,110) if user_clock != core_clock: cocotb.log.error(f"[TEST] Error: {clock_name} is directed with wrong value {clock_name} period = {user_clock} and core clock = {core_clock}") else: cocotb.log.info(f"[TEST] Pass: {clock_name} has directed successfully") #caravel clock clock_name = "caravel clock" await write_reg_spi(caravelEnv,0x1b,0x0) # disable caravel clock output redirect await cocotb.start(calculate_clk_period(dut.bin14_monitor,clock_name)) await ClockCycles(caravelEnv.clk,110) if caravel_clock != 0: cocotb.log.error(f"[TEST] Error: {clock_name} is directed while clk2_output_dest is disabled") else: cocotb.log.info(f"[TEST] Pass: {clock_name} has not directed when reg clk2_output_dest is disabled") await write_reg_spi(caravelEnv,0x1b,0x4) # enable caravel clock output redirect await cocotb.start(calculate_clk_period(dut.bin15_monitor,clock_name)) await ClockCycles(caravelEnv.clk,110) if caravel_clock != core_clock: cocotb.log.error(f"[TEST] Error: {clock_name} is directed with wrong value {clock_name} period = {caravel_clock} and core clock = {core_clock}") else: cocotb.log.info(f"[TEST] Pass: {clock_name} has directed successfully") async def calculate_clk_period(clk,name): await RisingEdge(clk) initial_time = cocotb.simulator.get_sim_time() initial_time = (initial_time[0] <<32) | (initial_time[1]) for i in range(100): await RisingEdge(clk) end_time = cocotb.simulator.get_sim_time() end_time = (end_time[0] <<32) | (end_time[1]) val = (end_time - initial_time) / 100 cocotb.log.debug(f"[TEST] clock of {name} is {val}") if name == "caravel clock": global caravel_clock caravel_clock = val elif name == "user clock": global user_clock user_clock = val elif name == "core clock": global core_clock core_clock = val return val