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()); } } } } } } }