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.*;
11 public class Verilog {
13 public static class SimpleValue implements Value {
14 public final String s;
15 public SimpleValue(String s) { this.s = s; }
16 public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
17 public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
18 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
19 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
20 public String getVerilogName() { return s; }
21 public String toString() { return s; }
22 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
25 public static class CatValue implements Value {
26 private final Value[] values;
27 public CatValue(Value[] values) { this.values = values; }
28 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
29 public Value getBits(int high, int low) {
30 throw new RuntimeException();
32 public Assignable getAssignableBits(int high, int low) {
33 throw new RuntimeException();
35 public String toString() { return getVerilogName(); }
36 public String getVerilogName() {
37 StringBuffer sb = new StringBuffer();
40 for(int i=0; i<values.length; i++) {
41 if (values[i]==null) continue;
42 if (!first) sb.append(", ");
43 sb.append(values[i].getVerilogName());
49 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
52 public static interface Action {
53 public String getVerilogAction();
56 public static interface Trigger {
57 public String getVerilogTrigger();
58 public Trigger invert();
61 public static class InvertedTrigger implements Trigger {
62 private final Trigger original;
63 public InvertedTrigger(Trigger original) { this.original = original; }
64 public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
65 public Trigger invert() { return original; }
68 public static interface Assignable {
69 public String getVerilogName();
70 public Assignable getAssignableBits(int high, int low);
73 public static interface Value extends Assignable {
74 public String getVerilogName();
75 public Value getBits(int high, int low);
76 public Value getBits(Mask mask);
77 public Value invertBits();
80 public static class ConditionalAction implements Action {
81 public String condition;
83 public ConditionalAction(String condition, Action action) {
84 this.condition = condition;
87 public String toString() { return getVerilogAction(); }
88 public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
91 public static class ConditionalTrigger implements Trigger {
92 public String condition;
93 public Trigger trigger;
94 public ConditionalTrigger(String condition, Trigger trigger) {
95 this.condition = condition;
96 this.trigger = trigger;
97 if (trigger instanceof Module.Port)
98 ((Module.Port)trigger).hasLatch = true;
100 public String getVerilogTrigger() {
101 return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
103 public Trigger invert() { return new InvertedTrigger(this); }
106 public static class SimpleAssignable implements Assignable {
107 public final String s;
108 public SimpleAssignable(String s) { this.s = s; }
109 public String getVerilogName() { return s; }
110 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
111 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
114 public static class AssignAction implements Action {
117 public AssignAction(Assignable left, Value right) {
118 this.left = left.getVerilogName();
119 this.right = right.getVerilogName().toString();
121 public AssignAction(Assignable left, String right) {
122 this.left = left.getVerilogName();
125 public String getVerilogAction() { return left + "<=" + right + ";"; }
126 public String toString() { return getVerilogAction(); }
129 public static class SimpleAction implements Action {
130 public final String verilog;
131 public SimpleAction(String verilog) { this.verilog = verilog; }
132 public String getVerilogAction() { return verilog; }
133 public String toString() { return verilog; }
136 public static class Module {
137 public void dump(String prefix) throws IOException {
138 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
141 for(InstantiatedModule m : instantiatedModules)
142 m.module.dump(prefix);
145 public final String name;
146 public String getName() { return name; }
147 public Port getPort(String name) { return ports.get(name); }
149 public HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
150 public final ArrayList<Event> events = new ArrayList<Event>();
152 // FIXME: always-alphabetical convention?
153 public final HashMap<String,Port> ports = new HashMap<String,Port>();
154 public final ArrayList<String> portorder = new ArrayList<String>();
155 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
156 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
158 public StringBuffer crap = new StringBuffer();
159 public StringBuffer precrap = new StringBuffer();
160 //public void addCrap(String s) { crap.append(s); crap.append('\n'); }
161 public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
162 public void addPreCrap0(String s) { precrap.append(s); }
164 public Module(String name) {
168 public SourcePort createInputPort(String name, int width) {
169 if (ports.get(name)!=null) throw new RuntimeException();
170 return new SourcePort(name, width, true);
172 public SourcePort getInputPort(String name) {
173 SourcePort ret = (SourcePort)ports.get(name);
174 if (ret==null) throw new RuntimeException();
177 public SinkPort createOutputPort(String name, int width, String resetBehavior) {
178 if (ports.get(name)!=null) throw new RuntimeException();
179 return new SinkPort(name, width, true, resetBehavior);
181 public SinkPort createWirePort(String name, int width) {
182 if (ports.get(name)!=null) throw new RuntimeException();
183 return new SinkPort(name, width, false, "");
185 public SourcePort createWireSourcePort(String name, int width) {
186 if (ports.get(name)!=null) throw new RuntimeException();
187 return new SourcePort(name, width, false);
189 public SinkPort getOutputPort(String name) {
190 SinkPort ret = (SinkPort)ports.get(name);
191 if (ret==null) throw new RuntimeException();
195 public class StateWire {
196 public final String name;
197 public final boolean initiallyFull;
198 public String getName() { return name; }
199 public Action isFull() { return new SimpleAction(name+"==1"); }
200 public Action isEmpty() { return new SimpleAction(name+"==0"); }
201 public Action doFill() { return new SimpleAction(name+"<=1;"); }
202 public Action doDrain() { return new SimpleAction(name+"<=0;"); }
203 public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
204 public StateWire(String name) { this(name, false); }
205 public StateWire(String name, boolean initiallyFull) {
207 this.initiallyFull = initiallyFull;
208 statewires.put(name, this);
210 public void dump(PrintWriter pw) {
211 pw.println(" reg "+name+";");
212 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
216 public class Latch implements Assignable, Value {
217 public final String name;
218 public final int width;
219 public final long initial;
220 public Latch(String name, int width) { this(name, width, 0); }
221 public Latch(String name, int width, long initial) {
224 this.initial = initial;
225 latches.put(name, this);
227 public String getVerilogName() { return name; }
228 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
229 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
230 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
231 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
232 public String doReset() { return name+"<="+initial+";"; }
233 public void dump(PrintWriter pw) {
234 pw.println(" reg ["+(width-1)+":0] "+name+";");
235 pw.println(" initial "+name+"="+initial+";");
237 public void connect(SinkPort driven) {
238 driven.latchDriver = this;
242 public abstract class Port implements Action, Assignable, Trigger {
243 public abstract String doReset();
244 public final String name;
245 public String getName() { return name; }
246 public final int width;
247 public int getWidth() { return width; }
248 public boolean hasLatch = false;
249 public boolean external;
250 public Port(String name, int width, boolean external) {
253 this.external = external;
254 ports.put(name, this);
258 public String getVerilogName() { return name; }
259 String getAck() { return name+"_a"; }
260 String getReq() { return name+"_r"; }
261 public String isFull() { return "("+name+"_r"+" && !"+name+"_a)"; }
262 public abstract String getInterface();
263 public abstract String getSimpleInterface();
264 public abstract String getDeclaration();
265 public abstract String getAssignments();
266 public abstract void connect(SinkPort driven);
267 public Trigger invert() { return new InvertedTrigger(this); }
270 public static class InstantiatedModule {
271 public final Module module;
272 public final Module thisModule;
274 public final HashMap<String,Port> ports = new HashMap<String,Port>();
275 public String getName() { return module.getName()+"_"+id; }
276 public InstantiatedModule(Module thisModule, Module module) {
277 this.thisModule = thisModule;
278 this.module = module;
279 this.id = thisModule.id++;
280 thisModule.instantiatedModules.add(this);
282 public void dump(PrintWriter pw) {
283 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
284 for(String s : module.portorder)
285 pw.println(", " + getPort(s).getSimpleInterface());
286 if (module.name.equals("dram")) {
287 pw.println(" , dram_addr");
288 pw.println(" , dram_addr_r");
289 pw.println(" , dram_addr_a");
290 pw.println(" , dram_isread");
291 pw.println(" , dram_write_data");
292 pw.println(" , dram_write_data_push");
293 pw.println(" , dram_write_data_full");
294 pw.println(" , dram_read_data");
295 pw.println(" , dram_read_data_pop");
296 pw.println(" , dram_read_data_empty");
297 pw.println(" , dram_read_data_latency");
299 if (module.name.equals("ddr2")) {
300 pw.println(" , ddr2_addr");
301 pw.println(" , ddr2_addr_r");
302 pw.println(" , ddr2_addr_a");
303 pw.println(" , ddr2_isread");
304 pw.println(" , ddr2_write_data");
305 pw.println(" , ddr2_write_data_push");
306 pw.println(" , ddr2_write_data_full");
307 pw.println(" , ddr2_read_data");
308 pw.println(" , ddr2_read_data_pop");
309 pw.println(" , ddr2_read_data_empty");
310 pw.println(" , ddr2_read_data_latency");
312 if (module.name.equals("video")) {
313 pw.println(" , vga_clk");
314 pw.println(" , vga_psave");
315 pw.println(" , vga_hsync");
316 pw.println(" , vga_vsync");
317 pw.println(" , vga_sync");
318 pw.println(" , vga_blank");
319 pw.println(" , vga_r");
320 pw.println(" , vga_g");
321 pw.println(" , vga_b");
322 pw.println(" , vga_clkout");
326 public Port getPort(String name) {
327 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
329 public SinkPort getInputPort(String name) {
330 int width = module.getPort(name).getWidth();
331 SinkPort port = (SinkPort)ports.get(name);
333 port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
334 ports.put(name, port);
338 public SourcePort getOutputPort(String name) {
339 int width = module.getPort(name).getWidth();
340 SourcePort port = (SourcePort)ports.get(name);
342 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
343 ports.put(name, port);
349 public class SourcePort extends Port implements Value {
350 public SourcePort(String name, int width, boolean external) {
351 super(name, width, external); }
352 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
353 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
354 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
355 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
356 public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
357 public String getVerilogAction() { return getAck() + " <= 1;"; }
358 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
359 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
360 public String testBit(int index, boolean value) {
361 return "("+name+"["+index+"]=="+(value?1:0)+")";
363 public String getDeclaration() {
364 StringBuffer sb = new StringBuffer();
366 sb.append("input " + name +"_r;\n");
367 sb.append("output " + name +"_a_;\n");
369 sb.append("input ["+(width-1)+":0]" + name +";\n");
371 sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess
373 sb.append("wire " + name +"_r;\n");
375 sb.append("wire ["+(width-1)+":0]" + name +";\n");
378 sb.append("wire " + name +"_a;\n");
380 sb.append("reg " + name +"_a;\n");
381 sb.append("initial " + name +"_a = 0;\n");
383 return sb.toString();
385 public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
386 public String getAssignments() {
387 StringBuffer sb = new StringBuffer();
389 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
390 return sb.toString();
392 public void connect(SinkPort driven) {
393 driven.driver = this;
396 public class SinkPort extends Port {
397 public SourcePort driver = null;
398 public boolean forceNoLatch = false;
399 public SinkPort driven = null;
400 public Value latchDriver = null;
401 public boolean noDriveLatches = false;
402 public final String resetBehavior;
403 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
404 public String getVerilogAction() { return getReq() + " <= 1;"; }
405 public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
406 public SinkPort(String name, int width, boolean external, String resetBehavior) {
407 super(name, width, external); this.resetBehavior=resetBehavior; }
408 public String getResetBehavior() { return resetBehavior; }
409 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
410 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
411 public String getDeclaration() {
412 StringBuffer sb = new StringBuffer();
414 sb.append("output " + name +"_r_;\n");
415 sb.append("input " + name +"_a;\n");
417 sb.append("output ["+(width-1)+":0]" + name +"_;\n");
419 sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess
421 sb.append("wire " + name +"_a;\n");
424 if (forceNoLatch || latchDriver!=null) {
425 sb.append("reg " + name +"_r;\n");
426 sb.append("initial " + name +"_r = 0;\n");
428 sb.append("wire ["+(width-1)+":0]" + name +";\n");
429 } else if (!hasLatch) {
430 sb.append("wire " + name +"_r;\n");
432 sb.append("wire ["+(width-1)+":0]" + name +";\n");
434 sb.append("reg " + name +"_r;\n");
435 sb.append("initial " + name +"_r = 0;\n");
437 sb.append("reg ["+(width-1)+":0]" + name +";\n");
438 if (!"/*NORESET*/".equals(resetBehavior))
439 sb.append("initial " + name +" = 0;\n");
442 return sb.toString();
444 public String doReset() {
445 return (forceNoLatch||latchDriver!=null||width==0)
448 ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;")))
451 public String getAssignments() {
452 StringBuffer sb = new StringBuffer();
454 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
456 sb.append("assign " + name +"_ = " + name + ";\n");
458 if (driven != null) {
459 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
460 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
462 sb.append("assign " + driven.name +" = " + name + ";\n");
464 if (driver != null) {
465 sb.append("assign " + name +"_r = " + driver.name + "_r;\n");
466 sb.append("assign " + driver.name +"_a = " + name + "_a;\n");
467 if (width>0 && !noDriveLatches)
468 sb.append("assign " + name +" = " + driver.name + ";\n");
470 if (latchDriver != null) {
472 sb.append("assign " + name +" = " + latchDriver.getVerilogName() + ";\n");
474 return sb.toString();
476 public void connect(SinkPort driven) {
477 this.driven = driven;
478 throw new RuntimeException();
482 public void dump(PrintWriter pw, boolean fix) {
483 pw.println("module "+name+"(clk, rst ");
484 for(String name : portorder) {
485 Port p = ports.get(name);
486 pw.println(" , " + p.getInterface());
488 if (this.name.equals("root")) {
489 pw.println(" , dram_addr");
490 pw.println(" , dram_addr_r");
491 pw.println(" , dram_addr_a");
492 pw.println(" , dram_isread");
493 pw.println(" , dram_write_data");
494 pw.println(" , dram_write_data_push");
495 pw.println(" , dram_write_data_full");
496 pw.println(" , dram_read_data");
497 pw.println(" , dram_read_data_pop");
498 pw.println(" , dram_read_data_empty");
499 pw.println(" , dram_read_data_latency");
500 pw.println(" , vga_clk");
501 pw.println(" , vga_psave");
502 pw.println(" , vga_hsync");
503 pw.println(" , vga_vsync");
504 pw.println(" , vga_sync");
505 pw.println(" , vga_blank");
506 pw.println(" , vga_r");
507 pw.println(" , vga_g");
508 pw.println(" , vga_b");
509 pw.println(" , vga_clkout");
510 pw.println(" , ddr2_addr");
511 pw.println(" , ddr2_addr_r");
512 pw.println(" , ddr2_addr_a");
513 pw.println(" , ddr2_isread");
514 pw.println(" , ddr2_write_data");
515 pw.println(" , ddr2_write_data_push");
516 pw.println(" , ddr2_write_data_full");
517 pw.println(" , ddr2_read_data");
518 pw.println(" , ddr2_read_data_pop");
519 pw.println(" , ddr2_read_data_empty");
520 pw.println(" , ddr2_read_data_latency");
524 pw.println(" input clk;");
525 pw.println(" input rst;");
526 if (this.name.equals("root")) {
527 pw.println("output [31:0] dram_addr;");
528 pw.println("output dram_addr_r;");
529 pw.println("input dram_addr_a;");
530 pw.println("output dram_isread;");
531 pw.println("output [63:0] dram_write_data;");
532 pw.println("output dram_write_data_push;");
533 pw.println("input dram_write_data_full;");
534 pw.println("input [63:0] dram_read_data;");
535 pw.println("output dram_read_data_pop;");
536 pw.println("input dram_read_data_empty;");
537 pw.println("input [1:0] dram_read_data_latency;");
538 pw.println("output [31:0] ddr2_addr;");
539 pw.println("output ddr2_addr_r;");
540 pw.println("input ddr2_addr_a;");
541 pw.println("output ddr2_isread;");
542 pw.println("output [63:0] ddr2_write_data;");
543 pw.println("output ddr2_write_data_push;");
544 pw.println("input ddr2_write_data_full;");
545 pw.println("input [63:0] ddr2_read_data;");
546 pw.println("output ddr2_read_data_pop;");
547 pw.println("input ddr2_read_data_empty;");
548 pw.println("input [1:0] ddr2_read_data_latency;");
549 pw.println("input vga_clk;");
550 pw.println("output vga_psave;");
551 pw.println("output vga_hsync;");
552 pw.println("output vga_vsync;");
553 pw.println("output vga_sync;");
554 pw.println("output vga_blank;");
555 pw.println("output [7:0] vga_r;");
556 pw.println("output [7:0] vga_g;");
557 pw.println("output [7:0] vga_b;");
558 pw.println("output vga_clkout;");
560 for(String name : ports.keySet()) {
561 Port p = ports.get(name);
562 pw.println(" " + p.getDeclaration());
564 for(StateWire sw : statewires.values())
566 for(Latch l : latches.values())
568 for(String name : ports.keySet()) {
569 Port p = ports.get(name);
570 pw.println(" " + p.getAssignments());
572 for(InstantiatedModule m : instantiatedModules) {
576 pw.println("always @(posedge clk) begin");
577 pw.println(" if (!rst) begin");
578 for(Latch l : latches.values())
579 pw.println(l.doReset());
580 for(StateWire sw : statewires.values())
581 pw.println(sw.doReset());
582 for(Port p : ports.values())
583 pw.println(p.doReset());
584 pw.println(" end else begin");
585 for(Port p : ports.values()) {
586 if (p instanceof SourcePort) {
587 SourcePort ip = (SourcePort)p;
589 pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
591 SinkPort op = (SinkPort)p;
593 pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
595 op.getResetBehavior()+" end");
598 for(Event a : events) a.dump(pw, fix);
599 pw.println(" begin end");
604 pw.println("endmodule");
608 public Object[] triggers;
609 public Object[] actions;
610 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
611 public Event(Object[] triggers, Object[] actions) {
612 Module.this.events.add(this);
613 this.triggers = triggers;
614 this.actions = actions;
615 for(int i=0; i<triggers.length; i++)
616 if (triggers[i] instanceof Port)
617 ((Port)triggers[i]).hasLatch = true;
619 public void dump(PrintWriter pw, boolean fix) {
621 for(Object o : triggers) {
622 if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
623 else pw.print(" && " + o);
625 pw.println(") begin ");
626 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
627 if (fix) pw.println("end /*else*/ ");
628 else pw.println("end else ");