first commit of nboard
This commit is contained in:
parent
0803387052
commit
66d294ab85
25
README.md
25
README.md
|
@ -15,9 +15,21 @@
|
|||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
##### 使用Verilator
|
||||
|
||||
使用Veriloator,把Verilog转换成C++。
|
||||
Virtual FPGA需要使用Verilator生成的一些接口。
|
||||
|
||||
##### 编写两个辅助函数
|
||||
|
||||
接下来,你需要编写两个辅助函数`update_input()`和`update_output()`。
|
||||
当你在虚拟FPGA上改变输入(比如拨动一个开关)的时候,
|
||||
虚拟FPGA会自动调用`update_input()`,让你编写的模块能够收到这个改变。
|
||||
模块得到新的输出之后,虚拟FPGA会调用`update_output()`,把模块的输出同步到GUI上。
|
||||
|
||||
##### 体验虚拟FPGA
|
||||
|
||||
要改变某个按键或开关的状态,可以使用键盘快捷键,也可以点击鼠标。
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
|
@ -29,9 +41,4 @@
|
|||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
1. 可以用`include/configs.h`选择贴图,让自己的虚拟FPGA开发板更有特色,贴图放在`pic`目录下;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// DESCRIPTION: Generated by verilator_includer via makefile
|
||||
#define VL_INCLUDE_OPT include
|
||||
#include "emu/Vtop.cpp"
|
||||
#include "emu/Vtop__Slow.cpp"
|
||||
#include "emu/Vtop__Syms.cpp"
|
Binary file not shown.
|
@ -0,0 +1,116 @@
|
|||
// Verilated -*- C++ -*-
|
||||
// DESCRIPTION: Verilator output: Design implementation internals
|
||||
// See Vtop.h for the primary calling header
|
||||
|
||||
#include "Vtop.h"
|
||||
#include "Vtop__Syms.h"
|
||||
|
||||
//==========
|
||||
|
||||
VerilatedContext* Vtop::contextp() {
|
||||
return __VlSymsp->_vm_contextp__;
|
||||
}
|
||||
|
||||
void Vtop::eval_step() {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+++++TOP Evaluate Vtop::eval\n"); );
|
||||
Vtop__Syms* __restrict vlSymsp = this->__VlSymsp; // Setup global symbol table
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
#ifdef VL_DEBUG
|
||||
// Debug assertions
|
||||
_eval_debug_assertions();
|
||||
#endif // VL_DEBUG
|
||||
// Initialize
|
||||
if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);
|
||||
// Evaluate till stable
|
||||
int __VclockLoop = 0;
|
||||
QData __Vchange = 1;
|
||||
do {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Clock loop\n"););
|
||||
_eval(vlSymsp);
|
||||
if (VL_UNLIKELY(++__VclockLoop > 100)) {
|
||||
// About to fail, so enable debug to see what's not settling.
|
||||
// Note you must run make with OPT=-DVL_DEBUG for debug prints.
|
||||
int __Vsaved_debug = Verilated::debug();
|
||||
Verilated::debug(1);
|
||||
__Vchange = _change_request(vlSymsp);
|
||||
Verilated::debug(__Vsaved_debug);
|
||||
VL_FATAL_MT("top.v", 2, "",
|
||||
"Verilated model didn't converge\n"
|
||||
"- See https://verilator.org/warn/DIDNOTCONVERGE");
|
||||
} else {
|
||||
__Vchange = _change_request(vlSymsp);
|
||||
}
|
||||
} while (VL_UNLIKELY(__Vchange));
|
||||
}
|
||||
|
||||
void Vtop::_eval_initial_loop(Vtop__Syms* __restrict vlSymsp) {
|
||||
vlSymsp->__Vm_didInit = true;
|
||||
_eval_initial(vlSymsp);
|
||||
// Evaluate till stable
|
||||
int __VclockLoop = 0;
|
||||
QData __Vchange = 1;
|
||||
do {
|
||||
_eval_settle(vlSymsp);
|
||||
_eval(vlSymsp);
|
||||
if (VL_UNLIKELY(++__VclockLoop > 100)) {
|
||||
// About to fail, so enable debug to see what's not settling.
|
||||
// Note you must run make with OPT=-DVL_DEBUG for debug prints.
|
||||
int __Vsaved_debug = Verilated::debug();
|
||||
Verilated::debug(1);
|
||||
__Vchange = _change_request(vlSymsp);
|
||||
Verilated::debug(__Vsaved_debug);
|
||||
VL_FATAL_MT("top.v", 2, "",
|
||||
"Verilated model didn't DC converge\n"
|
||||
"- See https://verilator.org/warn/DIDNOTCONVERGE");
|
||||
} else {
|
||||
__Vchange = _change_request(vlSymsp);
|
||||
}
|
||||
} while (VL_UNLIKELY(__Vchange));
|
||||
}
|
||||
|
||||
VL_INLINE_OPT void Vtop::_sequent__TOP__1(Vtop__Syms* __restrict vlSymsp) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_sequent__TOP__1\n"); );
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
// Body
|
||||
vlTOPp->out = ((IData)(vlTOPp->reset) ? 0U : (0xfU
|
||||
& ((IData)(1U)
|
||||
+ (IData)(vlTOPp->out))));
|
||||
}
|
||||
|
||||
void Vtop::_eval(Vtop__Syms* __restrict vlSymsp) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_eval\n"); );
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
// Body
|
||||
if (((IData)(vlTOPp->clk) & (~ (IData)(vlTOPp->__Vclklast__TOP__clk)))) {
|
||||
vlTOPp->_sequent__TOP__1(vlSymsp);
|
||||
}
|
||||
// Final
|
||||
vlTOPp->__Vclklast__TOP__clk = vlTOPp->clk;
|
||||
}
|
||||
|
||||
VL_INLINE_OPT QData Vtop::_change_request(Vtop__Syms* __restrict vlSymsp) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_change_request\n"); );
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
// Body
|
||||
return (vlTOPp->_change_request_1(vlSymsp));
|
||||
}
|
||||
|
||||
VL_INLINE_OPT QData Vtop::_change_request_1(Vtop__Syms* __restrict vlSymsp) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_change_request_1\n"); );
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
// Body
|
||||
// Change detection
|
||||
QData __req = false; // Logically a bool
|
||||
return __req;
|
||||
}
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
void Vtop::_eval_debug_assertions() {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_eval_debug_assertions\n"); );
|
||||
// Body
|
||||
if (VL_UNLIKELY((clk & 0xfeU))) {
|
||||
Verilated::overWidthError("clk");}
|
||||
if (VL_UNLIKELY((reset & 0xfeU))) {
|
||||
Verilated::overWidthError("reset");}
|
||||
}
|
||||
#endif // VL_DEBUG
|
|
@ -0,0 +1,87 @@
|
|||
// Verilated -*- C++ -*-
|
||||
// DESCRIPTION: Verilator output: Primary design header
|
||||
//
|
||||
// This header should be included by all source files instantiating the design.
|
||||
// The class here is then constructed to instantiate the design.
|
||||
// See the Verilator manual for examples.
|
||||
|
||||
#ifndef VERILATED_VTOP_H_
|
||||
#define VERILATED_VTOP_H_ // guard
|
||||
|
||||
#include "verilated_heavy.h"
|
||||
|
||||
//==========
|
||||
|
||||
class Vtop__Syms;
|
||||
|
||||
//----------
|
||||
|
||||
VL_MODULE(Vtop) {
|
||||
public:
|
||||
|
||||
// PORTS
|
||||
// The application code writes and reads these signals to
|
||||
// propagate new values into/out from the Verilated model.
|
||||
VL_IN8(clk,0,0);
|
||||
VL_IN8(reset,0,0);
|
||||
VL_OUT8(out,3,0);
|
||||
|
||||
// LOCAL VARIABLES
|
||||
// Internals; generally not touched by application code
|
||||
CData/*0:0*/ __Vclklast__TOP__clk;
|
||||
|
||||
// INTERNAL VARIABLES
|
||||
// Internals; generally not touched by application code
|
||||
Vtop__Syms* __VlSymsp; // Symbol table
|
||||
|
||||
// CONSTRUCTORS
|
||||
private:
|
||||
VL_UNCOPYABLE(Vtop); ///< Copying not allowed
|
||||
public:
|
||||
/// Construct the model; called by application code
|
||||
/// If contextp is null, then the model will use the default global context
|
||||
/// If name is "", then makes a wrapper with a
|
||||
/// single model invisible with respect to DPI scope names.
|
||||
Vtop(VerilatedContext* contextp, const char* name = "TOP");
|
||||
Vtop(const char* name = "TOP")
|
||||
: Vtop(nullptr, name) {}
|
||||
/// Destroy the model; called (often implicitly) by application code
|
||||
~Vtop();
|
||||
|
||||
// API METHODS
|
||||
/// Return current simulation context for this model.
|
||||
/// Used to get to e.g. simulation time via contextp()->time()
|
||||
VerilatedContext* contextp();
|
||||
/// Evaluate the model. Application must call when inputs change.
|
||||
void eval() { eval_step(); }
|
||||
/// Evaluate when calling multiple units/models per time step.
|
||||
void eval_step();
|
||||
/// Evaluate at end of a timestep for tracing, when using eval_step().
|
||||
/// Application must call after all eval() and before time changes.
|
||||
void eval_end_step() {}
|
||||
/// Simulation complete, run final blocks. Application must call on completion.
|
||||
void final();
|
||||
|
||||
// INTERNAL METHODS
|
||||
static void _eval_initial_loop(Vtop__Syms* __restrict vlSymsp);
|
||||
void __Vconfigure(Vtop__Syms* symsp, bool first);
|
||||
private:
|
||||
static QData _change_request(Vtop__Syms* __restrict vlSymsp);
|
||||
static QData _change_request_1(Vtop__Syms* __restrict vlSymsp);
|
||||
static void _ctor_var_reset(Vtop* self) VL_ATTR_COLD;
|
||||
public:
|
||||
static void _eval(Vtop__Syms* __restrict vlSymsp);
|
||||
private:
|
||||
#ifdef VL_DEBUG
|
||||
void _eval_debug_assertions();
|
||||
#endif // VL_DEBUG
|
||||
public:
|
||||
static void _eval_initial(Vtop__Syms* __restrict vlSymsp) VL_ATTR_COLD;
|
||||
static void _eval_settle(Vtop__Syms* __restrict vlSymsp) VL_ATTR_COLD;
|
||||
static void _sequent__TOP__1(Vtop__Syms* __restrict vlSymsp);
|
||||
} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES);
|
||||
|
||||
//----------
|
||||
|
||||
|
||||
#endif // guard
|
|
@ -0,0 +1,62 @@
|
|||
# Verilated -*- Makefile -*-
|
||||
# DESCRIPTION: Verilator output: Makefile for building Verilated archive or executable
|
||||
#
|
||||
# Execute this makefile from the object directory:
|
||||
# make -f Vtop.mk
|
||||
|
||||
default: Vtop
|
||||
|
||||
### Constants...
|
||||
# Perl executable (from $PERL)
|
||||
PERL = perl
|
||||
# Path to Verilator kit (from $VERILATOR_ROOT)
|
||||
VERILATOR_ROOT = /usr/share/verilator
|
||||
# SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE)
|
||||
SYSTEMC_INCLUDE ?=
|
||||
# SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR)
|
||||
SYSTEMC_LIBDIR ?=
|
||||
|
||||
### Switches...
|
||||
# SystemC output mode? 0/1 (from --sc)
|
||||
VM_SC = 0
|
||||
# Legacy or SystemC output mode? 0/1 (from --sc)
|
||||
VM_SP_OR_SC = $(VM_SC)
|
||||
# Deprecated
|
||||
VM_PCLI = 1
|
||||
# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)
|
||||
VM_SC_TARGET_ARCH = linux
|
||||
|
||||
### Vars...
|
||||
# Design prefix (from --prefix)
|
||||
VM_PREFIX = Vtop
|
||||
# Module prefix (from --prefix)
|
||||
VM_MODPREFIX = Vtop
|
||||
# User CFLAGS (from -CFLAGS on Verilator command line)
|
||||
VM_USER_CFLAGS = \
|
||||
|
||||
# User LDLIBS (from -LDFLAGS on Verilator command line)
|
||||
VM_USER_LDLIBS = \
|
||||
|
||||
# User .cpp files (from .cpp's on Verilator command line)
|
||||
VM_USER_CLASSES = \
|
||||
|
||||
# User .cpp directories (from .cpp's on Verilator command line)
|
||||
VM_USER_DIR = \
|
||||
|
||||
|
||||
### Default rules...
|
||||
# Include list of all generated classes
|
||||
include Vtop_classes.mk
|
||||
# Include global rules
|
||||
include $(VERILATOR_ROOT)/include/verilated.mk
|
||||
|
||||
### Executable rules... (from --exe)
|
||||
VPATH += $(VM_USER_DIR)
|
||||
|
||||
|
||||
### Link rules... (from --exe)
|
||||
Vtop: $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a $(VM_HIER_LIBS)
|
||||
$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@
|
||||
|
||||
|
||||
# Verilated -*- Makefile -*-
|
|
@ -0,0 +1,59 @@
|
|||
// Verilated -*- C++ -*-
|
||||
// DESCRIPTION: Verilator output: Design implementation internals
|
||||
// See Vtop.h for the primary calling header
|
||||
|
||||
#include "Vtop.h"
|
||||
#include "Vtop__Syms.h"
|
||||
|
||||
//==========
|
||||
|
||||
Vtop::Vtop(VerilatedContext* _vcontextp__, const char* _vcname__)
|
||||
: VerilatedModule{_vcname__}
|
||||
{
|
||||
Vtop__Syms* __restrict vlSymsp = __VlSymsp = new Vtop__Syms(_vcontextp__, this, name());
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
// Reset internal values
|
||||
|
||||
// Reset structure values
|
||||
_ctor_var_reset(this);
|
||||
}
|
||||
|
||||
void Vtop::__Vconfigure(Vtop__Syms* vlSymsp, bool first) {
|
||||
if (false && first) {} // Prevent unused
|
||||
this->__VlSymsp = vlSymsp;
|
||||
if (false && this->__VlSymsp) {} // Prevent unused
|
||||
vlSymsp->_vm_contextp__->timeunit(-12);
|
||||
vlSymsp->_vm_contextp__->timeprecision(-12);
|
||||
}
|
||||
|
||||
Vtop::~Vtop() {
|
||||
VL_DO_CLEAR(delete __VlSymsp, __VlSymsp = nullptr);
|
||||
}
|
||||
|
||||
void Vtop::_eval_initial(Vtop__Syms* __restrict vlSymsp) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_eval_initial\n"); );
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
// Body
|
||||
vlTOPp->__Vclklast__TOP__clk = vlTOPp->clk;
|
||||
}
|
||||
|
||||
void Vtop::final() {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::final\n"); );
|
||||
// Variables
|
||||
Vtop__Syms* __restrict vlSymsp = this->__VlSymsp;
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
}
|
||||
|
||||
void Vtop::_eval_settle(Vtop__Syms* __restrict vlSymsp) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_eval_settle\n"); );
|
||||
Vtop* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
|
||||
}
|
||||
|
||||
void Vtop::_ctor_var_reset(Vtop* self) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ Vtop::_ctor_var_reset\n"); );
|
||||
// Body
|
||||
if (false && self) {} // Prevent unused
|
||||
self->clk = VL_RAND_RESET_I(1);
|
||||
self->reset = VL_RAND_RESET_I(1);
|
||||
self->out = VL_RAND_RESET_I(4);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Verilated -*- C++ -*-
|
||||
// DESCRIPTION: Verilator output: Symbol table implementation internals
|
||||
|
||||
#include "Vtop__Syms.h"
|
||||
#include "Vtop.h"
|
||||
|
||||
|
||||
|
||||
// FUNCTIONS
|
||||
Vtop__Syms::~Vtop__Syms()
|
||||
{
|
||||
}
|
||||
|
||||
Vtop__Syms::Vtop__Syms(VerilatedContext* contextp, Vtop* topp, const char* namep)
|
||||
// Setup locals
|
||||
: VerilatedSyms{contextp}
|
||||
, __Vm_namep(namep)
|
||||
, __Vm_didInit(false)
|
||||
// Setup submodule names
|
||||
{
|
||||
// Pointer to top level
|
||||
TOPp = topp;
|
||||
// Setup each module's pointers to their submodules
|
||||
// Setup each module's pointer back to symbol table (for public functions)
|
||||
TOPp->__Vconfigure(this, true);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Verilated -*- C++ -*-
|
||||
// DESCRIPTION: Verilator output: Symbol table internal header
|
||||
//
|
||||
// Internal details; most calling programs do not need this header,
|
||||
// unless using verilator public meta comments.
|
||||
|
||||
#ifndef VERILATED_VTOP__SYMS_H_
|
||||
#define VERILATED_VTOP__SYMS_H_ // guard
|
||||
|
||||
#include "verilated_heavy.h"
|
||||
|
||||
// INCLUDE MODULE CLASSES
|
||||
#include "Vtop.h"
|
||||
|
||||
// SYMS CLASS
|
||||
class Vtop__Syms : public VerilatedSyms {
|
||||
public:
|
||||
|
||||
// LOCAL STATE
|
||||
const char* __Vm_namep;
|
||||
bool __Vm_didInit;
|
||||
|
||||
// SUBCELL STATE
|
||||
Vtop* TOPp;
|
||||
|
||||
// CREATORS
|
||||
Vtop__Syms(VerilatedContext* contextp, Vtop* topp, const char* namep);
|
||||
~Vtop__Syms();
|
||||
|
||||
// METHODS
|
||||
inline const char* name() { return __Vm_namep; }
|
||||
|
||||
} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES);
|
||||
|
||||
#endif // guard
|
|
@ -0,0 +1,13 @@
|
|||
# DESCRIPTION: Verilator output: Timestamp data for --skip-identical. Delete at will.
|
||||
C "-Wall --cc --exe top.v"
|
||||
S 9831216 3933823 1638793920 151505168 1638793920 151505168 "/usr/bin/verilator_bin"
|
||||
T 4156 2492193 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop.cpp"
|
||||
T 2906 2492191 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop.h"
|
||||
T 1653 2492195 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop.mk"
|
||||
T 1835 2492192 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop__Slow.cpp"
|
||||
T 618 2491962 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop__Syms.cpp"
|
||||
T 797 2492190 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop__Syms.h"
|
||||
T 215 2492196 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop__ver.d"
|
||||
T 0 0 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop__verFiles.dat"
|
||||
T 1580 2492194 1642246870 385360696 1642246870 385360696 "obj_dir/Vtop_classes.mk"
|
||||
S 176 2491397 1638621730 599207083 1638621730 599207083 "top.v"
|
|
@ -0,0 +1,49 @@
|
|||
# Verilated -*- Makefile -*-
|
||||
# DESCRIPTION: Verilator output: Make include file with class lists
|
||||
#
|
||||
# This file lists generated Verilated files, for including in higher level makefiles.
|
||||
# See Vtop.mk for the caller.
|
||||
|
||||
### Switches...
|
||||
# C11 constructs required? 0/1 (always on now)
|
||||
VM_C11 = 1
|
||||
# Coverage output mode? 0/1 (from --coverage)
|
||||
VM_COVERAGE = 0
|
||||
# Parallel builds? 0/1 (from --output-split)
|
||||
VM_PARALLEL_BUILDS = 0
|
||||
# Threaded output mode? 0/1/N threads (from --threads)
|
||||
VM_THREADS = 0
|
||||
# Tracing output mode? 0/1 (from --trace/--trace-fst)
|
||||
VM_TRACE = 0
|
||||
# Tracing output mode in FST format? 0/1 (from --trace-fst)
|
||||
VM_TRACE_FST = 0
|
||||
# Tracing threaded output mode? 0/1/N threads (from --trace-thread)
|
||||
VM_TRACE_THREADS = 0
|
||||
# Separate FST writer thread? 0/1 (from --trace-fst with --trace-thread > 0)
|
||||
VM_TRACE_FST_WRITER_THREAD = 0
|
||||
|
||||
### Object file lists...
|
||||
# Generated module classes, fast-path, compile with highest optimization
|
||||
VM_CLASSES_FAST += \
|
||||
Vtop \
|
||||
|
||||
# Generated module classes, non-fast-path, compile with low/medium optimization
|
||||
VM_CLASSES_SLOW += \
|
||||
Vtop__Slow \
|
||||
|
||||
# Generated support classes, fast-path, compile with highest optimization
|
||||
VM_SUPPORT_FAST += \
|
||||
|
||||
# Generated support classes, non-fast-path, compile with low/medium optimization
|
||||
VM_SUPPORT_SLOW += \
|
||||
Vtop__Syms \
|
||||
|
||||
# Global classes, need linked once per executable, fast-path, compile with highest optimization
|
||||
VM_GLOBAL_FAST += \
|
||||
verilated \
|
||||
|
||||
# Global classes, need linked once per executable, non-fast-path, compile with low/medium optimization
|
||||
VM_GLOBAL_SLOW += \
|
||||
|
||||
|
||||
# Verilated -*- Makefile -*-
|
|
@ -0,0 +1,3 @@
|
|||
#include "Vtop.h"
|
||||
|
||||
#define TOP_NAME Vtop
|
|
@ -0,0 +1,18 @@
|
|||
#include <nboard.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <topname.h>
|
||||
|
||||
extern std::map<std::string, bool> input_map, output_map;
|
||||
|
||||
void update_input(TOP_NAME *dut_ptr) {
|
||||
dut_ptr->clk = input_map["btnc"];
|
||||
dut_ptr->reset = input_map["rst"];
|
||||
}
|
||||
|
||||
void update_output(TOP_NAME *dut_ptr) {
|
||||
output_map["ld0"] = (dut_ptr->out >> 0) & 1;
|
||||
output_map["ld1"] = (dut_ptr->out >> 1) & 1;
|
||||
output_map["ld2"] = (dut_ptr->out >> 2) & 1;
|
||||
output_map["ld3"] = (dut_ptr->out >> 3) & 1;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef VFPGA_CLOCK_H
|
||||
#define VPFGA_CLOCK_H
|
||||
|
||||
bool read_clock();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef _VFPGA_CONFIGS_H
|
||||
#define _VFPGA_CONFIGS_H
|
||||
|
||||
|
||||
// You can replace pictures used in GUI
|
||||
|
||||
// 640*480 png
|
||||
#define BG_PATH "vbg_1.png"
|
||||
|
||||
// png
|
||||
#define VBTN_ON_PATH "vbtn_on.png"
|
||||
#define VBTN_OFF_PATH "vbtn_off.png"
|
||||
|
||||
// png
|
||||
#define VSW_ON_PATH "vsw_on.png"
|
||||
#define VSW_OFF_PATH "vsw_off.png"
|
||||
|
||||
// png
|
||||
#define SEG_BKGND_ENA
|
||||
//#define SEG_BKGND_CUSTOM
|
||||
#define VSEGLED_BG_PATH "vsegled_bg.png"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include <topname.h>
|
||||
|
||||
#ifndef _VFPGA_CONSTRS_H
|
||||
#define _VFPGA_CONSTRS_H
|
||||
|
||||
void update_input(TOP_NAME *dut_ptr);
|
||||
void update_output(TOP_NAME *dut_ptr);
|
||||
|
||||
void init_input();
|
||||
void init_output();
|
||||
|
||||
#define CLK_INPUT "clk"
|
||||
|
||||
#define RST_INPUT "rst"
|
||||
|
||||
#define BTN_INPUT "btnc", "btnu", "btnd", "btnl", "btnr"
|
||||
|
||||
#define SWITCH_INPUT "sw0", "sw1", "sw2", "sw3", \
|
||||
"sw4", "sw5", "sw6", "sw7", \
|
||||
"sw8", "sw9", "sw10", "sw11", \
|
||||
"sw12", "sw13", "sw14", "sw15"
|
||||
|
||||
#define NAIVE_LEDS "ld0", "ld1", "ld2", "ld3", \
|
||||
"ld4", "ld5", "ld6", "ld7", \
|
||||
"ld8", "ld9", "ld10", "ld11", \
|
||||
"ld12", "ld13", "ld14", "ld15"
|
||||
|
||||
#define RGB_LEDS "r16", "g16", "b16", "r17", "g17", "b17"
|
||||
|
||||
#define SEG7_LEDS "an0", "an1", "an2", "an3", \
|
||||
"an4", "an5", "an6", "an7", \
|
||||
"sega", "segb", "segc", "segd", \
|
||||
"sege", "segf", "segg", "decp"
|
||||
|
||||
//#define UART_OUTPUT
|
||||
|
||||
//#define VGA_OUTPUT
|
||||
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef VFPGA_EVENT_H
|
||||
#define VPFGA_EVENT_H
|
||||
|
||||
int read_event();
|
||||
|
||||
void dbg_wait_esc();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,5 @@
|
|||
#include "configs.h"
|
||||
#include "constrs.h"
|
||||
#include "render.h"
|
||||
#include "clock.h"
|
||||
#include "event.h"
|
|
@ -0,0 +1,53 @@
|
|||
#include <SDL2/SDL.h>
|
||||
|
||||
#ifndef VFPGA_RENDER_H
|
||||
#define VFPGA_RENDER_H
|
||||
|
||||
#define WINDOW_WIDTH 640
|
||||
#define WINDOW_HEIGHT 480
|
||||
|
||||
#define SWITCH_X 80
|
||||
#define SWITCH_Y 400
|
||||
#define SWITCH_SEP 10
|
||||
#define SWITCH_WIDTH 20
|
||||
#define SWITCH_HEIGHT 40
|
||||
|
||||
#define BTNC_X 500
|
||||
#define BTNC_Y 200
|
||||
#define BTNC_SEP 20
|
||||
#define BTNC_WIDTH 20
|
||||
#define BTNC_HEIGHT 20
|
||||
|
||||
#define LED_X 85
|
||||
#define LED_Y 360
|
||||
#define LED_SEP 20
|
||||
#define LED_WIDTH 10
|
||||
#define LED_HEIGHT 4
|
||||
|
||||
#define SEG_X 40
|
||||
#define SEG_Y 240
|
||||
|
||||
#define SEG_VER_WIDTH 2
|
||||
#define SEG_VER_HEIGHT 40
|
||||
#define SEG_HOR_WIDTH 40
|
||||
#define SEG_HOR_HEIGHT 2
|
||||
#define SEG_DOT_WIDTH 2
|
||||
#define SEG_DOT_HEIGHT 2
|
||||
|
||||
#define SEG_WIDTH_MARGIN 2
|
||||
#define SEG_HEIGHT_MARGIN 2
|
||||
|
||||
#define SEG_TOT_WIDTH (SEG_WIDTH_MARGIN * 17 + SEG_VER_WIDTH * 24 + SEG_HOR_WIDTH * 8)
|
||||
#define SEG_TOT_HEIGHT (SEG_HEIGHT_MARGIN * 2 + SEG_VER_HEIGHT * 2 + SEG_HOR_HEIGHT)
|
||||
|
||||
void load_background(SDL_Renderer *renderer);
|
||||
|
||||
void load_texture(SDL_Renderer *renderer);
|
||||
|
||||
void init_gui(SDL_Renderer *renderer);
|
||||
|
||||
void update_gui_input(SDL_Renderer *renderer);
|
||||
|
||||
void update_gui_output(SDL_Renderer *renderer);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,91 @@
|
|||
ifndef TOPNAME
|
||||
$(error TOPNAME should be given)
|
||||
endif
|
||||
|
||||
### Constants...
|
||||
# Perl executable (from $PERL)
|
||||
PERL = perl
|
||||
# Path to Verilator kit (from $VERILATOR_ROOT)
|
||||
VERILATOR_ROOT = /usr/share/verilator
|
||||
# SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE)
|
||||
SYSTEMC_INCLUDE ?=
|
||||
# SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR)
|
||||
SYSTEMC_LIBDIR ?=
|
||||
|
||||
### Switches...
|
||||
# SystemC output mode? 0/1 (from --sc)
|
||||
VM_SC = 0
|
||||
# Legacy or SystemC output mode? 0/1 (from --sc)
|
||||
VM_SP_OR_SC = $(VM_SC)
|
||||
# Deprecated
|
||||
VM_PCLI = 1
|
||||
# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)
|
||||
VM_SC_TARGET_ARCH = linux
|
||||
|
||||
### Vars...
|
||||
# Design prefix (from --prefix)
|
||||
VM_PREFIX = V$(TOPNAME)
|
||||
# Module prefix (from --prefix)
|
||||
VM_MODPREFIX = V$(TOPNAME)
|
||||
# User CFLAGS (from -CFLAGS on Verilator command line)
|
||||
VM_USER_CFLAGS =
|
||||
|
||||
# User LDLIBS (from -LDFLAGS on Verilator command line)
|
||||
VM_USER_LDLIBS =
|
||||
|
||||
# User .cpp files (from .cpp's on Verilator command line)
|
||||
VM_USER_CLASSES =
|
||||
|
||||
# User .cpp directories (from .cpp's on Verilator command line)
|
||||
VM_USER_DIR = .
|
||||
|
||||
# generated executable file
|
||||
DST_DIR = build
|
||||
DST_BIN = $(DST_DIR)/emu_board
|
||||
|
||||
# files of nboard
|
||||
NBD_SRC = src
|
||||
NBD_LIB = include
|
||||
NBD_SRCS := $(shell find $(NBD_SRC) -name "*.cpp")
|
||||
# update.cpp should be implemented by users.
|
||||
NBD_OBJS := $(addprefix $(DST_DIR)/, $(addsuffix .o, $(basename $(notdir $(NBD_SRCS))))) \
|
||||
$(DST_DIR)/update.o
|
||||
|
||||
# files of emu
|
||||
EMU_DIR = emu
|
||||
EMU_SRCS := $(shell find $(EMU_DIR) -name "*.cpp")
|
||||
EMU_OBJS := $(addprefix $(DST_DIR)/, $(addsuffix .o, $(basename $(notdir $(EMU_SRCS)))))
|
||||
|
||||
SDL_FLAGS = -lSDL2 -lSDL2_image
|
||||
|
||||
vpath %.cpp $(EMU_DIR)
|
||||
|
||||
### Default rules...
|
||||
# Include list of all generated classes
|
||||
include $(EMU_DIR)/V$(TOPNAME)_classes.mk
|
||||
# Include global rules
|
||||
include $(VERILATOR_ROOT)/include/verilated.mk
|
||||
|
||||
$(DST_BIN): $(NBD_OBJS) $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a $(VM_HIER_LIBS)
|
||||
@$(LINK) $(LD_FLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@ $(SDL_FLAGS)
|
||||
|
||||
$(DST_DIR)/%.o: $(NBD_SRC)/%.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) \
|
||||
-I $(NBD_LIB) -I $(EMU_DIR) -c -o $@ $^
|
||||
|
||||
$(DST_DIR)/%.o: $(EMU_DIR)/%.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) \
|
||||
-I $(NBD_LIB) -I $(EMU_DIR) -c -o $@ $^
|
||||
|
||||
src/update.cpp: emu/update.cpp
|
||||
@ln -sf $(realpath ./$(EMU_DIR)/update.cpp) $(NBD_SRC)/update.cpp
|
||||
|
||||
run: $(DST_BIN)
|
||||
@$(DST_BIN)
|
||||
|
||||
clean:
|
||||
@rm -rf $(DST_DIR)
|
||||
|
||||
.PHONY: clean run
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 622 B |
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,5 @@
|
|||
#include <nboard.h>
|
||||
|
||||
bool read_clock() {
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <nboard.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
std::map<std::string, bool> input_map, output_map;
|
||||
std::map<std::string, bool> prev_output_map, prev_input_map;
|
||||
|
||||
std::string input_pins[] = {
|
||||
CLK_INPUT, RST_INPUT, BTN_INPUT, SWITCH_INPUT
|
||||
};
|
||||
|
||||
const int input_size = sizeof(input_pins) / sizeof(std::string);
|
||||
|
||||
std::string output_pins[] = {
|
||||
NAIVE_LEDS, RGB_LEDS, SEG7_LEDS
|
||||
};
|
||||
|
||||
const int output_size = sizeof(output_pins) / sizeof(std::string);
|
||||
|
||||
void init_input() {
|
||||
for (auto str : input_pins) {
|
||||
input_map[str] = false;
|
||||
prev_input_map[str] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void init_output() {
|
||||
for (auto str : output_pins) {
|
||||
output_map[str] = false;
|
||||
prev_output_map[str] = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
#include <nboard.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
extern std::map<std::string, bool> input_map, output_map;
|
||||
|
||||
static int keydown_handler(const SDL_Event &ev) {
|
||||
if (ev.key.keysym.sym == SDLK_ESCAPE) {
|
||||
return -1;
|
||||
} else {
|
||||
switch (ev.key.keysym.sym) {
|
||||
case SDLK_k:
|
||||
input_map["sw0"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_j:
|
||||
input_map["sw1"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_h:
|
||||
input_map["sw2"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_g:
|
||||
input_map["sw3"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_f:
|
||||
input_map["sw4"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_d:
|
||||
input_map["sw5"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_s:
|
||||
input_map["sw6"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_a:
|
||||
input_map["sw7"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_COMMA:
|
||||
input_map["sw8"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_m:
|
||||
input_map["sw9"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_n:
|
||||
input_map["sw10"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_b:
|
||||
input_map["sw11"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_v:
|
||||
input_map["sw12"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_c:
|
||||
input_map["sw13"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_x:
|
||||
input_map["sw14"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_z:
|
||||
input_map["sw15"] ^= 1;
|
||||
return 1;
|
||||
case SDLK_l:
|
||||
input_map["btnl"] = 1;
|
||||
return 1;
|
||||
case SDLK_SEMICOLON:
|
||||
input_map["btnc"] = 1;
|
||||
return 1;
|
||||
case SDLK_QUOTE:
|
||||
input_map["btnr"] = 1;
|
||||
return 1;
|
||||
case SDLK_p:
|
||||
input_map["btnu"] = 1;
|
||||
return 1;
|
||||
case SDLK_PERIOD:
|
||||
input_map["btnd"] = 1;
|
||||
return 1;
|
||||
case SDLK_0:
|
||||
input_map["rst"] = 1;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keyup_handler(const SDL_Event &ev) {
|
||||
switch (ev.key.keysym.sym) {
|
||||
case SDLK_l:
|
||||
input_map["btnl"] = 0;
|
||||
return 1;
|
||||
case SDLK_SEMICOLON:
|
||||
input_map["btnc"] = 0;
|
||||
return 1;
|
||||
case SDLK_QUOTE:
|
||||
input_map["btnr"] = 0;
|
||||
return 1;
|
||||
case SDLK_p:
|
||||
input_map["btnu"] = 0;
|
||||
return 1;
|
||||
case SDLK_PERIOD:
|
||||
input_map["btnd"] = 0;
|
||||
return 1;
|
||||
case SDLK_0:
|
||||
input_map["rst"] = 0;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mousedown_handler(const SDL_Event &ev) {
|
||||
// TODO: finish this function
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mouseup_handler(const SDL_Event &ev) {
|
||||
// TODO: finish this function
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return -1 when esc is pressed.
|
||||
// Else return whether buttons / switches are pressed.
|
||||
int read_event() {
|
||||
SDL_Event ev;
|
||||
SDL_PollEvent(&ev);
|
||||
switch (ev.type) {
|
||||
case SDL_QUIT:
|
||||
return -1;
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
return keydown_handler(ev);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
return keyup_handler(ev);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
return mousedown_handler(ev);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
return mouseup_handler(ev);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dbg_wait_esc() {
|
||||
while (1) {
|
||||
if (read_event() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
#include <cstdio>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <string>
|
||||
|
||||
#include <verilated.h>
|
||||
#include <nboard.h>
|
||||
#include <topname.h>
|
||||
|
||||
TOP_NAME *dut_ptr;
|
||||
std::string nboard_home;
|
||||
|
||||
int main() {
|
||||
// init verilog module
|
||||
dut_ptr = new TOP_NAME;
|
||||
|
||||
// init SDL and SDL_image
|
||||
SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
IMG_Init(IMG_INIT_PNG);
|
||||
SDL_Window *window = nullptr;
|
||||
SDL_Renderer *render = nullptr;
|
||||
window = SDL_CreateWindow("nboard", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
|
||||
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
nboard_home = getenv("NBOARD_HOME");
|
||||
load_background(render);
|
||||
load_texture(render);
|
||||
//dbg_wait_esc();
|
||||
init_input();
|
||||
init_output();
|
||||
//dbg_wait_esc();
|
||||
update_input(dut_ptr);
|
||||
dut_ptr->eval();
|
||||
//dbg_wait_esc();
|
||||
init_gui(render);
|
||||
|
||||
// the main cycle
|
||||
while (1) {
|
||||
int ev = read_event();
|
||||
if (ev == -1) {
|
||||
break;
|
||||
} else if (ev) {
|
||||
update_input(dut_ptr);
|
||||
update_gui_input(render);
|
||||
dut_ptr->eval();
|
||||
printf("out : %d %d %d %d\n", (dut_ptr->out >> 3) & 1, (dut_ptr->out >> 2) & 1, (dut_ptr->out >> 1) & 1, (dut_ptr->out >> 0) & 1);
|
||||
update_output(dut_ptr);
|
||||
update_gui_output(render);
|
||||
}
|
||||
|
||||
if (read_clock()) {
|
||||
update_input(dut_ptr);
|
||||
dut_ptr->eval();
|
||||
update_output(dut_ptr);
|
||||
update_gui_output(render);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_DestroyRenderer(render);
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
delete dut_ptr;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
#include <nboard.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
static SDL_Surface *sbutton_on, *sbutton_off;
|
||||
static SDL_Surface *sswitch_on, *sswitch_off;
|
||||
static SDL_Surface *ssegled_ver_off, *ssegled_ver_on,
|
||||
*ssegled_hor_off, *ssegled_hor_on,
|
||||
*ssegled_dot_off, *ssegled_dot_on;
|
||||
static SDL_Surface *sled_off, *sled_r, *sled_g, *sled_b,
|
||||
*sled_rg, *sled_rb, *sled_gb, *sled_rgb;
|
||||
static SDL_Surface *sfpga_background;
|
||||
static SDL_Surface *sseg7_background;
|
||||
|
||||
static SDL_Texture *tbutton_on, *tbutton_off;
|
||||
static SDL_Texture *tswitch_on, *tswitch_off;
|
||||
static SDL_Texture *tsegled_ver_off, *tsegled_ver_on,
|
||||
*tsegled_hor_off, *tsegled_hor_on,
|
||||
*tsegled_dot_off, *tsegled_dot_on;
|
||||
static SDL_Texture *tled_off, *tled_r, *tled_g, *tled_b,
|
||||
*tled_rg, *tled_rb, *tled_gb, *tled_rgb;
|
||||
static SDL_Texture *tfpga_background;
|
||||
static SDL_Texture *tseg7_background;
|
||||
|
||||
extern std::string nboard_home;
|
||||
|
||||
void load_background(SDL_Renderer *renderer) {
|
||||
sfpga_background = IMG_Load((nboard_home + "/pic/" + BG_PATH).c_str());
|
||||
tfpga_background = SDL_CreateTextureFromSurface(renderer, sfpga_background);
|
||||
SDL_RenderCopy(renderer, tfpga_background, NULL, NULL);
|
||||
|
||||
#ifdef SEG_BKGND_ENA
|
||||
#ifdef SEG_BKGND_CUSTOM
|
||||
sseg7_background = IMG_Load((nboard_home + "/pic/" + VSEGLED_BG_PATH).c_str());
|
||||
#else
|
||||
sseg7_background = SDL_CreateRGBSurface(0, SEG_TOT_WIDTH, SEG_TOT_HEIGHT, 32, 0, 0, 0, 0);
|
||||
SDL_FillRect(sseg7_background, NULL, SDL_MapRGB(sseg7_background->format, 0x00, 0x00, 0x00));
|
||||
#endif
|
||||
|
||||
tseg7_background = SDL_CreateTextureFromSurface(renderer, sseg7_background);
|
||||
SDL_Rect rect = {SEG_X, SEG_Y, SEG_TOT_WIDTH, SEG_TOT_HEIGHT};
|
||||
SDL_RenderCopy(renderer, tseg7_background, NULL, &rect);
|
||||
#endif
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
void fill_rect_texture(SDL_Renderer *renderer, SDL_Surface **surface, SDL_Texture **texture, int r, int g, int b) {
|
||||
SDL_FillRect(*surface, NULL, SDL_MapRGB((*surface)->format, r, g, b));
|
||||
*texture = SDL_CreateTextureFromSurface(renderer, *surface);
|
||||
}
|
||||
|
||||
void load_texture(SDL_Renderer *renderer) {
|
||||
// buttons
|
||||
sbutton_on = IMG_Load((nboard_home + "/pic/" + VBTN_ON_PATH).c_str());
|
||||
assert(sbutton_on != nullptr);
|
||||
tbutton_on = SDL_CreateTextureFromSurface(renderer, sbutton_on);
|
||||
sbutton_off = IMG_Load((nboard_home + "/pic/" + VBTN_OFF_PATH).c_str());
|
||||
assert(sbutton_off != nullptr);
|
||||
tbutton_off = SDL_CreateTextureFromSurface(renderer, sbutton_off);
|
||||
|
||||
// switches
|
||||
sswitch_on = IMG_Load((nboard_home + "/pic/" + VSW_ON_PATH).c_str());
|
||||
tswitch_on = SDL_CreateTextureFromSurface(renderer, sswitch_on);
|
||||
sswitch_off = IMG_Load((nboard_home + "/pic/" + VSW_OFF_PATH).c_str());
|
||||
tswitch_off = SDL_CreateTextureFromSurface(renderer, sswitch_off);
|
||||
|
||||
// 7 segs
|
||||
// vertical
|
||||
ssegled_ver_on = SDL_CreateRGBSurface(0, SEG_VER_WIDTH, SEG_VER_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &ssegled_ver_on, &tsegled_ver_on, 0xff, 0x00, 0x00);
|
||||
ssegled_ver_off = SDL_CreateRGBSurface(0, SEG_VER_WIDTH, SEG_VER_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &ssegled_ver_off, &tsegled_ver_off, 0x7f, 0x7f, 0x7f);
|
||||
|
||||
// horizontal
|
||||
ssegled_hor_on = SDL_CreateRGBSurface(0, SEG_HOR_WIDTH, SEG_HOR_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &ssegled_hor_on, &tsegled_hor_on, 0xff, 0x00, 0x00);
|
||||
ssegled_hor_off = SDL_CreateRGBSurface(0, SEG_HOR_WIDTH, SEG_HOR_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &ssegled_hor_off, &tsegled_hor_off, 0x7f, 0x7f, 0x7f);
|
||||
|
||||
// dot
|
||||
ssegled_dot_on = SDL_CreateRGBSurface(0, SEG_DOT_WIDTH, SEG_DOT_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &ssegled_dot_on, &tsegled_dot_on, 0xff, 0x00, 0x00);
|
||||
ssegled_dot_off = SDL_CreateRGBSurface(0, SEG_DOT_WIDTH, SEG_DOT_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &ssegled_dot_off, &tsegled_dot_off, 0x7f, 0x7f, 0x7f);
|
||||
|
||||
// LEDs
|
||||
sled_off = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_off, &tled_off, 0x7f, 0x7f, 0x7f);
|
||||
|
||||
sled_r = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_r, &tled_r, 0xff, 0x00, 0x00);
|
||||
|
||||
sled_g = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_g, &tled_g, 0x00, 0xff, 0x00);
|
||||
|
||||
sled_b = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_b, &tled_b, 0x00, 0x00, 0xff);
|
||||
|
||||
sled_rg = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_rg, &tled_rg, 0xff, 0xff, 0x00);
|
||||
|
||||
sled_rb = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_rb, &tled_rb, 0xff, 0x00, 0xff);
|
||||
|
||||
sled_gb = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_gb, &tled_gb, 0x00, 0xff, 0xff);
|
||||
|
||||
sled_rgb = SDL_CreateRGBSurface(0, LED_WIDTH, LED_HEIGHT, 32, 0, 0, 0, 0);
|
||||
fill_rect_texture(renderer, &sled_rgb, &tled_rgb, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
extern std::map<std::string, bool> input_map, output_map;
|
||||
extern std::map<std::string, bool> prev_input_map, prev_output_map;
|
||||
|
||||
extern std::string input_pins[], output_pins[];
|
||||
extern const int input_size, output_size;
|
||||
|
||||
std::string input_btns[] = {
|
||||
BTN_INPUT, RST_INPUT
|
||||
};
|
||||
static const int btns_cnt = sizeof(input_btns) / sizeof(std::string);
|
||||
|
||||
std::string input_switches[] = {
|
||||
SWITCH_INPUT
|
||||
};
|
||||
static const int switches_cnt = sizeof(input_switches) / sizeof(std::string);
|
||||
|
||||
static void update_gui_switch(SDL_Renderer *renderer, int index, bool val) {
|
||||
index = 15 - index;
|
||||
SDL_Rect rect = {SWITCH_X + (SWITCH_WIDTH + SWITCH_SEP) * index, SWITCH_Y, SWITCH_WIDTH, SWITCH_HEIGHT};
|
||||
SDL_RenderCopy(renderer, val ? tswitch_on : tswitch_off, NULL, &rect);
|
||||
}
|
||||
|
||||
static void update_gui_button(SDL_Renderer *renderer, int index, bool val) {
|
||||
SDL_Rect rect;
|
||||
switch (index)
|
||||
{
|
||||
case 0: // BTNC
|
||||
rect = {BTNC_X, BTNC_Y, BTNC_WIDTH, BTNC_HEIGHT};
|
||||
break;
|
||||
case 1: // BTNU
|
||||
rect = {BTNC_X, BTNC_Y - BTNC_HEIGHT - BTNC_SEP, BTNC_WIDTH, BTNC_HEIGHT};
|
||||
break;
|
||||
case 2: // BTND
|
||||
rect = {BTNC_X, BTNC_Y + BTNC_HEIGHT + BTNC_SEP, BTNC_WIDTH, BTNC_HEIGHT};
|
||||
break;
|
||||
case 3: // BTNL
|
||||
rect = {BTNC_X - BTNC_WIDTH - BTNC_SEP, BTNC_Y, BTNC_WIDTH, BTNC_HEIGHT};
|
||||
break;
|
||||
case 4: // BTNR
|
||||
rect = {BTNC_X + BTNC_WIDTH + BTNC_SEP, BTNC_Y, BTNC_WIDTH, BTNC_HEIGHT};
|
||||
break;
|
||||
case 5: // RST
|
||||
rect = {BTNC_X, BTNC_Y - 2 * (BTNC_HEIGHT + BTNC_SEP), BTNC_WIDTH, BTNC_HEIGHT};
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
SDL_RenderCopy(renderer, val ? tbutton_on : tbutton_off, NULL, &rect);
|
||||
}
|
||||
|
||||
void update_gui_input(SDL_Renderer *renderer) {
|
||||
for (int i = 0; i < switches_cnt; ++i) {
|
||||
std::string &str = input_switches[i];
|
||||
if (input_map.count(str) && prev_input_map[str] != input_map[str]) {
|
||||
prev_input_map[str] = input_map[str];
|
||||
update_gui_switch(renderer, i, input_map[str]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < btns_cnt; ++i) {
|
||||
std::string &str = input_btns[i];
|
||||
if (input_map.count(str) && prev_input_map[str] != input_map[str]) {
|
||||
prev_input_map[str] = input_map[str];
|
||||
update_gui_button(renderer, i, input_map[str]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string output_naive_leds[] = {
|
||||
NAIVE_LEDS
|
||||
};
|
||||
const int naive_leds_cnt = sizeof(output_naive_leds) / sizeof(std::string);
|
||||
|
||||
std::string output_rgb_leds[] = {
|
||||
RGB_LEDS
|
||||
};
|
||||
|
||||
std::string output_seg7_leds[] = {
|
||||
SEG7_LEDS
|
||||
};
|
||||
|
||||
static void update_gui_naive_led(SDL_Renderer *renderer, int index, bool val) {
|
||||
//std::cout << "update " << index << std::endl;
|
||||
index = 15 - index;
|
||||
SDL_Rect rect = {LED_X + (LED_WIDTH + LED_SEP) * index, LED_Y, LED_WIDTH, LED_HEIGHT};
|
||||
SDL_RenderCopy(renderer, val ? tled_g : tled_off, NULL, &rect);
|
||||
}
|
||||
|
||||
static void update_gui_rgb_led(SDL_Renderer *renderer, int index, int color) {
|
||||
SDL_Texture *texture = nullptr;
|
||||
switch (color)
|
||||
{
|
||||
case 0b000:
|
||||
texture = tled_off;
|
||||
break;
|
||||
case 0b001:
|
||||
texture = tled_b;
|
||||
break;
|
||||
case 0b010:
|
||||
texture = tled_g;
|
||||
break;
|
||||
case 0b011:
|
||||
texture = tled_gb;
|
||||
break;
|
||||
case 0b100:
|
||||
texture = tled_r;
|
||||
break;
|
||||
case 0b101:
|
||||
texture = tled_rb;
|
||||
break;
|
||||
case 0b110:
|
||||
texture = tled_rg;
|
||||
break;
|
||||
case 0b111:
|
||||
texture = tled_rgb;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// After SDL receives the changes of inputs, call update_gui_input()
|
||||
|
||||
// After updating the outputs of module, call update_gui_output()
|
||||
void update_gui_output(SDL_Renderer *renderer) {
|
||||
// check naive_leds
|
||||
for (int i = 0; i < naive_leds_cnt; ++i) {
|
||||
std::string &str = output_naive_leds[i];
|
||||
if (output_map.count(str) && prev_output_map[str] != output_map[str]) {
|
||||
prev_output_map[str] = output_map[str];
|
||||
update_gui_naive_led(renderer, i, output_map[str]);
|
||||
}
|
||||
}
|
||||
// check rgb_leds
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
bool flag = false;
|
||||
int color = 0;
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
std::string &str = output_rgb_leds[i * 3 + j];
|
||||
if (output_map.count(str)) {
|
||||
if (prev_output_map[str] != output_map[str]) {
|
||||
flag = true;
|
||||
color = (color << 1) | (prev_output_map[str] = output_map[str]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
update_gui_rgb_led(renderer, i, color);
|
||||
}
|
||||
}
|
||||
|
||||
// check seg7s
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
return;
|
||||
}
|
||||
|
||||
// render buttons, switches, leds and 7-segs
|
||||
void init_gui(SDL_Renderer *renderer) {
|
||||
|
||||
for (int i = 0; i < switches_cnt; ++i) {
|
||||
update_gui_switch(renderer, i, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < btns_cnt; ++i) {
|
||||
update_gui_button(renderer, i, 0);
|
||||
}
|
||||
//SDL_RenderPresent(renderer);
|
||||
//dbg_wait_esc();
|
||||
for (int i = 0; i < naive_leds_cnt; ++i) {
|
||||
update_gui_naive_led(renderer, i, 0);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/home/yuyake/virtual-fpga/emu/update.cpp
|
|
@ -0,0 +1 @@
|
|||
/home/yuyake/virtual-fpga/emu/update.cpp
|
Loading…
Reference in New Issue