Vortex 2.0 changes:

+ Microarchitecture optimizations
+ 64-bit support
+ Xilinx FPGA support
+ LLVM-16 support
+ Refactoring and quality control fixes
This commit is contained in:
Blaise Tine
2023-10-19 20:51:22 -07:00
parent d69a64c32c
commit d47cccc157
1300 changed files with 247321 additions and 311189 deletions

View File

@@ -1,7 +1,19 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <cstdint>
#include <algorithm>
#include <assert.h>
constexpr uint32_t count_leading_zeros(uint32_t value) {
@@ -77,5 +89,15 @@ T sext(const T& word, uint32_t width) {
if (width == (sizeof(T) * 8))
return word;
T mask((static_cast<T>(1) << width) - 1);
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
}
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : (word & mask);
}
template <typename T = uint32_t>
T zext(const T& word, uint32_t width) {
assert(width > 1);
assert(width <= (sizeof(T) * 8));
if (width == (sizeof(T) * 8))
return word;
T mask((static_cast<T>(1) << width) - 1);
return word & mask;
}

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "mem.h"
#include <vector>
#include <iostream>
@@ -20,8 +33,9 @@ RamMemDevice::RamMemDevice(const char *filename, uint32_t wordSize)
contents_.push_back(input.get());
} while (input);
while (contents_.size() & (wordSize-1))
while (contents_.size() & (wordSize-1)) {
contents_.push_back(0x00);
}
}
RamMemDevice::RamMemDevice(uint64_t size, uint32_t wordSize)
@@ -29,7 +43,7 @@ RamMemDevice::RamMemDevice(uint64_t size, uint32_t wordSize)
, wordSize_(wordSize)
{}
void RamMemDevice::read(void *data, uint64_t addr, uint64_t size) {
void RamMemDevice::read(void* data, uint64_t addr, uint64_t size) {
auto addr_end = addr + size;
if ((addr & (wordSize_-1))
|| (addr_end & (wordSize_-1))
@@ -44,7 +58,7 @@ void RamMemDevice::read(void *data, uint64_t addr, uint64_t size) {
}
}
void RamMemDevice::write(const void *data, uint64_t addr, uint64_t size) {
void RamMemDevice::write(const void* data, uint64_t addr, uint64_t size) {
auto addr_end = addr + size;
if ((addr & (wordSize_-1))
|| (addr_end & (wordSize_-1))
@@ -68,26 +82,26 @@ void RomMemDevice::write(const void* /*data*/, uint64_t /*addr*/, uint64_t /*siz
///////////////////////////////////////////////////////////////////////////////
bool MemoryUnit::ADecoder::lookup(uint64_t a, uint32_t wordSize, mem_accessor_t* ma) {
uint64_t e = a + (wordSize - 1);
assert(e >= a);
bool MemoryUnit::ADecoder::lookup(uint64_t addr, uint32_t wordSize, mem_accessor_t* ma) {
uint64_t end = addr + (wordSize - 1);
assert(end >= addr);
for (auto iter = entries_.rbegin(), iterE = entries_.rend(); iter != iterE; ++iter) {
if (a >= iter->start && e <= iter->end) {
if (addr >= iter->start && end <= iter->end) {
ma->md = iter->md;
ma->addr = a - iter->start;
ma->addr = addr - iter->start;
return true;
}
}
return false;
}
void MemoryUnit::ADecoder::map(uint64_t a, uint64_t e, MemDevice &m) {
assert(e >= a);
entry_t entry{&m, a, e};
void MemoryUnit::ADecoder::map(uint64_t start, uint64_t end, MemDevice &md) {
assert(end >= start);
entry_t entry{&md, start, end};
entries_.emplace_back(entry);
}
void MemoryUnit::ADecoder::read(void *data, uint64_t addr, uint64_t size) {
void MemoryUnit::ADecoder::read(void* data, uint64_t addr, uint64_t size) {
mem_accessor_t ma;
if (!this->lookup(addr, size, &ma)) {
std::cout << "lookup of 0x" << std::hex << addr << " failed.\n";
@@ -96,7 +110,7 @@ void MemoryUnit::ADecoder::read(void *data, uint64_t addr, uint64_t size) {
ma.md->read(data, ma.addr, size);
}
void MemoryUnit::ADecoder::write(const void *data, uint64_t addr, uint64_t size) {
void MemoryUnit::ADecoder::write(const void* data, uint64_t addr, uint64_t size) {
mem_accessor_t ma;
if (!this->lookup(addr, size, &ma)) {
std::cout << "lookup of 0x" << std::hex << addr << " failed.\n";
@@ -107,11 +121,11 @@ void MemoryUnit::ADecoder::write(const void *data, uint64_t addr, uint64_t size)
///////////////////////////////////////////////////////////////////////////////
MemoryUnit::MemoryUnit(uint64_t pageSize, uint64_t addrBytes, bool disableVm)
MemoryUnit::MemoryUnit(uint64_t pageSize)
: pageSize_(pageSize)
, addrBytes_(addrBytes)
, disableVM_(disableVm) {
if (!disableVm) {
, enableVM_(pageSize != 0)
, amo_reservation_({0x0, false}) {
if (pageSize != 0) {
tlb_[0] = TLBEntry(0, 077);
}
}
@@ -133,30 +147,38 @@ MemoryUnit::TLBEntry MemoryUnit::tlbLookup(uint64_t vAddr, uint32_t flagMask) {
}
}
void MemoryUnit::read(void *data, uint64_t addr, uint64_t size, bool sup) {
uint64_t MemoryUnit::toPhyAddr(uint64_t addr, uint32_t flagMask) {
uint64_t pAddr;
if (disableVM_) {
pAddr = addr;
} else {
uint32_t flagMask = sup ? 8 : 1;
if (enableVM_) {
TLBEntry t = this->tlbLookup(addr, flagMask);
pAddr = t.pfn * pageSize_ + addr % pageSize_;
} else {
pAddr = addr;
}
return pAddr;
}
void MemoryUnit::read(void* data, uint64_t addr, uint64_t size, bool sup) {
uint64_t pAddr = this->toPhyAddr(addr, sup ? 8 : 1);
return decoder_.read(data, pAddr, size);
}
void MemoryUnit::write(const void *data, uint64_t addr, uint64_t size, bool sup) {
uint64_t pAddr;
if (disableVM_) {
pAddr = addr;
} else {
uint32_t flagMask = sup ? 16 : 2;
TLBEntry t = tlbLookup(addr, flagMask);
pAddr = t.pfn * pageSize_ + addr % pageSize_;
}
void MemoryUnit::write(const void* data, uint64_t addr, uint64_t size, bool sup) {
uint64_t pAddr = this->toPhyAddr(addr, sup ? 16 : 1);
decoder_.write(data, pAddr, size);
amo_reservation_.valid = false;
}
void MemoryUnit::amo_reserve(uint64_t addr) {
uint64_t pAddr = this->toPhyAddr(addr, 1);
amo_reservation_.addr = pAddr;
amo_reservation_.valid = true;
}
bool MemoryUnit::amo_check(uint64_t addr) {
uint64_t pAddr = this->toPhyAddr(addr, 1);
return amo_reservation_.valid && (amo_reservation_.addr == pAddr);
}
void MemoryUnit::tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags) {
tlb_[virt / pageSize_] = TLBEntry(phys / pageSize_, flags);
}
@@ -168,12 +190,14 @@ void MemoryUnit::tlbRm(uint64_t va) {
///////////////////////////////////////////////////////////////////////////////
RAM::RAM(uint32_t page_size)
: size_(0)
RAM::RAM(uint32_t page_size, uint64_t capacity)
: capacity_(capacity)
, page_bits_(log2ceil(page_size))
, last_page_(nullptr)
, last_page_index_(0) {
assert(ispow2(page_size));
assert(0 == capacity || ispow2(capacity));
assert(0 == (capacity % page_size));
}
RAM::~RAM() {
@@ -191,6 +215,9 @@ uint64_t RAM::size() const {
}
uint8_t *RAM::get(uint64_t address) const {
if (capacity_ != 0 && address >= capacity_) {
throw OutOfRange();
}
uint32_t page_size = 1 << page_bits_;
uint32_t page_offset = address & (page_size - 1);
uint64_t page_index = address >> page_bits_;
@@ -218,14 +245,14 @@ uint8_t *RAM::get(uint64_t address) const {
return page + page_offset;
}
void RAM::read(void *data, uint64_t addr, uint64_t size) {
void RAM::read(void* data, uint64_t addr, uint64_t size) {
uint8_t* d = (uint8_t*)data;
for (uint64_t i = 0; i < size; i++) {
d[i] = *this->get(addr + i);
}
}
void RAM::write(const void *data, uint64_t addr, uint64_t size) {
void RAM::write(const void* data, uint64_t addr, uint64_t size) {
const uint8_t* d = (const uint8_t*)data;
for (uint64_t i = 0; i < size; i++) {
*this->get(addr + i) = d[i];
@@ -236,6 +263,7 @@ void RAM::loadBinImage(const char* filename, uint64_t destination) {
std::ifstream ifs(filename);
if (!ifs) {
std::cout << "error: " << filename << " not found" << std::endl;
std::abort();
}
ifs.seekg(0, ifs.end);
@@ -268,6 +296,7 @@ void RAM::loadHexImage(const char* filename) {
std::ifstream ifs(filename);
if (!ifs) {
std::cout << "error: " << filename << " not found" << std::endl;
std::abort();
}
ifs.seekg(0, ifs.end);
@@ -313,4 +342,4 @@ void RAM::loadHexImage(const char* filename) {
++line;
--size;
}
}
}

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <cstdint>
@@ -7,13 +20,14 @@
namespace vortex {
struct BadAddress {};
struct OutOfRange {};
class MemDevice {
public:
virtual ~MemDevice() {}
virtual uint64_t size() const = 0;
virtual void read(void *data, uint64_t addr, uint64_t size) = 0;
virtual void write(const void *data, uint64_t addr, uint64_t size) = 0;
virtual void read(void* data, uint64_t addr, uint64_t size) = 0;
virtual void write(const void* data, uint64_t addr, uint64_t size) = 0;
};
///////////////////////////////////////////////////////////////////////////////
@@ -21,11 +35,11 @@ public:
class RamMemDevice : public MemDevice {
public:
RamMemDevice(uint64_t size, uint32_t wordSize);
RamMemDevice(const char *filename, uint32_t wordSize);
RamMemDevice(const char* filename, uint32_t wordSize);
~RamMemDevice() {}
void read(void *data, uint64_t addr, uint64_t size) override;
void write(const void *data, uint64_t addr, uint64_t size) override;
void read(void* data, uint64_t addr, uint64_t size) override;
void write(const void* data, uint64_t addr, uint64_t size) override;
virtual uint64_t size() const {
return contents_.size();
@@ -50,7 +64,7 @@ public:
~RomMemDevice();
void write(const void *data, uint64_t addr, uint64_t size) override;
void write(const void* data, uint64_t addr, uint64_t size) override;
};
///////////////////////////////////////////////////////////////////////////////
@@ -63,47 +77,56 @@ public:
: faultAddr(a)
, notFound(nf)
{}
uint64_t faultAddr;
bool notFound;
uint64_t faultAddr;
bool notFound;
};
MemoryUnit(uint64_t pageSize, uint64_t addrBytes, bool disableVm = false);
MemoryUnit(uint64_t pageSize = 0);
void attach(MemDevice &m, uint64_t start, uint64_t end);
void read(void *data, uint64_t addr, uint64_t size, bool sup);
void write(const void *data, uint64_t addr, uint64_t size, bool sup);
void read(void* data, uint64_t addr, uint64_t size, bool sup);
void write(const void* data, uint64_t addr, uint64_t size, bool sup);
void amo_reserve(uint64_t addr);
bool amo_check(uint64_t addr);
void tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags);
void tlbRm(uint64_t va);
void tlbRm(uint64_t vaddr);
void tlbFlush() {
tlb_.clear();
}
private:
struct amo_reservation_t {
uint64_t addr;
bool valid;
};
class ADecoder {
public:
ADecoder() {}
void read(void *data, uint64_t addr, uint64_t size);
void write(const void *data, uint64_t addr, uint64_t size);
void read(void* data, uint64_t addr, uint64_t size);
void write(const void* data, uint64_t addr, uint64_t size);
void map(uint64_t start, uint64_t end, MemDevice &md);
private:
struct mem_accessor_t {
MemDevice* md;
uint64_t addr;
MemDevice* md;
uint64_t addr;
};
struct entry_t {
MemDevice *md;
uint64_t start;
uint64_t end;
MemDevice* md;
uint64_t start;
uint64_t end;
};
bool lookup(uint64_t a, uint32_t wordSize, mem_accessor_t*);
bool lookup(uint64_t addr, uint32_t wordSize, mem_accessor_t*);
std::vector<entry_t> entries_;
};
@@ -120,11 +143,14 @@ private:
TLBEntry tlbLookup(uint64_t vAddr, uint32_t flagMask);
uint64_t toPhyAddr(uint64_t vAddr, uint32_t flagMask);
std::unordered_map<uint64_t, TLBEntry> tlb_;
uint64_t pageSize_;
uint64_t addrBytes_;
ADecoder decoder_;
bool disableVM_;
uint64_t pageSize_;
ADecoder decoder_;
bool enableVM_;
amo_reservation_t amo_reservation_;
};
///////////////////////////////////////////////////////////////////////////////
@@ -132,15 +158,15 @@ private:
class RAM : public MemDevice {
public:
RAM(uint32_t page_size);
RAM(uint32_t page_size, uint64_t capacity = 0);
~RAM();
void clear();
uint64_t size() const override;
void read(void *data, uint64_t addr, uint64_t size) override;
void write(const void *data, uint64_t addr, uint64_t size) override;
void read(void* data, uint64_t addr, uint64_t size) override;
void write(const void* data, uint64_t addr, uint64_t size) override;
void loadBinImage(const char* filename, uint64_t destination);
void loadHexImage(const char* filename);
@@ -157,11 +183,11 @@ private:
uint8_t *get(uint64_t address) const;
uint64_t size_;
uint64_t capacity_;
uint32_t page_bits_;
mutable std::unordered_map<uint64_t, uint8_t*> pages_;
mutable uint8_t* last_page_;
mutable uint64_t last_page_index_;
};
} // namespace vortex
} // namespace vortex

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stack>
@@ -18,8 +31,9 @@ public:
void* allocate() {
void* mem;
if (!free_list_.empty()) {
mem = static_cast<void*>(free_list_.top());
auto entry = free_list_.top();
free_list_.pop();
mem = static_cast<void*>(entry);
} else {
mem = ::operator new(sizeof(T));
}
@@ -36,12 +50,13 @@ public:
void flush() {
while (!free_list_.empty()) {
::operator delete(free_list_.top());
auto entry = free_list_.top();
free_list_.pop();
::operator delete(entry);
}
}
private:
std::stack<void*> free_list_;
std::stack<T*> free_list_;
uint32_t max_size_;
};
};

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "rvfloats.h"
#include <stdio.h>
@@ -16,12 +29,9 @@ inline float64_t to_float64_t(uint64_t x) { return float64_t{x}; }
inline uint32_t from_float32_t(float32_t x) { return uint32_t(x.v); }
inline uint64_t from_float64_t(float64_t x) { return uint64_t(x.v); }
inline uint32_t get_fflags() {
uint32_t fflags = softfloat_exceptionFlags;
if (fflags) {
softfloat_exceptionFlags = 0;
}
return fflags;
inline void rv_init(uint32_t frm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = frm;
}
#ifdef __cplusplus
@@ -29,289 +39,296 @@ extern "C" {
#endif
uint32_t rv_fadd_s(uint32_t a, uint32_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_add(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fadd_d(uint64_t a, uint64_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_add(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fsub_s(uint32_t a, uint32_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_sub(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fsub_d(uint64_t a, uint64_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_sub(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fmul_s(uint32_t a, uint32_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_mul(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fmul_d(uint64_t a, uint64_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_mul(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fmadd_s(uint32_t a, uint32_t b, uint32_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_mulAdd(to_float32_t(a), to_float32_t(b), to_float32_t(c));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fmadd_d(uint64_t a, uint64_t b, uint64_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_mulAdd(to_float64_t(a), to_float64_t(b), to_float64_t(c));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fmsub_s(uint32_t a, uint32_t b, uint32_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto c_neg = c ^ F32_SIGN;
auto r = f32_mulAdd(to_float32_t(a), to_float32_t(b), to_float32_t(c_neg));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fmsub_d(uint64_t a, uint64_t b, uint64_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto c_neg = c ^ F64_SIGN;
auto r = f64_mulAdd(to_float64_t(a), to_float64_t(b), to_float64_t(c_neg));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fnmadd_s(uint32_t a, uint32_t b, uint32_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto a_neg = a ^ F32_SIGN;
auto c_neg = c ^ F32_SIGN;
auto r = f32_mulAdd(to_float32_t(a_neg), to_float32_t(b), to_float32_t(c_neg));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fnmadd_d(uint64_t a, uint64_t b, uint64_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto a_neg = a ^ F64_SIGN;
auto c_neg = c ^ F64_SIGN;
auto r = f64_mulAdd(to_float64_t(a_neg), to_float64_t(b), to_float64_t(c_neg));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fnmsub_s(uint32_t a, uint32_t b, uint32_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto a_neg = a ^ F32_SIGN;
auto r = f32_mulAdd(to_float32_t(a_neg), to_float32_t(b), to_float32_t(c));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fnmsub_d(uint64_t a, uint64_t b, uint64_t c, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto a_neg = a ^ F64_SIGN;
auto r = f64_mulAdd(to_float64_t(a_neg), to_float64_t(b), to_float64_t(c));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fdiv_s(uint32_t a, uint32_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_div(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fdiv_d(uint64_t a, uint64_t b, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_div(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_fsqrt_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_sqrt(to_float32_t(a));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_fsqrt_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_sqrt(to_float64_t(a));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_ftoi_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_to_i32(to_float32_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint32_t rv_ftoi_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_to_i32(to_float64_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint32_t rv_ftou_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_to_ui32(to_float32_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint32_t rv_ftou_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_to_ui32(to_float64_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint64_t rv_ftol_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_to_i64(to_float32_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint64_t rv_ftol_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_to_i64(to_float64_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint64_t rv_ftolu_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f32_to_ui64(to_float32_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint64_t rv_ftolu_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = f64_to_ui64(to_float64_t(a), frm, true);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint32_t rv_itof_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = i32_to_f32(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_itof_d(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = i32_to_f64(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_utof_s(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = ui32_to_f32(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_utof_d(uint32_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = ui32_to_f64(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_ltof_s(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = i64_to_f32(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_ltof_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = i64_to_f64(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
uint32_t rv_lutof_s(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = ui64_to_f32(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float32_t(r);
}
uint64_t rv_lutof_d(uint64_t a, uint32_t frm, uint32_t* fflags) {
softfloat_roundingMode = frm;
rv_init(frm);
auto r = ui64_to_f64(a);
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return from_float64_t(r);
}
bool rv_flt_s(uint32_t a, uint32_t b, uint32_t* fflags) {
rv_init(0);
auto r = f32_lt(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
bool rv_flt_d(uint64_t a, uint64_t b, uint32_t* fflags) {
rv_init(0);
auto r = f64_lt(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
bool rv_fle_s(uint32_t a, uint32_t b, uint32_t* fflags) {
rv_init(0);
auto r = f32_le(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
bool rv_fle_d(uint64_t a, uint64_t b, uint32_t* fflags) {
rv_init(0);
auto r = f64_le(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
bool rv_feq_s(uint32_t a, uint32_t b, uint32_t* fflags) {
rv_init(0);
auto r = f32_eq(to_float32_t(a), to_float32_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
bool rv_feq_d(uint64_t a, uint64_t b, uint32_t* fflags) {
rv_init(0);
auto r = f64_eq(to_float64_t(a), to_float64_t(b));
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint32_t rv_fmin_s(uint32_t a, uint32_t b, uint32_t* fflags) {
uint32_t r;
rv_init(0);
if (isNaNF32UI(a) && isNaNF32UI(b)) {
r = defaultNaNF32UI;
} else {
@@ -324,12 +341,13 @@ uint32_t rv_fmin_s(uint32_t a, uint32_t b, uint32_t* fflags) {
r = b;
}
}
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint64_t rv_fmin_d(uint64_t a, uint64_t b, uint32_t* fflags) {
uint64_t r;
rv_init(0);
if (isNaNF64UI(a) && isNaNF64UI(b)) {
r = defaultNaNF64UI;
} else {
@@ -342,12 +360,13 @@ uint64_t rv_fmin_d(uint64_t a, uint64_t b, uint32_t* fflags) {
r = b;
}
}
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint32_t rv_fmax_s(uint32_t a, uint32_t b, uint32_t* fflags) {
uint32_t r;
rv_init(0);
if (isNaNF32UI(a) && isNaNF32UI(b)) {
r = defaultNaNF32UI;
} else {
@@ -360,12 +379,13 @@ uint32_t rv_fmax_s(uint32_t a, uint32_t b, uint32_t* fflags) {
r = b;
}
}
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}
uint64_t rv_fmax_d(uint64_t a, uint64_t b, uint32_t* fflags) {
uint64_t r;
rv_init(0);
if (isNaNF64UI(a) && isNaNF64UI(b)) {
r = defaultNaNF64UI;
} else {
@@ -378,7 +398,7 @@ uint64_t rv_fmax_d(uint64_t a, uint64_t b, uint32_t* fflags) {
r = b;
}
}
if (fflags) { *fflags = get_fflags(); }
if (fflags) { *fflags = softfloat_exceptionFlags; }
return r;
}

View File

@@ -1,5 +1,17 @@
#ifndef RVFLOATS_H
#define RVFLOATS_H
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <cstdint>
@@ -78,5 +90,3 @@ uint64_t rv_ftod(uint32_t a);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <functional>
@@ -84,33 +97,39 @@ public:
}
uint64_t pop() {
auto cycle = queue_.front().cycle;
auto cycles = queue_.front().cycles;
queue_.pop();
return cycle;
return cycles;
}
void tx_callback(const TxCallback& callback) {
tx_cb_ = callback;
}
uint64_t arrival_time() const {
if (queue_.empty())
return 0;
return queue_.front().cycles;
}
protected:
struct timed_pkt_t {
Pkt pkt;
uint64_t cycle;
uint64_t cycles;
};
std::queue<timed_pkt_t> queue_;
SimPort* peer_;
TxCallback tx_cb_;
void push(const Pkt& data, uint64_t cycle) {
void push(const Pkt& data, uint64_t cycles) {
if (tx_cb_) {
tx_cb_(data, cycle);
tx_cb_(data, cycles);
}
if (peer_) {
peer_->push(data, cycle);
peer_->push(data, cycles);
} else {
queue_.push({data, cycle});
queue_.push({data, cycles});
}
}
@@ -129,14 +148,14 @@ public:
virtual void fire() const = 0;
uint64_t time() const {
return time_;
uint64_t cycles() const {
return cycles_;
}
protected:
SimEventBase(uint64_t time) : time_(time) {}
SimEventBase(uint64_t cycles) : cycles_(cycles) {}
uint64_t time_;
uint64_t cycles_;
};
///////////////////////////////////////////////////////////////////////////////
@@ -150,8 +169,8 @@ public:
typedef std::function<void (const Pkt&)> Func;
SimCallEvent(const Func& func, const Pkt& pkt, uint64_t time)
: SimEventBase(time)
SimCallEvent(const Func& func, const Pkt& pkt, uint64_t cycles)
: SimEventBase(cycles)
, func_(func)
, pkt_(pkt)
{}
@@ -180,11 +199,11 @@ template <typename Pkt>
class SimPortEvent : public SimEventBase {
public:
void fire() const override {
const_cast<SimPort<Pkt>*>(port_)->push(pkt_, time_);
const_cast<SimPort<Pkt>*>(port_)->push(pkt_, cycles_);
}
SimPortEvent(const SimPort<Pkt>* port, const Pkt& pkt, uint64_t time)
: SimEventBase(time)
SimPortEvent(const SimPort<Pkt>* port, const Pkt& pkt, uint64_t cycles)
: SimEventBase(cycles)
, port_(port)
, pkt_(pkt)
{}
@@ -330,7 +349,7 @@ public:
auto evt_it_end = events_.end();
while (evt_it != evt_it_end) {
auto& event = *evt_it;
if (cycles_ >= event->time()) {
if (cycles_ >= event->cycles()) {
event->fire();
evt_it = events_.erase(evt_it);
} else {
@@ -395,5 +414,5 @@ void SimPort<Pkt>::send(const Pkt& pkt, uint64_t delay) const {
reinterpret_cast<const SimPort<Pkt>*>(peer_)->send(pkt, delay);
} else {
SimPlatform::instance().schedule(this, pkt, delay);
}
}
}
}

78
sim/common/stringutil.h Normal file
View File

@@ -0,0 +1,78 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <iostream>
#include <iomanip>
class ByteStream : public std::istream {
public:
ByteStream(const void *buf, std::size_t size) : buf_(buf), size_(size) {}
friend std::ostream& operator<<(std::ostream& os, const ByteStream& obj) {
auto oldflags = os.flags();
auto oldwidth = os.width();
auto oldfill = os.fill();
for (std::size_t i = 0, n = obj.size_; i < n; ++i) {
int byte = *((uint8_t*)obj.buf_ + (n - 1 - i));
os << std::hex << std::setw(2) << std::setfill('0') << byte;
}
os.fill(oldfill);
os.width(oldwidth);
os.flags(oldflags);
return os;
}
private:
const void *buf_;
std::size_t size_;
};
class IndentStream : public std::streambuf {
public:
explicit IndentStream(std::streambuf* dest, int indent = 4)
: dest_(dest)
, isBeginLine_(true)
, indent_(indent, ' ')
, owner_(nullptr)
{}
explicit IndentStream(std::ostream& dest, int indent = 4)
: dest_(dest.rdbuf())
, isBeginLine_(true)
, indent_(indent, ' ')
, owner_(&dest) {
owner_->rdbuf(this);
}
virtual ~IndentStream() {
if (owner_)
owner_->rdbuf(dest_);
}
protected:
virtual int overflow(int ch) {
if (isBeginLine_ && ch != '\n') {
dest_->sputn(indent_.data(), indent_.size());
}
isBeginLine_ = ch == '\n';
return dest_->sputc(ch);
}
private:
std::streambuf* dest_;
bool isBeginLine_;
std::string indent_;
std::ostream* owner_;
};

View File

@@ -1,237 +0,0 @@
#pragma once
#include <cstdint>
#include <cocogfx/include/fixed.h>
#include <bitmanip.h>
using namespace cocogfx;
enum class WrapMode {
Clamp,
Repeat,
Mirror,
};
enum class TexFormat {
A8R8G8B8,
R5G6B5,
A1R5G5B5,
A4R4G4B4,
A8L8,
L8,
A8,
};
template <uint32_t F, typename T = int32_t>
T Clamp(Fixed<F,T> fx, WrapMode mode) {
switch (mode) {
case WrapMode::Clamp: return (fx.data() < 0) ? 0 : ((fx.data() > Fixed<F,T>::MASK) ? Fixed<F,T>::MASK : fx.data());
case WrapMode::Repeat: return (fx.data() & Fixed<F,T>::MASK);
case WrapMode::Mirror: return (bit_get(fx.data(), Fixed<F,T>::FRAC) ? ~fx.data() : fx.data());
default:
std::abort();
return 0;
}
}
inline uint32_t Stride(TexFormat format) {
switch (format) {
case TexFormat::A8R8G8B8:
return 4;
case TexFormat::R5G6B5:
case TexFormat::A1R5G5B5:
case TexFormat::A4R4G4B4:
case TexFormat::A8L8:
return 2;
case TexFormat::L8:
case TexFormat::A8:
return 1;
default:
std::abort();
return 0;
}
}
inline void Unpack8888(TexFormat format,
uint32_t texel,
uint32_t* lo,
uint32_t* hi) {
uint32_t r, g, b, a;
switch (format) {
case TexFormat::A8R8G8B8:
r = (texel >> 16) & 0xff;
g = (texel >> 8) & 0xff;
b = texel & 0xff;
a = texel >> 24;
break;
case TexFormat::R5G6B5:
r = ((texel >> 11) << 3) | (texel >> 13);
g = ((texel >> 3) & 0xfc) | ((texel >> 9) & 0x3);
b = ((texel & 0x1f) << 3) | ((texel & 0x1c) >> 2);
a = 0xff;
break;
case TexFormat::A1R5G5B5:
r = ((texel >> 7) & 0xf8) | ((texel << 1) >> 13);
g = ((texel >> 2) & 0xf8) | ((texel >> 7) & 7);
b = ((texel & 0x1f) << 3) | ((texel & 0x1c) >> 2);
a = 0xff * (texel >> 15);
break;
case TexFormat::A4R4G4B4:
r = ((texel >> 4) & 0xf0) | ((texel >> 8) & 0x0f);
g = ((texel & 0xf0) >> 0) | ((texel & 0xf0) >> 4);
b = ((texel & 0x0f) << 4) | ((texel & 0x0f) >> 0);
a = ((texel >> 8) & 0xf0) | (texel >> 12);
break;
case TexFormat::A8L8:
r = texel & 0xff;
g = r;
b = r;
a = texel >> 8;
break;
case TexFormat::L8:
r = texel & 0xff;
g = r;
b = r;
a = 0xff;
break;
case TexFormat::A8:
r = 0xff;
g = 0xff;
b = 0xff;
a = texel & 0xff;
break;
default:
std::abort();
}
*lo = (r << 16) + b;
*hi = (a << 16) + g;
}
inline void Unpack8888(uint32_t texel, uint32_t* lo, uint32_t* hi) {
*lo = texel & 0x00ff00ff;
*hi = (texel >> 8) & 0x00ff00ff;
}
inline uint32_t Pack8888(uint32_t lo, uint32_t hi) {
return (hi << 8) | lo;
}
inline uint32_t Lerp8888(uint32_t a, uint32_t b, uint32_t f) {
return (a + (((b - a) * f) >> 8)) & 0x00ff00ff;
}
template <uint32_t F, typename T = int32_t>
void TexAddressLinear(Fixed<F,T> fu,
Fixed<F,T> fv,
uint32_t log_width,
uint32_t log_height,
WrapMode wrapu,
WrapMode wrapv,
uint32_t* addr00,
uint32_t* addr01,
uint32_t* addr10,
uint32_t* addr11,
uint32_t* alpha,
uint32_t* beta
) {
auto delta_x = Fixed<F,T>::make(Fixed<F,T>::HALF >> log_width);
auto delta_y = Fixed<F,T>::make(Fixed<F,T>::HALF >> log_height);
uint32_t u0 = Clamp(fu - delta_x, wrapu);
uint32_t u1 = Clamp(fu + delta_x, wrapu);
uint32_t v0 = Clamp(fv - delta_y, wrapv);
uint32_t v1 = Clamp(fv + delta_y, wrapv);
uint32_t shift_u = (Fixed<F,T>::FRAC - log_width);
uint32_t shift_v = (Fixed<F,T>::FRAC - log_height);
uint32_t x0s = (u0 << 8) >> shift_u;
uint32_t y0s = (v0 << 8) >> shift_v;
uint32_t x0 = x0s >> 8;
uint32_t y0 = y0s >> 8;
uint32_t x1 = u1 >> shift_u;
uint32_t y1 = v1 >> shift_v;
*addr00 = x0 + (y0 << log_width);
*addr01 = x1 + (y0 << log_width);
*addr10 = x0 + (y1 << log_width);
*addr11 = x1 + (y1 << log_width);
*alpha = x0s & 0xff;
*beta = y0s & 0xff;
//printf("*** fu=0x%x, fv=0x%x, u0=0x%x, u1=0x%x, v0=0x%x, v1=0x%x, x0=0x%x, x1=0x%x, y0=0x%x, y1=0x%x, addr00=0x%x, addr01=0x%x, addr10=0x%x, addr11=0x%x\n", fu.data(), fv.data(), u0, u1, v0, v1, x0, x1, y0, y1, *addr00, *addr01, *addr10, *addr11);
}
template <uint32_t F, typename T = int32_t>
void TexAddressPoint(Fixed<F,T> fu,
Fixed<F,T> fv,
uint32_t log_width,
uint32_t log_height,
WrapMode wrapu,
WrapMode wrapv,
uint32_t* addr
) {
uint32_t u = Clamp(fu, wrapu);
uint32_t v = Clamp(fv, wrapv);
uint32_t x = u >> (Fixed<F,T>::FRAC - log_width);
uint32_t y = v >> (Fixed<F,T>::FRAC - log_height);
*addr = x + (y << log_width);
//printf("*** fu=0x%x, fv=0x%x, u=0x%x, v=0x%x, x=0x%x, y=0x%x, addr=0x%x\n", fu.data(), fv.data(), u, v, x, y, *addr);
}
inline uint32_t TexFilterLinear(
TexFormat format,
uint32_t texel00,
uint32_t texel01,
uint32_t texel10,
uint32_t texel11,
uint32_t alpha,
uint32_t beta
) {
uint32_t c01l, c01h;
{
uint32_t c0l, c0h, c1l, c1h;
Unpack8888(format, texel00, &c0l, &c0h);
Unpack8888(format, texel01, &c1l, &c1h);
c01l = Lerp8888(c0l, c1l, alpha);
c01h = Lerp8888(c0h, c1h, alpha);
}
uint32_t c23l, c23h;
{
uint32_t c2l, c2h, c3l, c3h;
Unpack8888(format, texel10, &c2l, &c2h);
Unpack8888(format, texel11, &c3l, &c3h);
c23l = Lerp8888(c2l, c3l, alpha);
c23h = Lerp8888(c2h, c3h, alpha);
}
uint32_t color;
{
uint32_t cl = Lerp8888(c01l, c23l, beta);
uint32_t ch = Lerp8888(c01h, c23h, beta);
color = Pack8888(cl, ch);
}
//printf("*** texel00=0x%x, texel01=0x%x, texel10=0x%x, texel11=0x%x, color=0x%x\n", texel00, texel01, texel10, texel11, color);
return color;
}
inline uint32_t TexFilterPoint(TexFormat format, uint32_t texel) {
uint32_t color;
{
uint32_t cl, ch;
Unpack8888(format, texel, &cl, &ch);
color = Pack8888(cl, ch);
}
//printf("*** texel=0x%x, color=0x%x\n", texel, color);
return color;
}

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "util.h"
#include <string.h>
@@ -7,4 +20,20 @@ const char* fileExtension(const char* filepath) {
if (ext == NULL || ext == filepath)
return "";
return ext + 1;
}
void* aligned_malloc(size_t size, size_t alignment) {
// reserve margin for alignment and storing of unaligned address
assert((alignment & (alignment - 1)) == 0); // Power of 2 alignment.
size_t margin = (alignment-1) + sizeof(void*);
void *unaligned_addr = malloc(size + margin);
void **aligned_addr = (void**)((uintptr_t)(((uint8_t*)unaligned_addr) + margin) & ~(alignment-1));
aligned_addr[-1] = unaligned_addr;
return aligned_addr;
}
void aligned_free(void *ptr) {
// retreive the stored unaligned address and use it to free the allocation
void* unaligned_addr = ((void**)ptr)[-1];
free(unaligned_addr);
}

View File

@@ -1,3 +1,16 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <cstdint>
@@ -49,4 +62,7 @@ const char* fileExtension(const char* filepath);
#define DISABLE_WARNING_UNUSED_PARAMETER
#define DISABLE_WARNING_UNREFERENCED_FUNCTION
#define DISABLE_WARNING_ANONYMOUS_STRUCT
#endif
#endif
void *aligned_malloc(size_t size, size_t alignment);
void aligned_free(void *ptr);

55
sim/common/uuid_gen.h Normal file
View File

@@ -0,0 +1,55 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <unordered_map>
namespace vortex {
class UUIDGenerator {
public:
UUIDGenerator() : ids_(0) {}
virtual ~UUIDGenerator() {}
uint32_t get_uuid(uint64_t PC) {
uint32_t id;
uint32_t ref;
auto it = uuid_map_.find(PC);
if (it != uuid_map_.end()) {
uint64_t value = it->second;
id = value & 0xffff;
ref = value >> 16;
} else {
id = ids_++;
ref = -1;
}
++ref;
uint64_t ret = (uint64_t(ref) << 16) | id;
uuid_map_[PC] = ret;
return ret;
}
void reset() {
uuid_map_.clear();
ids_ = 0;
}
private:
std::unordered_map<uint64_t, uint32_t> uuid_map_;
uint32_t ids_;
};
}