adds initial files for mt test
Some checks failed
SCC Test/pipeline/head There was a failure building this commit
Some checks failed
SCC Test/pipeline/head There was a failure building this commit
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -48,4 +48,5 @@
|
|||||||
/.venv/
|
/.venv/
|
||||||
/.cache
|
/.cache
|
||||||
/CMakeUserPresets.json
|
/CMakeUserPresets.json
|
||||||
*.scview
|
/*.scview
|
||||||
|
/*.log
|
||||||
30
.vscode/launch.json
vendored
30
.vscode/launch.json
vendored
@@ -4,6 +4,36 @@
|
|||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "gdb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "quantum_keeper_mt",
|
||||||
|
"program": "${workspaceFolder}/build/Debug/tests/quantum_keeper_mt/quantum_keeper_mt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cppdbg quantum_keeper_mt",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/build/Debug/tests/quantum_keeper_mt/quantum_keeper_mt",
|
||||||
|
"args": [],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${fileDirname}",
|
||||||
|
"environment": [],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Set Disassembly Flavor to Intel",
|
||||||
|
"text": "-gdb-set disassembly-flavor intel",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "cci_param_restricted",
|
"name": "cci_param_restricted",
|
||||||
"type": "gdb",
|
"type": "gdb",
|
||||||
|
|||||||
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -6,6 +6,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
|
"editor.hover.delay": 1500,
|
||||||
"clangd.arguments": [
|
"clangd.arguments": [
|
||||||
"--pretty",
|
"--pretty",
|
||||||
"--background-index",
|
"--background-index",
|
||||||
|
|||||||
@@ -15,11 +15,12 @@
|
|||||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
|
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
|
||||||
"CMAKE_CXX_STANDARD": "17",
|
"CMAKE_CXX_STANDARD": "20",
|
||||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
||||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
||||||
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "cmake-conan/conan_provider.cmake",
|
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "cmake-conan/conan_provider.cmake",
|
||||||
"CONAN_BUILD_PROFILE": "auto-cmake"
|
"CONAN_HOST_PROFILE": "auto-cmake",
|
||||||
|
"CONAN_BUILD_PROFILE": "conan_host_profile"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class Pkg(ConanFile):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def requirements(self):
|
def requirements(self):
|
||||||
self.requires("systemc/2.3.4")
|
self.requires("systemc/3.0.1")
|
||||||
self.requires("fmt/8.0.1")
|
self.requires("fmt/8.0.1")
|
||||||
self.requires("spdlog/1.9.2")
|
self.requires("spdlog/1.9.2")
|
||||||
self.requires("boost/1.85.0")
|
self.requires("boost/1.85.0")
|
||||||
@@ -44,9 +44,6 @@ class Pkg(ConanFile):
|
|||||||
self.requires("yaml-cpp/0.7.0")
|
self.requires("yaml-cpp/0.7.0")
|
||||||
self.requires("jsoncpp/1.9.5")
|
self.requires("jsoncpp/1.9.5")
|
||||||
self.requires("zlib/1.2.12")
|
self.requires("zlib/1.2.12")
|
||||||
self.requires("rapidjson/cci.20230929")
|
|
||||||
if os.path.isdir("tgc-iss/dbt-rise-plugins"):
|
|
||||||
self.requires("lua/5.4.3")
|
|
||||||
|
|
||||||
def build_requirements(self):
|
def build_requirements(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
2
scc
2
scc
Submodule scc updated: 6c25b65dc9...e672491c6a
@@ -11,6 +11,7 @@ add_subdirectory(sc_fixed_tracing)
|
|||||||
add_subdirectory(cxs_tlm)
|
add_subdirectory(cxs_tlm)
|
||||||
add_subdirectory(tlm_memory)
|
add_subdirectory(tlm_memory)
|
||||||
add_subdirectory(memory_subsys)
|
add_subdirectory(memory_subsys)
|
||||||
|
add_subdirectory(quantum_keeper_mt)
|
||||||
add_subdirectory(sim_speed)
|
add_subdirectory(sim_speed)
|
||||||
if(FULL_TEST_SUITE)
|
if(FULL_TEST_SUITE)
|
||||||
add_subdirectory(sim_performance)
|
add_subdirectory(sim_performance)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#define EXAMPLES_EX09_HIERARCHICAL_OVERRIDE_OF_PARAMETER_VALUES_TOP_MODULE_H_
|
#define EXAMPLES_EX09_HIERARCHICAL_OVERRIDE_OF_PARAMETER_VALUES_TOP_MODULE_H_
|
||||||
|
|
||||||
#include <cci_configuration>
|
#include <cci_configuration>
|
||||||
|
#include <fmt/core.h>
|
||||||
#include <scc/report.h>
|
#include <scc/report.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <tlm>
|
#include <tlm>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
#include "initiator.h"
|
#include "initiator.h"
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class top_module
|
* @class top_module
|
||||||
@@ -89,15 +91,13 @@ public:
|
|||||||
|
|
||||||
/// Creating instances of initiator(s)
|
/// Creating instances of initiator(s)
|
||||||
for(int i = 0; i < n_initiators; i++) {
|
for(int i = 0; i < n_initiators; i++) {
|
||||||
snprintf(initiatorName, sizeof(initiatorName), "initiator_%d", i);
|
auto initiatorName = fmt::format("initiator_{}", i);
|
||||||
SCCINFO(SCMOD) << "[TOP_MODULE C_TOR] : Creating initiator : " << initiatorName;
|
SCCINFO(SCMOD) << "[TOP_MODULE C_TOR] : Creating initiator : " << initiatorName;
|
||||||
|
|
||||||
snprintf(stringMisc, sizeof(stringMisc), "%s.%s.initiator_ID", name(), initiatorName);
|
auto paramName = fmt::format("{}.{}.initiator_ID", name(), initiatorName);
|
||||||
|
auto quotedInitiatorName = fmt::format("\"initiator_{}\"", i);
|
||||||
snprintf(initiatorName, sizeof(initiatorName), "\"initiator_%d\"", i);
|
m_broker.set_preset_cci_value(paramName, cci::cci_value::from_json(quotedInitiatorName));
|
||||||
m_broker.set_preset_cci_value(stringMisc, cci::cci_value::from_json(initiatorName));
|
initiatorList.push_back(new initiator(initiatorName.c_str()));
|
||||||
snprintf(initiatorName, sizeof(initiatorName), "initiator_%d", i);
|
|
||||||
initiatorList.push_back(new initiator(initiatorName));
|
|
||||||
|
|
||||||
// Binding of initiator to Router
|
// Binding of initiator to Router
|
||||||
SCCINFO(SCMOD) << "[TOP MODULE C_TOR] : Binding Router_Initiator to " << initiatorName;
|
SCCINFO(SCMOD) << "[TOP MODULE C_TOR] : Binding Router_Initiator to " << initiatorName;
|
||||||
@@ -109,22 +109,21 @@ public:
|
|||||||
|
|
||||||
// Creating instances of target(s)
|
// Creating instances of target(s)
|
||||||
for(int i = 0; i < n_targets; i++) {
|
for(int i = 0; i < n_targets; i++) {
|
||||||
snprintf(targetName, sizeof(targetName), "target_%d", i);
|
auto targetName = fmt::format("target_{}", i);
|
||||||
SCCINFO(SCMOD) << "[TOP_MODULE C_TOR] : Creating target : " << targetName;
|
SCCINFO(SCMOD) << "[TOP_MODULE C_TOR] : Creating target : " << targetName;
|
||||||
|
|
||||||
snprintf(stringMisc, sizeof(stringMisc), "%s.%s.target_ID", name(), targetName);
|
auto paramName0 = fmt::format("{}.{}.initiator_ID", name(), targetName);
|
||||||
snprintf(targetName, sizeof(targetName), "\"target_%d\"", i);
|
auto quotedTargetName = fmt::format("\"target_{}\"", i);
|
||||||
m_broker.set_preset_cci_value(stringMisc, cci::cci_value::from_json(targetName));
|
m_broker.set_preset_cci_value(paramName0, cci::cci_value::from_json(targetName));
|
||||||
snprintf(targetName, sizeof(targetName), "target_%d", i);
|
|
||||||
|
|
||||||
// Set preset value for maximum target size(memory)
|
// Set preset value for maximum target size(memory)
|
||||||
snprintf(stringMisc, sizeof(stringMisc), "%s.%s.s_size", name(), targetName);
|
auto paramName1 = fmt::format("{}.{}.initiator_ID", name(), targetName);
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << targetSize;
|
ss << targetSize;
|
||||||
|
|
||||||
m_broker.set_preset_cci_value(stringMisc, cci::cci_value::from_json(ss.str()));
|
m_broker.set_preset_cci_value(paramName1, cci::cci_value::from_json(ss.str()));
|
||||||
targetList.push_back(new target(targetName));
|
targetList.push_back(new target(targetName.c_str()));
|
||||||
|
|
||||||
// Binding Router to target
|
// Binding Router to target
|
||||||
SCCINFO(SCMOD) << "[TOP MODULE C_TOR] : Binding Router_Initiator to " << targetName;
|
SCCINFO(SCMOD) << "[TOP MODULE C_TOR] : Binding Router_Initiator to " << targetName;
|
||||||
@@ -133,7 +132,7 @@ public:
|
|||||||
|
|
||||||
// Try re-setting locked values for Router Table contents
|
// Try re-setting locked values for Router Table contents
|
||||||
for(int i = 0; i < n_targets; i++) {
|
for(int i = 0; i < n_targets; i++) {
|
||||||
snprintf(targetName, sizeof(targetName), "%s.RouterInstance.r_index_%d", name(), i);
|
auto targetName = fmt::format("{}.RouterInstance.r_index_{}", name(), i);
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << i;
|
ss << i;
|
||||||
@@ -145,12 +144,12 @@ public:
|
|||||||
SCCINFO(SCMOD) << "[ROUTER : Caught] : " << exception.what();
|
SCCINFO(SCMOD) << "[ROUTER : Caught] : " << exception.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(targetName, sizeof(targetName), "%s.RouterInstance.r_sa_%d", name(), i);
|
targetName = fmt::format("{}.RouterInstance.r_sa_{}", name(), i);
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << (i * targetSize);
|
ss << (i * targetSize);
|
||||||
|
|
||||||
snprintf(targetBaseAddr, sizeof(targetBaseAddr), "%s.target_%d.s_base_addr", name(), i);
|
auto targetBaseAddr = fmt::format("{}.target_{}.s_base_addr", name(), i);
|
||||||
|
|
||||||
cci::cci_param_untyped_handle h = m_broker.get_param_handle(targetBaseAddr);
|
cci::cci_param_untyped_handle h = m_broker.get_param_handle(targetBaseAddr);
|
||||||
h.set_cci_value(cci::cci_value::from_json(ss.str()));
|
h.set_cci_value(cci::cci_value::from_json(ss.str()));
|
||||||
@@ -162,7 +161,7 @@ public:
|
|||||||
SCCINFO(SCMOD) << "[ROUTER : Caught] : " << exception.what();
|
SCCINFO(SCMOD) << "[ROUTER : Caught] : " << exception.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(targetName, sizeof(targetName), "%s.RouterInstance.r_ea_%d", name(), i);
|
targetName = fmt::format("{}.RouterInstance.r_ea_{}", name(), i);
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << ((i + 1) * targetSize - 1);
|
ss << ((i + 1) * targetSize - 1);
|
||||||
@@ -210,11 +209,6 @@ private:
|
|||||||
std::vector<initiator*> initiatorList; ///< STD::VECTOR for initiators
|
std::vector<initiator*> initiatorList; ///< STD::VECTOR for initiators
|
||||||
std::vector<target*> targetList; ///< STD::VECTOR for targets
|
std::vector<target*> targetList; ///< STD::VECTOR for targets
|
||||||
|
|
||||||
char initiatorName[50]; ///< initiator_ID
|
|
||||||
char targetName[50]; ///< target_ID
|
|
||||||
char stringMisc[50]; ///< String to be used for misc things
|
|
||||||
char targetBaseAddr[50]; ///< The base address of the target
|
|
||||||
|
|
||||||
int addrValue{0}; ///< Address Value
|
int addrValue{0}; ///< Address Value
|
||||||
int targetSize; ///< Maximum target Size (preset value)
|
int targetSize; ///< Maximum target Size (preset value)
|
||||||
int r_addr_max; ///< Maximum Router Table's memory range
|
int r_addr_max; ///< Maximum Router Table's memory range
|
||||||
|
|||||||
5
tests/quantum_keeper_mt/CMakeLists.txt
Normal file
5
tests/quantum_keeper_mt/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
add_executable (quantum_keeper_mt
|
||||||
|
sc_main.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries (quantum_keeper_mt LINK_PUBLIC scc-sysc)
|
||||||
|
add_test(NAME quantum_keeper_mt COMMAND quantum_keeper_mt)
|
||||||
46
tests/quantum_keeper_mt/sc_main.cpp
Normal file
46
tests/quantum_keeper_mt/sc_main.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "top_module.h"
|
||||||
|
#include "util/logging.h"
|
||||||
|
#include <csetjmp>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <scc/configurer.h>
|
||||||
|
#include <scc/report.h>
|
||||||
|
#include <scc/trace.h>
|
||||||
|
#include <scc/tracer.h>
|
||||||
|
#include <sysc/utils/sc_report.h>
|
||||||
|
#include <sysc/utils/sc_report_handler.h>
|
||||||
|
#include <tlm_utils/tlm_quantumkeeper.h>
|
||||||
|
#include <util/ities.h>
|
||||||
|
|
||||||
|
using namespace scc;
|
||||||
|
using namespace sc_core;
|
||||||
|
|
||||||
|
jmp_buf abrt;
|
||||||
|
void ABRThandler(int sig) { longjmp(abrt, 1); }
|
||||||
|
|
||||||
|
int sc_main(int argc, char* argv[]) {
|
||||||
|
signal(SIGABRT, ABRThandler);
|
||||||
|
auto my_name = util::split(argv[0], '/').back();
|
||||||
|
auto level = "3"; // getenv("SCC_TEST_VERBOSE");
|
||||||
|
auto log_lvl = level ? static_cast<scc::log>(std::min(strtoul(level, nullptr, 10) + 4, 7UL)) : log::FATAL;
|
||||||
|
scc::init_logging(LogConfig().logLevel(log_lvl).logAsync(false).msgTypeFieldWidth(35));
|
||||||
|
LOGGER(DEFAULT)::reporting_level().store(logging::TRACEALL);
|
||||||
|
scc::configurer cfg("");
|
||||||
|
// create tracer if environment variable SCC_TEST_TRACE is defined
|
||||||
|
std::unique_ptr<scc::tracer> tracer;
|
||||||
|
if(auto* test_trace = getenv("SCC_TEST_TRACE")) {
|
||||||
|
tracer = std::make_unique<scc::tracer>(my_name, scc::tracer::ENABLE, scc::tracer::ENABLE);
|
||||||
|
tracer->set_default_trace_enable(true);
|
||||||
|
}
|
||||||
|
int result = -1;
|
||||||
|
tlm_utils::tlm_quantumkeeper::set_global_quantum(3_us);
|
||||||
|
if(setjmp(abrt) == 0) {
|
||||||
|
// instantiate design(s)
|
||||||
|
top_module top_mod("top_module_inst");
|
||||||
|
// Start the simulation
|
||||||
|
sc_core::sc_start(20_us);
|
||||||
|
} else {
|
||||||
|
SCCERR() << "Some error occured";
|
||||||
|
}
|
||||||
|
return sc_core::sc_report_handler::get_count(sc_core::SC_ERROR) + sc_core::sc_report_handler::get_count(sc_core::SC_WARNING);
|
||||||
|
}
|
||||||
88
tests/quantum_keeper_mt/top_module.h
Normal file
88
tests/quantum_keeper_mt/top_module.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#ifndef _TOP_MODULE_H_
|
||||||
|
#define _TOP_MODULE_H_
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <scc/async_queue.h>
|
||||||
|
#include <scc/async_thread.h>
|
||||||
|
#include <scc/report.h>
|
||||||
|
#include <sysc/kernel/sc_initializer_function.h>
|
||||||
|
#include <sysc/kernel/sc_simcontext.h>
|
||||||
|
#include <thread>
|
||||||
|
#include <tlm/scc/quantum_keeper.h>
|
||||||
|
#include <tlm>
|
||||||
|
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h>
|
||||||
|
#include <tlm_utils/simple_initiator_socket.h>
|
||||||
|
#include <tlm_utils/simple_target_socket.h>
|
||||||
|
#include <util/logging.h>
|
||||||
|
|
||||||
|
struct initiator : ::sc_core ::sc_module {
|
||||||
|
tlm_utils::simple_initiator_socket<initiator, scc::LT> isckt{"isckt"};
|
||||||
|
|
||||||
|
initiator(sc_core::sc_module_name nm)
|
||||||
|
: sc_core::sc_module(nm) {
|
||||||
|
SC_THREAD(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
~initiator() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run() {
|
||||||
|
wait(sc_core::SC_ZERO_TIME); // guard elaboration phase
|
||||||
|
quantum_keeper.reset();
|
||||||
|
core_executor.start([this]() { return thread_exec(); });
|
||||||
|
wait(core_executor.thread_finish_event());
|
||||||
|
sc_core::sc_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_core::sc_time thread_exec() {
|
||||||
|
SCCDEBUG(SCMOD) << "starting thread_exec";
|
||||||
|
for(auto i = 0u; i < 16; ++i) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
if(i && (i % 3) == 0) {
|
||||||
|
tlm::tlm_generic_payload gp;
|
||||||
|
sc_core::sc_time t;
|
||||||
|
SCCDEBUG(SCMOD) << "initiating b_transport at local time " << quantum_keeper.get_local_absolute_time();
|
||||||
|
quantum_keeper.execute_on_sysc([this, &gp, &t]() {
|
||||||
|
SCCDEBUG(SCMOD) << "executing b_transport";
|
||||||
|
auto t0 = sc_core::sc_time_stamp();
|
||||||
|
this->isckt->b_transport(gp, t);
|
||||||
|
return t0 - sc_core::sc_time_stamp();
|
||||||
|
});
|
||||||
|
if(t.value()) {
|
||||||
|
SCCDEBUG(SCMOD) << "incrementing local time by b_transport delay of " << t;
|
||||||
|
quantum_keeper.inc(t);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quantum_keeper.check_and_sync(1_us);
|
||||||
|
}
|
||||||
|
SCCDEBUG(SCMOD) << "local time now " << quantum_keeper.get_local_absolute_time();
|
||||||
|
}
|
||||||
|
SCCDEBUG(SCMOD) << "finished thread_exec at local time " << quantum_keeper.get_local_absolute_time();
|
||||||
|
return quantum_keeper.get_local_absolute_time();
|
||||||
|
}
|
||||||
|
tlm::scc::quantumkeeper_mt quantum_keeper;
|
||||||
|
scc::async_thread core_executor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// top_module
|
||||||
|
struct top_module : ::sc_core ::sc_module {
|
||||||
|
initiator core{"core"};
|
||||||
|
|
||||||
|
tlm_utils::simple_target_socket<top_module, scc::LT> tsckt{"tsckt"};
|
||||||
|
|
||||||
|
top_module(sc_core::sc_module_name nm)
|
||||||
|
: sc_core::sc_module(nm) {
|
||||||
|
core.isckt(tsckt);
|
||||||
|
tsckt.register_b_transport(this, &top_module::b_transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
~top_module() {}
|
||||||
|
|
||||||
|
void b_transport(tlm::tlm_generic_payload& gp, sc_core::sc_time& t) {
|
||||||
|
SCCDEBUG(SCMOD) << "Received b_transport call at local time " << t;
|
||||||
|
t += 5_us;
|
||||||
|
gp.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // _TOP_MODULE_H_
|
||||||
Reference in New Issue
Block a user