Plugin Idea #1 : PLL Generator

26 views
Skip to first unread message

Rob Holmes

unread,
Dec 21, 2025, 12:35:55 PM (yesterday) Dec 21
to FPGAwars: explorando el lado libre
Was playing around with the plugin system and made this, wondered if its interesting to anyone? If so i can add the source code.

Probably doesnt need much explanation, you clcik the clock in the toolbar on the left, and in the window select the variables, hit Add PLL Code Block and you get your block. Only for the seriously lazy who dont want to type icepll in the command line ;)

pll.png

charli va

unread,
Dec 21, 2025, 12:48:40 PM (yesterday) Dec 21
to fpga-wars-explora...@googlegroups.com
Wohooo Rob!! very cool!!! i love it! thanks for your time in deep in plugin system !! thanks again!! i need to try it!  send the code!! :)

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para ver este debate, visita https://groups.google.com/d/msgid/fpga-wars-explorando-el-lado-libre/cd668856-2d92-4ffe-b505-591ef5919711n%40googlegroups.com.
Message has been deleted
Message has been deleted

Rob Holmes

unread,
Dec 21, 2025, 3:56:07 PM (yesterday) Dec 21
to FPGAwars: explorando el lado libre
I cant seem to upload a compressed folder that contains js files, i have to go out now so will try again in the morning, however one point:

One thing you'll need apart from the plugin folder(hopefully upload tomorrow) is the following:


 //-----------------------------------------------------------------------
    //-- Event listener for plugins to add blocks to the design
    //-----------------------------------------------------------------------
    iceStudio.bus.events.subscribe('plugin.addBlock', function (data) {
      if (data && data.blockType && data.blockData) {
        console.log('Graph service received plugin.addBlock event', data);

        // Create the block using blockforms
        if (data.blockType === 'basic.code') {
          // Load the code block from the data
          let cell = blockforms.loadBasic(data.blockData);

          // Add it to the design as a draggable block
          self.addDraggableCell(cell);
        }
      }
    });


which for want of a better location i put in graph.js service, only because i have another couple of plugins that also wanted to add blocks and the graph service had the  addDraggableCell function available, possibly not the place for it, but thats where i put it!



graph.png

Rob Holmes

unread,
Dec 21, 2025, 4:00:48 PM (yesterday) Dec 21
to fpga-wars-explora...@googlegroups.com

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

charli va

unread,
Dec 21, 2025, 4:03:58 PM (yesterday) Dec 21
to fpga-wars-explora...@googlegroups.com

Rob Holmes

unread,
3:55 AM (14 hours ago) 3:55 AM
to fpga-wars-explora...@googlegroups.com
Apologies for the roughness of any code i share, im largely just running tests to see whats possible, there are likely many wrong assumptions and shoddy code as i play.

Ive played with this a little more this morning and realised that the use case of adding a single block from a plugin can be extended to adding multiple prewired blocks with a change to the event listener... e.g.

image.png

This would make the listener look more like this:


   //-----------------------------------------------------------------------
    //-- Unified event listener for plugins to add blocks to the design
    //-- Supports both single blocks and multiple connected blocks
    //-- Backward compatible with old plugin.addBlock format
    //-----------------------------------------------------------------------
    iceStudio.bus.events.subscribe('plugin.addConnectedBlocks', function (data) {
   

      if (data && data.blocks && data.blocks.length > 0) {
        console.log('Graph service received plugin.addConnectedBlocks event', data);

        let blockCells = [];
        let allCells = [];

        // Create all blocks
        data.blocks.forEach(function(blockData) {
          if (blockData.type === 'basic.code') {
            // Ensure block has position before loading
            if (!blockData.position) {
              blockData.position = { x: 0, y: 0 };
            }
            let cell = blockforms.loadBasic(blockData);
            blockCells.push(cell);
          }
        });

        // Position blocks horizontally with spacing relative to first block
        if (blockCells.length > 0) {
          let spacing = 400;
         
          // Set relative positions for all blocks
          blockCells.forEach(function(cell, index) {
            cell.set('position', {
              x: index * spacing,
              y: 0
            });
          });

          // First, add the blocks using addDraggableCells (handles positioning, selection, dragging)
          self.addDraggableCells(blockCells);

          // After blocks are added to graph, create and add wires
          if (data.wires && data.wires.length > 0) {
            data.wires.forEach(function(wireSpec) {
              let sourceBlock = blockCells[wireSpec.source.blockIndex];
              let targetBlock = blockCells[wireSpec.target.blockIndex];

              if (sourceBlock && targetBlock) {
                let sourcePortId = null;
                let targetPortId = null;

                let sourceRightPorts = sourceBlock.get('rightPorts');
                let targetLeftPorts = targetBlock.get('leftPorts');

                // Find source port ID
                if (sourceRightPorts) {
                  sourceRightPorts.forEach(function(port) {
                    if (port.name === wireSpec.source.port) {
                      sourcePortId = port.id;
                    }
                  });
                }

                // Find target port ID
                if (targetLeftPorts) {
                  targetLeftPorts.forEach(function(port) {
                    if (port.name === wireSpec.target.port) {
                      targetPortId = port.id;
                    }
                  });
                }

                if (sourcePortId && targetPortId) {
                  let wire = new joint.shapes.ice.Wire({
                    source: { id: sourceBlock.id, port: sourcePortId },
                    target: { id: targetBlock.id, port: targetPortId }
                  });
                  graph.addCell(wire);
                }
              }
            });
          }
        }
      }
    });


So you can add multiple blocks and wires in one shot and then drag them to the location.


used in a plugin like this

function addTestBlocks() {
  console.log('Adding test connected blocks...');
 
  try {
    // Create first block (source) - generates a signal
    var block1Data = {
      type: 'basic.code',
      data: {
        code: '// Source block\nassign out = counter[0];',
        params: [],
        ports: {
          in: [],
          out: [
            { name: 'out' }
          ]
        }
      }
    };
   
    // Create second block (sink) - receives the signal
    var block2Data = {
      type: 'basic.code',
      data: {
        code: '// Sink block\nassign led = in;',
        params: [],
        ports: {
          in: [
            { name: 'in' }
          ],
          out: [
            { name: 'led' }
          ]
        }
      }
    };
   
    // Publish event to add connected blocks
    if (typeof iceStudio !== 'undefined' && iceStudio.bus && iceStudio.bus.events) {
      iceStudio.bus.events.publish('plugin.addConnectedBlocks', {
        blocks: [block1Data, block2Data],
        wires: [
          {
            source: { blockIndex: 0, port: 'out' },
            target: { blockIndex: 1, port: 'in' }
          }
        ]
      });
      console.log('Test blocks added successfully');
    } else {
      console.error('iceStudio event bus not available');
    }
   
  } catch (error) {
    console.error('Error adding test blocks:', error);
  }
}


charli va

unread,
4:00 AM (14 hours ago) 4:00 AM
to fpga-wars-explora...@googlegroups.com
Rob, it makes me so happy to see you using this. When I designed the plugin system, no one but me used it :)

The new IceStudio will have a plugin manager, and integrating plugins will be very easy. I'll have some great news for you sometime in January.

For now, if you have any questions, let me know, and I'll try to help. What you're doing is fantastic because I can use it as an example of "migration" to the new system, and if you'd like, it can be the first plugin uploaded to the system by a community member :)

I'll keep you posted, but great progress!

Jo mo

unread,
4:29 AM (13 hours ago) 4:29 AM
to FPGAwars: explorando el lado libre
Hello Rob and Charli,

Congratulations Rob, this is a great job! 
Up to now i was using the lattice tools for configuring my Plls! 
I may soon play with you plugin to update it also to ECP5 fpgas.
The coming icestudio versions are looking very interesting.

Thanks a lot my friends!
Reply all
Reply to author
Forward
0 new messages