[Modified] rm redundant files
This commit is contained in:
@@ -1,74 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.12)
|
|
||||||
cmake_policy(SET CMP0074 NEW)
|
|
||||||
project(neula)
|
|
||||||
|
|
||||||
# 为 Verilator 设置环境变量
|
|
||||||
if(NOT DEFINED VERILATOR_ROOT)
|
|
||||||
set(ENV{VERILATOR_ROOT} "/home/blur/gits/verilator")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# 设置 Verilator 头文件目录
|
|
||||||
include_directories($ENV{VERILATOR_ROOT}/include)
|
|
||||||
|
|
||||||
# 设置编译器参数
|
|
||||||
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
|
||||||
message("Turn On Debugger")
|
|
||||||
add_compile_options(-D DEBUG_MODE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
|
||||||
|
|
||||||
# ----- ----- 构建虚拟外设 ----- -----
|
|
||||||
set(LABUS labus)
|
|
||||||
set(LA_BUS_TARGET ${PROJECT_NAME}-bus)
|
|
||||||
|
|
||||||
# 包含头文件,以可以利用尖括号获取,辅助队友开发
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/${LABUS}/include)
|
|
||||||
|
|
||||||
# 获取所有的 CXX 源文件
|
|
||||||
file(GLOB_RECURSE LABUS_SRC ${CMAKE_SOURCE_DIR}/${LABUS}/*.cc)
|
|
||||||
|
|
||||||
add_library(${LA_BUS_TARGET} ${LABUS_SRC})
|
|
||||||
link_libraries(${LA_BUS_TARGET})
|
|
||||||
|
|
||||||
|
|
||||||
# ----- ----- 构建虚拟处理器 ----- -----
|
|
||||||
set(LASIM lasim)
|
|
||||||
set(LA_SIM_TARGET ${PROJECT_NAME}-sim)
|
|
||||||
|
|
||||||
# 包含头文件,以可以利用尖括号获取,辅助队友开发
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/${LASIM}/include)
|
|
||||||
|
|
||||||
# 获取所有的 CXX 源文件
|
|
||||||
file(GLOB_RECURSE LASIM_SRC ${CMAKE_SOURCE_DIR}/${LASIM}/*.cc)
|
|
||||||
|
|
||||||
add_executable(${LA_SIM_TARGET} ${LASIM_SRC})
|
|
||||||
|
|
||||||
|
|
||||||
# ----- ----- 构建操作系统 ----- -----
|
|
||||||
set(LAOS laos)
|
|
||||||
# add_custom_target(${LAOS} make build)
|
|
||||||
|
|
||||||
|
|
||||||
# ----- ----- 构建 Verilator 项目 ----- -----
|
|
||||||
# set(LACPU lacpu)
|
|
||||||
# set(LAVSIM lavsim)
|
|
||||||
# set(LA_VSIM_TARGET ${PROJECT_NAME}-vsim)
|
|
||||||
|
|
||||||
# find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT})
|
|
||||||
|
|
||||||
# if (NOT verilator_FOUND)
|
|
||||||
# message(FATAL_ERROR "Verilator was not found.")
|
|
||||||
# endif()
|
|
||||||
|
|
||||||
# # set default top module as top file
|
|
||||||
# set(VSRC ${CMAKE_SOURCE_DIR}/${LACPU}/rtl/soc_lite_top.v)
|
|
||||||
|
|
||||||
# # get all cxx source files from lavsim folder
|
|
||||||
# file(GLOB_RECURSE LAVSIM_SRC ${CMAKE_SOURCE_DIR}/${LAVSIM}/*.cc)
|
|
||||||
|
|
||||||
# add_executable(${LA_VSIM_TARGET} ${LAVSIM_SRC})
|
|
||||||
|
|
||||||
# verilate(${LA_VSIM_TARGET}
|
|
||||||
# INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/${LACPU}/rtl/cpu ${VERILATOR_ROOT}/include
|
|
||||||
# SOURCES ${VSRC})
|
|
||||||
24
README.md
24
README.md
@@ -7,27 +7,3 @@
|
|||||||
|文件夹名称|文件夹用处|
|
|文件夹名称|文件夹用处|
|
||||||
|-|-|
|
|-|-|
|
||||||
|lacpu | 龙芯处理器设计 Verilog |
|
|lacpu | 龙芯处理器设计 Verilog |
|
||||||
|lasim | 龙芯模拟 软件模拟 C++ |
|
|
||||||
|lavsim | 龙芯模拟 Verilator 模拟 |
|
|
||||||
|labus | 龙芯虚拟外设 |
|
|
||||||
|laos | 龙芯操作系统 |
|
|
||||||
|
|
||||||
除了 `lavsim` 和 `lacpu` 是在一起编译成一个文件,其余都会编译成单独的二进制文件
|
|
||||||
|
|
||||||
### lacpu
|
|
||||||
|
|
||||||
### lasim
|
|
||||||
|
|
||||||
`lasim` 模拟龙芯行为,主要用于操作系统的软件模拟,通过软件角度对龙芯的基本硬件特性进行模拟,以辅助操作系统设计。
|
|
||||||
|
|
||||||
### lavsim
|
|
||||||
|
|
||||||
`lavsim` 主要用于测试 Verilog 设计的正确性。
|
|
||||||
|
|
||||||
### labus
|
|
||||||
|
|
||||||
`labus` 模拟外设行为,主要用于设计虚拟外设以软件模拟外设行为是否正确。
|
|
||||||
|
|
||||||
### laos
|
|
||||||
|
|
||||||
`laos` 自主设计操作系统,会参考其他项目进行设计。
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <ctime>
|
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#ifndef COMMON_H__
|
|
||||||
#define COMMON_H__
|
|
||||||
|
|
||||||
#ifdef DEBUG_MODE
|
|
||||||
#define Log(fmt, ...) printf("[%s:%d %ld] " fmt "\n", __FILE__, __LINE__, clock(), ## __VA_ARGS__)
|
|
||||||
|
|
||||||
#define panic(x) do { \
|
|
||||||
Log(x); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define panicifnot(cond) do { \
|
|
||||||
if (!(cond)) { \
|
|
||||||
Log(#cond " fail"); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define Log(...)
|
|
||||||
#define panic(x)
|
|
||||||
#define panicifnot(cond)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef DEVADDR_H__
|
|
||||||
#define DEVADDR_H__
|
|
||||||
|
|
||||||
#define RAM_ADDR 0x0000'0000
|
|
||||||
#define RST_ADDR 0x1c00'0000
|
|
||||||
|
|
||||||
#define HEAP_ADDR 0x2000'0000
|
|
||||||
#define HEAP_SIZE 0x0020'0000
|
|
||||||
#define STAK_SIZE 0x0002'0000
|
|
||||||
#define STAK_ADDR (HEAP_ADDR + HEAP_SIZE + STAK_SIZE)
|
|
||||||
|
|
||||||
#define DEVICE_BASE 0xa0000000
|
|
||||||
#define MMIO_BASE 0xa0000000
|
|
||||||
|
|
||||||
#define SERIAL_PORT (DEVICE_BASE + 0x00003f8)
|
|
||||||
#define KBD_ADDR (DEVICE_BASE + 0x0000060)
|
|
||||||
#define RTC_ADDR (DEVICE_BASE + 0x0000048)
|
|
||||||
#define VGACTL_ADDR (DEVICE_BASE + 0x0000100)
|
|
||||||
#define AUDIO_ADDR (DEVICE_BASE + 0x0000200)
|
|
||||||
#define DISK_ADDR (DEVICE_BASE + 0x0000300)
|
|
||||||
#define FB_ADDR (MMIO_BASE + 0x1000000)
|
|
||||||
#define AUDIO_SBUF_ADDR (MMIO_BASE + 0x1200000)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#include <device.hh>
|
|
||||||
|
|
||||||
Device::Device(bool cacheable): cacheable_(cacheable) {}
|
|
||||||
|
|
||||||
bool Device::is_cacheable() { return cacheable_; }
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
|
|
||||||
class Device {
|
|
||||||
protected:
|
|
||||||
bool cacheable_ = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Device(bool cacheable);
|
|
||||||
|
|
||||||
bool is_cacheable();
|
|
||||||
|
|
||||||
virtual const size_t &size() const = 0;
|
|
||||||
|
|
||||||
virtual void write(char *buf, size_t addr, size_t len) = 0;
|
|
||||||
virtual void read(char *buf, size_t addr, size_t len) = 0;
|
|
||||||
|
|
||||||
virtual void write64(uint64_t &dword, size_t addr) = 0;
|
|
||||||
virtual void read64(uint64_t &dword, size_t addr) = 0;
|
|
||||||
|
|
||||||
virtual void write32(uint32_t &word, size_t addr) = 0;
|
|
||||||
virtual void read32(uint32_t &word, size_t addr) = 0;
|
|
||||||
|
|
||||||
virtual void write16(uint16_t &hword, size_t addr) = 0;
|
|
||||||
virtual void read16(uint16_t &hword, size_t addr) = 0;
|
|
||||||
|
|
||||||
virtual void write8(uint8_t &byte, size_t addr) = 0;
|
|
||||||
virtual void read8(uint8_t &byte, size_t addr) = 0;
|
|
||||||
|
|
||||||
virtual ~Device() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class WRDevice : public Device{
|
|
||||||
protected:
|
|
||||||
size_t devsiz;
|
|
||||||
|
|
||||||
public:
|
|
||||||
WRDevice(size_t siz);
|
|
||||||
|
|
||||||
virtual const size_t &size() const;
|
|
||||||
|
|
||||||
virtual void write(char *buf, size_t addr, size_t len);
|
|
||||||
virtual void read(char *buf, size_t addr, size_t len);
|
|
||||||
|
|
||||||
virtual void write64(uint64_t &dword, size_t addr);
|
|
||||||
virtual void read64(uint64_t &dword, size_t addr);
|
|
||||||
|
|
||||||
virtual void write32(uint32_t &word, size_t addr);
|
|
||||||
virtual void read32(uint32_t &word, size_t addr);
|
|
||||||
|
|
||||||
virtual void write16(uint16_t &hword, size_t addr);
|
|
||||||
virtual void read16(uint16_t &hword, size_t addr);
|
|
||||||
|
|
||||||
virtual void write8(uint8_t &byte, size_t addr);
|
|
||||||
virtual void read8(uint8_t &byte, size_t addr);
|
|
||||||
|
|
||||||
virtual ~WRDevice() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
WRDevice<T>::WRDevice(size_t siz) : devsiz(siz) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
const size_t &WRDevice<T>::size() const { return devsiz; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::write(char *buf, size_t addr, size_t len) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::read(char *buf, size_t addr, size_t len) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::write64(uint64_t &dword, size_t addr) {
|
|
||||||
uint8_t buf[sizeof(dword)];
|
|
||||||
buf[0] = (dword >> 0) & 0xFF;
|
|
||||||
buf[1] = (dword >> 8) & 0xFF;
|
|
||||||
buf[2] = (dword >> 16) & 0xFF;
|
|
||||||
buf[3] = (dword >> 24) & 0xFF;
|
|
||||||
buf[4] = (dword >> 32) & 0xFF;
|
|
||||||
buf[5] = (dword >> 40) & 0xFF;
|
|
||||||
buf[6] = (dword >> 48) & 0xFF;
|
|
||||||
buf[7] = (dword >> 56) & 0xFF;
|
|
||||||
static_cast<T *>(this)->write((char *)buf, addr, sizeof(dword));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::read64(uint64_t &dword, size_t addr) {
|
|
||||||
uint8_t buf[sizeof(dword)];
|
|
||||||
static_cast<T *>(this)->read((char *)buf, addr, sizeof(dword));
|
|
||||||
dword = (uint64_t) buf[0];
|
|
||||||
dword |= (uint64_t) buf[1] << 8;
|
|
||||||
dword |= (uint64_t) buf[2] << 16;
|
|
||||||
dword |= (uint64_t) buf[3] << 24;
|
|
||||||
dword |= (uint64_t) buf[4] << 32;
|
|
||||||
dword |= (uint64_t) buf[5] << 40;
|
|
||||||
dword |= (uint64_t) buf[6] << 48;
|
|
||||||
dword |= (uint64_t) buf[7] << 56;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::write32(uint32_t &word, size_t addr) {
|
|
||||||
uint8_t buf[sizeof(word)];
|
|
||||||
buf[0] = (word >> 0) & 0xFF;
|
|
||||||
buf[1] = (word >> 8) & 0xFF;
|
|
||||||
buf[2] = (word >> 16) & 0xFF;
|
|
||||||
buf[3] = (word >> 24) & 0xFF;
|
|
||||||
static_cast<T *>(this)->write((char *)buf, addr, sizeof(word));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::read32(uint32_t &word, size_t addr) {
|
|
||||||
uint8_t buf[sizeof(word)];
|
|
||||||
static_cast<T *>(this)->read((char *)buf, addr, sizeof(word));
|
|
||||||
word = (uint32_t) buf[0];
|
|
||||||
word |= (uint32_t) buf[1] << 8;
|
|
||||||
word |= (uint32_t) buf[2] << 16;
|
|
||||||
word |= (uint32_t) buf[3] << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::write16(uint16_t &hword, size_t addr) {
|
|
||||||
uint8_t buf[sizeof(hword)];
|
|
||||||
buf[0] = (hword >> 0) & 0xFF;
|
|
||||||
buf[1] = (hword >> 8) & 0xFF;
|
|
||||||
static_cast<T *>(this)->write((char *)buf, addr, sizeof(hword));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::read16(uint16_t &hword, size_t addr) {
|
|
||||||
uint8_t buf[sizeof(hword)];
|
|
||||||
static_cast<T *>(this)->read((char *)buf, addr, sizeof(hword));
|
|
||||||
hword = (uint16_t) buf[0];
|
|
||||||
hword |= (uint16_t) buf[1] << 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::write8(uint8_t &byte, size_t addr) {
|
|
||||||
static_cast<T *>(this)->write((char *)&byte, addr, sizeof(byte));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void WRDevice<T>::read8(uint8_t &byte, size_t addr) {
|
|
||||||
static_cast<T *>(this)->read((char *)&byte, addr, sizeof(byte));
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <device.hh>
|
|
||||||
|
|
||||||
class Memory : public WRDevice<Memory> {
|
|
||||||
char *data;
|
|
||||||
bool wen;
|
|
||||||
bool ren;
|
|
||||||
bool xen;
|
|
||||||
public:
|
|
||||||
Memory(size_t siz, bool w = true, bool r = true, bool x = true);
|
|
||||||
~Memory();
|
|
||||||
|
|
||||||
void load(const char *path);
|
|
||||||
void load(Memory *mem, size_t addr, size_t len);
|
|
||||||
|
|
||||||
void write(char *buf, size_t addr, size_t len);
|
|
||||||
void read(char *buf, size_t addr, size_t len);
|
|
||||||
};
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <device.hh>
|
|
||||||
|
|
||||||
class Serial : public WRDevice<Serial> {
|
|
||||||
public:
|
|
||||||
Serial(size_t siz);
|
|
||||||
|
|
||||||
void write(char *buf, size_t addr, size_t len);
|
|
||||||
};
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <device.hh>
|
|
||||||
|
|
||||||
class SystemBus {
|
|
||||||
std::map<uint64_t, Device *> iomap_;
|
|
||||||
|
|
||||||
std::pair<const uint64_t, Device *> &finddev(uint64_t addr);
|
|
||||||
|
|
||||||
public:
|
|
||||||
SystemBus() = default;
|
|
||||||
|
|
||||||
void regdev(Device *dev, uint64_t addr);
|
|
||||||
|
|
||||||
void write(char *buf, size_t addr, size_t len);
|
|
||||||
void read(char *buf, size_t addr, size_t len);
|
|
||||||
|
|
||||||
void write64(uint64_t &dword, size_t addr);
|
|
||||||
void read64(uint64_t &dword, size_t addr);
|
|
||||||
|
|
||||||
void write32(uint32_t &word, size_t addr);
|
|
||||||
void read32(uint32_t &word, size_t addr);
|
|
||||||
|
|
||||||
void write16(uint16_t &hword, size_t addr);
|
|
||||||
void read16(uint16_t &hword, size_t addr);
|
|
||||||
|
|
||||||
void write8(uint8_t &byte, size_t addr);
|
|
||||||
void read8(uint8_t &byte, size_t addr);
|
|
||||||
};
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#include <memory.hh>
|
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
Memory::Memory(size_t siz, bool w, bool r, bool x)
|
|
||||||
: WRDevice(siz), wen(w), ren(r), xen(x) {
|
|
||||||
data = new char[siz];
|
|
||||||
memset((void *)data, 0, siz);
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory::~Memory() {
|
|
||||||
if (data) {
|
|
||||||
delete [] data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::load(const char *path) {
|
|
||||||
std::fstream ifs(path, std::ios::in | std::ios::binary);
|
|
||||||
panicifnot(ifs);
|
|
||||||
ifs.read(data, this->size());
|
|
||||||
ifs.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::load(Memory *mem, size_t addr, size_t len) {
|
|
||||||
panicifnot(addr + len < this->size());
|
|
||||||
memcpy(&data[addr], mem->data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::write(char *buf, size_t addr, size_t len) {
|
|
||||||
if (!wen)
|
|
||||||
panic("permission denied");
|
|
||||||
size_t actlen = addr + len >= this->size() ? this->size() - addr : len;
|
|
||||||
memcpy(&data[addr], buf, actlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::read(char *buf, size_t addr, size_t len) {
|
|
||||||
if (!ren)
|
|
||||||
panic("permission denied");
|
|
||||||
size_t actlen = addr + len >= this->size() ? this->size() - addr : len;
|
|
||||||
memcpy(buf, &data[addr], actlen);
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#include <serial.hh>
|
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
Serial::Serial(size_t siz) : WRDevice(siz) {}
|
|
||||||
|
|
||||||
void Serial::write(char *buf, size_t addr, size_t len) {
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
putc(buf[i], stdout);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#include <sysbus.hh>
|
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
std::pair<const uint64_t, Device *> &SystemBus::finddev(uint64_t addr) {
|
|
||||||
Device *dev = nullptr;
|
|
||||||
auto &&iter = iomap_.upper_bound(addr);
|
|
||||||
if (iter == iomap_.begin())
|
|
||||||
panic("device not found");
|
|
||||||
iter--;
|
|
||||||
if (iter->first <= addr && iter->first + iter->second->size() > addr)
|
|
||||||
dev = iter->second;
|
|
||||||
panicifnot(dev);
|
|
||||||
return *iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::regdev(Device *dev, uint64_t addr) { iomap_.emplace(addr, dev); }
|
|
||||||
|
|
||||||
void SystemBus::write(char *buf, size_t addr, size_t len) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->write(buf, addr - dev.first, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::read(char *buf, size_t addr, size_t len) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->read(buf, addr - dev.first, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::write64(uint64_t &dword, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->write64(dword, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::read64(uint64_t &dword, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->read64(dword, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::write32(uint32_t &word, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->write32(word, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::read32(uint32_t &word, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->read32(word, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::write16(uint16_t &hword, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->write16(hword, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::read16(uint16_t &hword, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->read16(hword, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::write8(uint8_t &byte, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->write8(byte, addr - dev.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemBus::read8(uint8_t &byte, size_t addr) {
|
|
||||||
auto &&dev = finddev(addr);
|
|
||||||
dev.second->read8(byte, addr - dev.first);
|
|
||||||
}
|
|
||||||
1
laos/.gitignore
vendored
1
laos/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
build/
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
LA_BIN_PATH := $(CURDIR)/../ext/loongarch32r-linux-gnusf-2022-05-20/bin
|
|
||||||
LA_PREFIX := loongarch32r-linux-gnusf-
|
|
||||||
|
|
||||||
CC := $(LA_BIN_PATH)/$(LA_PREFIX)gcc
|
|
||||||
CXX := $(LA_BIN_PATH)/$(LA_PREFIX)g++
|
|
||||||
OD := $(LA_BIN_PATH)/$(LA_PREFIX)objdump
|
|
||||||
OC := $(LA_BIN_PATH)/$(LA_PREFIX)objcopy
|
|
||||||
RE := $(LA_BIN_PATH)/$(LA_PREFIX)readelf
|
|
||||||
|
|
||||||
NPROC := $(shell nproc)
|
|
||||||
|
|
||||||
CMAKE := cmake
|
|
||||||
|
|
||||||
BUILD_DIR := build
|
|
||||||
ABS_BUILD := $(CURDIR)/$(BUILD_DIR)
|
|
||||||
$(shell mkdir -p $(BUILD_DIR))
|
|
||||||
|
|
||||||
BIN := neula-os
|
|
||||||
BINARY := $(BUILD_DIR)/$(BIN)
|
|
||||||
|
|
||||||
TOP_SRC_DIR := src
|
|
||||||
MODULES := kernel util
|
|
||||||
SOURCE_DIRS := $(addprefix $(TOP_SRC_DIR)/,$(MODULES))
|
|
||||||
MK_DIRS := $(addprefix MAKE/,$(SOURCE_DIRS))
|
|
||||||
ALL_SRCS := $(shell find . -name '*.c')
|
|
||||||
LD_CSRIPT := kernel.ld
|
|
||||||
|
|
||||||
EXTRA_MACRO := # NDEBUG
|
|
||||||
|
|
||||||
EXTRA_FLAGS = -Wall -Werror -O0 -fno-omit-frame-pointer -ggdb -gdwarf-2
|
|
||||||
EXTRA_FLAGS += -mfpu=none -march=loongarch32r -mabi=ilp32s
|
|
||||||
EXTRA_FLAGS += -MD
|
|
||||||
EXTRA_FLAGS += -ffreestanding -fno-common -nostdlib
|
|
||||||
EXTRA_FLAGS += -I.
|
|
||||||
EXTRA_FLAGS += -fno-pie -no-pie
|
|
||||||
EXTRA_FLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
|
|
||||||
|
|
||||||
COMMONFLAGS := $(EXTRA_FLAGS)
|
|
||||||
CPPFLAGS += $(addprefix -D,$(EXTRA_MACRO)) -I$(CURDIR)/include
|
|
||||||
CFLAGS += $(COMMONFLAGS)
|
|
||||||
LDFLAGS += $(COMMONFLAGS) -z max-page-size=4096 -T$(LD_CSRIPT)
|
|
||||||
|
|
||||||
.PHONY: all build clean
|
|
||||||
|
|
||||||
all: build
|
|
||||||
|
|
||||||
$(MK_DIRS): MAKE/%:% $(shell find $(%) -name '*.c')
|
|
||||||
@TOP_BUILD_DIR=$(ABS_BUILD) \
|
|
||||||
CC=$(CC) \
|
|
||||||
CPPFLAGS="$(CPPFLAGS)" \
|
|
||||||
CFLAGS="$(CFLAGS)" \
|
|
||||||
LDFLAGS="$(LDFLAGS)" \
|
|
||||||
$(MAKE) -C $< -j$(NPROC)
|
|
||||||
|
|
||||||
build: $(MK_DIRS)
|
|
||||||
@$(CC) -o $(BINARY) $(shell find $(BUILD_DIR) -name '*.o') $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
|
||||||
@$(OD) -D $(BINARY) > $(BINARY).dump
|
|
||||||
@$(RE) -a $(BINARY) > $(BINARY).info
|
|
||||||
@$(OC) $(BINARY) -O binary $(BINARY).bin
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(BUILD_DIR)
|
|
||||||
|
|
||||||
|
|
||||||
# use native
|
|
||||||
|
|
||||||
clean-usr:
|
|
||||||
rm -rf $(BUILD_DIR)/user
|
|
||||||
|
|
||||||
usr:
|
|
||||||
@TOP_BUILD_DIR=$(ABS_BUILD) \
|
|
||||||
CPPFLAGS="$(CPPFLAGS)" \
|
|
||||||
$(MAKE) native -C $(TOP_SRC_DIR)/user -j$(NPROC)
|
|
||||||
|
|
||||||
tcpl:
|
|
||||||
$(CC) --target-help
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#include "defs.h"
|
|
||||||
|
|
||||||
#ifndef ASM_H__
|
|
||||||
#define ASM_H__
|
|
||||||
|
|
||||||
// CSR infos
|
|
||||||
#define CRMD 0x000 /* 当前模式信息 */
|
|
||||||
#define PRMD 0x001 /* 例外前模式信息 */
|
|
||||||
#define EUEN 0x002 /* 拓展部件使能 */
|
|
||||||
#define ECFG 0x004 /* 例外配置 */
|
|
||||||
#define ESTAT 0x005 /* 例外状态 */
|
|
||||||
#define ERA 0x006 /* 例外返回地址 */
|
|
||||||
#define BADV 0x007 /* 出错虚地址 */
|
|
||||||
#define EENTRY 0x00c /* 例外地址入口 */
|
|
||||||
#define TLBIDX 0x010 /* TLB 索引 */
|
|
||||||
#define TLBEHI 0x011 /* TLB 表项高位 */
|
|
||||||
#define TLBELO0 0x012 /* TLB 表项低位 0 */
|
|
||||||
#define TLBELO1 0x013 /* TLB 表项低位 1 */
|
|
||||||
#define ASID 0x018 /* 地址空间标识符 */
|
|
||||||
#define PGDL 0x019 /* 低半地址空间全局目录基址 */
|
|
||||||
#define PGDH 0x01a /* 高半地址空间全局目录基址 */
|
|
||||||
#define PGD 0x01b /* 全局目录基址 */
|
|
||||||
#define CPUID 0x020 /* 处理器编号 */
|
|
||||||
#define SAVE0 0x030 /* 数据保存 0*/
|
|
||||||
#define SAVE1 0x031 /* 数据保存 1*/
|
|
||||||
#define SAVE2 0x032 /* 数据保存 2 */
|
|
||||||
#define SAVE3 0x033 /* 数据保存 3 */
|
|
||||||
#define TID 0x040 /* 定时器编号 */
|
|
||||||
#define TCFG 0x041 /* 定时器配置 */
|
|
||||||
#define TVAL 0x042 /* 定时器值 */
|
|
||||||
#define TICLR 0x044 /* 定时中断清除 */
|
|
||||||
#define LLBCTL 0x060 /* LLBit 控制 */
|
|
||||||
#define TLBRENTRY 0x088 /* TLB 重填例外入口 */
|
|
||||||
#define CTAG 0x098 /* 高速缓存标签 */
|
|
||||||
#define DMW0 0x180 /* 直接映射配置窗口 0 */
|
|
||||||
#define DMW1 0x181 /* 直接映射配置窗口 1 */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef CONSOLE_H__
|
|
||||||
#define CONSOLE_H__
|
|
||||||
|
|
||||||
void consputc(int c);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#ifndef DEFS_H__
|
|
||||||
#define DEFS_H__
|
|
||||||
|
|
||||||
#define NULL ((void *)0)
|
|
||||||
|
|
||||||
#define NCPU 1
|
|
||||||
#define NPROC 64
|
|
||||||
#define NOFILE 16
|
|
||||||
|
|
||||||
|
|
||||||
#define SERIAL_TX_BUF_SIZE 32
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef DEV_H__
|
|
||||||
#define DEV_H__
|
|
||||||
|
|
||||||
extern char ioports[];
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#ifndef FCNTL_H__
|
|
||||||
#define FCNTL_H__
|
|
||||||
|
|
||||||
#define O_RDONLY 0x000
|
|
||||||
#define O_WRONLY 0x001
|
|
||||||
#define O_RDWR 0x002
|
|
||||||
#define O_CREATE 0x200
|
|
||||||
#define O_TRUNC 0x400
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#ifndef FILEPATH_H__
|
|
||||||
#define FILEPATH_H__
|
|
||||||
|
|
||||||
|
|
||||||
char *basename(char *bnm, const char *path);
|
|
||||||
char *rmext(char *noext, const char *fname);
|
|
||||||
char *bearname(char *bnm, const char *fname);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "defs.h"
|
|
||||||
|
|
||||||
#ifndef KERNEL_H__
|
|
||||||
#define KERNEL_H__
|
|
||||||
|
|
||||||
void _entry() __attribute__ ((section (".entry")));
|
|
||||||
|
|
||||||
void start();
|
|
||||||
void main();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef KPRINTF_H__
|
|
||||||
#define KPRINTF_H__
|
|
||||||
|
|
||||||
|
|
||||||
void kprintf(char *fmt, ...);
|
|
||||||
void panic(char *s);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "asm.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include "latype.h"
|
|
||||||
#include "macro.h"
|
|
||||||
|
|
||||||
#ifndef __loongarch32r
|
|
||||||
#define __loongarch32r
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "larchintrin.h"
|
|
||||||
|
|
||||||
#ifndef LA32R_H__
|
|
||||||
#define LA32R_H__
|
|
||||||
|
|
||||||
static inline uint r_crmd() {
|
|
||||||
uint recv;
|
|
||||||
asm volatile ("csrrd %0, " TOSTRING(CRMD) : "=r" (recv));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void w_crmd(uint wdata) {
|
|
||||||
asm volatile ("csrwr %0, " TOSTRING(CRMD) : "=r" (wdata));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void w_eentry(uint wdata) {
|
|
||||||
asm volatile ("csrwr %0, " TOSTRING(EENTRY) : "=r" (wdata));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint r_cpuid() {
|
|
||||||
uint recv;
|
|
||||||
asm volatile ("csrrd %0, " TOSTRING(CPUID) : "=r" (recv));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// specified register io
|
|
||||||
//
|
|
||||||
|
|
||||||
static inline uint r_sp() {
|
|
||||||
uint recv;
|
|
||||||
asm volatile ("add.w %0, $sp, $zero" : "=r" (recv));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint r_tp() {
|
|
||||||
uint recv;
|
|
||||||
asm volatile ("add.w %0, $tp, $zero" : "=r" (recv));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void w_tp(uint wdata) {
|
|
||||||
asm volatile("add.w $tp, %0, $zero" : : "r" (wdata));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint r_ra() {
|
|
||||||
uint recv;
|
|
||||||
asm volatile ("add.w %0, $ra, $zero" : "=r" (recv));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// mem misc
|
|
||||||
//
|
|
||||||
|
|
||||||
// need to be tested
|
|
||||||
static inline void synchronize() {
|
|
||||||
__dbar(0);
|
|
||||||
__ibar(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// tlb misc
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// cache misc
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// atomic
|
|
||||||
//
|
|
||||||
|
|
||||||
static inline uint llw(intptr_t addr) {
|
|
||||||
uint recv;
|
|
||||||
asm volatile ("ll.w %0, %1, 0": "=r" (recv) : "r" (addr));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint scw(uint wdata, intptr_t addr) {
|
|
||||||
uint recv;
|
|
||||||
asm volatile (
|
|
||||||
"add.w %0, %1, $zero" "\n\t"
|
|
||||||
"sc.w %0, %2, 0"
|
|
||||||
: "=r" (recv)
|
|
||||||
: "r" (wdata),
|
|
||||||
"r" (addr));
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#ifndef LATYPE_H__
|
|
||||||
#define LATYPE_H__
|
|
||||||
|
|
||||||
typedef char i8;
|
|
||||||
typedef unsigned char u8;
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
|
|
||||||
typedef short i16;
|
|
||||||
typedef unsigned short u16;
|
|
||||||
typedef unsigned short ushort;
|
|
||||||
|
|
||||||
typedef int i32;
|
|
||||||
typedef unsigned int u32;
|
|
||||||
typedef unsigned int uint;
|
|
||||||
|
|
||||||
typedef unsigned int size_t;
|
|
||||||
typedef unsigned int intptr_t;
|
|
||||||
|
|
||||||
typedef u32 pte_t;
|
|
||||||
typedef u32 *pagetable_t;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#ifndef MACRO_H__
|
|
||||||
#define MACRO_H__
|
|
||||||
|
|
||||||
#define TOSTRING_(x) #x
|
|
||||||
#define TOSTRING(x) TOSTRING_(x)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "latype.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MEMIO_H__
|
|
||||||
#define MEMIO_H__
|
|
||||||
|
|
||||||
#define memb(addr) (*(u8 *)(addr))
|
|
||||||
#define memh(addr) (*(u16 *)(addr))
|
|
||||||
#define memw(addr) (*(u32 *)(addr))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#ifndef MEMLAYOUT_H__
|
|
||||||
#define MEMLAYOUT_H__
|
|
||||||
|
|
||||||
#define DEV_BASE_ADDR 0xa0000000
|
|
||||||
|
|
||||||
|
|
||||||
#define SERIAL_OFFSET 0x00000000
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
#include "latype.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include "spinlock.h"
|
|
||||||
|
|
||||||
#ifndef PROC_H__
|
|
||||||
#define PROC_H__
|
|
||||||
|
|
||||||
// Saved registers for kernel context switches.
|
|
||||||
struct context {
|
|
||||||
u32 ra;
|
|
||||||
u32 sp;
|
|
||||||
|
|
||||||
// callee-saved
|
|
||||||
u32 s0;
|
|
||||||
u32 s1;
|
|
||||||
u32 s2;
|
|
||||||
u32 s3;
|
|
||||||
u32 s4;
|
|
||||||
u32 s5;
|
|
||||||
u32 s6;
|
|
||||||
u32 s7;
|
|
||||||
u32 s8;
|
|
||||||
u32 s9;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Per-CPU state.
|
|
||||||
struct cpu {
|
|
||||||
struct proc *proc; // The process running on this cpu, or null.
|
|
||||||
struct context context; // swtch() here to enter scheduler().
|
|
||||||
int noff; // Depth of push_off() nesting.
|
|
||||||
int intena; // Were interrupts enabled before push_off()?
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct cpu cpus[NCPU];
|
|
||||||
|
|
||||||
|
|
||||||
// per-process data for the trap handling code in trampoline.S.
|
|
||||||
// sits in a page by itself just under the trampoline page in the
|
|
||||||
// user page table. not specially mapped in the kernel page table.
|
|
||||||
// uservec in trampoline.S saves user registers in the trapframe,
|
|
||||||
// then initializes registers from the trapframe's
|
|
||||||
// kernel_sp, kernel_hartid, kernel_satp, and jumps to kernel_trap.
|
|
||||||
// usertrapret() and userret in trampoline.S set up
|
|
||||||
// the trapframe's kernel_*, restore user registers from the
|
|
||||||
// trapframe, switch to the user page table, and enter user space.
|
|
||||||
// the trapframe includes callee-saved user registers like s0-s11 because the
|
|
||||||
// return-to-user path via usertrapret() doesn't return through
|
|
||||||
// the entire kernel call stack.
|
|
||||||
struct trapframe {
|
|
||||||
/* 0 */ u32 kernel_satp; // kernel page table
|
|
||||||
/* 4 */ u32 kernel_sp; // top of process's kernel stack
|
|
||||||
/* 8 */ u32 kernel_trap; // usertrap()
|
|
||||||
/* 12 */ u32 eenrty; // saved user program counter
|
|
||||||
/* 16 */ u32 kernel_hartid; // saved kernel tp
|
|
||||||
/* 20 */ u32 ra;
|
|
||||||
/* 24 */ u32 tp;
|
|
||||||
/* 28 */ u32 sp;
|
|
||||||
/* 32 */ u32 a0;
|
|
||||||
/* 36 */ u32 a1;
|
|
||||||
/* 40 */ u32 a2;
|
|
||||||
/* 44 */ u32 a3;
|
|
||||||
/* 48 */ u32 a4;
|
|
||||||
/* 52 */ u32 a5;
|
|
||||||
/* 56 */ u32 a6;
|
|
||||||
/* 60 */ u32 a7;
|
|
||||||
/* 64 */ u32 t0;
|
|
||||||
/* 68 */ u32 t1;
|
|
||||||
/* 72 */ u32 t2;
|
|
||||||
/* 76 */ u32 t3;
|
|
||||||
/* 80 */ u32 t4;
|
|
||||||
/* 84 */ u32 t5;
|
|
||||||
/* 88 */ u32 t6;
|
|
||||||
/* 92 */ u32 t7;
|
|
||||||
/* 96 */ u32 t8;
|
|
||||||
/* 100 */ u32 r21;
|
|
||||||
/* 104 */ u32 s9;
|
|
||||||
/* 108 */ u32 s0;
|
|
||||||
/* 112 */ u32 s1;
|
|
||||||
/* 116 */ u32 s2;
|
|
||||||
/* 120 */ u32 s3;
|
|
||||||
/* 124 */ u32 s4;
|
|
||||||
/* 128 */ u32 s5;
|
|
||||||
/* 132 */ u32 s6;
|
|
||||||
/* 136 */ u32 s7;
|
|
||||||
/* 140 */ u32 s8;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
|
||||||
|
|
||||||
// Per-process state
|
|
||||||
struct proc {
|
|
||||||
struct spinlock lock;
|
|
||||||
|
|
||||||
// p->lock must be held when using these:
|
|
||||||
enum procstate state; // Process state
|
|
||||||
void *chan; // If non-zero, sleeping on chan
|
|
||||||
int killed; // If non-zero, have been killed
|
|
||||||
int xstate; // Exit status to be returned to parent's wait
|
|
||||||
int pid; // Process ID
|
|
||||||
|
|
||||||
// wait_lock must be held when using this:
|
|
||||||
struct proc *parent; // Parent process
|
|
||||||
|
|
||||||
// these are private to the process, so p->lock need not be held.
|
|
||||||
u32 kstack; // Virtual address of kernel stack
|
|
||||||
u32 sz; // Size of process memory (bytes)
|
|
||||||
pagetable_t pagetable; // User page table
|
|
||||||
struct trapframe *trapframe; // data page for trampoline.S
|
|
||||||
struct context context; // swtch() here to run process
|
|
||||||
struct file *ofile[NOFILE]; // Open files
|
|
||||||
struct inode *cwd; // Current directory
|
|
||||||
char name[16]; // Process name (debugging)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cpu *mycpu();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#include "latype.h"
|
|
||||||
|
|
||||||
#ifndef SPINLOCK_H__
|
|
||||||
#define SPINLOCK_H__
|
|
||||||
|
|
||||||
struct spinlock {
|
|
||||||
uint locked;
|
|
||||||
|
|
||||||
// debugging
|
|
||||||
char *name;
|
|
||||||
struct cpu *cpu;
|
|
||||||
};
|
|
||||||
|
|
||||||
void initlock(struct spinlock *lck, char *name);
|
|
||||||
|
|
||||||
void acquire(struct spinlock *lck);
|
|
||||||
void release(struct spinlock *lck);
|
|
||||||
|
|
||||||
int holding(struct spinlock *lck);
|
|
||||||
void push_off();
|
|
||||||
void pop_off();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#include "latype.h"
|
|
||||||
|
|
||||||
#ifndef STRING_H__
|
|
||||||
#define STRING_H__
|
|
||||||
|
|
||||||
void *memset (void *dst , int c, uint n);
|
|
||||||
int memcmp (const void *m1, const void *m2, uint n);
|
|
||||||
void *memmove (void *dst, const void *src, uint n);
|
|
||||||
void *memcpy (void *dst, const void *src, uint n);
|
|
||||||
|
|
||||||
int strncmp (const char *p, const char *q, uint n);
|
|
||||||
char *strncpy (char *s, const char *t, int n);
|
|
||||||
char *strcpy_s(char *s, const char *t, int n);
|
|
||||||
int strlen (const char *s);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#ifndef UNISTD_H__
|
|
||||||
#define UNISTD_H__
|
|
||||||
|
|
||||||
/* Standard file descriptors. */
|
|
||||||
#define STDIN_FILENO 0 /* Standard input. */
|
|
||||||
#define STDOUT_FILENO 1 /* Standard output. */
|
|
||||||
#define STDERR_FILENO 2 /* Standard error output. */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
OUTPUT_ARCH( "loongarch32r" )
|
|
||||||
ENTRY( _entry )
|
|
||||||
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* ensure that entry.S / _entry is at 0x1C000000,
|
|
||||||
*/
|
|
||||||
. = 0x1C000000;
|
|
||||||
|
|
||||||
.text : {
|
|
||||||
*(.entry)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
*(.text .text.*)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
PROVIDE(etext = .);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rodata : {
|
|
||||||
. = ALIGN(16);
|
|
||||||
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
|
||||||
. = ALIGN(16);
|
|
||||||
*(.rodata .rodata.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.data : {
|
|
||||||
. = ALIGN(16);
|
|
||||||
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
|
||||||
. = ALIGN(16);
|
|
||||||
*(.data .data.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.bss : {
|
|
||||||
. = ALIGN(16);
|
|
||||||
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
|
|
||||||
. = ALIGN(16);
|
|
||||||
*(.bss .bss.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
PROVIDE(end = .);
|
|
||||||
PROVIDE(ioports = 0xa0000000);
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
CURNAME := dev
|
|
||||||
BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME)
|
|
||||||
|
|
||||||
CSRC := $(wildcard *.c)
|
|
||||||
OBJS := $(patsubst %.c,%.o,$(CSRC))
|
|
||||||
BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS))
|
|
||||||
|
|
||||||
.PHONY: build all message
|
|
||||||
|
|
||||||
all: message build
|
|
||||||
|
|
||||||
$(BUILD_DIR):
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
|
|
||||||
$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR)
|
|
||||||
@$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
build: $(BUILD_OBJS)
|
|
||||||
|
|
||||||
message:
|
|
||||||
@echo "building $(CURNAME)"
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#include "dev.h"
|
|
||||||
|
|
||||||
char ioports[];
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "memlayout.h"
|
|
||||||
#include "latype.h"
|
|
||||||
#include "memio.h"
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
struct spinlock serial_tx_lock;
|
|
||||||
char serial_tx_buf[SERIAL_TX_BUF_SIZE];
|
|
||||||
|
|
||||||
u32 serial_tx_w; // write next to serial_tx_buf[serial_tx_w % SERIAL_TX_BUF_SIZE]
|
|
||||||
u32 serial_tx_r; // read next from serial_tx_buf[serial_tx_r % SERIAL_TX_BUF_SIZE]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void serial_putc(int c) {
|
|
||||||
acquire(&serial_tx_lock);
|
|
||||||
|
|
||||||
// if(panicked){
|
|
||||||
// for(;;)
|
|
||||||
// ;
|
|
||||||
// }
|
|
||||||
|
|
||||||
while(serial_tx_w == serial_tx_r + SERIAL_TX_BUF_SIZE){
|
|
||||||
// buffer is full.
|
|
||||||
// wait for serialstart() to open up space in the buffer.
|
|
||||||
// sleep(&serial_tx_r, &serial_tx_lock);
|
|
||||||
}
|
|
||||||
serial_tx_buf[serial_tx_w % SERIAL_TX_BUF_SIZE] = c;
|
|
||||||
serial_tx_w += 1;
|
|
||||||
// serialstart();
|
|
||||||
release(&serial_tx_lock);
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
CURNAME := kernel
|
|
||||||
BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME)
|
|
||||||
|
|
||||||
CSRC := $(wildcard *.c)
|
|
||||||
OBJS := $(patsubst %.c,%.o,$(CSRC))
|
|
||||||
BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS))
|
|
||||||
|
|
||||||
ASSRC := $(wildcard *.S)
|
|
||||||
ASOBJ := $(patsubst %.S,%.o,$(ASSRC))
|
|
||||||
BUILD_ASOBJ := $(addprefix $(BUILD_DIR)/,$(ASOBJ))
|
|
||||||
|
|
||||||
.PHONY: build all message
|
|
||||||
|
|
||||||
all: message build
|
|
||||||
|
|
||||||
$(BUILD_DIR):
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
|
|
||||||
$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR)
|
|
||||||
@$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
$(BUILD_ASOBJ): $(BUILD_DIR)/%.o:%.S $(BUILD_DIR)
|
|
||||||
@$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
build: $(BUILD_OBJS) $(BUILD_ASOBJ)
|
|
||||||
|
|
||||||
message:
|
|
||||||
@echo "building $(CURNAME)"
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#include "console.h"
|
|
||||||
#include "memio.h"
|
|
||||||
#include "memlayout.h"
|
|
||||||
#include "spinlock.h"
|
|
||||||
#include "dev.h"
|
|
||||||
|
|
||||||
void consputc(int c) {
|
|
||||||
volatile char *out = &ioports[SERIAL_OFFSET];
|
|
||||||
if (c == '\b') {
|
|
||||||
*out = '\b';
|
|
||||||
*out = ' ';
|
|
||||||
*out = '\b';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct spinlock lock;
|
|
||||||
|
|
||||||
// input
|
|
||||||
#define INPUT_BUF_SIZE 128
|
|
||||||
char buf[INPUT_BUF_SIZE];
|
|
||||||
uint r; // Read index
|
|
||||||
uint w; // Write index
|
|
||||||
uint e; // Edit index
|
|
||||||
} cons;
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#include "asm.h"
|
|
||||||
|
|
||||||
.section .entry
|
|
||||||
.global _entry
|
|
||||||
_entry:
|
|
||||||
# set up a stack for C.
|
|
||||||
# stack0 is declared in start.c,
|
|
||||||
# with a 4096-byte stack per CPU.
|
|
||||||
# sp = stack0 + (hartid * 4096)
|
|
||||||
la.global $sp, stack0
|
|
||||||
lu12i.w $a0, (1024*4 >> 12) & 0xfffff
|
|
||||||
addi.w $a0, $a0, 1024*4 & 0xfff
|
|
||||||
csrrd $a1, CPUID
|
|
||||||
addi.w $a1, $a1, 1
|
|
||||||
mul.w $a0, $a0, $a1
|
|
||||||
add.w $sp, $sp, $a0
|
|
||||||
# jump to start() in start.c
|
|
||||||
bl start
|
|
||||||
spin:
|
|
||||||
b spin
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
extern char end[];
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include "latype.h"
|
|
||||||
#include "console.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "spinlock.h"
|
|
||||||
|
|
||||||
volatile int panicked = 0;
|
|
||||||
|
|
||||||
// lock to avoid interleaving concurrent printf's.
|
|
||||||
static struct {
|
|
||||||
struct spinlock lock;
|
|
||||||
int locking;
|
|
||||||
} pr;
|
|
||||||
|
|
||||||
static char digits[] = "0123456789abcdef";
|
|
||||||
|
|
||||||
static void print_int(int xx, int base, int sign) {
|
|
||||||
char buf[32];
|
|
||||||
int i;
|
|
||||||
uint x;
|
|
||||||
if (sign && (sign = xx < 0)) {
|
|
||||||
x = -xx;
|
|
||||||
} else {
|
|
||||||
x = xx;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
buf[i++] = digits[x % base];
|
|
||||||
} while ((x /= base) != 0);
|
|
||||||
|
|
||||||
if(sign) {
|
|
||||||
buf[i++] = '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
while(--i >= 0)
|
|
||||||
consputc(buf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_ptr(intptr_t x) {
|
|
||||||
consputc('0');
|
|
||||||
consputc('x');
|
|
||||||
for (int i = 0; i < (sizeof(intptr_t) * 2); i++, x <<= 4)
|
|
||||||
consputc(digits[x >> (sizeof(intptr_t) * 8 - 4)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void kprintf(char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
int i, c, locking;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
locking = pr.locking;
|
|
||||||
if(locking)
|
|
||||||
acquire(&pr.lock);
|
|
||||||
|
|
||||||
if (fmt == 0)
|
|
||||||
panic("null fmt");
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
|
|
||||||
if (c != '%') {
|
|
||||||
consputc(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
c = fmt[++i] & 0xff;
|
|
||||||
if (c == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case 'd':
|
|
||||||
print_int(va_arg(ap, int), 10, 1);
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
print_int(va_arg(ap, int), 16, 1);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
print_ptr(va_arg(ap, intptr_t));
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if((s = va_arg(ap, char*)) == 0)
|
|
||||||
s = "(null)";
|
|
||||||
for(; *s; s++)
|
|
||||||
consputc(*s);
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
consputc('%');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Print unknown % sequence to draw attention.
|
|
||||||
consputc('%');
|
|
||||||
consputc(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if(locking)
|
|
||||||
release(&pr.lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void panic(char *s) {
|
|
||||||
pr.locking = 0;
|
|
||||||
kprintf("panic: ");
|
|
||||||
kprintf(s);
|
|
||||||
kprintf("\n");
|
|
||||||
panicked = 1; // freeze serial output from other CPUs
|
|
||||||
for(;;)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kprintf_init(void) {
|
|
||||||
initlock(&pr.lock, "pr");
|
|
||||||
pr.locking = 1;
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#include "la32r.h"
|
|
||||||
#include "spinlock.h"
|
|
||||||
|
|
||||||
|
|
||||||
volatile static int started = 0;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
struct spinlock lck[1];
|
|
||||||
initlock(lck, "main");
|
|
||||||
acquire(lck);
|
|
||||||
|
|
||||||
if (r_cpuid() == 0) {
|
|
||||||
|
|
||||||
|
|
||||||
synchronize();
|
|
||||||
started = 1;
|
|
||||||
} else {
|
|
||||||
// 当前假定只有一个 hart
|
|
||||||
while (started == 0)
|
|
||||||
;
|
|
||||||
synchronize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#include "proc.h"
|
|
||||||
#include "la32r.h"
|
|
||||||
#include "latype.h"
|
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
|
||||||
|
|
||||||
struct proc proc[NPROC];
|
|
||||||
|
|
||||||
struct proc *initproc;
|
|
||||||
|
|
||||||
int nextpid = 1;
|
|
||||||
struct spinlock pid_lock;
|
|
||||||
|
|
||||||
// helps ensure that wakeups of wait()ing
|
|
||||||
// parents are not lost. helps obey the
|
|
||||||
// memory model when using p->parent.
|
|
||||||
// must be acquired before any p->lock.
|
|
||||||
struct spinlock wait_lock;
|
|
||||||
|
|
||||||
struct cpu *mycpu() {
|
|
||||||
int id = r_cpuid();
|
|
||||||
struct cpu *c = &cpus[id];
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#include "spinlock.h"
|
|
||||||
#include "la32r.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "proc.h"
|
|
||||||
|
|
||||||
void initlock(struct spinlock *lck, char *name) {
|
|
||||||
lck->name = name;
|
|
||||||
lck->locked = 0;
|
|
||||||
lck->cpu = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void acquire(struct spinlock *lck) {
|
|
||||||
|
|
||||||
if(holding(lck)) {
|
|
||||||
panic("acquire");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
do {
|
|
||||||
// 如果已经上锁了,就等待
|
|
||||||
while (llw((intptr_t)&lck->locked) == 1)
|
|
||||||
;
|
|
||||||
// 此时没有上锁,那就开始抢锁
|
|
||||||
// 没有抢成功就进入新的循环
|
|
||||||
} while (scw(1, (intptr_t)&lck->locked) != 1);
|
|
||||||
|
|
||||||
synchronize();
|
|
||||||
lck->cpu = mycpu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void release(struct spinlock *lck) {
|
|
||||||
if (holding(lck) != 1) {
|
|
||||||
panic("release");
|
|
||||||
}
|
|
||||||
|
|
||||||
lck->cpu = NULL;
|
|
||||||
|
|
||||||
synchronize();
|
|
||||||
|
|
||||||
do {
|
|
||||||
// 标记上
|
|
||||||
llw((intptr_t)&lck->locked);
|
|
||||||
|
|
||||||
// 此时没有 hart 动,那就安全的释放
|
|
||||||
// 否则重新循环
|
|
||||||
} while (scw(0, (intptr_t)&lck->locked) != 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int holding(struct spinlock *lck) {
|
|
||||||
int r;
|
|
||||||
r = (lck->locked && lck->cpu == mycpu());
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#include "kernel.h"
|
|
||||||
#include "la32r.h"
|
|
||||||
|
|
||||||
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
// 设置特权等级
|
|
||||||
volatile u32 crmd_info = r_crmd();
|
|
||||||
crmd_info = crmd_info & 0xfffffffc;
|
|
||||||
w_crmd(crmd_info);
|
|
||||||
|
|
||||||
// ERTN 返回地址
|
|
||||||
w_eentry((intptr_t)main);
|
|
||||||
|
|
||||||
// 设置 tp
|
|
||||||
int id = r_cpuid();
|
|
||||||
w_tp(id);
|
|
||||||
|
|
||||||
asm volatile("ertn");
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
extern char etext[];
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
CURNAME := lib
|
|
||||||
BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME)
|
|
||||||
|
|
||||||
CSRC := $(wildcard *.c)
|
|
||||||
OBJS := $(patsubst %.c,%.o,$(CSRC))
|
|
||||||
BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS))
|
|
||||||
|
|
||||||
.PHONY: build all message
|
|
||||||
|
|
||||||
all: message build
|
|
||||||
|
|
||||||
$(BUILD_DIR):
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
|
|
||||||
$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR)
|
|
||||||
@$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
build: $(BUILD_OBJS)
|
|
||||||
|
|
||||||
message:
|
|
||||||
@echo "building $(CURNAME)"
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
CURNAME := user
|
|
||||||
BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME)
|
|
||||||
|
|
||||||
CSRC := $(wildcard *.c)
|
|
||||||
OBJS := $(patsubst %.c,%.o,$(CSRC))
|
|
||||||
BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS))
|
|
||||||
BASENAMES := $(basename $(CSRC))
|
|
||||||
BUILD_EXE := $(addprefix $(BUILD_DIR)/,$(BASENAMES))
|
|
||||||
|
|
||||||
.PHONY: build all message
|
|
||||||
|
|
||||||
all: message build
|
|
||||||
|
|
||||||
$(BUILD_DIR):
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
|
|
||||||
$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR)
|
|
||||||
@$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
$(BUILD_EXE): %:%.o
|
|
||||||
@$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
build: $(BUILD_EXE)
|
|
||||||
|
|
||||||
message:
|
|
||||||
@echo "building $(CURNAME)"
|
|
||||||
|
|
||||||
native: $(BUILD_EXE)
|
|
||||||
@echo $(BASENAMES)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
write(STDOUT_FILENO, argv[i], strlen(argv[i]));
|
|
||||||
if(i + 1 < argc){
|
|
||||||
write(STDOUT_FILENO, " ", 1);
|
|
||||||
} else {
|
|
||||||
write(STDOUT_FILENO, "\n", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
void remove_tail_newline(char *str, int len) {
|
|
||||||
if (len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (str[len - 1] == '\n') {
|
|
||||||
str[len - 1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
if (argc < 1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char **args = malloc(argc * sizeof(char *));
|
|
||||||
memcpy(args, &argv[1], (argc - 1) * sizeof(char *));
|
|
||||||
argc -= 1;
|
|
||||||
|
|
||||||
const char *filename = argv[1];
|
|
||||||
char input[128];
|
|
||||||
read(STDIN_FILENO, input, 128);
|
|
||||||
remove_tail_newline(input, strlen(input));
|
|
||||||
|
|
||||||
char *tok = strtok(input, " ");
|
|
||||||
while (tok) {
|
|
||||||
args = realloc(args, (argc + 1) * sizeof(char *));
|
|
||||||
args[argc] = tok;
|
|
||||||
argc += 1;
|
|
||||||
tok = strtok(NULL, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fork() == 0) {
|
|
||||||
execvp(filename, args);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
wait(NULL);
|
|
||||||
free(args);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
CURNAME := util
|
|
||||||
BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME)
|
|
||||||
|
|
||||||
CSRC := $(wildcard *.c)
|
|
||||||
OBJS := $(patsubst %.c,%.o,$(CSRC))
|
|
||||||
BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS))
|
|
||||||
|
|
||||||
.PHONY: build all message
|
|
||||||
|
|
||||||
all: message build
|
|
||||||
|
|
||||||
$(BUILD_DIR):
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
|
|
||||||
$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR)
|
|
||||||
@$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS)
|
|
||||||
|
|
||||||
build: $(BUILD_OBJS)
|
|
||||||
|
|
||||||
message:
|
|
||||||
@echo "building $(CURNAME)"
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#include "defs.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// bnm should be large enough to hold basename
|
|
||||||
//
|
|
||||||
char *basename(char *bnm, const char *path) {
|
|
||||||
const char *p = path;
|
|
||||||
const char *last_slash = NULL;
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '/' || *p == '\\') {
|
|
||||||
last_slash = p;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *q = bnm;
|
|
||||||
p = last_slash + 1;
|
|
||||||
while (*p) {
|
|
||||||
*q++ = *p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bnm;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// noext should be large enough to hold no-ext name
|
|
||||||
//
|
|
||||||
char *rmext(char *noext, const char *fname) {
|
|
||||||
const char *p = fname;
|
|
||||||
const char *last_dot = NULL;
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '.') {
|
|
||||||
last_dot = p;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *q = noext;
|
|
||||||
p = fname;
|
|
||||||
while (p != last_dot) {
|
|
||||||
*q++ = *p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return noext;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// bnm should be large enough to hold bearname name
|
|
||||||
//
|
|
||||||
char *bearname(char *bnm, const char *fname) {
|
|
||||||
const char *p = fname;
|
|
||||||
const char *last_slash = NULL;
|
|
||||||
const char *last_dot = NULL;
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '/' || *p == '\\') {
|
|
||||||
last_slash = p;
|
|
||||||
} else if (*p == '.') {
|
|
||||||
last_dot = p;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *q = bnm;
|
|
||||||
p = last_slash + 1;
|
|
||||||
while (p != last_dot) {
|
|
||||||
*q++ = *p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bnm;
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#include "string.h"
|
|
||||||
#include "latype.h"
|
|
||||||
|
|
||||||
// mem ops could be more better
|
|
||||||
// use loop unrolling
|
|
||||||
|
|
||||||
void *memset(void *dst, int c, uint n) {
|
|
||||||
char *cdst = (char *) dst;
|
|
||||||
for (uint i = 0; i < n; ++i) {
|
|
||||||
cdst[i] = c;
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
int memcmp(const void *m1, const void *m2, uint n) {
|
|
||||||
const uchar *s1, *s2;
|
|
||||||
|
|
||||||
s1 = m1;
|
|
||||||
s2 = m2;
|
|
||||||
|
|
||||||
while (n --> 0) {
|
|
||||||
if(*s1 != *s2)
|
|
||||||
return *s1 - *s2;
|
|
||||||
s1++;
|
|
||||||
s2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *memmove(void *dst, const void *src, uint n) {
|
|
||||||
const char *s;
|
|
||||||
char *d;
|
|
||||||
|
|
||||||
if(n == 0)
|
|
||||||
return dst;
|
|
||||||
|
|
||||||
s = src;
|
|
||||||
d = dst;
|
|
||||||
if(s < d && s + n > d){
|
|
||||||
s += n;
|
|
||||||
d += n;
|
|
||||||
while(n-- > 0)
|
|
||||||
*--d = *--s;
|
|
||||||
} else
|
|
||||||
while(n-- > 0)
|
|
||||||
*d++ = *s++;
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *memcpy(void *dst, const void *src, uint n) {
|
|
||||||
return memmove(dst, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int strncmp(const char *p, const char *q, uint n) {
|
|
||||||
while(n > 0 && *p && *p == *q)
|
|
||||||
n--, p++, q++;
|
|
||||||
if(n == 0)
|
|
||||||
return 0;
|
|
||||||
return (uchar)*p - (uchar)*q;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strncpy(char *s, const char *t, int n) {
|
|
||||||
char *os;
|
|
||||||
|
|
||||||
os = s;
|
|
||||||
while(n-- > 0 && (*s++ = *t++) != 0)
|
|
||||||
;
|
|
||||||
while(n-- > 0)
|
|
||||||
*s++ = 0;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strcpy_s(char *s, const char *t, int n) {
|
|
||||||
char *os;
|
|
||||||
|
|
||||||
os = s;
|
|
||||||
if(n <= 0)
|
|
||||||
return os;
|
|
||||||
while(--n > 0 && (*s++ = *t++) != 0)
|
|
||||||
;
|
|
||||||
*s = 0;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
int strlen(const char *s) {
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for(n = 0; s[n]; n++)
|
|
||||||
;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sysbus.hh>
|
|
||||||
|
|
||||||
class LA32R {
|
|
||||||
public:
|
|
||||||
LA32R(SystemBus *bus);
|
|
||||||
void Step(unsigned in);
|
|
||||||
};
|
|
||||||
1009
lasim/la32r.cc
1009
lasim/la32r.cc
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <sysbus.hh>
|
|
||||||
#include <memory.hh>
|
|
||||||
#include <serial.hh>
|
|
||||||
#include <la32r.hh>
|
|
||||||
#include <common.h>
|
|
||||||
#include <devaddr.h>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
// if (argc < 2) {
|
|
||||||
// std::cout << "Usage: sim <bin>";
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
SystemBus bus;
|
|
||||||
Memory ram(2 * 1024 * 1024);
|
|
||||||
Memory stk(256 * 1024);
|
|
||||||
|
|
||||||
Memory flash(1024 * 1024);
|
|
||||||
flash.load("../laos/build/neula-os");
|
|
||||||
ram.load(&flash, 0x0, flash.size());
|
|
||||||
|
|
||||||
bus.regdev(&ram, RAM_ADDR);
|
|
||||||
bus.regdev(&stk, STK_ADDR);
|
|
||||||
|
|
||||||
Serial bios(1);
|
|
||||||
bus.regdev(&bios, SERIAL_PORT);
|
|
||||||
|
|
||||||
auto cpu = new LA32R(&bus);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
cpu->Step(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete cpu;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
// DESCRIPTION: Verilator: Verilog example module
|
|
||||||
//
|
|
||||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
|
||||||
// any use, without warranty, 2017 by Wilson Snyder.
|
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
|
||||||
//======================================================================
|
|
||||||
|
|
||||||
// Include common routines
|
|
||||||
#include <verilated.h>
|
|
||||||
|
|
||||||
// Include model header, generated from Verilating "top.v"
|
|
||||||
#include "Vtop.h"
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
// See a similar example walkthrough in the verilator manpage.
|
|
||||||
|
|
||||||
// This is intended to be a minimal example. Before copying this to start a
|
|
||||||
// real project, it is better to start with a more complete example,
|
|
||||||
// e.g. examples/c_tracing.
|
|
||||||
|
|
||||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
|
||||||
// This needs to be called before you create any model
|
|
||||||
Verilated::commandArgs(argc, argv);
|
|
||||||
|
|
||||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
|
||||||
Vtop* top = new Vtop();
|
|
||||||
|
|
||||||
// Simulate until $finish
|
|
||||||
while (!Verilated::gotFinish()) {
|
|
||||||
|
|
||||||
// Evaluate model
|
|
||||||
top->eval();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Final model cleanup
|
|
||||||
top->final();
|
|
||||||
|
|
||||||
// Destroy model
|
|
||||||
delete top;
|
|
||||||
|
|
||||||
// Return good completion status
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user