Top Banner
Verification Learns a New Language Introducing Python UVM (pyuvm) © Siemens 2021 | DVClub Europe 2021 | Siemens EDA
31

Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Apr 28, 2021

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Verification Learns a New

Language

Introducing Python UVM (pyuvm)

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 2: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

The SystemVerilog Assumption

A structured testbench is only software making

function calls through a proxy

The UVM assumes the "software" is written in

SystemVerilog

Testbench "software" running on a simulator

engine is slow and leads to unacceleratable

testbenches.

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

This could be Python!

Page 3: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

How does Python drive the simulator? One approach: cocotb

Cocotb

• COroutine COsimulation TB

• https://github.com/cocotb/

Connects Python to most simulators through VPI and VHPI.

There are also DPI-based approaches

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 4: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Unique Python Elements No typing and other exceptions

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 5: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Everything in Python is an Object

No typing issues

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Typing leads to parameters

SystemVerilog

uvm_put_port #(txn_a) ff;

ff = new("ff",this);

txn_b bb;

bb = new("bb")

ff.put(bb);

^^^ Syntax Error

Python

ff=uvm_put_port("ff",this);

bb = TxnB("bb")

ff.put(bb);

Parameters lead to pain

unsigned short AA;

unsigned float BB;

AA = BB;

^^^^ lost data

AA

BB BB BB BB

AA

Typed Language copies data

AA = BB

AA = 6000

BB = 1600.00

BB

AA 6000

1600.00

BB

AA 6000

1600.00

Python copies handles

int

float

Page 6: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Forgiveness Instead of Permission

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

• Duck Typing

• If it walks like a

duck

• talks like a duck

• walks like a duck…

int ii;

uvm_get_port#(duck) duck_p;

ii = duck_p.get();

Permission Denied! Syntax Error

pp.put(100)

ii = duck_p.get()

ii.migrate()

-------------------------------------------------

AttributeError

<ipython> in <module>

7 pp.put(11)

8 ii = duck_p.get()

----> 9 ii.migrate()

AttributeError: 'int' object has no attribute 'migrate' Clearly not a duck.

Page 7: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

pyuvm Implementation

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 8: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Introducing pyuvm

UVM 1.2 IEEE Specification

Rules for Implementation

• Implement common features

• Ignore rarely-used features

• Follow spelling in spec

• uvm_test vs UvmTest

• Don’t reimplement Python

• copy.deepcopy() vs. do_copy()

• __str__() vs convert2string()

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

% pip install pyuvm

from pyuvm import *

Available on pypi.org

Equivalent to import uvm_pkg::*

class AluTest(uvm_test):

def run_phase(self):

self.raise_objection()

seqr = ConfigDB().get(self, "", "SEQR")

seq = AluSeq("seq")

seq.start(seqr)

time.sleep(1)

self.drop_objection()

uvm_root().run_test("AluTest")

Real UVM Behavior

Page 9: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Your UVM on Python

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class AluAgent(uvm_agent):

def build_phase(self):

super().build_phase()

if self.active():

self.driver = Driver.create("driver", self)

try:

self.is_monitor = ConfigDB().get(self, "", "is_monitor")

except UVMConfigItemNotFound:

self.is_monitor = True

if self.is_monitor:

self.cmd_mon = Monitor("cmd_mon", self, "get_cmd")

self.result_mon = Monitor("result_mon", self, "get_result")

UVM Underscore Class Names

No macros. Automatically in the factory

No phase arguments

Simplified factory access

Simplified

configDB access

Python exceptions simplify code

Page 10: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

1.2 Notes

5 Base Classes uvm_object does not capture transaction timing information

6 Reporting Classes Leverages logging, controlled using UVM hierarchy

8 Factory Classes All uvm_void classes automatically registered

9 Phasing Simplified to only common phases. Supports objection system

12 UVM TLM Interfaces Fully implemented

13 Predefined Component Classes Implements uvm_component with hierarchy, uvm_root

singleton,run_test(), simplified ConfigDB, uvm_driver, etc

14

15

Sequences, sequencer,

sequence_item

Refactored sequencer functionality leveraging Python language

capabilities. Simpler and more direct implementation

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Implemented Sections

Page 11: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Ignored UVM Features

Custom UVM Phasing

• Only runs with common UVM phases

uvm_resource_db

• Implements uvm_config_db interface to

uvm_resource_db

_imp classes

• Unneeded because of multiple inheritance

Report handlers

• Leverage Python logging instead

Synchronization classes

Container Classes

Recording classes

Transaction recording

Policy classes

Register layer and model

• Good open-source project

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 12: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Using the Factory without Incanations

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

function void build_phase(uvm_phase phase);

driver_h = driver::type_id::create("driver_h",this);

coverage_h = coverage::type_id::create ("coverage_h",this);

scoreboard_h = scoreboard::type_id::create("scoreboard_h",this);

SystemVerilog UVM

Python UVM

def build_phase(self):

self.driver = Driver.create("driver", self)

self.coverage = Coverage.create("coverage", self)

self.scoreboard = Scoreboard.create("scoreboard", self)

Page 13: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Simplified singleton implementation. No type parameters

• No uvm_resource_db

• Directly implement uvm_config_db interface

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

The Python ConfigDB

config_db#(uvm_sequencer)::set(null, "*", "SEQR", seqr)

if(!uvm_config_db #(uvm_sequencer)::get(this, "","SEQR",seqr))

`uvm_fatal("Could not find sequencer") # Error out if not there

ConfigDB().set(None, "*", "SEQR",self.seqr)

self.seqr = ConfigDB().get(self, "", "SEQR") # Automatically errors out

SystemVerilog UVM

Python UVM

Page 14: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Threads in Python

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

SystemVerilog barbarously

kills thread without warning

Python requires mechanism

for threads to put their affairs

order

Blocking get() functions

must exit.

class UVMQueue(queue.Queue):

#### In __init__()

self.end_while_predicate = ObjectionHandler().run_phase_complete

self.sleep_time = 0.1

####

def get(self, block=True, timeout=None):

if not block or timeout is not None:

try:

return super().get(block, timeout)

except queue.Empty:

raise

else: # create block that can die

while not self.end_while_predicate():

try:

datum = super().get(block=True,timeout=self.sleep_time)

return datum

except queue.Empty:

pass

sys.exit() # Kill thread if it's time to die

Page 15: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Phasing Refactored

Only implement UVM "common phases"

with default phase progression

• Common phases defined in UVM 1.2 Spec

Section 9.8.1

traverse runs phases top down and bottom

up.

Custom phases not implemented

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

uvm_common_phases = [

uvm_build_phase,

uvm_connect_phase,

uvm_end_of_elaboration_phase,

uvm_start_of_simulation_phase,

uvm_run_phase,

uvm_extract_phase,

uvm_check_phase,

uvm_report_phase,

uvm_final_phase]

class uvm_topdown_phase(uvm_phase):

@classmethod

def traverse(cls, comp):

...

class uvm_build_phase(uvm_topdown_phase, common_phase):

...

Page 16: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Python Logging replaces UVM Reporting

Loggers generate messages

Logging levels filter messages

Logging handlers output messages

• Screen, files, html, etc

Logging formatters format messages

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Level Numeric

value

CRITICAL 50

ERROR 40

WARNING 30

INFO 20

DEBUG 10

FIFO_DEBUG 5

NOTSET 0

pyuvm addition

Page 17: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Using Logging

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class LogComp(uvm_component):

def run_phase(self):

self.raise_objection()

self.logger.debug("This is debug")

self.logger.info("This is info")

self.logger.warning("This is warning")

self.logger.error("This is error")

self.logger.critical("This is critical")

self.logger.log(FIFO_DEBUG, "This is a FIFO message")

self.drop_objection()

DEBUG: <src_file>(6)[uvm_test_top.comp]: This is debug

INFO: <src_file>(7)[uvm_test_top.comp]: This is info

WARNING: <src_file>(8)[uvm_test_top.comp]: This is warning

ERROR: <src_file>(9)[uvm_test_top.comp]: This is error

CRITICAL: <src_file>(10)[uvm_test_top.comp]: This is critical

FIFO_DEBUG: <src_file>(11)[uvm_test_top.comp]: This is a FIFO message

Every component has self.logger

pyuvm formatter looks like UVM format (no message_id)

Page 18: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Controlling Logging

uvm_report_object

• set_logging_level(logging_level)

• add_logging_handler(handler)

• StreamHandler—Prints to sys.stdout and sys.stderr

• FileHandler—Writes to a File

• NullHandler—NOP for libraries.

• set_formatter_on_handlers(formatter)

uvm_component

• set_logging_level_hier(logging_level)

• add_logging_handler_hier(handler)

• set_formatter_on_handlers_hier(formatter)

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

As with SystemVerilog call logging control in end_of_elaboration_phase

Page 19: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Example of Python UVM The TinyALU Cocotb Testbench

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 20: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

TinyALU Example

Python testbench developed with no simulator

Simulator testbench developed with cocotb

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Cocotb Proxy with BFMS

Page 21: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Python and Simulation Have Same Proxy Interface

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class CocotbProxy:

def __init__(self, dut, label):

self.dut = dut

ConfigDB().set(None, "*", label, self)

self.driver_queue = UVMQueue(maxsize=1)

self.cmd_mon_queue = UVMQueue(maxsize=0)

+++

class PythonProxy(uvm_component):

def __init__(self, name, parent, label):

super().__init__(name, parent)

ConfigDB().set(None, "*", label, self)

+++ proxy.send_op(aa, bb, op)

cmd = proxy.get_cmd()

result = proxy.get_result()

Blocking API

maxsize = 0 means infinite size

Page 22: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Monitor

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class Monitor(uvm_component):

def __init__(self, name, parent, method_name):

super().__init__(name, parent)

self.method_name = method_name

def build_phase(self):

self.ap = uvm_analysis_port("ap", self)

def connect_phase(self):

self.proxy = self.cdb_get("PROXY")

def run_phase(self):

while not ObjectionHandler().run_phase_complete():

get_method = getattr(self.proxy, self.method_name)

datum = get_method()

self.ap.write(datum)

def build_phase(self):

self.cmd_mon = Monitor("cmd_mon", self, "get_cmd")

self.rslt_mon = Monitor("rslt_mon", self, "get_result")

Python allows us to

pass the name of

the monitoring

function as a string.

Page 23: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Cocotb Results Monitor BFM

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

async def result_mon_bfm(self):

prev_done = 0

while True:

await FallingEdge(self.dut.clk)

try:

done = int(self.dut.done)

except ValueError:

done = 0

if done == 1 and prev_done == 0:

self.result_mon_queue.put_nowait(int(self.dut.result.value))

prev_done = done

def get_result(self):

return self.result_mon_queue.get() A blocking get

Page 24: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Functional Coverage

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class Coverage(uvm_subscriber):

def end_of_elaboration_phase(self):

self.cvg = set()

def write(self, cmd):

self.cvg.add(cmd.op)

def check_phase(self):

if len(set(Ops) - self.cvg) > 0:

self.logger.error(f"Functional coverage error. Missed: {set(Ops)-self.cvg}")

No covergroup in Python. So, create set of all ops and set of seen ops.

Then subtract to find missed coverage

Page 25: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Sequence Item

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class AluSeqItem(uvm_sequence_item):

<snip __init__>

def __eq__(self, other):

same = self.A == other.A and self.B == other.B and self.op == other.op

return same

def __str__(self):

return f"{self.get_name()} : A: 0x{self.A:02x} OP: {self.op.name} "

f"({self.op.value}) B: 0x{self.B:02x}"

def randomize(self):

self.A = random.randint(0,255)

self.B = random.randint(0,255)

self.op = random.choice(list(Ops))

Here we replace do_compare() and convert2sring() with Python equivalents

Page 26: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Base ALUTest

Instantiate the environment

Set logging level to DEBUG

Raise and drop objections and run sequence

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class AluTest(uvm_test):

def build_phase(self):

self.env = AluEnv.create("env", self)

def end_of_elaboration_phase(self):

self.set_logging_level_hier(logging.DEBUG)

def run_phase(self):

self.raise_objection()

seqr = ConfigDB().get(self, "", "SEQR")

seq = AluSeq("seq")

seq.start(seqr)

time.sleep(1)

self.drop_objection()

Page 27: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Python and Cocotb Tests Extend AluTest

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

class PythonAluTest(AluTest):

def build_phase(self):

_ = PythonProxy("model_proxy", self, "PROXY")

super().build_phase()

class CocotbAluTest(AluTest):

def final_phase(self):

cocotb_proxy = self.cdb_get("PROXY")

cocotb_proxy.done.set()

• Instantiate a Python Proxy

• Store it at "PROXY"

• Notify cocotb that the test is

finished using the proxy

if __name__ == "__main__":

uvm_root().run_test("PythonAluTest") % python tinyalu_uvm.py

Page 28: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Cocotb Test

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

@cocotb.test()

async def test_alu(dut):

clock = Clock(dut.clk, 2, units="us")

cocotb.fork(clock.start())

proxy = CocotbProxy(dut, "PROXY")

await proxy.reset()

cocotb.fork(proxy.driver_bfm())

cocotb.fork(proxy.cmd_mon_bfm())

cocotb.fork(proxy.result_mon_bfm())

await FallingEdge(dut.clk)

test_thread = threading.Thread(target=run_uvm_test,

args=("CocotbAluTest",), name="run_test")

test_thread.start()

await proxy.done.wait()

await FallingEdge(dut.clk)

cocotb runs test

cocotb drives clock

Instantiate cocotb proxy

stores itself in ConfigDB()

Use cocotb.fork to launch

BFMS

Wait for them to start

Launch UVM test in thread

Wait for thread to notify of

completion and wait one clock

to let it finish

Page 29: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Run the sim with Cocotb

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

0.00ns INFO cocotb __init__.py:229 in _initialise_testbench Seeding

Python random module with 1610296863

0.00ns INFO cocotb.regression regression.py:127 in __init__

Found test tinyalu_cocotb.test_alu

0.00ns INFO cocotb.regression regression.py:459 in _start_test

Running test 1/1: test_alu

0.00ns INFO cocotb.test.test_alu.0x7fe84e6e4730 decorators.py:255 in _advance

Starting test: "test_alu"

Description: None

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: 4e OP: ALUOps.XOR (3) B: 71 = 003f

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: 1d OP: ALUOps.XOR (3) B: 66 = 007b

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: b8 OP: ALUOps.ADD (1) B: d4 = 018c

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: 28 OP: ALUOps.AND (2) B: b6 = 0020

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: c6 OP: ALUOps.XOR (3) B: 99 = 005f

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: 84 OP: ALUOps.ADD (1) B: 5b = 00df

INFO: tinyalu_uvm.py(204)[uvm_test_top.env.agent.sb_h]: Test passed: A: 72 OP: ALUOps.MUL (4) B: 98 = 43b0

Page 30: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Next Steps

Available on pypi.org

• % pip install pyuvm

Open Source Project on Github:

• https://github.com/pyuvm/pyuvm

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA

Page 31: Verification Learns a New Language...The SystemVerilog Assumption A structured testbench is only software making function calls through a proxy The UVM assumes the "software" is written

Contact Published by Siemens 2021

Ray Salemi

Aerospace and Defense and FPGA Solutions Manager

Division (IC Verification Solutions)

E-mail [email protected]

© Siemens 2021 | DVClub Europe 2021 | Siemens EDA