Some time back I, like other people before me, had the realization that doing verification is a lot like doing software programming. Modern hardware verification languages (HVLs) like SystemVerilog and e were conceived with this idea in mind, but many people didn't get the memo yet.
Now, like most other people in my field, I'm not a trained software engineer. I don't have a computer science background. I am at most a hobby programmer.
I started out with SystemVerilog back in 2009, when it was getting more popular. As an electrical engineer, I just knew how to write code that did the job, but was nothing fancy. Since then I've had the chance to do some more software development in Java and C++. This opened me up to a much bigger world and made me decide that I wanted to improve my code writing skills. There were many dimensions in which to improve: flexibility, performance, readability, etc.
I decided that the first one I wanted to improve is the one that is most often overlooked: correctness. I was stuck in a continuous loop of write, see it fail later, fix it, see if fail later (maybe somewhere else), and so on... This had gotten me pretty frustrated, but this is the way everybody around me was doing it so I didn't think there was a better way. This made me realize that the development process is as important as the code. You could have the cleanest, most extensible code, but it's equal to 0 if it doesn't work as it should. Even if you do eventually manage to also get it working, you will have wasted a lot of effort doing it.
Fortunately, when I decided I wanted to improve my development skills, Neil Johnson had already started AgileSoc.com. He was challenging the age old idea that the person who writes the code shouldn't also test the code. This idea is so ingrained in the minds of hardware developers that they believe it to be the panacea of chip design. His scope is broader than just verification code. He envisions a future where designers test their own code before committing it to be thoroughly verified. He was right though, the code I wrote ended up being tested by me anyway, just at a later point in time (when I would have mostly forgotten what it was supposed to do and how it was supposed to work).
Neil is a firm believer in test driven development (TDD). The idea behind TDD is to write the tests before the production code. You should test it when you write it because that's when you're in the zone. TDD goes hand in hand with unit testing, that is testing at the smallest possible level. He developed SVUnit to empower unit testing and TDD for SystemVerilog. I was in SystemC mode when I first read about it and afterwards I switched to e so I didn't get a chance to try it out then.
Late last year I got a break between projects and I was assigned to do some work to support my colleagues using SystemVerilog. We were developing some new VIPs from basically scratch. This was the chance to use SVUnit and put my money where my mouth was.
Well, we engineers are a strange bunch, aren't we? We like to tinker with new technologies, but make us do something differently than we're used to and you'll see that at the same time we hate change. I was afraid a bit. I was worried that by doing the switch to unit testing it would hamper my productivity. "In the end, how easy can it be? If it were so easy, then everyone would be doing it, right?", I thought. Because of this I put if off for a couple of weeks.
Eventually, I finally gathered the courage to download SVUnit and install it. As real men don't look at the example (until maybe later), I fired it up and created a test for a class I was working on that week. A call to a script here, a file generated there, a few lines of code in the new file and bam! a unit test. "Wow, that was way easier that I thought", I said to myself. Neil did a great job in automating a lot of things and letting the user worry about writing his tests and not the infrastructure. I won't talk about how to use SVUnit in this post. There are plenty of resources on the AgileSoc.com site on how to get started.
I started out slowly without much discipline. Sometimes I wrote the code first and then tested it. Other times I gave TDD a try and wrote the tests first, watched them fail and then wrote the code. I did end up having most of my code (and a lot of code written by my colleagues) unit tested. I didn't just rely on unit testing, though. I also did integration testing of the entire VIPs to emulate them working in the field, which did show some problems. Nevertheless, unit testing provided a granularity that I couldn't have easily achieved when debugging in the field because there's just too much other stuff going on in the background and because I had limited controllability.
Now the big question: "Was it all worth it in the end?". I like to think so. We had a much smoother ramp-up of our new VIPs after putting them to use in real projects. New feature requests came, we found performance problems with some pieces of code and also some bugs, but having the unit tests made refactoring much easier and they gave us more confidence in the code. It's also not an "either/or" approach as I thought in the beginning; you can use unit testing and also do stuff without unit testing as well (where it's too much effort for example). Also keep in mind that it's not a magic bullet that will solve all of your problems. Just because the parts are working properly, doesn't mean that the whole machine does as well, so you do need integration testing as well.
SVUnit did wet up the e guys' appetite as well, and Cadence didn't disappoint by releasing eUnit last year. Once I switch to e mode again this summer, I'll definitely give that a try as well.
If you do SystemVerilog development, I urge you to give unit testing and SVUnit a try. Make your code work first and make it fancy second!
Thanks for reading and see you next time!