3

Can someone clearly and intuitively explain what is the difference between an sc_port and an sc_export in SystemC? When does one use a port, and when an export?

I've been reading portions of the manual but I still fail to grasp the main conceptual difference between the two.

PieterNuyts
  • 496
  • 5
  • 20

2 Answers2

5

SystemC requirement is that every port or export MUST be bound/connected to a channel (exception of unbound ports, but let us ignore them for now). Where this channel is instantiated is what differentiates ports and exports.

For an export, the channel instance MUST reside within the same module that has the export, or inside a submodule located inside it.

For a port, the channel instance MUST reside outside the module with the port.

Imagine a module top_module with two submodules sender and receiver instantiated inside it with a one-bit data connecting sender to receiver. If you choose to make the sender's output data to be of type sc_port<>, then you will need to instantiate the channel, say sc_signal<>, in the top_module and the bind statement would ideally be in the constructor of the top_module. But if you choose to make the sender's output data to be of type sc_export<>, then you will need to instantiate the channel inside the submodule sender. Because you are essentially "exporting" the functionality of the channel to the world outside of sender.

This is my intuitive understanding of ports and exports. Please take my "MUST" statement with a grain of salt as the Accellera implementation enforces no such rule but has more to do with binding order (top-down vs bottom-up) than anything else.

As a thumb-rule, I always use exports for outputs and ports for inputs for all my modules. My philosophy is, "you drive it, you own it".

ASICcoder
  • 89
  • 1
  • 5
  • So in your example, I see 3 valid options: (a) both _sender_ and _receiver_ have a data port, and these are connected using an sc_signal in the _top_module_; (b) _sender_ has an export and _receiver_ has a port. Both are connected to each other without an sc_signal, but there's an sc_signal inside _sender_, and _sender_ drives the signal and not the export. (c) _sender_ has a port and _receiver_ has an export. Both are connected without an sc_signal but there's an sc_signal inside _receiver_, and _receiver_ reads the signal and not the export. – PieterNuyts Aug 19 '21 at 08:29
  • Is there an option (d) where they both have an export, and both have an internal sc_signal? Would there be a valid way to connect both exports together, or is this simply not going to work? – PieterNuyts Aug 19 '21 at 08:30
  • @PieterNuyts unfortunately there is no straight forward way to acheive option(d), especially not with *exports*. Because the actual functionalities like *read()*, *write()*, *value_changed_event()*, etc. are all implemented in channels like sc_signal<> or sc_buffer<>. The *ports* and *exports* are merely like a window to use those functions. Even when you call *port.read()*, it invokes *port->channel.read()* – ASICcoder Aug 20 '21 at 03:57
  • So *sc_signal<>* in both *sender* and *receiver* would mean two completely independent channels. Although you can technically achieve option(d) using *multiports*, using ports not exports, it would be a hassle and also inefficient. – ASICcoder Aug 20 '21 at 04:06
1

From IEEE Standard for Standard SystemC ® Language Reference Manual

Class sc_export allows a module to provide an interface to its parent module. An export forwards interface method calls to the channel to which the export is bound. An export defines a set of services (as identified by the type of the export) that are provided by the module containing the export.

Providing an interface through an export is an alternative to a module simply implementing the interface. The use of an explicit export allows a single module instance to provide multiple interfaces in a structured manner.

If a module is to call a member function belonging to a channel instance within a child module, that call should be made through an export of the child module.

The upshot of all this being that without sc_export one would need to create an sc_port in the parent module and connect it to the port of the child module in order to expose a child's port as a port of the parent module. Using sc_export allows one to directly expose a child port as port of the parent module. Simply create an instance of sc_export and bind it to a child port.

For a full description and class specification see section 5.13 of IEEE Standard for Standard SystemC ® Language Reference Manual

p.s. If you do not intend to convert your code to VHDL then there is no need to use sc_export. SystemC is just standard C++ and ports are just normal public members (you could have a private port but there hardly seems much point) so you can just take a reference to it and pretend that it's a member of its parent module or any other module that has access to it for that matter.

systemcpro
  • 856
  • 1
  • 7
  • 15
  • I noticed you use the word "connect" when referring to an sc_port and the word "bind" when referring to an sc_export. What's the difference? How is connecting a parent port to a child port less practical than binding a parent export to a child port? – PieterNuyts Mar 30 '21 at 08:22
  • @PieterNuyts I use the term connect for what we normally think of as getting a wire and connecting two ports together. Whereas bind I use for associating two things without any intermediate connecting wire. From the docs "At elaboration time the ports of a module are connected (bound) to designated channels. The interface, port, channel structure provides for great flexibility in modeling communication and in model refinement.". Hedging their bets here. Later they use "bound" in reference to `sc_export`. – systemcpro Mar 30 '21 at 09:14
  • @PieterNuyts. Or, I connect and SystemC binds at elaboration time or I explicitly bind without connecting. – systemcpro Mar 30 '21 at 09:23
  • 1
    I get what you mean now with bind vs. connect. But\ since you can also explicitly bind a child module port to a parent module port without needing an sc_signal in between (see section 5.12.7 of the LRM), I still don't get why this would be less practical than using exports? – PieterNuyts Apr 07 '21 at 13:01
  • 1
    @PieterNuyts. Correct and as it's just C++ you don't even need a parent port. You could just use a reference to the child port in the parent and no connecting or binding required. This, however, confuses the tools that automatically generate VHDL or Verilog from SystemC. As per my postscript, if you're not converting to VHDL there is no need for `sc_export` but for toolchains it is needed to explicitly inform the tool of the layout hierarchy. – systemcpro Apr 09 '21 at 06:21
  • But even if you do want to use tools to convert to VHDL,what's wrong with having a port in the parent which is bound to a port in the child? – PieterNuyts Apr 09 '21 at 07:53
  • @PieterNuyts. Nothing wrong with that at all. But you can get the tool to automatically generate the port for you using `sc_export`. Hence, every time you use that module the tool will automatically insert a port in the parent module for you. In principle you could have modules with no ports at all where all child modules export their ports. The tool would then generate all the ports in the parent module for you. That's all it is. Choose whichever method fits your use case best. All roads lead to Rome. But toolchains are fussy and have to be told explicitly told what to generate. – systemcpro Apr 09 '21 at 08:58
  • I'm afraid I still don't understand it. Surely the people who defined SystemC had a reason to include exports in the standard in addition to ports? I can't imagine the only reason being that certain tools can do stuff with exports but refuse to do the exact same stuff with ports. After all, SystemC had to be defined before any tools could support it at all. – PieterNuyts Apr 12 '21 at 13:05
  • My point is: Going back to your example about getting a wire and connecting two ports: You can also perfectly connect two ports without getting a wire at all, at least if one port is a port of a child module and the other is a port of the parent module. So if we want to connect (or bind) two ports without needing to get a wire, we can still use sc_port. So what do we need sc_export for? – PieterNuyts Apr 12 '21 at 13:07
  • So, following the conversation, it sounds like there is no reason and hardly any difference in syntax between using sc_port or sc_export, when binding directly between inner module and outer module – mattgately Mar 17 '22 at 19:29