📄 designcircuitgenerator.java
字号:
/* * LA-CC 05-135 Trident 0.7.1Copyright NoticeCopyright 2006 (c) the Regents of the University of California.This Software was produced under a U.S. Government contract(W-7405-ENG-36) by Los Alamos National Laboratory, which is operatedby the University of California for the U.S. Department of Energy. TheU.S. Government is licensed to use, reproduce, and distribute thisSoftware. Permission is granted to the public to copy and use thisSoftware without charge, provided that this Notice and any statementof authorship are reproduced on all copies. Neither the Government northe University makes any warranty, express or implied, or assumes anyliability or responsibility for the user of this Software. */package fp.synthesis;import fp.circuit.*;import fp.circuit.dot.*;import fp.circuit.vhdl.*;//import fp.passes.*;import fp.flowgraph.*;import fp.util.UniqueName;import fp.util.BooleanEquation;import fp.util.*;import fp.hardware.*;import fp.hwdesc.Chip;import fp.hwdesc.Hardware;import fp.hwdesc.Resource;import fp.GlobalOptions;import java.util.*;/** * This class generates an abstract circuit based on the CFG * that is passed in. */public class DesignCircuitGenerator extends GenericCircuitGenerator implements CircuitSwitch { private static HashMap _topLevelWires; private static HashSet _idleWires; private static HashMap _controlWires; protected static RegfileGenerator _regfile; private RegInfoList _reg_list; private MemInfoList _mem_list; protected static MemoryInterfaceGenerator _memory; private DataPathCircuitGenerator _dpGen; public DesignCircuitGenerator() { } // this constructor is used when using no top to the design. public DesignCircuitGenerator(String target, String name) { this(target, name, null, new RegInfoList(0,0,1), new MemInfoList()); // are these reasonable defaults ? Hardware hw = GlobalOptions.hardware; long reg_offset = 0L; long mem_offset = 0L; int memory_count = 0; // this code assumes one fpga and one block of memory ... it should be more flexible. // I should really put things into hash maps that can be recalled by name like // {'mem0' : addr 0x0000, 'mem1': addr 0x40000 ... for(Iterator iter = hw.chip.listIterator(); iter.hasNext(); ) { Chip chip = (Chip)iter.next(); if (chip.typeCode == Chip.FPGA_TYPE) { for(Iterator r_iter = chip.resource.listIterator(); r_iter.hasNext(); ) { Resource res = (Resource)r_iter.next(); if (res.typeCode == Resource.REGISTER_TYPE) { reg_offset = (long)res.address; } } } if (chip.typeCode == Chip.RAM_TYPE) { mem_offset = (long)chip.address; memory_count = memory_count + chip.count; } } } public DesignCircuitGenerator(String target, String name, Circuit parent, RegInfoList reg_list, MemInfoList mem_list) { super(target, name, parent); _topLevelWires = new HashMap(); _idleWires = new HashSet(); _controlWires = new HashMap(); _reg_list = reg_list; _mem_list = mem_list; } /** * Creates the top level structure of the abstract circuit * design. */ public void generate(BlockGraph graph) { /** * 1) create global signals * 2) create the block structures * -- create data path logic * -- create state machine * 3) create global registers */ BlockNode bn; Circuit block; int onetime, i = 0; HashSet already_seen = new HashSet(); HashSet add_to_ors = new HashSet(); // Create the register file and memory bus for the top level circuit. ArrayList extOpNames = graph.getExternalOperandNames(); _regfile = new RegfileGenerator(_circuit, extOpNames, _reg_list); ChipDef chipInfo = GlobalOptions.chipDef; _memory = new MemoryInterfaceGenerator(_circuit, _mem_list); _memory.generate(chipInfo); System.out.println(" MEM LIST "+_mem_list); if (hasExternalMemories()) { // disable before building GlobalOptions.makeTestBench = false; System.err.println("Disabling TestBench due to External Memories"); } // Create the global signals (clk, reset). if(_buildTop) { _circuit.insertInPort("start", "start", "start", 1); _circuit.insertInPort("clk", "clk", "clk", 1); _circuit.insertInPort("reset", "reset", "reset", 1); } else { _circuit.insertInPort("start", "start", 1); _circuit.insertInPort("clk", "clk", 1); _circuit.insertInPort("reset", "reset", 1); } onetime = graph.getAllNodes().size()-1; // Iterate over each block in the CFG. for(Iterator it1 = graph.getAllNodes().iterator(); it1.hasNext(); ) { bn = (BlockNode) it1.next(); // Don't make circuits for the "hidden" blocks. if( (bn == graph.ENTRY) || (bn == graph.EXIT) ) { i++; continue; } System.out.println(); System.out.println("BLOCK NAME -- " + bn.getLabel().getFullName()+", II="+ bn.getII()+", modulo:"+bn.getIsModuloScheduled()); // Create a sub-circuit for this block. block = _circuit.insertCircuit(bn.getLabel().getFullName()); block.insertInPort("clk", "i_clk", "clk", 1); block.insertInPort("reset", "i_reset", "reset", 1); // Create logic in the data path based on the instructions in this block. _dpGen = new DataPathCircuitGenerator(); HashSet wires = _dpGen.generate(block, bn, chipInfo); // Add access to the register file for all registers. already_seen.addAll(wires); if(i == onetime) { // Only do this code once at end of processing... // For each element in the register file... Iterator hit = _regfile.getRegisterLog().keySet().iterator(); while(hit.hasNext()) { String name = (String)hit.next(); int width = ((RegInfo)_regfile.getRegisterLog().get(name)).getWidth(); String entry = name+"/"+width; if(!already_seen.contains(entry)) { wires.add(name+"/"+width); add_to_ors.add(name+"/"+width); } } } //System.out.println("wires: "+wires); _topLevelWires.put(getCircuitName(block), wires); makeControlLogic(block, bn, (BlockNode)graph.EXIT); i++; } // This loop must occur after the first because makeblockcontrolinput() // uses _controlWires that was updated by the first loop. for(Iterator it2 = graph.getAllNodes().iterator(); it2.hasNext(); ) { BlockNode blk = (BlockNode) it2.next(); if(blk.equals(graph.ENTRY) || blk.equals(graph.EXIT)) continue; // Skip the entry and exit blocks! makeBlockControlInput(blk, (BlockNode)graph.ENTRY); } // Make the design's done signal. makeGlobalDoneSignal(graph); // Connect the data and write enable wires from the blocks to the regfile. makeConnectionsToRegfile(add_to_ors, extOpNames); // Connect the memory access-related wires. _memory.makeConnections(); if(!_buildTop) { // Give all the wires their widths, and check wire connectivity. resolveWidths(); // Build the circuit in the underlying representation. _circuit.build(graph.getName(), _objs); } } public HashMap getMemoryInterface() { return MemoryInterfaceGenerator.getMemoryInterface(); } public boolean hasExternalMemories() { if (_mem_list != null) { return _mem_list.size() > 0; } else return false; } private void makeGlobalDoneSignal(BlockGraph bg) { int i = 0; HashMap map = new HashMap(); // Add each block's idle wire to the inputs of the AND gate. Iterator it = _idleWires.iterator(); while(it.hasNext()) { String name = (String)it.next(); map.put(name, new PortTag(null, "in"+(i++), PortTag.IN, 1)); } // Add the output to the AND gate. map.put("and_done", new PortTag(null, "out", PortTag.OUT, 1)); // Make the AND operator and the OUT port... _circuit.insertOperator("and_done", Operation.AND, map); // delay a copy of the done signal String reg_out = _circuit.getUniqueWireName("reg_done"); _circuit.insertRegister("done_1", "and_done", (String)null, reg_out, 1, 1); _circuit.insertOperator(Operation.AND, "done", "and_done", reg_out, "done_2", 1); // this is silly, I have to register the output to avoid glitching... _circuit.insertRegister("done_2", "done_2", (String)null, "done", 1, 1); if(_buildTop) _circuit.insertOutPort("done", "o_done", "done", 1); else _circuit.insertOutPort("done", "o_done", 1); } /** * This method makes the control logic input to this block. */ private String makeBlockControlInput(BlockNode bn, BlockNode entry) { String block_name = bn.getLabel().getFullName(); String or_out = "start_"+bn.getLabel().getFullName(); int i = 0; boolean entryIsPointing = false; HashMap map = new HashMap(); map.put(or_out, new PortTag(null, "out", PortTag.OUT, 1)); // If the GlobalEntry node is pointing to this node... if(((BlockEdge)entry.getOutEdges().toArray()[0]).getSink().equals(bn)) { map.put("start", new PortTag(null, "in"+(i++), PortTag.IN, 1)); entryIsPointing = true; } LinkedList wires = (LinkedList) _controlWires.get(block_name); if(wires == null) { // If there will be no entries to the OR operator... if(!entryIsPointing) throw new SynthesisException("control: no control input to block!"); } else { // Add the wires to the OR operator... Iterator w_it = wires.listIterator(); while(w_it.hasNext()) { String wire = (String) w_it.next(); map.put(wire, new PortTag(null, "in"+(i++), PortTag.IN, 1)); } } _circuit.insertOperator("or_"+or_out, Operation.OR, map); return or_out; } private HashSet makeBlockControlOutput(Circuit block, BlockNode bn, StateMachine sm, BlockNode exit) { String block_name = bn.getLabel().getFullName(); Set outEdges = bn.getOutEdges(); HashSet predicates = new HashSet(); HashMap exitCond = sm.getExitConditions(); System.out.println("exit conditions: "+exitCond); // For each of the block's outedges... for(Iterator edge_it = outEdges.iterator(); edge_it.hasNext(); ) { BlockEdge edge = (BlockEdge) edge_it.next(); // Make out ports for every block that could follow this one. BlockNode sink_node = (BlockNode) edge.getSink(); String sink_name = sink_node.getLabel().getFullName(); if(sink_node.equals(exit)) continue; // Skip if this is the exit block... if(sink_node.equals(bn)) { continue; // Skip if this is a loop edge... } String out = "next_"+sink_name+_circuit.getUniqueName(); // Make a hashmap with the entries containing(dst node, list of wires) if(!_controlWires.containsKey(sink_name)) { LinkedList l = new LinkedList(); l.add(out); _controlWires.put(sink_name, l); } else { LinkedList l = (LinkedList)_controlWires.get(sink_name); if(l == null) throw new SynthesisException("makeblockcontroloutput() no linked list found!"); l.add(out); _controlWires.put(sink_name, l); } block.insertOutPort(out, "o_"+out, out, 1); // Check if predicate logic has already been made. HashMap existingPreds = _dpGen.getPredicateWires(); BooleanEquation edgePred = edge.getPredicate(); String pred_wire = null; if(edgePred.isTrue() || edgePred.isFalse()) { //System.out.println("PREDICATE IS TRUE OR FALSE"); pred_wire = "c_pred"+block.getUniqueName(); int val = (edgePred.isTrue()) ? 1 : 0; _dpGen._circuit.insertConstant("c_"+val, val, pred_wire, 1); } else if(!existingPreds.containsKey(edgePred.toString())) { // If the predicate doesn't exist, then create it in the datapath... pred_wire = _dpGen.makePredicateLogic(_dpGen._circuit, edgePred, getNumBlockCycles(bn), bn); if(pred_wire == null) throw new SynthesisException("makeBlockControlOutput(): "+ "predicate wasn't defined"); //System.out.println("MAKING PREDICATE: " + pred_wire); } else { pred_wire = (String)existingPreds.get(edgePred.toString()); //System.out.println("PREDICATE ALREADY EXISTS: " + pred_wire); } // Add an out port to the datapath if it doesn't already exist... if(!_dpGen.getDpOutWires().contains(pred_wire)) { _dpGen._circuit.insertOutPort(pred_wire, "o_pred_"+pred_wire, pred_wire, 1); _dpGen.getDpOutWires().add(pred_wire); //System.out.println("CREATING OUTPORT FOR PRED: "+ pred_wire); } // Get the state input to the next block's start signal.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -