Commit d9d2727d authored by Antônio Augusto Fröhlich's avatar Antônio Augusto Fröhlich
Browse files

Merging RISC-V improvements from 2020/2 into the final multicore project

from 2020/1.
parent f2d5c739
......@@ -119,19 +119,17 @@ int philosopher(int n, int l, int c)
}
void eat(unsigned long long n) {
static unsigned long long v;
v = busy_wait(n);
busy_wait(n);
}
void think(unsigned long long n) {
static unsigned long long v;
v = busy_wait(n);
busy_wait(n);
}
unsigned long long busy_wait(unsigned long long n)
{
volatile unsigned long long v;
for(long long int j = 0; j < 20 * n; j++)
for(unsigned long long int j = 0; j < 20 * n; j++)
v &= 2 ^ j;
return v;
}
......@@ -133,7 +133,7 @@ template<> struct Traits<Thread>: public Traits<Build>
static const bool trace_idle = hysterically_debugged;
static const bool simulate_capacity = false;
typedef Fixed_CPU Criterion;
typedef GRR Criterion;
static const unsigned int QUANTUM = 100000; // us
};
......
......@@ -129,7 +129,7 @@ template<> struct Traits<Thread>: public Traits<Build>
static const bool trace_idle = hysterically_debugged;
static const bool simulate_capacity = false;
typedef Fixed_CPU Criterion;
typedef GRR Criterion;
static const unsigned int QUANTUM = 10000; // us
};
......
......@@ -119,19 +119,17 @@ int philosopher(int n, int l, int c)
}
void eat(unsigned long long n) {
static unsigned long long v;
v = busy_wait(n);
busy_wait(n);
}
void think(unsigned long long n) {
static unsigned long long v;
v = busy_wait(n);
busy_wait(n);
}
unsigned long long busy_wait(unsigned long long n)
{
volatile unsigned long long v;
for(long long int j = 0; j < 20 * n; j++)
for(unsigned long long int j = 0; j < 20 * n; j++)
v &= 2 ^ j;
return v;
}
# EPOS Application Makefile
include ../../makedefs
all: install
$(APPLICATION): $(APPLICATION).o $(LIB)/*
$(ALD) $(ALDFLAGS) -o $@ $(APPLICATION).o
$(APPLICATION).o: $(APPLICATION).cc $(SRC)
$(ACC) $(ACCFLAGS) -o $@ $<
install: $(APPLICATION)
$(INSTALL) $(APPLICATION) $(IMG)
clean:
$(CLEAN) *.o $(APPLICATION)
// EPOS Semaphore Component Test Program
#include <machine/display.h>
#include <time.h>
#include <synchronizer.h>
#include <process.h>
using namespace EPOS;
const int iterations = 10;
Mutex table;
Thread * phil[5];
Semaphore * chopstick[5];
OStream cout;
int philosopher(int n, int l, int c);
int main()
{
table.lock();
Display::clear();
Display::position(0, 0);
cout << "The Philosopher's Dinner:" << endl;
for(int i = 0; i < 5; i++)
chopstick[i] = new Semaphore;
phil[0] = new Thread(&philosopher, 0, 5, 32);
phil[1] = new Thread(&philosopher, 1, 10, 44);
phil[2] = new Thread(&philosopher, 2, 16, 39);
phil[3] = new Thread(&philosopher, 3, 16, 24);
phil[4] = new Thread(&philosopher, 4, 10, 20);
cout << "Philosophers are alive and hungry!" << endl;
Display::position(7, 44);
cout << '/';
Display::position(13, 44);
cout << '\\';
Display::position(16, 35);
cout << '|';
Display::position(13, 27);
cout << '/';
Display::position(7, 27);
cout << '\\';
Display::position(19, 0);
cout << "The dinner is served ..." << endl;
table.unlock();
for(int i = 0; i < 5; i++) {
int ret = phil[i]->join();
table.lock();
Display::position(20 + i, 0);
cout << "Philosopher " << i << " ate " << ret << " times " << endl;
table.unlock();
}
for(int i = 0; i < 5; i++)
delete chopstick[i];
for(int i = 0; i < 5; i++)
delete phil[i];
cout << "The end!" << endl;
return 0;
}
int philosopher(int n, int l, int c)
{
int first = (n < 4)? n : 0;
int second = (n < 4)? n + 1 : 4;
for(int i = iterations; i > 0; i--) {
table.lock();
Display::position(l, c);
cout << "thinking";
table.unlock();
Delay thinking(1000000);
table.lock();
Display::position(l, c);
cout << " hungry ";
table.unlock();
chopstick[first]->p(); // get first chopstick
chopstick[second]->p(); // get second chopstick
table.lock();
Display::position(l, c);
cout << " eating ";
table.unlock();
Delay eating(500000);
table.lock();
Display::position(l, c);
cout << " sate ";
table.unlock();
chopstick[first]->v(); // release first chopstick
chopstick[second]->v(); // release second chopstick
}
table.lock();
Display::position(l, c);
cout << " done ";
table.unlock();
return iterations;
}
#ifndef __traits_h
#define __traits_h
#include <system/config.h>
__BEGIN_SYS
// Build
template<> struct Traits<Build>: public Traits_Tokens
{
// Basic configuration
static const unsigned int MODE = LIBRARY;
static const unsigned int ARCHITECTURE = RV32;
static const unsigned int MACHINE = RISCV;
static const unsigned int MODEL = SiFive_E;
static const unsigned int CPUS = 1;
static const unsigned int NODES = 1; // (> 1 => NETWORKING)
static const unsigned int EXPECTED_SIMULATION_TIME = 60; // s (0 => not simulated)
// Default flags
static const bool enabled = true;
static const bool monitored = false;
static const bool debugged = true;
static const bool hysterically_debugged = false;
// Default aspects
typedef ALIST<> ASPECTS;
};
// Utilities
template<> struct Traits<Debug>: public Traits<Build>
{
static const bool error = true;
static const bool warning = true;
static const bool info = false;
static const bool trace = false;
};
template<> struct Traits<Lists>: public Traits<Build>
{
static const bool debugged = hysterically_debugged;
};
template<> struct Traits<Spin>: public Traits<Build>
{
static const bool debugged = hysterically_debugged;
};
template<> struct Traits<Heaps>: public Traits<Build>
{
static const bool debugged = hysterically_debugged;
};
template<> struct Traits<Observers>: public Traits<Build>
{
// Some observed objects are created before initializing the Display
// Enabling debug may cause trouble in some Machines
static const bool debugged = false;
};
// System Parts (mostly to fine control debugging)
template<> struct Traits<Boot>: public Traits<Build>
{
};
template<> struct Traits<Setup>: public Traits<Build>
{
};
template<> struct Traits<Init>: public Traits<Build>
{
};
template<> struct Traits<Framework>: public Traits<Build>
{
};
template<> struct Traits<Aspect>: public Traits<Build>
{
static const bool debugged = hysterically_debugged;
};
__END_SYS
// Mediators
#include __ARCHITECTURE_TRAITS_H
#include __MACHINE_TRAITS_H
__BEGIN_SYS
// API Components
template<> struct Traits<Application>: public Traits<Build>
{
static const unsigned int STACK_SIZE = Traits<Machine>::STACK_SIZE;
static const unsigned int HEAP_SIZE = Traits<Machine>::HEAP_SIZE;
static const unsigned int MAX_THREADS = Traits<Machine>::MAX_THREADS;
};
template<> struct Traits<System>: public Traits<Build>
{
static const unsigned int mode = Traits<Build>::MODE;
static const bool multithread = (Traits<Build>::CPUS > 1) || (Traits<Application>::MAX_THREADS > 1);
static const bool multitask = (mode != Traits<Build>::LIBRARY);
static const bool multicore = (Traits<Build>::CPUS > 1) && multithread;
static const bool multiheap = multitask || Traits<Scratchpad>::enabled;
static const unsigned long LIFE_SPAN = 1 * YEAR; // s
static const unsigned int DUTY_CYCLE = 1000000; // ppm
static const bool reboot = true;
static const unsigned int STACK_SIZE = Traits<Machine>::STACK_SIZE;
static const unsigned int HEAP_SIZE = (Traits<Application>::MAX_THREADS + 1) * Traits<Application>::STACK_SIZE;
};
template<> struct Traits<Task>: public Traits<Build>
{
static const bool enabled = Traits<System>::multitask;
};
template<> struct Traits<Thread>: public Traits<Build>
{
static const bool enabled = Traits<System>::multithread;
static const bool smp = Traits<System>::multicore;
static const bool trace_idle = hysterically_debugged;
static const bool simulate_capacity = false;
typedef Priority Criterion;
static const unsigned int QUANTUM = 100000; // us
};
template<> struct Traits<Scheduler<Thread>>: public Traits<Build>
{
static const bool debugged = Traits<Thread>::trace_idle || hysterically_debugged;
};
template<> struct Traits<Synchronizer>: public Traits<Build>
{
static const bool enabled = Traits<System>::multithread;
};
template<> struct Traits<Alarm>: public Traits<Build>
{
static const bool visible = hysterically_debugged;
};
template<> struct Traits<SmartData>: public Traits<Build>
{
static const unsigned char PREDICTOR = NONE;
};
template<> struct Traits<Network>: public Traits<Build>
{
typedef LIST<> NETWORKS;
static const unsigned int RETRIES = 3;
static const unsigned int TIMEOUT = 10; // s
static const bool enabled = (Traits<Build>::NODES > 1) && (NETWORKS::Length > 0);
};
template<> struct Traits<ELP>: public Traits<Network>
{
typedef Ethernet NIC_Family;
static constexpr unsigned int NICS[] = {0}; // relative to NIC_Family (i.e. Traits<Ethernet>::DEVICES[NICS[i]]
static const unsigned int UNITS = COUNTOF(NICS);
static const bool enabled = Traits<Network>::enabled && (NETWORKS::Count<ELP>::Result > 0);
};
template<> struct Traits<TSTP>: public Traits<Network>
{
typedef Ethernet NIC_Family;
static constexpr unsigned int NICS[] = {0}; // relative to NIC_Family (i.e. Traits<Ethernet>::DEVICES[NICS[i]]
static const unsigned int UNITS = COUNTOF(NICS);
static const unsigned int KEY_SIZE = 16;
static const unsigned int RADIO_RANGE = 8000; // approximated radio range in centimeters
static const bool enabled = Traits<Network>::enabled && (NETWORKS::Count<TSTP>::Result > 0);
};
template<> struct Traits<IP>: public Traits<Network>
{
typedef Ethernet NIC_Family;
static constexpr unsigned int NICS[] = {0}; // relative to NIC_Family (i.e. Traits<Ethernet>::DEVICES[NICS[i]]
static const unsigned int UNITS = COUNTOF(NICS);
struct Default_Config {
static const unsigned int TYPE = DHCP;
static const unsigned long ADDRESS = 0;
static const unsigned long NETMASK = 0;
static const unsigned long GATEWAY = 0;
};
template<unsigned int UNIT>
struct Config: public Default_Config {};
static const unsigned int TTL = 0x40; // Time-to-live
static const bool enabled = Traits<Network>::enabled && (NETWORKS::Count<IP>::Result > 0);
};
template<> struct Traits<UDP>: public Traits<Network>
{
static const bool checksum = true;
};
template<> struct Traits<TCP>: public Traits<Network>
{
static const unsigned int WINDOW = 4096;
};
template<> struct Traits<DHCP>: public Traits<Network>
{
};
template<> struct Traits<Monitor>: public Traits<Build>
{
static const bool enabled = monitored;
static constexpr System_Event SYSTEM_EVENTS[] = {ELAPSED_TIME, DEADLINE_MISSES, CPU_EXECUTION_TIME, THREAD_EXECUTION_TIME, RUNNING_THREAD};
static constexpr unsigned int SYSTEM_EVENTS_FREQUENCIES[] = { 1, 1, 1, 1, 1}; // in Hz
static constexpr PMU_Event PMU_EVENTS[] = {COMMITED_INSTRUCTIONS, BRANCHES, CACHE_MISSES};
static constexpr unsigned int PMU_EVENTS_FREQUENCIES[] = { 1, 1, 1}; // in Hz
static constexpr unsigned int TRANSDUCER_EVENTS[] = {CPU_VOLTAGE, CPU_TEMPERATURE};
static constexpr unsigned int TRANSDUCER_EVENTS_FREQUENCIES[] = { 1, 1}; // in Hz
};
__END_SYS
#endif
......@@ -47,6 +47,8 @@ eposmkbi.conf: FORCE
@echo "ENDIANESS=$(shell $(BIN)/eposcfg ENDIANESS)" >> $@
@echo "MEM_BASE=$(shell $(BIN)/eposcfg MEM_BASE)" >> $@
@echo "MEM_TOP=$(shell $(BIN)/eposcfg MEM_TOP)" >> $@
@echo "MIO_BASE=$(shell $(BIN)/eposcfg MIO_BASE)" >> $@
@echo "MIO_TOP=$(shell $(BIN)/eposcfg MIO_TOP)" >> $@
@echo "BOOT_LENGTH_MIN=$(shell $(BIN)/eposcfg BOOT_LENGTH_MIN)" >> $@
@echo "BOOT_LENGTH_MAX=$(shell $(BIN)/eposcfg BOOT_LENGTH_MAX)" >> $@
@echo "NODE_ID=$(NODE_ID)" >> $@
......
......@@ -20,14 +20,14 @@ endif
DEBUGGER := $(MACH_DEBUGGER)
ifeq ($(DEBUG),1)
ifneq ($(wildcard $(IMG)/$(MACH)_setup),)
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(SRC)/setup/$(MACH)_setup,.text)"
ifneq ($(wildcard $(IMG)/setup_$(MMOD)),)
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(SRC)/setup/setup_$(MMOD),.text)"
endif
ifneq ($(wildcard $(IMG)/$(MACH)_init),)
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(SRC)/init/$(MACH)_init,.text)"
ifneq ($(wildcard $(IMG)/init_$(MMOD)),)
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(SRC)/init/init_$(MMOD),.text)"
endif
ifneq ($(wildcard $(IMG)/$(MACH)_system),)
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(SRC)/system/$(MACH)_system,.text)"
ifneq ($(wildcard $(IMG)/system_$(MMOD)),)
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(SRC)/system/system_$(MMOD),.text)"
endif
DEBUGGER := $(DEBUGGER) -ex "add-symbol-file $(call DBSEC,$(APP)/$(APPLICATION)/$(APPLICATION),.text)"
PEER_DEBUGGER := $(subst 1235,1236,$(DEBUGGER))
......
......@@ -4,6 +4,8 @@
#define __mmu_h
#include <architecture/cpu.h>
#include <utility/string.h>
#include <utility/list.h>
__BEGIN_SYS
......@@ -67,7 +69,7 @@ public:
public:
static unsigned int pages(unsigned int bytes) { return (bytes + sizeof(Page) - 1) / sizeof(Page); }
static unsigned int page_tables(unsigned int pages) { return (pages + PT_ENTRIES - 1) / PT_ENTRIES; }
static unsigned int page_tables(unsigned int pages) { return sizeof(Page) > sizeof(int) ? (pages + PT_ENTRIES - 1) / PT_ENTRIES : 0; }
static unsigned int offset(const Log_Addr & addr) { return addr & (sizeof(Page) - 1); }
static unsigned int indexes(const Log_Addr & addr) { return addr & ~(sizeof(Page) - 1); }
......@@ -76,9 +78,163 @@ public:
static unsigned int directory(const Log_Addr & addr) { return addr >> DIRECTORY_SHIFT; }
static Log_Addr align_page(const Log_Addr & addr) { return (addr + sizeof(Page) - 1) & ~(sizeof(Page) - 1); }
static Log_Addr align_directory(const Log_Addr & addr) { return (addr + sizeof(Page) * sizeof(Page) - 1) & ~(sizeof(Page) * sizeof(Page) - 1); }
static Log_Addr align_directory(const Log_Addr & addr) { return (addr + PT_ENTRIES * sizeof(Page) - 1) & ~(PT_ENTRIES * sizeof(Page) - 1); }
};
class No_MMU: public MMU_Common<0, 0, 0>
{
friend class CPU;
private:
typedef Grouping_List<unsigned int> List;
public:
// Page Flags
typedef Flags Page_Flags;
// Page_Table
class Page_Table {
friend OStream & operator<<(OStream & os, Page_Table & pt) {
os << "{}";
return os;
}
};
// Chunk (for Segment)
class Chunk
{
public:
Chunk() {}
Chunk(unsigned int bytes, Flags flags): _phy_addr(alloc(bytes)), _bytes(bytes), _flags(flags) {}
Chunk(Phy_Addr phy_addr, unsigned int bytes, Flags flags): _phy_addr(phy_addr), _bytes(bytes), _flags(flags) {}
~Chunk() { free(_phy_addr, _bytes); }
unsigned int pts() const { return 0; }
Flags flags() const { return _flags; }
Page_Table * pt() const { return 0; }
unsigned int size() const { return _bytes; }
Phy_Addr phy_address() const { return _phy_addr; } // always CT
int resize(unsigned int amount) { return 0; } // no resize in CT
private:
Phy_Addr _phy_addr;
unsigned int _bytes;
Flags _flags;
};
// Page Directory
typedef Page_Table Page_Directory;
// Directory (for Address_Space)
class Directory
{
public:
Directory() {}
Directory(Page_Directory * pd) {}
Page_Table * pd() const { return 0; }
void activate() {}
Log_Addr attach(const Chunk & chunk) { return chunk.phy_address(); }
Log_Addr attach(const Chunk & chunk, Log_Addr addr) { return (addr == chunk.phy_address())? addr : Log_Addr(false); }
void detach(const Chunk & chunk) {}
void detach(const Chunk & chunk, Log_Addr addr) {}
Phy_Addr physical(Log_Addr addr) { return addr; }
};
// DMA_Buffer (straightforward without paging)
class DMA_Buffer: public Chunk
{
public:
DMA_Buffer(unsigned int s): Chunk(s, Flags::CT) {}
Log_Addr log_address() const { return phy_address(); }
friend Debug & operator<<(Debug & db, const DMA_Buffer & b) {
db << "{phy=" << b.phy_address() << ",log=" << b.log_address() << ",size=" << b.size() << ",flags=" << b.flags() << "}";
return db;
}
};
// Class Translation performs manual logical to physical address translations for debugging purposes only
class Translation
{
public:
Translation(Log_Addr addr, bool pt = false, Page_Directory * pd = 0): _addr(addr) {}
friend OStream & operator<<(OStream & os, const Translation & t) {
os << "{addr=" << static_cast<void *>(t._addr) << ",pd=0" << ",pd[???]=0" << ",pt[???]=0" << ",*addr=" << hex << *static_cast<unsigned int *>(t._addr) << "}";
return os;
}