How to connect your SystemC reference model to your verification framework
Posted by Janick Bergeron on July 8th, 2009
Nasib Naser, Phd, CAE, Synopsys
Architects and designers have many reasons to start using the SystemC language to describe their high level specifications for their target System-on-Chip (SoC). In this blog I will not discuss the “why” the SystemC selection BUT the “how” to bring these models into the team’s design verification flow.
Mixed abstractions come from the fact that designers often develop models at the transaction level to capture the correct architecture and analyze the system performance and do so fairly early in the design cycle. Various components of a SoC developed with high level languages such as C, C++, SystemC, and SystemVerilog are increasingly in demand and for obvious reasons. They are faster to write and faster to simulate. High level reference models became increasingly important in verifying the implementation details at the RTL level.
Although SystemVerilog provides different methods (PLI, VPI, DPI, etc) to support communications between SystemVerilog and C/C++ domains, it is not so straight forward for SystemC interface methods. One important reason is that these SystemC methods can be “blocking”, i.e. these methods can “consume” time. And these “blocking” SystemC methods can return value as well. Users should build a very elaborate mechanism to maintain synchronization between the simulations running in the SystemVerilog and the SystemC domains.
Synopsys’ VCS functional verification solution addresses the challenge of this use model with its SystemC-SystemVerilog Transaction-Level Interface (TLI). With TLI, VCS automatically generates adapters to be instantiated in each domain to support SystemVerilog block calls of SystemC methods, or vice versa. These TLI adapters take care of the synchronization between both domains.
To demonstrate the ease of use of this unique interface we start by identifying the SystemC interface methods that SystemVerilog require accessibility to. In the following example we define Read and Write transactions as SC Interface methods as such:
#include<systemc.h>
class Mem_if : virtual public sc_interface {
public :
//do the pure virtual function declaration here
virtual void rd_data(int addr, int &data)=0;
virtual void wr_data(int addr, int data)=0;
};
Manually we create an interface configuration file that declares the methods required for the interface. These methods are declared in a file called Mem_if.h. The content of this configuration file is as follows:
interface Mem_if
direction sv_calls_sc
verilog_adapter Mem_if_adapt_vlog
systemc_adapter Mem_if_adapt_sc#include "Mem_if.h"
task rd_data
input int addVal
inout& int dataValtask wr_data
input int addVal
input int dataVal#endif
};
VCS uses this configuration file to generate the necessary SystemC and SystemVerilog code that enables complete synchronization. The command line is as follows:
%syscan -idf Mem_if.idf
This operation creates the following helper files:
Mem_if_adapt_sc.cpp
Mem_if_adapt_sc.h
Mem_if_adapt_vlog.sv
The helper file Mem_if_adapt_vlog.sv contains a SystemVerilog Interface called Mem_if_adapt_vlog which declares the following tasks:
task wr_data(input int addVal, input int dataVal);
task rd_data(input int addVal, inout int dataVal);
These tasks could then be wrapped and used in the SystemVerilog testbench to access SystemC methods as demonstrated in the following code:
module testbench;
reg clk;
int data;
int cnt;// Instantiate the helper interface
Mem_if_adapt_vlog #(0) mem_if_adapt_vlog_inst();// THE CODE BELOW IS WHERE ALL THE SC TLI FUNCTIONS ARE CALLED.
// VERILOG TASKS ARE WRITTEN AS A WRAPPER FOR READABILITY.
// THESE WRAPPER TASKS ARE INSTANTIATED IN THE VERILOG CODE.// Calling SC TLI function **Write Data**
task sv_wr_data(input int addr, input int data);
mem_if_adapt_vlog_inst.wr_data(addr,data);
endtask// Calling SC TLI function **Read Data**
task sv_rd_data(input int addr, output int data);
mem_if_adapt_vlog_inst.rd_data(addr,data);
endtask. . .
// Use the wrapper code
always @(posedge clk)
begin
if(cnt < 100)
begin
#8 sv_wr_data(cnt,cnt+100);
cnt = cnt+1;
end
endalways @(posedge clk)
begin
if(cnt < 100)
begin
#3 sv_rd_data(cnt-1,data);
end
endendmodule
July 8th, 2009 at 2:09 pm
[...] Nasib Naser at Synopsys looked at how to link a SystemC model to verification. This is the first stab we’ve seen at this, and it’s a good one, but it probably could turn into a series of books. Modeling is essential at advanced process nodes to allow flexibility in the design—something that will become quite obvious at the first respin—but it’s also going to become a requirement even at older nodes because it can shave time off the design process. [...]