/** * The Design should be the first Visitable that is visited by the GlobalConnector, indicating the * initialization of processing. * * @param design Description of Parameter */ @Override public void visit(Design design) { if (_schedule.db) { _schedule.ln(_schedule.GVISIT, "visiting design " + design); } final GenericJob job = EngineThread.getGenericJob(); this.design = design; beginFrame(); traverse(design); connectGlobalRegisters(design, getFrame()); generateKickers(); if (job.getUnscopedBooleanOptionValue(OptionRegistry.NO_BLOCK_IO)) { connectTasks(design); } design.accept(new MemoryConnectionVisitor()); // Connect all SimplePinRead and SimplePinWrite accesses to // their targetted pins. design.accept(new SimplePinConnector()); // Connect clock and reset to all design module elements. Do // this last in case any of the other connectors add global // level stuff. for (Component designComp : design.getDesignModule().getComponents()) { // Find the clock domain for each design level element and // connect the clock and/or reset pins. final String domainSpec = (String) ((OptionString) EngineThread.getGenericJob().getOption(OptionRegistry.CLOCK_DOMAIN)) .getValue(designComp.getSearchLabel()); assert domainSpec != null : "No clock domain specifier found for " + designComp; design.getClockDomain(domainSpec).connectComponentToDomain(designComp); } }
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); } } }