use getReq()/getAck() in isFull()
[fleet.git] / src / edu / berkeley / fleet / fpga / verilog / Verilog.java
1 package edu.berkeley.fleet.fpga.verilog;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.two.*;
4 import edu.berkeley.fleet.util.*;
5 import edu.berkeley.fleet.*;
6 import java.lang.reflect.*;
7 import java.util.*;
8 import java.io.*;
9 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
10
11 /*
12
13 - ideally: want to merge Fpga.dump() with this... but have to resolve
14   the handling of flushing first.
15
16 - eliminate uses of SimpleXXX
17    - force width parameter in remaining uses
18    - re-enable width checking (add zero-extend and sign-extend)
19
20 - ideally: make getVerilog() package-private somehow
21
22 - change Event constructors from Object[] to Event[]/Action[]
23 - change portorder to LinkedHashMap
24
25 => mangle the names given for strings
26 => ensure uniquification of percolated ports
27
28 => later: scan chain
29 */
30
31 /**
32  *  Among the benefits are:
33  *    - automatic scan-chain insertion
34  *    - better error-checking (for example, width mismatches) than Verilog provides
35  *    - pin percolation
36  *
37  *  One of the most annoying things about Verilog is that you cannot
38  *  "double-slice" a value; in other words, foo[10:2] is valid
39  *  Verilog, but foo[10:2][4:3] is not; the programmer must write
40  *  foo[4+2:3+2].  This lack of compositionality is the reason for
41  *  most of the complexity in the Value class.
42  */
43 public class Verilog {
44
45     public static interface Value {
46         public String  getVerilog();
47         public Value   getBits(int high, int low);
48         public Value   getBits(Mask mask);
49         public Trigger testMask(Mask mask);
50         public Value   invertBits();
51         public int     getWidth();
52     }
53
54     public static class SimpleValue implements Value {
55         public final String s;
56         private final String s0;
57         private final int high;
58         private final int low;
59         private final int width;
60         public SimpleValue(String s) { this(s, -1); }
61         public SimpleValue(String s, int width) {
62             this.s = s;
63             this.s0 = s;
64             this.high = -1;
65             this.low = -1;
66             this.width = width;
67         }
68         public SimpleValue(String s, int high, int low) {
69             this.s = s+"["+high+":"+low+"]";
70             this.s0 = s;
71             this.high = high;
72             this.low = low;
73             this.width = 1+high-low;
74         }
75         public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
76         public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
77         public Value getBits(int high, int low) {
78             if (this.high==-1 && this.low==-1) return new SimpleValue(s, high, low);
79             if (high+this.low > this.high) throw new RuntimeException("out of range");
80             return new SimpleValue(s0, high+this.low, low+this.low);
81         }
82         public String getVerilog() { return s; }
83         public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",width); }
84         public int getWidth() {
85             if (width==-1) throw new RuntimeException("not implemented");
86             return width;
87         }
88     }
89
90     public static class MuxValue implements Value {
91         private final Trigger sel;
92         private final Value if0;
93         private final Value if1;
94         public MuxValue(Trigger sel, Value if1, Value if0) {
95             this.sel = sel;
96             this.if0 = if0;
97             this.if1 = if1;
98             if (if0.getWidth() != if1.getWidth())
99                 throw new RuntimeException("width mismatch; "+if0+"="+if0.getWidth()+", "+if1+"="+if1.getWidth());
100         }
101         public int getWidth() { return if0.getWidth(); }
102         public String getVerilog() { return "("+sel.getVerilogTrigger()+" ? "+if1.getVerilog()+" : "+if0.getVerilog()+")"; }
103         public Value getBits(int high, int low) { return new MuxValue(sel, if1.getBits(high,low), if0.getBits(high,low)); }
104         public Value getBits(Mask mask) { return new MuxValue(sel, if1.getBits(mask), if0.getBits(mask)); }
105         public Value invertBits() { return new MuxValue(sel, if1.invertBits(), if0.invertBits()); }
106         public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
107     }
108
109     public static class ConstantValue implements Value {
110         private final BitVector bits;
111         public ConstantValue(BitVector bits) { this.bits = bits; }
112         public Value getBits(int high, int low) { return new ConstantValue(bits.get(high, low)); }
113         public Value getBits(Mask mask) { throw new RuntimeException("FIXME"); }
114         public Value invertBits() {
115             BitVector ret = new BitVector(bits.length());
116             for(int i=0; i<bits.length(); i++) ret.set(i, !bits.get(i));
117             return new ConstantValue(ret);
118         }
119         public String getVerilog() {
120             StringBuffer sb = new StringBuffer();
121             sb.append(bits.length());
122             sb.append("'b");
123             for(int i=bits.length()-1; i>=0; i--)
124                 sb.append(bits.get(i) ? '1' : '0');
125             return sb.toString();
126         }
127         public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
128         public int getWidth() { return bits.length(); }
129     }
130
131     public static class CatValue implements Value {
132         private final Value[] values;
133         public CatValue(Value[] values) { this.values = values; }
134         public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
135         public Value getBits(int high, int low) { throw new RuntimeException(); }
136         public int getWidth() {
137             int ret = 0;
138             for (Value val : values) ret += val.getWidth();
139             return ret;
140         }
141         public String getVerilog() {
142             StringBuffer sb = new StringBuffer();
143             sb.append("{ ");
144             boolean first = true;
145             for(int i=0; i<values.length; i++) {
146                 if (values[i]==null) continue;
147                 if (!first) sb.append(", ");
148                 sb.append(values[i].getVerilog());
149                 first = false;
150             }
151             sb.append(" }");
152             return sb.toString();
153         }
154         public Value invertBits() {
155             Value[] newvals = new Value[values.length];
156             for(int i=0; i<values.length; i++)
157                 newvals[i] = values[i].invertBits();
158             return new CatValue(newvals);
159         }
160         public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
161     }
162
163     public static class LogicValue implements Value {
164         public static enum LogicType { OR, AND };
165         private final Value v1;
166         private final Value v2;
167         private final LogicType tt;
168         public LogicValue(Value v1, LogicType tt, Value v2) {
169             this.v1 = v1;
170             this.v2 = v2;
171             this.tt = tt;
172             // FIXME: check width match
173         }
174         public String  getVerilog() {
175             switch(tt) {
176                 case OR:  return "("+v1.getVerilog()+"||"+v2.getVerilog()+")";
177                 case AND: return "("+v1.getVerilog()+"&&"+v2.getVerilog()+")";
178             }
179             throw new RuntimeException("impossible");
180         }
181         public Value   getBits(int high, int low) { return new LogicValue(v1.getBits(high,low),tt,v2.getBits(high,low)); }
182         public Value   getBits(Mask mask) { return new LogicValue(v1.getBits(mask),tt,v2.getBits(mask)); }
183         public Trigger testMask(Mask mask) { throw new RuntimeException("FIXME"); }
184         public Value   invertBits() { 
185             switch(tt) {
186                 case OR:  return new LogicValue(v1.invertBits(), LogicType.AND, v2.invertBits());
187                 case AND: return new LogicValue(v1.invertBits(), LogicType.OR, v2.invertBits());
188             }
189             throw new RuntimeException("impossible");
190         }
191         public int     getWidth() { return v1.getWidth(); }
192     }
193
194     public static class TestValue implements Value, Trigger {
195         public static enum TestType { NE, EQ, LT, GT, LE, GE };
196         private final Value v1;
197         private final Value v2;
198         private final TestType tt;
199         public TestValue(Value v1, TestType tt, Value v2) {
200             this.v1 = v1;
201             this.v2 = v2;
202             this.tt = tt;
203             // FIXME: check width match
204         }
205         public String  getVerilogTrigger() { return getVerilog(); }
206         public String  getVerilog() {
207             switch(tt) {
208                 case NE: return "("+v1.getVerilog()+"!="+v2.getVerilog()+")";
209                 case EQ: return "("+v1.getVerilog()+"=="+v2.getVerilog()+")";
210                 case LE: return "("+v1.getVerilog()+"<="+v2.getVerilog()+")";
211                 case GE: return "("+v1.getVerilog()+">="+v2.getVerilog()+")";
212                 case LT: return "("+v1.getVerilog()+"<" +v2.getVerilog()+")";
213                 case GT: return "("+v1.getVerilog()+">" +v2.getVerilog()+")";
214             }
215             throw new RuntimeException("impossible");
216         }
217         public Value   getBits(int high, int low) { throw new RuntimeException("you probably didn't mean to do this"); }
218         public Value   getBits(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
219         public Trigger testMask(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
220         public Trigger invert() { return invertMe(); }
221         public Value   invertBits() { return invertMe(); }
222         private TestValue invertMe() {
223             switch(tt) {
224                 case NE: return new TestValue(v1, TestType.EQ, v2);
225                 case EQ: return new TestValue(v1, TestType.NE, v2);
226                 case LE: return new TestValue(v1, TestType.GT, v2);
227                 case GE: return new TestValue(v1, TestType.LT, v2);
228                 case LT: return new TestValue(v1, TestType.GE, v2);
229                 case GT: return new TestValue(v1, TestType.LE, v2);
230             }
231             throw new RuntimeException("impossible");
232         }
233         public int     getWidth() { return 1; }
234     }
235
236     // Triggers //////////////////////////////////////////////////////////////////////////////
237
238     public static interface Trigger {
239         public String getVerilogTrigger();
240         public Trigger invert();
241     }
242
243     public static class SimpleTrigger implements Trigger {
244         private final String s;
245         public SimpleTrigger(String s) { this.s = s; }
246         public String getVerilogTrigger() { return s; }
247         public Trigger invert() { return new SimpleTrigger("!("+s+")"); }
248     }
249
250     public static class AndTrigger implements Trigger {
251         private final Trigger t1, t2;
252         public AndTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
253         public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" && "+t2.getVerilogTrigger()+")"; }
254         public Trigger invert() { return new InvertedTrigger(this); }
255     }
256
257     public static class OrTrigger implements Trigger {
258         private final Trigger t1, t2;
259         public OrTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
260         public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" || "+t2.getVerilogTrigger()+")"; }
261         public Trigger invert() { return new InvertedTrigger(this); }
262     }
263
264     public static class InvertedTrigger implements Trigger {
265         private final Trigger original;
266         public InvertedTrigger(Trigger original) { this.original = original; }
267         public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
268         public Trigger invert() { return original; }
269     }
270
271     public static class ConditionalTrigger implements Trigger {
272         public Trigger condition;
273         public Trigger trigger;
274         public ConditionalTrigger(Trigger condition, Trigger trigger) {
275             this.condition = condition;
276             this.trigger = trigger;
277         }
278         public String getVerilogTrigger() {
279             return "(("+condition.getVerilogTrigger()+") ? (" + trigger.getVerilogTrigger() + ") : 1)";
280         }
281         public Trigger invert() { return new InvertedTrigger(this); }
282     }
283
284     // Actions //////////////////////////////////////////////////////////////////////////////
285
286     public static interface Action {
287         public String getVerilogAction();
288     }
289
290     public static class ConditionalAction implements Action {
291         public Trigger condition;
292         public Action action;
293         public ConditionalAction(Trigger condition, Action action) {
294             this.condition = condition;
295             this.action = action;
296         }
297         public String getVerilogAction() { return "if ("+condition.getVerilogTrigger()+") begin "+action.getVerilogAction()+" end"; }
298     }
299
300     public static class AssignAction implements Action {
301         public Assignable left;
302         public Value right;
303         public AssignAction(Assignable left, Value right) {
304             this.left = left;
305             this.right = right;
306         }
307         public String getVerilogAction() { return left.getVerilog() + "<=" + right.getVerilog() + ";"; }
308     }
309
310     // Assignables //////////////////////////////////////////////////////////////////////////////
311
312     public static interface Assignable {
313         public String getVerilog();
314     }
315
316     public static class SimpleAssignable implements Assignable {
317         public final String s;
318         public SimpleAssignable(String s) { this.s = s; }
319         public String getVerilog() { return s; }
320     }
321
322     // Percolated Ports //////////////////////////////////////////////////////////////////////////////
323     
324     /**
325      *  A PercolatedPort is a connection to a top-level pin; it is
326      *  propagated up or down the hierarchy
327      */
328     public static class PercolatedPort {
329         public static enum PortType { UP, DOWN, INOUT };
330         public final String name;
331         public final int width;
332         public final PortType type;
333         public PercolatedPort(String name, int width, PortType type) {
334             this.name = name;
335             this.width = width;
336             this.type = type;
337         }
338     }
339
340
341     // Module Internals //////////////////////////////////////////////////////////////////////////////
342
343     public static class Module {
344         public void dump(String prefix) throws IOException {
345             PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
346             dump(pw, true);
347             pw.flush();
348             for(InstantiatedModule m : instantiatedModules)
349                 m.module.dump(prefix);
350         }
351         public int id = 0;
352         public final String name;
353         public String getName() { return name; }
354         public Port getPort(String name) { return ports.get(name); }
355
356         // order matters here
357         public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
358
359         // order matters here
360         public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
361         public final ArrayList<Event> events = new ArrayList<Event>();
362
363         // FIXME: always-alphabetical convention?
364         public final HashMap<String,Port> ports = new HashMap<String,Port>();
365         public final ArrayList<String> portorder = new ArrayList<String>();
366         public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
367         public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
368         public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
369         
370         public Module(String name) { this.name = name; }
371
372         public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); }
373         public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); }
374
375         // Latches and Wires //////////////////////////////////////////////////////////////////////////////
376
377         public class StateWire {
378             public final String name;
379             public final boolean initiallyFull;
380             public String getName() { return name; }
381             public Trigger isFull()  { return new SimpleTrigger("("+name+"==1)"); }
382             public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); }
383             public Action  doFill()  { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); }
384             public Action  doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); }
385             public String  getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; }
386             public StateWire(String name) { this(name, false); }
387             public StateWire(String name, boolean initiallyFull) {
388                 this.name = name;
389                 this.initiallyFull = initiallyFull;
390                 statewires.put(name, this);
391             }
392             public void dump(PrintWriter pw) {
393                 pw.println("  reg "+name+";");
394                 pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
395             }
396         }
397
398         public class Latch implements Assignable, Value {
399             public final String name;
400             public final int width;
401             public final long initial;
402             public Latch(String name, int width) { this(name, width, 0); }
403             public Latch(String name, int width, long initial) {
404                 this.width = width;
405                 this.name = name;
406                 this.initial = initial;
407                 latches.put(name, this);
408             }
409             public int getWidth() { return width; }
410             public String getVerilog() { return name; }
411             public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
412             public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
413             public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
414             public String getResetCode() { return name+"<="+initial+";"; }
415             public void dump(PrintWriter pw) {
416                 pw.println("  reg ["+(width-1)+":0] "+name+";");
417                 pw.println("  initial "+name+"="+initial+";");
418             }
419             public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }        
420         }
421
422         public class WireValue implements Value {
423             public final String name;
424             public final int width;
425             public final Value assign;
426             public WireValue(String name, int width, Value assign) {
427                 this.width = width;
428                 this.name = name;
429                 this.assign = assign;
430                 wires.put(name, this);
431             }
432             public int getWidth() { return width; }
433             public String getVerilog() { return name; }
434             public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
435             public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
436             public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
437             public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }        
438             public void dump(PrintWriter pw) { pw.println("  wire ["+(width-1)+":0] "+name+";"); }
439             public String getAssignments() { return "  assign "+name+" = "+assign.getVerilog()+";"; }
440         }
441
442         // Ports //////////////////////////////////////////////////////////////////////////////
443
444         public abstract class Port implements Action, Trigger {
445             final String name;
446             final int width;
447             final boolean external;
448             public Port(String name, int width, boolean external) {
449                 this.width = width;
450                 this.name = name;
451                 this.external = external;
452                 if (ports.get(name)!=null)
453                     throw new RuntimeException("port "+name+" already exists");
454                 ports.put(name, this);
455                 if (external)
456                     portorder.add(name);
457             }
458             public String getName() { return name; }
459             public int getWidth() { return width; }
460             public String getVerilog() { return name; }
461             String getAck() { return name+"_a"; }
462             String getReq() { return name+"_r"; }
463             public String isFull() { return "("+getReq()+" && !"+getAck()+")"; }
464             public abstract String getResetCode();
465             public abstract String getInterface();
466             public abstract String getSimpleInterface();
467             public abstract String getDeclaration();
468             public abstract String getAssignments();
469             public abstract String getCleanup();
470             public Trigger invert() { return new InvertedTrigger(this); }
471             public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
472         }
473
474         public class SourcePort extends Port implements Value {
475             private SinkPort driven = null;
476             public SourcePort(String name, int width, boolean external) { super(name, width, external); }
477             public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
478             public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
479             public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
480             public String getVerilogTrigger() { return getReq() + " && !"+getAck(); }
481             public String getVerilogAction() { return getAck() + " <= 1;"; }
482             public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
483             public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
484             public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; }
485             public String getDeclaration() {
486                 StringBuffer sb = new StringBuffer();
487                 if (external) {
488                     sb.append("input "  +                           name +"_r;\n");
489                     sb.append("output " +                           name +"_a_;\n");
490                     sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n");
491                 } else {
492                     sb.append("wire "  +                            name +"_r;\n");
493                     sb.append("wire ["+Math.max(0,width-1)+":0]"  + name +";\n");
494                 }
495                 if (driven!=null) {
496                     sb.append("wire "    +                 name +"_a;\n");
497                 } else {
498                     sb.append("reg "    +                  name +"_a;\n");
499                     sb.append("initial " +                 name +"_a = 0;\n");
500                 }
501                 return sb.toString();
502             }
503             public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; }
504             public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
505             public String getAssignments() {
506                 StringBuffer sb = new StringBuffer();
507                 if (external)
508                     sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
509                 return sb.toString();
510             }
511             public void connect(SinkPort driven) {
512                 if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver");
513                 if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver");
514                 if (this.driven!=null) throw new RuntimeException("driver already has a driven net");
515                 this.driven = driven;
516                 driven.controlDriver = this;
517                 driven.latchDriver = this;
518                 // FIXME
519                 // if (getWidth() != driven.getWidth())
520                 // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth());
521             }
522         }
523         
524         public class SinkPort extends Port implements Assignable {
525             SourcePort controlDriver = null;
526             Value latchDriver = null;
527             public SinkPort(String name, int width, boolean external) { super(name, width, external); }
528             public String getVerilogAction() { return getReq() + " <= 1;"; }
529             public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); }
530             public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
531             public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
532             public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; }
533             public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); }
534             public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; }
535             public void connectControl(SourcePort controlDriver) {
536                 if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice");
537                 this.controlDriver = controlDriver;
538             }
539             public void connectValue(Value val) {
540                 //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()");
541                 this.latchDriver = val;
542                 // FIXME
543                 //if (getWidth() != val.getWidth())
544                 //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth());
545             }
546             public String getDeclaration() {
547                 StringBuffer sb = new StringBuffer();
548                 if (external) {
549                     sb.append("output "  +                           name +"_r_;\n");
550                     sb.append("input "   +                           name +"_a;\n");
551                     sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n");
552                 } else {
553                     sb.append("wire "   +                 name +"_a;\n");
554                 }
555                 if (controlDriver!=null) {
556                     sb.append("wire "    +                 name +"_r;\n");
557                     sb.append("wire   ["+Math.max(0,width-1)+":0]" + name +";\n");
558                 } else {
559                     sb.append("reg "    +                  name +"_r;\n");
560                     sb.append("initial " +                 name +"_r = 0;\n");
561                     if (latchDriver!=null) sb.append("wire   ["+Math.max(0,width-1)+":0]" + name +";\n");
562                     else                   sb.append("reg    ["+Math.max(0,width-1)+":0]" + name +";\n");
563                 }
564                 return sb.toString();
565             }
566             public String getAssignments() {
567                 StringBuffer sb = new StringBuffer();
568                 if (external) {
569                     sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
570                     sb.append("assign " +                  name +"_ = " + name + ";\n");
571                 }
572                 if (controlDriver != null) {
573                     sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n");
574                     sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n");
575                     if (latchDriver==null)
576                         sb.append("assign " + name +"   = " + controlDriver.name + ";\n");
577                 }
578                 if (latchDriver != null)
579                     sb.append("assign " + name +"   = " + latchDriver.getVerilog() + ";\n");
580                 return sb.toString();
581             }
582         }
583
584         // InstantiatedModule //////////////////////////////////////////////////////////////////////////////
585
586         public static class InstantiatedModule {
587             public final Module module;
588             public final Module thisModule;
589             public final int id;
590             public final HashMap<String,Port> ports = new HashMap<String,Port>();
591             public String getName() { return module.getName()+"_"+id; }
592             public InstantiatedModule(Module thisModule, Module module) {
593                 this.thisModule = thisModule;
594                 this.module = module;
595                 this.id = thisModule.id++;
596                 thisModule.instantiatedModules.add(this);
597                 for(String s : module.portorder)
598                     getPort(s);
599             }
600             public void dump(PrintWriter pw) {
601                 pw.println("  " + module.getName() + " " + getName() + "(clk, rst ");
602                 for(String s : module.portorder)
603                     pw.println(", " + getPort(s).getSimpleInterface());
604                 for(PercolatedPort pp : module.percolatedPorts)
605                     pw.println("    , "+pp.name);
606                 pw.println("   );");
607             }
608             public Port getPort(String name) {
609                 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
610             }
611             public SinkPort getInputPort(String name) {
612                 int width = module.getPort(name).getWidth();
613                 SinkPort port = (SinkPort)ports.get(name);
614                 if (port == null) {
615                     port = thisModule.new SinkPort(getName()+"_"+name, width, false);
616                     ports.put(name, port);
617                 }
618                 return port;
619             }
620             public SourcePort getOutputPort(String name) {
621                 int width = module.getPort(name).getWidth();
622                 SourcePort port = (SourcePort)ports.get(name);
623                 if (port == null) {
624                     port = thisModule.new SourcePort(getName()+"_"+name, width, false);
625                     ports.put(name, port);
626                 }
627                 return port;
628             }
629         }
630
631         public void dump(PrintWriter pw, boolean fix) {
632                 if (!fix) throw new RuntimeException();
633             boolean isRoot = name.equals("main");
634             pw.print("module "+name);
635             pw.println(isRoot ? "(clk_pin, rst_pin " : "(clk, rst ");
636             for(String name : portorder) pw.println("    , " + ports.get(name).getInterface());
637             for (InstantiatedModule im : this.instantiatedModules)
638                 for(PercolatedPort pp : im.module.percolatedPorts)
639                     if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
640                         pw.println("    , "+pp.name);
641             pw.println("   );");
642             pw.println();
643
644             if (isRoot) {
645                 pw.println("  input clk_pin;");
646                 pw.println("  input rst_pin;");
647                 pw.println("  wire clk;");
648                 pw.println("  wire clk_fb;");
649                 pw.println("  wire clk_unbuffered;");
650                 pw.println("  assign clk_unbuffered = clk_pin;");
651                 //pw.println("  assign clk = clk_pin;");
652
653                 pw.println("  BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
654                 /*
655                 pw.println("  DCM");
656                 pw.println("   #(");
657                 pw.println("      .CLKFX_MULTIPLY(4),");
658                 pw.println("      .CLKFX_DIVIDE(8),");
659                 pw.println("      .CLKIN_PERIOD(\"10 ns\")");
660                 pw.println("    ) mydcm(");
661                 pw.println("      .CLKIN (clk_pin),");
662                 pw.println("      .CLKFB(clk_fb),");
663                 pw.println("      .CLKFX (clk_unbuffered),");
664                 pw.println("      .CLK0  (clk_fb)");
665                 pw.println("    );");
666                 */
667                 pw.println("  wire rst;");
668             } else {
669                 pw.println("    input clk;");
670                 pw.println("    input rst;");
671             }
672
673             for (InstantiatedModule im : this.instantiatedModules)
674                 for(PercolatedPort pp : im.module.percolatedPorts) {
675                     if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
676                         pw.print("wire");
677                     else  switch(pp.type) {
678                             case UP:    pw.print("output"); break;
679                             case DOWN:  pw.print("input");  break;
680                             case INOUT: pw.print("inout");  break;
681                         }
682                     pw.print("  ");
683                     if (pp.width > 1)
684                         pw.print("["+(pp.width-1)+":0]");
685                     pw.print(" ");
686                     pw.print(pp.name);
687                     pw.println(";");
688                 }
689
690             if (isRoot) {
691                 pw.println("  assign rst    = rst_out;");
692                 pw.println("  assign rst_in = !rst_pin;");
693             }
694
695             for(String name : ports.keySet()) pw.println("    " + ports.get(name).getDeclaration());
696             for(StateWire sw : statewires.values()) sw.dump(pw);
697             for(Latch l : latches.values()) l.dump(pw);
698             for(WireValue wv : wires.values()) wv.dump(pw);
699             for(String name : ports.keySet()) pw.println("    " + ports.get(name).getAssignments());
700             for(WireValue wv : wires.values()) pw.println("    " + wv.getAssignments());
701             for(InstantiatedModule m : instantiatedModules) m.dump(pw);
702             pw.println("always @(posedge clk) begin");
703             pw.println("  if (rst) begin");
704             for(Latch l : latches.values()) pw.println(l.getResetCode());
705             for(StateWire sw : statewires.values()) pw.println(sw.getResetCode());
706             for(Port p : ports.values()) pw.println(p.getResetCode());
707             pw.println("  end else begin");
708             for(Port p : ports.values()) pw.println(p.getCleanup());
709             for(Event a : events) a.dump(pw, fix);
710             pw.println("    begin end");
711             pw.println("    end");
712             pw.println("  end");
713             pw.println("endmodule");
714         }
715
716         public class Event {
717             public Object[]  triggers;
718             public Object[]  actions;
719             public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
720             public Event(Object[] triggers, Object[] actions) {
721                 Module.this.events.add(this);
722                 this.triggers = triggers;
723                 this.actions = actions;
724             }
725             public void dump(PrintWriter pw, boolean fix) {
726                 if (!fix) throw new RuntimeException();
727                 pw.print("if (1");
728                 for(Object o : triggers) {
729                     if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
730                     else                      pw.print(" && " + o);
731                 }
732                 pw.println(") begin ");
733                 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
734                 if (fix) pw.println("end /*else*/ ");
735                 else     pw.println("end else ");
736             }
737         }
738     }
739 }