2022-10-05 15:58:36 -05:00
import random
import cocotb
from cocotb . triggers import FallingEdge , RisingEdge , ClockCycles
import cocotb . log
2022-10-10 06:50:45 -05:00
from interfaces . cpu import RiskV
from interfaces . defsParser import Regs
2022-10-05 15:58:36 -05:00
from cocotb . result import TestSuccess
from tests . common_functions . test_functions import *
from tests . bitbang . bitbang_functions import *
2022-10-10 06:50:45 -05:00
from interfaces . caravel import GPIO_MODE
2022-10-05 15:58:36 -05:00
from cocotb . binary import BinaryValue
reg = Regs ( )
caravel_clock = 0
user_clock = 0
@cocotb.test ( )
@repot_test
async def pll ( dut ) :
2022-10-24 06:59:04 -05:00
caravelEnv , clock = await test_configure ( dut , timeout_cycles = 47279 )
2022-10-05 15:58:36 -05:00
cpu = RiskV ( dut )
cpu . cpu_force_reset ( )
cpu . cpu_release_reset ( )
error_margin = 0.1
await wait_reg1 ( cpu , caravelEnv , 0xA1 )
await cocotb . start ( calculate_clk_period ( dut . bin14_monitor , " caravel clock " ) )
await cocotb . start ( calculate_clk_period ( dut . bin15_monitor , " user clock " ) )
await wait_reg1 ( cpu , caravelEnv , 0xA3 )
if abs ( caravel_clock - user_clock ) > error_margin * caravel_clock :
cocotb . log . error ( f " [TEST] Error: clocks should be equal in phase 1 but caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
else :
cocotb . log . info ( f " [TEST] pass phase 1 caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
await cocotb . start ( calculate_clk_period ( dut . bin14_monitor , " caravel clock " ) )
await cocotb . start ( calculate_clk_period ( dut . bin15_monitor , " user clock " ) )
await wait_reg1 ( cpu , caravelEnv , 0xA5 )
if abs ( caravel_clock - user_clock ) > error_margin * caravel_clock :
cocotb . log . error ( f " [TEST] Error: clocks should be equal in phase 2 but caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
else :
cocotb . log . info ( f " [TEST] pass phase 2 caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
await cocotb . start ( calculate_clk_period ( dut . bin14_monitor , " caravel clock " ) )
await cocotb . start ( calculate_clk_period ( dut . bin15_monitor , " user clock " ) )
await wait_reg1 ( cpu , caravelEnv , 0xA7 )
if abs ( caravel_clock - user_clock * 3 ) > error_margin * caravel_clock :
cocotb . log . error ( f " [TEST] Error: user clock shoud be 3 times caravel clock in phase 3 but caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
else :
cocotb . log . info ( f " [TEST] pass phase 3 caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
await cocotb . start ( calculate_clk_period ( dut . bin14_monitor , " caravel clock " ) )
await cocotb . start ( calculate_clk_period ( dut . bin15_monitor , " user clock " ) )
await wait_reg1 ( cpu , caravelEnv , 0xA9 )
if abs ( caravel_clock - user_clock * 3 ) > error_margin * caravel_clock :
cocotb . log . error ( f " [TEST] Error: user clock shoud be 3 times caravel clock in phase 4 but caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
else :
cocotb . log . info ( f " [TEST] pass phase 4 caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
await cocotb . start ( calculate_clk_period ( dut . bin14_monitor , " caravel clock " ) )
await cocotb . start ( calculate_clk_period ( dut . bin15_monitor , " user clock " ) )
await wait_reg1 ( cpu , caravelEnv , 0xAa )
if abs ( caravel_clock - user_clock * 4 ) > error_margin * caravel_clock :
cocotb . log . error ( f " [TEST] Error: user clock shoud be 4 times caravel clock in phase 5 but caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
else :
cocotb . log . info ( f " [TEST] pass phase 5 caravel clock = { round ( 1000000 / caravel_clock , 2 ) } MHz user clock = { round ( 1000000 / user_clock , 2 ) } MHz " )
await ClockCycles ( caravelEnv . clk , 10000 )
# for i in range(1000):
# await ClockCycles(caravelEnv.clk,10000)
# cocotb.log.info(f"time = {cocotb.simulator.get_sim_time()}")
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
val = str ( val )
return val