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.*;
9 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
13 - ideally: want to merge Fpga.dump() with this... but have to resolve
14 the handling of flushing first.
16 - eliminate uses of SimpleXXX
17 - force width parameter in remaining uses
18 - re-enable width checking (add zero-extend and sign-extend)
20 - ideally: make getVerilog() package-private somehow
22 - change Event constructors from Object[] to Event[]/Action[]
23 - change portorder to LinkedHashMap
25 => mangle the names given for strings
26 => ensure uniquification of percolated ports
32 * Among the benefits are:
33 * - automatic scan-chain insertion
34 * - better error-checking (for example, width mismatches) than Verilog provides
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.
43 public class Verilog {
45 public static final int FORWARD_LATENCY = 6; // must be >=1
46 public static final int REVERSE_LATENCY = 4; // must be >=3
48 public static interface Value {
49 public String getVerilog();
50 public Value getBits(int high, int low);
51 public Value getBits(Mask mask);
52 public Trigger testMask(Mask mask);
53 public Value invertBits();
54 public int getWidth();
57 public static class SimpleValue implements Value {
58 public final String s;
59 private final String s0;
60 private final int high;
61 private final int low;
62 private final int width;
63 public SimpleValue(String s) { this(s, -1); }
64 public SimpleValue(String s, int width) {
71 public SimpleValue(String s, int high, int low) {
72 this.s = s+"["+high+":"+low+"]";
76 this.width = 1+high-low;
78 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
79 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
80 public Value getBits(int high, int low) {
81 if (this.high==-1 && this.low==-1) return new SimpleValue(s, high, low);
82 if (high+this.low > this.high) throw new RuntimeException("out of range");
83 return new SimpleValue(s0, high+this.low, low+this.low);
85 public String getVerilog() { return s; }
86 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",width); }
87 public int getWidth() {
88 if (width==-1) throw new RuntimeException("not implemented");
93 public static class MuxValue implements Value {
94 private final Trigger sel;
95 private final Value if0;
96 private final Value if1;
97 public MuxValue(Trigger sel, Value if1, Value if0) {
101 if (if0.getWidth() != if1.getWidth())
102 throw new RuntimeException("width mismatch; "+if0+"="+if0.getWidth()+", "+if1+"="+if1.getWidth());
104 public int getWidth() { return if0.getWidth(); }
105 public String getVerilog() { return "("+sel.getVerilogTrigger()+" ? "+if1.getVerilog()+" : "+if0.getVerilog()+")"; }
106 public Value getBits(int high, int low) { return new MuxValue(sel, if1.getBits(high,low), if0.getBits(high,low)); }
107 public Value getBits(Mask mask) { return new MuxValue(sel, if1.getBits(mask), if0.getBits(mask)); }
108 public Value invertBits() { return new MuxValue(sel, if1.invertBits(), if0.invertBits()); }
109 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
112 public static class ConstantValue implements Value {
113 private final BitVector bits;
114 public ConstantValue(BitVector bits) { this.bits = bits; }
115 public Value getBits(int high, int low) { return new ConstantValue(bits.get(high, low)); }
116 public Value getBits(Mask mask) { throw new RuntimeException("FIXME"); }
117 public Value invertBits() {
118 BitVector ret = new BitVector(bits.length());
119 for(int i=0; i<bits.length(); i++) ret.set(i, !bits.get(i));
120 return new ConstantValue(ret);
122 public String getVerilog() {
123 StringBuffer sb = new StringBuffer();
124 sb.append(bits.length());
126 for(int i=bits.length()-1; i>=0; i--)
127 sb.append(bits.get(i) ? '1' : '0');
128 return sb.toString();
130 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
131 public int getWidth() { return bits.length(); }
134 public static class CatValue implements Value {
135 private final Value[] values;
136 public CatValue(Value[] values) { this.values = values; }
137 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
138 public Value getBits(int high, int low) { throw new RuntimeException(); }
139 public int getWidth() {
141 for (Value val : values) ret += val.getWidth();
144 public String getVerilog() {
145 StringBuffer sb = new StringBuffer();
147 boolean first = true;
148 for(int i=0; i<values.length; i++) {
149 if (values[i]==null) continue;
150 if (!first) sb.append(", ");
151 sb.append(values[i].getVerilog());
155 return sb.toString();
157 public Value invertBits() {
158 Value[] newvals = new Value[values.length];
159 for(int i=0; i<values.length; i++)
160 newvals[i] = values[i].invertBits();
161 return new CatValue(newvals);
163 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
166 public static class LogicValue implements Value {
167 public static enum LogicType { OR, AND };
168 private final Value v1;
169 private final Value v2;
170 private final LogicType tt;
171 public LogicValue(Value v1, LogicType tt, Value v2) {
175 // FIXME: check width match
177 public String getVerilog() {
179 case OR: return "("+v1.getVerilog()+"||"+v2.getVerilog()+")";
180 case AND: return "("+v1.getVerilog()+"&&"+v2.getVerilog()+")";
182 throw new RuntimeException("impossible");
184 public Value getBits(int high, int low) { return new LogicValue(v1.getBits(high,low),tt,v2.getBits(high,low)); }
185 public Value getBits(Mask mask) { return new LogicValue(v1.getBits(mask),tt,v2.getBits(mask)); }
186 public Trigger testMask(Mask mask) { throw new RuntimeException("FIXME"); }
187 public Value invertBits() {
189 case OR: return new LogicValue(v1.invertBits(), LogicType.AND, v2.invertBits());
190 case AND: return new LogicValue(v1.invertBits(), LogicType.OR, v2.invertBits());
192 throw new RuntimeException("impossible");
194 public int getWidth() { return v1.getWidth(); }
197 public static class TestValue implements Value, Trigger {
198 public static enum TestType { NE, EQ, LT, GT, LE, GE };
199 private final Value v1;
200 private final Value v2;
201 private final TestType tt;
202 public TestValue(Value v1, TestType tt, Value v2) {
206 // FIXME: check width match
208 public String getVerilogTrigger() { return getVerilog(); }
209 public String getVerilog() {
211 case NE: return "("+v1.getVerilog()+"!="+v2.getVerilog()+")";
212 case EQ: return "("+v1.getVerilog()+"=="+v2.getVerilog()+")";
213 case LE: return "("+v1.getVerilog()+"<="+v2.getVerilog()+")";
214 case GE: return "("+v1.getVerilog()+">="+v2.getVerilog()+")";
215 case LT: return "("+v1.getVerilog()+"<" +v2.getVerilog()+")";
216 case GT: return "("+v1.getVerilog()+">" +v2.getVerilog()+")";
218 throw new RuntimeException("impossible");
220 public Value getBits(int high, int low) { throw new RuntimeException("you probably didn't mean to do this"); }
221 public Value getBits(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
222 public Trigger testMask(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
223 public Trigger invert() { return invertMe(); }
224 public Value invertBits() { return invertMe(); }
225 private TestValue invertMe() {
227 case NE: return new TestValue(v1, TestType.EQ, v2);
228 case EQ: return new TestValue(v1, TestType.NE, v2);
229 case LE: return new TestValue(v1, TestType.GT, v2);
230 case GE: return new TestValue(v1, TestType.LT, v2);
231 case LT: return new TestValue(v1, TestType.GE, v2);
232 case GT: return new TestValue(v1, TestType.LE, v2);
234 throw new RuntimeException("impossible");
236 public int getWidth() { return 1; }
239 // Triggers //////////////////////////////////////////////////////////////////////////////
241 public static interface Trigger {
242 public String getVerilogTrigger();
243 public Trigger invert();
246 public static class SimpleTrigger implements Trigger {
247 private final String s;
248 public SimpleTrigger(String s) { this.s = s; }
249 public String getVerilogTrigger() { return s; }
250 public Trigger invert() { return new SimpleTrigger("!("+s+")"); }
253 public static class AndTrigger implements Trigger {
254 private final Trigger t1, t2;
255 public AndTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
256 public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" && "+t2.getVerilogTrigger()+")"; }
257 public Trigger invert() { return new InvertedTrigger(this); }
260 public static class OrTrigger implements Trigger {
261 private final Trigger t1, t2;
262 public OrTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
263 public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" || "+t2.getVerilogTrigger()+")"; }
264 public Trigger invert() { return new InvertedTrigger(this); }
267 public static class InvertedTrigger implements Trigger {
268 private final Trigger original;
269 public InvertedTrigger(Trigger original) { this.original = original; }
270 public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
271 public Trigger invert() { return original; }
274 public static class ConditionalTrigger implements Trigger {
275 public Trigger condition;
276 public Trigger trigger;
277 public ConditionalTrigger(Trigger condition, Trigger trigger) {
278 this.condition = condition;
279 this.trigger = trigger;
281 public String getVerilogTrigger() {
282 return "(("+condition.getVerilogTrigger()+") ? (" + trigger.getVerilogTrigger() + ") : 1)";
284 public Trigger invert() { return new InvertedTrigger(this); }
287 // Actions //////////////////////////////////////////////////////////////////////////////
289 public static interface Action {
290 public String getVerilogAction();
293 public static class ConditionalAction implements Action {
294 public Trigger condition;
295 public Action action;
296 public ConditionalAction(Trigger condition, Action action) {
297 this.condition = condition;
298 this.action = action;
300 public String getVerilogAction() { return "if ("+condition.getVerilogTrigger()+") begin "+action.getVerilogAction()+" end"; }
303 public static class AssignAction implements Action {
304 public Assignable left;
306 public AssignAction(Assignable left, Value right) {
310 public String getVerilogAction() { return left.getVerilog() + "<=" + right.getVerilog() + ";"; }
313 // Assignables //////////////////////////////////////////////////////////////////////////////
315 public static interface Assignable {
316 public String getVerilog();
319 public static class SimpleAssignable implements Assignable {
320 public final String s;
321 public SimpleAssignable(String s) { this.s = s; }
322 public String getVerilog() { return s; }
325 // Module Internals //////////////////////////////////////////////////////////////////////////////
327 public static class Module {
328 // order matters here
329 public LinkedHashMap<String,InstantiatedModule> instantiatedModules = new LinkedHashMap<String,InstantiatedModule>();
331 public void dump(String prefix) throws IOException {
332 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
335 for(InstantiatedModule m : instantiatedModules.values())
336 m.module.dump(prefix);
339 public final String name;
340 public String getName() { return name; }
341 public Port getPort(String name) { return ports.get(name); }
343 // order matters here
344 public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
345 public final ArrayList<Event> events = new ArrayList<Event>();
347 // FIXME: always-alphabetical convention?
348 public final HashMap<String,Port> ports = new HashMap<String,Port>();
349 public final ArrayList<String> portorder = new ArrayList<String>();
350 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
351 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
352 public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
354 public Module(String name) { this.name = name; }
356 public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); }
357 public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); }
359 // Latches and Wires //////////////////////////////////////////////////////////////////////////////
361 public class StateWire {
362 public final String name;
363 public final boolean initiallyFull;
364 public String getName() { return name; }
365 public Trigger isFull() { return new SimpleTrigger("("+name+"==1)"); }
366 public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); }
367 public Action doFill() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); }
368 public Action doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); }
369 public String getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; }
370 public StateWire(String name) { this(name, false); }
371 public StateWire(String name, boolean initiallyFull) {
373 this.initiallyFull = initiallyFull;
374 statewires.put(name, this);
376 public void dump(PrintWriter pw) {
377 pw.println(" reg "+name+";");
378 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
382 public class Latch implements Assignable, Value {
383 public final String name;
384 public final int width;
385 public final long initial;
386 public Latch(String name, int width) { this(name, width, 0); }
387 public Latch(String name, int width, long initial) {
390 this.initial = initial;
391 latches.put(name, this);
393 public int getWidth() { return width; }
394 public String getVerilog() { return name; }
395 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
396 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
397 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
398 public String getResetCode() { return name+"<="+initial+";"; }
399 public void dump(PrintWriter pw) {
400 pw.println(" reg ["+(width-1)+":0] "+name+";");
401 pw.println(" initial "+name+"="+initial+";");
403 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
406 public class WireValue implements Value {
407 public final String name;
408 public final int width;
409 public final Value assign;
410 public WireValue(String name, int width, Value assign) {
413 this.assign = assign;
414 wires.put(name, this);
416 public int getWidth() { return width; }
417 public String getVerilog() { return name; }
418 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
419 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
420 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
421 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
422 public void dump(PrintWriter pw) { pw.println(" wire ["+(width-1)+":0] "+name+";"); }
423 public String getAssignments() { return " assign "+name+" = "+assign.getVerilog()+";"; }
426 // Ports //////////////////////////////////////////////////////////////////////////////
428 public abstract class Port implements Action, Trigger {
431 final boolean external;
432 public Port(String name, int width, boolean external) {
435 this.external = external;
436 if (ports.get(name)!=null)
437 throw new RuntimeException("port "+name+" already exists");
438 ports.put(name, this);
442 public String getName() { return name; }
443 public int getWidth() { return width; }
444 public String getVerilog() { return name; }
445 String getAck() { return name+"_a"; }
446 String getReq() { return name+"_r"; }
447 public String isFull() { return "("+getReq()+" && !"+getAck()+")"; }
448 public abstract String getResetCode();
449 public abstract String getInterface();
450 public abstract String getSimpleInterface();
451 public abstract String getDeclaration();
452 public abstract String getAssignments();
453 public abstract String getCleanup();
454 public Trigger invert() { return new InvertedTrigger(this); }
455 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
458 public class SourcePort extends Port implements Value {
459 private SinkPort driven = null;
460 public SourcePort(String name, int width, boolean external) { super(name, width, external); }
461 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
462 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
463 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
464 public String getVerilogTrigger() { return getReq() + " && !"+getAck(); }
465 public String getVerilogAction() { return getAck() + " <= 1;"; }
466 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
467 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
468 public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; }
469 public String getDeclaration() {
470 StringBuffer sb = new StringBuffer();
472 sb.append("input " + name +"_r;\n");
473 sb.append("output " + name +"_a_;\n");
474 sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n");
476 sb.append("wire " + name +"_r;\n");
477 sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
480 sb.append("wire " + name +"_a;\n");
482 sb.append("reg " + name +"_a;\n");
483 sb.append("initial " + name +"_a = 0;\n");
485 return sb.toString();
487 public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; }
488 public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
489 public String getAssignments() {
490 StringBuffer sb = new StringBuffer();
492 int a = REVERSE_LATENCY - 3;
494 throw new RuntimeException("cannot offer latency of " + REVERSE_LATENCY +"-3");
496 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
498 a = a-1; // CLK-to-Q gives us one cycle of latency anyways
499 sb.append("SRL16E srl16_"+name+"_a\n");
500 sb.append(" (.Q ("+name+"_a_),\n");
501 sb.append(" .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
502 sb.append(" .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
503 sb.append(" .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
504 sb.append(" .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
505 sb.append(" .CE (1),\n");
506 sb.append(" .CLK (clk),\n");
507 sb.append(" .D ("+name+"_a));\n");
510 return sb.toString();
512 public void connect(SinkPort driven) {
513 if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver");
514 if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver");
515 if (this.driven!=null) throw new RuntimeException("driver already has a driven net");
516 this.driven = driven;
517 driven.controlDriver = this;
518 driven.latchDriver = this;
520 // if (getWidth() != driven.getWidth())
521 // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth());
525 public class SinkPort extends Port implements Assignable {
526 SourcePort controlDriver = null;
527 Value latchDriver = null;
528 public SinkPort(String name, int width, boolean external) { super(name, width, external); }
529 public String getVerilogAction() { return getReq() + " <= 1;"; }
530 public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); }
531 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
532 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
533 public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; }
534 public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); }
535 public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; }
536 public void connectControl(SourcePort controlDriver) {
537 if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice");
538 this.controlDriver = controlDriver;
540 public void connectValue(Value val) {
541 //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()");
542 this.latchDriver = val;
544 //if (getWidth() != val.getWidth())
545 //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth());
547 public String getDeclaration() {
548 StringBuffer sb = new StringBuffer();
550 sb.append("output " + name +"_r_;\n");
551 sb.append("input " + name +"_a;\n");
552 sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n");
554 sb.append("wire " + name +"_a;\n");
556 if (controlDriver!=null) {
557 sb.append("wire " + name +"_r;\n");
558 sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
560 sb.append("reg " + name +"_r;\n");
561 sb.append("initial " + name +"_r = 0;\n");
562 if (latchDriver!=null) sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
563 else sb.append("reg ["+Math.max(0,width-1)+":0]" + name +";\n");
565 return sb.toString();
567 public String getAssignments() {
568 StringBuffer sb = new StringBuffer();
570 int a = FORWARD_LATENCY - 1;
572 throw new RuntimeException("cannot offer latency of " + FORWARD_LATENCY +"-1");
574 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
576 a = a-1; // CLK-to-Q gives us one cycle of latency anyways
577 sb.append("SRL16E srl16_"+name+"_r\n");
578 sb.append(" (.Q ("+name+"_r_),\n");
579 sb.append(" .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
580 sb.append(" .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
581 sb.append(" .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
582 sb.append(" .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
583 sb.append(" .CE (1),\n");
584 sb.append(" .CLK (clk),\n");
585 sb.append(" .D ("+name+"_r));\n");
587 sb.append("assign " + name +"_ = " + name + ";\n");
589 if (controlDriver != null) {
590 sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n");
591 sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n");
592 if (latchDriver==null)
593 sb.append("assign " + name +" = " + controlDriver.name + ";\n");
595 if (latchDriver != null)
596 sb.append("assign " + name +" = " + latchDriver.getVerilog() + ";\n");
597 return sb.toString();
601 // InstantiatedModule //////////////////////////////////////////////////////////////////////////////
603 public static class InstantiatedModule {
604 public final Module module;
605 public final Module thisModule;
607 public final HashMap<String,Port> ports = new HashMap<String,Port>();
608 private final String name;
609 public String getName() { return name; }
610 public InstantiatedModule(Module thisModule, Module module) {
611 this.thisModule = thisModule;
612 this.module = module;
615 while(thisModule.instantiatedModules.get(module.getName()+"_"+id)!=null) id++;
617 this.name = module.getName()+"_"+id;
618 thisModule.instantiatedModules.put(this.name, this);
619 for(String s : module.portorder)
622 public void dump(PrintWriter pw) {
623 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
624 for(String s : module.portorder)
625 pw.println(", " + getPort(s).getSimpleInterface());
626 for(PercolatedPort pp : module.percolatedPorts)
627 pw.println(" , "+pp.name);
630 public Port getPort(String name) {
631 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
633 public SinkPort getInputPort(String name) {
634 int width = module.getPort(name).getWidth();
635 SinkPort port = (SinkPort)ports.get(name);
637 port = thisModule.new SinkPort(getName()+"_"+name, width, false);
638 ports.put(name, port);
642 public SourcePort getOutputPort(String name) {
643 int width = module.getPort(name).getWidth();
644 SourcePort port = (SourcePort)ports.get(name);
646 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
647 ports.put(name, port);
653 public void dump(PrintWriter pw, boolean fix) {
654 if (!fix) throw new RuntimeException();
655 boolean isRoot = name.equals("main");
656 pw.print("module "+name);
657 pw.println(isRoot ? "(rst_pin " : "(clk, rst ");
658 for(String name : portorder) pw.println(" , " + ports.get(name).getInterface());
659 for (InstantiatedModule im : this.instantiatedModules.values())
660 for(PercolatedPort pp : im.module.percolatedPorts)
661 if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
662 pw.println(" , "+pp.name);
667 pw.println(" input rst_pin;");
668 pw.println(" wire clk;");
669 pw.println(" wire clk_fb;");
670 pw.println(" wire clk_unbuffered;");
675 pw.println(" .CLKFX_MULTIPLY(4),");
676 pw.println(" .CLKFX_DIVIDE(8),");
677 pw.println(" .CLKIN_PERIOD(\"10 ns\")");
678 pw.println(" ) mydcm(");
679 pw.println(" .CLKIN (clk_pin),");
680 pw.println(" .CLKFB(clk_fb),");
681 pw.println(" .CLKFX (clk_unbuffered),");
682 pw.println(" .CLK0 (clk_fb)");
685 pw.println(" wire rst;");
687 pw.println(" input clk;");
688 pw.println(" input rst;");
691 for (InstantiatedModule im : this.instantiatedModules.values())
692 for(PercolatedPort pp : im.module.percolatedPorts) {
693 if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
695 else switch(pp.type) {
696 case UP: pw.print("output"); break;
697 case DOWN: pw.print("input"); break;
698 case INOUT: pw.print("inout"); break;
702 pw.print("["+(pp.width-1)+":0]");
709 pw.println(" assign rst = rst_out;");
710 pw.println(" assign rst_in = !rst_pin;");
711 pw.println(" BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
712 pw.println(" assign clk_unbuffered = clk_out;");
715 for(String name : ports.keySet()) pw.println(" " + ports.get(name).getDeclaration());
716 for(StateWire sw : statewires.values()) sw.dump(pw);
717 for(Latch l : latches.values()) l.dump(pw);
718 for(WireValue wv : wires.values()) wv.dump(pw);
719 for(String name : ports.keySet()) pw.println(" " + ports.get(name).getAssignments());
720 for(WireValue wv : wires.values()) pw.println(" " + wv.getAssignments());
721 for(InstantiatedModule m : instantiatedModules.values()) m.dump(pw);
722 pw.println("always @(posedge clk) begin");
723 pw.println(" if (rst) begin");
724 for(Latch l : latches.values()) pw.println(l.getResetCode());
725 for(StateWire sw : statewires.values()) pw.println(sw.getResetCode());
726 for(Port p : ports.values()) pw.println(p.getResetCode());
727 pw.println(" end else begin");
728 for(Port p : ports.values()) pw.println(p.getCleanup());
729 for(Event a : events) a.dump(pw, fix);
730 pw.println(" begin end");
733 pw.println("endmodule");
737 public Object[] triggers;
738 public Object[] actions;
739 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
740 public Event(Object[] triggers, Object[] actions) {
741 Module.this.events.add(this);
742 this.triggers = triggers;
743 this.actions = actions;
745 public void dump(PrintWriter pw, boolean fix) {
746 if (!fix) throw new RuntimeException();
748 for(Object o : triggers) {
749 if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
750 else pw.print(" && " + o);
752 pw.println(") begin ");
753 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
754 if (fix) pw.println("end /*else*/ ");
755 else pw.println("end else ");