├── cac ├── src │ ├── memory.cxx │ ├── memory.h │ ├── caclib.h │ ├── lib │ │ ├── BUILD │ │ ├── cacTypeDef.h │ │ ├── cacConst.h │ │ ├── stateIdDef.h │ │ └── external.h │ ├── BUILD │ ├── register.h │ ├── info.h │ ├── cacCore.h │ ├── register.cxx │ ├── info.cxx │ └── cacCore.cxx └── README.md ├── bootrom ├── bootrom ├── bootrom.dis └── bootrom.S ├── lib └── .gitignore ├── docs └── images │ └── boom_cosim.png ├── LICENSE_understanding.txt ├── env ├── cosim_env.h ├── params.h ├── env_dpi.cc └── cosim_env.cc ├── bridge ├── bridge_base.h ├── whisper │ ├── config │ │ ├── ascalon.json │ │ ├── boom.json │ │ └── ocelot.json │ ├── whisper_client.h │ ├── WhisperMessage.h │ ├── svdpi │ │ ├── svdpi_src.h │ │ └── svdpi.h │ └── whisper_client.cpp ├── bridge.h ├── bridge.cc └── std │ └── vpi_user.h ├── WORKSPACE ├── BUILD.bazel ├── mon └── mon_instr │ ├── mon_instr.h │ ├── mon_instr_dpi.cc │ ├── txn_instr.h │ └── mon_instr.cc ├── Makefile ├── README.md └── LICENSE.TT /cac/src/memory.cxx: -------------------------------------------------------------------------------- 1 | #include "memory.h" -------------------------------------------------------------------------------- /cac/src/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_H 2 | #define MEMORY_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /bootrom/bootrom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tenstorrent/cosim-arch-checker/HEAD/bootrom/bootrom -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /docs/images/boom_cosim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tenstorrent/cosim-arch-checker/HEAD/docs/images/boom_cosim.png -------------------------------------------------------------------------------- /cac/src/caclib.h: -------------------------------------------------------------------------------- 1 | #ifndef CBOARD_LIB_H 2 | #define CBOARD_LIB_H 3 | 4 | #include "lib/cacConst.h" 5 | #include "lib/cacTypeDef.h" 6 | #include "lib/external.h" 7 | #include "lib/stateIdDef.h" 8 | 9 | #endif -------------------------------------------------------------------------------- /cac/src/lib/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | cc_library( 3 | name = "cacLibInclude", 4 | hdrs = ["cacConst.h", "cacTypeDef.h", "external.h", "stateIdDef.h"], 5 | visibility = ["//visibility:public"], 6 | ) 7 | -------------------------------------------------------------------------------- /LICENSE_understanding.txt: -------------------------------------------------------------------------------- 1 | For the avoidance of doubt, this software assists in programming Tenstorrent products. 2 | 3 | However, making, using, or selling hardware, models, or IP may require the license of rights (such as patent rights) from Tenstorrent or others. 4 | -------------------------------------------------------------------------------- /env/cosim_env.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include "mon_instr.h" 6 | 7 | class cCosimEnv { 8 | 9 | public: 10 | cCosimEnv(); 11 | 12 | void initial(); 13 | void final(); 14 | 15 | private: 16 | cMonInstr *monInstr; 17 | }; 18 | -------------------------------------------------------------------------------- /env/params.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #if ((CONFIG == MediumBoomVecConfig) || (CONFIG == MediumOcelotVecConfig)) 6 | 7 | namespace { 8 | 9 | const int k_NumHarts = 1; 10 | const int k_VLen = 256; 11 | 12 | } 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /bridge/bridge_base.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include "txn_instr.h" 6 | 7 | class cBridgeBase { 8 | 9 | public: 10 | 11 | virtual ~cBridgeBase() {} 12 | 13 | virtual void processDutInstrRetire(int hart, sRvInstr &dutInstr) = 0; 14 | 15 | }; 16 | -------------------------------------------------------------------------------- /env/env_dpi.cc: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #include "cosim_env.h" 4 | 5 | extern "C" { 6 | 7 | cCosimEnv *env; 8 | 9 | void env_init() { 10 | env = new cCosimEnv(); 11 | env->initial(); 12 | } 13 | 14 | void env_final() { 15 | env->final(); 16 | delete env; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /env/cosim_env.cc: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #include "cosim_env.h" 4 | 5 | cCosimEnv::cCosimEnv () 6 | : monInstr(new cMonInstr("mon_instr")) {} 7 | 8 | void cCosimEnv::initial() { 9 | monInstr->initial(); 10 | } 11 | 12 | void cCosimEnv::final() { 13 | monInstr->final(); 14 | delete monInstr; 15 | } 16 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 2 | 3 | whisper_hash="a057fb23891c9e5cc11b4ffa7a3b5ce4fdd01d78" 4 | git_repository( 5 | name = "whisper", 6 | commit = whisper_hash, 7 | remote = "https://github.com/tenstorrent/whisper.git", 8 | ) 9 | 10 | git_repository( 11 | name = "googletest", 12 | remote = "https://github.com/google/googletest", 13 | #commit = "1b18723e874b256c1e39378c6774a90701d70f7a" 14 | tag = "release-1.11.0", 15 | ) 16 | -------------------------------------------------------------------------------- /cac/src/lib/cacTypeDef.h: -------------------------------------------------------------------------------- 1 | #ifndef CAC_TYPEDEF_H 2 | #define CAC_TYPEDEF_H 3 | 4 | #include 5 | 6 | typedef unsigned char size1ByteT; 7 | typedef unsigned short int size2BytesT; 8 | typedef unsigned int size4BytesT; 9 | typedef unsigned long long int size8BytesT; 10 | 11 | typedef size2BytesT threadT; 12 | typedef size2BytesT stateIdT; 13 | typedef size2BytesT sizenBitT; 14 | typedef size8BytesT fuzzMaskT; 15 | typedef size8BytesT unitDataT; 16 | 17 | typedef std::vector dataVectorT; 18 | 19 | #endif -------------------------------------------------------------------------------- /cac/src/lib/cacConst.h: -------------------------------------------------------------------------------- 1 | #ifndef CAC_CONST_H 2 | #define CAC_CONST_H 3 | 4 | #include "cacTypeDef.h" 5 | 6 | const sizenBitT UNIT_BIT_NUM = 64; 7 | const sizenBitT VEC_128 = 128; 8 | const sizenBitT VEC_256 = 256; 9 | const sizenBitT VEC_512 = 512; 10 | const size8BytesT RST_8_BYTE_VALUE[] = {0x0}; 11 | 12 | // 0:RT_FIX, 1:RT_FLT, 2:RT_X, 3: RT_PAS, 4: RT_VEC 13 | const unsigned int REGISTER_RT_FIX_ENCODING = 0; 14 | const unsigned int REGISTER_RT_FLT_ENCODING = 1; 15 | const unsigned int REGISTER_RT_VEC_ENCODING = 4; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "dpi", 3 | srcs = glob(["**/*.cc", "**/*.cpp", "**/*.hpp", "**/*.h"]), 4 | linkshared = True, 5 | copts = [ 6 | "-Ibridge", 7 | "-Ibridge/std", 8 | "-Ibridge/whisper", 9 | "-Ibridge/whisper/svdpi", 10 | "-Imon/mon_instr", 11 | "-Ienv", 12 | "-Iexternal/CoreArchChecker/src", 13 | "-Iexternal/whisper", 14 | ], 15 | deps = [ 16 | "//cac/src:caccore", 17 | ], 18 | data = [ 19 | "@whisper//:whisper", 20 | ], 21 | ) 22 | 23 | -------------------------------------------------------------------------------- /bridge/whisper/config/ascalon.json: -------------------------------------------------------------------------------- 1 | { 2 | "xlen" : 64, 3 | "isa" : "rv64imabfdvus", 4 | "reset_vec" : "0x80000000", 5 | 6 | "csr" : { 7 | "misa" : { 8 | "reset-comment" : "imabfdvus", 9 | "reset" : "0x800000000094112d", 10 | "mask-comment" : "Misa is not writable by CSR instructions", 11 | "mask" : "0x0" 12 | }, 13 | "mip" : { 14 | "reset" : "0x0", 15 | "comment" : "Configure software interrupt on CPU0 to start the boot process" 16 | }, 17 | "mstatus" : { 18 | "reset" : "0x8000000a00007800", 19 | "mask-comment" : "Readonly fields: SXL[35:34], UXL[33:32], WPRI[31:23], VS[10:9]", 20 | "mask" : "0xFFFFFFF0007FF9FF" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bridge/whisper/config/boom.json: -------------------------------------------------------------------------------- 1 | { 2 | "xlen" : 64, 3 | 4 | "isa" : "rv64gc", 5 | 6 | "reset_vec" : "0x10040", 7 | 8 | "clint" : "0x2000000", 9 | 10 | "vector" : { 11 | "bytes_per_vec" : 32, 12 | "min_bytes_per_elem" : 1, 13 | "max_bytes_per_elem" : 8 14 | }, 15 | 16 | "csr" : { 17 | "misa" : { 18 | "reset-comment" : "rv64gc", 19 | "reset" : "0x800000000014112d", 20 | "mask-comment" : "Misa is not writable by CSR instructions", 21 | "mask" : "0x0" 22 | }, 23 | "mip" : { 24 | "reset" : "0x8", 25 | "comment" : "Configure software interrupt on CPU0 to start the boot process" 26 | }, 27 | "mstatus" : { 28 | "reset" : "0x8000000a00007e00", 29 | "mask-comment" : "Readonly fields: SXL[35:34], UXL[33:32], WPRI[31:23], VS[10:9]", 30 | "mask" : "0xFFFFFFF0007FF9FF" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /bridge/whisper/config/ocelot.json: -------------------------------------------------------------------------------- 1 | { 2 | "xlen" : 64, 3 | 4 | "isa" : "rv64imabfdvus_zfh", 5 | 6 | "reset_vec" : "0x10040", 7 | 8 | "clint" : "0x2000000", 9 | 10 | "vector" : { 11 | "bytes_per_vec" : 32, 12 | "min_bytes_per_elem" : 1, 13 | "max_bytes_per_elem" : 8 14 | }, 15 | 16 | "csr" : { 17 | "misa" : { 18 | "reset-comment" : "imabfdvus", 19 | "reset" : "0x8000000000b4112d", 20 | "mask-comment" : "Misa is not writable by CSR instructions", 21 | "mask" : "0x0" 22 | }, 23 | "mip" : { 24 | "reset" : "0x8", 25 | "comment" : "Configure software interrupt on CPU0 to start the boot process" 26 | }, 27 | "mstatus" : { 28 | "reset" : "0x8000000a00007e00", 29 | "mask-comment" : "Readonly fields: SXL[35:34], UXL[33:32], WPRI[31:23], VS[10:9]", 30 | "mask" : "0xFFFFFFF0007FF9FF" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cac/src/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | cc_library( 3 | name = "caccore", 4 | srcs = ["cacCore.cxx"], 5 | hdrs = [ 6 | "cacCore.h", 7 | "register.h", 8 | "info.h", 9 | ], 10 | visibility = ["//visibility:public"], 11 | deps = [ 12 | ":registerBuild", 13 | ":infoBuild", 14 | ":caclibBuild" 15 | ], 16 | ) 17 | 18 | cc_library( 19 | name = "registerBuild", 20 | srcs = ["register.cxx"], 21 | hdrs = [ 22 | "register.h", 23 | "caclib.h", 24 | ], 25 | deps = [ 26 | ":caclibBuild" 27 | ] 28 | ) 29 | 30 | cc_library( 31 | name = "infoBuild", 32 | srcs = ["info.cxx"], 33 | hdrs = [ 34 | "info.h", 35 | "caclib.h", 36 | ], 37 | deps = [ 38 | ":caclibBuild" 39 | ] 40 | ) 41 | 42 | cc_library( 43 | name = "caclibBuild", 44 | hdrs = [ 45 | "caclib.h", 46 | ], 47 | deps = [ 48 | "//cac/src/lib:cacLibInclude", 49 | ], 50 | ) 51 | -------------------------------------------------------------------------------- /mon/mon_instr/mon_instr.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include "bridge.h" 8 | #include "txn_instr.h" 9 | #include "params.h" 10 | #include "vpi_user.h" 11 | 12 | class cMonInstr { 13 | 14 | public: 15 | cMonInstr(std::string name); 16 | void initial(); 17 | void parseArgs(); 18 | void final(); 19 | 20 | void monRetire(int hart, std::uint64_t cycle, std::uint64_t tag, std::uint64_t pc, std::uint64_t opcode, std::uint32_t trap); 21 | void monGpr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data); 22 | void monFpr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data); 23 | void monVr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t *data); 24 | void monCsr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data); 25 | 26 | private: 27 | void display(int hart, const sRvInstr &instr); 28 | 29 | private: 30 | std::string name; 31 | bool monTracer = false; 32 | sRvInstr rvInstr; 33 | cBridge *bridge; 34 | 35 | }; 36 | -------------------------------------------------------------------------------- /cac/src/register.h: -------------------------------------------------------------------------------- 1 | #ifndef REGISTER_H 2 | #define REGISTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "caclib.h" 9 | 10 | class Register 11 | { 12 | public: 13 | Register(threadT tid, stateIdT rid, sizenBitT bitSize, unitDataT * data); 14 | void setValue(unitDataT * data); 15 | threadT getThreadId(); 16 | sizenBitT getSize(); 17 | void updateSize(sizenBitT sz); 18 | stateIdT getRegisterId(); 19 | std::vector getValue(); 20 | bool checkValue(unitDataT * data); 21 | private: 22 | threadT threadId; 23 | stateIdT registerId; 24 | sizenBitT size; 25 | std::vector valueV; 26 | }; 27 | 28 | class RegisterSnapshot 29 | { 30 | public: 31 | RegisterSnapshot(threadT tid); 32 | std::vector getValue(stateIdT id); 33 | void updateSize(unsigned int vlen); 34 | void updateValue(stateIdT id, unitDataT * data); 35 | bool checkValue(stateIdT id, unitDataT * data); 36 | private: 37 | threadT threadId; 38 | std::unordered_map snapshotCol; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Compiler settings 2 | CC = g++ 3 | CFLAGS = -std=c++17 -Wall -Werror -Wno-unused-private-field -fpic -Imon/mon_instr -Ibridge/std -Ibridge -Ienv -Ibridge/whisper/svdpi -Ibridge/whisper -Icac/src/lib -Icac/src 4 | LDLIBS = 5 | 6 | # Directories 7 | SRC_DIR = . 8 | BUILD_DIR = build 9 | LIB_DIR = lib 10 | 11 | # Source files 12 | SRCS = $(shell find . -name '*.cpp' -o -name '*.cxx' -o -name '*.cc') 13 | $(info SRCS=$(SRCS)) 14 | OBJS = $(patsubst $(SRC_DIR)/%.cc, $(BUILD_DIR)/%.o, $(patsubst $(SRC_DIR)/%.cxx, $(BUILD_DIR)/%.o, $(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.o, $(SRCS)))) 15 | $(info OBJS=$(OBJS)) 16 | DEPS = $(OBJS:.o=.d) 17 | 18 | # Library name and version 19 | LIB_NAME = cosim 20 | 21 | # Targets 22 | .PHONY: all clean 23 | 24 | all: $(LIB_DIR)/lib$(LIB_NAME).so 25 | 26 | clean: 27 | rm -rf $(BUILD_DIR)/* $(LIB_DIR)/* 28 | 29 | $(LIB_DIR)/lib$(LIB_NAME).so: $(OBJS) 30 | $(CC) $(LDLIBS) -shared -Wl,-soname,lib$(LIB_NAME).so -o $@ $^ 31 | 32 | -include $(DEPS) 33 | 34 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cc 35 | @mkdir -p $(dir $@) 36 | $(CC) $(CFLAGS) -MMD -MP -c -o $@ $< 37 | 38 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp 39 | @mkdir -p $(dir $@) 40 | $(CC) $(CFLAGS) -MMD -MP -c -o $@ $< 41 | 42 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cxx 43 | @mkdir -p $(dir $@) 44 | $(CC) $(CFLAGS) -MMD -MP -c -o $@ $< 45 | -------------------------------------------------------------------------------- /bridge/whisper/whisper_client.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include "svdpi.h" 6 | 7 | extern "C" 8 | int 9 | whisperConnect(const char* filePath); 10 | 11 | extern "C" 12 | void 13 | whisperDisconnect(); 14 | 15 | extern "C" 16 | bool 17 | whisperStep(int hart, uint64_t time, uint64_t instrTag, uint64_t& pc, 18 | uint32_t& instruction, unsigned& changeCount, char* buffer, unsigned bufferSize, 19 | uint32_t& privMode, uint32_t& fpFlags, bool& hasTrap); 20 | 21 | extern "C" 22 | bool 23 | whisperSimpleStep(int hart, uint64_t& pc, uint32_t& instruction, unsigned& changeCount); 24 | 25 | extern "C" 26 | bool 27 | whisperChange(int hart, uint32_t& resource, uint64_t& addr, uint64_t& value, 28 | bool& valid); 29 | 30 | extern "C" 31 | bool 32 | whisperMcmRead(int hart, uint64_t time, uint64_t instrTag, 33 | uint64_t addr, unsigned size, uint64_t value, bool internal, bool& valid); 34 | 35 | extern "C" 36 | bool 37 | whisperMcmInsert(int hart, uint64_t time, uint64_t instrTag, 38 | uint64_t addr, unsigned size, uint64_t value, bool& valid); 39 | 40 | extern "C" 41 | bool 42 | whisperMcmWrite(int hart, uint64_t time, uint64_t addr, unsigned size, 43 | svOpenArrayHandle handle, bool& valid); 44 | 45 | extern "C" 46 | bool 47 | whisperPoke(int hart, char resource, uint64_t addr, uint64_t value, 48 | bool& valid); 49 | 50 | extern "C" 51 | bool 52 | whisperPeek(int hart, char resource, uint64_t addr, uint64_t& value, 53 | bool& valid); 54 | 55 | extern "C" 56 | bool 57 | whisperReset(int hart, bool& valid); 58 | -------------------------------------------------------------------------------- /cac/src/info.h: -------------------------------------------------------------------------------- 1 | #ifndef INFO_H 2 | #define INFO_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "caclib.h" 9 | 10 | class Info 11 | { 12 | public: 13 | Info(threadT tid, stateIdT stateId, const std::string &type, unitDataT * item, unsigned int size); 14 | std::string getItemName(); 15 | unitDataT * getData(); 16 | std::string getFormatInfo(); 17 | std::string getType(); 18 | unsigned int getSize(); 19 | private: 20 | threadT threadId; 21 | stateIdT stateId; 22 | std::string infoType; 23 | std::string itemName; 24 | unitDataT * item; 25 | unsigned int size; 26 | std::string formatString; 27 | }; 28 | 29 | class InfoCol 30 | { 31 | public: 32 | InfoCol(threadT tid, int stepNum, const std::string &type); 33 | std::unordered_map getInfoDict(); 34 | void gatherInfo(Info &infoItem); 35 | void outputStates(InfoCol *infoColIns); 36 | private: 37 | threadT threadId; 38 | std::string infoColType; 39 | std::unordered_map infoDict; 40 | int stepNum; 41 | }; 42 | 43 | class Record 44 | { 45 | public: 46 | Record(threadT tNum); 47 | void addInfoCol(threadT tid, bool ifdut, InfoCol &col); 48 | void addInfo(threadT tid, bool ifdut, Info & info); 49 | InfoCol getInfoColByStep(threadT tid, bool ifdut, int stepN); 50 | private: 51 | threadT threadNum; 52 | std::unordered_map> recorderDutCol; 53 | std::unordered_map> recorderSimCol; 54 | }; 55 | 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /mon/mon_instr/mon_instr_dpi.cc: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #include 4 | #include 5 | 6 | #include "mon_instr.h" 7 | 8 | extern "C" { 9 | 10 | static std::map intfs; 11 | 12 | void instr_register_intf(std::string name, cMonInstr *intf) { 13 | intfs.insert({name, intf}); 14 | } 15 | 16 | void instr_deregister_intf(std::string name) { intfs.erase(name); } 17 | 18 | void monitor_instr(char *name, int hart, std::uint64_t cycle, std::uint64_t tag, std::uint64_t pc, std::uint64_t opcode, std::uint32_t trap) { 19 | auto ptr = intfs.find(name); 20 | if (ptr != intfs.end()) { 21 | ptr->second->monRetire(hart, cycle, tag, pc, opcode, trap); 22 | } 23 | } 24 | 25 | void monitor_gpr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data) { 26 | auto ptr = intfs.find(name); 27 | if (ptr != intfs.end()) { 28 | ptr->second->monGpr(hart, cycle, addr, data); 29 | } 30 | } 31 | 32 | void monitor_fpr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data) { 33 | auto ptr = intfs.find(name); 34 | if (ptr != intfs.end()) { 35 | ptr->second->monFpr(hart, cycle, addr, data); 36 | } 37 | } 38 | 39 | void monitor_vr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t *data) { 40 | auto ptr = intfs.find(name); 41 | if (ptr != intfs.end()) { 42 | ptr->second->monVr(hart, cycle, addr, data); 43 | } 44 | } 45 | 46 | void monitor_csr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data) { 47 | auto ptr = intfs.find(name); 48 | if (ptr != intfs.end()) { 49 | ptr->second->monCsr(hart, cycle, addr, data); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /mon/mon_instr/txn_instr.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include 6 | #include "params.h" 7 | 8 | struct sPc { 9 | bool valid; 10 | uint64_t pc_rdata; 11 | 12 | sPc() { 13 | clear(); 14 | } 15 | 16 | void clear() { 17 | valid = false; 18 | } 19 | }; 20 | 21 | struct sGpr { 22 | bool valid; 23 | uint64_t rd_addr; 24 | uint64_t rd_wdata; 25 | 26 | sGpr() { 27 | clear(); 28 | } 29 | 30 | void clear() { 31 | valid = false; 32 | } 33 | }; 34 | 35 | struct sFpr { 36 | bool valid; 37 | uint64_t frd_addr; 38 | bool frd_wvalid; 39 | uint64_t frd_wdata; 40 | 41 | sFpr() { 42 | clear(); 43 | } 44 | 45 | void clear() { 46 | valid = false; 47 | } 48 | }; 49 | 50 | struct sVr { 51 | bool valid; 52 | uint32_t vrd_addr; 53 | uint64_t vrd_wdata[k_VLen/64]; 54 | 55 | sVr() { 56 | clear(); 57 | } 58 | 59 | void clear() { 60 | valid = false; 61 | } 62 | }; 63 | 64 | struct sCsr { 65 | bool valid; 66 | uint32_t csr_count; 67 | uint32_t csr_addr; 68 | uint64_t csr_wmask; 69 | uint64_t csr_wdata; 70 | 71 | sCsr() { 72 | clear(); 73 | } 74 | 75 | void clear() { 76 | valid = false; 77 | } 78 | }; 79 | 80 | struct sRvInstr { 81 | // Metadata 82 | bool valid; 83 | uint64_t cycle; 84 | uint64_t tag; 85 | uint32_t opcode; 86 | bool trap; 87 | 88 | // Registers 89 | sPc pc; 90 | sGpr gpr; 91 | sFpr fpr; 92 | sVr vr; 93 | std::vector csrs; 94 | 95 | void clear() { 96 | valid = false; 97 | pc.clear(); 98 | gpr.clear(); 99 | fpr.clear(); 100 | vr.clear(); 101 | csrs.clear(); 102 | } 103 | }; 104 | -------------------------------------------------------------------------------- /bridge/whisper/WhisperMessage.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | 8 | enum WhisperMessageType { Peek, Poke, Step, Until, Change, ChangeCount, 9 | Quit, Invalid, Reset, Exception, EnterDebug, 10 | ExitDebug, LoadFinished, CancelDiv, CancelLr, 11 | DumpMemory, McmRead, McmInsert, McmWrite }; 12 | 13 | // Be careful changing this: test-bench file (defines.svh) needs to be 14 | // updated. 15 | enum WhisperExceptionType { InstAccessFault, DataAccessFault, 16 | ImpreciseStoreFault, ImpreciseLoadFault, 17 | PreciseStoreFault, PreciseLoadFault, 18 | NonMaskableInterrupt }; 19 | 20 | 21 | /// Structure used to communicate with the whisper program using 22 | /// sockets. When a ChangeCount message is returned by whisper (as a 23 | /// reply to a Step or a ChangeCount request), the address is set to 24 | /// the program-counter of the last executed instruction, the resource 25 | /// is set to the opcode of that instruction and the value is set to 26 | /// the number of change records generated by that instruction. 27 | struct WhisperMessage 28 | { 29 | #ifdef __cplusplus 30 | WhisperMessage(uint32_t hart = 0, WhisperMessageType type = Invalid, 31 | uint32_t resource = 0, uint64_t address = 0, 32 | uint64_t value = 0, uint32_t size = 0, uint64_t instrTag = 0, 33 | uint64_t time = 0) 34 | : hart(hart), type(type), resource(resource), size(size), flags(0), 35 | instrTag(instrTag), time(time), address(address), value(value) 36 | { 37 | buffer[0] = 0; 38 | tag[0] = 0; 39 | } 40 | #endif 41 | 42 | uint32_t hart; 43 | uint32_t type; 44 | uint32_t resource; 45 | uint32_t size; 46 | uint32_t flags; 47 | uint64_t instrTag; // Instruction tag. 48 | uint64_t time; // Time stamp. 49 | uint64_t address; 50 | uint64_t value; 51 | char buffer[128]; 52 | char tag[20]; 53 | }; 54 | -------------------------------------------------------------------------------- /cac/src/cacCore.h: -------------------------------------------------------------------------------- 1 | #ifndef CAC_CORE_H 2 | #define CAC_CORE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "caclib.h" 9 | #include "register.h" 10 | #include "info.h" 11 | 12 | class CacCore 13 | { 14 | public: 15 | // Constructor 16 | CacCore(threadT tNum); 17 | // Hello World function to make unit test work 18 | std::string getHello(); 19 | // Configuration API 20 | void configureVlen(unsigned int vlen); 21 | // Dut API to update Register 22 | void updateRegister(threadT threadId, unsigned int typeEncoding, unsigned int typeOffset, unitDataT * data); 23 | void updateRegister(threadT threadId, stateIdT id, unitDataT * data); 24 | // Simulator API to update Register 25 | void updateRefRegister(threadT threadId, unsigned int typeEncoding, unsigned int typeOffset, unitDataT * data); 26 | void updateRefRegister(threadT threadId, stateIdT id, unitDataT * data); 27 | // Make a lock step 28 | void step(threadT threadId); 29 | // Api to get which step it is 30 | int getStep(threadT threadId); 31 | // Api to get the check result 32 | bool getStatus(threadT threadId); 33 | void resetStatus(threadT threadId); 34 | 35 | // TODO: fuzz mask 36 | // void updateRegister(threadT threadId, stateIdT id, unitDataT * data, fuzzMaskT fuzzMask); 37 | //void updateMem(threadT threadId); 38 | private: 39 | threadT threadNum; 40 | unsigned int cfg_vlen = VEC_128; 41 | Record *record; 42 | std::unordered_map status; 43 | std::unordered_map stepCount; 44 | std::unordered_map dutChangeCount; 45 | std::unordered_map simChangeCount; 46 | std::unordered_map registerSnapshot; 47 | std::unordered_map> checkingBuffer; 48 | stateIdT generateStateId(unsigned int typeEncoding, unsigned int typeOffset); 49 | bool checkRegister(threadT threadId, stateIdT id, unitDataT * data); 50 | unsigned int getRegisterSize(stateIdT id); 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /bridge/whisper/svdpi/svdpi_src.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Copyright (C) 2004 Synopsys, Inc. All Rights Reserved. 4 | * Portions Copyright (C) 2004 Accellera Organization, Inc. 5 | * All Rights Reserved. Used with Permission. 6 | * 7 | * Chronologic VCS (TM) 8 | * 9 | * SystemVerilog 3.1 DPI (Direct Programming Interface). 10 | * 11 | * Source-level compatibility include file "svdpi_src.h" 12 | * 13 | * Revision: 14 | * as in Annex F of SystemVerilog 3.1a draft 5 15 | * Language Reference Manual 16 | * Accellera's Extensions to Verilog (R) 17 | * 18 | * 19 | * This file contains the macro definitions for declaring variables 20 | * to represent SystemVerilog packed arrays of type bit or logic. 21 | * 22 | * The actual definitions are implementation specific. 23 | * This version is for VCS 7.2. 24 | * 25 | * The file should be included with all C functions that use SystemVerilog 26 | * Direct Programming Interface and need to define data structures 27 | * corresponding to SystemVerilog data structures involving packed arrays. 28 | * 29 | ****************************************************************************/ 30 | 31 | /* $Revision$ */ 32 | 33 | #ifndef SVDPI_SRC_H /* allow multiple inclusions */ 34 | #define SVDPI_SRC_H 35 | 36 | /*---------------------------------------------------------------------------*/ 37 | /*------------------------------- definitions -------------------------------*/ 38 | /*---------------------------------------------------------------------------*/ 39 | 40 | #if defined(__cplusplus) 41 | extern "C" { 42 | #endif 43 | 44 | 45 | /* Macros for declaring variables to represent SystemVerilog */ 46 | /* packed arrays of type bit or logic. */ 47 | /* WIDTH = number of bits, */ 48 | /* NAME = name of a declared field/variable */ 49 | 50 | #define SV_BIT_PACKED_ARRAY(WIDTH,NAME) \ 51 | svBitVec32 NAME [ SV_CANONICAL_SIZE(WIDTH) ] 52 | 53 | #define SV_LOGIC_PACKED_ARRAY(WIDTH,NAME) \ 54 | svLogicVec32 NAME [ SV_CANONICAL_SIZE(WIDTH) ] 55 | 56 | 57 | #if defined(__cplusplus) 58 | } /* extern "C" */ 59 | #endif 60 | 61 | #endif /* SVDPI_SRC_H */ 62 | -------------------------------------------------------------------------------- /bootrom/bootrom.dis: -------------------------------------------------------------------------------- 1 | 2 | bootrom: file format elf64-littleriscv 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 0000000000010000 <_start>: 8 | 10000: 020005b7 lui a1,0x2000 9 | 10004: f1402573 csrr a0,mhartid 10 | 10008: 00050463 beqz a0,10010 <_start+0x10> 11 | 1000c: 0680006f j 10074 12 | 10010: 00458613 addi a2,a1,4 # 2000004 <_dtb+0x1feff54> 13 | 10014: 00100693 li a3,1 14 | 15 | 0000000000010018 : 16 | 10018: 00d62023 sw a3,0(a2) 17 | 1001c: 00460613 addi a2,a2,4 18 | 10020: ffc62683 lw a3,-4(a2) 19 | 10024: fe069ae3 bnez a3,10018 20 | 10028: 05c0006f j 10084 21 | 22 | Disassembly of section .text1: 23 | 24 | 0000000000010040 <_hang>: 25 | 10040: 00000517 auipc a0,0x0 26 | 10044: fc050513 addi a0,a0,-64 # 10000 <_start> 27 | 10048: 30551073 csrw mtvec,a0 28 | 1004c: 301022f3 csrr t0,misa 29 | 10050: 4122d293 srai t0,t0,0x12 30 | 10054: 0012f293 andi t0,t0,1 31 | 10058: 00028463 beqz t0,10060 <_hang+0x20> 32 | 1005c: 30301073 csrw mideleg,zero 33 | 10060: 00800513 li a0,8 34 | 10064: 30451073 csrw mie,a0 35 | 10068: 30052073 csrs mstatus,a0 36 | 37 | 000000000001006c : 38 | 1006c: 10500073 wfi 39 | 10070: ffdff06f j 1006c 40 | 41 | 0000000000010074 : 42 | 10074: 0005a283 lw t0,0(a1) 43 | 10078: fe029ee3 bnez t0,10074 44 | 1007c: 00251513 slli a0,a0,0x2 45 | 10080: 00b505b3 add a1,a0,a1 46 | 47 | 0000000000010084 : 48 | 10084: 0005a023 sw zero,0(a1) 49 | 10088: 00004537 lui a0,0x4 50 | 1008c: 00053503 ld a0,0(a0) # 4000 51 | 10090: 34151073 csrw mepc,a0 52 | 10094: f1402573 csrr a0,mhartid 53 | 10098: 00000597 auipc a1,0x0 54 | 1009c: 01858593 addi a1,a1,24 # 100b0 <_dtb> 55 | 100a0: 08000613 li a2,128 56 | 100a4: 30063073 csrc mstatus,a2 57 | 100a8: 30200073 mret 58 | 100ac: 00000013 nop 59 | -------------------------------------------------------------------------------- /cac/src/register.cxx: -------------------------------------------------------------------------------- 1 | #include "register.h" 2 | #include 3 | // Register 4 | Register::Register(threadT tid, stateIdT rid, sizenBitT bitSize, unitDataT * data):threadId(tid), registerId(rid), size(bitSize),valueV(data, data+size/64){}; 5 | 6 | stateIdT Register::getRegisterId(){ 7 | return(registerId); 8 | }; 9 | 10 | void Register::setValue(unitDataT * data){ 11 | valueV.clear(); 12 | //valueV.assign(data, data+size/64); 13 | for (int i = 0; i valueRef; 20 | for (int i = 0; i Register::getValue(){ 36 | return(valueV); 37 | }; 38 | 39 | //RegisterSnapshot 40 | RegisterSnapshot::RegisterSnapshot(threadT tid):threadId(tid){ 41 | for(const stateIdT &supportStateId : supportStates){ 42 | sizenBitT regSize = supportStatesSize[supportStateId]; 43 | size8BytesT rstValue[] = {0x0}; 44 | Register reg(threadId, supportStateId, regSize, rstValue); 45 | snapshotCol.insert_or_assign(supportStateId, reg); 46 | } 47 | }; 48 | 49 | std::vector RegisterSnapshot::getValue(stateIdT id){ 50 | Register reg = snapshotCol.at(id); 51 | return(reg.getValue()); 52 | }; 53 | 54 | void RegisterSnapshot::updateSize(unsigned int vlen){ 55 | for(const stateIdT &id : supportStates){ 56 | if (id >= CAC_STATE_RegV0_ID && id <= CAC_STATE_RegV31_ID) { 57 | Register reg = snapshotCol.at(id); 58 | reg.updateSize(vlen); 59 | snapshotCol.at(id) = reg; 60 | } 61 | } 62 | } 63 | 64 | void RegisterSnapshot::updateValue(stateIdT id, size8BytesT * data){ 65 | Register reg = snapshotCol.at(id); 66 | reg.setValue(data); 67 | snapshotCol.at(id) = reg; 68 | }; 69 | 70 | bool RegisterSnapshot::checkValue(stateIdT id, size8BytesT * data){ 71 | Register reg = snapshotCol.at(id); 72 | return(reg.checkValue(data)); 73 | }; 74 | -------------------------------------------------------------------------------- /bootrom/bootrom.S: -------------------------------------------------------------------------------- 1 | #define BOOTADDR_REG 0x4000 2 | 3 | // boot all cores (only hart 0) and jump to main program execution 4 | .section .text.start, "ax", @progbits 5 | .globl _start 6 | _start: 7 | li a1, 0x2000000 // base address of clint 8 | csrr a0, mhartid 9 | bnez a0, boot_core 10 | addi a2, a1, 4 11 | li a3, 1 12 | interrupt_loop: // trigger MSIP interrupts for other harts so that they also boot 13 | sw a3, 0(a2) 14 | addi a2, a2, 4 15 | lw a3, -4(a2) 16 | bnez a3, interrupt_loop 17 | // beqz a3, interrupt_loop 18 | j boot_core_hart0 19 | 20 | // this boot ROM doesn't know about any boot devices, so it just spins, 21 | // waiting for the serial interface to load the program and interrupt it 22 | .section .text.hang, "ax", @progbits 23 | .globl _hang 24 | _hang: // reset vector 25 | la a0, _start // on MSIP interrupt, go to _start 26 | csrw mtvec, a0 27 | csrr t0, misa // get MISA mask 28 | srai t0, t0, 'S' - 'A' // get 'S' supervisor bit 29 | andi t0, t0, 0x1 30 | beqz t0, 1f // only zero mideleg if supported 31 | csrw mideleg, zero // no delegation 32 | 1: 33 | li a0, 8 // MIE or MSIP bit 34 | csrw mie, a0 // set only MSIP in MIE CSR 35 | csrs mstatus, a0 // set MIE in mstatus CSR 36 | 37 | wfi_loop: // wait for MSIP interrupt to start program execution 38 | wfi 39 | j wfi_loop 40 | 41 | // other harts must wait until MSIP of hart 0 is cleared to continue 42 | boot_core: 43 | lw t0, 0(a1) // load hart 0 MSIP 44 | bnez t0, boot_core // block until hart 0 clears own MSIP 45 | sll a0, a0, 2 // offset for hart MSIP 46 | add a1, a0, a1 47 | boot_core_hart0: // begin executing code at DRAM_BASE 48 | sw zero, 0(a1) // clear the interrupt 49 | li a0, BOOTADDR_REG // program reset vector 50 | #if __riscv_xlen == 32 51 | lw a0, 0(a0) // get boot address from bootaddr_reg SCR 52 | #else 53 | ld a0, 0(a0) // get boot address from bootaddr_reg SCR 54 | #endif 55 | csrw mepc, a0 // return from interrupt to start of user program 56 | csrr a0, mhartid // hartid for next level bootloader 57 | la a1, _dtb // dtb address for next level bootloader 58 | li a2, 0x80 // set mstatus MPIE to 0 59 | csrc mstatus, a2 60 | mret 61 | 62 | .align 3 63 | _dtb: 64 | 65 | //Boom reads the the program start address from address 0x4000 66 | //The label junk is placed at location 0x4000 by the linker script (link.ld) 67 | .section .data 68 | .globl junk 69 | junk: 70 | .word 0x80000000 71 | 72 | -------------------------------------------------------------------------------- /bridge/bridge.h: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #pragma once 4 | 5 | #include 6 | #include // vpi_printf 7 | 8 | #include "bridge_base.h" 9 | #include "whisper_client.h" 10 | #include "cacCore.h" // CoreArchChecker 11 | 12 | class cBridge : public cBridgeBase { 13 | 14 | public: 15 | cBridge(int numHarts, int vLen); 16 | ~cBridge(); 17 | 18 | // DUT Interface API 19 | // Process instruction called on retire 20 | // - Metadata 21 | // - PC 22 | // - Register Read/Write 23 | // - CSRs 24 | // - Memory Access 25 | // - AMO 26 | // - Table Walks 27 | // - Exceptions/Interrupts 28 | virtual void processDutInstrRetire(int hart, sRvInstr &dutInstr) override; 29 | 30 | private: 31 | // Encapsulate whisper state 32 | typedef struct sWhisperState { 33 | //used in whisperStep 34 | uint64_t tag; 35 | uint64_t time; 36 | uint64_t pc; 37 | uint32_t opcode; 38 | unsigned changeCount; 39 | char buffer[128]; 40 | unsigned bufferSize = 128; 41 | //Used in whisperChange 42 | uint32_t resource; 43 | uint64_t address; 44 | uint64_t value; 45 | bool valid; 46 | uint32_t privMode; 47 | uint32_t fpFlags; 48 | bool trap; 49 | 50 | } sWhisperState; 51 | 52 | typedef enum { 53 | k_IntReg = 0, 54 | k_FpReg = 1, 55 | k_VecReg = 4 56 | } eResource; 57 | 58 | typedef enum { 59 | k_Dut, 60 | k_Whisper 61 | } eSrc; 62 | 63 | private: 64 | 65 | void parseArgs(); 66 | void connectWhisper(); 67 | void disconnectWhisper(); 68 | std::string getWhisperCmd(std::string testname); 69 | 70 | void stepWhisper(int hart, uint64_t cycle, uint64_t tag, sWhisperState &whisInstr); 71 | void updateCac(int hart, const sRvInstr &dutInstr); 72 | void updateCac(int hart, uint64_t cycle, uint64_t tag, sWhisperState &whisInstr); 73 | void updatePc(int hart, eSrc src, uint64_t data); 74 | void updateRegs(int hart, eSrc src, eResource resource, uint64_t addr, size8BytesT dwordArray[]); 75 | bool disChecks(const sWhisperState &whisInstr); 76 | void pokeWhisper(int hart, const sRvInstr &dutInstr); 77 | 78 | private: 79 | int numHarts_ = 0; 80 | int vLen_ = 0; 81 | CacCore cac_; 82 | 83 | bool bridge_tracer = true; 84 | std::string testname_ = ""; 85 | std::string bootcode_ = ""; 86 | std::string whisperPath_ = ""; 87 | std::string whisperJsonPath_ = ""; 88 | std::string archChecksExclude_ = ""; 89 | std::string archChecksInstrExclude_ = ""; 90 | 91 | const int k_whisperTimeoutInMilliSeconds = 1000; 92 | 93 | }; 94 | -------------------------------------------------------------------------------- /mon/mon_instr/mon_instr.cc: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mon_instr.h" 8 | 9 | extern "C" void instr_register_intf(std::string name, cMonInstr *intf); 10 | extern "C" void instr_deregister_intf(std::string name); 11 | 12 | 13 | cMonInstr::cMonInstr(std::string name) 14 | : name(name), 15 | bridge(new cBridge(k_NumHarts, k_VLen)) {} 16 | void cMonInstr::initial() { 17 | instr_register_intf(name, this); 18 | parseArgs(); 19 | } 20 | 21 | // Command line options 22 | void cMonInstr::parseArgs() { 23 | s_vpi_vlog_info info; 24 | vpi_get_vlog_info(&info); 25 | 26 | for (int i = 0; i < info.argc; i++) { 27 | std::string arg(info.argv[i]); 28 | 29 | if (arg.find("+dutmon_tracer") == 0) 30 | monTracer = true; 31 | } 32 | } 33 | 34 | void cMonInstr::final() { 35 | instr_deregister_intf(name); 36 | } 37 | 38 | void cMonInstr::monGpr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data) { 39 | rvInstr.gpr.valid = true; 40 | rvInstr.gpr.rd_addr = addr; 41 | rvInstr.gpr.rd_wdata = data; 42 | } 43 | 44 | void cMonInstr::monFpr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data) { 45 | rvInstr.fpr.valid = true; 46 | rvInstr.fpr.frd_addr = addr; 47 | rvInstr.fpr.frd_wdata = data; 48 | } 49 | 50 | void cMonInstr::monVr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t *data) { 51 | rvInstr.vr.valid = true; 52 | rvInstr.vr.vrd_addr = addr; 53 | for (int i = 0; i < k_VLen/64; i++) 54 | rvInstr.vr.vrd_wdata[i] = data[i]; 55 | } 56 | 57 | void cMonInstr::monCsr(int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data) { 58 | sCsr c; 59 | c.valid = true; 60 | c.csr_addr = addr; 61 | c.csr_wdata = data; 62 | rvInstr.csrs.push_back(c); 63 | } 64 | 65 | void cMonInstr::monRetire(int hart, std::uint64_t cycle, std::uint64_t tag, std::uint64_t pc, std::uint64_t opcode, std::uint32_t trap) { 66 | rvInstr.valid = true; 67 | rvInstr.cycle = cycle; 68 | rvInstr.tag = tag; 69 | rvInstr.pc.valid = true; 70 | rvInstr.pc.pc_rdata = pc; 71 | rvInstr.opcode = opcode; 72 | rvInstr.trap = trap; 73 | 74 | if (monTracer) { 75 | display(hart, rvInstr); 76 | } 77 | 78 | bridge->processDutInstrRetire(hart, rvInstr); 79 | 80 | rvInstr.clear(); 81 | } 82 | 83 | void cMonInstr::display(int hart, const sRvInstr &instr) { 84 | if (instr.gpr.valid) 85 | std::cout << "<" << std::dec << instr.cycle << ">" 86 | << " DutGprWr: " 87 | << "[Hart=" << hart << "," 88 | << " Reg=X" << std::dec << instr.gpr.rd_addr << "," 89 | << " Data=0x" << std::hex << instr.gpr.rd_wdata 90 | << "]\n"; 91 | if (instr.fpr.valid) 92 | std::cout << "<" << std::dec << instr.cycle << ">" 93 | << " DutFprWr: " 94 | << "[Hart=" << hart << "," 95 | << " Reg=F" << std::dec << instr.fpr.frd_addr << "," 96 | << " Data=0x" << std::hex << instr.fpr.frd_wdata 97 | << "]\n"; 98 | if (instr.vr.valid) { 99 | std::stringstream regval; 100 | uint64_t val[k_VLen/64] = {0}; 101 | int num_dwords = k_VLen/64; 102 | for (int i = 0; i < num_dwords; i++) { 103 | val[i] = instr.vr.vrd_wdata[i]; 104 | } 105 | regval << std::hex << std::setfill('0') << std::setw(16) << val[num_dwords-1]; 106 | for (int i=num_dwords-2; i>0; i--) { 107 | regval << "_" << std::hex << std::setfill('0') << std::setw(16) << val[i]; 108 | } 109 | regval << "_" << std::hex << std::setfill('0') << std::setw(16) << val[0]; 110 | std::cout << "<" << std::dec << instr.cycle << ">" 111 | << " DutVrWr: " 112 | << "[Hart=" << hart << "," 113 | << " Reg=V" << std::dec << instr.vr.vrd_addr << "," 114 | << " Data=0x" << std::hex << regval.str() 115 | << "]\n"; 116 | } 117 | // Retire 118 | std::cout << "<" << std::dec << instr.cycle << ">" 119 | << " DutRetire: " 120 | << "[Hart=" << hart << "," 121 | << " InstrTag=0x" << std::hex << instr.tag 122 | << " (" << std::dec << (instr.tag>>16) << "," << (instr.tag&0xffff) << ")" << "," 123 | << " PC=0x" << std::hex << instr.pc.pc_rdata << "," 124 | << " Opcode=0x" << std::hex << instr.opcode 125 | << "]\n"; 126 | } 127 | -------------------------------------------------------------------------------- /cac/src/lib/stateIdDef.h: -------------------------------------------------------------------------------- 1 | #ifndef CAC_STATE_ID_DEF_H 2 | #define CAC_STATE_ID_DEF_H 3 | 4 | const unsigned int CAC_STATE_PC_ID = 0; 5 | const unsigned int CAC_STATE_RegX0_ID = 1; 6 | const unsigned int CAC_STATE_RegX1_ID = 2; 7 | const unsigned int CAC_STATE_RegX2_ID = 3; 8 | const unsigned int CAC_STATE_RegX3_ID = 4; 9 | const unsigned int CAC_STATE_RegX4_ID = 5; 10 | const unsigned int CAC_STATE_RegX5_ID = 6; 11 | const unsigned int CAC_STATE_RegX6_ID = 7; 12 | const unsigned int CAC_STATE_RegX7_ID = 8; 13 | const unsigned int CAC_STATE_RegX8_ID = 9; 14 | const unsigned int CAC_STATE_RegX9_ID = 10; 15 | const unsigned int CAC_STATE_RegX10_ID = 11; 16 | const unsigned int CAC_STATE_RegX11_ID = 12; 17 | const unsigned int CAC_STATE_RegX12_ID = 13; 18 | const unsigned int CAC_STATE_RegX13_ID = 14; 19 | const unsigned int CAC_STATE_RegX14_ID = 15; 20 | const unsigned int CAC_STATE_RegX15_ID = 16; 21 | const unsigned int CAC_STATE_RegX16_ID = 17; 22 | const unsigned int CAC_STATE_RegX17_ID = 18; 23 | const unsigned int CAC_STATE_RegX18_ID = 19; 24 | const unsigned int CAC_STATE_RegX19_ID = 20; 25 | const unsigned int CAC_STATE_RegX20_ID = 21; 26 | const unsigned int CAC_STATE_RegX21_ID = 22; 27 | const unsigned int CAC_STATE_RegX22_ID = 23; 28 | const unsigned int CAC_STATE_RegX23_ID = 24; 29 | const unsigned int CAC_STATE_RegX24_ID = 25; 30 | const unsigned int CAC_STATE_RegX25_ID = 26; 31 | const unsigned int CAC_STATE_RegX26_ID = 27; 32 | const unsigned int CAC_STATE_RegX27_ID = 28; 33 | const unsigned int CAC_STATE_RegX28_ID = 29; 34 | const unsigned int CAC_STATE_RegX29_ID = 30; 35 | const unsigned int CAC_STATE_RegX30_ID = 31; 36 | const unsigned int CAC_STATE_RegX31_ID = 32; 37 | const unsigned int CAC_STATE_RegF0_ID = 33; 38 | const unsigned int CAC_STATE_RegF1_ID = 34; 39 | const unsigned int CAC_STATE_RegF2_ID = 35; 40 | const unsigned int CAC_STATE_RegF3_ID = 36; 41 | const unsigned int CAC_STATE_RegF4_ID = 37; 42 | const unsigned int CAC_STATE_RegF5_ID = 38; 43 | const unsigned int CAC_STATE_RegF6_ID = 39; 44 | const unsigned int CAC_STATE_RegF7_ID = 40; 45 | const unsigned int CAC_STATE_RegF8_ID = 41; 46 | const unsigned int CAC_STATE_RegF9_ID = 42; 47 | const unsigned int CAC_STATE_RegF10_ID = 43; 48 | const unsigned int CAC_STATE_RegF11_ID = 44; 49 | const unsigned int CAC_STATE_RegF12_ID = 45; 50 | const unsigned int CAC_STATE_RegF13_ID = 46; 51 | const unsigned int CAC_STATE_RegF14_ID = 47; 52 | const unsigned int CAC_STATE_RegF15_ID = 48; 53 | const unsigned int CAC_STATE_RegF16_ID = 49; 54 | const unsigned int CAC_STATE_RegF17_ID = 50; 55 | const unsigned int CAC_STATE_RegF18_ID = 51; 56 | const unsigned int CAC_STATE_RegF19_ID = 52; 57 | const unsigned int CAC_STATE_RegF20_ID = 53; 58 | const unsigned int CAC_STATE_RegF21_ID = 54; 59 | const unsigned int CAC_STATE_RegF22_ID = 55; 60 | const unsigned int CAC_STATE_RegF23_ID = 56; 61 | const unsigned int CAC_STATE_RegF24_ID = 57; 62 | const unsigned int CAC_STATE_RegF25_ID = 58; 63 | const unsigned int CAC_STATE_RegF26_ID = 59; 64 | const unsigned int CAC_STATE_RegF27_ID = 60; 65 | const unsigned int CAC_STATE_RegF28_ID = 61; 66 | const unsigned int CAC_STATE_RegF29_ID = 62; 67 | const unsigned int CAC_STATE_RegF30_ID = 63; 68 | const unsigned int CAC_STATE_RegF31_ID = 64; 69 | const unsigned int CAC_STATE_Instruction_ID = 65; 70 | const unsigned int CAC_STATE_RegV0_ID = 66; 71 | const unsigned int CAC_STATE_RegV1_ID = 67; 72 | const unsigned int CAC_STATE_RegV2_ID = 68; 73 | const unsigned int CAC_STATE_RegV3_ID = 69; 74 | const unsigned int CAC_STATE_RegV4_ID = 70; 75 | const unsigned int CAC_STATE_RegV5_ID = 71; 76 | const unsigned int CAC_STATE_RegV6_ID = 72; 77 | const unsigned int CAC_STATE_RegV7_ID = 73; 78 | const unsigned int CAC_STATE_RegV8_ID = 74; 79 | const unsigned int CAC_STATE_RegV9_ID = 75; 80 | const unsigned int CAC_STATE_RegV10_ID = 76; 81 | const unsigned int CAC_STATE_RegV11_ID = 77; 82 | const unsigned int CAC_STATE_RegV12_ID = 78; 83 | const unsigned int CAC_STATE_RegV13_ID = 79; 84 | const unsigned int CAC_STATE_RegV14_ID = 80; 85 | const unsigned int CAC_STATE_RegV15_ID = 81; 86 | const unsigned int CAC_STATE_RegV16_ID = 82; 87 | const unsigned int CAC_STATE_RegV17_ID = 83; 88 | const unsigned int CAC_STATE_RegV18_ID = 84; 89 | const unsigned int CAC_STATE_RegV19_ID = 85; 90 | const unsigned int CAC_STATE_RegV20_ID = 86; 91 | const unsigned int CAC_STATE_RegV21_ID = 87; 92 | const unsigned int CAC_STATE_RegV22_ID = 88; 93 | const unsigned int CAC_STATE_RegV23_ID = 89; 94 | const unsigned int CAC_STATE_RegV24_ID = 90; 95 | const unsigned int CAC_STATE_RegV25_ID = 91; 96 | const unsigned int CAC_STATE_RegV26_ID = 92; 97 | const unsigned int CAC_STATE_RegV27_ID = 93; 98 | const unsigned int CAC_STATE_RegV28_ID = 94; 99 | const unsigned int CAC_STATE_RegV29_ID = 95; 100 | const unsigned int CAC_STATE_RegV30_ID = 96; 101 | const unsigned int CAC_STATE_RegV31_ID = 97; 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cosim-arch-checker 2 | 3 | Framework to perform DUT vs ISS (Whisper) lockstep architectural checks 4 | 5 | ## Overview 6 | This repository contains the verification collateral needed to interface with a RISCV CPU core and perform lockstep architectural checks against the [Whisper](https://github.com/tenstorrent/whisper) RISCV CPU ISS. 7 | 8 | The main checks currently enabled are 9 | - Integer register checks 10 | - FP register checks 11 | - Vector register checks 12 | 13 | This has been verified using the [Boom core with Ocelot vector unit](https://github.com/tenstorrent/riscv-ocelot) inside [Chipyard](https://github.com/tenstorrent/chipyard) environment. 14 | 15 | ![](docs/images/boom_cosim.png) 16 | 17 | The main components involved here are 18 | - DUT DPI interface 19 | - Send CPU arch state with SV to C++ function calls 20 | - Whisper API interface 21 | - Step on instruction retire 22 | - Receive CPU arch state changes relative to previous step 23 | - Bridge 24 | - Orchestrate DUT vs ISS arch state collection 25 | - Send DUT vs ISS arch state to CAC 26 | - CAC (Core Arch Checker) 27 | - Compare DUT vs ISS arch state 28 | 29 | ## Directory Structure 30 | 31 | ``` 32 | |-- bin 33 | |-- env 34 | |-- mon 35 | | `-- mon_instr 36 | | |-- mon_instr_dpi.cc -- DUT DPI interface 37 | |-- bridge 38 | | `-- whisper 39 | | |-- config 40 | | | `-- ocelot.json -- Whisper config JSON 41 | | |-- whisper_client.cpp -- Whisper API interface 42 | | `-- whisper_client.h 43 | |-- cac 44 | |-- README.md 45 | ``` 46 | 47 | ## Usage 48 | To use the DV collateral on a custom DUT, the following steps need to be followed: 49 | - DUT interface 50 | - Set DUT specific config params in `env/params.h` 51 | - Call the DUT DPI interface functions from tb top or harness 52 | - Whisper API interface 53 | - Add DUT specific config json to `bridge/whisper/config` folder 54 | - Include the build command `bazel build :dpi` in tb build system with these build-time options 55 | - `WHISPER_PATH=` 56 | - `WHISPER_JSON=` 57 | - `TESTFILE=` 58 | - `BOOTCODE=` 59 | - Run the test with this run-time option: `+cosim` 60 | 61 | ### DUT config params 62 | Example: 63 | ``` 64 | const int k_NumHarts = 1; 65 | const int k_XLen = 64; 66 | const int k_VLen = 256; 67 | ``` 68 | 69 | ### DUT DPI interface 70 | ``` 71 | void monitor_gpr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data); 72 | void monitor_fpr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data); 73 | void monitor_vr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t *data); 74 | void monitor_csr(char *name, int hart, std::uint64_t cycle, std::uint32_t addr, std::uint64_t data); 75 | void monitor_retire(char *name, int hart, std::uint64_t cycle, std::uint64_t tag, std::uint64_t pc, std::uint64_t opcode, std::uint32_t trap); 76 | ``` 77 | 78 | ### Whisper config json 79 | Example: 80 | https://github.com/tenstorrent/cosim-arch-checker/blob/main/bridge/whisper/config/ocelot.json 81 | 82 | ## Sample output 83 | From stdout log file: 84 | ``` 85 | Cosim whisper command: /path/to/whisper /path/to/elf /path/to/bootrom --harts 1 --raw --configfile /path/to/json --logfile iss_cosim.log --traceload --server whisper_connect & 86 | Whisper connect succeeded in 60 ms 87 | <27> Whisper Step #0: [Hart=0, InstrTag=0x0, ChangeCount=1, PC=0x10040, Opcode=0x517, auipc x10, 0x0] 88 | <27> Whisper Step #0: [Hart=0, InstrTag=0x0, Resource=r, Addr=0xa, Data=0x10040] 89 | Step: 0 90 | X10 DUT:[Data:0000000000010040] 91 | SIM:[Data:0000000000010040] 92 | PC DUT:[Data:0000000000010040] 93 | SIM:[Data:0000000000010040] 94 | <33> Whisper Step #1: [Hart=0, InstrTag=0x1, ChangeCount=1, PC=0x10044, Opcode=0xfc050513, addi x10, x10, -64] 95 | <33> Whisper Step #1: [Hart=0, InstrTag=0x1, Resource=r, Addr=0xa, Data=0x10000] 96 | Step: 1 97 | X10 DUT:[Data:0000000000010000] 98 | SIM:[Data:0000000000010000] 99 | PC DUT:[Data:0000000000010044] 100 | SIM:[Data:0000000000010044] 101 | ``` 102 | 103 | ## Integration with Boom core with Ocelot vector in Chipyard 104 | 105 | Chipyard repo: https://github.com/tenstorrent/chipyard 106 | 107 | ### Build 108 | ``` 109 | bazel build :dpi --copt=-DCONFIG=MediumBoomVecConfig 110 | 111 | # The DUT params in params.h are set based on the CONFIG option 112 | ``` 113 | 114 | ### Run 115 | ``` 116 | make -C sims/vcs/ run-binary-debug-hex CONFIG=MediumBoomVecConfig BINARY=/path/to/elf SIM_FLAGS="+cosim" 117 | 118 | # Optional runtime options 119 | # +harness_tracer (default: OFF) 120 | # +dutmon_tracer (default: OFF) 121 | # +bridge_tracer (default: ON) 122 | ``` 123 | -------------------------------------------------------------------------------- /cac/src/info.cxx: -------------------------------------------------------------------------------- 1 | #include "info.h" 2 | #include 3 | #include 4 | #include 5 | 6 | //Info 7 | Info::Info(threadT tid, stateIdT stateId, const std::string &type, unitDataT * item, unsigned int size):threadId(tid),stateId(stateId),infoType(type),item(item),size(size){ 8 | itemName = supportStatesSymbol[stateId]; 9 | std::stringstream tmpStream; 10 | if (size == VEC_128) { 11 | tmpStream< InfoCol::getInfoDict(){ 57 | return(infoDict); 58 | }; 59 | 60 | void InfoCol::outputStates(InfoCol *infoColIns){ 61 | std::unordered_map infoDictIns = infoColIns->getInfoDict(); 62 | for(auto & infoIt : infoDict){ 63 | int width = 48; 64 | if (infoIt.first.substr(0,1) == "V") { 65 | if (infoIt.second.getSize() == VEC_128) { 66 | width = 71; 67 | } else if (infoIt.second.getSize() == VEC_256) { 68 | width = 105; 69 | } else if (infoIt.second.getSize() == VEC_512) { 70 | width = 173; 71 | } 72 | } 73 | std::cout< infoDutList; 92 | recorderDutCol.insert_or_assign(tid, infoDutList); 93 | std::vector infoSimList; 94 | recorderSimCol.insert_or_assign(tid, infoSimList); 95 | } 96 | }; 97 | 98 | void Record::addInfo(threadT tid, bool ifdut, Info &info){ 99 | if (ifdut == true){ 100 | recorderDutCol.at(tid).back().gatherInfo(info); 101 | }else{ 102 | recorderSimCol.at(tid).back().gatherInfo(info); 103 | } 104 | }; 105 | 106 | void Record::addInfoCol(threadT tid, bool ifdut, InfoCol &col){ 107 | if (ifdut == true){ 108 | recorderDutCol.at(tid).push_back(col); 109 | }else{ 110 | recorderSimCol.at(tid).push_back(col); 111 | } 112 | }; 113 | 114 | InfoCol Record::getInfoColByStep(threadT tid, bool ifdut, int stepN){ 115 | if (ifdut == true){ 116 | return(recorderDutCol.at(tid).at(stepN)); 117 | }else{ 118 | return(recorderSimCol.at(tid).at(stepN)); 119 | } 120 | }; 121 | -------------------------------------------------------------------------------- /cac/README.md: -------------------------------------------------------------------------------- 1 | # CoreArchChecker 2 | ## The Core Architectural Checker 3 | 4 | [![Build Status](https://travis-ci.org/joemccann/dillinger.svg?branch=master)](https://yyz-gitlab.local.tenstorrent.com/chuang/CoreArchChecker) 5 | 6 | CoreArchChecker is a framework to check CPU DUT's registers and memory against an architectural simulator (Whisper) in lock step. After each instruction retires or event gets triggered, the DUT and simulator's state is collected. CoreArchChecker maintains a snapshot of the current register states for both DUT and simulator separately, updating the register snapshot values after each step. If there is a mismatch in the state after the step, an error will return to bridge and the test will end. CoreArchChecker is also designed to provide memory sycchronization features to enable mutli-threaded run with memory sharing. 7 | ## Build CoreArchChecker 8 | Build the CoreArchChecker based on Bazel 9 | 10 | ```sh 11 | cd CoreArchChecker 12 | bazel build //src:caccore 13 | # bazel-out/darwin-fastbuild/bin/src/libcaccore.so 14 | ``` 15 | 16 | ## Supported API 17 | ```sh 18 | // Constructor 19 | CacCore(threadT tNum); 20 | // Dut API to update Register 21 | void updateRegister(threadT threadId, stateIdT id, unitDataT * data); 22 | // Simulator API to update Register 23 | void updateRefRegister(threadT threadId, stateIdT id, unitDataT * data); 24 | // make a lock step 25 | void step(threadT threadId); 26 | // get if mismatch 27 | bool getStatus(threadT threadId); 28 | ``` 29 | 30 | ## Example in Unit test 31 | ```sh 32 | threadT coreNum = 1; 33 | //instantiate CAC by core num 34 | CacCore cac(coreNum); 35 | threadT tid0 = 0; 36 | // Every step should match 37 | size8BytesT PCValue0 [] = {0xcafe0000}; 38 | size8BytesT RegXXValue0 [] = {0xbeefbeef}; 39 | size8BytesT PCValue1 [] = {0xcafe0008}; 40 | size8BytesT RegXXValue1 [] = {0x0}; 41 | size8BytesT PCValue2 [] = {0xcafe0010}; 42 | size8BytesT RegXXValue2 [] = {0xdeadbeef}; 43 | size8BytesT PCValue3 [] = {0xcafe0018}; 44 | size8BytesT RegXXValue3 [] = {0xabcdefffffffff}; 45 | // step 1 46 | //From Simulator: 47 | cac.updateRefRegister(tid0, CAC_STATE_PC_ID, PCValue0); 48 | cac.updateRefRegister(tid0, CAC_STATE_RegX0_ID, RegXXValue0); 49 | //From DUT 50 | cac.updateRegister(tid0, CAC_STATE_PC_ID, PCValue0); 51 | cac.updateRegister(tid0, CAC_STATE_RegX0_ID, RegXXValue0); 52 | //Single Step 53 | cac.step(tid0); 54 | EXPECT_TRUE(cac.getStatus(tid0)); 55 | // step 2 56 | //From Simulator: 57 | cac.updateRefRegister(tid0, CAC_STATE_PC_ID, PCValue1); 58 | cac.updateRefRegister(tid0, CAC_STATE_RegX0_ID, RegXXValue1); 59 | cac.updateRefRegister(tid0, CAC_STATE_RegX1_ID, RegXXValue0); 60 | cac.updateRefRegister(tid0, CAC_STATE_RegX11_ID, RegXXValue3); 61 | //From DUT 62 | cac.updateRegister(tid0, CAC_STATE_PC_ID, PCValue1); 63 | cac.updateRegister(tid0, CAC_STATE_RegX1_ID, RegXXValue0); 64 | cac.updateRegister(tid0, CAC_STATE_RegX11_ID, RegXXValue3); 65 | cac.updateRegister(tid0, CAC_STATE_RegX0_ID, RegXXValue1); 66 | //Single Step 67 | cac.step(tid0); 68 | EXPECT_TRUE(cac.getStatus(tid0)); 69 | // step 3 70 | //From Simulator: 71 | cac.updateRefRegister(tid0, CAC_STATE_PC_ID, PCValue2); 72 | cac.updateRefRegister(tid0, CAC_STATE_RegX0_ID, RegXXValue0); 73 | cac.updateRefRegister(tid0, CAC_STATE_RegX1_ID, RegXXValue2); 74 | //From DUT 75 | cac.updateRegister(tid0, CAC_STATE_PC_ID, PCValue3); 76 | cac.updateRegister(tid0, CAC_STATE_RegX1_ID, RegXXValue2); 77 | cac.updateRegister(tid0, CAC_STATE_RegX0_ID, RegXXValue0); 78 | //Single Step 79 | cac.step(tid0); 80 | EXPECT_FALSE(cac.getStatus(tid0)); 81 | ``` 82 | 83 | ## Result of Unit test 84 | ```sh 85 | Step: 0 86 | PC DUT:[Data:00000000cafe0000] 87 | SIM:[Data:00000000cafe0000] 88 | X0 DUT:[Data:00000000beefbeef] 89 | SIM:[Data:00000000beefbeef] 90 | Step: 1 91 | PC DUT:[Data:00000000cafe0008] 92 | SIM:[Data:00000000cafe0008] 93 | X0 DUT:[Data:0000000000000000] 94 | SIM:[Data:0000000000000000] 95 | X1 DUT:[Data:00000000beefbeef] 96 | SIM:[Data:00000000beefbeef] 97 | Register Mismatch 98 | Step: 2 99 | PC DUT:[Data:00000000cafe0018] 100 | SIM:[Data:00000000cafe0010] 101 | X0 DUT:[Data:00000000beefbeef] 102 | SIM:[Data:00000000beefbeef] 103 | X1 DUT:[Data:00000000deadbeef] 104 | SIM:[Data:00000000deadbeef] 105 | 106 | ``` 107 | 108 | ## Type definition 109 | ```sh 110 | typedef unsigned char size1ByteT; 111 | typedef unsigned short int size2BytesT; 112 | typedef unsigned int size4BytesT; 113 | typedef unsigned long long int size8BytesT; 114 | 115 | typedef size2BytesT threadT; 116 | typedef size2BytesT stateIdT; 117 | typedef size2BytesT sizenBitT; 118 | typedef size8BytesT fuzzMaskT; 119 | typedef size8BytesT unitDataT; 120 | ``` 121 | 122 | ## How to define architectural states to check 123 | In external.h, we define state ID, state size, state reset value and state symbol. 124 | ## Run unit tests 125 | Unit tests are based on google test 126 | 127 | ```sh 128 | cd CoreArchChecker 129 | bazel test //tests:testCacCore 130 | bazel test //tests:basicClassTest 131 | ``` 132 | 133 | -------------------------------------------------------------------------------- /cac/src/cacCore.cxx: -------------------------------------------------------------------------------- 1 | #include "cacCore.h" 2 | #include 3 | #include 4 | #include 5 | 6 | // CacCore 7 | CacCore::CacCore(threadT tNum):threadNum(tNum){ 8 | record = new Record(threadNum); 9 | for(threadT tid = 0; tid ckBuff; 13 | checkingBuffer.insert_or_assign(tid, ckBuff); 14 | stepCount.insert_or_assign(tid, 0); 15 | dutChangeCount.insert_or_assign(tid, 0); 16 | simChangeCount.insert_or_assign(tid, 0); 17 | status.insert_or_assign(tid, true); 18 | 19 | InfoCol dutInfoColIns(tid, stepCount.at(tid), "DUT"); 20 | record->addInfoCol(tid, true, dutInfoColIns); 21 | InfoCol simInfoColIns(tid, stepCount.at(tid), "SIM"); 22 | record->addInfoCol(tid, false, simInfoColIns); 23 | } 24 | }; 25 | 26 | std::string CacCore::getHello(){ 27 | return("CacCore has been constructed!"); 28 | } 29 | 30 | int CacCore::getStep(threadT threadId){ 31 | return(stepCount.at(threadId)); 32 | }; 33 | 34 | // get if mismatch 35 | bool CacCore::getStatus(threadT threadId){ 36 | return(status.at(threadId)); 37 | }; 38 | 39 | void CacCore::resetStatus(threadT threadId){ 40 | status.at(threadId) = true; 41 | }; 42 | 43 | // Configuration API 44 | void CacCore::configureVlen(unsigned int vlen) { 45 | cfg_vlen = vlen; 46 | for(threadT tid = 0; tid= CAC_STATE_RegV0_ID && id <= CAC_STATE_RegV31_ID) { 53 | return cfg_vlen; 54 | } else { 55 | return supportStatesSize[id]; 56 | } 57 | } 58 | 59 | // Simulator API to update Register 60 | void CacCore::updateRefRegister(threadT threadId, unsigned int typeEncoding, unsigned int typeOffset, unitDataT * data){ 61 | stateIdT id = generateStateId(typeEncoding, typeOffset); 62 | registerSnapshot.at(threadId).updateValue(id, data); 63 | Info infoIns(threadId, id, "SIM", data, getRegisterSize(id)); 64 | record->addInfo(threadId, false, infoIns); 65 | simChangeCount.at(threadId) = simChangeCount.at(threadId) + 1; 66 | }; 67 | void CacCore::updateRefRegister(threadT threadId, stateIdT id, unitDataT * data){ 68 | registerSnapshot.at(threadId).updateValue(id, data); 69 | Info infoIns(threadId, id, "SIM", data, getRegisterSize(id)); 70 | record->addInfo(threadId, false, infoIns); 71 | simChangeCount.at(threadId) = simChangeCount.at(threadId) + 1; 72 | }; 73 | 74 | 75 | // Dut API to update Register 76 | void CacCore::updateRegister(threadT threadId, unsigned int typeEncoding, unsigned int typeOffset, unitDataT * data){ 77 | stateIdT id = generateStateId(typeEncoding, typeOffset); 78 | Info infoIns(threadId, id, "DUT", data, getRegisterSize(id)); 79 | record->addInfo(threadId, true, infoIns); 80 | Register reg(threadId, id, getRegisterSize(id), data); 81 | checkingBuffer.at(threadId).push_back(reg); 82 | dutChangeCount.at(threadId) = dutChangeCount.at(threadId) + 1; 83 | }; 84 | void CacCore::updateRegister(threadT threadId, stateIdT id, unitDataT * data){ 85 | Info infoIns(threadId, id, "DUT", data, getRegisterSize(id)); 86 | record->addInfo(threadId, true, infoIns); 87 | Register reg(threadId, id, getRegisterSize(id), data); 88 | checkingBuffer.at(threadId).push_back(reg); 89 | dutChangeCount.at(threadId) = dutChangeCount.at(threadId) + 1; 90 | }; 91 | 92 | 93 | 94 | bool CacCore::checkRegister(threadT threadId, stateIdT id, unitDataT * data){ 95 | return(registerSnapshot.at(threadId).checkValue(id, data)); 96 | }; 97 | 98 | // make a lock step 99 | void CacCore::step(threadT threadId){ 100 | // print changecount mismatch as warning 101 | // Updates with same previous values are allowed, so not flagging as error 102 | // Updates with different values will show up as errors downstream 103 | if (dutChangeCount.at(threadId) != simChangeCount.at(threadId)) { 104 | std::cout<<"\nWarning: ChangeCount Mismatch" 105 | <<" DUT: "< buffer = checkingBuffer.at(threadId); 110 | for (std::vector::iterator it = buffer.begin(); it != buffer.end(); ++it) { 111 | std::vector reg = it->getValue(); 112 | unitDataT *dat = reg.data(); 113 | bool ckRst; 114 | ckRst = checkRegister(threadId, it->getRegisterId(), dat); 115 | status.at(threadId) = status.at(threadId) && ckRst; 116 | } 117 | //print out 118 | if (status.at(threadId) == false){ 119 | std::cout<<"\nRegister Mismatch"<getInfoColByStep(threadId, true, stepCount.at(threadId)); 123 | InfoCol simInfoColDebug = record->getInfoColByStep(threadId, false, stepCount.at(threadId)); 124 | dutInfoColDebug.outputStates(&simInfoColDebug); 125 | 126 | stepCount.at(threadId) = stepCount.at(threadId) + 1; 127 | checkingBuffer.at(threadId).clear(); 128 | dutChangeCount.insert_or_assign(threadId, 0); 129 | simChangeCount.insert_or_assign(threadId, 0); 130 | 131 | InfoCol dutInfoColIns(threadId, stepCount.at(threadId), "DUT"); 132 | record->addInfoCol(threadId, true, dutInfoColIns); 133 | InfoCol simInfoColIns(threadId, stepCount.at(threadId), "SIM"); 134 | record->addInfoCol(threadId, false, simInfoColIns); 135 | }; 136 | 137 | // Generate State Id by type encoding and offset 138 | // 0:RT_FIX, 1:RT_FLT, 2:RT_X, 3: RT_PAS 139 | // GPR, FPR, CSR, Vec, PC 140 | stateIdT CacCore::generateStateId(unsigned int typeEncoding, unsigned int typeOffset){ 141 | if (typeEncoding == REGISTER_RT_FIX_ENCODING){ 142 | return(CAC_STATE_RegX0_ID + typeOffset); 143 | } else if (typeEncoding == REGISTER_RT_FLT_ENCODING) { 144 | return(CAC_STATE_RegF0_ID + typeOffset); 145 | } else if (typeEncoding == REGISTER_RT_VEC_ENCODING) { 146 | return(CAC_STATE_RegV0_ID + typeOffset); 147 | }else{ 148 | std::cout<<"\nError: Unknown register type encoding"< supportStatesResetValue = { 312 | // {CBOARD_STATE_PC_ID, RST_8_BYTE_VALUE}, 313 | // {CBOARD_STATE_RegX0_ID, RST_8_BYTE_VALUE}, 314 | // {CBOARD_STATE_RegX1_ID, RST_8_BYTE_VALUE}, 315 | // {CBOARD_STATE_RegX2_ID, RST_8_BYTE_VALUE}, 316 | // {CBOARD_STATE_RegX3_ID, RST_8_BYTE_VALUE}, 317 | // {CBOARD_STATE_RegX4_ID, RST_8_BYTE_VALUE}, 318 | // {CBOARD_STATE_RegX5_ID, RST_8_BYTE_VALUE}, 319 | // {CBOARD_STATE_RegX6_ID, RST_8_BYTE_VALUE}, 320 | // {CBOARD_STATE_RegX7_ID, RST_8_BYTE_VALUE}, 321 | // {CBOARD_STATE_RegX8_ID, RST_8_BYTE_VALUE}, 322 | // {CBOARD_STATE_RegX9_ID, RST_8_BYTE_VALUE}, 323 | //} 324 | 325 | #endif 326 | -------------------------------------------------------------------------------- /bridge/bridge.cc: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #include "bridge.h" 4 | 5 | #include // stringstream 6 | #include // cout 7 | #include // std::this_thread::sleep_for 8 | #include // std::chrono::seconds 9 | #include // strlen 10 | #include // system 11 | 12 | // Constructor 13 | cBridge::cBridge(int numHarts, int vLen) 14 | : numHarts_(numHarts), 15 | vLen_(vLen), 16 | cac_(CacCore(numHarts)) 17 | { 18 | cac_.configureVlen(vLen_); 19 | parseArgs(); 20 | connectWhisper(); 21 | } 22 | 23 | // Destructor 24 | cBridge::~cBridge() { 25 | disconnectWhisper(); 26 | } 27 | 28 | // Command line options 29 | void cBridge::parseArgs() { 30 | s_vpi_vlog_info info; 31 | vpi_get_vlog_info(&info); 32 | 33 | for (int i = 0; i < info.argc; i++) { 34 | std::string arg(info.argv[i]); 35 | 36 | std::cout << "Arg: " << arg << "\n"; 37 | if (arg.find("+bridge_tracer") == 0) 38 | bridge_tracer = true; 39 | if (arg.find("+testfile=") == 0) 40 | testname_ = arg.substr(strlen("+testfile=")); 41 | if (arg.find("+bootcode=") == 0) 42 | bootcode_ = arg.substr(strlen("+bootcode=")); 43 | if (arg.find("+whisper_path=") == 0) 44 | whisperPath_ = arg.substr(strlen("+whisper_path=")); 45 | if (arg.find("+whisper_json_path=") == 0) 46 | whisperJsonPath_ = arg.substr(strlen("+whisper_json_path=")); 47 | if (arg.find("+arch_checks_exclude") == 0) 48 | archChecksExclude_ = arg.substr(strlen("+arch_checks_exclude=")); 49 | if (arg.find("+arch_checks_instr_exclude") == 0) 50 | archChecksInstrExclude_ = arg.substr(strlen("+arch_checks_instr_exclude=")); 51 | } 52 | } 53 | 54 | // Whisper command options 55 | std::string cBridge::getWhisperCmd(std::string testname_) { 56 | std::string cmd = whisperPath_ + " " + testname_ + " " + bootcode_ + 57 | " --harts " + std::to_string(numHarts_) + 58 | " --raw --configfile " + whisperJsonPath_ + 59 | " --logfile iss_cosim.log --traceload" + 60 | " --commandlog isscmd.log" + 61 | " --server whisper_connect &"; 62 | 63 | return cmd; 64 | } 65 | 66 | // Whisper connect 67 | void cBridge::connectWhisper() { 68 | std::string cmd = getWhisperCmd(testname_); 69 | std::cout << "Cosim whisper command: " << cmd << "\n"; 70 | system(cmd.c_str()); 71 | 72 | auto start = std::chrono::high_resolution_clock::now(); 73 | while (true) { 74 | std::this_thread::sleep_for (std::chrono::milliseconds(30)); 75 | auto end = std::chrono::high_resolution_clock::now(); 76 | auto duration = std::chrono::duration_cast(end - start).count(); 77 | if (whisperConnect("whisper_connect") >= 0) { 78 | std::cout << "Whisper connect succeeded in " << duration << " ms\n"; 79 | break; 80 | } 81 | else if (duration > k_whisperTimeoutInMilliSeconds) { 82 | std::cout << "Whisper connect failed. Stopping after " << duration << " ms.\n"; 83 | break; 84 | } 85 | } 86 | } 87 | 88 | // Whisper disconnect 89 | void cBridge::disconnectWhisper() { 90 | whisperDisconnect(); 91 | } 92 | 93 | // DUT Interface APIs 94 | // Process instruction called on retire 95 | void cBridge::processDutInstrRetire(int hart, sRvInstr &dutInstr) { 96 | // Push DUT state to CAC 97 | updateCac(hart, dutInstr); 98 | 99 | // Get whisper state and push to CAC 100 | sWhisperState whisInstr; 101 | stepWhisper(hart, dutInstr.cycle, dutInstr.tag, whisInstr); 102 | updateCac(hart, dutInstr.cycle, dutInstr.tag, whisInstr); 103 | 104 | // Check DUT vs whisper state 105 | // except when asked not to by user 106 | cac_.step(hart); 107 | if (disChecks(whisInstr)) { 108 | pokeWhisper(hart, dutInstr); 109 | cac_.resetStatus(hart); 110 | } 111 | if (!cac_.getStatus(hart)){ 112 | std::cout << "\nError: Core Arch Checker Mismatch\n"; 113 | vpi_control(vpiFinish); 114 | } 115 | } 116 | 117 | // Get whisper instruction state 118 | void cBridge::stepWhisper(int hart, uint64_t cycle, uint64_t tag, sWhisperState &whisInstr) { 119 | 120 | bool success = whisperStep(hart, cycle, tag, whisInstr.pc, whisInstr.opcode, whisInstr.changeCount, 121 | whisInstr.buffer, whisInstr.bufferSize, whisInstr.privMode, whisInstr.fpFlags, whisInstr.trap); 122 | if (!success) { 123 | std::cout << "Error: whisperStep failed at hart=" << hart << " step=" << cac_.getStep(hart) << "\n"; 124 | } 125 | if (bridge_tracer) { 126 | std::cout << "<" << std::dec << cycle << ">" 127 | << " Whisper Step #" << cac_.getStep(hart) << ": " 128 | << "[Hart=" << hart << "," 129 | << " InstrTag=0x" << std::hex << tag << "," 130 | << " ChangeCount=" << std::dec << whisInstr.changeCount << "," 131 | << " PC=0x" << std::hex << whisInstr.pc << "," 132 | << " Opcode=0x" << std::hex << whisInstr.opcode << "," 133 | << " " << whisInstr.buffer 134 | << "]\n"; 135 | } 136 | 137 | // Hack to step whisper an extra time on wfi to synch with RTL jump to handler 138 | std::string disasm(whisInstr.buffer, whisInstr.bufferSize); 139 | if (disasm.find("wfi") != std::string::npos) { 140 | success = whisperStep(hart, cycle, tag, whisInstr.pc, whisInstr.opcode, whisInstr.changeCount, 141 | whisInstr.buffer, whisInstr.bufferSize, whisInstr.privMode, whisInstr.fpFlags, whisInstr.trap); 142 | if (bridge_tracer) 143 | std::cout << "<" << std::dec << cycle << ">" 144 | << " Whisper Step #" << cac_.getStep(hart) << ": Extra step due to wfi" << "\n"; 145 | } 146 | } 147 | 148 | // Push DUT state to CAC 149 | void cBridge::updateCac(int hart, const sRvInstr &dutInstr) { 150 | // PC 151 | updatePc(hart, eSrc::k_Dut, dutInstr.pc.pc_rdata); 152 | // GPR 153 | if (dutInstr.gpr.valid) { 154 | size8BytesT dwordArray [1] = {dutInstr.gpr.rd_wdata}; 155 | updateRegs(hart, eSrc::k_Dut, eResource::k_IntReg, dutInstr.gpr.rd_addr, dwordArray); 156 | } 157 | // FPR 158 | if (dutInstr.fpr.valid) { 159 | size8BytesT dwordArray [1] = {dutInstr.fpr.frd_wdata}; 160 | updateRegs(hart, eSrc::k_Dut, eResource::k_FpReg, dutInstr.fpr.frd_addr, dwordArray); 161 | } 162 | // VR 163 | if (dutInstr.vr.valid) { 164 | size8BytesT dwordArray [128] = {0}; 165 | for (int i = 0; i< vLen_/64; i++) { 166 | dwordArray[i] = dutInstr.vr.vrd_wdata[i]; 167 | } 168 | updateRegs(hart, eSrc::k_Dut, eResource::k_VecReg, dutInstr.vr.vrd_addr, dwordArray); 169 | } 170 | } 171 | 172 | // Push whisper state to CAC 173 | void cBridge::updateCac(int hart, uint64_t cycle, uint64_t tag, sWhisperState &whisInstr) { 174 | // PC 175 | updatePc(hart, eSrc::k_Whisper, whisInstr.pc); 176 | // Iterate over other changes - r, f, v, 177 | size8BytesT dwordArray [1] = {0}; 178 | size8BytesT dwordVecArray [128] = {0}; 179 | uint32_t entries = vLen_/64; 180 | for (auto i = 0u; i < whisInstr.changeCount; i++) { 181 | bool success = whisperChange(hart, whisInstr.resource, whisInstr.address, whisInstr.value, whisInstr.valid); 182 | if (!success) { 183 | std::cout << "Error: whisperChange failed at hart=" << hart << " step=" << cac_.getStep(hart) << "\n"; 184 | } 185 | if (!whisInstr.valid) { 186 | std::cout << "Error: whisperChange returned invalid entry at hart=" << hart << " step=" << cac_.getStep(hart) << "\n"; 187 | } 188 | if (bridge_tracer) { 189 | std::cout << "<" << std::dec << cycle << ">" 190 | << " Whisper Step #" << cac_.getStep(hart) << ": " 191 | << "[Hart=" << hart << "," 192 | << " InstrTag=0x" << std::hex << tag << "," 193 | << " Resource=" << (char)whisInstr.resource << "," 194 | << " Addr=0x" << std::hex << whisInstr.address << "," 195 | << " Data=0x" << std::hex << whisInstr.value 196 | << "]\n"; 197 | } 198 | 199 | switch(whisInstr.resource) { 200 | case 'r': 201 | dwordArray [0] = whisInstr.value; 202 | updateRegs(hart, eSrc::k_Whisper, eResource::k_IntReg, whisInstr.address, dwordArray); 203 | break; 204 | case 'f': 205 | dwordArray [0] = whisInstr.value; 206 | updateRegs(hart, eSrc::k_Whisper, eResource::k_FpReg, whisInstr.address, dwordArray); 207 | break; 208 | case 'v': 209 | dwordVecArray [i % entries] = whisInstr.value; 210 | if ((i % entries) == (entries - 1)) 211 | updateRegs(hart, eSrc::k_Whisper, eResource::k_VecReg, whisInstr.address, dwordVecArray); 212 | break; 213 | default: 214 | break; 215 | } 216 | } 217 | } 218 | 219 | // Utility functions 220 | void cBridge::updatePc(int hart, eSrc src, uint64_t data) { 221 | size8BytesT dwordArray [1] = {data}; 222 | if (src == eSrc::k_Dut) { 223 | cac_.updateRegister(hart, CAC_STATE_PC_ID, dwordArray); 224 | } else { 225 | cac_.updateRefRegister(hart, CAC_STATE_PC_ID, dwordArray); 226 | } 227 | } 228 | 229 | void cBridge::updateRegs(int hart, eSrc src, eResource resource, uint64_t addr, size8BytesT dwordArray[]) { 230 | if (src == eSrc::k_Dut) { 231 | if ((resource == eResource::k_IntReg) && (addr == 0x0)) 232 | return; 233 | cac_.updateRegister(hart, resource, addr, dwordArray); 234 | } else { 235 | cac_.updateRefRegister(hart, resource, addr, dwordArray); 236 | } 237 | } 238 | 239 | // Skip checks on certain conditions if requested 240 | bool cBridge::disChecks(const sWhisperState &whisInstr) { 241 | if (archChecksInstrExclude_ == "") 242 | return false; 243 | 244 | std::string disasm(whisInstr.buffer, whisInstr.bufferSize); 245 | std::stringstream ss(archChecksInstrExclude_); 246 | 247 | while(ss.good()) { 248 | std::string instr; 249 | std::getline(ss, instr, ',' ); 250 | 251 | if (disasm.find(instr) != std::string::npos) { 252 | return true; 253 | } 254 | } 255 | return false; 256 | } 257 | 258 | // Poke resources in whisper 259 | void cBridge::pokeWhisper(int hart, const sRvInstr &dutInstr) { 260 | bool valid = false; 261 | bool success = false; 262 | if (dutInstr.gpr.valid) 263 | success = whisperPoke(hart, 'r', dutInstr.gpr.rd_addr, dutInstr.gpr.rd_wdata, valid); 264 | if (dutInstr.fpr.valid) 265 | success = whisperPoke(hart, 'f', dutInstr.fpr.frd_addr, dutInstr.fpr.frd_wdata, valid); 266 | // TODO Vector poke 267 | if (!success) { 268 | std::cout << "Error: whisperPoke failed at hart=" << hart << " step=" << cac_.getStep(hart) << "\n"; 269 | } 270 | if (!valid) { 271 | std::cout << "Error: whisperPoke returned invalid entry at hart=" << hart << " step=" << cac_.getStep(hart) << "\n"; 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /LICENSE.TT: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2022 Tenstorrent, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /bridge/whisper/whisper_client.cpp: -------------------------------------------------------------------------------- 1 | // Licensed under the Apache License, Version 2.0, see LICENSE.TT for details 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "svdpi.h" 11 | #include "WhisperMessage.h" 12 | 13 | 14 | static int whisperSoc = -1; 15 | 16 | 17 | // Connect to the whisper process running at the given host and 18 | // listening to the given port. Return non-negative connected socket 19 | // number on success and -1 on failure. 20 | extern "C" 21 | int 22 | whisperConnectHostPort(const char* host, unsigned port) 23 | { 24 | if (not host or not *host) 25 | { 26 | std::cerr << "Error: whisperConnectHostPort: Null host name\n"; 27 | return -1; 28 | } 29 | 30 | // 1. Create socket. 31 | int soc = socket(AF_INET, SOCK_STREAM, 0); 32 | if (soc < 0) 33 | { 34 | char buffer[512]; 35 | if (!strerror_r(errno, buffer, sizeof(buffer))) 36 | { 37 | char *p = buffer; 38 | std::cerr << "Failed to create socket: " << p << '\n'; 39 | return -1; 40 | } 41 | } 42 | 43 | // 2. Obtain host IP address. 44 | struct hostent* server = gethostbyname("localhost"); 45 | if (not server) 46 | { 47 | std::cerr << "Failed to find IP address of host " << host << '\n'; 48 | return -1; 49 | } 50 | 51 | // 3. Setup socket address (host address + port) 52 | struct sockaddr_in serverAddr; 53 | serverAddr.sin_family = AF_INET; 54 | serverAddr.sin_port = htons(port); 55 | bcopy(server->h_addr, &serverAddr.sin_addr.s_addr, server->h_length); 56 | 57 | // 4. Connect socket to socket address. 58 | if (connect(soc, (struct sockaddr*) &serverAddr, sizeof(serverAddr)) < 0) 59 | { 60 | std::cerr << "Socket connection failed\n"; 61 | return -1; 62 | } 63 | 64 | return soc; 65 | } 66 | 67 | 68 | // Connect to the whisper process defined by the given file. File 69 | // should contain a single line consisting of a host name followed by 70 | // a port number. Example: good-host 1700 71 | // Return non-negative socket number on success and -1 on failure. 72 | extern "C" 73 | int 74 | whisperConnect(const char* filePath) 75 | { 76 | if (whisperSoc >= 0) 77 | return whisperSoc; 78 | 79 | if (not filePath or not *filePath) 80 | { 81 | std::cerr << "Error: whisperConnect: Null file path\n"; 82 | return -1; 83 | } 84 | 85 | std::ifstream ifs(filePath); 86 | if (not ifs) 87 | { 88 | std::cerr << "Failed to open host-info file " << filePath << "\n"; 89 | return -1; 90 | } 91 | 92 | std::string hostName; 93 | unsigned port = -1; 94 | ifs >> hostName >> port; 95 | if (not ifs.good()) 96 | { 97 | std::cerr << "Failed to read host-name and port-number from file " 98 | << filePath << '\n'; 99 | return -1; 100 | } 101 | 102 | whisperSoc = whisperConnectHostPort(hostName.c_str(), port); 103 | return whisperSoc; 104 | } 105 | 106 | 107 | extern "C" 108 | void 109 | whisperDisconnect() 110 | { 111 | if (whisperSoc >= 0) 112 | close(whisperSoc); 113 | whisperSoc = -1; 114 | } 115 | 116 | 117 | /// Unpack socket message (received in server mode) into the given 118 | /// WhisperMessage object. 119 | static 120 | void 121 | deserializeMessage(const char buffer[], size_t bufferLen, 122 | WhisperMessage& msg) 123 | 124 | { 125 | assert (bufferLen >= sizeof(msg)); 126 | 127 | const char* p = buffer; 128 | uint32_t x = ntohl(* reinterpret_cast (p)); 129 | msg.hart = x; 130 | p += sizeof(x); 131 | 132 | x = ntohl(* reinterpret_cast (p)); 133 | msg.type = x; 134 | p += sizeof(x); 135 | 136 | x = ntohl(* reinterpret_cast (p)); 137 | msg.resource = x; 138 | p += sizeof(x); 139 | 140 | x = ntohl(* reinterpret_cast (p)); 141 | msg.size = x; 142 | p += sizeof(x); 143 | 144 | x = ntohl(* reinterpret_cast (p)); 145 | msg.flags = x; 146 | p += sizeof(x); 147 | 148 | uint32_t part = ntohl(* reinterpret_cast (p)); 149 | msg.instrTag = uint64_t(part) << 32; 150 | p += sizeof(part); 151 | 152 | part = ntohl(* reinterpret_cast (p)); 153 | msg.instrTag |= part; 154 | p += sizeof(part); 155 | 156 | part = ntohl(* reinterpret_cast (p)); 157 | msg.time = uint64_t(part) << 32; 158 | p += sizeof(part); 159 | 160 | part = ntohl(* reinterpret_cast (p)); 161 | msg.time |= part; 162 | p += sizeof(part); 163 | 164 | part = ntohl(* reinterpret_cast (p)); 165 | msg.address = uint64_t(part) << 32; 166 | p += sizeof(part); 167 | 168 | part = ntohl(* reinterpret_cast (p)); 169 | msg.address |= part; 170 | p += sizeof(part); 171 | 172 | part = ntohl(* reinterpret_cast (p)); 173 | msg.value = uint64_t(part) << 32; 174 | p += sizeof(part); 175 | 176 | part = ntohl(* reinterpret_cast (p)); 177 | msg.value |= part; 178 | p += sizeof(part); 179 | 180 | memcpy(msg.buffer, p, sizeof(msg.buffer)); 181 | p += sizeof(msg.buffer); 182 | 183 | memcpy(msg.tag, p, sizeof(msg.tag)); 184 | p += sizeof(msg.tag); 185 | 186 | assert(size_t(p - buffer) <= bufferLen); 187 | } 188 | 189 | 190 | static 191 | size_t 192 | serializeMessage(const WhisperMessage& msg, char buffer[], 193 | size_t bufferLen) 194 | { 195 | assert (bufferLen >= sizeof(msg)); 196 | 197 | char* p = buffer; 198 | uint32_t x = htonl(msg.hart); 199 | memcpy(p, &x, sizeof(x)); 200 | p += sizeof(x); 201 | 202 | x = htonl(msg.type); 203 | memcpy(p, &x, sizeof(x)); 204 | p += sizeof(x); 205 | 206 | x = htonl(msg.resource); 207 | memcpy(p, &x, sizeof(x)); 208 | p += sizeof(x); 209 | 210 | x = htonl(msg.size); 211 | memcpy(p, &x, sizeof(x)); 212 | p += sizeof(x); 213 | 214 | x = htonl(msg.flags); 215 | memcpy(p, &x, sizeof(x)); 216 | p += sizeof(x); 217 | 218 | uint32_t part = static_cast(msg.instrTag >> 32); 219 | x = htonl(part); 220 | memcpy(p, &x, sizeof(x)); 221 | p += sizeof(x); 222 | 223 | part = (msg.instrTag) & 0xffffffff; 224 | x = htonl(part); 225 | memcpy(p, &x, sizeof(x)); 226 | p += sizeof(x); 227 | 228 | part = static_cast(msg.time >> 32); 229 | x = htonl(part); 230 | memcpy(p, &x, sizeof(x)); 231 | p += sizeof(x); 232 | 233 | part = (msg.time) & 0xffffffff; 234 | x = htonl(part); 235 | memcpy(p, &x, sizeof(x)); 236 | p += sizeof(x); 237 | 238 | part = static_cast(msg.address >> 32); 239 | x = htonl(part); 240 | memcpy(p, &x, sizeof(x)); 241 | p += sizeof(x); 242 | 243 | part = (msg.address) & 0xffffffff; 244 | x = htonl(part); 245 | memcpy(p, &x, sizeof(x)); 246 | p += sizeof(x); 247 | 248 | part = static_cast(msg.value >> 32); 249 | x = htonl(part); 250 | memcpy(p, &x, sizeof(x)); 251 | p += sizeof(x); 252 | 253 | part = msg.value & 0xffffffff; 254 | x = htonl(part); 255 | memcpy(p, &x, sizeof(x)); 256 | p += sizeof(x); 257 | 258 | memcpy(p, msg.buffer, sizeof(msg.buffer)); 259 | p += sizeof(msg.buffer); 260 | 261 | memcpy(p, msg.tag, sizeof(msg.tag)); 262 | p += sizeof(msg.tag); 263 | 264 | size_t len = p - buffer; 265 | assert(len <= bufferLen); 266 | assert(len <= sizeof(msg)); 267 | for (size_t i = len; i < sizeof(msg); ++i) 268 | buffer[i] = 0; 269 | 270 | return sizeof(msg); 271 | } 272 | 273 | 274 | static bool 275 | receiveMessage(int soc, WhisperMessage& msg) 276 | { 277 | char buffer[sizeof(msg)]; 278 | char* p = buffer; 279 | 280 | size_t remain = sizeof(msg); 281 | 282 | while (remain > 0) 283 | { 284 | ssize_t l = recv(soc, p, remain, 0); 285 | if (l < 0) 286 | { 287 | if (errno == EINTR) 288 | continue; 289 | std::cerr << "Failed to receive socket message\n"; 290 | return false; 291 | } 292 | if (l == 0) 293 | { 294 | msg.type = Quit; 295 | return true; 296 | } 297 | remain -= l; 298 | p += l; 299 | } 300 | 301 | deserializeMessage(buffer, sizeof(buffer), msg); 302 | 303 | return true; 304 | } 305 | 306 | 307 | static bool 308 | sendMessage(int soc, const WhisperMessage& msg) 309 | { 310 | char buffer[sizeof(msg)]; 311 | 312 | serializeMessage(msg, buffer, sizeof(buffer)); 313 | 314 | // Send command. 315 | ssize_t remain = sizeof(msg); 316 | char* p = buffer; 317 | while (remain > 0) 318 | { 319 | ssize_t l = send(soc, p, remain , 0); 320 | if (l < 0) 321 | { 322 | if (errno == EINTR) 323 | continue; 324 | std::cerr << "Failed to send socket command\n"; 325 | return false; 326 | } 327 | remain -= l; 328 | p += l; 329 | } 330 | 331 | return true; 332 | } 333 | 334 | 335 | static 336 | bool 337 | whisperCommand(const WhisperMessage& req, WhisperMessage& reply) 338 | { 339 | assert(whisperSoc >= 0); 340 | 341 | if (not sendMessage(whisperSoc, req)) 342 | { 343 | std::cerr << "Failed to send request to whisper\n"; 344 | return false; 345 | } 346 | if (not receiveMessage(whisperSoc, reply)) 347 | { 348 | std::cerr << "Failed to receive reply from whisper\n"; 349 | return false; 350 | } 351 | return true; 352 | } 353 | 354 | 355 | extern "C" 356 | bool 357 | whisperPeek(int hart, char resource, uint64_t addr, uint64_t& value, 358 | bool& valid) 359 | { 360 | WhisperMessage req(hart, WhisperMessageType::Peek, resource, addr); 361 | WhisperMessage reply; 362 | 363 | if (not whisperCommand(req, reply)) 364 | return false; 365 | 366 | valid = reply.type != WhisperMessageType::Invalid; 367 | value = reply.value; 368 | return true; 369 | } 370 | 371 | 372 | // Send a whisper poke command. Retrun true on successful comunication 373 | // and false on failure. Set valid to false if hart/resource/addr 374 | // are invalid. 375 | extern "C" 376 | bool 377 | whisperPoke(int hart, char resource, uint64_t addr, uint64_t value, 378 | bool& valid) 379 | { 380 | WhisperMessage req(hart, WhisperMessageType::Poke, resource, addr, value); 381 | WhisperMessage reply; 382 | 383 | if (not whisperCommand(req, reply)) 384 | return false; 385 | 386 | valid = reply.type != WhisperMessageType::Invalid; 387 | return true; 388 | } 389 | 390 | 391 | extern "C" 392 | bool 393 | whisperStep(int hart, uint64_t time, uint64_t instrTag, uint64_t& pc, 394 | uint32_t& instruction, unsigned& changeCount, 395 | char* buffer, unsigned bufferSize, uint32_t& privMode, 396 | uint32_t& fpFlags, bool& hasTrap) 397 | { 398 | WhisperMessage req(hart, WhisperMessageType::Step); 399 | req.instrTag = instrTag; 400 | req.time = time; 401 | 402 | WhisperMessage reply; 403 | if (not whisperCommand(req, reply)) 404 | return false; 405 | 406 | pc = reply.address; 407 | instruction = reply.resource; 408 | changeCount = reply.value; 409 | 410 | // Recover privilege mode (2 bits), fpFlags (4 bits), and trap (1 411 | // bit) from flags field. 412 | unsigned mode = reply.flags & 3; 413 | unsigned flags = (reply.flags >> 2) & 0xf; 414 | unsigned trap = (reply.flags >> 6) & 1; 415 | 416 | privMode = mode; 417 | fpFlags = flags; 418 | hasTrap = trap; 419 | 420 | unsigned len = sizeof(reply.buffer); 421 | if (len > bufferSize) 422 | len = bufferSize; 423 | if (buffer) 424 | strncpy(buffer, reply.buffer, len); 425 | return true; 426 | } 427 | 428 | // Copied from chuang's LSTB Whisper Client 429 | extern "C" 430 | bool 431 | whisperSimpleStep(int hart, uint64_t& pc, uint32_t& instruction, unsigned& changeCount) 432 | { 433 | WhisperMessage req(hart, WhisperMessageType::Step); 434 | req.instrTag = 0; 435 | req.time = 0; 436 | 437 | WhisperMessage reply; 438 | if (not whisperCommand(req, reply)) 439 | return false; 440 | 441 | pc = reply.address; 442 | instruction = reply.resource; 443 | changeCount = reply.value; 444 | 445 | return true; 446 | } 447 | 448 | extern "C" 449 | bool 450 | whisperChange(int hart, uint32_t& resource, uint64_t& addr, uint64_t& value, 451 | bool& valid) 452 | { 453 | WhisperMessage req(hart, WhisperMessageType::Change); 454 | WhisperMessage reply; 455 | if (not whisperCommand(req, reply)) 456 | return false; 457 | 458 | resource = reply.resource; 459 | addr = reply.address; 460 | value = reply.value; 461 | valid = reply.type != WhisperMessageType::Invalid; 462 | return true; 463 | } 464 | 465 | 466 | extern "C" 467 | bool 468 | whisperMcmRead(int hart, uint64_t time, uint64_t instrTag, uint64_t addr, 469 | unsigned size, uint64_t value, bool internal, bool& valid) 470 | { 471 | WhisperMessage req(hart, WhisperMessageType::McmRead); 472 | req.time = time; 473 | req.instrTag = instrTag; 474 | req.address = addr; 475 | req.value = value; 476 | req.size = size; 477 | req.flags = not internal; 478 | 479 | WhisperMessage reply; 480 | if (not whisperCommand(req, reply)) 481 | return false; 482 | 483 | valid = reply.type != WhisperMessageType::Invalid; 484 | return true; 485 | } 486 | 487 | 488 | extern "C" 489 | bool 490 | whisperMcmInsert(int hart, uint64_t time, uint64_t instrTag, uint64_t addr, 491 | unsigned size, uint64_t value, bool& valid) 492 | { 493 | WhisperMessage req(hart, WhisperMessageType::McmInsert); 494 | req.time = time; 495 | req.instrTag = instrTag; 496 | req.address = addr; 497 | req.value = value; 498 | req.size = size; 499 | 500 | WhisperMessage reply; 501 | if (not whisperCommand(req, reply)) 502 | return false; 503 | 504 | valid = reply.type != WhisperMessageType::Invalid; 505 | return true; 506 | } 507 | 508 | 509 | extern "C" 510 | bool 511 | whisperMcmWrite(int hart, uint64_t time, uint64_t addr, 512 | unsigned size, svOpenArrayHandle handle , bool& valid) 513 | { 514 | WhisperMessage req(hart, WhisperMessageType::McmWrite); 515 | req.time = time; 516 | req.address = addr; 517 | req.size = size; 518 | if (req.size > sizeof(req.buffer)) 519 | { 520 | std::cerr << "whisperMcmWrite: write size too large: " << req.size << '\n'; 521 | valid = false; 522 | return true; 523 | } 524 | 525 | uint8_t* data = reinterpret_cast (handle); 526 | for (unsigned i = 0; i < size; ++i) 527 | req.buffer[i] = data[i]; 528 | 529 | WhisperMessage reply; 530 | if (not whisperCommand(req, reply)) 531 | return false; 532 | 533 | valid = reply.type != WhisperMessageType::Invalid; 534 | return true; 535 | } 536 | 537 | extern "C" 538 | bool 539 | whisperReset(int hart, bool& valid) 540 | { 541 | WhisperMessage req(hart, WhisperMessageType::Reset); 542 | WhisperMessage reply; 543 | 544 | if (not whisperCommand(req, reply)) 545 | return false; 546 | 547 | valid = reply.type != WhisperMessageType::Invalid; 548 | return true; 549 | } 550 | 551 | extern "C" 552 | bool 553 | whisperQuit() 554 | { 555 | assert(whisperSoc >= 0); 556 | 557 | WhisperMessage req(0 /*hart*/, WhisperMessageType::Quit); // Any hart will do 558 | if (not sendMessage(whisperSoc, req)) 559 | { 560 | std::cerr << "Failed to send request to whisper\n"; 561 | return false; 562 | } 563 | 564 | whisperDisconnect(); 565 | 566 | // There is no reply for quit command. 567 | return true; 568 | } 569 | 570 | 571 | #if 0 572 | 573 | int 574 | main(int argc, char* argv[]) 575 | { 576 | if (argc == 2) 577 | { 578 | std::string path = argv[1]; 579 | int soc = whisperConnect(path); 580 | if (soc >= 0) 581 | { 582 | std::cerr << "Connected to socket: " << soc << '\n'; 583 | uint64_t value = 0; 584 | unsigned hart = 0; 585 | bool valid = false; 586 | whisperPeek(soc, hart, 'r', 1, value, valid); 587 | whisperPeek(soc, hart, 'r', 2, value, valid); 588 | whisperPoke(soc, hart, 'p', 0, 0x1234, valid); 589 | whisperPeek(soc, hart, 'p', 0, value, valid); 590 | 591 | unsigned count = 0; 592 | whisperStep(soc, hart, count); 593 | std::cerr << "Change count: " << std::hex << count << '\n'; 594 | for (unsigned i = 0; i < count; ++i) 595 | { 596 | unsigned resource = 0; 597 | uint64_t addr = 0; 598 | if (whisperChange(soc, hart, resource, addr, value, valid) and valid) 599 | std::cerr << " " << char(resource) << " " << std::hex << addr 600 | << ' ' << std::hex << value << '\n'; 601 | } 602 | whisperQuit(soc); 603 | } 604 | } 605 | return 0; 606 | } 607 | 608 | #endif 609 | -------------------------------------------------------------------------------- /bridge/whisper/svdpi/svdpi.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Copyright (C) 2004 Synopsys, Inc. All Rights Reserved. 4 | * Portions Copyright (C) 2004 Accellera Organization, Inc. 5 | * All Rights Reserved. Used with Permission. 6 | * 7 | * Chronologic VCS (TM) 8 | * 9 | * SystemVerilog 1800 DPI (Direct Programming Interface). 10 | * 11 | * Binary-level compatibility include file "svdpi.h" 12 | * 13 | * Revision: 14 | * as in Annex G of IEEE-Std-1800-SystemVerilog_LRM_2005 15 | * Accellera's Extensions to Verilog (R) 16 | * 17 | * 18 | * This file contains the constant definitions, structure definitions, and 19 | * function declarations used by the SystemVerilog 1800 DPI. 20 | * 21 | * The file should be included with all C functions that use SystemVerilog 22 | * Direct Programming Interface. 23 | * 24 | ****************************************************************************/ 25 | 26 | /* $Revision$ */ 27 | #ifndef INCLUDED_SVDPI 28 | #define INCLUDED_SVDPI 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | /* Ensure that size-critical types are defined on all OS platforms. */ 33 | #if defined (_MSC_VER) 34 | typedef unsigned __int64 uint64_t; 35 | typedef unsigned __int32 uint32_t; 36 | typedef unsigned __int8 uint8_t; 37 | typedef signed __int64 int64_t; 38 | typedef signed __int32 int32_t; 39 | typedef signed __int8 int8_t; 40 | #elif defined(__MINGW32__) 41 | #include 42 | #elif defined(__linux) 43 | #include 44 | #else 45 | #include 46 | #endif 47 | /* Use to export a symbol from application */ 48 | #if defined (_MSC_VER) 49 | #define DPI_DLLISPEC __declspec(dllimport) 50 | #else 51 | #define DPI_DLLISPEC 52 | #endif 53 | /* Use to import a symbol into application */ 54 | #if defined (_MSC_VER) 55 | #define DPI_DLLESPEC __declspec(dllexport) 56 | #else 57 | #define DPI_DLLESPEC 58 | #endif 59 | /* Use to mark a function as external */ 60 | #ifndef DPI_EXTERN 61 | #define DPI_EXTERN 62 | #endif 63 | #ifndef DPI_PROTOTYPES 64 | #define DPI_PROTOTYPES 65 | /* object is defined imported by the application */ 66 | #define XXTERN DPI_EXTERN DPI_DLLISPEC 67 | /* object is exported by the application */ 68 | #define EETERN DPI_EXTERN DPI_DLLESPEC 69 | #endif 70 | /* canonical representation */ 71 | #define sv_0 0 72 | #define sv_1 1 73 | #define sv_z 2 74 | #define sv_x 3 75 | /* common type for 'bit' and 'logic' scalars. */ 76 | typedef uint8_t svScalar; 77 | typedef svScalar svBit; /* scalar */ 78 | typedef svScalar svLogic; /* scalar */ 79 | /* 80 | * DPI representation of packed arrays. 81 | * 2-state and 4-state vectors, exactly the same as PLI's avalue/bvalue. 82 | */ 83 | #ifndef VPI_VECVAL 84 | #define VPI_VECVAL 85 | /* For backward compatibility of IEEE STD 1800-2005 */ 86 | struct vpi_vecval { 87 | uint32_t aval; 88 | uint32_t bval; 89 | }; 90 | typedef struct t_vpi_vecval { 91 | uint32_t aval; 92 | uint32_t bval; 93 | } s_vpi_vecval, *p_vpi_vecval; 94 | #endif 95 | /* (a chunk of) packed logic array */ 96 | typedef s_vpi_vecval svLogicVecVal; 97 | /* typedef struct { unsigned int c; unsigned int d;} svLogicVecVal; temp solution before Phase 2 */ 98 | /* (a chunk of) packed bit array */ 99 | typedef uint32_t svBitVecVal; 100 | typedef struct { unsigned int c; unsigned int d;} svLogicVec32; /* (a chunk of) packed logic array */ 101 | /* Number of chunks required to represent the given width packed array */ 102 | #define SV_PACKED_DATA_NELEMS(WIDTH) (((WIDTH) + 31) >> 5) 103 | /* 104 | * Because the contents of the unused bits is undetermined, 105 | * the following macros can be handy. 106 | */ 107 | #define SV_MASK(N) (~(-1 << (N))) 108 | #define SV_GET_UNSIGNED_BITS(VALUE, N) \ 109 | ((N) == 32 ? (VALUE) : ((VALUE) & SV_MASK(N))) 110 | #define SV_GET_SIGNED_BITS(VALUE, N) \ 111 | ((N) == 32 ? (VALUE) : \ 112 | (((VALUE) & (1 << (N))) ? ((VALUE) | ~SV_MASK(N)) : ((VALUE) & SV_MASK(N)))) 113 | 114 | typedef struct _SVUserData { 115 | void* scope; 116 | void* userKey; 117 | void* userData; 118 | } SVUserData; 119 | 120 | /* 121 | * Implementation-dependent representation. 122 | */ 123 | /* 124 | * Return implementation version information string ("P1800-2005" or "SV3.1a"). 125 | */ 126 | XXTERN const char* svDpiVersion(void); 127 | /* a handle to a scope (an instance of a module or interface) */ 128 | XXTERN typedef void* svScope; 129 | /* a handle to a generic object (actually, unsized array) */ 130 | XXTERN typedef void* svOpenArrayHandle; 131 | 132 | XXTERN typedef void* svDynamicArrayHandle; 133 | XXTERN svDynamicArrayHandle svAllocDynArray(const svDynamicArrayHandle h, int numElements); 134 | XXTERN void* svGetDynArrayPtr(const svDynamicArrayHandle h); 135 | XXTERN void* svGetDynArrayElemType(const svDynamicArrayHandle h); 136 | XXTERN int svGetDynArrayElemNum(const svDynamicArrayHandle h); 137 | XXTERN int svGetDynArrayElemSize(const svDynamicArrayHandle h); 138 | 139 | /* 140 | * Bit-select utility functions. 141 | * 142 | * Packed arrays are assumed to be indexed n-1:0, 143 | * where 0 is the index of LSB 144 | */ 145 | /* s=source, i=bit-index */ 146 | XXTERN svBit svGetBitselBit(const svBitVecVal* s, int i); 147 | XXTERN svLogic svGetBitselLogic(const svLogicVecVal* s, int i); 148 | /* d=destination, i=bit-index, s=scalar */ 149 | XXTERN void svPutBitselBit(svBitVecVal* d, int i, svBit s); 150 | XXTERN void svPutBitselLogic(svLogicVecVal* d, int i, svLogic s); 151 | /* 152 | * Part-select utility functions. 153 | * 154 | * A narrow (<=32 bits) part-select is extracted from the 155 | * source representation and written into the destination word. 156 | * 157 | * Normalized ranges and indexing [n-1:0] are used for both arrays. 158 | * 159 | * s=source, d=destination, i=starting bit index, w=width 160 | * like for variable part-selects; limitations: w <= 32 161 | */ 162 | XXTERN void svGetPartselBit(svBitVecVal* d, const svBitVecVal* s, int i, int w); 163 | XXTERN void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int 164 | w); 165 | XXTERN void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w); 166 | XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal s, int i, int w); 167 | /* 168 | * Open array querying functions 169 | * These functions are modeled upon the SystemVerilog array 170 | * querying functions and use the same semantics. 171 | * 172 | * If the dimension is 0, then the query refers to the 173 | * packed part of an array (which is one-dimensional). 174 | * Dimensions > 0 refer to the unpacked part of an array. 175 | */ 176 | /* h= handle to open array, d=dimension */ 177 | XXTERN int svLeft(const svOpenArrayHandle h, int d); 178 | XXTERN int svRight(const svOpenArrayHandle h, int d); 179 | XXTERN int svLow(const svOpenArrayHandle h, int d); 180 | XXTERN int svHigh(const svOpenArrayHandle h, int d); 181 | XXTERN int svIncrement(const svOpenArrayHandle h, int d); 182 | XXTERN int svLength(const svOpenArrayHandle h, int d); 183 | XXTERN int svSize(const svOpenArrayHandle h, int d); 184 | XXTERN int svDimensions(const svOpenArrayHandle h); 185 | /* 186 | * Pointer to the actual representation of the whole array of any type 187 | * NULL if not in C layout 188 | */ 189 | XXTERN void *svGetArrayPtr(const svOpenArrayHandle); 190 | /* total size in bytes or 0 if not in C layout */ 191 | XXTERN int svSizeOfArray(const svOpenArrayHandle); 192 | /* 193 | * Return a pointer to an element of the array 194 | * or NULL if index outside the range or null pointer 195 | */ 196 | XXTERN void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...); 197 | /* specialized versions for 1-, 2- and 3-dimensional arrays: */ 198 | XXTERN void *svGetArrElemPtr1(const svOpenArrayHandle, int indx1); 199 | XXTERN void *svGetArrElemPtr2(const svOpenArrayHandle, int indx1, int indx2); 200 | XXTERN void *svGetArrElemPtr3(const svOpenArrayHandle, int indx1, int indx2, 201 | int indx3); 202 | /* 203 | * Functions for copying between simulator storage and user space. 204 | * These functions copy the whole packed array in either direction. 205 | * The user is responsible for allocating an array to hold the 206 | * canonical representation. 207 | */ 208 | /* s=source, d=destination */ 209 | /* From user space into simulator storage */ 210 | XXTERN void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, 211 | int indx1, ...); 212 | XXTERN void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, 213 | int indx1); 214 | XXTERN void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s, 215 | int indx1, int indx2); 216 | XXTERN void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s, 217 | int indx1, int indx2, int indx3); 218 | XXTERN void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, 219 | int indx1, ...); 220 | XXTERN void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, 221 | int indx1); 222 | XXTERN void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, 223 | int indx1, int indx2); 224 | XXTERN void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, 225 | int indx1, int indx2, int indx3); 226 | /* From simulator storage into user space */ 227 | XXTERN void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, 228 | int indx1, ...); 229 | XXTERN void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, 230 | int indx1); 231 | XXTERN void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s, 232 | int indx1, int indx2); 233 | XXTERN void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s, 234 | int indx1, int indx2, int indx3); 235 | XXTERN void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, 236 | int indx1, ...); 237 | XXTERN void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, 238 | int indx1); 239 | XXTERN void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s, 240 | int indx1, int indx2); 241 | XXTERN void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s, 242 | int indx1, int indx2, int indx3); 243 | XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...); 244 | XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1); 245 | XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2); 246 | XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2, 247 | int indx3); 248 | XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...); 249 | XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1); 250 | XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2); 251 | XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2, 252 | int indx3); 253 | XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, 254 | ...); 255 | XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1); 256 | XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, 257 | int indx2); 258 | XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, 259 | int indx2, int indx3); 260 | XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...); 261 | XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1); 262 | XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1, 263 | int indx2); 264 | XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1, 265 | int indx2, int indx3); 266 | /* Functions for working with DPI context */ 267 | /* 268 | * Retrieve the active instance scope currently associated with the executing 269 | * imported function. Unless a prior call to svSetScope has occurred, this 270 | * is the scope of the function's declaration site, not call site. 271 | * Returns NULL if called from C code that is *not* an imported function. 272 | */ 273 | XXTERN svScope svGetScope(void); 274 | /* 275 | * Set context for subsequent export function execution. 276 | * This function must be called before calling an export function, unless 277 | * the export function is called while executing an extern function. In that 278 | * case the export function shall inherit the scope of the surrounding extern 279 | * function. This is known as the "default scope". 280 | * The return is the previous active scope (per svGetScope) 281 | */ 282 | XXTERN svScope svSetScope(const svScope scope); 283 | /* Gets the fully qualified name of a scope handle */ 284 | XXTERN const char* svGetNameFromScope(const svScope); 285 | /* 286 | * Retrieve svScope to instance scope of an arbitrary function declaration. 287 | * (can be either module, program, interface, or generate scope) 288 | * The return value shall be NULL for unrecognized scope names. 289 | */ 290 | XXTERN svScope svGetScopeFromName(const char* scopeName); 291 | /* 292 | * Store an arbitrary user data pointer for later retrieval by svGetUserData() 293 | * The userKey is generated by the user. It must be guaranteed by the user to 294 | * be unique from all other userKey's for all unique data storage requirements 295 | * It is recommended that the address of static functions or variables in the 296 | * user's C code be used as the userKey. 297 | * It is illegal to pass in NULL values for either the scope or userData 298 | * arguments. It is also an error to call svPutUserData() with an invalid 299 | * svScope. This function returns -1 for all error cases, 0 upon success. It is 300 | * suggested that userData values of 0 (NULL) not be used as otherwise it can 301 | * be impossible to discern error status returns when calling svGetUserData() 302 | */ 303 | XXTERN int svPutUserData(const svScope scope, void *userKey, void* userData); 304 | /* 305 | * Retrieve an arbitrary user data pointer that was previously 306 | * stored by a call to svPutUserData(). See the comment above 307 | * svPutUserData() for an explanation of userKey, as well as 308 | * restrictions on NULL and illegal svScope and userKey values. 309 | * This function returns NULL for all error cases, 0 upon success. 310 | * This function also returns NULL in the event that a prior call 311 | * to svPutUserData() was never made. 312 | */ 313 | XXTERN void* svGetUserData(const svScope scope, void* userKey); 314 | /* 315 | * Returns the file and line number in the SV code from which the extern call 316 | * was made. If this information available, returns TRUE and updates fileName 317 | * and lineNumber to the appropriate values. Behavior is unpredictable if 318 | * fileName or lineNumber are not appropriate pointers. If this information is 319 | * not available return FALSE and contents of fileName and lineNumber not 320 | * modified. Whether this information is available or not is implementation- 321 | * specific. Note that the string provided (if any) is owned by the SV 322 | * implementation and is valid only until the next call to any SV function. 323 | * Applications must not modify this string or free it 324 | */ 325 | XXTERN int svGetCallerInfo(const char** fileName, int *lineNumber); 326 | /* 327 | * Returns 1 if the current execution thread is in the disabled state. 328 | * Disable protocol must be adhered to if in the disabled state. 329 | */ 330 | XXTERN int svIsDisabledState(void); 331 | /* 332 | * Imported functions call this API function during disable processing to 333 | * acknowledge that they are correctly participating in the DPI disable protocol. 334 | * This function must be called before returning from an imported function that is 335 | * in the disabled state. 336 | */ 337 | XXTERN void svAckDisabledState(void); 338 | /* 339 | ********************************************************** 340 | * DEPRECATED PORTION OF FILE STARTS FROM HERE. 341 | * IEEE-P1800-compliant tools may not provide 342 | * support for the following functionality. 343 | ********************************************************** 344 | */ 345 | /* 346 | * Canonical representation of packed arrays 347 | * 2-state and 4-state vectors, modeled upon PLI's avalue/bvalue 348 | */ 349 | #define SV_CANONICAL_SIZE(WIDTH) (((WIDTH)+31)>>5) 350 | typedef unsigned int svBitVec32;/* (a chunk of) packed bit array */ 351 | /* reference to a standalone packed array */ 352 | typedef void* svBitPackedArrRef; 353 | typedef void* svLogicPackedArrRef; 354 | /* 355 | * total size in bytes of the simulator's representation of a packed array 356 | * width in bits 357 | */ 358 | XXTERN int svSizeOfBitPackedArr(int width); 359 | XXTERN int svSizeOfLogicPackedArr(int width); 360 | /* Translation between the actual representation and the canonical representation */ 361 | /* s=source, d=destination, w=width */ 362 | /* actual <-- canonical */ 363 | XXTERN void svPutBitVec32(svBitPackedArrRef d, const svBitVec32* s, int w); 364 | XXTERN void svPutLogicVec32(svLogicPackedArrRef d, const svLogicVec32* s, int w); 365 | /* canonical <-- actual */ 366 | XXTERN void svGetBitVec32(svBitVec32* d, const svBitPackedArrRef s, int w); 367 | XXTERN void svGetLogicVec32(svLogicVec32* d, const svLogicPackedArrRef s, int w); 368 | /* 369 | * Bit-select functions 370 | * Packed arrays are assumed to be indexed n-1:0, 371 | * where 0 is the index of LSB 372 | */ 373 | /* s=source, i=bit-index */ 374 | XXTERN svBit svGetSelectBit(const svBitPackedArrRef s, int i); 375 | XXTERN svLogic svGetSelectLogic(const svLogicPackedArrRef s, int i); 376 | /* d=destination, i=bit-index, s=scalar */ 377 | XXTERN void svPutSelectBit(svBitPackedArrRef d, int i, svBit s); 378 | XXTERN void svPutSelectLogic(svLogicPackedArrRef d, int i, svLogic s); 379 | /* 380 | * functions for part-select 381 | * 382 | * a narrow (<=32 bits) part-select is copied between 383 | * the implementation representation and a single chunk of 384 | * canonical representation 385 | * Normalized ranges and indexing [n-1:0] are used for both arrays: 386 | * the array in the implementation representation and the canonical array. 387 | * 388 | * s=source, d=destination, i=starting bit index, w=width 389 | * like for variable part-selects; limitations: w <= 32 390 | */ 391 | /* canonical <-- actual */ 392 | XXTERN void svGetPartSelectBit(svBitVec32* d, const svBitPackedArrRef s, 393 | int i, int w); 394 | XXTERN svBitVec32 svGetBits(const svBitPackedArrRef s, int i, int w); 395 | XXTERN svBitVec32 svGet32Bits(const svBitPackedArrRef s, int i); /* 32-bits */ 396 | XXTERN uint64_t svGet64Bits(const svBitPackedArrRef s, int i); 397 | /* 64-bits */ 398 | XXTERN void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s, 399 | int i, int w); 400 | /* actual <-- canonical */ 401 | XXTERN void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s, 402 | int i, int w); 403 | XXTERN void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32 s, 404 | int i, int w); 405 | /* 406 | * Functions for open array translation between simulator and canonical 407 | representations. 408 | * These functions copy the whole packed array in either direction. The user is 409 | * responsible for allocating an array in the canonical representation. 410 | */ 411 | /* s=source, d=destination */ 412 | /* actual <-- canonical */ 413 | XXTERN void svPutBitArrElemVec32(const svOpenArrayHandle d, const svBitVec32* s, 414 | int indx1, ...); 415 | XXTERN void svPutBitArrElem1Vec32(const svOpenArrayHandle d, const svBitVec32* s, 416 | int indx1); 417 | XXTERN void svPutBitArrElem2Vec32(const svOpenArrayHandle d, const svBitVec32* s, 418 | int indx1, int indx2); 419 | XXTERN void svPutBitArrElem3Vec32(const svOpenArrayHandle d, const svBitVec32* s, 420 | int indx1, int indx2, int indx3); 421 | XXTERN void svPutLogicArrElemVec32(const svOpenArrayHandle d, const svLogicVec32* s, 422 | int indx1, ...); 423 | XXTERN void svPutLogicArrElem1Vec32(const svOpenArrayHandle d, const svLogicVec32* s, 424 | int indx1); 425 | XXTERN void svPutLogicArrElem2Vec32(const svOpenArrayHandle d, const svLogicVec32* s, 426 | int indx1, int indx2); 427 | XXTERN void svPutLogicArrElem3Vec32(const svOpenArrayHandle d, const svLogicVec32* s, 428 | int indx1, int indx2, int indx3); 429 | /* canonical <-- actual */ 430 | XXTERN void svGetBitArrElemVec32(svBitVec32* d, const svOpenArrayHandle s, 431 | int indx1, ...); 432 | XXTERN void svGetBitArrElem1Vec32(svBitVec32* d, const svOpenArrayHandle s, 433 | int indx1); 434 | XXTERN void svGetBitArrElem2Vec32(svBitVec32* d, const svOpenArrayHandle s, 435 | int indx1, int indx2); 436 | XXTERN void svGetBitArrElem3Vec32(svBitVec32* d, const svOpenArrayHandle s, 437 | int indx1, int indx2, int indx3); 438 | XXTERN void svGetLogicArrElemVec32(svLogicVec32* d, const svOpenArrayHandle s, 439 | int indx1, ...); 440 | XXTERN void svGetLogicArrElem1Vec32(svLogicVec32* d, const svOpenArrayHandle s, 441 | int indx1); 442 | XXTERN void svGetLogicArrElem2Vec32(svLogicVec32* d, const svOpenArrayHandle s, 443 | int indx1, int indx2); 444 | XXTERN void svGetLogicArrElem3Vec32(svLogicVec32* d, const svOpenArrayHandle s, 445 | int indx1, int indx2, int indx3); 446 | 447 | /* 448 | ********************************************************** 449 | * DEPRECATED PORTION OF FILE ENDS HERE. 450 | ********************************************************** 451 | */ 452 | #undef DPI_EXTERN 453 | #ifdef DPI_PROTOTYPES 454 | #undef DPI_PROTOTYPES 455 | #undef XXTERN 456 | #undef EETERN 457 | #endif 458 | #ifdef __cplusplus 459 | } 460 | #endif 461 | #endif 462 | -------------------------------------------------------------------------------- /bridge/std/vpi_user.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * vpi_user.h 3 | * 4 | * IEEE Std 1800 Programming Language Interface (PLI). 5 | * 6 | * This file contains the constant definitions, structure definitions, and 7 | * routine declarations used by the SystemVerilog Verification Procedural 8 | * Interface (VPI) access routines. 9 | * 10 | **************************************************************************/ 11 | 12 | /*************************************************************************** 13 | * NOTE: the constant values 1 through 299 are reserved for use in this 14 | * vpi_user.h file. 15 | **************************************************************************/ 16 | 17 | #ifndef VPI_USER_H 18 | #define VPI_USER_H 19 | 20 | #ifndef LIB_VPIUSER_H 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /*------------------------------------------------------------------------*/ 29 | /*-------------------------- Portability Help ----------------------------*/ 30 | /*------------------------------------------------------------------------*/ 31 | 32 | /* Define size-critical types on all OS platforms. */ 33 | #if defined (_MSC_VER) 34 | typedef unsigned __int64 uint64_t; 35 | typedef unsigned __int32 uint32_t; 36 | typedef unsigned __int8 uint8_t; 37 | typedef signed __int64 int64_t; 38 | typedef signed __int32 int32_t; 39 | typedef signed __int8 int8_t; 40 | #elif defined (__MINGW32__) 41 | #include 42 | #elif defined (__linux) 43 | #include 44 | #else 45 | #include 46 | #endif 47 | 48 | /* Sized variables */ 49 | #ifndef SVPI_TYPES 50 | #define SVPI_TYPES 51 | typedef int64_t PLI_INT64; 52 | typedef uint64_t PLI_UINT64; 53 | #endif 54 | 55 | #ifndef PLI_TYPES 56 | #define PLI_TYPES 57 | typedef int PLI_INT32; 58 | typedef unsigned int PLI_UINT32; 59 | typedef short PLI_INT16; 60 | typedef unsigned short PLI_UINT16; 61 | typedef char PLI_BYTE8; 62 | typedef unsigned char PLI_UBYTE8; 63 | #endif 64 | 65 | /* Use to export a symbol */ 66 | #if WIN32 67 | #ifndef PLI_DLLISPEC 68 | #define PLI_DLLISPEC __declspec(dllimport) 69 | #define VPI_USER_DEFINED_DLLISPEC 1 70 | #endif 71 | #else 72 | #ifndef PLI_DLLISPEC 73 | #define PLI_DLLISPEC 74 | #endif 75 | #endif 76 | 77 | /* Use to import a symbol */ 78 | #if WIN32 79 | #ifndef PLI_DLLESPEC 80 | #define PLI_DLLESPEC __declspec(dllexport) 81 | #define VPI_USER_DEFINED_DLLESPEC 1 82 | #endif 83 | #else 84 | #ifndef PLI_DLLESPEC 85 | #define PLI_DLLESPEC 86 | #endif 87 | #endif 88 | 89 | /* Use to mark a function as external */ 90 | #ifndef PLI_EXTERN 91 | #define PLI_EXTERN 92 | #endif 93 | 94 | /* Use to mark a variable as external */ 95 | #ifndef PLI_VEXTERN 96 | #define PLI_VEXTERN extern 97 | #endif 98 | 99 | #ifndef PLI_PROTOTYPES 100 | #define PLI_PROTOTYPES 101 | #define PROTO_PARAMS(params) params 102 | 103 | /* object is defined imported by the application */ 104 | #define XXTERN PLI_EXTERN PLI_DLLISPEC 105 | 106 | /* object is exported by the application */ 107 | 108 | #define EETERN PLI_EXTERN PLI_DLLESPEC 109 | #endif 110 | 111 | 112 | /******************************** TYPEDEFS ********************************/ 113 | 114 | typedef PLI_UINT32 *vpiHandle; 115 | 116 | /****************************** OBJECT TYPES ******************************/ 117 | #define vpiAlways 1 /* used in always block */ 118 | #define vpiAssignStmt 2 /* quasi-continuous assignment */ 119 | #define vpiAssignment 3 /* procedural assignment */ 120 | #define vpiBegin 4 /* block statement */ 121 | #define vpiCase 5 /* case statement */ 122 | #define vpiCaseItem 6 /* case statement item */ 123 | #define vpiConstant 7 /* numerical constant or literal string */ 124 | #define vpiContAssign 8 /* continuous assignment */ 125 | #define vpiDeassign 9 /* deassignment statement */ 126 | #define vpiDefParam 10 /* defparam */ 127 | #define vpiDelayControl 11 /* delay statement (e.g. #10) */ 128 | #define vpiDisable 12 /* named block disable statement */ 129 | #define vpiEventControl 13 /* wait on event, e.g. @e */ 130 | #define vpiEventStmt 14 /* event trigger, e.g. ->e */ 131 | #define vpiFor 15 /* for statement */ 132 | #define vpiForce 16 /* force statement */ 133 | #define vpiForever 17 /* forever statement */ 134 | #define vpiFork 18 /* fork-join block */ 135 | #define vpiFuncCall 19 /* HDL function call */ 136 | #define vpiFunction 20 /* HDL function */ 137 | #define vpiGate 21 /* primitive gate */ 138 | #define vpiIf 22 /* if statement */ 139 | #define vpiIfElse 23 /* if-else statement */ 140 | #define vpiInitial 24 /* initial block */ 141 | #define vpiIntegerVar 25 /* integer variable */ 142 | #define vpiInterModPath 26 /* intermodule wire delay */ 143 | #define vpiIterator 27 /* iterator */ 144 | #define vpiIODecl 28 /* input/output declaration */ 145 | #define vpiMemory 29 /* behavioral memory */ 146 | #define vpiMemoryWord 30 /* single word of memory */ 147 | #define vpiModPath 31 /* module path for path delays */ 148 | #define vpiModule 32 /* module instance */ 149 | #define vpiNamedBegin 33 /* named block statement */ 150 | #define vpiNamedEvent 34 /* event variable */ 151 | #define vpiNamedFork 35 /* named fork-join block */ 152 | #define vpiNet 36 /* scalar or vector net */ 153 | #define vpiNetBit 37 /* bit of vector net */ 154 | #define vpiNullStmt 38 /* a semicolon. Ie. #10 ; */ 155 | #define vpiOperation 39 /* behavioral operation */ 156 | #define vpiParamAssign 40 /* module parameter assignment */ 157 | #define vpiParameter 41 /* module parameter */ 158 | #define vpiPartSelect 42 /* part select */ 159 | #define vpiPathTerm 43 /* terminal of module path */ 160 | #define vpiPort 44 /* module port */ 161 | #define vpiPortBit 45 /* bit of vector module port */ 162 | #define vpiPrimTerm 46 /* primitive terminal */ 163 | #define vpiRealVar 47 /* real variable */ 164 | #define vpiReg 48 /* scalar or vector reg */ 165 | #define vpiRegBit 49 /* bit of vector reg */ 166 | #define vpiRelease 50 /* release statement */ 167 | #define vpiRepeat 51 /* repeat statement */ 168 | #define vpiRepeatControl 52 /* repeat control in an assign stmt */ 169 | #define vpiSchedEvent 53 /* vpi_put_value() event */ 170 | #define vpiSpecParam 54 /* specparam */ 171 | #define vpiSwitch 55 /* transistor switch */ 172 | #define vpiSysFuncCall 56 /* system function call */ 173 | #define vpiSysTaskCall 57 /* system task call */ 174 | #define vpiTableEntry 58 /* UDP state table entry */ 175 | #define vpiTask 59 /* HDL task */ 176 | #define vpiTaskCall 60 /* HDL task call */ 177 | #define vpiTchk 61 /* timing check */ 178 | #define vpiTchkTerm 62 /* terminal of timing check */ 179 | #define vpiTimeVar 63 /* time variable */ 180 | #define vpiTimeQueue 64 /* simulation event queue */ 181 | #define vpiUdp 65 /* user-defined primitive */ 182 | #define vpiUdpDefn 66 /* UDP definition */ 183 | #define vpiUserSystf 67 /* user defined system task or function */ 184 | #define vpiVarSelect 68 /* variable array selection */ 185 | #define vpiWait 69 /* wait statement */ 186 | #define vpiWhile 70 /* while statement */ 187 | 188 | /****************** object types added with 1364-2000 *********************/ 189 | #define vpiAttribute 105 /* attribute of an object */ 190 | #define vpiBitSelect 106 /* Bit select of parameter, var select */ 191 | #define vpiCallback 107 /* callback object */ 192 | #define vpiDelayTerm 108 /* Delay term which is a load or driver */ 193 | #define vpiDelayDevice 109 /* Delay object within a net */ 194 | #define vpiFrame 110 /* reentrant task/func frame */ 195 | #define vpiGateArray 111 /* gate instance array */ 196 | #define vpiModuleArray 112 /* module instance array */ 197 | #define vpiPrimitiveArray 113 /* vpiprimitiveArray type */ 198 | #define vpiNetArray 114 /* multidimensional net */ 199 | #define vpiRange 115 /* range declaration */ 200 | #define vpiRegArray 116 /* multidimensional reg */ 201 | #define vpiSwitchArray 117 /* switch instance array */ 202 | #define vpiUdpArray 118 /* UDP instance array */ 203 | #define vpiContAssignBit 128 /* Bit of a vector continuous assignment */ 204 | #define vpiNamedEventArray 129 /* multidimensional named event */ 205 | 206 | /************* object types added with 1364-2005 **************/ 207 | #define vpiIndexedPartSelect 130 /* Indexed part-select object */ 208 | #define vpiGenScopeArray 133 /* array of generated scopes */ 209 | #define vpiGenScope 134 /* A generated scope */ 210 | #define vpiGenVar 135 /* Object used to instantiate gen scopes */ 211 | 212 | /******************************** METHODS *********************************/ 213 | /************* methods used to traverse 1 to 1 relationships **************/ 214 | #define vpiCondition 71 /* condition expression */ 215 | #define vpiDelay 72 /* net or gate delay */ 216 | #define vpiElseStmt 73 /* else statement */ 217 | #define vpiForIncStmt 74 /* increment statement in for loop */ 218 | #define vpiForInitStmt 75 /* initialization statement in for loop */ 219 | #define vpiHighConn 76 /* higher connection to port */ 220 | #define vpiLhs 77 /* left-hand side of assignment */ 221 | #define vpiIndex 78 /* index of var select, bit select, etc. */ 222 | #define vpiLeftRange 79 /* left range of vector or part select */ 223 | #define vpiLowConn 80 /* lower connection to port */ 224 | #define vpiParent 81 /* parent object */ 225 | #define vpiRhs 82 /* right-hand side of assignment */ 226 | #define vpiRightRange 83 /* right range of vector or part select */ 227 | #define vpiScope 84 /* containing scope object */ 228 | #define vpiSysTfCall 85 /* task function call */ 229 | #define vpiTchkDataTerm 86 /* timing check data term */ 230 | #define vpiTchkNotifier 87 /* timing check notifier */ 231 | #define vpiTchkRefTerm 88 /* timing check reference term */ 232 | 233 | /************ methods used to traverse 1 to many relationships ************/ 234 | #define vpiArgument 89 /* argument to (system) task/function */ 235 | #define vpiBit 90 /* bit of vector net or port */ 236 | #define vpiDriver 91 /* driver for a net */ 237 | #define vpiInternalScope 92 /* internal scope in module */ 238 | #define vpiLoad 93 /* load on net or reg */ 239 | #define vpiModDataPathIn 94 /* data terminal of a module path */ 240 | #define vpiModPathIn 95 /* Input terminal of a module path */ 241 | #define vpiModPathOut 96 /* output terminal of a module path */ 242 | #define vpiOperand 97 /* operand of expression */ 243 | #define vpiPortInst 98 /* connected port instance */ 244 | #define vpiProcess 99 /* process in module */ 245 | #define vpiVariables 100 /* variables in module */ 246 | #define vpiUse 101 /* usage */ 247 | 248 | /***** methods which can traverse 1 to 1, or 1 to many relationships ******/ 249 | #define vpiExpr 102 /* connected expression */ 250 | #define vpiPrimitive 103 /* primitive (gate, switch, UDP) */ 251 | #define vpiStmt 104 /* statement in process or task */ 252 | 253 | /********************* methods added with 1364-2000 ***********************/ 254 | #define vpiActiveTimeFormat 119 /* active $timeformat() system task */ 255 | #define vpiInTerm 120 /* To get to a delay device's drivers. */ 256 | #define vpiInstanceArray 121 /* vpiInstance arrays */ 257 | #define vpiLocalDriver 122 /* local drivers (within a module */ 258 | #define vpiLocalLoad 123 /* local loads (within a module */ 259 | #define vpiOutTerm 124 /* To get to a delay device's loads. */ 260 | #define vpiPorts 125 /* Module port */ 261 | #define vpiSimNet 126 /* simulated net after collapsing */ 262 | #define vpiTaskFunc 127 /* HDL task or function */ 263 | 264 | /********************* methods added with 1364-2005 ***********************/ 265 | 266 | #define vpiBaseExpr 131 /* Indexed part-select's base expression */ 267 | #define vpiWidthExpr 132 /* Indexed part-select's width expression */ 268 | 269 | /********************* methods added with 1800-2009 ***********************/ 270 | #define vpiAutomatics 136 /* Automatic variables of a frame */ 271 | 272 | /************************ generic object properties ***********************/ 273 | #define vpiUndefined -1 /* undefined property */ 274 | #define vpiType 1 /* type of object */ 275 | #define vpiName 2 /* local name of object */ 276 | #define vpiFullName 3 /* full hierarchical name */ 277 | #define vpiSize 4 /* size of gate, net, port, etc. */ 278 | #define vpiFile 5 /* File name in which the object is used */ 279 | #define vpiLineNo 6 /* line number where the object is used */ 280 | 281 | /*************************** module properties ****************************/ 282 | #define vpiTopModule 7 /* top-level module (boolean) */ 283 | #define vpiCellInstance 8 /* cell (boolean) */ 284 | #define vpiDefName 9 /* module definition name */ 285 | #define vpiProtected 10 /* source protected module (boolean) */ 286 | #define vpiTimeUnit 11 /* module time unit */ 287 | #define vpiTimePrecision 12 /* module time precision */ 288 | #define vpiDefNetType 13 /* default net type */ 289 | #define vpiUnconnDrive 14 /* unconnected port drive strength */ 290 | #define vpiHighZ 1 /* No default drive given */ 291 | #define vpiPull1 2 /* default pull1 drive */ 292 | #define vpiPull0 3 /* default pull0 drive */ 293 | #define vpiDefFile 15 /* File name where the module is defined */ 294 | #define vpiDefLineNo 16 /* line number for module definition */ 295 | #define vpiDefDelayMode 47 /* Default delay mode for a module */ 296 | #define vpiDelayModeNone 1 /* no delay mode specified */ 297 | #define vpiDelayModePath 2 /* path delay mode */ 298 | #define vpiDelayModeDistrib 3 /* distributed delay mode */ 299 | #define vpiDelayModeUnit 4 /* unit delay mode */ 300 | #define vpiDelayModeZero 5 /* zero delay mode */ 301 | #define vpiDelayModeMTM 6 /* min:typ:max delay mode */ 302 | #define vpiDefDecayTime 48 /* Default decay time for a module */ 303 | 304 | /************************ port and net properties *************************/ 305 | #define vpiScalar 17 /* scalar (boolean) */ 306 | #define vpiVector 18 /* vector (boolean) */ 307 | #define vpiExplicitName 19 /* port is explicitly named */ 308 | #define vpiDirection 20 /* direction of port: */ 309 | #define vpiInput 1 /* input */ 310 | #define vpiOutput 2 /* output */ 311 | #define vpiInout 3 /* inout */ 312 | #define vpiMixedIO 4 /* mixed input-output */ 313 | #define vpiNoDirection 5 /* no direction */ 314 | #define vpiConnByName 21 /* connected by name (boolean) */ 315 | 316 | #define vpiNetType 22 /* net subtypes: */ 317 | #define vpiWire 1 /* wire net */ 318 | #define vpiWand 2 /* wire-and net */ 319 | #define vpiWor 3 /* wire-or net */ 320 | #define vpiTri 4 /* tri-state net */ 321 | #define vpiTri0 5 /* pull-down net */ 322 | #define vpiTri1 6 /* pull-up net */ 323 | #define vpiTriReg 7 /* tri state reg net */ 324 | #define vpiTriAnd 8 /* tri-state wire-and net */ 325 | #define vpiTriOr 9 /* tri-state wire-or net */ 326 | #define vpiSupply1 10 /* supply 1 net */ 327 | #define vpiSupply0 11 /* supply zero net */ 328 | #define vpiNone 12 /* no default net type (1364-2000) */ 329 | #define vpiUwire 13 /* unresolved wire net (1364-2005) */ 330 | 331 | #define vpiExplicitScalared 23 /* explicitly scalared (boolean) */ 332 | #define vpiExplicitVectored 24 /* explicitly vectored (boolean) */ 333 | #define vpiExpanded 25 /* expanded vector net (boolean) */ 334 | #define vpiImplicitDecl 26 /* implicitly declared net (boolean) */ 335 | #define vpiChargeStrength 27 /* charge decay strength of net */ 336 | 337 | /* Defined as part of strengths section. 338 | #define vpiLargeCharge 0x10 339 | #define vpiMediumCharge 0x04 340 | #define vpiSmallCharge 0x02 341 | */ 342 | #define vpiArray 28 /* variable array (boolean) */ 343 | #define vpiPortIndex 29 /* Port index */ 344 | 345 | /********************** gate and terminal properties **********************/ 346 | #define vpiTermIndex 30 /* Index of a primitive terminal */ 347 | #define vpiStrength0 31 /* 0-strength of net or gate */ 348 | #define vpiStrength1 32 /* 1-strength of net or gate */ 349 | #define vpiPrimType 33 /* prmitive subtypes: */ 350 | #define vpiAndPrim 1 /* and gate */ 351 | #define vpiNandPrim 2 /* nand gate */ 352 | #define vpiNorPrim 3 /* nor gate */ 353 | #define vpiOrPrim 4 /* or gate */ 354 | #define vpiXorPrim 5 /* xor gate */ 355 | #define vpiXnorPrim 6 /* xnor gate */ 356 | #define vpiBufPrim 7 /* buffer */ 357 | #define vpiNotPrim 8 /* not gate */ 358 | #define vpiBufif0Prim 9 /* zero-enabled buffer */ 359 | #define vpiBufif1Prim 10 /* one-enabled buffer */ 360 | #define vpiNotif0Prim 11 /* zero-enabled not gate */ 361 | #define vpiNotif1Prim 12 /* one-enabled not gate */ 362 | #define vpiNmosPrim 13 /* nmos switch */ 363 | #define vpiPmosPrim 14 /* pmos switch */ 364 | #define vpiCmosPrim 15 /* cmos switch */ 365 | #define vpiRnmosPrim 16 /* resistive nmos switch */ 366 | #define vpiRpmosPrim 17 /* resistive pmos switch */ 367 | #define vpiRcmosPrim 18 /* resistive cmos switch */ 368 | #define vpiRtranPrim 19 /* resistive bidirectional */ 369 | #define vpiRtranif0Prim 20 /* zero-enable resistive bidirectional */ 370 | #define vpiRtranif1Prim 21 /* one-enable resistive bidirectional */ 371 | #define vpiTranPrim 22 /* bidirectional */ 372 | #define vpiTranif0Prim 23 /* zero-enabled bidirectional */ 373 | #define vpiTranif1Prim 24 /* one-enabled bidirectional */ 374 | #define vpiPullupPrim 25 /* pullup */ 375 | #define vpiPulldownPrim 26 /* pulldown */ 376 | #define vpiSeqPrim 27 /* sequential UDP */ 377 | #define vpiCombPrim 28 /* combinational UDP */ 378 | 379 | /************** path, path terminal, timing check properties **************/ 380 | #define vpiPolarity 34 /* polarity of module path... */ 381 | #define vpiDataPolarity 35 /* ...or data path: */ 382 | #define vpiPositive 1 /* positive */ 383 | #define vpiNegative 2 /* negative */ 384 | #define vpiUnknown 3 /* unknown (unspecified) */ 385 | 386 | #define vpiEdge 36 /* edge type of module path: */ 387 | #define vpiNoEdge 0x00000000 /* no edge */ 388 | #define vpiEdge01 0x00000001 /* 0 -> 1 */ 389 | #define vpiEdge10 0x00000002 /* 1 -> 0 */ 390 | #define vpiEdge0x 0x00000004 /* 0 -> x */ 391 | #define vpiEdgex1 0x00000008 /* x -> 1 */ 392 | #define vpiEdge1x 0x00000010 /* 1 -> x */ 393 | #define vpiEdgex0 0x00000020 /* x -> 0 */ 394 | #define vpiPosedge (vpiEdgex1 | vpiEdge01 | vpiEdge0x) 395 | #define vpiNegedge (vpiEdgex0 | vpiEdge10 | vpiEdge1x) 396 | #define vpiAnyEdge (vpiPosedge | vpiNegedge) 397 | 398 | #define vpiPathType 37 /* path delay connection subtypes: */ 399 | #define vpiPathFull 1 /* ( a *> b ) */ 400 | #define vpiPathParallel 2 /* ( a => b ) */ 401 | 402 | #define vpiTchkType 38 /* timing check subtypes: */ 403 | #define vpiSetup 1 /* $setup */ 404 | #define vpiHold 2 /* $hold */ 405 | #define vpiPeriod 3 /* $period */ 406 | #define vpiWidth 4 /* $width */ 407 | #define vpiSkew 5 /* $skew */ 408 | #define vpiRecovery 6 /* $recovery */ 409 | #define vpiNoChange 7 /* $nochange */ 410 | #define vpiSetupHold 8 /* $setuphold */ 411 | #define vpiFullskew 9 /* $fullskew -- added for 1364-2000 */ 412 | #define vpiRecrem 10 /* $recrem -- added for 1364-2000 */ 413 | #define vpiRemoval 11 /* $removal -- added for 1364-2000 */ 414 | #define vpiTimeskew 12 /* $timeskew -- added for 1364-2000 */ 415 | 416 | /************************* expression properties **************************/ 417 | #define vpiOpType 39 /* operation subtypes: */ 418 | #define vpiMinusOp 1 /* unary minus */ 419 | #define vpiPlusOp 2 /* unary plus */ 420 | #define vpiNotOp 3 /* unary not */ 421 | #define vpiBitNegOp 4 /* bitwise negation */ 422 | #define vpiUnaryAndOp 5 /* bitwise reduction and */ 423 | #define vpiUnaryNandOp 6 /* bitwise reduction nand */ 424 | #define vpiUnaryOrOp 7 /* bitwise reduction or */ 425 | #define vpiUnaryNorOp 8 /* bitwise reduction nor */ 426 | #define vpiUnaryXorOp 9 /* bitwise reduction xor */ 427 | #define vpiUnaryXNorOp 10 /* bitwise reduction xnor */ 428 | #define vpiSubOp 11 /* binary subtraction */ 429 | #define vpiDivOp 12 /* binary division */ 430 | #define vpiModOp 13 /* binary modulus */ 431 | #define vpiEqOp 14 /* binary equality */ 432 | #define vpiNeqOp 15 /* binary inequality */ 433 | #define vpiCaseEqOp 16 /* case (x and z) equality */ 434 | #define vpiCaseNeqOp 17 /* case inequality */ 435 | #define vpiGtOp 18 /* binary greater than */ 436 | #define vpiGeOp 19 /* binary greater than or equal */ 437 | #define vpiLtOp 20 /* binary less than */ 438 | #define vpiLeOp 21 /* binary less than or equal */ 439 | #define vpiLShiftOp 22 /* binary left shift */ 440 | #define vpiRShiftOp 23 /* binary right shift */ 441 | #define vpiAddOp 24 /* binary addition */ 442 | #define vpiMultOp 25 /* binary multiplication */ 443 | #define vpiLogAndOp 26 /* binary logical and */ 444 | #define vpiLogOrOp 27 /* binary logical or */ 445 | #define vpiBitAndOp 28 /* binary bitwise and */ 446 | #define vpiBitOrOp 29 /* binary bitwise or */ 447 | #define vpiBitXorOp 30 /* binary bitwise xor */ 448 | #define vpiBitXNorOp 31 /* binary bitwise xnor */ 449 | #define vpiBitXnorOp vpiBitXNorOp /* added with 1364-2001 */ 450 | #define vpiConditionOp 32 /* ternary conditional */ 451 | #define vpiConcatOp 33 /* n-ary concatenation */ 452 | #define vpiMultiConcatOp 34 /* repeated concatenation */ 453 | #define vpiEventOrOp 35 /* event or */ 454 | #define vpiNullOp 36 /* null operation */ 455 | #define vpiListOp 37 /* list of expressions */ 456 | #define vpiMinTypMaxOp 38 /* min:typ:max: delay expression */ 457 | #define vpiPosedgeOp 39 /* posedge */ 458 | #define vpiNegedgeOp 40 /* negedge */ 459 | #define vpiArithLShiftOp 41 /* arithmetic left shift (1364-2000) */ 460 | #define vpiArithRShiftOp 42 /* arithmetic right shift (1364-2000) */ 461 | #define vpiPowerOp 43 /* arithmetic power op (1364-2000) */ 462 | #define vpiLogImplOp 45 /* binary logical implication */ 463 | #define vpiLogEquOp 46 /* binary logical euqivalence */ 464 | 465 | #define vpiConstType 40 /* constant subtypes: */ 466 | #define vpiDecConst 1 /* decimal integer */ 467 | #define vpiRealConst 2 /* real */ 468 | #define vpiBinaryConst 3 /* binary integer */ 469 | #define vpiOctConst 4 /* octal integer */ 470 | #define vpiHexConst 5 /* hexadecimal integer */ 471 | #define vpiStringConst 6 /* string literal */ 472 | #define vpiIntConst 7 /* HDL integer constant (1364-2001) */ 473 | #define vpiTimeConst 8 /* time constant */ 474 | 475 | #define vpiBlocking 41 /* blocking assignment (boolean) */ 476 | #define vpiCaseType 42 /* case statement subtypes: */ 477 | #define vpiCaseExact 1 /* exact match */ 478 | #define vpiCaseX 2 /* ignore X's */ 479 | #define vpiCaseZ 3 /* ignore Z's */ 480 | #define vpiCaseInside 4 /* case inside */ 481 | #define vpiNetDeclAssign 43 /* assign part of decl (boolean) */ 482 | 483 | /************** task/function properties **************/ 484 | #define vpiFuncType 44 /* HDL function and system function type */ 485 | #define vpiIntFunc 1 /* returns integer */ 486 | #define vpiRealFunc 2 /* returns real */ 487 | #define vpiTimeFunc 3 /* returns time */ 488 | #define vpiSizedFunc 4 /* returns an arbitrary size */ 489 | #define vpiSizedSignedFunc 5 /* returns sized signed value */ 490 | 491 | /* alias 1364-1995 system function subtypes to 1364-2001 function subtypes */ 492 | #define vpiSysFuncType vpiFuncType 493 | #define vpiSysFuncInt vpiIntFunc 494 | #define vpiSysFuncReal vpiRealFunc 495 | #define vpiSysFuncTime vpiTimeFunc 496 | #define vpiSysFuncSized vpiSizedFunc 497 | 498 | #define vpiUserDefn 45 /* user defined system task/func (boolean) */ 499 | #define vpiScheduled 46 /* object still scheduled (boolean) */ 500 | 501 | /*********************** properties added with 1364-2001 *******************/ 502 | 503 | #define vpiActive 49 /* reentrant task/func frame is active */ 504 | #define vpiAutomatic 50 /* task/func obj is automatic */ 505 | #define vpiCell 51 /* configuration cell */ 506 | #define vpiConfig 52 /* configuration config file */ 507 | #define vpiConstantSelect 53 /* (Boolean) bit-select or part-select 508 | indices are constant expressions */ 509 | #define vpiDecompile 54 /* decompile the object */ 510 | #define vpiDefAttribute 55 /* Attribute defined for the obj */ 511 | #define vpiDelayType 56 /* delay subtype */ 512 | #define vpiModPathDelay 1 /* module path delay */ 513 | #define vpiInterModPathDelay 2 /* intermodule path delay */ 514 | #define vpiMIPDelay 3 /* module input port delay */ 515 | #define vpiIteratorType 57 /* object type of an iterator */ 516 | #define vpiLibrary 58 /* configuration library */ 517 | #define vpiMultiArray 59 /* Object is a multidimensional array */ 518 | #define vpiOffset 60 /* offset from LSB */ 519 | #define vpiResolvedNetType 61 /* net subtype after resolution, returns 520 | same subtypes as vpiNetType */ 521 | #define vpiSaveRestartID 62 /* unique ID for save/restart data */ 522 | #define vpiSaveRestartLocation 63 /* name of save/restart data file */ 523 | /* vpiValid, vpiValidTrue, vpiValidFalse are deprecated in 1800-2009 */ 524 | #define vpiValid 64 /* reentrant task/func frame or 525 | automatic variable is valid */ 526 | #define vpiValidFalse 0 527 | #define vpiValidTrue 1 528 | #define vpiSigned 65 /* TRUE for vpiIODecl and any object in 529 | the expression class if the object 530 | has the signed attribute */ 531 | #define vpiLocalParam 70 /* TRUE when a param is declared as a 532 | localparam */ 533 | #define vpiModPathHasIfNone 71 /* Mod path has an ifnone statement */ 534 | 535 | /************* properties added with 1364-2005 ****************************/ 536 | 537 | #define vpiIndexedPartSelectType 72 /* Indexed part-select type */ 538 | #define vpiPosIndexed 1 /* +: */ 539 | #define vpiNegIndexed 2 /* -: */ 540 | #define vpiIsMemory 73 /* TRUE for a one-dimensional reg array */ 541 | #define vpiIsProtected 74 /* TRUE for a protected design information */ 542 | 543 | /************* vpi_control() constants (added with 1364-2001) *************/ 544 | 545 | #define vpiStop 66 /* execute simulator's $stop */ 546 | #define vpiFinish 67 /* execute simulator's $finish */ 547 | #define vpiReset 68 /* execute simulator's $reset */ 548 | #define vpiSetInteractiveScope 69 /* set simulator's interactive scope */ 549 | 550 | /************************** I/O related defines ***************************/ 551 | #define VPI_MCD_STDOUT 0x00000001 552 | 553 | /************************** STRUCTURE DEFINITIONS *************************/ 554 | 555 | /***************************** time structure *****************************/ 556 | typedef struct t_vpi_time 557 | { 558 | PLI_INT32 type; /* [vpiScaledRealTime, vpiSimTime, 559 | vpiSuppressTime] */ 560 | PLI_UINT32 high, low; /* for vpiSimTime */ 561 | double real; /* for vpiScaledRealTime */ 562 | } s_vpi_time, *p_vpi_time; 563 | 564 | /* time types */ 565 | #define vpiScaledRealTime 1 566 | #define vpiSimTime 2 567 | #define vpiSuppressTime 3 568 | 569 | /**************************** delay structures ****************************/ 570 | typedef struct t_vpi_delay 571 | { 572 | struct t_vpi_time *da; /* pointer to user allocated array of 573 | delay values */ 574 | PLI_INT32 no_of_delays; /* number of delays */ 575 | PLI_INT32 time_type; /* [vpiScaledRealTime, vpiSimTime, 576 | vpiSuppressTime] */ 577 | PLI_INT32 mtm_flag; /* true for mtm values */ 578 | PLI_INT32 append_flag; /* true for append */ 579 | PLI_INT32 pulsere_flag; /* true for pulsere values */ 580 | } s_vpi_delay, *p_vpi_delay; 581 | 582 | /**************************** value structures ****************************/ 583 | /* vector value */ 584 | #ifndef VPI_VECVAL 585 | #define VPI_VECVAL 586 | typedef struct t_vpi_vecval 587 | { 588 | /* following fields are repeated enough times to contain vector */ 589 | #ifdef ABVAL_AS_PLI_INT32_VCS 590 | PLI_INT32 aval, bval; /* bit encoding: 591 | ab: 00=0, 10=1, 11=X, 01=Z */ 592 | #else 593 | PLI_UINT32 aval, bval; 594 | #endif 595 | } s_vpi_vecval, *p_vpi_vecval; 596 | #endif 597 | 598 | /* strength (scalar) value */ 599 | typedef struct t_vpi_strengthval 600 | { 601 | PLI_INT32 logic; /* vpi[0,1,X,Z] */ 602 | PLI_INT32 s0, s1; /* refer to strength coding below */ 603 | } s_vpi_strengthval, *p_vpi_strengthval; 604 | 605 | /* strength values */ 606 | #define vpiSupplyDrive 0x80 607 | #define vpiStrongDrive 0x40 608 | #define vpiPullDrive 0x20 609 | #define vpiWeakDrive 0x08 610 | #define vpiLargeCharge 0x10 611 | #define vpiMediumCharge 0x04 612 | #define vpiSmallCharge 0x02 613 | #define vpiHiZ 0x01 614 | 615 | /* generic value */ 616 | typedef struct t_vpi_value 617 | { 618 | PLI_INT32 format; /* vpi[[Bin,Oct,Dec,Hex]Str,Scalar,Int,Real,String, 619 | Vector,Strength,Suppress,Time,ObjType]Val */ 620 | union 621 | { 622 | PLI_BYTE8 *str; /* string value */ 623 | PLI_INT32 scalar; /* vpi[0,1,X,Z] */ 624 | PLI_INT32 integer; /* integer value */ 625 | double real; /* real value */ 626 | struct t_vpi_time *time; /* time value */ 627 | struct t_vpi_vecval *vector; /* vector value */ 628 | struct t_vpi_strengthval *strength; /* strength value */ 629 | PLI_BYTE8 *misc; /* ... other */ 630 | void *p_agg_value_handle; /* agg valHandle */ 631 | /* Synopsys Internally used by StimGen */ 632 | } value; 633 | } s_vpi_value, *p_vpi_value; 634 | 635 | typedef struct t_vpi_arrayvalue 636 | { 637 | PLI_UINT32 format; /* vpi[Int, Real, Time, ShortInt, LongInt, 638 | ShortReal, RawTwoState, RawFourState]Val */ 639 | PLI_UINT32 flags; /* array bit flags- vpiUserAllocFlag */ 640 | union 641 | { 642 | PLI_INT32 *integers; /* integer values */ 643 | PLI_INT16 *shortints; /* short integer values */ 644 | PLI_INT64 *longints; /* long integer values */ 645 | PLI_BYTE8 *rawvals; /* 2/4 state vector elements */ 646 | struct t_vpi_vecval *vectors; /* 4-state vector elements */ 647 | struct t_vpi_time *times; /* time values */ 648 | double *reals; /* real values */ 649 | float *shortreals; /* short real values */ 650 | } value; 651 | } s_vpi_arrayvalue, *p_vpi_arrayvalue; 652 | 653 | /* value formats */ 654 | #define vpiBinStrVal 1 655 | #define vpiOctStrVal 2 656 | #define vpiDecStrVal 3 657 | #define vpiHexStrVal 4 658 | #define vpiScalarVal 5 659 | #define vpiIntVal 6 660 | #define vpiRealVal 7 661 | #define vpiStringVal 8 662 | #define vpiVectorVal 9 663 | #define vpiStrengthVal 10 664 | #define vpiTimeVal 11 665 | #define vpiObjTypeVal 12 666 | #define vpiSuppressVal 13 667 | #define vpiShortIntVal 14 668 | #define vpiLongIntVal 15 669 | #define vpiShortRealVal 16 670 | #define vpiRawTwoStateVal 17 671 | #define vpiRawFourStateVal 18 672 | 673 | /* delay modes */ 674 | #define vpiNoDelay 1 675 | #define vpiInertialDelay 2 676 | #define vpiTransportDelay 3 677 | #define vpiPureTransportDelay 4 678 | 679 | /* force and release flags */ 680 | #define vpiForceFlag 5 681 | #define vpiReleaseFlag 6 682 | 683 | /* scheduled event cancel flag */ 684 | #define vpiCancelEvent 7 685 | 686 | /* bit mask for the flags argument to vpi_put_value() */ 687 | #define vpiReturnEvent 0x1000 688 | 689 | /* bit flags for vpi_get_value_array flags field */ 690 | #define vpiUserAllocFlag 0x2000 691 | 692 | /* bit flags for vpi_put_value_array flags field */ 693 | #define vpiOneValue 0x4000 694 | #define vpiPropagateOff 0x8000 695 | 696 | /* scalar values */ 697 | #define vpi0 0 698 | #define vpi1 1 699 | #define vpiZ 2 700 | #define vpiX 3 701 | #define vpiH 4 702 | #define vpiL 5 703 | #define vpiDontCare 6 704 | /* 705 | #define vpiNoChange 7 Defined under vpiTchkType, but 706 | can be used here. 707 | */ 708 | 709 | /********************* system task/function structure *********************/ 710 | typedef struct t_vpi_systf_data 711 | { 712 | PLI_INT32 type; /* vpiSysTask, vpiSysFunc */ 713 | PLI_INT32 sysfunctype; /* vpiSysTask, vpi[Int,Real,Time, 714 | Sized, SizedSigned]Func */ 715 | PLI_BYTE8 *tfname; /* first character must be `$' */ 716 | PLI_INT32 (*calltf)(PLI_BYTE8 *); 717 | PLI_INT32 (*compiletf)(PLI_BYTE8 *); 718 | PLI_INT32 (*sizetf)(PLI_BYTE8 *); /* for sized function 719 | callbacks only */ 720 | PLI_BYTE8 *user_data; 721 | } s_vpi_systf_data, *p_vpi_systf_data; 722 | 723 | #define vpiSysTask 1 724 | #define vpiSysFunc 2 725 | 726 | /* the subtypes are defined under the vpiFuncType property */ 727 | 728 | /************* SystemVerilog execution information structure **************/ 729 | 730 | typedef struct t_vpi_vlog_info 731 | { 732 | PLI_INT32 argc; 733 | PLI_BYTE8 **argv; 734 | PLI_BYTE8 *product; 735 | PLI_BYTE8 *version; 736 | } s_vpi_vlog_info, *p_vpi_vlog_info; 737 | 738 | /******************** PLI error information structure *********************/ 739 | typedef struct t_vpi_error_info 740 | { 741 | PLI_INT32 state; /* vpi[Compile,PLI,Run] */ 742 | PLI_INT32 level; /* vpi[Notice,Warning,Error,System,Internal] */ 743 | PLI_BYTE8 *message; 744 | PLI_BYTE8 *product; 745 | PLI_BYTE8 *code; 746 | PLI_BYTE8 *file; 747 | PLI_INT32 line; 748 | } s_vpi_error_info, *p_vpi_error_info; 749 | 750 | /* state when error occurred */ 751 | #define vpiCompile 1 752 | #define vpiPLI 2 753 | #define vpiRun 3 754 | 755 | /* error severity levels */ 756 | 757 | #define vpiNotice 1 758 | #define vpiWarning 2 759 | #define vpiError 3 760 | #define vpiSystem 4 761 | #define vpiInternal 5 762 | 763 | /************************** callback structures ***************************/ 764 | 765 | /* normal callback structure */ 766 | 767 | typedef struct t_cb_data 768 | { 769 | PLI_INT32 reason; /* callback reason */ 770 | PLI_INT32 (*cb_rtn)(struct t_cb_data *); /* call routine */ 771 | vpiHandle obj; /* trigger object */ 772 | p_vpi_time time; /* callback time */ 773 | p_vpi_value value; /* trigger object value */ 774 | PLI_INT32 index; /* index of the memory word or 775 | var select that changed */ 776 | PLI_BYTE8 *user_data; 777 | } s_cb_data, *p_cb_data; 778 | 779 | /**************************** CALLBACK REASONS ****************************/ 780 | /*************************** Simulation related ***************************/ 781 | #define cbValueChange 1 782 | #define cbStmt 2 783 | #define cbForce 3 784 | #define cbRelease 4 785 | 786 | /****************************** Time related ******************************/ 787 | #define cbAtStartOfSimTime 5 788 | #define cbReadWriteSynch 6 789 | #define cbReadOnlySynch 7 790 | #define cbNextSimTime 8 791 | #define cbAfterDelay 9 792 | 793 | /***************************** Action related *****************************/ 794 | #define cbEndOfCompile 10 795 | #define cbStartOfSimulation 11 796 | #define cbEndOfSimulation 12 797 | #define cbError 13 798 | #define cbTchkViolation 14 799 | #define cbStartOfSave 15 800 | #define cbEndOfSave 16 801 | #define cbStartOfRestart 17 802 | #define cbEndOfRestart 18 803 | #define cbStartOfReset 19 804 | #define cbEndOfReset 20 805 | #define cbEnterInteractive 21 806 | #define cbExitInteractive 22 807 | #define cbInteractiveScopeChange 23 808 | #define cbUnresolvedSystf 24 809 | 810 | /************************** Added with 1364-2001 **************************/ 811 | #define cbAssign 25 812 | #define cbDeassign 26 813 | #define cbDisable 27 814 | #define cbPLIError 28 815 | #define cbSignal 29 816 | 817 | /************************** Added with 1364-2005 **************************/ 818 | #define cbNBASynch 30 819 | #define cbAtEndOfSimTime 31 /* As per LRM*/ 820 | 821 | /***************************** Configure Types *****************************/ 822 | #define vpiDisplayErrors 1 823 | #define vpiDisplayWarnings 2 824 | #define vpiDisplayClockOptError 3 825 | #define vpiDeepSearch 4 826 | #define vpiUseExprEvalHooks 5 /* Synopsys VCS internal usage only */ 827 | #define vpiIgnoreErrors 6 /* Synopsys VCS internal usage only */ 828 | #define vpiFindLowPowerDrivers 8 /* Synopsys VCS internal usage only */ 829 | #define vpiIterateOverGeneratedProcesses 9 /* Synopsys VCS internal usage only */ 830 | #define vpiShowPortMismatchDriver 10 /* Synopsys VCS internal usage only */ 831 | /* More configure types for Synopsys VCS internal usage are 832 | * defined in vcs_vpi_user.h: 7, 11-... */ 833 | 834 | 835 | /************************* FUNCTION DECLARATIONS **************************/ 836 | 837 | /* Include compatibility mode macro definitions. */ 838 | /* ---------------------------------------------------------------- */ 839 | /* @TODO :: To uncomment when VCS is ready with vpi_compatibility.h */ 840 | /* funtionality */ 841 | /* #include "vpi_compatibility.h" */ 842 | /* ---------------------------------------------------------------- */ 843 | 844 | /* callback related */ 845 | XXTERN vpiHandle vpi_register_cb PROTO_PARAMS((p_cb_data cb_data_p)); 846 | XXTERN PLI_INT32 vpi_remove_cb PROTO_PARAMS((vpiHandle cb_obj)); 847 | XXTERN void vpi_get_cb_info PROTO_PARAMS((vpiHandle object, 848 | p_cb_data cb_data_p)); 849 | XXTERN vpiHandle vpi_register_systf PROTO_PARAMS((p_vpi_systf_data 850 | systf_data_p)); 851 | XXTERN void vpi_get_systf_info PROTO_PARAMS((vpiHandle object, 852 | p_vpi_systf_data 853 | systf_data_p)); 854 | 855 | /* for obtaining handles */ 856 | XXTERN vpiHandle vpi_handle_by_name PROTO_PARAMS((PLI_BYTE8 *name, 857 | vpiHandle scope)); 858 | XXTERN vpiHandle vpi_handle_by_index PROTO_PARAMS((vpiHandle object, 859 | PLI_INT32 indx)); 860 | 861 | /* for traversing relationships */ 862 | XXTERN vpiHandle vpi_handle PROTO_PARAMS((PLI_INT32 type, 863 | vpiHandle refHandle)); 864 | XXTERN vpiHandle vpi_handle_multi PROTO_PARAMS((PLI_INT32 type, 865 | vpiHandle refHandle1, 866 | vpiHandle refHandle2, 867 | ... )); 868 | XXTERN vpiHandle vpi_iterate PROTO_PARAMS((PLI_INT32 type, 869 | vpiHandle refHandle)); 870 | XXTERN vpiHandle vpi_scan PROTO_PARAMS((vpiHandle iterator)); 871 | 872 | /* for processing properties */ 873 | XXTERN PLI_INT32 vpi_get PROTO_PARAMS((PLI_INT32 property, 874 | vpiHandle object)); 875 | XXTERN PLI_INT64 vpi_get64 PROTO_PARAMS((PLI_INT32 property, 876 | vpiHandle object)); 877 | XXTERN PLI_BYTE8 *vpi_get_str PROTO_PARAMS((PLI_INT32 property, 878 | vpiHandle object)); 879 | 880 | /* delay processing */ 881 | XXTERN void vpi_get_delays PROTO_PARAMS((vpiHandle object, 882 | p_vpi_delay delay_p)); 883 | XXTERN void vpi_put_delays PROTO_PARAMS((vpiHandle object, 884 | p_vpi_delay delay_p)); 885 | 886 | /* value processing */ 887 | XXTERN void vpi_get_value PROTO_PARAMS((vpiHandle expr, 888 | p_vpi_value value_p)); 889 | XXTERN vpiHandle vpi_put_value PROTO_PARAMS((vpiHandle object, 890 | p_vpi_value value_p, 891 | p_vpi_time time_p, 892 | PLI_INT32 flags)); 893 | XXTERN void vpi_get_value_array PROTO_PARAMS((vpiHandle object, 894 | p_vpi_arrayvalue arrayvalue_p, 895 | PLI_INT32 *index_p, 896 | PLI_UINT32 num)); 897 | XXTERN void vpi_put_value_array PROTO_PARAMS((vpiHandle object, 898 | p_vpi_arrayvalue arrayvalue_p, 899 | PLI_INT32 *index_p, 900 | PLI_UINT32 num)); 901 | 902 | /* time processing */ 903 | XXTERN void vpi_get_time PROTO_PARAMS((vpiHandle object, 904 | p_vpi_time time_p)); 905 | 906 | /* I/O routines */ 907 | XXTERN PLI_UINT32 vpi_mcd_open PROTO_PARAMS((PLI_BYTE8 *fileName)); 908 | XXTERN PLI_UINT32 vpi_mcd_close PROTO_PARAMS((PLI_UINT32 mcd)); 909 | XXTERN PLI_BYTE8 *vpi_mcd_name PROTO_PARAMS((PLI_UINT32 cd)); 910 | XXTERN PLI_INT32 vpi_mcd_printf PROTO_PARAMS((PLI_UINT32 mcd, 911 | PLI_BYTE8 *format, 912 | ...)); 913 | XXTERN PLI_INT32 vpi_printf PROTO_PARAMS((PLI_BYTE8 *format, 914 | ...)); 915 | 916 | /* utility routines */ 917 | XXTERN PLI_INT32 vpi_compare_objects PROTO_PARAMS((vpiHandle object1, 918 | vpiHandle object2)); 919 | XXTERN PLI_INT32 vpi_chk_error PROTO_PARAMS((p_vpi_error_info 920 | error_info_p)); 921 | XXTERN PLI_INT32 vpi_configure PROTO_PARAMS((PLI_INT32 item, 922 | PLI_BYTE8 *value)); 923 | 924 | /* vpi_free_object() is deprecated in 1800-2009 */ 925 | XXTERN PLI_INT32 vpi_free_object PROTO_PARAMS((vpiHandle object)); 926 | XXTERN PLI_INT32 vpi_release_handle PROTO_PARAMS((vpiHandle object)); 927 | XXTERN PLI_INT32 vpi_get_vlog_info PROTO_PARAMS((p_vpi_vlog_info 928 | vlog_info_p)); 929 | 930 | /* routines added with 1364-2001 */ 931 | XXTERN PLI_INT32 vpi_get_data PROTO_PARAMS((PLI_INT32 id, 932 | PLI_BYTE8 *dataLoc, 933 | PLI_INT32 numOfBytes)); 934 | XXTERN PLI_INT32 vpi_put_data PROTO_PARAMS((PLI_INT32 id, 935 | PLI_BYTE8 *dataLoc, 936 | PLI_INT32 numOfBytes)); 937 | XXTERN void *vpi_get_userdata PROTO_PARAMS((vpiHandle obj)); 938 | XXTERN PLI_INT32 vpi_put_userdata PROTO_PARAMS((vpiHandle obj, 939 | void *userdata)); 940 | XXTERN PLI_INT32 vpi_vprintf PROTO_PARAMS((PLI_BYTE8 *format, 941 | va_list ap)); 942 | XXTERN PLI_INT32 vpi_mcd_vprintf PROTO_PARAMS((PLI_UINT32 mcd, 943 | PLI_BYTE8 *format, 944 | va_list ap)); 945 | XXTERN PLI_INT32 vpi_flush PROTO_PARAMS((void)); 946 | XXTERN PLI_INT32 vpi_mcd_flush PROTO_PARAMS((PLI_UINT32 mcd)); 947 | XXTERN PLI_INT32 vpi_control PROTO_PARAMS((PLI_INT32 operation, 948 | ...)); 949 | XXTERN vpiHandle vpi_handle_by_multi_index PROTO_PARAMS((vpiHandle obj, 950 | PLI_INT32 num_index, 951 | PLI_INT32 *index_array)); 952 | 953 | /* utility routines */ 954 | XXTERN PLI_INT32 vpi_compare_objects_1364v1995 PROTO_PARAMS((vpiHandle object1, 955 | vpiHandle object2)); 956 | XXTERN PLI_INT32 vpi_control_1364v1995 PROTO_PARAMS((PLI_INT32 operation, 957 | ...)); 958 | /* for processing properties */ 959 | XXTERN PLI_INT32 vpi_get_1364v1995 PROTO_PARAMS((PLI_INT32 property, 960 | vpiHandle object)); 961 | XXTERN PLI_BYTE8 *vpi_get_str_1364v1995 PROTO_PARAMS((PLI_INT32 property, 962 | vpiHandle object)); 963 | /* value processing */ 964 | XXTERN void vpi_get_value_1364v1995 PROTO_PARAMS((vpiHandle expr, 965 | p_vpi_value value_p)); 966 | XXTERN vpiHandle vpi_handle_1364v1995 PROTO_PARAMS((PLI_INT32 type, 967 | vpiHandle refHandle)); 968 | XXTERN vpiHandle vpi_handle_by_index_1364v1995 PROTO_PARAMS((vpiHandle object, 969 | PLI_INT32 indx)); 970 | XXTERN vpiHandle vpi_handle_by_multi_index_1364v1995 PROTO_PARAMS((vpiHandle obj, 971 | PLI_INT32 num_index, 972 | PLI_INT32 *index_array)); 973 | XXTERN vpiHandle vpi_handle_by_name_1364v1995 PROTO_PARAMS((PLI_BYTE8 *name, 974 | vpiHandle scope)); 975 | XXTERN vpiHandle vpi_handle_multi_1364v1995 PROTO_PARAMS((PLI_INT32 type, 976 | vpiHandle refHandle1, 977 | vpiHandle refHandle2, 978 | ... )); 979 | XXTERN vpiHandle vpi_iterate_1364v1995 PROTO_PARAMS((PLI_INT32 type, 980 | vpiHandle refHandle)); 981 | XXTERN vpiHandle vpi_put_value_1364v1995 PROTO_PARAMS((vpiHandle object, 982 | p_vpi_value value_p, 983 | p_vpi_time time_p, 984 | PLI_INT32 flags)); 985 | XXTERN vpiHandle vpi_register_cb_1364v1995 PROTO_PARAMS((p_cb_data cb_data_p)); 986 | XXTERN vpiHandle vpi_scan_1364v1995 PROTO_PARAMS((vpiHandle iterator)); 987 | 988 | 989 | 990 | /* utility routines */ 991 | XXTERN PLI_INT32 vpi_compare_objects_1364v2001 PROTO_PARAMS((vpiHandle object1, 992 | vpiHandle object2)); 993 | XXTERN PLI_INT32 vpi_control_1364v2001 PROTO_PARAMS((PLI_INT32 operation, 994 | ...)); 995 | /* for processing properties */ 996 | XXTERN PLI_INT32 vpi_get_1364v2001 PROTO_PARAMS((PLI_INT32 property, 997 | vpiHandle object)); 998 | XXTERN PLI_BYTE8 *vpi_get_str_1364v2001 PROTO_PARAMS((PLI_INT32 property, 999 | vpiHandle object)); 1000 | /* value processing */ 1001 | XXTERN void vpi_get_value_1364v2001 PROTO_PARAMS((vpiHandle expr, 1002 | p_vpi_value value_p)); 1003 | XXTERN vpiHandle vpi_handle_1364v2001 PROTO_PARAMS((PLI_INT32 type, 1004 | vpiHandle refHandle)); 1005 | XXTERN vpiHandle vpi_handle_by_index_1364v2001 PROTO_PARAMS((vpiHandle object, 1006 | PLI_INT32 indx)); 1007 | XXTERN vpiHandle vpi_handle_by_multi_index_1364v2001 PROTO_PARAMS((vpiHandle obj, 1008 | PLI_INT32 num_index, 1009 | PLI_INT32 *index_array)); 1010 | XXTERN vpiHandle vpi_handle_by_name_1364v2001 PROTO_PARAMS((PLI_BYTE8 *name, 1011 | vpiHandle scope)); 1012 | XXTERN vpiHandle vpi_handle_multi_1364v2001 PROTO_PARAMS((PLI_INT32 type, 1013 | vpiHandle refHandle1, 1014 | vpiHandle refHandle2, 1015 | ... )); 1016 | XXTERN vpiHandle vpi_iterate_1364v2001 PROTO_PARAMS((PLI_INT32 type, 1017 | vpiHandle refHandle)); 1018 | XXTERN vpiHandle vpi_put_value_1364v2001 PROTO_PARAMS((vpiHandle object, 1019 | p_vpi_value value_p, 1020 | p_vpi_time time_p, 1021 | PLI_INT32 flags)); 1022 | XXTERN vpiHandle vpi_register_cb_1364v2001 PROTO_PARAMS((p_cb_data cb_data_p)); 1023 | XXTERN vpiHandle vpi_scan_1364v2001 PROTO_PARAMS((vpiHandle iterator)); 1024 | 1025 | /* utility routines */ 1026 | XXTERN PLI_INT32 vpi_compare_objects_1364v2005 PROTO_PARAMS((vpiHandle object1, 1027 | vpiHandle object2)); 1028 | XXTERN PLI_INT32 vpi_control_1364v2005 PROTO_PARAMS((PLI_INT32 operation, ...)); 1029 | /* for processing properties */ 1030 | XXTERN PLI_INT32 vpi_get_1364v2005 PROTO_PARAMS((PLI_INT32 property, 1031 | vpiHandle object)); 1032 | XXTERN PLI_BYTE8 *vpi_get_str_1364v2005 PROTO_PARAMS((PLI_INT32 property, 1033 | vpiHandle object)); 1034 | /* value processing */ 1035 | XXTERN void vpi_get_value_1364v2005 PROTO_PARAMS((vpiHandle expr, 1036 | p_vpi_value value_p)); 1037 | XXTERN vpiHandle vpi_handle_1364v2005 PROTO_PARAMS((PLI_INT32 type, 1038 | vpiHandle refHandle)); 1039 | XXTERN vpiHandle vpi_handle_by_index_1364v2005 PROTO_PARAMS((vpiHandle object, 1040 | PLI_INT32 indx)); 1041 | XXTERN vpiHandle vpi_handle_by_multi_index_1364v2005 PROTO_PARAMS((vpiHandle obj, 1042 | PLI_INT32 num_index, 1043 | PLI_INT32 *index_array)); 1044 | XXTERN vpiHandle vpi_handle_by_name_1364v2005 PROTO_PARAMS((PLI_BYTE8 *name, 1045 | vpiHandle scope)); 1046 | XXTERN vpiHandle vpi_handle_multi_1364v2005 PROTO_PARAMS((PLI_INT32 type, 1047 | vpiHandle refHandle1, 1048 | vpiHandle refHandle2, 1049 | ... )); 1050 | XXTERN vpiHandle vpi_iterate_1364v2005 PROTO_PARAMS((PLI_INT32 type, 1051 | vpiHandle refHandle)); 1052 | XXTERN vpiHandle vpi_put_value_1364v2005 PROTO_PARAMS((vpiHandle object, 1053 | p_vpi_value value_p, 1054 | p_vpi_time time_p, 1055 | PLI_INT32 flags)); 1056 | XXTERN vpiHandle vpi_register_cb_1364v2005 PROTO_PARAMS((p_cb_data cb_data_p)); 1057 | XXTERN vpiHandle vpi_scan_1364v2005 PROTO_PARAMS((vpiHandle iterator)); 1058 | 1059 | /* utility routines */ 1060 | XXTERN PLI_INT32 vpi_compare_objects_1800v2005 PROTO_PARAMS((vpiHandle object1, 1061 | vpiHandle object2)); 1062 | XXTERN PLI_INT32 vpi_control_1800v2005 PROTO_PARAMS((PLI_INT32 operation, 1063 | ...)); 1064 | /* for processing properties */ 1065 | XXTERN PLI_INT32 vpi_get_1800v2005 PROTO_PARAMS((PLI_INT32 property, 1066 | vpiHandle object)); 1067 | XXTERN PLI_BYTE8 *vpi_get_str_1800v2005 PROTO_PARAMS((PLI_INT32 property, 1068 | vpiHandle object)); 1069 | /* value processing */ 1070 | XXTERN void vpi_get_value_1800v2005 PROTO_PARAMS((vpiHandle expr, 1071 | p_vpi_value value_p)); 1072 | XXTERN vpiHandle vpi_handle_1800v2005 PROTO_PARAMS((PLI_INT32 type, 1073 | vpiHandle refHandle)); 1074 | XXTERN vpiHandle vpi_handle_by_index_1800v2005 PROTO_PARAMS((vpiHandle object, 1075 | PLI_INT32 indx)); 1076 | XXTERN vpiHandle vpi_handle_by_multi_index_1800v2005 PROTO_PARAMS((vpiHandle obj, 1077 | PLI_INT32 num_index, 1078 | PLI_INT32 *index_array)); 1079 | XXTERN vpiHandle vpi_handle_by_name_1800v2005 PROTO_PARAMS((PLI_BYTE8 *name, 1080 | vpiHandle scope)); 1081 | XXTERN vpiHandle vpi_handle_multi_1800v2005 PROTO_PARAMS((PLI_INT32 type, 1082 | vpiHandle refHandle1, 1083 | vpiHandle refHandle2, 1084 | ... )); 1085 | XXTERN vpiHandle vpi_iterate_1800v2005 PROTO_PARAMS((PLI_INT32 type, 1086 | vpiHandle refHandle)); 1087 | XXTERN vpiHandle vpi_put_value_1800v2005 PROTO_PARAMS((vpiHandle object, 1088 | p_vpi_value value_p, 1089 | p_vpi_time time_p, 1090 | PLI_INT32 flags)); 1091 | XXTERN vpiHandle vpi_register_cb_1800v2005 PROTO_PARAMS((p_cb_data cb_data_p)); 1092 | XXTERN vpiHandle vpi_scan_1800v2005 PROTO_PARAMS((vpiHandle iterator)); 1093 | 1094 | 1095 | 1096 | /* utility routines */ 1097 | XXTERN PLI_INT32 vpi_compare_objects_1800v2009 PROTO_PARAMS((vpiHandle object1, 1098 | vpiHandle object2)); 1099 | XXTERN PLI_INT32 vpi_control_1800v2009 PROTO_PARAMS((PLI_INT32 operation, 1100 | ...)); 1101 | /* for processing properties */ 1102 | XXTERN PLI_INT32 vpi_get_1800v2009 PROTO_PARAMS((PLI_INT32 property, 1103 | vpiHandle object)); 1104 | XXTERN PLI_BYTE8 *vpi_get_str_1800v2009 PROTO_PARAMS((PLI_INT32 property, 1105 | vpiHandle object)); 1106 | /* value processing */ 1107 | XXTERN void vpi_get_value_1800v2009 PROTO_PARAMS((vpiHandle expr, 1108 | p_vpi_value value_p)); 1109 | XXTERN vpiHandle vpi_handle_1800v2009 PROTO_PARAMS((PLI_INT32 type, 1110 | vpiHandle refHandle)); 1111 | XXTERN vpiHandle vpi_handle_by_index_1800v2009 PROTO_PARAMS((vpiHandle object, 1112 | PLI_INT32 indx)); 1113 | XXTERN vpiHandle vpi_handle_by_multi_index_1800v2009 PROTO_PARAMS((vpiHandle obj, 1114 | PLI_INT32 num_index, 1115 | PLI_INT32 *index_array)); 1116 | XXTERN vpiHandle vpi_handle_by_name_1800v2009 PROTO_PARAMS((PLI_BYTE8 *name, 1117 | vpiHandle scope)); 1118 | XXTERN vpiHandle vpi_handle_multi_1800v2009 PROTO_PARAMS((PLI_INT32 type, 1119 | vpiHandle refHandle1, 1120 | vpiHandle refHandle2, 1121 | ... )); 1122 | XXTERN vpiHandle vpi_iterate_1800v2009 PROTO_PARAMS((PLI_INT32 type, 1123 | vpiHandle refHandle)); 1124 | XXTERN vpiHandle vpi_put_value_1800v2009 PROTO_PARAMS((vpiHandle object, 1125 | p_vpi_value value_p, 1126 | p_vpi_time time_p, 1127 | PLI_INT32 flags)); 1128 | XXTERN vpiHandle vpi_register_cb_1800v2009 PROTO_PARAMS((p_cb_data cb_data_p)); 1129 | XXTERN vpiHandle vpi_scan_1800v2009 PROTO_PARAMS((vpiHandle iterator)); 1130 | 1131 | /**************************** GLOBAL VARIABLES ****************************/ 1132 | PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])(); 1133 | 1134 | /* array of function pointers, last pointer should be null */ 1135 | 1136 | #undef PLI_EXTERN 1137 | #undef PLI_VEXTERN 1138 | 1139 | #ifdef VPI_USER_DEFINED_DLLISPEC 1140 | #undef VPI_USER_DEFINED_DLLISPEC 1141 | #undef PLI_DLLISPEC 1142 | #endif 1143 | #ifdef VPI_USER_DEFINED_DLLESPEC 1144 | #undef VPI_USER_DEFINED_DLLESPEC 1145 | #undef PLI_DLLESPEC 1146 | #endif 1147 | 1148 | #ifdef PLI_PROTOTYPES 1149 | #undef PLI_PROTOTYPES 1150 | #undef PROTO_PARAMS 1151 | #undef XXTERN 1152 | #undef EETERN 1153 | #endif 1154 | 1155 | #ifdef __cplusplus 1156 | } 1157 | #endif 1158 | 1159 | #endif /* VPI_USER_H */ 1160 | #endif /* _LIB_VPI_USER_H */ 1161 | --------------------------------------------------------------------------------