Meridian RDC:


Meridian RDC is a tool by company called "Real Intent", which does RDC checks. Spyglass by synopsys is other tool that does CDC/RDC checks too. Cadence has their own RDc/CDC checkers.

Install Meridian RDC and then invoke it. Assuming mrdc is the Meridian RDC tool alias:

mrdc -input mrdc.tcl -log mrdc.log -project meridian_project  => we provide i/p file mrdc.tcl which has cmds for all the 4 steps below (instead of -input, we can also use short form -i, and instead of using *.tcl file, we can also use *.rdc file). option -project allows us to dump mrdc internal db into that dir, so that we can restore the old database for debug purpose (tool idebug is used, instead of mrdc. It's invoked as "idebug  -project meridian_project"). option -reset_scenario_mode enables using only reset scenarios instead of groups. So, all cmds use scenarios (scn) in place of group (grp). Total violations in scenario mode is more than in group mode. -reset_scenario_mode will become default in future release.



Steps: All of the tcl cmds are supported in mrdc.

1. design setup => Sets up design for RDC verification. Analyze and elaboarate of RTL done here.


set ri_search_path [list /home/project/ip/src  /home/myblock/rtl ] => optional, setting search path for RTL sources in case we don't provide full path of any rtl file below. There are 100's of meridian var that can be set, look at mrdc manual.
read_liberty [list /home/memory/memory.lib /home/clk_gen/pll.lib ] => optional since we are checking RTL (and not gates), reading in technology specific library cells
analyze -file rtl_file.f -svverilog => analyze all the RTL source files (rtl_file.f is same format as used for any other tool, which has paths of all rtl files, along with any options as "+define+, "-v2k", etc). we can also put options on cmd line as "-svverilog" to enable system verilog
elaborate design_top -black_box [list analog_d2a analog_a2d] => elaborates design with "design_top" as top module. We blackbox blocks that we do not want analyzed or are IP for which there is only verilog model. We can use -auto_black_box to automatically black box any block for which defn is not found, or use -black_box to give list of blocks to black box.

NOTE: elaborate produces internal The database which includes complete description of design. read_design_db cmd can be used to read this database. The name of database can be specified else it's some fixed name (i.e mdrdc.db or something). If we run hierarchical flow for mrdc (discussed later), then we use this elaborate cmd to create db for lower level modules. However, if there are multiple instantiation of this module in top level, then we won't be able to use the same name for different inst of same module. In such scenario, mrdc allows us to create unique db for each such module by having parameter names in name of db. i.e:

elaborate -hier_design_db {dut_block1} => here design db for dut_block1 created with names of all parameter values, i.e for parameter values 1,2,3,4, name=dut_block1-1-2-3-4 where this particular inst of dut_block1 has parameter values 1,2,3,4, similarly for all other parameter values. If -hier_design_db option was not used, then the design db would be named dut_block1 (all such db created under dir meridian_project/dut_block1/dbs/dut_block1-1-2-3-4.db).

read_design_db dut_block1-1-2-3-4 => This cmd used to read the previously created db. So, we don't need to read in all rtl files, we can just read this db for next run. This makes it load design faster. We don't specify dir, as it looks in standard path under project dir (here it's under meridian_project/dut_block1/dbs/)

2. environment setup => optional, needed only if SDC (.sdc) or ENV  (.env) files are already available. SDC is std sdc file, while ENV is native enirnoment file in lieu of sdc. Meridian needs these files to know what signals are clock, primary reset and functional reset. Primary reset are ones that are externally generated, while functional reset are ones that are internally generated (e.g. output of a counter, output of a S/W register, …). Constants should also be provided (i.e jtag_mode is set to 0, etc). Meridian can automatically figure out a lot of this info, and dumps that into a template file for user to review (incase the user doesn't provide the sdc or env file with this info). Any problems found are reported under "SDC_ENV_LINT" Rule group.

There is 1:1 conversion from sdc cmd to env cmd.

SDC: create_clock => ENV: create_clock. create_waveform/create_derived_waveform are used to define a waveform, and then these are used in "create_clock -waveform waveform_1 clk_1" cmd.

SDC: create_generated_clock => ENV: create_clock. create_waveform/create_derived_waveform

SDC: set_case_analysis => ENV: set_constant

SDC: set_input_delay/set_output_delay => ENV: create_input/create_output

ENV: create_reset (no equiv cmd in sdc) => this cmd needed to specify reset. Reset analysis is done in both assertion phase (i.e while reset is active) and de-assertion phase so that initial values are properly set on storage elements (i.e flops, latches, memory) as well as primary inputs for structural or formal analysis.

set_false_path and set_clock_groups are used to determine whether clocks are synchronous or asynchronous.


read_sdc [list /home/mydesign/clock.sdc  /home/mydesign/io.sdc  /home/mydesign/exception.sdc ] => reads in sdc to derive clock information, design boundary relation, and synchronous/asynchronous relationship
#read_env [list /home/mydesign/design_top.env ] => read an existing ENV file to derive design spec. We read either sdc or env file.

 #reset groups => reset group is a set of resets that are activated together during functional operation, along with any mode constraints at the time of activation.  Reset groupings control how checks are created - some checks occur only on resets within a group some checks occur only across groups. A reset domain is a set of flops that become initialized when a "reset group" is asserted. If we don't define reset gropus, then our results will be very noisy, as RDC won't won't know how these resets work with each other. Meridian RDC defines "reset_groups" using the set_reset_group command. However, we use below cmd to create groups automatically. We can also define other characteristics as if clocks are off, when reset is active,
 
create_set_reset_group_scripts -output reset_groups.tcl => rdc reset group definitions. All Primary resets are grouped into 1 group, while each functional reset is grouped into it's own separate group.
source reset_groups.tcl => source above file

An ex of env file:

set_hierarchy_separator . => here . is set as hier separator (Default is /)

create_waveform -period 10 -transition {0 5} CLKA_W
create_waveform -period 10 -transition {0 5} CLKB_W
create_clock -waveform CLKA_W clkA => creates clk on clkA pin/port/net with waveform CLKA_W
create_clock -waveform CLKB_W clkB

create_reset -interval 10 -low -async {reset_n} => specifies "reset_n" is primary reset (default), and is active low. -interval specifies the length the reset to be held active and should be set to lowest possible length (i.e. number of clock periods) that meets the design requirements. Here, it's set to 10 clk cycles. We can also specify waveform of reset pin using -waveform, but most of the times it's not needed, as it's simple state change. -async specifies that the waveform of this reset is to be automaticaly generated by the tool and is async to all other waveforms (generally true). -waveform and -async are mutually exclusive, so only 1 of them should be used.

create_reset -functional -low [get_object_name mod1/sync2/Q] => specifies sync2/Q is an internal reset, which is active low (by default it's active high)

create_input -async {PI_7} => associates waveforms for primary i/p. However, when we don't want to specify a waveform using -waveform, we use -async to indicate that waveform on this object is to be automatically created by the tool, and should be async to receiver (i.e capture clock waveform).

create_input -waveform CLKA_W {PI_1} =>Here we specify a waveform on PI_1.


set_constant -value 1’b0 jtag_pin_1 => All remaining i/p ports are assigned constant values (instead of waveforms)
set_constant -value 1’b1 mod1.gmi_mode => constant can also be set on internal nets and pins.

set_initial_value -interval 10 -value 1'b0 PI_3 => sets initial value on an i/p or inout port for specified interval. At end of interval, signal can take any value at any interval of time (independent of clk edge). This cmd is useful for design inittialization, but is seldom used, as usually we have waveform specified on i/p pin (clk and reset pins are enough)

set_stable_value PI_EN => makes a given port or net's value unchanged from first value that it gets. Thus it's different than above cmd, as we do not specify it's value, but is derived based on deign. After that, the value doesn't change. Thus this cmd excludes given signal from verification, as the signal remains stable, so is not verified during reset analysis. Used frequently for dft signals to cut down on unnecessary noise in results

 set_reset_scenario -name rst_scenario_1  { {reset_n {reset {@t0 0 ->t1} }} {reset_core {reset {@t1 1} }} } => this cmd is used to define resets that work together with other constraints. One command per scenario is needed. While processing a reset scenario, the resets are asserted and de-asserted as specified in the scenario. All reset signals that are not specified in the reset scenario being processed are considered to be in an unknown state (i.e. X). Here, we give the scenario a name "rst_scenario_1". Then we specify the behaviour of reset signals in this scenario. We specify behaviour of each reset signal. Any reset signal not defined in this scenario has a value of X. Here 2 reset signals: reset_n and reset_core are specified with thier behaviour. PI reset_n is specified as reset signal (signal can be either reset or constraint type), @t0 indicates an event at time 0, when the signal "reset_n" changes from x to 0. Arrow -> defines this event (when reset_n changes from x to 0) as t1, so that it can be used in other reset scenarios. Similarly PI reset_core is specified as changing from x to 1 at time t1 (which happens to be time 0). Other special characters as ^, v, # and $ are also used to specify delays. First edge of reset signal is treated as an assertion of reset for metastability checks. Subsequent edge of reset signal is treated as deassertion, but it doesn't matter for metastability checks as deassertion do not start metastability. We can have as many reset scenarios as we want by specifying "set_reset_scenario" multiple times.

set_rdc_false_path -from_scenario rst_scenario_1 => false path from specified scenario to all other. So, no RDC violations from scenario "rst_scenario_1" will be reported.

3. analyze intent => This step checks for correctness of spec provided in setup files. If step was not run, then an env file is created automatically via this cmd.

analyze_intent => all spec such as clocks, resets etc checked. Any problems reported under "MRDC_SETUP_CHECKS" Rule group

4. verify rdc => This is the step that does RDC verification of design.
verify_rdc => rdc structural analysis. Any problems reported under "MRDC_ANALYSIS_CHECKS" Rule group

#verify_rdc -db_model dut_block1-1-2-3-4 => When run with option -db_model, mrdc creates a reduced db with name=dut_block1-1-2-3-4, that doesn't have all design, but only that part that is needed to efficiently run rdc on this block. This is needed when we are running hierarchical flow (discussed below), which uses this lower level reduced db.

#read_rdc_db -block dut_block1-1-2-3-4 -name dut_block1-1-2-3-4 => This reads above created reduced db with name=dut_block1-1-2-3-4.db, for block=dut_block1-1-2-3-4 (dir=meridian_project/block_name/dbs/db_name.db).


source waivers_file => sources any waivers provided

report_policy -compat ALL -verbose -output full.rpt => reports for setup checks, waivers, analysis checks

5. exit => typing exit, quits the tool

 


 

Hierarchical flow for mrdc:

Here instead of running mrdc on top level design which may be very large and take days to run, we run mrdc on lower level blocks, dump the reduced db for these blocks. Then we run mrdc at top level, where we read these reduced db for lower level blocks. Tis saves significant run time and makes analysis easy to debug at top level, since lower level module issues are already cleaned up by this time (when we ran mrdc at block level, we try to get it clean, before running mrdc at top level). There may be some differences in violations being reported at top level hierarchical vs top level flat, as some design info is missing when we abstract models of lower level modules. All env files specified when running block level rdc, should be provided exactly the same when running top level runs, so that the constraints are the same, else the model may not reflect the right behaviour (as the model was created in the first place with those set of constraints, so if the constraints changed, then that model is not valid anymore).

IP abstraction: The same concept of hier run is applicable to IP for which we have verified rdc at IP level, and then we incorporate these IP in our design. We can create reduced db for these IP, and then use these reduced db when running rdc at higher level. We blackbox these IP or lower level modules when reading top level design, and then read their respective reduced db files only.

Top level hier run flow steps: Read design files for top level, then read rdc for block level, then provide constraints, and then analyze top level design

analyze -f chip_top.f => reads top level design

elaborate -black_box {dut_block1} => during elaboration, we blackbox lower level modules, since we are going to read their reduced db, instead of reading the whole design for these lower level modules

read_rdc_db -block dut_block1-1-2-3-4 -name dut_block1-1-2-3-4 => reads reduced db for dut_block1 with parameters 1,2,3,4

read_rdc_db -block dut_block1-5-6-7-8 -name dut_block1-5-6-7-8 => reads reduced db for dut_block1 with parameters 5,6,7,8

read_sdc, read_env, analyze_intent .... => Now run the flow as regular flow, and analyze results

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

Before we get into complicated stuff, let's start from the simplest buliding bllock, atom. Section 3 of Feymann lectures deals with quantum physics that we deal with when talking about atoms. Feynman has one of the best material on Physics.

http://www.feynmanlectures.caltech.edu/

 

ATOMS:

Atom is the smallest entity that exists for any material. It has neutrons and protons in the nuclues, and an electron circulating around it in orbit. These would seem like particle, but modern quantum theory states that quantum scale objects have wave-particle duality, and exhibit both wave like and particle like properties. There have been many controversies over this wave-particle nature of objects, but is now generally accepted. Bigger the size of object, it's wave characteristics become so small, that it acts like a particle fr most practical purpose. However, for very small objects, as electrons, wave characteristics are noticeable. Similarly all electromagentic radiation (i.e light, heat), etc are assumed to hold both wave and particle characteristics to help explain many phenomenon which can't be explained by assuming only a particle mode, or only a wave model.

For our purpose, we will treat all electron, proton and neutron as particles, with the understanding that they show wave properties. Electrons have -ve charge, protons have +ve charge, and neutrons are chargeless. All of them have mass, but their mass is too small (neutron/proton have 1800 times greater mass than electron, but still small). So, gravitational forces between these masses is too small. They are held together via electrostatic forces (forces b/w opposite charges).

electron: mass = 9.1 x 10^-31 kg = 0.0005amu, charge = -1.6 x 10^-19 C, (electron lot smaller than neutron/proton, so mostly viewed as wave)

proton: mass  = 1.7 x 10^-27 kg = 1.007amu, charge = +1.6 x 10^-19 C, 

neutron: mass = 1.7 x 10^-27 kg = 1.008amu, charge = 0 C,  (neuton slightly heavier than proton)

In any atom, neutron and proton are in center nucleus, while electron is in circular orbit. Number of protons and electron are equal, resulting in 0 charge for an atom. This is also called "atomic number" of atom (num of electrons).

With any atom, energy is needed to break it apart into electrons and protons, That means some energy was supplied to form an atom (electron and proton joined to form an atom). They were formed right after the "Big Bang" when our known universe originated from pure energy some billions of years ago. The energy was converted to the elementary or sub atomic particles (quarks, gluons, leptons etc...). These condensed to form electrons and protons. Very soon, a proton and an electron met, and formed a hydrogen atom (no neutron, so mass=1amu). The neutron came about in a similar manner, and condensed with neighboring electrons and protons to form a complex mixture of the isotopes of hydrogen and helium (helium has 2 neutrons, 2 protons and 2 electrons, so mass=4amu). From this sprang everything else. That is why we find hydrogen and helium in abundance everywhere in universe, since these were the earliest and rudimentary atoms formed.

We can calculate total energy present in any isolated atom, by calculating the electrostatic energy b/w proton and electron, and kinetic energy of electron. We postulate that this total energy has to be -ve, since we have to supply energy to it, to break it. If total energy was greater than 0, then electron would be free to roam around, w/o being bound to the proton.

Electrostatic potential energy: Two charges at infinite distance are assumed to have 0 potential energy. they have attractive/repulsive forces depending on polarity of charges. Let's assume there are 2 charges +q and -q at infinite distance. They have 0 potential and 0 kinetic energy. They start attracting each other because of attractive force. Since Work=F*distance*cos(theta), they do work W=∫ F*dx = ∫ k*q1*q2/r^2 * dx. Integrating this we get W= - k*q1*q2/distance, which represents the final electrostatic potential energy stored in the system of these 2 charges, as +ve work was done on the +q charge. This work done didn't get lost anywhere, and by conservation of energy has to be stored somewhere. The +q charge will finally have some velocity and acceleration (due to force F acting on it), but the final velocity doesn't account for all of the energy. Since the system had 0 initial energy (at infinite distance and zero velocity), final energy also has to be 0. Since final kinetic energy is +ve, an equivalent -ve energy has to be there, which is what is stored as electrostatic potential energy.

When electron and proton come together from infinity to form an atom, we see that the final kinetic and potential energy is not 0. Again, this is expected, since they formed a bond by giving out energy, and so total energy goes -ve. This means to get this atom to have 0 net energy, we need to apply a +ve energy of that value, and then this atom will break apart into an electron and proton. Let's do this calculation for hydrogen atom.

Bohr's model: Very early, Bohr gave a simplified model of what radii, electron are circulating around nucleus. Ground state is the lowest state available for electron which is at radii R = 5.3 * 10^-11m = 0.53A. This radius can actually be calculated by getting total energy of atom (PE+KE), and then minimize this energy. PE decreases as electron gets closer to proton, but KE increases because of velocity increase (required due to uncertainty priniciple, which states that as electron gets coser, uncertainty in it's position is reduced, which requires corresponding increase in velocity to keep the product above the limit). It will turn out that min energy happens at radius R=0.53A.  Look at Feymann's lectures III-02 on the derivation.

centripetal force for electron to revolve around proton is provided via electrostatic force. F = m*v^2/R = k*q^2/R^2 => m*v^2 = k*e^2/R (e is the charge of an electron)

KE = 1/2*m*v^2 = 1/2*k*e^2/R

PE = -k*q1*q2/R = -k*e^2/R

Total energy = KE+ PE = -1/2*k*e^2/R = -2.2*10^-18J = -13.6eV (NOTE: KE is 1/2 of PE but of opposite sign. If KE was same as PE then net energy would have been 0)

1eV=1.6*10^-19J since Force F = q*E = q*V/d (For electric field E= V/d, where V=potential difference b/w 2 points and d=distance b/w them). Then Work W=F.d=q*V/d*d = q*V = 1.6*10^-19*1V = 1.6*10^-19J = 1eV

So, it will take 13.6eV of energy to ionize an hydrogen atom (i.e remove an electron from ground state).

-13.6eV is the lowest possible energy state. An electron can't get any closer than this to the nucleus. An electron can get into larger radius, but then it's speed will decrease (in accordance with hisenberg uncertainty principle). The total energy in this case will increase (though will still be -ve). It turns out that electron can only be in certain discrete radius (i.e it's not possible for it to be in any arbitrary radius). These distinct radius gives rise to distinct energies. We call these different enery levels. This is what is referred to as quantum physics, as electron energy levels are quantized. Of course the highest energy can be anything infinite, but at that point electron and proton are separate and electron is moving at infinite speeds. For our purpose, highest energy level is 0, which is the state where electron and proton just separated, and electron is at rest (no KE). We call this energy level Einfinite. The lowest energy level (-13.6eV) is called E0 (ground state), next one is called E1 and so on (highere states called as excited states, which they get to by absorbing energy from outside. 2 primary ways to excite an electron are thru absorbing light and thru collisions) . In energy state E100 or higher, electron is so loosely bound to the atom, that any small perturbation or external energy will pull the electron out.

En=-E0/n^2 where n is the energy state = 1,2,3 ...

So, E1=-E0/4 = -3.4eV (i.e if electron was in this state, ionization energ = 3.4eV only)

Periodic table shows atoms with 1 electron, all the way to atoms with 100 or more electrons. Each of these atoms consitututes a different element, and that is all the elements we know about. Interesting that just having a different number of electron changes the material so drastically (i.e aluminum vs silicon). Electrons can be in state 1s, 2s, 2p, 3s, 3p, 4s, etc. s states can have max of 2 electrons, while p states can have max of 6 electrons. 1s states correspond to n=0, 2s/2p states to n=1, 3s/3p to n=2 and so on. For a simple atom like hydrogen which has only 1 electron, all states in same "n" have same energy. i.e all states in 3 (3s,3p,3d) have same energy E2=-13.6/9=-1.5eV, However for atoms that have multiple lectrons, these electrons interact with each other, giving rise to splitting of energy levels within same n. So, 2p states are little higher on energy diagram than 2s states, but still lower than 3s states. Detailed diagrams in II-19 of Feymann's lectures. This is why s states are occupied before p states, as electrons always occupy lowest energy states. One important observation is that from states 3s and beyond, energy states start getting closer to each other (E=E0/n^2), which causes many of these energy states to overlap each other. This results in 3d being at higher energy than 4s states. This is why 4s states are occupied before 3d states, as electrons always occupy lowest energy states. More complicated maths involving schrodinger eqn is needed here.

For helium, which has 2 electrons, E0=-24.6eV (so 24.6eV needed to ionize it, or remove 1 electron). If we want to ionize it further, by removing the last electron, ionization energy=-54.4eV. So any further ionization always requires more energy.

For silicon, which has 14 electrons, ionization energy = 8.1eV. Ionization energy is b/w 5-10eV for most elements except 10 elements in 1st and 2nd row of periodic table (since electrons are further out, so lower energy needed).

Collection of atoms:

Above theory applies to isolated atoms. However, when 2 atoms come close together, there is an interaction between the orbits of their electrons. This interaction causes a splitting of each individual energy level into two slightly different levels. The atoms in almost every crystalline solid are so close together that the energy levels produced after splitting due to interaction between the various orbits of different electrons will be very large and so close together as to form a band.

Consider imaginary formation of a diamond crystal from isolated carbon atoms. Link: http://www.engineeringenotes.com/electrical-engineering/conductivity/energy-bands-in-solids-conductivity-electrical-engineering/33944

Each isolated carbon atom has an electronic structure 1s2 2s2 2p2 in the ground state. Each atom has available two 1s states, two 2s states, six 2p states and higher states. If we consider, N atoms, there will be 2N, 2N and 6N states of type 1s, 2s and 2p respectively. As the interatomic spacing decreases, their energy level split into bands, beginning with the outer shell, i.e., n = 2. As the 2s and 2p bands grow, they merge into a single band composed of a mixture of energy levels. This band of 2s-2p levels contains 8N available states.

As the distance between atoms approaches the equilibrium interatomic spacing of the diamond, this band splits into two bands separated by an energy gap Eg. The upper band (conduction band) contains 4N states, as does the lower band (valence band). Thus, apart from the low lying and tightly bound 1s levels, the diamond crystal has two bands of available energy levels separated by an energy gap Eg wide which contains no allowed energy levels for electrons to occupy. These energy bands are actually made up of many discrete energy levels which are too close together to resolve. Within a band the number of levels is of the order of the number of atoms in the crystal, so although electrons are actually restricted to these energies, they appear to be able to take on a continuum of values. 

The lower 1s band is filled with the 2N electrons which originally resided in the collective 1s states of the isolated atoms. However, there were 4N electrons in the original isolated (n = 2) shell (2N in 2s and 2N in 2p states). These 4N electrons must occupy states in the valence band or the conduction band in the crystal. At 0 K the electrons will occupy the lowest energy states available to them. In the case of diamond crystal, there are exactly 4N states in the valence band available to the 4N electrons. Thus at 0 K, every state in the valence band will be filled, while the conduction band will be completely empty of electrons.

In an insulator and pure semiconductor, lower band is completely filled and the upper band is completely empty. The energy of the forbidden gap is denoted by Eg. The conduction takes place only when the electron in valence band jumps to the conduction band. In other words, the electron in valence band requires energy equal to Eg to jump to the conduction band. When the electron jumps from the valence band to the conduction band, then a vacancy electron called a hole is created in the valence band. Since hole is a deficiency of an electron and hence is positively charged. The forbidden energy gap in an insulator is of the order of 5 to 10 eV. The amount of energy cannot be imparted to the electrons in the valence band and hence the electron cannot jump from the valence to conduction band. Therefore, conduction is not possible in the insulators. The forbidden energy gap in case of semiconductor is usually, of the order of 0.75 to 1 eV. This amount of energy can be easily imparted to the electrons in the valence band by thermal agitation of the crystal lattice. Thus, with the increase in temperature, many electrons from the valence band acquire the required amount of energy to jump to the conduction band and these results in the increase of electron hole pairs. The forbidden energy gap Eg is the energy required to break the covalent bands so as to make the electron free for conduction. In a conductor, this bandgap is of order of 0.01eV, so virtually all electrons in valence band avilable for conduction.

 Very good explanation on spliting of energy bands => https://www.youtube.com/watch?v=-lHXZk5M6cI

 


 

Vesta comes with the qflow package. Here we try to do a stand alone vesta installation, as it's very simple to do:

In dir where you have qflow downloaded, do this:

cd qflow-1.3.13/src

vesta.c, hash.c and hash.h are the 3 files used to generate binary vesta.

Copy these files + Makefile in some temporary dir, and generate vesta binary over there, so as to not mess the original qflow dir.

mkdir vesta_temp; cd vesta_temp; cp vesta.c, hash.c, hash.h, Makefile

Run Makefile in this dir to generate executable =>

make vesta

It runs this rule:

vesta$(EXEEXT): vesta.o $(HASHLIB)
$(CC) $(LDFLAGS) vesta.o $(HASHLIB) -o $@ $(LIBS)

These are the cmds seen on screen =>

cc -g -O2 -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DTCLSH_PATH=\"/usr/local/bin/tclsh\" -DQFLOW_MAGIC_PATH=\"/usr/local/bin/magic\" -DQFLOW_NETGEN_PATH=\"/usr/local/bin/netgen\" -DQFLOW_QROUTER_PATH=\"/usr/local/bin/qrouter\" -DQFLOW_GRAYWOLF_PATH=\"/usr/local/bin/graywolf\" -DQFLOW_YOSYS_PATH=\"/usr/local/bin/yosys\" -DQFLOW_OPENTIMER_PATH=\"\" -DQFLOW_OPENSTA_PATH=\"\" -DQFLOW_VERSION=\"1.3\" -DQFLOW_REVISION=\"13\" -c vesta.c -o vesta.o

cc -g -O2  -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DTCLSH_PATH=\"/usr/local/bin/tclsh\" -DQFLOW_MAGIC_PATH=\"/usr/local/bin/magic\" -DQFLOW_NETGEN_PATH=\"/usr/local/bin/netgen\" -DQFLOW_QROUTER_PATH=\"/usr/local/bin/qrouter\" -DQFLOW_GRAYWOLF_PATH=\"/usr/local/bin/graywolf\" -DQFLOW_YOSYS_PATH=\"/usr/local/bin/yosys\" -DQFLOW_OPENTIMER_PATH=\"\" -DQFLOW_OPENSTA_PATH=\"\" -DQFLOW_VERSION=\"1.3\" -DQFLOW_REVISION=\"13\" -c hash.c -o hash.o

cc vesta.o hash.o -o vesta

Or run this single cmd: cc -g -O2 hash.c vesta.c -o vesta => this will generate vesta executable

NOTE: for some reason, compilation shows error with this line when run as single cmd above (one of the defines -D is required):

vesta.c: In function ‘main’:
vesta.c:3795:31: error: expected ‘)’ before ‘QFLOW_VERSION’
  fprintf(stdout, "for qflow " QFLOW_VERSION "." QFLOW_REVISION "\n");
                               ^

Just comment out this line and compilation goes fine => //fprintf(stdout, "for qflow " QFLOW_VERSION "." QFLOW_REVISION "\n");

Now run vesta providing liberty file and netlist

./vesta map9v3.rtlnopwr.v /usr/local/share/qflow/tech/osu035/osu035_stdcells.lib => verilog netlist is the one generated by qflow after synthesis/PnR stage.

vesta.c:

main routine:

1. process cmd line arguments

2. Read liberty file => libertyRead(flib, &tables, &cells);

    liberty file table values get stored in linked list "tables" (struct lutable) and "cells" (struct cells)

3. Read verilog netlist => verilogRead(fsrc, cells, &netlist, &instlist, &inputlist, &outputlist, Nethash);

  • Parse thru verilog netlist. Look for module/endmodule keywords for start or end of module.
  • Then look for i/p, o/p pins and assign those i/o nets to inputlist (struct connect) and output list (struct connect).
  • Then parser parses lines like this "CLKBUF CLKBUF_1 ( .A(clock), .Y(clock_buf4) );" Here CLKBUF is instance definition, and CLKBUF_1 is instance name. Both are parsed and instlist (struct instance) is created for CLKBUF_1, whose reference inst is CLKBUF. Then pin names A,Y are parsed and "struct connect" is created for each pin, here for "clock" with direction as i/p pin, and for "clock_buf4" with direction as o/p pin. netlist (struct net) is created for the nets connecting to these pins.

4. create internal links => createLinks(netlist, instlist, inputlist, outputlist);

5. Report on max delay paths

6. Report on min delay paths

5. Report on max delay paths

6. Report on min delay paths

 

 

DFT: Design for Testatbility

Any chip that is fabricated is going to have some defects during fabrication, which will cause some of the transistors or wires on the chip to not function properly. This may cause the chip to fail. One way to check if the chip manufactured is good or not, is to run thru the same functional patterns on the chip pins that the chip is going to go thru when it's in operation.

For small chips this method may work, but for large chips, it's practically not feasible for 2 reasons. First, there may be billions of such possible patterns on chip pins that we may have to aplly, which is time prohibitive. Secondly, it may still not find out all bad devices or bad connections in chip, since those patterns may not target 100% of the chip devices.

Without having 100% check to test each and every transistor and each and every connection, we can never be sure if the chip being shipped is 100% functional or not. This is where DFT comes. DFT simply means adding extra logic on chip so as to allow us to test the whole chip. DFT is a broad field by itself, an you will usually see thousands of job postings just for DFT engineers.

In this section, we will go thru the basics of DFT,

IEEE 1500:

IEEE 1500 defines a standard for test access of cores within a big chip. For small designs, we just do connections at top level, and pass on signals from 1 module to other. But for big designs, it can get very complex. For such designs, we treat each block as a chip in itself, having it's own controller for dft purpose, which handles all internal details of dft. Then, at top level we justhave a top level 1500 controller, which connects and controls these block level 1500 controllers. All connections are controlled via JTAG pins. These pins go into top level TAP controller, which processes and passes all the appr signals to each block.

We define standard port interface for IEEE 1500, to connect different blocks. Most signals are prefixed with W which stands for wrapper. WIR = wrapper instruction reg, while DR = data reg (WDR or wrapper data reg name not used for whatever reason). These IO signals are:

WRCK/WRCLK = Clock. This is actually connected to chip JTAG pin TCK.

WRSTN = Reset (active low). This resets all reg in WIR to 0, indicating func mod. This is actually connected to chip JTAG pin TRSTN.

SHIFTWR/SHIFTDR = Shift WIR or DR. With this signal high, Shift reg gets connected b/w WSI and WSO and starts getting values shifted in/out

UPDATEWR/UPDATEDR = Update WIR or DR. With this signal high, Update reg gets updated with values in shift reg.  These signals coming out of Update reg thenget stored in bunch of internal reg, which control all test related stuff in Func logic (i.e bist control signals, bypass, etc)

SELECTWIR = Operate on WIR. (we can have multiple SELECTWIR1, SELECTWIR2, etc if we have multiple partions within WIR, which we want to activate separately)

WSI / WSO Scan In/Out Data. These are single bit line for scanning data in and out of IR/DR. These are connected to chip JTAG pin TDI/TDO via daisy chain. First block's WSI comes from top TAP controller, which in ultimately connected to TDI pin, WSO pin connects to next block WSI pin, and so on. Last block's WSO pin goes to top TAP controller, which finally connects to chip TDO pin. The i/p pin WSI is captured on +ve clk edge, while o/p pin WSO is fired on -ve clk edge. This follows the same convention as for all other pins of JTAG which are fired on -ve edge, but captured on +ve edge of clk.

WPI /WPO Parallel In/Out Data. These are multi bit bus, and used for scanning data in and out of functional flops (i.e scan chain stitching of functional flops). These are same as SDI (scan Data in) and SDO (scan data out) pins that are used in designs for scan data in/out. The reason, we have a bus is to have mutiple chains of scan in/out for big designs (since they may have millions of flops, and shifting data in/out via just one pin is going to take hours). WPI/WPO are captured/fired on same clk edge as WSI/WSO.

 

See diagram.

Top level TAP:

We specify special JTAG inst to control the above signals at block level. We can define as many JTAG inst as needed to have control over various 1500 controllers in the design. We can have JTAG instructions for selecting specific 1500 controllers at block level ,

J1500I = JTAG 1500 inst for Inst Reg. This gets SELECTWIR signal high, and SHIFTWR or UPDATEWR signal high

J1500D = JTAG 1500 inst for Data Reg. This gets SELECTWIR signal low, and SHIFTDR or UPDATEDR signal high

Once you have all the pieces ready, we will download, qflow:

Head over to this link: http://opencircuitdesign.com/qflow/index.html

Download latest stable version that is under stable download link. I downloaded "qflow-1.3.13.tgz" (which was the latest version with release date of Mar 19, 2019). Extract it in a dir named "qflow-1.3.13". In this dir, we see a README file, which has all instructions for installing it:

cd qflow-1.3.13 => Now run below 3 cmds in this dir

1. ./configure => This will look for all tools that qflow needs. It shows configuration results at end.

Using yosys verilog synthesis tool at: /usr/local/bin/yosys
Using graywolf placement tool at: /usr/local/bin/graywolf
Using qrouter detail route tool at: /usr/local/bin/qrouter
Using Magic layout tool at: /usr/local/bin/magic
Using Netgen LVS tool at: /usr/local/bin/netgen
Using Vesta STA tool (internal)
Using Vesta STA tool (internal)

If some thing not found in std path, it will show warning: WARNING: Netgen LVS tool not found.  Use --with-netgen=<DIR>. We will need to fix this by downloading/installing that tool and specifying an alternate path for that tool (if it exists in some other dir).


2. make => make is run. Last 2 lines indicating successful compilation are:

make[2]: Leaving directory `/home/proj/qflow-1.3.13/tech/gscl45nm'
make[1]: Leaving directory `/home/proj/qflow-1.3.13/tech'

3. sudo make install => This puts qflow executable in correct dir. It shows same last 2 lines as in "make" step above.

/usr/local/bin/qflow => qflow script put here

/usr/local/share/qflow/* => all qflow related scripts, etc put here

Run "which qflow" to make sure it shows "/usr/local/bin/qflow" as the path. Type "qflow" on cmdline, and it should show you a help menu.

Project:

Now, we will setup a "experiment" dir where we will get a small project going.

mkdir test_ex1
cd test_ex1
emacs map9v3.v => this creates a new blank file called map93v3.v. This small file is on tutorials link on qflow page. Copy contents from there to this file.
qflow map9v3 => run qflow on this module named "map9v3". Note we do not provide the name of verilog file, but just the name of top level module. Then it will look for module named "map9v3", which it will find in file named map9v3.v. Screen shows this o/p:

--------------------------------
Qflow project setup
--------------------------------

No technology specified or found;  using default technology osu035

No actions specified on command line;
creating qflow script file /home/kailash/Project/test_ex1/qflow_exec.sh only.
Uncomment lines in this file and source the file to run the flow.

The flow created a csh file called qflow_exec.sh file, which is very simple wrapper for calling individual steps in the flow. All of these asteps re commented. We can uncomment lines 1 at a time, and run the script, or copy cmds from this cript, and run that cmd directly on the shell. All output files are generated in same dir. These are the steps, running them 1 by 1:

1. Synthesis => runs synthesis using Yosys and generates verilog gate netlist map9v3.rtlnopwr.v, map9v3.rtl.v, and bunch of other files.

/usr/local/share/qflow/scripts/synthesize.sh /home/Project/test_ex1 map9v3 /home/Project/test_ex1/map9v3.v || exit 1

2. Placement => runs placement using graywolf

/usr/local/share/qflow/scripts/placement.sh -d /home/Project/test_ex1 map9v3 || exit 1

3. Timing => runs timing using vesta. This is initial timing run on placed design (with no routing info)

/usr/local/share/qflow/scripts/vesta.sh  /home/Project/test_ex1 map9v3 || exit 1

4. Routing => runs detailed routing using qrouter

/usr/local/share/qflow/scripts/router.sh /home/Project/test_ex1 map9v3 || exit 1

5. Timing => runs timing using vesta. This is final timing run on routed design (with all wire delays included)

/usr/local/share/qflow/scripts/vesta.sh  -d /home/Project/test_ex1 map9v3 || exit 1

6. Migrate => runs magic to generate final layout

/usr/local/share/qflow/scripts/migrate.sh /home/Project/test_ex1 map9v3 || exit 1

7. DRC => runs drc using magic on final
/usr/local/share/qflow/scripts/drc.sh /home/Project/test_ex1 map9v3 || exit 1

8. LVS => run lvs using netgen
/usr/local/share/qflow/scripts/lvs.sh /home/Project/test_ex1 map9v3 || exit 1

9. GDS => run magic to generate gds
# /usr/local/share/qflow/scripts/gdsii.sh /home/Project/test_ex1 map9v3 || exit 1

10. cleanup => cleanup script to remove un-needed files
/usr/local/share/qflow/scripts/cleanup.sh /home/Project/test_ex1 map9v3 || exit 1

11. display => display final layout in gds using magic
 /usr/local/share/qflow/scripts/display.sh /home/Project/test_ex1 map9v3 || exit 1