/** Responsible for traversing within a Call */ @Override protected void traverse(Call node) { if (_schedule.db) _schedule.ln(_schedule.GDA, "Traversing Call " + node); if (node.getProcedure() != null) { node.getProcedure().accept(this); } }
/** * DOCUMENT ME! * * @param call DOCUMENT ME! */ @Override public void visit(Call call) { if (_schedule.db) { _schedule.ln(_schedule.GVISIT, "visiting call " + call); } beginFrame(); call.getProcedure().accept(this); ConnectionFrame procedureFrame = endFrame(); // record duplicates of the procedure's connections // Some connections contain the same buses (done & address) // which we only want 1 new port for not multiples... Map<ID, ID> duplicatedMap = new HashMap<ID, ID>(); // for (Iterator resources = // procedureFrame.getConnectedResources().iterator(); // resources.hasNext();) // { // Resource resource = (Resource)resources.next(); for (Resource resource : procedureFrame.getConnectedResources()) { Collection<Connection> readConnections = procedureFrame.getReadConnections(resource); for (Connection read : readConnections) { Connection duplicate = read.duplicate(call, duplicatedMap); mapPortsAndBuses(call, duplicate, read); recordRead(duplicate, call); } Collection<Connection> writeConnections = procedureFrame.getWriteConnections(resource); for (Connection write : writeConnections) { Connection duplicate = write.duplicate(call, duplicatedMap); mapPortsAndBuses(call, duplicate, write); recordWrite(duplicate, call); } } }
private InputPin connectInputPin(Design design, Call call, Port port, String name) { Port procedurePort = call.getProcedurePort(port); InputPin pin = new InputPin(procedurePort); port.setBus(pin.getBus()); IDSourceInfo info = (name != null) ? call.getProcedure().getIDSourceInfo().deriveField(name, -1, -1) : procedurePort.getIDSourceInfo(); pin.setIDSourceInfo(info); Bus pinBus = pin.getBus(); pinBus.setUsed(true); port.setBus(pinBus); design.addInputPin(pin, port); return pin; }
private void generateKickers() { final GenericJob job = EngineThread.getGenericJob(); final boolean blockIO = !job.getUnscopedBooleanOptionValue(OptionRegistry.NO_BLOCK_IO); // If // Do // BlockIO final boolean doBlockSched = !job.getUnscopedBooleanOptionValue(OptionRegistry.SCHEDULE_NO_BLOCK_SCHEDULING); final boolean moduleBuilder = EngineThread.getGenericJob().getUnscopedBooleanOptionValue(OptionRegistry.MODULE_BUILDER); final Map<String, Kicker> kickers = new HashMap<String, Kicker>(); for (Task task : design.getTasks()) { final Call call = task.getCall(); final String domainSpec = (String) ((OptionString) EngineThread.getGenericJob().getOption(OptionRegistry.CLOCK_DOMAIN)) .getValue(call.getSearchLabel()); if (!task.isKickerRequired()) { // Ensure that the Go port is validly connected if (!call.getGoPort().isConnected()) { job.warn("Task " + call.showIDLogical() + " is not autostart and has no enabling signal"); Constant constant = new SimpleConstant(0, 1, false); constant.pushValuesForward(); call.getGoPort().setBus(constant.getValueBus()); call.getGoPort().pushValueForward(); } continue; } Kicker kicker; final String kickerKey; if (doBlockSched && !moduleBuilder) { // Connect up a KickerContinuous that will keep us running at // max rate indefinately. We expect only one task in block // io, but if we have more than one, we need individual // kickers so that we use the right clock/reset for each. kicker = new Kicker.KickerContinuous(); // Use the kickers string b/c there will be a (unique) // feedback from the task done kickerKey = kicker.toString(); } else if (blockIO) { boolean fbRequired = checkFeedback(call.getProcedure().getBody()); // System.out.println("Generated perpetual kicker withT/withoutF " // + fbRequired + " feedback flop required"); // Connect up a KickerPerpetual that will keep us running // indefinately. We expect only one task in block io, but // if we have more than one, each needs its own kicker // anyway (since we OR back in the done). We could use // just one kicker for all and put the OR external but // there is no Design level module to put this stuff in. // Argh! kicker = new Kicker.KickerPerpetual(fbRequired); // Use the kickers string b/c there will be a (unique) // feedback from the task done kickerKey = kicker.toString(); } else { if (moduleBuilder) { continue; } // find a kicker that matches this calls clk and reset // kickerKey = call.getClockName() + call.getResetName(); kickerKey = domainSpec; kicker = kickers.get(kickerKey); // if we didn't find it, construct a new one if (kicker == null) { kicker = new Kicker(); } } if (!kickers.containsKey(kickerKey)) { kickers.put(kickerKey, kicker); design.addComponentToDesign(kicker); design.getClockDomain(domainSpec).connectComponentToDomain(kicker); } if (call.getGoPort().isUsed()) { call.getGoPort().setBus(kicker.getDoneBus()); } if (kicker.getRepeatPort() != null) { Bus callDone = call.getExit(Exit.DONE).getDoneBus(); if (!callDone.isUsed()) { // there is the off-chance that it has fixed timing // and thus needs no done. Create a sequence of flops // to bypass. if (!call.getLatency().isFixed()) { EngineThread.getEngine() .fatalError( "Unexpected internal state. Design does not have a control structure and has variable timing"); } Bus done = kicker.getDoneBus(); for (int i = 0; i < call.getLatency().getMinClocks(); i++) { // Needs RESET b/c it is in the control path Reg flop = Reg.getConfigurableReg(Reg.REGR, ID.showLogical(call) + "_go_done_" + i); design.getClockDomain(domainSpec).connectComponentToDomain(flop); flop.getInternalResetPort().setBus(flop.getResetPort().getBus()); flop.getDataPort().setBus(done); // Ensure that we've constant propagated the flop flop.propagateValuesForward(); done = flop.getResultBus(); design.addComponentToDesign(flop); } callDone = done; } kicker.getRepeatPort().setBus(callDone); } } }
/** * Creates Pins on the design to connect each task's I/O. * * @param design the Design to be connected */ @SuppressWarnings("deprecation") private void connectTasks(Design design) { // Map kickers = new HashMap(); for (Task task : design.getTasks()) { Call call = task.getCall(); // Note: when creating the InputPins, they are based on the related // procedure port instead of the call port, because the InputPin // needs // the Port's peer bus to get sizing information // might have a this port if (task.getCall().getThisPort() != null) { int width = task.getCall().getThisPort().getValue().getSize(); /* * The base address of the top level object reference is always * 0, since it isn't actually stored in memory. */ Constant constant = new SimpleConstant(0, width, false); task.setHiddenConstant(constant); } // If module_builder, then publish the ports, and don't use a kicker if (EngineThread.getGenericJob() .getUnscopedBooleanOptionValue(OptionRegistry.MODULE_BUILDER)) { // get the entry method EntryMethod em = call.getProcedure().getEntryMethod(); Port go = call.getGoPort(); if (go.isUsed()) { Pin p = connectInputPin(design, call, go, call.getGoName()); if (em != null) { p.setApiPin(em.getGoPin()); } } List<Port> dataPorts = new ArrayList<Port>(call.getDataPorts()); // 'this' port is handled specially. dataPorts.remove(call.getThisPort()); int index = 0; for (Port port : dataPorts) { if (port.getTag().equals(Component.NORMAL)) { if (port.isUsed()) { Pin p = connectInputPin(design, call, port, null); if (em != null) { p.setApiPin(em.getArgPin(index)); } } } index++; } Exit exit = call.getExit(Exit.DONE); Bus done = exit.getDoneBus(); if (done.isUsed()) { OutputPin pin = connectOutputPin(design, call, done, call.getProcedure().getDoneName()); if (em != null) { pin.setApiPin(em.getDonePin()); } } for (Bus bus : exit.getDataBuses()) { if (bus.getTag().equals(Component.NORMAL)) { if (bus.isUsed()) { OutputPin pin = connectOutputPin(design, call, bus, call.getProcedure().getResultName()); if (em != null) { pin.setApiPin(em.getResultPin()); } } } } } } }