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.*;
12 => get rid of getInputPort(String) and instead use members
14 => automatic width-setting/checking on ports
17 public class Verilog {
19 public static class PercolatedPort {
20 public final boolean up;
21 public final int width;
22 public final String name;
23 public PercolatedPort(String name, int width, boolean up) {
30 public static class SimpleValue implements Value {
31 public final String s;
32 public SimpleValue(String s) { this.s = s; }
33 public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
34 public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
35 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
36 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
37 public String getVerilogName() { return s; }
38 public String toString() { return s; }
39 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
42 public static class CatValue implements Value {
43 private final Value[] values;
44 public CatValue(Value[] values) { this.values = values; }
45 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
46 public Value getBits(int high, int low) {
47 throw new RuntimeException();
49 public Assignable getAssignableBits(int high, int low) {
50 throw new RuntimeException();
52 public String toString() { return getVerilogName(); }
53 public String getVerilogName() {
54 StringBuffer sb = new StringBuffer();
57 for(int i=0; i<values.length; i++) {
58 if (values[i]==null) continue;
59 if (!first) sb.append(", ");
60 sb.append(values[i].getVerilogName());
66 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
69 public static interface Action {
70 public String getVerilogAction();
73 public static interface Trigger {
74 public String getVerilogTrigger();
75 public Trigger invert();
78 public static class InvertedTrigger implements Trigger {
79 private final Trigger original;
80 public InvertedTrigger(Trigger original) { this.original = original; }
81 public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
82 public Trigger invert() { return original; }
85 public static interface Assignable {
86 public String getVerilogName();
87 public Assignable getAssignableBits(int high, int low);
90 public static interface Value extends Assignable {
91 public String getVerilogName();
92 public Value getBits(int high, int low);
93 public Value getBits(Mask mask);
94 public Value invertBits();
97 public static class ConditionalAction implements Action {
98 public String condition;
100 public ConditionalAction(String condition, Action action) {
101 this.condition = condition;
102 this.action = action;
104 public String toString() { return getVerilogAction(); }
105 public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
108 public static class ConditionalTrigger implements Trigger {
109 public String condition;
110 public Trigger trigger;
111 public ConditionalTrigger(String condition, Trigger trigger) {
112 this.condition = condition;
113 this.trigger = trigger;
114 if (trigger instanceof Module.Port)
115 ((Module.Port)trigger).hasLatch = true;
117 public String getVerilogTrigger() {
118 return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
120 public Trigger invert() { return new InvertedTrigger(this); }
123 public static class SimpleAssignable implements Assignable {
124 public final String s;
125 public SimpleAssignable(String s) { this.s = s; }
126 public String getVerilogName() { return s; }
127 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
128 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
131 public static class AssignAction implements Action {
134 public AssignAction(Assignable left, Value right) {
135 this.left = left.getVerilogName();
136 this.right = right.getVerilogName().toString();
138 public AssignAction(Assignable left, String right) {
139 this.left = left.getVerilogName();
142 public String getVerilogAction() { return left + "<=" + right + ";"; }
143 public String toString() { return getVerilogAction(); }
146 public static class SimpleAction implements Action {
147 public final String verilog;
148 public SimpleAction(String verilog) { this.verilog = verilog; }
149 public String getVerilogAction() { return verilog; }
150 public String toString() { return verilog; }
153 public static class Module {
154 public void dump(String prefix) throws IOException {
155 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
158 for(InstantiatedModule m : instantiatedModules)
159 m.module.dump(prefix);
162 public final String name;
163 public String getName() { return name; }
164 public Port getPort(String name) { return ports.get(name); }
166 // order matters here
167 public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
169 // order matters here
170 public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
171 public final ArrayList<Event> events = new ArrayList<Event>();
173 // FIXME: always-alphabetical convention?
174 public final HashMap<String,Port> ports = new HashMap<String,Port>();
175 public final ArrayList<String> portorder = new ArrayList<String>();
176 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
177 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
179 public StringBuffer crap = new StringBuffer();
180 public StringBuffer precrap = new StringBuffer();
181 //public void addCrap(String s) { crap.append(s); crap.append('\n'); }
182 public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
183 public void addPreCrap0(String s) { precrap.append(s); }
185 public Module(String name) {
189 public SourcePort createInputPort(String name, int width) {
190 if (ports.get(name)!=null) throw new RuntimeException();
191 return new SourcePort(name, width, true);
193 public SourcePort getInputPort(String name) {
194 SourcePort ret = (SourcePort)ports.get(name);
195 if (ret==null) throw new RuntimeException();
198 public SinkPort createOutputPort(String name, int width, String resetBehavior) {
199 if (ports.get(name)!=null) throw new RuntimeException();
200 return new SinkPort(name, width, true, resetBehavior);
202 public SinkPort createWirePort(String name, int width) {
203 if (ports.get(name)!=null) throw new RuntimeException();
204 return new SinkPort(name, width, false, "");
206 public SourcePort createWireSourcePort(String name, int width) {
207 if (ports.get(name)!=null) throw new RuntimeException();
208 return new SourcePort(name, width, false);
210 public SinkPort getOutputPort(String name) {
211 SinkPort ret = (SinkPort)ports.get(name);
212 if (ret==null) throw new RuntimeException();
216 public class StateWire {
217 public final String name;
218 public final boolean initiallyFull;
219 public String getName() { return name; }
220 public Action isFull() { return new SimpleAction(name+"==1"); }
221 public Action isEmpty() { return new SimpleAction(name+"==0"); }
222 public Action doFill() { return new SimpleAction(name+"<=1;"); }
223 public Action doDrain() { return new SimpleAction(name+"<=0;"); }
224 public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
225 public StateWire(String name) { this(name, false); }
226 public StateWire(String name, boolean initiallyFull) {
228 this.initiallyFull = initiallyFull;
229 statewires.put(name, this);
231 public void dump(PrintWriter pw) {
232 pw.println(" reg "+name+";");
233 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
237 public class Latch implements Assignable, Value {
238 public final String name;
239 public final int width;
240 public final long initial;
241 public Latch(String name, int width) { this(name, width, 0); }
242 public Latch(String name, int width, long initial) {
245 this.initial = initial;
246 latches.put(name, this);
248 public String getVerilogName() { return name; }
249 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
250 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
251 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
252 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
253 public String doReset() { return name+"<="+initial+";"; }
254 public void dump(PrintWriter pw) {
255 pw.println(" reg ["+(width-1)+":0] "+name+";");
256 pw.println(" initial "+name+"="+initial+";");
258 public void connect(SinkPort driven) {
259 driven.latchDriver = this;
263 public abstract class Port implements Action, Assignable, Trigger {
264 public abstract String doReset();
265 public final String name;
266 public String getName() { return name; }
267 public final int width;
268 public int getWidth() { return width; }
269 public boolean hasLatch = false;
270 public boolean external;
271 public Port(String name, int width, boolean external) {
274 this.external = external;
275 ports.put(name, this);
279 public String getVerilogName() { return name; }
280 String getAck() { return name+"_a"; }
281 String getReq() { return name+"_r"; }
282 public String isFull() { return "("+name+"_r"+" && !"+name+"_a)"; }
283 public abstract String getInterface();
284 public abstract String getSimpleInterface();
285 public abstract String getDeclaration();
286 public abstract String getAssignments();
287 public abstract void connect(SinkPort driven);
288 public Trigger invert() { return new InvertedTrigger(this); }
291 public static class InstantiatedModule {
292 public final Module module;
293 public final Module thisModule;
295 public final HashMap<String,Port> ports = new HashMap<String,Port>();
296 public String getName() { return module.getName()+"_"+id; }
297 public InstantiatedModule(Module thisModule, Module module) {
298 this.thisModule = thisModule;
299 this.module = module;
300 this.id = thisModule.id++;
301 thisModule.instantiatedModules.add(this);
303 public void dump(PrintWriter pw) {
304 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
305 for(String s : module.portorder)
306 pw.println(", " + getPort(s).getSimpleInterface());
307 for(PercolatedPort pp : module.percolatedPorts)
308 pw.println(" , "+pp.name);
309 if (module.name.equals("ddr2")) {
310 pw.println(" , ddr2_addr");
311 pw.println(" , ddr2_addr_r");
312 pw.println(" , ddr2_addr_a");
313 pw.println(" , ddr2_isread");
314 pw.println(" , ddr2_write_data");
315 pw.println(" , ddr2_write_data_push");
316 pw.println(" , ddr2_write_data_full");
317 pw.println(" , ddr2_read_data");
318 pw.println(" , ddr2_read_data_pop");
319 pw.println(" , ddr2_read_data_empty");
320 pw.println(" , ddr2_read_data_latency");
322 if (module.name.equals("video")) {
323 pw.println(" , vga_clk");
324 pw.println(" , vga_psave");
325 pw.println(" , vga_hsync");
326 pw.println(" , vga_vsync");
327 pw.println(" , vga_sync");
328 pw.println(" , vga_blank");
329 pw.println(" , vga_r");
330 pw.println(" , vga_g");
331 pw.println(" , vga_b");
332 pw.println(" , vga_clkout");
336 public Port getPort(String name) {
337 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
339 public SinkPort getInputPort(String name) {
340 int width = module.getPort(name).getWidth();
341 SinkPort port = (SinkPort)ports.get(name);
343 port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
344 ports.put(name, port);
348 public SourcePort getOutputPort(String name) {
349 int width = module.getPort(name).getWidth();
350 SourcePort port = (SourcePort)ports.get(name);
352 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
353 ports.put(name, port);
359 public class SourcePort extends Port implements Value {
360 public SourcePort(String name, int width, boolean external) {
361 super(name, width, external); }
362 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
363 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
364 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
365 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
366 public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
367 public String getVerilogAction() { return getAck() + " <= 1;"; }
368 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
369 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
370 public String testBit(int index, boolean value) {
371 return "("+name+"["+index+"]=="+(value?1:0)+")";
373 public String getDeclaration() {
374 StringBuffer sb = new StringBuffer();
376 sb.append("input " + name +"_r;\n");
377 sb.append("output " + name +"_a_;\n");
379 sb.append("input ["+(width-1)+":0]" + name +";\n");
381 sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess
383 sb.append("wire " + name +"_r;\n");
385 sb.append("wire ["+(width-1)+":0]" + name +";\n");
388 sb.append("wire " + name +"_a;\n");
390 sb.append("reg " + name +"_a;\n");
391 sb.append("initial " + name +"_a = 0;\n");
393 return sb.toString();
395 public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
396 public String getAssignments() {
397 StringBuffer sb = new StringBuffer();
399 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
400 return sb.toString();
402 public void connect(SinkPort driven) {
403 driven.driver = this;
406 public class SinkPort extends Port {
407 public SourcePort driver = null;
408 public boolean forceNoLatch = false;
409 public SinkPort driven = null;
410 public Value latchDriver = null;
411 public boolean noDriveLatches = false;
412 public final String resetBehavior;
413 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
414 public String getVerilogAction() { return getReq() + " <= 1;"; }
415 public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
416 public SinkPort(String name, int width, boolean external, String resetBehavior) {
417 super(name, width, external); this.resetBehavior=resetBehavior; }
418 public String getResetBehavior() { return resetBehavior; }
419 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
420 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
421 public String getDeclaration() {
422 StringBuffer sb = new StringBuffer();
424 sb.append("output " + name +"_r_;\n");
425 sb.append("input " + name +"_a;\n");
427 sb.append("output ["+(width-1)+":0]" + name +"_;\n");
429 sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess
431 sb.append("wire " + name +"_a;\n");
434 if (forceNoLatch || latchDriver!=null) {
435 sb.append("reg " + name +"_r;\n");
436 sb.append("initial " + name +"_r = 0;\n");
438 sb.append("wire ["+(width-1)+":0]" + name +";\n");
439 } else if (!hasLatch) {
440 sb.append("wire " + name +"_r;\n");
442 sb.append("wire ["+(width-1)+":0]" + name +";\n");
444 sb.append("reg " + name +"_r;\n");
445 sb.append("initial " + name +"_r = 0;\n");
447 sb.append("reg ["+(width-1)+":0]" + name +";\n");
448 if (!"/*NORESET*/".equals(resetBehavior))
449 sb.append("initial " + name +" = 0;\n");
452 return sb.toString();
454 public String doReset() {
455 return (forceNoLatch||latchDriver!=null||width==0)
458 ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;")))
461 public String getAssignments() {
462 StringBuffer sb = new StringBuffer();
464 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
466 sb.append("assign " + name +"_ = " + name + ";\n");
468 if (driven != null) {
469 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
470 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
472 sb.append("assign " + driven.name +" = " + name + ";\n");
474 if (driver != null) {
475 sb.append("assign " + name +"_r = " + driver.name + "_r;\n");
476 sb.append("assign " + driver.name +"_a = " + name + "_a;\n");
477 if (width>0 && !noDriveLatches && latchDriver==null)
478 sb.append("assign " + name +" = " + driver.name + ";\n");
480 if (latchDriver != null) {
482 sb.append("assign " + name +" = " + latchDriver.getVerilogName() + ";\n");
484 return sb.toString();
486 public void connect(SinkPort driven) {
487 this.driven = driven;
488 throw new RuntimeException();
492 public void dump(PrintWriter pw, boolean fix) {
493 pw.println("module "+name+"(clk, rst ");
494 for(String name : portorder) {
495 Port p = ports.get(name);
496 pw.println(" , " + p.getInterface());
498 for (InstantiatedModule im : this.instantiatedModules)
499 for(PercolatedPort pp : im.module.percolatedPorts)
500 pw.println(" , "+pp.name);
501 if (this.name.equals("root")) {
502 pw.println(" , vga_clk");
503 pw.println(" , vga_psave");
504 pw.println(" , vga_hsync");
505 pw.println(" , vga_vsync");
506 pw.println(" , vga_sync");
507 pw.println(" , vga_blank");
508 pw.println(" , vga_r");
509 pw.println(" , vga_g");
510 pw.println(" , vga_b");
511 pw.println(" , vga_clkout");
512 pw.println(" , ddr2_addr");
513 pw.println(" , ddr2_addr_r");
514 pw.println(" , ddr2_addr_a");
515 pw.println(" , ddr2_isread");
516 pw.println(" , ddr2_write_data");
517 pw.println(" , ddr2_write_data_push");
518 pw.println(" , ddr2_write_data_full");
519 pw.println(" , ddr2_read_data");
520 pw.println(" , ddr2_read_data_pop");
521 pw.println(" , ddr2_read_data_empty");
522 pw.println(" , ddr2_read_data_latency");
526 pw.println(" input clk;");
527 pw.println(" input rst;");
528 for (InstantiatedModule im : this.instantiatedModules)
529 for(PercolatedPort pp : im.module.percolatedPorts) {
530 pw.print(pp.up ? "output" : "input");
533 pw.print("["+(pp.width-1)+":0]");
538 if (this.name.equals("root")) {
539 pw.println("output [31:0] ddr2_addr;");
540 pw.println("output ddr2_addr_r;");
541 pw.println("input ddr2_addr_a;");
542 pw.println("output ddr2_isread;");
543 pw.println("output [63:0] ddr2_write_data;");
544 pw.println("output ddr2_write_data_push;");
545 pw.println("input ddr2_write_data_full;");
546 pw.println("input [63:0] ddr2_read_data;");
547 pw.println("output ddr2_read_data_pop;");
548 pw.println("input ddr2_read_data_empty;");
549 pw.println("input [1:0] ddr2_read_data_latency;");
550 pw.println("input vga_clk;");
551 pw.println("output vga_psave;");
552 pw.println("output vga_hsync;");
553 pw.println("output vga_vsync;");
554 pw.println("output vga_sync;");
555 pw.println("output vga_blank;");
556 pw.println("output [7:0] vga_r;");
557 pw.println("output [7:0] vga_g;");
558 pw.println("output [7:0] vga_b;");
559 pw.println("output vga_clkout;");
561 for(String name : ports.keySet()) {
562 Port p = ports.get(name);
563 pw.println(" " + p.getDeclaration());
565 for(StateWire sw : statewires.values())
567 for(Latch l : latches.values())
569 for(String name : ports.keySet()) {
570 Port p = ports.get(name);
571 pw.println(" " + p.getAssignments());
573 for(InstantiatedModule m : instantiatedModules) {
577 pw.println("always @(posedge clk) begin");
578 pw.println(" if (!rst) begin");
579 for(Latch l : latches.values())
580 pw.println(l.doReset());
581 for(StateWire sw : statewires.values())
582 pw.println(sw.doReset());
583 for(Port p : ports.values())
584 pw.println(p.doReset());
585 pw.println(" end else begin");
586 for(Port p : ports.values()) {
587 if (p instanceof SourcePort) {
588 SourcePort ip = (SourcePort)p;
590 pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
592 SinkPort op = (SinkPort)p;
594 pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
596 op.getResetBehavior()+" end");
599 for(Event a : events) a.dump(pw, fix);
600 pw.println(" begin end");
605 pw.println("endmodule");
609 public Object[] triggers;
610 public Object[] actions;
611 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
612 public Event(Object[] triggers, Object[] actions) {
613 Module.this.events.add(this);
614 this.triggers = triggers;
615 this.actions = actions;
616 for(int i=0; i<triggers.length; i++)
617 if (triggers[i] instanceof Port)
618 ((Port)triggers[i]).hasLatch = true;
620 public void dump(PrintWriter pw, boolean fix) {
622 for(Object o : triggers) {
623 if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
624 else pw.print(" && " + o);
626 pw.println(") begin ");
627 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
628 if (fix) pw.println("end /*else*/ ");
629 else pw.println("end else ");