1 package edu.berkeley.fleet.fpga.verilog;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.ies44.*;
4 import edu.berkeley.fleet.*;
5 import java.lang.reflect.*;
6 import edu.berkeley.sbp.chr.*;
7 import edu.berkeley.sbp.misc.*;
8 import edu.berkeley.sbp.meta.*;
9 import edu.berkeley.sbp.util.*;
12 import static edu.berkeley.fleet.ies44.InstructionEncoder.*;
14 public class Verilog {
16 public static class SimpleValue implements Value {
17 public final String s;
18 public SimpleValue(String s) { this.s = s; }
19 public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
20 public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
21 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
22 public String getVerilogName() { return s; }
23 public String toString() { return s; }
26 public static interface Action {
27 public String getVerilogAction();
30 public static interface Trigger {
31 public String getVerilogTrigger();
34 public static interface Assignable {
35 public String getVerilogName();
36 public Assignable getAssignableBits(int high, int low);
39 public static interface Value extends Assignable {
40 public String getVerilogName();
41 public Value getBits(int high, int low);
44 public static class ConditionalAction implements Action {
45 public String condition;
47 public ConditionalAction(String condition, Action action) {
48 this.condition = condition;
51 public String toString() { return getVerilogAction(); }
52 public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
55 public static class ConditionalTrigger implements Trigger {
56 public String condition;
57 public Trigger trigger;
58 public ConditionalTrigger(String condition, Trigger trigger) {
59 this.condition = condition;
60 this.trigger = trigger;
61 if (trigger instanceof Module.Port)
62 ((Module.Port)trigger).hasLatch = true;
64 public String getVerilogTrigger() {
65 return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
69 public static class SimpleAssignable implements Assignable {
70 public final String s;
71 public SimpleAssignable(String s) { this.s = s; }
72 public String getVerilogName() { return s; }
73 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
76 public static class AssignAction implements Action {
79 public AssignAction(Assignable left, Value right) {
80 this.left = left.getVerilogName();
81 this.right = right.getVerilogName().toString();
83 public AssignAction(Assignable left, String right) {
84 this.left = left.getVerilogName();
87 public String getVerilogAction() { return left + "<=" + right + ";"; }
88 public String toString() { return getVerilogAction(); }
91 public static class SimpleAction implements Action {
92 public final String verilog;
93 public SimpleAction(String verilog) { this.verilog = verilog; }
94 public String getVerilogAction() { return verilog; }
95 public String toString() { return verilog; }
98 public static class Module {
99 public void dump(String prefix) throws IOException {
100 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/bitfields.v")));
101 pw.println("`define DATAWIDTH "+WIDTH_WORD);
102 pw.println("`define CODEBAG_SIZE_BITS "+CBD_SIZE.valmaskwidth);
103 pw.println("`define INSTRUCTION_WIDTH "+WIDTH_WORD);
104 pw.println("`define packet_token(p) "+PACKET_TOKEN.verilogVal("p"));
105 pw.println("`define packet_data(p) "+PACKET_DATA.verilogVal("p"));
106 pw.println("`define packet_dest(p) "+PACKET_DEST.verilogVal("p"));
107 pw.println("`define instruction_dest(p) "+DISPATCH_PATH.verilogVal("p"));
110 pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
115 public final String name;
116 public String getName() { return name; }
117 public Port getPort(String name) { return ports.get(name); }
119 public HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
120 public final ArrayList<Event> events = new ArrayList<Event>();
122 // FIXME: always-alphabetical convention?
123 public final HashMap<String,Port> ports = new HashMap<String,Port>();
124 public final ArrayList<String> portorder = new ArrayList<String>();
125 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
126 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
128 public StringBuffer crap = new StringBuffer();
129 public StringBuffer precrap = new StringBuffer();
130 public void addCrap(String s) { crap.append(s); crap.append('\n'); }
131 public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
132 public void addPreCrap0(String s) { precrap.append(s); }
134 public Module(String name) {
138 public SourcePort createInputPort(String name, int width) {
139 if (ports.get(name)!=null) throw new RuntimeException();
140 return new SourcePort(name, width, true);
142 public SourcePort getInputPort(String name) {
143 SourcePort ret = (SourcePort)ports.get(name);
144 if (ret==null) throw new RuntimeException();
147 public SinkPort createOutputPort(String name, int width, String resetBehavior) {
148 if (ports.get(name)!=null) throw new RuntimeException();
149 return new SinkPort(name, width, true, resetBehavior);
151 public SinkPort createWirePort(String name, int width) {
152 if (ports.get(name)!=null) throw new RuntimeException();
153 return new SinkPort(name, width, false, "");
155 public SourcePort createWireSourcePort(String name, int width) {
156 if (ports.get(name)!=null) throw new RuntimeException();
157 return new SourcePort(name, width, false);
159 public SinkPort getOutputPort(String name) {
160 SinkPort ret = (SinkPort)ports.get(name);
161 if (ret==null) throw new RuntimeException();
165 public class StateWire {
166 public final String name;
167 public final boolean initiallyFull;
168 public String getName() { return name; }
169 public Action isFull() { return new SimpleAction(name+"==1"); }
170 public Action isEmpty() { return new SimpleAction(name+"==0"); }
171 public Action doFill() { return new SimpleAction(name+"<=1;"); }
172 public Action doDrain() { return new SimpleAction(name+"<=0;"); }
173 public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
174 public StateWire(String name) { this(name, false); }
175 public StateWire(String name, boolean initiallyFull) {
177 this.initiallyFull = initiallyFull;
178 statewires.put(name, this);
180 public void dump(PrintWriter pw) {
181 pw.println(" reg "+name+";");
182 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
186 public class Latch implements Assignable, Value {
187 public final String name;
188 public final int width;
189 public final long initial;
190 public Latch(String name, int width) { this(name, width, 0); }
191 public Latch(String name, int width, long initial) {
194 this.initial = initial;
195 latches.put(name, this);
197 public String getVerilogName() { return name; }
198 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
199 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
200 public String doReset() { return name+"<="+initial+";"; }
201 public void dump(PrintWriter pw) {
202 pw.println(" reg ["+(width-1)+":0] "+name+";");
203 pw.println(" initial "+name+"="+initial+";");
207 public abstract class Port implements Action, Assignable, Trigger {
208 public abstract String doReset();
209 public final String name;
210 public String getName() { return name; }
211 public final int width;
212 public int getWidth() { return width; }
213 public boolean hasLatch = false;
214 public boolean external;
215 public Port(String name, int width, boolean external) {
218 this.external = external;
219 ports.put(name, this);
223 public String getVerilogName() { return name; }
224 public String getAck() { return name+"_a"; }
225 public String getReq() { return name+"_r"; }
226 public abstract String getInterface();
227 public abstract String getSimpleInterface();
228 public abstract String getDeclaration();
229 public abstract String getAssignments();
230 public abstract void connect(SinkPort driven);
233 public static class InstantiatedModule {
234 public final Module module;
235 public final Module thisModule;
237 public final HashMap<String,Port> ports = new HashMap<String,Port>();
238 public String getName() { return module.getName()+"_"+id; }
239 public InstantiatedModule(Module thisModule, Module module) {
240 this.thisModule = thisModule;
241 this.module = module;
242 this.id = thisModule.id++;
243 thisModule.instantiatedModules.add(this);
245 public void dump(PrintWriter pw) {
246 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
247 for(String s : module.portorder)
248 pw.println(", " + getPort(s).getSimpleInterface());
251 public Port getPort(String name) {
252 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
254 public SinkPort getInputPort(String name) {
255 int width = module.getPort(name).getWidth();
256 SinkPort port = (SinkPort)ports.get(name);
258 port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
259 ports.put(name, port);
263 public SourcePort getOutputPort(String name) {
264 int width = module.getPort(name).getWidth();
265 SourcePort port = (SourcePort)ports.get(name);
267 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
268 ports.put(name, port);
274 public class SourcePort extends Port implements Value {
275 public SinkPort driven = null;
276 public SourcePort(String name, int width, boolean external) {
277 super(name, width, external); }
278 public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
279 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
280 public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
281 public String getVerilogAction() { return getAck() + " <= 1;"; }
282 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
283 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
284 public String getDeclaration() {
285 StringBuffer sb = new StringBuffer();
287 sb.append("input " + name +"_r;\n");
288 sb.append("output " + name +"_a_;\n");
289 sb.append("input ["+(width-1)+":0]" + name +";\n");
291 sb.append("wire " + name +"_r;\n");
292 sb.append("wire ["+(width-1)+":0]" + name +";\n");
295 sb.append("wire " + name +"_a;\n");
297 sb.append("reg " + name +"_a;\n");
298 sb.append("initial " + name +"_a = 0;\n");
300 return sb.toString();
302 public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
303 public String getAssignments() {
304 StringBuffer sb = new StringBuffer();
306 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
307 if (driven != null) {
308 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
309 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
310 sb.append("assign " + driven.name +" = " + name + ";\n");
312 return sb.toString();
314 public void connect(SinkPort driven) {
315 this.driven = driven;
318 public class SinkPort extends Port {
319 public boolean forceNoLatch = false;
320 public SinkPort driven = null;
321 public final String resetBehavior;
322 public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
323 public String getVerilogAction() { return getReq() + " <= 1;"; }
324 public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
325 public SinkPort(String name, int width, boolean external, String resetBehavior) {
326 super(name, width, external); this.resetBehavior=resetBehavior; }
327 public String getResetBehavior() { return resetBehavior; }
328 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
329 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
330 public String getDeclaration() {
331 StringBuffer sb = new StringBuffer();
333 sb.append("output " + name +"_r_;\n");
334 sb.append("input " + name +"_a;\n");
335 sb.append("output ["+(width-1)+":0]" + name +"_;\n");
337 sb.append("wire " + name +"_a;\n");
341 sb.append("reg " + name +"_r;\n");
342 sb.append("initial " + name +"_r = 0;\n");
343 sb.append("wire ["+(width-1)+":0]" + name +";\n");
344 } else if (!hasLatch) {
345 sb.append("wire " + name +"_r;\n");
346 sb.append("wire ["+(width-1)+":0]" + name +";\n");
348 sb.append("reg " + name +"_r;\n");
349 sb.append("initial " + name +"_r = 0;\n");
350 sb.append("reg ["+(width-1)+":0]" + name +";\n");
351 sb.append("initial " + name +" = 0;\n");
353 return sb.toString();
355 public String doReset() {
359 ? (name+"_r<=0; "+name+"<=0;")
362 public String getAssignments() {
363 StringBuffer sb = new StringBuffer();
365 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
366 sb.append("assign " + name +"_ = " + name + ";\n");
368 if (driven != null) {
369 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
370 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
371 sb.append("assign " + driven.name +" = " + name + ";\n");
373 return sb.toString();
375 public void connect(SinkPort driven) {
376 this.driven = driven;
380 public void dump(PrintWriter pw, boolean fix) {
381 pw.println("`include \"macros.v\"");
382 pw.println("module "+name+"(clk, rst ");
383 for(String name : portorder) {
384 Port p = ports.get(name);
385 pw.println(" , " + p.getInterface());
389 pw.println(" input clk;");
390 pw.println(" input rst;");
391 for(String name : ports.keySet()) {
392 Port p = ports.get(name);
393 pw.println(" " + p.getDeclaration());
395 for(StateWire sw : statewires.values())
397 for(Latch l : latches.values())
399 for(String name : ports.keySet()) {
400 Port p = ports.get(name);
401 pw.println(" " + p.getAssignments());
403 for(InstantiatedModule m : instantiatedModules) {
407 pw.println("always @(posedge clk) begin");
408 pw.println(" if (!rst) begin");
409 for(Latch l : latches.values())
410 pw.println(l.doReset());
411 for(StateWire sw : statewires.values())
412 pw.println(sw.doReset());
413 for(Port p : ports.values())
414 pw.println(p.doReset());
415 pw.println(" end else begin");
416 for(Port p : ports.values()) {
417 if (p instanceof SourcePort) {
418 SourcePort ip = (SourcePort)p;
420 pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
422 SinkPort op = (SinkPort)p;
424 pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
426 op.getResetBehavior()+" end");
429 for(Event a : events) a.dump(pw, fix);
430 pw.println(" begin end");
435 pw.println("endmodule");
439 public Object[] triggers;
440 public Object[] actions;
441 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
442 public Event(Object[] triggers, Object[] actions) {
443 Module.this.events.add(this);
444 this.triggers = triggers;
445 this.actions = actions;
446 for(int i=0; i<triggers.length; i++)
447 if (triggers[i] instanceof Port)
448 ((Port)triggers[i]).hasLatch = true;
450 public void dump(PrintWriter pw, boolean fix) {
452 for(Object o : triggers) {
453 if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
454 else pw.print(" && " + o);
456 pw.println(") begin ");
457 for(Object a : actions) pw.println(((Action)a).getVerilogAction());
458 if (fix) pw.println("end /*else*/ ");
459 else pw.println("end else ");