sifive / duh-bus

🚌 Bus definition DUH documents
https://github.com/sifive/duh
Apache License 2.0
1 stars 2 forks source link

Review TileLink busDefs #14

Open drom opened 4 years ago

drom commented 4 years ago

Review existing TL busDefs here: https://github.com/sifive/duh-bus/tree/master/specs/sifive.com/TL

Add props to https://github.com/sifive/duh-bus/tree/master/specs/sifive.com/TL

Similar to AXI props https://github.com/sifive/duh-bus/issues/4 we need to discuss TL props.

rpadler commented 4 years ago

TL should really be done as 1 interface with optional signals. As is, there are 3 copies of A and D interfaces between the 3 files - but in reality, it's all the same definition,. You could potentially also figure out a nesting/inheritance semantic.

drom commented 4 years ago

We discussed options of having a single TL busDefinition, and decided to go with 3 definitions to limit configurability, cross constraints and user confusion about the matter.

hcook commented 4 years ago

Parameters used to create individual tilelink bundles:

These are pretty specific to the on-chip, parallel physical channel implementation currently used in most of our interconnects.

hcook commented 4 years ago

Parameters used to calculate the above parameters based on the specific masters and slaves that can see a given link:

These properties are probably generally applicable regardless of which physical serialization of TileLink operations is used.

hcook commented 4 years ago

Parameters that are tracked for every master, as they appear on a particular link:

Parameters thats are tracked for every slave, as they appear on a particular link:

Region types which are used to generate PMAs:

drom commented 4 years ago

Parameters used to create individual tilelink bundles:

Example:

{component: {
  model: {ports:{
    ...,
    tl0_a_addr: 16, // (1)
    tl0_a_data: 32,
    tl0_b_addr: -14, // (3)
  }},
  busInterfaces: [{
    name: 'tl0', interfaceMode: 'slave', // (4)
    busType: {vendor: 'sifive.com', library: 'TL', name: 'C', version: '1.0.0'},
    abstractionTypes: [{
      portMaps: {
        ...,
        a_address: 'tl0_a_addr', // (2)
        a_data: 'tl0_a_data',
        b_address: 'tl0_b_addr',
        // c_address --> (5)
      }
    }]
  }]
}}

Note:

  1. width of physical port of component defined here
  2. width can be discovered from port mapping
  3. width can be different per channel AD[BC]
  4. inerfaceMode can be master or slave
{abstractionDefinition: {
  ..., // (1)
  busType: {vendor: 'sifive.com', library: 'TL', name: 'C', version: '1.0.0'},
    ports: { // (2)
      ...,
      a_valid: {
        description: 'The sender is offering progress on an operation.',
        wire: { // (3)
          onMaster: {direction: 'out', width: 1, presence: 'required'}, // (4)
          onSlave:  {direction: 'in',  width: 1, presence: 'required'}
        }
      },
      a_data: {
        description: 'Data payload for messages with data.',
        wire: {
          isData: true,
          onMaster: {direction: 'out', width: [8, 16, 32, 64, 128, 256]}, // (5)
          onSlave:  {direction: 'in',  width: [8, 16, 32, 64, 128, 256]}
        }
      },
      ...,
    }
  }
}

Note:

  1. busDef = abstractionDefinition document has to be provided that has matching busType
  2. list of possible logic ports
  3. expectations for master and slave interfaces of this type
  4. presence: 'required' attribute when port mapping is required
  5. width constraints

Note:

Will have associated ports.


Note: can be inferred from TL profile:


These are pretty specific to the on-chip, parallel physical channel implementation currently used in most of our interconnects.

drom commented 4 years ago

Parameters used to calculate the above parameters based on the specific masters and slaves that can see a given link:

Can be calculated by knowing:

Master:

comp.busInterfaces.reduce((maxAddress, bi) => {
  if (isTL(bi) && bi.interfaceMode === 'master') {
    const as = comp.addressSpaces.find(ref => ref === bi.addressSpaceRef);
    return max(maxAddress, as.range);
  }
  return maxAddress;
}, 0)

Slave:

comp.busInterfaces.reduce((maxAddress, bi) => {
  if (isTL(bi) && bi.interfaceMode === 'slave') {
    const mm = comp.memoryMaps.find(ref => ref === bi.memoryMapRef);
    const curMaxAddress = mm.addressBlocks.reduce((res, ab) =>
      max(res, ab.baseAddress + ab.range);
    }, 0);
    return max(maxAddress, mm.rang);
  }
  return maxAddress;
})

comp.busInterfaces.reduce((maxId, bi) => {
  if (isTL(bi) && bi.interfaceMode === 'master') {
    let ids = 0;
    if (bi.sourceIds) {
      ids = bi.sourceIds;
    } else {
      const port = bi.portMap.a_source;
      if (port) {
        const width = width(comp.model.port[port]);
        ids = 2 ** width - 1;
      }
    }
    maxId = max(maxId, ids);
  }
  return maxId;
}, 0)
comp.busInterfaces.reduce((maxId, bi) => {
  if (isTL(bi) && bi.interfaceMode === 'slave') {
    let ids = 0;
    if (bi.sinkIds) {
      ids = bi.sinkIds;
    } else {
      const port = bi.portMap.d_sink;
      if (port) {
        const width = width(comp.model.port[port]);
        ids = 2 ** width - 1;
      }
    }
    maxId = max(maxId, ids);
  }
  return maxId;
}, 0)