@@ -350,3 +350,268 @@ def sim_test():
350350 with Simulator (m , vcd_file = open ("test.vcd" , "w" )) as sim :
351351 sim .add_process (sim_test ())
352352 sim .run ()
353+
354+
355+ class ArbiterTestCase (unittest .TestCase ):
356+ def setUp (self ):
357+ self .dut = Arbiter (addr_width = 31 , data_width = 32 , granularity = 16 ,
358+ features = {"err" })
359+
360+ def test_add_wrong (self ):
361+ with self .assertRaisesRegex (TypeError ,
362+ r"Initiator bus must be an instance of wishbone\.Interface, not 'foo'" ):
363+ self .dut .add ("foo" )
364+
365+ def test_add_wrong_addr_width (self ):
366+ with self .assertRaisesRegex (ValueError ,
367+ r"Initiator bus has address width 15, which is not the same as arbiter "
368+ r"address width 31" ):
369+ self .dut .add (Interface (addr_width = 15 , data_width = 32 , granularity = 16 ))
370+
371+ def test_add_wrong_granularity (self ):
372+ with self .assertRaisesRegex (ValueError ,
373+ r"Initiator bus has granularity 8, which is lesser than "
374+ r"the arbiter granularity 16" ):
375+ self .dut .add (Interface (addr_width = 31 , data_width = 32 , granularity = 8 ))
376+
377+ def test_add_wrong_data_width (self ):
378+ with self .assertRaisesRegex (ValueError ,
379+ r"Initiator bus has data width 16, which is not the same as arbiter "
380+ r"data width 32" ):
381+ self .dut .add (Interface (addr_width = 31 , data_width = 16 , granularity = 16 ))
382+
383+ def test_add_wrong_optional_output (self ):
384+ with self .assertRaisesRegex (ValueError ,
385+ r"Arbiter has optional output 'err', but the initiator bus does "
386+ r"not have a corresponding input" ):
387+ self .dut .add (Interface (addr_width = 31 , data_width = 32 , granularity = 16 ))
388+
389+
390+ class ArbiterSimulationTestCase (unittest .TestCase ):
391+ def test_simple (self ):
392+ dut = Arbiter (addr_width = 30 , data_width = 32 , granularity = 8 ,
393+ features = {"err" , "rty" , "stall" , "lock" , "cti" , "bte" })
394+ intr_1 = Interface (addr_width = 30 , data_width = 32 , granularity = 8 ,
395+ features = {"err" , "rty" })
396+ dut .add (intr_1 )
397+ intr_2 = Interface (addr_width = 30 , data_width = 32 , granularity = 16 ,
398+ features = {"err" , "rty" , "stall" , "lock" , "cti" , "bte" })
399+ dut .add (intr_2 )
400+
401+ def sim_test ():
402+ yield intr_1 .adr .eq (0x7ffffffc >> 2 )
403+ yield intr_1 .cyc .eq (1 )
404+ yield intr_1 .stb .eq (1 )
405+ yield intr_1 .sel .eq (0b1111 )
406+ yield intr_1 .we .eq (1 )
407+ yield intr_1 .dat_w .eq (0x12345678 )
408+ yield dut .bus .dat_r .eq (0xabcdef01 )
409+ yield dut .bus .ack .eq (1 )
410+ yield dut .bus .err .eq (1 )
411+ yield dut .bus .rty .eq (1 )
412+ yield Delay (1e-7 )
413+ self .assertEqual ((yield dut .bus .adr ), 0x7ffffffc >> 2 )
414+ self .assertEqual ((yield dut .bus .cyc ), 1 )
415+ self .assertEqual ((yield dut .bus .stb ), 1 )
416+ self .assertEqual ((yield dut .bus .sel ), 0b1111 )
417+ self .assertEqual ((yield dut .bus .we ), 1 )
418+ self .assertEqual ((yield dut .bus .dat_w ), 0x12345678 )
419+ self .assertEqual ((yield dut .bus .lock ), 1 )
420+ self .assertEqual ((yield dut .bus .cti ), CycleType .CLASSIC .value )
421+ self .assertEqual ((yield dut .bus .bte ), BurstTypeExt .LINEAR .value )
422+ self .assertEqual ((yield intr_1 .dat_r ), 0xabcdef01 )
423+ self .assertEqual ((yield intr_1 .ack ), 1 )
424+ self .assertEqual ((yield intr_1 .err ), 1 )
425+ self .assertEqual ((yield intr_1 .rty ), 1 )
426+
427+ yield intr_1 .cyc .eq (0 )
428+ yield intr_2 .adr .eq (0xe0000000 >> 2 )
429+ yield intr_2 .cyc .eq (1 )
430+ yield intr_2 .stb .eq (1 )
431+ yield intr_2 .sel .eq (0b10 )
432+ yield intr_2 .we .eq (1 )
433+ yield intr_2 .dat_w .eq (0x43218765 )
434+ yield intr_2 .lock .eq (0 )
435+ yield intr_2 .cti .eq (CycleType .INCR_BURST )
436+ yield intr_2 .bte .eq (BurstTypeExt .WRAP_4 )
437+ yield Tick ()
438+
439+ yield dut .bus .stall .eq (0 )
440+ yield Delay (1e-7 )
441+ self .assertEqual ((yield dut .bus .adr ), 0xe0000000 >> 2 )
442+ self .assertEqual ((yield dut .bus .cyc ), 1 )
443+ self .assertEqual ((yield dut .bus .stb ), 1 )
444+ self .assertEqual ((yield dut .bus .sel ), 0b1100 )
445+ self .assertEqual ((yield dut .bus .we ), 1 )
446+ self .assertEqual ((yield dut .bus .dat_w ), 0x43218765 )
447+ self .assertEqual ((yield dut .bus .lock ), 0 )
448+ self .assertEqual ((yield dut .bus .cti ), CycleType .INCR_BURST .value )
449+ self .assertEqual ((yield dut .bus .bte ), BurstTypeExt .WRAP_4 .value )
450+ self .assertEqual ((yield intr_2 .dat_r ), 0xabcdef01 )
451+ self .assertEqual ((yield intr_2 .ack ), 1 )
452+ self .assertEqual ((yield intr_2 .err ), 1 )
453+ self .assertEqual ((yield intr_2 .rty ), 1 )
454+ self .assertEqual ((yield intr_2 .stall ), 0 )
455+
456+ with Simulator (dut , vcd_file = open ("test.vcd" , "w" )) as sim :
457+ sim .add_clock (1e-6 )
458+ sim .add_sync_process (sim_test ())
459+ sim .run ()
460+
461+ def test_lock (self ):
462+ dut = Arbiter (addr_width = 30 , data_width = 32 , features = {"lock" })
463+ intr_1 = Interface (addr_width = 30 , data_width = 32 , features = {"lock" })
464+ dut .add (intr_1 )
465+ intr_2 = Interface (addr_width = 30 , data_width = 32 , features = {"lock" })
466+ dut .add (intr_2 )
467+
468+ def sim_test ():
469+ yield intr_1 .cyc .eq (1 )
470+ yield intr_1 .lock .eq (1 )
471+ yield intr_2 .cyc .eq (1 )
472+ yield dut .bus .ack .eq (1 )
473+ yield Delay (1e-7 )
474+ self .assertEqual ((yield intr_1 .ack ), 1 )
475+ self .assertEqual ((yield intr_2 .ack ), 0 )
476+
477+ yield Tick ()
478+ yield Delay (1e-7 )
479+ self .assertEqual ((yield intr_1 .ack ), 1 )
480+ self .assertEqual ((yield intr_2 .ack ), 0 )
481+
482+ yield intr_1 .lock .eq (0 )
483+ yield Tick ()
484+ yield Delay (1e-7 )
485+ self .assertEqual ((yield intr_1 .ack ), 0 )
486+ self .assertEqual ((yield intr_2 .ack ), 1 )
487+
488+ yield intr_2 .cyc .eq (0 )
489+ yield Tick ()
490+ yield Delay (1e-7 )
491+ self .assertEqual ((yield intr_1 .ack ), 1 )
492+ self .assertEqual ((yield intr_2 .ack ), 0 )
493+
494+ yield intr_1 .stb .eq (1 )
495+ yield Tick ()
496+ yield Delay (1e-7 )
497+ self .assertEqual ((yield intr_1 .ack ), 1 )
498+ self .assertEqual ((yield intr_2 .ack ), 0 )
499+
500+ yield intr_1 .stb .eq (0 )
501+ yield intr_2 .cyc .eq (1 )
502+ yield Tick ()
503+ yield Delay (1e-7 )
504+ self .assertEqual ((yield intr_1 .ack ), 0 )
505+ self .assertEqual ((yield intr_2 .ack ), 1 )
506+
507+ with Simulator (dut , vcd_file = open ("test.vcd" , "w" )) as sim :
508+ sim .add_clock (1e-6 )
509+ sim .add_sync_process (sim_test ())
510+ sim .run ()
511+
512+ def test_stall (self ):
513+ dut = Arbiter (addr_width = 30 , data_width = 32 , features = {"stall" })
514+ intr_1 = Interface (addr_width = 30 , data_width = 32 , features = {"stall" })
515+ dut .add (intr_1 )
516+ intr_2 = Interface (addr_width = 30 , data_width = 32 , features = {"stall" })
517+ dut .add (intr_2 )
518+
519+ def sim_test ():
520+ yield intr_1 .cyc .eq (1 )
521+ yield intr_2 .cyc .eq (1 )
522+ yield dut .bus .stall .eq (0 )
523+ yield Delay (1e-6 )
524+ self .assertEqual ((yield intr_1 .stall ), 0 )
525+ self .assertEqual ((yield intr_2 .stall ), 1 )
526+
527+ yield dut .bus .stall .eq (1 )
528+ yield Delay (1e-6 )
529+ self .assertEqual ((yield intr_1 .stall ), 1 )
530+ self .assertEqual ((yield intr_2 .stall ), 1 )
531+
532+ with Simulator (dut , vcd_file = open ("test.vcd" , "w" )) as sim :
533+ sim .add_process (sim_test ())
534+ sim .run ()
535+
536+ def test_stall_compat (self ):
537+ dut = Arbiter (addr_width = 30 , data_width = 32 )
538+ intr_1 = Interface (addr_width = 30 , data_width = 32 , features = {"stall" })
539+ dut .add (intr_1 )
540+ intr_2 = Interface (addr_width = 30 , data_width = 32 , features = {"stall" })
541+ dut .add (intr_2 )
542+
543+ def sim_test ():
544+ yield intr_1 .cyc .eq (1 )
545+ yield intr_2 .cyc .eq (1 )
546+ yield Delay (1e-6 )
547+ self .assertEqual ((yield intr_1 .stall ), 1 )
548+ self .assertEqual ((yield intr_2 .stall ), 1 )
549+
550+ yield dut .bus .ack .eq (1 )
551+ yield Delay (1e-6 )
552+ self .assertEqual ((yield intr_1 .stall ), 0 )
553+ self .assertEqual ((yield intr_2 .stall ), 1 )
554+
555+ with Simulator (dut , vcd_file = open ("test.vcd" , "w" )) as sim :
556+ sim .add_process (sim_test ())
557+ sim .run ()
558+
559+ def test_roundrobin (self ):
560+ dut = Arbiter (addr_width = 30 , data_width = 32 )
561+ intr_1 = Interface (addr_width = 30 , data_width = 32 )
562+ dut .add (intr_1 )
563+ intr_2 = Interface (addr_width = 30 , data_width = 32 )
564+ dut .add (intr_2 )
565+ intr_3 = Interface (addr_width = 30 , data_width = 32 )
566+ dut .add (intr_3 )
567+
568+ def sim_test ():
569+ yield intr_1 .cyc .eq (1 )
570+ yield intr_2 .cyc .eq (0 )
571+ yield intr_3 .cyc .eq (1 )
572+ yield dut .bus .ack .eq (1 )
573+ yield Delay (1e-7 )
574+ self .assertEqual ((yield intr_1 .ack ), 1 )
575+ self .assertEqual ((yield intr_2 .ack ), 0 )
576+ self .assertEqual ((yield intr_3 .ack ), 0 )
577+
578+ yield intr_1 .cyc .eq (0 )
579+ yield intr_2 .cyc .eq (0 )
580+ yield intr_3 .cyc .eq (1 )
581+ yield Tick ()
582+ yield Delay (1e-7 )
583+ self .assertEqual ((yield intr_1 .ack ), 0 )
584+ self .assertEqual ((yield intr_2 .ack ), 0 )
585+ self .assertEqual ((yield intr_3 .ack ), 1 )
586+
587+ yield intr_1 .cyc .eq (1 )
588+ yield intr_2 .cyc .eq (1 )
589+ yield intr_3 .cyc .eq (0 )
590+ yield Tick ()
591+ yield Delay (1e-7 )
592+ self .assertEqual ((yield intr_1 .ack ), 1 )
593+ self .assertEqual ((yield intr_2 .ack ), 0 )
594+ self .assertEqual ((yield intr_3 .ack ), 0 )
595+
596+ yield intr_1 .cyc .eq (0 )
597+ yield intr_2 .cyc .eq (1 )
598+ yield intr_3 .cyc .eq (1 )
599+ yield Tick ()
600+ yield Delay (1e-7 )
601+ self .assertEqual ((yield intr_1 .ack ), 0 )
602+ self .assertEqual ((yield intr_2 .ack ), 1 )
603+ self .assertEqual ((yield intr_3 .ack ), 0 )
604+
605+ yield intr_1 .cyc .eq (1 )
606+ yield intr_2 .cyc .eq (0 )
607+ yield intr_3 .cyc .eq (1 )
608+ yield Tick ()
609+ yield Delay (1e-7 )
610+ self .assertEqual ((yield intr_1 .ack ), 0 )
611+ self .assertEqual ((yield intr_2 .ack ), 0 )
612+ self .assertEqual ((yield intr_3 .ack ), 1 )
613+
614+ with Simulator (dut , vcd_file = open ("test.vcd" , "w" )) as sim :
615+ sim .add_clock (1e-6 )
616+ sim .add_sync_process (sim_test ())
617+ sim .run ()
0 commit comments