Initial commit
This commit is contained in:
commit
36e067cbf6
12
.clang-format
Normal file
12
.clang-format
Normal file
@ -0,0 +1,12 @@
|
||||
BasedOnStyle: GNU
|
||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
||||
PointerAlignment: Left
|
||||
UseTab: Never
|
||||
IndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
BreakAfterReturnType: Automatic
|
||||
BreakConstructorInitializers: AfterColon
|
||||
PackConstructorInitializers: Never
|
||||
IncludeBlocks: Regroup
|
||||
BreakBeforeBraces: Allman
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.cache/
|
||||
build/
|
||||
13
CMakeLists.txt
Normal file
13
CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(vcppd)
|
||||
|
||||
add_library(vcppd src/vcd.cpp src/builder.cpp)
|
||||
target_include_directories(vcppd PUBLIC include)
|
||||
set_target_properties(vcppd PROPERTIES CXX_STANDARD 20)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
add_executable(vcppd-test test/test.cpp)
|
||||
target_link_libraries(vcppd-test PUBLIC vcppd)
|
||||
set_target_properties(vcppd-test PROPERTIES CXX_STANDARD 20)
|
||||
endif()
|
||||
42
include/vcppd/builder.h
Normal file
42
include/vcppd/builder.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef VCPPD_VCD_BUILDER_H
|
||||
#define VCPPD_VCD_BUILDER_H
|
||||
|
||||
#include "vcppd/vcd.h"
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace vcppd
|
||||
{
|
||||
|
||||
class Builder
|
||||
{
|
||||
friend Vcd;
|
||||
friend Scope<Builder>;
|
||||
|
||||
public:
|
||||
Builder(std::ostream& stream);
|
||||
|
||||
Vcd build() const;
|
||||
|
||||
Scope<Builder> scope(const std::string& name);
|
||||
|
||||
private:
|
||||
template <typename U>
|
||||
void trace(const std::string& name, const U& ref,
|
||||
const std::string& short_name)
|
||||
{
|
||||
stream << std::format("$var wire {} {} {} $end", sizeof(U) * 8, name,
|
||||
short_name)
|
||||
<< std::endl;
|
||||
variables[name] = detail::variable_entry{ &ref, sizeof(U) };
|
||||
}
|
||||
|
||||
void unscope();
|
||||
|
||||
std::ostream& stream;
|
||||
detail::variable_map variables;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VCPPD_VCD_BUILDER_H
|
||||
57
include/vcppd/scope.h
Normal file
57
include/vcppd/scope.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef VCPPD_VCD_SCOPE_H
|
||||
#define VCPPD_VCD_SCOPE_H
|
||||
|
||||
#include "vcppd/vcd.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace vcppd
|
||||
{
|
||||
|
||||
template <typename T> class Scope
|
||||
{
|
||||
friend T;
|
||||
|
||||
public:
|
||||
Scope(const Scope&) = delete;
|
||||
Scope& operator=(const Scope&) = delete;
|
||||
|
||||
Scope<Scope> scope(const std::string& name)
|
||||
{
|
||||
return Scope<Scope>(name, *this);
|
||||
}
|
||||
|
||||
T& unscope()
|
||||
{
|
||||
parent.unscope();
|
||||
return parent;
|
||||
}
|
||||
|
||||
template <typename U> Scope& trace(const std::string& name, const U& ref)
|
||||
{
|
||||
parent.trace(this->name + "_" + name, ref, name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Scope(const std::string& name, T& parent) :
|
||||
name(name),
|
||||
parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
Scope& trace(const std::string& name, const U& ref,
|
||||
const std::string& short_name)
|
||||
{
|
||||
parent.trace(this->name + "_" + name, ref, short_name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
T& parent;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VCPPD_VCD_SCOPE_H
|
||||
45
include/vcppd/vcd.h
Normal file
45
include/vcppd/vcd.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef VCPPD_VCD_H
|
||||
#define VCPPD_VCD_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace vcppd
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct variable_entry
|
||||
{
|
||||
const void* ref;
|
||||
size_t size;
|
||||
};
|
||||
using variable_map = std::unordered_map<std::string, variable_entry>;
|
||||
|
||||
}
|
||||
|
||||
template <typename T> class Scope;
|
||||
class Builder;
|
||||
|
||||
class Vcd
|
||||
{
|
||||
friend Builder;
|
||||
|
||||
public:
|
||||
~Vcd();
|
||||
|
||||
void tick();
|
||||
|
||||
private:
|
||||
Vcd(const Builder&);
|
||||
|
||||
std::ostream& stream;
|
||||
unsigned int current_time;
|
||||
detail::variable_map variables;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VCPPD_VCD_H
|
||||
8
include/vcppd/vcppd.h
Normal file
8
include/vcppd/vcppd.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef VCPPD_H
|
||||
#define VCPPD_H
|
||||
|
||||
#include "vcppd/builder.h"
|
||||
#include "vcppd/scope.h"
|
||||
#include "vcppd/vcd.h"
|
||||
|
||||
#endif // VCPPD_H
|
||||
34
src/builder.cpp
Normal file
34
src/builder.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "vcppd/builder.h"
|
||||
|
||||
#include "vcppd/scope.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace vcppd;
|
||||
|
||||
Builder::Builder(std::ostream& stream) :
|
||||
stream(stream)
|
||||
{
|
||||
auto t = std::time(nullptr);
|
||||
auto tm = *std::localtime(&t);
|
||||
|
||||
stream << "$version Generated by vcppd $end" << std::endl;
|
||||
stream << "$date " << std::put_time(&tm, "%A %B %e %T %Y") << " $end"
|
||||
<< std::endl;
|
||||
stream << "$timescale 1ns $end" << std::endl;
|
||||
}
|
||||
|
||||
Vcd Builder::build() const
|
||||
{
|
||||
stream << "$enddefinitions $end" << std::endl;
|
||||
return Vcd(*this);
|
||||
}
|
||||
|
||||
Scope<Builder> Builder::scope(const std::string& name)
|
||||
{
|
||||
stream << "$scope module " << name << " $end" << std::endl;
|
||||
return Scope<Builder>(name, *this);
|
||||
}
|
||||
|
||||
void Builder::unscope() { stream << "$upscope $end" << std::endl; }
|
||||
37
src/vcd.cpp
Normal file
37
src/vcd.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "vcppd/vcd.h"
|
||||
|
||||
#include "vcppd/builder.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <format>
|
||||
|
||||
using namespace vcppd;
|
||||
|
||||
Vcd::Vcd(const Builder& builder) :
|
||||
stream(builder.stream),
|
||||
variables(builder.variables),
|
||||
current_time(0)
|
||||
{
|
||||
}
|
||||
|
||||
Vcd::~Vcd() { stream << std::format("#{}", current_time) << std::endl; }
|
||||
|
||||
void Vcd::tick()
|
||||
{
|
||||
stream << std::format("#{}", current_time) << std::endl;
|
||||
|
||||
for (const auto& [name, entry] : variables)
|
||||
{
|
||||
stream << "b";
|
||||
for (int i = 0; i < entry.size; i++)
|
||||
{
|
||||
uint8_t byte;
|
||||
memcpy(&byte, static_cast<const uint8_t*>(entry.ref), 1);
|
||||
stream << std::format("{0:b}", byte);
|
||||
}
|
||||
stream << " " << name << std::endl;
|
||||
}
|
||||
|
||||
current_time += 1;
|
||||
}
|
||||
22
test/test.cpp
Normal file
22
test/test.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "vcppd/vcppd.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
uint8_t eae = 0;
|
||||
uint8_t eae2 = 0;
|
||||
|
||||
auto vcd = vcppd::Builder(std::cout)
|
||||
.scope("TOP")
|
||||
.trace("eae", eae)
|
||||
.trace("eae2", eae2)
|
||||
.unscope()
|
||||
.build();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
vcd.tick();
|
||||
eae += 1;
|
||||
eae2 += 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user