Post on 29-Nov-2023
transcript
HARDWARE EMULATION OF SEQUENTIAL ATPG-BASED
BOUNDED MODEL CHECKING
BY
GREGORY FICK FORD
Submitted in partial fulfilment of the requirements
for the degree of Master of Science
Thesis Advisor: Dr. Daniel Saab
Department of Electrical Engineering & Computer Science
CASE WESTERN RESERVE UNIVERSITY
January, 2014
i
CASE WESTERN RESERVE UNIVERISTY
SCHOOL OF GRADUATE STUDIES
We hereby approve the thesis of
Gregory Fick Ford
candidate for the Master of Science degree.
Dr. Daniel Saab
Dr. Francis Merat
Dr. Christos Papachristou
(date) 11/08/2013
* We also certify that written approval has been obtained for any proprietary material contained
therein.
ii
Contents
1 Background
1.1 Properties & Temporal Logic ………………………………..…………...
1.1.1 Linear Temporal Logic …………………..……………….
1.1.2 Computational Tree Logic …………………..……………
1.1.3 SUGAR …………………………………..……….………
1.1.4 OpenVera ………………………………..……….……….
1.1.5 Property Examples ……………………..…………………
1.2 Model Checking …………………………………………..………………
1.2.1 Ordered Binary Decision Diagrams ………..……………..
1.2.2 SAT Modeling …………………………….……………...
1.2.3 Bounded Model Checking ……………..…………………
1.2.4 Automatic Test Pattern Generation ………..….…………..
1.3 Prior Work ……………………………………………..…………………
2 Algorithm
3 Architecture
3.1 PI/PPI Decision Block ………………………………………..…………..
3.2 Objective Decision Block …………………………………..…………….
3.3 Forward Network Derivation …………………………………..…………
3.4 Backward Network Derivation ………………………………..………….
3.4.1 Backward Network Fanout Handling …………..………...
3.4.2 Backward Network Conflict Detection ………..….………
3.4.3 Backward Network Decoder ………………..….…………
3.4.4 Backward Network Encoder ………………..….…………
3.5 Translating Circuits into Forward/Backward Networks ……...…………..
3.5.1 Processing Input Data ………………………...…………..
3.5.2 In-Memory Data Structure ………………..………………
3.5.3 Writing Output Networks ……………………..………….
4 Results
5 Conclusion & Future Work
A Example Input Circuit and Network Translations
B Example DONE Simulation for c17 Benchmark Circuit
C Example FAIL Simulation for s27 Benchmark Circuit
1
2
2
4
5
6
7
10
10
13
16
16
21
24
28
30
46
54
57
60
65
67
70
74
74
75
78
80
88
90
98
107
iii
D FPGA Emulation Algorithm Implementation Base Verilog Code
E Forward / Backward Network Generation Program C++ Code
F FPGA Algorithm & Network Integration TCL Script
G Formal CTL Rules Generation TCL Script
Bibliography
156
192
250
252
253
iv
List of Figures
1.1 CTL Time/State Representation …..……………………………….……………..
1.2 Example Simple Search System Model ……………………………..……………
1.3 OBDD Graphical Representation Example ………………………..……………..
1.4 Variable Order Dependency in OBDDs …………………………….……………
1.5 Example of the One-Literal Rule in SAT ……………………………..………….
1.6 Propagation and Consistency in the D-Algorithm ………………………..……...
2.1 ILA Model of Sequential Circuit for k Time Frames ……………...…...………..
2.2 Objective Tracing Within a Frame ……………………………...…...…………..
2.3 Algorithm Flow Diagram ……...…………………………………………………
3.1 Top Level Architecture Block Diagram ……...……………………...…………..
3.2 PI/PPI Decision Block Structure Diagram ……...………………………………..
3.3 State Transition Model of “More Justification” Operation …………..………….
3.4 State Transition Model of “Move to Ti-1” Operation ………………..………….
3.5 State Containment Check Implementation ……………………………..………..
3.6 State Transition Model of “Backtrack” Operation ……………………..………..
3.7 State Transition Model of “Move to Ti+1” Operation ………………..…………
3.8 Objective Decision Block Structure Diagram ……...………………...………….
3.9 Objective Decision Block PPI Objective Read In ……………………...………..
3.10 Assembly of Frame-k Objective Word …………………………………..………
3.11 Objective Decision Block Conflict/Done Decision Logic ……...………………..
3.12 Objective Decision Block Sequencer Operation …………………………..…….
3.13 Abstract Backward Gate Values Dependence …………………………...………
3.14 Backward Fanout Signal Contention …………………………………...………..
3.15 Priority Encoder Structure for Required Objective Bit ………………...………..
3.16 Priority Encoder Structure for Required Objective Bit with Reset …...…………
3.17 Priority Encoder Structure for Objective Value Bit …………………...…………
3.18 Complete Structure for Backward Network Priority Encoder ………...…………
3.19 Trace-blocking Conflict ……………………………………………...…………..
3.20 Non-blocking Conflict ………………………………………………...…………
3.21 State Transition Diagram for Backward Network Decoder …………...…………
3.22 Backward Network Decoder Value Assignment ……………………...…………
3.23 State Transition Diagram of Backward Network Encoder ……………...……….
3.24 Backward Network Encoder Shiftout Operation ………………………...………
3.25 Network Translation Flow ……………………………………………...………..
3.26 Internally Consistent Pre-Processing …………………………………...………..
3.27 Gate Data Structure …………………………………………...………………….
4
8
11
12
14
17
24
25
26
28
30
32
35
36
39
43
46
48
49
50
51
57
61
62
63
64
64
66
67
68
69
70
71
74
75
76
v
3.28 Gate Fan-out List Structure ……………………………………...……………….
3.29 Level List Structure ……………………………...…………...………………….
4.1 Virtex-6 Utilization vs. ISCAS89 Benchmark Size …………………...………….
4.2 FPGA vs. Software Solve Time for ISCAS89 Benchmarks ……………………...
4.3 FPGA vs. Software Total Time for ISCAS89 Benchmarks ………………...……
B.1 c17 Benchmark Circuit Structure ……………………………….....……………..
B.2 c17 Simulation Circuit Structure …………………………………..……………..
B.3 c17 Simulation Backtrace …………………………………………..…………….
B.4 Contents of c17 Block RAM After Objective 1 …………………….....…………
B.5 c17 Simulation Trace / Implication ……………………………..…...…………...
B.6 Final c17 Block RAM Contents …………………………………..………………
C.1 s27 Benchmark Circuit Structure ………………………………..……………….
C.2 s27 Benchmark Simulation Structure …………………………..………………..
C.3 s27 Simulation Frame k Backtrace ……………………………..………………...
C.4 Contents of Block RAM After Frame k ………………………..…………………
C.5 Contents of Block RAM After Move to Frame k-1 ………………..……………..
C.6 Contents of RF in Frame k-1 ………………………………..……...…………….
C.7 s27 Simulation Frame k-1 Backtrace 1 ………………………..………………….
C.8 Contents of RAM in Frame k-1 with Backtrace 1 ………………..………………
C.9 s27 Simulation Frame k-1 Imply 1 ……………………………..………………...
C.10 Contents of RF and PO/PPO in Frame k-1, Imply 1 ……………….....………….
C.11 s27 Simulation Frame k-1 Backtrace 2 …………………………..……………….
C.12 s27 Simulation Frame k-1 Imply 2 ………………………………......…………...
C.13 Contents of RF and PO in Frame k-1, Imply 2 …………………………..……….
C.14 State Check Comparison for Frame k-1 ………………………..…...……………
C.15 Contents of RF in Frame k-2 …………………………………..…...…………….
C.16 Contents of Block RAM at Frame k-2 Start ……………………..……………….
C.17 s27 Simulation Frame k-2 Backtrace 1 …………………………..……………….
C.18 s27 Simulation Frame k-2 Backtrace 2 ………………………..………………….
C.19 Contents of Block RAM after First Clear Top ………………..……...…………..
C.20 Contents of Block RAM after First Swap Value ………………..………………..
C.21 s27 Simulation Frame k-2, Backtrack 1 Imply …………………..……………….
C.22 Simulation Frame k-2, Backtrack 1 Backtrace …………………..……………….
C.23 s27 Simulation Frame k-2, Backtrack 2 Imply …………………..……………….
C.24 Block RAM Contents after Move to Ti+1 and Swap Value ………..……………...
C.25 s27 Simulation Frame k-1, Backtrack 1 Imply …………………..……………….
C.26 RF Contents and PO/PPO after Move to Ti+1, Imply 1 …………..……………….
76
77
83
86
87
98
99
101
103
105
106
107
108
111
111
112
113
114
116
116
117
118
120
121
123
124
125
126
128
133
134
135
136
139
143
144
145
vi
C.27 Block RAM Contents after Move to Ti+1 and Backtrack ………..………………..
C.28 Block RAM Contents after Second Move to Ti+1 and Swap Value ……..………..
C.29 Simulation Frame k, Backtrack 1 Imply ……………………………..…………...
148
153
154
vii
List of Tables
1.1 Propositional Operators for LTL Formulae ……………………..……………….
1.2 Temporal Operators for LTL Formulae ……………………………...…………..
1.3 Temporal Operators for LTL Formulae ……………………………..….………..
1.4 Operators of the “Temporal Layer” in Sugar 2.0 ………………..…….…………
1.5 Directive Operators in OpenVera ………………………………..………………
1.6 Temporal Operators in OpenVera ………………………………..………………
1.7 Language Representations of a Safety Property …………………..……………..
1.8 Language Representations of a Liveness Property ………………..……………..
3.1 PI/PPI Decision Block Control Logic States ……………………..……………...
3.2 More Justification Operation Pseudo-code ……………………..……………….
3.3 Pseudo-code for “Move to Ti-1” Operation …………………..…………………
3.4 “Backtrack” Operation Pseudo-code …………………………………...………..
3.5 “Move to Ti+1” Operation Pseudo-code ………………………..……………….
3.6 Full One-Bit Truth Table for AND Gate ………………..……………………….
3.7 Two-Bit Truth Table for AND Gate ……………………..………………………
3.8 Split K-maps for AND Gate Output Bits ………………..…………….…………
3.9 Minterm Expressions for AND Gate Output Bits ………….………….…………
3.10 Forward Translation Equations for Basic Gates ………….…………….………..
3.11 Pseudo-code for AND Gate Backward Model Outputs ……..……….…………..
3.12 Truth Table for Backward Model of AND Gate …………..………….………….
3.13 Backward Translation Equations for Basic Gates ………….……………………
3.14 Input Network Format ……………………………………..…………………….
3.15 Forward Network Module Interface Example ………………..………………….
4.1 Virtex-6 Resource Utilization for ISCAS89 Benchmarks ………..….…………..
4.2 Runtime Comparison for ISCAS89 Benchmarks ……………..…………………
A.1 Benchmark Code for s27 Circuit …………………………..………...…………...
A.2 Forward Network Verilog for s27 Benchmark Circuit ………….………………..
A.3 Backward Network Verilog for s27 Benchmark Circuit …………..…...………...
A.4 Backward Network Priority Encoder Verilog Example ……….…………………
B.1 Circuit c17 Simulation Input Stimulus ………………………..……...…………..
B.2 Circuit c17 Initial Reset ………………………………………..…………………
B.3 Circuit c17 Simulation Cycle 1 …………………………..……………………….
B.4 Circuit c17 Simulation Cycles 2-4 …………………………..……………………
B.5 Circuit c17 Simulation Cycles 5-7 ………………………..………………………
3
3
5
5
7
7
8
9
31
32
34
38
42
54
55
55
56
56
58
59
60
75
78
82
84
90
91
92
96
99
99
100
100
101
viii
B.6 Circuit c17 Simulation Cycles 8-12 ……………………..………………………..
B.7 Circuit c17 Simulation Cycles 13-20 ……………………..………………………
B.8 Circuit c17 Simulation Cycle 21 …………………………..……………………...
B.9 Circuit c17 Simulation Cycles 22-23 ……………………..………………………
C.1 Circuit s27 Simulation Cycles 1-20 ………………………..……………………..
C.2 Circuit s27 Simulation Cycles 21-24 ……………………..………………………
C.3 Circuit s27 Simulation Cycles 25-26 ……………………..………………………
C.4 Circuit s27 Simulation Cycles 27-30 ……………………..………………………
C.5 Circuit s27 Simulation Cycles 31-41 ……………………..………………………
C.6 Circuit s27 Simulation Cycles 42-43 ……………………..………………………
C.7 Circuit s27 Simulation Cycles 44-47 ……………………..………………………
C.8 Circuit s27 Simulation Cycles 48-55 ……………………..………………………
C.9 Circuit s27 Simulation Cycles 56-57 ……………………..………………………
C.10 Circuit s27 Simulation Cycles 58-65 ……………………..………………………
C.11 Circuit s27 Simulation Cycles 66-73 ……………………..………………………
C.12 Circuit s27 Simulation Cycles 74-78 ……………………..………………………
C.13 Circuit s27 Simulation Cycles 79-95 ……………………..………………………
C.14 Circuit s27 Simulation Cycles 96-105 ……………………..……………………..
C.15 Circuit s27 Simulation Cycles 106-114 …………………..………………………
C.16 Circuit s27 Simulation Cycles 115-123 …………………..………………………
C.17 Circuit s27 Simulation Cycles 124-129 …………………..………………………
C.18 Circuit s27 Simulation Cycles 130-134 …………………..………………………
C.19 Circuit s27 Simulation Cycles 135-136 …………………..………………………
C.20 Circuit s27 Simulation Cycles 137-151 …………………..………………………
C.21 Circuit s27 Simulation Cycles 152-163 …………………..………………………
C.22 Circuit s27 Simulation Cycles 164-174 …………………..………………………
C.23 Circuit s27 Simulation Cycles 175-180 …………………..………………………
C.24 Circuit s27 Simulation Cycles 181-196 …………………..………………………
C.25 Circuit s27 Simulation Cycles 197-231 …………………..………………………
C.26 Circuit s27 Simulation Cycles 232-240 …………………..………………………
C.27 Circuit s27 Simulation Cycles 241-244 …………………..………………………
C.28 Circuit s27 Simulation Cycles 245-247 …………………..………………………
102
103
104
105
108
111
113
113
114
117
118
120
121
121
123
125
126
129
130
131
133
135
137
137
140
142
144
145
148
152
154
155
ix
Hardware Emulation of Sequential ATPG-Based
Bounded Model Checking
Abstract
by
GREGORY FICK FORD
The size and complexity of integrated circuits is continually increasing, in accordance with
Moore’s law. Along with this growth comes an expanded exposure to subtle design errors, thus
leaving a greater burden on the process of formal verification. Existing methods for formal
verification, including Automatic Test Pattern Generation (ATPG) are susceptible to exploding
model sizes and run times for larger and more complex circuits. In this paper, a method is
presented for emulating the process of sequential ATPG-based Bounded Model Checking on
reconfigurable hardware. This achieves a speed up over software based methods, due to the fine-
grain massive parallelism inherent to hardware.
1
1. Background
The complexity of integrated circuits is continually increasing, and with it, the chances of having
subtle errors in a design. This growth also increases the amount of work needed in verification,
hence driving up the total time that projects spend in verification and effecting the bottom line of
time-to-market. In 2010, the Wilson Research Group published a study on functional
verification, showing, among other things, that verification now accounts for over half of the
total time of digital design projects [1]. On top of that, this percentage is continuing to increase,
from 50% in 2007 to 55% in 2010.
Historically, simulation has been used as the main means of discovering bugs in a design, but as
designs grow larger, the chances of finding these bugs becomes less and less. Attention has
turned toward formal verification as a means to augment design verification in the face of
growing designs. Formal verification is well suited to the problem of comparing the register
transfer level (RTL) with the logic level for a design, as this is simply proving combinatorial
equivalence. On the other hand, comparing between the RTL and behavioral level is a much
more complicated problem, as the behavioral model is generally defined using code that follows
a natural language structure.
2
1.1. Properties & Temporal Logic
To address the problem of bridging the gap in formal verifiability between the RTL and behavior
level, the concept of properties is introduced. These are statements about the function of small
portions of the total design, written by the designers. These functional statements can then be
used as a means of comparison against the RTL. As described by Lamport in [2], properties can
be divided into two main categories. The first being a “safety property”, which is a statement
that a defined bad event will never happen. The second being a “liveness property”, which is a
statement that a defined good event will eventually happen. This, then, presents the issue of how
to formally define properties such that they can be verified.
1.1.1. Linear Temporal Logic
These properties are generally represented using “temporal logic”, which provides a means for
applying an assertion over a period of time. For example, if condition “p” is true in the present,
then another condition “q” must be true at some point in the future. Pnueli examined the
applicability of temporal logic to programs in [3], which can similarly be transferred to digital
design. In “Linear Temporal Logic” (LTL), time is represented as a linearly ordered set, or in
the context of digital design, a sequence of design states. As defined by Huth and Ryan in [4], a
formula in LTL is constructed from three different parts. The first are “propositional atoms”,
which are representative of conditions in the digital system (as “p” and “q”, above). The second
are “propositional operators”, which function as modifiers to propositional atoms, outside any
concept of time. Table 1.1 provides the definition of these operators.
3
Operator Name Description
┬ True Always True
┴ False Always False
⌐ p Negation True when p is False.
p ˄ q Conjunction True when both p AND q are True.
p ˅ q Disjunction True when p OR q (or both) is True.
p → q Implication IF p is True THEN q must also be True.
Table 1.1: Propositional Operators for LTL Formulae
The third, and final, are “temporal operators”, which function as modifiers to propositional atoms
based on a concept of time represented by design states occurring either before or after the
current state in a sequence. Table 1.2 provides the definition of these operators.
Operator Name Description
X p Next p is true at the next point in time.
F p Eventuality p is true at some time in the future.
G p Globally p is true at all future points in time.
p U q Until p is true, until a point in the future when
q becomes true.
Table 1.2: Temporal Operators for LTL Formulae
It is important to note that in the case of the “Until” operator, there are two possible conditions
where the operator could produce a true result. When p holds true for some time in the future,
there must be a point where q then holds true for all future points. If q must be true at some
point in the future (F q), then p U q is called a “Strong Until”. If q is not necessarily true at any
point in the future, then p U q is called a “Weak Until”. That is, p U q can be considered true
regardless of p, if q is never true at any point in the future.
4
1.1.2. Computational Tree Logic
Another system for constructing temporal logic formulae is Computational Tree Logic (CTL), as
defined by Clarke, et al. in [5]. CTL’s representation is based off the fact that for any point in
time, there are many possible futures; or for any design state, there are many possible sequences
of design states that follow, based on inputs. This is realized for any starting state, S0, where
each possible next state becomes a branch from S0 in the tree representation, and each further
state from those next states becomes a branch from them, ad infinitum. An example of this
construction is shown in Figure 1.1.
Figure 1.1: CTL Time/State Representation
CTL has its own set of temporal operators, which provide a means to formulate equations that
can assert properties based on conditions in branches of the tree. These are used in addition to
the base set of LTL operators, which are used to assert properties within a branch of the tree.
Table 1.3 provides the definitions of these operators.
5
Operator Name Description
A q Necessary q will always be true, along all branches.
E q Possible q is sometimes true, along some branches.
Table 1.3: Temporal Operators for LTL Formulae
1.1.3. SUGAR
Sugar 2.0 is another example of a formal specification language that can be used for verification,
as introduced by Eisner and Fisman in [6]. Sugar expressions are composed in four different
layers. The first layer is the “boolean layer”, which consists of Boolean operations on
propositional atoms, where any such expression can evaluate to a true or false logic value. This
can be thought of as equivalent to the “propositional operators” component of LTL, as outlined
in Table 1.1. The second layer is the “temporal layer”, which is used to define relationships
between expressions in the Boolean layer, over a period of time. The operators used in the
temporal layer and defined in Table 1.4.
Operator Description
always p p is true at all times.
never p p is false at all times.
next p p is true in the following cycle.
eventually p p is true at some cycle in the future.
p until q p is true until a point when q becomes true.
p before q p is true at a point in time before q is true.
Table 1.4: Operators of the “Temporal Layer” in Sugar 2.0
As an addition to these temporal operations, Sugar supports postfixes of “!” and “_”, in
appropriate cases. The exclamation point postfix is supported by “eventually”, “until” and
“before”. It defines the operator as being strong, as opposed to the default of weak. This is the
same context as “strong until”, as defined earlier, in that a strong operator requires that the
6
second argument be true at some point in time, excluding the case where the expression is true
by virtue of a case where the second argument never occurs (thereby never requiring a check on
the first argument). The underscore postfix is supported by “until” and “before”. The
underscore defines that there is an allowed overlap between the two arguments of one cycle. In
the context of “until”, this would mean that the first argument is true up to and including the first
cycle that the second argument is true. In the context of “before”, this would mean that the first
argument must be true before, or at the same time as, the second argument.
The third layer is the “verification layer”, which provides direction to a verification tool reading
the Sugar expressions. If an expression from the “temporal layer” is defined with “assert” in this
layer, then that instructs the verification tool that it must verify the defined properly. If an
expression is defined with “assume”, then that instructs the verification tool that it can assume
the behavior defined in the property to be true. The final layer is the “modeling layer”, which
allows for definition of the behavior of the propositional atoms in the expressions. In the context
of circuit verification, this can be thought of as assigning behavior to signals in the design.
1.1.4. OpenVera
A final example of another formal specification language used in verification is OpenVera, as
defined in [7]. OpenVera Assertions (OVAs) can be thought of as being divided into two
distinct components; directives and events. Directives make statements about events, defining
what conditions the verification tool should be checking for. This is similar in function to the
“verification layer” of Sugar 2.0. Table 1.5 shows the available directives.
7
Operator Description
check(e) Event e should always hold true.
forbid(e) Event e should never hold true.
Table 1.5: Directive Operators in OpenVera
Events are separately defined entities that contain expressions comprised of Boolean and
temporal logic. Events can be thought of as similar to a combination of the “boolean layer” and
“temporal layer” in Sugar 2.0. The operators used at this layer are summarized in Table 1.6.
Operator Description
#n p After n cycles, p is true.
#[n..m] p After between n and m cycles, p is true.
p followed_by q q is true at some point after p is true.
p triggers q q is true immediately after p is true.
p until q p is true until a point where q is true.
next p p is true in the next cycle.
Table 1.6: Temporal Operators in OpenVera
1.1.5. Property Examples
To illustrate the use of the different formal specification languages discussed here, consider a
simple searching system, as illustrated in Figure 1.2. This system has a memory containing
arbitrary data that can be searched. The system remains in an idle state until a request (req)
arrives with a pattern to be searched for. The system moves to a search state, and examines
locations in the memory for the pattern until one is found, at which point it acknowledges (ack)
that the pattern exists in memory.
8
Figure 1.2: Example Simple Search System Model
In this system, a safety property could be that the search never overflows from the memory.
That is, “index” should never exceed the number of locations in memory (defined here as
mem_rows). Table 1.7 shows how this property can be realized in each of the languages
discussed.
LTL G ⌐(index > mem_rows)
CTL AG ⌐(index > mem_rows)
Sugar 2.0 never (index > mem_rows)
OpenVera assert a_overflow : forbid(e_overflow) ;
event e_overflow : (index > mem_rows) ;
Table 1.7: Language Representations of a Safety Property
In LTL, the overflow condition (index > mem_rows) can be used as a negative argument to the
global operator G; that is, for all points in time the overflow condition should not be true. In
CTL, similarly, the overflow condition is used as a negative argument to the necessary operator;
that is, for all branches the overflow condition must not be true. In Sugar, the overflow condition
can be directly used as an argument to the “never” operator, stating that the condition can never
occur. In OpenVera, a directive is defined with the “forbid” operator, stating that the event
“e_overflow” can never happen. The event e_overflow is then defined as the overflow
condition.
9
In this system, a liveness property could be that the system always returns to its idle state. That
is, “ack” should eventually be asserted as a response to “req”. Table 1.8 shows how this
property can be implemented in each of the languages discussed.
LTL G (req → F ack)
CTL AG (req → F ack)
Sugar 2.0 always (req → eventually! ack)
OpenVera assert a_return : check(e_return) ;
event e_return : req followed_by ack ;
Table 1.8: Language Representations of a Liveness Property
In LTL, the “return to idle” condition can be represented as req implying that ack will eventually
be true. This statement is then asserted to be globally true. In CTL, the same set of statements
can be applied, with the addition of the necessary operator, adding that the condition must be true
for all branches of the tree. In Sugar, the “return to idle” condition is represented with req
implying ack with a strong eventually. Explicitly defining this as a strong eventually prevents
the case where req stays true forever, and ack never becomes true (thus potentially masking a
bug). In OpenVera, a directive is defined with the “check” operator, stating that the event
“e_return” should always happen. The event e_return then uses the “followed_by” operator to
state that the signal req becoming true must be followed by the signal ack becoming true at some
point in the future.
10
1.2. Model Checking
Properties expressed in temporal logic provide one of the inputs necessary for model checking.
The other input needed is a model of the circuit being verified. In model checking, the supplied
design model is analyzed with respect to the input properties. The result of the process is either a
sequence of states showing that the property is satisfied, or a statement that no satisfying
sequence could be found. One of the early implementations of model checking is “temporal
logic model checking”, as described by Clarke and Emerson in [8]. In this system, properties are
expressed in CTL, and the design is modeled as a state-transition diagram. The major limitation
of this early implementation is that both the CTL expressions needed to represent properties and
the design state model grow polynomially with respect to the size of the design being verified.
This is known as the “state explosion problem”.
1.2.1. Ordered Binary Decision Diagrams
The first major development in combating the state explosion problem was the SMV system,
introduced by McMillan in [9]. SMV reduces the growth of the design state space by applying
Ordered Binary Decision Diagrams (OBDDs) to the modeling of design states. OBDDs were
first detailed by Bryant in [10]. OBDDs for a given Boolean function can be represented as a
binary tree, where each level in the tree is assigned to a variable from the function, in order. At
any non-terminal vertex in the tree (representing a variable), there will be two possible
transitions to a following level of the tree. A transition to the left indicates a logical low, and a
transition to the right represents a logical high. If for a given transition, the overall value of the
function remains indeterminate, the transition will be to the next variable in order. If the
transition provides determination of the function value, then the transition will be to a terminal
11
node in the tree (0 or 1). Figure 1.3 shows an example OBDD graph representation, where
circles are non-terminal (variable) nodes and squares are terminal nodes.
Figure 1.3: OBDD Graphical Representation Example
Evaluation for the function (w·x + y·z) begins with variable w. If w is false, then the value of x
does not matter, so the transition proceeds to y. If w is true, then the transition proceeds to x. In
this case, there is only one instance of x, so if x is true, that means that the function is true (since
both w and x are true); the transition will then proceed to the “1” terminal vertex. If x is false,
then evaluation continues and the transition will proceed to y. Again, there is only one vertex for
y, and the precedent for being at vertex y is that the first term in the equation is false. Then, if y
is false, the second function is false, and the entire function is also false; the transition will then
proceed to terminal vertex “0”. If y is true, then evaluation continues by transitioning to vertex z.
Since vertex z is unique, the condition for being at the vertex is that the first term is false and y is
true, meaning that the overall function value will be determined by the value of z. If z is false,
then the second term is also false, making the overall function false; the transition then proceeds
12
to terminal vertex “0”. If z is true, then the second term is true, and the overall function is true;
the transition proceeds to terminal vertex “1”.
The usefulness of OBDDs for reducing the state explosion problem does have limitations,
though. One key issue faced in OBDD construction is that the resulting graphical structure is
directly linked to the variable ordering used in the Boolean equations being evaluated. The fact
that variables are evaluated in order can cause large variations in graph representation efficiency
among Boolean equations of the same structure. This problem is illustrated in Figure 1.4.
Figure 1.4: Variable Order Dependency in OBDDs
Consider a new equation, based on the one described in Figure 1.3, where the order of two of the
variables is changed. In both cases, the variable ordering w-x-y-z is used in evaluation, but vastly
different graph efficiencies result, even though the Boolean equation structure is the same. One
observation that can be made for this situation is that when related variables are not close
together in evaluation, the complexity of the graph grows. In the case of the new equation, w
and y are closely related, as well as x and z. But, both of these pairs of related variables are
13
separated in the variable evaluation ordering. Observations like this can be used as heuristics to
improve variable ordering, helping to maintain high efficiency in OBDDs.
As an example, Fujita, et al in [11] and Malik, et al in [12] present that a depth-first traversal of a
circuit being verified can often provide a reasonable variable ordering. In situations where
heuristics fail to give reasonable results, Rudell presents a solution in [13] called “dynamic
reordering”. In this solution, a “shifting algorithm” is periodically run within the OBDD in an
attempt to minimize it. In each shifting operation, given n variables, one variable is selected for
optimization and the order of the n-1 other variables is fixed. The position of the selected
variable is then shifted to a more ideal spot, out of the n possible choices. Additionally, further
enhancements to the OBDD model have been proposed by Brace, et al in [14]. Specifically,
more complicated sets of Boolean equations can be modeled as a multi-rooted OBDD, where the
different functions have opportunities to share sub-trees (instead of distinct single-rooted trees
for each equation).
1.2.2. SAT Modeling
OBDDs provide some mitigation of the state explosion problem, but they are still complete state-
space representations of a circuit being verified, and as such the model size can still quickly
grow too large as circuit complexity increases. Another approach that has been used to get
around this problem is modeling as satisfiability (SAT) problems. In this case, the circuit being
verified is modeled as a set of Boolean propositions, as opposed to a full expansion of design
states. One of the major methods for SAT problems is the Davis-Putnam method [15]. This
method consists of two parts. The first is the QFL-Generator, which uses the formula for the
14
property being verified to create a growing propositional calculus formula. The second part is
the Processor, which continually checks the propositional calculus formula for consistency. If, at
any point, the formula is found to be inconsistent, that provides a proof to the original formula
being verified. SATO is one implementation of a SAT solver that leverages the Davis-Putnam
method, as presented by Zhang in [16].
The process of checking a propositional calculus formula for consistency in this context involves
reduction of the formula via elimination of terms. This reduction is achieved with a variety of
rules. One-literal clauses can assist in reduction using the one-literal rule (also known as unit
propagation). This rule states that for a set of clauses, containing a unit clause (a clause that is a
single literal), each clause containing the unit clause can be eliminated and each occurrence of
the negation of the unit clause in other clauses can be deleted. The resulting reduced set of
clauses will be logically equivalent to the starting set. An example of this process is shown in
Figure 1.5.
Figure 1.5: Example of the One-Literal Rule in SAT
In this example, the one-literal clause is “x”. Therefore, each remaining clause in the set is
examined for inclusion of “x”. The clause “y˄z” does not contain “x”, and remains the same.
The clause “x˅z” contains an affirmative reference to x, and thus the clause is dropped. The
15
clause “⌐x˄y” contains a negative reference to x, so the negative reference to x is removed from
the clause. This then yields the reduced set of clauses {x, y˄z, y}.
Another rule for formula reduction is the affirmative-negative rule (also known as pure literal
elimination). This rule states that if a propositional variable only appears in a single form (either
affirmative or negated) across all uses in a set of clauses, then all clauses containing that variable
can be eliminated. If a propositional variable only appears with a single polarity (also called a
pure variable), then an assignment can always be made to make all clauses containing the pure
variable true.
A final rule that can be applied when the previous two rules have been exhausted is the splitting
rule, which allows for a re-structuring of clauses. Davis, et al examine this rule more closely in
[17]. The rule states that a formula F should first be put into the form of (A ˅ p) ˄ (B ˅ ⌐p) ˄ R.
This can be achieved by creating three groups of clauses; those containing p, those containing ⌐p
and those not containing p. p and ⌐p can then be factored out of the first two groups of clauses
to create the desired form. It can then be stated that formula F is inconsistent if and only if (A ˅
B) ˄ R is inconsistent. This can also be represented in another form, stating that formula F is
inconsistent if and only if A ˄ R and B ˄ R are both inconsistent. The splitting rule does,
though, also present one of the limitations of the model. The problem of how to select “p” for
splitting is difficult to solve, as the answer will vary depending on the model being verified.
Many heuristics exist to assist in selecting a reasonable “p”, as a poor selection of “p” can reduce
the performance of the Davis-Putnam SAT model by orders of magnitude.
16
1.2.3. Bounded Model Checking
A further technique for combating the problem of state explosion is Bounded Model Checking
(BMC), as introduced by Biere et al. in [18]. In the BMC technique, a limit of k is set on the
number of state transitions within which a property must hold. This means that the paths to be
searched in the model can have at most k + 1 states. Biere et al. also propose that in this model, k
should begin with a value of 0 (searching for a single state counterexample). k can then be
continually increased until either an imposed limit is hit, implying that there is no
counterexample, or a counterexample is found with a length of k + 1. This imposed upper limit
on k is information that would be provided by a user of the BMC system. As logic designers
generally know the bounds within which a given property should hold, expecting this input for
BMC is a reasonable assumption. Copty et al. investigated the effectiveness of BMC in an
industry setting in [19]. Portions of the Pentium 4TM
were used to test BMC with a SAT solver
against an OBDD symbolic model checker. BMC was found to provide improved productivity
over the OBDD solution, mainly due to the high amount of manual tuning required with OBDD
to optimize its performance.
1.2.4. Automatic Test Pattern Generation
Automatic Test Pattern Generation (ATPG) is another method that avoids the state-explosion
problem by employing a different approach to model checking. ATPG focuses on the stuck-at
fault model, which is designed to detect faults where a signal in the circuit being verified is stuck
at a constant value, regardless of circuit inputs. A Boolean model of the circuit being verified is
stored in memory, but a full state expansion is not required. This then presents the necessity to
have a method for modeling a circuit to be verified in memory for the ATPG algorithm to work
17
on. Armstrong presents a method for applying ATPG for combinatorial circuits in [20]. Hsiao
and Chia then extended this to implement a solution for ATPG in sequential circuits in [21].
One of the first ATPG methods was the D-Algorithm as introduced by Roth et al. in [22]. In this
method, combinations of primary input (PI) assignments are examined by making assignments at
internal circuit nodes, based on the fault being tested. A new logic value of “D” is introduced in
these assignments, which represents a value of 1 for a good circuit, when testing a stuck-at-0
fault ( D represents 0 when testing a stuck-at-1 fault). When working with a fault at some
internal net in a circuit, this method will both “propagate” the D value forward, and maintain
“consistency” by implying values back through the circuit based on propagated values. An
example of this is shown in Figure 1.6.
Figure 1.6: Propagation and Consistency in the D-Algorithm
Given a stuck-at-0 fault under test for net N, the first implication is that in a good circuit, gate 1
must output a 1 (D). This then requires inputs A and B to both be 1. Further, to observe this
fault on N, the value of D must propagate forward to output Z, passing through gate 2. For gate
18
2 to have a value of D on its output (Z), its other input must be 1, which implies that net P must
have a value of 1 to maintain consistency. That then requires gate 3 to have both its inputs be 1,
meaning that both net M and input D must be 1. Similarly, gate 4 must output a 1, implying that
input C must have a value of 0. This has then generated a complete assignment on all inputs.
One weakness in the D-Algorithm was first seen when exercising the method on circuits that
included error correction code (ECC) logic. With ECC logic, an XOR tree to compute parity
exists that is then reconvergent with the main logic being checked. This presents an efficiency
issue when testing a stuck-at fault in the main logic, as the entire ECC parity tree will need to be
evaluated to make a consistent assignment. To solve this problem, Goel presented the Path
Oriented Decision Making (PODEM) system in [23]. PODEM differs in approach from the D-
Algorithm, as instead of evaluating from the point of the stuck-at fault, it directly assigns PI
values and tracks their effects to generate a complete PI assignment. Initially, all PIs to the
circuit are assigned as “don’t care” (X). PODEM then chooses a PI to make an assignment on,
and implies that assignment forward through the circuit (similar to D-Algorithm propagation). If
the assignment made is consistent with the required stuck-at test, then further assignments are
selected, continuing until a complete assignment is made that satisfies the test. If an assignment
is determined to be inconsistent with the stuck-at fault being tested, that assignment will be
undone. One of the limitations of PODEM is that a good choice for what PI to assign and what
logic value to use are critical to finding a complete PI assignment without extraneous evaluation.
To assist with this Goel also presents heuristics for selecting a good assignment, which is based
on finding a gate which has the stuck-fault (D) as an input, a don’t care (X) on its output and is
close to a primary output (PO) of the circuit. The logic is then backtraced from this circuit to
19
find the closest PI related to that gate, which becomes the PI for which an assignment will be
made.
A further efficiency improvement of PODEM is the fan-out oriented test generation algorithm
(FAN), as presented by Fujiwara et al. in [24]. The core method used for improving efficiency is
by limiting the extent of back-trace operations. This is done using the concept of “head-lines”
and “fan-out points”. A head-line is a net in the circuit such that it is assigned a value of X (and
all of its generation logic is also assigned X), and it is adjacent to another net with an assigned
value. For example, a two input AND gate has one input with an assigned value, and another
input with an X value. This net would then be a head-line, which means that backtracing can
stop after a value assignment is made to the head-line. Since all final PI assignments associated
with the head-line assignment are directly implied by the head-line, they can be deferred until the
very end of the operation. Fan-out points are nets in the circuit that fan out to multiple gates.
These are convergence points, where consistency must be maintained while back-tracing, since
all of the fan-out points on the net must have values that do not present a conflict, or the
backtrace must be stopped and a new assignment will be tried. In FAN, backtracing is stopped at
the fan-out points, until all other objectives are exhausted. If one of the other objectives were to
present a conflict at a fan-out point, that will be detected, and a new assignment can be tried,
without having to have backtraced through all of the fan-out points.
Yet another efficiency improvement, building off of FAN, is the Structure-Oriented Cost-
Reducing Automatic TESt pattern generation system (SOCRATES) as presented by Schulz et al.
in [25]. One of the main ways that SOCRATES improves on FAN is by the addition of
20
implication learning. During value propagation, values that are being assigned are implied by
the original stuck-at value being propagated. SOCRATES evaluates these assignments to find
non-local implications; that is, implications that aren’t trivially determined by the normal FAN
implication procedures. These “learned” implications are then stored, such that they can help
speed up the future implication process.
21
1.3. Prior Work
Keller et al provided one of the first looks at the use of ATPG engines in [26], where they were
applied to general problems where a search space needed to be examined. Boppana et al
investigated the use of sequential ATPG for model checking in [27]. Their work focused on
safety properties and noted the fact that ATPG does not require explicit state-space storage
between time-frames as a major advantage. Cheng et al discussed the use of ATPG for property
checking in [28]. Their method involved mapping the property being checked into a
combinational circuit, where the output would be tested for a stuck-at fault.
Parthasarathy et al compared SAT and ATPG algorithms on combinational circuits in [29],
finding that there is no performance gap between the two. This comparison is extended by
Abraham et. al. in [30]. A software implementation for sequential ATPG was presented, and
tested on benchmark circuits for checking temporal logic properties. In this case it was shown
that ATPG outperformed SAT on smaller circuits, and further, SAT was unable to model some
of the largest circuits. Qiang et al show in [31] that even with ATPG, larger circuits can cause
software solvers to fail.
An effective way to push beyond these limitations is to leverage parallelism. Czutro et al applied
this idea with TIGUAN in [32]. TIGUAN applies a two-stage approach to SAT solving, where
the first stage is a single threaded run, quickly working out the easy to solve faults. The second
stage applies multi-threaded test generation to achieve a speedup on the hard to solve faults. Cai
et al extended the application of threading in [33]. By creating a system where test generation
22
and good/fault simulation were all threaded, they were able to achieve a linear speedup of
ATPG, up to the maximum of 8 CPUs used in testing.
Another way to approach parallelism is to take advantage of the inherent parallelism of
hardware. Sarmiento and Fernandez applied this method for fault emulation in [34]. By
translating a circuit under test onto reconfigurable hardware, they were able to take advantage of
hardware parallelism during propagation. This resulted in emulation being 27 to 2200 times
faster than the associated software-based simulation, in their testing. Dunbar and Nepal used a
similar strategy in [35], and found that by implementing multiple instantiations of a circuit under
test on an FPGA, they could reduce the final test pattern set by 13% on average, while
maintaining fault coverage and run time.
Abramovici et al apply emulation on reconfigurable hardware to a PODEM-like instance specific
SAT solver in [36], though only one objective is backtraced at a time. They put forth a new
architecture in [37] where multiple objectives are backtraced in parallel, taking greater advantage
of the parallelism available in hardware, and achieving an average 10x speed-up over software-
based solvers.
Gulati et al take this method further in [38], implementing an application specific SAT solver on
reconfigurable hardware. To achieve this, the Conjunctive Normal Form clauses of the problem
are split up into bins, which are then sequentially evaluated by the FPGA-based solver. This
allows very large problems, which normally may not fit onto an FPGA, to be evaluated with this
23
architecture. Ultimately, they demonstrated an average 17x speed-up over the best software-
based solvers.
Kocan and Saab also leverage reconfigurable hardware to implement a concurrent D-algorithm
in [39], handling both propagation and justification. They found this to be 3.25 to 14.8 times
faster than equivalent software, with higher speed-up for larger circuits.
This work extends the idea of reconfigurable hardware emulation to the more complex problem
of sequential ATPG. One of the unique core requirements of sequential ATPG is that multiple
frames must be modeled to account for the temporal aspect of the circuit. Like the previously
discussed works in reconfigurable hardware emulation, fine-grain massive parallelism is
leveraged to gain a significant benefit over software solvers.
24
2. Algorithm
The first step in designing an algorithm to support hardware emulation of sequential ATPG is
determining how to handle modeling the circuit being verified. Any sequential circuit can be
thought of as being composed of two parts, combinational logic and flip-flops (state elements).
To model the circuit’s behavior over time, it can be “unrolled” into an Iterative Logic Array
(ILA), as described by Abramovici et al in [40]. In this process, all flip-flops are removed from
the circuit, with their inputs and outputs being re-purposed as pseudo-primary inputs and outputs
of the circuit. The ILA consists of k instances of the circuit (where k is the search bound), with
each instance being referred to as a “time frame”. Each of these frames is connected together, in
order, by the state input/outputs from the removed flip-flops. This structure is illustrated in
Figure 2.1.
Figure 2.1: ILA Model of Sequential Circuit for k Time Frames
As part of the ILA modeling method, the property that is being checked is also transformed into
a structural monitor block on the primary outputs of the final frame of the ILA model. This
monitor is designed such that the property is achieved by assigning a value of 1 to “line k” (the
output of the monitor). Then, an ATPG-based justification algorithm can be applied to find a set
of conditions to satisfy line k = 1.
25
This property justification uses a PODEM-like approach to trace an objective on the output of a
frame, back to a set of required inputs to the frame. To distinguish the original combinational
inputs/outputs of the circuit from the new, state-based inputs/outputs, the originals are called
Primary Inputs and Primary Outputs (PIs and POs) and the state-based are called Pseudo-
Primary Inputs and Pseudo-Primary Outputs (PPIs and PPOs). The objective tracing function
within each frame is shown in Figure 2.2.
Figure 2.2: Objective Tracing Within a Frame
The algorithm works on one frame at a time, starting with frame k. As the first objective (line k
= 1) is traced back, any objective values that propagate to a PPI of the frame, then imply an
objective on the PPO of the previous frame that must also be traced. Objective values traced
back to PI values require no further justification, as these values can be set independent of the
time frame. Once all objective values for the current frame have been successfully traced back,
processing will make a decision on what more needs to be done. If only PI objectives were
traced back in the current frame (or the PPI objectives match an initial state PPI1), then the
algorithm has successfully found a test pattern to generate the original objective of line k = 1, and
is done. If there are any PPI objectives that require further justification, processing will move to
26
the previous frame in the ILA. This strategy is called Reverse-Time Processing (RTP), as
described by Marlett in [41].
If, while tracing objectives in a frame, a conflict is found (two objective traces require different
values on the same signal), a “Backtrack” operation will remove the conflicting assignment.
This will move processing back to the previous assignment. If there were no other assignments
remaining in the current frame, then processing will return to the prior frame (frame Ti+1) to get
back to the previous assignment. If conflicts are encountered such that line k = 1 cannot be
justified in frame k, then the algorithm fails. This decision flow is shown in Figure 2.3.
Figure 2.3: Algorithm Flow Diagram
The implementation of the algorithm flow chart shown in Figure 2.3 can be thought of in four
separate categories. The first category are decisions related to the current time frame; based on
27
the current state of objectives, should more processing be done on the current frame, or should
processing move to a different frame. These decisions fall to the “PI/PPI Decision Block”. The
second category consists of decisions based on objectives in the current frame; which objective
should be bracktraced, are there any conflicts and are all objectives satisfied. These are part of
the “Objective Decision Block”. The third category handles the “implication” portion of the
PODEM-based logic tracing. This is where current input objective values are propagated
forward through the circuit under test to verify the consistency of the output objective values
being traced. This is handled by the “Forward Network”. The fourth, and final, category
handles the “backtrace” portion of the PODEM-based logic tracing. This is where an output
objective value is backtraced to necessary objective values on inputs. This is handled by the
“Backward Network”.
28
3. The Architecture
As discussed in the previous section, the algorithm presented here can be divided up into four
discrete functional groups. These groups directly correspond to the different modules used in
implementing the algorithm on reconfigurable hardware. The required connections in the
algorithm flowchart then become data signals between each of the modules, as shown in Figure
3.1. The Verilog code implementing all of the modules described in this section is included in
Appendix D.
Figure 3.1: Top Level Architecture Block Diagram
The PI/PPI Decision Block controls time-frame based decisions, which are contingent on the
current state of objectives in the frame. Thus, the Objective Decision block communicates this
29
state using Done, Conflict, line_k_X, and line_k_1. The PI/PPI Decision Block must set up each
new time frame when moving to a new one, so it must set the new values in the Forward
Network (via the PI and PPI busses) as well as providing the objectives for the new frame to the
Objective Decision Block (via the ppi bus).
The Objective Decision Block is responsible for all objective-based operations. It must examine
the output of the Forward Network to ensure that all current objectives are consistent (via the PO
and PPO busses). When it selects the next objective to be worked on, it passes that objective to
the Backward Network over the obj bus. It must then also signal the PI/PPI Decision Block to
make a decision on the current frame, once the objective operations are complete.
The Forward and Backward Networks implement the logical tracing of objective values for the
circuit being tested. To maintain proper consistency when objectives are being backtraced, all
node values in the Forward Network must be passed to the Backward Network (via the STATE
busses). Finally, backtraced objective values from the Backward Network must be passed back
to the PI/PPI Decision Block for storage (via the in bus), as they represent objectives for the next
frame.
30
3.1 PI/PPI Decision Block
The PI/PPI Decision Block provides the central control system for the architecture, as well as the
main storage. As such, this block can be thought of in terms of two major components; the
control logic, and the results storage RAM. The full structure of this block can be seen in Figure
3.2.
Figure 3.2: PI/PPI Decision Block Structure Diagram
The results storage RAM component of the block is a 14 bit wide, by 8k deep FPGA block
RAM. The 14 bit word width of the RAM is fixed, based on a 14 bit objective encoding scheme,
described in section 3.2. The depth of the RAM is a variable limit on the total number of
objectives that can be stored, constrained by the available block RAM sizes on the FPGA being
utilized.
31
The control logic takes input signals from the Objective Decision Block (Done, Conflict,
line_k_1, line_k_X) and uses these to make decisions on how to proceed in the algorithm. These
decisions will result in one of four main operations performed by the PI/PPI Decision Block.
Inside the control logic is a state machine which executes these operations through multiple state
transitions. Table 3.1 summarizes these states and transitions.
State Transition(s) Operation Description
s0 init Idle / NoOp Waiting for external trigger.
s1 s16, s17 Make Decision Current frame assignment incomplete.
s2 s12 Pop Value Pop the top obj value from the RAM.
s3 s3, s7, s8,
s22 Frame Readout
Handle frame value readout when moving between
frames.
s4 s0 Set Top Mark Set frame top mark bit for move to frame Ti-1.
s5 s3 Move to Ti+1 Setup to start move to frame Ti+1 (back off frame).
s6 s12 Swap Val Swap the obj value of top word in current frame.
s7 s6, s9 Backtrack Return Handle returning from Ti+1 to Backtrack.
s8 s11 Start Counter Start counting up or down depending on cnt_dir.
s9 s12 Clear Val Clear top word from in current frame from RAM.
s10 s0, s2, s19 VF Assign (top) Assign current value on top into fwd value buffer
registers.
s11 s4 Stop Counter Stop counter after one decrement.
s12 s10, s18, s20 Backtrack Update Update VF based on last Backtrack operation.
s13 s13 (end) Fail Justification failed.
s14 s14 (end) Done Justification complete. Results in RAM.
s15 s3 Move to Ti-1 Setup to start move to frame Ti-1 (start new frame).
s16 s0 Done with Objs All objs in received. Push onto Forward Network.
s17 s10 Request Obj Request next obj from Backward Network Decoder.
s18 s5, s6, s9 Backtrack Op Selects current operation to perform in Backtrack.
s19 s10 Read RAM Read current addr in RAM.
s20 s10 VF Assign (ow) Assign current value on ow into fwd value buffer
registers.
s21 s9, s15 State Check Verify that current frame is unique before moving to Ti-1.
s22 s3 VF Assign (top) Assign current value on top into fwd value buffer
registers.
Table 3.1: PI/PPI Decision Block Control Logic States
The first major operation performed by the PI/PPI Decision Block is the “More Justification”
operation. This operation occurs when working inside a frame, once a new objective has been
32
backtraced, and new objectives are available on the Backward Network. Since the Backward
Network may have backtraced multiple new objectives, the goal of the “More Justification”
operation is to iterate as many times as necessary to push all objectives from the Backward
Network into the block RAM, and onto the Forward Network. The pseudo-code for this
operation is shown in Table 3.2.
while (in != 14’b11111111111111) begin
push in onto Block RAM;
push in[2:1] onto fwd buffer addr in[13:3];
signal back_encoder for next in value;
end
push fwd buffer values onto Fwd Network;
Table 3.2: More Justification Operation Pseudo-code
To achieve the function of this operation, four states act as operations in a loop, with an
additional state for operation when looping completes. The operation consists of a loop through
four states with an additional completion state, as illustrated in Figure 3.3.
Figure 3.3: State Transition Model of “More Justification” Operation
33
From the idle state of s0, when the Backward Network Encoder receives backtraced objectives
from the Backward Network, it saves them into a buffer and sets the NReady signal low. This
triggers the PI/PPI Decision Block to move into state s1. In this state, the PI/PPI Decision Block
sets the genobj signal high, which triggers the Backward Network Encoder to send an objective
value. The encoder scans through its buffer, starting from the last position of the objective
pointer (last objective sent out). If another objective is encountered, the 14 bit objective value is
pushed onto the in bus, back to the PI/PPI Decision Block. If the end of the buffer is reached (no
further objectives), in is set to all 1s. The PI/PPI Decision Block makes a transition based on
this. In the case where an objective value was set, the state moves to s17, where the objective
value on in is pushed into the block RAM. In the next clock cycle the state always proceeds to
s10, where the value that was just pushed into the RAM is also pushed through to the forward
network value buffers (within the PI/PPI Decision Block). The state then returns to s0; idle. In
the case where all 1s are set on in, the state moves to s16, which pushes all values in the Forward
Network values buffer onto the Forward Network, starting the “Imply” operation.
The second major operation of the PI/PPI Decision Block is “Move to Ti-1”. This operation is
triggered when all objectives in the current frame have been satisfied. In frame_k, this means
that the value on line_k=1 (signal line_k_1 high and line_k_X low). Beyond frame_k, this means
that all PPI objectives from the previous frame match the PPO values of the current frame (signal
Done high and Conflict low). The signals that trigger this operation are all generated by the
Objective Decision Block. The goal of the “Move to Ti-1” operation is to set up the system to
start working on the next frame in the justification. The “Move to Ti-1” operation consists of
three main parts. The first is state containment, where the assignment made in the current frame
34
is checked against all past frames to ensure a loop has not been encountered. The second is the
process of pushing all PPO objective values from the current frame out to the RF in the
Objective Decision Block, to be justified as PPIs in the frame that is being moved to. The third,
and last, is the clearing of the Forward Network, which then triggers the start of the “Imply”
operation. The pseudo-code for this operation is shown in Table 3.3:
//State Containment
while (addr != 14’b11111111111111) begin
if (top flag set) begin
if (current_frame == past_frame} begin
Stop Move to Ti-1;
Start Backtrack;
end
end
addr--;
end
//Push PPOs to Obj Dec Block
Reset addr to top;
while (!top flag set) begin
if (val at addr is PPI) begin
Push value to Obj Dec Block RF;
end
addr--;
end
//Clear Fwd Network
Set all values in Fwd Network buffer to 2’b11;
Push Fwd Network buffer values to Fwd Network;
//Update frame counter
frame_count--;
Table 3.3: Pseudo-code for “Move to Ti-1” Operation
The implementation of this operation utilizes 7 states in sequence, with 2 states having internal
loops to iterate on multiple objective values inside of and across frames. This logic flow is
shown in Figure 3.4:
35
Figure 3.4: State Transition Model of “Move to Ti-1” Operation
The triggering for the “Move to Ti-1” operation begins within the Objective Decision Block.
Whenever the “Imply” operation completes on the Forward Network (new PO/PPO values arrive
at the Objective Decision Block), these values are checked to see if the current objectives have
been met. If the system is currently in frame_k, then the only check is if line_k is 1. If so,
line_k_1 is set high and line_k_X is set low. If the system is beyond frame_k, then each PPO
value from the Forward Network is compared against each PPI value stored in the Objective
Decision Block’s RF. If all values match, then Done is set high and Conflict is set low. Once
this check completes positively, the Objective Decision Block sets the newframe_ready signal
high. This signal triggers the Backward Network Encoder, which controls the NReady signal.
The raising of the newframe_ready signal translates into a raising of the NReady signal, which
triggers the PI/PPI Decision Block to move out of idle. Given the signals set by the Objective
Decision Block, the PI/PPI Decision Block will begin the “Move to Ti-1” operation by moving to
state 21. This state implements the state containment check, as shown in Figure 3.5:
36
Figure 3.5: State Containment Check Implementation
The check keys off the fact that at the end of working on a frame, the full PI/PPI assignment for
that frame is contained in the buffer to the Forward Network (valuestofoward). A duplicate of
that buffer is used, called pastframevalues. A value from past frames stored in the block RAM is
read into pastframevalues each clock cycle. When the “top” mark bit is set on a value being read
out, this indicates that the last value read out was the last value of a complete frame, which
triggers the endofframe signal. When endofframe is set, the two sets of values in the buffers are
compared to check for an exact match, which becomes the statecheckresult value. If the end of
the values in the block RAM has not yet been reached, the values in pastframevalues will be
cleared and the next frames values will continue to be read in for another round of comparison.
If all values in the block RAM have been read out, and statecheckresult remains 0, the check
passes. When the check ends, either passing or failing, the donewithstatecheck signal will be
raised. When donewithstatecheck is raised, statecheckresult will determine the next state
transition; if 1, the state containment check failed, and the state will transition over to the
“Backtrack” operation – if 0, the state containment check passed, and the state will transition to
state 15 to continue the “Move to Ti-1” operation.
37
State 15 will always transition to state 3 on the next clock cycle. In state 3, the block RAM is
enabled in read mode, and one objective value per clock cycle is read out from the current frame.
These values are examined by the “isppi” module, which compares the address bits of the
objective to the number of PIs in the circuit to decide if the objective is a PPI. If the objective is
a PPI, the value is set on the ppi signal. This signal travels to the Objective Decision Block,
where the value will be read into the RF. When the “top” mark bit is encountered in the block
RAM, the current frame has been completely read out, and the endofframe signal is raised. This
triggers state 3 to transition to state 8.
State 8 enables the frame counter to count down (to track the move back by one frame to Ti-1) by
setting Cnt_enable high and Cnt_dir low. On the next clock cycle, the state will always
transition to state 11, which disables the counter by setting Cnt_enable low. As the counter is
allowed to run for one clock cycle, it will count down by 1, tracking to the new frame being
moved to; Ti-1. State 11 also sets the nclear signal to 2’b00, which triggers the valuestoforward
buffer to be cleared out, and the clear values to be pushed onto the Forward Network. This then
begins the next frame’s “Imply” operation. The PI/PPI Decision Block then completes one final
action by proceeding to state 4, which triggers the block RAM to set the “top” mark value on the
top word by setting rewrite1 high and rewrite0 low. This, then, marks the last word from the
frame pushed into the block RAM as the end of the current frame. The next clock cycle will
always transition back to state 0, idle, for the PI/PPI Decision Block to wait for its next trigger
based on the new “Imply” operation that was started.
38
The third major operation of the PI/PPI Decision block is “Backtrack”. This operation is
triggered by the Conflict signal from the Objective Decision Block. This signal being raised
indicates that either a PPO from the Forward Network conflicts with a stored PPI, or a
conflicting objective assignment has caused an objective propagation failure inside the Backward
Network. The “Backtrack” operation consists of two functions that are used in a complementary
fashion. The “Swap Val” function will change the value of the top objective between 0 and 1, as
well as set the “flag” bit to indicate that “Swap Val” has been run on this objective. The “Clear
Top” operation removes the top objective from the stack for the current frame. Whenever a
Conflict is encountered, any objectives that have already been swapped are cleared, and then the
next un-swapped objective value is swapped. This operation is detailed in the pseudo code
shown in Table 3.4:
//Clear Top
while (flag set on top word) begin
Rewrite top word: value=2’b11;
Push top to Fwd Network buffer;
Pop top off block RAM;
if (mark set on top word) begin
Start “Move to Ti+1” Operation;
end
addr--;
end
//Swap Val
Rewrite top word: swap value, set flag;
Push top to Fwd Network buffer;
Table 3.4: “Backtrack” Operation Pseudo-code
The “Backtrack” operation is implemented over a total of 7 states, with 4 handling the functions
and 2 handling the control flow (plus the idle state). This construction is show as a state
transition model in Figure 3.6:
39
Figure 3.6: State Transition Model of “Backtrack” Operation
The “Backtrack” operation begins external to the PI/PPI Decision Block, with a conflict in
objectives being detected. In one case, if a PPO value read out of the Forward Network
disagrees with a PPI value stored in the Objective Decision Block’s RF, the Conflict signal will
be raised and the newframe_ready signal will toggle. The toggling of newframe_ready triggers
the Backward Network Encoder to set the NReady signal low. In the other case, a new obj is
pushed onto the Backward Network. If this does not resolve into a change in the output of the
Backward Network by the next clock cycle, the Backward Network Encoder will time out and
raise the propfail signal and set delayed_nready. The propfail signal triggers the Objective
Decision Block to raise the Conflict signal. The delayed_nready signal will have the Backward
Network Encoder wait until the next clock cycle before setting NReady low, which allows time
for the Objective Decision Block to receive propfail and assert the Conflict signal.
Once the PI/PP Decision Block receives the NReady signal, it is triggered to leave the idle state,
s0. In this case, with Conflict set, there are three possible transitions that it could make. If the
40
current top word on the block RAM has its “mark” bit set, the “Move to Ti+1” operation will
start, as the “mark” bit indicates that the current top word is the last of a previous frame.
Otherwise, a function will be run on the top word based on its “flag” bit. If the “flag” bit is not
set, the value will be swapped, the “flag” bit will be set and the word will be written back to the
block RAM. If the “flag” bit is set, this word has already been swapped, so the value will be
cleared (set to 2’b11), the clearvaluescheck control var will be set and the word will be written
back to the block RAM. Both states then transition on to state 12.
State 12 acts as the main control state for the “Backtrack” operation. State 12 will always set the
control value sendvaluestoforward=0, which will suppress any value updates in the Forward
Network buffer from being sent through to the Forward Network. This allows for multiple value
updates (ie, “Clear Val” and then “Swap Val”) before finally triggering the Forward Network
with a new “Imply” operation. When first visiting state 12, no control bits are set, so the process
continues on to state 10. In state 10, the current top word value is pushed to the valuestoforward
buffer. If the previous function that was run was a “Swap Val”, then the operation is complete
and the state will transition back to the idle state s0. In this transition the sendvaluestoforward
control value will be set back to 1, which will then trigger the “Imply” operation to start onto the
Forward Network with the updated values on the Forward Network buffer. If the previous
function run was “Clear Val”, then the clearvaluescheck control value was set, which will cause
state 10 to transition to state 2 (clearvaluescheck will also be set back to 0 at this point).
State 2 will begin a pop operation in the block RAM, which will remove the current top word
from the stack. The popcheck control var will be set to 1 at this point, and the process will then
41
transition back to state 12. On this second visit to state 12, the control var popcheck has been set,
which will cause state 12 to redirect the process flow to state 18 (as well as resetting the
popcheck var to 0). In state 18, the new top word will be examined to determine what function
runs next (the same initial decision that was made transitioning out of state 0). If the “mark” bit
is set, the “Move to Ti+1” operation will start. If the “flag” bit is set, processing will return again
to state 9 to clear this word. In the default case, neither bit is set, indicating a fresh word.
Processing will then proceed to state 6.
In state 6, the value of the top word will be swapped and written back to the block RAM, along
with the “flag” bit being set. The process continues on, back to state 12. This time through,
again no control vars are set, so processing continues on to state 10. Assuming that this time
through, state 6 was visited and a value was swapped, the clearvaluescheck control var will not
be set and processing will finally return to state 0. As part of this transition, the
sendvaluestoforward control value will be set back to 1, which will trigger the updated Forward
Network buffer to send its values onto the Forward Network, beginning a new “Imply”
operation.
The fourth major operation of the PI/PPI Decision Block is “Move to Ti+1”. This operation is
called as part of the “Backtrack” operation, when all objectives in the current frame have been
exhausted. That is triggered when the top word on the block RAM has its “mark” bit set,
indicating that it is the last objective of the previous frame in the stack. The core function of the
“Move to Ti+1” operation is to restore the state of the system to what it was at the end of the
previous frame in the stack (Ti+1). The first step to accomplish this is to un-mark the top word
42
for frame Ti+1. Then, all objective values in frame Ti+1 need to be read back onto the Forward
Network. Finally, all PPI objective values from frame Ti+2 need to be loaded back into the RF in
the Objective Decision Block. Once this is complete, the “Bracktrack” operation which started
the “Move to Ti+1” operation can continue. The function described here is illustrated in pseudo-
code in Table 3.5:
Rewrite top word: mark=1’b0;
//Read Ti+1 objs to Fwd Network Buffer
while (!endofframe) begin
Read obj at block RAM addr to Fwd Network Buffer;
addr--;
end
//Read Ti+2 PPIs to Obj Dec RF
while (!endofframe) begin
if (val at addr is PPI) begin
Push val to Obj Dec Block RF;
end
addr--;
end
//Update frame counter
frame_count++;
//Return to Backtrack operation
Return to calling Backtrack;
Table 3.5: “Move to Ti+1” Operation Pseudo-code
The “Move to Ti+1” operation is implemented in a total of 4 states. One handling the starting
unmarking of the top word, another handling the frame counter update and return to “Backtrack”,
and the remaining two handling the looping read-out of objectives from the block RAM. The
processing flow of these states is shown with state transitions in Figure 3.7:
43
Figure 3.7: State Transition Model of “Move to Ti+1” Operation
The “Move to Ti+1” operation always starts coming from a “Backtrack” operation, where the top
word on the block RAM has its “mark” bit set, indicating that all objective words for the current
frame have been exhausted. The first way for this to occur is transitioning from state 0. If the
Conflict signal is set, as discussed in the startup of the “Backtrack” operation, but the top
objective word on the block RAM has its “mark” bit set, processing proceeds directly into the
“Move to Ti+1” operation, going to state 5. The alternate case is when the “Backtrack” operation
is proceeding, but after clearing all “flagged” objectives, the next one encountered on the block
RAM has its “mark” bit set. In this case, state 18 in the “Backtrack” operation will transition to
state 5 to start up the “Move to Ti+1” operation, so that “Backtrack” can continue.
State 5 completes a rewrite operation for the top word in the block RAM, reading the word out,
setting the “mark” bit to 1’b0 and then writing it back to the same address. Once the unmarking
is complete, state 5 transitions to state 3 in the next clock cycle. State 3 handles reading out
objectives from the memory to restore the system state to that of the previous frame. It puts the
44
block RAM into read mode, sets the current addr to the top word on the block RAM, and will
decrement addr every clock cycle, to read out one objective per cycle. When first transitioning
to state 5, the blockisppi2 control var is set, which blocks the output of the RAM from being
evaluated by the “isppi” block (forwarding PPIs to the Objective Decision Block RF). The first
set of objectives to be read out is frame Ti+1, so nothing goes through “isppi” to the RF. Since
blockisppi2 is not set, each clock cycle the process transitions to state 22. In this state, the
objective word that was just read out of the block RAM (into the top signal) is assigned into the
Forward Network buffer. State 22 then always transitions back to state 3 for the next clock
cycle.
In state 3, once the first “mark” bit is encountered while reading off objective words, the
blockisppi2 control var is set to 0. This “mark” bit indicates that the addr is now pointing into
frame Ti+2, so objective words should no longer be assigned into the Forward Network buffer and
should instead be passed through “isppi” to the Objective Decision Block RF. Processing will
now stay in state 3, as each clock cycle a new objective word is read from the block RAM into
the top signal, which feeds into the “isppi” block. For each of these objective words, if their
address value is greater than the number of PIs in the circuit under test, the objective value will
be forwarded on to the Objective Decision Block via the ppi signal, where it will be read into the
RF.
When the second “mark” bit is encountered in state 3, processing will proceed to state 7. The
second “mark” bit indicates that the current address is pointing into frame Ti+3, so there are no
more objective words to be read out in this operation. State 7 enables the frame counter to count
45
up by setting Cnt_enable to 1’b1 and Cnt_dir to 1’b1. The “flag” bit on the top word in the
block RAM is then examined to decide on which state in the “Backtrack” operation to return to.
If the “flag” bit is set, the current objective words has already been swapped, so processing
transitions to state 9 to clear the value and continue on in the “Backtrack” flow. If the “flag” but
is not set, the current objective has not yet been swapped, so processing transitions to state 6 to
swap the value and continue with “Backtrack”. Note that both state 6 and state 9 set Cnt_enable
to 1’b0, disabling the counter, which locks the counter back in after incrementing by 1 to track to
the new current frame.
46
3.2 Objective Decision Block
The Objective Decision Block serves as the main interface between the Forward Network and
Backward Network; providing two core functions. The first is selection of objective values to be
pushed onto the Backward Network as input to the Backtrace operation. The second is signaling
the PI/PPI Decision Block as to the status of objective satisfaction within the current frame being
operated on. To provide these functions, the Objective Decision Block must store a full set of
objectives for the current frame. To this end, the heart of the Objective Decision Block is a
register file which is sized to be able to contain as many objectives as there are PPI/PPOs in the
circuit under test (l). The high level structure of implementation for the Objective Decision
Block is illustrated in Figure 3.8:
Figure 3.8: Objective Decision Block Structure Diagram
Storing objectives for the current frame is an important action in the Objective Decision Block
which is the first action taken when a new frame is being evaluated. When the PI/PPI Decision
Block begins moving to a new frame, a signal will be sent to the Objective Decision Block. In
the case of moving to frame Ti+1, the tiplus1 signal will be set to 1. In the case of moving to
47
frame Ti-1, the output signals from the “State Check” sub-module of the PI/PPI Decision Block
will provide indication to the Objective Decision Block (donewithstatecheck=1’b1 and
statecheckresult=1’b0 indicates a successful move to frame Ti-1). When this “new frame” signal
is received, any current values in the RF are flushed out, replacing all words with 14’b0.
After the RF has been cleared out, the PI/PPI Decision Block begins shifting all objectives for
the current frame to the Objective Decision Block over the ppi bus. The idle state for the ppi bus
is 14’b11111111111111, so any time this is assigned to a different value, that indicates that a
new objective word is being pushed from the PI/PPI Decision Block. This value will then be
read from the ppi bus into the Objective Decision Block RF. The reading process involves
decoding the objective word, to insert the objective value into the proper associated RF address.
Since the value of the address represents the position of the objective value across all PIs and
PPIs, the address must be corrected by the number of PIs in the circuit under test (represented by
the parameter m). This shifts the address of the objective word to have a value from 0 to l, which
matches the size of the Objective Decision Block RF. This value read-in operation is illustrated
in Figure 3.9:
48
Figure 3.9: Objective Decision Block PPI Objective Read In
Selection of an objective value to begin a ‘Backtrace” operation with can be broken down into
two distinct cases. The first, simpler, case is when operating in frame k. In this case, there are
no PPI values from a prior frame to be satisfied; there is only one objective, which is the base
objective that the test is attempting to find a pattern for; line_k = 1. With line_k being the first
PO (based on the bit order of the PO bus), the objective is assembled with an address component
of 0, and an objective value of 1 (encoded with the standard three-value 2-bit encoding as 10).
The “flag” and “mark” bits are set to 0, as the PI/PPI Decision Block is the only place where
these bits can be modified to 1. The assembly of this bit data into the 14-bit objective word
format is shown in Figure 3.10:
49
Figure 3.10: Assembly of Frame-k Objective Word
The second, more complicated, case for selecting an objective is in a frame other than frame k.
In this case, there is a set of objectives that must be satisfied for the current frame; so the
Objective Decision Block must evaluate the current satisfaction of objectives in the frame and
select the next un-met objective for Backtrace. This evaluation occurs as a logical comparison
between the current fame objective values in the RF against the current PPO values from the
Forward Network. These comparisons can all occur in parallel, as shown in Figure 3.11:
50
Figure 3.11: Objective Decision Block Conflict/Done Decision Logic
The results of all comparison operations are combined together to produce composite Done and
Conflict signals. Done indicates that all current frame objective values match their associated
values on the Forward Network PPO, hence the current frame is completely satisfied. Conflict
indicates that a value on the Forward Network PPO is incompatible with the associated current
frame objective in the RF. If either Done or Conflict is set, then the newframe_ready signal will
also be toggled. This is seen by the Backward Network Encoder, which subsequently sets the
NReady signal low. The setting of the NReady signal triggers the PI/PPI Decision Block to start
51
evaluation. When Done is seen while operating outside of frame k, a Move to Ti-1 operation will
begin. When Conflict is seen outside of frame k, the PI/PPI Decision Block will take corrective
action via the “Backtrack” operation.
In the case where neither the Done or Conflict signal is set, more justification is required for the
current frame. This situation will trigger the sequencer to select a new objective value to start a
“Backtrace” on. The sequencer examines each objective value in the RF, until one is found
associated with an “X” (2’b11) value on the Forward Network PPO. This objective value is then
selected as the next objective to be pushed to the Backward Network for “Backtrace”. This
function of the sequencer is illustrated in Figure 3.12:
Figure 3.12: Objective Decision Block Sequencer Operation
52
In addition to selecting objective values, the Objective Decision Block is responsible for
maintaining state control signals that are output to the PI/PPI Decision Block. These include
Done and Conflict (as previously discussed), as well as line_k_X and line_k_1. Similar to how
Done and Conflict provide signaling to the PI/PPI Decision Block when not in frame k, both of
the line_k_* signals are used when in frame k. If the value of line k currently coming out of the
Forward Network is X/2’b11 (this is the state after initial reset), the Objective Decision Block
sets the objective of line_k=0, and also sets the line_k_X signal to the PI/PPI Decision Block. In
frame k, line_k_X will trigger the PI/PPI Decision Block to accept backtraced objective values
that will be coming from the Backward Network based on the selected objective. If in frame k,
and the value on line k from the Forward Network is 1, then frame k is completely satisfied. The
line_k_1 signal is set, and the newframe_ready signal is toggled. The toggle of newframe_ready
is detected by the Backward Network Encoder, which will consequently set the NReady signal
low. This then triggers the PI/PPI Decision Block, reading line_k_1 in frame k, causing a “Move
to Ti-1” operation to start.
One final control signal interlock managed by the Objective Decision Block is the propfail
signal, originating from the Backward Network Encoder. When an objective pushed onto the
Backward Network as part of a “Backtrace” operation does not produce any objective values, an
objective propagation failure has occurred. When this happens, a “Backtrack” operation is
needed from the PI/PPI Decision Block to undo the cause of the propagation failure. So, when
the Backward Network Encoder detects a propagation failure, the first action it takes is sending
the propfail signal to the Objective Decision Block. This signal triggers the Objective Decision
Block to set the Conflict signal. The Backward Network Encoder’s next action is then to set the
53
NReady signal low. This causes the PI/PPI Decision Block to begin an operation. As the
Conflict signal has been set, the PI/PPI Decision Block will begin the needed “Backtrack”
operation.
54
3.3 Forward Network Derivation
One important facet of the algorithm described here is the need to model 0, 1 and X values in the
circuit, and hence the need for signals in the network to be represented by 2-bit values. This
means that to be modeled in this architecture, circuits under test must first be transformed into
two-bit equivalent networks to be compatible. The more straightforward of the two required
network translations is the Forward Network, as it is a direct mapping of function from one bit to
two.
In mapping the Forward Network, the representations that will be used are 01 as a logic 0, 10 as
a logic 1 and 11 as a logic X. The first step in translation is to expand a gate’s one-bit truth table
into a full form, including the value X in all possible combinations. This expansion is shown in
Table 3.6, using an AND gate as an example.
A B Y
0 0 0
0 1 0
0 X 0
1 0 0
1 1 1
1 X X
X 0 0
X 1 X
X X X
Table 3.6: Full One-Bit Truth Table for AND Gate
The fully expanded truth table can then be directly mapped into a two-bit representation. Note
that in this translation to two-bit representation, the meaning of X changes. Xs from Table 3.6
are translated to 11, but since 00 is an unassigned value in the Forward Network, when either A
55
or B is 00, the output will be “don’t care” or X. Table 3.7 continues the example of this using an
AND gate.
A1 A0 B1 B0 Y1 Y0
0 0 0 0 X X
0 0 0 1 X X
0 0 1 0 X X
0 0 1 1 X X
0 1 0 0 X X
0 1 0 1 0 1
0 1 1 0 0 1
0 1 1 1 0 1
1 0 0 0 X X
1 0 0 1 0 1
1 0 1 0 1 0
1 0 1 1 1 1
1 1 0 0 X X
1 1 0 1 0 1
1 1 1 0 1 1
1 1 1 1 1 1
Table 3.7: Two-Bit Truth Table for AND Gate
The expanded two-bit truth table can then be broken up into two separate Karnaugh maps, one
for the output bit Y1 and another for the output bit Y0. Table 3.8 continues the example using
the AND gate, showing the associated K-maps with minimum groupings highlighted.
Table 3.8: Split K-maps for AND Gate Output Bits
56
From these Karnaugh maps, minterm expressions can be derived for both Y1 and Y0. Note
again that 00 is an unassigned value in the Forward Network, thus Xs are assigned to those spots
in the K-map, which can then be used to extend minterm groups for further simplification. Table
3.9 completes the example using the AND gate.
Y1 = A1 B1 Y0 = A0 + B0
Table 3.9: Minterm Expressions for AND Gate Output Bits
Using this method for each of the three basic gates, a full set of translation equations for the
Forward Network can be obtained. These equations are summarized in Table 3.10.
AND Gate OR Gate NOT Gate
Y1 = A1 B1
Y0 = A0 + B0
Y1 = A1 + B1
Y0 = A0 B0
Y1 = A0
Y0 = A1
Table 3.10: Forward Translation Equations for Basic Gates
57
3.4 Backward Network Derivation
The more complex of the two network translations is the Backward Network, due to the fact that
the function of each gate must be transformed, as opposed to being directly mapped between bit
representations. One important consideration in backtracing is that consistency must be
maintained. That is, if a backtrace is attempting to assign a value in the Backward Network that
does not match a value for that node that has already been assigned in the Forward Network, that
assignment must be prevented. In the context of backtracing through a gate, this means that
propagating an objective value requires the corresponding signal be “don’t care” (X) in the
Forward Network. This can either be implemented as a check against the inputs of each gate
being evaluated, or the output of each gate being evaluated. Here, the output of each gate is used
as the check to minimize the number of required consistency checks. This dependence is
illustrated in Figure 3.13.
Figure 3.13: Abstract Backward Gate Values Dependence
From this abstract model of a gate in the Backward Network, a functional definition must be
defined. To this end, pseudo-code defining the values for the A and B outputs can be defined, as
in Table 3.11.
58
A Obj Output
If (Z_obj is required obj) then
If (Z_fwd = X) then
A_obj = Z_obj
End
End
B Obj Output
If (Z_obj is required obj) then
If (Z_fwd = X) then
If (Z_obj = 1) then
B_obj = Z_obj
End
End
End
Table 3.11: Pseudo-code for AND Gate Backward Model Outputs
Note that the behaviors of the A and B objective values differ based on the Z objective value.
This is based on the requirement to complete a minimized backtrace operation. In the case of the
AND gate, when an objective value of 1 is required on Z, both A and B must also have a
required objective value of 1 to achieve this. When an objective value of 0 is required on Z,
however, only one input needs to be 0 to achieve this. In this case, A is used for propagating the
required objective of 0 and B is ignored.
The next step from this point is to derive a truth table to model the described functionality of this
gate. One important point in modeling this gate is that while the A/B state inputs from the
Forward Network already have a format definition (0=01, 1=10, X=11), the objective
inputs/outputs that are part of the flow of the Backward Network need a separate format. This is
required because while the Forward Network models 3 signal values, the backward network must
model 2 signal values, as well as whether or not the value is a required objective being
backtraced. To this end, the Backward Network also uses 2-bit representations of signals, where
59
the higher order bit represents whether a value is an objective (1=yes, 0=no) and the lower order
bit represents the value of the signal. Using this signal modeling, the truth table for a backward
model of a gate can be derived, as illustrated in Table 3.12 continuing the AND gate example.
Z_obj_1 Z_obj_0 Z_1 Z_0 A_obj_1 A_obj_0 B_obj_1 B_obj_0
0 0 0 0 X X X X
0 0 0 1 X X X X
0 0 1 0 X X X X
0 0 1 1 X X X X
0 1 0 0 X X X X
0 1 0 1 X X X X
0 1 1 0 X X X X
0 1 1 1 X X X X
1 0 0 0 X X X X
1 0 0 1 1 0 0 0
1 0 1 0 0 1 1 0
1 0 1 1 1 0 0 0
1 1 0 0 X X X X
1 1 0 1 0 0 0 1
1 1 1 0 1 1 0 1
1 1 1 1 1 1 1 1
Table 3.12: Truth Table for Backward Model of AND Gate
Many of the output values defined in the truth table are “don’t care”, since this will occur for
cases where the objective Z value is not a required objective, or if the Z value in the Forward
Network is in an unassigned/illegal state (00). This indicates that equations defining this
backwards gate model are likely to have a reasonably compact final form. In this case, the
pseudo-code presented earlier can be directly translated into the simplified Boolean equations
defining the backward model of the gate, as shown in Table 3.13:
60
AND Gate OR Gate NOT Gate
A1 = Z1 Z0 Zo1
A0 = Zo0
B1 = Z1 Z0 Zo1 Zo0
B0 = Zo0
A1 = Z1 Z0 Zo1
A0 = Zo0
B1 = Z1 Z0 Zo1 ! Zo0
B0 = Zo0
A1 = Z1 Z0 Zo1
A0 = ! Zo0
Table 3.13: Backward Translation Equations for Basic Gates
Since in the Backward Network encoding, the value is completely represented by the “0” bit, that
value can always be directly passed from the gate output to the gate inputs (inverted in the case
of NOT). The real decision being made in the backward model is with the “1” bit, whether or
not the required objective propagates. For all inputs, the Forward Network gate value must be X
(Z1 = 1, Z0 = 1). For the “A” input, the current output objective value in the Backward Network
must also be 1 (Zo1 = 1). For the “B” input, on top of all previous checks, the value of the
required objective in the Backward Network must be such that all inputs of the gate must be set
to achieve the objective (Zo0 = 1 for AND, Zo0 = 0 for OR).
3.4.1 Backward Network Fanout Handling
One added complexity in the Backward Network is logic fanout. The output of one gate driving
multiple inputs is a fairly common occurrence in the forward logic, but this presents a problem in
the Backward Network. When the logic flow is reversed, this would result in multiple gate
outputs driving single inputs, resulting in contention on the input, as illustrated in Figure 3.14.
61
Figure 3.14: Backward Fanout Signal Contention
An important consideration in resolving this issue is that delay through different paths will vary,
so different values may arrive at the fanout junctions at an arbitrary time. This opens the
possibility of having transient value states at the junction that could potentially propagate value
glitches to the output. To behave like a single input / single output node, these multiple input
backward nodes must switch once and retain that value until the backward network inputs are
changed. To this end, a priority encoder scheme is employed, such that the first objective value
to arrive at a multiple input node is locked in on the output and any further input changes are
blocked from propagating.
Since signals in the Backward Network are composed of two bits, one determining if a value is a
required objective and the other carrying the objective value, the priority encoding scheme will
require two modules. The first module will generate the higher order, required objective bit.
This is the simpler of the two from an implementation standpoint. The first time a required
objective arrives to the priority encoder, the 1 value should pass through to the output and lock in
62
at that value. This can be implemented in a straightforward way by using an OR gate to merge
required objective signals, and a feedback of the output to lock in a value of 1. This structure is
illustrated in Figure 3.15.
Figure 3.15: Priority Encoder Structure for Required Objective Bit
This architecture does present one additional challenge, though. With the loopback value lock
directly feeding back into its own generating OR gate, this effects a permanent lock of the gate
output value. Given that the Backward Network will be required to execute many backtraces in
any given justification operation, there needs to be a way to unlock these priority encoded
values. This can be implemented by a new priority_reset signal that is ANDed together with the
Final Req Obj output before the loopback value lock. In normal operation, the priority_reset is
held at 1, which allows the Final Req Obj to pass through. When the Backward Network values
need to be cleared out, the priority_reset signal is set to 0, which causes the loopback value lock
to reset. The priority encoder is then reset to an unlocked state, and is ready to re-lock when the
next required objective propagates. This addition to the structure is illustrated in Figure 3.16.
63
Figure 3.16: Priority Encoder Structure for Required Objective Bit with Reset
The second module will generate the lower order, objective value bit. This structure will be
slightly more complicated, because in addition to combining and locking values, values must
only pass through to the final locking stage if their corresponding required objective bit is set.
Given the requirement of the value passing with a control signal of 1 and being blocked with a
control signal of 0, a simple AND between the required objective bit and objective value bit will
generate the output value bit into the combination logic. These output value bits will remain 0
except in a case where a required objective of 1 arrives at the input of the node. In that case, the
corresponding output value bit will reflect the input objective value bit. When this happens, the
value must pass through as the final value bit into the locking logic. To achieve this, all output
value bits are ORed together. Since all non-required objective bits are locked to 0, this then
allows the value of the now required objective to pass through this stage of logic as well. This
structure is illustrated in Figure 3.17.
64
Figure 3.17: Priority Encoder Structure for Objective Value Bit
This half of the priority encoder will require locking and reset logic as well. One important note
in considering this implementation is that unlike the required objective bit, the objective value bit
does not have a set transition when it needs to be locked. For this reason, the locking bit from
the required objective bit must also be used to control value locking for the objective value bit.
Since both halves of the priority encoder share common locking and reset control signals, the
final structure can be represented in a single, complete unit, as shown in Figure 3.18.
Figure 3.18: Complete Structure for Backward Network Priority Encoder
65
This final structure achieves the required goal for resolving fanout node values in the Backward
Network. When the backward network is idle / cleared, the priority encoder passes through the
required objective bit of 0, and a 0 value bit. When a required objective value arrives at the
encoder, if the encoder is unlocked, the objective value will pass through the required AND filter
and the OR value combination and be output as the final objective value. The required objective
bit will pass through the OR value combination and be passed on to the output as the final
required objective bit. This signal will also lock in both the objective value bit and required
objective bit, so that further input changes are blocked from effecting the priority encoder output,
and hence the final network outputs. Finally, the priority reset signal serves to unlock the
priority encoder, so that the next new required objective can be locked in, by forcing the lock
value bit to 0, and allowing values from the inputs again to pass through to the outputs.
3.4.2 Backward Network Conflict Detection
While backtracing an objective, it is possible for a conflict to occur. This is a situation where a
prior objective in the same frame requires the output of a gate to be the opposite of the current
objective’s requirement. Since the Backward Network is designed to produce a single minimal
objective assignment, a conflict condition means that the frame can not converge with its current
set of objectives.
There are two possible conflict scenarios that can occur in backtracing. The first, as shown in
Figure 3.19 is a trace-blocking conflict. In this situation, the objective Z2=0 is backtraced first,
generating two new objectives (A=1, C=0). The second backtrace is for the objective Z1=1,
which encounters a conflict on the assignment of the output of G1. As this is the only active
66
backtraceing path for Z1, propagation is completely blocked. With the objective propagation
blocked, no new values are propagated through to the Backward Network Encoder module. The
Objective Decision module is signaled (via the prop_fail signal), causing it to raise the Conflict
signal.
Figure 3.19: Trace-blocking Conflict
The second possible conflict scenario, as shown in Figure 3.20, is the non-blocking conflict. In
this situation, the first objective backtraced is Z1=1. The second objective is Z2=0. This
objective requires the output of G3 (an OR gate) to be 0, hence all inputs must propagate the
objective of 0. Like in the previous example, a conflict occurs at the output of G1, but in this
case there are two active backtracing paths. While the path backtracing to A=1 is blocked, the
path backtracing to C=0 is not, so the Backward Network Encoder module still receives an
objective. The Backward Network Encoder will then provide this objective to the PI/PPI
Decision block as normal. Once the PI/PPI Decision Block pushes the new set of objectives to
the Forward Network, though, the Objective Decision block will see that the objective of Z2=0
67
was not achieved (it will remain 1 due to the output of G1). This will then directly cause the
Objective Decision block to raise the Conflict signal.
Figure 3.20: Non-blocking conflict
3.4.3 Backward Network Decoder
Due to the previously described need for the Backward Network to use a different value
encoding from the rest of the circuit, encoding and decoding modules are needed as wrappers
around the Backward Network. The Backward Network Decoder module acts as the interface
between the Objective Decision Block and the Backward Network. In addition to translating
objective value encoding between these two blocks, the decoder must also handle resetting the
priority encoding logic that is used to lock in values inside traces in the Backward Network. The
entire operation to assign a new objective takes 3 clock cycles to complete, implemented as a
state machine (controlled by the mode register) as shown in Figure 3.21:
68
Figure 3.21: State Transition Diagram for Backward Network Decoder
Operation in the Backward Network Decoder is triggered by a change in the obj_set signal from
the Objective Decision Block (a new objective value has been assigned to be backtraced). This
causes the decoder to move from idle into the Backward Network reset state. In this state, the
priority_reset signal is toggled, which causes priority encoder value locks within the Backward
Network to release. At the same time, all PI/PPI input values to the Backward Network are
cleared (value 2’b00) to flush out the network for a fresh value trace.
On the next clock cycle, the decoder moves into the assignment state. In this state, the decoder
makes an assignment to each PI/PPI Backward Network input bit. For the bit that corresponds to
the address in the new obj from the Objective Decision Block, that value is assigned into the
PI/PPI bus as a required objective. For all other bits, values are directly assigned from the
corresponding PO/PPO values output by the Forward Network. These values are not required
objectives, so their higher order “objective” bit is set to 0. This value assignment is detailed in
Figure 3.22:
69
Figure 3.22: Backward Network Decoder Value Assignment
Each address in the PI/PPI Backward Network input bus is compared to the address contained in
obj[13:4]. When these match, the associated objective value (obj[2]) is assigned into that PI/PPI
bus bit as a required objective (lower order bit is set to obj[2]; higher order bit is set to 1’b1).
For any other bits, the associated higher order bit on the PO/PPO output bus from the Forward
Network is assigned through into the lower order bits on the PI/PPI Backward Network input
bus. Note that because of the way values are encoded outside the Backward Network, and
because the Backward Network only deals with 0/1 (not X), the higher order value bit will
always represent the binary value of that 3-state value.
Once all bits in the PI/PPI Backward Network input bus have been assigned, the trace_start
signal is toggled. This signal is output to the Backward Network Encoder, and notifies it that a
new backtrace has started, so the Backward Network outputs should be monitored for a value
change. After toggling the signal to the encoder, the decoder returns to an idle state.
70
3.4.4 Backward Network Encoder
The Backward Network Encoder operates on the opposite side of the Backward Network, taking
the output from the Backward Network, encoding it back into the 14-bit objective scheme of the
architecture, and passing the data on to the PI/PPI Decision Block. In addition to value
translation, the encoder must also be able to track the output values of the backward network to
detect when a backtrace operation has failed to produce results. In order to implement these
functions, the Backward Network Encoder is constructed via three states (tracked by the state
register), as illustrated in Figure 3.23:
Figure 3.23: State Transition Diagram of Backward Network Encoder
The Backward Network Encoder begins operation in the idle state. When a “Backtrace”
operation is started by the Backward Network Decoder, the trace_start signal is toggled. This
signal triggers the encoder to move to the “check” state. At the start of the next clock cycle, in
the check state, the current output of the Backward Network is compared against the last saved
output from the network (the decoder saves the values output from the Backward Network every
cycle that it is not in the “check” state). If the values differ, that indicates that the “Backtrace”
operation successfully produced results. If that is the case, the higher order outputs bits are then
checked to ensure that at least one is set to 1’b1 (indicating a required objective). Once that has
been verified, the encoder moves on to the “shiftout” state. If the output values from the
71
Backward Network have not changed, or there are no required objectives, that indicates a
“Backtrace” propagation failure. The propfail signal is set, which triggers the Objective
Decision Block, which in turn triggers the PI/PPI Decision Block to start a corrective
“Backtrack” operation.
The “shiftout” operation is where communication of objective values happens between the
Backward Network Encoder and the PI/PPI Decision Block. Each objective value saved from
the Backward Network is sequentially shifted out to the PI/PPI Decision Block over the in signal
bus. Because the operation of the PI/PPI Decision Block to write a received objective value into
the block RAM takes multiple clock cycles, the triggering signals NReady and genobj are used to
communicate readiness in the operation. The structure of this communication is illustrated in
Figure 3.24:
Figure 3.24: Backward Network Encoder Shiftout Operation
72
When first transitioning to the “shiftout” state the NReady signal is set low, which communicates
to the PI/PPI Decision Block that a backtrace result will be ready. The PI/PPI Decision Block
responds by setting genobj high, indicating that it is ready to accept a new required objective
value on the in bus. This signal triggers the internal index in the encoder to start incrementing,
searching for the next required objective in the saved values. Once the next required objective
value is found, the value is encoded onto the in bus, and the NReady signal is again set to 0. This
triggers the PI/PPI Decision Block to read the new value on in and store it into the block RAM.
Once this operation is complete, the PI/PPI Decision Block again sets genobj, triggering the
Backward Network Encoder to start scanning for the next required objective.
When the index reaches the end of the PO/PPOs saved from the Backward Network, indicating
that there are no more required objectives, the encoder sets the in bus to all 1s, and sets NReady
low. This value on the in bus then causes the PI/PPI Decision Block to move on to start the next
“Imply”operation on the Forward Network.
One additional function provided by the Backward Network Encoder, because it controls the
NReady signal, is forwarding trigger request on to the PI/PPI Decision Block. Specifically, this
relates to the newframe_ready signal, which comes from the Objective Decision Block. When it
is determined that the current frame is Done (all previous frame PPIs match current frame PPOs)
or in Conflict (value conflict between previous frame PPI and current frame PPO), the
corresponding signals are set from the Objective Decision Block to the PI/PPI Decision Block.
Once complete, the NReady signal still needs to be set low to trigger the PI/PPI Decision Block
to start an operation and examine those set values. To this end, the Objective Decision block
74
3.5 Translating Circuits into Forward/Backward Networks
In order to place a specific circuit under test in the ATPG architecture outlined here, the network
must first be translated from its basic form into a structure that is compatible to properly
interface with adjacent blocks in the ATPG architecture. To accomplish this in an automated
fashion, a translation program is implemented in C++ code to perform the mapping, which is
included in Appendix E. This section outlines the operation and flow of this utility, as shown in
Figure 3.25.
Figure 3.25: Network Translation Flow
3.5.1 Processing Input Data
The translation program is designed around reading a specific function-level format for networks
to be translated. In this format, each net in the circuit is functionally defined with one line of
code. The exception to this are output nets, which are defined by two lines; one with their
logical definition and the other defining them as an output net. Appendix A contains a sample
input circuit (along with translated circuits output) and Table 3.14 shows the general definition
of this format.
75
Input Code Functional Description
INPUT(G0) Defines G0 as an input to the circuit.
OUTPUT(G1) Defines G1 as an output of the circuit.
G1 = not(G0) Defines G1 as the inverse of G0.
G2 = and(G0,G1) Defines G2 as a 2-input and of G0 and G1.
G3 = or(G0,G1,G2) Defines G3 as a 3-input or of G0, G1 and G2.
G4 = xor(G2,G3) Defines G4 as the exclusive or of G2 and G3.
G5 = dff(G4) Defines a D-flip-flop with input G4 and output
G5.
Table 3.14: Input Network Format
When reading in circuit data, the program does some pre-processing of structures before storing
them in memory. This pre-processing consists of breaking arbitrary complex logic gates down
into constituent base components (AND, OR, NOT). By employing this method of only
modeling the circuit with the most basic components, the task of later translating these circuit
gates into the functional blocks that make up the Forward/Backward Networks is simplified to a
limited number of transforms. This also allows for full flexibility to support any arbitrary
complex gate that is employed in the circuit to be translated. Figure 3.26 provides a simple
example of how the pre-processing is handled in an internally consistent way.
Figure 3.26: Internally Consistent Pre-Processing
3.5.2 In-Memory Data Structure
Once the input circuit has been pre-processed, there are gates that must be stored in memory to
maintain a model of the circuit. Each gate that is read in is modeled into a custom data structure.
This structure contains essential information about the gate being stored, such as name, function,
76
logical level in the circuit, other gates that are inputs to this one and other gates that are outputs
of this one. This data structure is shown in Figure 3.27.
Figure 3.27: Gate Data Structure
Multiple gates are strung together in linked lists, using gate-nodes as the linking elements in the
list. These lists are employed in many functions, including global lists of inputs, outputs, DFFs
and circuit logic levels. Also of note is the fact that a gate may have multiple gates fanning in to
it or out from it, so these attributes of a gate are also modeled in a linked fashion, as shown in
Figure 3.28.
Figure 3.28: Gate Fan-out List Structure
77
The main global data structure that ties together gates into the model used is the level list. This
is a two-way linked list, which in its first dimension links together each logical level of the
circuit and in its second dimension links together the list of gates associated with a given logic
level. Inputs and DFF outputs (pseudo-primary inputs) are placed on level 0. Remaining levels
are populated by placing each gate on a level that is one higher than the highest level of its entire
set of fan in gates. This structure is illustrated in Figure 3.29.
Figure 3.29: Level List Structure
Other structured lists of gates include the input list, which links together all input records for the
circuit, the output list, which links together all gates that are also drivers of outputs, the DFF list,
which links together all DFF gates, and the gate list, which links together all combinational gates
in the circuit. Note that the gate list and DFF list are mutually exclusive, because DFFs are
78
translated into inputs/outputs in the final network output, unlike combination gates that are
translated into Forward/Backward Network equation equivalents.
3.5.3 Writing Output Networks
The final output of the translation program is the Forward and Backward Network Verilog,
which then interface with the rest of the ATPG architecture. As the in-memory model of the
circuit only contains AND, OR and NOT gates, only three transforms are needed at this point to
map the circuit model into the Forward or Backward Network. To write out a network Verilog,
standard module headers are first written out, which include parameterized interface constructs
for primary inputs, pseudo-primary inputs, primary outputs, pseudo-primary outputs and state
bits for all gates. Table 3.15 shows an example of how the interface is defined.
module fwd_net (PI_1, PI_0, PPI_1, PPI_0, STATE_1, STATE_0,
PO_1, PO_0, PPO_1, PPO_0);
parameter n = 1;
parameter m = 4;
parameter l = 3;
parameter s = 20;
input [m-1:0] PI_1;
input [m-1:0] PI_0;
input [l-1:0] PPI_1;
input [l-1:0] PPI_0;
output [s-1:0] STATE_1;
output [s-1:0] STATE_0;
output [n-1:0] PO_1;
output [n-1:0] PO_0;
output [l-1:0] PPO_1;
output [l-1:0] PPO_0;
Table 3.15: Forward Network Module Interface Example
The parameters defined at the top of the module (n, m, l, s) are used to size the interface busses
based on the attributes of the circuit in memory. The parameter n represents the number of
primary outputs in the circuit, and thus sizes the PO_1 and PO_0 interface busses. The
79
parameter m represents the number of primary inputs and thus sizes the PI_1 and PI_0 interface
busses. The parameter l represents the number of D-flip-flops and thus sizes both the
PPO_1/PPO_0 and PPI_1/PPO_0 interface busses. The parameter s represents the total number
of gates in the circuit and thus sizes the STATE_1 and STATE_0 interface busses.
Once the module header information has been written out, the next phase is to handle assignment
of all bits in the input busses to internal signals. Since the input busses consist of both circuit
inputs (in the case of the Forward Network) and circuit DFFs, the program loops through all
defined inputs and then all defined DFFs to generate a complete internal assignment from the
module inputs.
The next step is to loop through all gates in the design, in level order. For the Forward Network,
levels are traversed in ascending order and for the Backwards Network, in descending order.
Each gate modeled in memory is translated to its equivalent network equations based on the
transforms outlined in sections 3.3 and 3.4.
Once equations for each gate have been written out, the final phase is to assign internal network
bit values onto the module output busses. In the case of the Forward Network, all primary
outputs and DFF inputs (pseudo-primary outputs) also have a corresponding internal gate driving
them that defines their value. So, once equations are written out for all gates, values are
available for all POs and PPOs. By traversing the list of all outputs and all DFFs, corresponding
gate output bits are assigned into the module output busses.
80
4. Results
When setting up testing for the implementation of the architecture described here, it is important
to note that the architecture itself has no function without a test circuit being integrated in the
form of Forward and Backward Networks. To this end, the ISCAS89 benchmark circuits are
integrated as test circuits. This provides a wide range of size, structure and complexity which
will then produce a robust set of testing results.
The first property of interest in the architecture proposed here is the intent that it be implemented
on an FPGA. This means that to be consistent with that goal, the architecture must both
successfully synthesize with an FPGA library, and also fit within the resource constraints of the
FPGA. To test against this constraint, the Xilinx Virtex- 6 board was selected, and synthesis was
completed using Mentor Graphics Precision RTL Synthesis 2012b.10_64-bit. Table 4.1
summarizes utilization of the Virtex-6 resources for the ISCAS89 circuits, once integrated into
the architecture.
The “s35932”, “s38417” and “s38584” benchmark circuits are not listed in the compiled results.
As described in section 3.2, the 14-bit encoding scheme for data in this system uses 10 bits for
address. Addresses in this context index the set of PI/PPIs for the circuit being tested. That then
places a limit of 1024 on the number of PIs plus sequential elements in a circuit to be tested. The
three benchmark circuits excluded all have more than 1024 flip-flops, which then overflows the
current addressing scheme, leading to unpredictable results.
81
It is important to note that while all resource utilization increases along with the relative size /
complexity of the benchmark circuit, LUT and CLB utilization represents the real constraint on
size, as DFF usage is much lower. Aside from DFF usage for the RF within the Objective
Decision Block, and DFF buffering of busses between modules, the size of the non-network
portion of the architecture is largely static.
82
Circuit LUTs
CLB
Slices DFF/Latches
c17 1.25% 1.25% 0.30%
c432 2.97% 2.97% 0.62%
c499 4.05% 4.05% 0.66%
c880 4.02% 4.02% 0.84%
c1355 7.12% 7.12% 0.96%
c1908 6.44% 6.44% 1.00%
c2670 13.96% 13.96% 2.72%
c3540 9.42% 9.42% 1.11%
c5315 14.05% 14.05% 2.37%
c6288 24.52% 24.52% 2.06%
c7552 24.55% 24.55% 3.19%
s27 1.35% 1.35% 0.35%
s208 2.20% 2.21% 0.54%
s298 2.47% 2.47% 0.58%
s344 2.88% 2.88% 0.69%
s349 2.93% 2.94% 0.69%
s386 2.37% 2.37% 0.46%
s420 3.46% 3.46% 0.82%
s444 3.14% 3.14% 0.74%
s510 3.20% 3.20% 0.60%
s526 3.06% 3.07% 0.71%
s526n 3.09% 3.09% 0.71%
s641 4.34% 4.34% 1.02%
s713 4.59% 4.59% 1.05%
s820 3.24% 3.24% 0.55%
s832 3.17% 3.17% 0.55%
s838 6.02% 6.02% 1.35%
s953 5.77% 5.77% 1.09%
s1196 3.30% 3.31% 0.72%
s1238 3.49% 3.50% 0.72%
s1423 8.00% 8.00% 2.08%
s1488 3.66% 3.66% 0.49%
s1494 3.75% 3.75% 0.49%
s5378 17.92% 17.92% 4.80%
s9234 22.76% 22.76% 4.46%
s13207 62.20% 62.21% 13.20%
s15850 59.57% 59.57% 12.46%
Table 4.1: Virtex-6 Resource Utilization for IACAS89 Benchmarks
83
This then points to the generated Forward / Backward Networks as the core contributor to
utilization, which directly relates to the size and complexity of the input benchmark circuit. The
relationship between benchmark circuit size and utilization can be seen plotted in Figure 4.1.
Figure 4.l: Virtex-6 Utilization vs. ISCAS89 Benchmark Size
The data shows a roughly linear relationship between benchmark circuit size and FPGA
utilization. It is also important to note that the variance from the relationship increases with the
size of the circuit. This behavior is expected, as larger circuits have more nodes where variations
in net fanout can occur. Higher net fanouts result in more required circuits for the Backward
Network, as discussed in section 3.4.1, hence the more nets there are in the benchmark circuit,
the more potential variation in resulting utilization of the translated circuit.
84
The second point of interest for the architecture is simulating the resulting benchmark circuits.
This determines the number of clock cycles required for operation to complete in each of the
benchmark circuits, as well as a check that the intended behavior of the architecture is followed.
For this purpose, the ISCAS89 benchmark circuits that were synthesized were also simulated in
Mentor Graphics QuestaSim-64 6.5f r2010.06. This data is then combined with the maximum
achievable clock frequency reported in Precision during synthesis to obtain the total runtime on
the FPGA. Finally, as a point of comparison, the Formal software ATPG solver tool was run for
each of the same benchmark circuits. This data is summarized in Table 4.2.
ATPG Emulation Software Solver Clocking Simulation Run Time Run Time
Circuit Freq
(Mhz) Sim Cycles Gen (s)
Compile (s)
Synthesis (s)
Sim Time (s)
Total Time (s)
Rules Gen (s)
Model Gen (s)
Solve (s)
Total Time (s)
s298 78.046 483 0.036 2 56.5 6.19E-06 58.5 0.001 0.002 6.028 6.031
s344 75.884 56 0.038 3 59.6 7.38E-07 62.6 0.001 0.002 0.001 0.004
s349 66.702 56 0.033 3 57 8.40E-07 60.0 0.001 0.002 0.001 0.004
s386 86.957 56 0.034 2 53.4 6.44E-07 55.4 0.001 0.002 0.012 0.015
s444 67.668 207 0.04 4 68 3.06E-06 72.0 0.001 0.002 3.192 3.195
s510 71.922 36 0.045 3 58.4 5.01E-07 61.4 0.001 0.002 0.028 0.031
s526 83.977 483 0.042 4 69.2 5.75E-06 73.2 0.001 0.002 8.964 8.967
s526n 86.505 483 0.047 4 64 5.58E-06 68.0 0.001 0.002 9.02 9.023
s641 38.728 939 0.046 4 83.9 2.42E-05 87.9 0.001 0.002 0.028 0.031
s713 41.416 12688 0.146 5 90 3.06E-04 95.1 0.001 0.002 0.04 0.043
s820 59.144 84 0.057 4 61.8 1.42E-06 65.9 0.001 0.002 0.001 0.004
s832 56.893 84 0.057 4 62.8 1.48E-06 66.9 0.001 0.002 0.001 0.004
s953 56.825 352 0.059 6 97.7 6.19E-06 103.8 0.001 0.002 14.96 14.967
s1196 49.039 100 0.069 6 83.4 2.04E-06 89.5 0.001 0.002 0.004 0.007
s1238 58.306 104 0.072 6 85.6 1.78E-06 91.7 0.001 0.002 0.004 0.007
s1423 32.951 77 0.092 15 166.8 2.34E-06 181.9 0.001 0.002 0.044 0.047
s1488 59.963 64 0.09 7 65 1.07E-06 72.1 0.001 0.002 0.004 0.007
s1494 57.478 64 0.085 7 71.6 1.11E-06 78.7 0.001 0.002 0.004 0.007
s5378 45.116 332 0.668 57 597.1 7.36E-06 654.8 0.009 0.002 0.016 0.027
s9234 29.462 128 1.655 81 784.2 4.34E-06 866.9 0.008 0.002 0.012 0.022
s13207 17.493 540 4.139 605 9024.5 3.09E-05 9633.6 0.013 0.002 0.012 0.027
s15850 16.876 461 5.196 416 6057.5 2.73E-05 6478.7 0.014 0.002 0.092 0.108
Table 4.2: Runtime Comparison for ISCAS89 Benchmarks
85
The runtime data is broken down among the required processes from start to finish for each of
the solvers. In the case of the ATPG emulation architecture, this starts out with the time it takes
to generate a set of Forward/Backward Network Verilog code from the input benchmark circuit.
The complete Verilog must then be compiled and synthesized before it can finally be loaded onto
an FPGA and run to complete the solve operation.
In the case of the Formal software solver, the first step is to generate a CTL rule statement based
on the circuit to match what is being solved by the FPGA (in this case, the ANDing of all POs).
This rule generation is automated for this test case with the TCL script included in Appendix G.
This rule is then merged with the benchmark circuit, and the combined code is translated into a
model that Formal understands. That model is read into Formal and the solve operation is then
run. Note that the Formal solve operation has an internal time limit before giving up early. The
solve times highlighted in Table 4.2 indicate runs where Formal gave up early. For that reason,
those benchmarks are not included in further analysis, as no direct comparison could be drawn.
There are two interesting sets of data to compare within the run time results. The first is the raw
solve time between the FPGA and the software-based solver, as shown in Figure 4.2.
86
Figure 4.2: FPGA vs. Software Solve Time for ISCAS89 Benchmarks
The solve times here were plotted using a logarithmic scale due to the large difference between
the two. It is seen, then, that on average the FPGA architecture solves the ATPG problem 3
orders of magnitude faster than the software-based solver (average of 6991x faster, with a
minimum of 131x for s713 and a maximum of 55939x for s510). In addition to this result,
though, the complete process run time must also be considered, as shown in Figure 4.3.
87
Figure 4.3: FPGA vs. Software Total Time for ISCAS89 Benchmarks
When the complete process time is considered, the results are the complete reverse of the solve
time alone, with the software-based solver being 4 orders of magnitude faster than the FPGA
based solution (average of 36309x faster, with a minimum of 2048x for s510 and a maximum of
356801x for s13207). This discrepancy shows that the FPGA based solution still has limitations
inherited from pre-processing required before the FPGA can actually solve a problem. Compile
and synthesis time dwarf all other run time considerations with the FPGA solution, and present
the largest barrier between the FPGA and software solutions.
88
5. Conclusion & Future Work
Circuits are continually increasing in size and complexity, and this growth increases exposure to
subtle bugs in circuit function. This leads to increased reliance on methods of formal verification
to catch design flaws, and provide assurance of function. Formal verification methods also
suffer issues such as “state explosion” and increasing runtime with larger circuits. To keep up,
formal verification tequiniques continue to evolve, as described in section 1.2. This has lead up
to the current use of ATPG-based methods for formal verification.
As circuit sizes approach the limits of even ATPG-based method feasibility, further solutions are
required. A method has been presented here for implementing an ATPG-based algorithm for
formal verification in reconfigurable hardware (FPGA). This implementation has been shown to
have a linear relationship between the size of the circuit being verified and ultimate FPGA
resource utilization. This implies a reasonable bound on the size of the implementation, as
opposed to an exponential utilization explosion as circuit size increases.
One limitation encountered that prevented simulation with the three largest benchmark circuits
was the limit of 1024 PI/flops for a circuit under test, due to the 10-bit addressing scheme used in
the current implementation. With larger FPGAs to accommodate larger circuits for testing, this
limit could be increased. Increasing the bit width of the data words across the emulation
implementation to support a larger address size is mostly trivial. The only portion that would
require more re-work is the interface with the block RAM, as the address / data bit allocation
configuration would need to change to a different implementation that supported the new desired
size for the address.
89
This method has been shown to be and average of 3 orders of magnitude faster than a similar
software-based approach, based on the time for solving a given ATPG problem. At the same
time, though, total runtime for the FPGA emulation based implementation is significantly limited
by the parts of its process still in software (mainly compilation and synthesis). One future
enhancement that could be made to improve this limitation would be to split the property
monitor portion of the circuit under test into a separate module. Currently the property monitor
for a given CTL rule is integrated as part of the Forward and Backward Networks, and as such
the whole set of networks must be re-compiled and re-synthesized for each new property to be
tested. If the property monitor portion were to be separated out, then only that relatively small
portion of the total circuit would need to be re-compiled and re-synthesized for each iteration of
different properties on the same circuit. This would reduce the impact of high compile and
synthesis time overhead, and make FPGA based emulation a more attractive substitute for
software based solvers, with that benefit being directly proportional to circuit size.
90
Appendix A: Example Input Circuit and Network Translations
The code used to generate Forward and Backward Networks for the architecture described here
is designed to accept a specific input format. The specific constructs used in this format were
described in section 3.5.1. Those constructs can then be applied to create an input circuit for
translation, as exemplified in Table A.1, which is the ISCAS89 circuit “s27”.
# 4 inputs
# 1 outputs
# 3 D-type flipflops
# 2 inverters
# 8 gates (1 ANDs + 1 NANDs + 2 ORs + 4 NORs)
INPUT(G0)
INPUT(G1)
INPUT(G2)
INPUT(G3)
OUTPUT(G17)
G5 = DFF(G10)
G6 = DFF(G11)
G7 = DFF(G13)
G14 = NOT(G0)
G17 = NOT(G11)
G8 = AND(G14, G6)
G15 = OR(G12, G8)
G16 = OR(G3, G8)
G9 = NAND(G16, G15)
G10 = NOR(G14, G11)
G11 = NOR(G5, G9)
G12 = NOR(G1, G7)
G13 = NOR(G2, G12)
Table A.1: Benchmark Code for s27 Circuit
This input circuit code is read into the in-memory model of the translation code, which then
generates the networks. The first network to be generated is the Forward Network, which is a
direct translation of the circuit, with the DFFs being mapped to PPIs/PPOs and the functional bit
91
encoding being changed to a 2-bit representation (to model 3 logic values; 0, 1 and X). Given
the direct nature of this translation, each “wire” line defining a gate in the forward network is
directly linked to (and has the same base name as) a gate from the input circuit, in a one-to-one
relationship. Table A.2 shows the generated forward network code for “s27”.
module fwd_net (PI_1, PI_0, PPI_1, PPI_0, STATE_1, STATE_0, PO_1, PO_0, PPO_1,
PPO_0);
parameter n = 1;
parameter m = 4;
parameter l = 3;
parameter s = 20;
input [m-1:0] PI_1;
input [m-1:0] PI_0;
input [l-1:0] PPI_1;
input [l-1:0] PPI_0;
output [s-1:0] STATE_1;
output [s-1:0] STATE_0;
output [n-1:0] PO_1;
output [n-1:0] PO_0;
output [l-1:0] PPO_1;
output [l-1:0] PPO_0;
wire G3_1, G2_1, G1_1, G0_1, G3_0, G2_0, G1_0, G0_0, G7_z1, G6_z1, G5_z1, G7_z0,
G6_z0, G5_z0; assign {G3_1, G2_1, G1_1, G0_1} = PI_1;
assign {G3_0, G2_0, G1_0, G0_0} = PI_0;
assign {G7_z1, G6_z1, G5_z1} = PPI_1;
assign {G7_z0, G6_z0, G5_z0} = PPI_0;
wire G14_z1 = G0_0;
wire G14_z0 = G0_1;
wire G12_base_z1 = G7_z1 | G1_1;
wire G12_base_z0 = G7_z0 & G1_0;
wire G12_z1 = G12_base_z0;
wire G12_z0 = G12_base_z1;
wire G8_z1 = G6_z1 & G14_z1;
wire G8_z0 = G6_z0 | G14_z0;
wire G16_z1 = G8_z1 | G3_1;
wire G16_z0 = G8_z0 & G3_0;
wire G15_z1 = G8_z1 | G12_z1;
wire G15_z0 = G8_z0 & G12_z0;
wire G13_base_z1 = G12_z1 | G2_1;
wire G13_base_z0 = G12_z0 & G2_0;
wire G13_z1 = G13_base_z0;
wire G13_z0 = G13_base_z1;
wire G9_base_z1 = G15_z1 & G16_z1;
wire G9_base_z0 = G15_z0 | G16_z0;
wire G9_z1 = G9_base_z0;
wire G9_z0 = G9_base_z1;
wire G11_base_z1 = G9_z1 | G5_z1;
wire G11_base_z0 = G9_z0 & G5_z0;
wire G11_z1 = G11_base_z0;
wire G11_z0 = G11_base_z1;
wire G10_base_z1 = G11_z1 | G14_z1;
wire G10_base_z0 = G11_z0 & G14_z0;
wire G17_z1 = G11_z0;
92
wire G17_z0 = G11_z1;
wire G10_z1 = G10_base_z0;
wire G10_z0 = G10_base_z1;
assign STATE_1 = {G3_1, G2_1, G1_1, G0_1, G7_z1, G6_z1, G5_z1, G14_z1, G12_base_z1,
G12_z1, G8_z1, G16_z1, G15_z1, G13_base_z1, G13_z1, G9_base_z1, G9_z1,
G11_base_z1, G11_z1, G10_base_z1, G17_z1, G10_z1}; assign STATE_0 = {G3_0, G2_0, G1_0, G0_0, G7_z0, G6_z0, G5_z0, G14_z0, G12_base_z0,
G12_z0, G8_z0, G16_z0, G15_z0, G13_base_z0, G13_z0, G9_base_z0, G9_z0,
G11_base_z0, G11_z0, G10_base_z0, G17_z0, G10_z0}; assign PO_1 = {G17_z1};
assign PO_0 = {G17_z0};
assign PPO_1 = {G13_z1, G11_z1, G10_z1};
assign PPO_0 = {G13_z0, G11_z0, G10_z0};
endmodule
Table A.2: Forward Network Verilog for s27 Benchmark Circuit
The Backward Network is more complex in its relationship back to the input circuit, since each
input gate maps to multiple Backward Network gates, and special circuitry to handle fanout
conditions needs to be inserted. The same base names from the input circuit are still used for the
related gates in the Backward Network, though there are many post-fixes used to handle the one-
to-many mapping. Table A.3 shows the generated Backward Network code for “s27”.
module back_net (priority_reset, PO_1, PO_0, PPO_1, PPO_0, STATE_1, STATE_0, PI_1,
PI_0, PPI_1, PPI_0); parameter n = 1;
parameter m = 4;
parameter l = 3;
parameter s = 20;
input priority_reset;
input [n-1:0] PO_1;
input [n-1:0] PO_0;
input [l-1:0] PPO_1;
input [l-1:0] PPO_0;
input [s-1:0] STATE_1;
input [s-1:0] STATE_0;
output [m-1:0] PI_1;
output [m-1:0] PI_0;
output [l-1:0] PPI_1;
output [l-1:0] PPI_0;
wire G17_zo1, G17_zo0, G3_1, G2_1, G1_1, G0_1, G7_z1, G6_z1, G5_z1, G14_z1,
G12_base_z1, G12_z1, G8_z1, G16_z1, G15_z1, G13_base_z1, G13_z1, G9_base_z1,
G9_z1, G11_base_z1, G11_z1, G10_base_z1, G17_z1, G10_z1, G3_0, G2_0, G1_0,
G0_0, G7_z0, G6_z0, G5_z0, G14_z0, G12_base_z0, G12_z0, G8_z0, G16_z0,
G15_z0, G13_base_z0, G13_z0, G9_base_z0, G9_z0, G11_base_z0, G11_z0,
G10_base_z0, G17_z0, G10_z0, G13_zo1, G11_zo1, G10_zo1, G13_zo0, G11_zo0,
G10_zo0; assign {G17_zo1} = PO_1;
assign {G17_zo0} = PO_0;
assign {G13_zo1, G11_zo1, G10_zo1} = PPO_1;
assign {G13_zo0, G11_zo0, G10_zo0} = PPO_0;
93
assign {G3_1, G2_1, G1_1, G0_1, G7_z1, G6_z1, G5_z1, G14_z1, G12_base_z1, G12_z1,
G8_z1, G16_z1, G15_z1, G13_base_z1, G13_z1, G9_base_z1, G9_z1, G11_base_z1,
G11_z1, G10_base_z1, G17_z1, G10_z1} = STATE_1; assign {G3_0, G2_0, G1_0, G0_0, G7_z0, G6_z0, G5_z0, G14_z0, G12_base_z0, G12_z0,
G8_z0, G16_z0, G15_z0, G13_base_z0, G13_z0, G9_base_z0, G9_z0, G11_base_z0,
G11_z0, G10_base_z0, G17_z0, G10_z0} = STATE_0; wire G17_zo1_1 = G17_zo1;
wire G17_zo0_1 = G17_zo0;
wire G10_base_zo1 = G10_zo1 & G10_base_z1 & G10_base_z0;
wire G10_base_zo0 = ~G10_zo0;
wire G11_zo1_1 = G10_base_zo1 & G11_z1 & G11_z0;
wire G11_zo0_1 = G10_base_zo0;
wire G14_zo1 = G10_base_zo1 & ~G10_base_zo0 & G14_z1 & G14_z0;
wire G14_zo0 = G10_base_zo0;
reg G17_priority_0;
reg G17_priority_1;
reg G17_priority_last_reset;
always @(priority_reset, G17_zo1, G17_priority_1, G17_priority_0, G17_zo1_1) begin
if (G17_priority_last_reset != priority_reset) begin
G17_priority_0 = 1'b0;
G17_priority_1 = 1'b0;
G17_priority_last_reset = priority_reset;
end
else begin
G17_priority_0 = G17_zo1 & ~G17_priority_1;
G17_priority_1 = ~G17_priority_0 & G17_zo1_1;
end
end
wire G17_zo1_2 = G17_priority_0 | G17_priority_1;
wire G17_zo0_2 = (G17_priority_0 & G17_zo0) | (G17_priority_1 & G17_zo0_1);
wire G11_zo1_2 = G17_zo1_2 & G11_z1 & G11_z0;
wire G11_zo0_2 = ~G17_zo0_2;
reg G11_priority_0;
reg G11_priority_1;
reg G11_priority_2;
reg G11_priority_last_reset;
always @(priority_reset, G11_zo1, G11_priority_1, G11_priority_2, G11_priority_0,
G11_zo1_1, G11_priority_2, G11_priority_0, G11_priority_1, G11_zo1_2) begin if (G11_priority_last_reset != priority_reset) begin
G11_priority_0 = 1'b0;
G11_priority_1 = 1'b0;
G11_priority_2 = 1'b0;
G11_priority_last_reset = priority_reset;
end
else begin
G11_priority_0 = G11_zo1 & ~G11_priority_1 & ~G11_priority_2;
G11_priority_1 = ~G11_priority_0 & G11_zo1_1 & ~G11_priority_2;
G11_priority_2 = ~G11_priority_0 & ~G11_priority_1 & G11_zo1_2;
end
end
wire G11_zo1_3 = G11_priority_0 | G11_priority_1 | G11_priority_2;
wire G11_zo0_3 = (G11_priority_0 & G11_zo0) | (G11_priority_1 & G11_zo0_1) |
(G11_priority_2 & G11_zo0_2); wire G11_base_zo1 = G11_zo1_3 & G11_base_z1 & G11_base_z0;
wire G11_base_zo0 = ~G11_zo0_3;
wire G9_zo1 = G11_base_zo1 & G9_z1 & G9_z0;
wire G9_zo0 = G11_base_zo0;
wire G5_o1_0 = G11_base_zo1 & ~G11_base_zo0 & G5_z1 & G5_z0;
wire G5_o0_0 = G11_base_zo0;
wire G9_base_zo1 = G9_zo1 & G9_base_z1 & G9_base_z0;
wire G9_base_zo0 = ~G9_zo0;
wire G13_base_zo1 = G13_zo1 & G13_base_z1 & G13_base_z0;
94
wire G13_base_zo0 = ~G13_zo0;
wire G15_zo1 = G9_base_zo1 & G15_z1 & G15_z0;
wire G15_zo0 = G9_base_zo0;
wire G16_zo1 = G9_base_zo1 & G9_base_zo0 & G16_z1 & G16_z0;
wire G16_zo0 = G9_base_zo0;
wire G8_zo1 = G16_zo1 & G8_z1 & G8_z0;
wire G8_zo0 = G16_zo0;
wire G3_o1_0 = G16_zo1 & ~G16_zo0 & G3_1 & G3_0;
wire G3_o0_0 = G16_zo0;
wire G8_zo1_1 = G15_zo1 & G8_z1 & G8_z0;
wire G8_zo0_1 = G15_zo0;
wire G12_zo1 = G15_zo1 & ~G15_zo0 & G12_z1 & G12_z0;
wire G12_zo0 = G15_zo0;
wire G12_zo1_1 = G13_base_zo1 & G12_z1 & G12_z0;
wire G12_zo0_1 = G13_base_zo0;
wire G2_o1_0 = G13_base_zo1 & ~G13_base_zo0 & G2_1 & G2_0;
wire G2_o0_0 = G13_base_zo0;
reg G12_priority_0;
reg G12_priority_1;
reg G12_priority_last_reset;
always @(priority_reset, G12_zo1, G12_priority_1, G12_priority_0, G12_zo1_1) begin
if (G12_priority_last_reset != priority_reset) begin
G12_priority_0 = 1'b0;
G12_priority_1 = 1'b0;
G12_priority_last_reset = priority_reset;
end
else begin
G12_priority_0 = G12_zo1 & ~G12_priority_1;
G12_priority_1 = ~G12_priority_0 & G12_zo1_1;
end
end
wire G12_zo1_2 = G12_priority_0 | G12_priority_1;
wire G12_zo0_2 = (G12_priority_0 & G12_zo0) | (G12_priority_1 & G12_zo0_1);
wire G12_base_zo1 = G12_zo1_2 & G12_base_z1 & G12_base_z0;
wire G12_base_zo0 = ~G12_zo0_2;
reg G8_priority_0;
reg G8_priority_1;
reg G8_priority_last_reset;
always @(priority_reset, G8_zo1, G8_priority_1, G8_priority_0, G8_zo1_1) begin
if (G8_priority_last_reset != priority_reset) begin
G8_priority_0 = 1'b0;
G8_priority_1 = 1'b0;
G8_priority_last_reset = priority_reset;
end
else begin
G8_priority_0 = G8_zo1 & ~G8_priority_1;
G8_priority_1 = ~G8_priority_0 & G8_zo1_1;
end
end
wire G8_zo1_2 = G8_priority_0 | G8_priority_1;
wire G8_zo0_2 = (G8_priority_0 & G8_zo0) | (G8_priority_1 & G8_zo0_1);
wire G6_o1_0 = G8_zo1_2 & G6_z1 & G6_z0;
wire G6_o0_0 = G8_zo0_2;
wire G14_zo1_1 = G8_zo1_2 & G8_zo0_2 & G14_z1 & G14_z0;
wire G14_zo0_1 = G8_zo0_2;
reg G14_priority_0;
reg G14_priority_1;
reg G14_priority_last_reset;
always @(priority_reset, G14_zo1, G14_priority_1, G14_priority_0, G14_zo1_1) begin
if (G14_priority_last_reset != priority_reset) begin
G14_priority_0 = 1'b0;
G14_priority_1 = 1'b0;
95
G14_priority_last_reset = priority_reset;
end
else begin
G14_priority_0 = G14_zo1 & ~G14_priority_1;
G14_priority_1 = ~G14_priority_0 & G14_zo1_1;
end
end
wire G14_zo1_2 = G14_priority_0 | G14_priority_1;
wire G14_zo0_2 = (G14_priority_0 & G14_zo0) | (G14_priority_1 & G14_zo0_1);
wire G0_o1_0 = G14_zo1_2 & G0_1 & G0_0;
wire G0_o0_0 = ~G14_zo0_2;
wire G7_o1_0 = G12_base_zo1 & G7_z1 & G7_z0;
wire G7_o0_0 = G12_base_zo0;
wire G1_o1_0 = G12_base_zo1 & ~G12_base_zo0 & G1_1 & G1_0;
wire G1_o0_0 = G12_base_zo0;
wire G3_o1 = G3_o1_0;
wire G3_o0 = G3_o0_0;
wire G2_o1 = G2_o1_0;
wire G2_o0 = G2_o0_0;
wire G1_o1 = G1_o1_0;
wire G1_o0 = G1_o0_0;
wire G0_o1 = G0_o1_0;
wire G0_o0 = G0_o0_0;
wire G7_zo1 = G7_o1_0;
wire G7_zo0 = G7_o0_0;
wire G6_zo1 = G6_o1_0;
wire G6_zo0 = G6_o0_0;
wire G5_zo1 = G5_o1_0;
wire G5_zo0 = G5_o0_0;
assign PI_1 = {G3_o1, G2_o1, G1_o1, G0_o1};
assign PI_0 = {G3_o0, G2_o0, G1_o0, G0_o0};
assign PPI_1 = {G7_zo1, G6_zo1, G5_zo1};
assign PPI_0 = {G7_zo0, G6_zo0, G5_zo0};
endmodule
Table A.3: Backward Network Verilog for s27 Benchmark Circuit
One piece of repeated code that is important to note in the backward network, is the priority
encoder logic that is used to handle logical fanout when translating the network to the reverse
direction. Table A.4 shows an excerpt from the backward network code which is used to
implement the priority encoder.
96
...
assign {G13_zo1, G11_zo1, G10_zo1} = PPO_1;
assign {G13_zo0, G11_zo0, G10_zo0} = PPO_0;
...
wire G11_zo1_1 = G10_base_zo1 & G11_z1 & G11_z0;
wire G11_zo0_1 = G10_base_zo0;
...
wire G11_zo1_2 = G17_zo1_2 & G11_z1 & G11_z0;
wire G11_zo0_2 = ~G17_zo0_2;
reg G11_priority_0;
reg G11_priority_1;
reg G11_priority_2;
reg G11_priority_last_reset;
always @(priority_reset, G11_zo1, G11_priority_1, G11_priority_2, G11_priority_0,
G11_zo1_1, G11_priority_2, G11_priority_0, G11_priority_1, G11_zo1_2)
begin if (G11_priority_last_reset != priority_reset) begin
G11_priority_0 = 1'b0;
G11_priority_1 = 1'b0;
G11_priority_2 = 1'b0;
G11_priority_last_reset = priority_reset;
end
else begin
G11_priority_0 = G11_zo1 & ~G11_priority_1 & ~G11_priority_2;
G11_priority_1 = ~G11_priority_0 & G11_zo1_1 & ~G11_priority_2;
G11_priority_2 = ~G11_priority_0 & ~G11_priority_1 & G11_zo1_2;
end
end
wire G11_zo1_3 = G11_priority_0 | G11_priority_1 | G11_priority_2;
wire G11_zo0_3 = (G11_priority_0 & G11_zo0) | (G11_priority_1 & G11_zo0_1) |
(G11_priority_2 & G11_zo0_2); ...
Table A.4: Backward Network Priority Encoder Verilog Example
Each time the translation code processes a gate input while generating the backward network, the
name of the driving cell is recorded. If another instance of a gate input being sourced by the
same driver cell is encountered, the next incremental post-fix is selected to reference that version
of the driver cell output in the backward model.
Once processing arrives at the driving gate that has multiple sinks, and thus multiple versions
created of its output, those multiple signals need to be resolved into a single signal to continue
propagation through the Backward Network. So, at this point, a priority encoder is instantiated.
97
This is modeled as a block that triggers off any change in the “required objective” bits for any of
the versions of the driver cell output signal (or the global priority_reset signal used for clearing
the Backward Network). Whenever the first change occurs in those signals, the priority bits in
the encoder lock in, preventing any changes until a priority reset occurs.
The final portion of the priority encoder occurs outside of the detect/lock code block. In the
following two “wire” statements, the merged driver cell signal is defined. The “zo1” (required
objective) bit is defined by ORing together all the priority signals. Since one of these will lock
in with a value of 1 once the first one arrives, this will then cause the final output to also lock in
with a value of 1. The “zo0” (objective value) bit is defined by ANDing together each objective
value with its priority bit, and then ORing them all together. Since the AND operation will act as
a pass-through for the objective value only when the priority input is 1, only the term with the
locked-in priority bit will be passed through (all other terms will always be 0). These are then all
ORed together, effectively propagating the single term representing the locked-in objective from
the encoder into the final merged objective value bit.
98
Appendix B: Example DONE Simulation for c17 Benchmark Circuit
The following results are taken from simulation of the “c17” ISCAS89 benchmark circuit using
Mentor Graphics QuestaSim-64 6.5f r2010.06. For reference, the logical structure of “c17” is
shown in Figure B.1. Note that as a c* class benchmark circuit, there are no sequential elements,
and thus no PPIs/PPOs. Also note that the model of the circuit used in the verification
architecture uses separate AND + NOT structures in place of the NANDs defined in the base
circuit. For the sake of diagram simplicity, these will remain abstracted as singular NAND gates.
Figure B.1: c17 Benchmark Circuit Structure
One final note about the structure of the circuit to keep in mind is that in the case of this
simulation, a property monitor is used which ANDs together all POs, effectively translating the
test of line_k=1 to testing if all POs can be 1 at the same time. Thus, the structure that is being
simulated is the one shown in Figure B.2.
99
Figure B.2: c17 Simulation Circuit Structure
To begin simulation of the circuit, the “clk” input is defined with a 100ps period (first rising edge
arriving at +50ps) and the “global_reset” signal is pulsed high for 5ps to initialize the circuit:
force -freeze sim/:top:clk 0 0, 1 {50 ps} -r 100
force -freeze sim/:top:global_reset 1 0 -cancel 5
Table B.1: Circuit c17 Simulation Input Stimulus
When global_reset goes high, the first operation in the circuit is executed, with all modules
resetting to their initial states.
# fourcounter | reseting the frame counter
# statecheck | reset
# obj-dec | RESET
# back-bec | RESET
# back-enc | RESET
# fourcounter | global reset
# PPI Decision Block / Reset of PPI Decision Block
# memram | ADDRESS=0=0000000000
# PPI Decision Block / Reset of PPI Decision Block
# PPI Decision Block / Reset of PPI Decision Block
# fourcounter | global reset
# mycontrol | executing state 0
Table B.2: Circuit c17 Initial Reset
100
As part of this reset, the values sent from the PI/PPI Decision Block to the Forward Network are
cleared to all Xs (2’b11). Thus in the first clock cycle, the Objective Decision Block sees that it
is in frame_k with line_k=X. Thus, an objective of line_k=1 is set, and pushed to the Backward
Network Decoder.
# mycontrol | in state 0
# obj-dec | line_k = X
# obj-dec | push obj: 00000000000100
Table B.3: Circuit c17 Simulation Cycle 1
The Backward Network Decoder receives this objective value and begins the process of a
“Backtrace” on the Backward Network. This involves two cycles of operation. In the first, the
Backward Network is cleared, where all priority encoders are unlocked, so that new propagation
can occur. In the second cycle, the objective is pushed onto the Backward Network, and the
Backward Network Encoder is signaled that a ‘Backtrace” operation has started via toggling of
the trace_start signal.
# mycontrol | in state 0
# back-dec | received new obj: 00000000000100
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000000000100
Table B.4: Circuit c17 Simulation Cycles 2-4
Once the objective is pushed onto the Backward Network, tracing takes place in a single cycle,
while the Backward Network Encoder waits for trace results. Figure B.3 shows the result of the
“Backtrace” on the circuit structure. Note that in the circuit diagram, the bottom inputs to gates
101
are considered the “A” input, and as such when a gate output objective only requires one input to
be set as an objective, the bottom input will be set.
Figure B.3: c17 Simulation Backtrace
While this “Backtrace” is happening, the Backward Network Encoder is waiting for results.
Once the results are available, the Backward Network Encoder sets the NReady signal low to
indicate to the PI/PPI Decision Block that backtraced results are ready to send to it. It moves to
state 1 to prepare to accept a new objective value from the Backward Network.
# mycontrol | in state 0
# back-enc | trace started, waiting for results
# ------------------------------
# mycontrol | in state 0
# back-enc | traced values received
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
Table B.5: Circuit c17 Simulation Cycles 5-7
From state 1, the PI/PPI Decision Block moves to state 16, where it sets genobj to high,
indicating to the Backward Network Encoder that it is ready to accept an objective value. In the
following cycle the PI/PPI Decision Block returns to state 0 (idle), while the Backward Network
102
Encoder finds the first objective value on the Backward Network outputs. It finds an objective
value of “1” (encoded from “11” to “10”) at PI index 1. This corresponds to the assignment of
“G2gat” to 1. This objective is pushed onto the in bus and NReady is set low, triggering the
PI/PPI Decision Block to action. The PI/PPI Decision Block moves through state 1 and on to
state 17.
# mycontrol | in state 1
# mycontrol | executing state 16
# ------------------------------
# mycontrol | in state 16
# back-enc | found obj at PI index 0000000001: 10
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000000
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000000010100
# memram | ADDRESS=li=0000
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000001
# val=10
Table B.6: Circuit c17 Simulation Cycles 8-12
In state 17, the PI/PPI Decision Block pushes the value on in onto the Block RAM, which will
then contain its first value, as shown in Figure B.4.
103
Figure B.4: Contents of c17 Block RAM After Objective 1
The PI/PPI Decision Block then moves on to state 10, where the same objective value is loaded
into the Forward Network input buffer. At the same time, genobj is set, signaling the Backward
Network Encoder that the PI/PPI Decision Block will be ready to accept another objective value.
The PI/PPI Decision Block then returns to state 0, and the same cycle that just completed runs 2
more times to pass on the objective values set on G6gat and G7gat.
# mycontrol | in state 10
# back-enc | found obj at PI index 0000000011: 01
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000000
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000000110010
# memram | ADDRESS=li=0001
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000011
# val=01
# ------------------------------
# mycontrol | in state 10
# back-enc | found obj at PI index 0000000100: 10
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
104
# memram | beginning push
# memram | ADDRESS=0=0000000001
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001000100
# memram | ADDRESS=li=0010
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000100
# val=10
Table B.7: Circuit c17 Simulation Cycles 13-20
After the final objective value has been passed from the Backward Network Encoder to the
PI/PPI Decision Block, genobj is again set high. This time, the Backward Network Encoder has
no more objectives to pass. Detecting that it is done, it sets the in bus to all 1s, indicating no
value, and again triggers the PI/PPI Decision Block by setting NReady to 0. Receiving this
signal that there are no further objectives, the PI/PPI Decision Block pushes the values in the
buffer onto the Forward Network, starting a new trace. The newvaluestoforward signal is also
toggled to signal the Objective Decision Block that a new trace has started.
# mycontrol | in state 10
# back-enc | no objectives; done
# PPI Decision Block | Assign vf (from top)
# addr=0000000100
# val=10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
Table B.8: Circuit c17 Simulation Cycle 21
The same three objective values that were backtraced are pushed onto the Forward Network,
which propagates the values from PI to PO. The flow of this trace on the circuit structure is
shown in Figure B.5.
105
Figure B.5: c17 Simulation Trace / Implication
In the next cycle, the Objective Decision Block sees nexvaluestoforward has toggled, and checks
the values on the Forward Network. The PO value of “final_zo” has changed from X (2’b11) to
1 (2’b10), indicating a successful trace. Since the circuit is in frame_1 (circuits without
sequential elements only operate in a single frame; frame_k=frame_1), the Objective Decision
Block checks the Forward Network state against the objective of line_k=1. Since line_k
(final_zo) is set to 1, the final objective in frame_1 has been satisfied. The Done signal is set
high, indicating a done state, and the newframe_ready signal is toggled indicating that the current
frame is complete (in a sequential circuit this would mean moving to the next frame).
# mycontrol | in state 0
# obj-dec | line_k = 1
# obj-dec | DONE with frame
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
# DONE!!
# cycle= 23 FAIL=0 DONE=1
# back-enc | recovering nready in idle
Table B.9: Circuit c17 Simulation Cycles 22-23
106
In the final cycle, the Backward Network Encoder receives the toggle of the newframe_ready
signal, which triggers it to set NReady low, passing on the signal to the PI/PPI Decision Block.
The PI/PPI Decision Block receives the NReady signal and also sees that the signals Done=1,
Conflict=0 and frame_1=1, indicating that the final objective has been satisfied in frame_1. The
PI/PPI Decision Block then moves to the final state 14, where DONE=1 is passed to the global
output, completing the simulation. At this point, the full set of PI/PPI assignment vectors
required to reproduce the line_k=1 objective are located in the Block RAM for extraction.
Figure B.6: Final c17 Block RAM Contents
107
Appendix C: Example FAIL Simulation for s27 Benchmark Circuit
The following results are taken from simulation of the “s27” ISCAS89 benchmark circuit using
Mentor Graphics QuestaSim-64 6.5f r2010.06. For reference, the logical structure of “s27” is
shown in Figure C.1.
Figure C.1: s27 Benchmark Circuit Structure
Note that as part of the translation into the Forward and Backward Networks, the sequential
elements are removed, and converted into PPI/PPOs of the circuit. In illustration, the PPIs are
located along the bottom of the circuit, using lower case notation. Their corresponding PPOs are
along the right side of the circuit, using the same name with an upper case notation. Also note
that inverting gates are converted into a non-inverting gate and a separate not gate, but for the
sake of illustration simplicity, these gates remain singular in this example. The final network
structure for tracing in simulation is shown in Figure C.2.
108
Figure C.2: s27 Benchmark Simulation Structure
Simulation begins with an input clock defined with a 100ps period (first rising edge at 50ps), and
a pulse of global_reset to high for 5ps, to trigger initialization/reset of the circuit. From this
point, simulation of the first frame begins. Since the first frame objective is always line_k=1,
simulation proceeds exactly as in Appendix B, up until the point that the first frame is complete.
Simulation output from the first frame is shown in Table C.1, but is not discussed in detail for
this reason.
# fourcounter | reseting the frame counter
# statecheck | reset
# obj-dec | RESET
# back-bec | RESET
# back-enc | RESET
# fourcounter | global reset
# PPI Decision Block / Reset of PPI Decision Block
# memram | ADDRESS=0=0000000000
# PPI Decision Block / Reset of PPI Decision Block
# PPI Decision Block / Reset of PPI Decision Block
# fourcounter | global reset
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# obj-dec | line_k = X
# obj-dec | push obj: 00000000000100
# ------------------------------
# mycontrol | in state 0
# back-dec | received new obj: 00000000000100
109
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000000000100
# ------------------------------
# mycontrol | in state 0
# back-enc | trace started, waiting for results
# ------------------------------
# mycontrol | in state 0
# back-enc | traced values received
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 16
# ------------------------------
# mycontrol | in state 16
# back-enc | found obj at PPI index
00000000000000000000000000000101: 01
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000000
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001010010
# memram | ADDRESS=li=0000
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=01
# ------------------------------
# mycontrol | in state 10
# back-enc | found obj at PPI index
00000000000000000000000000000110: 10
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
110
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000000
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001100100
# memram | ADDRESS=li=0001
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=10
# ------------------------------
# mycontrol | in state 10
# back-enc | no objectives; done
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
# ------------------------------
# mycontrol | in state 0
# obj-dec | line_k = 1
# obj-dec | DONE with frame
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
# ------------------------------
# mycontrol | in state 0
# back-enc | recovering nready in idle
# mycontrol | executing state 15
Table C.1: Circuit s27 Simulation Cycles 1-20
The only difference in the first frame between s27 and Appendix B is the result of the
“Backtrace” operation in the Backward Network, and hence the set of values passed to the PI/PPI
Decision Block to be stored in the Block RAM. The “Backtrace” of the circuit for the first
processed frame (frame_k; line_k=1) is shown in Figure C.3, where G17 is line_k, being the only
PO of the circuit.
111
Figure C.3: s27 Simulation Frame k Backtrace
At this point, the Block RAM contains two entries, storing the two PPI objective values that were
backtraced. These contents are shown in Figure C.4. Note that the “top” bit for the last
objective read onto the memory is currently 0.
Figure C.4: Contents of Block RAM After Frame k
This is where processing diverges from the example in Appendix B. Since sequential elements
exist, the current frame is k, but not 1. Thus, the PI/PPI Decision Block, having PPIs to justify,
moves to state 15 to begin a move to frame k-1. From here processing moves to state 3, where
each PPI assignment from the previous frame is read from the RAM onto the ppi bus to the
Objective Decision Block. The Objective Decision Block reads these values into the RF.
# mycontrol | in state 15
# mycontrol | executing state 3
# memram | ADDRESS=addr=00000000000001
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti-1)
112
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# isppi | evaluating output to RF; in=00000001100100
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# obj-dec | read in PPI: 00000001100100
# memram | ram reading out - =00000001010010
# memram | ADDRESS=li=0001
# Reading the ram
# isppi | evaluating output to RF; in=00000001010010
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# obj-dec | read in PPI: 00000001010010
# mycontrol | executing state 8
# fourcounter | counting a frame DOWN
# memram | setting Top in RAM
Table C.2: Circuit s27 Simulation Cycles 21-24
Within the PI/PPI Decision Block, the frame counter counts down 1. After this, the “top mark”
bit is set on the last objective from this frame. This process requires reading out and writing
back to the memory over multiple cycles, and this it occurs concurrently with the other processes
over the next 3 cycles. The contents of the Block RAM after this operation are shown in Figure
C.5.
Figure C.5: Contents of Block RAM After Move to Frame k-1
The PI/PPI Decision Block then finishes the “Move to Ti-1” operation by clearing the Forward
Network and toggling newvaluestoforward, which triggers the Objective Decision Block to
action.
113
# mycontrol | in state 8
# mycontrol | executing state 11
# PPI Decision Block | Clearing ValuestoForward
# ------------------------------
# mycontrol | in state 11
# obj-dec | not frame k, check for conflict/done
# obj-dec | push obj: 00000001010010
# mycontrol | executing state 4
# memram | beginning rewrite1
# memram | ADDRESS=li=0001
Table C.3: Circuit s27 Simulation Cycles 25-26
The Objective Decision Block again has all Xs from the output of the cleared Forward Network,
but this time it is no longer frame_k, so the contents of the RF (PPI objectives from previous
frame; PPO objectives for this frame) must be checked against the current Forward Network
PPOs to determine the state of the frame. The current contents of the RF are shown in Figure
C.6.
Figure C.6: Contents of RF in Frame k-1
Since all PPOs are currently X, the first objective value in the RF is selected to be the next
objective, and pushed to the Backward Network Decoder.
# mycontrol | in state 4
# back-dec | received new obj: 00000001010010
# mycontrol | executing state 0
# memram | setting the flag in RAM
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000001010010
# ------------------------------
# mycontrol | in state 0
114
# back-enc | trace started, waiting for results
Table C.4: Circuit s27 Simulation Cycles 27-30
The Backward Network Decoder receives the new objective and starts by clearing the Backward
Network of values locked into the priority encoders from the previous “Backtrace”. Once
complete, the new objective is pushed into the Backward Network, and the trace_start signal is
toggled, triggering the Backward Network Encoder to begin waiting for “Backtrace’ results. The
first “Bracktrace” in the current frame (k-1) is shown in Figure C.7.
Figure C.7: s27 Simulation Frame k-1 Backtrace 1
The “Backtrace” completes, and again the objective values are passed on to the PI/PPI Decision
Block, where they are pushed into the Block RAM.
# mycontrol | in state 0
# back-enc | traced values received
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 16
# ------------------------------
115
# mycontrol | in state 16
# back-enc | found obj at PPI index
00000000000000000000000000000101: 01
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000001
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001010010
# memram | ADDRESS=li=0010
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=01
# ------------------------------
# mycontrol | in state 10
# back-enc | found obj at PPI index
00000000000000000000000000000110: 10
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000010
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001100100
# memram | ADDRESS=li=0011
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=10
Table C.5: Circuit s27 Simulation Cycles 31-41
116
At this point the Block RAM contains a completed frame k assignment, and a partial assignment
for frame k-1 (only the justification of the first objective has been completed) as shown in Figure
C.7.
Figure C.8: Contents of RAM in Frame k-1 with Backtrace 1
After receiving the final objective, the PI/PPI Decision Block pushes the received values into the
Forward Network to complete the “Imply” operation, and generate the new objective’s resultant
PO/PPO values. The PI/PPI Decision Block also toggles the newvaluestofoward signal,
triggering the Objective Decision Block to take action. This forward trace is shown in Figure
C.9.
Figure C.9: s27 Simulation Frame k-1 Imply 1
117
# mycontrol | in state 10
# back-enc | no objectives; done
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
# ------------------------------
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | push obj: 00000001100100
Table C.6: Circuit s27 Simulation Cycles 42-43
In the following cycle, the Objective Decision Block again checks the state of the current frame.
This time, the first value in the RF is satisfied by having an equal assignment on its
corresponding PPO from the Forward Network, as shown in Figure C.10.
Figure C.10: Contents of RF and PO/PPO in Frame k-1, Imply 1
Thus, the Objective Decision Block selects the second (and final) value in the RF as the
objective for further justification, as its corresponding PPO value from the Forward Network is
still X. The objective value is pushed to the Backward Network Decoder, which again clears the
Backward Network for a new “Backtrace” operation. The objective is then pushed onto the
Backward Network, and trace_start is toggled, triggering the Backward Network Encoder to
begin waiting for “Backtrace” results.
118
# mycontrol | in state 0
# back-dec | received new obj: 00000001100100
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000001100100
# ------------------------------
# mycontrol | in state 0
# back-enc | trace started, waiting for results
Table C.7: Circuit s27 Simulation Cycles 44-47
Note that this time in “Backtrace”, the Forward Network is not cleared (all Xs), so there are
current STATE values for each gate that factor in to whether or not an objective will continue
propagating in the “Backtrace”. These values are shown as blue in the “Backtrace” 2 illustration,
Figure C.11.
Figure C.11: s27 Simulation Frame k-1 Backtrace 2
The value being backtraced on “G7” does eventually interact with a current STATE value from
the Forward Network, at G12. Here the gate is already assigned a value of 0 in the Forward
Network. Since the current value is not “X”, the “Backtrace” stops on this path. Since the
values are the same, the justification for this part of the path was already completed and further
119
evaluation along this path is not required. If the values were not equal, that would present a
conflict. Evaluation on the path would still stop, but a conflict would then be detected by the
Objective Decision Block in the subsequent “Imply” operation on the Forward Network, as a
complete assignment for the backtraced objective will not have been generated.
As shown, one objective is found in the second “Backtrace”. This value is received by the
encoder and passed to the PI/PPI Decision Block. The PI/PPI Decision Block stores this value in
memory, and adds it into the current Forward Network output buffer (in addition to the values
already in place from the first forward trace).
# mycontrol | in state 0
# back-enc | traced values received
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 16
# ------------------------------
# mycontrol | in state 16
# back-enc | found obj at PI index 0000000010: 01
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000011
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000000100010
# memram | ADDRESS=li=0100
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
120
# addr=0000000010
# val=01
# ------------------------------
# mycontrol | in state 10
# back-enc | no objectives; done
# PPI Decision Block | Assign vf (from top)
# addr=0000000010
# val=01
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
Table C.8: Circuit s27 Simulation Cycles 48-55
Once it is determined that there are no more objective values from the Backward Network
Encoder, the current values in the buffer are pushed onto the Forward Network and
newvaluestoforward is toggled to inform the Objective Decision Block that a trace has started
and action will be necessary. This second trace / “Imply” operation is shown in Figure C.12.
Figure C.12: s27 Simulation Frame k-1 Imply 2
In the next cycle, the “Imply” operation is complete and updated values are available on the
output of the Forward Network. The current PPO values are checked against their associated
values in the RF, as shown in Figure C.13. This time, both values in the RF are satisfied by their
corresponding Forward Network PPO values, so the Done signal is set and newframe_ready is
121
toggled, making the Backward Network encoder signal the PI/PPI Decision Block to take action
via NReady.
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | DONE with frame
# obj-dec | signal newframe_ready
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
Table C.9: Circuit s27 Simulation Cycles 56-57
Figure C.13: Contents of RF and PO in Frame k-1, Imply 2
Since Done is asserted, it is not frame_1, and there are no PPOs in the current frame to be further
justified, processing must move back yet another frame, to k-2. This time, though, before
proceeding, the PI/PPI Decision Block goes to state 21. This is the State Check, which is run for
each “Move to Ti-1” operation beyond frame_k.
# mycontrol | in state 0
# back-enc | recovering nready in idle
# mycontrol | executing state 21
# memram | ADDRESS=addr=00000000000100
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 11111111111111
# memram | ram reading out - =00000000100010
# memram | ADDRESS=addr=00000000000011
# Reading the ram
# ------------------------------
# mycontrol | in state 21
122
# statecheck | store value in Out: 00000000100010
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000010
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001100100
# memram | ram reading out - =00000001010010
# memram | ADDRESS=addr=00000000000001
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001010010
# memram | ram reading out - =00000001101100
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | end of frame compare (Addr=00000000000000)
# statecheck | store value in Out: 00000001101100
# memram | ram reading out - =00000001010010
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001010010
# memram | setting Top in RAM
# memram | ADDRESS=addr=11111111111110
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | end of frame compare (Addr=11111111111110)
# statecheck | check finished with no duplicates
# memram | ram reading out - =xxxxxxxxxxxxxx
# memram | ADDRESS=addr=11111111111101
# Reading the ram
Table C.10: Circuit s27 Simulation Cycles 58-65
The Forward Network output buffer contains the PI/PPI assignment that defines the current
frame to be locked into memory. To check this, State Check has a separate buffer that each past
frame in the memory is read out to. Each cycle, another past objective from the RAM is read out
into the State Check buffer. When a “top” mark bit is hit, it indicates the current RAM entry is
the start of a different frame. The current values in the State Check buffer are then compared to
123
the Forward Network output buffer. If the first entry in the RAM is reached and the final State
Check comparison passes, then no duplicates were found, and the “Move to Ti-1” process will
begin. In this example, the current assignment for frame k-1 is compared to the assignment for
frame k. It is found to be different, as shown in Figure C.14, so processing continues.
Figure C.14: State Check Comparison for Frame k-1
With the state check complete, the PI/PPI Decision Block continues through the “Move to Ti-1”
operation. Upon seeing the donewithstatecheck signal, the Objective Decision Block clears the
values currently in the RF, in preparation for the next frame to begin. The PI/PPI Decision
Block then begins passing the PPI objectives from the last frame to the Objective Decision
Block, which again stores them in the RF as the PPO objectives for the next frame.
# mycontrol | in state 21
# obj-dec | clearing RF for new frame
# mycontrol | executing state 15
# memram | ram reading out - =xxxxxxxxxxxxxx
# memram | ADDRESS=addr=00000000000100
# Reading the ram
# ------------------------------
# mycontrol | in state 15
# mycontrol | executing state 3
# memram | ram reading out - =00000000100010
# memram | ADDRESS=addr=00000000000100
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# memram | ram reading out - =00000000100010
# memram | ADDRESS=addr=00000000000011
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000010
124
# Reading the ram
# isppi | evaluating output to RF; in=00000001100100
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# obj-dec | read in PPI: 00000001100100
# memram | ram reading out - =00000001010010
# memram | ADDRESS=addr=00000000000001
# Reading the ram
# isppi | evaluating output to RF; in=00000001010010
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# obj-dec | read in PPI: 00000001010010
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti-1)
# obj-dec | read in PPI: 00000001010010
# mycontrol | executing state 8
# fourcounter | counting a frame DOWN
# memram | ram reading out - =00000001010010
# ------------------------------
# mycontrol | in state 8
# mycontrol | executing state 11
# PPI Decision Block | Clearing ValuestoForward
Table C.11: Circuit s27 Simulation Cycles 66-73
Note that although three objectives were written to the Block RAM as part of frame k-1, only
two objective values are transferred to the RF for frame k-2. This is because one of the
objectives in frame k-1 is a PI, which can be set arbitrarily, and thus does not require further
justification. Thus, the “isppi” module filters that objective in the memory while reading, and it
is not passed on to the Objective Decision Block. The contents of the RF after these new values
have been shifted in can be seen in Figure C.15.
Figure C.15: Contents of RF in Frame k-2
125
The PI/PPI Decision Block then clears the Forward Network and proceeds to mark the last
objective in the Block RAM with the “top” bit, indicating the end of the last frame. The contents
of the RAM at this point can be seen in Figure C.16.
Figure C.16: Contents of Block RAM at Frame k-2 Start
At the same time that the “top” bit is being marked, the Objective Decision Block has again been
triggered to action. All PO/PPOs from the Forward Network are cleared (values of X), and it is
not frame_1, so an objective from the RF will be selected for justification. The first value is
selected and passed to the Backward Network Decoder. The decoder clears the Backward
Network, pushes the new objective on, and signals the Backward Network Encoder that a new
“Backtrace” is starting.
# mycontrol | in state 11
# obj-dec | not frame k, check for conflict/done
# obj-dec | push obj: 00000001010010
# mycontrol | executing state 4
# memram | beginning rewrite1
# memram | ADDRESS=li=0100
# ------------------------------
# mycontrol | in state 4
# back-dec | received new obj: 00000001010010
# mycontrol | executing state 0
# memram | setting the flag in RAM
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000001010010
126
# ------------------------------
# mycontrol | in state 0
# back-enc | trace started, waiting for results
Table C.12: Circuit s27 Simulation Cycles 74-78
Note that this first objective is the same as the first objective Backtraced as part of frame k-1,
and as such, the results of the “Backtrace” operation will be the same, as shown in Figure C.17.
Figure C.17: s27 Simulation Frame k-2 Backtrace 1
The same traced values as before are received and passed back to the PI/PPI Decision Block.
These values are again stored in the Block RAM, and pushed onto the Forward Network, leading
to the same situation as in frame k-1.
# mycontrol | in state 0
# back-enc | traced values received
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 16
# ------------------------------
# mycontrol | in state 16
# back-enc | found obj at PPI index
00000000000000000000000000000101: 01
# mycontrol | executing state 0
127
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000100
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001010010
# memram | ADDRESS=li=0101
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=01
# ------------------------------
# mycontrol | in state 10
# back-enc | found obj at PPI index
00000000000000000000000000000110: 10
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000101
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000001100100
# memram | ADDRESS=li=0110
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=10
# ------------------------------
# mycontrol | in state 10
# back-enc | no objectives; done
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
# ------------------------------
128
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | push obj: 00000001100100
# ------------------------------
# mycontrol | in state 0
# back-dec | received new obj: 00000001100100
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000001100100
# ------------------------------
# mycontrol | in state 0
# back-enc | trace started, waiting for results
Table C.13: Circuit s27 Simulation Cycles 79-95
The second objective to be pushed to the Backward Network is also the same, and the state of the
Forward Network is the same, so the second “Backtrace” operation is also identical, as shown in
Figure C.18.
Figure C.18: s27 Simulation Frame k-2 Backtrace 2
Again, the same objective is backtraced and returned to the PI/PPI Decision Block, which in turn
pushes the update onto the Forward Network. The Objective Decision Block is now in the exact
same state as it was in frame k-1. Since both objectives in the RF are satisfied, the Done signal
is set and the PI/PPI Decision Block is again triggered that the current frame is done.
129
# mycontrol | in state 0
# back-enc | traced values received
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 16
# ------------------------------
# mycontrol | in state 16
# back-enc | found obj at PI index 0000000010: 01
# mycontrol | executing state 0
# ------------------------------
# mycontrol | in state 0
# back-enc | reset nready signal
# mycontrol | executing state 1
# memram | beginning push
# memram | ADDRESS=0=0000000110
# ------------------------------
# mycontrol | in state 1
# mycontrol | executing state 17
# memram | pushing on to ram
# input word=00000000100010
# memram | ADDRESS=li=0111
# ------------------------------
# mycontrol | in state 17
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000010
# val=01
# ------------------------------
# mycontrol | in state 10
# back-enc | no objectives; done
# PPI Decision Block | Assign vf (from top)
# addr=0000000010
# val=01
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
# ------------------------------
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | DONE with frame
# obj-dec | signal newframe_ready
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
Table C.14: Circuit s27 Simulation Cycles 96-105
130
Since it is not frame_k or frame_1 and there are PPI objectives from the last frame, a “Move to
Ti-1” operation is desired. This then again triggers the State Check operation, which begins
reading out past frame values to the State Check buffer for comparison vs. the last frame’s
assignment.
# mycontrol | in state 0
# back-enc | recovering nready in idle
# mycontrol | executing state 21
# memram | ADDRESS=addr=00000000000111
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 11111111111111
# memram | ram reading out - =00000000100010
# memram | ADDRESS=addr=00000000000110
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000000100010
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000101
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001100100
# memram | ram reading out - =00000001010010
# memram | ADDRESS=addr=00000000000100
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001010010
# memram | ram reading out - =00000000101010
# memram | ADDRESS=addr=00000000000011
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | end of frame compare (Addr=00000000000011)
# statecheck | store value in Out: 00000000101010
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000010
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001100100
# memram | ram reading out - =00000001010010
131
# memram | ADDRESS=addr=00000000000001
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | store value in Out: 00000001010010
# memram | ram reading out - =00000001101100
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# ------------------------------
# mycontrol | in state 21
# statecheck | end of frame compare (Addr=00000000000000)
# statecheck | duplicate found
# memram | ram reading out - =00000001010010
# memram | ADDRESS=li=0111
# Reading the ram
Table C.15: Circuit s27 Simulation Cycles 106-114
This time in the State Check, a duplicate is found, as frame k-1 was exactly the same as the
current frame k-2. The presence of the duplicate indicates a loop in frame assignments, so a
Backtrack operation is started. In this case of a State Check failure, the PI/PPI Decision Block
goes directly to state 9, which completes a “Clear Top” operation, removing the last set objective
on the RAM.
# mycontrol | in state 21
# isppi | evaluating output to RF; in=00000001010010
# mycontrol | executing state 9
# memram | setting Top in RAM
# memram | beginning cleartop
# memram | ADDRESS=li=0111
# ------------------------------
# mycontrol | in state 9 (cycle 1)
# mycontrol | executing state 9
# memram | clearing top value in RAM
# ------------------------------
# mycontrol | in state 9 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0111
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0111
# Reading the ram
132
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000010
# val=11
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 2
# memram | beginning pop
# memram | ADDRESS=li=0111
# ------------------------------
# mycontrol | in state 2
# mycontrol | executing state 12
# memram | popping off of RAM
# memram | ADDRESS=li=0110
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0110
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 18
# memram | setting Top in RAM
# memram | ADDRESS=li=0110
# Reading the ram
Table C.16: Circuit s27 Simulation Cycles 115-123
After clearing the value in the RAM, the Forward Network output buffer is also updated to clear
the associated value to “X”. Finally, the “top” mark bit is updated to the second to last objective
value from the last frame, as the cleared value is no longer part of the last frame. The contents of
the Block RAM after this clear operation are shown in Figure C.19.
133
Figure C.19: Contents of Block RAM after First Clear Top
After the “Clear Top” operation completes, the PI/PPI Decision Block moves to state 6 to
continue the Backtrack with a “Swap Value” operation. In this process the current top objective
in the RAM for the last frame is read out, its value is swapped from 1 to 0, and it is written back
into the Block RAM. The contents of the Block RAM after the “Swap Value” operation are
shown in Figure C.20.
# mycontrol | in state 18
# mycontrol | executing state 6
# memram | setting Top in RAM
# memram | beginning swapwrite
# memram | ADDRESS=li=0110
# ------------------------------
# mycontrol | in state 6 (cycle 1)
# mycontrol | executing state 6
# memram | swapping values in RAM
# ram_DATA_IN before swap: xx0000000001100100
# memram | ram_DATA_IN after swap: xx0000000001100011
# memram | ram_ADDRESS=0000000110
# ------------------------------
# mycontrol | in state 6 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0110
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0110
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
134
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=01
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
Table C.17: Circuit s27 Simulation Cycles 124-129
Figure C.20: Contents of Block RAM after First Swap Value
After the objective value is updated in both the Block RAM and the Forward Network output
buffer, a new trace is started on the Forward Network, and the Objective Decision Block is
signaled to expect trace results. The new Forward Trace with the swapped value is shown in
Figure C.21. Note that the value that was cleared was associated with “G2” and the value that
was swapped was associated with “g6”. The value of “g7” remains the same.
135
Figure C.21: s27 Simulation Frame k-2, Backtrack 1 Imply
Although two objective values are pushed onto the Forward Network, they both stop propagating
within the circuit, which results in the PO/PPO feeding the Objective Decision block with all Xs.
Thus, for the Objective Decision Block, the current state looks the same as the start of frame k-2,
with two objectives in the RF to justify, and no current PPO values from the Forward Network.
The first objective (G6=0) is selected.
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | push obj: 00000001010010
# ------------------------------
# mycontrol | in state 0
# back-dec | received new obj: 00000001010010
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000001010010
# ------------------------------
# mycontrol | in state 0
# back-enc | trace started, waiting for results
Table C.18: Circuit s27 Simulation Cycles 130-134
The Backward Network Decoder clears the Backward Network and pushes this new objective on
to be backtraced. Note that this time for the “Backtrace” of G6=0, there are different STATE
136
values coming from the Forward Network, which change the behavior of the operation, as shown
in Figure C.22.
Figure C.22: Simulation Frame k-2, Backtrack 1 Backtrace
One portion of the Backtrace is stopped at gate G8 due to a prior assignment in the Forward
Network. The other portion of the Backtrace, going to “g7” is also stopped, though the reason is
not apparent due to another abstraction in the illustration. As part of DFF handling, isolation
buffers are added to all DFF outputs. This prevents no-logic paths from being introduced into
the networks by DFFs feeding other DFFs. One other effect of this is that these buffers are
present on all PPI inputs in the networks. Thus, this “virtual” buffer on “g7” has an inherited
value of 0 from the Forward Network due to the traced assignment. Thus, the value that is
attempting to be Backtraced to “g7” is blocked.
This situation leads to no change in the Backward Network output. This trace failure is caught
by the Backward Network Encoder, which signals the Objective Decision Block via the propfail
signal. The Objective Decision Block sees this signal and raises Conflict to the PI/PPI Decision
137
Block. At the same time, the Backward Network Encoder also sets NReady low to trigger the
PI/PPI Decision Block to action.
# mycontrol | in state 0
# back-enc | no obj propagated; signaling propagation failure
# ------------------------------
# mycontrol | in state 0
# obj-dec | back-net propagation failure
# back-enc | asserting delayed NReady
Table C.19: Circuit s27 Simulation Cycles 135-136
With Conflict asserted, the PI/PPI Decision Block again moves to state 9, starting another
Backtrack operation with a “Clear Top”. After that, “Swap Value” is again performed, updating
both the Block RAM and Forward Network output buffer. Upon completion of this “Backtrack”,
the latest values are again pushed onto the Forward Network.
# mycontrol | in state 0
# obj-dec | back-net propagation failure
# back-enc | recovering nready in idle
# mycontrol | executing state 9
# memram | beginning cleartop
# memram | ADDRESS=li=0110
# ------------------------------
# mycontrol | in state 9 (cycle 1)
# mycontrol | executing state 9
# memram | clearing top value in RAM
# ------------------------------
# mycontrol | in state 9 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0110
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0110
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
138
# val=11
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 2
# memram | beginning pop
# memram | ADDRESS=li=0110
# ------------------------------
# mycontrol | in state 2
# mycontrol | executing state 12
# memram | popping off of RAM
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 18
# memram | setting Top in RAM
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 18
# mycontrol | executing state 6
# memram | setting Top in RAM
# memram | beginning swapwrite
# memram | ADDRESS=li=0101
# ------------------------------
# mycontrol | in state 6 (cycle 1)
# mycontrol | executing state 6
# memram | swapping values in RAM
# ram_DATA_IN before swap: xx0000000001010010
# memram | ram_DATA_IN after swap: xx0000000001010101
# memram | ram_ADDRESS=0000000101
# ------------------------------
# mycontrol | in state 6 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
139
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=10
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
Table C.20: Circuit s27 Simulation Cycles 137-151
Note that in this second “Backtrack” operation the value of G7 was cleared, and the value of G6
was swapped from 0 to 1. Once these updated values are pushed onto the Forward Network, the
resulting “Imply” operation is shown in Figure C.23.
Figure C.23: s27 Simulation Frame k-2, Backtrack 2 Imply
This time in the “Imply” operation, the remaining value of g6=1 is immediately stopped, as it
directly feeds a single AND gate, and a value of 1 just passes through the X on the other input.
No PO/PPO values change from the Forward Network, and the Objective Decision Block then
detects a propagation failure on the Forward Network. The Conflict signal is again raised, with
newframe_ready being sent to the Backward Network Encoder to signal the PI/PPI Decision
Block with NReady. The PI/PPI Decision Block, having Conflict set again, begins another
“Backtrack” operation.
140
# mycontrol | in state 0
# obj_dec | fwd network propagation failure
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
# ------------------------------
# mycontrol | in state 0
# back-enc | recovering nready in idle
# mycontrol | executing state 9
# memram | beginning cleartop
# memram | ADDRESS=li=0101
# ------------------------------
# mycontrol | in state 9 (cycle 1)
# mycontrol | executing state 9
# memram | clearing top value in RAM
# ------------------------------
# mycontrol | in state 9 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0101
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=11
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 2
# memram | beginning pop
# memram | ADDRESS=li=0101
# ------------------------------
# mycontrol | in state 2
# mycontrol | executing state 12
# memram | popping off of RAM
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
141
# mycontrol | executing state 18
# memram | setting Top in RAM
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 18
# mycontrol | executing state 5
# memram | setting Top in RAM
# memram | beginning rewrite0
# memram | ADDRESS=li=0100
Table C.21: Circuit s27 Simulation Cycles 152-163
This time, there is only one objective left in the current frame k-2. Once the “Clear Top”
operation has completed, the PI/PPI Decision block sees the “top” bit set on the next objective
that it needs to execute a “Swap Value” on. This indicates that all options in the current frame
have been exhausted and a “Move to Ti+1” operation must be completed to continue the
“Backtrack” operation.
When the “Move to Ti+1” operation begins, the PI/PPI Decision Block sets the tiplus1 signal,
which triggers the Objective Decision Block to clear the RF, in preparation for a new frame. The
first operation that the PI/PPI Decision Block needs to complete is restoring the final state from
the frame that is being moved to. To do this, each objective value from the new frame is read out
from the Block RAM and into the Forward Network output buffer, cycling between states 3 and
22. Once complete, the previous PPO objective values in the RF must be restored. The
objective values from the frame prior to the one being moved to are also read out, and passed
over the ppi bus to the Objective Decision Block to read into the RF. Once all objective values
have been read out, the “top” mark bit is cleared from the last objective in the RAM, “unlocking”
the frame being moved to, and the counter increments by 1 to reflect the new current state.
142
# mycontrol | in state 5 (cycle 1)
# obj-dec | clearing RF for new frame
# clearing the flag in RAM
# ------------------------------
# mycontrol | in state 5 (cycle 2)
# mycontrol | executing state 3
# memram | ADDRESS=addr=00000000000100
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# mycontrol | executing state 22
# PPI Decision Block | Assign vf (from Out)
# addr=1111111111
# val=11
# memram | ram reading out - =00000000100010
# memram | ADDRESS=addr=00000000000011
# Reading the ram
# PPI Decision Block | Assign vf (from Out)
# addr=0000000010
# val=01
# ------------------------------
# mycontrol | in state 22
# mycontrol | executing state 3
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000011
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# mycontrol | executing state 22
# PPI Decision Block | Assign vf (from Out)
# addr=0000000110
# val=10
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000010
# Reading the ram
# ------------------------------
# mycontrol | in state 22
# mycontrol | executing state 3
# memram | ram reading out - =00000001010010
# memram | ADDRESS=addr=00000000000010
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# mycontrol | executing state 22
# PPI Decision Block | Assign vf (from Out)
# addr=0000000101
# val=01
# memram | ram reading out - =00000001010010
# memram | ADDRESS=addr=00000000000001
# Reading the ram
143
# ------------------------------
# mycontrol | in state 22
# mycontrol | executing state 3
# memram | ram reading out - =00000001101100
# memram | ADDRESS=addr=00000000000001
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# isppi | evaluating output to RF; in=00000001101100
# memram | ram reading out - =00000001101100
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# obj-dec | read in PPI: 00000001101100
# memram | ram reading out - =00000001010010
# memram | ADDRESS=li=0100
# Reading the ram
# isppi | evaluating output to RF; in=00000001010010
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# obj-dec | read in PPI: 00000001010010
# mycontrol | executing state 7
# fourcounter | counting a frame UP
# memram | setting Top in RAM
Table C.22: Circuit s27 Simulation Cycles 164-174
Once the “Move to Ti+1” operation has completed, the Backtrack that was in progress can
continue. It left off waiting to run a “Swap Value” on the last value in the frame that is now the
current frame (k-1). That “Swap Value” is now executed, and the current memory state after
both the “Move to Ti+1” and “Swap Value” is shown in Figure C.24.
Figure C.24: Block RAM Contents after Move to Ti+1 and Swap Value
144
Once the value is swapped in the Block RAM, it is also updated in the Forward Network output
buffer. The PI/PPI Decision Block then pushes these updated values into the Forward Network
to start a new “Imply” operation. Note that this time, the value that was swapped was that of G2,
changing from 0 to 1, while g7 remains 1 and g6 remains 0, for frame k-1. This “Imply”
operation is shown in Figure C.25.
Figure C.25: s27 Simulation Frame k-1, Backtrack 1 Imply
# mycontrol | in state 7
# mycontrol | executing state 6
# memram | beginning swapwrite
# memram | ADDRESS=li=0100
# ------------------------------
# mycontrol | in state 6 (cycle 1)
# mycontrol | executing state 6
# memram | swapping values in RAM
# ram_DATA_IN before swap: xx0000000000100010
# memram | ram_DATA_IN after swap: xx0000000000100101
# memram | ram_ADDRESS=0000000100
# ------------------------------
# mycontrol | in state 6 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0100
# Reading the ram
145
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000010
# val=10
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
Table C.23: Circuit s27 Simulation Cycles 175-180
Note that this time when the “Imply” operation completes the PO/PPO assignment from the
Forward Network includes the assignment G7=0. Comparing this with the contents of the RF, as
shown in Figure C.26, there is now a value conflict between the required PPO value of G7 from
the previous frame (1), and the assigned value in the current frame (0).
Figure C.26: RF Contents and PO/PPO after Move to Ti+1, Imply 1
The Objective Decision Block detects this conflict, causing it to raise the Conflict signal again.
The newframe_ready signal is sent to the Backward Network Encoder, which again sets the
NReady signal, triggering the PI/PPI Decision Block to take action. With the Conflict signal
raised, the PI/PPI Decision Block will run another iteration of the “Backtrack” operation.
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | CONFLICT found
# obj-dec | signal newframe_ready
# ------------------------------
146
# mycontrol | in state 0
# back-enc | forwarding newframe nready
# ------------------------------
# mycontrol | in state 0
# back-enc | recovering nready in idle
# mycontrol | executing state 9
# memram | beginning cleartop
# memram | ADDRESS=li=0100
# ------------------------------
# mycontrol | in state 9 (cycle 1)
# mycontrol | executing state 9
# memram | clearing top value in RAM
# ------------------------------
# mycontrol | in state 9 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0100
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000010
# val=11
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 2
# memram | beginning pop
# memram | ADDRESS=li=0100
# ------------------------------
# mycontrol | in state 2
# mycontrol | executing state 12
# memram | popping off of RAM
# memram | ADDRESS=li=0011
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0011
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 18
# memram | setting Top in RAM
# memram | ADDRESS=li=0011
147
# Reading the ram
# ------------------------------
# mycontrol | in state 18
# mycontrol | executing state 6
# memram | setting Top in RAM
# memram | beginning swapwrite
# memram | ADDRESS=li=0011
# ------------------------------
# mycontrol | in state 6 (cycle 1)
# mycontrol | executing state 6
# memram | swapping values in RAM
# ram_DATA_IN before swap: xx0000000001100100
# memram | ram_DATA_IN after swap: xx0000000001100011
# memram | ram_ADDRESS=0000000011
# ------------------------------
# mycontrol | in state 6 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0011
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0011
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=01
# memram | setting Top in RAM
Table C.24: Circuit s27 Simulation Cycles 181-196
Note that after this “Backtrack” operation, the contents of the Block RAM for frame k-1 are
exactly the same as the contents of the RAM were for frame k-2 after the first “Backtrack”
operation. The current contents of the Block RAM at this point are shown in Figure C.27.
148
Figure C.27: Block RAM Contents after Move to Ti+1 and Backtrack
Since the current state in frame k-1 is the same as it was in frame k-2 after the first “Backtrack”,
the simulation will proceed exactly as it did in that state, triggering two more “Backtrack”
operations, until the end of frame k-1 is encountered.
# mycontrol | in state 10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
# ------------------------------
# mycontrol | in state 0
# obj-dec | not frame k, check for conflict/done
# obj-dec | push obj: 00000001010010
# ------------------------------
# mycontrol | in state 0
# back-dec | received new obj: 00000001010010
# ------------------------------
# mycontrol | in state 0
# back-dec | clearing back-net
# ------------------------------
# mycontrol | in state 0
# back-dec | pushing obj onto back-net: 00000001010010
# ------------------------------
# mycontrol | in state 0
# back-enc | trace started, waiting for results
# ------------------------------
# mycontrol | in state 0
# back-enc | no obj propagated; signaling propagation failure
# ------------------------------
# mycontrol | in state 0
# obj-dec | back-net propagation failure
# back-enc | asserting delayed NReady
# ------------------------------
# mycontrol | in state 0
# obj-dec | back-net propagation failure
149
# back-enc | recovering nready in idle
# mycontrol | executing state 9
# memram | beginning cleartop
# memram | ADDRESS=li=0011
# ------------------------------
# mycontrol | in state 9 (cycle 1)
# mycontrol | executing state 9
# memram | clearing top value in RAM
# ------------------------------
# mycontrol | in state 9 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0011
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0011
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=11
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 2
# memram | beginning pop
# memram | ADDRESS=li=0011
# ------------------------------
# mycontrol | in state 2
# mycontrol | executing state 12
# memram | popping off of RAM
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 18
# memram | setting Top in RAM
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 18
# mycontrol | executing state 6
150
# memram | setting Top in RAM
# memram | beginning swapwrite
# memram | ADDRESS=li=0010
# ------------------------------
# mycontrol | in state 6 (cycle 1)
# mycontrol | executing state 6
# memram | swapping values in RAM
# ram_DATA_IN before swap: xx0000000001010010
# memram | ram_DATA_IN after swap: xx0000000001010101
# memram | ram_ADDRESS=0000000010
# ------------------------------
# mycontrol | in state 6 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=10
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
# ------------------------------
# mycontrol | in state 0
# obj_dec | fwd network propagation failure
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
# ------------------------------
# mycontrol | in state 0
# back-enc | recovering nready in idle
# mycontrol | executing state 9
# memram | beginning cleartop
# memram | ADDRESS=li=0010
# ------------------------------
# mycontrol | in state 9 (cycle 1)
# mycontrol | executing state 9
# memram | clearing top value in RAM
# ------------------------------
# mycontrol | in state 9 (cycle 2)
# mycontrol | executing state 12
151
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0010
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000101
# val=11
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 2
# memram | beginning pop
# memram | ADDRESS=li=0010
# ------------------------------
# mycontrol | in state 2
# mycontrol | executing state 12
# memram | popping off of RAM
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 18
# memram | setting Top in RAM
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
# mycontrol | in state 18
# mycontrol | executing state 5
# memram | setting Top in RAM
# memram | beginning rewrite0
# memram | ADDRESS=li=0001
Table C.25: Circuit s27 Simulation Cycles 197-231
Once the third “Backtrack” operation in frame k-1 starts, it encounters the same situation as in
frame k-2. There are no more objectives in frame k-1, and the next objective to be set is part of
152
frame k. Thus the PI/PPI Decision Block starts another “Move to Ti+1” operation. Note that this
time, the Forward Network output buffer is updated with the frame k PI/PPI assignments, but no
PPO objective values are sent to the RF in the Objective Decision Block, once it clears itself for
the new frame. Since the new frame is frame k, there is no frame before it where PPO objectives
would have been inherited from. The only objective in frame k is line_k=1, which is specially
checked by the Objective Decision Block (instead of checking the RF) when in frame_k.
# mycontrol | in state 5 (cycle 1)
# obj-dec | clearing RF for new frame
# clearing the flag in RAM
# ------------------------------
# mycontrol | in state 5 (cycle 2)
# mycontrol | executing state 3
# memram | ADDRESS=addr=00000000000001
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# mycontrol | executing state 22
# PPI Decision Block | Assign vf (from Out)
# addr=1111111111
# val=11
# memram | ram reading out - =00000001100100
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# PPI Decision Block | Assign vf (from Out)
# addr=0000000110
# val=10
# ------------------------------
# mycontrol | in state 22
# mycontrol | executing state 3
# memram | ram reading out - =00000001010010
# memram | ADDRESS=addr=00000000000000
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# mycontrol | executing state 22
# PPI Decision Block | Assign vf (from Out)
# addr=0000000101
# val=01
# memram | ram reading out - =00000001010010
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
153
# mycontrol | in state 22
# mycontrol | executing state 3
# memram | setting Top in RAM
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
# mycontrol | in state 3 (Ti+1)
# mycontrol | executing state 7
# fourcounter | counting a frame UP
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 7
# mycontrol | executing state 6
# memram | beginning swapwrite
# memram | ADDRESS=li=0001
# ------------------------------
# mycontrol | in state 6 (cycle 1)
# mycontrol | executing state 6
# memram | swapping values in RAM
# ram_DATA_IN before swap: xx0000000001100100
# memram | ram_DATA_IN after swap: xx0000000001100011
# memram | ram_ADDRESS=0000000001
Table C.26: Circuit s27 Simulation Cycles 232-240
After the “Move to Ti+1” operation and the following “Swap Value” occur, the circuit is back in
frame_k, with a changed value for the second objective that was part of that frame (g7). The
state of the Block RAM at this point can be seen in Figure C.28.
Figure C.28: Block RAM Contents after Second Move to Ti+1 and Swap Value
154
After swapping the value in the Block RAM, the value is also updated in the Forward Network
output buffer, which is then pushed onto the Forward Network to start a new “Imply” operation.
This new “Imply” with g7 swapped to 0 and g6 remaining 0 is shown in Figure C.29.
Figure C.29: Simulation Frame k, Backtrack 1 Imply
# mycontrol | in state 6 (cycle 2)
# mycontrol | executing state 12
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 1)
# memram | setting Top in RAM
# memram | ADDRESS=li=0001
# Reading the ram
# ------------------------------
# mycontrol | in state 12 (cycle 2)
# mycontrol | executing state 10
# PPI Decision Block | Assign vf (from top)
# addr=0000000110
# val=01
# memram | setting Top in RAM
# ------------------------------
# mycontrol | in state 10
# mycontrol | executing state 0
# PPI Decision Block | Sending Values to Forward Network
Table C.27: Circuit s27 Simulation Cycles 241-244
155
Propagation of both objectives is stopped early, as they cause single 0 inputs to OR gates, which
passes through a value of X. Thus, the PO/PPO outputs of the Forward Network remain all Xs,
causing the Objective Decision Block to detect a Forward Network propagation failure. The
Objective Decision Block raises Conflict and toggles newframe_ready, triggering the Backward
Network Encoder to set NReady low. The PI/PPI Decision Block is triggered by NReady, and
sees the current state of Conflict and frame_k, which indicates a final FAIL. The PI/PPI Decision
Block moves to a final state of 13, which sets the FAIL output of the circuit high.
# mycontrol | in state 0
# obj_dec | fwd network propagation failure
# ------------------------------
# mycontrol | in state 0
# back-enc | forwarding newframe nready
# ------------------------------
# mycontrol | in state 0
# back-enc | recovering nready in idle
# FAIL!!!
# cycle= 247 FAIL=1 DONE=0
Table C.28: Circuit s27 Simulation Cycles 245-247
156
Appendix D: FPGA Emulation Algorithm Implementation Base Verilog Code
Included in this appendix is the base Verilog code implementing the FPGA emulation for the
algorithm presented here. Each module is implemented as described in section 3. Forward and
Backward Networks are excluded from this code, as they are specific to the circuit under test.
Example network code can be found in Appendix A. Note that the n/m/l/s parameter settings in
the code are not generic, and are updated for each different circuit under test via the script in
Appendix F.
00000001 //
00000002 //
00000003 // STATIC CODE
00000004 //
00000005 //
00000006
00000007 module vcontrol (Top, In, Out);
00000008 input [13:0] Top;
00000009 input [13:0] In;
00000010
00000011 output reg [1:0] Out;
00000012
00000013 //reg [13:0] last_Top;
00000014 //reg [13:0] last_In;
00000015
00000016 always @(Top, In) begin
00000017 //if (Top != last_Top) begin
00000018 // Out = Top[2:1];
00000019 //end
00000020 //else begin
00000021 // Out = In[2:1];
00000022 //end
00000023
00000024 //last_Top is not controlled, so this always reads Top
00000025 Out = Top[2:1];
00000026 end
00000027
00000028 endmodule
00000029
00000030 module obj_dec(global_reset, clk, ppi, PO_0, PO_1, PPO_0, PPO_1, frame_k, obj, Done,
Conflict, line_k_1, line_k_X, obj_set, propfail, newframe_ready, newvaluestoforward,
donewithstatecheck, statecheckresult, tiplus1);
00000031 //parameters - filled in generation
00000032 parameter n = 1;
00000033 parameter m = 4;
00000034 parameter l = 3;
00000035 parameter s = 22;
00000036
00000037 //io
00000038 input global_reset;
00000039 input clk;
00000040 input [13:0] ppi;
00000041 input [n-1:0] PO_0; //gen (n)
00000042 input [n-1:0] PO_1; //gen (n)
00000043 input [l-1:0] PPO_0; //gen (l)
00000044 input [l-1:0] PPO_1; //gen (l)
157
00000045 input frame_k;
00000046 input propfail;
00000047 input newvaluestoforward;
00000048 input donewithstatecheck;
00000049 input statecheckresult;
00000050 input tiplus1;
00000051 output reg [13:0] obj;
00000052 output reg Done;
00000053 output reg Conflict;
00000054 output reg line_k_1;
00000055 output reg line_k_X;
00000056 output reg obj_set;
00000057 output reg newframe_ready;
00000058
00000059 //vars
00000060 reg [13:0] RF [l-1:0];
00000061 reg [l-1:0] val_ppo_1;
00000062 reg [l-1:0] val_ppo_0;
00000063 reg [n-1:0] val_po_1;
00000064 reg [n-1:0] val_po_0;
00000065 reg last_newvaluestoforward;
00000066 reg [31:0] i;
00000067 reg [31:0] j;
00000068 reg rf_clear;
00000069
00000070 //At clock, determine what to do
00000071 always @(posedge global_reset, posedge clk) begin
00000072 //$display("obj-dec | TRIGGER");
00000073 //$display(" global_reset=%b", global_reset);
00000074 //$display(" propfail=%b", propfail);
00000075 //$display(" ppi=%b", ppi);
00000076 //$display(" PO_1=%b", PO_1);
00000077 //$display(" PO_0=%b", PO_0);
00000078 //$display(" PPO_1=%b", PPO_1);
00000079 //$display(" PPO_0=%b", PPO_0);
00000080
00000081 if (global_reset) begin
00000082 $display("obj-dec | RESET");
00000083 val_ppo_1 = {l{1'b0}};
00000084 val_ppo_0 = {l{1'b0}};
00000085 val_po_1 = {n{1'b0}};
00000086 val_po_0 = {n{1'b0}};
00000087 i = 32'b0;
00000088 j = 32'b0;
00000089 newframe_ready = 1'b0;
00000090 obj = 14'b00000000000000;
00000091 obj_set = 1'b0;
00000092 last_newvaluestoforward = 1'b0;
00000093 Done = 1'b0;
00000094 Conflict = 1'b0;
00000095 line_k_1 = 1'b0;
00000096 line_k_X = 1'b0;
00000097
00000098 //clear out RF
00000099 while(i<l) begin
00000100 RF[i] = 14'b0;
00000101 i = i + 1;
00000102 end
00000103
00000104 rf_clear = 1'b1;
00000105 i = 32'b0;
00000106 end
00000107 else if (propfail) begin
00000108 $display("obj-dec | back-net propagation failure");
00000109 Conflict = 1'b1;
00000110 end
00000111 else if (ppi != 14'b11111111111111) begin
00000112 //PPI value being sent from Dec block
00000113 if (ppi[2:1] == 2'b11) begin
158
00000114 //Value is 11; clear entry
00000115 $display("obj-dec | clear RF for PPI: %b", ppi);
00000116 RF[ppi[13:4]-m] = 14'b0;
00000117 end
00000118 else begin
00000119 //Read in ppi value
00000120 $display("obj-dec | read in PPI: %b", ppi);
00000121 RF[ppi[13:4]-m] = ppi;
00000122 rf_clear = 1'b0;
00000123 end
00000124 end
00000125 else if ((donewithstatecheck && !statecheckresult) || tiplus1) begin
00000126 //Moving between frames - clear the RF
00000127 if (!rf_clear) begin
00000128 $display("obj-dec | clearing RF for new frame");
00000129 i = 32'b0;
00000130 while(i<l) begin
00000131 RF[i] = 14'b0;
00000132 i = i + 1;
00000133 end
00000134 rf_clear = 1'b1;
00000135 end
00000136 end
00000137 else if (PPO_1 != val_ppo_1 || PPO_0 != val_ppo_0 || PO_1 != val_po_1
|| PO_0 != val_po_0) begin
00000138 //Reset signals
00000139 //Ready = 1'b1;
00000140 //newframe_ready = 1'b0;
00000141 last_newvaluestoforward = newvaluestoforward;
00000142
00000143 //Data on fwd, read in
00000144 val_ppo_1 = PPO_1;
00000145 val_ppo_0 = PPO_0;
00000146 val_po_1 = PO_1;
00000147 val_po_0 = PO_0;
00000148
00000149 //Is this frame k?
00000150 if(frame_k == 1'b1) begin
00000151 //Frame k, check line_k
00000152 if(val_po_1[0] == 1'b1 && val_po_0[0] == 1'b1) begin
00000153 $display("obj-dec | line_k = X");
00000154 //Line_k = X
00000155 line_k_X = 1'b1;
00000156 line_k_1 = 1'b0;
00000157 //Set line_k=1 on objective
00000158 $display("obj-dec | push obj: %b",
14'b00000000000100);
00000159 obj = 14'b00000000000100;
00000160 obj_set = ~obj_set;
00000161 //Need more justification, stay in frame
00000162 end
00000163 else if(val_po_1[0] == 1'b1 && val_po_0[0] == 1'b0)
begin
00000164 $display("obj-dec | line_k = 1");
00000165 $display("obj-dec | DONE with frame");
00000166 //Line_k = 1
00000167 line_k_X = 1'b0;
00000168 line_k_1 = 1'b1;
00000169 newframe_ready = ~newframe_ready;
00000170 if(l == 1) begin
00000171 Done = 1'b1;
00000172 Conflict = 1'b0;
00000173 end
00000174 //Done with Tk, move to new frame
00000175 end
00000176 else begin
00000177 $display("obj-dec | line_k = 0");
00000178 $display("obj-dec | FAIL");
00000179 //Line_k = 0
159
00000180 line_k_X = 1'b0;
00000181 line_k_1 = 1'b0;
00000182 newframe_ready = ~newframe_ready;
00000183 //FAIL
00000184 end
00000185 end
00000186 else begin
00000187 $display("obj-dec | not frame k, check for
conflict/done");
00000188 //Not frame k, check control logic
00000189 line_k_X = 1'b0;
00000190 line_k_1 = 1'b0;
00000191
00000192 //Conflict/Done logic - created in generation
00000193 // If generated PPO matches past PPI (RF), then Done
00000194 // If PPO/RF mismatch, then Conflict
00000195 // Else, continue to try and assign 11 (X) PPOs
00000196 Conflict = 1'b0;
00000197 Done = 1'b0;
00000198 i = 32'b0;
00000199 j = 32'b0;
00000200 while(i < l) begin
00000201 if((RF[i][2] == 1'b1 && RF[i][1] == 1'b0) &&
(PPO_1[i] == 1'b1 && PPO_0[i] == 1'b0)) begin
00000202 //RF = 10, PPO = 10 : match
00000203 j = j + 1;
00000204 end
00000205 else if((RF[i][2] == 1'b0 && RF[i][1] == 1'b1) &&
(PPO_1[i] == 1'b0 && PPO_0[i] == 1'b1)) begin
00000206 //RF = 01, PPO = 01 : match
00000207 j = j + 1;
00000208 end
00000209 else if((RF[i][2] == 1'b1 && RF[i][1] == 1'b0) &&
(PPO_1[i] == 1'b0 && PPO_0[i] == 1'b1)) begin
00000210 //RF = 10, PPO = 01 : CONFLICT
00000211 $display("obj-dec | CONFLICT found");
00000212 Conflict = 1'b1;
00000213 end
00000214 else if((RF[i][2] == 1'b0 && RF[i][1] == 1'b1) &&
(PPO_1[i] == 1'b1 && PPO_0[i] == 1'b0)) begin
00000215 //RF = 01, PPO = 10 : CONFLICT
00000216 $display("obj-dec | CONFLICT found");
00000217 Conflict = 1'b1;
00000218 end
00000219 else if(RF[i][2] == 1'b0 && RF[i][1] == 1'b0)
begin
00000220 //RF = 00 : NO ASSIGNMENT TO MATCH
00000221 j = j + 1;
00000222 end
00000223
00000224 i = i + 1;
00000225 end
00000226
00000227 if(j == l) begin
00000228 //All RF entries match PPO, we are DONE
00000229 $display("obj-dec | DONE with frame");
00000230 Done = 1'b1;
00000231 end
00000232
00000233
00000234 //If no conflict and not done, pick new obj
00000235 if((Conflict | Done) == 0) begin
00000236 //Start sequencer
00000237 // Find unassigned PPO (11)
00000238 // Where associated PPI is assigned (not 00)
00000239 i = 32'b0;
00000240 j = 32'b0;
00000241 while(j < l && i == 0) begin
00000242 if((RF[j][2] == 1'b0) && (RF[j][1] ==
160
1'b0)) begin
00000243 //No objective at this index in
RF, skip
00000244 end
00000245 else if((PPO_1[j] == 1'b1) && (PPO_0[j]
== 1'b1)) begin
00000246 //RF for this index is not empty
and currently PPO is X, pick up as obj and halt sequencer
00000247 i = j;
00000248 end
00000249 else begin
00000250 //Current RF[j] = PPO[j], already
traced, pick next possible objective
00000251 end
00000252 j = j + 1;
00000253 end
00000254 //Found unassigned ppo with index i
00000255 $display("obj-dec | push obj: %b", RF[i]);
00000256 obj = RF[i];
00000257 obj_set = ~obj_set;
00000258 end
00000259 else begin
00000260 $display("obj-dec | signal newframe_ready");
00000261 //Either DONE or in CONFLICT
00000262 // Signal the Dec_Block
00000263 newframe_ready = ~newframe_ready;
00000264 end
00000265 end
00000266 end
00000267 else if (newvaluestoforward != last_newvaluestoforward) begin
00000268 //Failure to trace on forward network
00000269 $display("obj_dec | fwd network propagation failure");
00000270 Conflict = 1'b1;
00000271 newframe_ready = ~newframe_ready;
00000272 last_newvaluestoforward = newvaluestoforward;
00000273 end
00000274 else begin
00000275 //$display("obj-dec | doing nothing");
00000276 end
00000277 end
00000278 endmodule
00000279
00000280
00000281 module back_encoder(global_reset, clk, trace_start, PI_1, PI_0, PPI_1, PPI_0, NReady,
in, mode, genobj, propfail, newframe_ready);
00000282 ////parameters - filled in generation
00000283 parameter n = 1;
00000284 parameter m = 4;
00000285 parameter l = 3;
00000286 parameter s = 22;
00000287
00000288 //io
00000289 input global_reset;
00000290 input clk;
00000291 input trace_start;
00000292 input genobj;
00000293 input [m-1:0] PI_1;
00000294 input [m-1:0] PI_0;
00000295 input [l-1:0] PPI_1;
00000296 input [l-1:0] PPI_0;
00000297 input newframe_ready;
00000298 output reg NReady;
00000299 output reg [13:0] in;
00000300 output reg mode;
00000301 output reg propfail;
00000302
00000303 //vars
00000304 reg [31:0] i;
00000305 reg last_trace_start;
161
00000306 reg [1:0] state;
00000307 reg [m-1:0] PI_1_save;
00000308 reg [m-1:0] PI_0_save;
00000309 reg [l-1:0] PPI_1_save;
00000310 reg [l-1:0] PPI_0_save;
00000311 reg [m-1:0] PI_1_last;
00000312 reg [m-1:0] PI_0_last;
00000313 reg [l-1:0] PPI_1_last;
00000314 reg [l-1:0] PPI_0_last;
00000315 reg last_newframe_ready;
00000316 reg delayed_nready;
00000317
00000318 always @(posedge clk, posedge global_reset) begin
00000319 if (global_reset) begin
00000320 $display("back-enc | RESET");
00000321 i = 32'b0;
00000322 last_trace_start = 1'b0;
00000323 mode = 1'b0;
00000324 state = 2'b00;
00000325 NReady = 1'b1;
00000326 last_newframe_ready = 1'b0;
00000327 in = 14'b11111111111111;
00000328 delayed_nready = 1'b0;
00000329 propfail = 1'b0;
00000330 PI_1_save = {m{1'b0}};
00000331 PI_0_save = {m{1'b0}};
00000332 PPI_1_save = {l{1'b0}};
00000333 PPI_0_save = {l{1'b0}};
00000334 PI_1_last = {m{1'b0}};
00000335 PI_0_last = {m{1'b0}};
00000336 PPI_1_last = {l{1'b0}};
00000337 PPI_0_last = {l{1'b0}};
00000338 end
00000339 else begin
00000340 if (state == 2'b00) begin
00000341 //STATE=IDLE
00000342 if (trace_start != last_trace_start) begin
00000343 //Ready has toggled, a back-trace is in progress
00000344 $display("back-enc | trace started, waiting for
results");
00000345 mode = 1'b1;
00000346 last_trace_start = trace_start;
00000347 state = 2'b01;
00000348 NReady = 1'b1;
00000349 propfail = 1'b0;
00000350 end
00000351 else if (newframe_ready != last_newframe_ready) begin
00000352 //Trigger Dec to move to new frame
00000353 $display("back-enc | forwarding newframe
nready");
00000354 last_newframe_ready = newframe_ready;
00000355 NReady = 1'b0;
00000356 end
00000357 else if (delayed_nready == 1'b1) begin
00000358 //Assert delayed NReady signal
00000359 $display("back-enc | asserting delayed NReady");
00000360 delayed_nready = 1'b0;
00000361 NReady = 1'b0;
00000362 end
00000363 else if (NReady == 1'b0) begin
00000364 //Reset NReady to 1
00000365 $display("back-enc | recovering nready in idle");
00000366 NReady = 1'b1;
00000367 if (propfail) begin
00000368 propfail = 1'b0;
00000369 end
00000370 end
00000371 end
00000372 else if (state == 2'b01) begin
162
00000373 //STATE=WAITING ON TRACE
00000374 if (PI_1 == PI_1_last && PI_0 == PI_0_last && PPI_1 ==
PPI_1_last && PPI_0 == PPI_0_last) begin
00000375 //Backtrace has failed (no value change)
00000376 $display("back-enc | no values change; signaling
propagation failure");
00000377 propfail = 1'b1;
00000378 state = 2'b00;
00000379 mode = 1'b0;
00000380 delayed_nready = 1'b1;
00000381 end
00000382 else if (PI_1 == {m{1'b0}} && PPI_1 == {l{1'b0}}) begin
00000383 //Backtrace has failed (no objective propagation)
00000384 $display("back-enc | no obj propagated; signaling
propagation failure");
00000385 propfail = 1'b1;
00000386 state = 2'b00;
00000387 mode = 1'b0;
00000388 delayed_nready = 1'b1;
00000389 end
00000390 else begin
00000391 //Backtrace success, save values
00000392 $display("back-enc | traced values received");
00000393 PI_1_save = PI_1;
00000394 PI_0_save = PI_0;
00000395 PPI_1_save = PPI_1;
00000396 PPI_0_save = PPI_0;
00000397 state = 2'b10;
00000398 NReady = 1'b0;
00000399 end
00000400 end
00000401 else if (state == 2'b10) begin
00000402 //STATE=PUSHING TO DEC BLOCK
00000403 if (NReady) begin
00000404 //Ready to push an objective out
00000405 if (genobj) begin
00000406 //Obj encode requested
00000407 i = 32'b0;
00000408 while ((i < m) && (PI_1_save[i] != 1'b1))
begin
00000409 i = i + 1;
00000410 end
00000411
00000412 if (i >= m) begin
00000413 //No objective on PI, check PPI
00000414 if (l > 1) begin
00000415 i = 32'b0;
00000416 while ((i < l) &&
(PPI_1_save[i] != 1'b1)) begin
00000417 i = i + 1;
00000418 end
00000419
00000420 if (i != l) begin
00000421 //Found objective
input with index i, PPI(i), encode
00000422 $display("back-enc
| found obj at PPI index %b: %b%b", i+m, PPI_0_save[i], !PPI_0_save[i]);
00000423 in[13:4] = i + m;
00000424 in[3] = 1'b0;
00000425 in[2] =
PPI_0_save[i];
00000426 in[1] =
!PPI_0_save[i];
00000427 in[0] = 1'b0;
00000428 PPI_1_save[i] =
1'b0;
00000429 NReady = 1'b0;
00000430 end
00000431 else begin
163
00000432 //No ojbective
found, set mode to done
00000433 $display("back-enc
| no objectives; done");
00000434 in =
14'b11111111111111;
00000435 mode = 1'b0;
00000436 state = 2'b00;
00000437 end
00000438 end
00000439 else begin
00000440 $display("back-enc | no
objectives; done");
00000441 in = 14'b11111111111111;
00000442 mode = 1'b0;
00000443 state = 2'b00;
00000444 end
00000445 end
00000446 else begin
00000447 //Found objective input with index
i, encode
00000448 $display("back-enc | found obj at
PI index %b: %b%b", i, PI_0_save[i], !PI_0_save[i]);
00000449 in[13:4] = i;
00000450 in[3] = 1'b0;
00000451 in[2] = PI_0_save[i];
00000452 in[1] = !PI_0_save[i];
00000453 in[0] = 1'b0;
00000454 PI_1_save[i] = 1'b0;
00000455 NReady = 1'b0;
00000456 end
00000457 end
00000458 end
00000459 else begin
00000460 //Reset ready cycle
00000461 $display("back-enc | reset nready signal");
00000462 NReady = 1'b1;
00000463 end
00000464 end
00000465
00000466 if (mode != 2'b01) begin
00000467 //Not waiting on trace - save current back net values
00000468 PI_1_last = PI_1;
00000469 PI_0_last = PI_0;
00000470 PPI_1_last = PPI_1;
00000471 PPI_0_last = PPI_0;
00000472 end
00000473 end
00000474 end
00000475 endmodule
00000476
00000477
00000478 module back_decoder(global_reset, clk, obj, obj_set, PO_1, PO_0, PPO_1, PPO_0, PI_1,
PI_0, PPI_1, PPI_0, priority_reset, trace_start);
00000479 ////parameters - filled in generation
00000480 parameter n = 1;
00000481 parameter m = 4;
00000482 parameter l = 3;
00000483 parameter s = 22;
00000484
00000485 //io
00000486 input global_reset;
00000487 input clk;
00000488 input [13:0] obj;
00000489 input obj_set;
00000490 input [n-1:0] PO_1;
00000491 input [n-1:0] PO_0;
00000492 input [l-1:0] PPO_1;
00000493 input [l-1:0] PPO_0;
164
00000494 output reg [n-1:0] PI_1;
00000495 output reg [n-1:0] PI_0;
00000496 output reg [l-1:0] PPI_1;
00000497 output reg [l-1:0] PPI_0;
00000498 output reg priority_reset;
00000499 output reg trace_start;
00000500
00000501 //vars
00000502 reg [31:0] i;
00000503 reg [1:0] mode;
00000504 reg last_obj_set;
00000505
00000506 always @(posedge clk, posedge global_reset) begin
00000507 if (global_reset) begin
00000508 $display("back-bec | RESET");
00000509 priority_reset = 1'b0;
00000510 trace_start = 1'b0;
00000511 i = 32'b0;
00000512 mode = 2'b00;
00000513 last_obj_set = 1'b0;
00000514 PI_1 = {n{1'b0}};
00000515 PI_0 = {n{1'b0}};
00000516 PPI_1 = {l{1'b0}};
00000517 PPI_0 = {l{1'b0}};
00000518 end
00000519 else begin
00000520 if (mode == 2'b00 && obj_set != last_obj_set) begin
00000521 //Obj has changed - start clear/encode sequence
00000522 $display("back-dec | received new obj: %b", obj);
00000523 mode = 2'b01;
00000524 last_obj_set = obj_set;
00000525 end
00000526 else if(mode == 2'b01) begin
00000527 //Clear the back net
00000528 $display("back-dec | clearing back-net");
00000529 PI_1 = {n{1'b0}};
00000530 PI_0 = {n{1'b0}};
00000531 PPI_1 = {l{1'b0}};
00000532 PPI_0 = {l{1'b0}};
00000533 priority_reset = ~priority_reset;
00000534 mode = 2'b10;
00000535 end
00000536 else if(mode == 2'b10) begin
00000537 $display("back-dec | pushing obj onto back-net: %b",
obj);
00000538 //Do back-net assignment
00000539 for(i = 0; i < n; i = i + 1) begin
00000540 if(i == obj[13:4]) begin
00000541 //found obj index, insert obj
00000542 PI_1[i] = 1'b1;
00000543 PI_0[i] = obj[2];
00000544 end
00000545 else begin
00000546 //insert regular ppo
00000547 PI_1[i] = 1'b0;
00000548 PI_0[i] = PO_1[i];
00000549 end
00000550 end
00000551
00000552 if(l > 1) begin
00000553 for(i = m; i < m+l; i = i + 1) begin
00000554 if(i == obj[13:4]) begin
00000555 //found obj index, insert obj
00000556 PPI_1[i-m] = 1'b1;
00000557 PPI_0[i-m] = obj[2];
00000558 end
00000559 else begin
00000560 //insert regular ppo
00000561 PPI_1[i-m] = 1'b0;
165
00000562 PPI_0[i-m] = PPO_1[i-m];
00000563 end
00000564 end
00000565 end
00000566
00000567 trace_start = ~trace_start;
00000568 mode = 2'b00;
00000569 end
00000570 end
00000571 end
00000572 endmodule
00000573
00000574 module control ( global_reset, clk, push, line_k_1, cnt_dir, nready, DONE, done,
comp_tried, rw, line_k_X, cnt_enable, pop, empty, conflict, frame_k, frame_1, addr, FAIL,
top_mark, value, rewrite0, rewrite1, swapwrite, cleartop, notclear, last_in, next_top,
ninputs, genobj, sendvaluestoforward, inputwordallones, readingow, endofframe,
beginstatecheck, donewithstatecheck, statecheckresult, blockisppi, owmark, tiplus1);
00000575 input global_reset;
00000576 input clk;
00000577 input conflict ;
00000578 input line_k_1 ;
00000579 input nready ;
00000580 input frame_k ;
00000581 input done ;
00000582 input comp_tried ;
00000583 input line_k_X ;
00000584 input frame_1 ;
00000585 input [1:0] value ;
00000586 input top_mark ;
00000587 input empty ;
00000588 input [31:0] last_in;
00000589 input next_top;
00000590 input inputwordallones;
00000591 input endofframe;
00000592 input donewithstatecheck; //Is the dup state check done?
00000593 input statecheckresult; //Did the dup state check pass?
00000594 input owmark; //Passes in the mark bit from the output word from memram
00000595
00000596 output reg push;
00000597 output reg cnt_dir;
00000598 output reg DONE;
00000599 output reg [1:0] rw;
00000600 output reg cnt_enable;
00000601 output reg [13:0] addr;
00000602 output reg FAIL;
00000603 output reg pop;
00000604 output reg rewrite0;
00000605 output reg rewrite1;
00000606 output reg swapwrite;
00000607 output reg cleartop;
00000608 output reg [1:0] notclear;
00000609 output reg [2:0] ninputs;
00000610 output reg genobj;
00000611 output reg sendvaluestoforward;
00000612 output reg readingow; //signals top if it should read Top or ow into VF
00000613 output reg beginstatecheck; //signals to start dup state check prior to move
back to Ti-1
00000614 output reg blockisppi;
00000615 output reg tiplus1;
00000616
00000617 reg blockisppi2; //flag bit to control output to isppi during Ti+1
00000618 reg [4:0] state;
00000619 reg wwait;
00000620 reg timinus1;
00000621 reg waits5; //add another clock cycle to state 5
00000622 reg waits6; //add another clock cycle to state 6
00000623 reg waits9; //add another clock cycle to state 9
00000624 reg waits12; //add another clock cycle to state 12
00000625 //reg swapchecks12; //handle comp_tried checking in s12 -> s2?s10
166
00000626 reg popchecks12; //handle top update after pop operation
00000627 reg clearvalueschecks12; //handle vf update in backtrack top clear operation
00000628
00000629 parameter s0 = 5'b00000; parameter s1 = 5'b00001; parameter s2 = 5'b00010;
parameter s3 = 5'b00011;
00000630 parameter s4 = 5'b00100; parameter s5 = 5'b00101; parameter s6 = 5'b00110;
parameter s7 = 5'b00111;
00000631 parameter s8 = 5'b01000; parameter s9 = 5'b01001; parameter s10 = 5'b01010;
parameter s11 = 5'b01011;
00000632 parameter s12 = 5'b01100; parameter s13 = 5'b01101; parameter s14 = 5'b01110;
parameter s15 = 5'b01111;
00000633 parameter s16 = 5'b10000; parameter s17 = 5'b10001; parameter s18 = 5'b10010;
parameter s19 = 5'b10011;
00000634 parameter s20 = 5'b10100; parameter s21 = 5'b10101; parameter s22 = 5'b10110;
00000635
00000636 always @(posedge clk, posedge global_reset) begin
00000637 if(global_reset) begin
00000638 state = s0;
00000639 tiplus1 = 0;
00000640 timinus1 = 0;
00000641 beginstatecheck = 1'b0;
00000642 blockisppi = 1'b0;
00000643 blockisppi2 = 1'b0;
00000644 waits5 = 1'b1;
00000645 waits6 = 1'b1;
00000646 waits9 = 1'b1;
00000647 waits12 = 1'b1;
00000648 addr = 14'b11111111111111;
00000649 wwait = 1'b0;
00000650 end
00000651 else if(nready == 1'b0 && wwait == 1'b0) begin
00000652 wwait = 1'b1;
00000653 end
00000654 else begin
00000655 case(state)
00000656 s1: begin
00000657 if (inputwordallones) begin
00000658 state = s16;
00000659 end
00000660 else begin
00000661 state = s17;
00000662 end
00000663 $display ("mycontrol | in state 1");
00000664 end
00000665 s2: begin
00000666 $display ("mycontrol | in state 2");
00000667 addr = 14'b11111111111111;
00000668 state = s12;
00000669 end
00000670 s3: begin
00000671 if (tiplus1) begin
00000672 //Moving to Ti+1
00000673 $display ("mycontrol | in state 3
(Ti+1)");
00000674 if (!blockisppi2 && addr ==
14'b11111111111111) begin
00000675 //In frame k - no Ti-2 to read to
RF
00000676 tiplus1 = 1'b0;
00000677 state = s7;
00000678 end
00000679 else if (!owmark && !blockisppi2) begin
00000680 //Reading Ti-1 into VF
00000681 blockisppi = 1'b1;
00000682 addr = addr - 1;
00000683 state = s22;
00000684 end
00000685 else if (owmark) begin
00000686 //Switch to frame Ti-2
167
00000687 blockisppi = 1'b0;
00000688 blockisppi2 = 1'b1;
00000689 addr = addr - 1;
00000690 end
00000691 else if (blockisppi2 && (owmark || addr
== 14'b11111111111111)) begin
00000692 //Done reading Ti-2
00000693 blockisppi = 1'b1;
00000694 tiplus1 = 1'b0;
00000695 state = s7;
00000696 end
00000697 else begin
00000698 //Reading Ti-2 into RF
00000699 state = s3;
00000700 addr = addr - 1;
00000701 end
00000702 end
00000703 else begin
00000704 //Moving to Ti-1
00000705 $display ("mycontrol | in state 3 (Ti-
1)");
00000706 if (addr == 14'b11111111111111 ||
endofframe == 1'b1) begin
00000707 state = s8;
00000708 end
00000709 else begin
00000710 state = s3;
00000711 addr = addr - 1;
00000712 end
00000713 end
00000714 end
00000715 s4: begin
00000716 blockisppi = 1'b0;
00000717 blockisppi2 = 1'b0;
00000718 state = s0;
00000719 $display ("mycontrol | in state 4");
00000720 end
00000721 s5: begin
00000722 if (waits5) begin
00000723 $display ("mycontrol | in state 5 (cycle
1)");
00000724 waits5 = 1'b0;
00000725 end
00000726 else begin
00000727 $display ("mycontrol | in state 5 (cycle
2)");
00000728 waits5 = 1'b1;
00000729 addr = last_in;
00000730 state = s3;
00000731 end
00000732 end
00000733 s6: begin
00000734 if (waits6) begin
00000735 $display ("mycontrol | in state 6 (cycle
1)");
00000736 waits6 = 1'b0;
00000737 end
00000738 else begin
00000739 $display ("mycontrol | in state 6 (cycle
2)");
00000740 waits6 = 1'b1;
00000741 addr = 14'b11111111111111;
00000742 state = s12;
00000743 end
00000744 end
00000745 s7: begin
00000746 $display ("mycontrol | in state 7");
00000747 if(comp_tried) begin
00000748 state = s9;
168
00000749 end
00000750 else begin
00000751 state = s6;
00000752 end
00000753 end
00000754 s8: begin
00000755 state = s11;
00000756 $display ("mycontrol | in state 8");
00000757 end
00000758 s9: begin
00000759 if (waits9) begin
00000760 $display ("mycontrol | in state 9 (cycle
1)");
00000761 waits9 = 1'b0;
00000762 end
00000763 else begin
00000764 $display ("mycontrol | in state 9 (cycle
2)");
00000765 waits9 = 1'b1;
00000766 addr = 14'b11111111111111;
00000767 state = s12;
00000768 end
00000769 end
00000770 s10: begin
00000771 $display ("mycontrol | in state 10");
00000772 if (tiplus1) begin
00000773 state = s19;
00000774 addr = addr - 1;
00000775 end
00000776 else if (clearvalueschecks12) begin
00000777 state = s2;
00000778 end
00000779 else begin
00000780 blockisppi = 1'b0;
00000781 blockisppi2 = 1'b0;
00000782 state = s0;
00000783 end
00000784 end
00000785 s11: begin
00000786 state = s4;
00000787 $display ("mycontrol | in state 11");
00000788 end
00000789 s12: begin
00000790 if (waits12) begin
00000791 $display ("mycontrol | in state 12 (cycle
1)");
00000792 waits12 = 1'b0;
00000793 end
00000794 else begin
00000795 $display ("mycontrol | in state 12 (cycle
2)");
00000796 waits12 = 1'b1;
00000797 if (popchecks12) begin
00000798 state = s18;
00000799 end
00000800 /*else if(!swapchecks12) begin
00000801 swapchecks12 = 1'b1;
00000802 state = s2;
00000803 end*/
00000804 else if(tiplus1) begin
00000805 state = s20;
00000806 end
00000807 else begin
00000808 state = s10;
00000809 end
00000810 end
00000811 end
00000812 s13: state = s13;
00000813 s14: state = s14;
169
00000814 s15: begin
00000815 $display ("mycontrol | in state 15");
00000816 state = s3;
00000817 end
00000818 s16: begin
00000819 $display("mycontrol | in state 16");
00000820 blockisppi = 1'b0;
00000821 blockisppi2 = 1'b0;
00000822 state = s0;
00000823 end
00000824 s17: begin
00000825 $display("mycontrol | in state 17");
00000826 state = s10;
00000827 end
00000828 s18: begin
00000829 $display ("mycontrol | in state 18");
00000830 if(top_mark) begin
00000831 tiplus1 = 1'b1;
00000832 timinus1 = 1'b0;
00000833 state = s5;
00000834 end
00000835 else if(comp_tried) begin
00000836 state = s9;
00000837 end
00000838 else begin
00000839 state = s6;
00000840 end
00000841 end
00000842 s19: begin
00000843 $display ("mycontrol | in state 19");
00000844 if (addr == 14'b11111111111111) begin
00000845 tiplus1 = 1'b0;
00000846 end
00000847 state = s10;
00000848 end
00000849 s20: begin
00000850 $display ("mycontrol | in state 20");
00000851 addr = last_in + 1;
00000852 state = s10;
00000853 end
00000854 s21: begin
00000855 $display("mycontrol | in state 21");
00000856 if (donewithstatecheck) begin
00000857 beginstatecheck = 1'b0;
00000858 if (statecheckresult) begin
00000859 //State check found duplicate -
backtrack
00000860 addr = last_in;
00000861 state = s9;
00000862 end
00000863 else begin
00000864 //State check clean - move to Ti-1
00000865 addr = last_in;
00000866 state = s15;
00000867 end
00000868 end
00000869 else begin
00000870 addr = addr - 1;
00000871 end
00000872 end
00000873 s22: begin
00000874 $display ("mycontrol | in state 22");
00000875 state = s3;
00000876 end
00000877 default: begin
00000878 //Default case is assumed to be IDLE (s0)
00000879 $display ("mycontrol | in state 0");
00000880 if(frame_1 && !conflict && done) begin
00000881 state = s14;
170
00000882 end
00000883 else if(wwait) begin
00000884 if(!frame_k && !conflict && done &&
frame_1) state = s14;
00000885 if(!frame_k && !conflict && done &&
!frame_1) begin
00000886 //state = s15;
00000887 addr = last_in;
00000888 beginstatecheck = 1'b1;
00000889 state = s21;
00000890 tiplus1 = 1'b0;
00000891 timinus1 = 1'b1;
00000892 end
00000893 if(!frame_k && !conflict && !done) state
= s1;
00000894 if(!frame_k && conflict && !empty &&
comp_tried) state = s9;
00000895 if(!frame_k && conflict && !empty &&
!comp_tried) state = s6;
00000896 if(!frame_k && conflict && empty) begin
00000897 tiplus1 = 1'b1;
00000898 timinus1 = 1'b0;
00000899 state = s5;
00000900 end
00000901 if(frame_k && !line_k_X && !line_k_1)
state = s13;
00000902 if(frame_k && !line_k_X && line_k_1)
begin
00000903 addr = last_in;
00000904 state = s15;
00000905 tiplus1 = 1'b0;
00000906 timinus1 = 1'b1;
00000907 end
00000908 if(frame_k && line_k_X) state = s1;
00000909 if(frame_k && conflict) state = s13;
00000910
00000911 wwait = 1'b0;
00000912 end
00000913 else begin
00000914 blockisppi = 1'b0;
00000915 blockisppi2 = 1'b0;
00000916 state = s0;
00000917 end
00000918 end
00000919 endcase
00000920 end
00000921 end
00000922
00000923 always @(global_reset, state, waits6, waits9) begin
00000924 if(global_reset) begin
00000925 notclear = 2'b11;
00000926 genobj = 1'b0;
00000927 ninputs = 0;
00000928 end
00000929 else begin
00000930 case(state)
00000931 s0: begin
00000932 $display("mycontrol | executing state 0");
00000933 push = 1'b0;
00000934 pop = 1'b0;
00000935 rw = 2'b00;
00000936 rewrite0 = 1'b0;
00000937 rewrite1 = 1'b0;
00000938 swapwrite = 1'b0;
00000939 cleartop = 1'b0;
00000940 cnt_enable = 1'b0;
00000941 DONE = 1'b0;
00000942 FAIL = 1'b0;
00000943 notclear = 2'b11;
171
00000944 genobj = 1'b0;
00000945 sendvaluestoforward = 1'b1;
00000946 //swapchecks12 = 1'b0;
00000947 popchecks12 = 1'b0;
00000948 readingow = 1'b0;
00000949 clearvalueschecks12 = 1'b0;
00000950 end
00000951 s1: begin
00000952 $display("mycontrol | executing state 1");
00000953 push = 1'b1;
00000954 pop = 1'b0;
00000955 rw = 2'b00;
00000956 rewrite0 = 1'b0;
00000957 rewrite1 = 1'b0;
00000958 swapwrite = 1'b0;
00000959 cleartop = 1'b0;
00000960 cnt_enable = 1'b0;
00000961 DONE = 1'b0;
00000962 FAIL = 1'b0;
00000963 ninputs = ninputs + 1;
00000964 sendvaluestoforward = 1'b1;
00000965 end
00000966 s2: begin
00000967 $display("mycontrol | executing state 2");
00000968 push = 1'b0;
00000969 pop = 1'b1;
00000970 rw = 2'b00;
00000971 rewrite0 = 1'b0;
00000972 rewrite1 = 1'b0;
00000973 swapwrite = 1'b0;
00000974 cleartop = 1'b0;
00000975 cnt_enable = 1'b0;
00000976 DONE = 1'b0;
00000977 FAIL = 1'b0;
00000978 popchecks12 = 1'b1;
00000979 clearvalueschecks12 = 1'b0;
00000980 end
00000981 s3: begin
00000982 $display("mycontrol | executing state 3");
00000983 push = 1'b0;
00000984 pop = 1'b0;
00000985 rw = 2'b10;
00000986 rewrite0 = 1'b0;
00000987 rewrite1 = 1'b0;
00000988 swapwrite = 1'b0;
00000989 cleartop = 1'b0;
00000990 cnt_enable = 1'b0;
00000991 DONE = 1'b0;
00000992 FAIL = 1'b0;
00000993 ninputs = 1'b0;
00000994 notclear = 2'b11;
00000995 readingow = 1'b1;
00000996 sendvaluestoforward = 1'b0;
00000997 end
00000998 s4: begin
00000999 $display("mycontrol | executing state 4");
00001000 push = 1'b0;
00001001 pop = 1'b0;
00001002 rw = 2'b00;
00001003 rewrite0 = 1'b0;
00001004 rewrite1 = 1'b1;
00001005 swapwrite = 1'b0;
00001006 cleartop = 1'b0;
00001007 cnt_enable = 1'b0;
00001008 DONE = 1'b0;
00001009 FAIL = 1'b0;
00001010 end
00001011 s5: begin
00001012 $display("mycontrol | executing state 5");
172
00001013 ninputs = 1'b0;
00001014 push = 1'b0;
00001015 pop = 1'b0;
00001016 rw = 2'b00;
00001017 rewrite1 = 1'b0;
00001018 swapwrite = 1'b0;
00001019 cleartop = 1'b0;
00001020 cnt_enable = 1'b0;
00001021 DONE = 1'b0;
00001022 FAIL = 1'b0;
00001023 //This had to moved from above
00001024 if (waits5) begin
00001025 rewrite0 = 1'b1;
00001026 end
00001027 else begin
00001028 rewrite0 = 1'b0;
00001029 end
00001030 end
00001031 s6: begin
00001032 $display("mycontrol | executing state 6");
00001033 if (waits6) begin
00001034 push = 1'b0;
00001035 pop = 1'b0;
00001036 rw = 2'b00;
00001037 rewrite0 = 1'b0;
00001038 rewrite1 = 1'b0;
00001039 swapwrite = 1'b1;
00001040 cleartop = 1'b0;
00001041 cnt_enable = 1'b0;
00001042 DONE = 1'b0;
00001043 FAIL = 1'b0;
00001044 //swapchecks12 = 1'b1;
00001045 end
00001046 else begin
00001047 swapwrite = 1'b0;
00001048 end
00001049 end
00001050 s7: begin
00001051 $display("mycontrol | executing state 7");
00001052 push = 1'b0;
00001053 pop = 1'b0;
00001054 rw = 2'b00;
00001055 rewrite0 = 1'b0;
00001056 rewrite1 = 1'b0;
00001057 swapwrite = 1'b0;
00001058 cleartop = 1'b0;
00001059 cnt_enable = 1'b1;
00001060 cnt_dir = 1'b1;
00001061 DONE = 1'b0;
00001062 FAIL = 1'b0;
00001063 readingow = 1'b0;
00001064 end
00001065 s8: begin
00001066 $display("mycontrol | executing state 8");
00001067 push = 1'b0;
00001068 pop = 1'b0;
00001069 rw = 2'b00;
00001070 rewrite0 = 1'b0;
00001071 rewrite1 = 1'b0;
00001072 swapwrite = 1'b0;
00001073 cleartop = 1'b0;
00001074 cnt_enable = 1'b1;
00001075 cnt_dir = 1'b0;
00001076 DONE = 1'b0;
00001077 FAIL = 1'b0;
00001078 end
00001079 s9: begin
00001080 $display("mycontrol | executing state 9");
00001081 if (waits9) begin
173
00001082 cleartop = 1'b1;
00001083 push = 1'b0;
00001084 pop = 1'b0;
00001085 rw = 2'b00;
00001086 rewrite0 = 1'b0;
00001087 rewrite1 = 1'b0;
00001088 swapwrite = 1'b0;
00001089 cnt_enable = 1'b0;
00001090 DONE = 1'b0;
00001091 FAIL = 1'b0;
00001092 clearvalueschecks12 = 1'b1;
00001093 end
00001094 else begin
00001095 cleartop = 1'b0;
00001096 end
00001097 end
00001098 s10: begin
00001099 $display("mycontrol | executing state 10");
00001100 push = 1'b0;
00001101 pop = 1'b0;
00001102 if(!tiplus1) begin
00001103 rw = 2'b00;
00001104 end
00001105 rewrite0 = 1'b0;
00001106 rewrite1 = 1'b0;
00001107 swapwrite = 1'b0;
00001108 cleartop = 1'b0;
00001109 cnt_enable = 1'b0;
00001110 DONE = 1'b0;
00001111 FAIL = 1'b0;
00001112 genobj = 1'b1;
00001113 notclear = 2'b01;
00001114 end
00001115 s11: begin
00001116 $display("mycontrol | executing state 11");
00001117 push = 1'b0;
00001118 pop = 1'b0;
00001119 rw = 2'b00;
00001120 notclear = 2'b00;
00001121 rewrite0 = 1'b0;
00001122 rewrite1 = 1'b0;
00001123 swapwrite = 1'b0;
00001124 cleartop = 1'b0;
00001125 cnt_enable = 1'b0;
00001126 DONE = 1'b0;
00001127 FAIL = 1'b0;
00001128 end
00001129 s12: begin
00001130 $display("mycontrol | executing state 12");
00001131 push = 1'b0;
00001132 pop = 1'b0;
00001133 rw = 2'b10;
00001134 rewrite0 = 1'b0;
00001135 rewrite1 = 1'b0;
00001136 swapwrite = 1'b0;
00001137 cleartop = 1'b0;
00001138 cnt_enable = 1'b0;
00001139 DONE = 1'b0;
00001140 FAIL = 1'b0;
00001141 sendvaluestoforward = 1'b0;
00001142 notclear = 2'b11;
00001143 end
00001144 s13: begin
00001145 $display("FAIL!!!");
00001146 FAIL = 1'b1;
00001147 end
00001148 s14: begin
00001149 $display("DONE!!");
00001150 DONE = 1'b1;
174
00001151 end
00001152 s15: begin
00001153 $display("mycontrol | executing state 15");
00001154 end
00001155 s16: begin
00001156 $display("mycontrol | executing state 16");
00001157 push = 1'b0;
00001158 pop = 1'b0;
00001159 rw = 2'b00;
00001160 rewrite0 = 1'b0;
00001161 rewrite1 = 1'b0;
00001162 swapwrite = 1'b0;
00001163 cleartop = 1'b0;
00001164 cnt_enable = 1'b0;
00001165 DONE = 1'b0;
00001166 FAIL = 1'b0;
00001167 genobj = 1'b1;
00001168 notclear = 2'b11;
00001169 end
00001170 s17: begin
00001171 $display("mycontrol | executing state 17");
00001172 push = 1'b0;
00001173 end
00001174 s18: begin
00001175 $display("mycontrol | executing state 18");
00001176 popchecks12 = 1'b0;
00001177 end
00001178 s19: begin
00001179 $display("mycontrol | executing state 19");
00001180 push = 1'b0;
00001181 pop = 1'b0;
00001182 rw = 2'b10;
00001183 notclear = 2'b11;
00001184 rewrite0 = 1'b0;
00001185 rewrite1 = 1'b0;
00001186 swapwrite = 1'b0;
00001187 cleartop = 1'b0;
00001188 cnt_enable = 1'b0;
00001189 DONE = 1'b0;
00001190 FAIL = 1'b0;
00001191 ninputs = 1'b0;
00001192 sendvaluestoforward = 1'b0;
00001193 end
00001194 s20: begin
00001195 $display("mycontrol | executing state 20");
00001196 push = 1'b0;
00001197 pop = 1'b0;
00001198 rw = 2'b00;
00001199 notclear = 2'b10;
00001200 rewrite0 = 1'b0;
00001201 rewrite1 = 1'b0;
00001202 swapwrite = 1'b0;
00001203 cleartop = 1'b0;
00001204 cnt_enable = 1'b0;
00001205 DONE = 1'b0;
00001206 FAIL = 1'b0;
00001207 readingow = 1'b1;
00001208 end
00001209 s21: begin
00001210 $display("mycontrol | executing state 21");
00001211 push = 1'b0;
00001212 pop = 1'b0;
00001213 rw = 2'b10;
00001214 rewrite0 = 1'b0;
00001215 rewrite1 = 1'b0;
00001216 swapwrite = 1'b0;
00001217 cleartop = 1'b0;
00001218 cnt_enable = 1'b0;
00001219 DONE = 1'b0;
175
00001220 FAIL = 1'b0;
00001221 ninputs = 1'b0;
00001222 sendvaluestoforward = 1'b0;
00001223 end
00001224 s22: begin
00001225 $display("mycontrol | executing state 22");
00001226 push = 1'b0;
00001227 pop = 1'b0;
00001228 if(!tiplus1) begin
00001229 rw = 2'b00;
00001230 end
00001231 rewrite0 = 1'b0;
00001232 rewrite1 = 1'b0;
00001233 swapwrite = 1'b0;
00001234 cleartop = 1'b0;
00001235 cnt_enable = 1'b0;
00001236 DONE = 1'b0;
00001237 FAIL = 1'b0;
00001238 genobj = 1'b1;
00001239 notclear = 2'b01;
00001240 end
00001241 endcase
00001242 end
00001243 end
00001244
00001245 endmodule
00001246
00001247
00001248 module fourcounter ( global_reset, frame_1 ,cnt_dir ,cnt_enable ,frame_k);
00001249 parameter n = 1;
00001250 parameter m = 4;
00001251 parameter l = 3;
00001252 parameter s = 22;
00001253
00001254 input cnt_dir ;
00001255 input cnt_enable ;
00001256 input global_reset;
00001257 output reg frame_1 ;
00001258 output reg frame_k ;
00001259
00001260 reg [l-1:0] tmp;
00001261
00001262 always @(posedge cnt_enable, posedge global_reset) begin
00001263 if(global_reset) begin
00001264 $display ("fourcounter | reseting the frame counter");
00001265 tmp = 2**l-1;
00001266 if(l-1 == 0) begin
00001267 frame_k = 1'b1;
00001268 frame_1 = 1'b1;
00001269 end
00001270 else begin
00001271 frame_k = 1'b1;
00001272 frame_1 = 1'b0;
00001273 end
00001274 end
00001275 else begin
00001276 if(cnt_dir) begin
00001277 if(tmp == 0) begin
00001278 frame_1 = 1'b1;
00001279 end
00001280 else if (tmp == 2**l-2) begin
00001281 frame_k = 1'b1;
00001282 end
00001283 else begin
00001284 frame_1 = 1'b0;
00001285 frame_k = 1'b0;
00001286 end
00001287 $display ("fourcounter | counting a frame UP");
00001288 tmp = tmp + 1'b1;
176
00001289 end
00001290 else begin
00001291 if(tmp == 2) begin
00001292 frame_1 = 1'b1;
00001293 end
00001294 else if (tmp == 2**l) begin
00001295 frame_k = 1'b1;
00001296 end
00001297 else begin
00001298 frame_1 = 1'b0;
00001299 frame_k = 1'b0;
00001300 end
00001301 $display ("fourcounter | counting a frame DOWN");
00001302 tmp = tmp - 1'b1;
00001303 end
00001304 end
00001305 end
00001306
00001307 endmodule
00001308
00001309
00001310 module decoder (top, value, top_mark, comp_tried );
00001311 input [13:0] top ;
00001312 output reg [1:0] value ;
00001313 output reg top_mark ;
00001314 output reg comp_tried ;
00001315
00001316 always @(top) begin
00001317 value = top[2:1];
00001318 top_mark = top[3];
00001319 comp_tried = top[0];
00001320 end
00001321
00001322 endmodule
00001323
00001324
00001325 module isppi ( out, in, blockisppi );
00001326 parameter n = 1;
00001327 parameter m = 4;
00001328 parameter l = 3;
00001329 parameter s = 22;
00001330
00001331 input [13:0] in ;
00001332 input blockisppi;
00001333 output reg [13:0] out ;
00001334
00001335 always @(in, blockisppi) begin
00001336 if(!blockisppi && in != 14'b11111111111111 && in[13:4] > m) begin
00001337 $display("isppi | evaluating output to RF; in=%b", in);
00001338 out = in;
00001339 end
00001340 else begin
00001341 out = 14'b11111111111111;
00001342 end
00001343 end
00001344
00001345 endmodule
00001346
00001347
00001348 // Module: XC2V_RAMB_1_PORT
00001349 // Description: 18Kb Block SelectRAM-II example
00001350 // Single Port 512 x 36 bits
00001351 // Use template "SelectRAM_A36.v"
00001352 //
00001353 // Device: Virtex-II Pro Family
00001354 //-------------------------------------------------------------------
00001355 module XC2V_RAMB_1_PORT (CLK, SET_RESET, ENABLE, WRITE_EN, ADDRESS, DATA_IN,
DATA_OUT);
00001356 input CLK, SET_RESET, ENABLE, WRITE_EN;
177
00001357 input [17:0] DATA_IN;
00001358 input [9:0] ADDRESS;
00001359 output [17:0] DATA_OUT;
00001360 wire CLK_BUFG, INV_SET_RESET;
00001361
00001362 //Use of the free inverter on SSR pin
00001363 assign INV_SET_RESET = ~SET_RESET;
00001364
00001365 // initialize block ram for simulation
00001366 // synopsys translate_off
00001367 defparam
00001368
00001369 //"Read during Write" attribute for functional simulation
00001370 U_RAMB16_S36.WRITE_MODE = "READ_FIRST", //WRITE_FIRST(default)/READ_FIRST/
NO_CHANGE
00001371
00001372 //Output value after configuration
00001373 U_RAMB16_S36.INIT = 36'h000000000,
00001374
00001375 //Output value if SSR active
00001376 U_RAMB16_S36.SRVAL = 36'h012345678,
00001377
00001378 //Plus bits initial content
00001379 U_RAMB16_S36.INITP_00 =
256'h0123456789ABCDEF000000000000000000000000000000000000000000000000,
00001380 U_RAMB16_S36.INITP_01 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001381 U_RAMB16_S36.INITP_02 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001382 U_RAMB16_S36.INITP_03 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001383 U_RAMB16_S36.INITP_04 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001384 U_RAMB16_S36.INITP_05 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001385 U_RAMB16_S36.INITP_06 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001386 U_RAMB16_S36.INITP_07 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001387
00001388 //Regular bits initial content
00001389 U_RAMB16_S36.INIT_00 =
256'h0123456789ABCDEF000000000000000000000000000000000000000000000000,
00001390 U_RAMB16_S36.INIT_01 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001391 U_RAMB16_S36.INIT_02 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001392 U_RAMB16_S36.INIT_03 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001393 U_RAMB16_S36.INIT_04 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001394 U_RAMB16_S36.INIT_05 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001395 U_RAMB16_S36.INIT_06 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001396 U_RAMB16_S36.INIT_07 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001397 U_RAMB16_S36.INIT_08 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001398 U_RAMB16_S36.INIT_09 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001399 U_RAMB16_S36.INIT_0A =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001400 U_RAMB16_S36.INIT_0B =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001401 U_RAMB16_S36.INIT_0C =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001402 U_RAMB16_S36.INIT_0D =
256'h0000000000000000000000000000000000000000000000000000000000000000,
178
00001403 U_RAMB16_S36.INIT_0E =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001404 U_RAMB16_S36.INIT_0F =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001405 U_RAMB16_S36.INIT_10 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001406 U_RAMB16_S36.INIT_11 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001407 U_RAMB16_S36.INIT_12 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001408 U_RAMB16_S36.INIT_13 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001409 U_RAMB16_S36.INIT_14 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001410 U_RAMB16_S36.INIT_15 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001411 U_RAMB16_S36.INIT_16 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001412 U_RAMB16_S36.INIT_17 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001413 U_RAMB16_S36.INIT_18 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001414 U_RAMB16_S36.INIT_19 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001415 U_RAMB16_S36.INIT_1A =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001416 U_RAMB16_S36.INIT_1B =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001417 U_RAMB16_S36.INIT_1C =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001418 U_RAMB16_S36.INIT_1D =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001419 U_RAMB16_S36.INIT_1E =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001420 U_RAMB16_S36.INIT_1F =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001421 U_RAMB16_S36.INIT_20 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001422 U_RAMB16_S36.INIT_21 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001423 U_RAMB16_S36.INIT_22 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001424 U_RAMB16_S36.INIT_23 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001425 U_RAMB16_S36.INIT_24 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001426 U_RAMB16_S36.INIT_25 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001427 U_RAMB16_S36.INIT_26 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001428 U_RAMB16_S36.INIT_27 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001429 U_RAMB16_S36.INIT_28 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001430 U_RAMB16_S36.INIT_29 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001431 U_RAMB16_S36.INIT_2A =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001432 U_RAMB16_S36.INIT_2B =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001433 U_RAMB16_S36.INIT_2C =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001434 U_RAMB16_S36.INIT_2D =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001435 U_RAMB16_S36.INIT_2E =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001436 U_RAMB16_S36.INIT_2F =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001437 U_RAMB16_S36.INIT_30 =
179
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001438 U_RAMB16_S36.INIT_31 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001439 U_RAMB16_S36.INIT_32 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001440 U_RAMB16_S36.INIT_33 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001441 U_RAMB16_S36.INIT_34 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001442 U_RAMB16_S36.INIT_35 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001443 U_RAMB16_S36.INIT_36 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001444 U_RAMB16_S36.INIT_37 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001445 U_RAMB16_S36.INIT_38 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001446 U_RAMB16_S36.INIT_39 =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001447 U_RAMB16_S36.INIT_3A =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001448 U_RAMB16_S36.INIT_3B =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001449 U_RAMB16_S36.INIT_3C =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001450 U_RAMB16_S36.INIT_3D =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001451 U_RAMB16_S36.INIT_3E =
256'h0000000000000000000000000000000000000000000000000000000000000000,
00001452 U_RAMB16_S36.INIT_3F =
256'h0000000000000000000000000000000000000000000000000000000000000000
00001453
00001454 // synopsys translate_on
00001455 //Instantiate the clock Buffer
00001456 BUFG U_BUFG ( .I(CLK), .O(CLK_BUFG));
00001457
00001458 //Block SelectRAM Instantiation
00001459 RAMB16_S36 U_RAMB16_S36 ( .DI(DATA_IN[15:0]),
00001460 .DIP(DATA_IN[17:16]),
00001461 .ADDR(ADDRESS),
00001462 .EN(ENABLE),
00001463 .WE(WRITE_EN),
00001464 .SSR(INV_SET_RESET),
00001465 .CLK(CLK),
00001466 .DO(DATA_OUT[15:0]),
00001467 .DOP(DATA_OUT[17:16]));
00001468
00001469 // synthesis attribute declarations
00001470 /* synopsys attribute
00001471 WRITE_MODE "READ_FIRST"
00001472 INIT "000000000"
00001473 SRVAL "012345678"
00001474
00001475 INITP_00
00001476 "0123456789ABCDEF000000000000000000000000000000000000000000000000"
00001477 INITP_01
00001478 "0000000000000000000000000000000000000000000000000000000000000000"
00001479 INITP_02
00001480 "0000000000000000000000000000000000000000000000000000000000000000"
00001481 INITP_03
00001482 "0000000000000000000000000000000000000000000000000000000000000000"
00001483 INITP_04
00001484 "0000000000000000000000000000000000000000000000000000000000000000"
00001485 INITP_05
00001486 "0000000000000000000000000000000000000000000000000000000000000000"
00001487 INITP_06
00001488 "0000000000000000000000000000000000000000000000000000000000000000"
00001489 INITP_07
00001490 "0000000000000000000000000000000000000000000000000000000000000000"
180
00001491
00001492 INIT_00
00001493 "0123456789ABCDEF000000000000000000000000000000000000000000000000"
00001494 INIT_01
00001495 "0000000000000000000000000000000000000000000000000000000000000000"
00001496 INIT_02
00001497 "0000000000000000000000000000000000000000000000000000000000000000"
00001498 INIT_03
00001499 "0000000000000000000000000000000000000000000000000000000000000000"
00001500 INIT_04
00001501 "0000000000000000000000000000000000000000000000000000000000000000"
00001502 INIT_05
00001503 "0000000000000000000000000000000000000000000000000000000000000000"
00001504 INIT_06
00001505 "0000000000000000000000000000000000000000000000000000000000000000"
00001506 INIT_07
00001507 "0000000000000000000000000000000000000000000000000000000000000000"
00001508 INIT_08
00001509 "0000000000000000000000000000000000000000000000000000000000000000"
00001510 INIT_09
00001511 "0000000000000000000000000000000000000000000000000000000000000000"
00001512 INIT_0A
00001513 "0000000000000000000000000000000000000000000000000000000000000000"
00001514 INIT_0B
00001515 "0000000000000000000000000000000000000000000000000000000000000000"
00001516 INIT_0C
00001517 "0000000000000000000000000000000000000000000000000000000000000000"
00001518 INIT_0D
00001519 "0000000000000000000000000000000000000000000000000000000000000000"
00001520 INIT_0E
00001521 "0000000000000000000000000000000000000000000000000000000000000000"
00001522 INIT_0F
00001523 "0000000000000000000000000000000000000000000000000000000000000000"
00001524 INIT_10
00001525 "0000000000000000000000000000000000000000000000000000000000000000"
00001526 INIT_11
00001527 "0000000000000000000000000000000000000000000000000000000000000000"
00001528 INIT_12
00001529 "0000000000000000000000000000000000000000000000000000000000000000"
00001530 INIT_13
00001531 "0000000000000000000000000000000000000000000000000000000000000000"
00001532 INIT_14
00001533 "0000000000000000000000000000000000000000000000000000000000000000"
00001534 INIT_15
00001535 "0000000000000000000000000000000000000000000000000000000000000000"
00001536 INIT_16
00001537 "0000000000000000000000000000000000000000000000000000000000000000"
00001538 INIT_17
00001539 "0000000000000000000000000000000000000000000000000000000000000000"
00001540 INIT_18
00001541 "0000000000000000000000000000000000000000000000000000000000000000"
00001542 INIT_19
00001543 "0000000000000000000000000000000000000000000000000000000000000000"
00001544 INIT_1A
00001545 "0000000000000000000000000000000000000000000000000000000000000000"
00001546 INIT_1B
00001547 "0000000000000000000000000000000000000000000000000000000000000000"
00001548 INIT_1C
00001549 "0000000000000000000000000000000000000000000000000000000000000000"
00001550 INIT_1D
00001551 "0000000000000000000000000000000000000000000000000000000000000000"
00001552 INIT_1E
00001553 "0000000000000000000000000000000000000000000000000000000000000000"
00001554 INIT_1F
00001555 "0000000000000000000000000000000000000000000000000000000000000000"
00001556 INIT_20
00001557 "0000000000000000000000000000000000000000000000000000000000000000"
00001558 INIT_21
00001559 "0000000000000000000000000000000000000000000000000000000000000000"
181
00001560 INIT_22
00001561 "0000000000000000000000000000000000000000000000000000000000000000"
00001562 INIT_23
00001563 "0000000000000000000000000000000000000000000000000000000000000000"
00001564 INIT_24
00001565 "0000000000000000000000000000000000000000000000000000000000000000"
00001566 INIT_25
00001567 "0000000000000000000000000000000000000000000000000000000000000000"
00001568 INIT_26
00001569 "0000000000000000000000000000000000000000000000000000000000000000"
00001570 INIT_27
00001571 "0000000000000000000000000000000000000000000000000000000000000000"
00001572 INIT_28
00001573 "0000000000000000000000000000000000000000000000000000000000000000"
00001574 INIT_29
00001575 "0000000000000000000000000000000000000000000000000000000000000000"
00001576 INIT_2A
00001577 "0000000000000000000000000000000000000000000000000000000000000000"
00001578 INIT_2B
00001579 "0000000000000000000000000000000000000000000000000000000000000000"
00001580 INIT_2C
00001581 "0000000000000000000000000000000000000000000000000000000000000000"
00001582 INIT_2D
00001583 "0000000000000000000000000000000000000000000000000000000000000000"
00001584 INIT_2E
00001585 "0000000000000000000000000000000000000000000000000000000000000000"
00001586 INIT_2F
00001587 "0000000000000000000000000000000000000000000000000000000000000000"
00001588 INIT_30
00001589 "0000000000000000000000000000000000000000000000000000000000000000"
00001590 INIT_31
00001591 "0000000000000000000000000000000000000000000000000000000000000000"
00001592 INIT_32
00001593 "0000000000000000000000000000000000000000000000000000000000000000"
00001594 INIT_33
00001595 "0000000000000000000000000000000000000000000000000000000000000000"
00001596 INIT_34
00001597 "0000000000000000000000000000000000000000000000000000000000000000"
00001598 INIT_35
00001599 "0000000000000000000000000000000000000000000000000000000000000000"
00001600 INIT_36
00001601 "0000000000000000000000000000000000000000000000000000000000000000"
00001602 INIT_37
00001603 "0000000000000000000000000000000000000000000000000000000000000000"
00001604 INIT_38
00001605 "0000000000000000000000000000000000000000000000000000000000000000"
00001606 INIT_39
00001607 "0000000000000000000000000000000000000000000000000000000000000000"
00001608 INIT_3A
00001609 "0000000000000000000000000000000000000000000000000000000000000000"
00001610 INIT_3B
00001611 "0000000000000000000000000000000000000000000000000000000000000000"
00001612 INIT_3C
00001613 "0000000000000000000000000000000000000000000000000000000000000000"
00001614 INIT_3D
00001615 "0000000000000000000000000000000000000000000000000000000000000000"
00001616 INIT_3E
00001617 "0000000000000000000000000000000000000000000000000000000000000000"
00001618 INIT_3F
00001619 "0000000000000000000000000000000000000000000000000000000000000000"
00001620 */
00001621 endmodule
00001622
00001623
00001624 module memram ( global_reset, clk, push ,rw ,top ,out_word ,addr ,input_word, empty,
pop, rewrite0, rewrite1, swapwrite, cleartop, last_in, next_top, ninputs, inputwordallones,
endofframe, read_through_frame, owmark);
00001625 input push;
00001626 input [1:0] rw;
182
00001627 input [13:0] addr;
00001628 input [13:0] input_word;
00001629 input pop;
00001630 input rewrite0;
00001631 input rewrite1;
00001632 input swapwrite;
00001633 input cleartop;
00001634 input [2:0] ninputs;
00001635 input clk;
00001636 input global_reset;
00001637 input read_through_frame;
00001638
00001639 output reg [13:0] top ;
00001640 output reg [13:0] out_word ;
00001641 output reg empty ;
00001642 output reg [9:0] last_in;
00001643 output reg next_top;
00001644 output reg inputwordallones;
00001645 output reg endofframe;
00001646 output reg owmark; // outputs the mark bit of the output word
00001647
00001648 reg flag;
00001649 reg push_flag;
00001650
00001651 //Mem interface wires
00001652 reg ram_SET_RESET;
00001653 reg ram_ENABLE;
00001654 reg ram_WRITE_EN;
00001655 reg [9:0] ram_ADDRESS;
00001656 reg [17:0] ram_DATA_IN;
00001657 wire [17:0] ram_DATA_OUT;
00001658
00001659 reg ram_activity;
00001660 reg ram_read;
00001661 reg ram_read_flag;
00001662 reg ram_write;
00001663 reg ram_push;
00001664 reg ram_pop;
00001665 reg ram_clear_flag;
00001666 reg ram_set_flag;
00001667 reg ram_swap_val;
00001668 reg ram_read_top;
00001669 reg ram_clear_top;
00001670
00001671 always @(negedge clk, posedge global_reset) begin
00001672 if (global_reset) begin
00001673 ram_activity = 1'b0;
00001674 ram_SET_RESET = 1'b0;
00001675 ram_ENABLE = 1'b0;
00001676 ram_WRITE_EN = 1'b0;
00001677 $display("memram | ADDRESS=0=%b", 10'b0);
00001678 ram_ADDRESS = 1'b0;
00001679 ram_DATA_IN = 1'b0;
00001680 last_in = 10'b1111111111;
00001681 empty = 1;
00001682 flag = 1'b0;
00001683 push_flag = 1'b0;
00001684 ram_read = 1'b0;
00001685 ram_read_flag = 1'b0;
00001686 ram_write = 1'b0;
00001687 ram_push = 1'b0;
00001688 ram_pop = 1'b0;
00001689 ram_clear_flag = 1'b0;
00001690 ram_set_flag = 1'b0;
00001691 ram_swap_val = 1'b0;
00001692 ram_read_top = 1'b0;
00001693 ram_clear_top = 1'b0;
00001694 out_word = 14'b11111111111111;
00001695 owmark = out_word[3];
183
00001696 inputwordallones = 1'b1;
00001697 endofframe = 1'b0;
00001698 next_top = 1'b0;
00001699 top = 14'b11111111111111;
00001700 end
00001701 else begin
00001702 if (input_word == 14'b11111111111111) begin
00001703 inputwordallones = 1'b1;
00001704 end
00001705 else begin
00001706 inputwordallones = 1'b0;
00001707 end
00001708
00001709 if (ram_activity) begin
00001710 if (ram_read == 1'b1) begin
00001711 if (ram_DATA_OUT[3] == 1'b1) begin
00001712 endofframe = 1'b1;
00001713 if (read_through_frame) begin
00001714 //Keep pushing next frame top when
state checking
00001715 out_word = ram_DATA_OUT[13:0];
00001716 owmark = out_word[3];
00001717 $display("memram | ram reading out
- =%b", out_word);
00001718 ram_ENABLE = 1'b0;
00001719 ram_read = 1'b0;
00001720 end
00001721 end
00001722 else begin
00001723 endofframe = 1'b0;
00001724 out_word = ram_DATA_OUT[13:0];
00001725 owmark = out_word[3];
00001726 if (ram_ADDRESS == last_in) begin
00001727 top = out_word;
00001728 end
00001729 $display("memram | ram reading out -
=%b", out_word);
00001730 ram_ENABLE = 1'b0;
00001731 ram_read = 1'b0;
00001732 end
00001733 end
00001734 if (ram_read_flag) begin
00001735 $display ("memram | checking if at top of
frame");
00001736 next_top = ram_DATA_OUT[3];
00001737 ram_ENABLE = 1'b0;
00001738 ram_read_flag = 1'b0;
00001739 end
00001740 if (ram_write == 1'b1) begin
00001741 $display ("memram | writing to ram");
00001742 ram_ENABLE = 1'b0;
00001743 ram_WRITE_EN = 1'b0;
00001744 ram_write = 1'b0;
00001745 end
00001746 if (ram_push == 1'b1) begin
00001747 $display ("memram | pushing on to ram");
00001748 $display(" input word=%b",
input_word);
00001749 push_flag = 1'b1;
00001750 if(ram_DATA_OUT[13:0] == input_word) begin
00001751 $display ("duplicate word identified");
00001752 ram_ENABLE = 1'b0;
00001753 ram_WRITE_EN = 1'b0;
00001754 ram_push = 1'b0;
00001755 last_in = last_in - 1;
00001756 end
00001757 else begin
00001758 ram_push = 1'b0;
00001759 $display("memram | ADDRESS=li=%b",
184
last_in);
00001760 ram_ADDRESS = last_in;
00001761 ram_DATA_IN = input_word;
00001762 top = input_word;
00001763 ram_ENABLE = 1'b1;
00001764 ram_WRITE_EN = 1'b1;
00001765 push_flag = 1'b0;
00001766 end
00001767 end
00001768 if (ram_pop == 1'b1) begin
00001769 $display ("memram | popping off of RAM");
00001770 ram_ENABLE = 1'b0;
00001771 ram_pop = 1'b0;
00001772 last_in = last_in - 1;
00001773 ram_WRITE_EN = 1'b0;
00001774 end
00001775 if (ram_clear_flag == 1'b1) begin
00001776 $display ("clearing the flag in RAM");
00001777 ram_ENABLE = 1'b1;
00001778 ram_WRITE_EN = 1'b1;
00001779 ram_DATA_IN = ram_DATA_OUT;
00001780 ram_DATA_IN[3] = 1'b0;
00001781 ram_clear_flag = 1'b0;
00001782 end
00001783 if (ram_set_flag == 1'b1) begin
00001784 $display ("memram | setting the flag in RAM");
00001785 ram_ENABLE = 1'b1;
00001786 ram_WRITE_EN = 1'b1;
00001787 ram_DATA_IN = ram_DATA_OUT;
00001788 ram_DATA_IN[3] = 1'b1;
00001789 ram_set_flag = 1'b0;
00001790 end
00001791 if (ram_swap_val == 1'b1) begin
00001792 $display ("memram | swapping values in RAM");
00001793 ram_swap_val = 1'b0;
00001794 ram_DATA_IN = ram_DATA_OUT;
00001795 $display("ram_DATA_IN before swap: %b",
ram_DATA_IN);
00001796 ram_DATA_IN[0] = 1'b1;
00001797 if(ram_DATA_IN[2:1] == 2'b10) begin
00001798 ram_DATA_IN[2:1] = 2'b01;
00001799 end
00001800 else if(ram_DATA_IN[2:1] == 2'b01) begin
00001801 ram_DATA_IN[2:1] = 2'b10;
00001802 end
00001803 $display("memram | ram_DATA_IN after swap: %b",
ram_DATA_IN);
00001804 $display("memram | ram_ADDRESS=%b", ram_ADDRESS);
00001805 ram_ENABLE = 1'b1;
00001806 ram_WRITE_EN = 1'b1;
00001807 end
00001808 if (ram_clear_top == 1'b1) begin
00001809 $display("memram | clearing top value in RAM");
00001810 ram_clear_top = 1'b0;
00001811 ram_DATA_IN = ram_DATA_OUT;
00001812 ram_DATA_IN[2:1] = 2'b11;
00001813 ram_ENABLE = 1'b1;
00001814 ram_WRITE_EN = 1'b1;
00001815 end
00001816 end
00001817 if (ram_read_top == 1'b1) begin
00001818 $display("memram | setting Top in RAM");
00001819 ram_read_top = 1'b0;
00001820 top = ram_DATA_OUT;
00001821 ram_ENABLE = 1'b0;
00001822 end
00001823
00001824 ram_activity = 1'b0;
00001825
185
00001826 if (rw == 2'b10) begin
00001827 if (addr == 14'b11111111111111) begin
00001828 ram_ADDRESS = last_in;
00001829 $display("memram | ADDRESS=li=%b", last_in);
00001830 ram_read_top = 1'b1;
00001831 end
00001832 else begin
00001833 ram_ADDRESS = addr;
00001834 $display("memram | ADDRESS=addr=%b", addr);
00001835 ram_read = 1'b1;
00001836 end
00001837 ram_activity = 1'b1;
00001838 ram_ENABLE = 1'b1;
00001839 ram_WRITE_EN = 1'b0;
00001840 $display ("Reading the ram");
00001841 end
00001842 else if (rw == 2'b01) begin
00001843 ram_write = 1'b1;
00001844 ram_activity = 1'b1;
00001845 $display("memram | ADDRESS=addr=%b", addr);
00001846 ram_ADDRESS = addr;
00001847 ram_DATA_IN = input_word;
00001848 ram_ENABLE = 1'b1;
00001849 ram_WRITE_EN = 1'b1;
00001850 $display("Writing to RAM");
00001851 end
00001852 else begin
00001853 out_word = 14'b11111111111111;
00001854 owmark = 1'b0;
00001855 end
00001856
00001857 if (addr == 14'b11111111111111) begin
00001858 next_top = 1'b1;
00001859 end
00001860 /*else if (addr != 14'b0) begin
00001861 // old code 'next_top = ram[addr-1][3];
00001862 ram_read_flag = 1;
00001863 ram_activity = 1;
00001864 $display("memram | ADDRESS=addr-1=%b", addr - 1);
00001865 ram_ADDRESS = addr - 1;
00001866 ram_ENABLE = 1;
00001867 end*/
00001868
00001869 if(push && input_word != 14'b11111111111111) begin
00001870 $display("memram | beginning push");
00001871 ram_push = 1'b1;
00001872 ram_activity = 1;
00001873 push_flag = 1'b0;
00001874 ram_ENABLE = 1'b0;
00001875 ram_WRITE_EN = 1'b0;
00001876 $display("memram | ADDRESS=0=%b", ram_ADDRESS);
00001877 ram_ADDRESS = 10'b0000000000;
00001878 last_in = last_in + 1;
00001879 empty = 1'b0;
00001880 end
00001881 if(pop) begin
00001882 $display("memram | beginning pop");
00001883 ram_pop = 1'b1;
00001884 ram_activity = 1'b1;
00001885 $display("memram | ADDRESS=li=%b", last_in);
00001886 ram_ADDRESS = last_in;
00001887 ram_ENABLE = 1'b1;
00001888 ram_WRITE_EN = 1'b1;
00001889 ram_DATA_IN = 18'b111111111111111111;
00001890 if(last_in == 0) empty = 1'b1;
00001891 end
00001892
00001893 if(rewrite0) begin
00001894 $display("memram | beginning rewrite0");
186
00001895 ram_clear_flag = 1'b1;
00001896 ram_activity = 1'b1;
00001897 $display("memram | ADDRESS=li=%b", last_in);
00001898 ram_ADDRESS = last_in;
00001899 ram_ENABLE = 1'b1;
00001900 ram_WRITE_EN = 1'b0;
00001901 empty = 1'b0;
00001902 end
00001903 if(rewrite1) begin
00001904 $display("memram | beginning rewrite1");
00001905 ram_set_flag = 1'b1;
00001906 ram_activity = 1'b1;
00001907 $display("memram | ADDRESS=li=%b", last_in);
00001908 ram_ADDRESS = last_in;
00001909 ram_ENABLE = 1'b1;
00001910 ram_WRITE_EN = 1'b0;
00001911 empty = 1'b1;
00001912 end
00001913 if(swapwrite) begin
00001914 $display("memram | beginning swapwrite");
00001915 ram_swap_val = 1'b1;
00001916 ram_activity = 1'b1;
00001917 $display("memram | ADDRESS=li=%b", last_in);
00001918 ram_ADDRESS = last_in;
00001919 ram_ENABLE = 1'b1;
00001920 ram_WRITE_EN = 1'b0;
00001921 end
00001922 if(cleartop) begin
00001923 $display("memram | beginning cleartop");
00001924 ram_clear_top = 1'b1;
00001925 ram_activity = 1'b1;
00001926 $display("memram | ADDRESS=li=%b", last_in);
00001927 ram_ADDRESS = last_in;
00001928 ram_ENABLE = 1'b1;
00001929 ram_WRITE_EN = 1'b0;
00001930 end
00001931 end
00001932 end
00001933
00001934 XC2V_RAMB_1_PORT bi_ram (clk, ram_SET_RESET, ram_ENABLE, ram_WRITE_EN,
ram_ADDRESS, ram_DATA_IN, ram_DATA_OUT);
00001935 endmodule
00001936
00001937
00001938 module statecheck (global_reset, clk, valuestoforward0, valuestoforward1, Out, Addr,
endofframe, beginstatecheck, donewithstatecheck, statecheckresult);
00001939 parameter n = 1;
00001940 parameter m = 4;
00001941 parameter l = 3;
00001942 parameter s = 22;
00001943
00001944 input global_reset;
00001945 input clk;
00001946 input [m+l-1:0] valuestoforward0;
00001947 input [m+l-1:0] valuestoforward1;
00001948 input [13:0] Out;
00001949 input [13:0] Addr;
00001950 input endofframe;
00001951 input beginstatecheck;
00001952 output reg donewithstatecheck;
00001953 output reg statecheckresult;
00001954
00001955 reg [m+l-1:0] pastframevalues0;
00001956 reg [m+l-1:0] pastframevalues1;
00001957 reg currentframebypass;
00001958
00001959 always @(posedge global_reset, posedge clk) begin
00001960 if (global_reset) begin
00001961 $display("statecheck | reset");
187
00001962 donewithstatecheck = 1'b0;
00001963 statecheckresult = 1'b0;
00001964 pastframevalues0 = {(m+l){1'b1}};
00001965 pastframevalues1 = {(m+l){1'b1}};
00001966 currentframebypass = 1'b1;
00001967 end
00001968 else begin
00001969 if (beginstatecheck) begin
00001970 if (endofframe || Addr == 14'b11111111111110) begin
00001971 //Frame read done - compare values
00001972 $display("statecheck | end of frame compare
(Addr=%b)", Addr);
00001973 if (!currentframebypass && (pastframevalues0 ==
valuestoforward0 && pastframevalues1 == valuestoforward1)) begin
00001974 //Duplicate state found
00001975 $display("statecheck | duplicate found");
00001976 statecheckresult = 1'b1;
00001977 donewithstatecheck = 1'b1;
00001978 currentframebypass = 1'b1;
00001979 end
00001980 else if (Addr == 14'b11111111111110) begin
00001981 //All frames checked and no duplicates
00001982 $display("statecheck | check finished
with no duplicates");
00001983 statecheckresult = 1'b0;
00001984 donewithstatecheck = 1'b1;
00001985 currentframebypass = 1'b1;
00001986 end
00001987 else if (currentframebypass) begin
00001988 //Disable bypass after first frame
compare (frame compare to itself)
00001989 currentframebypass = 1'b0;
00001990 end
00001991
00001992 //Clear out frame past values compare registers
00001993 pastframevalues0 = {(m+l){1'b1}};
00001994 pastframevalues1 = {(m+l){1'b1}};
00001995 end
00001996
00001997 if (!donewithstatecheck) begin
00001998 //Store current values from past frame
00001999 $display("statecheck | store value in Out: %b",
Out);
00002000 pastframevalues0[Out[13:4]] = Out[1];
00002001 pastframevalues1[Out[13:4]] = Out[2];
00002002 end
00002003 else if (!(endofframe || Addr == 14'b11111111111110) &&
donewithstatecheck) begin
00002004 //Reset done signal after completion
00002005 donewithstatecheck = 1'b0;
00002006 end
00002007 end
00002008 end
00002009 end
00002010 endmodule
00002011
00002012 module mytop (global_reset, clk, line_k_X, line_k_1, Conflict, NReady, mode, Done,
in, PPI, FAIL, frame_k, DONE, valuestoforward0, valuestoforward1, genobj, newvaluestoforward,
donewithstatecheck, statecheckresult, tiplus1);
00002013 parameter n = 1;
00002014 parameter m = 4;
00002015 parameter l = 3;
00002016 parameter s = 22;
00002017
00002018 input line_k_X;
00002019 input line_k_1;
00002020 input Conflict;
00002021 input NReady;
00002022 input mode;
188
00002023 input Done;
00002024 input [13:0] in;
00002025 input global_reset;
00002026 input clk;
00002027
00002028 output [13:0] PPI;
00002029 output FAIL;
00002030 output frame_k;
00002031 output DONE;
00002032 output reg [m+l-1:0] valuestoforward0;
00002033 output reg [m+l-1:0] valuestoforward1;
00002034 output genobj;
00002035 output reg newvaluestoforward;
00002036 output donewithstatecheck;
00002037 output statecheckresult;
00002038 output tiplus1;
00002039
00002040 reg [m+l-1:0] vf0;
00002041 reg [m+l-1:0] vf1;
00002042 reg new_values_trigger;
00002043
00002044 wire [2:0] ninputs;
00002045 wire clk;
00002046 wire [13:0] top;
00002047 wire [13:0] Out;
00002048 wire push;
00002049 wire pop;
00002050 wire empty;
00002051 wire [13:0] Addr;
00002052 wire [1:0] RW;
00002053 wire comp_tried;
00002054 wire top_mark;
00002055 wire [1:0] value;
00002056 wire [1:0] nclear;
00002057 wire cnt_enable;
00002058 wire cnt_dir;
00002059 wire frame_1;
00002060 wire rewrite0;
00002061 wire rewrite1;
00002062 wire swapwrite;
00002063 wire cleartop;
00002064 wire [1:0] pvalue;
00002065 wire frame_k;
00002066 wire next_top;
00002067 wire sendvaluestoforward;
00002068 wire inputwordallones;
00002069 wire readingow; // used to decide if VF should be assigned off Top or ow
00002070 wire endofframe; // tracks if currently read mem data is the top of previous
frame
00002071 wire beginstatecheck;
00002072 wire donewithstatecheck;
00002073 wire statecheckresult;
00002074 wire control_blockisppi;
00002075 wire blockisppi;
00002076 wire owmark;
00002077 wire tiplus1;
00002078
00002079 wire [31:0] last_in;
00002080
00002081 fourcounter mycounter (global_reset, frame_1, cnt_dir, cnt_enable,frame_k);
00002082 isppi myisppi(PPI, Out, blockisppi);
00002083 decoder mydecoder (top, value, top_mark, comp_tried );
00002084 control mycontrol( global_reset, clk, push ,line_k_1 ,cnt_dir ,NReady ,DONE
,Done ,comp_tried ,RW ,line_k_X ,cnt_enable , pop ,empty ,Conflict ,frame_k ,frame_1 ,Addr
,FAIL ,top_mark ,value, rewrite0, rewrite1, swapwrite, cleartop, nclear, last_in, next_top,
ninputs, genobj, sendvaluestoforward, inputwordallones, readingow, endofframe,
beginstatecheck, donewithstatecheck, statecheckresult, control_blockisppi, owmark, tiplus1);
00002085 memram mymemram ( global_reset, clk, push ,RW ,top ,Out ,Addr ,in ,empty ,pop,
rewrite0, rewrite1, swapwrite, cleartop, last_in, next_top, ninputs, inputwordallones,
189
endofframe, read_through_frame, owmark);
00002086 vcontrol myvcontrol (top, Out, pvalue);
00002087 statecheck mystatecheck(global_reset, clk, valuestoforward0, valuestoforward1,
Out, Addr, endofframe, beginstatecheck, donewithstatecheck, statecheckresult);
00002088
00002089 always @(pvalue, nclear, mode, global_reset) begin
00002090 if(global_reset) begin
00002091 $display ("PPI Decision Block / Reset of PPI Decision Block");
00002092 valuestoforward0 = {(m+l){1'b1}};
00002093 valuestoforward1 = {(m+l){1'b1}};
00002094 vf0 = {(m+l){1'b1}};
00002095 vf1 = {(m+l){1'b1}};
00002096 newvaluestoforward = 1'b0;
00002097 new_values_trigger = 1'b1;
00002098 end
00002099 else begin
00002100 if(nclear == 2'b01) begin
00002101 if (readingow) begin
00002102 $display("PPI Decision Block | Assign vf (from
Out)");
00002103 $display(" addr=%b",
Out[13:4]);
00002104 $display(" val=%b",
{Out[2],Out[1]});
00002105 vf0[Out[13:4]] = Out[1];
00002106 vf1[Out[13:4]] = Out[2];
00002107 new_values_trigger = 1'b1;
00002108 end
00002109 else begin
00002110 $display("PPI Decision Block | Assign vf (from
top)");
00002111 $display(" addr=%b",
top[13:4]);
00002112 $display(" val=%b",
{top[2],top[1]});
00002113 vf0[top[13:4]] = top[1];
00002114 vf1[top[13:4]] = top[2];
00002115 new_values_trigger = 1'b1;
00002116 end
00002117 end
00002118 else if (nclear == 2'b00) begin
00002119 $display ("PPI Decision Block | Clearing
ValuestoForward");
00002120 valuestoforward0 = {(m+l){1'b1}};
00002121 valuestoforward1 = {(m+l){1'b1}};
00002122 vf0 = {(m+l){1'b1}};
00002123 vf1 = {(m+l){1'b1}};
00002124 newvaluestoforward = ~newvaluestoforward;
00002125 end
00002126 else if (nclear == 2'b10) begin
00002127 $display ("PPI Decision Block | Clearing VF0 & VF1");
00002128 vf0 = {(m+l){1'b1}};
00002129 vf1 = {(m+l){1'b1}};
00002130 end
00002131 else if (mode == 1'b0 && sendvaluestoforward == 1'b1 &&
new_values_trigger == 1'b1) begin
00002132 $display("PPI Decision Block | Sending Values to Forward
Network");
00002133 valuestoforward0 = vf0;
00002134 valuestoforward1 = vf1;
00002135 newvaluestoforward = ~newvaluestoforward;
00002136 new_values_trigger = 1'b0;
00002137 end
00002138 end
00002139 end
00002140
00002141 assign blockisppi = beginstatecheck | control_blockisppi;
00002142 assign read_through_frame = beginstatecheck | tiplus1;
00002143 endmodule
190
00002144
00002145
00002146 module top_back_net(global_reset, clk, obj_set, obj, po_1, po_0, ppo_1, ppo_0,
STATE_1, STATE_0, NReady, in, mode, genobj, propfail, newframe_ready);
00002147 ////parameters
00002148 parameter n = 1;
00002149 parameter m = 4;
00002150 parameter l = 3;
00002151 parameter s = 22;
00002152
00002153 //io
00002154 input global_reset;
00002155 input clk;
00002156 input obj_set;
00002157 input genobj;
00002158 input [13:0] obj;
00002159 input [n-1:0] po_1;
00002160 input [n-1:0] po_0;
00002161 input [l-1:0] ppo_1;
00002162 input [l-1:0] ppo_0;
00002163 input [s-1:0] STATE_1;
00002164 input [s-1:0] STATE_0;
00002165 input newframe_ready;
00002166 output NReady;
00002167 output [13:0] in;
00002168 output mode;
00002169 output propfail;
00002170
00002171 //wires
00002172 wire [n-1:0] pi_1;
00002173 wire [n-1:0] pi_0;
00002174 wire [l-1:0] ppi_1;
00002175 wire [l-1:0] ppi_0;
00002176 wire [m-1:0] b_po_1;
00002177 wire [m-1:0] b_po_0;
00002178 wire [l-1:0] b_ppo_1;
00002179 wire [l-1:0] b_ppo_0;
00002180 wire priority_reset;
00002181 wire trace_start;
00002182
00002183 //Block connections
00002184 back_decoder Back_Decoder(global_reset, clk, obj, obj_set, po_1, po_0, ppo_1,
ppo_0, pi_1, pi_0, ppi_1, ppi_0, priority_reset, trace_start);
00002185 back_net Back_Net(priority_reset, pi_1, pi_0, ppi_1, ppi_0, STATE_1, STATE_0,
b_po_1, b_po_0, b_ppo_1, b_ppo_0);
00002186 back_encoder Back_Encoder (global_reset, clk, trace_start, b_po_1, b_po_0,
b_ppo_1, b_ppo_0, NReady, in, mode, genobj, propfail, newframe_ready);
00002187 endmodule
00002188
00002189
00002190 module top(global_reset, clk, fail, done);
00002191 ////parameters
00002192 parameter n = 1;
00002193 parameter m = 4;
00002194 parameter l = 3;
00002195 parameter s = 22;
00002196
00002197 //io
00002198 input global_reset;
00002199 input clk;
00002200 output fail;
00002201 output done;
00002202
00002203 //wires - Dec Block - Fwd Net
00002204 wire [m+l-1:0] composit_pi_1;
00002205 wire [m+l-1:0] composit_pi_0;
00002206 wire [m-1:0] pi_1;
00002207 wire [m-1:0] pi_0;
00002208 wire [l-1:0] ppi_1;
191
00002209 wire [l-1:0] ppi_0;
00002210
00002211 //Wires - Fwd Net - Obj Dec/Back Net
00002212 wire [n-1:0] po_1;
00002213 wire [n-1:0] po_0;
00002214 wire [l-1:0] ppo_1;
00002215 wire [l-1:0] ppo_0;
00002216
00002217 //Wires - Obj Dec - Back Net
00002218 wire [13:0] obj;
00002219 wire propfail;
00002220 wire newframe_ready;
00002221
00002222 //Wires - Fwd Net - Back Net
00002223 wire [s-1:0] STATE_1;
00002224 wire [s-1:0] STATE_0;
00002225
00002226 //Wires - Back Net - Dec Block
00002227 wire [13:0] in;
00002228 wire NReady;
00002229 wire mode;
00002230 wire genobj;
00002231
00002232 //wires - Dec Block - Obj Dec
00002233 wire [13:0] ppi;
00002234 wire frame_k;
00002235 wire newvaluestoforward;
00002236 wire donewithstatecheck;
00002237 wire statecheckresult;
00002238 wire tiplus1;
00002239
00002240 //Wires - Obj Dec - Dec Block
00002241 wire Done;
00002242 wire Conflict;
00002243 wire line_k_1;
00002244 wire line_k_X;
00002245
00002246 //Handle composit pi/ppi wires from Dec block
00002247 assign {ppi_1, pi_1} = composit_pi_1;
00002248 assign {ppi_0, pi_0} = composit_pi_0;
00002249
00002250 //Block Wirings
00002251 mytop Dec_Block (global_reset, clk, line_k_X, line_k_1, Conflict, NReady, mode,
Done, in, ppi, fail, frame_k, done, composit_pi_0, composit_pi_1, genobj, newvaluestoforward,
donewithstatecheck, statecheckresult, tiplus1);
00002252 obj_dec Obj_Dec_Block (global_reset, clk, ppi, po_0, po_1, ppo_0, ppo_1,
frame_k, obj, Done, Conflict, line_k_1, line_k_X, obj_set, propfail, newframe_ready,
newvaluestoforward, donewithstatecheck, statecheckresult, tiplus1);
00002253 fwd_net Fwd_Net (pi_1, pi_0, ppi_1, ppi_0, STATE_1, STATE_0, po_1, po_0, ppo_1,
ppo_0);
00002254 top_back_net Back_Net (.global_reset(global_reset), .clk(clk),
.obj_set(obj_set), .obj(obj), .po_1(po_1), .po_0(po_0), .ppo_1(ppo_1), .ppo_0(ppo_0),
.STATE_1(STATE_1), .STATE_0(STATE_0), .NReady(NReady), .in(in), .mode(mode), .genobj(genobj),
.propfail(propfail), .newframe_ready(newframe_ready));
00002255 endmodule
192
Appendix E: Forward / Backward Network Generation Program C++ Code
Included in this appendix is the C++ code for the program that reads in a benchmark circuit and
writes out Forward / Backward Networks, as described in section 3.5. The program takes a
single command-line argument, which is the name of the benchmark circuit to be translated. The
output fwd_net.v and back_net.v are written into the same directory that the program is located
in.
00000001 //---------------------------
00000002 //
00000003 // Veri Circuit Generator
00000004 //
00000005 //---------------------------
00000006
00000007 #include <stdio.h>
00000008 #include <stdlib.h>
00000009 #include <string.h>
00000010 #include <sstream>
00000011 #include <iostream>
00000012 #include <fstream>
00000013 #include <ctype.h>
00000014
00000015 using namespace std;
00000016
00000017
00000018 //Struct for standard gate pointing node
00000019 struct gate_node{
00000020 struct gate * gate_ptr;
00000021 struct gate_node * next_ptr;
00000022 struct gate_node * prev_ptr;
00000023 };
00000024
00000025 //Struct for holding gate data
00000026 struct gate{
00000027 char name[25];
00000028 char type[10];
00000029 int state;
00000030 int level;
00000031 struct gate * sched;
00000032 struct gate_node * fanin_list;
00000033 struct gate_node * fanout_list;
00000034 };
00000035
00000036 //Level node
00000037 struct level_node{
00000038 int level;
00000039 struct gate_node * gate_ptr;
00000040 struct level_node * next_ptr;
00000041 struct level_node * prev_ptr;
00000042 };
00000043
00000044
00000045 //FUCTIONS - Circuit load and prep
00000046 void load_circuit(char []);
00000047 int level_circuit();
00000048 int find_level(struct gate *);
00000049 void reverse_lists();
193
00000050
00000051 //FUNCTIONS - Generate forward network
00000052 void fwd_network(int);
00000053 string fwd_pi_list_1();
00000054 string fwd_pi_list_0();
00000055 int fwd_pi_count();
00000056 string fwd_ppi_list_1();
00000057 string fwd_ppi_list_0();
00000058 int fwd_ppi_count();
00000059 string fwd_state_list_1(int);
00000060 string fwd_state_list_0(int);
00000061 string fwd_wire_list_1(int);
00000062 string fwd_wire_list_0(int);
00000063 int fwd_gate_count(int);
00000064 string fwd_po_list_1();
00000065 string fwd_po_list_0();
00000066 int fwd_po_count();
00000067 string fwd_ppo_list_1();
00000068 string fwd_ppo_list_0();
00000069 int fwd_ppo_count();
00000070
00000071 //FUNCTIONS - Generate backward network
00000072 void back_network(int);
00000073 string back_pi_list_1();
00000074 string back_pi_list_0();
00000075 int back_pi_count();
00000076 string back_ppi_list_1();
00000077 string back_ppi_list_0();
00000078 int back_ppi_count();
00000079 string back_state_list_1(int);
00000080 string back_state_list_0(int);
00000081 string back_wire_list_1(int);
00000082 string back_wire_list_0(int);
00000083 int back_gate_count(int);
00000084 string back_po_list_1();
00000085 string back_po_list_0();
00000086 int back_po_count();
00000087 string back_ppo_list_1();
00000088 string back_ppo_list_0();
00000089 int back_ppo_count();
00000090
00000091 void makeupper(char []);
00000092
00000093 //Define global variables
00000094 struct gate_node * input_list = NULL;
00000095 struct gate_node * output_list = NULL;
00000096 struct gate_node * dff_list = NULL;
00000097 struct gate_node * gate_list = NULL;
00000098 struct level_node * level_list = NULL;
00000099 struct level_node * sched_list = NULL;
00000100
00000101
00000102 //--------------------------------------------------------------------
00000103
00000104 int main(int argc, char *argv[]){
00000105 //Check args
00000106 if(argc != 2){
00000107 cout << "Single input bench file must be specified. " << endl;
00000108 return -1;
00000109 }
00000110
00000111 cout << "Working on file " << argv[1] << "..." << endl;
00000112
00000113 //Load Circuit From File
00000114 cout << "Loading gates from file...";
00000115 load_circuit(argv[1]);
00000116 cout << "Done" << endl;
00000117
00000118 //Load Circuit into Levels
194
00000119 cout << "Leveling gates...";
00000120 int max_level = level_circuit();
00000121
00000122 //Generate Nets
00000123 cout << "Starting fwd/back network generation..." << endl;
00000124 fwd_network(max_level);
00000125 back_network(max_level);
00000126
00000127 //Push down output line
00000128 printf("\n");
00000129 return 0;
00000130 }
00000131
00000132 //--------------------------------------------------------------------
00000133
00000134
00000135 //Load Circuit
00000136 // Get V file from user and parse file into gate stuctures
00000137 void load_circuit(char file_name[]){
00000138 //Local variables
00000139 char current_line_ws[100];
00000140 char current_line[100];
00000141
00000142 int i = 0;
00000143 while(file_name[i] != '\n' && file_name[i] != '\0'){i++;}
00000144 file_name[i] = '\0';
00000145
00000146 //Open file for input
00000147 FILE * v_file;
00000148 v_file = fopen(file_name, "r");
00000149 if(v_file == NULL){
00000150 puts("ERROR opening file\n");
00000151 exit(1);
00000152 }
00000153
00000154 //Begin reading in
00000155 while(fgets(current_line_ws, 100, v_file)){
00000156 //Trim leading WS
00000157 int i = 0;
00000158 while(current_line_ws[i] == ' ' || (current_line_ws[i] == '\t')){i++;}
00000159 strncpy(current_line, current_line_ws+i, 100-i);
00000160
00000161 if((current_line[0] == '\n') || (current_line[0] == '#')){
00000162 //Blank line, ignore
00000163 }
00000164 else{
00000165 //Readable Line
00000166 char input_test[10];
00000167 strncpy(input_test, current_line, 5);
00000168 input_test[5] = '\0';
00000169 makeupper(input_test);
00000170
00000171 if(strcmp(input_test, "INPUT") == 0){
00000172 //Get name
00000173 i = 0;
00000174 while(current_line[i] != '('){i++;}
00000175 i++;
00000176 int j = i;
00000177 while(current_line[j] != ')'){j++;}
00000178 char gate_name[25] = "";
00000179 strncpy(gate_name, current_line+i, j-i);
00000180 gate_name[j-i] = '\0';
00000181
00000182 //Setup Input struct
00000183 struct gate_node * in_ptr = gate_list;
00000184 while((in_ptr != NULL) && (strcmp(in_ptr->gate_ptr-
>name, gate_name) != 0)){in_ptr = in_ptr->next_ptr;}
00000185 if(in_ptr == NULL){
00000186 //New input, set up
195
00000187 struct gate * new_gate = new gate;
00000188 strcpy(new_gate->name, gate_name);
00000189 strcpy(new_gate->type, "INPUT");
00000190 new_gate->state = 4;
00000191 new_gate->level = 0;
00000192 new_gate->sched = NULL;
00000193 new_gate->fanin_list = NULL;
00000194 new_gate->fanout_list = NULL;
00000195
00000196 //Link to input list
00000197 struct gate_node * new_gate_node = new gate_node;
00000198 new_gate_node->gate_ptr = new_gate;
00000199 new_gate_node->next_ptr = input_list;
00000200 if(input_list != NULL){
00000201 input_list->prev_ptr = new_gate_node;
00000202 }
00000203 input_list = new_gate_node;
00000204 }
00000205 }
00000206 else{
00000207 //Test for OUTPUT
00000208 char output_test[10];
00000209 strncpy(output_test, current_line, 6);
00000210 output_test[6] = '\0';
00000211 makeupper(output_test);
00000212
00000213 if(strcmp(output_test, "OUTPUT") == 0){
00000214 //Get name
00000215 i = 0;
00000216 while(current_line[i] != '('){i++;}
00000217 i++;
00000218 int j = i;
00000219 while(current_line[j] != ')'){j++;}
00000220 char gate_name[25] = "";
00000221 strncpy(gate_name, current_line+i, j-i);
00000222 gate_name[j-i] = '\0';
00000223
00000224 //Check if we already pre-assigned this output
00000225 struct gate_node * out_ptr = gate_list;
00000226 while((out_ptr != NULL) && (strcmp(out_ptr-
>gate_ptr->name, gate_name) != 0)){out_ptr = out_ptr->next_ptr;}
00000227 if(out_ptr == NULL){
00000228 //Check if we already assigned this as an
output
00000229 out_ptr = output_list;
00000230 while((out_ptr != NULL) &&
(strcmp(out_ptr->gate_ptr->name, gate_name) != 0)){out_ptr = out_ptr->next_ptr;}
00000231 if(out_ptr == NULL){
00000232 //Check if this output comes
directly from an output
00000233 out_ptr = input_list;
00000234 while((out_ptr != NULL) &&
(strcmp(out_ptr->gate_ptr->name, gate_name) != 0)){out_ptr = out_ptr->next_ptr;}
00000235 if(out_ptr == NULL){
00000236 //This output is new
00000237 //Setup Output struct
00000238 struct gate * new_gate =
new gate;
00000239 strcpy(new_gate->name,
gate_name);
00000240 strcpy(new_gate->type,
"OUTPUT");
00000241 new_gate->state = 4;
00000242 new_gate->level = -1;
00000243 new_gate->sched = NULL;
00000244 new_gate->fanin_list =
NULL;
00000245 new_gate->fanout_list =
NULL;
196
00000246
00000247 //Link to gate list (end
gate = output)
00000248 struct gate_node *
new_gate_node2 = new gate_node;
00000249 new_gate_node2->gate_ptr =
new_gate;
00000250 new_gate_node2->next_ptr =
gate_list;
00000251 gate_list =
new_gate_node2;
00000252
00000253 out_ptr = new_gate_node2;
00000254 }
00000255 }
00000256 }
00000257
00000258 //Check if this is already an output
00000259 struct gate_node * link_ptr = output_list;
00000260 while((link_ptr != NULL) && (strcmp(link_ptr-
>gate_ptr->name, gate_name) != 0)){link_ptr = link_ptr->next_ptr;}
00000261 if(link_ptr == NULL){
00000262 //Link to output list
00000263 struct gate_node * new_gate_node = new
gate_node;
00000264 new_gate_node->gate_ptr = out_ptr-
>gate_ptr;
00000265 new_gate_node->next_ptr = output_list;
00000266 if(output_list != NULL){
00000267 output_list->prev_ptr =
new_gate_node;
00000268 }
00000269 output_list = new_gate_node;
00000270 }
00000271 }
00000272 else{
00000273 //Otherwise, line represents a gate, process
00000274
00000275 //Read gate name
00000276 i = 0;
00000277 while(current_line[i] != '='){i++;}
00000278 char name[25];
00000279 strncpy(name, current_line, i-1);
00000280 name[i-1] = '\0';
00000281
00000282 //Read gate type
00000283 i = i + 2;
00000284 int j = i;
00000285 while((current_line[j] != '(') &&
(current_line[j] != '\n')){j++;}
00000286 char type[10];
00000287 strncpy(type, current_line+i, j-i);
00000288 type[j-i] = '\0';
00000289 makeupper(type);
00000290
00000291 //Check for gate
00000292 struct gate_node * gate_ptr = gate_list;
00000293 struct gate * new_gate;
00000294 while((gate_ptr != NULL) && (strcmp(gate_ptr-
>gate_ptr->name, name) != 0)){gate_ptr = gate_ptr->next_ptr;}
00000295 if(gate_ptr == NULL){
00000296 //Create a new gate for assignment
00000297 new_gate = new gate;
00000298 strcpy(new_gate->name, name);
00000299 strcpy(new_gate->type, type);
00000300 new_gate->state = 4;
00000301 new_gate->level = -1;
00000302 new_gate->sched = NULL;
00000303 new_gate->fanin_list = NULL;
197
00000304 new_gate->fanout_list = NULL;
00000305 //Link to gate list
00000306 struct gate_node * new_gate_node = new
gate_node;
00000307 new_gate_node->gate_ptr = new_gate;
00000308 new_gate_node->next_ptr = gate_list;
00000309 gate_list = new_gate_node;
00000310
00000311 gate_ptr = new_gate_node;
00000312 }
00000313 else{
00000314 //Update gate type
00000315 strcpy(gate_ptr->gate_ptr->type, type);
00000316 }
00000317
00000318 j++;
00000319 i = j;
00000320 while((current_line[j] != ',') &&
(current_line[j] != ')')){j++;}
00000321 char input1[25];
00000322 strncpy(input1, current_line+i, j-i);
00000323 input1[j-i] = '\0';
00000324
00000325 int prev_j = j;
00000326 do{
00000327 //Find input 1 in list
00000328 struct gate_node * in_ptr = gate_list;
00000329 while((in_ptr != NULL) && (strcmp(in_ptr-
>gate_ptr->name, input1) != 0)){in_ptr = in_ptr->next_ptr;}
00000330 if(in_ptr == NULL){
00000331 //Keep looking in inputs
00000332 in_ptr = input_list;
00000333 while((in_ptr != NULL) &&
(strcmp(in_ptr->gate_ptr->name, input1) != 0)){in_ptr = in_ptr->next_ptr;}
00000334 if(in_ptr == NULL){
00000335 //Keep looking in DFFs
00000336 in_ptr = dff_list;
00000337 while((in_ptr != NULL) &&
(strcmp(in_ptr->gate_ptr->name, input1) != 0)){in_ptr = in_ptr->next_ptr;}
00000338
00000339 if(in_ptr == NULL){
00000340 //This appears to
be the first reference to this gate, create as output
00000341 struct gate *
new_gate = new gate;
00000342 strcpy(new_gate-
>name, input1);
00000343 strcpy(new_gate-
>type, "OUTPUT");
00000344 new_gate->state =
4;
00000345 new_gate->level = -
1;
00000346 new_gate->sched =
NULL;
00000347 new_gate-
>fanin_list = NULL;
00000348 new_gate-
>fanout_list = NULL;
00000349
00000350 //Link to gate list
(end gate = output)
00000351 struct gate_node *
new_gate_node2 = new gate_node;
00000352 new_gate_node2-
>gate_ptr = new_gate;
00000353 new_gate_node2-
>next_ptr = gate_list;
00000354 gate_list =
198
new_gate_node2;
00000355
00000356 in_ptr =
new_gate_node2;
00000357 }
00000358 }
00000359 }
00000360
00000361 //Add input1 to gate fanin
00000362 struct gate_node * new_gate_node1 = new
gate_node;
00000363 new_gate_node1->gate_ptr = in_ptr-
>gate_ptr;
00000364 new_gate_node1->next_ptr = gate_ptr-
>gate_ptr->fanin_list;
00000365 gate_ptr->gate_ptr->fanin_list =
new_gate_node1;
00000366
00000367 //Make sure to not add DFF to fanout
00000368 if(strcmp(type, "DFF") != 0){
00000369 //Add gate to input1 fanout
00000370 struct gate_node * new_gate_node2
= new gate_node;
00000371 new_gate_node2->gate_ptr =
gate_ptr->gate_ptr;
00000372 new_gate_node2->next_ptr = in_ptr-
>gate_ptr->fanout_list;
00000373 in_ptr->gate_ptr->fanout_list =
new_gate_node2;
00000374 }
00000375 else{
00000376 //Add gate to DFF list
00000377 struct gate_node * new_gate_node2
= new gate_node;
00000378 new_gate_node2->gate_ptr =
gate_ptr->gate_ptr;
00000379 new_gate_node2->next_ptr =
dff_list;
00000380 dff_list = new_gate_node2;
00000381
00000382 //Add inverter pair to the DFF
input for isolation
00000383 char inv0_name[35];
00000384 strcpy(inv0_name, name);
00000385 strcat(inv0_name, "_inv_iso_0");
00000386 char inv1_name[35];
00000387 strcpy(inv1_name, name);
00000388 strcat(inv1_name, "_inv_iso_1");
00000389 struct gate * new_inv0 = new gate;
00000390 strcpy(new_inv0->name, inv0_name);
00000391 strcpy(new_inv0->type, "NOT");
00000392 new_inv0->state = 4;
00000393 new_inv0->level = -1;
00000394 new_inv0->sched = NULL;
00000395 new_inv0->fanin_list = NULL;
00000396 new_inv0->fanout_list = NULL;
00000397 struct gate * new_inv1 = new gate;
00000398 strcpy(new_inv1->name, inv1_name);
00000399 strcpy(new_inv1->type, "NOT");
00000400 new_inv1->state = 4;
00000401 new_inv1->level = -1;
00000402 new_inv1->sched = NULL;
00000403 new_inv1->fanin_list = NULL;
00000404 new_inv1->fanout_list = NULL;
00000405
00000406 //Link to gate list
00000407 struct gate_node * new_gate_node9
= new gate_node;
00000408 new_gate_node9->gate_ptr =
199
new_inv0;
00000409 new_gate_node9->next_ptr =
gate_list;
00000410 gate_list = new_gate_node9;
00000411
00000412 struct gate_node * new_gate_node3
= new gate_node;
00000413 new_gate_node3->gate_ptr =
new_inv1;
00000414 new_gate_node3->next_ptr =
gate_list;
00000415 gate_list = new_gate_node3;
00000416
00000417 //Add inv0 to input1 fanout
00000418 struct gate_node * new_gate_node4
= new gate_node;
00000419 new_gate_node4->gate_ptr =
new_inv0;
00000420 new_gate_node4->next_ptr = in_ptr-
>gate_ptr->fanout_list;
00000421 in_ptr->gate_ptr->fanout_list =
new_gate_node4;
00000422
00000423 //Add input1 to inv0 fanin
00000424 struct gate_node * new_gate_node5
= new gate_node;
00000425 new_gate_node5->gate_ptr = in_ptr-
>gate_ptr;
00000426 new_gate_node5->next_ptr =
new_inv0->fanin_list;
00000427 new_inv0->fanin_list =
new_gate_node5;
00000428
00000429 //Add inv1 to inv0 fanout
00000430 struct gate_node * new_gate_node6
= new gate_node;
00000431 new_gate_node6->gate_ptr =
new_inv1;
00000432 new_gate_node6->next_ptr =
new_inv0->fanout_list;
00000433 new_inv0->fanout_list =
new_gate_node6;
00000434
00000435 //Add inv0 to inv1 fanin
00000436 struct gate_node * new_gate_node7
= new gate_node;
00000437 new_gate_node7->gate_ptr =
new_inv0;
00000438 new_gate_node7->next_ptr =
new_inv1->fanin_list;
00000439 new_inv1->fanin_list =
new_gate_node7;
00000440
00000441 //Override DFF fanin to inv1
00000442 struct gate_node * new_gate_node8
= new gate_node;
00000443 new_gate_node8->gate_ptr =
new_inv1;
00000444 new_gate_node8->next_ptr = NULL;
00000445 gate_ptr->gate_ptr->fanin_list =
new_gate_node8;
00000446 }
00000447
00000448 prev_j = j;
00000449 if(current_line[j] != ')'){
00000450 if(current_line[j+1] == ' '){j = j
+ 2;}
00000451 else{j++;}
00000452 i=j;
200
00000453 while((current_line[j] != ',') &&
(current_line[j] != ')')){j++;}
00000454 strncpy(input1, current_line+i, j-
i);
00000455 input1[j-i] = '\0';
00000456 }
00000457
00000458 }
00000459 while(current_line[prev_j] != ')');
00000460
00000461 //Handling for NAND, NOR, BUF
00000462 if((strcmp(type, "NAND") == 0) || (strcmp(type,
"NOR") == 0) || (strcmp(type, "BUF") == 0)){
00000463 //Rename original gate to _base and
change type
00000464 char name_base[25];
00000465 strcpy(name_base, name);
00000466 strcat(name_base, "_base");
00000467 strcpy(gate_ptr->gate_ptr->name,
name_base);
00000468 if(strcmp(gate_ptr->gate_ptr->type,
"NAND") == 0){strcpy(gate_ptr->gate_ptr->type, "AND");}
00000469 if(strcmp(gate_ptr->gate_ptr->type,
"NOR") == 0){strcpy(gate_ptr->gate_ptr->type, "OR");}
00000470 if(strcmp(gate_ptr->gate_ptr->type,
"BUF") == 0){strcpy(gate_ptr->gate_ptr->type, "NOT");}
00000471
00000472 //Add an inverter to gate output to
impliment negative gate
00000473 struct gate * new_gate2 = new gate;
00000474 strcpy(new_gate2->name, name);
00000475 strcpy(new_gate2->type, "NOT");
00000476 new_gate2->state = 4;
00000477 new_gate2->level = -1;
00000478 new_gate2->sched = NULL;
00000479 new_gate2->fanin_list = NULL;
00000480 new_gate2->fanout_list = NULL;
00000481
00000482 //Update DFF fanins
00000483 struct gate_node * dff_ptr = dff_list;
00000484 while(dff_ptr != NULL){
00000485 struct gate_node * in_ptr =
dff_ptr->gate_ptr->fanin_list;
00000486 while(in_ptr != NULL){
00000487 if(strcmp(in_ptr-
>gate_ptr->name, name_base) == 0){
00000488 //Gate on fanin,
move to inv
00000489 in_ptr->gate_ptr =
new_gate2;
00000490 }
00000491 in_ptr = in_ptr->next_ptr;
00000492 }
00000493 dff_ptr = dff_ptr->next_ptr;
00000494 }
00000495
00000496 //Update all gate fanins
00000497 struct gate_node * gates_ptr = gate_list;
00000498 while(gates_ptr != NULL){
00000499 struct gate_node * in_ptr =
gates_ptr->gate_ptr->fanin_list;
00000500 while(in_ptr != NULL){
00000501 if(strcmp(in_ptr-
>gate_ptr->name, name_base) == 0){
00000502 //Gate on fanin,
move to inv
00000503 in_ptr->gate_ptr =
new_gate2;
00000504 }
201
00000505 in_ptr = in_ptr->next_ptr;
00000506 }
00000507 gates_ptr = gates_ptr->next_ptr;
00000508 }
00000509
00000510 //Link to gate list
00000511 struct gate_node * new_gate_node2 = new
gate_node;
00000512 new_gate_node2->gate_ptr = new_gate2;
00000513 new_gate_node2->next_ptr = gate_list;
00000514 gate_list = new_gate_node2;
00000515
00000516 //Add base gate to NOT fanin
00000517 struct gate_node * new_gate_node5 = new
gate_node;
00000518 new_gate_node5->gate_ptr = gate_ptr-
>gate_ptr;
00000519 new_gate_node5->next_ptr = new_gate2-
>fanin_list;
00000520 new_gate2->fanin_list = new_gate_node5;
00000521
00000522 //Move all base gate fanouts to inverter
00000523 struct gate_node * fanout_ptr = gate_ptr-
>gate_ptr->fanout_list;
00000524 while(fanout_ptr != NULL){
00000525 struct gate_node * new_gate_node7
= new gate_node;
00000526 new_gate_node7->gate_ptr =
fanout_ptr->gate_ptr;
00000527 new_gate_node7->next_ptr =
new_gate2->fanout_list;
00000528 new_gate2->fanout_list =
new_gate_node7;
00000529
00000530 fanout_ptr = fanout_ptr->next_ptr;
00000531 }
00000532
00000533 //Add NOT to base gate fanout (as only
fanout)
00000534 struct gate_node * new_gate_node6 = new
gate_node;
00000535 new_gate_node6->gate_ptr = new_gate2;
00000536 new_gate_node6->next_ptr = NULL;
00000537 gate_ptr->gate_ptr->fanout_list =
new_gate_node6;
00000538
00000539 //Scan output list for this gate
00000540 strcpy(name_base, name);
00000541 strcat(name_base, "_base");
00000542 struct gate_node * out_ptr = output_list;
00000543 while((out_ptr != NULL) &&
(strcmp(out_ptr->gate_ptr->name, name_base) != 0)){out_ptr = out_ptr->next_ptr;}
00000544 if(out_ptr != NULL){
00000545 //Found matching gate, need to
replace with new NOT gate
00000546 out_ptr->gate_ptr = new_gate2;
00000547 }
00000548 }
00000549 }
00000550 }
00000551 }
00000552 }
00000553
00000554 //Done, close V file
00000555 fclose(v_file);
00000556
00000557 //Final processing on POs
00000558 int out_cnt = 0;
00000559 struct gate_node * link_ptr = output_list;
202
00000560 while(link_ptr != NULL){
00000561 out_cnt++;
00000562 link_ptr = link_ptr->next_ptr;
00000563 }
00000564
00000565 //Add monitor circuit to check for: all POs = 1 ?
00000566 if(out_cnt > 1){
00000567 //Step 1: Create new combining gate
00000568 struct gate * final_po_gate = new gate;
00000569 strcpy(final_po_gate->name, "final_po");
00000570 strcpy(final_po_gate->type, "AND");
00000571 final_po_gate->state = 4;
00000572 final_po_gate->level = -1;
00000573 final_po_gate->sched = NULL;
00000574 final_po_gate->fanin_list = NULL;
00000575 final_po_gate->fanout_list = NULL;
00000576
00000577 struct gate_node * final_po_node = new gate_node;
00000578 final_po_node->gate_ptr = final_po_gate;
00000579 final_po_node->next_ptr = gate_list;
00000580 gate_list = final_po_node;
00000581
00000582
00000583 //Step 2: Update fanin/fanout links
00000584 link_ptr = output_list;
00000585 while(link_ptr != NULL){
00000586 //For each current output, link fanout to new gate, link output
to new gate fanin
00000587 struct gate_node * new_gate_node = new gate_node;
00000588 new_gate_node->gate_ptr = final_po_gate;
00000589 new_gate_node->next_ptr = link_ptr->gate_ptr->fanout_list;
00000590 link_ptr->gate_ptr->fanout_list = new_gate_node;
00000591
00000592 struct gate_node * new_gate_node2 = new gate_node;
00000593 new_gate_node2->gate_ptr = link_ptr->gate_ptr;
00000594 new_gate_node2->next_ptr = final_po_gate->fanin_list;
00000595 final_po_gate->fanin_list = new_gate_node2;
00000596
00000597 link_ptr = link_ptr->next_ptr;
00000598 }
00000599
00000600
00000601 //Step 3: Update output list
00000602 struct gate_node * output_po_node = new gate_node;
00000603 output_po_node->gate_ptr = final_po_gate;
00000604 output_po_node->next_ptr = NULL;
00000605 output_list = output_po_node;
00000606 }
00000607 }
00000608
00000609 //--------------------------------------------------------------------
00000610
00000611 //Level Circuit
00000612 //
00000613 int level_circuit(){
00000614 //Setup first level for inputs
00000615 struct level_node * new_level_node = new level_node;
00000616 new_level_node->level = 0;
00000617 new_level_node->gate_ptr = NULL;
00000618 new_level_node->next_ptr = level_list;
00000619 new_level_node->prev_ptr = NULL;
00000620 level_list = new_level_node;
00000621
00000622 struct level_node * level_ptr = new_level_node;
00000623
00000624 //Add all inputs to level 0
00000625 struct gate_node * in_ptr = input_list;
00000626 while(in_ptr != NULL){
00000627 //Link current input onto level
203
00000628 struct gate_node * new_gate_ptr = new gate_node;
00000629 new_gate_ptr->gate_ptr = in_ptr->gate_ptr;
00000630 new_gate_ptr->next_ptr = level_ptr->gate_ptr;
00000631 level_ptr->gate_ptr = new_gate_ptr;
00000632
00000633 in_ptr->gate_ptr->level = 0;
00000634
00000635 //Move to next input
00000636 in_ptr = in_ptr->next_ptr;
00000637 }
00000638
00000639 //Add all DFFs to level 0
00000640 struct gate_node * dff_ptr = dff_list;
00000641 while(dff_ptr != NULL){
00000642 //Link current input onto level
00000643 struct gate_node * new_gate_ptr = new gate_node;
00000644 new_gate_ptr->gate_ptr = dff_ptr->gate_ptr;
00000645 new_gate_ptr->next_ptr = level_ptr->gate_ptr;
00000646 level_ptr->gate_ptr = new_gate_ptr;
00000647
00000648 dff_ptr->gate_ptr->level = 0;
00000649
00000650 //Move to next input
00000651 dff_ptr = dff_ptr->next_ptr;
00000652 }
00000653
00000654
00000655
00000656 //For all gates on current level, check if we can level fanouts
00000657 int leveled_gates = 1;
00000658 int current_level = 1;
00000659 struct gate_node * gate_ptr = gate_list;
00000660 while(leveled_gates != 0){
00000661 //Set up next level
00000662 leveled_gates = 0;
00000663 struct level_node * new_level_node = new level_node;
00000664 new_level_node->gate_ptr = NULL;
00000665 new_level_node->level = current_level;
00000666 new_level_node->prev_ptr = level_ptr;
00000667 level_ptr->next_ptr = new_level_node;
00000668
00000669 //cout << "Working on level << current_level << endl;
00000670
00000671 //For all gates in current level
00000672 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00000673 while(gate_ptr != NULL){
00000674 //For all fanouts of current gate
00000675 struct gate_node * fanout_ptr = gate_ptr->gate_ptr->fanout_list;
00000676 while(fanout_ptr != NULL){
00000677 //Get min level of fanins
00000678 int minlevel = 999;
00000679 int maxlevel = -999;
00000680 char minex[35];
00000681 char maxex[35];
00000682 struct gate_node * fanin_ptr = fanout_ptr->gate_ptr-
>fanin_list;
00000683 while(fanin_ptr != NULL){
00000684 //Check level
00000685 if(fanin_ptr->gate_ptr->level < minlevel){
00000686 minlevel = fanin_ptr->gate_ptr->level;
00000687 strcpy(minex, fanin_ptr->gate_ptr->name);
00000688 }
00000689 if(fanin_ptr->gate_ptr->level > maxlevel){
00000690 maxlevel = fanin_ptr->gate_ptr->level;
00000691 strcpy(maxex, fanin_ptr->gate_ptr->name);
00000692 }
00000693
00000694 //Move to next fanin
00000695 fanin_ptr = fanin_ptr->next_ptr;
204
00000696 }
00000697
00000698 //Check if we can level this fanout
00000699 // MUST HAVE: No unleveled inputs && No inputs on
the current level && No level itself
00000700 if(minlevel > -1 && minlevel != current_level &&
maxlevel != current_level && fanout_ptr->gate_ptr->level == -1){
00000701 //This fanout can be leveled to current level
00000702 leveled_gates++;
00000703 fanout_ptr->gate_ptr->level = current_level;
00000704 struct gate_node * new_gate_ptr = new gate_node;
00000705 new_gate_ptr->gate_ptr = fanout_ptr->gate_ptr;
00000706 new_gate_ptr->next_ptr = new_level_node-
>gate_ptr;
00000707 new_level_node->gate_ptr = new_gate_ptr;
00000708 }
00000709
00000710 //Move to next fanout
00000711 fanout_ptr = fanout_ptr->next_ptr;
00000712 }
00000713
00000714 //Next gate in level
00000715 gate_ptr = gate_ptr->next_ptr;
00000716 }
00000717
00000718 //Move to next level
00000719 level_ptr = new_level_node;
00000720 current_level++;
00000721 }
00000722
00000723 //DEBUG: count unleveled gates
00000724 int unleveled = 0;
00000725 int total = 0;
00000726 gate_ptr = gate_list;
00000727 while(gate_ptr != NULL){
00000728 if(gate_ptr->gate_ptr->level == -1){
00000729 //cout << gate_ptr->gate_ptr->name << " ";
00000730 unleveled++;
00000731 }
00000732 total++;
00000733 gate_ptr = gate_ptr->next_ptr;
00000734 }
00000735 //cout << "\n\n";
00000736 cout << "Done (Gates leveled: " << total - unleveled << "/" << total << " | Max
level: " << current_level - 1 << ")" << endl;
00000737
00000738 return current_level-1;
00000739 }
00000740
00000741 //--------------------------------------------------------------------
00000742
00000743
00000744 //Find Level
00000745 //
00000746 int find_level(struct gate * gate_ptr){
00000747 char type[10];
00000748 strcpy(type, gate_ptr->type);
00000749 makeupper(type);
00000750
00000751 if((strcmp(type, "INPUT") == 0) || (strcmp(type, "DFF") == 0)){
00000752 return 0;
00000753 }
00000754 else{
00000755 if(strcmp(type, "NOT") == 0){
00000756 return find_level(gate_ptr->fanin_list->gate_ptr) + 1;
00000757 }
00000758 else{
00000759 int in1 = find_level(gate_ptr->fanin_list->gate_ptr);
00000760 int in2 = find_level(gate_ptr->fanin_list->next_ptr->gate_ptr);
205
00000761 if(in1 > in2){return in1 + 1;}
00000762 else{return in2 + 1;}
00000763 }
00000764 }
00000765 }
00000766
00000767 //--------------------------------------------------------------------
00000768
00000769
00000770 //Reverse lists
00000771 //
00000772 void reverse_lists(){
00000773 //Reverse input_list, output_list so they are in proper order
00000774 struct gate_node * prev_node = NULL;
00000775 while(input_list != NULL){
00000776 struct gate_node * new_node = new gate_node;
00000777 new_node->next_ptr = prev_node;
00000778 new_node->gate_ptr = input_list->gate_ptr;
00000779 prev_node = new_node;
00000780 input_list = input_list->next_ptr;
00000781 }
00000782 input_list = prev_node;
00000783
00000784 prev_node = NULL;
00000785 while(output_list != NULL){
00000786 struct gate_node * new_node = new gate_node;
00000787 new_node->next_ptr = prev_node;
00000788 new_node->gate_ptr = output_list->gate_ptr;
00000789 prev_node = new_node;
00000790 output_list = output_list->next_ptr;
00000791 }
00000792 output_list = prev_node;
00000793 }
00000794
00000795 //--------------------------------------------------------------------
00000796
00000797 //
00000798 // OUTPUT FORWARD
00000799 // Creates the forward network from loaded circuit
00000800 // and outputs to file fwd_net.v
00000801 //
00000802 void fwd_network(int max_level){
00000803 ofstream outfile;
00000804 outfile.open("fwd_net.v");
00000805
00000806 //Keep count of gates output
00000807 int fwd_num_gates = 0;
00000808
00000809 //Output module header
00000810 outfile << "module fwd_net (PI_1, PI_0, PPI_1, PPI_0, STATE_1, STATE_0, PO_1,
PO_0, PPO_1, PPO_0);\n";
00000811
00000812 outfile << "parameter n = " << fwd_po_count() << ";\n";
00000813 //cout << "po count" << endl;
00000814 outfile << "parameter m = " << fwd_pi_count() << ";\n";
00000815 //cout << "pi count" << endl;
00000816 if(fwd_ppi_count() == 0){outfile << "parameter l = 1;\n";}
00000817 else{outfile << "parameter l = " << fwd_ppi_count() << ";\n";}
00000818 //cout << "ppi count" << endl;
00000819 outfile << "parameter s = " << fwd_gate_count(max_level) + fwd_pi_count() +
fwd_ppi_count() << ";\n";
00000820 //cout << "gate count" << endl;
00000821
00000822 outfile << "input [m-1:0] PI_1;\n";
00000823 outfile << "input [m-1:0] PI_0;\n";
00000824 outfile << "input [l-1:0] PPI_1;\n";
00000825 outfile << "input [l-1:0] PPI_0;\n";
00000826 outfile << "output [s-1:0] STATE_1;\n";
00000827 outfile << "output [s-1:0] STATE_0;\n";
206
00000828 outfile << "output [n-1:0] PO_1;\n";
00000829 outfile << "output [n-1:0] PO_0;\n";
00000830 outfile << "output [l-1:0] PPO_1;\n";
00000831 outfile << "output [l-1:0] PPO_0;\n";
00000832
00000833 //Predefine wires for input array assigment
00000834 outfile << "wire " << fwd_pi_list_1() << ", " << fwd_pi_list_0();
00000835 if(fwd_ppo_list_1() != ""){
00000836 outfile << ", " << fwd_ppi_list_1() << ", " << fwd_ppi_list_0() <<
";\n";
00000837 }
00000838 else{
00000839 outfile << ";\n";
00000840 }
00000841
00000842 //Output input signal arrays
00000843 outfile << "assign {" << fwd_pi_list_1() << "} = PI_1;\n";
00000844 outfile << "assign {" << fwd_pi_list_0() << "} = PI_0;\n";
00000845 if(fwd_ppi_list_1() != ""){
00000846 outfile << "assign {" << fwd_ppi_list_1() << "} = PPI_1;\n";
00000847 outfile << "assign {" << fwd_ppi_list_0() << "} = PPI_0;\n";
00000848 }
00000849
00000850 //Go through levels and output gate equations
00000851 struct level_node * level_ptr = level_list;
00000852 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00000853 for(int i = 1; i <= max_level; i++){
00000854 //Traverse all gates on this level
00000855 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00000856 while(gate_ptr != NULL){
00000857 //Get gate from gate node
00000858 struct gate * curr_gate = gate_ptr->gate_ptr;
00000859
00000860 //Define outputs
00000861 char z1[35];
00000862 strcpy(z1, curr_gate->name);
00000863 strcat(z1, "_z1");
00000864 char z0[35];
00000865 strcpy(z0, curr_gate->name);
00000866 strcat(z0, "_z0");
00000867
00000868 if(strcmp(curr_gate->type, "AND") == 0){
00000869 //AND gate
00000870 char in1[35];
00000871 char in0[35];
00000872
00000873 //Loop though all inputs and append to equations
00000874 outfile << "wire " << z1 << " = ";
00000875 int firstrun = 1;
00000876 struct gate_node * in_ptr = curr_gate->fanin_list;
00000877 while(in_ptr != NULL){
00000878 if(firstrun == 1){
00000879 firstrun = 0;
00000880 }
00000881 else{
00000882 outfile << " & ";
00000883 }
00000884 outfile << in_ptr->gate_ptr->name;
00000885
00000886 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00000887 outfile << "_1";
00000888 }
00000889 else{
00000890 outfile << "_z1";
00000891 }
00000892
00000893 in_ptr = in_ptr->next_ptr;
00000894 }
207
00000895 outfile << ";\n";
00000896
00000897 outfile << "wire " << z0 << " = ";
00000898 firstrun = 1;
00000899 in_ptr = curr_gate->fanin_list;
00000900 while(in_ptr != NULL){
00000901 if(firstrun == 1){
00000902 firstrun = 0;
00000903 }
00000904 else{
00000905 outfile << " | ";
00000906 }
00000907 outfile << in_ptr->gate_ptr->name;
00000908
00000909 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00000910 outfile << "_0";
00000911 }
00000912 else{
00000913 outfile << "_z0";
00000914 }
00000915
00000916 in_ptr = in_ptr->next_ptr;
00000917 }
00000918 outfile << ";\n";
00000919
00000920 fwd_num_gates = fwd_num_gates + 2;
00000921 }
00000922 else if(strcmp(curr_gate->type, "OR") == 0){
00000923 //OR gate
00000924 char in1[35];
00000925 char in0[35];
00000926
00000927 //Loop though all inputs and append to equations
00000928 outfile << "wire " << z1 << " = ";
00000929 int firstrun = 1;
00000930 struct gate_node * in_ptr = curr_gate->fanin_list;
00000931 while(in_ptr != NULL){
00000932 if(firstrun == 1){
00000933 firstrun = 0;
00000934 }
00000935 else{
00000936 outfile << " | ";
00000937 }
00000938 outfile << in_ptr->gate_ptr->name;
00000939
00000940 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00000941 outfile << "_1";
00000942 }
00000943 else{
00000944 outfile << "_z1";
00000945 }
00000946
00000947 in_ptr = in_ptr->next_ptr;
00000948 }
00000949 outfile << ";\n";
00000950
00000951 outfile << "wire " << z0 << " = ";
00000952 firstrun = 1;
00000953 in_ptr = curr_gate->fanin_list;
00000954 while(in_ptr != NULL){
00000955 if(firstrun == 1){
00000956 firstrun = 0;
00000957 }
00000958 else{
00000959 outfile << " & ";
00000960 }
00000961 outfile << in_ptr->gate_ptr->name;
208
00000962
00000963 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00000964 outfile << "_0";
00000965 }
00000966 else{
00000967 outfile << "_z0";
00000968 }
00000969
00000970 in_ptr = in_ptr->next_ptr;
00000971 }
00000972 outfile << ";\n";
00000973
00000974 fwd_num_gates = fwd_num_gates + 2;
00000975 }
00000976 else if(strcmp(curr_gate->type, "NOT") == 0){
00000977 //NOT gate
00000978 char a1[35];
00000979 char a0[35];
00000980 if(strcmp(curr_gate->fanin_list->gate_ptr->type,
"INPUT") == 0){
00000981 //Input A is type INPUT
00000982 strcpy(a1, curr_gate->fanin_list->gate_ptr-
>name);
00000983 strcat(a1, "_1");
00000984 strcpy(a0, curr_gate->fanin_list->gate_ptr-
>name);
00000985 strcat(a0, "_0");
00000986 }
00000987 else{
00000988 //Input A is type GATE
00000989 strcpy(a1, curr_gate->fanin_list->gate_ptr-
>name);
00000990 strcat(a1, "_z1");
00000991 strcpy(a0, curr_gate->fanin_list->gate_ptr-
>name);
00000992 strcat(a0, "_z0");
00000993 }
00000994
00000995 //Output equations
00000996 outfile << "wire " << z1 << " = " << a0 << ";\n";
00000997 outfile << "wire " << z0 << " = " << a1 << ";\n";
00000998 }
00000999 else if(strcmp(curr_gate->type, "XOR") == 0){
00001000 //XOR gate
00001001 char a1[35];
00001002 char a0[35];
00001003 char b1[35];
00001004 char b0[35];
00001005
00001006 if(strcmp(curr_gate->fanin_list->gate_ptr->type,
"INPUT") == 0){
00001007 strcpy(a1, curr_gate->fanin_list->gate_ptr-
>name);
00001008 strcat(a1, "_1");
00001009 strcpy(a0, curr_gate->fanin_list->gate_ptr-
>name);
00001010 strcat(a0, "_0");
00001011 }
00001012 else{
00001013 strcpy(a1, curr_gate->fanin_list->gate_ptr-
>name);
00001014 strcat(a1, "_z1");
00001015 strcpy(a0, curr_gate->fanin_list->gate_ptr-
>name);
00001016 strcat(a0, "_z0");
00001017 }
00001018
00001019 if(strcmp(curr_gate->fanin_list->next_ptr->gate_ptr-
209
>type, "INPUT") == 0){
00001020 strcpy(b1, curr_gate->fanin_list->next_ptr-
>gate_ptr->name);
00001021 strcat(b1, "_1");
00001022 strcpy(b0, curr_gate->fanin_list->next_ptr-
>gate_ptr->name);
00001023 strcat(b0, "_0");
00001024 }
00001025 else{
00001026 strcpy(b1, curr_gate->fanin_list->next_ptr-
>gate_ptr->name);
00001027 strcat(b1, "_z1");
00001028 strcpy(b0, curr_gate->fanin_list->next_ptr-
>gate_ptr->name);
00001029 strcat(b0, "_z0");
00001030 }
00001031
00001032 outfile << "wire " << z1 << " = " << "((" << a1 << " & "
<< a0 << ") | (" << b1 << " & " << b0 << ")) | (" << a1 << " ^ " << b1 << ");\n";
00001033 outfile << "wire " << z0 << " = " << "((" << a1 << " & "
<< a0 << ") | (" << b1 << " & " << b0 << ")) | !(" << a1 << " ^ " << b1 << ");\n";
00001034 }
00001035
00001036 gate_ptr = gate_ptr->next_ptr;
00001037 }
00001038 level_ptr = level_ptr->next_ptr;
00001039 }
00001040
00001041 //Output output signal array
00001042 outfile << "assign STATE_1 = {" << fwd_state_list_1(max_level) << "};\n";
00001043 outfile << "assign STATE_0 = {" << fwd_state_list_0(max_level) << "};\n";
00001044 outfile << "assign PO_1 = {" << fwd_po_list_1() << "};\n";
00001045 outfile << "assign PO_0 = {" << fwd_po_list_0() << "};\n";
00001046 if(fwd_ppo_list_1() != ""){
00001047 outfile << "assign PPO_1 = {" << fwd_ppo_list_1() << "};\n";
00001048 outfile << "assign PPO_0 = {" << fwd_ppo_list_0() << "};\n";
00001049 }
00001050
00001051 outfile << "endmodule\n\n";
00001052
00001053 //Insert gate stats into network as comments
00001054 outfile << "//--- GATE STATISTICS ---\n";
00001055 outfile << "//Original Circuit: " << fwd_gate_count(max_level) << "\n";
00001056 outfile << "//Forward Network: " << fwd_num_gates << "\n";
00001057
00001058 outfile.close();
00001059
00001060 //Output gate stats
00001061 cout << "--- GATE STATISTICS ---" << endl;
00001062 cout << "Original Circuit: " << fwd_gate_count(max_level) << endl;
00001063 cout << "Forward Network: " << fwd_num_gates << endl;
00001064 }
00001065
00001066 //--------------------------------------------------------------------
00001067
00001068 //
00001069 //FORWARD PI LIST
00001070 // Returns a list of PIs to the forward network
00001071 //
00001072 string fwd_pi_list_1(){
00001073 //Form input list string
00001074 string input_list_str = "";
00001075 int first_run = 0;
00001076
00001077 //Traverse input list
00001078 struct gate_node * input_ptr = input_list;
00001079 while(input_ptr != NULL){
00001080 //Get current input name
00001081 char curr_input[35];
210
00001082 strcpy(curr_input, input_ptr->gate_ptr->name);
00001083
00001084 string inputstr = "";
00001085 if(first_run == 0){
00001086 inputstr = strcat(curr_input, "_1");
00001087 first_run = 1;
00001088 }
00001089 else{
00001090 strcpy(curr_input, ", ");
00001091 strcat(curr_input, input_ptr->gate_ptr->name);
00001092 inputstr = strcat(curr_input, "_1");
00001093 }
00001094 input_list_str = input_list_str + inputstr;
00001095
00001096 input_ptr = input_ptr->next_ptr;
00001097 }
00001098
00001099
00001100 return input_list_str;
00001101 }
00001102
00001103 //--------------------------------------------------------------------
00001104
00001105 //
00001106 //FORWARD PI LIST
00001107 // Returns a list of PIs to the forward network
00001108 //
00001109 string fwd_pi_list_0(){
00001110 //Form input list string
00001111 string input_list_str = "";
00001112 int first_run = 0;
00001113
00001114 //Traverse input list
00001115 struct gate_node * input_ptr = input_list;
00001116 while(input_ptr != NULL){
00001117 //Get current input name
00001118 char curr_input[35];
00001119 strcpy(curr_input, input_ptr->gate_ptr->name);
00001120
00001121 string inputstr = "";
00001122 if(first_run == 0){
00001123 inputstr = strcat(curr_input, "_0");
00001124 first_run = 1;
00001125 }
00001126 else{
00001127 strcpy(curr_input, ", ");
00001128 strcat(curr_input, input_ptr->gate_ptr->name);
00001129 inputstr = strcat(curr_input, "_0");
00001130 }
00001131 input_list_str = input_list_str + inputstr;
00001132
00001133 input_ptr = input_ptr->next_ptr;
00001134 }
00001135
00001136
00001137 return input_list_str;
00001138 }
00001139
00001140 //--------------------------------------------------------------------
00001141
00001142 //
00001143 //FORWARD PI COUNT
00001144 // Returns the number of PIs in the forward network
00001145 //
00001146 int fwd_pi_count(){
00001147 //Traverse input list
00001148 int count = 0;
00001149 struct gate_node * input_ptr = input_list;
00001150 while(input_ptr != NULL){
211
00001151 count++;
00001152 input_ptr = input_ptr->next_ptr;
00001153 }
00001154
00001155 return count;
00001156 }
00001157
00001158 //--------------------------------------------------------------------
00001159
00001160 string fwd_ppi_list_1(){
00001161 //Get PPI list from DFF list (ppis are dff outputs)
00001162 string ppi_list_str = "";
00001163 int first_run = 0;
00001164
00001165 //Traverse dff list
00001166 struct gate_node * ppi_ptr = dff_list;
00001167 while(ppi_ptr != NULL){
00001168 //Get current dff name
00001169 char curr_ppi[35];
00001170 strcpy(curr_ppi, ppi_ptr->gate_ptr->name);
00001171
00001172 string ppistr = "";
00001173 if(first_run == 0){
00001174 ppistr = strcat(curr_ppi, "_z1");
00001175 first_run = 1;
00001176 }
00001177 else{
00001178 strcpy(curr_ppi, ", ");
00001179 strcat(curr_ppi, ppi_ptr->gate_ptr->name);
00001180 ppistr = strcat(curr_ppi, "_z1");
00001181 }
00001182 ppi_list_str = ppi_list_str + ppistr;
00001183
00001184 ppi_ptr = ppi_ptr->next_ptr;
00001185 }
00001186
00001187 return ppi_list_str;
00001188 }
00001189
00001190 //--------------------------------------------------------------------
00001191
00001192 string fwd_ppi_list_0(){
00001193 //Get PPI list from DFF list (ppis are dff outputs)
00001194 string ppi_list_str = "";
00001195 int first_run = 0;
00001196
00001197 //Traverse dff list
00001198 struct gate_node * ppi_ptr = dff_list;
00001199 while(ppi_ptr != NULL){
00001200 //Get current dff name
00001201 char curr_ppi[35];
00001202 strcpy(curr_ppi, ppi_ptr->gate_ptr->name);
00001203
00001204 string ppistr = "";
00001205 if(first_run == 0){
00001206 ppistr = strcat(curr_ppi, "_z0");
00001207 first_run = 1;
00001208 }
00001209 else{
00001210 strcpy(curr_ppi, ", ");
00001211 strcat(curr_ppi, ppi_ptr->gate_ptr->name);
00001212 ppistr = strcat(curr_ppi, "_z0");
00001213 }
00001214 ppi_list_str = ppi_list_str + ppistr;
00001215
00001216 ppi_ptr = ppi_ptr->next_ptr;
00001217 }
00001218
00001219 return ppi_list_str;
212
00001220 }
00001221
00001222 //--------------------------------------------------------------------
00001223
00001224 int fwd_ppi_count(){
00001225 //Num of ppis = number of DFFs
00001226 int count = 0;
00001227 struct gate_node * ppi_ptr = dff_list;
00001228 while(ppi_ptr != NULL){
00001229 count++;
00001230 ppi_ptr = ppi_ptr->next_ptr;
00001231 }
00001232
00001233 return count;
00001234 }
00001235
00001236 //--------------------------------------------------------------------
00001237
00001238 string fwd_state_list_1(int max_level){
00001239 //Form output list string
00001240 string output_list_str = "";
00001241 int first_run = 0;
00001242
00001243 //Add inputs to state list
00001244 //Traverse input list
00001245 struct gate_node * input_ptr = input_list;
00001246 while(input_ptr != NULL){
00001247 //Get current input name
00001248 char curr_input[35];
00001249 strcpy(curr_input, input_ptr->gate_ptr->name);
00001250
00001251 string inputstr = "";
00001252 if(first_run == 0){
00001253 inputstr = strcat(curr_input, "_1");
00001254 first_run = 1;
00001255 }
00001256 else{
00001257 strcpy(curr_input, ", ");
00001258 strcat(curr_input, input_ptr->gate_ptr->name);
00001259 inputstr = strcat(curr_input, "_1");
00001260 }
00001261 output_list_str = output_list_str + inputstr;
00001262
00001263 input_ptr = input_ptr->next_ptr;
00001264 }
00001265
00001266 //Add ppis to state list
00001267 //Traverse dff list
00001268 gate_node * ppi_ptr = dff_list;
00001269 while(ppi_ptr != NULL){
00001270 //Get current dff name
00001271 char curr_ppi[35];
00001272 strcpy(curr_ppi, ppi_ptr->gate_ptr->name);
00001273
00001274 string ppistr = "";
00001275 if(first_run == 0){
00001276 ppistr = strcat(curr_ppi, "_z1");
00001277 first_run = 1;
00001278 }
00001279 else{
00001280 strcpy(curr_ppi, ", ");
00001281 strcat(curr_ppi, ppi_ptr->gate_ptr->name);
00001282 ppistr = strcat(curr_ppi, "_z1");
00001283 }
00001284 output_list_str = output_list_str + ppistr;
00001285
00001286 ppi_ptr = ppi_ptr->next_ptr;
00001287 }
00001288
213
00001289 //Traverse all gates and output state (outputs)
00001290 struct level_node * level_ptr = level_list;
00001291 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00001292 for(int i = 1; i < max_level; i++){
00001293 //Traverse all gates on this level
00001294 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00001295 while(gate_ptr != NULL){
00001296 //Get gate from gate node
00001297 struct gate * curr_gate = gate_ptr->gate_ptr;
00001298
00001299 //Define outputs
00001300 char z1[35];
00001301 string z1_str = "";
00001302 if(first_run == 0){
00001303 strcpy(z1, curr_gate->name);
00001304 z1_str = strcat(z1, "_z1");
00001305 first_run = 1;
00001306 }
00001307 else{
00001308 strcpy(z1, ", ");
00001309 strcat(z1, curr_gate->name);
00001310 z1_str = strcat(z1, "_z1");
00001311 }
00001312 output_list_str = output_list_str + z1_str;
00001313
00001314 gate_ptr = gate_ptr->next_ptr;
00001315 }
00001316 level_ptr = level_ptr->next_ptr;
00001317 }
00001318
00001319 //Add outputs to state list
00001320 //Traverse output list
00001321 /*gate_node * output_ptr = output_list;
00001322 while(output_ptr != NULL){
00001323 //Get current output name
00001324 char curr_output[20];
00001325 strcpy(curr_output, output_ptr->gate_ptr->name);
00001326
00001327 string outputstr = "";
00001328 if(first_run == 0){
00001329 outputstr = strcat(curr_output, "_z1");
00001330 first_run = 1;
00001331 }
00001332 else{
00001333 strcpy(curr_output, ", ");
00001334 strcat(curr_output, output_ptr->gate_ptr->name);
00001335 outputstr = strcat(curr_output, "_z1");
00001336 }
00001337 output_list_str = output_list_str + outputstr;
00001338
00001339 output_ptr = output_ptr->next_ptr;
00001340 }*/
00001341
00001342 return output_list_str;
00001343 }
00001344
00001345 //--------------------------------------------------------------------
00001346
00001347 string fwd_state_list_0(int max_level){
00001348 //Form output list string
00001349 string output_list_str = "";
00001350 int first_run = 0;
00001351
00001352 //Traverse input list
00001353 struct gate_node * input_ptr = input_list;
00001354 while(input_ptr != NULL){
00001355 //Get current input name
00001356 char curr_input[35];
00001357 strcpy(curr_input, input_ptr->gate_ptr->name);
214
00001358
00001359 string inputstr = "";
00001360 if(first_run == 0){
00001361 inputstr = strcat(curr_input, "_0");
00001362 first_run = 1;
00001363 }
00001364 else{
00001365 strcpy(curr_input, ", ");
00001366 strcat(curr_input, input_ptr->gate_ptr->name);
00001367 inputstr = strcat(curr_input, "_0");
00001368 }
00001369 output_list_str = output_list_str + inputstr;
00001370
00001371 input_ptr = input_ptr->next_ptr;
00001372 }
00001373
00001374 //Add ppis to state list
00001375 //Traverse dff list
00001376 gate_node * ppi_ptr = dff_list;
00001377 while(ppi_ptr != NULL){
00001378 //Get current dff name
00001379 char curr_ppi[35];
00001380 strcpy(curr_ppi, ppi_ptr->gate_ptr->name);
00001381
00001382 string ppistr = "";
00001383 if(first_run == 0){
00001384 ppistr = strcat(curr_ppi, "_z0");
00001385 first_run = 1;
00001386 }
00001387 else{
00001388 strcpy(curr_ppi, ", ");
00001389 strcat(curr_ppi, ppi_ptr->gate_ptr->name);
00001390 ppistr = strcat(curr_ppi, "_z0");
00001391 }
00001392 output_list_str = output_list_str + ppistr;
00001393
00001394 ppi_ptr = ppi_ptr->next_ptr;
00001395 }
00001396
00001397 //Traverse all gates and output state (outputs)
00001398 struct level_node * level_ptr = level_list;
00001399 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00001400 for(int i = 1; i < max_level; i++){
00001401 //Traverse all gates on this level
00001402 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00001403 while(gate_ptr != NULL){
00001404 //Get gate from gate node
00001405 struct gate * curr_gate = gate_ptr->gate_ptr;
00001406
00001407 //Define outputs
00001408 char z0[35];
00001409 string z0_str = "";
00001410 if(first_run == 0){
00001411 strcpy(z0, curr_gate->name);
00001412 z0_str = strcat(z0, "_z0");
00001413 first_run = 1;
00001414 }
00001415 else{
00001416 strcpy(z0, ", ");
00001417 strcat(z0, curr_gate->name);
00001418 z0_str = strcat(z0, "_z0");
00001419 }
00001420 output_list_str = output_list_str + z0_str;
00001421
00001422 gate_ptr = gate_ptr->next_ptr;
00001423 }
00001424 level_ptr = level_ptr->next_ptr;
00001425 }
00001426
215
00001427 //Add outputs to state list
00001428 //Traverse output list
00001429 /*gate_node * output_ptr = output_list;
00001430 while(output_ptr != NULL){
00001431 //Get current output name
00001432 char curr_output[20];
00001433 strcpy(curr_output, output_ptr->gate_ptr->name);
00001434
00001435 string outputstr = "";
00001436 if(first_run == 0){
00001437 outputstr = strcat(curr_output, "_z0");
00001438 first_run = 1;
00001439 }
00001440 else{
00001441 strcpy(curr_output, ", ");
00001442 strcat(curr_output, output_ptr->gate_ptr->name);
00001443 outputstr = strcat(curr_output, "_z0");
00001444 }
00001445 output_list_str = output_list_str + outputstr;
00001446
00001447 output_ptr = output_ptr->next_ptr;
00001448 }*/
00001449
00001450 return output_list_str;
00001451 }
00001452
00001453 //--------------------------------------------------------------------
00001454
00001455 string fwd_wire_list_1(int max_level){
00001456 //Form output list string
00001457 string output_list_str = "";
00001458 int first_run = 0;
00001459
00001460 //Traverse all gates and output state (outputs)
00001461 struct level_node * level_ptr = level_list;
00001462 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00001463 for(int i = 1; i <= max_level; i++){
00001464 //Traverse all gates on this level
00001465 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00001466 while(gate_ptr != NULL){
00001467 //Get gate from gate node
00001468 struct gate * curr_gate = gate_ptr->gate_ptr;
00001469
00001470 //Define outputs
00001471 char z0[35];
00001472 string z0_str = "";
00001473 if(first_run == 0){
00001474 strcpy(z0, curr_gate->name);
00001475 z0_str = strcat(z0, "_z1");
00001476 first_run = 1;
00001477 }
00001478 else{
00001479 strcpy(z0, ", ");
00001480 strcat(z0, curr_gate->name);
00001481 z0_str = strcat(z0, "_z1");
00001482 }
00001483 output_list_str = output_list_str + z0_str;
00001484
00001485 gate_ptr = gate_ptr->next_ptr;
00001486 }
00001487 level_ptr = level_ptr->next_ptr;
00001488 }
00001489
00001490 return output_list_str;
00001491 }
00001492
00001493 //--------------------------------------------------------------------
00001494
00001495 string fwd_wire_list_0(int max_level){
216
00001496 //Form output list string
00001497 string output_list_str = "";
00001498 int first_run = 0;
00001499
00001500 //Traverse all gates and output state (outputs)
00001501 struct level_node * level_ptr = level_list;
00001502 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00001503 for(int i = 1; i <= max_level; i++){
00001504 //Traverse all gates on this level
00001505 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00001506 while(gate_ptr != NULL){
00001507 //Get gate from gate node
00001508 struct gate * curr_gate = gate_ptr->gate_ptr;
00001509
00001510 //Define outputs
00001511 char z0[35];
00001512 string z0_str = "";
00001513 if(first_run == 0){
00001514 strcpy(z0, curr_gate->name);
00001515 z0_str = strcat(z0, "_z0");
00001516 first_run = 1;
00001517 }
00001518 else{
00001519 strcpy(z0, ", ");
00001520 strcat(z0, curr_gate->name);
00001521 z0_str = strcat(z0, "_z0");
00001522 }
00001523 output_list_str = output_list_str + z0_str;
00001524
00001525 gate_ptr = gate_ptr->next_ptr;
00001526 }
00001527 level_ptr = level_ptr->next_ptr;
00001528 }
00001529
00001530 return output_list_str;
00001531 }
00001532
00001533 //--------------------------------------------------------------------
00001534
00001535 int fwd_gate_count(int max_level){
00001536 //Traverse all gates and output state (outputs)
00001537 struct level_node * level_ptr = level_list;
00001538 int count = 0;
00001539 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00001540 for(int i = 1; i <= max_level; i++){
00001541 //Traverse all gates on this level
00001542 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00001543 while(gate_ptr != NULL){
00001544 count++;
00001545 gate_ptr = gate_ptr->next_ptr;
00001546 }
00001547 level_ptr = level_ptr->next_ptr;
00001548 }
00001549
00001550 return count;
00001551 }
00001552
00001553 //--------------------------------------------------------------------
00001554
00001555 string fwd_po_list_1(){
00001556 //Form output list string
00001557 string output_list_str = "";
00001558 int first_run = 0;
00001559
00001560 //Traverse output list
00001561 struct gate_node * output_ptr = output_list;
00001562 while(output_ptr != NULL){
00001563 //Get current output name
00001564 char curr_output[35];
217
00001565 strcpy(curr_output, output_ptr->gate_ptr->name);
00001566
00001567 string outputstr = "";
00001568 if(first_run == 0){
00001569 outputstr = strcat(curr_output, "_z1");
00001570 first_run = 1;
00001571 }
00001572 else{
00001573 strcpy(curr_output, ", ");
00001574 strcat(curr_output, output_ptr->gate_ptr->name);
00001575 outputstr = strcat(curr_output, "_z1");
00001576 }
00001577 output_list_str = output_list_str + outputstr;
00001578
00001579 output_ptr = output_ptr->next_ptr;
00001580 }
00001581
00001582 return output_list_str;
00001583 }
00001584
00001585 //--------------------------------------------------------------------
00001586
00001587 string fwd_po_list_0(){
00001588 //Form output list string
00001589 string output_list_str = "";
00001590 int first_run = 0;
00001591
00001592 //Traverse output list
00001593 struct gate_node * output_ptr = output_list;
00001594 while(output_ptr != NULL){
00001595 //Get current output name
00001596 char curr_output[35];
00001597 strcpy(curr_output, output_ptr->gate_ptr->name);
00001598
00001599 string outputstr = "";
00001600 if(first_run == 0){
00001601 outputstr = strcat(curr_output, "_z0");
00001602 first_run = 1;
00001603 }
00001604 else{
00001605 strcpy(curr_output, ", ");
00001606 strcat(curr_output, output_ptr->gate_ptr->name);
00001607 outputstr = strcat(curr_output, "_z0");
00001608 }
00001609 output_list_str = output_list_str + outputstr;
00001610
00001611 output_ptr = output_ptr->next_ptr;
00001612 }
00001613
00001614 return output_list_str;
00001615 }
00001616
00001617 //--------------------------------------------------------------------
00001618
00001619 int fwd_po_count(){
00001620 //Traverse output list
00001621 struct gate_node * output_ptr = output_list;
00001622 int count = 0;
00001623 while(output_ptr != NULL){
00001624 count++;
00001625 output_ptr = output_ptr->next_ptr;
00001626 }
00001627
00001628 return count;
00001629 }
00001630
00001631 //--------------------------------------------------------------------
00001632
00001633 string fwd_ppo_list_1(){
218
00001634 //Output ppo list from DFF list (dff inputs)
00001635 string ppo_list_str = "";
00001636 int first_run = 0;
00001637
00001638 //Traverse dff list
00001639 struct gate_node * ppo_ptr = dff_list;
00001640 while(ppo_ptr != NULL){
00001641 //Get current dff name
00001642 char curr_ppo[35];
00001643 strcpy(curr_ppo, ppo_ptr->gate_ptr->fanin_list->gate_ptr->name);
00001644
00001645 string ppostr = "";
00001646 if(first_run == 0){
00001647 ppostr = strcat(curr_ppo, "_z1");
00001648 first_run = 1;
00001649 }
00001650 else{
00001651 strcpy(curr_ppo, ", ");
00001652 strcat(curr_ppo, ppo_ptr->gate_ptr->fanin_list->gate_ptr->name);
00001653 ppostr = strcat(curr_ppo, "_z1");
00001654 }
00001655 ppo_list_str = ppo_list_str + ppostr;
00001656
00001657 ppo_ptr = ppo_ptr->next_ptr;
00001658 }
00001659
00001660 return ppo_list_str;
00001661 }
00001662
00001663 //--------------------------------------------------------------------
00001664
00001665 string fwd_ppo_list_0(){
00001666 //Output ppo list from DFF list (dff inputs)
00001667 string ppo_list_str = "";
00001668 int first_run = 0;
00001669
00001670 //Traverse dff list
00001671 struct gate_node * ppo_ptr = dff_list;
00001672 while(ppo_ptr != NULL){
00001673 //Get current dff name
00001674 char curr_ppo[35];
00001675 strcpy(curr_ppo, ppo_ptr->gate_ptr->fanin_list->gate_ptr->name);
00001676
00001677 string ppostr = "";
00001678 if(first_run == 0){
00001679 ppostr = strcat(curr_ppo, "_z0");
00001680 first_run = 1;
00001681 }
00001682 else{
00001683 strcpy(curr_ppo, ", ");
00001684 strcat(curr_ppo, ppo_ptr->gate_ptr->fanin_list->gate_ptr->name);
00001685 ppostr = strcat(curr_ppo, "_z0");
00001686 }
00001687 ppo_list_str = ppo_list_str + ppostr;
00001688
00001689 ppo_ptr = ppo_ptr->next_ptr;
00001690 }
00001691
00001692 return ppo_list_str;
00001693 }
00001694
00001695 //--------------------------------------------------------------------
00001696
00001697 int fwd_ppo_count(){
00001698 //Output number of PPOs = num of DFFs
00001699 int count = 0;
00001700 struct gate_node * ppo_ptr = dff_list;
00001701 while(ppo_ptr != NULL){
00001702 count++;
219
00001703 ppo_ptr = ppo_ptr->next_ptr;
00001704 }
00001705
00001706 return count;
00001707 }
00001708
00001709 //--------------------------------------------------------------------
00001710
00001711 // Backwards network
00001712 //
00001713 void back_network(int max_level){
00001714 ofstream outfile;
00001715 outfile.open("back_net.v");
00001716
00001717 //Keep count of gates in backwards net
00001718 int back_num_gates = 0;
00001719
00001720 //Output module header
00001721 outfile << "module back_net (priority_reset, PO_1, PO_0, PPO_1, PPO_0, STATE_1,
STATE_0, PI_1, PI_0, PPI_1, PPI_0);\n";
00001722
00001723 outfile << "parameter n = " << fwd_po_count() << ";\n";
00001724 outfile << "parameter m = " << fwd_pi_count() << ";\n";
00001725 if(fwd_ppi_count() == 0){
00001726 outfile << "parameter l = 1;\n";
00001727 }
00001728 else{
00001729 outfile << "parameter l = " << fwd_ppi_count() << ";\n";
00001730 }
00001731 outfile << "parameter s = " << fwd_gate_count(max_level) + fwd_pi_count() +
fwd_ppi_count() << ";\n";
00001732
00001733 outfile << "input priority_reset;\n";
00001734 outfile << "input [n-1:0] PO_1;\n";
00001735 outfile << "input [n-1:0] PO_0;\n";
00001736 outfile << "input [l-1:0] PPO_1;\n";
00001737 outfile << "input [l-1:0] PPO_0;\n";
00001738 outfile << "input [s-1:0] STATE_1;\n";
00001739 outfile << "input [s-1:0] STATE_0;\n";
00001740 outfile << "output [m-1:0] PI_1;\n";
00001741 outfile << "output [m-1:0] PI_0;\n";
00001742 outfile << "output [l-1:0] PPI_1;\n";
00001743 outfile << "output [l-1:0] PPI_0;\n";
00001744
00001745 //Predefine wires for input array mapping
00001746 outfile << "wire " << back_po_list_1() << ", " << back_po_list_0() << ", " <<
back_state_list_1(max_level) << ", " << back_state_list_0(max_level);
00001747 if(back_ppi_list_1() != ""){outfile << ", " << back_ppo_list_1() << ", " <<
back_ppo_list_0() << ";\n";}
00001748 else{outfile << ";\n";}
00001749
00001750 //Assign input arrays to wires
00001751 outfile << "assign {" << back_po_list_1() << "} = PO_1;\n";
00001752 outfile << "assign {" << back_po_list_0() << "} = PO_0;\n";
00001753 if(back_ppo_list_1() != ""){
00001754 outfile << "assign {" << back_ppo_list_1() << "} = PPO_1;\n";
00001755 outfile << "assign {" << back_ppo_list_0() << "} = PPO_0;\n";
00001756 }
00001757 outfile << "assign {" << back_state_list_1(max_level) << "} = STATE_1;\n";
00001758 outfile << "assign {" << back_state_list_0(max_level) << "} = STATE_0;\n";
00001759
00001760 //Set up matricies for branch handling
00001761 int output_array_size = fwd_gate_count(max_level) + fwd_pi_count() +
fwd_ppi_count();
00001762 char output_name[output_array_size][35];
00001763 int output_count[output_array_size];
00001764 for(int i = 0; i < output_array_size; i++){
00001765 strcpy(output_name[i], "");
00001766 output_count[i] = 0;
220
00001767 }
00001768
00001769 //Instert PPOs into output list to handle PPO branches
00001770 int i = 0;
00001771 struct gate_node * ppo_ptr = dff_list;
00001772 while(ppo_ptr != NULL){
00001773 //Scan for this gate
00001774 int k = 0;
00001775 while(k < output_array_size && strcmp(output_name[k], ppo_ptr-
>gate_ptr->fanin_list->gate_ptr->name) != 0){
00001776 k++;
00001777 }
00001778 if(k == output_array_size) {
00001779 //PPO is unique, insert
00001780 strcpy(output_name[i], ppo_ptr->gate_ptr->fanin_list->gate_ptr-
>name);
00001781 output_count[i]++;
00001782 i++;
00001783 } else {
00001784 //PPO already used, incr use count
00001785 output_count[k]++;
00001786 }
00001787
00001788 ppo_ptr = ppo_ptr->next_ptr;
00001789 }
00001790
00001791 //Insert POs into output list to handle PO branches
00001792 // NOTE: To accomodate the priority encoder generation used, we must equate PO
and PO_1
00001793 i = 0;
00001794 struct gate_node * po_ptr = output_list;
00001795 while(po_ptr != NULL){
00001796 //Get current PO name
00001797 strcpy(output_name[i], po_ptr->gate_ptr->name);
00001798 output_count[i]++;
00001799 i++;
00001800
00001801 outfile << "wire " << po_ptr->gate_ptr->name << "_zo1_1 = " << po_ptr-
>gate_ptr->name << "_zo1;\n";
00001802 outfile << "wire " << po_ptr->gate_ptr->name << "_zo0_1 = " << po_ptr-
>gate_ptr->name << "_zo0;\n";
00001803
00001804 po_ptr = po_ptr->next_ptr;
00001805 }
00001806
00001807 //For all Dual PO/PPOs, output merging equations
00001808 // NOTE: This may be obsolete due to the new handling for fanouts
00001809 po_ptr = output_list;
00001810 while(po_ptr != NULL){
00001811 //Check PPOs to see if this PO is dual
00001812 struct gate_node * ppo_ptr = dff_list;
00001813 while(ppo_ptr != NULL){
00001814 if(strcmp(po_ptr->gate_ptr->name, ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name) == 0){
00001815 //Match found, output merging equations
00001816 char output1[35];
00001817 strcpy(output1, po_ptr->gate_ptr->name);
00001818 strcat(output1, "_zo1");
00001819 char output0[35];
00001820 strcpy(output0, po_ptr->gate_ptr->name);
00001821 strcat(output0, "_zo0");
00001822 char inputa_1[35];
00001823 strcpy(inputa_1, po_ptr->gate_ptr->name);
00001824 strcat(inputa_1, "_zo1_po");
00001825 char inputa_0[35];
00001826 strcpy(inputa_0, po_ptr->gate_ptr->name);
00001827 strcat(inputa_0, "_zo0_po");
00001828 char inputb_1[35];
00001829 strcpy(inputb_1, po_ptr->gate_ptr->name);
221
00001830 strcat(inputb_1, "_zo1_ppo");
00001831 char inputb_0[35];
00001832 strcpy(inputb_0, po_ptr->gate_ptr->name);
00001833 strcat(inputb_0, "_zo0_ppo");
00001834
00001835 outfile << "wire " << output1 << " = (" << inputa_1 << "
| " << inputb_1 << ") & ~((" << inputa_1 << " & " << inputb_1 << ") & (" << inputa_0 << " ^ "
<< inputb_0 << "));\n";
00001836 outfile << "wire " << output0 << " = (" << inputa_1 << "
& " << inputa_0 << ") | (" << inputb_1 << " & " << inputb_0 << ");\n";
00001837 }
00001838 ppo_ptr = ppo_ptr->next_ptr;
00001839 }
00001840 po_ptr = po_ptr->next_ptr;
00001841 }
00001842
00001843
00001844 //Traverse to end of level list
00001845 struct level_node * level_ptr = level_list;
00001846 while(level_ptr->level < max_level){level_ptr = level_ptr->next_ptr;}
00001847
00001848 //Go through levels in reverse and output gate equations
00001849 for(int i = max_level; i > 0; i--){
00001850 //Traverse all gates on this level
00001851 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00001852 while(gate_ptr != NULL){
00001853 //Get gate from gate node
00001854 struct gate * curr_gate = gate_ptr->gate_ptr;
00001855
00001856 //Define Z wires
00001857 char z1[35];
00001858 char z0[35];
00001859 strcpy(z1, curr_gate->name);
00001860 strcat(z1, "_z1");
00001861 strcpy(z0, curr_gate->name);
00001862 strcat(z0, "_z0");
00001863 char zo1[35];
00001864 char zo0[35];
00001865 //Scan for this gate
00001866 int k = 0;
00001867 while(k < output_array_size && strcmp(output_name[k], curr_gate-
>name) != 0){
00001868 k++;
00001869 }
00001870 if(k == output_array_size || output_count[k] == 1){
00001871 //Gate not found or is single, output as is
00001872 strcpy(zo1, curr_gate->name);
00001873 strcat(zo1, "_zo1");
00001874 strcpy(zo0, curr_gate->name);
00001875 strcat(zo0, "_zo0");
00001876 }
00001877 else{
00001878 //Gate found, output with subscript
00001879 char output_num[35];
00001880 sprintf(output_num, "%i", output_count[k]);
00001881 strcpy(zo1, curr_gate->name);
00001882 strcat(zo1, "_zo1_");
00001883 strcat(zo1, output_num);
00001884 strcpy(zo0, curr_gate->name);
00001885 strcat(zo0, "_zo0_");
00001886 strcat(zo0, output_num);
00001887
00001888 //-------------------------------------
00001889 // Output priority encoder to merge zo
00001890 //-------------------------------------
00001891
00001892 //Predefine output wires from blocking gates
00001893 for(int a = 0; a < output_count[k]; a++){
00001894 outfile << "reg " << curr_gate->name <<
222
"_priority_" << a << ";\n";
00001895 }
00001896 outfile << "reg " << curr_gate->name <<
"_priority_last_reset;\n";
00001897
00001898 //Generate trigger list for priority encoder
00001899 outfile << "always @(priority_reset, ";
00001900 int firstrun = 1;
00001901 for(int a = 0; a < output_count[k]; a++){
00001902 if(strcmp(curr_gate->type, "INPUT") == 0){
00001903 for(int b = 0; b < output_count[k]; b++){
00001904 if(firstrun == 1){
00001905 firstrun = 0;
00001906 }
00001907 else{
00001908 outfile << ", ";
00001909 }
00001910
00001911 if(a == b){
00001912 outfile << curr_gate->name
<< "_o1_" << b;
00001913 }
00001914 else{
00001915 outfile << curr_gate->name
<< "_priority_" << b;
00001916 }
00001917 }
00001918 }
00001919 else{
00001920 for(int b = 0; b < output_count[k]; b++){
00001921 if(firstrun == 1){
00001922 firstrun = 0;
00001923 if(a == b){
00001924 outfile <<
curr_gate->name << "_zo1";
00001925 }
00001926 else{
00001927 outfile <<
curr_gate->name << "_priority_" << b;
00001928 }
00001929 }
00001930 else{
00001931 outfile << ", ";
00001932 if(a == b){
00001933 outfile <<
curr_gate->name << "_zo1_" << b;
00001934 }
00001935 else{
00001936 outfile <<
curr_gate->name << "_priority_" << b;
00001937 }
00001938 }
00001939 }
00001940 }
00001941 }
00001942 outfile << ") begin\n";
00001943
00001944 //Create bounding if statement for priority assignment
reset
00001945 outfile << " if (" << curr_gate->name <<
"_priority_last_reset != priority_reset) begin\n";
00001946 for(int a = 0; a < output_count[k]; a++){
00001947 outfile << " " << curr_gate->name <<
"_priority_" << a << " = 1'b0;\n";
00001948 }
00001949 outfile << " " << curr_gate->name <<
"_priority_last_reset = priority_reset;\n";
00001950 outfile << " end\n";
00001951 outfile << " else begin\n";
223
00001952
00001953 //Output blocking AND gates for each fanout
00001954 for(int a = 0; a < output_count[k]; a++){
00001955 //
00001956 if(strcmp(curr_gate->type, "INPUT") == 0){
00001957 //
00001958 outfile << " " << curr_gate->name <<
"_priority_" << a << " = ";
00001959 firstrun = 1;
00001960 for(int b = 0; b < output_count[k]; b++){
00001961 if(firstrun == 1){
00001962 firstrun = 0;
00001963 }
00001964 else{
00001965 outfile << " & ";
00001966 }
00001967
00001968 if(a == b){
00001969 outfile << curr_gate->name
<< "_o1_" << b;
00001970 }
00001971 else{
00001972 outfile << "~" <<
curr_gate->name << "_priority_" << b;
00001973 }
00001974 }
00001975 outfile << ";\n";
00001976 back_num_gates = back_num_gates + 1;
00001977 }
00001978 else{
00001979 //
00001980 outfile << " " << curr_gate->name <<
"_priority_" << a << " = ";
00001981 firstrun = 1;
00001982 for(int b = 0; b < output_count[k]; b++){
00001983 if(firstrun == 1){
00001984 firstrun = 0;
00001985 if(a == b){
00001986 outfile <<
curr_gate->name << "_zo1";
00001987 }
00001988 else{
00001989 outfile << "~" <<
curr_gate->name << "_priority_" << b;
00001990 }
00001991 }
00001992 else{
00001993 outfile << " & ";
00001994 if(a == b){
00001995 outfile <<
curr_gate->name << "_zo1_" << b;
00001996 }
00001997 else{
00001998 outfile << "~" <<
curr_gate->name << "_priority_" << b;
00001999 }
00002000 }
00002001 }
00002002 outfile << ";\n";
00002003 back_num_gates = back_num_gates + 1;
00002004 }
00002005 }
00002006 outfile << " end\n";
00002007 outfile << "end\n";
00002008
00002009 //Generate final objective from priority blocks
00002010 outfile << "wire " << curr_gate->name << "_zo1_" <<
output_count[k] << " = ";
00002011 firstrun = 1;
224
00002012 for(int a = 0; a < output_count[k]; a++){
00002013 //
00002014 if(firstrun == 1){
00002015 firstrun = 0;
00002016 }
00002017 else{
00002018 outfile << " | ";
00002019 }
00002020
00002021 outfile << curr_gate->name << "_priority_" << a;
00002022 }
00002023 outfile << ";\n";
00002024 back_num_gates = back_num_gates + 1;
00002025
00002026 //Generate objective value from priority blocks and obj
inputs
00002027 outfile << "wire " << curr_gate->name << "_zo0_" <<
output_count[k] << " = ";
00002028 firstrun = 1;
00002029 for(int a = 0; a < output_count[k]; a++){
00002030 //
00002031 if(firstrun == 1){
00002032 firstrun = 0;
00002033 }
00002034 else{
00002035 outfile << " | ";
00002036 }
00002037
00002038 if(strcmp(curr_gate->type, "INPUT") == 0){
00002039 //
00002040 outfile << "(" << curr_gate->name <<
"_priority_" << a << " & " << curr_gate->name << "_o0_" << a << ")";
00002041 }
00002042 else{
00002043 //
00002044 if(a == 0){outfile << "(" << curr_gate-
>name << "_priority_" << a << " & " << curr_gate->name << "_zo0)";}
00002045 else{outfile << "(" << curr_gate->name <<
"_priority_" << a << " & " << curr_gate->name << "_zo0_" << a << ")";}
00002046 }
00002047 }
00002048 outfile << ";\n";
00002049 back_num_gates = back_num_gates + output_count[k] + 1;
00002050
00002051 }
00002052
00002053 if(strcmp(curr_gate->type, "AND") == 0){
00002054 //AND gate
00002055 back_num_gates = back_num_gates + 3;
00002056
00002057 //Loop through input wires
00002058 char in1[35];
00002059 char in0[35];
00002060 char ino1[35];
00002061 char ino0[35];
00002062
00002063 struct gate_node * in_ptr = curr_gate->fanin_list;
00002064 int firstrun = 1;
00002065 while(in_ptr != NULL){
00002066 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00002067 //Input is type INPUT
00002068 strcpy(in1, in_ptr->gate_ptr->name);
00002069 strcat(in1, "_1");
00002070 strcpy(in0, in_ptr->gate_ptr->name);
00002071 strcat(in0, "_0");
00002072 }
00002073 else{
00002074 //Input is type GATE
00002075 strcpy(in1, in_ptr->gate_ptr->name);
225
00002076 strcat(in1, "_z1");
00002077 strcpy(in0, in_ptr->gate_ptr->name);
00002078 strcat(in0, "_z0");
00002079 }
00002080
00002081 //Check if current input objective is part of a
fanout
00002082 int j = 0;
00002083 while(j < output_array_size &&
strcmp(output_name[j], in_ptr->gate_ptr->name) != 0){
00002084 j++;
00002085 }
00002086 if(j == output_array_size){
00002087 //gate not found, output as is and add
00002088 int k = 0;
00002089 while(k < output_array_size &&
(strcmp(output_name[k], "") != 0)){k++;}
00002090 if(k == output_array_size){
00002091 //Error, don't store
00002092 printf("ERROR: Naming array
overflow.\n");
00002093 }
00002094 else{
00002095 strcpy(output_name[k], in_ptr-
>gate_ptr->name);
00002096 output_count[k]++;
00002097 }
00002098
00002099 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002100 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002101 strcat(ino1, "_o1_0");
00002102 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002103 strcat(ino0, "_o0_0");
00002104 }
00002105 else{
00002106 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002107 strcat(ino1, "_zo1");
00002108 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002109 strcat(ino0, "_zo0");
00002110 }
00002111 }
00002112 else{
00002113 //Gate found, output with subscript and
set to handle branch
00002114 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002115 char output_num[35];
00002116 sprintf(output_num, "%i",
output_count[j]);
00002117 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002118 strcat(ino1, "_o1_");
00002119 strcat(ino1, output_num);
00002120 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002121 strcat(ino0, "_o0_");
00002122 strcat(ino0, output_num);
00002123 output_count[j]++;
00002124 }
00002125 else{
00002126 char output_num[35];
00002127 sprintf(output_num, "%i",
output_count[j]);
00002128 strcpy(ino1, in_ptr->gate_ptr-
226
>name);
00002129 strcat(ino1, "_zo1_");
00002130 strcat(ino1, output_num);
00002131 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002132 strcat(ino0, "_zo0_");
00002133 strcat(ino0, output_num);
00002134 output_count[j]++;
00002135 }
00002136 }
00002137
00002138 if(firstrun == 1){
00002139 firstrun = 0;
00002140 //Output equation for first input
00002141 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << in1 << " & " << in0 << ";\n";
00002142 outfile << "wire " << ino0 << " = " <<
zo0 << ";\n";
00002143 }
00002144 else{
00002145 //Output equation for subsequent inputs
00002146 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << zo0 << " & " << in1 << " & " << in0 << ";\n";
00002147 outfile << "wire " << ino0 << " = " <<
zo0 << ";\n";
00002148 }
00002149
00002150 in_ptr = in_ptr->next_ptr;
00002151 }
00002152 }
00002153 else if(strcmp(curr_gate->type, "OR") == 0){
00002154 //OR gate
00002155 back_num_gates = back_num_gates + 4;
00002156
00002157 //Loop through input wires
00002158 char in1[35];
00002159 char in0[35];
00002160 char ino1[35];
00002161 char ino0[35];
00002162
00002163 struct gate_node * in_ptr = curr_gate->fanin_list;
00002164 int firstrun = 1;
00002165 while(in_ptr != NULL){
00002166 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00002167 //Input is type INPUT
00002168 strcpy(in1, in_ptr->gate_ptr->name);
00002169 strcat(in1, "_1");
00002170 strcpy(in0, in_ptr->gate_ptr->name);
00002171 strcat(in0, "_0");
00002172 }
00002173 else{
00002174 //Input is type GATE
00002175 strcpy(in1, in_ptr->gate_ptr->name);
00002176 strcat(in1, "_z1");
00002177 strcpy(in0, in_ptr->gate_ptr->name);
00002178 strcat(in0, "_z0");
00002179 }
00002180
00002181 //Check if current input objective is part of a
fanout
00002182 int j = 0;
00002183 while(j < output_array_size &&
strcmp(output_name[j], in_ptr->gate_ptr->name) != 0){
00002184 j++;
00002185 }
00002186 if(j == output_array_size){
00002187 //gate not found, output as is and add
00002188 int k = 0;
00002189 while(k < output_array_size &&
227
(strcmp(output_name[k], "") != 0)){k++;}
00002190 if(k == output_array_size){
00002191 //Error, don't store
00002192 printf("ERROR: Naming array
overflow.\n");
00002193 }
00002194 else{
00002195 strcpy(output_name[k], in_ptr-
>gate_ptr->name);
00002196 output_count[k]++;
00002197 }
00002198
00002199 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002200 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002201 strcat(ino1, "_o1_0");
00002202 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002203 strcat(ino0, "_o0_0");
00002204 }
00002205 else{
00002206 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002207 strcat(ino1, "_zo1");
00002208 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002209 strcat(ino0, "_zo0");
00002210 }
00002211 }
00002212 else{
00002213 //Gate found, output with subscript and
set to handle branch
00002214 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002215 char output_num[35];
00002216 sprintf(output_num, "%i",
output_count[j]);
00002217 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002218 strcat(ino1, "_o1_");
00002219 strcat(ino1, output_num);
00002220 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002221 strcat(ino0, "_o0_");
00002222 strcat(ino0, output_num);
00002223 output_count[j]++;
00002224 }
00002225 else{
00002226 char output_num[35];
00002227 sprintf(output_num, "%i",
output_count[j]);
00002228 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002229 strcat(ino1, "_zo1_");
00002230 strcat(ino1, output_num);
00002231 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002232 strcat(ino0, "_zo0_");
00002233 strcat(ino0, output_num);
00002234 output_count[j]++;
00002235 }
00002236 }
00002237
00002238 if(firstrun == 1){
00002239 firstrun = 0;
00002240 //Output equation for first input
00002241 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << in1 << " & " << in0 << ";\n";
228
00002242 outfile << "wire " << ino0 << " = " <<
zo0 << ";\n";
00002243 }
00002244 else{
00002245 //Output equation for subsequent inputs
00002246 outfile << "wire " << ino1 << " = " <<
zo1 << " & ~" << zo0 << " & " << in1 << " & " << in0 << ";\n";
00002247 outfile << "wire " << ino0 << " = " <<
zo0 << ";\n";
00002248 }
00002249
00002250 in_ptr = in_ptr->next_ptr;
00002251 }
00002252 }
00002253 else if(strcmp(curr_gate->type, "NOT") == 0){
00002254 //NOT gate
00002255 back_num_gates = back_num_gates + 3;
00002256
00002257 //Loop through input wires
00002258 char in1[35];
00002259 char in0[35];
00002260 char ino1[35];
00002261 char ino0[35];
00002262
00002263 struct gate_node * in_ptr = curr_gate->fanin_list;
00002264 int firstrun = 1;
00002265 while(in_ptr != NULL){
00002266 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00002267 //Input is type INPUT
00002268 strcpy(in1, in_ptr->gate_ptr->name);
00002269 strcat(in1, "_1");
00002270 strcpy(in0, in_ptr->gate_ptr->name);
00002271 strcat(in0, "_0");
00002272 }
00002273 else{
00002274 //Input is type GATE
00002275 strcpy(in1, in_ptr->gate_ptr->name);
00002276 strcat(in1, "_z1");
00002277 strcpy(in0, in_ptr->gate_ptr->name);
00002278 strcat(in0, "_z0");
00002279 }
00002280
00002281 //Check if current input objective is part of a
fanout
00002282 int j = 0;
00002283 while(j < output_array_size &&
strcmp(output_name[j], in_ptr->gate_ptr->name) != 0){
00002284 j++;
00002285 }
00002286 if(j == output_array_size){
00002287 //gate not found, output as is and add
00002288 int k = 0;
00002289 while(k < output_array_size &&
(strcmp(output_name[k], "") != 0)){k++;}
00002290 if(k == output_array_size){
00002291 //Error, don't store
00002292 printf("ERROR: Naming array
overflow.\n");
00002293 }
00002294 else{
00002295 strcpy(output_name[k], in_ptr-
>gate_ptr->name);
00002296 output_count[k]++;
00002297 }
00002298
00002299 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002300 strcpy(ino1, in_ptr->gate_ptr-
>name);
229
00002301 strcat(ino1, "_o1_0");
00002302 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002303 strcat(ino0, "_o0_0");
00002304 }
00002305 else{
00002306 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002307 strcat(ino1, "_zo1");
00002308 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002309 strcat(ino0, "_zo0");
00002310 }
00002311 }
00002312 else{
00002313 //Gate found, output with subscript and
set to handle branch
00002314 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002315 char output_num[35];
00002316 sprintf(output_num, "%i",
output_count[j]);
00002317 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002318 strcat(ino1, "_o1_");
00002319 strcat(ino1, output_num);
00002320 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002321 strcat(ino0, "_o0_");
00002322 strcat(ino0, output_num);
00002323 output_count[j]++;
00002324 }
00002325 else{
00002326 char output_num[35];
00002327 sprintf(output_num, "%i",
output_count[j]);
00002328 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002329 strcat(ino1, "_zo1_");
00002330 strcat(ino1, output_num);
00002331 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002332 strcat(ino0, "_zo0_");
00002333 strcat(ino0, output_num);
00002334 output_count[j]++;
00002335 }
00002336 }
00002337
00002338 if(firstrun == 1){
00002339 firstrun = 0;
00002340 //Output equation for first input
00002341 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << in1 << " & " << in0 << ";\n";
00002342 outfile << "wire " << ino0 << " = ~" <<
zo0 << ";\n";
00002343 }
00002344 else{
00002345 //Output equation for subsequent inputs
00002346 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << in1 << " & " << in0 << ";\n";
00002347 outfile << "wire " << ino0 << " = ~" <<
zo0 << ";\n";
00002348 }
00002349
00002350 in_ptr = in_ptr->next_ptr;
00002351 }
00002352 }
00002353 else if(strcmp(curr_gate->type, "XOR") == 0){
00002354 //XOR gate
230
00002355 back_num_gates = back_num_gates + 2;
00002356
00002357 //Loop through input wires
00002358 char in1[35];
00002359 char in0[35];
00002360 char ino1[35];
00002361 char ino0[35];
00002362
00002363 struct gate_node * in_ptr = curr_gate->fanin_list;
00002364 int firstrun = 1;
00002365 while(in_ptr != NULL){
00002366 if(strcmp(in_ptr->gate_ptr->type, "INPUT") == 0){
00002367 //Input is type INPUT
00002368 strcpy(in1, in_ptr->gate_ptr->name);
00002369 strcat(in1, "_1");
00002370 strcpy(in0, in_ptr->gate_ptr->name);
00002371 strcat(in0, "_0");
00002372 }
00002373 else{
00002374 //Input is type GATE
00002375 strcpy(in1, in_ptr->gate_ptr->name);
00002376 strcat(in1, "_z1");
00002377 strcpy(in0, in_ptr->gate_ptr->name);
00002378 strcat(in0, "_z0");
00002379 }
00002380
00002381 //Check if current input objective is part of a
fanout
00002382 int j = 0;
00002383 while(j < output_array_size &&
strcmp(output_name[j], in_ptr->gate_ptr->name) != 0){
00002384 j++;
00002385 }
00002386 if(j == output_array_size){
00002387 //gate not found, output as is and add
00002388 int k = 0;
00002389 while(k < output_array_size &&
(strcmp(output_name[k], "") != 0)){k++;}
00002390 if(k == output_array_size){
00002391 //Error, don't store
00002392 printf("ERROR: Naming array
overflow.\n");
00002393 }
00002394 else{
00002395 strcpy(output_name[k], in_ptr-
>gate_ptr->name);
00002396 output_count[k]++;
00002397 }
00002398
00002399 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002400 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002401 strcat(ino1, "_o1_0");
00002402 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002403 strcat(ino0, "_o0_0");
00002404 }
00002405 else{
00002406 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002407 strcat(ino1, "_zo1");
00002408 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002409 strcat(ino0, "_zo0");
00002410 }
00002411 }
00002412 else{
00002413 //Gate found, output with subscript and
231
set to handle branch
00002414 if(strcmp(in_ptr->gate_ptr->type,
"INPUT") == 0 || strcmp(in_ptr->gate_ptr->type, "DFF") == 0){
00002415 char output_num[35];
00002416 sprintf(output_num, "%i",
output_count[j]);
00002417 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002418 strcat(ino1, "_o1_");
00002419 strcat(ino1, output_num);
00002420 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002421 strcat(ino0, "_o0_");
00002422 strcat(ino0, output_num);
00002423 output_count[j]++;
00002424 }
00002425 else{
00002426 char output_num[35];
00002427 sprintf(output_num, "%i",
output_count[j]);
00002428 strcpy(ino1, in_ptr->gate_ptr-
>name);
00002429 strcat(ino1, "_zo1_");
00002430 strcat(ino1, output_num);
00002431 strcpy(ino0, in_ptr->gate_ptr-
>name);
00002432 strcat(ino0, "_zo0_");
00002433 strcat(ino0, output_num);
00002434 output_count[j]++;
00002435 }
00002436 }
00002437
00002438 if(firstrun == 1){
00002439 firstrun = 0;
00002440 //Output equation for first input
00002441 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << in1 << " & " << in0 << ";\n";
00002442 outfile << "wire " << ino0 << " = " <<
zo0 << ";\n";
00002443 }
00002444 else{
00002445 //Output equation for subsequent inputs
00002446 outfile << "wire " << ino1 << " = " <<
zo1 << " & " << in1 << " & " << in0 << ";\n";
00002447 outfile << "wire " << ino0 << " =
1'b0;\n";
00002448 }
00002449
00002450 in_ptr = in_ptr->next_ptr;
00002451 }
00002452 }
00002453 gate_ptr = gate_ptr->next_ptr;
00002454 }
00002455 level_ptr = level_ptr->prev_ptr;
00002456 }
00002457
00002458 //Traverse through input list and make final PI assignments
00002459 struct gate_node * input_ptr = input_list;
00002460 while(input_ptr != NULL){
00002461 //Get current input name
00002462 char curr_input[35];
00002463 strcpy(curr_input, input_ptr->gate_ptr->name);
00002464
00002465 //Find input in gate list
00002466 int j = 0;
00002467 while(j < output_array_size && strcmp(output_name[j], curr_input) !=
0){
00002468 j++;
00002469 }
232
00002470 if(j == output_array_size){
00002471 //gate not found
00002472 //either direct input->output assignment, or possible error
00002473 //assume input->output
00002474 outfile << "wire " << curr_input << "_o1 = " << curr_input <<
"_zo1;\n";
00002475 outfile << "wire " << curr_input << "_o0 = " << curr_input <<
"_zo0;\n";
00002476 }
00002477 else{
00002478 //Gate found, output assignment
00002479 char zo1[35];
00002480 char zo0[35];
00002481 char output_num[35];
00002482 sprintf(output_num, "%i", output_count[j]-1);
00002483
00002484 if (strcmp(output_num, "0") == 0){
00002485 //Single fanout - pass through
00002486 strcpy(zo1, curr_input);
00002487 strcat(zo1, "_o1_");
00002488 strcat(zo1, output_num);
00002489 strcpy(zo0, curr_input);
00002490 strcat(zo0, "_o0_");
00002491 strcat(zo0, output_num);
00002492 //Output
00002493 outfile << "wire " << curr_input << "_o1 = " << zo1 <<
";\n";
00002494 outfile << "wire " << curr_input << "_o0 = " << zo0 <<
";\n";
00002495 }
00002496 else{
00002497 //Multi-fanout - priority encode
00002498 strcpy(zo1, curr_input);
00002499 strcat(zo1, "_o1_");
00002500 strcat(zo1, output_num);
00002501 strcpy(zo0, curr_input);
00002502 strcat(zo0, "_o0_");
00002503 strcat(zo0, output_num);
00002504
00002505 //-------------------------------------
00002506 // Output priority encoder to merge zo
00002507 //-------------------------------------
00002508
00002509 //Predefine output wires from blocking gates
00002510 for(int a = 0; a < output_count[j]; a++){
00002511 outfile << "reg " << curr_input << "_priority_"
<< a << ";\n";
00002512 }
00002513 outfile << "reg " << curr_input <<
"_priority_last_reset;\n";
00002514
00002515 //Generate trigger list for priority encoder
00002516 outfile << "always @(priority_reset, ";
00002517 int firstrun = 1;
00002518 for(int a = 0; a < output_count[j]; a++){
00002519 for(int b = 0; b < output_count[j]; b++){
00002520 if(firstrun == 1){
00002521 firstrun = 0;
00002522 }
00002523 else{
00002524 outfile << ", ";
00002525 }
00002526
00002527 if(a == b){
00002528 outfile << curr_input << "_o1_" <<
b;
00002529 }
00002530 else{
00002531 outfile << curr_input <<
233
"_priority_" << b;
00002532 }
00002533 }
00002534 }
00002535 outfile << ") begin\n";
00002536
00002537 //Create bounding if statement for priority assignment
reset
00002538 outfile << " if (" << curr_input <<
"_priority_last_reset != priority_reset) begin\n";
00002539 for(int a = 0; a < output_count[j]; a++){
00002540 outfile << " " << curr_input << "_priority_"
<< a << " = 1'b0;\n";
00002541 }
00002542 outfile << " " << curr_input << "_priority_last_reset
= priority_reset;\n";
00002543 outfile << " end\n";
00002544 outfile << " else begin\n";
00002545
00002546 //Output blocking AND gates for each fanout
00002547 for(int a = 0; a < output_count[j]; a++){
00002548 outfile << " " << curr_input << "_priority_"
<< a << " = ";
00002549 firstrun = 1;
00002550 for(int b = 0; b < output_count[j]; b++){
00002551 if(firstrun == 1){
00002552 firstrun = 0;
00002553 }
00002554 else{
00002555 outfile << " & ";
00002556 }
00002557
00002558 if(a == b){
00002559 outfile << curr_input << "_o1_" <<
b;
00002560 }
00002561 else{
00002562 outfile << "~" << curr_input <<
"_priority_" << b;
00002563 }
00002564 }
00002565 outfile << ";\n";
00002566 back_num_gates = back_num_gates + 1;
00002567 }
00002568 outfile << " end\n";
00002569 outfile << "end\n";
00002570
00002571 //Generate final objective from priority blocks
00002572 outfile << "wire " << curr_input << "_o1 = ";
00002573 firstrun = 1;
00002574 for(int a = 0; a < output_count[j]; a++){
00002575 //
00002576 if(firstrun == 1){
00002577 firstrun = 0;
00002578 }
00002579 else{
00002580 outfile << " | ";
00002581 }
00002582
00002583 outfile << curr_input << "_priority_" << a;
00002584 }
00002585 outfile << ";\n";
00002586 back_num_gates = back_num_gates + 1;
00002587
00002588 //Generate objective value from priority blocks and obj
inputs
00002589 outfile << "wire " << curr_input << "_o0 = ";
00002590 firstrun = 1;
00002591 for(int a = 0; a < output_count[j]; a++){
234
00002592 //
00002593 if(firstrun == 1){
00002594 firstrun = 0;
00002595 }
00002596 else{
00002597 outfile << " | ";
00002598 }
00002599
00002600 outfile << "(" << curr_input << "_priority_" << a
<< " & " << curr_input << "_o0_" << a << ")";
00002601 }
00002602 outfile << ";\n";
00002603 back_num_gates = back_num_gates + output_count[j] + 1;
00002604 }
00002605 }
00002606
00002607 input_ptr = input_ptr->next_ptr;
00002608 }
00002609
00002610 //Traverse through DFF list and make final PPI assignments
00002611 struct gate_node * dff_ptr = dff_list;
00002612 while(dff_ptr != NULL){
00002613 //Get current input name
00002614 char curr_dff[35];
00002615 strcpy(curr_dff, dff_ptr->gate_ptr->name);
00002616
00002617 //Find dff in gate list
00002618 int j = 0;
00002619 while(j < output_array_size && strcmp(output_name[j], curr_dff) != 0){
00002620 j++;
00002621 }
00002622 if(j == output_array_size){
00002623 //gate not found
00002624 //direct PI->DFF assignment?
00002625 cout << "ERROR: DFF with missing input def: " << curr_dff <<
endl;
00002626 }
00002627 else{
00002628 //Gate found, output assignment
00002629 char zo1[35];
00002630 char zo0[35];
00002631 char output_num[35];
00002632 sprintf(output_num, "%i", output_count[j]-1);
00002633
00002634 if (strcmp(output_num, "0") == 0){
00002635 //Single fanout - pass through
00002636 //Verify fanout is not another DFF (already defined if
it is)
00002637 bool dff_fanout = 0;
00002638 struct gate_node * dff2_ptr = dff_list;
00002639 while(dff2_ptr != NULL){
00002640 if (strcmp(dff2_ptr->gate_ptr->fanin_list-
>gate_ptr->name, curr_dff) == 0) {
00002641 dff_fanout = 1;
00002642 }
00002643 dff2_ptr = dff2_ptr->next_ptr;
00002644 }
00002645
00002646 if (!dff_fanout) {
00002647 strcpy(zo1, curr_dff);
00002648 strcat(zo1, "_o1_");
00002649 strcat(zo1, output_num);
00002650 strcpy(zo0, curr_dff);
00002651 strcat(zo0, "_o0_");
00002652 strcat(zo0, output_num);
00002653 //Output
00002654 outfile << "wire " << curr_dff << "_zo1 = " <<
zo1 << ";\n";
00002655 outfile << "wire " << curr_dff << "_zo0 = " <<
235
zo0 << ";\n";
00002656 }
00002657 }
00002658 else{
00002659 //Multi-fanout - priority encode
00002660 strcpy(zo1, curr_dff);
00002661 strcat(zo1, "_o1_");
00002662 strcat(zo1, output_num);
00002663 strcpy(zo0, curr_dff);
00002664 strcat(zo0, "_o0_");
00002665 strcat(zo0, output_num);
00002666
00002667 //-------------------------------------
00002668 // Output priority encoder to merge zo
00002669 //-------------------------------------
00002670
00002671 //Predefine output wires from blocking gates
00002672 for(int a = 0; a < output_count[j]; a++){
00002673 outfile << "reg " << curr_dff << "_priority_" <<
a << ";\n";
00002674 }
00002675 outfile << "reg " << curr_dff <<
"_priority_last_reset;\n";
00002676
00002677 //Generate trigger list for priority encoder
00002678 outfile << "always @(priority_reset, ";
00002679 int firstrun = 1;
00002680 for(int a = 0; a < output_count[j]; a++){
00002681 for(int b = 0; b < output_count[j]; b++){
00002682 if(firstrun == 1){
00002683 firstrun = 0;
00002684 }
00002685 else{
00002686 outfile << ", ";
00002687 }
00002688
00002689 if(a == b){
00002690 outfile << curr_dff << "_o1_" <<
b;
00002691 }
00002692 else{
00002693 outfile << curr_dff <<
"_priority_" << b;
00002694 }
00002695 }
00002696 }
00002697 outfile << ") begin\n";
00002698
00002699 //Create bounding if statement for priority assignment
reset
00002700 outfile << " if (" << curr_dff << "_priority_last_reset
!= priority_reset) begin\n";
00002701 for(int a = 0; a < output_count[j]; a++){
00002702 outfile << " " << curr_dff << "_priority_" <<
a << " = 1'b0;\n";
00002703 }
00002704 outfile << " " << curr_dff << "_priority_last_reset =
priority_reset;\n";
00002705 outfile << " end\n";
00002706 outfile << " else begin\n";
00002707
00002708 //Output blocking AND gates for each fanout
00002709 for(int a = 0; a < output_count[j]; a++){
00002710 outfile << " " << curr_dff << "_priority_" <<
a << " = ";
00002711 firstrun = 1;
00002712 for(int b = 0; b < output_count[j]; b++){
00002713 if(firstrun == 1){
00002714 firstrun = 0;
236
00002715 }
00002716 else{
00002717 outfile << " & ";
00002718 }
00002719
00002720 if(a == b){
00002721 outfile << curr_dff << "_o1_" <<
b;
00002722 }
00002723 else{
00002724 outfile << "~" << curr_dff <<
"_priority_" << b;
00002725 }
00002726 }
00002727 outfile << ";\n";
00002728 back_num_gates = back_num_gates + 1;
00002729 }
00002730 outfile << " end\n";
00002731 outfile << "end\n";
00002732
00002733 //Generate final objective from priority blocks
00002734 outfile << "wire " << curr_dff << "_zo1 = ";
00002735 firstrun = 1;
00002736 for(int a = 0; a < output_count[j]; a++){
00002737 //
00002738 if(firstrun == 1){
00002739 firstrun = 0;
00002740 }
00002741 else{
00002742 outfile << " | ";
00002743 }
00002744
00002745 outfile << curr_dff << "_priority_" << a;
00002746 }
00002747 outfile << ";\n";
00002748 back_num_gates = back_num_gates + 1;
00002749
00002750 //Generate objective value from priority blocks and obj
inputs
00002751 outfile << "wire " << curr_dff << "_zo0 = ";
00002752 firstrun = 1;
00002753 for(int a = 0; a < output_count[j]; a++){
00002754 //
00002755 if(firstrun == 1){
00002756 firstrun = 0;
00002757 }
00002758 else{
00002759 outfile << " | ";
00002760 }
00002761
00002762 outfile << "(" << curr_dff << "_priority_" << a
<< " & " << curr_dff << "_o0_" << a << ")";
00002763 }
00002764 outfile << ";\n";
00002765 back_num_gates = back_num_gates + output_count[j] + 1;
00002766 }
00002767 }
00002768
00002769 dff_ptr = dff_ptr->next_ptr;
00002770 }
00002771
00002772 //Assign wires to output array
00002773 outfile << "assign PI_1 = {" << back_pi_list_1() << "};\n";
00002774 outfile << "assign PI_0 = {" << back_pi_list_0() << "};\n";
00002775 if(back_ppi_list_1() != ""){
00002776 outfile << "assign PPI_1 = {" << back_ppi_list_1() << "};\n";
00002777 outfile << "assign PPI_0 = {" << back_ppi_list_0() << "};\n";
00002778 }
00002779
237
00002780 //Output the priority encoder reset block
00002781 //outfile << priority_encoder_reset;
00002782 //outfile << "end\n";
00002783
00002784 //DEBUG
00002785 //for(int i = 0; i < output_array_size; i++){
00002786 // cout << i << ": " << output_name[i] << endl;
00002787 //}
00002788
00002789 outfile << "endmodule\n\n";
00002790
00002791 //Insert gate stats into network as comments
00002792 outfile << "//--- GATE STATISTICS ---\n";
00002793 outfile << "//Original Circuit: " << fwd_gate_count(max_level) << "\n";
00002794 outfile << "//Backward Network: " << back_num_gates << "\n";
00002795
00002796 outfile.close();
00002797
00002798 //Output gate stats
00002799 cout << "Backward Network: " << back_num_gates << endl;
00002800 }
00002801
00002802 //--------------------------------------------------------------------
00002803
00002804 string back_po_list_1(){
00002805 //Form input list string
00002806 string output_list_str = "";
00002807 int first_run = 0;
00002808
00002809 //Traverse output list
00002810 struct gate_node * output_ptr = output_list;
00002811 while(output_ptr != NULL){
00002812 //Get current output name
00002813 char curr_output[35];
00002814 strcpy(curr_output, output_ptr->gate_ptr->name);
00002815
00002816 //Check if this PO is also a PPO
00002817 struct gate_node * ppo_ptr = dff_list;
00002818 while((ppo_ptr != NULL) && (strcmp(ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name, curr_output) != 0)){
00002819 ppo_ptr = ppo_ptr->next_ptr;
00002820 }
00002821
00002822 string outputstr = "";
00002823 if(ppo_ptr == NULL){
00002824 //Regular PO, output normally
00002825 if(first_run == 0){
00002826 outputstr = strcat(curr_output, "_zo1");
00002827 first_run = 1;
00002828 }
00002829 else{
00002830 strcpy(curr_output, ", ");
00002831 strcat(curr_output, output_ptr->gate_ptr->name);
00002832 outputstr = strcat(curr_output, "_zo1");
00002833 }
00002834 }
00002835 else{
00002836 //Dual PO/PPO, output with _po
00002837 if(first_run == 0){
00002838 outputstr = strcat(curr_output, "_zo1_po");
00002839 first_run = 1;
00002840 }
00002841 else{
00002842 strcpy(curr_output, ", ");
00002843 strcat(curr_output, output_ptr->gate_ptr->name);
00002844 outputstr = strcat(curr_output, "_zo1_po");
00002845 }
00002846 }
00002847 output_list_str = output_list_str + outputstr;
238
00002848
00002849 output_ptr = output_ptr->next_ptr;
00002850 }
00002851
00002852 return output_list_str;
00002853 }
00002854
00002855 //--------------------------------------------------------------------
00002856
00002857 string back_po_list_0(){
00002858 //Form input list string
00002859 string output_list_str = "";
00002860 int first_run = 0;
00002861
00002862 //Traverse output list
00002863 struct gate_node * output_ptr = output_list;
00002864 while(output_ptr != NULL){
00002865 //Get current output name
00002866 char curr_output[35];
00002867 strcpy(curr_output, output_ptr->gate_ptr->name);
00002868
00002869 //Check if this PO is also a PPO
00002870 struct gate_node * ppo_ptr = dff_list;
00002871 while((ppo_ptr != NULL) && (strcmp(ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name, curr_output) != 0)){
00002872 ppo_ptr = ppo_ptr->next_ptr;
00002873 }
00002874
00002875 string outputstr = "";
00002876 if(ppo_ptr == NULL){
00002877 //Regular PO, output normally
00002878 if(first_run == 0){
00002879 outputstr = strcat(curr_output, "_zo0");
00002880 first_run = 1;
00002881 }
00002882 else{
00002883 strcpy(curr_output, ", ");
00002884 strcat(curr_output, output_ptr->gate_ptr->name);
00002885 outputstr = strcat(curr_output, "_zo0");
00002886 }
00002887 }
00002888 else{
00002889 //Dual PO/PPO, output with _po
00002890 if(first_run == 0){
00002891 outputstr = strcat(curr_output, "_zo0_po");
00002892 first_run = 1;
00002893 }
00002894 else{
00002895 strcpy(curr_output, ", ");
00002896 strcat(curr_output, output_ptr->gate_ptr->name);
00002897 outputstr = strcat(curr_output, "_zo0_po");
00002898 }
00002899 }
00002900 output_list_str = output_list_str + outputstr;
00002901
00002902 output_ptr = output_ptr->next_ptr;
00002903 }
00002904
00002905 return output_list_str;
00002906 }
00002907
00002908 //--------------------------------------------------------------------
00002909
00002910 int back_po_count(){
00002911 //Traverse output list
00002912 struct gate_node * output_ptr = output_list;
00002913 int count = 0;
00002914 while(output_ptr != NULL){
00002915 count++;
239
00002916 output_ptr = output_ptr->next_ptr;
00002917 }
00002918
00002919 return count;
00002920 }
00002921
00002922 //--------------------------------------------------------------------
00002923
00002924 string back_ppi_list_1(){
00002925 //List ppis = dff inputs
00002926 string ppi_list_str = "";
00002927 int first_run = 0;
00002928
00002929 //Traverse dff list
00002930 struct gate_node * ppi_ptr = dff_list;
00002931 while(ppi_ptr != NULL){
00002932 //Get current dff name
00002933 char curr_ppi[35];
00002934 strcpy(curr_ppi, ppi_ptr->gate_ptr->name);
00002935
00002936 string ppistr = "";
00002937 if(first_run == 0){
00002938 ppistr = strcat(curr_ppi, "_zo1");
00002939 first_run = 1;
00002940 }
00002941 else{
00002942 strcpy(curr_ppi, ", ");
00002943 strcat(curr_ppi, ppi_ptr->gate_ptr->name);
00002944 ppistr = strcat(curr_ppi, "_zo1");
00002945 }
00002946 ppi_list_str = ppi_list_str + ppistr;
00002947
00002948 ppi_ptr = ppi_ptr->next_ptr;
00002949 }
00002950
00002951
00002952 return ppi_list_str;
00002953 }
00002954
00002955 //--------------------------------------------------------------------
00002956
00002957 string back_ppi_list_0(){
00002958 //List ppis = dff inputs
00002959 string ppi_list_str = "";
00002960 int first_run = 0;
00002961
00002962 //Traverse dff list
00002963 struct gate_node * ppi_ptr = dff_list;
00002964 while(ppi_ptr != NULL){
00002965 //Get current dff name
00002966 char curr_ppi[35];
00002967 strcpy(curr_ppi, ppi_ptr->gate_ptr->name);
00002968
00002969 string ppistr = "";
00002970 if(first_run == 0){
00002971 ppistr = strcat(curr_ppi, "_zo0");
00002972 first_run = 1;
00002973 }
00002974 else{
00002975 strcpy(curr_ppi, ", ");
00002976 strcat(curr_ppi, ppi_ptr->gate_ptr->name);
00002977 ppistr = strcat(curr_ppi, "_zo0");
00002978 }
00002979 ppi_list_str = ppi_list_str + ppistr;
00002980
00002981 ppi_ptr = ppi_ptr->next_ptr;
00002982 }
00002983
00002984
240
00002985 return ppi_list_str;
00002986 }
00002987
00002988 //--------------------------------------------------------------------
00002989
00002990 int back_ppi_count(){
00002991 //Count number of ppis = num of dffs
00002992 int count = 0;
00002993 struct gate_node * ppi_ptr = dff_list;
00002994 while(ppi_ptr != NULL){
00002995 count++;
00002996 ppi_ptr = ppi_ptr->next_ptr;
00002997 }
00002998
00002999 return count;
00003000 }
00003001
00003002 //--------------------------------------------------------------------
00003003
00003004 string back_state_list_1(int max_level){
00003005 //Form input list string
00003006 string output_list_str = "";
00003007 int first_run = 0;
00003008
00003009 //Add inputs onto state list
00003010 //Traverse input list
00003011 struct gate_node * input_ptr = input_list;
00003012 while(input_ptr != NULL){
00003013 //Get current input name
00003014 char curr_input[35];
00003015 strcpy(curr_input, input_ptr->gate_ptr->name);
00003016
00003017 string inputstr = "";
00003018 if(first_run == 0){
00003019 inputstr = strcat(curr_input, "_1");
00003020 first_run = 1;
00003021 }
00003022 else{
00003023 strcpy(curr_input, ", ");
00003024 strcat(curr_input, input_ptr->gate_ptr->name);
00003025 inputstr = strcat(curr_input, "_1");
00003026 }
00003027 output_list_str = output_list_str + inputstr;
00003028
00003029 input_ptr = input_ptr->next_ptr;
00003030 }
00003031
00003032 //Add ppis to state list
00003033 //Traverse dff list
00003034 gate_node * ppo_ptr = dff_list;
00003035 while(ppo_ptr != NULL){
00003036 //Get current dff name
00003037 char curr_ppo[35];
00003038 strcpy(curr_ppo, ppo_ptr->gate_ptr->name);
00003039
00003040 string ppostr = "";
00003041 if(first_run == 0){
00003042 ppostr = strcat(curr_ppo, "_z1");
00003043 first_run = 1;
00003044 }
00003045 else{
00003046 strcpy(curr_ppo, ", ");
00003047 strcat(curr_ppo, ppo_ptr->gate_ptr->name);
00003048 ppostr = strcat(curr_ppo, "_z1");
00003049 }
00003050 output_list_str = output_list_str + ppostr;
00003051
00003052 ppo_ptr = ppo_ptr->next_ptr;
00003053 }
241
00003054
00003055 //Traverse all gates and output state (outputs)
00003056 struct level_node * level_ptr = level_list;
00003057 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00003058 for(int i = 1; i < max_level; i++){
00003059 //Traverse all gates on this level
00003060 gate_node * gate_ptr = level_ptr->gate_ptr;
00003061 while(gate_ptr != NULL){
00003062 //Get gate from gate node
00003063 struct gate * curr_gate = gate_ptr->gate_ptr;
00003064
00003065 //Define outputs
00003066 char z1[35];
00003067 string z1_str = "";
00003068 if(first_run == 0){
00003069 strcpy(z1, curr_gate->name);
00003070 z1_str = strcat(z1, "_z1");
00003071 first_run = 1;
00003072 }
00003073 else{
00003074 strcpy(z1, ", ");
00003075 strcat(z1, curr_gate->name);
00003076 z1_str = strcat(z1, "_z1");
00003077 }
00003078 output_list_str = output_list_str + z1_str;
00003079
00003080 gate_ptr = gate_ptr->next_ptr;
00003081 }
00003082 level_ptr = level_ptr->next_ptr;
00003083 }
00003084
00003085 //Add outputs to state list
00003086 //Traverse output list
00003087 /*gate_node * output_ptr = output_list;
00003088 while(output_ptr != NULL){
00003089 //Get current output name
00003090 char curr_output[20];
00003091 strcpy(curr_output, output_ptr->gate_ptr->name);
00003092
00003093 string outputstr = "";
00003094 if(first_run == 0){
00003095 outputstr = strcat(curr_output, "_z1");
00003096 first_run = 1;
00003097 }
00003098 else{
00003099 strcpy(curr_output, ", ");
00003100 strcat(curr_output, output_ptr->gate_ptr->name);
00003101 outputstr = strcat(curr_output, "_z1");
00003102 }
00003103 output_list_str = output_list_str + outputstr;
00003104
00003105 output_ptr = output_ptr->next_ptr;
00003106 }*/
00003107
00003108 return output_list_str;
00003109 }
00003110
00003111 //--------------------------------------------------------------------
00003112
00003113 string back_state_list_0(int max_level){
00003114 //Form input list string
00003115 string output_list_str = "";
00003116 int first_run = 0;
00003117
00003118 //Traverse input list
00003119 struct gate_node * input_ptr = input_list;
00003120 while(input_ptr != NULL){
00003121 //Get current input name
00003122 char curr_input[35];
242
00003123 strcpy(curr_input, input_ptr->gate_ptr->name);
00003124
00003125 string inputstr = "";
00003126 if(first_run == 0){
00003127 inputstr = strcat(curr_input, "_0");
00003128 first_run = 1;
00003129 }
00003130 else{
00003131 strcpy(curr_input, ", ");
00003132 strcat(curr_input, input_ptr->gate_ptr->name);
00003133 inputstr = strcat(curr_input, "_0");
00003134 }
00003135 output_list_str = output_list_str + inputstr;
00003136
00003137 input_ptr = input_ptr->next_ptr;
00003138 }
00003139
00003140 //Add ppis to state list
00003141 //Traverse dff list
00003142 gate_node * ppo_ptr = dff_list;
00003143 while(ppo_ptr != NULL){
00003144 //Get current dff name
00003145 char curr_ppo[35];
00003146 strcpy(curr_ppo, ppo_ptr->gate_ptr->name);
00003147
00003148 string ppostr = "";
00003149 if(first_run == 0){
00003150 ppostr = strcat(curr_ppo, "_z0");
00003151 first_run = 1;
00003152 }
00003153 else{
00003154 strcpy(curr_ppo, ", ");
00003155 strcat(curr_ppo, ppo_ptr->gate_ptr->name);
00003156 ppostr = strcat(curr_ppo, "_z0");
00003157 }
00003158 output_list_str = output_list_str + ppostr;
00003159
00003160 ppo_ptr = ppo_ptr->next_ptr;
00003161 }
00003162
00003163 //Traverse all gates and output state (outputs)
00003164 struct level_node * level_ptr = level_list;
00003165 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00003166 for(int i = 1; i < max_level; i++){
00003167 //Traverse all gates on this level
00003168 gate_node * gate_ptr = level_ptr->gate_ptr;
00003169 while(gate_ptr != NULL){
00003170 //Get gate from gate node
00003171 struct gate * curr_gate = gate_ptr->gate_ptr;
00003172
00003173 //Define outputs
00003174 char z0[35];
00003175 string z0_str = "";
00003176 if(first_run == 0){
00003177 strcpy(z0, curr_gate->name);
00003178 z0_str = strcat(z0, "_z0");
00003179 first_run = 1;
00003180 }
00003181 else{
00003182 strcpy(z0, ", ");
00003183 strcat(z0, curr_gate->name);
00003184 z0_str = strcat(z0, "_z0");
00003185 }
00003186 output_list_str = output_list_str + z0_str;
00003187
00003188 gate_ptr = gate_ptr->next_ptr;
00003189 }
00003190 level_ptr = level_ptr->next_ptr;
00003191 }
243
00003192
00003193 //Add outputs to state list
00003194 //Traverse output list
00003195 /*gate_node * output_ptr = output_list;
00003196 while(output_ptr != NULL){
00003197 //Get current output name
00003198 char curr_output[20];
00003199 strcpy(curr_output, output_ptr->gate_ptr->name);
00003200
00003201 string outputstr = "";
00003202 if(first_run == 0){
00003203 outputstr = strcat(curr_output, "_z0");
00003204 first_run = 1;
00003205 }
00003206 else{
00003207 strcpy(curr_output, ", ");
00003208 strcat(curr_output, output_ptr->gate_ptr->name);
00003209 outputstr = strcat(curr_output, "_z0");
00003210 }
00003211 output_list_str = output_list_str + outputstr;
00003212
00003213 output_ptr = output_ptr->next_ptr;
00003214 }*/
00003215
00003216 return output_list_str;
00003217 }
00003218
00003219 //--------------------------------------------------------------------
00003220
00003221 string back_wire_list_1(int max_level){
00003222 //Form input list string
00003223 string output_list_str = "";
00003224 int first_run = 0;
00003225
00003226 //Traverse input list
00003227 struct gate_node * input_ptr = input_list;
00003228 while(input_ptr != NULL){
00003229 //Get current input name
00003230 char curr_input[35];
00003231 strcpy(curr_input, input_ptr->gate_ptr->name);
00003232
00003233 string inputstr = "";
00003234 if(first_run == 0){
00003235 inputstr = strcat(curr_input, "_1");
00003236 first_run = 1;
00003237 }
00003238 else{
00003239 strcpy(curr_input, ", ");
00003240 strcat(curr_input, input_ptr->gate_ptr->name);
00003241 inputstr = strcat(curr_input, "_1");
00003242 }
00003243 output_list_str = output_list_str + inputstr;
00003244
00003245 input_ptr = input_ptr->next_ptr;
00003246 }
00003247
00003248 //Traverse all gates and output state (outputs)
00003249 struct level_node * level_ptr = level_list;
00003250 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00003251 for(int i = 1; i < max_level; i++){
00003252 //Traverse all gates on this level
00003253 gate_node * gate_ptr = level_ptr->gate_ptr;
00003254 while(gate_ptr != NULL){
00003255 //Get gate from gate node
00003256 struct gate * curr_gate = gate_ptr->gate_ptr;
00003257
00003258 //Define outputs
00003259 char z1[35];
00003260 string z1_str = "";
244
00003261 if(first_run == 0){
00003262 strcpy(z1, curr_gate->name);
00003263 z1_str = strcat(z1, "_z1");
00003264 first_run = 1;
00003265 }
00003266 else{
00003267 strcpy(z1, ", ");
00003268 strcat(z1, curr_gate->name);
00003269 z1_str = strcat(z1, "_z1");
00003270 }
00003271 output_list_str = output_list_str + z1_str;
00003272
00003273 gate_ptr = gate_ptr->next_ptr;
00003274 }
00003275 level_ptr = level_ptr->next_ptr;
00003276 }
00003277
00003278 return output_list_str;
00003279 }
00003280
00003281 //--------------------------------------------------------------------
00003282
00003283 string back_wire_list_0(int max_level){
00003284 //Form input list string
00003285 string output_list_str = "";
00003286 int first_run = 0;
00003287
00003288 //Traverse input list
00003289 struct gate_node * input_ptr = input_list;
00003290 while(input_ptr != NULL){
00003291 //Get current input name
00003292 char curr_input[35];
00003293 strcpy(curr_input, input_ptr->gate_ptr->name);
00003294
00003295 string inputstr = "";
00003296 if(first_run == 0){
00003297 inputstr = strcat(curr_input, "_0");
00003298 first_run = 1;
00003299 }
00003300 else{
00003301 strcpy(curr_input, ", ");
00003302 strcat(curr_input, input_ptr->gate_ptr->name);
00003303 inputstr = strcat(curr_input, "_0");
00003304 }
00003305 output_list_str = output_list_str + inputstr;
00003306
00003307 input_ptr = input_ptr->next_ptr;
00003308 }
00003309
00003310 //Traverse all gates and output state (outputs)
00003311 struct level_node * level_ptr = level_list;
00003312 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00003313 for(int i = 1; i < max_level; i++){
00003314 //Traverse all gates on this level
00003315 gate_node * gate_ptr = level_ptr->gate_ptr;
00003316 while(gate_ptr != NULL){
00003317 //Get gate from gate node
00003318 struct gate * curr_gate = gate_ptr->gate_ptr;
00003319
00003320 //Define outputs
00003321 char z0[35];
00003322 string z0_str = "";
00003323 if(first_run == 0){
00003324 strcpy(z0, curr_gate->name);
00003325 z0_str = strcat(z0, "_z0");
00003326 first_run = 1;
00003327 }
00003328 else{
00003329 strcpy(z0, ", ");
245
00003330 strcat(z0, curr_gate->name);
00003331 z0_str = strcat(z0, "_z0");
00003332 }
00003333 output_list_str = output_list_str + z0_str;
00003334
00003335 gate_ptr = gate_ptr->next_ptr;
00003336 }
00003337 level_ptr = level_ptr->next_ptr;
00003338 }
00003339
00003340 return output_list_str;
00003341 }
00003342
00003343 //--------------------------------------------------------------------
00003344
00003345 int back_gate_count(int max_level){
00003346 //Traverse all gates and output state (outputs)
00003347 struct level_node * level_ptr = level_list;
00003348 int count = 0;
00003349 level_ptr = level_ptr->next_ptr; //Skip lvl 0, inputs
00003350 for(int i = 1; i < max_level; i++){
00003351 //Traverse all gates on this level
00003352 struct gate_node * gate_ptr = level_ptr->gate_ptr;
00003353 while(gate_ptr != NULL){
00003354 count++;
00003355 gate_ptr = gate_ptr->next_ptr;
00003356 }
00003357 level_ptr = level_ptr->next_ptr;
00003358 }
00003359
00003360 return count;
00003361 }
00003362
00003363 //--------------------------------------------------------------------
00003364
00003365 string back_pi_list_1(){
00003366 //Form input list string
00003367 string input_list_str = "";
00003368 int first_run = 0;
00003369
00003370 //Traverse input list
00003371 struct gate_node * input_ptr = input_list;
00003372 while(input_ptr != NULL){
00003373 //Get current input name
00003374 char curr_input[35];
00003375 strcpy(curr_input, input_ptr->gate_ptr->name);
00003376
00003377 string inputstr = "";
00003378 if(first_run == 0){
00003379 inputstr = strcat(curr_input, "_o1");
00003380 first_run = 1;
00003381 }
00003382 else{
00003383 strcpy(curr_input, ", ");
00003384 strcat(curr_input, input_ptr->gate_ptr->name);
00003385 inputstr = strcat(curr_input, "_o1");
00003386 }
00003387 input_list_str = input_list_str + inputstr;
00003388
00003389 input_ptr = input_ptr->next_ptr;
00003390 }
00003391
00003392
00003393 return input_list_str;
00003394 }
00003395
00003396 //--------------------------------------------------------------------
00003397
00003398 string back_pi_list_0(){
246
00003399 //Form input list string
00003400 string input_list_str = "";
00003401 int first_run = 0;
00003402
00003403 //Traverse input list
00003404 struct gate_node * input_ptr = input_list;
00003405 while(input_ptr != NULL){
00003406 //Get current input name
00003407 char curr_input[35];
00003408 strcpy(curr_input, input_ptr->gate_ptr->name);
00003409
00003410 string inputstr = "";
00003411 if(first_run == 0){
00003412 inputstr = strcat(curr_input, "_o0");
00003413 first_run = 1;
00003414 }
00003415 else{
00003416 strcpy(curr_input, ", ");
00003417 strcat(curr_input, input_ptr->gate_ptr->name);
00003418 inputstr = strcat(curr_input, "_o0");
00003419 }
00003420 input_list_str = input_list_str + inputstr;
00003421
00003422 input_ptr = input_ptr->next_ptr;
00003423 }
00003424
00003425
00003426 return input_list_str;
00003427 }
00003428
00003429 //--------------------------------------------------------------------
00003430
00003431 int back_pi_count(){
00003432 //Traverse input list
00003433 struct gate_node * input_ptr = input_list;
00003434 int count = 0;
00003435 while(input_ptr != NULL){
00003436 count++;
00003437 input_ptr = input_ptr->next_ptr;
00003438 }
00003439
00003440 return count;
00003441 }
00003442
00003443 //--------------------------------------------------------------------
00003444
00003445 string back_ppo_list_1(){
00003446 //List ppos = dff outputs
00003447 string ppo_list_str = "";
00003448 int first_run = 0;
00003449
00003450 //Set up matricies for duplicate ppo handling
00003451 int ppo_array_size = fwd_ppi_count();
00003452 char ppo_name[ppo_array_size][35];
00003453 int ppo_count[ppo_array_size];
00003454 for(int i = 0; i < ppo_array_size; i++){
00003455 strcpy(ppo_name[i], "");
00003456 ppo_count[i] = 0;
00003457 }
00003458
00003459 //Traverse dff list
00003460 struct gate_node * ppo_ptr = dff_list;
00003461 while(ppo_ptr != NULL){
00003462 //Get current dff name
00003463 char curr_ppo[35];
00003464 strcpy(curr_ppo, ppo_ptr->gate_ptr->fanin_list->gate_ptr->name);
00003465
00003466 //Check if this PPO is also a PO
00003467 struct gate_node * po_ptr = output_list;
247
00003468 while((po_ptr != NULL) && (strcmp(po_ptr->gate_ptr->name, curr_ppo) !=
0)){
00003469 po_ptr = po_ptr->next_ptr;
00003470 }
00003471
00003472 //Check if this PPO has been used already
00003473 char ppo_tail[10];
00003474 strcpy(ppo_tail, "");
00003475 int k = 0;
00003476 while(k < ppo_array_size && strcmp(ppo_name[k], curr_ppo) != 0){
00003477 k++;
00003478 }
00003479 if(k == ppo_array_size) {
00003480 //First PPO use, add to list
00003481 int l = 0;
00003482 while(l < ppo_array_size && strcmp(ppo_name[l], "") != 0){
00003483 l++;
00003484 }
00003485 if (l == ppo_array_size) {
00003486 cout<<"ERROR: PPO ame array overflow."<<endl;
00003487 } else {
00003488 strcpy(ppo_name[l], curr_ppo);
00003489 ppo_count[l]++;
00003490 }
00003491 } else {
00003492 //Duplicate PPO, append unique # and incr count
00003493 strcpy(ppo_tail, "_");
00003494 char ppo_num[10];
00003495 sprintf(ppo_num, "%i", ppo_count[k]);
00003496 strcat(ppo_tail, ppo_num);
00003497 ppo_count[k]++;
00003498 }
00003499
00003500 string ppostr = "";
00003501 if(po_ptr == NULL){
00003502 //Regular PPO, output normally
00003503 if(first_run == 0){
00003504 strcat(curr_ppo, "_zo1");
00003505 ppostr = strcat(curr_ppo, ppo_tail);
00003506 first_run = 1;
00003507 }
00003508 else{
00003509 strcpy(curr_ppo, ", ");
00003510 strcat(curr_ppo, ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name);
00003511 strcat(curr_ppo, "_zo1");
00003512 ppostr = strcat(curr_ppo, ppo_tail);
00003513 }
00003514 }
00003515 else{
00003516 //Dual PPO/PO, output with _ppo
00003517 if(first_run == 0){
00003518 ppostr = strcat(curr_ppo, "_zo1_ppo");
00003519 first_run = 1;
00003520 }
00003521 else{
00003522 strcpy(curr_ppo, ", ");
00003523 strcat(curr_ppo, ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name);
00003524 ppostr = strcat(curr_ppo, "_zo1_ppo");
00003525 }
00003526 }
00003527 ppo_list_str = ppo_list_str + ppostr;
00003528
00003529 ppo_ptr = ppo_ptr->next_ptr;
00003530 }
00003531
00003532
00003533 return ppo_list_str;
248
00003534 }
00003535
00003536 //--------------------------------------------------------------------
00003537
00003538 string back_ppo_list_0(){
00003539 //List ppos = dff outputs
00003540 string ppo_list_str = "";
00003541 int first_run = 0;
00003542
00003543 //Set up matricies for duplicate ppo handling
00003544 int ppo_array_size = fwd_ppi_count();
00003545 char ppo_name[ppo_array_size][35];
00003546 int ppo_count[ppo_array_size];
00003547 for(int i = 0; i < ppo_array_size; i++){
00003548 strcpy(ppo_name[i], "");
00003549 ppo_count[i] = 0;
00003550 }
00003551
00003552 //Traverse dff list
00003553 struct gate_node * ppo_ptr = dff_list;
00003554 while(ppo_ptr != NULL){
00003555 //Get current dff name
00003556 char curr_ppo[35];
00003557 strcpy(curr_ppo, ppo_ptr->gate_ptr->fanin_list->gate_ptr->name);
00003558
00003559 //Check if this PPO is also a PO
00003560 struct gate_node * po_ptr = output_list;
00003561 while((po_ptr != NULL) && (strcmp(po_ptr->gate_ptr->name, curr_ppo) !=
0)){
00003562 po_ptr = po_ptr->next_ptr;
00003563 }
00003564
00003565 //Check if this PPO has been used already
00003566 char ppo_tail[10];
00003567 strcpy(ppo_tail, "");
00003568 int k = 0;
00003569 while(k < ppo_array_size && strcmp(ppo_name[k], curr_ppo) != 0){
00003570 k++;
00003571 }
00003572 if(k == ppo_array_size) {
00003573 //First PPO use, add to list
00003574 int l = 0;
00003575 while(l < ppo_array_size && strcmp(ppo_name[l], "") != 0){
00003576 l++;
00003577 }
00003578 if (l == ppo_array_size) {
00003579 cout<<"ERROR: PPO ame array overflow."<<endl;
00003580 } else {
00003581 strcpy(ppo_name[l], curr_ppo);
00003582 ppo_count[l]++;
00003583 }
00003584 } else {
00003585 //Duplicate PPO, append unique # and incr count
00003586 strcpy(ppo_tail, "_");
00003587 char ppo_num[10];
00003588 sprintf(ppo_num, "%i", ppo_count[k]);
00003589 strcat(ppo_tail, ppo_num);
00003590 ppo_count[k]++;
00003591 }
00003592
00003593 string ppostr = "";
00003594 if(po_ptr == NULL){
00003595 //Regular PPO, output normally
00003596 if(first_run == 0){
00003597 strcat(curr_ppo, "_zo0");
00003598 ppostr = strcat(curr_ppo, ppo_tail);
00003599 first_run = 1;
00003600 }
00003601 else{
249
00003602 strcpy(curr_ppo, ", ");
00003603 strcat(curr_ppo, ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name);
00003604 strcat(curr_ppo, "_zo0");
00003605 ppostr = strcat(curr_ppo, ppo_tail);
00003606 }
00003607 }
00003608 else{
00003609 //Dual PPO/PO, output with _ppo
00003610 if(first_run == 0){
00003611 ppostr = strcat(curr_ppo, "_zo0_ppo");
00003612 first_run = 1;
00003613 }
00003614 else{
00003615 strcpy(curr_ppo, ", ");
00003616 strcat(curr_ppo, ppo_ptr->gate_ptr->fanin_list-
>gate_ptr->name);
00003617 ppostr = strcat(curr_ppo, "_zo0_ppo");
00003618 }
00003619 }
00003620 ppo_list_str = ppo_list_str + ppostr;
00003621
00003622 ppo_ptr = ppo_ptr->next_ptr;
00003623 }
00003624
00003625
00003626 return ppo_list_str;
00003627 }
00003628
00003629 //--------------------------------------------------------------------
00003630
00003631 int back_ppo_count(){
00003632 //Count number of ppos = num of dffs
00003633 int count = 0;
00003634 struct gate_node * ppo_ptr = dff_list;
00003635 while(ppo_ptr != NULL){
00003636 count++;
00003637 ppo_ptr = ppo_ptr->next_ptr;
00003638 }
00003639
00003640 return count;
00003641 }
00003642
00003643 //----------
00003644
00003645 void makeupper(char str[]){
00003646 int i = 0;
00003647 while(i < sizeof(str)){
00003648 str[i] = toupper(str[i]);
00003649 i++;
00003650 }
00003651
00003652 return;
00003653 }
250
Appendix F: FPGA Algorithm & Network Integration TCL Script
Included in this appendix is the support TCL script described in Appendix A, which ties together
the base algorithm Verilog code with the generated Forward / Backward Network Verilog code.
This script finds all provided benchmark circuits and then for each one will run the network
translation program to generate Forward / Backward Networks. The n/m/l/s parameters from
those networks are then extracted and all of those values in the base Verilog are replaced with
these new values. Finally, the Verilog for the Forward and Backward Networks are merged with
the updated base Verilog to form one unified Verilog file for the given benchmark circuit.
00000001 #!/usr/bin/tclsh
00000002
00000003 set loc [file dirname [info script]]
00000004
00000005 set tf_code [list]
00000006 set fi [open ${loc}/tf.v r]
00000007 while {![eof $fi]} {
00000008 gets $fi fl
00000009 lappend tf_code $fl
00000010 }
00000011 catch {close $fi}
00000012
00000013 foreach file [glob -tails -directory ${loc}/bench *] {
00000014 set start_time [clock clicks -milliseconds]
00000015
00000016 #Generate fwd/back networks for bench
00000017 eval exec -- ./gen bench/${file}
00000018
00000019 if {[file exist ${loc}/fwd_net.v] && [file exist ${loc}/back_net.v]} {
00000020 set fo [open ${loc}/out/tf_[file rootname ${file}].v w]
00000021 puts $fo "'timescale 1ns / 1ps"
00000022 puts $fo ""
00000023
00000024 #Extract n/m/l/s parameters from networks
00000025 set n -1
00000026 set m -1
00000027 set l -1
00000028 set s -1
00000029 set ff [open ${loc}/fwd_net.v r]
00000030 while {![eof $ff]} {
00000031 gets $ff fl
00000032 set line_split [split [string trim $fl] " "]
00000033 if {[lindex $line_split 0] == "parameter"} {
00000034 if {[lindex $line_split 1] == "n"} {
00000035 set n [lindex $line_split 3]
00000036 } elseif {[lindex $line_split 1] == "m"} {
00000037 set m [lindex $line_split 3]
00000038 } elseif {[lindex $line_split 1] == "l"} {
00000039 set l [lindex $line_split 3]
00000040 } elseif {[lindex $line_split 1] == "s"} {
00000041 set s [lindex $line_split 3]
00000042 }
00000043 }
251
00000044 puts $fo $fl
00000045 }
00000046 catch {close $ff}
00000047
00000048 if {$m == -1 || $n == -1 || $l == -1 || $s == -1} {
00000049 puts "Parameter collection failed for ${file} (n=${n} m=${m}
l=${l} s=${s}"
00000050 } else {
00000051 set fb [open ${loc}/back_net.v r]
00000052 while {![eof $fb]} {
00000053 gets $fb fl
00000054 puts $fo $fl
00000055 }
00000056 catch {close $fb}
00000057
00000058 #Substitute in current bench parameter values
00000059 foreach line $tf_code {
00000060 if {[string match "parameter n *" [string trim $line]]}
{
00000061 puts $fo "parameter n = ${n}"
00000062 } elseif {[string match "parameter m *" [string trim
$line]]} {
00000063 puts $fo "parameter m = ${m}"
00000064 } elseif {[string match "parameter l *" [string trim
$line]]} {
00000065 puts $fo "parameter l = ${l}"
00000066 } elseif {[string match "parameter s *" [string trim
$line]]} {
00000067 puts $fo "parameter s = ${s}"
00000068 } else {
00000069 puts $fo $line
00000070 }
00000071 }
00000072 catch {close $fo}
00000073
00000074 puts "Generated networks for ${file} in [expr [clock clicks -
milliseconds] - $start_time]ms"
00000075 }
00000076
00000077 #Remove temporary network files
00000078 file delete -force ${loc}/fwd_net.v
00000079 file delete -force ${loc}/back_net.v
00000080 } else {
00000081 puts "ERROR: Network generation failed for ${file}"
00000082 }
00000083 }
00000084 puts "Done"
252
Appendix G: Formal CTL Rules Generation TCL Script
Included in this appendix is the support TCL script for generating CTL rules from benchmark
circuits, as described in section 4. In this case, the script reads in each provided benchmark
circuit, finds all OUTPUT statements, and then writes a rule that ANDs them all together. The
final rule is then “EF” for the AND term (eventually on some banch, everything is 1). This is
then written out to a file with the same name as the benchmark circuit, but with a “rules”
extension.
00000001 #!/usr/bin/tclsh
00000002
00000003 set loc [file dirname [info script]]
00000004
00000005 foreach file [glob -tails -directory ${loc}/bench *] {
00000006 set start_time [clock clicks -milliseconds]
00000007
00000008 #Get all OUTPUTs from bench
00000009 set out_terms [list]
00000010 set fi [open ${loc}/bench/${file} r]
00000011 while {![eof $fi]} {
00000012 gets $fi fl
00000013 if {[string match "OUTPUT(*" $fl]} {
00000014 lappend out_terms [string range $fl 7 [expr [string length $fl]
- 2]]
00000015 }
00000016 }
00000017 catch {close $fi}
00000018
00000019 #Create AND term for rules file
00000020 set out_and [lindex $out_terms 0]
00000021 set index 1
00000022 while {$index < [llength $out_terms]} {
00000023 set out_and "${out_and}, [lindex $out_terms $index]"
00000024 incr index
00000025 }
00000026
00000027 #Create a rules file for bench
00000028 set fo [open ${loc}/bench/[string range $file 0 [string last "." $file]]rules
w]
00000029 puts $fo "rule1 = EF( out )"
00000030 puts $fo "out = and (${out_and})"
00000031 catch {close $fo}
00000032
00000033 puts "Generated rules for ${file} in [expr [clock clicks -milliseconds] -
$start_time]ms"
00000034 }
253
Bibliography
[1] “The 2010 Mentor Graphics and Wilson Research Group Study on Functional
Verification,” In http://blogs.mentor.com/verificationhorizons/blog/2011/03/30/prologue-
the-2010-wilson-research-group-functional-verification-study, 2010.
[2] L. Lamport, "Proving the correctness of multiprocess programs,” IEEE Transactions on
Software Engineering, Vol. SE-3, no. 2, March 1977, pp. 124-143.
[3] A. Pnueli. “The Temporal Logic of Programs.” 18th Annual Symposium on the
Foundations of Computer Science, IEEE, November, 1977.
[4] M. R. A. Huth and M. D. Ryan, “Logic in Computer Science: Modeling and Reasoning
about Systems.” Cambridge University Press, 2000.
[5] E. Clarke, E. A. Emerson and A. Sistla, “Automatic Verification of Finite State
Concurrent Systems Using Temporal Logic Specifications,” ACM Trans. Programming
Languages and Systems, Vol. 1, no. 2, 1986, pp. 244-263.
[6] C. Eisner and D. Fisman, “Sugar 2.0 Proposal Presented to the Accellera Formal
Verification Technical Committee,” In
http://www.haifa.il.ibm.com/projects/verification/sugar/Sugar_2.0_Accellera.ps, 2002.
[7] “OpenVera Assertions,” white paper. Synopsys Inc, 2002.
[8] E. M. Clarke and E. A. Emerson. “Synthesis of synchronization skeletons for branching
time temporal logic.” in Logic of Programs: Workshop, Yorktown Heights, NY, May
1981. Volume 131 of Lecture Notes in Computer Science. Springer Verlag, 1981.
[9] K. L. McMillan, “Symbolic Model Checking,” Kluwer Academic Publishers, 1993.
[10] R. E. Bryant. “Graph based algorithms for boolean function manipulation.” IEEE
Transactions on Computers. C 35(8), 1986.
[11] M. Fujita. H. Fujisawa, and N. Kawato, “Evaluation and improvements of boolean
comparison method based on binary decision diagrams,” in Proceedings of the 1988
IEEE International Conference on Computer Aided Design. IEEE Computer Society
Press, November 1988.
254
[12] S. Malik, A. Wang, R. Brayton, and A. Sangiovanni Vincenteli. “Logic verification using
binary decision diagrams in a logic synthesis environment.” in International Conference
on Computer-Aided Design, pages 6-9, 1988.
[13] R. Rudell. “Dynamic variable ordering for ordered binary decision diagrams.” in Intl.
Conf. on Computer Aided Design. Santa Clara, CA. November 1993.
[14] K. S. Brace, R. L. Rudell, and R. E. Bryant. “Efficient implementation of a BDD
package.” in Proceedings of the 27th
ACM/IEEE Design Automation Conference. IEEE
Computer Society Press, June 1990.
[15] Martin Davis and Hilary Putnam, “A Computing Procedure for Quantification Theory.”
J. ACM Vol. 7, No. 3, (1960), 201-215.
[16] H. Zhang. “SATO: An efficient propositional prover.” in International Conference on
Automated Deduction (CADE’97), number 1249 in LNAI, pages 272-275. Springer-
Verlag, 1997.
[17] Davis, M., G. Logemann, and D. Loveland. “A machine program for theorem-proving.”
in Communications of the Association for Computing Machininery 5, 7 (July 1962), 394-
397.
[18] A Biere, A. Cimatti, E. M. Clarke and Y. Zhu, “Symbolic Model Checking without
BDDs.” Tools and Algorithms for the Analysis and Construction of Systems,
(TACAS’99), LNCS 1579, March 1999, pp. 193-207.
[19] F. Copty, L. Fix, R.Fraer, E. Gunchiglai, G. Kamhi, A. Tacchella and M. Y. Vardi,
“Benefits of Bounded Model Checking at an Industrial Setting,” Computer-Aided
Verification (CAV01), July 2001, pp. 436-453.
[20] D. B. Armstrong, “On Finding a Nearly Minimal Set of Fault Detection Tests for
Combinatorial Logic Nets,” IEEE Trans. On Computers, EC-15, No. 1 (February 1966),
pp. 66-73.
[21] M. Y. Hsiao and D. K. Chia, “Boolean Difference for Fault Detection in Asynchronous
Sequential Machines,” IEEE Trans. On Computers, C-20, No.11 (November 1971), pp.
1356-1361.
255
[22] J. P. Roth, W. G. Bouricius and P. R. Schneider, “Programmed Algorithms to Compute
Tests to Detect and Distinguish Between Failures in Logic Circuits,” IEEE Trans. On
Electronic Computers, Vol. EC-16, No. 10, pp.567-579, Oct. 1967.
[23] P. Goel, “An Implicit Enumeration Algorithm to Generate Tests for Combinatorial Logic
Circuits,” IEEE Trans. On Computers, Vol. C-30, No. 3 pp. 125-222, March 1981.
[24] H. Fujiwara and T. Shimono, “On the acceleration of test generation algorithms,” IEEE
Trans. On Computers, vol. C-32, pp. 1137-1144, Dec. 1983.
[25] M. H. Schulz, E. Trischler, and T. M. Sarfert, “SOCRATES: A highly efficient automatic
test pattern generation system,” IEEE Trans. Computer-Aided Design, vol. 7, pp. 126-
127, Jan. 1988.
[26] B. Keller, K. McCauley, J. Swenton and J. Youngs, “ATPG in Practical and non-
Traditional Applications,” Proceedings of the International Test Conference, October
1998, pp. 632–640
[27] V. Boppana, S. P. Rajan, K. Takayama and M. Fujita, “Model Checking Based on
Sequential ATPG,” Computer-Aided Verification, July 99, pp. 418–429.
[28] K. T. Cheng and A. Kristic, “Current Directions in Automatic Test-Generation,” IEEE
Design and Test, Vol. 32, November 1999, pp. 58-64.
[29] G. Parthasarathy, C.-Y. Huang and K.-T. Cheng, “An analysis of ATPG and SAT
algorithms for formal verification,” Proceedings High-Level Design Validation and Test
Workshop, November 2001, pp. 177-182.
[30] J. A. Abraham, V. M. Vedula, and D. G. Saab, “Verifying properties using sequential
atpg,” in Proc. Intl. Test Conf., 2002, pp. 194–202.
[31] Q. Qiang, C. Chang, D. Saab, and J. Abraham, “Case study of atpg-based model
checking: Verifying usb 2.0 ip core,” in Intl. Conf. on Computer Design, 2005.
[32] A. Czutro, I. Polian, M. Lewis, P. Engelke, S.M. Reddy, and B. Becker, "TIGUAN:
Thread-parallel integrated test pattern generator utilizing satisfiability analysis," in
International conference on VLSI Design, pages 227–232, 2009.
256
[33] X. Cai, P. Wohl, J.A. Waicukauski and P. Notiyath, “Highly Efficient Parallel ATPG
Based on Shared Memory,” in Proceedings of the International Test Conference,
November 2010, pp. 1-7.
[34] J.A.C. Sarmiento and F.J.R. Fernandez, “Methodology and platform for fault co-
emulation,” in Proceedings of the Latin American Test Workshop, March 2011, pp. 1-6.
[35] C. Dunbar and K. Nepal, “Using Platform FPGAs to Fault Emulation and Test-set
Generation to Detect Stuck-at Faults,” in Journal of Computers, Vol. 6, No. 11,
November 2011, pp. 2335-2344.
[36] M. Abramovici and D. Saab, “Satisfiability On Reconfigurable Hardware,” in Proc.
Intn’l. Workshop on Field-Programmable Logic and Applications, Sept. 1997.
[37] M. Abramovcic, J.T. de Sousa, and D. Saab, "A massively-parallel easily-scalable
satisfiability solver using reconfigurable hardware," in Design Automation Conference,
1999, 684–690.
[38] K. Gulati, S. Paul, S.P. Khatri, S. Patil and A. Jas, “FPGA-Based Hardware Acceleration
for Boolean Satisfiability,” in ACM Trans. Des. Autom. Elect. Syst, Vol. 14, Issue 2,
March 2009, Article 33.
[39] F. Kocan and D. G. Saab, “Atpg for combinational circuits on configurable hardware,”
IEEE Trans. on VLSI Systems, vol. 9, no. 1, pp. 117 – 129, Feb 2001.
[40] M. Abramovici, M. A. Breuer, and A. D. Friedman, “Digital Systems Testing and
Testable Design.” IEEE Press, 1990.
[41] R. A. Marlett, “Ebt: A comprehensive test generation technique for highly sequential
circuits,” in Proc. the 15th DAC, June 1978, pp. 335–339.