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 SimpleValue implements Value {
20 public final String s;
21 public SimpleValue(String s) { this.s = s; }
22 public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
23 public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
24 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
25 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
26 public String getVerilogName() { return s; }
27 public String toString() { return s; }
28 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
31 public static class CatValue implements Value {
32 private final Value[] values;
33 public CatValue(Value[] values) { this.values = values; }
34 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
35 public Value getBits(int high, int low) {
36 throw new RuntimeException();
38 public Assignable getAssignableBits(int high, int low) {
39 throw new RuntimeException();
41 public String toString() { return getVerilogName(); }
42 public String getVerilogName() {
43 StringBuffer sb = new StringBuffer();
46 for(int i=0; i<values.length; i++) {
47 if (values[i]==null) continue;
48 if (!first) sb.append(", ");
49 sb.append(values[i].getVerilogName());
55 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
58 public static interface Action {
59 public String getVerilogAction();
62 public static interface Trigger {
63 public String getVerilogTrigger();
64 public Trigger invert();
67 public static class InvertedTrigger implements Trigger {
68 private final Trigger original;
69 public InvertedTrigger(Trigger original) { this.original = original; }
70 public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
71 public Trigger invert() { return original; }
74 public static interface Assignable {
75 public String getVerilogName();
76 public Assignable getAssignableBits(int high, int low);
79 public static interface Value extends Assignable {
80 public String getVerilogName();
81 public Value getBits(int high, int low);
82 public Value getBits(Mask mask);
83 public Value invertBits();
86 public static class ConditionalAction implements Action {
87 public String condition;
89 public ConditionalAction(String condition, Action action) {
90 this.condition = condition;
93 public String toString() { return getVerilogAction(); }
94 public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
97 public static class ConditionalTrigger implements Trigger {
98 public String condition;
99 public Trigger trigger;
100 public ConditionalTrigger(String condition, Trigger trigger) {
101 this.condition = condition;
102 this.trigger = trigger;
103 if (trigger instanceof Module.Port)
104 ((Module.Port)trigger).hasLatch = true;
106 public String getVerilogTrigger() {
107 return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
109 public Trigger invert() { return new InvertedTrigger(this); }
112 public static class SimpleAssignable implements Assignable {
113 public final String s;
114 public SimpleAssignable(String s) { this.s = s; }
115 public String getVerilogName() { return s; }
116 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
117 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
120 public static class AssignAction implements Action {
123 public AssignAction(Assignable left, Value right) {
124 this.left = left.getVerilogName();
125 this.right = right.getVerilogName().toString();
127 public AssignAction(Assignable left, String right) {
128 this.left = left.getVerilogName();
131 public String getVerilogAction() { return left + "<=" + right + ";"; }
132 public String toString() { return getVerilogAction(); }
135 public static class SimpleAction implements Action {
136 public final String verilog;
137 public SimpleAction(String verilog) { this.verilog = verilog; }
138 public String getVerilogAction() { return verilog; }
139 public String toString() { return verilog; }
142 public static class Module {
143 public void dump(String prefix) throws IOException {
144 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
147 for(InstantiatedModule m : instantiatedModules)
148 m.module.dump(prefix);
151 public final String name;
152 public String getName() { return name; }
153 public Port getPort(String name) { return ports.get(name); }
155 public HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
156 public final ArrayList<Event> events = new ArrayList<Event>();
158 // FIXME: always-alphabetical convention?
159 public final HashMap<String,Port> ports = new HashMap<String,Port>();
160 public final ArrayList<String> portorder = new ArrayList<String>();
161 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
162 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
164 public StringBuffer crap = new StringBuffer();
165 public StringBuffer precrap = new StringBuffer();
166 //public void addCrap(String s) { crap.append(s); crap.append('\n'); }
167 public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
168 public void addPreCrap0(String s) { precrap.append(s); }
170 public Module(String name) {
174 public SourcePort createInputPort(String name, int width) {
175 if (ports.get(name)!=null) throw new RuntimeException();
176 return new SourcePort(name, width, true);
178 public SourcePort getInputPort(String name) {
179 SourcePort ret = (SourcePort)ports.get(name);
180 if (ret==null) throw new RuntimeException();
183 public SinkPort createOutputPort(String name, int width, String resetBehavior) {
184 if (ports.get(name)!=null) throw new RuntimeException();
185 return new SinkPort(name, width, true, resetBehavior);
187 public SinkPort createWirePort(String name, int width) {
188 if (ports.get(name)!=null) throw new RuntimeException();
189 return new SinkPort(name, width, false, "");
191 public SourcePort createWireSourcePort(String name, int width) {
192 if (ports.get(name)!=null) throw new RuntimeException();
193 return new SourcePort(name, width, false);
195 public SinkPort getOutputPort(String name) {
196 SinkPort ret = (SinkPort)ports.get(name);
197 if (ret==null) throw new RuntimeException();
201 public class StateWire {
202 public final String name;
203 public final boolean initiallyFull;
204 public String getName() { return name; }
205 public Action isFull() { return new SimpleAction(name+"==1"); }
206 public Action isEmpty() { return new SimpleAction(name+"==0"); }
207 public Action doFill() { return new SimpleAction(name+"<=1;"); }
208 public Action doDrain() { return new SimpleAction(name+"<=0;"); }
209 public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
210 public StateWire(String name) { this(name, false); }
211 public StateWire(String name, boolean initiallyFull) {
213 this.initiallyFull = initiallyFull;
214 statewires.put(name, this);
216 public void dump(PrintWriter pw) {
217 pw.println(" reg "+name+";");
218 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
222 public class Latch implements Assignable, Value {
223 public final String name;
224 public final int width;
225 public final long initial;
226 public Latch(String name, int width) { this(name, width, 0); }
227 public Latch(String name, int width, long initial) {
230 this.initial = initial;
231 latches.put(name, this);
233 public String getVerilogName() { return name; }
234 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
235 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
236 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
237 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
238 public String doReset() { return name+"<="+initial+";"; }
239 public void dump(PrintWriter pw) {
240 pw.println(" reg ["+(width-1)+":0] "+name+";");
241 pw.println(" initial "+name+"="+initial+";");
243 public void connect(SinkPort driven) {
244 driven.latchDriver = this;
248 public abstract class Port implements Action, Assignable, Trigger {
249 public abstract String doReset();
250 public final String name;
251 public String getName() { return name; }
252 public final int width;
253 public int getWidth() { return width; }
254 public boolean hasLatch = false;
255 public boolean external;
256 public Port(String name, int width, boolean external) {
259 this.external = external;
260 ports.put(name, this);
264 public String getVerilogName() { return name; }
265 String getAck() { return name+"_a"; }
266 String getReq() { return name+"_r"; }
267 public String isFull() { return "("+name+"_r"+" && !"+name+"_a)"; }
268 public abstract String getInterface();
269 public abstract String getSimpleInterface();
270 public abstract String getDeclaration();
271 public abstract String getAssignments();
272 public abstract void connect(SinkPort driven);
273 public Trigger invert() { return new InvertedTrigger(this); }
276 public static class InstantiatedModule {
277 public final Module module;
278 public final Module thisModule;
280 public final HashMap<String,Port> ports = new HashMap<String,Port>();
281 public String getName() { return module.getName()+"_"+id; }
282 public InstantiatedModule(Module thisModule, Module module) {
283 this.thisModule = thisModule;
284 this.module = module;
285 this.id = thisModule.id++;
286 thisModule.instantiatedModules.add(this);
288 public void dump(PrintWriter pw) {
289 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
290 for(String s : module.portorder)
291 pw.println(", " + getPort(s).getSimpleInterface());
292 if (module.name.equals("dram")) {
293 pw.println(" , dram_addr");
294 pw.println(" , dram_addr_r");
295 pw.println(" , dram_addr_a");
296 pw.println(" , dram_isread");
297 pw.println(" , dram_write_data");
298 pw.println(" , dram_write_data_push");
299 pw.println(" , dram_write_data_full");
300 pw.println(" , dram_read_data");
301 pw.println(" , dram_read_data_pop");
302 pw.println(" , dram_read_data_empty");
303 pw.println(" , dram_read_data_latency");
305 if (module.name.equals("ddr2")) {
306 pw.println(" , ddr2_addr");
307 pw.println(" , ddr2_addr_r");
308 pw.println(" , ddr2_addr_a");
309 pw.println(" , ddr2_isread");
310 pw.println(" , ddr2_write_data");
311 pw.println(" , ddr2_write_data_push");
312 pw.println(" , ddr2_write_data_full");
313 pw.println(" , ddr2_read_data");
314 pw.println(" , ddr2_read_data_pop");
315 pw.println(" , ddr2_read_data_empty");
316 pw.println(" , ddr2_read_data_latency");
318 if (module.name.equals("video")) {
319 pw.println(" , vga_clk");
320 pw.println(" , vga_psave");
321 pw.println(" , vga_hsync");
322 pw.println(" , vga_vsync");
323 pw.println(" , vga_sync");
324 pw.println(" , vga_blank");
325 pw.println(" , vga_r");
326 pw.println(" , vga_g");
327 pw.println(" , vga_b");
328 pw.println(" , vga_clkout");
332 public Port getPort(String name) {
333 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
335 public SinkPort getInputPort(String name) {
336 int width = module.getPort(name).getWidth();
337 SinkPort port = (SinkPort)ports.get(name);
339 port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
340 ports.put(name, port);
344 public SourcePort getOutputPort(String name) {
345 int width = module.getPort(name).getWidth();
346 SourcePort port = (SourcePort)ports.get(name);
348 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
349 ports.put(name, port);
355 public class SourcePort extends Port implements Value {
356 public SourcePort(String name, int width, boolean external) {
357 super(name, width, external); }
358 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
359 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
360 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
361 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
362 public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
363 public String getVerilogAction() { return getAck() + " <= 1;"; }
364 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
365 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
366 public String testBit(int index, boolean value) {
367 return "("+name+"["+index+"]=="+(value?1:0)+")";
369 public String getDeclaration() {
370 StringBuffer sb = new StringBuffer();
372 sb.append("input " + name +"_r;\n");
373 sb.append("output " + name +"_a_;\n");
375 sb.append("input ["+(width-1)+":0]" + name +";\n");
377 sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess
379 sb.append("wire " + name +"_r;\n");
381 sb.append("wire ["+(width-1)+":0]" + name +";\n");
384 sb.append("wire " + name +"_a;\n");
386 sb.append("reg " + name +"_a;\n");
387 sb.append("initial " + name +"_a = 0;\n");
389 return sb.toString();
391 public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
392 public String getAssignments() {
393 StringBuffer sb = new StringBuffer();
395 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
396 return sb.toString();
398 public void connect(SinkPort driven) {
399 driven.driver = this;
402 public class SinkPort extends Port {
403 public SourcePort driver = null;
404 public boolean forceNoLatch = false;
405 public SinkPort driven = null;
406 public Value latchDriver = null;
407 public boolean noDriveLatches = false;
408 public final String resetBehavior;
409 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
410 public String getVerilogAction() { return getReq() + " <= 1;"; }
411 public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
412 public SinkPort(String name, int width, boolean external, String resetBehavior) {
413 super(name, width, external); this.resetBehavior=resetBehavior; }
414 public String getResetBehavior() { return resetBehavior; }
415 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
416 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
417 public String getDeclaration() {
418 StringBuffer sb = new StringBuffer();
420 sb.append("output " + name +"_r_;\n");
421 sb.append("input " + name +"_a;\n");
423 sb.append("output ["+(width-1)+":0]" + name +"_;\n");
425 sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess
427 sb.append("wire " + name +"_a;\n");
430 if (forceNoLatch || latchDriver!=null) {
431 sb.append("reg " + name +"_r;\n");
432 sb.append("initial " + name +"_r = 0;\n");
434 sb.append("wire ["+(width-1)+":0]" + name +";\n");
435 } else if (!hasLatch) {
436 sb.append("wire " + name +"_r;\n");
438 sb.append("wire ["+(width-1)+":0]" + name +";\n");
440 sb.append("reg " + name +"_r;\n");
441 sb.append("initial " + name +"_r = 0;\n");
443 sb.append("reg ["+(width-1)+":0]" + name +";\n");
444 if (!"/*NORESET*/".equals(resetBehavior))
445 sb.append("initial " + name +" = 0;\n");
448 return sb.toString();
450 public String doReset() {
451 return (forceNoLatch||latchDriver!=null||width==0)
454 ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;")))
457 public String getAssignments() {
458 StringBuffer sb = new StringBuffer();
460 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
462 sb.append("assign " + name +"_ = " + name + ";\n");
464 if (driven != null) {
465 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
466 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
468 sb.append("assign " + driven.name +" = " + name + ";\n");
470 if (driver != null) {
471 sb.append("assign " + name +"_r = " + driver.name + "_r;\n");
472 sb.append("assign " + driver.name +"_a = " + name + "_a;\n");
473 if (width>0 && !noDriveLatches && latchDriver==null)
474 sb.append("assign " + name +" = " + driver.name + ";\n");
476 if (latchDriver != null) {
478 sb.append("assign " + name +" = " + latchDriver.getVerilogName() + ";\n");
480 return sb.toString();
482 public void connect(SinkPort driven) {
483 this.driven = driven;
484 throw new RuntimeException();
488 public void dump(PrintWriter pw, boolean fix) {
489 pw.println("module "+name+"(clk, rst ");
490 for(String name : portorder) {
491 Port p = ports.get(name);
492 pw.println(" , " + p.getInterface());
494 if (this.name.equals("root")) {
495 pw.println(" , dram_addr");
496 pw.println(" , dram_addr_r");
497 pw.println(" , dram_addr_a");
498 pw.println(" , dram_isread");
499 pw.println(" , dram_write_data");
500 pw.println(" , dram_write_data_push");
501 pw.println(" , dram_write_data_full");
502 pw.println(" , dram_read_data");
503 pw.println(" , dram_read_data_pop");
504 pw.println(" , dram_read_data_empty");
505 pw.println(" , dram_read_data_latency");
506 pw.println(" , vga_clk");
507 pw.println(" , vga_psave");
508 pw.println(" , vga_hsync");
509 pw.println(" , vga_vsync");
510 pw.println(" , vga_sync");
511 pw.println(" , vga_blank");
512 pw.println(" , vga_r");
513 pw.println(" , vga_g");
514 pw.println(" , vga_b");
515 pw.println(" , vga_clkout");
516 pw.println(" , ddr2_addr");
517 pw.println(" , ddr2_addr_r");
518 pw.println(" , ddr2_addr_a");
519 pw.println(" , ddr2_isread");
520 pw.println(" , ddr2_write_data");
521 pw.println(" , ddr2_write_data_push");
522 pw.println(" , ddr2_write_data_full");
523 pw.println(" , ddr2_read_data");
524 pw.println(" , ddr2_read_data_pop");
525 pw.println(" , ddr2_read_data_empty");
526 pw.println(" , ddr2_read_data_latency");
530 pw.println(" input clk;");
531 pw.println(" input rst;");
532 if (this.name.equals("root")) {
533 pw.println("output [31:0] dram_addr;");
534 pw.println("output dram_addr_r;");
535 pw.println("input dram_addr_a;");
536 pw.println("output dram_isread;");
537 pw.println("output [63:0] dram_write_data;");
538 pw.println("output dram_write_data_push;");
539 pw.println("input dram_write_data_full;");
540 pw.println("input [63:0] dram_read_data;");
541 pw.println("output dram_read_data_pop;");
542 pw.println("input dram_read_data_empty;");
543 pw.println("input [1:0] dram_read_data_latency;");
544 pw.println("output [31:0] ddr2_addr;");
545 pw.println("output ddr2_addr_r;");
546 pw.println("input ddr2_addr_a;");
547 pw.println("output ddr2_isread;");
548 pw.println("output [63:0] ddr2_write_data;");
549 pw.println("output ddr2_write_data_push;");
550 pw.println("input ddr2_write_data_full;");
551 pw.println("input [63:0] ddr2_read_data;");
552 pw.println("output ddr2_read_data_pop;");
553 pw.println("input ddr2_read_data_empty;");
554 pw.println("input [1:0] ddr2_read_data_latency;");
555 pw.println("input vga_clk;");
556 pw.println("output vga_psave;");
557 pw.println("output vga_hsync;");
558 pw.println("output vga_vsync;");
559 pw.println("output vga_sync;");
560 pw.println("output vga_blank;");
561 pw.println("output [7:0] vga_r;");
562 pw.println("output [7:0] vga_g;");
563 pw.println("output [7:0] vga_b;");
564 pw.println("output vga_clkout;");
566 for(String name : ports.keySet()) {
567 Port p = ports.get(name);
568 pw.println(" " + p.getDeclaration());
570 for(StateWire sw : statewires.values())
572 for(Latch l : latches.values())
574 for(String name : ports.keySet()) {
575 Port p = ports.get(name);
576 pw.println(" " + p.getAssignments());
578 for(InstantiatedModule m : instantiatedModules) {
582 pw.println("always @(posedge clk) begin");
583 pw.println(" if (!rst) begin");
584 for(Latch l : latches.values())
585 pw.println(l.doReset());
586 for(StateWire sw : statewires.values())
587 pw.println(sw.doReset());
588 for(Port p : ports.values())
589 pw.println(p.doReset());
590 pw.println(" end else begin");
591 for(Port p : ports.values()) {
592 if (p instanceof SourcePort) {
593 SourcePort ip = (SourcePort)p;
595 pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
597 SinkPort op = (SinkPort)p;
599 pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
601 op.getResetBehavior()+" end");
604 for(Event a : events) a.dump(pw, fix);
605 pw.println(" begin end");
610 pw.println("endmodule");
614 public Object[] triggers;
615 public Object[] actions;
616 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
617 public Event(Object[] triggers, Object[] actions) {
618 Module.this.events.add(this);
619 this.triggers = triggers;
620 this.actions = actions;
621 for(int i=0; i<triggers.length; i++)
622 if (triggers[i] instanceof Port)
623 ((Port)triggers[i]).hasLatch = true;
625 public void dump(PrintWriter pw, boolean fix) {
627 for(Object o : triggers) {
628 if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
629 else pw.print(" && " + o);
631 pw.println(") begin ");
632 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
633 if (fix) pw.println("end /*else*/ ");
634 else pw.println("end else ");