Showing posts with label Verilog. Show all posts
Showing posts with label Verilog. Show all posts

Friday, February 1, 2008

The Big Green Button




The Holy Grail of EDA has been the ability to go directly from an abstracted version of the design (such as RTL or System C) to the physical implementation, that is GDSII.

The result is that many players in the chip design business are hawking their own canned methodologies or flows. The idea is that you can take a fairly junior engineer, put him in front of the terminal, and tell him to push the "Big Green Button". It reads in the RTL and in just a few hours the completed physical design pops out the other end.


There are two main problems with this idea. The first is that very few designs are "typical". There tend to be issues that are specific to any particular design that require unique attention. Therefore, it is very difficult to construct the tool that will handle all cases.

If this was the only problem, it would be OK for the tools team on any given project to spend an inordinate amount of time solving it. But the second big issue deals with the fact that the effort to create the Big Green Button actually makes using the tools more difficult. Specifically, the "environment" generally abstracts the user from the tools he is using. Now the poor soul trying to implement the design needs to not only know what he wants the tools to do, but he needs to know how to make the environment make the tool do what he wants it to do.

What do I mean? Let's talk about something simple like trying to read the RTL into the synthesis tool. If you were driving the tools, you would know that the tcl command read_verilog does a pretty good job of reading Verilog into Design Compiler. One company I worked with did not want you to touch the scripts; therefore you needed to call a perl script to run the tcl to read the Verilog. Not a big deal, but it is a level of unnecessary abstraction.


I worked on another project, building an environment, and the process of reading in a Verilog file called a pointer that pointed to a pointer, ad nauseam. By the time the process was over, there were 13 levels of indirection to get to the Verilog file. It may have made sense to the developer, but it was a little difficult for the user to understand what was going on.


This brings us to fact that tools vendors tend to document their tools pretty well. The environment development team seldom does. As a result, not only is your job more difficult, there is no easy way to find out what needs to be done.

In my opinion, a good tool flow is a directory structure, a set of scripts, and a method to reliably rerun the scripts. It should allow the designer to be able to experiment with a myriad of strategies to complete the required tasks. The tool flow should not abstract the designer from the tools themselves.

Maybe some day, the tools will be so sophisticated that they will not require much human intervention. They are not there yet.

Wednesday, August 1, 2007

It Ain't Really Software

To a certain extent, Integrated Circuit designers these days are really software designers. They enter code (RTL) that gets compiled. They write code (C, System C, Verilog, VERA, whatever) to verify the funtionality of the RTL. The people who do the compilation, that is the implementation, write all sorts of scripts to make it happen.

The big difference between the software and hardware jobs is what happens to the fruit of your labors. For a software person, the result is virtual. There are bits whose existence is fleeting and abstract. The hardware person creates something that is solid and tangible. For a software designer, software is the goal. For a hardware designer, software is the means to a goal.

Because the results are so much different, so are the requirements. Nothing makes me feel more secure in my job than an engineer that makes the statement something like: "It simulates, therefore it must work." I have heard mutterings like this on several occassions.

One of the more interesting of these types of events happened some number of years ago when an engineer came to me with an issue. Specifically, he had coded a 46-bit accumulator. He had then synthesized this accumulator in a 130 nm process. The accumulator did not resolve in 1ns. What should he do? I then suggested that there was no way he could design a 46 bit accumulator to resolve in 1ns, and that he would have to pipeline the operation. He didn't have a clue about pipelining.

Then he asked the question that was really bugging him: "Why didn't the Verilog simulator tell me there was an issue?" I tried to explain that RTL is merely a functional representation of hardware. It does NOT contain timing information. You have to have a feel for what the RTL is going to create. I don't know how you develop that expertise, except for practice. He went away unconvinced and irritated, because, after all, it had simulated, therefore it ought to have worked.



I have had the opportunity to see a handful of ugly RTL implementations in the past. These are a few.



Three-state mess:

I once was exposed to a piece of code in which the author was trying to implement a multiplexer function. The operation looked something like:

assign out = (sel == 0) ? in1 : 8'hzz;

assign out = (sel == 1) ? in2 : 8'hzz;

assign out = (sel == 2) ? in3 : 8'hzz;

assign out = (sel == 3) ? in4 : 8'hzz;

Given that select is a 2 bit vector, I have functionally created a four input mux. What got synthesized into hardware is a three-state bus, with 4 drivers on each net. (Just for the record, the case that I saw in real code was a lot bigger that this). Not only is the implementation huge, because typically three state drivers are big, to drive big busses, but there isn't really any improvement that can be made via synthesis, because synthesis tools do not usually touch three-state buses.

Lesson: Anytime a "Z" appears in your RTL, be very cautions.


Magnitude vs. Equality:

I once ran accross a huge compare function. Ultimately the coder was trying to determine if a data bus ever equaled any of several preset values. He coded something that looked like this:

(Oh, for the record, the "or" signs keep disappearing from my html. Imagine they are there between terms).



assign hit = ((in > 6) & (in <9))

((in > 8'h17) & (in < 8'h1a))

((in > 8'h26) & (in < 8'h29))

((in > 8'h35) & (in < 8'h38))

((in > 8'h44) & (in < 8'h47))

((in > 8'h53) & (in < 8'h56))

((in > 8'h62) & (in < 8'h65))

((in > 8'h71) & (in < 8'h74))

((in > 8'h80) & (in < 8'h83))

((in > 8'h9f) & (in < 8'ha2))

((in > 8'hae) & (in < 8'hb1))

((in > 8'hbd) & (in < 8'hc0))

((in > 8'hcc) & (in < 8'hcf))

((in > 8'hdb) & (in < 8'hdd))

((in > 8'hea) & (in < 8'hed))

((in > 8'hfc) & (in < 8'hfe));



For the record there were hundreds of compares in the real code. The problem with this code is that magnitude compares are fairly complex things. They require a carry or borrow operation that forces each bit in the compare to interact with each other bit. If you are using design compiler, it goes out and grabs a Design Ware component for each compare. In order to optimize this code, it does something called resource sharing. This is compute intensive.

I suggested that the designer replace his code with something like the following:



assign hit = ((in == 7) (in == 8)

(in == 8'h18) (in == 8'h19)

(in == 8'h27) (in == 8'h28)

(in == 8'h36) (in == 8'h37)

(in == 8'h45) (in == 8'h46)

(in == 8'h54) (in == 8'h55)

(in == 8'h63) (in == 8'h64)

(in == 8'h72) (in == 8'h73)

(in == 8'h81) (in == 8'h82)

(in == 8'ha0) (in == 8'ha1)

(in == 8'haf) (in == 8'hb0)

(in == 8'hbe) (in == 8'hbf)

(in == 8'hcd) (in == 8'hce)

(in == 8'hdc)

(in == 8'heb) (in == 8'hec)

(in == 8'hfd)) ;



The two sets of code are equivalent logically. (I checked with a formal verification tool). I ran it in design compiler to see what the results would be, using a TSMC 130 nm library. I gave it fairly agressive timing goals (300 ps) and set the max area at 0.


Magnitude
comparator result:

  • Area 332
  • Compile time 10 sec
  • Violated timing by 10 ps.

Equality comparator result:

  • Area 228
  • Compile time 5 sec
  • Met timing

I then ran again, using compile_ultra.

Magnitude comparator:

  • Area 240
  • Compile time 33 sec
  • Met timing

Equality Comparator:

  • Area 188
  • Compile time 7 sec
  • Met timing

So, what is the big deal about a few seconds of compile time, or a few square microns. Well, for one thing, the original case that I ran into had hundreds of terms, not the handful I demonstrated here. So compile time that had been hours, became minutes. Secondly, it is a way of thinking. Any time you can make it easier on the tools, you will make things simpler on yourself. If a designer of a large block is conscious of these types of issues, he can make the implementation of that block a lot less painful.

Lesson: You need to understand a little about how your tools think.

Note: You can take this lesson too far. I have known of teams that want to turn all of their code into sum of products to make sure they know what the tool is going to produce. I don't think this is a good return on investment.

Muxing Mess

I was once asked to work on a program that was "almost finished." The team had already put together the Verilog, simulated it to demonstrate that it worked, and synthesized it to prove that it was close to meeting timing. All we needed to do was to do the physical implementation. The problem with this design was that it contained a 64 X 266 bit multiplexer.

This synthesized just fine in Design Compiler, because there are not many levels of logic, and from a statistical wireload perspective, it was not very challenging. The reality of the design however is that multiplexing operations are difficult in standard cells. Big muxes are really difficult, because of the routing issues. So, the design that seemed easy in DC would not converge when we went to the physical tools. The result was that the solution had to be rearchitected, and took several more months of work.



If you want to look at more details, check out:

http://www.designcon.com/infovault/paper.asp?PAPER_ID=87


Lesson: You need to understand the physical ramifications of design decisions.