Commit 6e7ed406 authored by Frédéric Pétrot's avatar Frédéric Pétrot
Browse files

Ajout des sujets de TPs et du code correspondant

parent 262ba811
# -*- mode: makefile -*-
.SUFFIXES:
.SECONDARY:
SHELL = /bin/sh
AT = @
ifndef SYSTEMCROOT
$(error Please set environment variable SYSTEMCROOT)
endif
SYSTEMC = $(SYSTEMCROOT)
ifndef ENSITLM
ENSITLM = $(ROOT)/ensitlm/
endif
ENSITLM_LIB=$(ENSITLM)/libensitlm.a
CLANG_FORMAT=clang-format-3.7
ifdef WITH_SDL
ifeq ($(strip $(shell which sdl-config)),)
ifeq ($(strip $(shell which sdl2-config)),)
$(error SDL library not found)
else
SDLCFG := sdl2-config
endif
else
SDLCFG := sdl-config
endif
SDLLIB = $(shell ${SDLCFG} --libs)
SDLCC = $(shell ${SDLCFG} --cflags)
else
SDLLIB =
SDSCC =
endif
# guess target os name used by systemc's configure
# translate it to what SystemC expects.
ARCH = $(shell uname -m | sed -e 's/x86_64.*/linux64/' -e 's/i.86.*/linux/')
CXX = g++
CPPFLAGS = -I$(SYSTEMC)/include
CPPFLAGS += -I$(ENSITLM) $(SDLCC)
CPPFLAGS += -MMD -MP -MF $(basename $@).d
CXXFLAGS = -O3 -g -Wall -Wextra -Winvalid-pch -Wno-unused-parameter #--std=gnu++11
# Used when using SDL, hence precompiled header use it, hence we have
# to use it everywhere if we want PCH support:
CXXFLAGS += -D_GNU_SOURCE=1 -D_REENTRANT
CC = gcc
CFLAGS = -O3 -g -Wall -Wextra
LD = $(CXX)
SC_LIB = -Xlinker -Bstatic -lsystemc -Xlinker -Bdynamic
LDFLAGS = $(CXXFLAGS)
LDLIBS =
ifdef WITH_X11
LDLIBS = -L/usr/X11R6/lib -lX11
endif
LDLIBS += $(SDLLIB)
LDLIBS += -L$(SYSTEMC)/lib-$(ARCH) $(SC_LIB) $(ENSITLM_LIB) -pthread
RM = -rm -f
OBJS = $(SRCS:%.cpp=%.o)
DEPS = $(SRCS:%.cpp=%.d)
.PHONY: $(MODULE)
$(MODULE): $(TARGET)
.PHONY: clean
clean:
$(RM) *.d *.o $(TARGET)
%.o: %.cpp $(filter-out %.d, $(MAKEFILE_LIST))
$(CXX) -c $< -o $@ $(CPPFLAGS) $(CXXFLAGS) $(CXXEXTRAFLAGS)
# "user-friendly" output of make for commands the students may not
# know:
.PHONY: $(ENSITLM_LIB)
$(ENSITLM_LIB):
@cd $(ENSITLM) && $(MAKE) ensitlm.h.gch && $(MAKE)
%.a: $(OBJS)
@echo "[$(MODULE)] creating static lib $@..."
$(AT)ar cr $@ $^
$(AT)ranlib $@
%.gch: % $(filter-out %.d, $(MAKEFILE_LIST))
@echo "[$(MODULE)] pre-compiling $<..."
$(AT)$(RM) $@
# Create file atomically -> create to .tmp and rename
$(AT)$(CXX) -x c++-header -c $* -o $@.tmp $(CPPFLAGS) $(CXXFLAGS) $(CXXEXTRAFLAGS)
$(AT)mv $@.tmp $@
%.d: ;
# Include dependency files
-include $(DEPS)
Travaux Pratiques (encadrés et en temps libre)
File added
File added
File added
/ensitlm.h.gch
/libensitlm.a
MODULE = ensitlm
TARGET = ensitlm.h.gch libensitlm.a
SRCS = bus.cpp
ROOT=..
include $(ROOT)/Makefile.common
FILES=${wildcard *.h *.cpp}
clang-format:
$(CLANG_FORMAT) -i $(FILES)
This must be compiled with the same -std=c++11 flag than SystemC (or without the same flags)
#include "ensitlm.h"
#include "bus.h"
using namespace std;
Bus::Bus(sc_core::sc_module_name name) : sc_core::sc_module(name) {
cout << name << ": Ensitlm bus" << endl;
}
void Bus::map(ensitlm::compatible_socket &port, ensitlm::addr_t start_addr,
ensitlm::addr_t size) {
port_map.insert(std::pair<ensitlm::compatible_socket *, addr_range>(
&port, addr_range(start_addr, start_addr + size - 1)));
}
void Bus::end_of_elaboration() {
// for each target connected to this bus initiator port
for (int i = 0; i < initiator.size(); ++i) {
// get the target
ensitlm::compatible_socket *target =
dynamic_cast<ensitlm::compatible_socket *>(initiator[i]);
if (!target) {
std::cerr << name()
<< ": target is not a tlm_target_socket\n";
abort();
}
// get the set of port maps which correspond to this name
std::pair<port_map_t::iterator, port_map_t::iterator> it =
port_map.equal_range(target);
// if no port map corresponds
if (it.first == it.second) {
std::cerr << name() << ": no address map information "
"available for target "
<< target->name() << "\n";
abort();
}
// iterate through port maps
for (port_map_t::iterator j = it.first; j != it.second; ++j) {
std::pair<addr_range, int> map_entry((*j).second, i);
// add to address map and check for conflicts
if (!addr_map.insert(map_entry).second) {
std::pair<addr_range, int> map_entry_bis =
(*addr_map.find((*j).second));
int k = map_entry_bis.second;
ensitlm::compatible_socket *target_bis =
dynamic_cast<ensitlm::compatible_socket *>(
initiator[k]);
std::cerr << name() << ": address map conflict "
"between target ports "
<< target->name() << " and "
<< target_bis->name() << "\n";
abort();
}
}
}
// #ifdef DEBUG
print_addr_map();
// #endif
}
void Bus::print_addr_map() {
// iterate through port maps
for (addr_map_t::iterator i = addr_map.begin(); i != addr_map.end();
++i) {
std::cout << name() << ": range [" << std::hex
<< (*i).first.begin << "-" << (*i).first.end + 1
<< "[ is mapped to target '"
<< dynamic_cast<ensitlm::compatible_socket *>(
initiator[((*i).second)])->name() << "'\n";
}
}
tlm::tlm_response_status Bus::read(ensitlm::addr_t a, ensitlm::data_t &d) {
if (a % sizeof(ensitlm::data_t)) {
std::stringstream s;
s << "unaligned read at 0x" << std::hex << a;
SC_REPORT_ERROR(name(), s.str().c_str());
return tlm::TLM_ADDRESS_ERROR_RESPONSE;
}
addr_map_t::iterator it = addr_map.find(addr_range(a, a));
if (it == addr_map.end()) {
std::cerr << name() << ": no target at address " << std::hex
<< a << std::endl;
return tlm::TLM_ADDRESS_ERROR_RESPONSE;
}
tlm::tlm_response_status s =
initiator.read(a - (*it).first.begin, d, (*it).second);
#ifdef DEBUG
std::cout << "Debug: " << name() << ": read access at " << std::hex
<< std::showbase << a << " (data: " << d << ")\n";
#endif
return s;
}
tlm::tlm_response_status Bus::write(ensitlm::addr_t a, ensitlm::data_t d) {
if (a % sizeof(ensitlm::data_t)) {
std::stringstream s;
s << "unaligned write at 0x" << std::hex << a;
SC_REPORT_ERROR(name(), s.str().c_str());
return tlm::TLM_ADDRESS_ERROR_RESPONSE;
}
addr_map_t::iterator it = addr_map.find(addr_range(a, a));
if (it == addr_map.end()) {
std::cerr << name() << ": no target at address " << std::hex
<< a << std::endl;
return tlm::TLM_ADDRESS_ERROR_RESPONSE;
}
#ifdef DEBUG
std::cout << "Debug: " << name() << ": write access at " << std::hex
<< std::showbase << a << " (data: " << d << ")\n";
#endif
tlm::tlm_response_status s =
initiator.write(a - (*it).first.begin, d, (*it).second);
return s;
}
#ifndef BUS_H
#define BUS_H
#include "ensitlm.h"
#include <map>
SC_MODULE(Bus) {
// The bus is the only component needing this "true" template
// parameter, to allow multi-port connections.
ensitlm::initiator_socket<Bus, true> initiator;
ensitlm::target_socket<Bus, true> target;
Bus(sc_core::sc_module_name name);
tlm::tlm_response_status read(ensitlm::addr_t a, ensitlm::data_t & d);
tlm::tlm_response_status write(ensitlm::addr_t a, ensitlm::data_t d);
void map(ensitlm::compatible_socket & port, ensitlm::addr_t start_addr,
ensitlm::addr_t size);
private:
void print_addr_map();
void end_of_elaboration();
class addr_range {
public:
addr_range(ensitlm::addr_t b, ensitlm::addr_t e)
: begin(b), end(e) {
}
const ensitlm::addr_t begin;
const ensitlm::addr_t end;
bool operator<(const addr_range &ar) const {
return (end < ar.begin);
}
};
typedef std::multimap<ensitlm::compatible_socket *, addr_range>
port_map_t;
port_map_t port_map;
typedef std::map<addr_range, int> addr_map_t;
addr_map_t addr_map;
};
#endif
#ifndef ENSITLM_H
#define ENSITLM_H
#include <systemc>
#include <tlm.h>
#include <stdint.h>
#include <sstream>
namespace ensitlm {
typedef uint32_t addr_t;
typedef uint32_t data_t;
}
#include "initiator_socket.h"
#include "target_socket.h"
#endif
#ifndef BASIC_INITIATOR_SOCKET_H
#define BASIC_INITIATOR_SOCKET_H
#include "ensitlm.h"
#include <vector>
namespace ensitlm {
template <typename MODULE, bool MULTIPORT = false>
class initiator_socket
: public tlm::tlm_initiator_socket<CHAR_BIT * sizeof(data_t),
tlm::tlm_base_protocol_types,
MULTIPORT ? 0 : 1>,
private tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types> {
typedef tlm::tlm_initiator_socket<CHAR_BIT * sizeof(data_t),
tlm::tlm_base_protocol_types,
MULTIPORT ? 0 : 1> base_type;
typedef tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>
bw_if_type;
public:
initiator_socket()
: base_type(sc_core::sc_gen_unique_name(kind())),
time(sc_core::SC_ZERO_TIME) {
init();
}
explicit initiator_socket(const char *name)
: base_type(name), time(sc_core::SC_ZERO_TIME) {
init();
}
~initiator_socket() {
tlm::tlm_generic_payload *trans;
while (!container.empty()) {
trans = container.back();
container.pop_back();
delete trans;
}
}
tlm::tlm_response_status read(const addr_t &addr, data_t &data,
int port = 0) {
tlm::tlm_generic_payload *trans;
// allocate the payload
if (!container.empty()) {
trans = container.back();
container.pop_back();
} else {
trans = new tlm::tlm_generic_payload();
}
// build the payload ...
trans->set_command(tlm::TLM_READ_COMMAND);
trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
trans->set_address(addr);
trans->set_data_ptr(reinterpret_cast<unsigned char *>(&data));
// No block transaction => just one piece of data
trans->set_data_length(sizeof(data_t));
// no streaming => streaming_width == data_length
trans->set_streaming_width(sizeof(data_t));
// ... and send it.
(*this)[port]->b_transport(*trans, time);
container.push_back(trans);
return trans->get_response_status();
}
tlm::tlm_response_status write(const addr_t &addr, data_t data,
int port = 0) {
tlm::tlm_generic_payload *trans;
if (!container.empty()) {
trans = container.back();
container.pop_back();
} else {
trans = new tlm::tlm_generic_payload();
}
trans->set_command(tlm::TLM_WRITE_COMMAND);
trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
trans->set_address(addr);
trans->set_data_ptr(reinterpret_cast<unsigned char *>(&data));
trans->set_data_length(sizeof(data_t));
trans->set_streaming_width(sizeof(data_t));
(*this)[port]->b_transport(*trans, time);
container.push_back(trans);
return trans->get_response_status();
}
virtual const char *kind() const {
return "ensitlm::initiator_socket";
}
void invalidate_direct_mem_ptr(sc_dt::uint64, sc_dt::uint64) {
std::cerr << "invalidate_direct_mem_ptr not implemented"
<< std::endl;
abort();
}
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &,
tlm::tlm_phase &,
sc_core::sc_time &) {
std::cerr << "nb_transport_bw not implemented" << std::endl;
abort();
}
private:
// container to keep the unused payloads (avoids calling new too often)
std::vector<tlm::tlm_generic_payload *> container;
// zero time, but allocated once and for all for performance reasons.
sc_core::sc_time time;
void init() {
// we're not actually using the backward interface,
// but we need to bind the sc_export of the socket to something.
this->bind(*(static_cast<bw_if_type *>(this)));
}
};
}
#endif
#ifndef BASIC_TARGET_SOCKET_H
#define BASIC_TARGET_SOCKET_H
#include "ensitlm.h"
namespace ensitlm {
typedef tlm::tlm_target_socket<CHAR_BIT * sizeof(data_t),
tlm::tlm_base_protocol_types> compatible_socket;
template <typename MODULE, bool MULTIPORT = false>
class target_socket
: public tlm::tlm_target_socket<CHAR_BIT * sizeof(data_t),
tlm::tlm_base_protocol_types,
MULTIPORT ? 0 : 1>,
public tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types> {
typedef tlm::tlm_target_socket<CHAR_BIT * sizeof(data_t),
tlm::tlm_base_protocol_types,
MULTIPORT ? 0 : 1> base_type;
typedef tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>
fw_if_type;
public:
target_socket() : base_type(sc_core::sc_gen_unique_name(kind())) {
// check_typing() is never actually called, but should be
// statically reachable to force the compiler to do the
// typechecking.
if (false)
check_typing();
init();
}
explicit target_socket(const char *name) : base_type(name) {
init();
}
virtual const char *kind() const {
return "ensitlm::target_socket";
}
bool get_direct_mem_ptr(tlm::tlm_generic_payload &, tlm::tlm_dmi &) {
std::cerr << "get_direct_mem_ptr not implemented" << std::endl;
abort();
}
unsigned int transport_dbg(tlm::tlm_generic_payload &) {
std::cerr << "transport_dbg not implemented" << std::endl;
abort();
}
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &,
tlm::tlm_phase &,
sc_core::sc_time &) {
std::cerr << "nb_transport_fw not implemented" << std::endl;
abort();
}
private:
void check_typing() {
std::cerr << "You should never call this function, it is only "
"meant for typechecking"
<< std::endl;
abort();
const ensitlm::data_t const_data = 12;
const ensitlm::addr_t const_addr = 42;
ensitlm::data_t data;
// Check that MODULE inherits publicly from
// sc_module. If You get an error on the following
// line, check that the first template argument
// is an sc_module.
(void)static_cast<sc_core::sc_module *>(m_mod);
// Check that the parent module declares read and
// write methods properly. If you get an error on
// one of the following lines, check that the
// declaration of read and write match *exactly*
// the ones in initiator_socket.h
tlm::tlm_response_status s;
s = m_mod->read(const_addr, data);
s = m_mod->write(const_addr, const_data);
(void)s;
}
void b_transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &t) {
(void)t;
addr_t addr = static_cast<addr_t>(trans.get_address());
data_t &data =
*(reinterpret_cast<data_t *>(trans.get_data_ptr()));
switch (trans.get_command()) {
case tlm::TLM_READ_COMMAND:
trans.set_response_status(m_mod->read(addr, data));
break;
case tlm::TLM_WRITE_COMMAND:
trans.set_response_status(m_mod->write(addr, data));
break;
case tlm::TLM_IGNORE_COMMAND:
break;
default:
trans.set_response_status(
tlm::TLM_COMMAND_ERROR_RESPONSE);
}
}
void init() {
// we'll receive transactions ourselves ...
this->bind(*(static_cast<fw_if_type *>(this)));
// ... but we'll need to call read/write in the parent module.
sc_core::sc_object *parent = this->get_parent_object();
if (!parent) {
std::cerr << this->name()
<< ": target socket has no parent object."
<< std::endl;
abort();
}
m_mod = dynamic_cast<MODULE *>(parent);
if (!m_mod) {
std::cerr << this->name() << ": parent object "
<< parent->name()
<< " of socket has the wrong type."
<< std::endl;
abort();
}
}
MODULE *m_mod;
};
}
#endif
#! /bin/echo Non, il ne faut pas executer ce fichier, mais faire: source $0
export SYSTEMCROOT=/matieres/5MMMTSP/tlm/systemc-2.3.2/
# Chaine de cross-compilation MicroBlaze, pour le TP3
xilinx=/matieres/5MMMTSP/tlm/microblaze/setup.sh
if [ -f "$xilinx" ]; then
source "$xilinx"
fi
// LCD Controller
// (c) 2005 Jerome Cornet
// 2007 Matthieu Moy
#include "LCDC.h"
#include "LCDC_registermap.h"
#include "ensitlm.h"
using namespace std;
using namespace sc_core;
// constants
const int LCDC::kWidth = 320;
const int LCDC::kHeight = 240;