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
15 => mangle the names given for strings
18 public class Verilog {
20 public static class PercolatedPort {
21 public static enum PortType { UP, DOWN, INOUT };
22 public final String name;
23 public final int width;
24 public final PortType type;
25 public PercolatedPort(String name, int width, PortType type) {
32 public static class SimpleValue implements Value {
33 public final String s;
34 public SimpleValue(String s) { this.s = s; }
35 public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
36 public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
37 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
38 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
39 public String getVerilogName() { return s; }
40 public String toString() { return s; }
41 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
44 public static class CatValue implements Value {
45 private final Value[] values;
46 public CatValue(Value[] values) { this.values = values; }
47 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
48 public Value getBits(int high, int low) {
49 throw new RuntimeException();
51 public Assignable getAssignableBits(int high, int low) {
52 throw new RuntimeException();
54 public String toString() { return getVerilogName(); }
55 public String getVerilogName() {
56 StringBuffer sb = new StringBuffer();
59 for(int i=0; i<values.length; i++) {
60 if (values[i]==null) continue;
61 if (!first) sb.append(", ");
62 sb.append(values[i].getVerilogName());
68 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
71 public static interface Action {
72 public String getVerilogAction();
75 public static interface Trigger {
76 public String getVerilogTrigger();
77 public Trigger invert();
80 public static class InvertedTrigger implements Trigger {
81 private final Trigger original;
82 public InvertedTrigger(Trigger original) { this.original = original; }
83 public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
84 public Trigger invert() { return original; }
87 public static interface Assignable {
88 public String getVerilogName();
89 public Assignable getAssignableBits(int high, int low);
92 public static interface Value extends Assignable {
93 public String getVerilogName();
94 public Value getBits(int high, int low);
95 public Value getBits(Mask mask);
96 public Value invertBits();
99 public static class ConditionalAction implements Action {
100 public String condition;
101 public Action action;
102 public ConditionalAction(String condition, Action action) {
103 this.condition = condition;
104 this.action = action;
106 public String toString() { return getVerilogAction(); }
107 public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
110 public static class ConditionalTrigger implements Trigger {
111 public String condition;
112 public Trigger trigger;
113 public ConditionalTrigger(String condition, Trigger trigger) {
114 this.condition = condition;
115 this.trigger = trigger;
116 if (trigger instanceof Module.Port)
117 ((Module.Port)trigger).hasLatch = true;
119 public String getVerilogTrigger() {
120 return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
122 public Trigger invert() { return new InvertedTrigger(this); }
125 public static class SimpleAssignable implements Assignable {
126 public final String s;
127 public SimpleAssignable(String s) { this.s = s; }
128 public String getVerilogName() { return s; }
129 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
130 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
133 public static class AssignAction implements Action {
136 public AssignAction(Assignable left, Value right) {
137 this.left = left.getVerilogName();
138 this.right = right.getVerilogName().toString();
140 public AssignAction(Assignable left, String right) {
141 this.left = left.getVerilogName();
144 public String getVerilogAction() { return left + "<=" + right + ";"; }
145 public String toString() { return getVerilogAction(); }
148 public static class SimpleAction implements Action {
149 public final String verilog;
150 public SimpleAction(String verilog) { this.verilog = verilog; }
151 public String getVerilogAction() { return verilog; }
152 public String toString() { return verilog; }
155 public static class Module {
156 public void dump(String prefix) throws IOException {
157 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
160 for(InstantiatedModule m : instantiatedModules)
161 m.module.dump(prefix);
164 public final String name;
165 public String getName() { return name; }
166 public Port getPort(String name) { return ports.get(name); }
168 // order matters here
169 public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
171 // order matters here
172 public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
173 public final ArrayList<Event> events = new ArrayList<Event>();
175 // FIXME: always-alphabetical convention?
176 public final HashMap<String,Port> ports = new HashMap<String,Port>();
177 public final ArrayList<String> portorder = new ArrayList<String>();
178 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
179 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
181 public StringBuffer crap = new StringBuffer();
182 public StringBuffer precrap = new StringBuffer();
183 //public void addCrap(String s) { crap.append(s); crap.append('\n'); }
184 public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
185 public void addPreCrap0(String s) { precrap.append(s); }
187 public Module(String name) {
191 public SourcePort createInputPort(String name, int width) {
192 if (ports.get(name)!=null) throw new RuntimeException();
193 return new SourcePort(name, width, true);
195 public SourcePort getInputPort(String name) {
196 SourcePort ret = (SourcePort)ports.get(name);
197 if (ret==null) throw new RuntimeException();
200 public SinkPort createOutputPort(String name, int width, String resetBehavior) {
201 if (ports.get(name)!=null) throw new RuntimeException();
202 return new SinkPort(name, width, true, resetBehavior);
204 public SinkPort createWirePort(String name, int width) {
205 if (ports.get(name)!=null) throw new RuntimeException();
206 return new SinkPort(name, width, false, "");
208 public SourcePort createWireSourcePort(String name, int width) {
209 if (ports.get(name)!=null) throw new RuntimeException();
210 return new SourcePort(name, width, false);
212 public SinkPort getOutputPort(String name) {
213 SinkPort ret = (SinkPort)ports.get(name);
214 if (ret==null) throw new RuntimeException();
218 public class StateWire {
219 public final String name;
220 public final boolean initiallyFull;
221 public String getName() { return name; }
222 public Action isFull() { return new SimpleAction(name+"==1"); }
223 public Action isEmpty() { return new SimpleAction(name+"==0"); }
224 public Action doFill() { return new SimpleAction(name+"<=1;"); }
225 public Action doDrain() { return new SimpleAction(name+"<=0;"); }
226 public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
227 public StateWire(String name) { this(name, false); }
228 public StateWire(String name, boolean initiallyFull) {
230 this.initiallyFull = initiallyFull;
231 statewires.put(name, this);
233 public void dump(PrintWriter pw) {
234 pw.println(" reg "+name+";");
235 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
239 public class Latch implements Assignable, Value {
240 public final String name;
241 public final int width;
242 public final long initial;
243 public Latch(String name, int width) { this(name, width, 0); }
244 public Latch(String name, int width, long initial) {
247 this.initial = initial;
248 latches.put(name, this);
250 public String getVerilogName() { return name; }
251 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
252 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
253 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
254 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
255 public String doReset() { return name+"<="+initial+";"; }
256 public void dump(PrintWriter pw) {
257 pw.println(" reg ["+(width-1)+":0] "+name+";");
258 pw.println(" initial "+name+"="+initial+";");
260 public void connect(SinkPort driven) {
261 driven.latchDriver = this;
265 public abstract class Port implements Action, Assignable, Trigger {
266 public abstract String doReset();
267 public final String name;
268 public String getName() { return name; }
269 public final int width;
270 public int getWidth() { return width; }
271 public boolean hasLatch = false;
272 public boolean external;
273 public Port(String name, int width, boolean external) {
276 this.external = external;
277 ports.put(name, this);
281 public String getVerilogName() { return name; }
282 String getAck() { return name+"_a"; }
283 String getReq() { return name+"_r"; }
284 public String isFull() { return "("+name+"_r"+" && !"+name+"_a)"; }
285 public abstract String getInterface();
286 public abstract String getSimpleInterface();
287 public abstract String getDeclaration();
288 public abstract String getAssignments();
289 public abstract void connect(SinkPort driven);
290 public Trigger invert() { return new InvertedTrigger(this); }
293 public static class InstantiatedModule {
294 public final Module module;
295 public final Module thisModule;
297 public final HashMap<String,Port> ports = new HashMap<String,Port>();
298 public String getName() { return module.getName()+"_"+id; }
299 public InstantiatedModule(Module thisModule, Module module) {
300 this.thisModule = thisModule;
301 this.module = module;
302 this.id = thisModule.id++;
303 thisModule.instantiatedModules.add(this);
305 public void dump(PrintWriter pw) {
306 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
307 for(String s : module.portorder)
308 pw.println(", " + getPort(s).getSimpleInterface());
309 for(PercolatedPort pp : module.percolatedPorts)
310 pw.println(" , "+pp.name);
313 public Port getPort(String name) {
314 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
316 public SinkPort getInputPort(String name) {
317 int width = module.getPort(name).getWidth();
318 SinkPort port = (SinkPort)ports.get(name);
320 port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
321 ports.put(name, port);
325 public SourcePort getOutputPort(String name) {
326 int width = module.getPort(name).getWidth();
327 SourcePort port = (SourcePort)ports.get(name);
329 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
330 ports.put(name, port);
336 public class SourcePort extends Port implements Value {
337 public SourcePort(String name, int width, boolean external) {
338 super(name, width, external); }
339 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
340 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
341 public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
342 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
343 public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
344 public String getVerilogAction() { return getAck() + " <= 1;"; }
345 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
346 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
347 public String testBit(int index, boolean value) {
348 return "("+name+"["+index+"]=="+(value?1:0)+")";
350 public String getDeclaration() {
351 StringBuffer sb = new StringBuffer();
353 sb.append("input " + name +"_r;\n");
354 sb.append("output " + name +"_a_;\n");
356 sb.append("input ["+(width-1)+":0]" + name +";\n");
358 sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess
360 sb.append("wire " + name +"_r;\n");
362 sb.append("wire ["+(width-1)+":0]" + name +";\n");
365 sb.append("wire " + name +"_a;\n");
367 sb.append("reg " + name +"_a;\n");
368 sb.append("initial " + name +"_a = 0;\n");
370 return sb.toString();
372 public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
373 public String getAssignments() {
374 StringBuffer sb = new StringBuffer();
376 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
377 return sb.toString();
379 public void connect(SinkPort driven) {
380 driven.driver = this;
383 public class SinkPort extends Port {
384 public SourcePort driver = null;
385 public boolean forceNoLatch = false;
386 public SinkPort driven = null;
387 public Value latchDriver = null;
388 public boolean noDriveLatches = false;
389 public final String resetBehavior;
390 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
391 public String getVerilogAction() { return getReq() + " <= 1;"; }
392 public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
393 public SinkPort(String name, int width, boolean external, String resetBehavior) {
394 super(name, width, external); this.resetBehavior=resetBehavior; }
395 public String getResetBehavior() { return resetBehavior; }
396 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
397 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
398 public String getDeclaration() {
399 StringBuffer sb = new StringBuffer();
401 sb.append("output " + name +"_r_;\n");
402 sb.append("input " + name +"_a;\n");
404 sb.append("output ["+(width-1)+":0]" + name +"_;\n");
406 sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess
408 sb.append("wire " + name +"_a;\n");
411 if (forceNoLatch || latchDriver!=null) {
412 sb.append("reg " + name +"_r;\n");
413 sb.append("initial " + name +"_r = 0;\n");
415 sb.append("wire ["+(width-1)+":0]" + name +";\n");
416 } else if (!hasLatch) {
417 sb.append("wire " + name +"_r;\n");
419 sb.append("wire ["+(width-1)+":0]" + name +";\n");
421 sb.append("reg " + name +"_r;\n");
422 sb.append("initial " + name +"_r = 0;\n");
424 sb.append("reg ["+(width-1)+":0]" + name +";\n");
425 if (!"/*NORESET*/".equals(resetBehavior))
426 sb.append("initial " + name +" = 0;\n");
429 return sb.toString();
431 public String doReset() {
432 return (forceNoLatch||latchDriver!=null||width==0)
435 ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;")))
438 public String getAssignments() {
439 StringBuffer sb = new StringBuffer();
441 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
443 sb.append("assign " + name +"_ = " + name + ";\n");
445 if (driven != null) {
446 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
447 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
449 sb.append("assign " + driven.name +" = " + name + ";\n");
451 if (driver != null) {
452 sb.append("assign " + name +"_r = " + driver.name + "_r;\n");
453 sb.append("assign " + driver.name +"_a = " + name + "_a;\n");
454 if (width>0 && !noDriveLatches && latchDriver==null)
455 sb.append("assign " + name +" = " + driver.name + ";\n");
457 if (latchDriver != null) {
459 sb.append("assign " + name +" = " + latchDriver.getVerilogName() + ";\n");
461 return sb.toString();
463 public void connect(SinkPort driven) {
464 this.driven = driven;
465 throw new RuntimeException();
469 public void dump(PrintWriter pw, boolean fix) {
470 boolean isRoot = name.equals("main");
471 pw.print("module "+name);
473 pw.println("(clk_pin, rst_pin ");
475 pw.println("(clk, rst ");
477 for(String name : portorder) {
478 Port p = ports.get(name);
479 pw.println(" , " + p.getInterface());
481 for (InstantiatedModule im : this.instantiatedModules)
482 for(PercolatedPort pp : im.module.percolatedPorts)
483 if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
484 pw.println(" , "+pp.name);
489 pw.println(" input clk_pin;");
490 pw.println(" input rst_pin;");
491 pw.println(" wire clk;");
492 pw.println(" wire clk_fb;");
493 pw.println(" wire clk_unbuffered;");
494 pw.println(" BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
497 pw.println(" .CLKFX_MULTIPLY(4),");
498 pw.println(" .CLKFX_DIVIDE(8),");
499 pw.println(" .CLKIN_PERIOD(\"10 ns\")");
500 pw.println(" ) mydcm(");
501 pw.println(" .CLKIN (clk_pin),");
502 pw.println(" .CLKFB(clk_fb),");
503 pw.println(" .CLKFX (clk_unbuffered),");
504 pw.println(" .CLK0 (clk_fb)");
506 pw.println(" wire rst;");
508 pw.println(" input clk;");
509 pw.println(" input rst;");
512 for (InstantiatedModule im : this.instantiatedModules)
513 for(PercolatedPort pp : im.module.percolatedPorts) {
514 if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
516 else switch(pp.type) {
517 case UP: pw.print("output"); break;
518 case DOWN: pw.print("input"); break;
519 case INOUT: pw.print("inout"); break;
523 pw.print("["+(pp.width-1)+":0]");
530 pw.println(" assign rst = rst_out;");
531 pw.println(" assign rst_in = rst_pin;");
534 for(String name : ports.keySet()) {
535 Port p = ports.get(name);
536 pw.println(" " + p.getDeclaration());
538 for(StateWire sw : statewires.values())
540 for(Latch l : latches.values())
542 for(String name : ports.keySet()) {
543 Port p = ports.get(name);
544 pw.println(" " + p.getAssignments());
546 for(InstantiatedModule m : instantiatedModules) {
550 pw.println("always @(posedge clk) begin");
551 pw.println(" if (!rst) begin");
552 for(Latch l : latches.values())
553 pw.println(l.doReset());
554 for(StateWire sw : statewires.values())
555 pw.println(sw.doReset());
556 for(Port p : ports.values())
557 pw.println(p.doReset());
558 pw.println(" end else begin");
559 for(Port p : ports.values()) {
560 if (p instanceof SourcePort) {
561 SourcePort ip = (SourcePort)p;
563 pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
565 SinkPort op = (SinkPort)p;
567 pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
569 op.getResetBehavior()+" end");
572 for(Event a : events) a.dump(pw, fix);
573 pw.println(" begin end");
578 pw.println("endmodule");
582 public Object[] triggers;
583 public Object[] actions;
584 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
585 public Event(Object[] triggers, Object[] actions) {
586 Module.this.events.add(this);
587 this.triggers = triggers;
588 this.actions = actions;
589 for(int i=0; i<triggers.length; i++)
590 if (triggers[i] instanceof Port)
591 ((Port)triggers[i]).hasLatch = true;
593 public void dump(PrintWriter pw, boolean fix) {
595 for(Object o : triggers) {
596 if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
597 else pw.print(" && " + o);
599 pw.println(") begin ");
600 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
601 if (fix) pw.println("end /*else*/ ");
602 else pw.println("end else ");