{"id":16786,"date":"2022-01-14T10:04:49","date_gmt":"2022-01-14T15:04:49","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=16786"},"modified":"2026-03-27T08:48:19","modified_gmt":"2026-03-27T12:48:19","slug":"odds-and-ends","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2022\/01\/14\/odds-and-ends\/","title":{"rendered":"Odds and Ends"},"content":{"rendered":"\n<p>I hope that the <a href=\"https:\/\/verificationacademy.com\/news\/the-python-for-verification-series\" target=\"_blank\" rel=\"noopener\">Python for Verification Series<\/a> has demonstrated that Python is a new tool in the verification team\u2019s toolbox. We can now write complete UVM testbenches in Python using <strong>pyuvm<\/strong> and connect them to the simulator using <strong>cocotb<\/strong>. Python as a verification language explodes the ecosystem at a verification engineer\u2019s fingertips while making it easier to hire engineers who know the team\u2019s language (Python) immediately.<\/p>\n\n<p>This final blog post in the series discusses odds and ends that may have gotten little attention in the blog posts or may not have been invented when the blog post was written. <\/p>\n\n<h2>Python and SystemVerilog<\/h2>\n\n<p>Verification falls into a deeply committed relationship with every language it meets. You can look across the verification landscape and find old friends such as VHDL, Verilog, SystemC, <em>e<\/em>, and C++. Our industry will likely add Python to that list, using it on projects where it does the most good.<\/p>\n\n<p>SystemVerilog is still the best way to define complicated randomization constraints and functional coverage bins. Python needs to take advantage of what SystemVerilog has to offer.<\/p>\n\n<p>Siemens EDA has a skunkworks project named SVConduit that allows engineers to define objects using YAML and then pass those objects between SystemVerilog and Python using <code>put()<\/code> and <code>get()<\/code> operations. Python uses <code>get()<\/code> to retrieve a randomized transaction and <code>put()<\/code> to store functional coverage.<\/p>\n\n<p>SVConduit is an example of how SystemVerilog will remain relevant in the future. Contact your Siemens EDA AE if you\u2019d like the SVConduit source code.<\/p>\n\n<h2>pyuvm changes to run_test()<\/h2>\n\n<p><strong>pyuvm<\/strong> changes the <code>run_test()<\/code> task in several ways, starting with the fact that you use the <code>await<\/code> keyword to start your test.<\/p>\n\n<pre><code>await uvm_root().run_test(&quot;MyTest&quot;)<\/code><\/pre>\n\n<h3>Passing classes to run_test()<\/h3>\n\n<p>The string in the above call raises another change. <strong>pyuvm<\/strong> slavishly copied the SystemVerilog UVM\u2019s use of a string to hold the test name. There is no need to do that in Python as we can pass the class directly. This also enables error checking for misspellings. So now we can do this without the string:<\/p>\n\n<pre><code>await uvm_root().run_test(MyTest)<\/code><\/pre>\n\n<h3>pyuvm does not need uvm_test<\/h3>\n\n<p>Python has no typing, so <strong>pyuvm<\/strong> does not need <code>uvm_test<\/code>, though it implements it to follow the standard. Here is the <code>uvm_test<\/code> implementation. It is an empty extension:<\/p>\n\n<pre><code># 13.2 \nclass uvm_test(uvm_component):\n    &quot;&quot;&quot;\n        The base class for all tests\n    &quot;&quot;&quot;<\/code><\/pre>\n\n<p>This means we could pass a <code>uvm_component<\/code> class to <code>run_test()<\/code>, and it would work with no problem.<\/p>\n\n<h3>Keeping singletons<\/h3>\n\n<p>The SystemVerilog UVM built and ran a single UVM testbench per simulation run. <strong>cocotb<\/strong> allows you to store many tests in one Python file and run a different <strong>pyuvm<\/strong> test in each of them.<\/p>\n\n<p>This feature was broken before version 2.6 because the singletons in one test carried over to the next test. For example, the <code>ConfigDB()<\/code> would keep data from the previous test.<\/p>\n\n<p>Starting in 2.6, <code>run_test()<\/code> clears all singletons except the <code>uvm_factory()<\/code>. It clears the overrides in <code>uvm_factory()<\/code>. You can keep the singletons by using the <code>keep_singletons<\/code>argument:<\/p>\n\n<pre><code>uvm_root().run_test(keep_singletons=True)<\/code><\/pre>\n\n<p>This argument will also keep the existing factory overrides. You can clear them explicitly using <code>uvm_factory().clear_overrides()<\/code>.<\/p>\n\n<p>If you want to keep data between calls to <code>run_test()<\/code> you store it in one or more singletons, and tell <code>run_test()<\/code> to keep them using <code>keep_set<\/code>. For example, you may keep persistent data in a singleton class named <code>GlobalData<\/code><\/p>\n\n<pre><code>uvm_root().run_test(MyTest, keep_set=set([GlobalData])<\/code><\/pre>\n\n<p>This will clear all the singletons but <code>GlobalData<\/code><\/p>\n\n<h2>Enabling deep UVM log messages<\/h2>\n\n<p>The Python <strong>logging<\/strong> module defines logging levels. A message is more likely to be logged if its logging level is high. The default logging levels range from <code>CRITICAL<\/code> (50) to <code>DEBUG<\/code> (10). <\/p>\n\n<p><strong>pyuvm<\/strong> adds two logging levels below <code>DEBUG<\/code>: <code>FIFO_DEBUG<\/code> (5) and <code>PYUVM_DEBUG<\/code> (4). Setting a FIFO\u2019s logging level to <code>PYUVM<\/code> will log all the activity in the FIFO. It is useful if your testbench is hanging.<\/p>\n\n<p>The <code>PYUVM_DEBUG<\/code> level will become more verbose over time as there is more need to print UVM debug messages.<\/p>\n\n<h3>Changing the default logging level<\/h3>\n\n<p><strong>pyuvm<\/strong> sets logger objects to the <code>INFO<\/code> logging level by default. You can change that default before awaiting <code>run_test()<\/code>:<\/p>\n\n<pre><code>uvm_report_object.set_default_logging_level(DEBUG)\nuvm_root().run_test(MyTest)<\/code><\/pre>\n\n<h2>pyuvm does not need uvm_subscriber<em>\n<\/em><\/h2>\n\n<p>The SystemVerilog UVM provides the <code>uvm_subscriber<\/code> class as a convenience class. <code>uvm_subscriber<\/code> creates an <code>analysis_export<\/code> with the correct parameterized type and links it to the <code>write()<\/code> function. One could code this manually, and one does to have multiple <code>analysis_export<\/code> objects in a single subscriber, such as a scoreboard.<\/p>\n\n<p>Python doesn\u2019t have typing issues, so a programmer can create a subscriber by directly extending <code>uvm_analysis_export<\/code> and providing the <code>write()<\/code> function.<\/p>\n\n<p>This is the same procedure as using <code>uvm_subscriber<\/code>, except you can pass an object that extends <code>analysis_export<\/code> directly to the <code>connect()<\/code> function.<\/p>\n\n<p>Here is an example. We define <code>Adder<\/code> by extending <code>uvm_analysis_export<\/code> and instantiate it in the test. Then we pass the instantiated adder (<code>self.sum<\/code>) directly to the <code>ap.connect()<\/code> function:<\/p>\n\n<pre><code>class Adder(uvm_analysis_export):\n    def start_of_simulation_phase(self):\n        self.sum = 0\n\n    def write(self, nn):\n        self.sum += nn\n\n    def report_phase(self):\n        self.logger.info(f&quot;Sum: {self.sum}&quot;)\n\n\nclass AdderTest(uvm_test):\n    def build_phase(self):\n        self.num_gen = NumberGenerator(&quot;num_gen&quot;, self)\n        self.sum = Adder(&quot;sum&quot;, self)\n\n    def connect_phase(self):\n        self.num_gen.ap.connect(self.sum)<\/code><\/pre>\n\n<h2>Summary<\/h2>\n\n<p>This blog post examined how <strong>pyuvm<\/strong> is different from the SystemVerilog UVM. I hope it becomes a valuable tool in the verification engineer\u2019s toolbox.<\/p>\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>I hope that the Python for Verification Series has demonstrated that Python is a new tool in the verification team\u2019s&#8230;<\/p>\n","protected":false},"author":74314,"featured_media":16788,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[1],"tags":[989,902,971,787,788,819],"industry":[],"product":[],"coauthors":[947],"class_list":["post-16786","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","tag-cocotb","tag-python","tag-pyuvm","tag-uvm","tag-uvm-1-2","tag-verification"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2022\/01\/lego-blocks.jpeg","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/users\/74314"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=16786"}],"version-history":[{"count":3,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16786\/revisions"}],"predecessor-version":[{"id":16961,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16786\/revisions\/16961"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/16788"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=16786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=16786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=16786"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=16786"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=16786"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=16786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}