UVM-SystemC
The source code for this example can be found in examples/uvm-systemc
Description
This example shows how to do simulation using UVM-SystemC with SoCMake.
In this case, it's reusing the uvm-systemc hello world example and implement it with SoCMake.
Example
Directory structure
Lets take a look at the directory structure of the example first.
.
├── CMakeLists.txt
├── consumer.h
├── hello_world.cpp
├── packet.h
├── producer.h
└── top.h
packet.h
C++ header to describe the packet used in the UVM transaction.
Show packet.h
//----------------------------------------------------------------------
// Copyright 2014 NXP B.V.
// Copyright 2007-2010 Mentor Graphics Corporation
// Copyright 2007-2010 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------------------
#ifndef PACKET_H_
#define PACKET_H_
#include <uvm>
class packet : public uvm::uvm_transaction
{
public:
int addr;
UVM_OBJECT_UTILS(packet);
// TODO constraints
//constraint c { addr >= 0 && addr < 'h100; }
packet( std::string name = "packet" )
: uvm_transaction(name)
{}
virtual void do_print(const uvm::uvm_printer& printer) const
{
printer.print_field_int("addr", addr);
}
};
#endif /* PACKET_H_ */
consumer.h
C++ header to describe the consumer, an UVM component
Show consumer.h
//----------------------------------------------------------------------
// Copyright 2014 NXP B.V.
// Copyright 2007-2010 Mentor Graphics Corporation
// Copyright 2007-2011 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------------------
#ifndef CONSUMER_H_
#define CONSUMER_H_
#include <systemc>
#include <uvm>
#include "packet.h"
template <typename T = packet>
class consumer : public uvm::uvm_component
{
public:
uvm::uvm_blocking_put_imp<T,consumer<T> > in;
uvm::uvm_get_port<T> out;
consumer( uvm::uvm_component_name name )
: uvm::uvm_component(name),
in("in", this),
out("out"),
count(0)
{}
UVM_COMPONENT_UTILS(consumer<T>);
virtual void run_phase(uvm::uvm_phase& phase)
{
T p;
while(out.size())
{
out->get(p);
put(p);
}
}
void put(const T& p)
{
m.lock(); //lock.get();
count++;
accept_tr(p);
sc_core::wait(10, sc_core::SC_US);
begin_tr(p);
sc_core::wait(30, sc_core::SC_US);
end_tr(p);
std::ostringstream str;
str << "Received "
<< p
<< " local_count="
<< count;
UVM_INFO("consumer", str.str(), uvm::UVM_MEDIUM);
if( uvm::uvm_report_enabled( uvm::UVM_HIGH, uvm::UVM_INFO, ""))
p.print();
m.unlock(); //lock.put();
}
private:
int count;
sc_core::sc_mutex m; // semaphore lock
};
#endif /* CONSUMER_H_ */
producer.h
C++ header to describe the producer, an UVM component
Show producer.h
//----------------------------------------------------------------------
// Copyright 2014 NXP B.V.
// Copyright 2007-2010 Mentor Graphics Corporation
// Copyright 2007-2011 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------------------
#ifndef PRODUCER_H_
#define PRODUCER_H_
#include <systemc>
#include <uvm>
#include "packet.h"
template <typename T = packet>
class producer : public uvm::uvm_component
{
public:
uvm::uvm_blocking_put_port<T> out;
producer( uvm::uvm_component_name name ) : uvm::uvm_component(name), out("out"), num_packets(0), count(0)
{
uvm::uvm_config_db<int>::get(this, "", "num_packets", num_packets);
}
/* TODO implement all transaction functions
`uvm_component_utils_begin(producer #(T))
`uvm_field_object(proto, UVM_ALL_ON + UVM_REFERENCE)
`uvm_field_int(num_packets, UVM_ALL_ON + UVM_DEC)
`uvm_field_int(count, UVM_ALL_ON + UVM_DEC + UVM_READONLY)
`uvm_component_utils_end
*/
virtual void run_phase( uvm::uvm_phase& phase )
{
T p;
std::stringstream num;
UVM_INFO(get_name(), "Starting.", uvm::UVM_MEDIUM);
for (count = 0; count < num_packets; count++)
{
num.str(""); // clear string
num << count;
p.set_name(get_name() + "-" + num.str());
// TODO
//p.set_initiator(this);
//if ((uvm::uvm_verbosity)recording_detail != uvm::UVM_NONE)
// p.enable_recording("packet_stream");
// p.randomize();
// fill address field with dummy value
p.addr = 0x100 + count;
UVM_INFO(get_name(), "Sending " + p.get_name(), uvm::UVM_MEDIUM);
if( uvm_report_enabled( uvm::UVM_HIGH, uvm::UVM_INFO, ""))
p.print();
out->put(p);
sc_core::wait(10.0, sc_core::SC_US); // 10us;
}
UVM_INFO(get_name(), "Exiting.", uvm::UVM_MEDIUM);
}
protected:
T proto;
int num_packets;
int count;
};
#endif /* PRODUCER_H_ */
top.h
C++ header to describe the top module used in the UVM environment
//----------------------------------------------------------------------
// Copyright 2014 NXP B.V.
// Copyright 2007-2010 Mentor Graphics Corporation
// Copyright 2007-2010 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------------------
#ifndef TOP_H_
#define TOP_H_
#include <systemc>
#include <uvm>
#include "producer.h"
#include "consumer.h"
#include "packet.h"
class top : public uvm::uvm_component
{
public:
producer<packet> p1;
producer<packet> p2;
tlm::tlm_fifo<packet> f; // there is no uvm_tlm_fifo in UVM-SystemC
consumer<packet> c;
UVM_COMPONENT_UTILS(top);
top( uvm::uvm_component_name name )
: uvm::uvm_component(name),
p1("producer1"),
p2("producer2"),
f("fifo"),
c("consumer")
{
p1.out.connect(c.in);
p2.out.connect(f); // f.blocking_put_export
c.out.connect(f); // f.get_export
}
virtual void run_phase( uvm::uvm_phase& phase )
{
phase.raise_objection(this);
sc_core::wait(1.0, sc_core::SC_MS); // 1ms
phase.drop_objection(this);
}
};
#endif /* TOP_H_ */
hello_world.cpp
This is a standard SystemC file. It will create the UVM environment by instantiating it different modules.
//----------------------------------------------------------------------
// Copyright 2014 NXP B.V.
// Copyright 2007-2010 Mentor Graphics Corporation
// Copyright 2007-2010 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------------------
#include <systemc>
#include <uvm>
#include "top.h"
using namespace uvm;
int sc_main(int, char*[])
{
uvm::uvm_config_db<int>::set(NULL, "top.producer1", "num_packets", 2);
uvm::uvm_config_db<int>::set(NULL, "top.producer2", "num_packets", 4);
uvm::uvm_config_db<int>::set(NULL, "*", "recording_detail", uvm::UVM_LOW);
top mytop("top");
uvm_default_printer->knobs.reference = 0;
uvm::uvm_root::get()->print_topology();
run_test();
return 0;
}
CMakeLists.txt
And finally we need a top CMakeLists.txt that will assemble the full project and create simulation targets.
cmake_minimum_required(VERSION 3.27)
project(uvm-systemc_example CXX C)
include("../../SoCMakeConfig.cmake")
systemc_build(VERSION 3.0.0 EXACT_VERSION)
uvm_systemc_build(VERSION 1.0-beta6)
add_executable(systemc_example
hello_world.cpp
)
target_include_directories(systemc_example PUBLIC
.
)
target_link_libraries(systemc_example PUBLIC
SystemC::systemc
UVM-SystemC::shared)
add_custom_target(run_systemc_example
COMMAND systemc_example)
This one is very similar to the one in the systemc example.
The current directory is included to the target, using target_include_directories(), to give path to the different headers.
We also link the UVM-SystemC library as usual.
Running the simulation
Simulation can be run the same way as always:
mkdir build
cd build
cmake ../ # Configure project
make run_systemc_example # Build and run testbench