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 // Percolated Ports //////////////////////////////////////////////////////////////////////////////
328 * A PercolatedPort is a connection to a top-level pin; it is
329 * propagated up or down the hierarchy
331 public static class PercolatedPort {
332 public static enum PortType { UP, DOWN, INOUT };
333 public final String name;
334 public final int width;
335 public final PortType type;
336 public PercolatedPort(String name, int width, PortType type) {
344 // Module Internals //////////////////////////////////////////////////////////////////////////////
346 public static class Module {
347 public void dump(String prefix) throws IOException {
348 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
351 for(InstantiatedModule m : instantiatedModules)
352 m.module.dump(prefix);
355 public final String name;
356 public String getName() { return name; }
357 public Port getPort(String name) { return ports.get(name); }
359 // order matters here
360 public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
362 // order matters here
363 public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
364 public final ArrayList<Event> events = new ArrayList<Event>();
366 // FIXME: always-alphabetical convention?
367 public final HashMap<String,Port> ports = new HashMap<String,Port>();
368 public final ArrayList<String> portorder = new ArrayList<String>();
369 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
370 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
371 public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
373 public Module(String name) { this.name = name; }
375 public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); }
376 public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); }
378 // Latches and Wires //////////////////////////////////////////////////////////////////////////////
380 public class StateWire {
381 public final String name;
382 public final boolean initiallyFull;
383 public String getName() { return name; }
384 public Trigger isFull() { return new SimpleTrigger("("+name+"==1)"); }
385 public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); }
386 public Action doFill() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); }
387 public Action doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); }
388 public String getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; }
389 public StateWire(String name) { this(name, false); }
390 public StateWire(String name, boolean initiallyFull) {
392 this.initiallyFull = initiallyFull;
393 statewires.put(name, this);
395 public void dump(PrintWriter pw) {
396 pw.println(" reg "+name+";");
397 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
401 public class Latch implements Assignable, Value {
402 public final String name;
403 public final int width;
404 public final long initial;
405 public Latch(String name, int width) { this(name, width, 0); }
406 public Latch(String name, int width, long initial) {
409 this.initial = initial;
410 latches.put(name, this);
412 public int getWidth() { return width; }
413 public String getVerilog() { return name; }
414 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
415 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
416 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
417 public String getResetCode() { return name+"<="+initial+";"; }
418 public void dump(PrintWriter pw) {
419 pw.println(" reg ["+(width-1)+":0] "+name+";");
420 pw.println(" initial "+name+"="+initial+";");
422 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
425 public class WireValue implements Value {
426 public final String name;
427 public final int width;
428 public final Value assign;
429 public WireValue(String name, int width, Value assign) {
432 this.assign = assign;
433 wires.put(name, this);
435 public int getWidth() { return width; }
436 public String getVerilog() { return name; }
437 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
438 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
439 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
440 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
441 public void dump(PrintWriter pw) { pw.println(" wire ["+(width-1)+":0] "+name+";"); }
442 public String getAssignments() { return " assign "+name+" = "+assign.getVerilog()+";"; }
445 // Ports //////////////////////////////////////////////////////////////////////////////
447 public abstract class Port implements Action, Trigger {
450 final boolean external;
451 public Port(String name, int width, boolean external) {
454 this.external = external;
455 if (ports.get(name)!=null)
456 throw new RuntimeException("port "+name+" already exists");
457 ports.put(name, this);
461 public String getName() { return name; }
462 public int getWidth() { return width; }
463 public String getVerilog() { return name; }
464 String getAck() { return name+"_a"; }
465 String getReq() { return name+"_r"; }
466 public String isFull() { return "("+getReq()+" && !"+getAck()+")"; }
467 public abstract String getResetCode();
468 public abstract String getInterface();
469 public abstract String getSimpleInterface();
470 public abstract String getDeclaration();
471 public abstract String getAssignments();
472 public abstract String getCleanup();
473 public Trigger invert() { return new InvertedTrigger(this); }
474 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
477 public class SourcePort extends Port implements Value {
478 private SinkPort driven = null;
479 public SourcePort(String name, int width, boolean external) { super(name, width, external); }
480 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
481 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
482 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
483 public String getVerilogTrigger() { return getReq() + " && !"+getAck(); }
484 public String getVerilogAction() { return getAck() + " <= 1;"; }
485 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
486 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
487 public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; }
488 public String getDeclaration() {
489 StringBuffer sb = new StringBuffer();
491 sb.append("input " + name +"_r;\n");
492 sb.append("output " + name +"_a_;\n");
493 sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n");
495 sb.append("wire " + name +"_r;\n");
496 sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
499 sb.append("wire " + name +"_a;\n");
501 sb.append("reg " + name +"_a;\n");
502 sb.append("initial " + name +"_a = 0;\n");
504 return sb.toString();
506 public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; }
507 public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
508 public String getAssignments() {
509 StringBuffer sb = new StringBuffer();
511 int a = REVERSE_LATENCY - 3;
513 throw new RuntimeException("cannot offer latency of " + REVERSE_LATENCY +"-3");
515 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
517 a = a-1; // CLK-to-Q gives us one cycle of latency anyways
518 sb.append("SRL16E srl16_"+name+"_a\n");
519 sb.append(" (.Q ("+name+"_a_),\n");
520 sb.append(" .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
521 sb.append(" .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
522 sb.append(" .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
523 sb.append(" .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
524 sb.append(" .CE (1),\n");
525 sb.append(" .CLK (clk),\n");
526 sb.append(" .D ("+name+"_a));\n");
529 return sb.toString();
531 public void connect(SinkPort driven) {
532 if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver");
533 if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver");
534 if (this.driven!=null) throw new RuntimeException("driver already has a driven net");
535 this.driven = driven;
536 driven.controlDriver = this;
537 driven.latchDriver = this;
539 // if (getWidth() != driven.getWidth())
540 // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth());
544 public class SinkPort extends Port implements Assignable {
545 SourcePort controlDriver = null;
546 Value latchDriver = null;
547 public SinkPort(String name, int width, boolean external) { super(name, width, external); }
548 public String getVerilogAction() { return getReq() + " <= 1;"; }
549 public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); }
550 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
551 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
552 public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; }
553 public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); }
554 public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; }
555 public void connectControl(SourcePort controlDriver) {
556 if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice");
557 this.controlDriver = controlDriver;
559 public void connectValue(Value val) {
560 //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()");
561 this.latchDriver = val;
563 //if (getWidth() != val.getWidth())
564 //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth());
566 public String getDeclaration() {
567 StringBuffer sb = new StringBuffer();
569 sb.append("output " + name +"_r_;\n");
570 sb.append("input " + name +"_a;\n");
571 sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n");
573 sb.append("wire " + name +"_a;\n");
575 if (controlDriver!=null) {
576 sb.append("wire " + name +"_r;\n");
577 sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
579 sb.append("reg " + name +"_r;\n");
580 sb.append("initial " + name +"_r = 0;\n");
581 if (latchDriver!=null) sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
582 else sb.append("reg ["+Math.max(0,width-1)+":0]" + name +";\n");
584 return sb.toString();
586 public String getAssignments() {
587 StringBuffer sb = new StringBuffer();
589 int a = FORWARD_LATENCY - 1;
591 throw new RuntimeException("cannot offer latency of " + FORWARD_LATENCY +"-1");
593 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
595 a = a-1; // CLK-to-Q gives us one cycle of latency anyways
596 sb.append("SRL16E srl16_"+name+"_r\n");
597 sb.append(" (.Q ("+name+"_r_),\n");
598 sb.append(" .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
599 sb.append(" .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
600 sb.append(" .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
601 sb.append(" .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
602 sb.append(" .CE (1),\n");
603 sb.append(" .CLK (clk),\n");
604 sb.append(" .D ("+name+"_r));\n");
606 sb.append("assign " + name +"_ = " + name + ";\n");
608 if (controlDriver != null) {
609 sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n");
610 sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n");
611 if (latchDriver==null)
612 sb.append("assign " + name +" = " + controlDriver.name + ";\n");
614 if (latchDriver != null)
615 sb.append("assign " + name +" = " + latchDriver.getVerilog() + ";\n");
616 return sb.toString();
620 // InstantiatedModule //////////////////////////////////////////////////////////////////////////////
622 public static class InstantiatedModule {
623 public final Module module;
624 public final Module thisModule;
626 public final HashMap<String,Port> ports = new HashMap<String,Port>();
627 public String getName() { return module.getName()+"_"+id; }
628 public InstantiatedModule(Module thisModule, Module module) {
629 this.thisModule = thisModule;
630 this.module = module;
634 for (InstantiatedModule im : thisModule.instantiatedModules)
635 if (im.getName().equals(module.getName()+"_"+id)) {
642 thisModule.instantiatedModules.add(this);
643 for(String s : module.portorder)
646 public void dump(PrintWriter pw) {
647 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
648 for(String s : module.portorder)
649 pw.println(", " + getPort(s).getSimpleInterface());
650 for(PercolatedPort pp : module.percolatedPorts)
651 pw.println(" , "+pp.name);
654 public Port getPort(String name) {
655 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
657 public SinkPort getInputPort(String name) {
658 int width = module.getPort(name).getWidth();
659 SinkPort port = (SinkPort)ports.get(name);
661 port = thisModule.new SinkPort(getName()+"_"+name, width, false);
662 ports.put(name, port);
666 public SourcePort getOutputPort(String name) {
667 int width = module.getPort(name).getWidth();
668 SourcePort port = (SourcePort)ports.get(name);
670 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
671 ports.put(name, port);
677 public void dump(PrintWriter pw, boolean fix) {
678 if (!fix) throw new RuntimeException();
679 boolean isRoot = name.equals("main");
680 pw.print("module "+name);
681 pw.println(isRoot ? "(clk_pin, rst_pin " : "(clk, rst ");
682 for(String name : portorder) pw.println(" , " + ports.get(name).getInterface());
683 for (InstantiatedModule im : this.instantiatedModules)
684 for(PercolatedPort pp : im.module.percolatedPorts)
685 if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
686 pw.println(" , "+pp.name);
691 pw.println(" input clk_pin;");
692 pw.println(" input rst_pin;");
693 pw.println(" wire clk;");
694 pw.println(" wire clk_fb;");
695 pw.println(" wire clk_unbuffered;");
696 pw.println(" assign clk_unbuffered = clk_pin;");
697 //pw.println(" assign clk = clk_pin;");
699 pw.println(" BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
703 pw.println(" .CLKFX_MULTIPLY(4),");
704 pw.println(" .CLKFX_DIVIDE(8),");
705 pw.println(" .CLKIN_PERIOD(\"10 ns\")");
706 pw.println(" ) mydcm(");
707 pw.println(" .CLKIN (clk_pin),");
708 pw.println(" .CLKFB(clk_fb),");
709 pw.println(" .CLKFX (clk_unbuffered),");
710 pw.println(" .CLK0 (clk_fb)");
713 pw.println(" wire rst;");
715 pw.println(" input clk;");
716 pw.println(" input rst;");
719 for (InstantiatedModule im : this.instantiatedModules)
720 for(PercolatedPort pp : im.module.percolatedPorts) {
721 if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
723 else switch(pp.type) {
724 case UP: pw.print("output"); break;
725 case DOWN: pw.print("input"); break;
726 case INOUT: pw.print("inout"); break;
730 pw.print("["+(pp.width-1)+":0]");
737 pw.println(" assign rst = rst_out;");
738 pw.println(" assign rst_in = !rst_pin;");
741 for(String name : ports.keySet()) pw.println(" " + ports.get(name).getDeclaration());
742 for(StateWire sw : statewires.values()) sw.dump(pw);
743 for(Latch l : latches.values()) l.dump(pw);
744 for(WireValue wv : wires.values()) wv.dump(pw);
745 for(String name : ports.keySet()) pw.println(" " + ports.get(name).getAssignments());
746 for(WireValue wv : wires.values()) pw.println(" " + wv.getAssignments());
747 for(InstantiatedModule m : instantiatedModules) m.dump(pw);
748 pw.println("always @(posedge clk) begin");
749 pw.println(" if (rst) begin");
750 for(Latch l : latches.values()) pw.println(l.getResetCode());
751 for(StateWire sw : statewires.values()) pw.println(sw.getResetCode());
752 for(Port p : ports.values()) pw.println(p.getResetCode());
753 pw.println(" end else begin");
754 for(Port p : ports.values()) pw.println(p.getCleanup());
755 for(Event a : events) a.dump(pw, fix);
756 pw.println(" begin end");
759 pw.println("endmodule");
763 public Object[] triggers;
764 public Object[] actions;
765 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
766 public Event(Object[] triggers, Object[] actions) {
767 Module.this.events.add(this);
768 this.triggers = triggers;
769 this.actions = actions;
771 public void dump(PrintWriter pw, boolean fix) {
772 if (!fix) throw new RuntimeException();
774 for(Object o : triggers) {
775 if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
776 else pw.print(" && " + o);
778 pw.println(") begin ");
779 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
780 if (fix) pw.println("end /*else*/ ");
781 else pw.println("end else ");